异步FIFO设计

news/2024/11/17 1:29:22/文章来源:https://www.cnblogs.com/HiDark/p/18351563

Asynchronous FIFO Design

总结来自Clifford E. Cummings论文 《Simulation and Synthesis Techniques for Asynchronous FIFO Design》

一、设计难点

  • 使用格雷码计数时空和满的判断。
  • 同步FIFO读写时钟相同,而异步FIFO读写来自不同两个读写时钟,需要考虑跨时钟域设计。

二、设计思路

把多bit信号跨时钟域是有问题的。设计一般通过FIFO对多bit信号进行安全的跨时钟域传递。

2.1 空满判断

1、二进制空满判断

如图1,在二进制计数nbit地址时,判断full和empty的条件都是waddr==raddr,为了区分,增加1bit,这样地址位宽范围变为[n:0]。此时,当 waddr[n:0]==raddr[n:0] 时,为empty。而full时,waddr会绕raddr一圈,因此判定为

{~waddr[n],waddr[n-1:0]}==raddr[n:0]

image-20240802163021289

2、格雷码空满判断

但采用格雷码计数时,虽然MSB依然是前半部分是0,后半部分是1,但[n-1:0]却不是循环,而是对称,如下图所示。

image-20240805093747915 image-20240805093559025

但是也能看出来,当最高位变成1后,除了最高的前两位,其余位是符合最高位是0时候的顺序规律。因此可通过

{~waddr[n],~waddr[n-1:0],waddr[n-2:0]}==raddr[n:0]判断full。当 waddr[n:0]==raddr[n:0] 时,为empty。

3、保守空满

思考一下,当判断空或满的时候,总有一个指针是通过两级触发器同步过来的,也就意味着有延迟,那这样的判断真的准确吗?下面分别从空和满的角度去分析:

  1. 假空

判断空的时候,需要用读指针和经过读时钟同步过来的写指针来比较。如果在同步写指针时,继续写操作,同步过来的仍然是之前落后的写指针,此时即使读指针和经过读时钟同步过来的写指针满足空的条件,FIFO仍有新写入的数据,即假空。

  1. 假满

判断满的时候,需要写指针和经过写时钟同步过来的读指针进行比较。如果在同步读指针时,继续读操作,同步过来的仍然是之前落后的读指针,此时即使写指针和经过写时钟同步过来的读指针满足满的条件,FIFO仍然有数据已经被读出,即假满。

综上所述,假满和假空虽然存在,但最多会降低运行吞吐率,性能降低,功能仍正确,而不会出现上溢出和下溢出。

但是想一想为什么要在写侧判断满,而在读测判断空?在读测判断满行不行?

答案是不可以。如果在读侧判断满,当读指针和读时钟同步过来的写指针满足满的条件式,已经有了延迟,如果写操作仍在进行,就会覆盖数据,造成功能不正确

2.2 Multi-bit 跨时钟域同步

1、快时钟频率是慢时钟的两倍甚至更快,那么快域地址变化两次,慢时钟域采样一次,前后采样值变化了两次,会产生多位同步的问题吗?

不会,只有多个位同时变化时才会有问题。因为在慢时钟域下只能看到最近的一次跳变,格雷码相邻跳变只有一位不同。

2、Multi-bit 异步复位

异步复位通常会导致指针位多bit产生变化,这会有问题吗?

因为复位后fifo里的数据已经无效,因此不会有问题,另外,虽然读写各有单独的复位信号,但单侧复位时必须通知另一侧,否则会出错。

2.3 格雷码计数器设计

文章给出两种结构,下面依次介绍

1、 第一种

第一种寄存器存储的均是格雷码。

image-20240805173534195

2、第二种

第二种计数器存储的是二进制,直接用二进制对存储器寻址。二进制到格雷码转换的逻辑转移到下面的寄存器。即格雷码只用于跨时钟域的同步。这样做减少延迟,提高频率。

image-20240805173649528

三、RTL结构与设计

1、FIFO结构

结构如下。

image-20240805180008595

根据不同的功能和时钟域,分为以下六个模块:

名字 功能 时钟域
fifo1.v 顶层 所有
fifomem.v 存储,一般用伪双端口ram 所有
sync_r2w.v 写时钟同步读指针
sync_w2r.v 读时钟同步写指针
rptr_empty.v 空判断
wptr_full.v 满判断

2、Verilog代码

  1. fifo.v
module fifo1 #( parameter DSIZE = 8,parameter ASIZE = 4)(output [DSIZE-1:0] rdata,output wfull,output rempty,input [DSIZE-1:0] wdata,input winc, wclk, wrst_n,input rinc, rclk, rrst_n
);wire [ASIZE-1:0] waddr, raddr;wire [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr;sync_r2w sync_r2w (.wq2_rptr(wq2_rptr), .rptr(rptr),.wclk(wclk), .wrst_n(wrst_n));sync_w2r sync_w2r (.rq2_wptr(rq2_wptr), .wptr(wptr),.rclk(rclk), .rrst_n(rrst_n));fifomem #(DSIZE, ASIZE) fifomem(.rdata(rdata), .wdata(wdata),.waddr(waddr), .raddr(raddr),.wclken(winc), .wfull(wfull),.wclk(wclk));rptr_empty #(ASIZE) rptr_empty(.rempty(rempty),.raddr(raddr),.rptr(rptr), .rq2_wptr(rq2_wptr),.rinc(rinc), .rclk(rclk),.rrst_n(rrst_n));wptr_full #(ASIZE) wptr_full(.wfull(wfull), .waddr(waddr),.wptr(wptr), .wq2_rptr(wq2_rptr),.winc(winc), .wclk(wclk),.wrst_n(wrst_n));
endmodule
  1. fifomem.v
module fifomem #(   parameter DATASIZE = 8, // Memory data word widthparameter ADDRSIZE = 4)( // Number of mem address bitsoutput  [DATASIZE-1:0]  rdata,input   [DATASIZE-1:0]  wdata,input   [ADDRSIZE-1:0]  waddr, raddr,input                   wclken, wfull, wclk);
`ifdef VENDORRAM// instantiation of a vendor's dual-port RAMvendor_ram mem (.dout(rdata), .din(wdata),.waddr(waddr), .raddr(raddr),.wclken(wclken),.wclken_n(wfull), .clk(wclk));
`else// RTL Verilog memory modellocalparam DEPTH = 1<<ADDRSIZE;reg [DATASIZE-1:0] mem [0:DEPTH-1];assign rdata = mem[raddr];always @(posedge wclk)if (wclken && !wfull) mem[waddr] <= wdata;
`endif
endmodule
  1. sync_r2w.v
module sync_r2w #(parameter ADDRSIZE = 4)(output reg  [ADDRSIZE:0] wq2_rptr,input       [ADDRSIZE:0] rptr,input                    wclk, wrst_n
);
reg  [ADDRSIZE:0] wq1_rptr;
always @(posedge wclk, negedge wrst_n) beginif(!wrst_n){wq2_rptr,wq1_rptr} <=  'b0;else {wq2_rptr,wq1_rptr} <=  {wq1_rptr,rptr};       
end
endmodule
  1. sync_w2r.v
module sync_w2r #(parameter ADDRSIZE = 4)(output reg  [ADDRSIZE:0] rq2_wptr,input       [ADDRSIZE:0] wptr,input                    rclk, rrst_n
);
reg  [ADDRSIZE:0] rq1_wptr;
always @(posedge rclk, negedge rrst_n) beginif(!rrst_n){rq2_wptr,rq1_wptr} <=  'b0;else {rq2_wptr,rq1_wptr} <=  {rq1_wptr,wptr};       
end
endmodule
  1. rptr_empty.v
module rptr_empty #(parameter ADDRSIZE = 4) (output  reg                 rempty, output      [ADDRSIZE-1:0]  raddr, output  reg [ADDRSIZE :0]   rptr, input       [ADDRSIZE :0]   rq2_wptr, input                       rinc, rclk, rrst_n
);
reg  [ADDRSIZE:0]   rbin;
wire [ADDRSIZE:0] bnext,gnext;
assign raddr = rbin[ADDRSIZE-1:0];
// bin counter
assign bnext = rbin + (rinc & ~rempty);
always @(posedge rclk or negedge rrst_n) beginif(!rrst_n)rbin    <=  {(ADDRSIZE+1){1'b0}};elserbin    <=  bnext;
end
// gray counter
assign gnext = (bnext>>1) ^ bnext;
always @(posedge rclk or negedge rrst_n) beginif(!rrst_n)rptr    <=  {(ADDRSIZE+1){1'b0}};elserptr    <=  gnext;
end
// empty flag
always @(posedge rclk or negedge rrst_n) beginif(!rrst_n)rempty    <=  1'b1;elserempty    <=  rq2_wptr == gnext;
end
endmodule
  1. wptr_full.v
module wptr_full #(parameter ADDRSIZE = 4)(output reg                  wfull,output      [ADDRSIZE-1:0]  waddr,output reg  [ADDRSIZE :0]   wptr,input       [ADDRSIZE :0]   wq2_rptr,input                       winc, wclk, wrst_n
);
reg  [ADDRSIZE:0]   wbin;
wire [ADDRSIZE:0] bnext,gnext;assign waddr = wbin[ADDRSIZE-1:0];
// bin counter
assign bnext = wbin + (winc & ~wfull);
always @(posedge wclk or negedge wrst_n) beginif(!wrst_n)wbin    <=  {(ADDRSIZE+1){1'b0}};elsewbin    <=  bnext;
end
// gray counter
assign gnext = (bnext>>1) ^ bnext;
always @(posedge wclk or negedge wrst_n) beginif(!wrst_n)wptr    <=  {(ADDRSIZE+1){1'b0}};elsewptr    <=  gnext;
end
// full flag
always @(posedge wclk or negedge wrst_n) beginif(!wrst_n)wfull   <=  1'b0;elsewfull   <=  gnext == {~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]};
end
endmodule

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

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

相关文章

常量的基础认知和相互转化

常量:在java程序运行过程中,其值不能够发送改变的量 分类:字面值常量:字符串常量:被双引号括起来的字符序列 "java"字符常量:被单引号括起来的单个字符 a整数常量:所有的整数 100 200 -100小数常量:所有的小数 1.23 3.14 -1.23布尔常量:true false空常…

.NET 窗口/屏幕录制

窗口/屏幕截图适用于截图、批注等工具场景,时时获取窗口/屏幕图像数据流呢,下面讲下视频会议共享桌面、远程桌面这些场景是如何实现画面录制的。 常见的屏幕画面时时采集方案,主要有GDI、WGC、DXGI。 GDI GDI(Graphics Device Interface)就是使用user32下WindowsAPI来实现…

.NET 屏幕录制

窗口/屏幕截图适用于截图、批注等工具场景,时时获取窗口/屏幕图像数据流呢,下面讲下视频会议共享桌面、远程桌面这些场景是如何实现画面录制的。 常见的屏幕画面时时采集方案,主要有GDI、WGC、DXGI。 GDI GDI(Graphics Device Interface)就是使用user32下WindowsAPI来实现…

Kubernetes-POD的QoS

目录背景问题分析进一步排查问题原因Pod的QoS服务质量等级结论 背景 今天开发团队反馈,测试环境中部分业务功能无法正常使用。经过初步排查,发现某个业务Pod在一天内重启了10次,因此需要进一步调查原因。 问题分析 首先,我查看了Pod的日志,发现JVM并未抛出任何错误,服务却…

2024.8.9 鲜花

几张图?推歌:早安大森林 ![](https://baike.baidu.com/pic/%E6%97%A9%E5%AE%89%E5%A4%A7%E6%A3%AE%E6%9E%97/64160919/1/b17eca8065380cd791236bebf51cba345982b2b72b26?fr=lemma&fromModule=lemma_content-image#aid=1&pic=b17eca8065380cd791236bebf51cba345982b2…

赋值运算符和+号的用法(两个练习)

string strName = "kakaxi";string strVillage = "huoyingcun";int iAge = 20;string strEmail = "1287195315@qq.com";decimal deSalary = 2000m;Console.WriteLine("大家好,我叫{0},我今年{1}岁了, 我住在{2},我的邮箱是{3}, 我的工资有足…

中国四大软件外包公司

今天我们来聊聊国内的四大软件外包公司。这些公司不仅在国内市场中占据重要地位,还对全球软件外包行业产生了影响。部分数据来源网络排名,按照职位量、增长速度排名,排名仅供参考,去某家公司一定要多方位参考,比如企查查、脉脉等。要说软件外包这块大蛋糕,谁不想来一口呢…

六、决策树

决策1:如何选择在每个节点上分割什么特征?最大限度地提高纯度(或最小限度地减少不纯)。决策2:什么时候停止拆分?当一个节点是一个单一类时 当拆分一个节点会导致树超过最大的深度 当纯度分数的改进低于一个阈值(获得的信息增益很小小于阈值) 当一个节点中的例子数量低于…

性能测试面试题大曝光,让你如何迅速拿下 offer!

性能测试面试题精选1、 以前做过性能测试么?请结合例子具体说明性能测试的流程 面试考察点:性能测试的流程首选做性能测试的需求分析,明确性能测试的目标、范围、场景和性能指标(如响应时间、吞吐量、并发用户数等)。测试性能测试环境搭建:搭建与生产环境尽可能一致的测试…

[Java并发]ThreadLocal补充

ThreadLocal缺点及解决方案 每个Thread上都有一个threadLocals属性,它是一个ThreadLocalMap,里面存放着一个Entry数组,key是ThreadLocal类型的弱引用,value是对用的值。所有的操作都是基于这个ThreadLocalMap操作的。 但是它有一个局限性,就是不能在父子线程之间传递。 即…

NuminaMath 是如何荣膺首届 AIMO 进步奖的?

今年,Numina 和 Hugging Face 合作角逐 AI 数学奥林匹克 (AI Math Olympiad,AIMO) 的首届进步奖。此次比赛旨在对开放 LLM 进行微调,以使其能解决高中难度的国际数学奥林匹克训练题。我们很高兴向大家报告: 我们的模型 - NuminaMath 7B TIR - 在比赛中脱颖而出,成功解决了私…

【题解】ABC365(A~E)

前四题30min切,然后T5死磕70min+几发小唐错,距离比赛结束还有16s交最后一发,AC了。 目录A. Leap Year题目描述思路代码B. Second Best题目描述思路代码C. Transportation Expenses题目描述思路代码D. AtCoder Janken 3题目描述思路代码E. Xor Sigma Problem题目描述思路代码…