1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-02-07 06:44:09 +08:00
oh/stdlib/rtl/oh_fifo_async.v
Andreas.Olofsson e631bfe3f1 Fixing naming error
-The directory should contain rtl only.
-HDL is too broad a term
2022-06-22 11:04:54 -04:00

184 lines
5.9 KiB
Verilog

//#############################################################################
//# Function: Parametrized FIFO #
//#############################################################################
// Notes: #
// Soft reference implementation always instantiated #
// Assumed to be optimized away in synthesis if needed #
//# Author: Andreas Olofsson #
//# License: MIT (see LICENSE file in OH! repository) #
//#############################################################################
module oh_fifo_async
#(parameter N = 32, // FIFO width
parameter DEPTH = 32, // FIFO depth
parameter REG = 1, // Register fifo output
parameter AW = $clog2(DEPTH),// rd_count width (derived)
parameter SYNCPIPE = 2, // depth of synchronization pipeline
parameter TARGET = "DEFAULT", // implementation type
parameter PROGFULL = DEPTH-1, // programmable almost full level
parameter SHAPE = "SQUARE" // hard macro shape (square, tall, wide)
)
(//nreset
input nreset,
//write port
input wr_clk,
input [N-1:0] wr_din, // data to write
input wr_en, // write fifo
output wr_full, // fifo full
output wr_almost_full, //one entry left
output wr_prog_full, //programmable full level
output [AW-1:0] wr_count, // pessimistic report of entries from wr side
//read port
input rd_clk,
output [N-1:0] rd_dout, // output data (next cycle)
input rd_en, // read fifo
output rd_empty, // fifo is empty
output [AW-1:0] rd_count, // pessimistic report of entries from rd side
// BIST interface
input bist_en, // bist enable
input bist_we, // write enable global signal
input [N-1:0] bist_wem, // write enable vector
input [AW-1:0] bist_addr, // address
input [N-1:0] bist_din, // data input
input [N-1:0] bist_dout, // data input
// Power/repair (hard macro only)
input shutdown, // shutdown signal
input vss, // ground signal
input vdd, // memory array power
input vddio, // periphery/io power
input [7:0] memconfig, // generic memory config
input [7:0] memrepair // repair vector
);
//local wires
reg [AW:0] wr_addr; // extra bit for wraparound comparison
reg [AW:0] rd_addr;
wire [AW:0] wr_addr_gray;
wire [AW:0] wr_addr_gray_sync;
wire [AW:0] rd_addr_gray;
wire [AW:0] rd_addr_gray_sync;
wire [AW:0] rd_addr_sync;
wire fifo_write;
wire rd_nreset;
wire wr_nreset;
//###########################
//# Reset synchronizers
//###########################
oh_rsync #(.TARGET(TARGET),
.SYNCPIPE(SYNCPIPE))
wr_rsync (.nrst_out (wr_nreset),
.clk (wr_clk),
.nrst_in (nreset));
oh_rsync #(.TARGET(TARGET),
.SYNCPIPE(SYNCPIPE))
rd_rsync (.nrst_out (rd_nreset),
.clk (rd_clk),
.nrst_in (nreset));
//###########################
//# Write side address counter
//###########################
assign fifo_write = wr_en & ~wr_full;
always @ ( posedge wr_clk or negedge wr_nreset)
if(!wr_nreset)
wr_addr[AW:0] <= 'b0;
else if(fifo_write)
wr_addr[AW:0] <= wr_addr[AW:0] + 'd1;
//###########################
//# Read side address counter
//###########################
always @ ( posedge rd_clk or negedge rd_nreset)
if(!rd_nreset)
rd_addr[AW:0] <= 'd0;
else if(rd_en)
rd_addr[AW:0] <= rd_addr[AW:0] + 'd1;
//############################################
//# Synchronizaztion logic for async FIFO
//############################################
//###########################
//# WRITE --> READ
//###########################
// convert to gray code (only one bit can toggle)
oh_bin2gray #(.N(AW+1))
wr_bin2gray (.out (wr_addr_gray[AW:0]),
.in (wr_addr[AW:0]));
// synchronize to read clock
oh_dsync #(.TARGET(TARGET),
.SYNCPIPE(SYNCPIPE))
wr_sync[AW:0] (.dout (wr_addr_gray_sync[AW:0]),
.clk (rd_clk),
.nreset (rd_nreset),
.din (wr_addr_gray[AW:0]));
//###########################
//# READ ---> WRITE
//###########################
oh_bin2gray #(.N(AW+1))
rd_bin2gray (.out (rd_addr_gray[AW:0]),
.in (rd_addr[AW:0]));
//synchronize to wr clock
oh_dsync #(.TARGET(TARGET),
.SYNCPIPE(SYNCPIPE))
rd_sync[AW:0] (.dout (rd_addr_gray_sync[AW:0]),
.clk (wr_clk),
.nreset (wr_nreset),
.din (rd_addr_gray[AW:0]));
//###########################
//# Full/empty indicators
//###########################
// fifo indicators
assign rd_empty = (rd_addr_gray[AW:0] == wr_addr_gray_sync[AW:0]);
// fifo full
assign wr_full = (wr_addr[AW-1:0] == rd_addr_sync[AW-1:0]) &
(wr_addr[AW] != rd_addr_sync[AW]);
//###########################
//# Memory Array
//###########################
oh_dpram #(.N(N),
.DEPTH(DEPTH),
.REG(REG),
.TARGET(TARGET),
.SHAPE(SHAPE))
oh_dpram(.wr_wem ({(N){1'b1}}),
.wr_en (fifo_write),
/*AUTOINST*/
// Outputs
.rd_dout (rd_dout[N-1:0]),
// Inputs
.wr_clk (wr_clk),
.wr_addr (wr_addr[AW-1:0]),
.wr_din (wr_din[N-1:0]),
.rd_clk (rd_clk),
.rd_en (rd_en),
.rd_addr (rd_addr[AW-1:0]),
.bist_en (bist_en),
.bist_we (bist_we),
.bist_wem (bist_wem[N-1:0]),
.bist_addr (bist_addr[AW-1:0]),
.bist_din (bist_din[N-1:0]),
.shutdown (shutdown),
.vss (vss),
.vdd (vdd),
.vddio (vddio),
.memconfig (memconfig[7:0]),
.memrepair (memrepair[7:0]));
endmodule // oh_fifo_async