0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

AXI握手时序优化—pipeline缓冲器

FPGA设计论坛 来源:FPGA设计论坛 2025-03-08 17:10 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

skid buffer(pipeline缓冲器)介绍

  解决ready/valid两路握手的时序困难,使路径流水线化。
  只关心valid时序参考这篇写得很好的博客链接:握手协议(pvld/prdy或者valid-ready或AXI)中Valid及data打拍技巧;只关心ready时序修复可以参考同作者这篇文章链接:(AXI)握手协议(pvld/prdy或者valid-ready)中ready打拍技巧
  一个skid buffer是最小的Pipeline FIFO Buffer,只有两个入口。当您需要在发送者和接收者之间为并发和/或定时流水线化路径时,它很有用,但不能消除数据速率不匹配。它还只需要两个数据寄存器,在这个规模上比LUT RAM或Block RAM小(取决于实现),并且具有更大的布局和布线自由度。

背景

  片上网络 (NoC) 和pipeline具有作为基本构建块的握手机制,其中链路的每一端都可以发出信号,如果它们有数据要发送(“valid”),或者它们是否能够接收数据(“ready”)。当两端一致(有效且均为高电平)时,在该时钟周期发生数据传输。
   但是,流水线握手更复杂:1.如果直接将valid、ready和data流水线寄存是可以工作的,但是每次传输需要两个周期开始,两个周期停止。如果每次握手只传输一个数据块,这在带宽利用方面还不错。但是现在接收器必须知道它和发送器之间存在多少管道阶段,才能有足够的内部缓冲数据(在它发出不再准备好接收更多数据的信号后,吸收不断到达的数据,因为说了ready要过一拍才能传上去)。
  这是基于信用的连接的基础(不在这里讨论),它可以最大化带宽,但是如果只需要在两端之间添加单个pipe阶段,而无需修改master/slave,只是满足时序或允许每一端发送一项数据而不必等待打拍的延迟响应(因此重叠通信,这是可取的)。

需求与模块定义

  为了开始设计一个pipeline缓冲器,让我们想象一个可以执行valid/ready握手并接收输入数据的单元,输出执行相同的握手以输出数据。

e0bec09e-fbd2-11ef-9310-92fbcf53809c.png

  理想情况下,输入和输出接口同时握手以获得最大带宽:即在相同的时钟周期内,输入接口接收到新的数据并将其放入内部寄存器中;此时该寄存器同时在输出接口被握手读出。但是,如果输出接口在给定周期内没有发送数据,则输入接口在该周期内也不能输入数据,否则旧数据将被覆盖。为避免此问题,上游输入边的ready接口应该在下游输出端ready未就绪的同一周期中声明自己未就绪。但这形成了它们之间的直接组合连接,而不是流水线连接。
  为了解决这个矛盾,我们需要一个额外的缓冲buffer来保存数据,此时输入接口正在获取数据但输出接口没有发送数据的情况,并且pipeline寄存器中已经有数据。然后,在下一个周期,输入接口可以发出信号它不再准备好,并且没有数据丢失。我们可以想象这个额外的缓冲buffer允许输入接口“延迟一拍”停止,而不是立即停止(与ready打一拍同步了),解决了之前的问题。
下面展示一些内联代码片。

`default_nettype none

module Pipeline_Skid_Buffer
#(
    parameter WORD_WIDTH = 0
)
(
    input   wire                        clock,
    input   wire                        clear,

    input   wire                        input_valid,
    output  wire                        input_ready,
    input   wire    [WORD_WIDTH-1:0]    input_data,

    output  wire                        output_valid,
    input   wire                        output_ready,
    output  wire    [WORD_WIDTH-1:0]    output_data
);

    localparam WORD_ZERO = {WORD_WIDTH{1'b0}};

数据路径

  数据路径的作用:在Buffer有数据时从buffer送数据给pipeline寄存器(输出数据寄存器),没有数据时从输入数据寄存。
  注意到,我们选择了将不同输入数据到单个输出寄存器(pipeline寄存器)的方案,而不是在两个相同的输出寄存器后加入MUX选通,从而避免新的单元和路径延迟。单个输出寄存器还能在下游继续重定时优化时序。
  选通的初始默认值为选通输入数据寄存,即认为buffer的“空”状态。因此默认情况下,第一个到达的数据最终一定会直接给到pipeline寄存器。我们不必担心此时选通信号的状态。

    reg                     data_buffer_wren = 1'b0; // EMPTY at start, so don't load.
    wire [WORD_WIDTH-1:0]   data_buffer_out;

    Register
    #(
        .WORD_WIDTH     (WORD_WIDTH),
        .RESET_VALUE    (WORD_ZERO)
    )
    data_buffer_reg
    (
        .clock          (clock),
        .clock_enable   (data_buffer_wren),
        .clear          (clear),
        .data_in        (input_data),
        .data_out       (data_buffer_out)
    );

    reg                     data_out_wren       = 1'b1; // EMPTY at start, so accept data.
    reg                     use_buffered_data   = 1'b0;
    reg [WORD_WIDTH-1:0]    selected_data       = WORD_ZERO;

    always @(*) begin
        selected_data = (use_buffered_data == 1'b1) ? data_buffer_out : input_data;
    end

    Register
    #(
        .WORD_WIDTH     (WORD_WIDTH),
        .RESET_VALUE    (WORD_ZERO)
    )
    data_out_reg
    (
        .clock          (clock),
        .clock_enable   (data_out_wren),
        .clear          (clear),
        .data_in        (selected_data),
        .data_out       (output_data)
    );

控制路径

  我们将控制路径模块单独出来,因此数据路径模块不必知道有关当前状态或其编码的任何信息。
  控制路径为一个状态机,此FSM假定valid/ready握手信号的通常含义和行为——当两者都为高电平时,数据在时钟周期结束时传输。当无法接受数据时拉高ready或在无法发送数据时拉高valid都是错误的。这些协议层面的错误并不会被处理。
  要将使用我们的控制路径模块来操控数据路径用作缓冲区,我们需要了解我们希望允许它处于哪些状态,以及状态怎么转换。该pipeline缓冲器具有三种状态:
     1. Empty: Buffer和pipeline寄存器是空的。
     2. Busy: Pipeline寄存器满,此时等待新的数据或完成数据传送。
     3. Full: buffer和pipeline寄存器全满,必须等待pipeline寄存器及buffer都清空(将buffer加载进pipeline寄存器),否则“延迟一拍”将不再有效。
  在这些状态转换时的操作是:
    a. 将数据握手后送入数据路径的输入接口(+)
    b. 从数据路径中删除数据项的输出接口 ( -)
    c. 两个接口同时插入和移除 ( ±)
  我们还描述性地命名了状态之间的每个转换。这些名称稍后会出现在代码中。

e0d23e4e-fbd2-11ef-9310-92fbcf53809c.png

  从状态图转移中我们可以看出,当datapath为空时,只能支持写入,而当datapath满时,只能支持读出。这些限制将在以后变得非常重要。如果接口尝试在 Empty 时读出,或在 Full 时写入,则数据将分别重复或丢失。
  这个简单的 FSM 描述帮助我们澄清了问题,但它也掩盖了实现时的潜在复杂性:3 个状态中,总共两对握手信号,每个状态共有16个可能的组合转换,即总共 48 种可能的状态转换。
  没人会想手动枚举所有转换来合并等效的转换并排除所有不可能的情况。相反,如果我们用逻辑表达我们从状态图中确定的删除和插入的约束,以及数据路径上可能的转换,那么我们几乎可以轻松获得状态转换逻辑和数据路径控制信号逻辑。
  让我们描述数据路径的可能状态,并对其进行初始化。此代码描述了二进制状态编码,但CAD工具可以对状态编码进行重新编码和重新编号。

    localparam STATE_BITS = 2;

    localparam [STATE_BITS-1:0] EMPTY = 'd0; // Output and buffer registers empty
    localparam [STATE_BITS-1:0] BUSY  = 'd1; // Output register holds data
    localparam [STATE_BITS-1:0] FULL  = 'd2; // Both output and buffer registers hold data
    // There is no case where only the buffer register would hold data.

    // No handling of erroneous and unreachable state 3.
    // We could check and raise an error flag.

    wire [STATE_BITS-1:0] state;
    reg  [STATE_BITS-1:0] state_next = EMPTY;

  现在,让我们表达我们从状态图中得出的约束:
     1. 输入接口只能在数据路径不处于FULL时接受数据。
     2. 只有当数据路径不为Empty时,输出接口才能读出数据。
  我们通过根据数据路径FSM的状态计算允许的读出时的valid/ready握手信号。我们使用state_next所以我们可以有很好的寄存器输出。这段代码删掉了大量无效的状态转换。
  这段代码很关键,因为它还暗示了pipeline缓冲区的基本操作假设:上游接口的当前状态不能依赖于下游接口的当前状态,否则会有组合路径也就起不到时序优化。
  计算上游的ready信号(非满不写)。

    Register
    #(
        .WORD_WIDTH     (1),
        .RESET_VALUE    (1'b1) // EMPTY at start, so accept data
    )
    input_ready_reg
    (
        .clock          (clock),
        .clock_enable   (1'b1),
        .clear          (clear),
        .data_in        (state_next != FULL),
        .data_out       (input_ready)
    );

  计算下游的valid信号(非空可读)。

    Register
    #(
        .WORD_WIDTH     (1),
        .RESET_VALUE    (1'b0)
    )
    output_valid_reg
    (
        .clock          (clock),
        .clock_enable   (1'b1),
        .clear          (clear),
        .data_in        (state_next != EMPTY),
        .data_out       (output_valid)
    );

  之后,让我们描述实现我们在数据路径模块上的两个基本操作的接口信号条件:读入和读出握手。这消除了许多可能的状态转换。

    reg insert = 1'b0;
    reg remove = 1'b0;

    always @(*) begin
        insert = (input_valid  == 1'b1) && (input_ready  == 1'b1);
        remove = (output_valid == 1'b1) && (output_ready == 1'b1);
    end

  现在我们有了数据路径的状态和操作,让我们用它们来描述对数据路径的可能转换,以及它们可能发生的状态。你会看到这些准确地描述了状态图中的5条边,并且由于我们修剪了不必要的逻辑,使用了最少的逻辑来描述它们。

    reg load    = 1'b0; // Empty datapath inserts data into output register.
    reg flow    = 1'b0; // New inserted data into output register as the old data is removed.
    reg fill    = 1'b0; // New inserted data into buffer register. Data not removed from output register.
    reg flush   = 1'b0; // Move data from buffer register into output register. Remove old data. No new data inserted.
    reg unload  = 1'b0; // Remove data from output register, leaving the datapath empty.

    always @(*) begin
        load    = (state == EMPTY) && (insert == 1'b1) && (remove == 1'b0);
        flow    = (state == BUSY)  && (insert == 1'b1) && (remove == 1'b1);
        fill    = (state == BUSY)  && (insert == 1'b1) && (remove == 1'b0);
        flush   = (state == FULL)  && (insert == 1'b0) && (remove == 1'b1);
        unload  = (state == BUSY)  && (insert == 1'b0) && (remove == 1'b1);
    end

  现在我们只需要计算每次数据路径转换后的下一个状态:

    always @(*) begin
        state_next = (load   == 1'b1) ? BUSY  : state;
        state_next = (flow   == 1'b1) ? BUSY  : state_next;
        state_next = (fill   == 1'b1) ? FULL  : state_next;
        state_next = (flush  == 1'b1) ? BUSY  : state_next;
        state_next = (unload == 1'b1) ? EMPTY : state_next;
    end

    Register
    #(
        .WORD_WIDTH     (STATE_BITS),
        .RESET_VALUE    (EMPTY)         // Initial state
    )
    state_reg
    (
        .clock          (clock),
        .clock_enable   (1'b1),
        .clear          (clear),
        .data_in        (state_next),
        .data_out       (state)
    );

  同样,从控制FSM转换中,我们可以计算数据路径所需的所有控制信号。

    always @(*) begin
        data_out_wren     = (load  == 1'b1) || (flow == 1'b1) || (flush == 1'b1);
        data_buffer_wren  = (fill  == 1'b1);
        use_buffered_data = (flush == 1'b1);
    end

endmodule

  对于64bit连接,生成的pipeline缓冲器使用128个寄存器,4到9个寄存器用于FSM和接口输出,具体取决于CAD工具选择的特定状态编码,并且很容易达到高运行速度。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5590

    浏览量

    129111
  • 缓冲器
    +关注

    关注

    6

    文章

    2215

    浏览量

    48703
  • 高电平
    +关注

    关注

    6

    文章

    225

    浏览量

    22698
  • AXI
    AXI
    +关注

    关注

    1

    文章

    143

    浏览量

    17799

原文标题:AXI握手时序优化——pipeline缓冲器

文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    【芯片设计】握手协议的介绍与时序说明

    最早接触到握手协议是在校期间学习PCIe的AXI总线时,至今日虽然PCIe的结构已经忘得一干二净,但握手协议经过不断的使用还算掌握的不错。
    的头像 发表于 12-11 14:11 5248次阅读
    【芯片设计】<b class='flag-5'>握手</b>协议的介绍与<b class='flag-5'>时序</b>说明

    为什么你的缓冲器要么输出电平乱跳,要么直接不输出

    缓冲器
    一兀科技
    发布于 :2022年09月15日 16:20:29

    高性能DAQ系统的ADC电压基准两级缓冲器优化设计

    描述适用于高性能 DAQ 系统的 TIDA-01055 参考设计优化了 ADC 基准缓冲器,以提高 SNR 性能并降低功耗(使用 TI OPA837 高速运算放大器)。该器件用于复合缓冲器配置
    发表于 12-07 11:51

    请问如何扩展AXI VDMA帧缓冲器

    为了减少VDMA调用的数量,我需要一个更大的帧缓冲32.我想扩展它,但我没有找到任何源文档或验证测试平台。有人可以推荐一种方法吗?我还考虑过使用AXI DMA。使用分辨率,我可以缓冲超过32帧,但仍然不够。感谢您的支持!
    发表于 04-27 08:05

    大电流缓冲器

    大电流缓冲器 通过4049非门
    发表于 09-11 10:47 3339次阅读
    大电流<b class='flag-5'>缓冲器</b>

    缓冲器,缓冲器是什么?

    缓冲器,缓冲器是什么? buffer   中文译名: 缓冲缓冲器缓冲液  解释:1、 电信设备。在数据传输中,用来弥补不同数据处
    发表于 03-08 13:30 2721次阅读

    缓冲器,缓冲器基本原理是什么?

    缓冲器,缓冲器基本原理是什么? 最基本线路构成的门电路存在着抗干扰性能差和不对称等缺点。为了克服这些缺点,可以在输出或输
    发表于 09-03 19:10 9839次阅读

    三态缓冲器介绍

    三态缓冲器三态缓冲器三态缓冲器三态缓冲器三态缓冲器三态缓冲器三态
    发表于 11-16 11:59 0次下载

    缓冲器的工作原理及它的作用

    缓冲器分为输入缓冲器和输出缓冲器两种;输入缓冲器的作用是将外设送来的数据暂时存放,以便处理将它取走,输出
    的头像 发表于 08-25 17:31 2.8w次阅读

    什么是时钟缓冲器(Buffer)?时钟缓冲器(Buffer)参数解析

    什么是时钟缓冲器(Buffer)?时钟缓冲器(Buffer)参数解析 什么是时钟缓冲器(Buffer)?我们先把这个概念搞清楚。 时钟缓冲器就是常说的Clock Buffer,通常是指
    发表于 10-18 18:36 3w次阅读
    什么是时钟<b class='flag-5'>缓冲器</b>(Buffer)?时钟<b class='flag-5'>缓冲器</b>(Buffer)参数解析

    液压缓冲器怎么调节

    液压缓冲器强度是否能够调节,取决于液压缓冲器的种类,目前市面上较为常用的液压缓冲器包括可调液压缓冲器、不可调液压缓冲器,这两种
    发表于 04-24 16:12 4873次阅读

    AXI4协议五个不同通道的握手机制

    AXI4 协议定义了五个不同的通道,如 AXI 通道中所述。所有这些通道共享基于 VALID 和 READY 信号的相同握手机制
    的头像 发表于 05-08 11:37 1990次阅读
    <b class='flag-5'>AXI</b>4协议五个不同通道的<b class='flag-5'>握手</b>机制

    封装寄存进VO缓冲器的概念及其优点简析

    许多FPGA有构造在输入和输出缓冲器中的触发优化芯片的时序入和出。同时这些专门的IO缓冲器是使能或禁止把这些寄存
    的头像 发表于 04-01 11:37 1452次阅读
    封装寄存<b class='flag-5'>器</b>进VO<b class='flag-5'>缓冲器</b>的概念及其优点简析

    缓冲器是干嘛的

    缓冲器是干嘛的 缓冲器是一种广泛应用于电子、电气、通信、计算机、自动化控制等领域的电子元件。它的作用是在电路中起到稳定电压、电流、信号等参数的作用,以保证电路的正常工作和性能。本文将详细介绍缓冲器
    的头像 发表于 06-10 16:06 1.1w次阅读

    时钟缓冲器在现代化建设中的作用

    的同步性和系统的稳定性,成为支撑现代电子设备不可或缺的“心脏”。一、时钟缓冲器的基本功能时钟缓冲器主要用于调整和优化时钟信号,保证数据在传输过程中的时序准确性。它可
    的头像 发表于 05-27 14:08 501次阅读
    时钟<b class='flag-5'>缓冲器</b>在现代化建设中的作用