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

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

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

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

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

以下是FIFO的结构框图:

 

 

 

 

 

 

 

 

设计的关键: 如何产生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                     empty
12 );
13 //addr
14 reg[ADDR_WIDTH-1:0]        wr_addr,rd_addr;
15 //memory
16 reg[DATA_WIDTH-1:0]        mem[DATA_DEPTH-1:0];
17 //counter
18 reg[ADDR_WIDTH-1:0]        count;
19 
20 wire                    rd_allow = rd_en && !empty;
21 wire                    wr_allow = wr_en && !full;
22 
23 
24 //empty
25 always @(posedge clk or negedge rst_n)
26     if (!rst_n)
27         empty <= 1'b1;
28     else
29         empty <= (!wr_en && count[ADDR_WIDTH-1:1]=='b0) && (count[0]==1'b0 || rd_en);
30         
31 //full
32 always @(posedge clk or negedge rst_n)
33     if (!rst_n)
34         full <= 1'b0;
35     else
36         full <= (!rd_en && count[ADDR_WIDTH-1:1]=={ADDR_WIDTH-1{1'b1}})  && (count[0]==1'b1 || wr_en);
37 
38 //rd_addr
39 always @(posedge clk or negedge rst_n)
40     if (!rst_n)
41         rd_addr <= 'd0;
42     else if(rd_allow) begin
43         rd_data <= mem[rd_addr];
44         rd_addr <= rd_addr + 1'b1;
45     end
46         
47 
48 //wr_addr
49 always @(posedge clk or negedge rst_n)
50     if (!rst_n)
51         wr_addr <= 'd0;
52     else if(wr_allow) begin
53         mem[wr_addr] <= wr_data;
54         wr_addr <= wr_addr + 1'b1;
55     end
56 
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) ) begin
61         if( wr_allow )
62             count <= count + 1'b1;
63         else 
64             count <= count - 1'b1;
65     end
66 
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 begin
31     rst_n = 0;
32     clk = 0;
33     #5
34     rst_n = 1;
35 end
36 
37 always #(PERIOD/2)    clk=~clk;
38 
39 initial begin
40     wr_en = 0;
41     rd_en = 0;
42     #5
43     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     #400
63     $finish;
64 end
65 
66 endmodule

DVE仿真:

此次记录同步FIFO的设计。

关注公众号,回复“sync_fifo_1” 可获源码。

 

 

posted @ 2021-03-14 01:58  辰风阆苑  阅读(910)  评论(0编辑  收藏  举报