verilog之异步FIFO代码,已验证,有波形

源代码

module fifo_async 
  #(parameter    FIFO_PTR   = 4                              ,
                 FIFO_WIDTH = 32                                           
 )
 (
  input                               fifo_wr_clk            ,
  input                               fifo_wr_reset_n        ,
  input                               fifo_wren              ,
  input       [(FIFO_WIDTH-1) : 0]    fifo_wrdata            ,
  input                               fifo_rd_clk            ,
  input                               fifo_rd_reset_n        ,
  input                               fifo_rden              ,
  input       [(FIFO_WIDTH-1) : 0]    fifo_rddata            ,
  output                              fifo_full              ,
  output                              fifo_empty                      
 );
 
 localparam   FIFO_DEPTH = 1 << FIFO_PTR                     ;
  reg         [FIFO_PTR : 0]          wr_ptr                 ;
  reg         [FIFO_PTR : 0]          wr_ptr_gray            ;
  reg         [FIFO_PTR : 0]          wr_gray_buf1           ;
  reg         [FIFO_PTR : 0]          wr_gray_buf2           ;
  reg         [FIFO_PTR : 0]          wr_ptr_sync            ;
  reg         [FIFO_PTR : 0]          rd_ptr                 ;
  reg         [FIFO_PTR : 0]          rd_ptr_gray            ;
  reg         [FIFO_PTR : 0]          rd_gray_buf1           ;
  reg         [FIFO_PTR : 0]          rd_gray_buf2           ;
  reg         [FIFO_PTR : 0]          rd_ptr_sync            ;
  wire                                wren_ram               ;
  wire                                rden_ram               ;
  integer                             i                      ;
  integer                             j                      ;
  
//write_ptr 
  always@(posedge fifo_wr_clk or negedge fifo_wr_reset_n) begin                     
    if(!fifo_wr_reset_n) 
      wr_ptr   <= 'd0                                        ; 
    else if(wren_ram) 
      wr_ptr   <= wr_ptr + 1'b1                              ;
   end 
  assign wren_ram  = (fifo_wren && (!fifo_full))             ;
  assign fifo_full = (wr_ptr[FIFO_PTR] ^ rd_ptr_sync[FIFO_PTR]) && (wr_ptr[FIFO_PTR-1 : 0] == rd_ptr_sync[FIFO_PTR-1 : 0]) ;
  
//read_ptr 
  always@(posedge fifo_rd_clk or negedge fifo_rd_reset_n) begin                     
    if(!fifo_rd_reset_n) 
      rd_ptr   <= 'd0                                        ; 
    else if(rden_ram) 
      rd_ptr   <= rd_ptr + 1'b1                              ;
   end 
  assign rden_ram   = (fifo_rden && (!fifo_empty))           ;
  assign fifo_empty = (rd_ptr[FIFO_PTR : 0] == wr_ptr_sync[FIFO_PTR : 0]) ; 
  
//write to read,fifo_full
//bin to gray
  always@(posedge fifo_wr_clk or negedge fifo_wr_reset_n) begin                   
    if(!fifo_wr_reset_n) 
      wr_ptr_gray <= 'd0                                     ;
    else
      wr_ptr_gray <= wr_ptr ^ (wr_ptr >>1)                   ;
   end
   
  always@(posedge fifo_rd_clk or negedge fifo_rd_reset_n) begin                   
    if(!fifo_rd_reset_n) begin
      wr_gray_buf1 <= 'd0                                    ;
      wr_gray_buf2 <= 'd0                                    ;
     end
    else begin
      wr_gray_buf1 <= wr_ptr_gray                            ;
      wr_gray_buf2 <= wr_gray_buf1                           ;
    end
   end
    
 //gray to bin 
  always@(posedge fifo_rd_clk or negedge fifo_rd_reset_n) begin                   
    if(!fifo_rd_reset_n) 
      wr_ptr_sync <= 'd0                                     ;
    else begin
      wr_ptr_sync[FIFO_PTR] <= wr_gray_buf2[FIFO_PTR]        ;
      for (i=0;i<FIFO_PTR;i=i+1)
        wr_ptr_sync[i] <= ^(wr_gray_buf2 >>i)                 ;
    end
   end
   
//read to write,fifo_empty
//bin to gray
  always@(posedge fifo_rd_clk or negedge fifo_rd_reset_n) begin                   
    if(!fifo_rd_reset_n) 
      rd_ptr_gray <= 'd0                                     ;
    else
      rd_ptr_gray <= rd_ptr ^ (rd_ptr >>1)                   ;
   end
   
  always@(posedge fifo_wr_clk or negedge fifo_wr_reset_n) begin                   
    if(!fifo_wr_reset_n) begin
      rd_gray_buf1 <= 'd0                                    ;
      rd_gray_buf2 <= 'd0                                    ;
     end
    else begin
      rd_gray_buf1 <= rd_ptr_gray                            ;
      rd_gray_buf2 <= rd_gray_buf1                           ;
    end
   end
    
 //gray to bin 
  always@(posedge fifo_wr_clk or negedge fifo_wr_reset_n) begin                   
    if(!fifo_wr_reset_n) 
      rd_ptr_sync <= 'd0                                     ;
    else begin
      rd_ptr_sync[FIFO_PTR] <= rd_gray_buf2[FIFO_PTR]        ;
      for (j=0;j<FIFO_PTR;j=j+1)
        rd_ptr_sync[j] <= ^(rd_gray_buf2 >>j)                ;
    end
   end
  
  fifo_async_ram
  #(            .FIFO_PTR    (FIFO_PTR)                      ,
                .FIFO_WIDTH  (FIFO_WIDTH)
  ) U_fifo_async_ram
  (
                    .wrclk    (fifo_wr_clk)                  ,
                    .wren     (wren_ram)                     ,
                    .wrptr    (wr_ptr)                       ,
                    .wrdata   (fifo_wrdata)                  ,
                    .rdclk    (fifo_rd_clk)                  ,
                    .rden     (rden_ram)                     ,
                    .rdptr    (rd_ptr)                       ,
                    .rddata   (fifo_rddata)
  );
  
endmodule

SRAM代码

module fifo_async_ram
  #(parameter    FIFO_PTR   = 4                        ,
                 FIFO_WIDTH = 32
  )
  (
  input                              wrclk             ,
  input                              wren              ,
  input      [(FIFO_PTR-1) : 0]      wrptr             ,
  input      [(FIFO_WIDTH-1) : 0]    wrdata            ,
  input                              rdclk             ,
  input                              rden              ,
  input      [(FIFO_PTR-1) : 0]      rdptr             ,
  output reg [(FIFO_WIDTH-1) : 0]    rddata
  );
  
  localparam FIFO_DEPTH = 1 << FIFO_PTR                ;
  reg  [(FIFO_WIDTH-1) : 0] ram [0:(FIFO_DEPTH - 1)]   ;
  reg  [(FIFO_WIDTH-1) : 0] rdata                      ;
  always@(posedge wrclk) begin
    if(wren)
      ram[wrptr] <= wrdata                             ;
    end
    
  always@(posedge rdclk) begin
    if(rden)
      rddata <=ram [rdptr]                             ;
    end
endmodule

tb代码

`timescale 1ns/1ps
module fifo_sync_tb()                                 ;
  parameter       FIFO_PTR   = 4                      ;
  parameter       FIFO_WIDTH = 32                     ;              
  parameter       CYCLE      = 10                     ;//100MHz
  
  reg                                fifo_wr_clk      ;
  reg                                fifo_wr_reset_n  ;
  reg                                fifo_wren        ;
  reg  [(FIFO_WIDTH-1) : 0]          fifo_wrdata      ;
  reg                                fifo_rd_clk      ;
  reg                                fifo_rd_reset_n  ;
  reg                                fifo_rden        ;
  wire [(FIFO_WIDTH-1) : 0]          fifo_rddata      ;
  wire                               fifo_full        ;
  wire                               fifo_empty       ;
  
  
  fifo_async 
  #(             .FIFO_PTR   (FIFO_PTR)               ,
                 .FIFO_WIDTH (FIFO_WIDTH)                                           
 ) U_fifo_async
 (
                 .fifo_wr_clk      (fifo_wr_clk)      ,
                 .fifo_wr_reset_n  (fifo_wr_reset_n)  ,
                 .fifo_wren        (fifo_wren)        ,
                 .fifo_wrdata      (fifo_wrdata)      ,
                 .fifo_rd_clk      (fifo_rd_clk)      ,
                 .fifo_rd_reset_n  (fifo_rd_reset_n)  ,
                 .fifo_rden        (fifo_rden)        ,
                 .fifo_rddata      (fifo_rddata)      ,
                 .fifo_full        (fifo_full)        ,
                 .fifo_empty       (fifo_empty)                     
 );
 
 initial begin
                 fifo_wr_clk      = 1'b0              ;  
                 fifo_wr_reset_n  = 1'b0              ;
                 fifo_wrdata      = 32'd0             ;
                 fifo_rd_clk      = 1'b0              ;  
                 fifo_rd_reset_n  = 1'b0              ;                 
                 fifo_wren        = 1'b0              ; 
                 fifo_rden        = 1'b0              ;   

                 #(CYCLE+1)
                 fifo_wr_reset_n  = 1'b1              ; 
                 fifo_rd_reset_n  = 1'b1              ;                  
                                  
                 #(CYCLE*2+1)     
                 fifo_wren        = 1'b1              ;                   
                 fifo_rden        = 1'b0              ;
                                  
                 #(CYCLE*20+1)    
                 fifo_wren        = 1'b0              ;                   
                 fifo_rden        = 1'b1              ; 
                                  
                 #(CYCLE*10+1)    
                 fifo_wren        = 1'b1              ;                   
                 fifo_rden        = 1'b0              ; 
                                  
                 #(CYCLE*20+1)    
                 fifo_wren        = 1'b0              ;                   
                 fifo_rden        = 1'b1              ; 
                                  
                 #(CYCLE*10+1)    
                 fifo_wren        = 1'b1              ;                   
                 fifo_rden        = 1'b1              ; 
                                  
                 #(CYCLE*20+1)    
                 fifo_wren        = 1'b0              ;                   
                 fifo_rden        = 1'b1              ;

                 #(CYCLE*2000+1)
                 $stop                                ;  
     end
  always #(CYCLE/2) fifo_wr_clk = ~fifo_wr_clk        ;
  always #(CYCLE/3) fifo_rd_clk = ~fifo_rd_clk        ;
  
  
  always@(posedge fifo_wr_clk or negedge fifo_wr_reset_n) begin                     
    if(!fifo_wr_reset_n) 
      fifo_wrdata   <= #(CYCLE/10) 32'd0              ; 
    else if(fifo_wren && (!fifo_full)) 
      fifo_wrdata   <= #(CYCLE/10) fifo_wrdata + 1'b1 ;
    else
      fifo_wrdata   <= #(CYCLE/10) 32'd0              ; 
   end 
   
endmodule                                           

如下图所示,空间写满时,fifo_full为1在这里插入图片描述
如下图所示,数据读完时,fifo_empty为1
在这里插入图片描述
写指针同步到读时钟域
在这里插入图片描述
读指针同步到写时钟域
在这里插入图片描述

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页