当前位置:网站首页>从底层结构开始学习FPGA----FIFO IP的定制与测试
从底层结构开始学习FPGA----FIFO IP的定制与测试
2022-07-06 17:39:00 【孤独的单刀】
文章目录
系列目录与传送门
在定制一个FIFO IP核之前,强烈建议您先阅读:从底层结构开始学习FPGA----FIFO IP核及其关键参数介绍
在这篇文章中,已经对FIFO IP核的各个关键因素做了详细的讲解。
1、FIFO IP的定制
- 在新建一个工程后, 点击IP Catalog
- 点击后会出现 IP Catalog 页面,在 IP 核的搜索框中搜索 fifo
- 根据筛选,双击选择fifo核“FIFO Generator”
①、第一页
②、第二页
③、第三页
④、第四页
⑤、第五页
2、FIFO IP的例化与测试
2.1、例化一个FIFO IP核
按上述步骤生成IP后,复制 IP核自带的例化模板。
2.2、RTL
我们编写一个RTL代码来验证一下这个FIFO IP,并学习一下它的时序逻辑。
由于是异步FIFO,所以还例化了一个PLL来生成写时钟50M,读时钟75M。RTL代码使用了一个简单的状态机,以实现如下逻辑:
- 等待PLL稳定
- PLL稳定后对FIFO进行复位,时长10个周期以上
- FIFO复位完成后,写入数据直到写满,写入数据分别为0,1,2···14,共15个数据
- 写完数据后,从FIFO中读取数据,观察读取数据是否与写入数据一致
module fifot_test(
(* MARK_DEBUG="true" *) input sys_clk,
(* MARK_DEBUG="true" *) input sys_rst_n
);
(* MARK_DEBUG="true" *)reg fifo_rst ; //自己生成一个FIFO的复位信号
(* MARK_DEBUG="true" *)reg [3:0] din ;
(* MARK_DEBUG="true" *)reg [3:0] rst_cnt ; //复位计数器
(* MARK_DEBUG="true" *)reg wr_en ;
(* MARK_DEBUG="true" *)reg rd_en ;
(* MARK_DEBUG="true" *)reg [2:0] state ;
reg [2:0] state_rd1 ;
reg [2:0] state_rd2 ;
(* MARK_DEBUG="true" *)wire locked ;
(* MARK_DEBUG="true" *)wire rst_n ;
(* MARK_DEBUG="true" *)wire rd_clk ;
(* MARK_DEBUG="true" *)wire wr_clk ;
(* MARK_DEBUG="true" *)wire [3 : 0] dout ;
(* MARK_DEBUG="true" *)wire full ;
(* MARK_DEBUG="true" *)wire almost_full ;
(* MARK_DEBUG="true" *)wire wr_ack ;
(* MARK_DEBUG="true" *)wire overflow ;
(* MARK_DEBUG="true" *)wire empty ;
(* MARK_DEBUG="true" *)wire almost_empty ;
(* MARK_DEBUG="true" *)wire valid ;
(* MARK_DEBUG="true" *)wire underflow ;
(* MARK_DEBUG="true" *)wire [3 : 0] rd_data_count ;
(* MARK_DEBUG="true" *)wire [3 : 0] wr_data_count ;
(* MARK_DEBUG="true" *)wire prog_full ;
(* MARK_DEBUG="true" *)wire prog_empty ;
(* MARK_DEBUG="true" *)wire wr_rst_busy ;
(* MARK_DEBUG="true" *)wire rd_rst_busy ;
assign rst_n = sys_rst_n && locked; //在locked拉高之前一直复位
//PLL输出波形后,开始计数直到1111
always @(posedge sys_clk or negedge rst_n)begin
if(~rst_n)
rst_cnt <= 1'b0;
else if(&rst_cnt) //rst_cnt == 1111
rst_cnt <= rst_cnt;
else
rst_cnt <= rst_cnt + 1;
end
always @(posedge sys_clk or negedge rst_n)begin
if(~rst_n)
fifo_rst <= 1'b1;
else if(&rst_cnt)
fifo_rst <= 1'b0;
else
fifo_rst <= 1'b1;
end
always @(posedge sys_clk or negedge rst_n)begin
if(~rst_n)
state <= 3'd0;
else begin
case(state)
3'd0:begin
if(~fifo_rst)
state <= 3'd1;
else
state <= state;
end
3'd1:begin
if(~wr_rst_busy && ~full)
state <= 3'd2;
else
state <= state;
end
3'd2:begin
if(almost_full)
state <= 3'd3;
else
state <= state;
end
3'd3:begin
if(~rd_rst_busy && ~empty)
state <= 3'd4;
else
state <= state;
end
3'd4:begin
if(almost_empty)
state <= 3'd5;
else
state <= state;
end
3'd5:begin
state <= state;
end
default:state <= 3'd0;
endcase
end
end
//写使能
always @(posedge wr_clk or negedge rst_n)begin
if(~rst_n)
wr_en <= 1'b0;
else if(state == 3'd2)
wr_en <= 1'b1;
else
wr_en <= 1'b0;
end
//写数据
always @(posedge wr_clk or negedge rst_n)begin
if(~rst_n)
din <= 4'd0;
else if(wr_en)
din <= din + 1;
end
//把状态state同步到读时钟域
always @(posedge rd_clk or negedge rst_n)begin
if(~rst_n)begin
state_rd1 <= 3'd0;
state_rd2 <= 3'd0;
end
else begin
state_rd1 <= state;
state_rd2 <= state_rd1;
end
end
//读使能
always @(posedge rd_clk or negedge rst_n)begin
if(~rst_n)
rd_en <= 1'b0;
else if(state_rd2 == 3'd4)
rd_en <= 1'b1;
else
rd_en <= 1'b0;
end
clk_wiz_0 clk_wiz_0_inst
(
.clk_in1 (sys_clk ),
.clk_out1 (wr_clk ), //50M
.clk_out2 (rd_clk ), //75M
.resetn (sys_rst_n ),
.locked (locked )
);
//例化FIFO
fifo_w4_d16 fifo_w4_d16_inst(
.rst (fifo_rst),
.wr_clk (wr_clk),
.din (din),
.wr_en (wr_en),
.wr_rst_busy (wr_rst_busy),
.wr_data_count (wr_data_count),
.prog_full (prog_full),
.full (full),
.almost_full (almost_full),
.wr_ack (wr_ack),
.overflow (overflow),
.rd_clk (rd_clk),
.rd_en (rd_en),
.empty (empty),
.almost_empty (almost_empty),
.valid (valid),
.rd_data_count (rd_data_count),
.dout (dout),
.underflow (underflow),
.prog_empty (prog_empty),
.rd_rst_busy (rd_rst_busy)
);
endmodule
2.3、仿真测试与测试结果
由于测试逻辑都在RTL中实现了,所以testbench就比较简单了,只需要例化被测模块和实现时钟和复位即可。
`timescale 1 ns / 1 ns
module tb_fifo_test();
reg sys_clk;
reg sys_rst_n;
initial begin
sys_clk = 0;
sys_rst_n = 0;
#60
sys_rst_n = 1;
#6000
$finish; //停止仿真
end
always #10 sys_clk = ~ sys_clk;
fifot_test fifot_test_inst(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n )
);
endmodule
使用vivado自带的仿真工具simulator运行仿真,仿真结果如下:
(1)整体
(2)PLL从不稳定到稳定
(3)FIFO复位完成后需要一定的时间才可以操作
(4)写FIFO操作
(5)读FIFO操作
写入数据0-14共15个数据,读出数据也是0-14共15个数据。写、读一致,功能验证无误。
2.4、下板实测
把代码下载到开发板,用ILA观察一下,观察结果和仿真结果是一致的,不赘述,只放几张图:
(1)PLL稳定及FIFO复位
(2)写FIFO操作,写入数据0-14
(3)读FIFO操作,读取数据0-14
3、总结与参考
- FIFO的使用要注意实际深度
- FIFO使用需要先复位,复位时间要足够长,且复位后需要一定的时间才能使用FIFO
- 同步FIFO的使用会比较简单,因为其没有异步FIFO所需要的同步时钟域导致的延迟问题
- 不同资源实现的FIFO在各个功能特性上会有细微的区别,使用之前一定要认真测试,总结时序
- 异步FIFO的计数器不是精确的,只能作为大致的参考,以实现例如半空半满、1/4空满等判断
- 可编程空满的实现是依赖计数器的,其值同样不够精确
参考资料1:pg057-fifo-generator
- 博客主页:wuzhikai.blog.csdn.net
- 本文由 孤独的单刀 原创,首发于CSDN平台
- 文章还在持续更新,您有任何问题,都可以在评论区和我交流!
- 创作不易,您的支持是我持续更新的最大动力!如果本文对您有帮助,还请多多点赞、评论和收藏!
边栏推荐
- 【案例分享】网络环路检测基本功能配置
- Make Jar, Not War
- Rainstorm effect in levels - ue5
- LLDP兼容CDP功能配置
- Anfulai embedded weekly report no. 272: 2022.06.27--2022.07.03
- Table table setting fillet
- Neon Optimization: About Cross access and reverse cross access
- Force buckle 1037 Effective boomerang
- Tensorflow GPU installation
- ARM裸板调试之JTAG原理
猜你喜欢
boot - prometheus-push gateway 使用
MySQL script batch queries all tables containing specified field types in the database
Your cache folder contains root-owned files, due to a bug in npm ERR! previous versions of npm which
云呐|工单管理办法,如何开展工单管理
Niuke cold training camp 6B (Freund has no green name level)
2022 Google CTF SEGFAULT LABYRINTH wp
HMM notes
HMM 笔记
Installation of gazebo & connection with ROS
405 method not allowed appears when the third party jumps to the website
随机推荐
界面控件DevExpress WinForms皮肤编辑器的这个补丁,你了解了吗?
Data type of pytorch tensor
405 method not allowed appears when the third party jumps to the website
Can the system hibernation file be deleted? How to delete the system hibernation file
JTAG principle of arm bare board debugging
[HFCTF2020]BabyUpload session解析引擎
系统休眠文件可以删除吗 系统休眠文件怎么删除
pytorch之数据类型tensor
Taro2.* 小程序配置分享微信朋友圈
736. Lisp 语法解析 : DFS 模拟题
Taro2.* applet configuration sharing wechat circle of friends
Segmenttree
Oracle:CDB限制PDB资源实战
黑马笔记---创建不可变集合与Stream流
Asset security issues or constraints on the development of the encryption industry, risk control + compliance has become the key to breaking the platform
NEON优化:关于交叉存取与反向交叉存取
Analysis of mutex principle in golang
NEON优化:log10函数的优化案例
「笔记」折半搜索(Meet in the Middle)
如何管理分布式团队?