OpenCores
URL https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [basal/] [src/] [FIFOs/] [Beyond_Circuits/] [sync_fifo.v] - Rev 40

Go to most recent revision | Compare with Previous | Blame | View Log

// -*- mode: Verilog; verilog-auto-lineup-declaration: nil; -*-
//-----------------------------------------------------------------------------
// Title         : Synchronous FIFO
// Project       : Common
//-----------------------------------------------------------------------------
// File          : sync_fifo.v
//-----------------------------------------------------------------------------
// Description : Synchronous FIFO using BRAM.
//
// Implements a variable width/depth synchronous FIFO. The synthesis
// tool may choose to implement the memory as a block RAM.
//-----------------------------------------------------------------------------
// Copyright 1994-2009 Beyond Circuits. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   1. Redistributions of source code must retain the above copyright notice, 
//      this list of conditions and the following disclaimer.
//   2. Redistributions in binary form must reproduce the above copyright notice, 
//      this list of conditions and the following disclaimer in the documentation 
//      and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE BEYOND CIRCUITS ``AS IS'' AND ANY EXPRESS OR 
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL BEYOND CIRCUITS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//------------------------------------------------------------------------------
 
`timescale 1ns/1ns
module sync_fifo
  #(
    parameter depth = 32,
    parameter width = 32,
    // Need the log of the parameters as parameters also due to an XST bug.
    parameter log2_depth = log2(depth),
    parameter log2_depthp1 = log2(depth+1)
    )
  (
   input clk,
   input reset,
   input wr_enable,
   input rd_enable,
   output reg empty,
   output reg full,
   output [width-1:0] rd_data,
   input [width-1:0] wr_data,
   output reg [log2_depthp1-1:0] count
   );
 
  // log2 -- return the log base 2 of value.
  function integer log2;
    input [31:0] value;
    begin
      value = value-1;
      for (log2=0; value>0; log2=log2+1)
	value = value>>1;
    end
  endfunction
 
  // increment -- add one to value modulo depth.
  function [log2_depth-1:0] increment;
    input [log2_depth-1:0] value;
    begin
      if (value == depth-1)
	increment = 0;
      else
	increment = value+1;
    end
  endfunction
 
  // writing -- true when we write to the RAM.
  wire writing = wr_enable && (rd_enable || !full);
 
  // reading -- true when we are reading from the RAM.
  wire reading = rd_enable && !empty;
 
  // rd_ptr -- the read pointer.
  reg [log2_depth-1:0] rd_ptr;
 
  // next_rd_ptr -- the next value for the read pointer.
  // We need to name this combinational value because it
  // is needed to use the write-before-read style RAM.
  reg [log2_depth-1:0] next_rd_ptr;
  always @(*)
    if (reset)
      next_rd_ptr = 0;
    else if (reading)
      next_rd_ptr = increment(rd_ptr);
    else
      next_rd_ptr = rd_ptr;
 
  always @(posedge clk)
    rd_ptr <= next_rd_ptr;
 
  // wr_ptr -- the write pointer
  reg [log2_depth-1:0] wr_ptr;
 
  // next_wr_ptr -- the next value for the write pointer.
  reg [log2_depth-1:0] next_wr_ptr;
  always @(*)
    if (reset)
      next_wr_ptr = 0;
    else if (writing)
      next_wr_ptr = increment(wr_ptr);
    else
      next_wr_ptr = wr_ptr;
 
  always @(posedge clk)
    wr_ptr <= next_wr_ptr;
 
  // count -- the number of valid entries in the FIFO.
  always @(posedge clk)
    if (reset)
      count <= 0;
    else if (writing && !reading)
      count <= count+1;
    else if (reading && !writing)
      count <= count-1;
 
  // empty -- true if the FIFO is empty.
  // Note that this doesn't depend on count so if the count
  // output is unused the logic for computing the count can
  // be optimized away.
  always @(posedge clk)
    if (reset)
      empty <= 1;
    else if (reading && next_wr_ptr == next_rd_ptr && !full)
      empty <= 1;
    else
      if (writing && !reading)
	empty <= 0;
 
  // full -- true if the FIFO is full.
  // Again, this is not dependent on count.
  always @(posedge clk)
    if (reset)
      full <= 0;
    else if (writing && next_wr_ptr == next_rd_ptr)
      full <= 1;
    else if (reading && !writing)
      full <= 0;
 
  // We need to infer a write first style RAM so that when 
  // the FIFO is empty the write data can flow through to
  // the read side and be available the next clock cycle.
  reg [width-1:0] mem [depth-1:0];
 
  always @(posedge clk)
    if (writing)
      mem[wr_ptr] <= wr_data;
 
  assign rd_data = mem[rd_ptr];
 
endmodule
 
 

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.