vusb_fifo.v 7.47 KB
/*******************************************************************************

-- File Type:    Verilog HDL 
-- Tool Version: VHDL2verilog  v4.4 Tue Sep 19 10:06:32 EDT 2000 SunOS 5.5.1 
-- Input file was: vusb_fifo
-- Date Created: Tue Jul 16 14:00:42 2002

*******************************************************************************/


`timescale 1 ns / 1 ns // timescale for following modules

// ----------------------------------------------------------------------------
//  Copyright 2001 VAutomation Inc. Nashua NH USA. All rights reserved.
//  This software is provided under license and contains proprietary
//  and confidential material which is the property of VAutomation Inc.
//  HTTP://www.vautomation.com
// ----------------------------------------------------------------------------
//  File Name: $Workfile: vusb_fifo.vhdl$
//  Revision: $Revision: 1.1.1.1 $
//  Description:
// 
//  Description:
//       This is a FIFO core. The depth of the fifo is passed into this file as
//       a generic. 
//       The constant DEPTH should be set to 2-16 and must be even. DEPTH could be
//       more than 16 but you'd be better off using a DPRAM. Currently only a
//       depth of 16 has been verified in simulation.
// 
//       Since it is so small, it is
//       built out of clock enabled DFFs. This results in more gates than using
//       a Dual Port RAM architecture, but it is much easier to synthesize.
//       The FIFO has a latency of DEPTH clocks where DEPTH is the depth of the
//       FIFO.
// 
//       Note that there is a seperate EMPTY and OUT_VALID flags. The FIFO can be
//       not EMPTY but OUT_VALID is low indicating that a byte has been loaded into
//       the FIFO but it's still rippling down the pipeline.
// 
//       Taking this fifo and re-naming the port signals to something more
//       meaningful. Also removing the out_valid outputs and generating a half
//       full flag.
// 
// -----------------------------------------------------------------------------
//  This product is licensed to:
//  John Princen of RouteFree
// for use at site(s):
// broadon
// -----------Revision History--------------------------------------------------
//  $Log: 
//   7    VUSB      1.6         4/11/02 2:49:15 PM     Patrick Koran   all 
//         checked in from pats pc, week of Starteam upgrade 4.6 to 5.1
//   6    VUSB      1.5         2/11/02 3:04:02 PM     Tom Frechette   Moving 
//         fifo flush into fifo module.
//   5    VUSB      1.4         8/15/01 2:57:51 PM     Tom Frechette   Changed 
//         full flag.
//   4    VUSB      1.3         7/18/01 4:45:01 PM     Tom Frechette   Changed 
//         full and empty flags.
//   3    VUSB      1.2         7/18/01 12:00:55 PM    Tom Frechette   Fixed 
//         full and empty signals.
//   2    VUSB      1.1         6/27/01 3:12:22 PM     Tom Frechette   Removed 
//         generate loop
//   1    VUSB      1.0         6/21/01 9:25:20 AM     Tom Frechette   
//  $
//  $NoKeywords$
// -----------------------------------------------------------------------------
// ---------------------------ENTITY  ---------------------
module vusb_fifo (clk,
   rst,
   rst_a,
   flush,
   wr,
   rd,
   full,
   half_full,
   empty,
   out_valid,
   data_in,
   data_out);
parameter DEPTH = 16;
parameter ADDR_SIZE = 3;
input   clk; //  everything clocks on rising edge
input   rst; //  reset active high
input   rst_a; //  reset active high
input   flush; //  flush fifo pointers
input   wr; //  write a byte
input   rd; //  read a byte
output   full; //  1=FIFO is full
output   half_full; //  1=FIFO is half full
output   empty; //  1=FIFO is empty
output   out_valid; //  
input   [7:0] data_in; //  data bus in
output   [7:0] data_out; 
wire    full; 
wire    half_full; 
wire    empty; 
reg     out_valid; 
wire    [7:0] data_out; 
parameter THRESHOLD = DEPTH / 2; 
reg     [7:0] fifo_regs [0:DEPTH - 1]; 
//  address pointers 
reg     [ADDR_SIZE:0] wr_addr_rg; //  write address pointer 
reg     [ADDR_SIZE:0] rd_addr_rg; //  read  address pointer
wire    [ADDR_SIZE:0] next_wr_addr; //  write address increment
wire    [ADDR_SIZE:0] next_rd_addr; //  read  address increment
wire    [ADDR_SIZE:0] prev_rd_addr; //  Previous address increment
wire    [ADDR_SIZE:0] distance; //  distance between write & read pointers
wire    reached_threshold; 
reg     fifo_full; //  Fifo full signal design
wire    full_sig; //  Fifo full signal
wire    empty_sig; //  internal copy of empty output

always @(posedge clk)
   begin : regs
   if (wr == 1'b 1)
      begin
      fifo_regs[wr_addr_rg] <= data_in;	
      end
   end
//  Data out read mux for simulation, lets read zeros instead of x's when its empty
assign data_out = empty_sig == 1'b 0 ? fifo_regs[rd_addr_rg] : 
	{8{1'b 0}}; 
assign next_wr_addr = wr_addr_rg + 1; 
assign next_rd_addr = rd_addr_rg + 1; 
assign prev_rd_addr = rd_addr_rg - 1; 
//  FIFO full
assign full = fifo_full | full_sig; 
//  1=FIFO is full
assign full_sig = wr_addr_rg == prev_rd_addr & wr == 1'b 1 ? 1'b 1 : 
	1'b 0; 
//  Compute FIFO empty detect
assign empty = empty_sig; 
assign empty_sig = wr_addr_rg == rd_addr_rg & fifo_full == 1'b 0 ? 1'b 1 : 
	1'b 0; 
//  Must compute the distance between the write address pointer
//  and the read address pointer. This is used to detect when
//  we must then begin refilling the FIFO.
assign distance = wr_addr_rg - rd_addr_rg; 
//  When ever the distance between the read address pointer and
//  write address pointer reaches the THRESHOLD value we must
//  stop reading data from the FIFO.
assign half_full = distance >= THRESHOLD ? 1'b 1 : 
	1'b 0; //  When ever the distance between the read address pointer and 
//  write address pointer reaches the THRESHOLD value we must
//  stop reading data from the FIFO.
assign reached_threshold = distance >= THRESHOLD ? 1'b 1 : 
	1'b 0; 
always @(posedge clk or posedge rst_a)
   begin : addr_cnt
   if (rst_a == 1'b 1)
      begin
      wr_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};	
      rd_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};	
      fifo_full <= 1'b 0;	
      out_valid <= 1'b 0;	
      end
   else
      begin
      if (rst == 1'b 1)
         begin
         wr_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};	
         rd_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};	
         fifo_full <= 1'b 0;	
         out_valid <= 1'b 0;	
         end
      else
         begin
         if (full_sig == 1'b 1)
            begin
            fifo_full <= 1'b 1;	
            end
         else if (rd == 1'b 1 | flush == 1'b 1 )
            begin
            fifo_full <= 1'b 0;	
//  FIFO output valid control with hysterisis
            end
         if (reached_threshold == 1'b 1)
            begin
            out_valid <= 1'b 1;	
            end
         else if (empty_sig == 1'b 1 | flush == 1'b 1 )
            begin
            out_valid <= 1'b 0;	
            end
         if (flush == 1'b 1)
            begin
            wr_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};	
            end
         else if (wr == 1'b 1 )
            begin
            wr_addr_rg <= next_wr_addr;	
            end
         else
            begin
            wr_addr_rg <= wr_addr_rg;	
            end
         if (flush == 1'b 1)
            begin
            rd_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};	
            end
         else if (rd == 1'b 1 & empty_sig == 1'b 0 )
            begin
            rd_addr_rg <= next_rd_addr;	
            end
         else
            begin
            rd_addr_rg <= rd_addr_rg;	
            end
         end
      end
   end

//  Set the threshold to be 1/2 the depth

endmodule // module vusb_fifo