diff options
Diffstat (limited to 'usrp2/extramfifo')
-rw-r--r-- | usrp2/extramfifo/ext_fifo.v | 29 | ||||
-rw-r--r-- | usrp2/extramfifo/ext_fifo_tb.v | 70 | ||||
-rw-r--r-- | usrp2/extramfifo/nobl_fifo.v | 229 |
3 files changed, 102 insertions, 226 deletions
diff --git a/usrp2/extramfifo/ext_fifo.v b/usrp2/extramfifo/ext_fifo.v index 398e5ef81..c6a64fc65 100644 --- a/usrp2/extramfifo/ext_fifo.v +++ b/usrp2/extramfifo/ext_fifo.v @@ -15,8 +15,10 @@ // packed into the IO ring. // + //`define NO_EXT_FIFO + module ext_fifo - #(parameter INT_WIDTH=36,EXT_WIDTH=18,DEPTH=19) + #(parameter INT_WIDTH=36,EXT_WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19) ( input int_clk, input ext_clk, @@ -24,7 +26,7 @@ module ext_fifo input [EXT_WIDTH-1:0] RAM_D_pi, output [EXT_WIDTH-1:0] RAM_D_po, output RAM_D_poe, - output [DEPTH-1:0] RAM_A, + output [RAM_DEPTH-1:0] RAM_A, output RAM_WEn, output RAM_CENn, output RAM_LDn, @@ -59,16 +61,15 @@ module ext_fifo .empty(empty1)); assign dst_rdy_o = ~full1; - -/* -----\/----- EXCLUDED -----\/----- + +`ifdef NO_EXT_FIFO assign space_avail = ~full2; assign data_avail = ~empty1; assign read_data = write_data; - -----/\----- EXCLUDED -----/\----- */ +`else - // External FIFO running at ext clock rate and 18 bit width. - nobl_fifo #(.WIDTH(EXT_WIDTH),.DEPTH(DEPTH),.FDEPTH(DEPTH)) + nobl_fifo #(.WIDTH(EXT_WIDTH),.RAM_DEPTH(RAM_DEPTH),.FIFO_DEPTH(FIFO_DEPTH)) nobl_fifo_i1 ( .clk(ext_clk), @@ -83,14 +84,14 @@ module ext_fifo .RAM_OEn(RAM_OEn), .RAM_CE1n(RAM_CE1n), .write_data(write_data), - .write_strobe(space_avail & ~empty1 ), + .write_strobe(~empty1 ), .space_avail(space_avail), .read_data(read_data), - .read_strobe(data_avail & ~full2), - .data_avail(data_avail), - .upstream_full(almost_full2) + .read_strobe(~almost_full2), + .data_avail(data_avail) ); - +`endif // !`ifdef NO_EXT_FIFO + // FIFO buffers data read from external FIFO into DSP clk domain and to TX DSP. fifo_xlnx_512x36_2clk_18to36 fifo_xlnx_512x36_2clk_18to36_i1 ( @@ -98,7 +99,7 @@ module ext_fifo .wr_clk(ext_clk), .rd_clk(int_clk), .din(read_data), // Bus [17 : 0] - .wr_en(data_avail & ~full2 ), + .wr_en(data_avail), .rd_en(dst_rdy_i), .dout(dataout), // Bus [35 : 0] .full(full2), @@ -106,5 +107,5 @@ module ext_fifo .empty(empty2)); assign src_rdy_o = ~empty2; - + endmodule // ext_fifo diff --git a/usrp2/extramfifo/ext_fifo_tb.v b/usrp2/extramfifo/ext_fifo_tb.v index a93d524d5..db5f31a9d 100644 --- a/usrp2/extramfifo/ext_fifo_tb.v +++ b/usrp2/extramfifo/ext_fifo_tb.v @@ -1,7 +1,8 @@ `timescale 1ns / 1ps `define INT_WIDTH 36 `define EXT_WIDTH 18 -`define DEPTH 19 +`define RAM_DEPTH 19 +`define FIFO_DEPTH 8 `define DUMP_VCD_FULL module ext_fifo_tb(); @@ -17,7 +18,7 @@ module ext_fifo_tb(); wire [`EXT_WIDTH-1:0] RAM_D_po; wire [`EXT_WIDTH-1:0] RAM_D; wire RAM_D_poe; - wire [`DEPTH-1:0] RAM_A; + wire [`RAM_DEPTH-1:0] RAM_A; wire RAM_WEn; wire RAM_CENn; wire RAM_LDn; @@ -30,6 +31,7 @@ module ext_fifo_tb(); reg [`INT_WIDTH-1:0] ref_dataout; wire src_rdy_o; // not EMPTY reg dst_rdy_i; + integer ether_frame; // Clocks @@ -39,7 +41,6 @@ module ext_fifo_tb(); begin int_clk <= 0; ext_clk <= 0; - datain <= 0; ref_dataout <= 1; src_rdy_i <= 0; dst_rdy_i <= 0; @@ -53,6 +54,9 @@ module ext_fifo_tb(); initial begin + datain <= 0; + ether_frame <= 0; + rst <= 1; repeat (5) @(negedge int_clk); rst <= 0; @@ -62,6 +66,18 @@ module ext_fifo_tb(); @(negedge int_clk); datain <= datain + dst_rdy_o; src_rdy_i <= dst_rdy_o; + // Simulate inter-frame time + if (ether_frame == 1500) + begin + ether_frame <= 0; + repeat(1600) + begin + @(negedge int_clk); + src_rdy_i <= 0; + end + end + else + ether_frame <= ether_frame + dst_rdy_o; end end // initial begin @@ -73,8 +89,20 @@ module ext_fifo_tb(); // Fall through fifo, first output already valid if (dataout !== ref_dataout) $display("Error: Expected %x, got %x",ref_dataout, dataout); - - while (ref_dataout < 10000) + // Decimate by 16 rate + while (ref_dataout < 2000) + begin + @(negedge int_clk); + ref_dataout <= ref_dataout + src_rdy_o ; + dst_rdy_i <= src_rdy_o; + if ((dataout !== ref_dataout) && src_rdy_o) + $display("Error: Expected %x, got %x",ref_dataout, dataout); + @(negedge int_clk); + dst_rdy_i <= 0; + repeat(14) @(negedge int_clk); + end // while (ref_dataout < 10000) + // Decimate by 8 rate + while (ref_dataout < 4000) begin @(negedge int_clk); ref_dataout <= ref_dataout + src_rdy_o ; @@ -84,7 +112,33 @@ module ext_fifo_tb(); @(negedge int_clk); dst_rdy_i <= 0; repeat(6) @(negedge int_clk); - end + end // while (ref_dataout < 10000) + // Decimate by 4 rate + while (ref_dataout < 6000) + begin + @(negedge int_clk); + ref_dataout <= ref_dataout + src_rdy_o ; + dst_rdy_i <= src_rdy_o; + if ((dataout !== ref_dataout) && src_rdy_o) + $display("Error: Expected %x, got %x",ref_dataout, dataout); + @(negedge int_clk); + dst_rdy_i <= 0; + repeat(2) @(negedge int_clk); + end // while (ref_dataout < 10000) + // Max rate + while (ref_dataout < 10000) + begin + @(negedge int_clk); + ref_dataout <= ref_dataout + src_rdy_o ; + dst_rdy_i <= src_rdy_o; + if ((dataout !== ref_dataout) && src_rdy_o) + $display("Error: Expected %x, got %x",ref_dataout, dataout); + + end // while (ref_dataout < 10000) + + @(negedge int_clk); + $finish; + end @@ -228,7 +282,7 @@ module ext_fifo_tb(); endgenerate - wire [`DEPTH-1:0] RAM_A_ext; + wire [`RAM_DEPTH-1:0] RAM_A_ext; wire RAM_WEn_ext,RAM_LDn_ext,RAM_CE1n_ext,RAM_OEn_ext,RAM_CENn_ext; assign #1 RAM_D_pi = RAM_D_pi_ext; @@ -292,7 +346,7 @@ module ext_fifo_tb(); ext_fifo - #(.INT_WIDTH(`INT_WIDTH),.EXT_WIDTH(`EXT_WIDTH),.DEPTH(`DEPTH)) + #(.INT_WIDTH(`INT_WIDTH),.EXT_WIDTH(`EXT_WIDTH),.RAM_DEPTH(`RAM_DEPTH),.FIFO_DEPTH(`FIFO_DEPTH)) ext_fifo_i1 ( .int_clk(int_clk), diff --git a/usrp2/extramfifo/nobl_fifo.v b/usrp2/extramfifo/nobl_fifo.v index 03e3f5223..19f5fb84e 100644 --- a/usrp2/extramfifo/nobl_fifo.v +++ b/usrp2/extramfifo/nobl_fifo.v @@ -1,18 +1,19 @@ // Since this FIFO uses a ZBT/NoBL SRAM for its storage which is a since port // device it can only sustain data throughput at half the RAM clock rate. // Fair arbitration to ensure this occurs is included in this logic and -// requests for transactions that can not be completed are held off by (re)using the -// "full" and "empty" flags. +// requests for transactions that can not be completed are held off. +// This FIFO requires a an external signal driving read_strobe that assures space for at least 6 +// reads since this the theopretical maximum number in flight due to pipeling. module nobl_fifo - #(parameter WIDTH=18,DEPTH=19,FDEPTH=10) + #(parameter WIDTH=18,RAM_DEPTH=19,FIFO_DEPTH=19) ( input clk, input rst, input [WIDTH-1:0] RAM_D_pi, output [WIDTH-1:0] RAM_D_po, output RAM_D_poe, - output [DEPTH-1:0] RAM_A, + output [RAM_DEPTH-1:0] RAM_A, output RAM_WEn, output RAM_CENn, output RAM_LDn, @@ -21,42 +22,32 @@ module nobl_fifo input [WIDTH-1:0] write_data, input write_strobe, output reg space_avail, - output reg [WIDTH-1:0] read_data, - input read_strobe, - output reg data_avail, - input upstream_full // (Connect to almost full flag upstream) + output [WIDTH-1:0] read_data, + input read_strobe, // Triggers a read, result in approximately 6 cycles. + output data_avail // Qulaifys read data available this cycle on read_data. ); - reg [FDEPTH-1:0] capacity; - reg [FDEPTH-1:0] wr_pointer; - reg [FDEPTH-1:0] rd_pointer; - wire [DEPTH-1:0] address; - reg supress; - reg data_avail_int; // Data available with high latency from ext FIFO flag - wire [WIDTH-1:0] data_in; - wire data_in_valid; - reg [WIDTH-1:0] read_data_pending; - reg pending_avail; - wire read_strobe_int; + reg [FIFO_DEPTH-1:0] capacity; + reg [FIFO_DEPTH-1:0] wr_pointer; + reg [FIFO_DEPTH-1:0] rd_pointer; + wire [RAM_DEPTH-1:0] address; + reg data_avail_int; // Internal not empty flag. - - - assign read = read_strobe_int && data_avail_int; - assign write = write_strobe && space_avail; + assign read = read_strobe && data_avail_int; + assign write = write_strobe && space_avail; - // When a read and write collision occur, supress the availability flags next cycle + // When a read and write collision occur, supress the space_avail flag next cycle // and complete write followed by read over 2 cycles. This forces balanced arbitration // and makes for a simple logic design. always @(posedge clk) if (rst) begin - capacity <= 1 << (FDEPTH-1); + capacity <= 1 << (FIFO_DEPTH-1); wr_pointer <= 0; rd_pointer <= 0; space_avail <= 0; data_avail_int <= 0; - supress <= 0; end else begin @@ -64,187 +55,15 @@ module nobl_fifo // Capacity is already zero; Capacity is 1 and write is asserted (lookahead); both read and write are asserted (collision) space_avail <= ~((capacity == 0) || (read&&write) || ((capacity == 1) && write) ); // Capacity has 1 cycle delay so look ahead here for corner case of read of last item in FIFO. - data_avail_int <= ~((capacity == (1 << (FDEPTH-1))) || (read&&write) || ((capacity == ((1 << (FDEPTH-1))-1)) && read) ); - supress <= read && write; + data_avail_int <= ~((capacity == (1 << (FIFO_DEPTH-1))) || ((capacity == ((1 << (FIFO_DEPTH-1))-1)) && read) ); wr_pointer <= wr_pointer + write; - rd_pointer <= rd_pointer + ((~write && read) || supress); - capacity <= capacity - write + ((~write && read) || supress); // REVISIT + rd_pointer <= rd_pointer + (~write && read); + capacity <= capacity - write + (~write && read) ; end // else: !if(rst) assign address = write ? wr_pointer : rd_pointer; - assign enable = write || read || supress; - - // - // Need to have first item in external FIFO moved into local registers for single cycle latency and throughput on read. - // 2 local registers are provided so that a read every other clock cycle can be sustained. - // No fowarding logic is provided to bypass the external FIFO as latency is of no concern. - // - always @(posedge clk) - if (rst) - begin - read_data <= 0; - data_avail <= 0; - read_data_pending <= 0; - pending_avail <= 0; - end - else - begin - case({read_strobe,data_in_valid}) - // No read externally, no new data arriving from external FIFO - 2'b00: begin - case({data_avail,pending_avail}) - // Start Data empty, Pending empty. - // - // End Data full, Pending empty - 2'b00: begin - read_data <= read_data; - data_avail <= data_avail; - read_data_pending <= read_data_pending ; - pending_avail <= pending_avail; - end - // Start Data empty, Pending full. - // Data <= Pending, - // End Data full, Penidng empty. - 2'b01: begin - read_data <= read_data_pending; - data_avail <= 1'b1; - read_data_pending <= read_data_pending ; - pending_avail <= 1'b0; - end - // Start Data full, Pending empty. - // - // End Data full, Pending empty - 2'b10: begin - read_data <= read_data; - data_avail <= data_avail; - read_data_pending <= read_data_pending ; - pending_avail <= pending_avail; - end - // Start Data full, Pending full. - // - // End Data full, Pending full. - 2'b11: begin - read_data <= read_data; - data_avail <= data_avail; - read_data_pending <= read_data_pending ; - pending_avail <= pending_avail; - end - endcase - end - // No read externally, new data arriving from external FIFO - 2'b01: begin - case({data_avail,pending_avail}) - // Start Data empty, Pending empty. - // Data <= FIFO - // End Data full, Pending empty - 2'b00: begin - read_data <= data_in; - data_avail <= 1'b1; - read_data_pending <= read_data_pending ; - pending_avail <= 1'b0; - end - // Start Data empty, Pending full. - // Data <= Pending, Pending <= FIFO - // End Data full, Penidng full. - 2'b01: begin - read_data <= read_data_pending; - data_avail <= 1'b1; - read_data_pending <= data_in ; - pending_avail <= 1'b1; - end - // Start Data full, Pending empty. - // Pending <= FIFO - // End Data full, Pending full - 2'b10: begin - read_data <= read_data; - data_avail <= 1'b1; - read_data_pending <= data_in ; - pending_avail <= 1'b1; - end - // Data full, Pending full. - // *ILLEGAL STATE* - 2'b11: begin - - end - endcase - end - // Read externally, no new data arriving from external FIFO - 2'b10: begin - case({data_avail,pending_avail}) - // Start Data empty, Pending empty. - // *ILLEGAL STATE* - 2'b00: begin - - end - // Start Data empty, Pending full. - // *ILLEGAL STATE* - 2'b01: begin - - end - // Start Data full, Pending empty. - // Out <= Data - // End Data empty, Pending empty. - 2'b10: begin - read_data <= read_data; - data_avail <= 1'b0; - read_data_pending <= read_data_pending ; - pending_avail <= 1'b0; - end - // Start Data full, Pending full. - // Out <= Data, - // End Data full, Pending empty - 2'b11: begin - read_data <= read_data_pending; - data_avail <= 1'b1; - read_data_pending <= read_data_pending ; - pending_avail <= 1'b0; - end - endcase - end - // Read externally, new data arriving from external FIFO - 2'b11: begin - case({data_avail,pending_avail}) - // Start Data empty, Pending empty. - // *ILLEGAL STATE* - 2'b00: begin - - end - // Start Data empty, Pending full. - // *ILLEGAL STATE* - 2'b01: begin - - end - // Start Data full, Pending empty. - // Out <= Data, Data <= FIFO - // End Data full, Pending empty. - 2'b10: begin - read_data <= data_in; - data_avail <= 1'b1; - read_data_pending <= read_data_pending ; - pending_avail <= 1'b0; - end - // Start Data full, Pending full. - // Out <= Data, Data <= Pending, Pending <= FIFO - // End Data full, Pending full - 2'b11: begin - read_data <= read_data_pending; - data_avail <= 1'b1; - read_data_pending <= data_in ; - pending_avail <= 1'b1; - end - endcase - end - endcase - end + assign enable = write || read; - // Start an external FIFO read as soon as a read of the buffer reg is strobed to minimise refill latency. - // If the buffer reg or the pending buffer reg is already empty also pre-emptively start a read. - // However there must be something in the main external FIFO to read for this to occur!. - // Pay special attention to upstream devices signalling full due to the number of potential in-flight reads\ that need - // to be stalled and stored somewhere. - // This means that there can be 3 outstanding reads to the ext FIFO active at any time helping to hide latency. - assign read_strobe_int = (read_strobe && data_avail && ~pending_avail && ~upstream_full) || (~data_avail && ~pending_avail && ~upstream_full); - // // Simple NoBL SRAM interface, 4 cycle read latency. @@ -265,10 +84,12 @@ module nobl_fifo .RAM_CE1n(RAM_CE1n), .address(address), .data_out(write_data), - .data_in(data_in), - .data_in_valid(data_in_valid), + .data_in(read_data), + .data_in_valid(data_avail), .write(write), .enable(enable) ); + + endmodule // nobl_fifo |