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