同步FIFO学习
在网上找的一个经典同步FIFO例子。
一、前言
FIFO (First-In-First-Out) 是一种先进先出的数据交互方式,在数字ASIC设计中常常被使用。FIFO按工作时钟域的不同又可以分为:同步FIFO和异步FIFO。
同步FIFO的写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑,常常用于交互数据缓冲。异步FIFO的写时钟和读时钟为异步时钟,FIFO内部的写逻辑和读逻辑的交互需要异步处理,异步FIFO常用于跨时钟域交互。
本文介绍同步FIFO的典型设计方法。
二、原理
典型同步FIFO有三部分组成: (1) FIFO写控制逻辑; (2)FIFO读控制逻辑; (3)FIFO 存储实体(如Memory、Reg)。
FIFO写控制逻辑主要功能:产生FIFO写地址、写有效信号,同时产生FIFO写满、写错等状态信号;
FIFO读控制逻辑主要功能:产生FIFO读地址、读有效信号,同时产生FIFO读空、读错等状态信号。
如下图所示,FIFO读写过程的地址控制:
(1)当FIFO初始化(复位)时fifo_write_addr与fifo_read_addr同指到0x0,此时FIFO处于空状态;
(2)当FIFO进行写操作时,fifo_write_addr递增(增加到FIFO DEPTH时回绕),与fifo_read_addr错开,此时FIFO处于非空状态;
(3)当FIFO进行读操作时,fifo_read_addr递增;
FIFO空满状态产生:
为产生FIFO空满标志,引入FIFO Count计数器,FIFO Count寄数器用于指示FIFO内部存储数据个数;
(1)当只有写操作时,FIFO Count加1;只有读操作是,FIFO Count减1;其他情况下,FIFO Count保持;
(2)当FIFO Count为0时,说明FIFO为空,fifo_empty置位;
(3)当FIFO Count等于FIFO_DEPTH时,说明FIFO已满,fifo_full置位;
三、代码
1 //--====================================================================================-- 2 // THIS FILE IS PROVIDED IN SOURCE FORM FOR FREE EVALUATION, FOR EDUCATIONAL USE OR FOR 3 // PEACEFUL RESEARCH. DO NOT USE IT IN A COMMERCIAL PRODUCT . IF YOU PLAN ON USING THIS 4 // CODE IN A COMMERCIAL PRODUCT, PLEASE CONTACT JUSTFORYOU200@163.COM TO PROPERLY LICENSE 5 // ITS USE IN YOUR PRODUCT. 6 // 7 // Project : Verilog Common Module 8 // File Name : sync_fifo_ctrl.v 9 // Creator(s) : justforyou200@163.com 10 // Date : 2015/12/01 11 // Description : A sync fifo ctrl 12 // 13 // Modification : 14 // (1) Initial design 2015-12-01 15 // 16 // 17 //--====================================================================================-- 18 19 module SYNC_FIFO_CTRL 20 ( 21 clk , 22 rst_n , 23 fifo_wr_en , 24 fifo_rd_en , 25 fifo_wr_data , 26 fifo_full , 27 fifo_wr_err , 28 fifo_empty , 29 fifo_rd_err , 30 fifo_data_cnt , 31 fifo_rd_data 32 ); 33 34 //PARA DECLARATION 35 parameter FIFO_DATA_WIDTH = 32 ; 36 parameter FIFO_ADDR_WIDTH = 8 ; 37 38 //INPUT DECLARATION 39 input clk ; //fifo clock 40 input rst_n ; //fifo clock reset (0: reset) 41 input fifo_wr_en ; //fifo write enable(1: enable) 42 43 input fifo_rd_en ; //fifo read enable(1: enable) 44 input [FIFO_DATA_WIDTH-1:0] fifo_wr_data ; //fifo write data 45 46 //OUTPUT DECLARATION 47 output fifo_full ; //fifo full status 48 output fifo_wr_err ; //fifo write error status 49 output fifo_empty ; //fifo empty status 50 output fifo_rd_err ; //fifo read error status 51 output [FIFO_ADDR_WIDTH :0] fifo_data_cnt; //fifo valid data cnt 52 output [FIFO_DATA_WIDTH-1:0] fifo_rd_data ; //fifo read data 53 54 //INTER DECLARATION 55 wire fifo_full ; //fifo full status 56 wire fifo_wr_err ; //fifo write error status 57 wire fifo_empty ; //fifo empty status 58 wire fifo_rd_err ; //fifo read error status 59 reg [FIFO_ADDR_WIDTH :0] fifo_data_cnt; //fifo valid data cnt 60 reg [FIFO_DATA_WIDTH-1:0] fifo_rd_data ; //fifo read data 61 reg [FIFO_ADDR_WIDTH-1:0] fifo_wr_addr ; //fifo write addr 62 reg [FIFO_ADDR_WIDTH-1:0] fifo_rd_addr ; //fifo write addr 63 64 //FIFO MEMORY INSTANCE 65 reg [FIFO_DATA_WIDTH-1:0] fifo_mem [{(FIFO_ADDR_WIDTH){1'b1}}:0] ; 66 integer i ; 67 68 //--========================MODULE SOURCE CODE==========================-- 69 70 //--=========================================-- 71 // SRAM INSTANCE : 72 // You Can use Reg Memory or Memory model here; 73 // FIFO Wdata & FIFO Rdata; 74 //--=========================================-- 75 always @(posedge clk or negedge rst_n) 76 begin 77 if(rst_n == 1'b0) 78 begin 79 for(i=0;i<= {(FIFO_ADDR_WIDTH){1'b0}};i=i+1) 80 fifo_mem[i] <= {(FIFO_DATA_WIDTH){1'b0}} ; 81 end 82 else if (fifo_wr_en & (~ fifo_full)) 83 fifo_mem[fifo_wr_addr] <= fifo_wr_data ; 84 end 85 86 always @(posedge clk or negedge rst_n) 87 begin 88 if(rst_n == 1'b0) 89 fifo_rd_data <= {(FIFO_DATA_WIDTH){1'b0}} ; 90 else if (fifo_rd_en & (~ fifo_empty)) 91 fifo_rd_data <= fifo_mem[fifo_rd_addr] ; 92 end 93 94 //--=========================================-- 95 // READ CONTROL : 96 // Read address increase when read enable AND 97 // Not empty; 98 //--=========================================-- 99 always @(posedge clk or negedge rst_n) 100 begin 101 if(rst_n == 1'b0) 102 fifo_rd_addr <= {(FIFO_ADDR_WIDTH){1'b0}} ; 103 else if (fifo_rd_en & (~ fifo_empty)) 104 fifo_rd_addr <= fifo_rd_addr + 1'b1 ; 105 end 106 107 //--=========================================-- 108 // WRITE CONTROL : 109 // Write address increase when write enable AND 110 // Not full. 111 //--=========================================-- 112 always @(posedge clk or negedge rst_n) 113 begin 114 if(rst_n == 1'b0) 115 fifo_wr_addr <= {(FIFO_ADDR_WIDTH){1'b0}} ; 116 else if (fifo_wr_en & (~ fifo_full)) 117 fifo_wr_addr <= fifo_wr_addr + 1'b1 ; 118 end 119 120 //--=========================================-- 121 // FIFO DATA CNT : 122 // Valid Write Only, increase data cnt; 123 // Valid Read Only, decrease data cnt; 124 //--=========================================-- 125 always @(posedge clk or negedge rst_n) 126 begin 127 if(rst_n == 1'b0) 128 fifo_data_cnt <= {(FIFO_ADDR_WIDTH + 1){1'b0}} ; 129 else if (fifo_wr_en & (~ fifo_full) & (~(fifo_rd_en & (~fifo_empty)))) //Valid Write Only, increase data cnt; 130 fifo_data_cnt <= fifo_data_cnt + 1'b1 ; 131 else if (fifo_rd_en & (~ fifo_empty) & (~(fifo_wr_en & (~fifo_full)))) //Valid Read Only, decrease data cnt; 132 fifo_data_cnt <= fifo_data_cnt - 1'b1 ; 133 end 134 135 //--=========================================-- 136 // FIFO Status : 137 // 1. fifo_empty when cnt ==0 ; 138 // 2. fifo full when cnt == MAX ; 139 //--=========================================-- 140 assign fifo_empty = (fifo_data_cnt == 0 ) ; 141 assign fifo_rd_err = (fifo_data_cnt == 0 ) & fifo_rd_en ; 142 143 assign fifo_full = (fifo_data_cnt == ({(FIFO_ADDR_WIDTH){1'b1}} +1) ) ; 144 assign fifo_wr_err = (fifo_data_cnt == ({(FIFO_ADDR_WIDTH){1'b1}} +1) ) & fifo_wr_en ; 145 146 endmodule