请选择 进入手机版 | 继续访问电脑版

明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信扫一扫,快捷登录!

查看: 6388|回复: 0

【FPGA至简设计原理与应用】第一篇第三章硬件描述语言Verilog第5节移位运算符

[复制链接]
发表于 2020-9-7 18:59:13 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本案例的编号为:001500000141,如果有疑问,请按编号在下面贴子查找答案:MDY案例交流【汇总贴】_FPGA-明德扬科教 (mdy-edu.com)
本文为明德扬原创及录用文章,转载请注明出处

大家好,近期我们会连载《FPGA至简设计原理与应用》一书,有兴趣的同学可以学习,也希望大家可以对我们的书提出宝贵的意见和建议。


FPGA至简设计原理与应用》书籍连载索引目录

http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=989


读过的朋友可积极在贴后留言,书籍正式出版时,我们会从留言者中挑选20位幸运读者,幸运读者可获潘老师亲笔签名书籍一本。

注:手机浏览可能格式会乱,建议用电脑端进行浏览。




5.7 移位运算符
本文档编号:001100000061
要看对应的视频,请点击视频编号:001100000064
1. 本节主要进行组合逻辑的介绍,包括:程序语句(assign语句、always语句),数字进制(二进制、不定态、高阻态),算数运算符(加、减、乘、除运算符),逻辑运算符(逻辑与、或、非运算符),按位逻辑运算符(单目按位与、或、非运算符,双目按位与、或、异或运算符),关系运算符,移位运算符(左移、右移运算符),条件运算符(三目运算符、if语句、case语句、选择语句等),拼接运算符;
2. ALTERA和VIVADO文档

Verilog HDL中有两种移位运算符,分别为“<<”(左移位运算符)和“>>”(右移位运算符)。
下面分别介绍两者的用法:


5.7.1左移运算符

Verilog HDL中,用“<<”表示左移运算符。其一般表达式为:
A<< n
其中,A代表要进行移位的操作数,n代表要左移多少位。此表达式的意义是把操作数A左移n位。左移操作属于逻辑移位,需要用0来填补移出的空位,即在低位补0。左移n位,就要补n0
1
  
2
wire[3:0] a;
  
assign a = 4’b0111<<  2;
以上代码由于左移了2位,所以在低位补2个零,所以上面代码运行结果是:a = 4’b1100
左移操作中有以下三点值得注意的地方:
1)左移操作是不消耗逻辑资源的,甚至连与门、非门都不需要,它只是线的连接。
1
  
2
  
3
wire[3:0] c;
  
wire[3:0]b;
  
assign c = b  << 2;
上面代码是将信号b左移两位并赋给c,其所对应的硬件电路如下图:

2)左移操作需根据位宽储存结果

读者在学习过程中可能看到过如下代码:
4’b1001<<1=4’b00104’b1001<<1=5’b10010
为什么操作数同样是4’b1001,都是左移一位,但结果一个是4’b0010,一个是5’b10010呢?
这是因为左移操作后,要看用多少位来存储结果。
1
  
2
  
3
wire[3:0] a;
  
assign b = 4’b1001;
  
assign a = b << 1;
上面代码中由于a4比特,只能保存4位结果,所以b左移1位赋给4 bita,用0填补移出的位后结果为a = 4’b0010
1
  
2
  
3
  
4
wire[4:0] a;
  
assign b = 4’b1001;
  
assign a = b << 1;
  
a=10010;
而上面代码中由于a5比特,能保存5位结果,所以b左移1位赋给5 bita,用0填补移出的位后结果为a = 5’b10010

3)左移操作的操作数可以是常数,也可以是信号。同样,左移操作的移位数、常数也可以是信号。
1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
reg[4:0] a;
  
reg[2:0]   cnt;
  
always   @(posedge clk or negedge rst_n)begin
  
     if(rst_n==1'b0)begin
  
cnt<= 0;
  
     end
  
     else begin
  
cnt<= cnt + 1;
  
     end
  
end
  
always   @(*)begin
  
     a = 4'b1 <<cnt;
  
end

上面代码中cnt每个时钟加1,由于是3比特,所以值为0~2a则是4’b1左移cnt位。当cnt等于0时左移0位,a等于4’b1;当cnt等于1时左移1位,a等于4’b10。以此类推,a的每个时钟变化情况如下所示:  



需要注意的是,当移位数是信号时,其综合的电路并不是简单的连线,可能会综合出如下图所示的选择器。然而即便如此,这种硬件电路所消耗的资源依然比较少。



5.7.2右移运算符

Verilog HDL中,用“>>”表示右移运算符。其一般表达式为:
A >>n
其中,A代表要进行移位的操作数,n代表要右移多少位。此代码表示的意义是把操作数A右移n位。

在右移操作中有以下三点值得注意的地方:
1)右移操作属于逻辑移位,需要用0来填补移出的空位,即在高位补0,补多少个0,取决于保存结果的信号的位宽。
1
  
2
wire[5:0] a;
  
assign a = 4’b0111<<  2;
4’b0111右移两位后的结果为2’b01,由于a6位的,2位赋值给6位需要在高位补0,因此需要补40。所以上面代码运行结果是:
a = 6’b0001
2)与左移操作相似,右移操作是不消耗逻辑资源的,甚至连与门、非门都不需要,其只是线的连接。
1
  
2
  
3
wire[3:0] a;
  
wire[3:0] b;
  
assign a = b  >> 2;
上面代码是将信号b左移两位并赋给a,其所对应的硬件电路如下图所示。

3)左移操作的操作数可以是常数,也可以是信号。同样,右移操作的移位数可以是常数,也可以是信号。
1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
reg[4:0] a;
  
reg[2:0]   cnt;
  
always   @(posedge clk or negedge rst_n)begin
  
     if(rst_n==1'b0)begin
  
cnt<= 0;
  
     end
  
     else begin
  
cnt<= cnt + 1;
  
     end
  
end
  
always   @(*)begin
  
     a = 4'b1000>>cnt;
  
end
上面代码中,cnt每个时钟加1,由于是3比特,所以值为0~2a则是4’b1000右移cnt位。当cnt等于0时右移0位,a等于4’b1000;当cnt等于1时右移1位,a等于4’b0100。以此类推,a的每个时钟变化情况如下图所示。


与左移操作类似,在右移操作中,如果移位数是信号时,其综合的电路就不是简单的连线,而是有可能会综合出如下图所示的选择器。然而同样在这一情况下,这种硬件电路所消耗的资源依然比较
少。


5.7.3经验总结


  • 通过左移乘法运算
FPGA中要尽量避免乘法运算,因为这种计算需要占用较大的硬件资源,并且运算速度较慢。当不得不使用乘法的时候,尽量乘以2N次方,这样在设计中可以利用左移运算来实现该乘法运算,从而大大减少硬件资源。
当乘数是2N次方的常数时可以用移位运算来实现乘法。例如:a*2,等价于 a<<1a*4等价于a<<2a*8等价于a<<3,依此类推。
即使乘数不是2N次方的常数,也可以通过移位运算来简化实现。例如:
1
  
2
assign b = a*127;
  
assign c = (a<<7) –a;
上面代码中bc都可以实现a*127,但第1行消耗了一个乘法,而第2行则只用到一个减法器。
1
  
2
assign b = a*67;
  
assign c = (a<<6) +(a<<1) +a;
上面代码中,bc都可以实现a*67,但第1行消耗了一个乘法,而第2行则只用到两个加法器,从而节省了资源。

有读者可能注意到,上面两个例子中的乘数都是常数,那么在设计时这种乘法也要花时间和精力来考虑优化吗?其实是不必要的,因为现在综合工具都很强大,当工具发现乘数是常数时会自动按上述过程进行优化,也就是说乘以常数在实质上并不消耗乘法器资源,读者可以放心使用。
但当出现乘数不是常数的情况时,读者就要注意乘法的使用了。尽量将信号转换为与2N次方相关的形式。例如当数据要扩大后来计算时,不要按照惯有思维将数据扩大100倍,而是应该直接将其扩大128倍。

  • 利用右移实现除法运算
FPGA设计中要极力避免除法,在笔者眼中甚至是严禁使用“ /”来用于除法计算。这是由于除法器会占用极大的资源,其占用资源量要多于乘法器,而且很多时候不能在一个时钟周期内得出结果。而当不得不使用除法的时候,读者应尽量使除法转化为除以2N次方形式,这样便可以利用右移运算来实现该除法运算,从而大大减少硬件资源。

当除数是2N次方的常数时,就可以用移位运算来实现除法。例如:a/2,等价于 a>>1a/4等价于a>>2a/8等价于a>>3,依此类推。
与左移不同的是,当除数不是2N次方的常数时,不能简单地通过移位运算来简化实现。

总而言之,在FPGA设计中应尽力避免除法。

  • 利用左移位产生独热码
独热码,也叫one-hot code,就是只有1个比特为1,其他全为0的一种码制。例如8’b000100008’b1000000等。

独热码在设计时非常有用,可以用来表示状态机的状态使状态机更健壮,也可以用于多选一的电路中,表示选择其中的一个。

利用左移位操作,可以方便地产生独热码,例如产生4’b0010,可以是4’b1 << 1。类似地,也可以产生1个比特为0,其他为1的码制。例如产生4’b1011,可以是~(4’b1<<2)。利用左移操作,还可以产生其他需要的数字结果:
例如,产生5’b00111,可以是(5’b1<<3)-1
例如,产生5’b11100,可以是~((5’b1<<2)-1)





您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|MDYBBS ( 粤ICP备16061416号 )

GMT+8, 2024-3-28 19:05 , Processed in 0.051589 second(s), 21 queries .

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2019 Comsenz Inc.

快速回复 返回顶部 返回列表