流水线中的握手信号笔记

news2024/11/25 18:38:42

1.《握手信号的打拍(一)》

解释了,为什么在流水线中,握手信号不能简单得加一级寄存器

业界关于流水线级握手信号的标准答案是 skid buffer,此外还有人提到了 Register slice

2.《握手信号的打拍(二)》

为什么简单加一级寄存器会握手失败 ?

从图1可以看出,加入 Handshake Pipe Module 之后,在 Sender 端有一组握手信号,在 Receiver 也有一组握手信号。也就是说,我们必须同时满足 Sender 端和 Receiver 端的握手,才能保证握手成功。

但是简单加一级寄存器只是满足一边的,图2是对 valid+data 打一拍,可以看出只能满足 Sender 端的握手时序。

如图,对 valid + data 打一拍,只满足了 Sender 端的握手时序

握手信号 valid 打拍的改进

观察图2,我们可以看到,Receiver 端不能满足握手时序的原因是 Sender 端认为数据已经被接收,从而拉低 valid,导致 valid_pipe 也被拉低。那么我们解决的办法应该是在 pipe 模块中保持住 valid 直到 receiver 端也握手成功,如图3所示。

图3 - handshake valid pipe example1

为了提高效率,我们可以在 IDLE 状态(即没有保持数据)时让 pipe 模块输出 ready_o 高电平,直到 Sender 端握手成功。接着保持住 valid 和 data,直到 Receiver 端也握手成功。如图4所示。

图4 - handshake valid pipe example2

图5是 Sender 端连续发送数据,但是 Receiver 端 ready 不连续的例子。可以看到 Sender 端有三次握手,Receiver 端也有三次握手。

图5 - handshake valid pipe example3

图6是 Sender 端连续发送数据,Receiver 端 ready 也连续的例子。

图6 - handshake valid pipe example4

后面有对 ready 信号打拍的内容,不明白为什么要打拍,我觉得现在这样就挺好,skip

3. 芯片设计-握手与反压(valid&ready)

从工厂流水线说起

本来一众打工人在流水线上"快快乐乐"地搬砖,突然receiver处理不过来了,拉低了data_o_ready。为避免数据丢失,得立刻启动应急方案。

应急方案1 (receiver 直接告知 sender 不接受新数据,同时使用 FIFO 接收流水线中的数据) (缺点:成本高)

receiver立刻通知sender,拉低data_i_ready(assign data_i_ready = data_o_ready),不允许再进新数据了。

(注:本章所有图示均用红色表示该pipe处于工作状态,无色表示该pipe处于空闲状态)

此时虽然没有新输入了,但是流水线中的搬砖人没有得到通知,还在继续工作。意味着流水线还会输出3个数据,但是receiver已经拒绝接收数据了。没办法,这时我们得放个fifo在流水线末尾,fifo深度等于流水线级数。

虽然这个方案解决了问题,但增加了fifo,提升了工厂成本。老板不允许,想想其他方案吧。

应急方案2 (reciver 暂停整个 sender 和所有流水级)     (缺点:流水级中没有被塞满的部分也会空转,每次流水线复位都会有气泡在悬停)

在这个方案中,receiver不仅通知sender暂停,还会通知整个pipe暂停。此时不会有数据输出,也不需要加fifo了。

但从上图我们可以看到,PIPE2是空闲的,这意味着虽然此时receiver拒绝接收,但其实没必要立刻停掉流水线的,完全可以再跑一拍流水的。可能打工人觉得没啥,等一下就好,但工厂老板可不是这样想的。

首先,出现pipe空闲的情况,都是在流水初始阶段,这时候后级流水需要等若干拍才能拿到数据来干活。而我们往往会在完成一次任务后复位流水,而每次复位都会存在PIPE空闲的情况。

我们假设一次任务处理16个数据,流水线为3级,处理完后需要复位流水线。

(注:在ISP中,一般是一帧为一次任务,在vblank期间复位流水线。这里为描述方便简化处理)

理想情况下,需要16+3拍才能完成任务,这里的3拍我们称之为气泡。这意味着对于receiver来说,他需要等待。老板不希望有气泡时间,希望的是他的receiver能够满负荷工作,即一旦receiver准备好了(data_o_ready为高),就能立刻接收到数据。

所以,方案还得改善……

应急方案3

我们得想办法挤掉气泡,别data_o_ready一拉低,大家就摸鱼,可以干的得继续干。

如方案2所提到的,气泡仅出现在流水线初始阶段,且持续拍数=流水级数。也就是说,在前几拍的时候,不用管data_o_ready什么状态,大家努力干活就是。

因此,我们添加一个计数器,当data_i_ready & data_i_valid有效时,计数器+1。当计数器小于流水级数时,流水线保持工作;当计数器≥流水级数时,流水线工作与否取决于data_o_ready.

本方案虽然把气泡挤掉了,但是控制会麻烦许多,因此:

  • 如果你的应用不在意这点气泡,比如一帧4K图像仅有几十拍的气泡,那用方案2也没啥问题。
  • 如果你的应用不会出现起始阶段,receiver不ready的情况,那也没必要用本方案

老板对本方案表示很满意,但我们可以继续想想有没有其他方案。

 目前看到应急方案4

应急方案4

逐级反压,只要我的后级空闲或ready, 我就传数据给他。

以下是代码。注意:以下代码要配合下面的图,才比较好看懂

用代码表示:

module pipe_ctrl #(
	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

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

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

相关文章

抖音SEO系统源码开发搭建/MVC二次开发定制

首先&#xff0c;抖音SEO矩阵系统源码开发&#xff0c;如何做独立部署&#xff0c;首先我们需要深刻理解这个系统的开发逻辑是什么&#xff1f;开发的前言是在抖音平台做流量新增&#xff0c;现在抖音及各大主流短视频平台&#xff0c;流量新增&#xff0c;各大企业需要在短视频…

Redis BigKey

Redis BigKey 一 面试题引入二 MoreKey案例2.1 大批量往redis里面插入2000W测试数据key2.1.1 Linux Bash下执行&#xff0c;插入100W2.1.2 通过redis提供的管道 --pipe命令插入100W大批量数据 2.2 key *2.3 生产上如何限制keys*/flushdb/flushall等危险命令以防止误删误用&…

我们在操作自动化测如何实现用例设计实例

在编写用例之间&#xff0c;笔者再次强调几点编写自动化测试用例的原则&#xff1a; 1、一个脚本是一个完整的场景&#xff0c;从用户登陆操作到用户退出系统关闭浏览器。 2、一个脚本脚本只验证一个功能点&#xff0c;不要试图用户登陆系统后把所有的功能都进行验证再退出系统…

【结构体-位段】

位段 在结构体中&#xff0c;以位为单位的成员&#xff0c;咱们称之为位段(位域)。 struct packed_data{unsigned int a:2;unsigned int b:6;unsigned int c:4;unsigned int d:4;unsigned int i; } data;注意&#xff1a;不能对位段成员取地址。 #include<stdio.h>str…

5.名词复数、动词规则、代词、形容词、副词(不包含不规则)

目录 一、 名词、动词、代词、形容词、副词五种的规则变化。 &#xff08;1&#xff09;名词。 &#xff08;1.1&#xff09;名词复数变化。 &#xff08;1.2&#xff09;名词所有格。 &#xff08;2&#xff09; 动词变化规则。 &#xff08;3&#xff09;代词。 &…

C语言-double和float在内存中的存储方式

本文主要介绍double和float数据类型在C语言中的存储方式 文章目录 double和float存储方式介绍如何存储&#xff1f; double和float存储方式介绍 从存储结构和算法上来讲&#xff0c;double和float是一样的&#xff0c;不一样的地方仅仅是float是32位的&#xff0c;double是64位…

【CAN卡通信的下位机-STM32cubeIDE-hal库+STMF1xx和STMF4xx+数据发送和接收+轮询接收方式+基础样例(1)】

【CAN卡通信的下位机-STM32cubeIDE-hal库数据发送和接收轮询接收方式基础样例1】 1、概述2、实验环境3、自我总结与提升(1)道理学习了一堆&#xff0c;如何使用STM32进行can的收发的话&#xff0c;配置还是挺简单。(2)自己实现了can的收发后&#xff0c;要反过来&#xff0c;补…

shell编程——Here Document免交互与Expect(免交互,高效率)

shell编程——Here Document免交互与Expect&#xff08;免交互&#xff0c;高效率&#xff09; 一、Here Document免交互概述二、Here Document常规用法1、免交互方式实现对行数地统计2、通过read/tee命令接受输入并打印3、通过passwd给用户设置密码4、支持变量替换5、整体赋值…

K8S基础操作之命令篇

目录 第一章.陈述式资源管理 1.1陈述式资源管理方法 1.2.基本命令查看信息 1.3.K8S管理操作分为2大类 1.4.数据网络端口访问流程 第二章.基本信息查看 2.1.命令格式 2.2.命令 2.3.项目的生命周期 第三章.service 3.1.概述 3.2.service 的 type 类型 3.3 headless …

神级指标DMI魔改免费公开!在宽基指数上也可以收获40倍收益,每年都在创新高!

一、写在前头 今天,我们要讲的DMI实际上是一组指标,它由表示多空方向的PDI、MDI以及表示趋势强度的ADX、ADXR共四条线组成。在正式开讲之前,我们先聊几句近期的行情。 上周我们根据量化策略提示了一些板块的机会,其中有一些已经开始有所表现。比如今天涨幅前十的板块中,…

【python笔记】可变对象和不可变对象

前言 在python中&#xff0c;一切事物皆是对象&#xff0c;变量是对象在内存中的存储和地址的抽象。类型也是属于对象的&#xff0c;而不是变量。变量和对象是分离的&#xff0c;对象是内存中储存数据的实体&#xff0c;变量则是指向对象的指针。 “”(赋值号)是将右侧对象的内…

网络编程与netty

目录 NIO 网络编程Buffer&#xff08;缓冲区&#xff09;Channel&#xff08;通道&#xff09;Selector&#xff08;选择器&#xff09;SelectionKey 零拷贝原生NIO存在的问题 线程模型传统阻塞 I/O 服务模型Reactor 模式单 Reactor 单线程单 Reactor 多线程主从 Reactor 多线程…

RabbitMQ养成记 (3.MQ的简单工作模式 和 Pub/sub 订阅模式)

上一篇是一个简单的helloworld。 我们直接发直接收 这种是最简单的。 下面我们再来接触更加复杂一点&#xff1a; 简单工作模式 work queues 工作队列模式&#xff1a; 这里注意 这里的消息 对两个消费者 c1 c2来说是竞争关系 而不是等份分发关系&#xff0c; 就像两个线程…

[山海关crypto 训练营 day10]

日常鼓励自己&#xff1a;别抱怨努力的苦&#xff0c;那是你去看世界的路。 最近几天一直忙着项目的结项答辩&#xff0c;今天终于是搞完了&#xff0c;得到了老师们的一致好评&#xff0c;最近几天的努力也没白费&#xff01;现在可以愉快刷题了&#xff0c;先复现下LiteCtf的…

c++核心知识—文件操作

目录 一、文件操作 1、文本文件 2、二进制文件 一、文件操作 文件操作头文件&#xff1a;<fstream> 操作文件的三大流&#xff1a; 1、ofstream&#xff1a;写操作 2、ifstream&#xff1a;读操作 3、fstream&#xff1a;读写操作 1、文本文件 写文件 步骤&…

【数据结构】-学习链表所需要的预备知识

知识点收集于网络&#xff0c;我会加以总结&#xff0c;如果把预备知识学好了。那么后面的操作就不难了 用节或者结都可以&#xff0c;不要在意字的差别 目录 一、头指针与头结点的概念 二、链表带头结点和不带头节点的区别 三、八大链表类型&#xff1a; 四、链表节点为…

unity制作幽灵猎手射击游戏

文章目录 介绍人物向着鼠标点击的位置跑动、旋转lerp函数让摄像机平滑跟随敌人导航敌人攻击发射子弹攻击敌人玩家健康敌人健康分数显示刷怪笼游戏结束动画 介绍 玩家鼠标控制人物转向 玩家鼠标点击控制光线发射的终点 玩家受到伤害屏幕闪红 有三个怪物生成点 玩家射杀敌人获得分…

linux-项目部署软件安装

安装jdk 操作步骤&#xff1a; 1、使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux jdk-8u171-linux-x64.tar.gz 2、解压安装包&#xff0c;命令为tar -zxvf jdk-8u171-linux-x64.tar.gz -C /usr/local 3、配置环境变量&#xff0c;使用vim命令修改/etc/profile文…

【JavaWeb】-- Filter、Listener、Ajax、Vue

文章目录 Filter1.概述2.快速入门2.1 开发步骤2.2 代码演示 3.Filter执行流程4. Filter拦截路径配置5.过滤器链5.1 概述5.2 代码演示5.3 问题 Listener1.概述2. 分类3.代码演示 Ajax1.概述1.1作用1.2 同步和异步 2.快速入门2.1 服务端实现2.2 客户端实现2.3 测试 3.axios3.1 基…

“Shell“Awk命令

文章目录 一.Awk二.Awk按行输出文本三.Awk按字段输出文本四.通过管道&#xff0c;双引号调用shell命令五.总结&#xff1a; 一.Awk Awk的工作原理&#xff1a; 逐行读取文本&#xff0c;默认以空格或tab键为分隔符进行分隔&#xff0c;将分隔所得的各个字段保存到内建变量中&a…