FIFO,First In First Out ,是一种先进先出的数据缓存器。

没有外部读写地址线,只能顺序写入数据,顺序的读出数据, 其数据地址由内部读写指针自动加1完成。

不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

FIFO一般用于不同时钟域之间的数据传输,根据工作的时钟域,分为同步FIFO和异步FIFO。

同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。

异步FIFO是指读写时钟不一致,读写时钟是互相独立的。

同步FIFO

 `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2018/05/02 21:34:02
// Design Name:
// Module Name: FIFO_16bits_16
// Project Name:
// Target Devices:
// Tool Versions:
// Description: synchronous fifo 16bits * 16
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define ADDR_WIDTH //ADDR WIDTH = 4,
`define FIFO_DEPTH //FIFO DEPTH
`define FIFO_WIDTH //FIFO WIDTH 16 BITS module myFIFO(
input wire clk,
input wire rst_n,
input wire wr_en,
input wire rd_en, //wire write/read enable
input wire [`FIFO_WIDTH:] buf_in, // data input to be pushed to buffer
output reg [`FIFO_WIDTH:] buf_out, // port to output the data using pop.
output wire buf_empty,
output wire buf_full, // fifo buffer empty/full indication
output reg [`ADDR_WIDTH:] fifo_cnt // number of data pushed in to buffer,16-> FULL;0-> EMPTY
); reg [`ADDR_WIDTH-:] rd_ptr,wr_ptr; //ADDR PTR .INDEX ,CYCLE 0->15->0->15
reg [`FIFO_WIDTH:] buf_mem[:`FIFO_DEPTH-];
reg rst_nr;
//juge full/empty
assign buf_empty = (fifo_cnt == )?:;
assign buf_full = (fifo_cnt == `FIFO_DEPTH)?:;
//Asynchronous reset,synch release
// always @(posedge clk)begin
// rst_nr <= rst_n;
// end
//FIFO_CNT
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
fifo_cnt <= ;
else if((!buf_full&&wr_en)&&(!buf_empty&&rd_en)) //WRTITE & READ ,HOLD
fifo_cnt <= fifo_cnt;
else if(!buf_full && wr_en) //WRITE-> +1
fifo_cnt <= fifo_cnt + ;
else if(!buf_empty && rd_en) //READ -> -1
fifo_cnt <= fifo_cnt-;
else
fifo_cnt <= fifo_cnt;
end
//READ
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
buf_out <= ;
if(rd_en && !buf_empty)
buf_out <= buf_mem[rd_ptr];
end
//WRITE
always @(posedge clk) begin
if(wr_en && !buf_full)
buf_mem[wr_ptr] <= buf_in;
end
//wr_ptr & rd_ptr ,ADDR PTR
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
wr_ptr <= ;
rd_ptr <= ;
end
else begin
if(!buf_full && wr_en)
wr_ptr <= wr_ptr + ;
if(!buf_empty && rd_en)
rd_ptr <= rd_ptr + ;
end
end endmodule

testbench

 `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2018/05/02 21:42:06
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define ADDR_WIDTH //ADDR WIDTH = 4,
`define BUF_DEPTH //FIFO DEPTH
`define FIFO_WIDTH //FIFO WIDTH 16 BITS module tb;
reg clk,rst_n;
reg wr_en,rd_en;
reg [:] buf_in; // data input to be pushed to buffer
wire [:] buf_out; // port to output the data using pop.
wire buf_empty,buf_full; // buffer empty and full indication
wire [`ADDR_WIDTH-:] fifo_cnt; // number of data pushed in to buffer myFIFO dut(
.clk(clk),
.rst_n(rst_n),
.buf_in(buf_in),
.buf_out(buf_out),
.wr_en(wr_en),
.rd_en(rd_en),
.buf_empty(buf_empty),
.buf_full(buf_full),
.fifo_cnt(fifo_cnt)
); always # clk = ~clk; reg [:] tempdata = ;
initial begin
clk = ;
rst_n = ;
wr_en = ;
rd_en = ;
buf_in = ;
#;
rst_n = ; push();
fork
push();
pop(tempdata);
join //push and pop together
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push();
push(); pop(tempdata);
push(tempdata); pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
push();
pop(tempdata);
push(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
push();
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata); #;
rst_n = ;
#;
rst_n = ;
push();
fork
push();
pop(tempdata);
join //push and pop together
push();
push();
push();
pop(tempdata);
pop(tempdata);
pop(tempdata);
end task push (input [:] data);
if(buf_full)
$display("---Cannot push %d: Buffer Full---",data);
else begin
$display("Push:%d",data);
buf_in = data;
wr_en = ;
@(posedge clk);
# wr_en = ;
end
endtask task pop(output[:] data);
if(buf_empty)
$display("---Cannot Pop: Buffer Empty---");
else begin
rd_en = ;
@(posedge clk);
# rd_en = ;
data = buf_out;
$display("------Poped:%d",data);
end
endtask endmodule

在综合是出现错误

[Synth 8-91] ambiguous clock in event control [:61]

是因为该段没有else语句,于是将该段改为

 //READ
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
buf_out <= ;
else begin
if(rd_en && !buf_empty)
buf_out <= buf_mem[rd_ptr];
end
end

通过。

//********************************************************************************

异步FIFO

参考了很多文章。

直接上代码

 `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2018/05/03 13:56:26
// Design Name:
// Module Name: AsyncFIFO
// Project Name:
// Target Devices:
// Tool Versions:
// Description: asynchronous fifo
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////// module AsyncFIFO
#(
parameter fifo_width = ,
parameter fifo_depth = , // = ((1<<addr_width) -1)
parameter addr_width =
)
(
input wire wclk,
input wire rclk,
input wire wrst_n,
input wire rrst_n,
input wire winc,
input wire rinc,
input wire [fifo_width-:] wdata,
output wire [fifo_width-:] rdata,
output reg wfull,
output reg rempty
//output reg [addr_width:0] fifo_cnt
); reg [addr_width:] wptr,rptr;
reg [addr_width:] rbin,wbin;
reg [addr_width:] wq1_rptr,rq1_wptr,wq2_rptr,rq2_wptr;
reg [fifo_width-:] fifo_mem [:fifo_depth-];
wire [addr_width-:] waddr,raddr;
wire [addr_width:] rgraynext,rbinnext,wgraynext,wbinnext;
wire rempty_val,wfull_val;
//snyc wptr
always @(posedge wclk or negedge wrst_n)
if(!wrst_n) begin
{wq2_rptr,wq1_rptr} <= ;
end
else begin
{wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
end
//snyc rptr
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) begin
{rq2_wptr,rq1_wptr} <= ;
end
else begin
{rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
end
//dualRAM
assign rdata = fifo_mem[raddr];
always@(posedge wclk)
if (winc && !wfull) fifo_mem[waddr] <= wdata;
//------------------------rempty & raddr----------------------------
always @(posedge rclk or negedge rrst_n) // GRAYSTYLE-2 pointer
if (!rrst_n) {rbin, rptr} <= ;
else {rbin, rptr} <= {rbinnext, rgraynext};
// Memory read-address pointer (okay to use binary to address memory)
assign raddr = rbin[addr_width-:];
assign rbinnext = rbin + (rinc & ~rempty);
assign rgraynext = (rbinnext>>) ^ rbinnext;//binary to gray
// FIFO empty when the next rptr == synchronized wptr or on reset
assign rempty_val = (rgraynext == rq2_wptr)?:;
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) rempty <= 'b1;
else rempty <= rempty_val;
//-----------------------wfull & waddr------------------------------
always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer
if (!wrst_n) {wbin, wptr} <= ;
else {wbin, wptr} <= {wbinnext, wgraynext};
// Memory write-address pointer (okay to use binary to address memory)
assign waddr = wbin[addr_width-:];
assign wbinnext = wbin + (winc & ~wfull);
assign wgraynext = (wbinnext>>) ^ wbinnext;
//------------------------------------------------------------------
// Simplified version of the three necessary full-tests:
// assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) &&
// (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) &&
// (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0]));
//------------------------------------------------------------------
assign wfull_val = (wgraynext=={~wq2_rptr[addr_width:addr_width-], wq2_rptr[addr_width-:]});
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) wfull <= 'b0;
else wfull <= wfull_val; endmodule

测试程序

 `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2018/05/03 16:53:39
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////// module tb;
// parameter fifo_width = 16;
// parameter fifo_depth = 16;
// parameter addr_width = 4; reg wclk,rclk,wrst_n,rrst_n;
reg winc,rinc;
reg [:] wdata;
wire [:] rdata;
wire rempty,wfull; AsyncFIFO i1(
.wclk(wclk),
.rclk(rclk),
.wrst_n(wrst_n),
.rrst_n(rrst_n),
.winc(winc),
.rinc(rinc),
.wdata(wdata),
.rdata(rdata),
.wfull(wfull),
.rempty(rempty)
);
always # wclk = ~wclk;
always # rclk = ~rclk; reg [:] tempdata;
reg [:] data1;
reg [:] data2;
initial begin
wclk = ;
rclk = ;
wrst_n = ;
rrst_n = ;
winc = ;
rinc = ;
wdata = ;
data1 = ; #
fork
wrst_n = ;
rrst_n = ;
join
#
push();
push();
push();
push();
#
//pop(tempdata);
//push and pop together
while()begin
fork
wr;
rd;
join
end
push();
push();
push();
push();
push(); end task wr;begin
while(!wfull)begin
push(data1);
data1 =data1+;
end
end
endtask task rd;begin
while(!rempty)
# pop(tempdata); end
endtask task push (input [:] data);
if(wfull)
$display("---Cannot push %d: Buffer Full---",data);
else begin
$display("Push:%d",data);
wdata = data;
winc = ;
@(posedge wclk);
# winc = ;
end
endtask task pop(output[:] data);
if(rempty)
$display("---Cannot Pop: Buffer Empty---");
else begin
rinc = ;
@(posedge rclk);
# rinc = ;
data = rdata;
$display("------Poped:%d",data);
end
endtask endmodule

测试算是通过,但还是有点问题。相同再弄了。

Verilog笔记.6.FIFO的更多相关文章

  1. Verilog笔记——Verilog数字系统设计(第二版)夏宇闻

    本片记录Verilog学习笔记,主要是和以往用的C语言的不同之处,以例子.代码的形式记录.学习以<Verilog数字系统设计>(第二版)为参考资料,援助作者夏宇闻. 1. C语言和Veri ...

  2. 基于Verilog的带FIFO写入缓冲的串口发送接口封装

    一.模块框图及基本思路 tx_module:串口发送的核心模块,详细介绍请参照前面的“基于Verilog的串口发送实验” fifo2tx_module:当fifo不为空时,读取fifo中的数据并使能发 ...

  3. 基于Verilog的带FIFO输出缓冲的串口接收接口封装

    一.模块框图及基本思路 rx_module:串口接收的核心模块,详细介绍请见“基于Verilog的串口接收实验” rx2fifo_module:rx_module与rx_fifo之间的控制模块,其功能 ...

  4. 基于Verilog的简单FIFO读写实验

    一.模块框图及基本思路 fifo_ip:ISE生成的IP fifo_control:在fifo未满情况下不断写入递增的四位数,每隔1s读出一个数据驱动Led显示 fifo_top:前两个模块的组合 二 ...

  5. Verilog设计异步FIFO

    转自http://ninghechuan.com 异步FIFO有两个异步时钟,一个端口写入数据,一个端口读出数据.通常被用于数据的跨时钟域的传输. 同步FIFO的设计.一个时钟控制一个计数器,计数器增 ...

  6. Verilog笔记.三段式状态机

    之前都是用的一段式状态机,逻辑与输出混在一起,复杂点的就比较吃力了. 所以就开始着手三段式状态机. 组合逻辑与时序逻辑分开,这样就能简单许多了. 但是两者在思考方式上也有着很大的区别. 三段式,分作: ...

  7. Verilog笔记.1.基本语法

    0.前 抽象模型分级: • 系统级(system):用高级语言结构实现设计模块的外部性能的模型.• 算法级(algorithm):用高级语言结构实现设计算法的模型.• RTL级(Register Tr ...

  8. Verilog笔记——YUV2RGB的模块测试

    1 YUV2RGB的模块如下: module yuv2rgb( clk, //时钟输入 rstn, //复位输入,低电平复位 y_in, //变换前Y分量输出 cb_in, //变换前Cb分量输出 c ...

  9. Verilog笔记.5.同步、异步

    在数字电路中经常有同步synchronism.异步asynchronism的概念.异步指输入信号和时钟无关:同步指输入信号和时钟信号有关,实际上就是输入信号和时钟信号进行了与运算或者与非运算.实际开发 ...

随机推荐

  1. (转)Elasticsearch search-guard 插件部署

    我之前写了ELK+shield的部署文档,由于shield是商业收费的,很多人都推崇开源项目search-guard来做ELK的安全组件,准确来说是elasticsearch的安全组件.search- ...

  2. hibernate.cfg.xml案例

    一.概念. hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库.既然学习Hibernate那么第 ...

  3. webgl 深度缓冲

    传统的画2d画布就是后画的会盖在先画的上面,但是在画一些三维图形时,这很难控制 深度缓冲区的作用就是区分颜色所在的层次,防止把被遮挡住的颜色显示出来. 深度缓冲很强大,用起来很简单 开启深度缓冲(测试 ...

  4. python3判断字典、列表、元组为空以及字典是否存在某个key的方法

    #!/usr/bin/python3 #False,0,'',[],{},()都可以视为假 m1=[] m2={} m3=() m4={"name":1,"age&quo ...

  5. SQL中的逻辑运算符

    逻辑运算符和比较运算符一样,都是返回 true 或 false 值得布尔数据类型.   运算符 行为 ALL 如果一个比较集中全部都是 true ,则值为 true AND 如果两个布尔值表达式均为 ...

  6. day 008 文件操作

    08. 万恶之源-⽂文件操作本节主要内容:1. 初识⽂文件操作2. 只读(r, rb)3. 只写(w, wb)4. 追加(a, ab)5. r+读写6. w+写读7. a+写读(追加写读)8. 其他操 ...

  7. 【开发工具IDE】Eclipse相关配置

    1. 修改workspace编码为UTF-8 1.1. 修改jsp编码为UTF-8 2. 修改字体 3. 添加系统中的JDK 4. 导入formatter模板 5. 修改maven配置文件 打开文件: ...

  8. The Necklace UVA - 10054(欧拉回路)

    题目分析:1.无向图欧拉回路是否连通2.所有点的度为偶数.并查集+degree 这题题目保证了是联通的  所以就不用判断是否联通了 #include <iostream> #include ...

  9. Java SSM 整合

    从2012年的“用户标签”到2014年的“用户画像”,从2015年的“大数据”到2017年的“人工智能”,大数据正在从神坛走向现实.“标签”到“画像”,代表着数据在数量和维度上,逐渐在丰富:“大数据” ...

  10. Linux内核设计与实现第四周读书笔记

    第5章系统调用 5.1与内核通信 主要作用: 为用户控件提供了一种硬件的抽象接口. 保证了系统稳定性与安全性. 为用户空间&系统提供公共接口. 5.2API.POSIX和C库 一般情况,应用程 ...