这个同步FIFO的设计方法是调用异步读写双端口RAM来实现的。

关于异步读写双端口RAM的设计,前面博文已经讲到过了:【FPGA】双端口RAM的设计(异步读写)

此时使用双端口RAM来设计FIFO,可以使用一套端口进行写操作,一套端口进行读操作的方式来实现,例如例化方式大概是这样的:

ram_dp_ar_aw #(DATA_WIDTH,ADDR_WIDTH) DP_RAM (
.address_0 (wr_pointer) , // address_0 input 
.data_0    (data_in)    , // data_0 bi-directional
.cs_0      (wr_cs)      , // chip select
.we_0      (wr_en)      , // write enable
.oe_0      (1'b0)       , // output enable
.address_1 (rd_pointer) , // address_q input
.data_1    (data_ram)   , // data_1 bi-directional
.cs_1      (rd_cs)      , // chip select
.we_1      (1'b0)       , // Read enable
.oe_1      (rd_en)        // output enable
);

这样就可以同时读写。


其原理大概如此:

FIFO uses a dual port memory and there will be two pointers to point read and write addresses. Here is a generalized block diagram of FIFO.

Generally fifos are implementedusing rotating pointers. We can call write and read pointers of a FIFO as headand tail of data area. Initially read and write pointers of the FIFO will pointto the same location

Here is an example to explain howFIFO uses the memory. This is a fifo of length 8, WP and RP are the locationswhere write pointer and read pointer points. Shaded area in the diagram isfilled with data.

When ever FIFO counter becomes zeroor BUF_LENGTH, empty or full flags will be set.

使用fifo_counter记录FIFO RAM中的数据个数,等于0时,给出empty信号,等于BUF_LENGTH时,给出full信号

fifo_counter is incremented ifwrite takes place and buffer is not full and will be decremented id read takesplace and buffer is not empty. If both read and write takes place, counter willremain the same.

fifo_counter写而未满时增加1,读而未空时减1。同时发生读写操作时,fifo_counter不变。

rd_ptr and wr_ptr are read andwrite pointers. Since we selected the bits in these registers same as addresswidth of buffer, when buffer overflows, values will overflow and become 0.

读写指针宽度与地址宽度相当,地址增加而溢出后,自动变成0。

给出同步FIFO的Verilog描述:

`timescale 1ns / 1ps
//-----------------------------------------------------
// Design Name : syn_fifo
// File Name   : syn_fifo.v
// Function    : Synchronous (single clock) FIFO
//-----------------------------------------------------
module syn_fifo (
clk      , // Clock input
rst      , // Active high reset
wr_cs    , // Write chip select
rd_cs    , // Read chipe select
data_in  , // Data input
rd_en    , // Read enable
wr_en    , // Write Enable
data_out , // Data Output
empty    , // FIFO empty
full       // FIFO full
);    // FIFO constants
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 8;
parameter RAM_DEPTH = (1 << ADDR_WIDTH);
// Port Declarations
input clk ;
input rst ;
input wr_cs ;
input rd_cs ;
input rd_en ;
input wr_en ;
input [DATA_WIDTH-1:0] data_in ;
output full ;
output empty ;
output [DATA_WIDTH-1:0] data_out ;//-----------Internal variables-------------------
reg [ADDR_WIDTH-1:0] wr_pointer;
reg [ADDR_WIDTH-1:0] rd_pointer;
reg [ADDR_WIDTH :0] status_cnt;
reg [DATA_WIDTH-1:0] data_out ;
wire [DATA_WIDTH-1:0] data_ram ;//-----------Variable assignments---------------
assign full = (status_cnt == (RAM_DEPTH));
assign empty = (status_cnt == 0);//-----------Code Start---------------------------
always @ (posedge clk or posedge rst)
begin : WRITE_POINTERif (rst) beginwr_pointer <= 0;end else if (wr_cs && wr_en ) beginwr_pointer <= wr_pointer + 1;end
endalways @ (posedge clk or posedge rst)
begin : READ_POINTERif (rst) beginrd_pointer <= 0;end else if (rd_cs && rd_en ) beginrd_pointer <= rd_pointer + 1;end
endalways  @ (posedge clk or posedge rst)
begin : READ_DATAif (rst) begindata_out <= 0;end else if (rd_cs && rd_en ) begindata_out <= data_ram;end
endalways @ (posedge clk or posedge rst)
begin : STATUS_COUNTERif (rst) beginstatus_cnt <= 0;// Read but no write.end else if ((rd_cs && rd_en) && !(wr_cs && wr_en) && (status_cnt != 0)) beginstatus_cnt <= status_cnt - 1;// Write but no read.end else if ((wr_cs && wr_en) && !(rd_cs && rd_en) && (status_cnt != RAM_DEPTH)) beginstatus_cnt <= status_cnt + 1;end
end ram_dp_ar_aw #(DATA_WIDTH,ADDR_WIDTH) DP_RAM (
.address_0 (wr_pointer) , // address_0 input
.data_0    (data_in)    , // data_0 bi-directional
.cs_0      (wr_cs)      , // chip select
.we_0      (wr_en)      , // write enable
.oe_0      (1'b0)       , // output enable
.address_1 (rd_pointer) , // address_q input
.data_1    (data_ram)   , // data_1 bi-directional
.cs_1      (rd_cs)      , // chip select
.we_1      (1'b0)       , // Read enable
.oe_1      (rd_en)        // output enable
);     endmodule

给出异步读写双端口RAM的Verilog描述代码:

`timescale 1ns / 1ps
//
// Create Date: 2019/05/29 21:11:08
// Design Name:
// Module Name: ram_dp_ar_aw
//module ram_dp_ar_aw #(parameter DATA_WIDTH = 8,parameter ADDR_WIDTH = 8,parameter RAM_DEPTH = 1 << ADDR_WIDTH )(input [ADDR_WIDTH - 1 : 0] address_0,inout [DATA_WIDTH - 1 : 0] data_0,input cs_0,input we_0,input oe_0,input [ADDR_WIDTH - 1 : 0] address_1,inout [DATA_WIDTH - 1 : 0] data_1,input cs_1,input we_1,input oe_1);reg [DATA_WIDTH - 1 : 0] mem [RAM_DEPTH - 1 : 0];integer i;// initializationinitial beginfor(i = 0; i < RAM_DEPTH; i = i + 1) beginmem[i] = 0;endend//writealways@(*) beginif(cs_0 && we_0) beginmem[address_0] = data_0;endelse if(cs_1 && we_0) beginmem[address_1] = data_1;endelse;end//readreg [DATA_WIDTH - 1 : 0] data_out0;assign data_0 = (cs_0 && !we_0 && oe_0) ? data_out0  : 'hz;always@(*) beginif(cs_0 && !we_0 && oe_0) begindata_out0 = mem[address_0];endelse begindata_out0 = 0;endendreg [DATA_WIDTH - 1 : 0] data_out1;assign data_1 = (cs_1 && !we_1 && oe_1) ? data_out1 : 'hz;always@(*) beginif(cs_1 && !we_1 && oe_1) begindata_out1 = mem[address_1];endelse begindata_out1 = 0;endendendmodule

简单测试下:

测试代码:

`timescale 1ns / 1ps
//
// Create Date: 2019/05/29 22:01:38
// Design Name:
// Module Name: syn_fifo_tb
//module syn_fifo_tb();reg clk ;reg rst ;reg wr_cs ;reg rd_cs ;reg rd_en ;reg wr_en ;reg [7:0] data_in ;wire full ;wire empty ;wire [7:0] data_out ;initial beginclk = 0;forever#2 clk = ~clk;endinteger i=0;initial beginrst = 1;wr_cs = 0;rd_cs = 0;wr_en = 0;rd_en = 0;data_in = 0;#8rst = 0;//writewr_cs = 1;wr_en = 1;for(i = 0; i < 256; i = i + 1) begin@(negedge clk) begindata_in = data_in + 1;endend//read//#8wr_cs = 0;wr_en = 0;rd_cs = 1;rd_en = 1;endsyn_fifo u_syn_fifo(.clk(clk),.rst(rst),.wr_cs(wr_cs),.rd_cs(rd_cs),.rd_en(rd_en),.wr_en(wr_en),.data_in(data_in),.full(full),.empty(empty),.data_out(data_out));endmodule

当然测试代码并没有测试同时读写的情况,但至少验证了,先进先出的事实,且读写数据都符合预期。

下一篇:异步FIFO的设计

【FPGA】FIFO的Verilog设计之同步FIFO的设计相关推荐

  1. 跨时钟域信号处理(二)——异步fifo的Verilog实现(附同步fifo的实现)

    需要回答几个问题: 1.什么是异步FIFO,异步FIFO有什么功能? 跨时钟域的数据交换,防止亚稳态. 2.在产生写满与读空信号时需要进行跨时钟域如何做的,且如何能正确指示空满状态? 寄存器打两拍+格 ...

  2. 01 【Verilog实战】同步FIFO的设计(附源码RTL/TB)

    虚拟机:VMware -14.0.0.24051 环 境:ubuntu 18.04.1 脚 本:makefile(点击查看) 应用工具:vcs 和 verdi 写在前面 这个专栏的内容记录的是个人学习 ...

  3. 7 centos 时钟跟物理机同步_同步FIFO和异步FIFO

    1.定义 FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出 ...

  4. 同步fifo与异步fifo

    参考以下帖子: https://blog.csdn.net/hengzo/article/details/49683707 https://blog.csdn.net/Times_poem/artic ...

  5. 同步FIFO和异步FIFO

    1.定义 FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出 ...

  6. FPGA基础知识极简教程(3)从FIFO设计讲起之同步FIFO篇

    博文目录 写在前面 正文 FPGA/ASIC中的FIFO 同步FIFO的设计 参考资料 交个朋友 写在前面 个人博客首页 注:学习交流使用! 正文 FPGA/ASIC中的FIFO FIFO缓冲区如何用 ...

  7. 可能是最简单的同步fifo 的设计

    文章目录 可能是最简单的同步fifo 设计 什么是FIFO FIFO的分类 设计FIFO的关键 FIFO空满判断方法 本次同步FIFO设计的基本参数 具体代码实现过程 可能是最简单的同步fifo 设计 ...

  8. 02【Verilog实战】异步FIFO设计(附源码RTL/TB)

    脚 本:makefile 工 具:vcs 和 verdi 文 章:1. 同步FIFO的设计和功能验证(附源码)     2. Verilog的亚稳态现象和跨时钟域处理方法 写在前面 这个专栏的内容记录 ...

  9. Verilog实现FIFO专题5-异步FIFO设计(异步FIFO工作方式、异步FIFO介绍、异步FIFO介绍)

    FIFO根据输入输出时钟是否一致,分为同步FIFO与异步FIFO.同步FIFO中,读写控制信号以及数据均处于同一时钟域,满足STA分析时一般不会出现亚稳态等不稳定情形:而对于异步FIFO,读写相关信号 ...

最新文章

  1. 星光不问赶路人——任正非
  2. Android中Activity和task,活动亲和力,启动模式,活动状态以及生命周期,激活钝化
  3. R语言心得-分词包的安装
  4. matlab xlsread参数_利用MATLAB批量完成科研数据处理
  5. stm32 ucosii消息队列 串口_STM32F1的UART4串口配置
  6. 薄荷Toolbar(ActionBar)的适配方案
  7. FGSM攻击机器学习模型
  8. 实现Matlab将16进制数据存储到txt文件
  9. 硕士论文查重原理与快速通过的七大方法(转载)
  10. 5位数的数字黑洞是多少_揭秘数字黑洞6174
  11. 一些特殊字符(如:←↑→↓等箭头符号)的Unicode码值
  12. HTML基础学习(全)
  13. 攻防世界web做题步骤
  14. 【算法】滴滴-2021校招在线笔试0913 X星文
  15. 豆豆趣事[2016年06月]
  16. 符合OpenDRIVE规范的xodr文件格式解读(1) ——road部分
  17. 宿舍管理系统(Java毕业设计)
  18. 如何退出SCALA命令界面
  19. mini6410移植全攻略(4)--uboot移植之支持nand flansh启动(中)
  20. 基于Python的ADF单位根检验方法——时间序列平稳检验

热门文章

  1. 网页编程,JS模态窗口,子页面向父页面传递值
  2. 镜头视场角计算工具_什么是变焦镜头 变焦镜头介绍【详解】
  3. 3704对象关闭时_VB中“对象关闭时,不允许操作”解决方案 3704 錯誤 | 学步园...
  4. php4种九九乘法表编程,PHP 99乘法表的几种实现代码
  5. 公司--ajax获取数据
  6. python括号匹配算法_使用Python的栈实现括号匹配算法
  7. android文字广告的循环滚动,android怎样写一个循环文字滚动的TextView
  8. 第十六届全国大学智能汽车竞赛全向组沁恒芯片申请统计情况
  9. 2021春季学期-创新设计与实践-Lesson5
  10. 新工科教育的实践与思考——曾勇校长在工程教育高峰论坛上的报告