同步FIFO设计(二)

目录

一、前言

二、原理

三、参考代码

 三、功能完备一点的同步FIFO


一、前言

  FIFO (First-In-First-Out) 是一种先进先出的数据交互方式,FIFO按工作时钟域的不同又可以分为:同步FIFO和异步FIFO。

  同步FIFO的写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑,常常用于交互数据缓冲异步FIFO的写时钟和读时钟为异步时钟,FIFO内部的写逻辑和读逻辑的交互需要异步处理,异步FIFO常用于跨时钟域处理

  更多介绍见FIFO存储器概念介绍_冬天里的棉袄博客-CSDN博客

二、原理

  典型同步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置位;

  

三、参考代码

 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

 三、功能完备一点的同步FIFO

下面这个FIFO具有寄存状room_avail,data_avail态判断FIFO内数据占用的状态

module synch_fifo #(parameter    FIFO_PTR     = 4,
                                 FIFO_WIDTH   = 32,
                                 FIFO_DEPTH   = 16)
                  (
                    clk,
                    rstn,
                    wren,
                    wrdata,
                    rden,
                    rddata,
                    full,
                    empty,
                    room_avail,
                    data_avail
                   );
 //***********************************************************
  input                     clk;
  input                     rstn;
  input                     wren;
  input  [FIFO_WIDTH-1:0]   wrdata;
  input                     rden;
  input  [FIFO_WIDTH-1:0]   rddata;
  output                    full;
  output                    empty;
  output [FIFO_PTR:0]       room_avail;
  output [FIFO_PTR:0]       data_avail;
  
  localparam  FIFO_DEPTH_MINUS1 = FIFO_DEPTH-1;
 //************************************************************
  reg    [FIFO_PTR-1:0]     wr_ptr,wr_ptr_nxt;
  reg    [FIFO_PTR-1:0]     rd_ptr,rd_ptr_nxt;
  reg    [FIFO_PTR:0]       num_entries,num_entries_nxt;
  reg                       full,empty;
  wire                      full_next,empty_nxt;
  reg    [FIFO_PTR:0]       room_avail;
  wire   [FIFO_PTR:0]       room_avail_next;
  wire   [FIFO_PTR:0]       data_avail;
  
 //write-pointer control logic
 //**********************************************************
 always@(*)
   begin
        wr_ptr_next = wr_ptr;
        if(wren)
          begin
            if(wr_ptr == FIFO_DEPTH_MINUS1)
              wr_ptr_next = 'd0;
            else
              wr_ptr_nxt = wr_ptr + 1'b1;
          end
   end

 //read-pointer control logic
 //************************************************************
  always@(*)
   begin
        rd_ptr_next = rd_ptr;
        if(rden)
          begin
            if(rd_ptr == FIFO_DEPTH_MINUS1)
              rd_ptr_next = 'd0;
            else
              rd_ptr_nxt = rd_ptr + 1'b1;
          end
   end

 //Calculate number of occupied entries in the FIFO
 //****************************************************************
 always@(*)
   begin
     num_entries_nxt = num_entries;
     if(wren && rden)                 //no change to num_entries 
       num_entries_nxt = num_entries;
     else if(wren)
       num_entries_nxt = num_entries + 1'b1;
     else if(rden)
       num_entries_nxt = num_entries - 1'b1;
   end

 assign full_nxt   = (num_entries_nxt == FIFO_DEPTH);
 assign empty_nxt  = (num_entries_nxt == 'd0);
 assign data_avail = num_entries;
 assign room_avail_nxt = (FIFO_DEPTH - num_entries_nxt);

 //********************************************************************
 always @(posedge clk or negedge rst_n)
   begin
     if(!rst_n)
       begin
            wr_ptr        <= 'd0;
            rd_ptr        <= 'd0;
            num_entries   <= 'd0;
            full          <=1'b0;
            empty         <=1'b1;
            room_avail    <=FIFO_DEPTH;
       end
     else
       begin
            wr_ptr        <= wr_ptr_nxt;
            rd_ptr        <= rd_ptr_nxt;
            num_entries   <= num_entries_nxt;
            full          <= full_nxt;
            empty         <= empty_nxt;
            room_avail    <= room_avail_nxt;
       end
   end
 
 //SRAM memory instantiation 
 //***********************************************************************
 sram u_srm #(.ADDR_WIDTH (FIFO_PTR),
              .DATA_WIDTH (FIFO_WIDTH),
              .MEM_DEPTH  (FIFO_DEPTH))
              
              (.wrclk        (clk),
               .rdclk        (clk),
               .wren         (wren),
               .rden         (rden),
               .wraddr       (wr_ptr),
               .rdaddr       (rd_ptr),
               .wrdata       (wrdata),
               .rddata       (rddata)
               );
endmodule

 双端口RAM代码

//dual port RAM   
module sram #(parameter  ADDR_WIDTH  =  3,
                         DATA_WIDTH  =  8,
                         MEM_DEPTH   =  8)
             (
               rddata,
               wraddr,
               rdaddr,
               wrdata,
               wren,
               rden,
               wrclk,
               rdclk
             );

   output [DATA_WIDTH-1:0] rddata;                 //output data
   input  [DATA_WIDTH-1:0] wrdata;                 //input data
   input  [ADDR_WIDTH-1:0] wraddr;                //write data address signal
   input  [ADDR_WIDTH-1:0] rdaddr;               //output data address signal
   input                   wren;                   //write data contral signal
   input                   rden;                   //read data contral signal
   input                   wrclk;                  //write data clock
   input                   rdclk;                  //read data clock

   reg    [DATA_WIDTH-1:0] rddata;
   reg    [DATA_WIDTH-1:0]mem[MEM_DEPTH-1:0];             //8*8 bites register

   always@(posedge wrclk)
     begin
        if(wren) begin
        mem[wraddr] <= wrdata;
        end
     end
   always@(posedge rdclk)
     begin
        if(rden) begin
       rddata <= mem[rdaddr];
        end   
     end
endmodule

 参考链接:

 【设计开发】 典型同步电路设计- 同步FIFO - digital-world - 博客园

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值