异步FIFO的设计

  1 `timescale 1ns / 1ns
  2 module async_fifo #(
  3     parameter   DP = 8,
  4     parameter   DW = 32 )(
  5     input               wr_clk,
  6     input               wr_reset_n,
  7     input               wr_en,
  8     input   [DW-1:0]    wr_data,
  9     output              full,
 10     output              afull,
 11     input               rd_clk,
 12     input               rd_reset_n,
 13     input               rd_en,
 14     output  [DW-1:0]    rd_data,
 15     output              empty,
 16     output              aempty
 17 );
 18 
 19 localparam  AW      = $clog2(DP);
 20 localparam  WR_FAST = 1'b1;
 21 localparam  RD_FAST = 1'b1;
 22 
 23 reg     [DW-1:0]    mem[DP-1:0];
 24 reg     [AW:0]      sync_rd_ptr_0, sync_rd_ptr_1;
 25 wire    [AW:0]      sync_rd_ptr;
 26 reg                 full_q;
 27 reg     [AW:0]      wr_ptr, gray_wr_ptr;
 28 reg     [AW:0]      gray_rd_ptr;
 29 wire    [AW:0]      wr_ptr_inc = wr_ptr + 1'b1;
 30 wire    [AW:0]      wr_cnt = get_cnt(wr_ptr, sync_rd_ptr);
 31 wire                full_c  = (wr_cnt == DP) ? 1'b1 : 1'b0;
 32 reg     [AW:0]      sync_wr_ptr_0, sync_wr_ptr_1;
 33 wire    [AW:0]      sync_wr_ptr;
 34 reg     [AW:0]      rd_ptr;
 35 reg                 empty_q;
 36 wire    [AW:0]      rd_ptr_inc = rd_ptr + 1'b1;
 37 wire    [AW:0]      rd_cnt = get_cnt(sync_wr_ptr, rd_ptr);
 38 wire                empty_c  = (rd_cnt == 0) ? 1'b1 : 1'b0;
 39 reg     [DW-1:0]    rd_data_q;
 40 wire    [DW-1:0]    rd_data_c = mem[rd_ptr[AW-1:0]];
 41 
 42 always @(posedge wr_clk or negedge wr_reset_n)
 43     if (!wr_reset_n) begin
 44         wr_ptr <= 'd0;
 45         gray_wr_ptr <= 'd0;
 46         full_q <= 'b0;
 47     end
 48     else if (wr_en) begin
 49         wr_ptr <= wr_ptr_inc;
 50         gray_wr_ptr <= bin2gray(wr_ptr_inc);
 51         if (wr_cnt == (DP-'d1)) begin
 52             full_q <= 'b1;
 53         end
 54     end
 55     else begin
 56         if (full_q && (wr_cnt<DP)) begin
 57             full_q <= 'b0;
 58         end
 59     end
 60 
 61 assign full  = (WR_FAST == 1) ? full_c : full_q;
 62 assign afull = (wr_cnt >= DP/2 - 1) ? 1'b1 : 1'b0;
 63 
 64 always @(posedge wr_clk)
 65     if (wr_en) begin
 66         mem[wr_ptr[AW-1:0]] <= wr_data;
 67     end
 68 
 69 // read pointer synchronizer
 70 always @(posedge wr_clk or negedge wr_reset_n)
 71     if (!wr_reset_n) begin
 72         sync_rd_ptr_0 <= 'b0;
 73         sync_rd_ptr_1 <= 'b0;
 74     end
 75     else begin
 76         sync_rd_ptr_0 <= gray_rd_ptr;
 77         sync_rd_ptr_1 <= sync_rd_ptr_0;
 78     end
 79 
 80 assign sync_rd_ptr = gray2bin(sync_rd_ptr_1);
 81 
 82 always @(posedge rd_clk or negedge rd_reset_n)
 83     if (!rd_reset_n) begin
 84         rd_ptr <= 'd0;
 85         gray_rd_ptr <= 'd0;
 86         empty_q <= 'b1;
 87     end
 88     else begin
 89         if (rd_en) begin
 90             rd_ptr <= rd_ptr_inc;
 91             gray_rd_ptr <= bin2gray(rd_ptr_inc);
 92             if (rd_cnt=='d1) begin
 93                 empty_q <= 'b1;
 94             end
 95         end
 96         else begin
 97             if (empty_q && (rd_cnt!='d0)) begin
 98                 empty_q <= 'b0;
 99             end
100         end
101     end
102 
103 assign empty  = (RD_FAST == 1) ? empty_c : empty_q;
104 assign aempty = (rd_cnt < DP/2 - 'd3) ? 1'b1 : 1'b0;
105 
106 always @(posedge rd_clk)
107     rd_data_q <= rd_data_c;
108 
109 assign rd_data  = (RD_FAST == 1) ? rd_data_c : rd_data_q;
110 
111 // write pointer synchronizer
112 always @(posedge rd_clk or negedge rd_reset_n)
113     if (!rd_reset_n) begin
114        sync_wr_ptr_0 <= 'b0;
115        sync_wr_ptr_1 <= 'b0;
116     end
117     else begin
118        sync_wr_ptr_0 <= gray_wr_ptr;
119        sync_wr_ptr_1 <= sync_wr_ptr_0;
120     end
121 
122 assign sync_wr_ptr = gray2bin(sync_wr_ptr_1);
123 
124 function [AW:0] get_cnt;
125 input [AW:0] wr_ptr, rd_ptr;
126 begin
127     if (wr_ptr >= rd_ptr) begin
128         get_cnt = (wr_ptr - rd_ptr);
129     end
130     else begin
131         get_cnt = DP*2 - (rd_ptr - wr_ptr);
132     end
133 end
134 endfunction
135 
136 function [AW:0] bin2gray;
137 input   [AW:0]  bin;
138 
139 bin2gray = (bin >> 1) ^ bin;
140 
141 endfunction
142 
143 function [AW:0] gray2bin;
144 input   [AW:0]  gray;
145 integer         k;
146 
147 for (k = 0; k <= AW; k = k + 1)
148     gray2bin[k] = ^(gray >> k);
149 
150 endfunction
151 
152 endmodule
原文地址:https://www.cnblogs.com/lyuyangly/p/6816212.html