调试成功的简单异步FIFO--verilog实现+testbench

最近在写一个异步FIFO的时候,从网上找了许多资料,文章都写的相当不错,只是附在后面的代码都多多少少有些小错误。

于是自己写了一个调试成功的代码,放上来供大家参考。

非原创 原理参考下面:

原文 https://www.cnblogs.com/SYoong/p/6110328.html

上代码:

 1 module Asyn_FIFO
 2 #(
 3     parameter WIDTH = 8,
 4     parameter DEPTH = 4
 5 )
 6 (
 7     input  clk_wr,
 8     input  clk_rd,
 9     input  rst_n_rd,
10     input  rst_n_wr,
11     input  wr_en,
12     input  rd_en,
13     input  [WIDTH-1:0] data_wr,
14     output [WIDTH-1:0] data_rd,
15     output reg rd_empty,
16     output reg wr_full
17 );
18 
19     //defination
20     reg  [WIDTH-1 : 0] mem [0 : (1<<DEPTH)-1];        //2^DEPTH numbers
21     reg  [DEPTH   : 0] wp, rp;
22     reg  [DEPTH   : 0] wr1_rp, wr2_rp, rd1_wp, rd2_wp;
23     reg  [DEPTH   : 0] wbin, rbin;
24 
25 
26     wire [DEPTH-1 : 0] waddr, raddr;
27     wire [DEPTH   : 0] wbin_next, rbin_next;        //bincode
28     wire [DEPTH   : 0] wgray_next, rgray_next;        //graycode
29     
30     wire rd_empty_val, wr_full_val;
31     
32     //output
33     assign data_rd = mem[raddr];
34 
35     //input
36     always@(posedge clk_wr)
37         if(wr_en && !wr_full)
38             mem[waddr] <= data_wr;
39 
40 /*----------generate waddr and raddr-------------------------*/
41     //gen raddr and read gray code
42     always@(posedge clk_rd or negedge rst_n_rd)
43         if(!rst_n_rd)
44             {rbin, rp} <= 0;
45         else
46             {rbin, rp} <= {rbin_next, rgray_next};
47 
48     assign raddr = rbin[DEPTH-1 : 0];
49     assign rbin_next = rbin + (rd_en & ~rd_empty);
50     assign rgray_next = rbin_next ^ (rbin_next >> 1);
51 
52     //gen waddr and write gray code
53     always@(posedge clk_wr or negedge rst_n_wr)
54         if(!rst_n_wr)
55             {wbin, wp} <= 0;
56         else
57             {wbin, wp} <= {wbin_next, wgray_next};
58 
59     assign waddr = wbin[DEPTH-1 : 0];
60     assign wbin_next = wbin + (wr_en & ~wr_full);
61     assign wgray_next = wbin_next ^ (wbin_next >> 1);
62 
63 /*---------------synchro rp and wp--------------------------*/
64     //synchro rp
65     always@(posedge clk_wr or negedge rst_n_wr)
66         if(!rst_n_wr)
67             {wr2_rp, wr1_rp} <= 0;
68         else
69             {wr2_rp, wr1_rp} <= {wr1_rp, rp}; //delay two clock
70 
71     //synchro wp
72     always@(posedge clk_rd or negedge rst_n_rd)
73         if(!rst_n_rd)
74             {rd2_wp, rd1_wp} <= 0;
75         else
76             {rd2_wp, rd1_wp} <= {rd1_wp, wp};
77 
78 /*---------------empty and full flags--------------------------*/
79     //gen rd_empty
80     assign rd_empty_val = (rd2_wp == rgray_next);
81     always@(posedge clk_rd or negedge rst_n_rd)
82         if(!rst_n_rd)
83             rd_empty <= 1'b1;
84         else
85             rd_empty <= rd_empty_val;
86 
87     //gen wr_full, two high bit do not equal
88     assign wr_full_val = ({~wr2_rp[DEPTH : DEPTH-1], wr2_rp[DEPTH-2 : 0]} == wgray_next);
89     always@(posedge clk_wr or negedge rst_n_wr)
90         if(!rst_n_wr)
91             wr_full <= 1'b0;
92         else
93             wr_full <= wr_full_val;
94 
95 endmodule
Asyn_FIFO.v
 1 module Asyn_FIFO_tb;
 2 
 3     parameter WIDTH = 8;
 4 
 5     reg clk_wr;
 6     reg clk_rd;
 7     reg rst_n_rd;
 8     reg rst_n_wr;
 9 
10     reg  [WIDTH-1:0] data_wr;
11     reg  wr_en;
12     wire wr_full;
13 
14     wire [WIDTH-1:0] data_rd;
15     reg  rd_en;
16     wire rd_empty;
17 
18 
19     Asyn_FIFO fifo_inst(
20     .clk_wr(clk_wr), 
21     .rst_n_rd(rst_n_rd),
22     .rst_n_wr(rst_n_wr),
23     .wr_en(wr_en), 
24     .data_wr(data_wr), 
25     .clk_rd(clk_rd), 
26     .rd_en(rd_en), 
27     .data_rd(data_rd), 
28     .rd_empty(rd_empty), 
29     .wr_full(wr_full)
30     );
31     
32     initial begin
33         rst_n_rd = 0;
34         rst_n_wr = 0;
35         clk_wr = 0;
36         clk_rd = 0;
37         wr_en = 0;
38         rd_en = 0;
39         
40         #20
41         rst_n_rd = 1;
42         rst_n_wr = 1;
43         
44         #80
45         wr_en = 1;
46         rd_en = 0;
47         
48         #10000
49         wr_en = 0;
50         rd_en = 1;
51     end
52 
53     always #10 clk_wr = ~clk_wr;
54     always #20 clk_rd = ~clk_rd;
55     
56 /*     always @(posedge clk_rd)
57         rd_en <= ($random) % 2;
58 
59     always @(posedge clk_wr)
60         wr_en <= ($random) % 2; */
61     
62     always @(posedge clk_wr)
63         data_wr <= ($random) % 256;
64     
65 endmodule
Asyn_FIFO_tb.v

注意wire、reg类型的赋值。

猜你喜欢

转载自www.cnblogs.com/HolmeXin/p/9448626.html