fpga 寄存器输出不稳定
写代码过程中需要用到组合逻辑,当时没考虑太多,就直接用了
代码如下:其中r_w_fifo_len_dout 位宽为16bit
assign r_w_fifo_len_dout = read_fifo_len_en ? w_fifo_len_dout :i_pmac_send_len_val ? i_pmac_send_len :r_w_fifo_len_dout;
后边编译显示生成了逻辑环于是就把 r_w_fifo_len_dout 改成了reg类型,同同时代码做了改进
always@(*)//更改为时序逻辑
begin
if(i_rst)
r_w_fifo_len_dout = 'd254;
else if(read_fifo_len_en)
r_w_fifo_len_dout = w_fifo_len_dout;
else if(i_pmac_send_len_val)
r_w_fifo_len_dout = i_pmac_send_len;
else
r_w_fifo_len_dout = r_w_fifo_len_dout;
end
改进之后成功的生成了bit流文件,但是上板验证过程中发现输出的结果不符合逻辑。
从图片中可以看出来,当read_fifo_len_en信号拉高的时候r_w_fifo_len_dout 得到了正确的赋值1024,但是一个时钟周期,在没达到其他触发条件的时候r_w_fifo_len_dout 又变成了256,导致后续代码结果出错。
后来把这个组合逻辑改成时序逻辑结果就对了。
更改后的代码:
always@(posedge i_clk,posedge i_rst)//更改为时序逻辑
begin
if(i_rst)
r_w_fifo_len_dout <= 'd254;
else if(read_fifo_len_en)
r_w_fifo_len_dout <= w_fifo_len_dout;
else if(i_pmac_send_len_val)
r_w_fifo_len_dout <= i_pmac_send_len;
else
r_w_fifo_len_dout <= r_w_fifo_len_dout;
end
更改后的结果
可以看出更改之后结果就不会跳到错误点去了。
后经过查资料感觉因该是由于不同路径的延迟不一致所导致的数据线上出现了一个或多个非预期的中间状态。但是对于第一个图中稳定之后又发生变化还是有点不解。
总的来讲,写代码的时候能用时序逻辑尽量用时序逻辑,特别是对于一些大位宽的数据。
如果寄存器只包含一个触发器,即寄存器的容量为1bit,在下一个有效时钟边沿到来时,要将一个1bit位宽的寄存器的输出从逻辑0变为逻辑1,不会出现不稳定态,因为一个时钟有效边沿最多只能改变输出一次。此时用组合逻辑是ok的。
对于多触发器寄存器,由于组成寄存器的各个触发器变化不一致(线延迟的存在)导致时钟信号到达各个寄存器的时间可能不一致,也导致各个触发器的输出端口到信号接收端所需的时间可能不一样,再加上各个寄存器的t{co}等参数不可能精确一致,所以当我们改变多触发器寄存器的输出时,就会出现不稳定态。