当前位置:网站首页>【数字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仿真一般检查不出异步的问题。
边栏推荐
- [unity] several ideas about circular motion of objects
- [UVM practice] Chapter 2: a simple UVM verification platform (2) only driver verification platform
- Resource create package method
- Quickly use Jacobo code coverage statistics
- 3D reconstruction - stereo correction
- Custom class loader loads network class
- Explore dry goods! Apifox construction ideas
- Leetcode 43 String multiplication (2022.02.12)
- Few-Shot Learning && Meta Learning:小样本学习原理和Siamese网络结构(一)
- [VHDL parallel statement execution]
猜你喜欢
Linux server development, SQL statements, indexes, views, stored procedures, triggers
Implementation of replacement function of shell script
【webrtc】m98 screen和window采集
2022 recurrent training question bank and answers of refrigeration and air conditioning equipment operation
@component(““)
Li Kou interview question 04.01 Path between nodes
【p2p】本地抓包
探索干货篇!Apifox 建设思路
通信设备商,到底有哪些岗位?
[SUCTF 2019]Game
随机推荐
Paddlepaddle 29 dynamically modify the network structure without model definition code (relu changes to prelu, conv2d changes to conv3d, 2D semantic segmentation model changes to 3D semantic segmentat
快速使用 Jacoco 代码覆盖率统计
Quickly use Jacobo code coverage statistics
[performance pressure test] how to do a good job of performance pressure test?
[OBS] win capture requires winrt
Zhilian + AV, AITO asked M7 to do more than ideal one
dash plotly
[matlab] when matrix multiplication in Simulink user-defined function does not work properly, matrix multiplication module in module library can be used instead
CTF daily question day43 rsa5
解决问题:Unable to connect to Redis
这5个摸鱼神器太火了!程序员:知道了快删!
What is the interval in gatk4??
Leetcode 43 String multiplication (2022.02.12)
Rust Versus Go(哪种是我的首选语言?)
Explore dry goods! Apifox construction ideas
[UVM foundation] what is transaction
【斯坦福计网CS144项目】Lab3: TCPSender
[CV] Wu Enda machine learning course notes | Chapter 8
Technology cloud report: from robot to Cobot, human-computer integration is creating an era
[VHDL parallel statement execution]