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深度(简单来说就是需要存多少个数据) ...
随机推荐
- Blazor入门100天 : 自做一个支持长按事件的按钮组件
好长时间没继续写这个系列博客了, 不知道大家还记得我吗? 话不多说,直接开撸. 1. 新建 net8 blazor 工程 b19LongPressButton 至于用什么模式大家各取所需, 我创建的是 ...
- 【Python微信机器人】第六篇:优化使用方式,可pip安装
优化内容 这篇不聊技术点,说一下优化后的Python机器人代码怎么使用,优化内容如下: 将hook库独立成一个库,发布到pypi,可使用pip安装 将微信相关的代码发布成另一个库,也可以pip安装 g ...
- 数据库系列:业内主流MySQL数据中间件梳理
数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩容 数据库 ...
- 华企盾DSC客户端连接服务器正常,控制台找不到客户端
1.首先客户端查一下策略状态,看一下客户端在哪个组,是否在回收站,或者无策略组: 2.查看一下数据库的CLIENT_GROUP_TABLE_表中是否有查出来的组,CLIENT_GROUP_TABLE_ ...
- WinRM服务应用及配置说明
一.什么是winRM服务 1.1.winRM服务介绍 Windows远程管理(WinRM)服务是Windows Server 2003 R2以上版本中一种新式的方便远程管理的服务.通过WinRM服务, ...
- 降低node版本,怎么降低node版本
降低node版本,怎么降低node版本? 部分老旧项目需要使用低版本的node,网上很多是无效的,高版本无法直接安装低版本node,但是低版本nodejs可以安装部分高版本node,从而达到升级效果. ...
- STM32CubeMX教程10 RTC 实时时钟 - 周期唤醒、闹钟A/B事件和备份寄存器
本实验主要使用STM32CubeMX软件配置STM32F407开发板实现RTC周期唤醒.闹钟A/B事件功能,周期唤醒中输出RTC时间,闹钟A/B事件发生时利用串口输出闹钟A/B事件发生提示 1.准备材 ...
- DevOps|我们需要什么样的产研项目管理工具
上一篇文章<DevOps|产研运协作工具链上的皇冠-项目管理工具>主要讲了项目管理工具对软件研发的重要性,本篇文章主要想讲清楚我们需要什么样的项目管理工具,项目管理工具必须具备的功能有哪些 ...
- 物联网通信技术最全科普!你一定要了解的NB-IoT
摘要: NB-IoT(窄带蜂窝物联网)产业正在迅速崛起. 我们这一期的文章主要是普及一些NB-IoT通信技术的相关知识点.也希望你能get到属于自己的知识盲点! 一.前言 NB-IoT(窄带蜂窝物联网 ...
- 使用appuploader工具发布证书和描述性文件教程
使用APPuploader工具发布证书和描述性文件教程 之前用AppCan平台开发了一个应用,平台可以同时生成安卓版和苹果版,想着也把这应用上架到App Store试试,于是找同学借了个苹果开发者账号 ...