当前位置:   article > 正文

【芯片前端】保持代码手感——握手协议ready打拍时序优化_backwardpipe

backwardpipe

在valid-ready双向握手机制下,对下游反馈的ready进行打拍,实现对上游接口的ready信号时序优化。当拍若ready有效则数据可以直接向下游握手,若ready无效则数据寄存一拍。要求数据输出不能丢弃或乱序,且上游的ready为寄存器输出

接口如下:

  1. module backward_pipe #(
  2. parameter WIDTH = 8)
  3. (
  4. input clk,
  5. input rst_n,
  6. input [WIDTH -1:0]data_in,
  7. input data_in_valid,
  8. output data_in_ready,
  9. output[WIDTH -1:0]data_out,
  10. output data_out_valid,
  11. input data_out_ready
  12. );
  13. endmodule

题目解析

给ready打拍一直都是我没想明白的操作,所以这次一定要把他想清楚。这个题目的核心就是给前级传的ready必须是寄存器输出,所以我想了三个小时,终于把这个寄存器给做出来了:

  1. wire out_ready_en = data_in_valid || data_out_ready;
  2. wire out_ready_d = data_out_ready;
  3. wire out_ready_q;
  4. dffse #(.WIDTH(1), .VALUE(1'b1))
  5. u_out_ready_dffse(
  6. .clk(clk),
  7. .rst_n(rst_n),
  8. .d(out_ready_d),
  9. .en(out_ready_en),
  10. .q(out_ready_q)
  11. );
  12. assign data_in_ready = out_ready_q;

这个寄存器必须是复位值为1,因为不管上来有没有ready这个打拍也能存一拍。那么这个寄存器的含义是啥呢?他表示着此时data的寄存器里的值是不是一个有效的值,如果为1表示data寄存器没有用或者没值,为0表示data的寄存器里有有效值。所以上来复位值为1表示此时data寄存器里没有有效值。而后每次en时把data_out_ready更新进去,如果更新进去的是1那么就意味着数据直接被下游拿走了(“当拍若ready有效则数据可以直接向下游握手”),如果更新进去的值是0则意味着数据下游没接,存在data寄存器里了。

那么out_ready_en的逻辑实际是比较难做的。当data_out_ready为1时肯定是可以更新寄存器的,那么另外一种情况就是data_in_valid为1时,看下面的场景分析:

data_in_validdata_out_readydata_in_readydata_out_ready_en

下一拍data_in_ready

即data_out_ready_q

10010

data寄存器中存放着有效数据,无法接上游数据;

data_in_validdata_out_readydata_in_readydata_out_ready_en

下一拍data_in_ready

即data_out_ready_q

11011

data寄存器中存放着有效数据,当拍被取走,因此刷新 data_out_ready_q表示从下一拍的data寄存器里没有有效值,如果下一拍的out_ready还是为1那么数据就透传了,如果下一拍out_ready又变成0那么数据存入data寄存器(因为下一拍data_in_ready一定是1)。如果还是没说清楚,那一会看下波形吧。

data寄存器的逻辑还是非常简单:

  1. wire data_en = data_in_valid && data_in_ready;
  2. wire [WIDTH -1:0]data_d = data_in;
  3. wire [WIDTH -1:0]data_q;
  4. dffe #(.WIDTH(WIDTH))
  5. u_in_data_dffe(
  6. .clk(clk),
  7. .d(data_d),
  8. .en(data_en),
  9. .q(data_q)
  10. );

接下来是产生对外输出的逻辑:

  1. assign data_out_valid = data_in_valid || (~out_ready_q);
  2. assign data_out = out_ready_q ? data_in : data_q;
  3. assign data_in_ready = out_ready_q;

out_ready_q的含义很清楚,为0时表示data寄存器里有值需要往外取。可以看到这样给上游传出去的data_in_ready是寄存器输出,逻辑非常干净。

波形分析

感觉给ready打拍这个事啊,拿话说根本说不清以后我就拿这个题去考别人好了,看谁能说清。

看这个波形,时刻1上游有valid下游没有ready,那么把数据存入了寄存器,上游ready跳变位0表示data寄存器里有有效值,不能再接上游的数据了;

时刻2,下游ready起了,把data寄存器里的数据0取走;时刻3下游ready持续有效,直接把值1透传给下游(注意此时数据还是同时写入了data寄存器,但是data_out_ready_q即data_in_ready标记为1即data寄存器里的值是无效值);

时刻4,下游ready起了,把data寄存器里的数据2取走;而后下一拍data_out_ready回归为0,则值3被写到了寄存器中且被标记有效;

时刻5,数值3被取走,且后面从时刻6开始又可以透传了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/206924
推荐阅读
相关标签
  

闽ICP备14008679号