数字前端/FPGA设计——握手与反压问题


 声明:本文来自0431大小回


前言:在芯片设计或者FPGA设计过程中,流水设计是经常用到的,但是考虑数据安全性,需要与前后级模块进行握手通信,这时候就需要对流水数据进行反压处理,本文将具体介绍握手与反压。

目录

  • 握手协议
  • 握手与反压
  • 反压
  • 带存储体的反压
    • 字节的问题
    • 代码分析
    • 逐级反压与跨级反压
  • 不带存储体的反压
    • 代码分析

握手协议

本文讲述valid-ready握手,下面列出三种握手情况,目的是解释清楚握手的时序。

  • valid先发起请求

  • ready先发起请求

  • 同时发起请求

  • 分析

仔细观察上述3幅时序图,我们了解valid-ready握手机制需要注意三件事:

  1. valid与ready不可过度依赖,比如valid不可以等待ready到达再拉高,但是在axi协议中的握手信号,ready是可以等待valid拉高再拉高的,valid不可依赖ready的原因是防止死锁(deadlock),本文的代码他俩彼此可以互相独立发出请求拉高;
  2. valid拉高时与有效数据同步,时钟要对齐;
  3. 当数据计算好后,valid可以拉高等待ready拉高,但是每当握手成功之后,数据需要更新,如果此时没有新的有效数据,valid要拉低。

握手与反压

当入口流量大于出口流量,这时候就需要反压,或者,当后级未准备好时,如果本级进行数据传递,那么它就需要反压前级,所以此时前级需要将数据保持不动,直到握手成功才能更新数据。而反压在多级流水线中就变得稍显复杂,原因在于,比如我们采用三级流水设计,如果我们收到后级反压信号,我们理所当然想反压本级输出信号的寄存器,但是如果只反压最后一级寄存器,那么会面临一个问题,就是最后一级寄存器数据会被前两级流水冲毁,导致数据丢失,引出数据安全问题,所以我们此时需要考虑反压设计。

反压

常用的反压方法有三种:

  • 不带存储体的反压

也就是后级反压信号对本级模块中所有流水寄存器都进行控制,由于不包含存储体,为了保证数据安全性,后级反压信号可以同时反压本模块中所有流水寄存器。

优点:节省面积资源

缺点:寄存器端口控制复杂

适用情况:流水线深度较大时

  • 带存储体的逐级反压

如果流水级数不深,可以在每一需要握手交互模块增加存储体,原理上相当于,如果后级发出反压信号,可以直接对本级流水线数据源头进行反压,其余中间级不需控制,但后级需要包含RAM或FIFO等存储体,可以接收流水,并需设置水线(water line),确定反压时间,防止数据溢出,保证数据安全性。

优点:各级流水寄存器端口控制简单

缺点:需要额外存储体

适用情况:流水线深度较小,每一模块都包含存储体时

  • 带存储体的跨级反压

很多时候在具体设计过程中,颗粒度划分不精细,反压这时候是对模块而言,而不是说模块内部有多少级流水。此外,并不是每一模块都带有存储体。比如,其中可能a模块没有存储体,b模块没有存储体,但ab模块内部还有多级流水,如果c模块有存储体,并且需要反压前级模块,这时候可以选择反压a模块的源头输入数据,然后将ab的流水都存储到带有存储体的c模块,但是如果ab不是都没有存储体的话,就不应该跨级反压,而应该逐级反压,具体原因后续会讲。

优点:控制简单方便

缺点:需要额外存储体,模块间耦合度高

适用情况:某些模块带存储体,某些模块不带存储体时

带存储体的反压

如上文所述,很多时候我们不喜欢对每一级细分流水都进行反压,所以可以选择带存储体的反压,也就是增加RAM或者FIFO,在反压上级模块的同时,本级有足够的深度来存储上一级的流水数据。具体内容如下图所示:

此时我们假设车库就是最后一级模块,需要对前一级进行反压,车库是带有存储体的模块,那么此时就需要设计水线waterline,也就是当waterline为多少时开始反压前一级模块(车库入口闸机)。由上图可知,当waterline最大为90时,必须向上一模块发出反压请求,因为在途的还有10辆车,这个就相当于我们设计的10级流水,其中有10级寄存器有流水数据输出,所以车库的剩余容量还可以存储住途中流水,保证了数据安全。

举个例子——字节的问题

问题:设计一个并行6输入32比特加法器,输出1个带截断的32比特加法结果,要求用三级流水设计,带前后反压。

主要输入:

  1. 6个32bit数据
  2. 上一级的valid_i
  3. 下一级的ready_i

输出:

  1. 1个32bit结果
  2. 给上一级的ready_o
  3. 给下一级的valid_o
  • 分析

其实在多级流水设计中,如果每一级只有一个寄存器,并且都在一个模块中,也就是说当颗粒度划分的很细的时候,一般使用带存储体的反压,比如六级流水,那么就设计好水线,在FIFO未满时提前发出反压信号,一般水线设为FIFO_DEPTH - 流水级数,下面是我设计的代码。

核心思想就是如果FIFO未达到水线(WATERLINE)时,给上一级的反压信号ready_o就持续拉高,否则拉低;FIFO非空时就可以给下一级valid_o拉高,然后下一级的反压信号ready_i可以作为FIFO的读使能信号,具体请参考下文代码。

//还未仿真,欢迎指出问题
module handshake_fifo #(parameter           FIFO_DATA_WIDTH = 32,parameter           FIFO_DEPTH = 8
)(input  wire         clk,input  wire         rst,input  wire         valid_i,input  wire         ready_i,input  wire  [31:0] a,input  wire  [31:0] b,input  wire  [31:0] c,input  wire  [31:0] d,input  wire  [31:0] e,input  wire  [31:0] f,output logic [31:0] dout,output logic        ready_o,output logic        valid_o);localparam          WATERLINE = FIFO_DEPTH - 3; //three levels' pipelinelogic               handshake;logic               handshake_ff1;logic               handshake_ff2;logic               wr_en;assign handshake = ready_o & valid_i;always @ (posedge clk or posedge rst) beginif(rst) beginhandshake_ff1 <= '0;handshake_ff2 <= '0;endelse beginhandshake_ff1 <= handshake;handshake_ff2 <= handshake_ff1;endendreg [31 : 0] r1_ab;always @ (posedge clk or posedge rst) beginif(rst) beginr1_ab <= '0;endelse if(handshake)beginr1_ab <= a + b;endendreg [31 : 0] r1_cd;always @ (posedge clk or posedge rst) beginif(rst) beginr1_cd <= '0;endelse if(handshake)beginr1_cd <= c + d;endendreg [31 : 0] r1_ef;always @ (posedge clk or posedge rst) beginif(rst) beginr1_ef <= '0;endelse if(handshake)beginr1_ef <= e + f;endendreg [31 : 0] r2_abcd;always @ (posedge clk or posedge rst) beginif(rst) beginr2_abcd <= '0;endelse if(handshake_ff1) beginr2_abcd <= r1_ab + r1_cd;endendreg [31 : 0] r2_ef;always @ (posedge clk or posedge rst) beginif(rst) beginr2_ef <= '0;endelse if(handshake_ff1) beginr2_ef <= r1_ef;endendreg [31 : 0] r3;always @ (posedge clk or posedge rst) beginif(rst) beginr3 <= '0;endelse if(handshake_ff2) beginr3 <= r2_ef + r2_abcd;endendalways @ (posedge clk or posedge rst) beginif(rst) beginwr_en <= 1'b0;endelse if(handshake_ff2) beginwr_en <= 1'b1;endelse beginwr_en <= 1'b0;endendalways_ff @(posedge clk)beginif(rst)beginready_o <= 1'b0;endelse if(usedw > WATERLINE)beginready_o <= 1'b0;endelse beginready_o <= 1'b1;endendassign valid_o = ~empty;sync_fifo # (.MEM_TYPE   ("auto"         ),.READ_MODE  ("fwft"         ),.WIDTH      (FIFO_DATA_WIDTH),.DEPTH      (FIFO_DEPTH     ))fifo_inst(.clk    (clk                ), // input  wire.rst_n  (rst_n              ), // input  wire.wren   (wr_en              ), // input  wire.din    (r3                 ), // input  wire [WIDTH-1:0].rden   (ready_i            ), // input  wire.dout   (dout               ), // output reg  [WIDTH-1:0].empty  (empty              ), // output wire.usedw  (usedw              ));endmodule

逐级反压与跨级反压

这时候的反压包括逐级反压和跨级反压,具体区别可以参考下图:

由上图可见,3个模块都包含存储体,我们假设此时module3到达了它的水线,那么它有两种方式反压前面的模块,一种是从最源头进行反压,另一种是逐级反压。

建议:当每一模块都有存储体时,建议逐级反压。

原因:如果逐级反压的话,方法就是module3到达水线则反压module2,module2到达水线反压module1,每一级的水线和存储体大小设计就如上文车库模型所述,简单清晰。但是,如果选择跨级反压,那么module3的存储体深度 = waterlie3 + 在途1 + waterline1 + 在途2 + waterline2 + 在途3,可见每一级的存储体会变大并且水线计算复杂,另外路径变长,模块间耦合度增高,不利于复用与维护。但是,如果不是每一模块都包含存储体,那么可以选择跨级反压。

不带存储体的反压

分析与代码

同样是上文字节的问题,如果此时要求不允许使用FIFO,那应该怎么设计呢?

核心思想就是保证每一级流水中的每一级寄存器的数据安全,可以把每一级寄存器当成一个深度为1的FIFO,下一级有无数据可以看对应的valid信号。下一级无数据或者下一级已经准备好了,那么就可以向上一级取数据,本质上是pre-fetch结构。具体内容可以参考如下代码,注意:我没有把重复部分的代码写全,但是写出了所有核心代码,可供参考。

module handshake_pb #(
)(input  wire         clk,input  wire         rst,input  wire         valid_i,output wire         ready_o,input  wire  [31:0] a,input  wire  [31:0] b,input  wire  [31:0] c,input  wire  [31:0] d,input  wire  [31:0] e,input  wire  [31:0] f,output wire  [31:0] dout,input  wire         ready_i,output reg          valid_o);assign ready_o = ~valid_r1 || ready_r1;//pre_fetch结构//valid_r1为0代表下一级无数据//ready_r1代表下一级准备好了读always_ff @ (posedge clk) begin if(rst)beginvalid_r1    <= 1'b0;endelse if(ready_o)beginvalid_r1    <= valid_i;endendalways_ff @ (posedge clk) beginif(ready_o & valid_i)beginr1_ab       <= a + b;   //数据信号不复位endendassign ready_r1 = ~valid_r2 || ready_r2;reg [31 : 0] r2_abcd;always_ff @ (posedge clk) begin if(rst)beginvalid_r2    <= 1'b0;endelse if(ready_r1)beginvalid_r2    <= valid_r1;endendalways_ff @ (posedge clk) beginif(ready_r1 & valid_r1)beginr2_abcd     <= r1_ab + r1_cd;endendassign ready_r2 = ~valid_r3 || ready_i;reg [31 : 0] r3;always_ff @ (posedge clk) begin if(rst)beginvalid_r3    <= 1'b0;endelse if(ready_r2)beginvalid_r3    <= valid_r2;endendalways_ff @ (posedge clk) beginif(ready_r2 & valid_r2)beginr3          <= r2_ef + r2_abcd;endendassign dout     = r3;assign valid_o  = valid_r3;
endmodule

值得大家注意的是ready和valid的输入输出,此外就是每一级流水的握手信号处理。

对于不带存储体的反压,

不带存储体的反压的主要缺点还是timing差,不适合长流水。流水线最下游的ready会一路传导到最上游,会导致组合逻辑过长,引起时序问题。可以考虑中间再加一级寄存器,输出一级寄存器,可以参考xilinx的axis handshake ip。

此外,这里的代码按照握手协议,valid不能够看ready信号,但是ready是可以等valid来了再拉高的。如果下一级ready信号初始一直为0,输出的valid也会一直为0,这样就死锁了。这个代码主要还是为了解决这道题,不能用作标准模块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/627079.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源内网穿透工具FRP配置SSH和网站访问,构建本地私有云NAS,非常详细的配置细节,复刻即可成功

简介&#xff1a; FRP 是一个可用于内网穿透的高性能的反向代理应用&#xff0c;支持 tcp, udp 协议&#xff0c;为 http 和 https 应用协议提供了额外的能力&#xff0c;且尝试性支持了点对点穿透。名称其实就是使用了 Fast Reverse Proxy 的首字母缩写。 需求&#xff1a; 有…

基于英特尔傲腾持久内存的下一代高性能计算存储系统DAOS

本文内容来自 Intel极限存储架构和开发首席工程师 梁震 在2021CCF全国高性能计算学术年会&#xff08;CCF HPC China 2021&#xff09;上的演讲资料&#xff0c;供大家参考。 目录 - 分布式异步对象存储(DAOS)的系统架构 - DAOS系统栈结构 - DAOS 的部署方式 - DAOS 存储服…

WebGL在家居设计领域中的应用

WebGL&#xff08;Web Graphics Library&#xff09;是一种用于在Web浏览器中进行3D图形渲染的JavaScript API。在家居设计方面&#xff0c;WebGL可以提供一些强大的应用&#xff0c;使用户能够交互式地浏览和体验设计方案。以下是一些家居设计领域中WebGL的应用&#xff0c;希…

蓝桥杯:随意组合

题目描述&#xff1a; 算法思路&#xff1a; 主要是将其中一个数组进行全排列&#xff0c;16中排列顺序&#xff0c;再与 另外一个数组进行匹配求和。在这里就要用到next_permutation()函数&#xff0c;具体用法就是直接用数组a[]&#xff0c;进行排序next_permutation(a&…

芯品荟|电梯外呼面板屏驱市场调研报告

PART ONE 产品简介 - Introduction - 1.电梯外呼面板介绍 电梯外呼面板&#xff0c;用于显示电梯当前位置、运行状态和楼层信息&#xff0c;以便乘客在等待电梯时了解电梯的运行情况。 电梯外呼面板&#xff0c;按显示屏的种类&#xff0c;分为3类&#xff0c;分别是LED屏、L…

处理HTTP请求中的表单数据

处理HTTP请求中的表单数据是Web开发中常见的任务。在Go语言中&#xff0c;可以使用net/http包来解析HTTP请求中的表单数据。 首先&#xff0c;确保你已经创建了一个HTTP服务器&#xff0c;并且能够接收和处理POST请求。然后&#xff0c;你可以使用r.ParseForm()函数来解析请求…

Android项目架构怎么做

项目架构指南 本指南包含一些最佳做法和推荐架构&#xff0c;有助于构建强大而优质的应用。 注意&#xff1a; 本页假定您对 Android 框架有基本的了解。 移动应用用户体验 典型的 Android 应用包含多个应用组件&#xff0c;包括 Activity、Fragment、Service、内容提供程序…

自然语言处理实战项目25-T5模型和BERT模型的应用场景以及对比研究、问题解答

大家好,我是微学AI,今天给大家介绍一下自然语言处理实战项目25-T5模型和BERT模型的应用场景以及对比研究、问题解答。T5模型和BERT模型是两种常用的自然语言处理模型。T5是一种序列到序列模型,可以处理各种NLP任务,而BERT主要用于预训练语言表示。T5使用了类似于BERT的预训…

融云 CEO 董晗入选「2023 福布斯中国 · 出海全球化人物 TOP30」

近日&#xff0c;福布斯中国发布“出海全球化 30&30”评选结果&#xff0c;融云 CEO 董晗入选“2023 福布斯中国 出海全球化人物 TOP30”。移步【融云全球互联网通信云】了解更多 在全球市场新秩序的构建中&#xff0c;中国品牌的影响力和作用日益凸显。针对中国出海全球…

操作系统课程设计:常用页面置换算法(OPT、FIFO、LRU)的实现及缺页率的计算(C语言)

名人说&#xff1a;莫听穿林打叶声&#xff0c;何妨吟啸且徐行。—— 苏轼《定风波莫听穿林打叶声》 Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#xff09; 目录 一、效果图二、代码&#xff08;带注释&#xff09;三、说明 一、效果图 二、代码&#xff08;带…

git中的语法和术语含义

目录 第一章、git常用术语1.1&#xff09;文件状态1.2&#xff09;git常用术语的含义 第二章、git文件状态解析2.1&#xff09;从git init开始&#xff1a;Untracked&#xff08;未跟踪&#xff09;2.2&#xff09;git add fileName后&#xff1a;Staged&#xff08;已暂存&…

超强文档搜索引擎AnyTXT Searcher本地搭建

文章目录 前言1. AnyTXT Searcher1.1 下载安装AnyTXT Searcher 2. 下载安装注册cpolar3. AnyTXT Searcher设置和操作3.1 AnyTXT结合cpolar—公网访问搜索神器3.2 公网访问测试 4. 固定连接公网地址 前言 你是否遇到过这种情况&#xff0c;异地办公或者不在公司&#xff0c;想找…

探索GpuMall智算云平台的AI云计算:SSH连接GPU云主机进行深度学习

#GpuMall# #GpuMall智算云# #算力租赁# #ai# 在人工智能和机器学习的领域中&#xff0c;获取强大的计算资源已经成为推进项目进展的关键。随着AI研究的深入&#xff0c;需求对GPU加速的计算能力也在不断提升。GPU云主机、GPU云服务器、GPU闲置、GPU变现、GPU收益、AI云、算力…

Copley高性能工业伺服驱动器制造者,为客户提供运动控制方案

在当今高度自动化的工业领域中&#xff0c;驱动器作为核心部件&#xff0c;其性能和稳定性对整个系统的运行至关重要。北京北成新控伺服技术有限公司深谙此道&#xff0c;成为Copley高性能工业伺服驱动器重要合作伙伴&#xff0c;以满足市场对于高精度、高动态性能的运动控制解…

入门实战丨Python小游戏经典案例

文章目录 写在前面判断与循环小游戏猜数游戏龙的世界 写在后面 写在前面 本期内容&#xff1a;两个个简单的Python小游戏入门案例。 实验需求&#xff1a;python 实验目标&#xff1a;掌握基本的判断与循环语句。 判断与循环 判断与循环是编程中非常重要的两个概念&#x…

Java零基础教学文档servlet(3)

【AJax】 1.传统开发模式的不足 传统开发模式基于浏览器数据传输功能,页面填写数据/展示数据。浏览器通过访问一个URL地址&#xff0c;将页面的数据提交给服务器。服务器将需要展示的数据返回给浏览器&#xff0c;浏览器再进行数据解析&#xff0c;将数据呈现在用户面前。这种…

【复习】人工智能 第7章 专家系统与机器学习

专家系统就是让机器人当某个领域的专家&#xff0c;但这章专家系统不咋考&#xff0c;主要靠书上没有的机器学习。 一、专家系统的基本组成 二、专家系统与传统程序的比较 &#xff08;1&#xff09;编程思想&#xff1a; 传统程序 数据结构 算法 专家系统 知识 推理 &…

maya , motionbuilder 骨骼动画相关操作与脚本

文章目录 Maya导入时增加namespacemaya 解除/增加父子关系maya 修改骨骼局部坐标系显示骨骼局部坐标系删除不需要的骨骼重命名骨骼重定向基础细节 Motionbuildermb同时打开两个动画文件 Maya 导入时增加namespace import pymel.core as pm pm.namespace(add"src") …

SpringBoot项目打包

1.在pom.xml的build>plugins中加入如下配置 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.1.0</version><configuration>…

C++ STL--->stack和queue

文章目录 stackstack实现参考源码 queuequeue实现参考源码 stack stack文档 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行 元素的插入与提取操作。stack是作为容器适配器被实现的&#xff0c;容器适配器…