当前位置: 首页 > news >正文

FPGA工程师面试资料【22】—— 握手机制的实现

FPGA工程师面试资料【22】—— 握手机制的实现

  • 握手机制
    • 核心握手机制:vld 与 rdy
    • 逐级反压 (Backpressure) 的实现
    • 设计要点与常见实现
    • 总结
  • 不带存储器的逐级反压
  • 数据累加输出

握手机制

核心握手机制:vld 与 rdy

这两个信号共同构成了一个双向握手协议,用于控制数据在模块间的可靠传输。

  • vld (输出信号):由数据发送方(上游模块)产生。当vld = 1时,表示当前时钟沿上,输出端口data上的数据是有效的、可用的;
  • rdy (输入信号):由数据接收方(下游模块)产生。当rdy = 1时,表示接收方当前时钟周期内可以接收新数据。rdy = 0表示接收方内部缓冲区已满或正忙,无法接收。

数据传输成功的条件:在一个时钟上升沿,只有当vld && rdy同时为高时,数据才被成功从发送方传递到接收方。我们通常称此时发生了一次握手成功或数据传递。

时序行为示例:

  1. 发送方有数据要发 (vld=1),但接收方没准备好 (rdy=0) -> 数据保持不动,等待下一个周期。
  2. 发送方没数据 (vld=0),接收方准备好了 (rdy=1) -> 无数据传输。
  3. 双方都就绪 (vld=1, rdy=1) -> 数据成功传输,发送方可以在下一个周期更新数据(或保持)。

这种机制确保了:数据不会因为接收方未准备好而丢失,发送方也不会在接收方忙碌时盲目发送无效数据。

逐级反压 (Backpressure) 的实现

在实际的流水线或处理链中,模块往往是串联的。一个模块同时是上游模块的“接收方”,又是下游模块的“发送方”。rdy 信号可以像波浪一样,从数据流的末端(最终消费者,如DDR控制器、输出接口)逐级向前传递,直到最源头(数据生产者,如传感器接口、DMA),从而控制整个数据流的启停。这就是“逐级反压”。

关键点:一个模块的输出 rdy(告诉上游“我是否可以接收”),通常取决于两件事:

  1. 模块自身内部的状态(如 FIFO 是否将满、处理单元是否忙碌)。
  2. 模块的下游是否就绪(即来自下游的输入 rdy 信号)。

举例:一个三级流水线处理链
假设有三个模块串联:A -> B -> C。数据从 A 流到 C。

  • C 是最终端。它的rdy_out可能由外部决定(如输出FIFO满信号);
  • B 的rdy_out(输出给 A)的计算逻辑通常是:B_rdy_out = (B 内部有空间) && (C_rdy_out == 1)。即,B 只有在自己能存数据并且下游 C 也能接收时,才会告诉 A “我准备好了”;
  • A 的rdy_out(可能连接更上游)计算逻辑:A_rdy_out = (A 内部有空间) && (B_rdy_out == 1)

反压传播过程:

  1. 如果 C 因为输出堵塞而拉低rdy_out (C_rdy_out=0)
  2. 则 B 发现下游不就绪,即使自己内部有空间,也会立即拉低自己的B_rdy_out为 0。
  3. A 看到B_rdy_out=0,随即也拉低自己的A_rdy_out
  4. 瞬间,整个数据流从 C 到 A 的源头都暂停了。直到 C 的堵塞解除,rdy信号才会从 C 到 B 再到 A 逐级恢复为高,数据流重新开始。

设计要点与常见实现

  1. 组合逻辑路径:rdy信号通常是组合逻辑产生的(如rdy = !fifo_almost_full),而vld通常是寄存器输出。需要注意rdy信号组合逻辑路径过长可能成为时序瓶颈,因为它需要在一个周期内从末端传播到源头。
  2. FIFO 是解耦反压的利器:在两级处理模块之间插入一个 FIFO(如 AXI-Stream 中的 TREADY 信号通常与 FIFO 的空满状态相关)。FIFO 提供了一定的数据缓冲能力,允许生产者和消费者短暂地独立工作,缓解了反压的严格性。只有当 FIFO 快满时,才会向上游发出反压信号 (rdy=0)。
  3. Skid Buffer:一种非常常用且高效的实现方式,用于在rdy突然变低时,临时缓存一个来不及收回的数据。它本质上是一个深度为1或2的微型 FIFO,用少量寄存器实现了握手机制,且时序很好。
  4. 性能与面积权衡:反压机制保证了正确性,但可能降低峰值吞吐率。通过增加缓冲(FIFO深度)可以提高吞吐,但会增加资源消耗。设计时需要平衡。
  5. 标准接口:工业标准如 AXI-Stream 的核心就是基于 TVALID 和 TREADY 的握手机制。理解了这个,就理解了 AXI-Stream 的精髓。

总结

vld/rdy握手机制是 FPGA 数据流设计的“交通规则”,它通过简单的信号交互,确保了数据在异步时钟域或不同处理速度模块间可靠传输。逐级反压是该机制的自然结果,它使得系统能够根据最慢环节的动态状态进行自我调节,是构建可伸缩、高鲁棒性数字系统的基石。在设计时,结合 FIFO 或 Skid Buffer 来优化反压路径,是达到高性能的关键。


不带存储器的逐级反压

module hand_shake#( parameter DW = 8 )( input clk, input rst_n, output data_i_ready, input data_i_valid, input [DW-1:0] data_i, input data_o_ready, output data_o_valid, output [DW-1:0] data_o ); // ------------------- // signals def // ------------------- reg valid_l1; wire ready_l1; reg [DW-1:0] data_l1; reg valid_l2; wire ready_l2; reg [DW-1:0] data_l2; reg valid_l3; wire ready_l3; reg [DW-1:0] data_l3; // ------------------- // pipe logic // ------------------- // l0 assign data_i_ready = ~valid_l1 || ready_l1; // l1 always @ (posedge clk or negedge rst_n) begin if(!rst_n) valid_l1 <= 0; else if(data_i_ready) valid_l1 <= data_i_valid; end assign ready_l1 = ~valid_l2 || ready_l2; always @ (posedge clk) begin if(data_i_ready && data_i_valid) data_l1 <= data_i + 1; end // l2 always @ (posedge clk or negedge rst_n) begin if(!rst_n) valid_l2 <= 0; else if(ready_l1) valid_l2 <= valid_l1; end assign ready_l2 = ~valid_l3 || ready_l3; always @ (posedge clk) begin if(ready_l1 && valid_l1) data_l2 <= data_l1 * 2; end // l3 always @ (posedge clk or negedge rst_n) begin if(!rst_n) valid_l3 <= 0; else if(ready_l2) valid_l3 <= valid_l2; end assign ready_l3 = data_o_ready; always @ (posedge clk) begin if(ready_l2 && valid_l2) data_l3 <= data_l2 + 3; end // ------------------- // output // ------------------- assign data_o_valid = valid_l3; assign data_o = data_l3; endmodule

数据累加输出

实现串行输入数据累加输出,输入端输入8bit数据,每当模块接收到4个输入数据后,输出端输出4个接收到数据的累加结果。输入端和输出端与上下游的交互采用valid-ready双向握手机制。要求上下游均能满速传输时,数据传输无气泡,不能由于本模块的设计原因产生额外的性能损失。其中valid_a用来指示数据输入data_in的有效性,valid_b用来指示数据输出data_out的有效性;ready_a用来指示本模块是否准备好接收上游数据,ready_b表示下游是否准备好接收本模块的输出数据;

module valid_ready( input clk , input rst_n , input [7:0] data_in , input valid_a , input ready_b , output ready_a , output reg valid_b , output reg [9:0] data_out ); reg [1:0] data_cnt; assign ready_a = (!valid_b) | ready_b;//如果下游ready_b拉高,表示下游可以接收模块输出数据,那么此时ready_a应拉高,即本模块可以接收上游数据;如果没有接收够4个数据,即valid_b未拉高,那么表示本模块仍可以接收上游数据此时ready_a应拉高。 always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_cnt <= 'd0; else if(valid_a && ready_a) data_cnt <= (data_cnt == 2'd3) ? 'd0 : (data_cnt + 1'd1); end // 当和上游正常通讯时(即valid_a和ready_a均为高),数据正常接收,但注意计数了4个就得加起来输出一次,所以data_cnt == 2'd3时拉高valid_b;而等待下游接收,即当ready_b也拉高表示接收完成,则拉低valid_b,保证只有在四个数之和的时候才拉高。 always @(posedge clk or negedge rst_n ) begin if(!rst_n) valid_b <= 'd0; else if(data_cnt == 2'd3 && valid_a && ready_a) valid_b <= 1'd1; else if(valid_b && ready_b) valid_b <= 1'd0; end // 同理,当和上游正常通讯时(即valid_a和ready_a均为高),数据正常接收,数据累加, always @(posedge clk or negedge rst_n ) begin if(!rst_n) data_out <= 'd0; else if(valid_a && ready_a && (data_cnt == 2'd0)) data_out <= data_in; else if(valid_a && ready_a) data_out <= data_out + data_in; end endmodule

💓 💖 💓 💖 🍉 🌈 🍓 🕔 ~ 本节完结 ~ 🕔 🍓 🌈 🍉 💖 💓 💖 💓

关注以下公众号了解更多:

http://www.jsqmd.com/news/933519/

相关文章:

  • AS5047P磁性编码器SPI通信避坑指南:为什么你的角度值总跳变?
  • 别再只调Prompt了!用Qwen-VL-Chat实战多图对话与细粒度视觉问答(保姆级教程)
  • 东南大学密码学课设用ElGamal加解密C++工程:含可运行代码与填空式实验报告
  • 别急着买新Mac!用Parallels Desktop在Intel芯片的Mac上体验Windows 11,这份配置指南请收好
  • 2026武汉配眼镜推荐,梅雨季一个月没太阳,孩子视力悄悄下降 - 配眼镜新资讯
  • 微软开放数据项目:从数据可用到研究可复现的实践指南
  • ROI 计算模板 把错误成本 合规成本 机会成本一起算清
  • 如何使用Forza Painter将任意图片转化为Forza车辆涂装:完整指南
  • 如何3分钟完成B站缓存视频转换:m4s转MP4完整教程
  • 【字节跳动】·南京江北新区机房(北纬32.2287°,东经118.6742°)
  • 告别卡顿!Unity 2020.3 LTS安卓高刷屏适配指南:从deltaTime波动到帧率稳定
  • 别再死记硬背了!用STM32F103C8T6最小系统板,手把手教你理解复位、时钟与启动电路
  • 基于 UCI 真实数据的城市 PM2.5 预测与预警系统实战
  • 一线名师闭门分享:用Sora 2 72小时内完成一学期16节AI增强型实验课视频(含物理/化学/生物全科案例包)
  • Kronos股票预测模型:基于深度学习的金融时间序列预测解决方案
  • 智能体的可解释性:用户信任的关键因素
  • 基于 RAG 的三级工单智能分类系统:从自然语言到工单分类的完整落地方案
  • 当SCP收容失效:用Unreal Engine 5构建一个基于SCP-136的心理恐怖游戏原型
  • Hermes WebUI HTML作为Python原始字符串:ADR-002决策解析
  • 开源跨平台音乐聚合解决方案:LX Music桌面版的技术创新与实践价值
  • 保姆级教程:用Adams/Car和Simulink搞定整车联合仿真(附模型文件)
  • 手把手教你给Nginx服务器开启IPv6访问(附本地测试与验证全流程)
  • FPGA跨时钟域信号处理:从亚稳态的‘山顶滚球’到实战中的同步器链设计
  • 别再只仿真了!用ILA抓取Vivado FIFO IP核的真实波形,深度解读full/empty信号时序
  • AI Agent工具链集成:API与RAG
  • 从ROS Bag到YOLOv5模型:手把手教你打造车载交通信号灯识别系统(Ubuntu 20.04环境)
  • Solana智能代理安全架构:基于闭包的密钥隔离与确定性决策引擎
  • 茅台预约自动化神器:5分钟部署的智能抢购解决方案
  • 别再死记硬背代码了!拆解C51按键控制LED的底层逻辑与寄存器操作
  • OBS StreamFX插件:从零开始打造专业级直播画面的完整指南