对于阻塞赋值以及非阻塞赋值的一些理解
最近在看别人的FPGA卷积程序时有一段程序逻辑不太理解,主要是对于非阻塞赋值理解的不够深刻。现在基本弄清楚了,写个笔记记录一下~
首先这段程序如下:
always @(posedge clk) begin
if (!local_rst_n) begin
wr_addr <= 16'h0000;
user_wr_rdy_n <= 1'b1;
wr_state <= WR_RST;
pre_port_wr_rdy <= 1'b0;
end
else begin
pre_port_wr_rdy <= wr_port_rdy_n;
case(wr_state)
WR_RST:begin
user_wr_rdy_n <= 1'b1;
if (!user_rd_start_n)
wr_state <= WR_RDY;
else
wr_state <= WR_RST;
end
WR_RDY:begin
user_wr_rdy_n <= 1'b0;
if ((!wr_port_rdy_n)&&(pre_port_wr_rdy)) //
wr_state <= WR_DONE;
else
wr_state <= WR_RDY;
end
WR_DONE:begin
user_wr_rdy_n <= 1'b1;
wr_state <= WR_RST;
wr_addr <= wr_addr + 1'b1;
end
endcase
end
if (wr_addr == 12'b000000000010) //(wr_addr[10:0] == 11'b10000000000)
work_led <= 1;
else
work_led <= 0;
end
可以无视这段代码的变量名称,单纯看逻辑。这里
pre_port_wr_rdy <= wr_port_rdy_n;
wr_port_rdy_n对pre_port_wr_rdy做了一个非阻塞赋值,然后下面的条件判断语句
if ((!wr_port_rdy_n)&&(pre_port_wr_rdy))
这里的reg型变量pre_port_wr_rdy是被赋值前的pre_port_wr_rdy还是被赋值后的pre_port_wr_rdy?
答案当然应该是赋值前的pre_port_wr_rdy,不然条件判断语句就没有意义,可为什么呢?
这关于非阻塞赋值的定义:非阻塞赋值分为两个过程,RHS的计算为第一步,LHS的赋值为第二步;但由于两步时间非常短,表现出来就是在时钟边沿瞬间完成,故表现结果非阻塞和阻塞一样。
但如果条件判断式中含有非阻塞赋值的reg型变量,结果就不一样了。条件判断式中的条件相当于采样,而被采样的reg变量使用了非阻塞赋值,非阻塞赋值完成有两个步骤,在某一个仿真节拍(不是一个仿真周期),被采样的还没有赋值完成(处在RHS的计算阶段),而采样时同时进行,这样,采样到的就是上一个周期的reg变量的值,虽然马上在边沿完成赋值,但采样已经结束了,所以条件判断语句里的reg变量是被赋值前的值。
通过对这段程序的行为级仿真,我们也能验证之前的说法:
这里还需注意的是 wr_port_rdy_n在时钟沿上升的同时下拉,pre_port_wr_rdy并不是同时被下拉而是延后了一个时钟周期。