Verilog 提供了移位运算符方便移位操作,移位操作符有四种分别是逻辑左移<<,逻辑右移>> ,算术左移<<<,算术右移>>>。移位操作符是双目操作数运算符。
1. 逻辑左移<<
将左操作数按照右操作数(RHS) 指定的位数左移,左操作数移出的位数丢弃,右边补零;
例:
wire [7:0] a,b;
assign a = 7;
assign b = a << 3;
由于a的2进制数是8’b0000_0111, 左移三位后的数值是8’b0011_1000; 因此b的值为8’b0011_1000。
在有效位移出之前相当于乘以23 。
2. 逻辑右移>>
将左操作数按照右操作数(RHS) 指定的位数右移,左操作数移出的位数丢弃,左边补零;
例:
wire [7:0] a,b;
assign a = 31;
assign b = a >> 3;
由于a的2进制数是8’b0001_1111, 右移三位后的数值是8’b0000_0011; 因此b的值为8’b0000_0011,十进制3。
相当于除以23 取整。
例:
设计文件 logic_shift.v
|
1 2 3 4 5 6 7 8 9 10 |
module logic_shift ( input [7:0] a,b, output [15:0] c,d ); assign c = a << b; assign d = a >> b; endmodule |
仿真文件tb.v
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
`timescale 1ns/1ps module tb ( ); reg [7:0] a, b; wire [15:0] c; wire [15:0] d; initial begin a = 'b0; b = 'b0; #10 a = 'd15; b = 'd3; #10 a = 'd31; b = 'd4; end logic_shift logic_shift_dut ( .a (a), .b (b), .c (c), .d (d) ); endmodule |
Modelsim 仿真波形

从上图可以看出当a==8’b0001_1111,且左移4位时,主要c的位宽足够宽,左移时并没有将溢出的位数丢弃。可见在左移前,右边的变量会根据赋值语句左边的变量自动调整宽度。
3. 算术左移 <<<
算术左移将被移位的操作数左移指定的位数,左边移出的位数丢弃(注意赋值语句位宽调整),右边补零。除了被移位的操作数按有符号数,其它与<<几乎没有差别。
4. 算术右移 >>>
算术右移将被移位的操作数右移指定的位数,右边移出的位数丢弃(注意赋值语句位宽调整),左边补符号位。一般有符号数的最高位(2进制)为符号位,因此右移时,符号位在左边不断复制并右移。
例:
wire signed [7:0] a;
wire signed [7:0] c;
assign c = a >>> 3;
则c 的值实际为 {a[7],a[7],a[7],a[7:3]};
要实现算术右移的结果,被移位的操作数必须定义为有符号数,如:
wire signed [7:0] a; 否则其结果与>>一致。
例:
设计文件 arith_shift.v:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
module arith_shift ( input signed [7:0] a,b, output signed [3:0] test, output signed [15:0] c,d ); assign test = a <<< b; assign c = a <<< b; assign d = a >>> b; endmodule |
仿真文件 tb.v
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
`timescale 1ns/1ps module tb ( ); reg [7:0] a, b; wire [3:0] test; wire [15:0] c; wire [15:0] d; initial begin a = 'b0; b = 'b0; #10 a = 'd15; b = 'd3; #10 a = 'd31; b = 'd4; #10 a = -'d3; b = 'd4; #10 b = 'd6; #10 b = 'd8; #10 b = 'd10; #10 b = 'd11; #10 b = 'd12; #10 b = 'd13; #10 b = 'd14; #10 b = 'd15; #10 b = 'd16; end arith_shift arith_shift_dut ( .a (a), .b (b), .test (test), .c (c), .d (d) ); endmodule |
Modelsim 仿真波形


从上图可以看出,除了复制符号位扩展,算术左移与逻辑左移几乎没有区别,右移自动填充符号位。
对应视频: