Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //--------------------------------------------------------------------------
- //
- // $Id: $
- //
- // $Change: $
- //
- // Notes: This module is the control logic for a Virage RAM FIFO. It has
- // a 3 cycle we -> ~empty latency. This block works with the Virage
- // RAMs that have both inputs, outputs, and outreg_enable signale
- // pipelined internal to the RAM. There is a SKID rank of flops and
- // an output mux to account for the outreg_enable signal being
- // pipelined. It is important to realize the output timing of this
- // block is CLK->Q + MUX delay.
- // ,
- // FIFO_*, SKID_WORDS, and SKID_FULL are the parameters which
- // are user adjustable. SKID_WORDS is the number of SKID entries
- // in the FIFO. SKID_FULL says whether or not the FULL signal should
- // de-assert if the FIFO has entered the SKID entries, but is being
- // read from. Setting SKID_WORDS=0 and SKID_FULL=0 causes this module
- // to act as a FIFO without any SKID entries. This is the default.
- //
- // Copyright: Trade secret of ATI Technologies, Inc.
- // (C) Copyright 2001-2005, ATI Technologies, Inc., (unpublished)
- //
- // All rights reserved. This notice is intended as a precaution against
- // inadvertent publication and does not imply publication or any waiver
- // of confidentiality. The year included in the foregoing notice is the
- // year of creation of the work.
- //
- // Author: Brian Rerecich
- //
- //--------------------------------------------------------------------------
- `ifdef SIMULATION
- `include "msgio_defines.vh"
- `endif
- module ati_fifo_ctrl_pipe (// Outputs
- read_data,
- full,
- empty,
- busy,
- mem_waddr,
- mem_we,
- mem_raddr,
- mem_re,
- // Inputs
- we,
- re,
- mem_data,
- clk,
- reset
- );
- //**************
- //* Parameters *
- //**************
- parameter FIFO_WIDTH = 1;
- parameter FIFO_DEPTH = 2;
- parameter SKID_WORDS = 0;
- parameter SKID_FULL = 0;
- parameter FIFO_NAME = "";
- parameter ADDR_WIDTH = ((FIFO_DEPTH <= 4) ? 2 :
- (FIFO_DEPTH <= 8) ? 3 :
- (FIFO_DEPTH <= 16) ? 4 :
- (FIFO_DEPTH <= 32) ? 5 :
- (FIFO_DEPTH <= 64) ? 6 :
- (FIFO_DEPTH <= 128) ? 7 :
- (FIFO_DEPTH <= 256) ? 8 :
- (FIFO_DEPTH <= 512) ? 9 :
- (FIFO_DEPTH <= 1024) ? 10 :
- (FIFO_DEPTH <= 2048) ? 11 : 12); // Bigger than 4096??? i hope not.
- //***********************
- //* Output Declarations *
- //***********************
- output [FIFO_WIDTH-1:0] read_data; // Flopped data from Virage RAM
- output full; // FIFO Full signal
- output empty; // FIFO Empty signal
- output busy;
- output [ADDR_WIDTH-1:0] mem_waddr; // Write Address for RAM
- output mem_we; // Write Enable
- output [ADDR_WIDTH-1:0] mem_raddr; // Read Address for RAM
- output mem_re; // Read Enable for RAM
- //**********************
- //* Input Declarations *
- //**********************
- input we; // Write Enable
- input re; // Read Enable
- input [FIFO_WIDTH-1:0] mem_data; // Data from Virage MEM
- input clk;
- input reset;
- //***************************
- //* Output REG Declarations *
- //***************************
- reg [FIFO_WIDTH-1:0] read_data;
- reg full;
- reg empty;
- reg busy;
- reg [ADDR_WIDTH-1:0] mem_waddr;
- reg mem_we;
- reg [ADDR_WIDTH-1:0] mem_raddr;
- reg mem_re;
- //*****************************
- //* Internal REG Declarations *
- //*****************************
- reg [ADDR_WIDTH-1:0] read_ptr_q; // Read Pointer
- reg [ADDR_WIDTH-1:0] write_ptr_q; // Write Pointer
- reg [ADDR_WIDTH-1:0] read_ptr_d;
- reg [ADDR_WIDTH-1:0] write_ptr_d;
- reg full_d;
- reg int_empty_d;
- reg int_empty_q;
- reg mem_empty_q;
- reg read_mem;
- reg read_fifo;
- reg [ADDR_WIDTH:0] cnt_q;
- reg [ADDR_WIDTH:0] cnt_d;
- reg write_last; // Write Pointer is at last location in FIFO
- reg read_last; // Read Pointer is at last location in FIFO
- reg cnt_gt_skid_limit;
- reg cnt_eq_skid_limit;
- reg [FIFO_WIDTH-1:0] skid_flop_d; // SKID flop
- reg [FIFO_WIDTH-1:0] skid_flop_q;
- reg ld_skid_flop;
- reg skid_flop_vld_d;
- reg skid_flop_vld_q;
- reg mem_re_q;
- //*********************
- //* Wire Declarations *
- //*********************
- wire empty_d;
- wire mem_empty_d;
- //***********************
- //* Combinatorial Logic *
- //***********************
- always_comb begin
- // NOTE: Instead of putting the burden of knowing the internal latency
- // of the FIFO, we delay the de-assertion of empty to the outside
- // world by the internal latency of the FIFO so that whenever
- // (~empty & re) is true (as seen by the outside world) the read_data
- // is valid on the output
- //
- read_mem = re | empty;
- read_fifo = read_mem | mem_empty_q;
- mem_re = read_fifo & ~int_empty_q;
- busy = ~(int_empty_q & mem_empty_q & empty);
- // Easy assignments....
- mem_waddr = write_ptr_q;
- mem_raddr = read_ptr_q;
- mem_we = we;
- ld_skid_flop = mem_re_q & ~empty & ~re;
- skid_flop_vld_d = ((mem_re_q & ~empty) | skid_flop_vld_q) & ~re; // (set | hold) & ~clr;
- skid_flop_d = skid_flop_vld_q ? skid_flop_q : mem_data;
- read_data = skid_flop_d;
- end
- always_comb begin
- // Logic for Read and Write Pointers
- read_last = (read_ptr_q == (FIFO_DEPTH-1));
- casez({mem_re,read_last})
- 2'b0?: read_ptr_d = read_ptr_q;
- 2'b10: read_ptr_d = read_ptr_q + 1;
- 2'b11: read_ptr_d = 0;
- endcase // casez({re,read_last})
- write_last = (write_ptr_q == (FIFO_DEPTH-1));
- casez({we,write_last})
- 2'b0?: write_ptr_d = write_ptr_q;
- 2'b10: write_ptr_d = write_ptr_q + 1;
- 2'b11: write_ptr_d = 0;
- endcase // casez({we,write_last})
- end // always @ (...
- always_comb begin
- cnt_gt_skid_limit = (cnt_q > (FIFO_DEPTH - SKID_WORDS - 1));
- cnt_eq_skid_limit = (cnt_q == (FIFO_DEPTH - SKID_WORDS - 1));
- // Logic for FULL is based on the different SKID parameters
- // Toggle FULL once in SKID territory if an entry is read
- if (SKID_FULL)
- full_d = (cnt_eq_skid_limit & ~mem_re & we) | // hit limit, writing, and not reading
- (cnt_gt_skid_limit & ~mem_re); // over limit and not reading.
- // Keep FULL asserted once FIFO has entered the SKID entries
- else if (SKID_WORDS > 0)
- full_d = (cnt_eq_skid_limit & ~mem_re & we) | // hit limit, writing, and not reading
- cnt_gt_skid_limit; // over limit
- // No SKID entries in FIFO
- else
- full_d = (cnt_eq_skid_limit & ~mem_re & we) | // hit limit, writing, and not reading
- (full & ~we & ~mem_re) | // store value (no read, no write)
- (full & we & mem_re); // store value (read, write)
- // Logic for Full, Empty, and Count
- casez({we, mem_re})
- // both or none, do the same
- 2'b00,
- 2'b11: begin
- cnt_d = cnt_q;
- int_empty_d = int_empty_q;
- end
- // read, no write
- 2'b01: begin
- cnt_d = cnt_q - 1;
- int_empty_d = (cnt_q == 1);
- end
- // write, no read
- 2'b10: begin
- cnt_d = cnt_q + 1;
- int_empty_d = 0;
- end
- endcase // casez({we, re})
- end // always @ (...
- // Determine if empty should be updated or left the same.
- assign empty_d = read_mem ? mem_empty_q : empty;
- assign mem_empty_d = read_fifo ? int_empty_q : mem_empty_q;
- //******************
- //* FFs with reset *
- //******************
- always @ (posedge clk) begin
- if (reset) begin
- read_ptr_q <= {ADDR_WIDTH{1'b0}};
- write_ptr_q <= {ADDR_WIDTH{1'b0}};
- int_empty_q <= 1'b1;
- empty <= 1'b1;
- mem_empty_q <= 1'b1;
- full <= 1'b0;
- cnt_q <= {(ADDR_WIDTH+1){1'b0}};
- skid_flop_vld_q <= 1'b0;
- end // if (reset) begin
- else begin
- if (mem_re) begin
- read_ptr_q <= read_ptr_d;
- end
- if (we) begin
- write_ptr_q <= write_ptr_d;
- end
- if (mem_re | we) begin
- cnt_q <= cnt_d;
- int_empty_q <= int_empty_d;
- end
- skid_flop_vld_q <= skid_flop_vld_d;
- empty <= empty_d;
- full <= full_d;
- mem_empty_q <= mem_empty_d;
- end // else begin
- end // always @ (posedge clk)
- //*********************
- //* FFs without reset *
- //*********************
- `ifdef SIMULATION
- // VCS coverage off
- reg [ADDR_WIDTH:0] cnt_q_fix;
- // VCS coverage on
- `endif
- always @ (posedge clk) begin
- mem_re_q <= mem_re;
- `ifdef SIMULATION
- // VCS coverage off
- // error checking
- cnt_q_fix <= {(ADDR_WIDTH+1){!reset}} & cnt_d;
- if (!reset && we && (cnt_q_fix == FIFO_DEPTH))
- // leda DCVER_274 off
- `MSGIO_DISPLAY("ATI_Fifo ERROR (%m): %s fifo written when full -- data dropped at time %t", FIFO_NAME, $time);
- // leda DCVER_274 on
- // VCS coverage on
- `endif
- end
- always @ (posedge clk)
- begin
- if (ld_skid_flop) // only load skid when valid
- skid_flop_q <= skid_flop_d;
- end
- endmodule // ati_fifo_circular
Advertisement
Add Comment
Please, Sign In to add comment