always@ (posedge clk)的不足
目的是实现:每一次s_axis_data_tready和s_axis_data_tvalid完成握手的时候,对应的在rom中的数据也同时会被读取。
如果使用的是时序逻辑,效果如下
分析:如图中的代码,发生了第一次握手,读取的是初值0+i0,但是实际上应该是读取1+i0。
第二次握手读取的是1+i0,但是实际上应该读取0.314956486225128 - 0.949106097221375i
如果打拍的话,能不能解决呢
s_axis_data_tready是FFT的IP核给的,不能打拍,FFT的IP核内部会用自己的s_axis_data_tready和输入的s_axis_data_tvalid的 && 来判断数据是否是能够放进IP核里面。
单单给s_axis_data_tvalid打拍,这样的话,确实能够读到数据了,但是如果下一个时钟周期的s_axis_data_tready拉低了(无法不能输出数据了,但是本身这个数据是应该进入到FFT的IP核中的),在有背压的情况下,就会出问题。
下图为乐观情况
下图为特殊情况,存在背压,这时候该数据本该是应该被写进fft的IP核中的,但是没有握手,数据无法被写入
always@*的解释
在代码中的误用
如图中的代码,本意是让每一次的握手发生了之后,马上就能更改地址计数器data_in_cnt的值,然后马上得到新的s_axis_data_tdata的值,这样我马上就能够将本周期的值修改为要读取的数据,然后在完成握手的同时给FFT的IP核输入正确的数据。
但是如图中,data_in_cnt等于462的时候,发生了一次握手,但是data_in_cnt没有增加,连带着data_in_cnt,s_axis_data_tdata都没有改变。为什么呢?
always@*会自动生成敏感列表,敏感列表中,检测到有一个值发生变化,整个always块中的代码都会被重新执行一遍。如果没错,图中代码的敏感列表就只是valid和ready两个握手信号 。但是坏就坏在,红圈圈出来的第二个时钟周期,两个握手信号的值都没有变化,导致地址计数器data_in_cnt的值没有办法增加。导致代码功能仿真不符合预期。