Testbench

仿真过程

  1. 读/写时钟域复位并释放

  2. 设计两串读/写使能序列,作为DUT的rd_en_i和wr_en_i输入,其值在相应时钟的上升沿发生变化

  3. 设计待写入数据序列从4’b0000开始递增,作为DUT的wr_dat_i输入,其值在写时钟的上升沿发生变化

  4. 完成复位释放后,同步给入使能信号和待写入数据,并观察相应输出信号的变化

备注

  • 为了分别验证慢时钟域(写)到快时钟域(读)和快时钟域(写)到慢时钟域(读),设置了两组激励,可根据实际需要选用

  • 已完成慢时钟域到快时钟域以及快时钟域到慢时钟域模式下的仿真验证,FIFO工作正常

仿真代码

tb_fifo.v
 1// testbench of fifo (top module)
 2`timescale 1ns/1ps
 3// `define HALF_CLK_PERIOD_RD 5
 4`define HALF_CLK_PERIOD_RD 18
 5// `define HALF_CLK_PERIOD_WR 18
 6`define HALF_CLK_PERIOD_WR 5
 7
 8module tb_fifo;
 9
10    parameter                           FIFO_DEPTH      =   8   ;
11    parameter                           FIFO_DAT_WD     =   4   ;
12    parameter                           FIFO_ADDR_WD    =   3   ;
13
14
15    reg                                 wr_clk      ;
16    reg                                 wr_rstn     ;
17    reg     [FIFO_DAT_WD    -1:0]       wr_dat_i    ;
18    wire                                wr_en_i     ;
19    reg                                 rd_clk      ;
20    reg                                 rd_rstn     ;
21    wire    [FIFO_DAT_WD    -1:0]       rd_dat_o    ;
22    wire                                rd_en_i     ;
23
24    fifo #(.FIFO_DEPTH(FIFO_DEPTH), .FIFO_DAT_WD(FIFO_DAT_WD), .FIFO_ADDR_WD(FIFO_ADDR_WD)) fifo(
25        .wr_clk     (   wr_clk      ),
26        .wr_rstn    (   wr_rstn     ),
27        .wr_dat_i   (   wr_dat_i    ),
28        .wr_en_i    (   wr_en_i     ),
29        .rd_clk     (   rd_clk      ),
30        .rd_rstn    (   rd_rstn     ),
31        .rd_dat_o   (   rd_dat_o    ),
32        .rd_en_i    (   rd_en_i     )
33    );
34
35    // reg     [64             -1:0]       rd_en_i_array   = 64'b0100000000000000000000000000000001010101010101010101010101010101;
36    reg     [64             -1:0]       rd_en_i_array   = 64'b0101010101010101010101010101010101010101010101010101010101010101;
37    // reg     [64             -1:0]       wr_en_i_array   = 64'b0000001010101010101010101010101010101010101010101010101010101010;
38    reg     [64             -1:0]       wr_en_i_array   = 64'b0000101010101010101010101010101000000000000000000000000000000000;
39
40    assign  rd_en_i         = rd_en_i_array     [64 -1] ;
41    assign  wr_en_i         = wr_en_i_array     [64 -1] ;
42
43    initial begin
44        rd_clk = 1'b0;
45        wr_clk = 1'b0;
46    end
47
48    always #(`HALF_CLK_PERIOD_RD) rd_clk = ~rd_clk;
49    always #(`HALF_CLK_PERIOD_WR) wr_clk = ~wr_clk;
50
51    initial begin
52        rd_rstn = 1'b0;
53        wr_rstn = 1'b0;
54        #21;
55        rd_rstn = 1'b1;
56        wr_rstn = 1'b1;
57    end
58
59    always@(posedge rd_clk) begin
60        if(rd_rstn) begin
61            rd_en_i_array   = rd_en_i_array     << 1;
62        end
63    end
64
65    always@(posedge wr_clk) begin
66        if(wr_rstn) begin
67            wr_en_i_array   = wr_en_i_array     << 1;
68        end
69    end
70
71    always @(posedge wr_clk or negedge wr_rstn) begin
72        if(~wr_rstn) begin
73            wr_dat_i = 0;
74        end
75        else begin
76            wr_dat_i = wr_dat_i + 1'b1;
77        end
78    end
79
80endmodule