Verilog笔记.6.FIFO
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的更多相关文章
- Verilog笔记——Verilog数字系统设计(第二版)夏宇闻
本片记录Verilog学习笔记,主要是和以往用的C语言的不同之处,以例子.代码的形式记录.学习以<Verilog数字系统设计>(第二版)为参考资料,援助作者夏宇闻. 1. C语言和Veri ...
- 基于Verilog的带FIFO写入缓冲的串口发送接口封装
一.模块框图及基本思路 tx_module:串口发送的核心模块,详细介绍请参照前面的“基于Verilog的串口发送实验” fifo2tx_module:当fifo不为空时,读取fifo中的数据并使能发 ...
- 基于Verilog的带FIFO输出缓冲的串口接收接口封装
一.模块框图及基本思路 rx_module:串口接收的核心模块,详细介绍请见“基于Verilog的串口接收实验” rx2fifo_module:rx_module与rx_fifo之间的控制模块,其功能 ...
- 基于Verilog的简单FIFO读写实验
一.模块框图及基本思路 fifo_ip:ISE生成的IP fifo_control:在fifo未满情况下不断写入递增的四位数,每隔1s读出一个数据驱动Led显示 fifo_top:前两个模块的组合 二 ...
- Verilog设计异步FIFO
转自http://ninghechuan.com 异步FIFO有两个异步时钟,一个端口写入数据,一个端口读出数据.通常被用于数据的跨时钟域的传输. 同步FIFO的设计.一个时钟控制一个计数器,计数器增 ...
- Verilog笔记.三段式状态机
之前都是用的一段式状态机,逻辑与输出混在一起,复杂点的就比较吃力了. 所以就开始着手三段式状态机. 组合逻辑与时序逻辑分开,这样就能简单许多了. 但是两者在思考方式上也有着很大的区别. 三段式,分作: ...
- Verilog笔记.1.基本语法
0.前 抽象模型分级: • 系统级(system):用高级语言结构实现设计模块的外部性能的模型.• 算法级(algorithm):用高级语言结构实现设计算法的模型.• RTL级(Register Tr ...
- Verilog笔记——YUV2RGB的模块测试
1 YUV2RGB的模块如下: module yuv2rgb( clk, //时钟输入 rstn, //复位输入,低电平复位 y_in, //变换前Y分量输出 cb_in, //变换前Cb分量输出 c ...
- Verilog笔记.5.同步、异步
在数字电路中经常有同步synchronism.异步asynchronism的概念.异步指输入信号和时钟无关:同步指输入信号和时钟信号有关,实际上就是输入信号和时钟信号进行了与运算或者与非运算.实际开发 ...
随机推荐
- vue-cli配置axios,并基于axios进行后台请求函数封装
文章https://www.cnblogs.com/XHappyness/p/7677153.html已经对axios配置进行了说明,后台请求时可直接this.$axios直接进行.这里的缺点是后端请 ...
- PHP面向对象之接口
接口(interface)技术 什么是接口? 先看抽象类: abstract class 类名 { 属性1: 属性2: ..... 非抽象方法1: 非抽象方法2: ...... 抽象方法1: 抽 ...
- HDU4497——GCD and LCM
这个题目挺不错的,看到是通化邀请赛的题目,是一个很综合的数论题目. 是这样的,给你三个数的GCD和LCM,现在要你求出这三个数有多少种可能的情况. 对于是否存在这个问题,直接看 LCM%GCD是否为0 ...
- Django 2.0 学习(14):Django ORM 数据库操作(上)
Django ORM 数据库操作(上) ORM介绍 映射关系: 数据库表名 ---------->类名:数据库字段 ---------->类属性:数据库表一行数据 ----------&g ...
- 【JavaScript&jQuery】$.ajax()
$(function(){ $('#send').click(function(){ $.ajax({ type: "GET", url: "test.json" ...
- hbase 基本的JavaApi 数据操作及数据过滤(filter)
本文主要是hbase的表操作.数据操作.数据查询过滤等,如果对JDBC或ADO有了解,容易理解HBASE API. hbase版本是2.0. 1.为了方便先贴helper的部分代码(文末git上有完整 ...
- 【BZOJ4311】向量(线段树分治,斜率优化)
[BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...
- 【BZOJ3052】【UOJ#58】【WC2013】糖果公园(树上莫队)
[BZOJ3052][UOJ#58][WC2013]糖果公园(树上莫队) 题面 UOJ 洛谷 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引 ...
- Unity3D动态加载外部MovieTexture视频
网上大家也写了很多Unity3D中播放视频的教程,关于播放外部视频的还是比较少,所以写这篇文章,不足之处,还望读者指正. 在Unity3D中,我们一般使用播放视频的方法:将*.mov,*.mp4等格式 ...
- tyvj1305 最大子序和 【单调队列优化dp】
描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当m=2或m=3时,S=5+1=6 输 ...