OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.