如何写控制逻辑(三):模块级流水和valid/ready协议

本文详细介绍了如何在模块级流水线中处理Valid/Ready协议,包括OutReady恒为1的情况、有OutReady反压时的处理逻辑、多个输入模块对多个输出模块的握手方式,以及解决死锁和Valid/Ready撤销的方法。通过实例和代码解释,帮助读者理解在FPGA设计中控制逻辑的关键点。
摘要由CSDN通过智能技术生成

如何写控制逻辑(三):模块级流水和valid/ready协议

大概八月份就开始想总结下控制逻辑的写法了,然后开始找资料,没有直接讲这个的,零零散散的看了很多,断断续续的写了很长时间,自闭无岁月···
就先写一篇发出来吧,抓住2020的尾巴 <-_<-
所以上两篇嘛,第一篇总结下控制逻辑,第二篇写FSM状态机,敬请期待 :)
全程都是菜鸟的理解,代码也未经验证,如果觉得不对欢迎指出来!

OutLine

1 基本流水中间单元

1.1 OutReady 恒为1的情况

1.2 有OutReady 反压的情况

1.2.1 推理逻辑一
1.2.1 推理逻辑二

1.3 多个输入模块对多个输出模块

1.3.1 在valid/ready中加入一些控制信号
1.3.2 多对多握手

2 skid buffer

3 死锁

4 Valid/ready 撤销

Reference

规模较大的设计一般划分为若干子模块,子模块之间通过FIFO连接。FIFO的作用就是实现模块间的rate balance,匹配不同模块的处理速率,从而实现模块间的解耦,这样每个模块可以单独设计控制逻辑,不需要考虑其他模块的影响。
这些子模块可以是一些实现具体功能的模块,也可以是再划分为若干子模块,然后通过模块级的流水实现控制,无论哪种方式,都需要和FIFO的空满状态打交道。
我们知道FIFO的空满其实就是Valid/ready,所以对于模块级流水而言,这些流水模块一定是处于两个FIFO之间的,这两个FIFO就是流水的发端和收端。而且发端FIFO的Valid很独立,没有依赖于Ready;收端FIFO的Ready很独立,没有依赖于Valid;所以他们是完美的发端和收端,而中间这些流水模块的Valid/ready有依赖关系是完全没问题的,带来的后果也仅仅是当Valid依赖ready时是ready before valid,会有气泡;而当ready依赖valid时是valid before ready,没有气泡。而且如同我们下面介绍的ready before valid时还可以有方法挤掉气泡。
而如果两个FIFO之间没有再划分子模块,则可以将其视为模块流水中的一级。

此外,对于Valid/ready传输协议,若是在一堆组合逻辑模块传来传去,则都不用打拍的,直接一根线贯穿到底即可,但是这样组合逻辑太长,Timing会紧张,所以有了(模块)流水线,在每一级模块对数据和InValid插入寄存器切断组合逻辑,以跑更高的时钟频率;而OutReady一般不用打拍,但是由于它是一根信号驱动中间所有模块的ready,所以如果流水级数多了fanout会比较大,而且还有gate delays,进而Timing也可能会有问题,所以这时也需要对ready打拍。

1 基本流水中间单元

如上所讲,流水线的sender和receiver分别是两边的FIFO,所以下面介绍的都是中间的单元,他们传递InValid到OutValid,传递OutReady到InReady,在InReady和InValid握上手时对InData做一些处理,比如我们这里将其乘3。它们的模块接口都如下:

module MiddlePipe #(parameter
    DW = 10
)
(
    //Interface
    input           Clk         ,
    input           Clear       ,
    input           Rstn        ,

    //In interface
    input  [DW-1:0] DataIn      ,
    input           DataInVld   ,
    output          DataInRdy   ,

    //Out interface
    output [DW+1:0] DataOut     ,
    output          DataOutVld  ,
    input           DataOutRdy
);

//---------------------------------------------------------------------
reg data_in_rdy;
assign DataInRdy = data_in_rdy;

reg [DW+1:0] data_out;
assign DataOut = data_out;

reg data_out_vld;
assign DataOutVld = data_out_vld;
//---------------------------------------------------------------------

1.1 OutReady 恒为1的情况

OutReady 恒为1意味着不会有来自后级模块的反压,也即此时的模块级流水和模块内的流水线运算是一样的,写法如下:

//------Version 1: if DataOutRdy = 1-----------
always @ *
begin
    data_in_rdy = 'h1;
end

always @( posedge Clk or negedge Rstn )
begin
    if( ~Rstn )
        data_out <= 'h0;
    else if( Clear )
        data_out <= 'h0;
    else if( DataInVld )
        data_out <= DataIn << 1 + DataIn;
end

always @( posedge Clk or negedge Rstn )
begin
    if( ~Rstn )
        data_out_vld <= 'h0;
    else if( Clear )
        data_out_vld <= 'h0;
    else
        data_out_vld <= DataInVld;
end
//------Version 1: if DataOutRdy = 1-----------

1.2 有OutReady 反压的情况

1.2.1 推理逻辑一

此时来自后级模块的反压,其实追跟到底是来自后面那个作为receiver的FIFO的反压,比如它满了,则传给前面的Ready都要拉下来以防丢数据。
前面我们提过,模块级流水就是在valid/ready协议的valid和数据通路中插入寄存器切断组合逻辑,ready要具有反压能力自然要控制这些寄存器,以在ready=0时使其停下来,而且ready可以不打拍,所以逻辑如下:

//----------------------Version 2:without bubble collapse--------------------------
always @ *
begin
    data_in_rdy = DataOutRdy;
end

always @( posedge Clk or negedge Rstn )
begin
    if( ~Rstn )
        data_out <= 'h0;
    else if( Clear )
        data_out <= 'h0;
    else if( data_in_rdy && DataInVld  )//backpressure:data_in_rdy &&
        data_out <&
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值