FIFO设计
- first in first out,先进先出
- fifo是基于RAM进行设计的
双端口RAM设计(16*8)
- 如果大的RAM可以调用IP
- RAM的关键参数:深度和宽度
module dual_ram
#(
parameter ADDR_WIDTH = 4,
parameter RAM_WIDTH = 8,
parameter DLY=1
)
(
input wire read_clk ,
input wire write_clk ,
input wire [ADDR_WIDTH-1:0] read_addr ,
input wire [ADDR_WIDTH-1:0] write_addr ,
input wire read_allow ,
input wire write_allow ,
input wire [RAM_WIDTH-1:0] write_data ,
output reg [RAM_WIDTH-1:0] read_data
);
reg [RAM_WIDTH-1:0] memory [ADDR_WIDTH-1:0];
always @(posedge read_clk) begin
if(read_allow)
read_data <= #DLY memory[read_addr];
end
always @(posedge write_clk) begin
if(write_allow)
memory[write_addr] <= #DLY write_data;
end
endmodule
单端口ram
module single_port_ram
#(
parameter ADDR_WIDTH = 8,
parameter RAM_WIDTH = 8,
parameter RAM_DEPTH = 255,
parameter DLY = 1
)
(
input wire clk,
input wire rst_n,
input wire [ADDR_WIDTH-1:0] addr,
input wire wr_en, // 1-write 0-read
input wire [RAM_WIDTH-1:0] wdata,
output wire [RAM_WIDTH-1:0] rata
);
reg [RAM_DEPTH-1:0] mem [RAM_WIDTH-1:0];
integer i;
always @(posedge clk or negedge rst_n) begin
if(rst_n)
for(i=0;i<=255;i=i+1) begin
mem[i] = 16'h0000;
end
else if(wr_en)
mem[addr] <= wdata;
end
assign radta = (!wr_en) ? mem[addr] : 16'h0000 ;
// always @(posedge clk or negedge rst_n) begin
// if(!rst_n)
// radta <= 'h0;
// else if(!wr_en)
// r_data <= mem[addr];
// end
endmodule
同步FIFO设计
module sync_fifo_counter
#(
parameter ADDR_WIDTH = 9,
parameter RAM_WIDTH = 8
)
(
input wire fifo_clk,
input wire fifo_rst_n,
input wire read_en,
input wire write_en,
input wire [RAM_WIDTH-1:0] w_data,
output wire [RAM_WIDTH-1:0] r_data,
output reg empty,
output reg full,
output reg [ADDR_WIDTH-1:0] fcounter
);
reg [ADDR_WIDTH-1:0] write_addr;
reg [ADDR_WIDTH-1:0] read_addr;
wire write_allow = write_en && (!empty);
wire read_allow = read_en && (!full);
// empty
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(fifo_rst_n)
empty <= 1'b1;
else
empty <= (!write_allow) && (fcounter[ADDR_WIDTH-1:1] == 8'h0) && (fcounter[0] == 0||read_allow);
end
// full
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(fifo_rst_n)
full <= 1'b0;
else
full <= (!read_allow) && (fcounter[ADDR_WIDTH-1:1] == 8'hff) && (fcounter[0] == 1||write_allow);
end
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(fifo_rst_n)
fcounter <= {ADDR_WIDTH{1'b0}};
else if( (!read_allow) && (write_allow)||(read_allow) && (!write_allow)) begin
if(write_allow)
fcounter <= fcounter + 1'b1;
else
fcounter <= fcounter - 1'b1;
end
end
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(fifo_rst_n)
write_addr <= {ADDR_WIDTH{1'b0}};
else if(write_allow)
write_addr <= write_addr + 1'b1;
end
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(fifo_rst_n)
read_addr <= {ADDR_WIDTH{1'b0}};
else if(write_allow)
read_addr <= read_addr + 1'b1;
end
dual_ram u_dual_ram
(
.read_clk (fifo_clk),
.write_clk (fifo_clk),
.read_addr (read_addr),
.write_addr (write_addr),
.read_allow (read_allow),
.write_allow (write_allow),
.write_data (w_data),
.read_data (r_data)
);
endmodule
module sync_fifo
#(
parameter ADDR_WIDTH = 4,
parameter RAM_WIDTH = 8,
parameter RAM_DEPTH = 16
)
(
input wire fifo_clk,
input wire fifo_rst_n,
input wire read_en,
input wire write_en,
input wire [RAM_WIDTH-1:0] w_data,
output reg [RAM_WIDTH-1:0] r_data,
output wire empty,
output wire full
);
// 指针
reg [ADDR_WIDTH:0] write_addr;
reg [ADDR_WIDTH:0] read_addr;
wire [ADDR_WIDTH-1:0] w_addr;
wire [ADDR_WIDTH-1:0] r_addr;
wire write_allow = write_en && (!empty);
wire read_allow = read_en && (!full);
reg [RAM_WIDTH-1:0] mem [RAM_DEPTH-1:0];
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(!fifo_rst_n)
read_addr <= {ADDR_WIDTH{1'b0}};
else if(read_allow) begin
r_data <= mem[read_addr];
read_addr <= read_addr + 1;
end
end
always @(posedge fifo_clk or negedge fifo_rst_n) begin
if(!fifo_rst_n)
write_addr <= {ADDR_WIDTH{1'b0}};
else if(write_allow) begin
mem[write_addr] <= w_data;
write_addr <= write_addr + 1;
end
end
assign empty = read_addr == write_addr ? 1 : 0;
assign full = (read_addr[ADDR_WIDTH]!=write_addr[ADDR_WIDTH]) &&
(read_addr[ADDR_WIDTH-1:0] == write_addr[ADDR_WIDTH-1:0]);
assign r_addr = read_addr[ADDR_WIDTH-1:0];
assign w_addr = write_addr[ADDR_WIDTH-1:0];
endmodule
module sync_fifo_tb();
parameter ADDR_WIDTH = 4;
parameter RAM_WIDTH = 8;
parameter RAM_DEPTH = 16;
reg fifo_clk;
reg fifo_rst_n;
reg read_en;
reg write_en;
reg [RAM_WIDTH-1:0] w_data;
wire [RAM_WIDTH-1:0] rdata;
wire empty;
wire full;
// 例化模块 - 省略
sync_fifo u_sysc_fifo(
.fifo_clk (fifo_clk ) ,
.fifo_rst_n (fifo_rst_n) ,
.read_en (read_en ) ,
.write_en (write_en ) ,
.w_data (w_data ) ,
.r_data (r_data ) ,
.empty (empty ) ,
.full (full )
);
initial begin
fifo_rst_n = 1;
fifo_clk = 0;
#1 fifo_rst_n = 0;
#5 fifo_rst_n = 1;
end
always #20 fifo_clk = ~fifo_clk;
initial begin
write_en = 0;
#1 write_en = 1;
end
initial begin
read_en = 0;
#650 read_en = 1;
write_en = 0;
end
initial begin
w_data = 8'h0;
#40 w_data = 8'h1;
#40 w_data = 8'h2;
#40 w_data = 8'h3;
#40 w_data = 8'h4;
#40 w_data = 8'h5;
#40 w_data = 8'h6;
#40 w_data = 8'h7;
#40 w_data = 8'h9;
#40 w_data = 8'ha;
#40 w_data = 8'hb;
#40 w_data = 8'hc;
#40 w_data = 8'hd;
#40 w_data = 8'he;
#40 w_data = 8'hf;
#200 $finish;
end
initial begin
$vcdpluson();
end
endmodule
FIFO设计的更多相关文章
- FPGA Asynchronous FIFO设计思路(2)
FPGA Asynchronous FIFO设计思路(2) 首先讨论格雷码的编码方式: 先看4bit的格雷码,当MSB为0时,正向计数,当MSB为1时,即指针已经走过一遍了,最高位翻转,此时的格雷码是 ...
- FPGA Asynchronous FIFO设计思路
FPGA Asynchronous FIFO设计思路 将一个多位宽,且在不停变化的数据从一个时钟域传递到另一个时钟域是比较困难的. 同步FIFO的指针比较好确定,当FIFO counter达到上限值时 ...
- FIFO设计中的深度计算【zz】
FIFO设计中的深度计算: 写时钟频率 w_clk, 读时钟频率 r_clk, 写时钟周期里,每B个时钟周期会有A个数据写入FIFO: 读时钟周期里,每Y个时钟周期会有X个数据读出FIFO: 则,FI ...
- 基于FPGA的异步FIFO设计
今天要介绍的异步FIFO,可以有不同的读写时钟,即不同的时钟域.由于异步FIFO没有外部地址端口,因此内部采用读写指针并顺序读写,即先写进FIFO的数据先读取(简称先进先出).这里的读写指针是异步的, ...
- FIFO设计思考之一
不管同步FIFO还是异步FIFO,设计难点是full/empty状态flag的正确性. 要保证任何情况 FULL时NO WRITE,EMPTY时NO READ.overflow / underflow ...
- 异步FIFO设计
参考http://www.cnblogs.com/BitArt/archive/2013/04/10/3010073.html http://blog.sina.com.cn/s/blog_6d30f ...
- 异步fifo的设计
本文首先对异步 FIFO 设计的重点难点进行分析 最后给出详细代码 一.FIFO简单讲解 FIFO的本质是RAM, 先进先出 重要参数:fifo深度(简单来说就是需要存多少个数据) ...
- 同步fifo的verilogHDL设计实例
原创 设计一个fifo,输入16bit,输出16bit的data,寻址宽度5bit,有空满标志. top 层如下所示: /* date : 2014/10/14 version : modelsim ...
- Verilog设计异步FIFO
转自http://ninghechuan.com 异步FIFO有两个异步时钟,一个端口写入数据,一个端口读出数据.通常被用于数据的跨时钟域的传输. 同步FIFO的设计.一个时钟控制一个计数器,计数器增 ...
- 异步fifo的设计(FPGA)
本文首先对异步 FIFO 设计的重点难点进行分析 最后给出详细代码 一.FIFO简单讲解 FIFO的本质是RAM, 先进先出 重要参数:fifo深度(简单来说就是需要存多少个数据) ...
随机推荐
- 【2016】开机出现 system32\config\system,代码:0xc00000e9解决方法
这是16年刚工作时写的笔记,也带来这里做个记录吧.实际工作这几年里也时不时会遇到,大多数和非正常关机有关系 今天早上,就在刚才,一个同事的电脑开不了机了,开机提示的是system32\config\s ...
- mybatis测试类的书写步骤
mybatis测试类的书写步骤 private SqlSession session; @Test //* 1.根据UserMapper接口的Class对象获取Mapper接口类型的对象 //* 2. ...
- 春秋云镜 - CVE-2022-29464
WSO2文件上传漏洞(CVE-2022-29464)是Orange Tsai发现的WSO2上的严重漏洞.该漏洞是一种未经身份验证的无限制任意文件上传,允许未经身份验证的攻击者通过上传恶意JSP文件在W ...
- 关于开放签CA数字证书设计的思考
这几天在调研CA数字证书以及思考如何在产品中集成使用CA数字证书,主要的目的和方向有以下几点: 有法律效力的电子文件的签署需要使用权威的证书颁发机构(CA)颁发的数字证书: 我们希望找到更便宜的证书方 ...
- ZincSearch轻量级全文搜索引擎入门到
ZincSearch轻量级全文搜索引擎入门到 Zinc是一个用于对文档进行全文搜索的搜索引擎.它是开源的,内置在 Go 中.Zinc不是从头开始构建索引引擎,而是构建在 bluge 之上,这是一个出色 ...
- Java日期时间处理详解
Java中SimpleDateFormat.LocalDateTime和DateTimeFormatter的区别及使用 在Java的世界里,处理日期和时间是常见的任务.尤其在Java 8之前,Simp ...
- Istio 为服务指定协议
1.背景 Istio 默认支持代理所有 TCP 流量.包括 HTTP.HTTPS.gRPC 以及原始 TCP 协议.但为了提供额外的能力,比如路由和丰富的指标,必须确定协议.协议可以被自动检测或者手动 ...
- LeetCode141环形链表I、II
141. 环形链表 给定一个链表,判断链表中是否有环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 -1,则在该链表中没有环. ...
- GaussDB技术解读系列丨运维自动驾驶探索
本文分享自华为云社区<DTCC 2023专家解读 | GaussDB技术解读系列之运维自动驾驶探索>,作者:GaussDB 数据库 . 近日,在第14届中国数据库技术大会(DTCC2023 ...
- 云小课 | 一分钟了解AppCube中的应用
阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:应用魔方(AppC ...