1. 移位运算符
移位运算符是双目运算符,将运算符左边的操作数左移或右移运算符右边的操作数指定的位数,用 0 来补充空闲位。如果右边操作数的值为 X 或 Z,则移位结果为未知X。
Verilog HDL 中有两种移位运算符: <<(左逻辑移)和>>(右逻辑移)。
例程:
moduleShift_led(clk,rst_n);
inputrst_n;
inputclk;
reg[3:0]a;
reg[3:0]b;
always@(posedgeclkornegedgerst_n)
if(!rst_n)begin
a=1;
b=3;
end
elsebegin
a<=(a<<1);
b<=(b>>1);
end
endmodule
//仿真代码
`timescale1ns/1ns
`defineclk_period20
moduleShift_led_tb;
regclk;
regrst_n;
initialclk=1;
always#(`clk_period/2)clk=~clk;
initialbegin
rst_n=0;
#(`clk_period*5);
rst_n=1;
#(`clk_period*20);
$stop;
end
Shift_ledShift_led(.clk(clk),.rst_n(rst_n));
endmodule
仿真波形图:
从仿真图,可以看出,每次 a 都向左边移动移位,后面补充 0,直到把逻辑1 溢出,后面就一直为 0 了。 每次 b 都向右边移动移位,前面补充 0,直到把逻辑 1 溢出,就一直为 0 了。
备注:移位运算符的使用时,左移可以看成是乘以 2,右移可以看成是除以2。 所以移位运算符用在计算中,代替乘法和除法。
2. 位拼运算符
位拼运算符是将多个小的表达式合并形成一个大的表达式,用符号{}来实现多个表达式的连接运算,各个表达式之间用“,”隔开。
moduleConcatation(clk,rst_n,out);
inputclk;
inputrst_n;
outputreg[3:0]out;
reg[1:0]a;
reg[1:0]b;
always@(posedgeclkornegedgerst_n)
if(!rst_n)begin
a<=2'b11;
b<=2'b01;
out<=4'b0011;
end
elsebegin
a<=(a<<1);
b<=(b<<1);
out<={a,b};
end
endmodule
//`tb.v同移位注意修改例化
仿真波形图为:
通过波形图,我们可以清晰的看到移位和位拼结合的效果
注:用位拼"{ }"同样可以实现循环效果
例程:
if()
...
out<=4'b0111;
...
else
...
out<={out[0],out[3:1]};
...
//感兴趣的可以试一下,这里不做展示
3.LED显示移位,位拼效果.
下面我们通过例程说明
moduleConcatation(clk,rst_n,led);
inputclk;
inputrst_n;
output[3:0]led;
reg[3:0]out;
reg[1:0]a;
reg[1:0]b;
always@(posedgeclkornegedgerst_n)
if(!rst_n)begin
a<=2'b11;
b<=2'b01;
out<=4'b0011;
end
elsebegin
a<=(a<<1);
b<=(b<<1);
out<={a,b};
end
assignled=out;
endmodule
///////////////////////////////////////////////////////
`timescale1ns/1ns
`defineclk_period20
moduleConcatation_tb;
regclk;
regrst_n;
initialclk=1;
always#(`clk_period/2)clk=~clk;
initialbegin
rst_n=0;
#(`clk_period*5);
rst_n=1;
#(`clk_period*20);
$stop;
end
ConcatationConcatation(.clk(clk),.rst_n(rst_n),.led(led));
endmodule
仿真效果
我们通过观察led和out的输出,可以看到结果相同,通过led信号我们下载到板卡上时,就能观察到led显示同波形图
注:真正下载板卡让led显示时,我们需要通过计数延时,要不然人眼观察不出led变化