最近在学习FIFO,于是将学习成果记录一下。

仿真工具为VCS,并用DVE观测波形。

FIFO 表示先入先出,它是一种存储器结构,被广泛的应用与芯片设计中。FIFO分为同步FIFO和异步FIFO,本次记录同步FIFO的设计和验证。

在同步FIFO中,单一时钟同时用于写入和读取数据操作。FIFO的设计原则:满不能写,空不能读。

以下是FIFO的结构框图:

Verilog RTL 设计:同步FIFO的设计与验证 方法一_Verilog

 

 

 

 

 

 

 

 

设计的关键: 如何产生empty和full信号。

      方法一:采用一个计数器,当执行一次写操作时,计数器加1,执行一次读操作时,计数器减一。

          当计数器为0时,说明FIFO为空,或者计数器为1时,此时正在执行读操作,都说明FIFO为空。此时empty拉高。

          当计数器为最大FIFO深度时,说明FIFO为满,或者计数器差一个到最大FIFO深度,而此时正在写操作,都说明FIFO为满,此时full拉高。

                      在后续会采用另外一种方法来实现FIFO的空满信号的产生。

RTL设计:

 

 1 module    sync_fifo #(parameter     DATA_WIDTH = 8, 2                                     DATA_DEPTH = 16, 3                                     ADDR_WIDTH = 4) 4 (   input    wire                    clk, 5     input     wire                    rst_n, 6     input    wire                    wr_en, 7     input    wire[DATA_WIDTH-1:0]    wr_data, 8     input     wire                     rd_en, 9     output     reg [DATA_WIDTH-1:0]    rd_data,10     output    reg                        full,11     output    reg                     empty12 );13 //addr14 reg[ADDR_WIDTH-1:0]        wr_addr,rd_addr;15 //memory16 reg[DATA_WIDTH-1:0]        mem[DATA_DEPTH-1:0];17 //counter18 reg[ADDR_WIDTH-1:0]        count;19 20 wire                    rd_allow = rd_en && !empty;21 wire                    wr_allow = wr_en && !full;22 23 24 //empty25 always @(posedge clk or negedge rst_n)26     if (!rst_n)27         empty <= 1'b1;28     else29         empty <= (!wr_en && count[ADDR_WIDTH-1:1]=='b0) && (count[0]==1'b0 || rd_en);30         31 //full32 always @(posedge clk or negedge rst_n)33     if (!rst_n)34         full <= 1'b0;35     else36         full <= (!rd_en && count[ADDR_WIDTH-1:1]=={ADDR_WIDTH-1{1'b1}})  && (count[0]==1'b1 || wr_en);37 38 //rd_addr39 always @(posedge clk or negedge rst_n)40     if (!rst_n)41         rd_addr <= 'd0;42     else if(rd_allow) begin43         rd_data <= mem[rd_addr];44         rd_addr <= rd_addr + 1'b1;45     end46         47 48 //wr_addr49 always @(posedge clk or negedge rst_n)50     if (!rst_n)51         wr_addr <= 'd0;52     else if(wr_allow) begin53         mem[wr_addr] <= wr_data;54         wr_addr <= wr_addr + 1'b1;55     end56 57 always @(posedge clk or negedge rst_n)58     if (!rst_n)59         count <= 'd0;60     else if ( (!rd_allow && wr_allow) || (rd_allow && !wr_allow) ) begin61         if( wr_allow )62             count <= count + 1'b1;63         else 64             count <= count - 1'b1;65     end66 67 endmodule

 

testbench设计:

 

 1 `timescale 1ns/1ps 2 module sync_fifo_tb; 3  4 parameter        DATA_WIDTH = 8, 5                 DATA_DEPTH = 16, 6                 ADDR_WIDTH = 4, 7                 PERIOD       = 20; 8  9 10 reg                        clk,rst_n,wr_en,rd_en;11 reg[DATA_WIDTH-1:0]        wr_data;12 wire                    full,empty;13 wire[DATA_WIDTH-1:0]    rd_data;14 15 sync_fifo #(.DATA_WIDTH(DATA_WIDTH),16             .DATA_DEPTH(DATA_DEPTH),17             .ADDR_WIDTH(ADDR_WIDTH)18             )19 sync_fifo_inst(    
20     .clk    (clk    ),21     .rst_n    (rst_n    ),22     .wr_en    (wr_en    ),23     .wr_data(wr_data),24     .rd_en    (rd_en    ),25     .rd_data(rd_data),26     .full    (full    ),27     .empty    (empty    )28 );29 30 initial begin31     rst_n = 0;32     clk = 0;33     #534     rst_n = 1;35 end36 37 always #(PERIOD/2)    clk=~clk;38 39 initial begin40     wr_en = 0;41     rd_en = 0;42     #543     wr_en = 1;44     #20    wr_data = 8'h0;45     #20    wr_data = 8'h1;46     #20    wr_data = 8'h2;47     #20    wr_data = 8'h3;48     #20    wr_data = 8'h4;49     #20    wr_data = 8'h5;50     #20    wr_data = 8'h6;51     #20    wr_data = 8'h7;52     #20    wr_data = 8'h8;53     #20    wr_data = 8'h9;54     #20    wr_data = 8'hA;55     #20    wr_data = 8'hB;56     #20    wr_data = 8'hC;57     #20    wr_data = 8'hD;58     #20    wr_data = 8'hE;59     #20    wr_data = 8'hF;60     rd_en = 1;61     wr_en = 0;62     #40063     $finish;64 end65 66 endmodule

DVE仿真:

Verilog RTL 设计:同步FIFO的设计与验证 方法一_Verilog_02

此次记录同步FIFO的设计。