在之前的文章中,我们分别讨论了Verilog HDL里面的"非阻塞赋值"和"阻塞赋值"。用实例分析了如果在一个always块内等式右边的表达式或者变量,是另一个always块内等式左边的表达式或者变量,仿真器在同一个时间(同一个时钟的边沿)内同时执行两个等式,这就会导致竞争产生。并且我们详细分析了在同一个always块里面,如果混合使用"非阻塞赋值"和"阻塞赋值",所可能出现的结果,并且给出了建议的编码方式。 今天我们继续探讨如何使用Verilog HDL描述电路的情况,并且特别拿出了几个常见的误区,多一个分析讨论。 一个always块内同一信号的多处非阻塞赋值 在之前的文章中,我们探讨了很多种情况,其中有两种情况如下所示:同一个信号在多个always块内进行非阻塞赋值;同一个信号在一个always块内多次进行非阻塞赋值。 对上面的两种情况,我都有很详细的说明,并给出了例子进行比较。但是后面我有看到有的朋友质疑说,Verilog并没有严格定义同一个信号在一个always块内多次进行非阻塞赋值。我需要再说明一下,Verilog标准其实是有严格定义的,具体来说就是,如果同一个信号在一个always块内多次进行非阻塞赋值,那么此信号的最终取值是最后一个非阻塞赋值的结果。 我们还是来看个例子。 input clk, rst_n; input in1, in2; output[1:0] out; reg[1:0] out; always@(posedge clk or negedge rst_n) begin if(!rst_n) out <= 1"b0; else begin out <= 1"b1; out <= in1 & in2; end end 在上面的例子中,我们可以看到对输出out,在同一个always块内出现了两次赋值,但是根据我们上面的介绍可以知道,最终out的结果是in1 & in2。但是需要强调的是,虽然Verilog HDL语法允许可以这么描述,但是我建议说,尽量不要出现这种描述。 $display和非阻塞赋值 很多朋友问我,在使用非阻塞赋值时,想用$display,却发现不起作用,是不是两个不能混合使用?答案是否定的。 还是举个例子来探讨一下这个问题。 input clk, rst_n; output[1:0] out; reg[1:0] out; always@(posedge clk or negedge rst_n) begin if(!rst_n) out <= 1"b0; else begin out <= 1"b1; $display("$display: out = %b", out); end end 这段RTL的结果是显示$display: out = 0,似乎和很多朋友说一样,$display显示有问题,其实不是。因为$display显示的是非阻塞赋值执行前的数据。 小结 今天我们分享的两个问题,是我们经常碰到,但是却不容易理解的,所以希望能对朋友有一点帮助了。