当前位置:网站首页>数字 06 verilog_关于异步FIFO
数字 06 verilog_关于异步FIFO
2022-08-09 02:22:00 【影子才是本体】
为了应对不同时钟域模块之间的通信,fifo诞生了。
fifo就是first-in-first-out,先进先出。
通常会使用写指针和读指针来判断fifo是空还是满,为了方便,一般设计会将指针设置为比位宽多1Bit,用最高位的数据来判断是写指针追上了读指针还是读指针追上了写指针。
先说一下自己掉的坑:
1、reg [width-1:0] mem[depth-1:0],这里的depth是mem中width位寄存器的总个数,一共有depth个而不是2的depth次方个。
比如depth是8,那么mem总共有8个width位宽的寄存器而不是256个。(怪我看书不认真)
2、搞清楚哪些是同步信号哪些是异步信号
3、
设计之前要知道两个概念
1、格雷码
2、缓冲(2级D触发器)
这两个概念的设计都是为了减少模块的亚稳态概率。
1、格雷码
简单来说,格雷码是源码左移1Bit然后和源码本身异或。
格雷码的作用是避免亚稳态的产生,因为格雷码在源码从0一直+1到N时,格雷码每次只会变化本身的一个位。
第二列就是格雷码
用了格雷码之后,满信号和空信号的判别就需要重新思考了,这里直接放结论:
Gray码的最高位和次高位为空满标志位,满:读写地址的最高位和次高位相反,空:读写地址的最高位和次高位相同
2、两级D触发器缓冲
因为触发器进入亚稳态的时间,可以用参数 MTBF(Mean Time Between Failures,平均故障间隔时间)来描述,采用两级触发器可以让这个时间延长很久,也就是让故障的概率降低到很低很低。具体见:
为什么两级级联能降低亚稳态出现的概率
作者:龚黎明
链接:https://www.zhihu.com/question/43571892/answer/95940354
来源:知乎
模块设计框图
我自己设计的时候是按照模块来写的,先写了左边FIFO写模块,再写了右边FIFO读模块,然后是中间的FIFO存储器模块,最后是整个系统的连线,在连线的时候我发现,需要补上上图框图中的两根线,才是完整的。我的程序可以实现仿真,但是没有全面测试过,还在学习如何完善。
1、写模块
根据设计要求,设计了格雷码和2级d触发器。
module fifo_w(
input wire wclk, //fifo写模块时钟
input wire wen, //写使能
input wire[8:0] wq2_rptr, //从读模块传过来的读指针位置
input wire wrst_n, //复位信号
output wire[8:0] wptr, //写指针的位置
output wire[8:0] waddr, //写地址
output wire wfull //fifo已经被写满了
);
reg[8:0] waddr_ptr; //写地址
reg[8:0] dfilp1,dfilp2; //两级D触发器,减小亚稳态发生
initial//初始置位
begin
waddr_ptr<= 9'b0_0000_0000;
dfilp1 <= 9'b0_0000_0000;
dfilp1 <= 9'b0_0000_0000;
end
[email protected](posedge wclk or negedge wrst_n)//上升沿
begin
dfilp1 <= wq2_rptr;
dfilp2 <= dfilp1;
if(wrst_n==0)//复位
begin
waddr_ptr<= 9'b0_0000_0000;
end
else if((wfull!=1)&&(wen==1))//正常写情况就地址指针+1
begin
waddr_ptr <= waddr_ptr+1;
end
else
begin //如果满了或者不允许写,那就地址指针位置不变
waddr_ptr <= waddr_ptr;
end
end
assign wptr = (waddr_ptr>>1)^waddr_ptr;//生成格雷码
assign wfull = ((wptr[8]!=dfilp2[8])&&(wptr[7]!=dfilp2[7])&&(wptr<<2==dfilp2<<2))?1'b1:1'b0;//满信号判断
assign waddr = waddr_ptr;//
Endmodule
写模块做了个小测试
格雷码正确
我把读地址写成了0,写指针转了一圈之后回来,正确产生了满信号
2、读模块
module fifo_r(
input wire rclk, //fifo读模块时钟
input wire ren, //读使能
input wire[8:0] rq2_wptr, //从写模块传过来的写指针位置
input wire rrst_n, //复位信号
output wire[8:0] rptr, //读指针的位置
output wire[8:0] raddr, //读地址
output wire rempty //fifo
);
reg[8:0] raddr_ptr; //读地址
reg[8:0] dfilp1,dfilp2; //两级D触发器,减小亚稳态发生
initial//初始置位
begin
raddr_ptr<= 9'b0_0000_0000;
dfilp1 <= 9'b0_0000_0000;
dfilp1 <= 9'b0_0000_0000;
end
[email protected](posedge rclk or negedge rrst_n)//上升沿
begin
dfilp1 <= rq2_wptr;
dfilp2 <= dfilp1;
if(rrst_n==0)//复位
begin
raddr_ptr<= 9'b0_0000_0000;
end
else if((rempty!=1)&&(ren==1))//允许读 且不是空状态,就读,然后指针+1
begin
raddr_ptr <= raddr_ptr+1;
end
else
begin//不允许读 或者是空状态,就不变
raddr_ptr <= raddr_ptr;
end
end
assign rptr = (raddr_ptr>>1)^raddr_ptr;//生成格雷码
assign rempty = (rptr==dfilp2)?1'b1:1'b0;//空信号判断
assign raddr = raddr_ptr;//
Endmodule
测试仿真
格雷码正确,也生成了空信号
3、存储器模块,双口ram
module fifo_dualram(
input[7:0] wdata,
input[7:0] waddr,
input[7:0] raddr,
input wfull,//满状态,1为满状态,0是不满的状态
input rempty,//空状态,1为空状态,0是不空的状态
input wen,//写使能,1为使能态
input ren,//读使能,1为使能态
input wclk,
input rclk,
input ramrst_n,//复位信号
output reg[7:0] rdata
);
wire wclken;//这个信号是(满信号取反)和(写使能)的逻辑与
wire rclken;//这个信号是(空信号取反)和(读使能)的逻辑与
reg[7:0] fifo_dualram[256:0];
//存储器初始化
genvar i;
generate
for(i=0;i<256;i=i+1)
begin:initfifo
initial
begin
fifo_dualram[i] <= 8'h00;
end
end
endgenerate
//输出数据初始化
initial
begin
rdata <= 8'h00;
end
//复位
genvar j;
generate
for(j=0;j<256;j=j+1)
begin
[email protected](negedge ramrst_n )
begin
if(!ramrst_n)
begin
fifo_dualram[j] <= 8'h00;
end
end
end
endgenerate
//写模块
[email protected](posedge wclk)
begin
if(wclken!=0)
begin
fifo_dualram[waddr]<=wdata;//如果可以写的正常状态,就写数据
end
else
begin
fifo_dualram[waddr]<=fifo_dualram[waddr];//否则内容不变
end
end
[email protected](posedge rclk)
begin
if(rclken!=0)
begin
rdata<=fifo_dualram[raddr];//如果可以读的正常状态,就读数据
end
else
begin
rdata <= 8'h00;//否则输出数据置0
end
end
assign wclken=(wen&(!wfull));//这个信号是(满信号取反)和(写使能)的逻辑与
assign rclken=(ren&(!rempty));//这个信号是(空信号取反)和(读使能)的逻辑与
endmodule
按照地址的循序写了,01 03 中间02好像被跳过了,总是可以读得出来,循序也对
4、系统整合 模块
module sys_fifo(
input wen,
input wclk,
input wrst_n,
input[7:0] wdata,
input ren,
input rclk,
input rrst_n,
output[7:0] rdata,
input ramrst_n
);
wire[8:0] wq2_rptr;
wire[8:0] rq2_wptr;
wire[8:0] waddr;
wire[8:0] raddr;
wire wfull;
wire rempty;
fifo_w w(
.wen(wen),
.wclk(wclk),
.wrst_n(wrst_n),
.wq2_rptr(wq2_rptr),
.wptr(rq2_wptr),
.waddr(waddr),
.wfull(wfull));
fifo_r r(
.ren(ren),
.rclk(rclk),
.rrst_n(rrst_n),
.rq2_wptr(rq2_wptr),
.rptr(wq2_rptr),
.raddr(raddr),
.rempty(rempty));
fifo_dualram dualram(
.wdata(wdata),
.waddr(waddr),
.raddr(raddr),
.wfull(wfull),
.wen(wen),
.ren(ren),
.rempty(rempty),
.wclk(wclk),
.rclk(rclk),
.ramrst_n(ramrst_n),
.rdata(rdata)
);
endmodule
5、简单的测试模块,tb
module tb_fifodualram;
reg[7:0] wdata;
wire[7:0] rdata;
reg wen;
reg wclk;
reg wrst_n;
reg ren;
reg rclk;
reg rrst_n;
reg ramrst_n;
initial
begin
wclk <= 1'b0;
rclk <= 1'b0;
wen <= 1'b0;
ren <= 1'b0;
wrst_n <= 1'b0;
rrst_n <= 1'b0;
ramrst_n<= 1'b0;
wdata<= 8'b0000_0000;
end
always #5 wclk <= ~wclk;
always #20 rclk <= ~rclk;
initial
fork
#1 wrst_n = 1'b1;
#2 ramrst_n= 1'b1;
#3 rrst_n = 1'b1;
#10 wdata = 8'b0000_0001;
#20 wdata = 8'b0000_0010;
#30 wdata = 8'b0000_0100;
#40 wdata = 8'b0000_1000;
#11 wen = 1'b1;
//#102 [email protected] #5 wdata = wdata+1;
#100 wen = 1'b0;
#120 ren = 1'b1;
#540 ren = 1'b0;
#550 ramrst_n = 1'b0;
#600 ramrst_n = 1'b1;
#650 ren = 1'b1;
join
sys_fifo sys(.wen(wen),.ren(ren),.wclk(wclk),.rclk(rclk),.wrst_n(wrst_n),.rrst_n(rrst_n),.ramrst_n(ramrst_n),.wdata(wdata),.rdata(rdata));
endmodule
系统测试仿真图
边栏推荐
- 如何保护智能家居避免黑客攻击
- A40i gxl3680 ts_print报错:tslib: Selected device is not a touchscreen (must support ABS and KEY event
- MT4 / MQ4L entry to the master of EA tutorial lesson two (2) - - MQL language commonly used function account information commonly used functions
- 2022/8/8 比赛思维+状压dp
- JDBC technology (1) - a simple JDBC test
- Appium常用操作及H5页面元素定位
- Composer usage record
- OJ:L3-001 凑零钱 DFS
- Summary of pytorch related knowledge points
- 通过安装VNC服务器x11vnc(或vnc4server)和配置x11vnc.service实现远程通过VNC-Viewer访问VNC服务器。
猜你喜欢
HMS Core分析服务智能运营6.5.1版本上线
为什么应用程序依赖关系映射对于云迁移至关重要
Educational Codeforces Round 132 (Rated for Div. 2)
How js implements array deduplication (7 kinds)
The last exam before the NPDP revision!caution
The first lesson of HNUMSC-C language
MySQL/Oracle字符串分割
Likou Brush Question Record 8.1-----206. Reverse linked list
线段树知识整理
【云计算】XaaS最全介绍(按24字母合集):AaaS、BaaS、CaaS、DaaS、EaaS、FaaS、GaaS、HaaS、IDaaS…
随机推荐
Likou Brush Question Record 5.1-----59. Spiral Matrix II
2022 PMP Project Management Certification Exam Registration Guide (1)
年金险的安全性怎么样啊?可靠吗?
The most fierce "employee" in history, madly complaining about the billionaire boss Xiao Zha: So rich, he always wears the same clothes!
点击div内部默认文本被选中
企业从云服务的承诺支出中获得最大收益的四种方法
2022 Eye Care Products Exhibition, Beijing Eye Health Exhibition, Ophthalmology Exhibition, Myopia Correction Equipment Exhibition
MT4/MQL4 entry to proficient foreign exchange EA tutorial Lesson 1 Getting to know MetaEditor
Group DETR:分组一对多匹配是加速DETR收敛的关键
力扣刷题记录3.1-----977. 有序数组的平方
MT4 / MQL4 entry to the master of EA course lesson two - commonly used functions
炫酷-轮播图-走马灯
【AspNetCore】实现JWT(使用Microsoft.AspNetCore.Authentication.JwtBearer)
2022眼康品牌加盟展,北京视力保健展,中国眼科医学技术峰会
NPDP改版前最后一次考试!请注意
如何在推荐系统中玩转知识图谱
Summary of Database Design
UsernameAuthenticationFilter授权成功后调用AuthenticationSuccessHandler时的解析
微信公众号跳转小程序 wx-open-launch-weapp (最全指南及坑)
Go-8-Gin framework