当前位置:网站首页>【数字IC验证快速入门】10、Verilog RTL设计必会的FIFO
【数字IC验证快速入门】10、Verilog RTL设计必会的FIFO
2022-07-07 04:43:00 【luoganttcc】
导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思、清华紫光、联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。
文章目录
一、同步FIFO
FIFO,First In First Out,先入先出的队列。
学会了同步FIFO后,再学习异步FIFO学起来就容易了。
学习FIFO的要求,不要求要能够完全写出来,但是要懂得基本概念,FIFO是什么功能,设计FIFO基本要求等
1.1、RAM(Random Access Memory)的设计
设计实现一个16x8的双端口RAM
- RAM宽度8bit
- RAM深度16
- ADDR位宽2^4,取值范围0~15

对应的代码
module dp_ram(//dp = dual port
input wire write_clock,
input wire read_clock,
input wire write_allow,
input wire read_allow,
input wire [ADDR_WIDTH-1:0] write_addr,
input wire [ADDR_WIDTH-1:0] read_addr,
input wire [RAM_WIDTH-1:0 ] write_data,
output reg [RAM_WIDTH-1:0 ] read_data
);
parameter DLY = 1;
parameter RAM_WIDTH = 8;
parameter RAM_EDPTH = 16;
parameter ADDR_WIDTH= 4;
reg [RAM_WIDTH-1:0 ] memory[RAM_EDPTH-1:0];
[email protected](posedge write_clock) begin
if(write_allow)
memory[write_addr] <= #DLY write_data;
end
[email protected](posedge read_clock) begin
if(read_allow)
read_data <= #DLY memory[read_addr];
end
endmodule
1.2、同步FIFO的设计
- FIFO原则:满不能写,空不能读
- 关键:full和empty信号如何产生
- 方法1:用长度计数器factor,执行一次写操作,factor加1;执行一次读操作,factor减1.【占用资源会多点,但是实现较容易】
- 方法2:地址位扩展一位,用最高位来判断空满。【占用资源较少,实现稍复杂】
1.2.1、方法1对应的
module SYNCFIFO(
input wire Fifo_rst,
input wire Clock,
input wire Read_enable,
input wire Write_enable,
input wire [DATA_WIDTH-1:0] Write_data,
output reg [DATA_WIDTH-1:0] Read_data,
output reg Full,
output reg Empty,
output reg [ADDR_WIDTH-1:0] Fcounter
);
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 9;
reg [ADDR_WIDTH-1:0] Read_addr;
reg [ADDR_WIDTH-1:0] Write_addr;
wire Read_allow = (Read_enable && !Empty); //空不能读;最好不要这样写,容易出错,该写法等效于assign的那种!
wire Write_allow = (Write_enable && !Full); //满不能写
DUALRAM U_RAM(
.Write_clock (Clock),
.Read_clock (Clock ),
.Write_allow (Write_allow),
.Read_allow (Read_allow ),
.Write_addr (Write_addr ),
.Read_addr (Read_addr ),
.Write_data (Write_data ),
.Read_data (Read_data )
);
[email protected](posedge Clock or posedge Fifo_rst)
if(Fifo_rst)
Empty <= 'b1;
else
有点复杂化了,只要Fcounter[8:0]==9'h0,那么Empty就为1即可!
Empty <= (!Write_enable && (Fcounter[8:1]==8'h0) && ((Fcounter[0] == 0) || Read_enable) );
[email protected](posedge Clock or posedge Fifo_rst)
if(Fifo_rst)
Full <= 'b1;
else
//同样复杂化了,只要Fcounter[8:0]==9'b1_1111_1111,那么Full就为1即可!
Full <= (!Read_enable && (Fcounter[8:1]==8'hFF) && ((Fcounter[0]==1) || Write_enable));
[email protected](posedge clock or posedge Fifo_rst)
if(Fifo_rst)
Read_addr <= 'h0;
else if(Read_allow)
Read_addr <= Read_addr + 'b1;//最好加个边界限制,eg:if(Read_addr >= Depth-1) Read_addr <= 'h0之类的!
[email protected](posedge clock or posedge Fifo_rst)
if(Fifo_rst)
Write_addr <= 'h0;
else if(Write_allow)
Write_addr <= Write_addr + 'b1;//同样最好加个边界限制
[email protected](posedge clock or posedge Fifo_rst)
if(Fifo_rst)
Fcounter <= 'h0;
else if((!Read_allow && Write_allow) || (Read_allow && !Write_allow))
begin
if(Write_allow) Fcounter <= Fcounter + 'b1;
else Fcounter <= Fcounter - 'b1;
end
endmodule
- 跟RAM相比,FIFO看不到地址,只看到读写使能,来顺序产生RAM地址。
小知识:RTL代码不是程序,程序是编译成一条条指令和数据,放置到内存中,通过CPU取指令、译码、执行!RTL代码没有编译一说,综合映射成网表,体现实际硬件电路!
1.2.2、方法2对应的Verilog代码
- 深度为4的FIFO,实际位宽2bit就够了,拓展一位就变成了3bit。

- 场景1和3,读写最高位相等,即w[2] = r[2],且w[1:0] = r[1:0],empty有效,为空。
- 场景2和4,读写最高位不等,即w[2] != r[2],且w[1:0] = r[1:0],full有效,为满。
- 扩展为来判断场景!
module sync_fifo(
input wire clk,
input wire rst,
input wire wr_en,
input wire rd_en,
input wire [7:0] data_in,
output wire empty,
output wire full,
output reg [7:0] data_out,
);
reg [7:0] mem[15:0];
wire [3:0] w_addr,r_addr;
reg [4:0] r_addr_a, w_addr_a; //16个地址深度,4位就够了即[3:0],此处[4:0]扩展了1位
assign r_addr = r_addr_a[3:0];
assign w_addr = w_addr_a[3:0];
[email protected](posedge clk or negedge rst)
if(!rst)
r_addr_a <= 5'b0;
else begin
if(rd_en==1 && empty==0) begin
data_out <= mem[r_addr];
r_addr_a <= r_addr_a + 1;
end
end
[email protected](posedge clk or negedge rst)
if(!rst)
w_addr_a <= 5'b0;
else begin
if(wr_en==1 && full==0) begin
mem[w_addr] <= data_in;
w_addr_a <= w_addr_a + 1;
end
end
assign empty = (r_addr_a == w_addr_a) ? 1 : 0;
assign full = (r_addr_a[4] != w_addr_a[4] && r_addr_a[3:0] == w_addr_a[3:0]) ? 1 : 0;
endmodule
对应的TestBench


二、异步FIFO
- 使用扩展地址位的方式来判断空满
- 读写信号时钟不同
- 关键:格雷码的使用【异步FIFO:读写时钟域不一样】【格雷码:只有一个bit跳变】
- 读写地址进行转换,转换之后再同步,这样可以避免多比特同时翻转引入的中间亚稳态!

格雷码转换模块对应的RTL代码





- 跟同步FIFO不一样的地方,要进行一个跨时钟域的地址采样,采样要经过一个格雷码的转换的,否则采样会出现问题。
- 此处仅用了一个异步时钟cycle去采,而实际为了防止亚稳态,要采三拍的,这个地方写的不规范!
- EDA仿真一般检查不出异步的问题。
边栏推荐
- Wechat applet data binding multiple data
- Explore dry goods! Apifox construction ideas
- Linux server development, MySQL cache strategy
- Force buckle 144 Preorder traversal of binary tree
- Operation suggestions for today's spot Silver
- 【數字IC驗證快速入門】15、SystemVerilog學習之基本語法2(操作符、類型轉換、循環、Task/Function...內含實踐練習)
- pytest+allure+jenkins安装问题:pytest: error: unrecognized arguments: --alluredir
- Explore Cassandra's decentralized distributed architecture
- Custom class loader loads network class
- dash plotly
猜你喜欢

What are the positions of communication equipment manufacturers?

Implementation of replacement function of shell script

Technology cloud report: from robot to Cobot, human-computer integration is creating an era

Force buckle 144 Preorder traversal of binary tree

The configuration that needs to be modified when switching between high and low versions of MySQL 5-8 (take aicode as an example here)

Cnopendata list data of Chinese colleges and Universities

Sign up now | oar hacker marathon phase III, waiting for your challenge

【数字IC验证快速入门】17、SystemVerilog学习之基本语法4(随机化Randomization)

QT learning 26 integrated example of layout management

SQL优化的魅力!从 30248s 到 0.001s
随机推荐
Qt学习27 应用程序中的主窗口
【数字IC验证快速入门】15、SystemVerilog学习之基本语法2(操作符、类型转换、循环、Task/Function...内含实践练习)
[P2P] local packet capturing
Hands on deep learning (IV) -- convolutional neural network CNN
[UVM basics] summary of important knowledge points of "UVM practice" (continuous update...)
【VHDL 并行语句执行】
Téléchargement des données de conception des puces
Resource create package method
Most elements
Figure out the working principle of gpt3
Rust Versus Go(哪种是我的首选语言?)
pytest+allure+jenkins環境--填坑完畢
Idea add class annotation template and method template
What is the interval in gatk4??
C语言通信行程卡后台系统
Info | webrtc M97 update
Ansible
pytest+allure+jenkins环境--填坑完毕
padavan手动安装php
Pytest + allure + Jenkins Environment - - achèvement du remplissage de la fosse