最近在写一个异步FIFO的时候,从网上找了许多资料,文章都写的相当不错,只是附在后面的代码都多多少少有些小错误。
于是自己写了一个调试成功的代码,放上来供大家参考。
非原创 原理参考下面:
原文 https://www.cnblogs.com/SYoong/p/6110328.html
上代码:
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
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 = (rd_en && !rd_empty) ? mem[raddr] : 0; //clear "xx" state 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
注意wire、reg类型的赋值。