diff options
Diffstat (limited to 'usrp2/extramfifo/nobl_fifo.v')
-rw-r--r-- | usrp2/extramfifo/nobl_fifo.v | 229 |
1 files changed, 25 insertions, 204 deletions
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 |