Verilog的无符号移位运算(“>>“和“<<“)和算术移位运算(“<<<“和“>>>“)的设计

1.无符号移位

1.1.基本设计

我们在进行Verilog代码设计时经常会用到移位运算,对于无符号运算,我们只需要使用移位运算符("<<“和”>>")就能够实现移位的功能,这个很容易理解。
如无符号左移时,接收寄存器要比源寄存器多出对应移位位宽。

reg [3:0] reg1;
reg [5:0] reg2;
always@(posedge clk)
	reg2 <= reg1 << 2;//左移两位,reg2比reg1多出两位。 

同理对于无符号右移时,只需要减少对应位宽就行。

reg [3:0] reg1;
reg [2:0] reg2;
always@(posedge clk)
	reg2 <= reg1 >> 1;//右移1位,reg2比reg1减少1位。 

1.1.易错

有的时候移位的位数可能是从别的电路传过来的。比如下面的:

wire [1:0] a,b;
assign a = 2'd1;
assign b = 2'd1;
reg [3:0] reg1;
reg [9:0] reg2;
always@(posedge clk)
	reg2 <= reg1 << (a+b+3'd4);

这样写,一般是没有问题的,但是在一些大型电路中,就可能会存在移位位数发生错误的问题,导致移位的位数不能按照我们所预期的结果去移位。
建议代码这样写:

wire [1:0] a,b;
assign a = 2'd1;
assign b = 2'd1;
wire [4:0] shift;
assign shift = a+b+3'd4; 
reg [3:0] reg1;
reg [9:0] reg2;
always@(posedge clk)
	reg2 <= reg1 << shift ; 

或者把移位内部的表达式中的数据表示成integer,即32位位宽的形式。(3’d4直接改为4)

always@(posedge clk)
	reg2 <= reg1 << (a+b+4);

不过最好写成上面第一种建议,以免造成不必要的资源浪费。

2.有符号算术移位

2.1.基本设计

既然是使用了算术移位了,那么肯定是涉及到有符号数的运算了,那就不要再把寄存器定义成无符号数了。把上面的代码改为有符号数,移位符号改为算术移位,抄下来就行了。
左移:

reg signed [3:0] reg1;
reg signed [5:0] reg2;
always@(posedge clk)
	reg2 <= reg1 <<< 2;//左移两位,reg2比reg1多出两位。 

右移:

reg signed [3:0] reg1;
reg signed [2:0] reg2;
always@(posedge clk)
	reg2 <= reg1 >>> 1;//右移1位,reg2比reg1减少1位。 

说明:在进行设计的时候,有符号运算就写成服务于有符号运算的运算符和数据类型定义,无符号就写成服务于无符号运算的运算符和数据类型定义。如果乱写,会很麻烦,建议不要乱搞,否则会浪费很多时间。

上一篇:「工具」正则表达式


下一篇:# 1. 正则表达以及失去焦点验证的JS书写