1//
2// Copyright 2011 Ettus Research LLC
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16//
17
18//
19// FIFO backed by an off chip ZBT/NoBL SRAM.
20//
21// This module and its sub-hierarchy implment a FIFO capable of sustaining
22// a data throughput rate of at least int_clk/2 * 36bits and bursts of int_clk * 36bits.
23//
24// This has been designed and tested for an int_clk of 100MHz and an ext_clk of 125MHz,
25// your milage may vary with other clock ratio's especially those where int_clk < ext_clk.
26// Testing has also exclusively used a rst signal synchronized to int_clk.
27//
28// Interface operation mimics a Xilinx FIFO configured as "First Word Fall Through",
29// though signal naming differs.
30//
31// For FPGA use registers interfacing directly with signals prefixed "RAM_*" should be
32// packed into the IO ring.
33//
34
35 //`define NO_EXT_FIFO
36
37module ext_fifo
38  #(parameter INT_WIDTH=36,EXT_WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19)
39    (
40     input int_clk,
41     input ext_clk,
42     input rst,
43     input [EXT_WIDTH-1:0] RAM_D_pi,
44     output [EXT_WIDTH-1:0] RAM_D_po,
45     output RAM_D_poe,
46     output [RAM_DEPTH-1:0] RAM_A,
47     output RAM_WEn,
48     output RAM_CENn,
49     output RAM_LDn,
50     output RAM_OEn,
51     output RAM_CE1n,
52     input [INT_WIDTH-1:0] datain,
53     input src_rdy_i,                // WRITE
54     output dst_rdy_o,               // not FULL
55     output [INT_WIDTH-1:0] dataout,
56     output src_rdy_o,               // not EMPTY
57     input dst_rdy_i,                 // READ
58     output reg [31:0] debug,
59     output reg [31:0] debug2
60     );
61
62   wire [EXT_WIDTH-1:0] write_data;
63   wire [EXT_WIDTH-1:0] read_data;
64   wire 		full1, empty1;
65   wire 		almost_full2, almost_full2_spread, full2, empty2;
66   wire [FIFO_DEPTH-1:0] capacity;
67   wire 		 space_avail;
68   wire 		 data_avail;
69
70   // These next 2 lines here purely because ICARUS is crap at handling generate statements.
71   // Empirically this has been determined to make simulations work.
72   wire 		 read_input_fifo = space_avail & ~empty1;
73   wire 		 write_output_fifo = data_avail;
74
75   assign 		 src_rdy_o = ~empty2;
76   assign 		 dst_rdy_o = ~full1;
77
78`ifdef NO_EXT_FIFO
79   assign 		 space_avail = ~full2;
80   assign 		 data_avail = ~empty1;
81   assign 		 read_data = write_data;
82`else
83
84   // External FIFO running at ext clock rate  and 18 or 36 bit width.
85   nobl_fifo  #(.WIDTH(EXT_WIDTH),.RAM_DEPTH(RAM_DEPTH),.FIFO_DEPTH(FIFO_DEPTH))
86     nobl_fifo_i1
87       (
88	   .clk(ext_clk),
89	   .rst(rst),
90	   .RAM_D_pi(RAM_D_pi),
91	   .RAM_D_po(RAM_D_po),
92	   .RAM_D_poe(RAM_D_poe),
93	   .RAM_A(RAM_A),
94	   .RAM_WEn(RAM_WEn),
95	   .RAM_CENn(RAM_CENn),
96	   .RAM_LDn(RAM_LDn),
97	   .RAM_OEn(RAM_OEn),
98	   .RAM_CE1n(RAM_CE1n),
99	   .write_data(write_data),
100	   .write_strobe(~empty1 ),
101	   .space_avail(space_avail),
102	   .read_data(read_data),
103	   .read_strobe(~almost_full2_spread),
104	   .data_avail(data_avail),
105	   .capacity(capacity)
106	   );
107`endif // !`ifdef NO_EXT_FIFO
108
109
110   generate
111      if (EXT_WIDTH == 18 && INT_WIDTH == 36) begin: fifo_g1
112	 // FIFO buffers data from UDP engine into external FIFO clock domain.
113	 fifo_xlnx_512x36_2clk_36to18 fifo_xlnx_512x36_2clk_36to18_i1 (
114								       .rst(rst),
115								       .wr_clk(int_clk),
116								       .rd_clk(ext_clk),
117								       .din(datain), // Bus [35 : 0]
118								       .wr_en(src_rdy_i),
119								       .rd_en(read_input_fifo),
120								       .dout(write_data), // Bus [17 : 0]
121								       .full(full1),
122							               .empty(empty1));
123
124
125	 // FIFO buffers data read from external FIFO into DSP clk domain and to TX DSP.
126	 fifo_xlnx_512x36_2clk_18to36 fifo_xlnx_512x36_2clk_18to36_i1 (
127								       .rst(rst),
128								       .wr_clk(ext_clk),
129								       .rd_clk(int_clk),
130								       .din(read_data), // Bus [17 : 0]
131								       .wr_en(write_output_fifo),
132								       .rd_en(dst_rdy_i),
133								       .dout(dataout), // Bus [35 : 0]
134								       .full(full2),
135								       .prog_full(almost_full2),
136								       .empty(empty2));
137      end // block: fifo_g1
138      else if (EXT_WIDTH == 36 && INT_WIDTH == 36) begin: fifo_g1
139	 // FIFO buffers data from UDP engine into external FIFO clock domain.
140	 fifo_xlnx_32x36_2clk fifo_xlnx_32x36_2clk_i1 (
141						       .rst(rst),
142						       .wr_clk(int_clk),
143						       .rd_clk(ext_clk),
144						       .din(datain), // Bus [35 : 0]
145						       .wr_en(src_rdy_i),
146						       .rd_en(read_input_fifo),
147						       .dout(write_data), // Bus [35 : 0]
148						       .full(full1),
149						       .empty(empty1));
150
151	 // FIFO buffers data read from external FIFO into DSP clk domain and to TX DSP.
152	 fifo_xlnx_512x36_2clk_prog_full fifo_xlnx_32x36_2clk_prog_full_i1 (
153									    .rst(rst),
154									    .wr_clk(ext_clk),
155									    .rd_clk(int_clk),
156									    .din(read_data), // Bus [35 : 0]
157									    .wr_en(write_output_fifo),
158									    .rd_en(dst_rdy_i),
159									    .dout(dataout), // Bus [35 : 0]
160									    .full(full2),
161									    .empty(empty2),
162									    .prog_full(almost_full2));
163
164      end
165   endgenerate
166
167
168   refill_randomizer #(.BITS(7))
169     refill_randomizer_i1 (
170			   .clk(ext_clk),
171			   .rst(rst),
172			   .full_in(almost_full2),
173			   .full_out(almost_full2_spread)
174			   );
175
176//   always @ (posedge int_clk)
177//     debug[31:28] <= {empty2,full1,dst_rdy_i,src_rdy_i };
178
179   always @ (posedge ext_clk)
180 //    debug[27:0] <= {RAM_WEn,RAM_CE1n,RAM_A[3:0],read_data[17:0],empty1,space_avail,data_avail,almost_full2 };
181     debug[31:0] <= {7'h0,src_rdy_i,read_input_fifo,write_output_fifo,dst_rdy_i,full2,almost_full2,empty2,full1,empty1,write_data[7:0],read_data[7:0]};
182
183
184   always@ (posedge ext_clk)
185     //     debug2[31:0] <= {write_data[15:0],read_data[15:0]};
186     debug2[31:0] <= 0;
187
188endmodule // ext_fifo
189