verilog 基础语法与应用3
verilog中的阻塞赋值和非阻塞赋值
// 这里既不是阻塞也不是非阻塞
always@(*)
case(a,b,c)
0:out=8'b00000001;
// 非阻塞赋值
always@(posedge clk)
counter <= counter + 1
阻塞与非阻塞,只存在于 时序逻辑中
module block_nonblock(
clk,
reset,
a,
b,
c,
out
);
input clk;
input reset;
input a,b,c;
output reg [1:0]out;
reg [1:0] d;
// 时序逻辑
always@(posedge clk or negedge reset)
if(!reset) begin
out <= 2'b0;
d <= 0;
end
else begin
// d <= a+ b;
// out <= d+c;
out <= a+b+c; // 和前面一样吗?
end
endmodule
分成两段的话,时序逻辑一定是D触发器为输出的,所以 d=a+b 的电路图为:
对应得 d=a+b, out = d+c 得图
如果是 out = a+b+c的图示是怎么样的呢?
留两个思考的问题:
非阻塞赋值:
这种情况下,阻塞和非阻塞是一模一样的
但是现在要变了:
区别在 d=a+b 写到了前面,发现没有的d_reg
a ,b,c 三个信号先做了加法,再放到d触发器。就是换了个顺序,结构就变了。如果写代码的时候,用阻塞赋值的话,写的先后顺序会影响最后的电路结构。
out 在整个过程中,没有出现0的状态,没有的原因在于 out=a+b+c
,d在里面不管怎么变都没有影响
方式2:非阻塞赋值的写法
细节:
这里out 会有个0
这里上升沿的时候,d=0和c=0,在下一拍的时候 d变成1,所以后面就是1
阻塞赋值中,书写的顺序,会影响结果的变化。如果把阻塞赋值的顺序换一下,就会出现非阻塞赋值中有个0的变化。
如果给延时2,时钟上升沿2us后,才会发生变化。
D触发器的电路细节,一个D端口一个Q端口,当时钟上升沿到来的时刻。D从内部传到Q,是存在一定的延迟。
容易犯迷糊的时候,可以写加个延时2us,来确定有效的时候是上升沿之前,还是上升沿之后。在仿真的时候模拟寄存器的仿真延时。
小结:非阻塞赋值,无论顺序,综合的电路都是一模一样的。时序逻辑中用阻塞赋值来写,综合的电路,大不相同。
一般情况下,在时序逻辑中,一律使用 非阻塞赋值,无论谁写在前面还是后面一定是一样的。
小作业:一个LED闪烁的例子,counter <= counter + 1’b1 , 改成阻塞赋值,通过仿真来测量LED翻转的时间有没有区别。
24999 是 500ms
用阻塞赋值
500us - 20us
所以说时序逻辑中,用阻塞赋值会有一些奇奇怪怪的问题