URL
https://opencores.org/ocsvn/srdydrdy_lib/srdydrdy_lib/trunk
Subversion Repositories srdydrdy_lib
[/] [srdydrdy_lib/] [trunk/] [rtl/] [verilog/] [buffers/] [sd_fifo_tail_b.v] - Rev 16
Go to most recent revision | Compare with Previous | Blame | View Log
//---------------------------------------------------------------------- // Srdy/Drdy FIFO Tail "B" // // Building block for FIFOs. The "B" (big) FIFO is design for larger FIFOs // based around memories, with sizes that may not be a power of 2. // // The bound inputs allow multiple FIFO controllers to share a single // memory. The enable input is for arbitration between multiple FIFO // controllers, or between the fifo head and tail controllers on a // single port memory. // // The commit parameter enables read/commit behavior. This creates // two read pointers, one which is used for reading from memory and // a commit pointer which is sent to the head block. The abort behavior // has a 3-cycle performance penalty due to pipeline flush. // // The FIFO tail assumes a memory with one-cycle read latency, and // has output buffering to compensate for this. // // Naming convention: c = consumer, p = producer, i = internal interface //---------------------------------------------------------------------- // Author: Guy Hutchison // // This block is uncopyrighted and released into the public domain. //---------------------------------------------------------------------- // Clocking statement for synchronous blocks. Default is for // posedge clocking and positive async reset `ifndef SDLIB_CLOCKING `define SDLIB_CLOCKING posedge clk or posedge reset `endif // delay unit for nonblocking assigns, default is to #1 `ifndef SDLIB_DELAY `define SDLIB_DELAY #1 `endif module sd_fifo_tail_b #(parameter width=8, parameter depth=16, parameter commit=0, parameter asz=$clog2(depth), parameter usz=$clog2(depth+1) ) ( input clk, input reset, input enable, input [asz-1:0] bound_low, input [asz-1:0] bound_high, output reg [asz-1:0] cur_rdptr, output reg [asz-1:0] com_rdptr, input [asz-1:0] wrptr, output reg mem_re, input mem_we, output reg [usz:0] p_usage, output p_srdy, input p_drdy, input p_commit, input p_abort, input [width-1:0] mem_rd_data, output [width-1:0] p_data ); reg [asz-1:0] nxt_cur_rdptr; reg [asz-1:0] cur_rdptr_p1; reg empty, full; reg nxt_irdy; reg [width-1:0] hold_a, hold_b; reg valid_a, valid_b; reg prev_re; reg [usz:0] tmp_usage; reg [usz:0] fifo_size; wire rbuf1_drdy; wire ip_srdy, ip_drdy; wire [width-1:0] ip_data; // Stage 1 -- Read pipeline // issue a read if: // 1) we are enabled // 2) valid_a is 0, OR // 3) valid_b is 0, OR // 4) valid_a && valid_b && trdy always @* begin if (cur_rdptr[asz-1:0] == (bound_high)) begin cur_rdptr_p1[asz-1:0] = bound_low; end else cur_rdptr_p1 = cur_rdptr + 1; empty = (wrptr == cur_rdptr); if (commit && p_abort) begin nxt_cur_rdptr = com_rdptr; mem_re = 0; end // else if (enable & !empty & (!valid_a | (!prev_re & !valid_b) | // (valid_a & valid_b & p_drdy))) else if (enable & !empty & ip_drdy) begin nxt_cur_rdptr = cur_rdptr_p1; mem_re = 1; end else begin nxt_cur_rdptr = cur_rdptr; mem_re = 0; end // else: !if(enable & !empty & (!valid_a | !valid_b |... fifo_size = (bound_high - bound_low + 1); tmp_usage = wrptr[asz-1:0] - cur_rdptr[asz-1:0]; if (~tmp_usage[usz]) p_usage = tmp_usage[usz-1:0]; else p_usage = fifo_size - (cur_rdptr[asz-1:0] - wrptr[asz-1:0]); end // always @ * /* -----\/----- EXCLUDED -----\/----- // alternate usage calc reg [asz-1:0] prev_wr; reg [asz:0] usage2, nxt_usage2; wire lcl_wr_en; //assign lcl_wr_en = (prev_wr0 != wrptr[0]); always @(posedge clk) begin if (reset) begin /-*AUTORESET*-/ // Beginning of autoreset for uninitialized flops usage2 <= {(1+(asz)){1'b0}}; // End of automatics end else begin usage2 <= #1 nxt_usage2; end end always @* begin if (mem_re & !mem_we) nxt_usage2 = usage2 - 1; else if (!mem_re & mem_we) nxt_usage2 = usage2 + 1; else nxt_usage2 = usage2; end -----/\----- EXCLUDED -----/\----- */ always @(posedge clk) begin if (reset) cur_rdptr <= `SDLIB_DELAY bound_low; else cur_rdptr <= `SDLIB_DELAY nxt_cur_rdptr; end reg [asz-1:0] rdaddr_s0, rdaddr_a, rdaddr_b; reg [asz-1:0] nxt_com_rdptr; generate if (commit == 1) begin : gen_s0 always @(posedge clk) begin if (reset) com_rdptr <= `SDLIB_DELAY bound_low; else com_rdptr <= `SDLIB_DELAY nxt_com_rdptr; if (mem_re) rdaddr_s0 <= `SDLIB_DELAY cur_rdptr; end end else begin : gen_ns0 always @* com_rdptr = cur_rdptr; end endgenerate // Stage 2 -- read buffering always @(`SDLIB_CLOCKING) begin if (reset) begin prev_re <= `SDLIB_DELAY 0; end else begin if (commit && p_abort) prev_re <= `SDLIB_DELAY 0; else prev_re <= `SDLIB_DELAY mem_re; end // else: !if(reset) end // always @ (`SDLIB_CLOCKING) generate if (commit == 1) begin : gen_s2 wire [asz-1:0] ip_rdaddr, p_rdaddr; sd_input #(asz+width) rbuf1 (.clk (clk), .reset (p_abort | reset), .c_srdy (prev_re), .c_drdy (rbuf1_drdy), .c_data ({rdaddr_s0,mem_rd_data}), .ip_srdy (ip_srdy), .ip_drdy (ip_drdy), .ip_data ({ip_rdaddr,ip_data})); sd_output #(asz+width) rbuf2 (.clk (clk), .reset (p_abort | reset), .ic_srdy (ip_srdy), .ic_drdy (ip_drdy), .ic_data ({ip_rdaddr,ip_data}), .p_srdy (p_srdy), .p_drdy (p_drdy), .p_data ({p_rdaddr,p_data})); always @* begin if (p_commit & p_srdy & p_drdy) nxt_com_rdptr = p_rdaddr; else nxt_com_rdptr = com_rdptr; end end // if (commit == 1) else begin : gen_ns2 sd_input #(width) rbuf1 (.clk (clk), .reset (p_abort | reset), .c_srdy (prev_re), .c_drdy (rbuf1_drdy), .c_data (mem_rd_data), .ip_srdy (ip_srdy), .ip_drdy (ip_drdy), .ip_data (ip_data)); sd_output #(width) rbuf2 (.clk (clk), .reset (p_abort | reset), .ic_srdy (ip_srdy), .ic_drdy (ip_drdy), .ic_data (ip_data), .p_srdy (p_srdy), .p_drdy (p_drdy), .p_data (p_data)); end // else: !if(commit == 1) endgenerate endmodule // it_fifo
Go to most recent revision | Compare with Previous | Blame | View Log