2015-11-28 20:15:06 -05:00
|
|
|
|
|
|
|
/*verilator lint_off IMPLICIT*/
|
|
|
|
/*verilator lint_off WIDTH*/
|
|
|
|
/*verilator lint_off LITENDIAN*/
|
|
|
|
/* verilator lint_off COMBDLY*/
|
|
|
|
|
2015-11-12 09:57:55 -05:00
|
|
|
/*
|
|
|
|
*******************************************************************************
|
|
|
|
*
|
|
|
|
* FIFO Generator - Verilog Behavioral Model
|
|
|
|
*
|
|
|
|
*******************************************************************************
|
|
|
|
*
|
|
|
|
* (c) Copyright 1995 - 2009 Xilinx, Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* This file contains confidential and proprietary information
|
|
|
|
* of Xilinx, Inc. and is protected under U.S. and
|
|
|
|
* international copyright and other intellectual property
|
|
|
|
* laws.
|
|
|
|
*
|
|
|
|
* DISCLAIMER
|
|
|
|
* This disclaimer is not a license and does not grant any
|
|
|
|
* rights to the materials distributed herewith. Except as
|
|
|
|
* otherwise provided in a valid license issued to you by
|
|
|
|
* Xilinx, and to the maximum extent permitted by applicable
|
|
|
|
* law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
|
|
|
|
* WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
|
|
|
|
* AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
|
|
|
|
* BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
|
|
|
|
* INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
|
|
|
|
* (2) Xilinx shall not be liable (whether in contract or tort,
|
|
|
|
* including negligence, or under any other theory of
|
|
|
|
* liability) for any loss or damage of any kind or nature
|
|
|
|
* related to, arising under or in connection with these
|
|
|
|
* materials, including for any direct, or any indirect,
|
|
|
|
* special, incidental, or consequential loss or damage
|
|
|
|
* (including loss of data, profits, goodwill, or any type of
|
|
|
|
* loss or damage suffered as a result of any action brought
|
|
|
|
* by a third party) even if such damage or loss was
|
|
|
|
* reasonably foreseeable or Xilinx had been advised of the
|
|
|
|
* possibility of the same.
|
|
|
|
*
|
|
|
|
* CRITICAL APPLICATIONS
|
|
|
|
* Xilinx products are not designed or intended to be fail-
|
|
|
|
* safe, or for use in any application requiring fail-safe
|
|
|
|
* performance, such as life-support or safety devices or
|
|
|
|
* systems, Class III medical devices, nuclear facilities,
|
|
|
|
* applications related to the deployment of airbags, or any
|
|
|
|
* other applications that could lead to death, personal
|
|
|
|
* injury, or severe property or environmental damage
|
|
|
|
* (individually and collectively, "Critical
|
|
|
|
* Applications"). Customer assumes the sole risk and
|
|
|
|
* liability of any use of Xilinx products in Critical
|
|
|
|
* Applications, subject only to applicable laws and
|
|
|
|
* regulations governing limitations on product liability.
|
|
|
|
*
|
|
|
|
* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
|
|
|
|
* PART OF THIS FILE AT ALL TIMES.
|
|
|
|
*
|
|
|
|
*******************************************************************************
|
|
|
|
*******************************************************************************
|
|
|
|
*
|
|
|
|
* Filename: fifo_generator_vlog_beh.v
|
|
|
|
*
|
|
|
|
* Author : Xilinx
|
|
|
|
*
|
|
|
|
*******************************************************************************
|
|
|
|
* Structure:
|
|
|
|
*
|
|
|
|
* fifo_generator_vlog_beh.v
|
|
|
|
* |
|
|
|
|
* +-fifo_generator_v12_0_bhv_ver_as
|
|
|
|
* |
|
|
|
|
* +-fifo_generator_v12_0_bhv_ver_ss
|
|
|
|
* |
|
|
|
|
* +-fifo_generator_v12_0_bhv_ver_preload0
|
|
|
|
*
|
|
|
|
*******************************************************************************
|
|
|
|
* Description:
|
|
|
|
*
|
|
|
|
* The Verilog behavioral model for the FIFO Generator.
|
|
|
|
*
|
|
|
|
* The behavioral model has three parts:
|
|
|
|
* - The behavioral model for independent clocks FIFOs (_as)
|
|
|
|
* - The behavioral model for common clock FIFOs (_ss)
|
|
|
|
* - The "preload logic" block which implements First-word Fall-through
|
|
|
|
*
|
|
|
|
*******************************************************************************
|
|
|
|
* Description:
|
|
|
|
* The verilog behavioral model for the FIFO generator core.
|
|
|
|
*
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
`timescale 1ps/1ps
|
|
|
|
`ifndef TCQ
|
|
|
|
`define TCQ 100
|
|
|
|
`endif
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Declaration of top-level module
|
|
|
|
******************************************************************************/
|
|
|
|
module fifo_generator_vlog_beh
|
|
|
|
#(
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
// Generic Declarations
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
parameter C_COMMON_CLOCK = 0,
|
|
|
|
parameter C_COUNT_TYPE = 0,
|
|
|
|
parameter C_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_DEFAULT_VALUE = "",
|
|
|
|
parameter C_DIN_WIDTH = 8,
|
|
|
|
parameter C_DOUT_RST_VAL = "",
|
|
|
|
parameter C_DOUT_WIDTH = 8,
|
|
|
|
parameter C_ENABLE_RLOCS = 0,
|
|
|
|
parameter C_FAMILY = "",
|
|
|
|
parameter C_FULL_FLAGS_RST_VAL = 1,
|
|
|
|
parameter C_HAS_ALMOST_EMPTY = 0,
|
|
|
|
parameter C_HAS_ALMOST_FULL = 0,
|
|
|
|
parameter C_HAS_BACKUP = 0,
|
|
|
|
parameter C_HAS_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_INT_CLK = 0,
|
|
|
|
parameter C_HAS_MEMINIT_FILE = 0,
|
|
|
|
parameter C_HAS_OVERFLOW = 0,
|
|
|
|
parameter C_HAS_RD_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_RD_RST = 0,
|
|
|
|
parameter C_HAS_RST = 1,
|
|
|
|
parameter C_HAS_SRST = 0,
|
|
|
|
parameter C_HAS_UNDERFLOW = 0,
|
|
|
|
parameter C_HAS_VALID = 0,
|
|
|
|
parameter C_HAS_WR_ACK = 0,
|
|
|
|
parameter C_HAS_WR_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_WR_RST = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE = 0,
|
|
|
|
parameter C_INIT_WR_PNTR_VAL = 0,
|
|
|
|
parameter C_MEMORY_TYPE = 1,
|
|
|
|
parameter C_MIF_FILE_NAME = "",
|
|
|
|
parameter C_OPTIMIZATION_MODE = 0,
|
|
|
|
parameter C_OVERFLOW_LOW = 0,
|
|
|
|
parameter C_PRELOAD_LATENCY = 1,
|
|
|
|
parameter C_PRELOAD_REGS = 0,
|
|
|
|
parameter C_PRIM_FIFO_TYPE = "4kx4",
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE = 0,
|
|
|
|
parameter C_RD_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_RD_DEPTH = 256,
|
|
|
|
parameter C_RD_FREQ = 1,
|
|
|
|
parameter C_RD_PNTR_WIDTH = 8,
|
|
|
|
parameter C_UNDERFLOW_LOW = 0,
|
|
|
|
parameter C_USE_DOUT_RST = 0,
|
|
|
|
parameter C_USE_ECC = 0,
|
|
|
|
parameter C_USE_EMBEDDED_REG = 0,
|
|
|
|
parameter C_USE_PIPELINE_REG = 0,
|
|
|
|
parameter C_POWER_SAVING_MODE = 0,
|
|
|
|
parameter C_USE_FIFO16_FLAGS = 0,
|
|
|
|
parameter C_USE_FWFT_DATA_COUNT = 0,
|
|
|
|
parameter C_VALID_LOW = 0,
|
|
|
|
parameter C_WR_ACK_LOW = 0,
|
|
|
|
parameter C_WR_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_WR_DEPTH = 256,
|
|
|
|
parameter C_WR_FREQ = 1,
|
|
|
|
parameter C_WR_PNTR_WIDTH = 8,
|
|
|
|
parameter C_WR_RESPONSE_LATENCY = 1,
|
|
|
|
parameter C_MSGON_VAL = 1,
|
|
|
|
parameter C_ENABLE_RST_SYNC = 1,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE = 0,
|
|
|
|
parameter C_SYNCHRONIZER_STAGE = 2,
|
|
|
|
|
|
|
|
// AXI Interface related parameters start here
|
|
|
|
parameter C_INTERFACE_TYPE = 0, // 0: Native Interface, 1: AXI4 Stream, 2: AXI4/AXI3
|
|
|
|
parameter C_AXI_TYPE = 0, // 1: AXI4, 2: AXI4 Lite, 3: AXI3
|
|
|
|
parameter C_HAS_AXI_WR_CHANNEL = 0,
|
|
|
|
parameter C_HAS_AXI_RD_CHANNEL = 0,
|
|
|
|
parameter C_HAS_SLAVE_CE = 0,
|
|
|
|
parameter C_HAS_MASTER_CE = 0,
|
|
|
|
parameter C_ADD_NGC_CONSTRAINT = 0,
|
|
|
|
parameter C_USE_COMMON_UNDERFLOW = 0,
|
|
|
|
parameter C_USE_COMMON_OVERFLOW = 0,
|
|
|
|
parameter C_USE_DEFAULT_SETTINGS = 0,
|
|
|
|
|
|
|
|
// AXI Full/Lite
|
|
|
|
parameter C_AXI_ID_WIDTH = 0,
|
|
|
|
parameter C_AXI_ADDR_WIDTH = 0,
|
|
|
|
parameter C_AXI_DATA_WIDTH = 0,
|
|
|
|
parameter C_AXI_LEN_WIDTH = 8,
|
|
|
|
parameter C_AXI_LOCK_WIDTH = 2,
|
|
|
|
parameter C_HAS_AXI_ID = 0,
|
|
|
|
parameter C_HAS_AXI_AWUSER = 0,
|
|
|
|
parameter C_HAS_AXI_WUSER = 0,
|
|
|
|
parameter C_HAS_AXI_BUSER = 0,
|
|
|
|
parameter C_HAS_AXI_ARUSER = 0,
|
|
|
|
parameter C_HAS_AXI_RUSER = 0,
|
|
|
|
parameter C_AXI_ARUSER_WIDTH = 0,
|
|
|
|
parameter C_AXI_AWUSER_WIDTH = 0,
|
|
|
|
parameter C_AXI_WUSER_WIDTH = 0,
|
|
|
|
parameter C_AXI_BUSER_WIDTH = 0,
|
|
|
|
parameter C_AXI_RUSER_WIDTH = 0,
|
|
|
|
|
|
|
|
// AXI Streaming
|
|
|
|
parameter C_HAS_AXIS_TDATA = 0,
|
|
|
|
parameter C_HAS_AXIS_TID = 0,
|
|
|
|
parameter C_HAS_AXIS_TDEST = 0,
|
|
|
|
parameter C_HAS_AXIS_TUSER = 0,
|
|
|
|
parameter C_HAS_AXIS_TREADY = 0,
|
|
|
|
parameter C_HAS_AXIS_TLAST = 0,
|
|
|
|
parameter C_HAS_AXIS_TSTRB = 0,
|
|
|
|
parameter C_HAS_AXIS_TKEEP = 0,
|
|
|
|
parameter C_AXIS_TDATA_WIDTH = 1,
|
|
|
|
parameter C_AXIS_TID_WIDTH = 1,
|
|
|
|
parameter C_AXIS_TDEST_WIDTH = 1,
|
|
|
|
parameter C_AXIS_TUSER_WIDTH = 1,
|
|
|
|
parameter C_AXIS_TSTRB_WIDTH = 1,
|
|
|
|
parameter C_AXIS_TKEEP_WIDTH = 1,
|
|
|
|
|
|
|
|
// AXI Channel Type
|
|
|
|
// WACH --> Write Address Channel
|
|
|
|
// WDCH --> Write Data Channel
|
|
|
|
// WRCH --> Write Response Channel
|
|
|
|
// RACH --> Read Address Channel
|
|
|
|
// RDCH --> Read Data Channel
|
|
|
|
// AXIS --> AXI Streaming
|
|
|
|
parameter C_WACH_TYPE = 0, // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logic
|
|
|
|
parameter C_WDCH_TYPE = 0, // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
|
|
|
parameter C_WRCH_TYPE = 0, // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
|
|
|
parameter C_RACH_TYPE = 0, // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
|
|
|
parameter C_RDCH_TYPE = 0, // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
|
|
|
parameter C_AXIS_TYPE = 0, // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
|
|
|
|
|
|
|
// AXI Implementation Type
|
|
|
|
// 1 = Common Clock Block RAM FIFO
|
|
|
|
// 2 = Common Clock Distributed RAM FIFO
|
|
|
|
// 11 = Independent Clock Block RAM FIFO
|
|
|
|
// 12 = Independent Clock Distributed RAM FIFO
|
|
|
|
parameter C_IMPLEMENTATION_TYPE_WACH = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE_WDCH = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE_WRCH = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE_RACH = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE_RDCH = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE_AXIS = 0,
|
|
|
|
|
|
|
|
// AXI FIFO Type
|
|
|
|
// 0 = Data FIFO
|
|
|
|
// 1 = Packet FIFO
|
|
|
|
// 2 = Low Latency Sync FIFO
|
|
|
|
// 3 = Low Latency Async FIFO
|
|
|
|
parameter C_APPLICATION_TYPE_WACH = 0,
|
|
|
|
parameter C_APPLICATION_TYPE_WDCH = 0,
|
|
|
|
parameter C_APPLICATION_TYPE_WRCH = 0,
|
|
|
|
parameter C_APPLICATION_TYPE_RACH = 0,
|
|
|
|
parameter C_APPLICATION_TYPE_RDCH = 0,
|
|
|
|
parameter C_APPLICATION_TYPE_AXIS = 0,
|
|
|
|
|
|
|
|
// AXI Built-in FIFO Primitive Type
|
|
|
|
// 512x36, 1kx18, 2kx9, 4kx4, etc
|
|
|
|
parameter C_PRIM_FIFO_TYPE_WACH = "512x36",
|
|
|
|
parameter C_PRIM_FIFO_TYPE_WDCH = "512x36",
|
|
|
|
parameter C_PRIM_FIFO_TYPE_WRCH = "512x36",
|
|
|
|
parameter C_PRIM_FIFO_TYPE_RACH = "512x36",
|
|
|
|
parameter C_PRIM_FIFO_TYPE_RDCH = "512x36",
|
|
|
|
parameter C_PRIM_FIFO_TYPE_AXIS = "512x36",
|
|
|
|
|
|
|
|
// Enable ECC
|
|
|
|
// 0 = ECC disabled
|
|
|
|
// 1 = ECC enabled
|
|
|
|
parameter C_USE_ECC_WACH = 0,
|
|
|
|
parameter C_USE_ECC_WDCH = 0,
|
|
|
|
parameter C_USE_ECC_WRCH = 0,
|
|
|
|
parameter C_USE_ECC_RACH = 0,
|
|
|
|
parameter C_USE_ECC_RDCH = 0,
|
|
|
|
parameter C_USE_ECC_AXIS = 0,
|
|
|
|
|
|
|
|
// ECC Error Injection Type
|
|
|
|
// 0 = No Error Injection
|
|
|
|
// 1 = Single Bit Error Injection
|
|
|
|
// 2 = Double Bit Error Injection
|
|
|
|
// 3 = Single Bit and Double Bit Error Injection
|
|
|
|
parameter C_ERROR_INJECTION_TYPE_WACH = 0,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE_WDCH = 0,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE_WRCH = 0,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE_RACH = 0,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE_RDCH = 0,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE_AXIS = 0,
|
|
|
|
|
|
|
|
// Input Data Width
|
|
|
|
// Accumulation of all AXI input signal's width
|
|
|
|
parameter C_DIN_WIDTH_WACH = 1,
|
|
|
|
parameter C_DIN_WIDTH_WDCH = 1,
|
|
|
|
parameter C_DIN_WIDTH_WRCH = 1,
|
|
|
|
parameter C_DIN_WIDTH_RACH = 1,
|
|
|
|
parameter C_DIN_WIDTH_RDCH = 1,
|
|
|
|
parameter C_DIN_WIDTH_AXIS = 1,
|
|
|
|
|
|
|
|
parameter C_WR_DEPTH_WACH = 16,
|
|
|
|
parameter C_WR_DEPTH_WDCH = 16,
|
|
|
|
parameter C_WR_DEPTH_WRCH = 16,
|
|
|
|
parameter C_WR_DEPTH_RACH = 16,
|
|
|
|
parameter C_WR_DEPTH_RDCH = 16,
|
|
|
|
parameter C_WR_DEPTH_AXIS = 16,
|
|
|
|
|
|
|
|
parameter C_WR_PNTR_WIDTH_WACH = 4,
|
|
|
|
parameter C_WR_PNTR_WIDTH_WDCH = 4,
|
|
|
|
parameter C_WR_PNTR_WIDTH_WRCH = 4,
|
|
|
|
parameter C_WR_PNTR_WIDTH_RACH = 4,
|
|
|
|
parameter C_WR_PNTR_WIDTH_RDCH = 4,
|
|
|
|
parameter C_WR_PNTR_WIDTH_AXIS = 4,
|
|
|
|
|
|
|
|
parameter C_HAS_DATA_COUNTS_WACH = 0,
|
|
|
|
parameter C_HAS_DATA_COUNTS_WDCH = 0,
|
|
|
|
parameter C_HAS_DATA_COUNTS_WRCH = 0,
|
|
|
|
parameter C_HAS_DATA_COUNTS_RACH = 0,
|
|
|
|
parameter C_HAS_DATA_COUNTS_RDCH = 0,
|
|
|
|
parameter C_HAS_DATA_COUNTS_AXIS = 0,
|
|
|
|
|
|
|
|
parameter C_HAS_PROG_FLAGS_WACH = 0,
|
|
|
|
parameter C_HAS_PROG_FLAGS_WDCH = 0,
|
|
|
|
parameter C_HAS_PROG_FLAGS_WRCH = 0,
|
|
|
|
parameter C_HAS_PROG_FLAGS_RACH = 0,
|
|
|
|
parameter C_HAS_PROG_FLAGS_RDCH = 0,
|
|
|
|
parameter C_HAS_PROG_FLAGS_AXIS = 0,
|
|
|
|
|
|
|
|
parameter C_PROG_FULL_TYPE_WACH = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE_WDCH = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE_WRCH = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE_RACH = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE_RDCH = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE_AXIS = 0,
|
|
|
|
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL_WACH = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL_WDCH = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL_WRCH = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL_RACH = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL_RDCH = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL_AXIS = 0,
|
|
|
|
|
|
|
|
parameter C_PROG_EMPTY_TYPE_WACH = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE_WDCH = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE_WRCH = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE_RACH = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE_RDCH = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE_AXIS = 0,
|
|
|
|
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL_WACH = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL_WDCH = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL_WRCH = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL_RACH = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL_RDCH = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL_AXIS = 0,
|
|
|
|
|
|
|
|
parameter C_REG_SLICE_MODE_WACH = 0,
|
|
|
|
parameter C_REG_SLICE_MODE_WDCH = 0,
|
|
|
|
parameter C_REG_SLICE_MODE_WRCH = 0,
|
|
|
|
parameter C_REG_SLICE_MODE_RACH = 0,
|
|
|
|
parameter C_REG_SLICE_MODE_RDCH = 0,
|
|
|
|
parameter C_REG_SLICE_MODE_AXIS = 0
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
(
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Input and Output Declarations
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Conventional FIFO Interface Signals
|
|
|
|
input backup,
|
|
|
|
input backup_marker,
|
|
|
|
input clk,
|
|
|
|
input rst,
|
|
|
|
input srst,
|
|
|
|
input wr_clk,
|
|
|
|
input wr_rst,
|
|
|
|
input rd_clk,
|
|
|
|
input rd_rst,
|
|
|
|
input [C_DIN_WIDTH-1:0] din,
|
|
|
|
input wr_en,
|
|
|
|
input rd_en,
|
|
|
|
// Optional inputs
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] prog_empty_thresh,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] prog_empty_thresh_assert,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] prog_empty_thresh_negate,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] prog_full_thresh_assert,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] prog_full_thresh_negate,
|
|
|
|
input int_clk,
|
|
|
|
input injectdbiterr,
|
|
|
|
input injectsbiterr,
|
|
|
|
input sleep,
|
|
|
|
|
|
|
|
output [C_DOUT_WIDTH-1:0] dout,
|
|
|
|
output full,
|
|
|
|
output almost_full,
|
|
|
|
output wr_ack,
|
|
|
|
output overflow,
|
|
|
|
output empty,
|
|
|
|
output almost_empty,
|
|
|
|
output valid,
|
|
|
|
output underflow,
|
|
|
|
output [C_DATA_COUNT_WIDTH-1:0] data_count,
|
|
|
|
output [C_RD_DATA_COUNT_WIDTH-1:0] rd_data_count,
|
|
|
|
output [C_WR_DATA_COUNT_WIDTH-1:0] wr_data_count,
|
|
|
|
output prog_full,
|
|
|
|
output prog_empty,
|
|
|
|
output sbiterr,
|
|
|
|
output dbiterr,
|
|
|
|
output wr_rst_busy,
|
|
|
|
output rd_rst_busy,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Global Signal
|
|
|
|
input m_aclk,
|
|
|
|
input s_aclk,
|
|
|
|
input s_aresetn,
|
|
|
|
input s_aclk_en,
|
|
|
|
input m_aclk_en,
|
|
|
|
|
|
|
|
// AXI Full/Lite Slave Write Channel (write side)
|
|
|
|
input [C_AXI_ID_WIDTH-1:0] s_axi_awid,
|
|
|
|
input [C_AXI_ADDR_WIDTH-1:0] s_axi_awaddr,
|
|
|
|
input [C_AXI_LEN_WIDTH-1:0] s_axi_awlen,
|
|
|
|
input [3-1:0] s_axi_awsize,
|
|
|
|
input [2-1:0] s_axi_awburst,
|
|
|
|
input [C_AXI_LOCK_WIDTH-1:0] s_axi_awlock,
|
|
|
|
input [4-1:0] s_axi_awcache,
|
|
|
|
input [3-1:0] s_axi_awprot,
|
|
|
|
input [4-1:0] s_axi_awqos,
|
|
|
|
input [4-1:0] s_axi_awregion,
|
|
|
|
input [C_AXI_AWUSER_WIDTH-1:0] s_axi_awuser,
|
|
|
|
input s_axi_awvalid,
|
|
|
|
output s_axi_awready,
|
|
|
|
input [C_AXI_ID_WIDTH-1:0] s_axi_wid,
|
|
|
|
input [C_AXI_DATA_WIDTH-1:0] s_axi_wdata,
|
|
|
|
input [C_AXI_DATA_WIDTH/8-1:0] s_axi_wstrb,
|
|
|
|
input s_axi_wlast,
|
|
|
|
input [C_AXI_WUSER_WIDTH-1:0] s_axi_wuser,
|
|
|
|
input s_axi_wvalid,
|
|
|
|
output s_axi_wready,
|
|
|
|
output [C_AXI_ID_WIDTH-1:0] s_axi_bid,
|
|
|
|
output [2-1:0] s_axi_bresp,
|
|
|
|
output [C_AXI_BUSER_WIDTH-1:0] s_axi_buser,
|
|
|
|
output s_axi_bvalid,
|
|
|
|
input s_axi_bready,
|
|
|
|
|
|
|
|
// AXI Full/Lite Master Write Channel (read side)
|
|
|
|
output [C_AXI_ID_WIDTH-1:0] m_axi_awid,
|
|
|
|
output [C_AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
|
|
|
output [C_AXI_LEN_WIDTH-1:0] m_axi_awlen,
|
|
|
|
output [3-1:0] m_axi_awsize,
|
|
|
|
output [2-1:0] m_axi_awburst,
|
|
|
|
output [C_AXI_LOCK_WIDTH-1:0] m_axi_awlock,
|
|
|
|
output [4-1:0] m_axi_awcache,
|
|
|
|
output [3-1:0] m_axi_awprot,
|
|
|
|
output [4-1:0] m_axi_awqos,
|
|
|
|
output [4-1:0] m_axi_awregion,
|
|
|
|
output [C_AXI_AWUSER_WIDTH-1:0] m_axi_awuser,
|
|
|
|
output m_axi_awvalid,
|
|
|
|
input m_axi_awready,
|
|
|
|
output [C_AXI_ID_WIDTH-1:0] m_axi_wid,
|
|
|
|
output [C_AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
|
|
|
output [C_AXI_DATA_WIDTH/8-1:0] m_axi_wstrb,
|
|
|
|
output m_axi_wlast,
|
|
|
|
output [C_AXI_WUSER_WIDTH-1:0] m_axi_wuser,
|
|
|
|
output m_axi_wvalid,
|
|
|
|
input m_axi_wready,
|
|
|
|
input [C_AXI_ID_WIDTH-1:0] m_axi_bid,
|
|
|
|
input [2-1:0] m_axi_bresp,
|
|
|
|
input [C_AXI_BUSER_WIDTH-1:0] m_axi_buser,
|
|
|
|
input m_axi_bvalid,
|
|
|
|
output m_axi_bready,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Slave Read Channel (write side)
|
|
|
|
input [C_AXI_ID_WIDTH-1:0] s_axi_arid,
|
|
|
|
input [C_AXI_ADDR_WIDTH-1:0] s_axi_araddr,
|
|
|
|
input [C_AXI_LEN_WIDTH-1:0] s_axi_arlen,
|
|
|
|
input [3-1:0] s_axi_arsize,
|
|
|
|
input [2-1:0] s_axi_arburst,
|
|
|
|
input [C_AXI_LOCK_WIDTH-1:0] s_axi_arlock,
|
|
|
|
input [4-1:0] s_axi_arcache,
|
|
|
|
input [3-1:0] s_axi_arprot,
|
|
|
|
input [4-1:0] s_axi_arqos,
|
|
|
|
input [4-1:0] s_axi_arregion,
|
|
|
|
input [C_AXI_ARUSER_WIDTH-1:0] s_axi_aruser,
|
|
|
|
input s_axi_arvalid,
|
|
|
|
output s_axi_arready,
|
|
|
|
output [C_AXI_ID_WIDTH-1:0] s_axi_rid,
|
|
|
|
output [C_AXI_DATA_WIDTH-1:0] s_axi_rdata,
|
|
|
|
output [2-1:0] s_axi_rresp,
|
|
|
|
output s_axi_rlast,
|
|
|
|
output [C_AXI_RUSER_WIDTH-1:0] s_axi_ruser,
|
|
|
|
output s_axi_rvalid,
|
|
|
|
input s_axi_rready,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Master Read Channel (read side)
|
|
|
|
output [C_AXI_ID_WIDTH-1:0] m_axi_arid,
|
|
|
|
output [C_AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
|
|
|
output [C_AXI_LEN_WIDTH-1:0] m_axi_arlen,
|
|
|
|
output [3-1:0] m_axi_arsize,
|
|
|
|
output [2-1:0] m_axi_arburst,
|
|
|
|
output [C_AXI_LOCK_WIDTH-1:0] m_axi_arlock,
|
|
|
|
output [4-1:0] m_axi_arcache,
|
|
|
|
output [3-1:0] m_axi_arprot,
|
|
|
|
output [4-1:0] m_axi_arqos,
|
|
|
|
output [4-1:0] m_axi_arregion,
|
|
|
|
output [C_AXI_ARUSER_WIDTH-1:0] m_axi_aruser,
|
|
|
|
output m_axi_arvalid,
|
|
|
|
input m_axi_arready,
|
|
|
|
input [C_AXI_ID_WIDTH-1:0] m_axi_rid,
|
|
|
|
input [C_AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
|
|
|
input [2-1:0] m_axi_rresp,
|
|
|
|
input m_axi_rlast,
|
|
|
|
input [C_AXI_RUSER_WIDTH-1:0] m_axi_ruser,
|
|
|
|
input m_axi_rvalid,
|
|
|
|
output m_axi_rready,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Streaming Slave Signals (Write side)
|
|
|
|
input s_axis_tvalid,
|
|
|
|
output s_axis_tready,
|
|
|
|
input [C_AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
|
|
|
|
input [C_AXIS_TSTRB_WIDTH-1:0] s_axis_tstrb,
|
|
|
|
input [C_AXIS_TKEEP_WIDTH-1:0] s_axis_tkeep,
|
|
|
|
input s_axis_tlast,
|
|
|
|
input [C_AXIS_TID_WIDTH-1:0] s_axis_tid,
|
|
|
|
input [C_AXIS_TDEST_WIDTH-1:0] s_axis_tdest,
|
|
|
|
input [C_AXIS_TUSER_WIDTH-1:0] s_axis_tuser,
|
|
|
|
|
|
|
|
// AXI Streaming Master Signals (Read side)
|
|
|
|
output m_axis_tvalid,
|
|
|
|
input m_axis_tready,
|
|
|
|
output [C_AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
|
|
|
|
output [C_AXIS_TSTRB_WIDTH-1:0] m_axis_tstrb,
|
|
|
|
output [C_AXIS_TKEEP_WIDTH-1:0] m_axis_tkeep,
|
|
|
|
output m_axis_tlast,
|
|
|
|
output [C_AXIS_TID_WIDTH-1:0] m_axis_tid,
|
|
|
|
output [C_AXIS_TDEST_WIDTH-1:0] m_axis_tdest,
|
|
|
|
output [C_AXIS_TUSER_WIDTH-1:0] m_axis_tuser,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Write Address Channel signals
|
|
|
|
input axi_aw_injectsbiterr,
|
|
|
|
input axi_aw_injectdbiterr,
|
|
|
|
input [C_WR_PNTR_WIDTH_WACH-1:0] axi_aw_prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH_WACH-1:0] axi_aw_prog_empty_thresh,
|
|
|
|
output [C_WR_PNTR_WIDTH_WACH:0] axi_aw_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_WACH:0] axi_aw_wr_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_WACH:0] axi_aw_rd_data_count,
|
|
|
|
output axi_aw_sbiterr,
|
|
|
|
output axi_aw_dbiterr,
|
|
|
|
output axi_aw_overflow,
|
|
|
|
output axi_aw_underflow,
|
|
|
|
output axi_aw_prog_full,
|
|
|
|
output axi_aw_prog_empty,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Write Data Channel signals
|
|
|
|
input axi_w_injectsbiterr,
|
|
|
|
input axi_w_injectdbiterr,
|
|
|
|
input [C_WR_PNTR_WIDTH_WDCH-1:0] axi_w_prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH_WDCH-1:0] axi_w_prog_empty_thresh,
|
|
|
|
output [C_WR_PNTR_WIDTH_WDCH:0] axi_w_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_WDCH:0] axi_w_wr_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_WDCH:0] axi_w_rd_data_count,
|
|
|
|
output axi_w_sbiterr,
|
|
|
|
output axi_w_dbiterr,
|
|
|
|
output axi_w_overflow,
|
|
|
|
output axi_w_underflow,
|
|
|
|
output axi_w_prog_full,
|
|
|
|
output axi_w_prog_empty,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Write Response Channel signals
|
|
|
|
input axi_b_injectsbiterr,
|
|
|
|
input axi_b_injectdbiterr,
|
|
|
|
input [C_WR_PNTR_WIDTH_WRCH-1:0] axi_b_prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH_WRCH-1:0] axi_b_prog_empty_thresh,
|
|
|
|
output [C_WR_PNTR_WIDTH_WRCH:0] axi_b_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_WRCH:0] axi_b_wr_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_WRCH:0] axi_b_rd_data_count,
|
|
|
|
output axi_b_sbiterr,
|
|
|
|
output axi_b_dbiterr,
|
|
|
|
output axi_b_overflow,
|
|
|
|
output axi_b_underflow,
|
|
|
|
output axi_b_prog_full,
|
|
|
|
output axi_b_prog_empty,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Read Address Channel signals
|
|
|
|
input axi_ar_injectsbiterr,
|
|
|
|
input axi_ar_injectdbiterr,
|
|
|
|
input [C_WR_PNTR_WIDTH_RACH-1:0] axi_ar_prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH_RACH-1:0] axi_ar_prog_empty_thresh,
|
|
|
|
output [C_WR_PNTR_WIDTH_RACH:0] axi_ar_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_RACH:0] axi_ar_wr_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_RACH:0] axi_ar_rd_data_count,
|
|
|
|
output axi_ar_sbiterr,
|
|
|
|
output axi_ar_dbiterr,
|
|
|
|
output axi_ar_overflow,
|
|
|
|
output axi_ar_underflow,
|
|
|
|
output axi_ar_prog_full,
|
|
|
|
output axi_ar_prog_empty,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Full/Lite Read Data Channel Signals
|
|
|
|
input axi_r_injectsbiterr,
|
|
|
|
input axi_r_injectdbiterr,
|
|
|
|
input [C_WR_PNTR_WIDTH_RDCH-1:0] axi_r_prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH_RDCH-1:0] axi_r_prog_empty_thresh,
|
|
|
|
output [C_WR_PNTR_WIDTH_RDCH:0] axi_r_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_RDCH:0] axi_r_wr_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_RDCH:0] axi_r_rd_data_count,
|
|
|
|
output axi_r_sbiterr,
|
|
|
|
output axi_r_dbiterr,
|
|
|
|
output axi_r_overflow,
|
|
|
|
output axi_r_underflow,
|
|
|
|
output axi_r_prog_full,
|
|
|
|
output axi_r_prog_empty,
|
|
|
|
|
|
|
|
|
|
|
|
// AXI Streaming FIFO Related Signals
|
|
|
|
input axis_injectsbiterr,
|
|
|
|
input axis_injectdbiterr,
|
|
|
|
input [C_WR_PNTR_WIDTH_AXIS-1:0] axis_prog_full_thresh,
|
|
|
|
input [C_WR_PNTR_WIDTH_AXIS-1:0] axis_prog_empty_thresh,
|
|
|
|
output [C_WR_PNTR_WIDTH_AXIS:0] axis_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_AXIS:0] axis_wr_data_count,
|
|
|
|
output [C_WR_PNTR_WIDTH_AXIS:0] axis_rd_data_count,
|
|
|
|
output axis_sbiterr,
|
|
|
|
output axis_dbiterr,
|
|
|
|
output axis_overflow,
|
|
|
|
output axis_underflow,
|
|
|
|
output axis_prog_full,
|
|
|
|
output axis_prog_empty
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
wire BACKUP;
|
|
|
|
wire BACKUP_MARKER;
|
|
|
|
wire CLK;
|
|
|
|
wire RST;
|
|
|
|
wire SRST;
|
|
|
|
wire WR_CLK;
|
|
|
|
wire WR_RST;
|
|
|
|
wire RD_CLK;
|
|
|
|
wire RD_RST;
|
|
|
|
wire [C_DIN_WIDTH-1:0] DIN;
|
|
|
|
wire WR_EN;
|
|
|
|
wire RD_EN;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE;
|
|
|
|
wire INT_CLK;
|
|
|
|
wire INJECTDBITERR;
|
|
|
|
wire INJECTSBITERR;
|
|
|
|
wire SLEEP;
|
|
|
|
wire [C_DOUT_WIDTH-1:0] DOUT;
|
|
|
|
wire FULL;
|
|
|
|
wire ALMOST_FULL;
|
|
|
|
wire WR_ACK;
|
|
|
|
wire OVERFLOW;
|
|
|
|
wire EMPTY;
|
|
|
|
wire ALMOST_EMPTY;
|
|
|
|
wire VALID;
|
|
|
|
wire UNDERFLOW;
|
|
|
|
wire [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT;
|
|
|
|
wire [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT;
|
|
|
|
wire [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT;
|
|
|
|
wire PROG_FULL;
|
|
|
|
wire PROG_EMPTY;
|
|
|
|
wire SBITERR;
|
|
|
|
wire DBITERR;
|
|
|
|
wire WR_RST_BUSY;
|
|
|
|
wire RD_RST_BUSY;
|
|
|
|
wire M_ACLK;
|
|
|
|
wire S_ACLK;
|
|
|
|
wire S_ARESETN;
|
|
|
|
wire S_ACLK_EN;
|
|
|
|
wire M_ACLK_EN;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] S_AXI_AWID;
|
|
|
|
wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_AWADDR;
|
|
|
|
wire [C_AXI_LEN_WIDTH-1:0] S_AXI_AWLEN;
|
|
|
|
wire [3-1:0] S_AXI_AWSIZE;
|
|
|
|
wire [2-1:0] S_AXI_AWBURST;
|
|
|
|
wire [C_AXI_LOCK_WIDTH-1:0] S_AXI_AWLOCK;
|
|
|
|
wire [4-1:0] S_AXI_AWCACHE;
|
|
|
|
wire [3-1:0] S_AXI_AWPROT;
|
|
|
|
wire [4-1:0] S_AXI_AWQOS;
|
|
|
|
wire [4-1:0] S_AXI_AWREGION;
|
|
|
|
wire [C_AXI_AWUSER_WIDTH-1:0] S_AXI_AWUSER;
|
|
|
|
wire S_AXI_AWVALID;
|
|
|
|
wire S_AXI_AWREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] S_AXI_WID;
|
|
|
|
wire [C_AXI_DATA_WIDTH-1:0] S_AXI_WDATA;
|
|
|
|
wire [C_AXI_DATA_WIDTH/8-1:0] S_AXI_WSTRB;
|
|
|
|
wire S_AXI_WLAST;
|
|
|
|
wire [C_AXI_WUSER_WIDTH-1:0] S_AXI_WUSER;
|
|
|
|
wire S_AXI_WVALID;
|
|
|
|
wire S_AXI_WREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] S_AXI_BID;
|
|
|
|
wire [2-1:0] S_AXI_BRESP;
|
|
|
|
wire [C_AXI_BUSER_WIDTH-1:0] S_AXI_BUSER;
|
|
|
|
wire S_AXI_BVALID;
|
|
|
|
wire S_AXI_BREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] M_AXI_AWID;
|
|
|
|
wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR;
|
|
|
|
wire [C_AXI_LEN_WIDTH-1:0] M_AXI_AWLEN;
|
|
|
|
wire [3-1:0] M_AXI_AWSIZE;
|
|
|
|
wire [2-1:0] M_AXI_AWBURST;
|
|
|
|
wire [C_AXI_LOCK_WIDTH-1:0] M_AXI_AWLOCK;
|
|
|
|
wire [4-1:0] M_AXI_AWCACHE;
|
|
|
|
wire [3-1:0] M_AXI_AWPROT;
|
|
|
|
wire [4-1:0] M_AXI_AWQOS;
|
|
|
|
wire [4-1:0] M_AXI_AWREGION;
|
|
|
|
wire [C_AXI_AWUSER_WIDTH-1:0] M_AXI_AWUSER;
|
|
|
|
wire M_AXI_AWVALID;
|
|
|
|
wire M_AXI_AWREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] M_AXI_WID;
|
|
|
|
wire [C_AXI_DATA_WIDTH-1:0] M_AXI_WDATA;
|
|
|
|
wire [C_AXI_DATA_WIDTH/8-1:0] M_AXI_WSTRB;
|
|
|
|
wire M_AXI_WLAST;
|
|
|
|
wire [C_AXI_WUSER_WIDTH-1:0] M_AXI_WUSER;
|
|
|
|
wire M_AXI_WVALID;
|
|
|
|
wire M_AXI_WREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] M_AXI_BID;
|
|
|
|
wire [2-1:0] M_AXI_BRESP;
|
|
|
|
wire [C_AXI_BUSER_WIDTH-1:0] M_AXI_BUSER;
|
|
|
|
wire M_AXI_BVALID;
|
|
|
|
wire M_AXI_BREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] S_AXI_ARID;
|
|
|
|
wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_ARADDR;
|
|
|
|
wire [C_AXI_LEN_WIDTH-1:0] S_AXI_ARLEN;
|
|
|
|
wire [3-1:0] S_AXI_ARSIZE;
|
|
|
|
wire [2-1:0] S_AXI_ARBURST;
|
|
|
|
wire [C_AXI_LOCK_WIDTH-1:0] S_AXI_ARLOCK;
|
|
|
|
wire [4-1:0] S_AXI_ARCACHE;
|
|
|
|
wire [3-1:0] S_AXI_ARPROT;
|
|
|
|
wire [4-1:0] S_AXI_ARQOS;
|
|
|
|
wire [4-1:0] S_AXI_ARREGION;
|
|
|
|
wire [C_AXI_ARUSER_WIDTH-1:0] S_AXI_ARUSER;
|
|
|
|
wire S_AXI_ARVALID;
|
|
|
|
wire S_AXI_ARREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] S_AXI_RID;
|
|
|
|
wire [C_AXI_DATA_WIDTH-1:0] S_AXI_RDATA;
|
|
|
|
wire [2-1:0] S_AXI_RRESP;
|
|
|
|
wire S_AXI_RLAST;
|
|
|
|
wire [C_AXI_RUSER_WIDTH-1:0] S_AXI_RUSER;
|
|
|
|
wire S_AXI_RVALID;
|
|
|
|
wire S_AXI_RREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] M_AXI_ARID;
|
|
|
|
wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR;
|
|
|
|
wire [C_AXI_LEN_WIDTH-1:0] M_AXI_ARLEN;
|
|
|
|
wire [3-1:0] M_AXI_ARSIZE;
|
|
|
|
wire [2-1:0] M_AXI_ARBURST;
|
|
|
|
wire [C_AXI_LOCK_WIDTH-1:0] M_AXI_ARLOCK;
|
|
|
|
wire [4-1:0] M_AXI_ARCACHE;
|
|
|
|
wire [3-1:0] M_AXI_ARPROT;
|
|
|
|
wire [4-1:0] M_AXI_ARQOS;
|
|
|
|
wire [4-1:0] M_AXI_ARREGION;
|
|
|
|
wire [C_AXI_ARUSER_WIDTH-1:0] M_AXI_ARUSER;
|
|
|
|
wire M_AXI_ARVALID;
|
|
|
|
wire M_AXI_ARREADY;
|
|
|
|
wire [C_AXI_ID_WIDTH-1:0] M_AXI_RID;
|
|
|
|
wire [C_AXI_DATA_WIDTH-1:0] M_AXI_RDATA;
|
|
|
|
wire [2-1:0] M_AXI_RRESP;
|
|
|
|
wire M_AXI_RLAST;
|
|
|
|
wire [C_AXI_RUSER_WIDTH-1:0] M_AXI_RUSER;
|
|
|
|
wire M_AXI_RVALID;
|
|
|
|
wire M_AXI_RREADY;
|
|
|
|
wire S_AXIS_TVALID;
|
|
|
|
wire S_AXIS_TREADY;
|
|
|
|
wire [C_AXIS_TDATA_WIDTH-1:0] S_AXIS_TDATA;
|
|
|
|
wire [C_AXIS_TSTRB_WIDTH-1:0] S_AXIS_TSTRB;
|
|
|
|
wire [C_AXIS_TKEEP_WIDTH-1:0] S_AXIS_TKEEP;
|
|
|
|
wire S_AXIS_TLAST;
|
|
|
|
wire [C_AXIS_TID_WIDTH-1:0] S_AXIS_TID;
|
|
|
|
wire [C_AXIS_TDEST_WIDTH-1:0] S_AXIS_TDEST;
|
|
|
|
wire [C_AXIS_TUSER_WIDTH-1:0] S_AXIS_TUSER;
|
|
|
|
wire M_AXIS_TVALID;
|
|
|
|
wire M_AXIS_TREADY;
|
|
|
|
wire [C_AXIS_TDATA_WIDTH-1:0] M_AXIS_TDATA;
|
|
|
|
wire [C_AXIS_TSTRB_WIDTH-1:0] M_AXIS_TSTRB;
|
|
|
|
wire [C_AXIS_TKEEP_WIDTH-1:0] M_AXIS_TKEEP;
|
|
|
|
wire M_AXIS_TLAST;
|
|
|
|
wire [C_AXIS_TID_WIDTH-1:0] M_AXIS_TID;
|
|
|
|
wire [C_AXIS_TDEST_WIDTH-1:0] M_AXIS_TDEST;
|
|
|
|
wire [C_AXIS_TUSER_WIDTH-1:0] M_AXIS_TUSER;
|
|
|
|
wire AXI_AW_INJECTSBITERR;
|
|
|
|
wire AXI_AW_INJECTDBITERR;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WACH-1:0] AXI_AW_PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WACH-1:0] AXI_AW_PROG_EMPTY_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WACH:0] AXI_AW_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WACH:0] AXI_AW_WR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WACH:0] AXI_AW_RD_DATA_COUNT;
|
|
|
|
wire AXI_AW_SBITERR;
|
|
|
|
wire AXI_AW_DBITERR;
|
|
|
|
wire AXI_AW_OVERFLOW;
|
|
|
|
wire AXI_AW_UNDERFLOW;
|
|
|
|
wire AXI_AW_PROG_FULL;
|
|
|
|
wire AXI_AW_PROG_EMPTY;
|
|
|
|
wire AXI_W_INJECTSBITERR;
|
|
|
|
wire AXI_W_INJECTDBITERR;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WDCH-1:0] AXI_W_PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WDCH-1:0] AXI_W_PROG_EMPTY_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WDCH:0] AXI_W_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WDCH:0] AXI_W_WR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WDCH:0] AXI_W_RD_DATA_COUNT;
|
|
|
|
wire AXI_W_SBITERR;
|
|
|
|
wire AXI_W_DBITERR;
|
|
|
|
wire AXI_W_OVERFLOW;
|
|
|
|
wire AXI_W_UNDERFLOW;
|
|
|
|
wire AXI_W_PROG_FULL;
|
|
|
|
wire AXI_W_PROG_EMPTY;
|
|
|
|
wire AXI_B_INJECTSBITERR;
|
|
|
|
wire AXI_B_INJECTDBITERR;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WRCH-1:0] AXI_B_PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WRCH-1:0] AXI_B_PROG_EMPTY_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WRCH:0] AXI_B_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WRCH:0] AXI_B_WR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_WRCH:0] AXI_B_RD_DATA_COUNT;
|
|
|
|
wire AXI_B_SBITERR;
|
|
|
|
wire AXI_B_DBITERR;
|
|
|
|
wire AXI_B_OVERFLOW;
|
|
|
|
wire AXI_B_UNDERFLOW;
|
|
|
|
wire AXI_B_PROG_FULL;
|
|
|
|
wire AXI_B_PROG_EMPTY;
|
|
|
|
wire AXI_AR_INJECTSBITERR;
|
|
|
|
wire AXI_AR_INJECTDBITERR;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RACH-1:0] AXI_AR_PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RACH-1:0] AXI_AR_PROG_EMPTY_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RACH:0] AXI_AR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RACH:0] AXI_AR_WR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RACH:0] AXI_AR_RD_DATA_COUNT;
|
|
|
|
wire AXI_AR_SBITERR;
|
|
|
|
wire AXI_AR_DBITERR;
|
|
|
|
wire AXI_AR_OVERFLOW;
|
|
|
|
wire AXI_AR_UNDERFLOW;
|
|
|
|
wire AXI_AR_PROG_FULL;
|
|
|
|
wire AXI_AR_PROG_EMPTY;
|
|
|
|
wire AXI_R_INJECTSBITERR;
|
|
|
|
wire AXI_R_INJECTDBITERR;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RDCH-1:0] AXI_R_PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RDCH-1:0] AXI_R_PROG_EMPTY_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RDCH:0] AXI_R_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RDCH:0] AXI_R_WR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_RDCH:0] AXI_R_RD_DATA_COUNT;
|
|
|
|
wire AXI_R_SBITERR;
|
|
|
|
wire AXI_R_DBITERR;
|
|
|
|
wire AXI_R_OVERFLOW;
|
|
|
|
wire AXI_R_UNDERFLOW;
|
|
|
|
wire AXI_R_PROG_FULL;
|
|
|
|
wire AXI_R_PROG_EMPTY;
|
|
|
|
wire AXIS_INJECTSBITERR;
|
|
|
|
wire AXIS_INJECTDBITERR;
|
|
|
|
wire [C_WR_PNTR_WIDTH_AXIS-1:0] AXIS_PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_AXIS-1:0] AXIS_PROG_EMPTY_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH_AXIS:0] AXIS_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_AXIS:0] AXIS_WR_DATA_COUNT;
|
|
|
|
wire [C_WR_PNTR_WIDTH_AXIS:0] AXIS_RD_DATA_COUNT;
|
|
|
|
wire AXIS_SBITERR;
|
|
|
|
wire AXIS_DBITERR;
|
|
|
|
wire AXIS_OVERFLOW;
|
|
|
|
wire AXIS_UNDERFLOW;
|
|
|
|
wire AXIS_PROG_FULL;
|
|
|
|
wire AXIS_PROG_EMPTY;
|
|
|
|
wire [C_WR_DATA_COUNT_WIDTH-1:0] wr_data_count_in;
|
|
|
|
wire wr_rst_int;
|
|
|
|
wire rd_rst_int;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function integer find_log2;
|
|
|
|
input integer int_val;
|
|
|
|
integer i,j;
|
|
|
|
begin
|
|
|
|
i = 1;
|
|
|
|
j = 0;
|
|
|
|
for (i = 1; i < int_val; i = i*2) begin
|
|
|
|
j = j + 1;
|
|
|
|
end
|
|
|
|
find_log2 = j;
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Conventional FIFO Interface Signals
|
|
|
|
assign BACKUP = backup;
|
|
|
|
assign BACKUP_MARKER = backup_marker;
|
|
|
|
assign CLK = clk;
|
|
|
|
assign RST = rst;
|
|
|
|
assign SRST = srst;
|
|
|
|
assign WR_CLK = wr_clk;
|
|
|
|
assign WR_RST = wr_rst;
|
|
|
|
assign RD_CLK = rd_clk;
|
|
|
|
assign RD_RST = rd_rst;
|
|
|
|
assign WR_EN = wr_en;
|
|
|
|
assign RD_EN = rd_en;
|
|
|
|
assign INT_CLK = int_clk;
|
|
|
|
assign INJECTDBITERR = injectdbiterr;
|
|
|
|
assign INJECTSBITERR = injectsbiterr;
|
|
|
|
assign SLEEP = sleep;
|
|
|
|
assign full = FULL;
|
|
|
|
assign almost_full = ALMOST_FULL;
|
|
|
|
assign wr_ack = WR_ACK;
|
|
|
|
assign overflow = OVERFLOW;
|
|
|
|
assign empty = EMPTY;
|
|
|
|
assign almost_empty = ALMOST_EMPTY;
|
|
|
|
assign valid = VALID;
|
|
|
|
assign underflow = UNDERFLOW;
|
|
|
|
assign prog_full = PROG_FULL;
|
|
|
|
assign prog_empty = PROG_EMPTY;
|
|
|
|
assign sbiterr = SBITERR;
|
|
|
|
assign dbiterr = DBITERR;
|
|
|
|
assign wr_rst_busy = WR_RST_BUSY;
|
|
|
|
assign rd_rst_busy = RD_RST_BUSY;
|
|
|
|
assign M_ACLK = m_aclk;
|
|
|
|
assign S_ACLK = s_aclk;
|
|
|
|
assign S_ARESETN = s_aresetn;
|
|
|
|
assign S_ACLK_EN = s_aclk_en;
|
|
|
|
assign M_ACLK_EN = m_aclk_en;
|
|
|
|
assign S_AXI_AWVALID = s_axi_awvalid;
|
|
|
|
assign s_axi_awready = S_AXI_AWREADY;
|
|
|
|
assign S_AXI_WLAST = s_axi_wlast;
|
|
|
|
assign S_AXI_WVALID = s_axi_wvalid;
|
|
|
|
assign s_axi_wready = S_AXI_WREADY;
|
|
|
|
assign s_axi_bvalid = S_AXI_BVALID;
|
|
|
|
assign S_AXI_BREADY = s_axi_bready;
|
|
|
|
assign m_axi_awvalid = M_AXI_AWVALID;
|
|
|
|
assign M_AXI_AWREADY = m_axi_awready;
|
|
|
|
assign m_axi_wlast = M_AXI_WLAST;
|
|
|
|
assign m_axi_wvalid = M_AXI_WVALID;
|
|
|
|
assign M_AXI_WREADY = m_axi_wready;
|
|
|
|
assign M_AXI_BVALID = m_axi_bvalid;
|
|
|
|
assign m_axi_bready = M_AXI_BREADY;
|
|
|
|
assign S_AXI_ARVALID = s_axi_arvalid;
|
|
|
|
assign s_axi_arready = S_AXI_ARREADY;
|
|
|
|
assign s_axi_rlast = S_AXI_RLAST;
|
|
|
|
assign s_axi_rvalid = S_AXI_RVALID;
|
|
|
|
assign S_AXI_RREADY = s_axi_rready;
|
|
|
|
assign m_axi_arvalid = M_AXI_ARVALID;
|
|
|
|
assign M_AXI_ARREADY = m_axi_arready;
|
|
|
|
assign M_AXI_RLAST = m_axi_rlast;
|
|
|
|
assign M_AXI_RVALID = m_axi_rvalid;
|
|
|
|
assign m_axi_rready = M_AXI_RREADY;
|
|
|
|
assign S_AXIS_TVALID = s_axis_tvalid;
|
|
|
|
assign s_axis_tready = S_AXIS_TREADY;
|
|
|
|
assign S_AXIS_TLAST = s_axis_tlast;
|
|
|
|
assign m_axis_tvalid = M_AXIS_TVALID;
|
|
|
|
assign M_AXIS_TREADY = m_axis_tready;
|
|
|
|
assign m_axis_tlast = M_AXIS_TLAST;
|
|
|
|
assign AXI_AW_INJECTSBITERR = axi_aw_injectsbiterr;
|
|
|
|
assign AXI_AW_INJECTDBITERR = axi_aw_injectdbiterr;
|
|
|
|
assign axi_aw_sbiterr = AXI_AW_SBITERR;
|
|
|
|
assign axi_aw_dbiterr = AXI_AW_DBITERR;
|
|
|
|
assign axi_aw_overflow = AXI_AW_OVERFLOW;
|
|
|
|
assign axi_aw_underflow = AXI_AW_UNDERFLOW;
|
|
|
|
assign axi_aw_prog_full = AXI_AW_PROG_FULL;
|
|
|
|
assign axi_aw_prog_empty = AXI_AW_PROG_EMPTY;
|
|
|
|
assign AXI_W_INJECTSBITERR = axi_w_injectsbiterr;
|
|
|
|
assign AXI_W_INJECTDBITERR = axi_w_injectdbiterr;
|
|
|
|
assign axi_w_sbiterr = AXI_W_SBITERR;
|
|
|
|
assign axi_w_dbiterr = AXI_W_DBITERR;
|
|
|
|
assign axi_w_overflow = AXI_W_OVERFLOW;
|
|
|
|
assign axi_w_underflow = AXI_W_UNDERFLOW;
|
|
|
|
assign axi_w_prog_full = AXI_W_PROG_FULL;
|
|
|
|
assign axi_w_prog_empty = AXI_W_PROG_EMPTY;
|
|
|
|
assign AXI_B_INJECTSBITERR = axi_b_injectsbiterr;
|
|
|
|
assign AXI_B_INJECTDBITERR = axi_b_injectdbiterr;
|
|
|
|
assign axi_b_sbiterr = AXI_B_SBITERR;
|
|
|
|
assign axi_b_dbiterr = AXI_B_DBITERR;
|
|
|
|
assign axi_b_overflow = AXI_B_OVERFLOW;
|
|
|
|
assign axi_b_underflow = AXI_B_UNDERFLOW;
|
|
|
|
assign axi_b_prog_full = AXI_B_PROG_FULL;
|
|
|
|
assign axi_b_prog_empty = AXI_B_PROG_EMPTY;
|
|
|
|
assign AXI_AR_INJECTSBITERR = axi_ar_injectsbiterr;
|
|
|
|
assign AXI_AR_INJECTDBITERR = axi_ar_injectdbiterr;
|
|
|
|
assign axi_ar_sbiterr = AXI_AR_SBITERR;
|
|
|
|
assign axi_ar_dbiterr = AXI_AR_DBITERR;
|
|
|
|
assign axi_ar_overflow = AXI_AR_OVERFLOW;
|
|
|
|
assign axi_ar_underflow = AXI_AR_UNDERFLOW;
|
|
|
|
assign axi_ar_prog_full = AXI_AR_PROG_FULL;
|
|
|
|
assign axi_ar_prog_empty = AXI_AR_PROG_EMPTY;
|
|
|
|
assign AXI_R_INJECTSBITERR = axi_r_injectsbiterr;
|
|
|
|
assign AXI_R_INJECTDBITERR = axi_r_injectdbiterr;
|
|
|
|
assign axi_r_sbiterr = AXI_R_SBITERR;
|
|
|
|
assign axi_r_dbiterr = AXI_R_DBITERR;
|
|
|
|
assign axi_r_overflow = AXI_R_OVERFLOW;
|
|
|
|
assign axi_r_underflow = AXI_R_UNDERFLOW;
|
|
|
|
assign axi_r_prog_full = AXI_R_PROG_FULL;
|
|
|
|
assign axi_r_prog_empty = AXI_R_PROG_EMPTY;
|
|
|
|
assign AXIS_INJECTSBITERR = axis_injectsbiterr;
|
|
|
|
assign AXIS_INJECTDBITERR = axis_injectdbiterr;
|
|
|
|
assign axis_sbiterr = AXIS_SBITERR;
|
|
|
|
assign axis_dbiterr = AXIS_DBITERR;
|
|
|
|
assign axis_overflow = AXIS_OVERFLOW;
|
|
|
|
assign axis_underflow = AXIS_UNDERFLOW;
|
|
|
|
assign axis_prog_full = AXIS_PROG_FULL;
|
|
|
|
assign axis_prog_empty = AXIS_PROG_EMPTY;
|
|
|
|
|
|
|
|
|
|
|
|
assign DIN = din;
|
|
|
|
assign PROG_EMPTY_THRESH = prog_empty_thresh;
|
|
|
|
assign PROG_EMPTY_THRESH_ASSERT = prog_empty_thresh_assert;
|
|
|
|
assign PROG_EMPTY_THRESH_NEGATE = prog_empty_thresh_negate;
|
|
|
|
assign PROG_FULL_THRESH = prog_full_thresh;
|
|
|
|
assign PROG_FULL_THRESH_ASSERT = prog_full_thresh_assert;
|
|
|
|
assign PROG_FULL_THRESH_NEGATE = prog_full_thresh_negate;
|
|
|
|
assign dout = DOUT;
|
|
|
|
assign data_count = DATA_COUNT;
|
|
|
|
assign rd_data_count = RD_DATA_COUNT;
|
|
|
|
assign wr_data_count = WR_DATA_COUNT;
|
|
|
|
assign S_AXI_AWID = s_axi_awid;
|
|
|
|
assign S_AXI_AWADDR = s_axi_awaddr;
|
|
|
|
assign S_AXI_AWLEN = s_axi_awlen;
|
|
|
|
assign S_AXI_AWSIZE = s_axi_awsize;
|
|
|
|
assign S_AXI_AWBURST = s_axi_awburst;
|
|
|
|
assign S_AXI_AWLOCK = s_axi_awlock;
|
|
|
|
assign S_AXI_AWCACHE = s_axi_awcache;
|
|
|
|
assign S_AXI_AWPROT = s_axi_awprot;
|
|
|
|
assign S_AXI_AWQOS = s_axi_awqos;
|
|
|
|
assign S_AXI_AWREGION = s_axi_awregion;
|
|
|
|
assign S_AXI_AWUSER = s_axi_awuser;
|
|
|
|
assign S_AXI_WID = s_axi_wid;
|
|
|
|
assign S_AXI_WDATA = s_axi_wdata;
|
|
|
|
assign S_AXI_WSTRB = s_axi_wstrb;
|
|
|
|
assign S_AXI_WUSER = s_axi_wuser;
|
|
|
|
assign s_axi_bid = S_AXI_BID;
|
|
|
|
assign s_axi_bresp = S_AXI_BRESP;
|
|
|
|
assign s_axi_buser = S_AXI_BUSER;
|
|
|
|
assign m_axi_awid = M_AXI_AWID;
|
|
|
|
assign m_axi_awaddr = M_AXI_AWADDR;
|
|
|
|
assign m_axi_awlen = M_AXI_AWLEN;
|
|
|
|
assign m_axi_awsize = M_AXI_AWSIZE;
|
|
|
|
assign m_axi_awburst = M_AXI_AWBURST;
|
|
|
|
assign m_axi_awlock = M_AXI_AWLOCK;
|
|
|
|
assign m_axi_awcache = M_AXI_AWCACHE;
|
|
|
|
assign m_axi_awprot = M_AXI_AWPROT;
|
|
|
|
assign m_axi_awqos = M_AXI_AWQOS;
|
|
|
|
assign m_axi_awregion = M_AXI_AWREGION;
|
|
|
|
assign m_axi_awuser = M_AXI_AWUSER;
|
|
|
|
assign m_axi_wid = M_AXI_WID;
|
|
|
|
assign m_axi_wdata = M_AXI_WDATA;
|
|
|
|
assign m_axi_wstrb = M_AXI_WSTRB;
|
|
|
|
assign m_axi_wuser = M_AXI_WUSER;
|
|
|
|
assign M_AXI_BID = m_axi_bid;
|
|
|
|
assign M_AXI_BRESP = m_axi_bresp;
|
|
|
|
assign M_AXI_BUSER = m_axi_buser;
|
|
|
|
assign S_AXI_ARID = s_axi_arid;
|
|
|
|
assign S_AXI_ARADDR = s_axi_araddr;
|
|
|
|
assign S_AXI_ARLEN = s_axi_arlen;
|
|
|
|
assign S_AXI_ARSIZE = s_axi_arsize;
|
|
|
|
assign S_AXI_ARBURST = s_axi_arburst;
|
|
|
|
assign S_AXI_ARLOCK = s_axi_arlock;
|
|
|
|
assign S_AXI_ARCACHE = s_axi_arcache;
|
|
|
|
assign S_AXI_ARPROT = s_axi_arprot;
|
|
|
|
assign S_AXI_ARQOS = s_axi_arqos;
|
|
|
|
assign S_AXI_ARREGION = s_axi_arregion;
|
|
|
|
assign S_AXI_ARUSER = s_axi_aruser;
|
|
|
|
assign s_axi_rid = S_AXI_RID;
|
|
|
|
assign s_axi_rdata = S_AXI_RDATA;
|
|
|
|
assign s_axi_rresp = S_AXI_RRESP;
|
|
|
|
assign s_axi_ruser = S_AXI_RUSER;
|
|
|
|
assign m_axi_arid = M_AXI_ARID;
|
|
|
|
assign m_axi_araddr = M_AXI_ARADDR;
|
|
|
|
assign m_axi_arlen = M_AXI_ARLEN;
|
|
|
|
assign m_axi_arsize = M_AXI_ARSIZE;
|
|
|
|
assign m_axi_arburst = M_AXI_ARBURST;
|
|
|
|
assign m_axi_arlock = M_AXI_ARLOCK;
|
|
|
|
assign m_axi_arcache = M_AXI_ARCACHE;
|
|
|
|
assign m_axi_arprot = M_AXI_ARPROT;
|
|
|
|
assign m_axi_arqos = M_AXI_ARQOS;
|
|
|
|
assign m_axi_arregion = M_AXI_ARREGION;
|
|
|
|
assign m_axi_aruser = M_AXI_ARUSER;
|
|
|
|
assign M_AXI_RID = m_axi_rid;
|
|
|
|
assign M_AXI_RDATA = m_axi_rdata;
|
|
|
|
assign M_AXI_RRESP = m_axi_rresp;
|
|
|
|
assign M_AXI_RUSER = m_axi_ruser;
|
|
|
|
assign S_AXIS_TDATA = s_axis_tdata;
|
|
|
|
assign S_AXIS_TSTRB = s_axis_tstrb;
|
|
|
|
assign S_AXIS_TKEEP = s_axis_tkeep;
|
|
|
|
assign S_AXIS_TID = s_axis_tid;
|
|
|
|
assign S_AXIS_TDEST = s_axis_tdest;
|
|
|
|
assign S_AXIS_TUSER = s_axis_tuser;
|
|
|
|
assign m_axis_tdata = M_AXIS_TDATA;
|
|
|
|
assign m_axis_tstrb = M_AXIS_TSTRB;
|
|
|
|
assign m_axis_tkeep = M_AXIS_TKEEP;
|
|
|
|
assign m_axis_tid = M_AXIS_TID;
|
|
|
|
assign m_axis_tdest = M_AXIS_TDEST;
|
|
|
|
assign m_axis_tuser = M_AXIS_TUSER;
|
|
|
|
assign AXI_AW_PROG_FULL_THRESH = axi_aw_prog_full_thresh;
|
|
|
|
assign AXI_AW_PROG_EMPTY_THRESH = axi_aw_prog_empty_thresh;
|
|
|
|
assign axi_aw_data_count = AXI_AW_DATA_COUNT;
|
|
|
|
assign axi_aw_wr_data_count = AXI_AW_WR_DATA_COUNT;
|
|
|
|
assign axi_aw_rd_data_count = AXI_AW_RD_DATA_COUNT;
|
|
|
|
assign AXI_W_PROG_FULL_THRESH = axi_w_prog_full_thresh;
|
|
|
|
assign AXI_W_PROG_EMPTY_THRESH = axi_w_prog_empty_thresh;
|
|
|
|
assign axi_w_data_count = AXI_W_DATA_COUNT;
|
|
|
|
assign axi_w_wr_data_count = AXI_W_WR_DATA_COUNT;
|
|
|
|
assign axi_w_rd_data_count = AXI_W_RD_DATA_COUNT;
|
|
|
|
assign AXI_B_PROG_FULL_THRESH = axi_b_prog_full_thresh;
|
|
|
|
assign AXI_B_PROG_EMPTY_THRESH = axi_b_prog_empty_thresh;
|
|
|
|
assign axi_b_data_count = AXI_B_DATA_COUNT;
|
|
|
|
assign axi_b_wr_data_count = AXI_B_WR_DATA_COUNT;
|
|
|
|
assign axi_b_rd_data_count = AXI_B_RD_DATA_COUNT;
|
|
|
|
assign AXI_AR_PROG_FULL_THRESH = axi_ar_prog_full_thresh;
|
|
|
|
assign AXI_AR_PROG_EMPTY_THRESH = axi_ar_prog_empty_thresh;
|
|
|
|
assign axi_ar_data_count = AXI_AR_DATA_COUNT;
|
|
|
|
assign axi_ar_wr_data_count = AXI_AR_WR_DATA_COUNT;
|
|
|
|
assign axi_ar_rd_data_count = AXI_AR_RD_DATA_COUNT;
|
|
|
|
assign AXI_R_PROG_FULL_THRESH = axi_r_prog_full_thresh;
|
|
|
|
assign AXI_R_PROG_EMPTY_THRESH = axi_r_prog_empty_thresh;
|
|
|
|
assign axi_r_data_count = AXI_R_DATA_COUNT;
|
|
|
|
assign axi_r_wr_data_count = AXI_R_WR_DATA_COUNT;
|
|
|
|
assign axi_r_rd_data_count = AXI_R_RD_DATA_COUNT;
|
|
|
|
assign AXIS_PROG_FULL_THRESH = axis_prog_full_thresh;
|
|
|
|
assign AXIS_PROG_EMPTY_THRESH = axis_prog_empty_thresh;
|
|
|
|
assign axis_data_count = AXIS_DATA_COUNT;
|
|
|
|
assign axis_wr_data_count = AXIS_WR_DATA_COUNT;
|
|
|
|
assign axis_rd_data_count = AXIS_RD_DATA_COUNT;
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_INTERFACE_TYPE == 0) begin : conv_fifo
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_DATA_COUNT_WIDTH),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH),
|
|
|
|
.C_DOUT_RST_VAL (C_USE_DOUT_RST == 1 ? C_DOUT_RST_VAL : 0),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (C_FULL_FLAGS_RST_VAL),
|
|
|
|
.C_HAS_ALMOST_EMPTY (C_HAS_ALMOST_EMPTY),
|
|
|
|
.C_HAS_ALMOST_FULL (C_HAS_ALMOST_FULL),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_DATA_COUNT (C_HAS_DATA_COUNT),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_HAS_RD_DATA_COUNT (C_HAS_RD_DATA_COUNT),
|
|
|
|
.C_HAS_RD_RST (C_HAS_RD_RST),
|
|
|
|
.C_HAS_RST (C_HAS_RST),
|
|
|
|
.C_HAS_SRST (C_HAS_SRST),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_HAS_VALID (C_HAS_VALID),
|
|
|
|
.C_HAS_WR_ACK (C_HAS_WR_ACK),
|
|
|
|
.C_HAS_WR_DATA_COUNT (C_HAS_WR_DATA_COUNT),
|
|
|
|
.C_HAS_WR_RST (C_HAS_WR_RST),
|
|
|
|
.C_IMPLEMENTATION_TYPE (C_IMPLEMENTATION_TYPE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_MEMORY_TYPE (C_MEMORY_TYPE),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
.C_PRELOAD_LATENCY (C_PRELOAD_LATENCY),
|
|
|
|
.C_PRELOAD_REGS (C_PRELOAD_REGS),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_EMPTY_THRESH_NEGATE_VAL (C_PROG_EMPTY_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_FULL_THRESH_NEGATE_VAL (C_PROG_FULL_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_RD_DATA_COUNT_WIDTH),
|
|
|
|
.C_RD_DEPTH (C_RD_DEPTH),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_RD_PNTR_WIDTH (C_RD_PNTR_WIDTH),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_USE_ECC (C_USE_ECC),
|
|
|
|
.C_USE_EMBEDDED_REG (C_USE_EMBEDDED_REG),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (C_USE_FWFT_DATA_COUNT),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_DATA_COUNT_WIDTH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (C_ENABLE_RST_SYNC),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE),
|
|
|
|
.C_AXI_TYPE (C_AXI_TYPE),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_conv_dut
|
|
|
|
(
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST (RST),
|
|
|
|
.SRST (SRST),
|
|
|
|
.WR_CLK (WR_CLK),
|
|
|
|
.WR_RST (WR_RST),
|
|
|
|
.RD_CLK (RD_CLK),
|
|
|
|
.RD_RST (RD_RST),
|
|
|
|
.DIN (DIN),
|
|
|
|
.WR_EN (WR_EN),
|
|
|
|
.RD_EN (RD_EN),
|
|
|
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT (PROG_EMPTY_THRESH_ASSERT),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE (PROG_EMPTY_THRESH_NEGATE),
|
|
|
|
.PROG_FULL_THRESH (PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT (PROG_FULL_THRESH_ASSERT),
|
|
|
|
.PROG_FULL_THRESH_NEGATE (PROG_FULL_THRESH_NEGATE),
|
|
|
|
.INT_CLK (INT_CLK),
|
|
|
|
.INJECTDBITERR (INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (INJECTSBITERR),
|
|
|
|
|
|
|
|
.DOUT (DOUT),
|
|
|
|
.FULL (FULL),
|
|
|
|
.ALMOST_FULL (ALMOST_FULL),
|
|
|
|
.WR_ACK (WR_ACK),
|
|
|
|
.OVERFLOW (OVERFLOW),
|
|
|
|
.EMPTY (EMPTY),
|
|
|
|
.ALMOST_EMPTY (ALMOST_EMPTY),
|
|
|
|
.VALID (VALID),
|
|
|
|
.UNDERFLOW (UNDERFLOW),
|
|
|
|
.DATA_COUNT (DATA_COUNT),
|
|
|
|
.RD_DATA_COUNT (RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (wr_data_count_in),
|
|
|
|
.PROG_FULL (PROG_FULL),
|
|
|
|
.PROG_EMPTY (PROG_EMPTY),
|
|
|
|
.SBITERR (SBITERR),
|
|
|
|
.DBITERR (DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy),
|
|
|
|
.rd_rst_busy (rd_rst_busy),
|
|
|
|
.wr_rst_i_out (wr_rst_int),
|
|
|
|
.rd_rst_i_out (rd_rst_int)
|
|
|
|
);
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
localparam IS_8SERIES = (C_FAMILY == "virtexu" || C_FAMILY == "kintexu" || C_FAMILY == "artixu" || C_FAMILY == "virtexum" || C_FAMILY == "zynque") ? 1 : 0;
|
|
|
|
localparam C_AXI_SIZE_WIDTH = 3;
|
|
|
|
localparam C_AXI_BURST_WIDTH = 2;
|
|
|
|
localparam C_AXI_CACHE_WIDTH = 4;
|
|
|
|
localparam C_AXI_PROT_WIDTH = 3;
|
|
|
|
localparam C_AXI_QOS_WIDTH = 4;
|
|
|
|
localparam C_AXI_REGION_WIDTH = 4;
|
|
|
|
localparam C_AXI_BRESP_WIDTH = 2;
|
|
|
|
localparam C_AXI_RRESP_WIDTH = 2;
|
|
|
|
|
|
|
|
localparam IS_AXI_STREAMING = C_INTERFACE_TYPE == 1 ? 1 : 0;
|
|
|
|
localparam TDATA_OFFSET = C_HAS_AXIS_TDATA == 1 ? C_DIN_WIDTH_AXIS-C_AXIS_TDATA_WIDTH : C_DIN_WIDTH_AXIS;
|
|
|
|
localparam TSTRB_OFFSET = C_HAS_AXIS_TSTRB == 1 ? TDATA_OFFSET-C_AXIS_TSTRB_WIDTH : TDATA_OFFSET;
|
|
|
|
localparam TKEEP_OFFSET = C_HAS_AXIS_TKEEP == 1 ? TSTRB_OFFSET-C_AXIS_TKEEP_WIDTH : TSTRB_OFFSET;
|
|
|
|
localparam TID_OFFSET = C_HAS_AXIS_TID == 1 ? TKEEP_OFFSET-C_AXIS_TID_WIDTH : TKEEP_OFFSET;
|
|
|
|
localparam TDEST_OFFSET = C_HAS_AXIS_TDEST == 1 ? TID_OFFSET-C_AXIS_TDEST_WIDTH : TID_OFFSET;
|
|
|
|
localparam TUSER_OFFSET = C_HAS_AXIS_TUSER == 1 ? TDEST_OFFSET-C_AXIS_TUSER_WIDTH : TDEST_OFFSET;
|
|
|
|
localparam LOG_DEPTH_AXIS = find_log2(C_WR_DEPTH_AXIS);
|
|
|
|
localparam LOG_WR_DEPTH = find_log2(C_WR_DEPTH);
|
|
|
|
|
|
|
|
|
|
|
|
function [LOG_DEPTH_AXIS-1:0] bin2gray;
|
|
|
|
input [LOG_DEPTH_AXIS-1:0] x;
|
|
|
|
begin
|
|
|
|
bin2gray = x ^ (x>>1);
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function [LOG_DEPTH_AXIS-1:0] gray2bin;
|
|
|
|
input [LOG_DEPTH_AXIS-1:0] x;
|
|
|
|
integer i;
|
|
|
|
begin
|
|
|
|
gray2bin[LOG_DEPTH_AXIS-1] = x[LOG_DEPTH_AXIS-1];
|
|
|
|
for(i=LOG_DEPTH_AXIS-2; i>=0; i=i-1) begin
|
|
|
|
gray2bin[i] = gray2bin[i+1] ^ x[i];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
wire [(LOG_WR_DEPTH)-1 : 0] w_cnt_gc_asreg_last;
|
|
|
|
wire [LOG_WR_DEPTH-1 : 0] w_q [0:C_SYNCHRONIZER_STAGE] ;
|
|
|
|
wire [LOG_WR_DEPTH-1 : 0] w_q_temp [1:C_SYNCHRONIZER_STAGE] ;
|
|
|
|
reg [LOG_WR_DEPTH-1 : 0] w_cnt_rd = 0;
|
|
|
|
reg [LOG_WR_DEPTH-1 : 0] w_cnt = 0;
|
|
|
|
reg [LOG_WR_DEPTH-1 : 0] w_cnt_gc = 0;
|
|
|
|
reg [LOG_WR_DEPTH-1 : 0] r_cnt = 0;
|
|
|
|
wire [LOG_WR_DEPTH : 0] adj_w_cnt_rd_pad;
|
|
|
|
wire [LOG_WR_DEPTH : 0] r_inv_pad;
|
|
|
|
wire [LOG_WR_DEPTH-1 : 0] d_cnt;
|
|
|
|
reg [LOG_WR_DEPTH : 0] d_cnt_pad = 0;
|
|
|
|
reg adj_w_cnt_rd_pad_0 = 0;
|
|
|
|
reg r_inv_pad_0 = 0;
|
|
|
|
|
|
|
|
|
|
|
|
genvar l;
|
|
|
|
|
|
|
|
generate for (l = 1; ((l <= C_SYNCHRONIZER_STAGE) && (C_HAS_DATA_COUNTS_AXIS == 3 && C_INTERFACE_TYPE == 0) ); l = l + 1) begin : g_cnt_sync_stage
|
|
|
|
fifo_generator_v12_0_sync_stage
|
|
|
|
#(
|
|
|
|
.C_WIDTH (LOG_WR_DEPTH)
|
|
|
|
)
|
|
|
|
rd_stg_inst
|
|
|
|
(
|
|
|
|
.RST (rd_rst_int),
|
|
|
|
.CLK (RD_CLK),
|
|
|
|
.DIN (w_q[l-1]),
|
|
|
|
.DOUT (w_q[l])
|
|
|
|
);
|
|
|
|
end endgenerate // gpkt_cnt_sync_stage
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-11-13 16:25:38 -05:00
|
|
|
generate if (C_INTERFACE_TYPE == 0 && C_HAS_DATA_COUNTS_AXIS == 3) begin : fifo_ic_adapter
|
2015-11-12 09:57:55 -05:00
|
|
|
assign wr_eop_ad = WR_EN & !(FULL);
|
|
|
|
assign rd_eop_ad = RD_EN & !(EMPTY);
|
|
|
|
|
|
|
|
|
|
|
|
always @ (posedge wr_rst_int or posedge WR_CLK)
|
|
|
|
begin
|
|
|
|
if (wr_rst_int)
|
|
|
|
w_cnt <= 1'b0;
|
|
|
|
else if (wr_eop_ad)
|
|
|
|
w_cnt <= w_cnt + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge wr_rst_int or posedge WR_CLK)
|
|
|
|
begin
|
|
|
|
if (wr_rst_int)
|
|
|
|
w_cnt_gc <= 1'b0;
|
|
|
|
else
|
|
|
|
w_cnt_gc <= bin2gray(w_cnt);
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
assign w_q[0] = w_cnt_gc;
|
|
|
|
assign w_cnt_gc_asreg_last = w_q[C_SYNCHRONIZER_STAGE];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
always @ (posedge rd_rst_int or posedge RD_CLK)
|
|
|
|
begin
|
|
|
|
if (rd_rst_int)
|
|
|
|
w_cnt_rd <= 1'b0;
|
|
|
|
else
|
|
|
|
w_cnt_rd <= gray2bin(w_cnt_gc_asreg_last);
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge rd_rst_int or posedge RD_CLK)
|
|
|
|
begin
|
|
|
|
if (rd_rst_int)
|
|
|
|
r_cnt <= 1'b0;
|
|
|
|
else if (rd_eop_ad)
|
|
|
|
r_cnt <= r_cnt + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
// Take the difference of write and read packet count
|
|
|
|
// Logic is similar to rd_pe_as
|
|
|
|
assign adj_w_cnt_rd_pad[LOG_WR_DEPTH : 1] = w_cnt_rd;
|
|
|
|
assign r_inv_pad[LOG_WR_DEPTH : 1] = ~r_cnt;
|
|
|
|
assign adj_w_cnt_rd_pad[0] = adj_w_cnt_rd_pad_0;
|
|
|
|
assign r_inv_pad[0] = r_inv_pad_0;
|
|
|
|
|
|
|
|
|
|
|
|
always @ ( rd_eop_ad )
|
|
|
|
begin
|
|
|
|
if (!rd_eop_ad) begin
|
|
|
|
adj_w_cnt_rd_pad_0 <= 1'b1;
|
|
|
|
r_inv_pad_0 <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
adj_w_cnt_rd_pad_0 <= 1'b0;
|
|
|
|
r_inv_pad_0 <= 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge rd_rst_int or posedge RD_CLK)
|
|
|
|
begin
|
|
|
|
if (rd_rst_int)
|
|
|
|
d_cnt_pad <= 1'b0;
|
|
|
|
else
|
|
|
|
d_cnt_pad <= adj_w_cnt_rd_pad + r_inv_pad ;
|
|
|
|
end
|
|
|
|
|
|
|
|
assign d_cnt = d_cnt_pad [LOG_WR_DEPTH : 1] ;
|
|
|
|
assign WR_DATA_COUNT = d_cnt;
|
|
|
|
|
|
|
|
end endgenerate // fifo_ic_adapter
|
|
|
|
|
|
|
|
generate if (C_INTERFACE_TYPE == 0 && C_HAS_DATA_COUNTS_AXIS != 3) begin : fifo_icn_adapter
|
|
|
|
assign WR_DATA_COUNT = wr_data_count_in;
|
|
|
|
|
|
|
|
end endgenerate // fifo_icn_adapter
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wire inverted_reset = ~S_ARESETN;
|
|
|
|
wire axi_rs_rst;
|
|
|
|
reg rst_d1 = 0 ;
|
|
|
|
reg rst_d2 = 0 ;
|
|
|
|
wire [C_DIN_WIDTH_AXIS-1:0] axis_din ;
|
|
|
|
wire [C_DIN_WIDTH_AXIS-1:0] axis_dout ;
|
|
|
|
wire axis_full ;
|
|
|
|
wire axis_almost_full ;
|
|
|
|
wire axis_empty ;
|
|
|
|
wire axis_s_axis_tready;
|
|
|
|
wire axis_m_axis_tvalid;
|
|
|
|
wire axis_wr_en ;
|
|
|
|
wire axis_rd_en ;
|
|
|
|
wire axis_we ;
|
|
|
|
wire axis_re ;
|
|
|
|
wire [C_WR_PNTR_WIDTH_AXIS:0] axis_dc;
|
|
|
|
reg axis_pkt_read = 1'b0;
|
|
|
|
wire axis_rd_rst;
|
|
|
|
wire axis_wr_rst;
|
|
|
|
|
|
|
|
generate if (C_INTERFACE_TYPE > 0 && (C_AXIS_TYPE == 1 || C_WACH_TYPE == 1 ||
|
|
|
|
C_WDCH_TYPE == 1 || C_WRCH_TYPE == 1 || C_RACH_TYPE == 1 || C_RDCH_TYPE == 1)) begin : gaxi_rs_rst
|
|
|
|
always @ (posedge inverted_reset or posedge S_ACLK) begin
|
|
|
|
if (inverted_reset) begin
|
|
|
|
rst_d1 <= 1'b1;
|
|
|
|
rst_d2 <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
rst_d1 <= #`TCQ 1'b0;
|
|
|
|
rst_d2 <= #`TCQ rst_d1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assign axi_rs_rst = rst_d2;
|
|
|
|
end endgenerate // gaxi_rs_rst
|
|
|
|
|
|
|
|
generate if (IS_AXI_STREAMING == 1 && C_AXIS_TYPE == 0) begin : axi_streaming
|
|
|
|
|
|
|
|
// Write protection when almost full or prog_full is high
|
|
|
|
assign axis_we = (C_PROG_FULL_TYPE_AXIS != 0) ? axis_s_axis_tready & S_AXIS_TVALID :
|
|
|
|
(C_APPLICATION_TYPE_AXIS == 1) ? axis_s_axis_tready & S_AXIS_TVALID : S_AXIS_TVALID;
|
|
|
|
|
|
|
|
// Read protection when almost empty or prog_empty is high
|
|
|
|
assign axis_re = (C_PROG_EMPTY_TYPE_AXIS != 0) ? axis_m_axis_tvalid & M_AXIS_TREADY :
|
|
|
|
(C_APPLICATION_TYPE_AXIS == 1) ? axis_m_axis_tvalid & M_AXIS_TREADY : M_AXIS_TREADY;
|
|
|
|
assign axis_wr_en = (C_HAS_SLAVE_CE == 1) ? axis_we & S_ACLK_EN : axis_we;
|
|
|
|
assign axis_rd_en = (C_HAS_MASTER_CE == 1) ? axis_re & M_ACLK_EN : axis_re;
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_MEMORY_TYPE ((C_IMPLEMENTATION_TYPE_AXIS == 1 || C_IMPLEMENTATION_TYPE_AXIS == 11) ? 1 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_AXIS == 2 || C_IMPLEMENTATION_TYPE_AXIS == 12) ? 2 : 4),
|
|
|
|
.C_IMPLEMENTATION_TYPE ((C_IMPLEMENTATION_TYPE_AXIS == 1 || C_IMPLEMENTATION_TYPE_AXIS == 2) ? 0 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_AXIS == 11 || C_IMPLEMENTATION_TYPE_AXIS == 12) ? 2 : 6),
|
|
|
|
.C_PRELOAD_REGS (1), // always FWFT for AXI
|
|
|
|
.C_PRELOAD_LATENCY (0), // always FWFT for AXI
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH_AXIS),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH_AXIS),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH_AXIS),
|
|
|
|
.C_DOUT_WIDTH (C_DIN_WIDTH_AXIS),
|
|
|
|
.C_RD_DEPTH (C_WR_DEPTH_AXIS),
|
|
|
|
.C_RD_PNTR_WIDTH (C_WR_PNTR_WIDTH_AXIS),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE_AXIS),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL_AXIS),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE_AXIS),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL_AXIS),
|
|
|
|
.C_USE_ECC (C_USE_ECC_AXIS),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE_AXIS),
|
|
|
|
.C_HAS_ALMOST_EMPTY (0),
|
|
|
|
.C_HAS_ALMOST_FULL (C_APPLICATION_TYPE_AXIS == 1 ? 1: 0),
|
|
|
|
.C_AXI_TYPE (C_INTERFACE_TYPE == 1 ? 0 : C_AXI_TYPE),
|
|
|
|
.C_USE_EMBEDDED_REG (C_USE_EMBEDDED_REG),
|
|
|
|
|
|
|
|
.C_FIFO_TYPE (C_APPLICATION_TYPE_AXIS == 1 ? 0: C_APPLICATION_TYPE_AXIS),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
|
|
|
|
.C_HAS_WR_RST (0),
|
|
|
|
.C_HAS_RD_RST (0),
|
|
|
|
.C_HAS_RST (1),
|
|
|
|
.C_HAS_SRST (0),
|
|
|
|
.C_DOUT_RST_VAL (0),
|
|
|
|
|
|
|
|
.C_HAS_VALID (0),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_HAS_WR_ACK (0),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
|
|
|
|
.C_HAS_DATA_COUNT ((C_COMMON_CLOCK == 1 && C_HAS_DATA_COUNTS_AXIS == 1) ? 1 : 0),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_AXIS + 1),
|
|
|
|
.C_HAS_RD_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_AXIS == 1) ? 1 : 0),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_AXIS + 1),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (1), // use extra logic is always true
|
|
|
|
.C_HAS_WR_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_AXIS == 1) ? 1 : 0),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_AXIS + 1),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (1),
|
|
|
|
.C_USE_DOUT_RST (0),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (1),
|
|
|
|
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_axis_dut
|
|
|
|
(
|
|
|
|
.CLK (S_ACLK),
|
|
|
|
.WR_CLK (S_ACLK),
|
|
|
|
.RD_CLK (M_ACLK),
|
|
|
|
.RST (inverted_reset),
|
|
|
|
.SRST (1'b0),
|
|
|
|
.WR_RST (inverted_reset),
|
|
|
|
.RD_RST (inverted_reset),
|
|
|
|
.WR_EN (axis_wr_en),
|
|
|
|
.RD_EN (axis_rd_en),
|
|
|
|
.PROG_FULL_THRESH (AXIS_PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT ({C_WR_PNTR_WIDTH_AXIS{1'b0}}),
|
|
|
|
.PROG_FULL_THRESH_NEGATE ({C_WR_PNTR_WIDTH_AXIS{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH (AXIS_PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT ({C_WR_PNTR_WIDTH_AXIS{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE ({C_WR_PNTR_WIDTH_AXIS{1'b0}}),
|
|
|
|
.INJECTDBITERR (AXIS_INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (AXIS_INJECTSBITERR),
|
|
|
|
|
|
|
|
.DIN (axis_din),
|
|
|
|
.DOUT (axis_dout),
|
|
|
|
.FULL (axis_full),
|
|
|
|
.EMPTY (axis_empty),
|
|
|
|
.ALMOST_FULL (axis_almost_full),
|
|
|
|
.PROG_FULL (AXIS_PROG_FULL),
|
|
|
|
.ALMOST_EMPTY (),
|
|
|
|
.PROG_EMPTY (AXIS_PROG_EMPTY),
|
|
|
|
|
|
|
|
.WR_ACK (),
|
|
|
|
.OVERFLOW (AXIS_OVERFLOW),
|
|
|
|
.VALID (),
|
|
|
|
.UNDERFLOW (AXIS_UNDERFLOW),
|
|
|
|
.DATA_COUNT (axis_dc),
|
|
|
|
.RD_DATA_COUNT (AXIS_RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (AXIS_WR_DATA_COUNT),
|
|
|
|
.SBITERR (AXIS_SBITERR),
|
|
|
|
.DBITERR (AXIS_DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy_axis),
|
|
|
|
.rd_rst_busy (rd_rst_busy_axis),
|
|
|
|
.wr_rst_i_out (axis_wr_rst),
|
|
|
|
.rd_rst_i_out (axis_rd_rst),
|
|
|
|
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.INT_CLK (INT_CLK)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign axis_s_axis_tready = (IS_8SERIES == 0) ? ~axis_full : (C_IMPLEMENTATION_TYPE_AXIS == 5 || C_IMPLEMENTATION_TYPE_AXIS == 13) ? ~(axis_full | wr_rst_busy_axis) : ~axis_full;
|
|
|
|
assign axis_m_axis_tvalid = (C_APPLICATION_TYPE_AXIS != 1) ? ~axis_empty : ~axis_empty & axis_pkt_read;
|
|
|
|
assign S_AXIS_TREADY = axis_s_axis_tready;
|
|
|
|
assign M_AXIS_TVALID = axis_m_axis_tvalid;
|
|
|
|
|
|
|
|
end endgenerate // axi_streaming
|
|
|
|
|
|
|
|
wire axis_wr_eop;
|
|
|
|
reg axis_wr_eop_d1 = 1'b0;
|
|
|
|
wire axis_rd_eop;
|
|
|
|
integer axis_pkt_cnt;
|
|
|
|
|
|
|
|
generate if (C_APPLICATION_TYPE_AXIS == 1 && C_COMMON_CLOCK == 1) begin : gaxis_pkt_fifo_cc
|
|
|
|
assign axis_wr_eop = axis_wr_en & S_AXIS_TLAST;
|
|
|
|
assign axis_rd_eop = axis_rd_en & axis_dout[0];
|
|
|
|
|
|
|
|
always @ (posedge inverted_reset or posedge S_ACLK)
|
|
|
|
begin
|
|
|
|
if (inverted_reset)
|
|
|
|
axis_pkt_read <= 1'b0;
|
|
|
|
else if (axis_rd_eop && (axis_pkt_cnt == 1) && ~axis_wr_eop_d1)
|
|
|
|
axis_pkt_read <= 1'b0;
|
|
|
|
else if ((axis_pkt_cnt > 0) || (axis_almost_full && ~axis_empty))
|
|
|
|
axis_pkt_read <= 1'b1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge inverted_reset or posedge S_ACLK)
|
|
|
|
begin
|
|
|
|
if (inverted_reset)
|
|
|
|
axis_wr_eop_d1 <= 1'b0;
|
|
|
|
else
|
|
|
|
axis_wr_eop_d1 <= axis_wr_eop;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge inverted_reset or posedge S_ACLK)
|
|
|
|
begin
|
|
|
|
if (inverted_reset)
|
|
|
|
axis_pkt_cnt <= 0;
|
|
|
|
else if (axis_wr_eop_d1 && ~axis_rd_eop)
|
|
|
|
axis_pkt_cnt <= axis_pkt_cnt + 1;
|
|
|
|
else if (axis_rd_eop && ~axis_wr_eop_d1)
|
|
|
|
axis_pkt_cnt <= axis_pkt_cnt - 1;
|
|
|
|
end
|
|
|
|
end endgenerate // gaxis_pkt_fifo_cc
|
|
|
|
|
|
|
|
|
|
|
|
reg [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt_gc = 0;
|
|
|
|
wire [(LOG_DEPTH_AXIS)-1 : 0] axis_wpkt_cnt_gc_asreg_last;
|
|
|
|
wire axis_rd_has_rst;
|
|
|
|
wire [0:C_SYNCHRONIZER_STAGE] axis_af_q ;
|
|
|
|
wire [LOG_DEPTH_AXIS-1 : 0] wpkt_q [0:C_SYNCHRONIZER_STAGE] ;
|
|
|
|
wire [1:C_SYNCHRONIZER_STAGE] axis_af_q_temp = 0;
|
|
|
|
wire [LOG_DEPTH_AXIS-1 : 0] wpkt_q_temp [1:C_SYNCHRONIZER_STAGE] ;
|
|
|
|
reg [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt_rd = 0;
|
|
|
|
reg [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt = 0;
|
|
|
|
reg [LOG_DEPTH_AXIS-1 : 0] axis_rpkt_cnt = 0;
|
|
|
|
wire [LOG_DEPTH_AXIS : 0] adj_axis_wpkt_cnt_rd_pad;
|
|
|
|
wire [LOG_DEPTH_AXIS : 0] rpkt_inv_pad;
|
|
|
|
wire [LOG_DEPTH_AXIS-1 : 0] diff_pkt_cnt;
|
|
|
|
reg [LOG_DEPTH_AXIS : 0] diff_pkt_cnt_pad = 0;
|
|
|
|
reg adj_axis_wpkt_cnt_rd_pad_0 = 0;
|
|
|
|
reg rpkt_inv_pad_0 = 0;
|
|
|
|
wire axis_af_rd ;
|
|
|
|
|
|
|
|
generate if (C_HAS_RST == 1) begin : rst_blk_has
|
|
|
|
assign axis_rd_has_rst = axis_rd_rst;
|
|
|
|
end endgenerate //rst_blk_has
|
|
|
|
|
|
|
|
generate if (C_HAS_RST == 0) begin :rst_blk_no
|
|
|
|
assign axis_rd_has_rst = 1'b0;
|
|
|
|
end endgenerate //rst_blk_no
|
|
|
|
|
|
|
|
genvar i;
|
|
|
|
|
|
|
|
generate for (i = 1; ((i <= C_SYNCHRONIZER_STAGE) && (C_APPLICATION_TYPE_AXIS == 1 && C_COMMON_CLOCK == 0) ); i = i + 1) begin : gpkt_cnt_sync_stage
|
|
|
|
fifo_generator_v12_0_sync_stage
|
|
|
|
#(
|
|
|
|
.C_WIDTH (LOG_DEPTH_AXIS)
|
|
|
|
)
|
|
|
|
rd_stg_inst
|
|
|
|
(
|
|
|
|
.RST (axis_rd_has_rst),
|
|
|
|
.CLK (M_ACLK),
|
|
|
|
.DIN (wpkt_q[i-1]),
|
|
|
|
.DOUT (wpkt_q[i])
|
|
|
|
);
|
|
|
|
|
|
|
|
fifo_generator_v12_0_sync_stage
|
|
|
|
#(
|
|
|
|
.C_WIDTH (1)
|
|
|
|
)
|
|
|
|
wr_stg_inst
|
|
|
|
(
|
|
|
|
.RST (axis_rd_has_rst),
|
|
|
|
.CLK (M_ACLK),
|
|
|
|
.DIN (axis_af_q[i-1]),
|
|
|
|
.DOUT (axis_af_q[i])
|
|
|
|
);
|
|
|
|
end endgenerate // gpkt_cnt_sync_stage
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_APPLICATION_TYPE_AXIS == 1 && C_COMMON_CLOCK == 0) begin : gaxis_pkt_fifo_ic
|
|
|
|
assign axis_wr_eop = axis_wr_en & S_AXIS_TLAST;
|
|
|
|
assign axis_rd_eop = axis_rd_en & axis_dout[0];
|
|
|
|
|
|
|
|
always @ (posedge axis_rd_has_rst or posedge M_ACLK)
|
|
|
|
begin
|
|
|
|
if (axis_rd_has_rst)
|
|
|
|
axis_pkt_read <= 1'b0;
|
|
|
|
else if (axis_rd_eop && (diff_pkt_cnt == 1))
|
|
|
|
axis_pkt_read <= 1'b0;
|
|
|
|
else if ((diff_pkt_cnt > 0) || (axis_af_rd && ~axis_empty))
|
|
|
|
axis_pkt_read <= 1'b1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge axis_wr_rst or posedge S_ACLK)
|
|
|
|
begin
|
|
|
|
if (axis_wr_rst)
|
|
|
|
axis_wpkt_cnt <= 1'b0;
|
|
|
|
else if (axis_wr_eop)
|
|
|
|
axis_wpkt_cnt <= axis_wpkt_cnt + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge axis_wr_rst or posedge S_ACLK)
|
|
|
|
begin
|
|
|
|
if (axis_wr_rst)
|
|
|
|
axis_wpkt_cnt_gc <= 1'b0;
|
|
|
|
else
|
|
|
|
axis_wpkt_cnt_gc <= bin2gray(axis_wpkt_cnt);
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
assign wpkt_q[0] = axis_wpkt_cnt_gc;
|
|
|
|
assign axis_wpkt_cnt_gc_asreg_last = wpkt_q[C_SYNCHRONIZER_STAGE];
|
|
|
|
assign axis_af_q[0] = axis_almost_full;
|
|
|
|
//assign axis_af_q[1:C_SYNCHRONIZER_STAGE] = axis_af_q_temp[1:C_SYNCHRONIZER_STAGE];
|
|
|
|
assign axis_af_rd = axis_af_q[C_SYNCHRONIZER_STAGE];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
always @ (posedge axis_rd_has_rst or posedge M_ACLK)
|
|
|
|
begin
|
|
|
|
if (axis_rd_has_rst)
|
|
|
|
axis_wpkt_cnt_rd <= 1'b0;
|
|
|
|
else
|
|
|
|
axis_wpkt_cnt_rd <= gray2bin(axis_wpkt_cnt_gc_asreg_last);
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge axis_rd_rst or posedge M_ACLK)
|
|
|
|
begin
|
|
|
|
if (axis_rd_has_rst)
|
|
|
|
axis_rpkt_cnt <= 1'b0;
|
|
|
|
else if (axis_rd_eop)
|
|
|
|
axis_rpkt_cnt <= axis_rpkt_cnt + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
// Take the difference of write and read packet count
|
|
|
|
// Logic is similar to rd_pe_as
|
|
|
|
assign adj_axis_wpkt_cnt_rd_pad[LOG_DEPTH_AXIS : 1] = axis_wpkt_cnt_rd;
|
|
|
|
assign rpkt_inv_pad[LOG_DEPTH_AXIS : 1] = ~axis_rpkt_cnt;
|
|
|
|
assign adj_axis_wpkt_cnt_rd_pad[0] = adj_axis_wpkt_cnt_rd_pad_0;
|
|
|
|
assign rpkt_inv_pad[0] = rpkt_inv_pad_0;
|
|
|
|
|
|
|
|
|
|
|
|
always @ ( axis_rd_eop )
|
|
|
|
begin
|
|
|
|
if (!axis_rd_eop) begin
|
|
|
|
adj_axis_wpkt_cnt_rd_pad_0 <= 1'b1;
|
|
|
|
rpkt_inv_pad_0 <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
adj_axis_wpkt_cnt_rd_pad_0 <= 1'b0;
|
|
|
|
rpkt_inv_pad_0 <= 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge axis_rd_rst or posedge M_ACLK)
|
|
|
|
begin
|
|
|
|
if (axis_rd_has_rst)
|
|
|
|
diff_pkt_cnt_pad <= 1'b0;
|
|
|
|
else
|
|
|
|
diff_pkt_cnt_pad <= adj_axis_wpkt_cnt_rd_pad + rpkt_inv_pad ;
|
|
|
|
end
|
|
|
|
|
|
|
|
assign diff_pkt_cnt = diff_pkt_cnt_pad [LOG_DEPTH_AXIS : 1] ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end endgenerate // gaxis_pkt_fifo_ic
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate the accurate data count for axi stream packet fifo configuration
|
|
|
|
reg [C_WR_PNTR_WIDTH_AXIS:0] axis_dc_pkt_fifo = 0;
|
|
|
|
generate if (IS_AXI_STREAMING == 1 && C_HAS_DATA_COUNTS_AXIS == 1 && C_APPLICATION_TYPE_AXIS == 1) begin : gdc_pkt
|
|
|
|
always @ (posedge inverted_reset or posedge S_ACLK)
|
|
|
|
begin
|
|
|
|
if (inverted_reset)
|
|
|
|
axis_dc_pkt_fifo <= 0;
|
|
|
|
else if (axis_wr_en && (~axis_rd_en))
|
|
|
|
axis_dc_pkt_fifo <= #`TCQ axis_dc_pkt_fifo + 1;
|
|
|
|
else if (~axis_wr_en && axis_rd_en)
|
|
|
|
axis_dc_pkt_fifo <= #`TCQ axis_dc_pkt_fifo - 1;
|
|
|
|
end
|
|
|
|
assign AXIS_DATA_COUNT = axis_dc_pkt_fifo;
|
|
|
|
end endgenerate // gdc_pkt
|
|
|
|
|
|
|
|
generate if (IS_AXI_STREAMING == 1 && C_HAS_DATA_COUNTS_AXIS == 0 && C_APPLICATION_TYPE_AXIS == 1) begin : gndc_pkt
|
|
|
|
assign AXIS_DATA_COUNT = 0;
|
|
|
|
end endgenerate // gndc_pkt
|
|
|
|
|
|
|
|
generate if (IS_AXI_STREAMING == 1 && C_APPLICATION_TYPE_AXIS != 1) begin : gdc
|
|
|
|
assign AXIS_DATA_COUNT = axis_dc;
|
|
|
|
end endgenerate // gdc
|
|
|
|
|
|
|
|
// Register Slice for Write Address Channel
|
|
|
|
generate if (C_AXIS_TYPE == 1) begin : gaxis_reg_slice
|
|
|
|
assign axis_wr_en = (C_HAS_SLAVE_CE == 1) ? S_AXIS_TVALID & S_ACLK_EN : S_AXIS_TVALID;
|
|
|
|
assign axis_rd_en = (C_HAS_MASTER_CE == 1) ? M_AXIS_TREADY & M_ACLK_EN : M_AXIS_TREADY;
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_AXIS),
|
|
|
|
.C_REG_CONFIG (C_REG_SLICE_MODE_AXIS)
|
|
|
|
)
|
|
|
|
axis_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (axi_rs_rst),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (axis_din),
|
|
|
|
.S_VALID (axis_wr_en),
|
|
|
|
.S_READY (S_AXIS_TREADY),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (axis_dout),
|
|
|
|
.M_VALID (M_AXIS_TVALID),
|
|
|
|
.M_READY (axis_rd_en)
|
|
|
|
);
|
|
|
|
end endgenerate // gaxis_reg_slice
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TDATA == 1) begin : tdata
|
|
|
|
assign axis_din[C_DIN_WIDTH_AXIS-1:TDATA_OFFSET] = S_AXIS_TDATA;
|
|
|
|
assign M_AXIS_TDATA = axis_dout[C_DIN_WIDTH_AXIS-1:TDATA_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TSTRB == 1) begin : tstrb
|
|
|
|
assign axis_din[TDATA_OFFSET-1:TSTRB_OFFSET] = S_AXIS_TSTRB;
|
|
|
|
assign M_AXIS_TSTRB = axis_dout[TDATA_OFFSET-1:TSTRB_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TKEEP == 1) begin : tkeep
|
|
|
|
assign axis_din[TSTRB_OFFSET-1:TKEEP_OFFSET] = S_AXIS_TKEEP;
|
|
|
|
assign M_AXIS_TKEEP = axis_dout[TSTRB_OFFSET-1:TKEEP_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TID == 1) begin : tid
|
|
|
|
assign axis_din[TKEEP_OFFSET-1:TID_OFFSET] = S_AXIS_TID;
|
|
|
|
assign M_AXIS_TID = axis_dout[TKEEP_OFFSET-1:TID_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TDEST == 1) begin : tdest
|
|
|
|
assign axis_din[TID_OFFSET-1:TDEST_OFFSET] = S_AXIS_TDEST;
|
|
|
|
assign M_AXIS_TDEST = axis_dout[TID_OFFSET-1:TDEST_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TUSER == 1) begin : tuser
|
|
|
|
assign axis_din[TDEST_OFFSET-1:TUSER_OFFSET] = S_AXIS_TUSER;
|
|
|
|
assign M_AXIS_TUSER = axis_dout[TDEST_OFFSET-1:TUSER_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_STREAMING == 1 || C_AXIS_TYPE == 1) && C_HAS_AXIS_TLAST == 1) begin : tlast
|
|
|
|
assign axis_din[0] = S_AXIS_TLAST;
|
|
|
|
assign M_AXIS_TLAST = axis_dout[0];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
//###########################################################################
|
|
|
|
// AXI FULL Write Channel (axi_write_channel)
|
|
|
|
//###########################################################################
|
|
|
|
|
|
|
|
localparam IS_AXI_FULL = ((C_INTERFACE_TYPE == 2) && (C_AXI_TYPE != 2)) ? 1 : 0;
|
|
|
|
localparam IS_AXI_LITE = ((C_INTERFACE_TYPE == 2) && (C_AXI_TYPE == 2)) ? 1 : 0;
|
|
|
|
|
|
|
|
localparam IS_AXI_FULL_WACH = ((IS_AXI_FULL == 1) && (C_WACH_TYPE == 0) && C_HAS_AXI_WR_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_FULL_WDCH = ((IS_AXI_FULL == 1) && (C_WDCH_TYPE == 0) && C_HAS_AXI_WR_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_FULL_WRCH = ((IS_AXI_FULL == 1) && (C_WRCH_TYPE == 0) && C_HAS_AXI_WR_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_FULL_RACH = ((IS_AXI_FULL == 1) && (C_RACH_TYPE == 0) && C_HAS_AXI_RD_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_FULL_RDCH = ((IS_AXI_FULL == 1) && (C_RDCH_TYPE == 0) && C_HAS_AXI_RD_CHANNEL == 1) ? 1 : 0;
|
|
|
|
|
|
|
|
localparam IS_AXI_LITE_WACH = ((IS_AXI_LITE == 1) && (C_WACH_TYPE == 0) && C_HAS_AXI_WR_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_LITE_WDCH = ((IS_AXI_LITE == 1) && (C_WDCH_TYPE == 0) && C_HAS_AXI_WR_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_LITE_WRCH = ((IS_AXI_LITE == 1) && (C_WRCH_TYPE == 0) && C_HAS_AXI_WR_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_LITE_RACH = ((IS_AXI_LITE == 1) && (C_RACH_TYPE == 0) && C_HAS_AXI_RD_CHANNEL == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXI_LITE_RDCH = ((IS_AXI_LITE == 1) && (C_RDCH_TYPE == 0) && C_HAS_AXI_RD_CHANNEL == 1) ? 1 : 0;
|
|
|
|
|
|
|
|
localparam IS_WR_ADDR_CH = ((IS_AXI_FULL_WACH == 1) || (IS_AXI_LITE_WACH == 1)) ? 1 : 0;
|
|
|
|
localparam IS_WR_DATA_CH = ((IS_AXI_FULL_WDCH == 1) || (IS_AXI_LITE_WDCH == 1)) ? 1 : 0;
|
|
|
|
localparam IS_WR_RESP_CH = ((IS_AXI_FULL_WRCH == 1) || (IS_AXI_LITE_WRCH == 1)) ? 1 : 0;
|
|
|
|
localparam IS_RD_ADDR_CH = ((IS_AXI_FULL_RACH == 1) || (IS_AXI_LITE_RACH == 1)) ? 1 : 0;
|
|
|
|
localparam IS_RD_DATA_CH = ((IS_AXI_FULL_RDCH == 1) || (IS_AXI_LITE_RDCH == 1)) ? 1 : 0;
|
|
|
|
|
|
|
|
localparam AWID_OFFSET = (C_AXI_TYPE != 2 && C_HAS_AXI_ID == 1) ? C_DIN_WIDTH_WACH - C_AXI_ID_WIDTH : C_DIN_WIDTH_WACH;
|
|
|
|
localparam AWADDR_OFFSET = AWID_OFFSET - C_AXI_ADDR_WIDTH;
|
|
|
|
localparam AWLEN_OFFSET = C_AXI_TYPE != 2 ? AWADDR_OFFSET - C_AXI_LEN_WIDTH : AWADDR_OFFSET;
|
|
|
|
localparam AWSIZE_OFFSET = C_AXI_TYPE != 2 ? AWLEN_OFFSET - C_AXI_SIZE_WIDTH : AWLEN_OFFSET;
|
|
|
|
localparam AWBURST_OFFSET = C_AXI_TYPE != 2 ? AWSIZE_OFFSET - C_AXI_BURST_WIDTH : AWSIZE_OFFSET;
|
|
|
|
localparam AWLOCK_OFFSET = C_AXI_TYPE != 2 ? AWBURST_OFFSET - C_AXI_LOCK_WIDTH : AWBURST_OFFSET;
|
|
|
|
localparam AWCACHE_OFFSET = C_AXI_TYPE != 2 ? AWLOCK_OFFSET - C_AXI_CACHE_WIDTH : AWLOCK_OFFSET;
|
|
|
|
localparam AWPROT_OFFSET = AWCACHE_OFFSET - C_AXI_PROT_WIDTH;
|
|
|
|
localparam AWQOS_OFFSET = AWPROT_OFFSET - C_AXI_QOS_WIDTH;
|
|
|
|
localparam AWREGION_OFFSET = C_AXI_TYPE == 1 ? AWQOS_OFFSET - C_AXI_REGION_WIDTH : AWQOS_OFFSET;
|
|
|
|
localparam AWUSER_OFFSET = C_HAS_AXI_AWUSER == 1 ? AWREGION_OFFSET-C_AXI_AWUSER_WIDTH : AWREGION_OFFSET;
|
|
|
|
|
|
|
|
localparam WID_OFFSET = (C_AXI_TYPE == 3 && C_HAS_AXI_ID == 1) ? C_DIN_WIDTH_WDCH - C_AXI_ID_WIDTH : C_DIN_WIDTH_WDCH;
|
|
|
|
localparam WDATA_OFFSET = WID_OFFSET - C_AXI_DATA_WIDTH;
|
|
|
|
localparam WSTRB_OFFSET = WDATA_OFFSET - C_AXI_DATA_WIDTH/8;
|
|
|
|
localparam WUSER_OFFSET = C_HAS_AXI_WUSER == 1 ? WSTRB_OFFSET-C_AXI_WUSER_WIDTH : WSTRB_OFFSET;
|
|
|
|
|
|
|
|
localparam BID_OFFSET = (C_AXI_TYPE != 2 && C_HAS_AXI_ID == 1) ? C_DIN_WIDTH_WRCH - C_AXI_ID_WIDTH : C_DIN_WIDTH_WRCH;
|
|
|
|
localparam BRESP_OFFSET = BID_OFFSET - C_AXI_BRESP_WIDTH;
|
|
|
|
localparam BUSER_OFFSET = C_HAS_AXI_BUSER == 1 ? BRESP_OFFSET-C_AXI_BUSER_WIDTH : BRESP_OFFSET;
|
|
|
|
|
|
|
|
|
|
|
|
wire [C_DIN_WIDTH_WACH-1:0] wach_din ;
|
|
|
|
wire [C_DIN_WIDTH_WACH-1:0] wach_dout ;
|
|
|
|
wire [C_DIN_WIDTH_WACH-1:0] wach_dout_pkt ;
|
|
|
|
wire wach_full ;
|
|
|
|
wire wach_almost_full ;
|
|
|
|
wire wach_prog_full ;
|
|
|
|
wire wach_empty ;
|
|
|
|
wire wach_almost_empty ;
|
|
|
|
wire wach_prog_empty ;
|
|
|
|
wire [C_DIN_WIDTH_WDCH-1:0] wdch_din ;
|
|
|
|
wire [C_DIN_WIDTH_WDCH-1:0] wdch_dout ;
|
|
|
|
wire wdch_full ;
|
|
|
|
wire wdch_almost_full ;
|
|
|
|
wire wdch_prog_full ;
|
|
|
|
wire wdch_empty ;
|
|
|
|
wire wdch_almost_empty ;
|
|
|
|
wire wdch_prog_empty ;
|
|
|
|
wire [C_DIN_WIDTH_WRCH-1:0] wrch_din ;
|
|
|
|
wire [C_DIN_WIDTH_WRCH-1:0] wrch_dout ;
|
|
|
|
wire wrch_full ;
|
|
|
|
wire wrch_almost_full ;
|
|
|
|
wire wrch_prog_full ;
|
|
|
|
wire wrch_empty ;
|
|
|
|
wire wrch_almost_empty ;
|
|
|
|
wire wrch_prog_empty ;
|
|
|
|
wire axi_aw_underflow_i;
|
|
|
|
wire axi_w_underflow_i ;
|
|
|
|
wire axi_b_underflow_i ;
|
|
|
|
wire axi_aw_overflow_i ;
|
|
|
|
wire axi_w_overflow_i ;
|
|
|
|
wire axi_b_overflow_i ;
|
|
|
|
wire axi_wr_underflow_i;
|
|
|
|
wire axi_wr_overflow_i ;
|
|
|
|
wire wach_s_axi_awready;
|
|
|
|
wire wach_m_axi_awvalid;
|
|
|
|
wire wach_wr_en ;
|
|
|
|
wire wach_rd_en ;
|
|
|
|
wire wdch_s_axi_wready ;
|
|
|
|
wire wdch_m_axi_wvalid ;
|
|
|
|
wire wdch_wr_en ;
|
|
|
|
wire wdch_rd_en ;
|
|
|
|
wire wrch_s_axi_bvalid ;
|
|
|
|
wire wrch_m_axi_bready ;
|
|
|
|
wire wrch_wr_en ;
|
|
|
|
wire wrch_rd_en ;
|
|
|
|
wire txn_count_up ;
|
|
|
|
wire txn_count_down ;
|
|
|
|
wire awvalid_en ;
|
|
|
|
wire awvalid_pkt ;
|
|
|
|
wire awready_pkt ;
|
|
|
|
integer wr_pkt_count ;
|
|
|
|
wire wach_we ;
|
|
|
|
wire wach_re ;
|
|
|
|
wire wdch_we ;
|
|
|
|
wire wdch_re ;
|
|
|
|
wire wrch_we ;
|
|
|
|
wire wrch_re ;
|
|
|
|
|
|
|
|
generate if (IS_WR_ADDR_CH == 1) begin : axi_write_address_channel
|
|
|
|
// Write protection when almost full or prog_full is high
|
|
|
|
assign wach_we = (C_PROG_FULL_TYPE_WACH != 0) ? wach_s_axi_awready & S_AXI_AWVALID : S_AXI_AWVALID;
|
|
|
|
|
|
|
|
// Read protection when almost empty or prog_empty is high
|
|
|
|
assign wach_re = (C_PROG_EMPTY_TYPE_WACH != 0 && C_APPLICATION_TYPE_WACH == 1) ?
|
|
|
|
wach_m_axi_awvalid & awready_pkt & awvalid_en :
|
|
|
|
(C_PROG_EMPTY_TYPE_WACH != 0 && C_APPLICATION_TYPE_WACH != 1) ?
|
|
|
|
M_AXI_AWREADY && wach_m_axi_awvalid :
|
|
|
|
(C_PROG_EMPTY_TYPE_WACH == 0 && C_APPLICATION_TYPE_WACH == 1) ?
|
|
|
|
awready_pkt & awvalid_en :
|
|
|
|
(C_PROG_EMPTY_TYPE_WACH == 0 && C_APPLICATION_TYPE_WACH != 1) ?
|
|
|
|
M_AXI_AWREADY : 1'b0;
|
|
|
|
assign wach_wr_en = (C_HAS_SLAVE_CE == 1) ? wach_we & S_ACLK_EN : wach_we;
|
|
|
|
assign wach_rd_en = (C_HAS_MASTER_CE == 1) ? wach_re & M_ACLK_EN : wach_re;
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_MEMORY_TYPE ((C_IMPLEMENTATION_TYPE_WACH == 1 || C_IMPLEMENTATION_TYPE_WACH == 11) ? 1 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_WACH == 2 || C_IMPLEMENTATION_TYPE_WACH == 12) ? 2 : 4),
|
|
|
|
.C_IMPLEMENTATION_TYPE ((C_IMPLEMENTATION_TYPE_WACH == 1 || C_IMPLEMENTATION_TYPE_WACH == 2) ? 0 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_WACH == 11 || C_IMPLEMENTATION_TYPE_WACH == 12) ? 2 : 6),
|
|
|
|
.C_PRELOAD_REGS (1), // always FWFT for AXI
|
|
|
|
.C_PRELOAD_LATENCY (0), // always FWFT for AXI
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH_WACH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH_WACH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH_WACH),
|
|
|
|
.C_DOUT_WIDTH (C_DIN_WIDTH_WACH),
|
|
|
|
.C_RD_DEPTH (C_WR_DEPTH_WACH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_WR_PNTR_WIDTH_WACH),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE_WACH),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL_WACH),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE_WACH),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL_WACH),
|
|
|
|
.C_USE_ECC (C_USE_ECC_WACH),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE_WACH),
|
|
|
|
.C_HAS_ALMOST_EMPTY (0),
|
|
|
|
.C_HAS_ALMOST_FULL (0),
|
|
|
|
.C_AXI_TYPE (C_INTERFACE_TYPE == 1 ? 0 : C_AXI_TYPE),
|
|
|
|
|
|
|
|
.C_FIFO_TYPE ((C_APPLICATION_TYPE_WACH == 1)?0:C_APPLICATION_TYPE_WACH),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
|
|
|
|
.C_HAS_WR_RST (0),
|
|
|
|
.C_HAS_RD_RST (0),
|
|
|
|
.C_HAS_RST (1),
|
|
|
|
.C_HAS_SRST (0),
|
|
|
|
.C_DOUT_RST_VAL (0),
|
|
|
|
|
|
|
|
.C_HAS_VALID (0),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_HAS_WR_ACK (0),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
|
|
|
|
.C_HAS_DATA_COUNT ((C_COMMON_CLOCK == 1 && C_HAS_DATA_COUNTS_WACH == 1) ? 1 : 0),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WACH + 1),
|
|
|
|
.C_HAS_RD_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_WACH == 1) ? 1 : 0),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WACH + 1),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (1), // use extra logic is always true
|
|
|
|
.C_HAS_WR_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_WACH == 1) ? 1 : 0),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WACH + 1),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (1),
|
|
|
|
.C_USE_EMBEDDED_REG (0),
|
|
|
|
.C_USE_DOUT_RST (0),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (1),
|
|
|
|
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_wach_dut
|
|
|
|
(
|
|
|
|
.CLK (S_ACLK),
|
|
|
|
.WR_CLK (S_ACLK),
|
|
|
|
.RD_CLK (M_ACLK),
|
|
|
|
.RST (inverted_reset),
|
|
|
|
.SRST (1'b0),
|
|
|
|
.WR_RST (inverted_reset),
|
|
|
|
.RD_RST (inverted_reset),
|
|
|
|
.WR_EN (wach_wr_en),
|
|
|
|
.RD_EN (wach_rd_en),
|
|
|
|
.PROG_FULL_THRESH (AXI_AW_PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT ({C_WR_PNTR_WIDTH_WACH{1'b0}}),
|
|
|
|
.PROG_FULL_THRESH_NEGATE ({C_WR_PNTR_WIDTH_WACH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH (AXI_AW_PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT ({C_WR_PNTR_WIDTH_WACH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE ({C_WR_PNTR_WIDTH_WACH{1'b0}}),
|
|
|
|
.INJECTDBITERR (AXI_AW_INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (AXI_AW_INJECTSBITERR),
|
|
|
|
|
|
|
|
.DIN (wach_din),
|
|
|
|
.DOUT (wach_dout_pkt),
|
|
|
|
.FULL (wach_full),
|
|
|
|
.EMPTY (wach_empty),
|
|
|
|
.ALMOST_FULL (),
|
|
|
|
.PROG_FULL (AXI_AW_PROG_FULL),
|
|
|
|
.ALMOST_EMPTY (),
|
|
|
|
.PROG_EMPTY (AXI_AW_PROG_EMPTY),
|
|
|
|
|
|
|
|
.WR_ACK (),
|
|
|
|
.OVERFLOW (axi_aw_overflow_i),
|
|
|
|
.VALID (),
|
|
|
|
.UNDERFLOW (axi_aw_underflow_i),
|
|
|
|
.DATA_COUNT (AXI_AW_DATA_COUNT),
|
|
|
|
.RD_DATA_COUNT (AXI_AW_RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (AXI_AW_WR_DATA_COUNT),
|
|
|
|
.SBITERR (AXI_AW_SBITERR),
|
|
|
|
.DBITERR (AXI_AW_DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy_wach),
|
|
|
|
.rd_rst_busy (rd_rst_busy_wach),
|
|
|
|
.wr_rst_i_out (),
|
|
|
|
.rd_rst_i_out (),
|
|
|
|
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.INT_CLK (INT_CLK)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign wach_s_axi_awready = (IS_8SERIES == 0) ? ~wach_full : (C_IMPLEMENTATION_TYPE_WACH == 5 || C_IMPLEMENTATION_TYPE_WACH == 13) ? ~(wach_full | wr_rst_busy_wach) : ~wach_full;
|
|
|
|
assign wach_m_axi_awvalid = ~wach_empty;
|
|
|
|
assign S_AXI_AWREADY = wach_s_axi_awready;
|
|
|
|
|
|
|
|
assign AXI_AW_UNDERFLOW = C_USE_COMMON_UNDERFLOW == 0 ? axi_aw_underflow_i : 0;
|
|
|
|
assign AXI_AW_OVERFLOW = C_USE_COMMON_OVERFLOW == 0 ? axi_aw_overflow_i : 0;
|
|
|
|
|
|
|
|
end endgenerate // axi_write_address_channel
|
|
|
|
|
|
|
|
// Register Slice for Write Address Channel
|
|
|
|
generate if (C_WACH_TYPE == 1) begin : gwach_reg_slice
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_WACH),
|
|
|
|
.C_REG_CONFIG (C_REG_SLICE_MODE_WACH)
|
|
|
|
)
|
|
|
|
wach_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (axi_rs_rst),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (wach_din),
|
|
|
|
.S_VALID (S_AXI_AWVALID),
|
|
|
|
.S_READY (S_AXI_AWREADY),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (wach_dout),
|
|
|
|
.M_VALID (M_AXI_AWVALID),
|
|
|
|
.M_READY (M_AXI_AWREADY)
|
|
|
|
);
|
|
|
|
end endgenerate // gwach_reg_slice
|
|
|
|
|
|
|
|
generate if (C_APPLICATION_TYPE_WACH == 1 && C_HAS_AXI_WR_CHANNEL == 1) begin : axi_mm_pkt_fifo_wr
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_WACH),
|
|
|
|
.C_REG_CONFIG (1)
|
|
|
|
)
|
|
|
|
wach_pkt_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (inverted_reset),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (wach_dout_pkt),
|
|
|
|
.S_VALID (awvalid_pkt),
|
|
|
|
.S_READY (awready_pkt),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (wach_dout),
|
|
|
|
.M_VALID (M_AXI_AWVALID),
|
|
|
|
.M_READY (M_AXI_AWREADY)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign awvalid_pkt = wach_m_axi_awvalid && awvalid_en;
|
|
|
|
|
|
|
|
assign txn_count_up = wdch_s_axi_wready && wdch_wr_en && wdch_din[0];
|
|
|
|
assign txn_count_down = wach_m_axi_awvalid && awready_pkt && awvalid_en;
|
|
|
|
|
|
|
|
always@(posedge S_ACLK or posedge inverted_reset) begin
|
|
|
|
if(inverted_reset == 1) begin
|
|
|
|
wr_pkt_count <= 0;
|
|
|
|
end else begin
|
|
|
|
if(txn_count_up == 1 && txn_count_down == 0) begin
|
|
|
|
wr_pkt_count <= wr_pkt_count + 1;
|
|
|
|
end else if(txn_count_up == 0 && txn_count_down == 1) begin
|
|
|
|
wr_pkt_count <= wr_pkt_count - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end //Always end
|
|
|
|
assign awvalid_en = (wr_pkt_count > 0)?1:0;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_APPLICATION_TYPE_WACH != 1) begin : axi_mm_fifo_wr
|
|
|
|
assign awvalid_en = 1;
|
|
|
|
assign wach_dout = wach_dout_pkt;
|
|
|
|
assign M_AXI_AWVALID = wach_m_axi_awvalid;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generate if (IS_WR_DATA_CH == 1) begin : axi_write_data_channel
|
|
|
|
// Write protection when almost full or prog_full is high
|
|
|
|
assign wdch_we = (C_PROG_FULL_TYPE_WDCH != 0) ? wdch_s_axi_wready & S_AXI_WVALID : S_AXI_WVALID;
|
|
|
|
|
|
|
|
// Read protection when almost empty or prog_empty is high
|
|
|
|
assign wdch_re = (C_PROG_EMPTY_TYPE_WDCH != 0) ? wdch_m_axi_wvalid & M_AXI_WREADY : M_AXI_WREADY;
|
|
|
|
assign wdch_wr_en = (C_HAS_SLAVE_CE == 1) ? wdch_we & S_ACLK_EN : wdch_we;
|
|
|
|
assign wdch_rd_en = (C_HAS_MASTER_CE == 1) ? wdch_re & M_ACLK_EN : wdch_re;
|
|
|
|
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_MEMORY_TYPE ((C_IMPLEMENTATION_TYPE_WDCH == 1 || C_IMPLEMENTATION_TYPE_WDCH == 11) ? 1 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_WDCH == 2 || C_IMPLEMENTATION_TYPE_WDCH == 12) ? 2 : 4),
|
|
|
|
.C_IMPLEMENTATION_TYPE ((C_IMPLEMENTATION_TYPE_WDCH == 1 || C_IMPLEMENTATION_TYPE_WDCH == 2) ? 0 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_WDCH == 11 || C_IMPLEMENTATION_TYPE_WDCH == 12) ? 2 : 6),
|
|
|
|
.C_PRELOAD_REGS (1), // always FWFT for AXI
|
|
|
|
.C_PRELOAD_LATENCY (0), // always FWFT for AXI
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH_WDCH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH_WDCH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH_WDCH),
|
|
|
|
.C_DOUT_WIDTH (C_DIN_WIDTH_WDCH),
|
|
|
|
.C_RD_DEPTH (C_WR_DEPTH_WDCH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_WR_PNTR_WIDTH_WDCH),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE_WDCH),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL_WDCH),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE_WDCH),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL_WDCH),
|
|
|
|
.C_USE_ECC (C_USE_ECC_WDCH),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE_WDCH),
|
|
|
|
.C_HAS_ALMOST_EMPTY (0),
|
|
|
|
.C_HAS_ALMOST_FULL (0),
|
|
|
|
.C_AXI_TYPE (C_INTERFACE_TYPE == 1 ? 0 : C_AXI_TYPE),
|
|
|
|
|
|
|
|
.C_FIFO_TYPE (C_APPLICATION_TYPE_WDCH),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
|
|
|
|
.C_HAS_WR_RST (0),
|
|
|
|
.C_HAS_RD_RST (0),
|
|
|
|
.C_HAS_RST (1),
|
|
|
|
.C_HAS_SRST (0),
|
|
|
|
.C_DOUT_RST_VAL (0),
|
|
|
|
|
|
|
|
.C_HAS_VALID (0),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_HAS_WR_ACK (0),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
|
|
|
|
.C_HAS_DATA_COUNT ((C_COMMON_CLOCK == 1 && C_HAS_DATA_COUNTS_WDCH == 1) ? 1 : 0),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WDCH + 1),
|
|
|
|
.C_HAS_RD_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_WDCH == 1) ? 1 : 0),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WDCH + 1),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (1), // use extra logic is always true
|
|
|
|
.C_HAS_WR_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_WDCH == 1) ? 1 : 0),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WDCH + 1),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (1),
|
|
|
|
.C_USE_EMBEDDED_REG (0),
|
|
|
|
.C_USE_DOUT_RST (0),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (1),
|
|
|
|
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_wdch_dut
|
|
|
|
(
|
|
|
|
.CLK (S_ACLK),
|
|
|
|
.WR_CLK (S_ACLK),
|
|
|
|
.RD_CLK (M_ACLK),
|
|
|
|
.RST (inverted_reset),
|
|
|
|
.SRST (1'b0),
|
|
|
|
.WR_RST (inverted_reset),
|
|
|
|
.RD_RST (inverted_reset),
|
|
|
|
.WR_EN (wdch_wr_en),
|
|
|
|
.RD_EN (wdch_rd_en),
|
|
|
|
.PROG_FULL_THRESH (AXI_W_PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT ({C_WR_PNTR_WIDTH_WDCH{1'b0}}),
|
|
|
|
.PROG_FULL_THRESH_NEGATE ({C_WR_PNTR_WIDTH_WDCH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH (AXI_W_PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT ({C_WR_PNTR_WIDTH_WDCH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE ({C_WR_PNTR_WIDTH_WDCH{1'b0}}),
|
|
|
|
.INJECTDBITERR (AXI_W_INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (AXI_W_INJECTSBITERR),
|
|
|
|
|
|
|
|
.DIN (wdch_din),
|
|
|
|
.DOUT (wdch_dout),
|
|
|
|
.FULL (wdch_full),
|
|
|
|
.EMPTY (wdch_empty),
|
|
|
|
.ALMOST_FULL (),
|
|
|
|
.PROG_FULL (AXI_W_PROG_FULL),
|
|
|
|
.ALMOST_EMPTY (),
|
|
|
|
.PROG_EMPTY (AXI_W_PROG_EMPTY),
|
|
|
|
|
|
|
|
.WR_ACK (),
|
|
|
|
.OVERFLOW (axi_w_overflow_i),
|
|
|
|
.VALID (),
|
|
|
|
.UNDERFLOW (axi_w_underflow_i),
|
|
|
|
.DATA_COUNT (AXI_W_DATA_COUNT),
|
|
|
|
.RD_DATA_COUNT (AXI_W_RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (AXI_W_WR_DATA_COUNT),
|
|
|
|
.SBITERR (AXI_W_SBITERR),
|
|
|
|
.DBITERR (AXI_W_DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy_wdch),
|
|
|
|
.rd_rst_busy (rd_rst_busy_wdch),
|
|
|
|
.wr_rst_i_out (),
|
|
|
|
.rd_rst_i_out (),
|
|
|
|
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.INT_CLK (INT_CLK)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign wdch_s_axi_wready = (IS_8SERIES == 0) ? ~wdch_full : (C_IMPLEMENTATION_TYPE_WDCH == 5 || C_IMPLEMENTATION_TYPE_WDCH == 13) ? ~(wdch_full | wr_rst_busy_wdch) : ~wdch_full;
|
|
|
|
assign wdch_m_axi_wvalid = ~wdch_empty;
|
|
|
|
assign S_AXI_WREADY = wdch_s_axi_wready;
|
|
|
|
assign M_AXI_WVALID = wdch_m_axi_wvalid;
|
|
|
|
|
|
|
|
assign AXI_W_UNDERFLOW = C_USE_COMMON_UNDERFLOW == 0 ? axi_w_underflow_i : 0;
|
|
|
|
assign AXI_W_OVERFLOW = C_USE_COMMON_OVERFLOW == 0 ? axi_w_overflow_i : 0;
|
|
|
|
|
|
|
|
end endgenerate // axi_write_data_channel
|
|
|
|
|
|
|
|
// Register Slice for Write Data Channel
|
|
|
|
generate if (C_WDCH_TYPE == 1) begin : gwdch_reg_slice
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_WDCH),
|
|
|
|
.C_REG_CONFIG (C_REG_SLICE_MODE_WDCH)
|
|
|
|
)
|
|
|
|
wdch_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (axi_rs_rst),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (wdch_din),
|
|
|
|
.S_VALID (S_AXI_WVALID),
|
|
|
|
.S_READY (S_AXI_WREADY),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (wdch_dout),
|
|
|
|
.M_VALID (M_AXI_WVALID),
|
|
|
|
.M_READY (M_AXI_WREADY)
|
|
|
|
);
|
|
|
|
end endgenerate // gwdch_reg_slice
|
|
|
|
|
|
|
|
generate if (IS_WR_RESP_CH == 1) begin : axi_write_resp_channel
|
|
|
|
// Write protection when almost full or prog_full is high
|
|
|
|
assign wrch_we = (C_PROG_FULL_TYPE_WRCH != 0) ? wrch_m_axi_bready & M_AXI_BVALID : M_AXI_BVALID;
|
|
|
|
|
|
|
|
// Read protection when almost empty or prog_empty is high
|
|
|
|
assign wrch_re = (C_PROG_EMPTY_TYPE_WRCH != 0) ? wrch_s_axi_bvalid & S_AXI_BREADY : S_AXI_BREADY;
|
|
|
|
assign wrch_wr_en = (C_HAS_SLAVE_CE == 1) ? wrch_we & S_ACLK_EN : wrch_we;
|
|
|
|
assign wrch_rd_en = (C_HAS_MASTER_CE == 1) ? wrch_re & M_ACLK_EN : wrch_re;
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_MEMORY_TYPE ((C_IMPLEMENTATION_TYPE_WRCH == 1 || C_IMPLEMENTATION_TYPE_WRCH == 11) ? 1 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_WRCH == 2 || C_IMPLEMENTATION_TYPE_WRCH == 12) ? 2 : 4),
|
|
|
|
.C_IMPLEMENTATION_TYPE ((C_IMPLEMENTATION_TYPE_WRCH == 1 || C_IMPLEMENTATION_TYPE_WRCH == 2) ? 0 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_WRCH == 11 || C_IMPLEMENTATION_TYPE_WRCH == 12) ? 2 : 6),
|
|
|
|
.C_PRELOAD_REGS (1), // always FWFT for AXI
|
|
|
|
.C_PRELOAD_LATENCY (0), // always FWFT for AXI
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH_WRCH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH_WRCH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH_WRCH),
|
|
|
|
.C_DOUT_WIDTH (C_DIN_WIDTH_WRCH),
|
|
|
|
.C_RD_DEPTH (C_WR_DEPTH_WRCH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_WR_PNTR_WIDTH_WRCH),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE_WRCH),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL_WRCH),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE_WRCH),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL_WRCH),
|
|
|
|
.C_USE_ECC (C_USE_ECC_WRCH),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE_WRCH),
|
|
|
|
.C_HAS_ALMOST_EMPTY (0),
|
|
|
|
.C_HAS_ALMOST_FULL (0),
|
|
|
|
.C_AXI_TYPE (C_INTERFACE_TYPE == 1 ? 0 : C_AXI_TYPE),
|
|
|
|
|
|
|
|
.C_FIFO_TYPE (C_APPLICATION_TYPE_WRCH),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
|
|
|
|
.C_HAS_WR_RST (0),
|
|
|
|
.C_HAS_RD_RST (0),
|
|
|
|
.C_HAS_RST (1),
|
|
|
|
.C_HAS_SRST (0),
|
|
|
|
.C_DOUT_RST_VAL (0),
|
|
|
|
|
|
|
|
.C_HAS_VALID (0),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_HAS_WR_ACK (0),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
|
|
|
|
.C_HAS_DATA_COUNT ((C_COMMON_CLOCK == 1 && C_HAS_DATA_COUNTS_WRCH == 1) ? 1 : 0),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WRCH + 1),
|
|
|
|
.C_HAS_RD_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_WRCH == 1) ? 1 : 0),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WRCH + 1),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (1), // use extra logic is always true
|
|
|
|
.C_HAS_WR_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_WRCH == 1) ? 1 : 0),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_WRCH + 1),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (1),
|
|
|
|
.C_USE_EMBEDDED_REG (0),
|
|
|
|
.C_USE_DOUT_RST (0),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (1),
|
|
|
|
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_wrch_dut
|
|
|
|
(
|
|
|
|
.CLK (S_ACLK),
|
|
|
|
.WR_CLK (M_ACLK),
|
|
|
|
.RD_CLK (S_ACLK),
|
|
|
|
.RST (inverted_reset),
|
|
|
|
.SRST (1'b0),
|
|
|
|
.WR_RST (inverted_reset),
|
|
|
|
.RD_RST (inverted_reset),
|
|
|
|
.WR_EN (wrch_wr_en),
|
|
|
|
.RD_EN (wrch_rd_en),
|
|
|
|
.PROG_FULL_THRESH (AXI_B_PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT ({C_WR_PNTR_WIDTH_WRCH{1'b0}}),
|
|
|
|
.PROG_FULL_THRESH_NEGATE ({C_WR_PNTR_WIDTH_WRCH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH (AXI_B_PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT ({C_WR_PNTR_WIDTH_WRCH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE ({C_WR_PNTR_WIDTH_WRCH{1'b0}}),
|
|
|
|
.INJECTDBITERR (AXI_B_INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (AXI_B_INJECTSBITERR),
|
|
|
|
|
|
|
|
.DIN (wrch_din),
|
|
|
|
.DOUT (wrch_dout),
|
|
|
|
.FULL (wrch_full),
|
|
|
|
.EMPTY (wrch_empty),
|
|
|
|
.ALMOST_FULL (),
|
|
|
|
.ALMOST_EMPTY (),
|
|
|
|
.PROG_FULL (AXI_B_PROG_FULL),
|
|
|
|
.PROG_EMPTY (AXI_B_PROG_EMPTY),
|
|
|
|
|
|
|
|
.WR_ACK (),
|
|
|
|
.OVERFLOW (axi_b_overflow_i),
|
|
|
|
.VALID (),
|
|
|
|
.UNDERFLOW (axi_b_underflow_i),
|
|
|
|
.DATA_COUNT (AXI_B_DATA_COUNT),
|
|
|
|
.RD_DATA_COUNT (AXI_B_RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (AXI_B_WR_DATA_COUNT),
|
|
|
|
.SBITERR (AXI_B_SBITERR),
|
|
|
|
.DBITERR (AXI_B_DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy_wrch),
|
|
|
|
.rd_rst_busy (rd_rst_busy_wrch),
|
|
|
|
.wr_rst_i_out (),
|
|
|
|
.rd_rst_i_out (),
|
|
|
|
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.INT_CLK (INT_CLK)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign wrch_s_axi_bvalid = ~wrch_empty;
|
|
|
|
assign wrch_m_axi_bready = (IS_8SERIES == 0) ? ~wrch_full : (C_IMPLEMENTATION_TYPE_WRCH == 5 || C_IMPLEMENTATION_TYPE_WRCH == 13) ? ~(wrch_full | wr_rst_busy_wrch) : ~wrch_full;
|
|
|
|
assign S_AXI_BVALID = wrch_s_axi_bvalid;
|
|
|
|
assign M_AXI_BREADY = wrch_m_axi_bready;
|
|
|
|
|
|
|
|
assign AXI_B_UNDERFLOW = C_USE_COMMON_UNDERFLOW == 0 ? axi_b_underflow_i : 0;
|
|
|
|
assign AXI_B_OVERFLOW = C_USE_COMMON_OVERFLOW == 0 ? axi_b_overflow_i : 0;
|
|
|
|
end endgenerate // axi_write_resp_channel
|
|
|
|
|
|
|
|
// Register Slice for Write Response Channel
|
|
|
|
generate if (C_WRCH_TYPE == 1) begin : gwrch_reg_slice
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_WRCH),
|
|
|
|
.C_REG_CONFIG (C_REG_SLICE_MODE_WRCH)
|
|
|
|
)
|
|
|
|
wrch_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (axi_rs_rst),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (wrch_din),
|
|
|
|
.S_VALID (M_AXI_BVALID),
|
|
|
|
.S_READY (M_AXI_BREADY),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (wrch_dout),
|
|
|
|
.M_VALID (S_AXI_BVALID),
|
|
|
|
.M_READY (S_AXI_BREADY)
|
|
|
|
);
|
|
|
|
end endgenerate // gwrch_reg_slice
|
|
|
|
|
|
|
|
|
|
|
|
assign axi_wr_underflow_i = C_USE_COMMON_UNDERFLOW == 1 ? (axi_aw_underflow_i || axi_w_underflow_i || axi_b_underflow_i) : 0;
|
|
|
|
assign axi_wr_overflow_i = C_USE_COMMON_OVERFLOW == 1 ? (axi_aw_overflow_i || axi_w_overflow_i || axi_b_overflow_i) : 0;
|
|
|
|
|
|
|
|
generate if (IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) begin : axi_wach_output
|
|
|
|
assign M_AXI_AWADDR = wach_dout[AWID_OFFSET-1:AWADDR_OFFSET];
|
|
|
|
assign M_AXI_AWLEN = wach_dout[AWADDR_OFFSET-1:AWLEN_OFFSET];
|
|
|
|
assign M_AXI_AWSIZE = wach_dout[AWLEN_OFFSET-1:AWSIZE_OFFSET];
|
|
|
|
assign M_AXI_AWBURST = wach_dout[AWSIZE_OFFSET-1:AWBURST_OFFSET];
|
|
|
|
assign M_AXI_AWLOCK = wach_dout[AWBURST_OFFSET-1:AWLOCK_OFFSET];
|
|
|
|
assign M_AXI_AWCACHE = wach_dout[AWLOCK_OFFSET-1:AWCACHE_OFFSET];
|
|
|
|
assign M_AXI_AWPROT = wach_dout[AWCACHE_OFFSET-1:AWPROT_OFFSET];
|
|
|
|
assign M_AXI_AWQOS = wach_dout[AWPROT_OFFSET-1:AWQOS_OFFSET];
|
|
|
|
assign wach_din[AWID_OFFSET-1:AWADDR_OFFSET] = S_AXI_AWADDR;
|
|
|
|
assign wach_din[AWADDR_OFFSET-1:AWLEN_OFFSET] = S_AXI_AWLEN;
|
|
|
|
assign wach_din[AWLEN_OFFSET-1:AWSIZE_OFFSET] = S_AXI_AWSIZE;
|
|
|
|
assign wach_din[AWSIZE_OFFSET-1:AWBURST_OFFSET] = S_AXI_AWBURST;
|
|
|
|
assign wach_din[AWBURST_OFFSET-1:AWLOCK_OFFSET] = S_AXI_AWLOCK;
|
|
|
|
assign wach_din[AWLOCK_OFFSET-1:AWCACHE_OFFSET] = S_AXI_AWCACHE;
|
|
|
|
assign wach_din[AWCACHE_OFFSET-1:AWPROT_OFFSET] = S_AXI_AWPROT;
|
|
|
|
assign wach_din[AWPROT_OFFSET-1:AWQOS_OFFSET] = S_AXI_AWQOS;
|
|
|
|
end endgenerate // axi_wach_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_AXI_TYPE == 1) begin : axi_awregion
|
|
|
|
assign M_AXI_AWREGION = wach_dout[AWQOS_OFFSET-1:AWREGION_OFFSET];
|
|
|
|
end endgenerate // axi_awregion
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_AXI_TYPE != 1) begin : naxi_awregion
|
|
|
|
assign M_AXI_AWREGION = 0;
|
|
|
|
end endgenerate // naxi_awregion
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_HAS_AXI_AWUSER == 1) begin : axi_awuser
|
|
|
|
assign M_AXI_AWUSER = wach_dout[AWREGION_OFFSET-1:AWUSER_OFFSET];
|
|
|
|
end endgenerate // axi_awuser
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_HAS_AXI_AWUSER == 0) begin : naxi_awuser
|
|
|
|
assign M_AXI_AWUSER = 0;
|
|
|
|
end endgenerate // naxi_awuser
|
|
|
|
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : axi_awid
|
|
|
|
assign M_AXI_AWID = wach_dout[C_DIN_WIDTH_WACH-1:AWID_OFFSET];
|
|
|
|
end endgenerate //axi_awid
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_HAS_AXI_ID == 0) begin : naxi_awid
|
|
|
|
assign M_AXI_AWID = 0;
|
|
|
|
end endgenerate //naxi_awid
|
|
|
|
|
|
|
|
generate if (IS_AXI_FULL_WDCH == 1 || (IS_AXI_FULL == 1 && C_WDCH_TYPE == 1)) begin : axi_wdch_output
|
|
|
|
assign M_AXI_WDATA = wdch_dout[WID_OFFSET-1:WDATA_OFFSET];
|
|
|
|
assign M_AXI_WSTRB = wdch_dout[WDATA_OFFSET-1:WSTRB_OFFSET];
|
|
|
|
assign M_AXI_WLAST = wdch_dout[0];
|
|
|
|
assign wdch_din[WID_OFFSET-1:WDATA_OFFSET] = S_AXI_WDATA;
|
|
|
|
assign wdch_din[WDATA_OFFSET-1:WSTRB_OFFSET] = S_AXI_WSTRB;
|
|
|
|
assign wdch_din[0] = S_AXI_WLAST;
|
|
|
|
end endgenerate // axi_wdch_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WDCH == 1 || (IS_AXI_FULL == 1 && C_WDCH_TYPE == 1)) && C_HAS_AXI_ID == 1 && C_AXI_TYPE == 3) begin
|
|
|
|
assign M_AXI_WID = wdch_dout[C_DIN_WIDTH_WDCH-1:WID_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
generate if ((IS_AXI_FULL_WDCH == 1 || (IS_AXI_FULL == 1 && C_WDCH_TYPE == 1)) && (C_HAS_AXI_ID == 0 || C_AXI_TYPE != 3)) begin
|
|
|
|
assign M_AXI_WID = 0;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WDCH == 1 || (IS_AXI_FULL == 1 && C_WDCH_TYPE == 1)) && C_HAS_AXI_WUSER == 1 ) begin
|
|
|
|
assign M_AXI_WUSER = wdch_dout[WSTRB_OFFSET-1:WUSER_OFFSET];
|
|
|
|
end endgenerate
|
|
|
|
generate if (C_HAS_AXI_WUSER == 0) begin
|
|
|
|
assign M_AXI_WUSER = 0;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) begin : axi_wrch_output
|
|
|
|
assign S_AXI_BRESP = wrch_dout[BID_OFFSET-1:BRESP_OFFSET];
|
|
|
|
assign wrch_din[BID_OFFSET-1:BRESP_OFFSET] = M_AXI_BRESP;
|
|
|
|
end endgenerate // axi_wrch_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) && C_HAS_AXI_BUSER == 1) begin : axi_buser
|
|
|
|
assign S_AXI_BUSER = wrch_dout[BRESP_OFFSET-1:BUSER_OFFSET];
|
|
|
|
end endgenerate // axi_buser
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) && C_HAS_AXI_BUSER == 0) begin : naxi_buser
|
|
|
|
assign S_AXI_BUSER = 0;
|
|
|
|
end endgenerate // naxi_buser
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : axi_bid
|
|
|
|
assign S_AXI_BID = wrch_dout[C_DIN_WIDTH_WRCH-1:BID_OFFSET];
|
|
|
|
end endgenerate // axi_bid
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) && C_HAS_AXI_ID == 0) begin : naxi_bid
|
|
|
|
assign S_AXI_BID = 0 ;
|
|
|
|
end endgenerate // naxi_bid
|
|
|
|
|
|
|
|
|
|
|
|
generate if (IS_AXI_LITE_WACH == 1 || (IS_AXI_LITE == 1 && C_WACH_TYPE == 1)) begin : axi_wach_output1
|
|
|
|
assign wach_din = {S_AXI_AWADDR, S_AXI_AWPROT};
|
|
|
|
assign M_AXI_AWADDR = wach_dout[C_DIN_WIDTH_WACH-1:AWADDR_OFFSET];
|
|
|
|
assign M_AXI_AWPROT = wach_dout[AWADDR_OFFSET-1:AWPROT_OFFSET];
|
|
|
|
end endgenerate // axi_wach_output1
|
|
|
|
|
|
|
|
generate if (IS_AXI_LITE_WDCH == 1 || (IS_AXI_LITE == 1 && C_WDCH_TYPE == 1)) begin : axi_wdch_output1
|
|
|
|
assign wdch_din = {S_AXI_WDATA, S_AXI_WSTRB};
|
|
|
|
assign M_AXI_WDATA = wdch_dout[C_DIN_WIDTH_WDCH-1:WDATA_OFFSET];
|
|
|
|
assign M_AXI_WSTRB = wdch_dout[WDATA_OFFSET-1:WSTRB_OFFSET];
|
|
|
|
end endgenerate // axi_wdch_output1
|
|
|
|
|
|
|
|
generate if (IS_AXI_LITE_WRCH == 1 || (IS_AXI_LITE == 1 && C_WRCH_TYPE == 1)) begin : axi_wrch_output1
|
|
|
|
assign wrch_din = M_AXI_BRESP;
|
|
|
|
assign S_AXI_BRESP = wrch_dout[C_DIN_WIDTH_WRCH-1:BRESP_OFFSET];
|
|
|
|
end endgenerate // axi_wrch_output1
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_HAS_AXI_AWUSER == 1) begin : gwach_din1
|
|
|
|
assign wach_din[AWREGION_OFFSET-1:AWUSER_OFFSET] = S_AXI_AWUSER;
|
|
|
|
end endgenerate // gwach_din1
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : gwach_din2
|
|
|
|
assign wach_din[C_DIN_WIDTH_WACH-1:AWID_OFFSET] = S_AXI_AWID;
|
|
|
|
end endgenerate // gwach_din2
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WACH == 1 || (IS_AXI_FULL == 1 && C_WACH_TYPE == 1)) && C_AXI_TYPE == 1) begin : gwach_din3
|
|
|
|
assign wach_din[AWQOS_OFFSET-1:AWREGION_OFFSET] = S_AXI_AWREGION;
|
|
|
|
end endgenerate // gwach_din3
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WDCH == 1 || (IS_AXI_FULL == 1 && C_WDCH_TYPE == 1)) && C_HAS_AXI_WUSER == 1) begin : gwdch_din1
|
|
|
|
assign wdch_din[WSTRB_OFFSET-1:WUSER_OFFSET] = S_AXI_WUSER;
|
|
|
|
end endgenerate // gwdch_din1
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WDCH == 1 || (IS_AXI_FULL == 1 && C_WDCH_TYPE == 1)) && C_HAS_AXI_ID == 1 && C_AXI_TYPE == 3) begin : gwdch_din2
|
|
|
|
assign wdch_din[C_DIN_WIDTH_WDCH-1:WID_OFFSET] = S_AXI_WID;
|
|
|
|
end endgenerate // gwdch_din2
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) && C_HAS_AXI_BUSER == 1) begin : gwrch_din1
|
|
|
|
assign wrch_din[BRESP_OFFSET-1:BUSER_OFFSET] = M_AXI_BUSER;
|
|
|
|
end endgenerate // gwrch_din1
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_WRCH == 1 || (IS_AXI_FULL == 1 && C_WRCH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : gwrch_din2
|
|
|
|
assign wrch_din[C_DIN_WIDTH_WRCH-1:BID_OFFSET] = M_AXI_BID;
|
|
|
|
end endgenerate // gwrch_din2
|
|
|
|
|
|
|
|
//end of axi_write_channel
|
|
|
|
|
|
|
|
//###########################################################################
|
|
|
|
// AXI FULL Read Channel (axi_read_channel)
|
|
|
|
//###########################################################################
|
|
|
|
wire [C_DIN_WIDTH_RACH-1:0] rach_din ;
|
|
|
|
wire [C_DIN_WIDTH_RACH-1:0] rach_dout ;
|
|
|
|
wire [C_DIN_WIDTH_RACH-1:0] rach_dout_pkt ;
|
|
|
|
wire rach_full ;
|
|
|
|
wire rach_almost_full ;
|
|
|
|
wire rach_prog_full ;
|
|
|
|
wire rach_empty ;
|
|
|
|
wire rach_almost_empty ;
|
|
|
|
wire rach_prog_empty ;
|
|
|
|
wire [C_DIN_WIDTH_RDCH-1:0] rdch_din ;
|
|
|
|
wire [C_DIN_WIDTH_RDCH-1:0] rdch_dout ;
|
|
|
|
wire rdch_full ;
|
|
|
|
wire rdch_almost_full ;
|
|
|
|
wire rdch_prog_full ;
|
|
|
|
wire rdch_empty ;
|
|
|
|
wire rdch_almost_empty ;
|
|
|
|
wire rdch_prog_empty ;
|
|
|
|
wire axi_ar_underflow_i ;
|
|
|
|
wire axi_r_underflow_i ;
|
|
|
|
wire axi_ar_overflow_i ;
|
|
|
|
wire axi_r_overflow_i ;
|
|
|
|
wire axi_rd_underflow_i ;
|
|
|
|
wire axi_rd_overflow_i ;
|
|
|
|
wire rach_s_axi_arready ;
|
|
|
|
wire rach_m_axi_arvalid ;
|
|
|
|
wire rach_wr_en ;
|
|
|
|
wire rach_rd_en ;
|
|
|
|
wire rdch_m_axi_rready ;
|
|
|
|
wire rdch_s_axi_rvalid ;
|
|
|
|
wire rdch_wr_en ;
|
|
|
|
wire rdch_rd_en ;
|
|
|
|
wire arvalid_pkt ;
|
|
|
|
wire arready_pkt ;
|
|
|
|
wire arvalid_en ;
|
|
|
|
wire rdch_rd_ok ;
|
|
|
|
wire accept_next_pkt ;
|
|
|
|
integer rdch_free_space ;
|
|
|
|
integer rdch_commited_space ;
|
|
|
|
wire rach_we ;
|
|
|
|
wire rach_re ;
|
|
|
|
wire rdch_we ;
|
|
|
|
wire rdch_re ;
|
|
|
|
|
|
|
|
localparam ARID_OFFSET = (C_AXI_TYPE != 2 && C_HAS_AXI_ID == 1) ? C_DIN_WIDTH_RACH - C_AXI_ID_WIDTH : C_DIN_WIDTH_RACH;
|
|
|
|
localparam ARADDR_OFFSET = ARID_OFFSET - C_AXI_ADDR_WIDTH;
|
|
|
|
localparam ARLEN_OFFSET = C_AXI_TYPE != 2 ? ARADDR_OFFSET - C_AXI_LEN_WIDTH : ARADDR_OFFSET;
|
|
|
|
localparam ARSIZE_OFFSET = C_AXI_TYPE != 2 ? ARLEN_OFFSET - C_AXI_SIZE_WIDTH : ARLEN_OFFSET;
|
|
|
|
localparam ARBURST_OFFSET = C_AXI_TYPE != 2 ? ARSIZE_OFFSET - C_AXI_BURST_WIDTH : ARSIZE_OFFSET;
|
|
|
|
localparam ARLOCK_OFFSET = C_AXI_TYPE != 2 ? ARBURST_OFFSET - C_AXI_LOCK_WIDTH : ARBURST_OFFSET;
|
|
|
|
localparam ARCACHE_OFFSET = C_AXI_TYPE != 2 ? ARLOCK_OFFSET - C_AXI_CACHE_WIDTH : ARLOCK_OFFSET;
|
|
|
|
localparam ARPROT_OFFSET = ARCACHE_OFFSET - C_AXI_PROT_WIDTH;
|
|
|
|
localparam ARQOS_OFFSET = ARPROT_OFFSET - C_AXI_QOS_WIDTH;
|
|
|
|
localparam ARREGION_OFFSET = C_AXI_TYPE == 1 ? ARQOS_OFFSET - C_AXI_REGION_WIDTH : ARQOS_OFFSET;
|
|
|
|
localparam ARUSER_OFFSET = C_HAS_AXI_ARUSER == 1 ? ARREGION_OFFSET-C_AXI_ARUSER_WIDTH : ARREGION_OFFSET;
|
|
|
|
|
|
|
|
localparam RID_OFFSET = (C_AXI_TYPE != 2 && C_HAS_AXI_ID == 1) ? C_DIN_WIDTH_RDCH - C_AXI_ID_WIDTH : C_DIN_WIDTH_RDCH;
|
|
|
|
localparam RDATA_OFFSET = RID_OFFSET - C_AXI_DATA_WIDTH;
|
|
|
|
localparam RRESP_OFFSET = RDATA_OFFSET - C_AXI_RRESP_WIDTH;
|
|
|
|
localparam RUSER_OFFSET = C_HAS_AXI_RUSER == 1 ? RRESP_OFFSET-C_AXI_RUSER_WIDTH : RRESP_OFFSET;
|
|
|
|
|
|
|
|
|
|
|
|
generate if (IS_RD_ADDR_CH == 1) begin : axi_read_addr_channel
|
|
|
|
|
|
|
|
// Write protection when almost full or prog_full is high
|
|
|
|
assign rach_we = (C_PROG_FULL_TYPE_RACH != 0) ? rach_s_axi_arready & S_AXI_ARVALID : S_AXI_ARVALID;
|
|
|
|
|
|
|
|
// Read protection when almost empty or prog_empty is high
|
|
|
|
// assign rach_rd_en = (C_PROG_EMPTY_TYPE_RACH != 5) ? rach_m_axi_arvalid & M_AXI_ARREADY : M_AXI_ARREADY && arvalid_en;
|
|
|
|
assign rach_re = (C_PROG_EMPTY_TYPE_RACH != 0 && C_APPLICATION_TYPE_RACH == 1) ?
|
|
|
|
rach_m_axi_arvalid & arready_pkt & arvalid_en :
|
|
|
|
(C_PROG_EMPTY_TYPE_RACH != 0 && C_APPLICATION_TYPE_RACH != 1) ?
|
|
|
|
M_AXI_ARREADY && rach_m_axi_arvalid :
|
|
|
|
(C_PROG_EMPTY_TYPE_RACH == 0 && C_APPLICATION_TYPE_RACH == 1) ?
|
|
|
|
arready_pkt & arvalid_en :
|
|
|
|
(C_PROG_EMPTY_TYPE_RACH == 0 && C_APPLICATION_TYPE_RACH != 1) ?
|
|
|
|
M_AXI_ARREADY : 1'b0;
|
|
|
|
assign rach_wr_en = (C_HAS_SLAVE_CE == 1) ? rach_we & S_ACLK_EN : rach_we;
|
|
|
|
assign rach_rd_en = (C_HAS_MASTER_CE == 1) ? rach_re & M_ACLK_EN : rach_re;
|
|
|
|
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_MEMORY_TYPE ((C_IMPLEMENTATION_TYPE_RACH == 1 || C_IMPLEMENTATION_TYPE_RACH == 11) ? 1 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_RACH == 2 || C_IMPLEMENTATION_TYPE_RACH == 12) ? 2 : 4),
|
|
|
|
.C_IMPLEMENTATION_TYPE ((C_IMPLEMENTATION_TYPE_RACH == 1 || C_IMPLEMENTATION_TYPE_RACH == 2) ? 0 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_RACH == 11 || C_IMPLEMENTATION_TYPE_RACH == 12) ? 2 : 6),
|
|
|
|
.C_PRELOAD_REGS (1), // always FWFT for AXI
|
|
|
|
.C_PRELOAD_LATENCY (0), // always FWFT for AXI
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH_RACH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH_RACH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH_RACH),
|
|
|
|
.C_DOUT_WIDTH (C_DIN_WIDTH_RACH),
|
|
|
|
.C_RD_DEPTH (C_WR_DEPTH_RACH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_WR_PNTR_WIDTH_RACH),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE_RACH),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL_RACH),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE_RACH),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL_RACH),
|
|
|
|
.C_USE_ECC (C_USE_ECC_RACH),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE_RACH),
|
|
|
|
.C_HAS_ALMOST_EMPTY (0),
|
|
|
|
.C_HAS_ALMOST_FULL (0),
|
|
|
|
.C_AXI_TYPE (C_INTERFACE_TYPE == 1 ? 0 : C_AXI_TYPE),
|
|
|
|
|
|
|
|
.C_FIFO_TYPE ((C_APPLICATION_TYPE_RACH == 1)?0:C_APPLICATION_TYPE_RACH),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
|
|
|
|
.C_HAS_WR_RST (0),
|
|
|
|
.C_HAS_RD_RST (0),
|
|
|
|
.C_HAS_RST (1),
|
|
|
|
.C_HAS_SRST (0),
|
|
|
|
.C_DOUT_RST_VAL (0),
|
|
|
|
|
|
|
|
.C_HAS_VALID (0),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_HAS_WR_ACK (0),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
|
|
|
|
.C_HAS_DATA_COUNT ((C_COMMON_CLOCK == 1 && C_HAS_DATA_COUNTS_RACH == 1) ? 1 : 0),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_RACH + 1),
|
|
|
|
.C_HAS_RD_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_RACH == 1) ? 1 : 0),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_RACH + 1),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (1), // use extra logic is always true
|
|
|
|
.C_HAS_WR_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_RACH == 1) ? 1 : 0),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_RACH + 1),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (1),
|
|
|
|
.C_USE_EMBEDDED_REG (0),
|
|
|
|
.C_USE_DOUT_RST (0),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (1),
|
|
|
|
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_rach_dut
|
|
|
|
(
|
|
|
|
.CLK (S_ACLK),
|
|
|
|
.WR_CLK (S_ACLK),
|
|
|
|
.RD_CLK (M_ACLK),
|
|
|
|
.RST (inverted_reset),
|
|
|
|
.SRST (1'b0),
|
|
|
|
.WR_RST (inverted_reset),
|
|
|
|
.RD_RST (inverted_reset),
|
|
|
|
.WR_EN (rach_wr_en),
|
|
|
|
.RD_EN (rach_rd_en),
|
|
|
|
.PROG_FULL_THRESH (AXI_AR_PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT ({C_WR_PNTR_WIDTH_RACH{1'b0}}),
|
|
|
|
.PROG_FULL_THRESH_NEGATE ({C_WR_PNTR_WIDTH_RACH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH (AXI_AR_PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT ({C_WR_PNTR_WIDTH_RACH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE ({C_WR_PNTR_WIDTH_RACH{1'b0}}),
|
|
|
|
.INJECTDBITERR (AXI_AR_INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (AXI_AR_INJECTSBITERR),
|
|
|
|
|
|
|
|
.DIN (rach_din),
|
|
|
|
.DOUT (rach_dout_pkt),
|
|
|
|
.FULL (rach_full),
|
|
|
|
.EMPTY (rach_empty),
|
|
|
|
.ALMOST_FULL (),
|
|
|
|
.ALMOST_EMPTY (),
|
|
|
|
.PROG_FULL (AXI_AR_PROG_FULL),
|
|
|
|
.PROG_EMPTY (AXI_AR_PROG_EMPTY),
|
|
|
|
|
|
|
|
.WR_ACK (),
|
|
|
|
.OVERFLOW (axi_ar_overflow_i),
|
|
|
|
.VALID (),
|
|
|
|
.UNDERFLOW (axi_ar_underflow_i),
|
|
|
|
.DATA_COUNT (AXI_AR_DATA_COUNT),
|
|
|
|
.RD_DATA_COUNT (AXI_AR_RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (AXI_AR_WR_DATA_COUNT),
|
|
|
|
.SBITERR (AXI_AR_SBITERR),
|
|
|
|
.DBITERR (AXI_AR_DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy_rach),
|
|
|
|
.rd_rst_busy (rd_rst_busy_rach),
|
|
|
|
.wr_rst_i_out (),
|
|
|
|
.rd_rst_i_out (),
|
|
|
|
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.INT_CLK (INT_CLK)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign rach_s_axi_arready = (IS_8SERIES == 0) ? ~rach_full : (C_IMPLEMENTATION_TYPE_RACH == 5 || C_IMPLEMENTATION_TYPE_RACH == 13) ? ~(rach_full | wr_rst_busy_rach) : ~rach_full;
|
|
|
|
assign rach_m_axi_arvalid = ~rach_empty;
|
|
|
|
assign S_AXI_ARREADY = rach_s_axi_arready;
|
|
|
|
|
|
|
|
assign AXI_AR_UNDERFLOW = C_USE_COMMON_UNDERFLOW == 0 ? axi_ar_underflow_i : 0;
|
|
|
|
assign AXI_AR_OVERFLOW = C_USE_COMMON_OVERFLOW == 0 ? axi_ar_overflow_i : 0;
|
|
|
|
|
|
|
|
end endgenerate // axi_read_addr_channel
|
|
|
|
|
|
|
|
// Register Slice for Read Address Channel
|
|
|
|
generate if (C_RACH_TYPE == 1) begin : grach_reg_slice
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
|
|
|
.C_REG_CONFIG (C_REG_SLICE_MODE_RACH)
|
|
|
|
)
|
|
|
|
rach_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (axi_rs_rst),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (rach_din),
|
|
|
|
.S_VALID (S_AXI_ARVALID),
|
|
|
|
.S_READY (S_AXI_ARREADY),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (rach_dout),
|
|
|
|
.M_VALID (M_AXI_ARVALID),
|
|
|
|
.M_READY (M_AXI_ARREADY)
|
|
|
|
);
|
|
|
|
end endgenerate // grach_reg_slice
|
|
|
|
|
|
|
|
// Register Slice for Read Address Channel for MM Packet FIFO
|
|
|
|
generate if (C_RACH_TYPE == 0 && C_APPLICATION_TYPE_RACH == 1) begin : grach_reg_slice_mm_pkt_fifo
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
|
|
|
.C_REG_CONFIG (1)
|
|
|
|
)
|
|
|
|
reg_slice_mm_pkt_fifo_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (inverted_reset),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (rach_dout_pkt),
|
|
|
|
.S_VALID (arvalid_pkt),
|
|
|
|
.S_READY (arready_pkt),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (rach_dout),
|
|
|
|
.M_VALID (M_AXI_ARVALID),
|
|
|
|
.M_READY (M_AXI_ARREADY)
|
|
|
|
);
|
|
|
|
end endgenerate // grach_reg_slice_mm_pkt_fifo
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_RACH_TYPE == 0 && C_APPLICATION_TYPE_RACH != 1) begin : grach_m_axi_arvalid
|
|
|
|
assign M_AXI_ARVALID = rach_m_axi_arvalid;
|
|
|
|
assign rach_dout = rach_dout_pkt;
|
|
|
|
end endgenerate // grach_m_axi_arvalid
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_APPLICATION_TYPE_RACH == 1 && C_HAS_AXI_RD_CHANNEL == 1) begin : axi_mm_pkt_fifo_rd
|
|
|
|
assign rdch_rd_ok = rdch_s_axi_rvalid && rdch_rd_en;
|
|
|
|
assign arvalid_pkt = rach_m_axi_arvalid && arvalid_en;
|
|
|
|
assign accept_next_pkt = rach_m_axi_arvalid && arready_pkt && arvalid_en;
|
|
|
|
|
|
|
|
always@(posedge S_ACLK or posedge inverted_reset) begin
|
|
|
|
if(inverted_reset) begin
|
|
|
|
rdch_commited_space <= 0;
|
|
|
|
end else begin
|
|
|
|
if(rdch_rd_ok && !accept_next_pkt) begin
|
|
|
|
rdch_commited_space <= rdch_commited_space-1;
|
|
|
|
end else if(!rdch_rd_ok && accept_next_pkt) begin
|
|
|
|
rdch_commited_space <= rdch_commited_space+(rach_dout_pkt[ARADDR_OFFSET-1:ARLEN_OFFSET]+1);
|
|
|
|
end else if(rdch_rd_ok && accept_next_pkt) begin
|
|
|
|
rdch_commited_space <= rdch_commited_space+(rach_dout_pkt[ARADDR_OFFSET-1:ARLEN_OFFSET]);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end //Always end
|
|
|
|
|
|
|
|
always@(*) begin
|
|
|
|
rdch_free_space <= (C_WR_DEPTH_RDCH-(rdch_commited_space+rach_dout_pkt[ARADDR_OFFSET-1:ARLEN_OFFSET]+1));
|
|
|
|
end
|
|
|
|
|
|
|
|
assign arvalid_en = (rdch_free_space >= 0)?1:0;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate if (C_APPLICATION_TYPE_RACH != 1) begin : axi_mm_fifo_rd
|
|
|
|
assign arvalid_en = 1;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate if (IS_RD_DATA_CH == 1) begin : axi_read_data_channel
|
|
|
|
|
|
|
|
// Write protection when almost full or prog_full is high
|
|
|
|
assign rdch_we = (C_PROG_FULL_TYPE_RDCH != 0) ? rdch_m_axi_rready & M_AXI_RVALID : M_AXI_RVALID;
|
|
|
|
|
|
|
|
// Read protection when almost empty or prog_empty is high
|
|
|
|
assign rdch_re = (C_PROG_EMPTY_TYPE_RDCH != 0) ? rdch_s_axi_rvalid & S_AXI_RREADY : S_AXI_RREADY;
|
|
|
|
assign rdch_wr_en = (C_HAS_SLAVE_CE == 1) ? rdch_we & S_ACLK_EN : rdch_we;
|
|
|
|
assign rdch_rd_en = (C_HAS_MASTER_CE == 1) ? rdch_re & M_ACLK_EN : rdch_re;
|
|
|
|
|
|
|
|
FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_COMMON_CLOCK (C_COMMON_CLOCK),
|
|
|
|
.C_MEMORY_TYPE ((C_IMPLEMENTATION_TYPE_RDCH == 1 || C_IMPLEMENTATION_TYPE_RDCH == 11) ? 1 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_RDCH == 2 || C_IMPLEMENTATION_TYPE_RDCH == 12) ? 2 : 4),
|
|
|
|
.C_IMPLEMENTATION_TYPE ((C_IMPLEMENTATION_TYPE_RDCH == 1 || C_IMPLEMENTATION_TYPE_RDCH == 2) ? 0 :
|
|
|
|
(C_IMPLEMENTATION_TYPE_RDCH == 11 || C_IMPLEMENTATION_TYPE_RDCH == 12) ? 2 : 6),
|
|
|
|
.C_PRELOAD_REGS (1), // always FWFT for AXI
|
|
|
|
.C_PRELOAD_LATENCY (0), // always FWFT for AXI
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH_RDCH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH_RDCH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH_RDCH),
|
|
|
|
.C_DOUT_WIDTH (C_DIN_WIDTH_RDCH),
|
|
|
|
.C_RD_DEPTH (C_WR_DEPTH_RDCH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_WR_PNTR_WIDTH_RDCH),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE_RDCH),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL_RDCH),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE_RDCH),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL_RDCH),
|
|
|
|
.C_USE_ECC (C_USE_ECC_RDCH),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE_RDCH),
|
|
|
|
.C_HAS_ALMOST_EMPTY (0),
|
|
|
|
.C_HAS_ALMOST_FULL (0),
|
|
|
|
.C_AXI_TYPE (C_INTERFACE_TYPE == 1 ? 0 : C_AXI_TYPE),
|
|
|
|
|
|
|
|
.C_FIFO_TYPE (C_APPLICATION_TYPE_RDCH),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
|
|
|
|
.C_HAS_WR_RST (0),
|
|
|
|
.C_HAS_RD_RST (0),
|
|
|
|
.C_HAS_RST (1),
|
|
|
|
.C_HAS_SRST (0),
|
|
|
|
.C_DOUT_RST_VAL (0),
|
|
|
|
|
|
|
|
.C_HAS_VALID (0),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_HAS_WR_ACK (0),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
|
|
|
|
.C_HAS_DATA_COUNT ((C_COMMON_CLOCK == 1 && C_HAS_DATA_COUNTS_RDCH == 1) ? 1 : 0),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_RDCH + 1),
|
|
|
|
.C_HAS_RD_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_RDCH == 1) ? 1 : 0),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_RDCH + 1),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (1), // use extra logic is always true
|
|
|
|
.C_HAS_WR_DATA_COUNT ((C_COMMON_CLOCK == 0 && C_HAS_DATA_COUNTS_RDCH == 1) ? 1 : 0),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_PNTR_WIDTH_RDCH + 1),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (1),
|
|
|
|
.C_USE_EMBEDDED_REG (0),
|
|
|
|
.C_USE_DOUT_RST (0),
|
|
|
|
.C_MSGON_VAL (C_MSGON_VAL),
|
|
|
|
.C_ENABLE_RST_SYNC (1),
|
|
|
|
|
|
|
|
.C_COUNT_TYPE (C_COUNT_TYPE),
|
|
|
|
.C_DEFAULT_VALUE (C_DEFAULT_VALUE),
|
|
|
|
.C_ENABLE_RLOCS (C_ENABLE_RLOCS),
|
|
|
|
.C_HAS_BACKUP (C_HAS_BACKUP),
|
|
|
|
.C_HAS_INT_CLK (C_HAS_INT_CLK),
|
|
|
|
.C_MIF_FILE_NAME (C_MIF_FILE_NAME),
|
|
|
|
.C_HAS_MEMINIT_FILE (C_HAS_MEMINIT_FILE),
|
|
|
|
.C_INIT_WR_PNTR_VAL (C_INIT_WR_PNTR_VAL),
|
|
|
|
.C_OPTIMIZATION_MODE (C_OPTIMIZATION_MODE),
|
|
|
|
.C_PRIM_FIFO_TYPE (C_PRIM_FIFO_TYPE),
|
|
|
|
.C_RD_FREQ (C_RD_FREQ),
|
|
|
|
.C_USE_FIFO16_FLAGS (C_USE_FIFO16_FLAGS),
|
|
|
|
.C_WR_FREQ (C_WR_FREQ),
|
|
|
|
.C_WR_RESPONSE_LATENCY (C_WR_RESPONSE_LATENCY)
|
|
|
|
)
|
|
|
|
fifo_generator_v12_0_rdch_dut
|
|
|
|
(
|
|
|
|
.CLK (S_ACLK),
|
|
|
|
.WR_CLK (M_ACLK),
|
|
|
|
.RD_CLK (S_ACLK),
|
|
|
|
.RST (inverted_reset),
|
|
|
|
.SRST (1'b0),
|
|
|
|
.WR_RST (inverted_reset),
|
|
|
|
.RD_RST (inverted_reset),
|
|
|
|
.WR_EN (rdch_wr_en),
|
|
|
|
.RD_EN (rdch_rd_en),
|
|
|
|
.PROG_FULL_THRESH (AXI_R_PROG_FULL_THRESH),
|
|
|
|
.PROG_FULL_THRESH_ASSERT ({C_WR_PNTR_WIDTH_RDCH{1'b0}}),
|
|
|
|
.PROG_FULL_THRESH_NEGATE ({C_WR_PNTR_WIDTH_RDCH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH (AXI_R_PROG_EMPTY_THRESH),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT ({C_WR_PNTR_WIDTH_RDCH{1'b0}}),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE ({C_WR_PNTR_WIDTH_RDCH{1'b0}}),
|
|
|
|
.INJECTDBITERR (AXI_R_INJECTDBITERR),
|
|
|
|
.INJECTSBITERR (AXI_R_INJECTSBITERR),
|
|
|
|
|
|
|
|
.DIN (rdch_din),
|
|
|
|
.DOUT (rdch_dout),
|
|
|
|
.FULL (rdch_full),
|
|
|
|
.EMPTY (rdch_empty),
|
|
|
|
.ALMOST_FULL (),
|
|
|
|
.ALMOST_EMPTY (),
|
|
|
|
.PROG_FULL (AXI_R_PROG_FULL),
|
|
|
|
.PROG_EMPTY (AXI_R_PROG_EMPTY),
|
|
|
|
|
|
|
|
.WR_ACK (),
|
|
|
|
.OVERFLOW (axi_r_overflow_i),
|
|
|
|
.VALID (),
|
|
|
|
.UNDERFLOW (axi_r_underflow_i),
|
|
|
|
.DATA_COUNT (AXI_R_DATA_COUNT),
|
|
|
|
.RD_DATA_COUNT (AXI_R_RD_DATA_COUNT),
|
|
|
|
.WR_DATA_COUNT (AXI_R_WR_DATA_COUNT),
|
|
|
|
.SBITERR (AXI_R_SBITERR),
|
|
|
|
.DBITERR (AXI_R_DBITERR),
|
|
|
|
.wr_rst_busy (wr_rst_busy_rdch),
|
|
|
|
.rd_rst_busy (rd_rst_busy_rdch),
|
|
|
|
.wr_rst_i_out (),
|
|
|
|
.rd_rst_i_out (),
|
|
|
|
|
|
|
|
.BACKUP (BACKUP),
|
|
|
|
.BACKUP_MARKER (BACKUP_MARKER),
|
|
|
|
.INT_CLK (INT_CLK)
|
|
|
|
);
|
|
|
|
|
|
|
|
assign rdch_s_axi_rvalid = ~rdch_empty;
|
|
|
|
assign rdch_m_axi_rready = (IS_8SERIES == 0) ? ~rdch_full : (C_IMPLEMENTATION_TYPE_RDCH == 5 || C_IMPLEMENTATION_TYPE_RDCH == 13) ? ~(rdch_full | wr_rst_busy_rdch) : ~rdch_full;
|
|
|
|
assign S_AXI_RVALID = rdch_s_axi_rvalid;
|
|
|
|
assign M_AXI_RREADY = rdch_m_axi_rready;
|
|
|
|
|
|
|
|
assign AXI_R_UNDERFLOW = C_USE_COMMON_UNDERFLOW == 0 ? axi_r_underflow_i : 0;
|
|
|
|
assign AXI_R_OVERFLOW = C_USE_COMMON_OVERFLOW == 0 ? axi_r_overflow_i : 0;
|
|
|
|
|
|
|
|
end endgenerate //axi_read_data_channel
|
|
|
|
|
|
|
|
// Register Slice for read Data Channel
|
|
|
|
generate if (C_RDCH_TYPE == 1) begin : grdch_reg_slice
|
|
|
|
|
|
|
|
fifo_generator_v12_0_axic_reg_slice
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_WIDTH (C_DIN_WIDTH_RDCH),
|
|
|
|
.C_REG_CONFIG (C_REG_SLICE_MODE_RDCH)
|
|
|
|
)
|
|
|
|
rdch_reg_slice_inst
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
.ACLK (S_ACLK),
|
|
|
|
.ARESET (axi_rs_rst),
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
.S_PAYLOAD_DATA (rdch_din),
|
|
|
|
.S_VALID (M_AXI_RVALID),
|
|
|
|
.S_READY (M_AXI_RREADY),
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
.M_PAYLOAD_DATA (rdch_dout),
|
|
|
|
.M_VALID (S_AXI_RVALID),
|
|
|
|
.M_READY (S_AXI_RREADY)
|
|
|
|
);
|
|
|
|
end endgenerate // grdch_reg_slice
|
|
|
|
|
|
|
|
|
|
|
|
assign axi_rd_underflow_i = C_USE_COMMON_UNDERFLOW == 1 ? (axi_ar_underflow_i || axi_r_underflow_i) : 0;
|
|
|
|
assign axi_rd_overflow_i = C_USE_COMMON_OVERFLOW == 1 ? (axi_ar_overflow_i || axi_r_overflow_i) : 0;
|
|
|
|
|
|
|
|
|
|
|
|
generate if (IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) begin : axi_full_rach_output
|
|
|
|
assign M_AXI_ARADDR = rach_dout[ARID_OFFSET-1:ARADDR_OFFSET];
|
|
|
|
assign M_AXI_ARLEN = rach_dout[ARADDR_OFFSET-1:ARLEN_OFFSET];
|
|
|
|
assign M_AXI_ARSIZE = rach_dout[ARLEN_OFFSET-1:ARSIZE_OFFSET];
|
|
|
|
assign M_AXI_ARBURST = rach_dout[ARSIZE_OFFSET-1:ARBURST_OFFSET];
|
|
|
|
assign M_AXI_ARLOCK = rach_dout[ARBURST_OFFSET-1:ARLOCK_OFFSET];
|
|
|
|
assign M_AXI_ARCACHE = rach_dout[ARLOCK_OFFSET-1:ARCACHE_OFFSET];
|
|
|
|
assign M_AXI_ARPROT = rach_dout[ARCACHE_OFFSET-1:ARPROT_OFFSET];
|
|
|
|
assign M_AXI_ARQOS = rach_dout[ARPROT_OFFSET-1:ARQOS_OFFSET];
|
|
|
|
assign rach_din[ARID_OFFSET-1:ARADDR_OFFSET] = S_AXI_ARADDR;
|
|
|
|
assign rach_din[ARADDR_OFFSET-1:ARLEN_OFFSET] = S_AXI_ARLEN;
|
|
|
|
assign rach_din[ARLEN_OFFSET-1:ARSIZE_OFFSET] = S_AXI_ARSIZE;
|
|
|
|
assign rach_din[ARSIZE_OFFSET-1:ARBURST_OFFSET] = S_AXI_ARBURST;
|
|
|
|
assign rach_din[ARBURST_OFFSET-1:ARLOCK_OFFSET] = S_AXI_ARLOCK;
|
|
|
|
assign rach_din[ARLOCK_OFFSET-1:ARCACHE_OFFSET] = S_AXI_ARCACHE;
|
|
|
|
assign rach_din[ARCACHE_OFFSET-1:ARPROT_OFFSET] = S_AXI_ARPROT;
|
|
|
|
assign rach_din[ARPROT_OFFSET-1:ARQOS_OFFSET] = S_AXI_ARQOS;
|
|
|
|
end endgenerate // axi_full_rach_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_AXI_TYPE == 1) begin : axi_arregion
|
|
|
|
assign M_AXI_ARREGION = rach_dout[ARQOS_OFFSET-1:ARREGION_OFFSET];
|
|
|
|
end endgenerate // axi_arregion
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_AXI_TYPE != 1) begin : naxi_arregion
|
|
|
|
assign M_AXI_ARREGION = 0;
|
|
|
|
end endgenerate // naxi_arregion
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_HAS_AXI_ARUSER == 1) begin : axi_aruser
|
|
|
|
assign M_AXI_ARUSER = rach_dout[ARREGION_OFFSET-1:ARUSER_OFFSET];
|
|
|
|
end endgenerate // axi_aruser
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_HAS_AXI_ARUSER == 0) begin : naxi_aruser
|
|
|
|
assign M_AXI_ARUSER = 0;
|
|
|
|
end endgenerate // naxi_aruser
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : axi_arid
|
|
|
|
assign M_AXI_ARID = rach_dout[C_DIN_WIDTH_RACH-1:ARID_OFFSET];
|
|
|
|
end endgenerate // axi_arid
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_HAS_AXI_ID == 0) begin : naxi_arid
|
|
|
|
assign M_AXI_ARID = 0;
|
|
|
|
end endgenerate // naxi_arid
|
|
|
|
|
|
|
|
generate if (IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) begin : axi_full_rdch_output
|
|
|
|
assign S_AXI_RDATA = rdch_dout[RID_OFFSET-1:RDATA_OFFSET];
|
|
|
|
assign S_AXI_RRESP = rdch_dout[RDATA_OFFSET-1:RRESP_OFFSET];
|
|
|
|
assign S_AXI_RLAST = rdch_dout[0];
|
|
|
|
assign rdch_din[RID_OFFSET-1:RDATA_OFFSET] = M_AXI_RDATA;
|
|
|
|
assign rdch_din[RDATA_OFFSET-1:RRESP_OFFSET] = M_AXI_RRESP;
|
|
|
|
assign rdch_din[0] = M_AXI_RLAST;
|
|
|
|
end endgenerate // axi_full_rdch_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) && C_HAS_AXI_RUSER == 1) begin : axi_full_ruser_output
|
|
|
|
assign S_AXI_RUSER = rdch_dout[RRESP_OFFSET-1:RUSER_OFFSET];
|
|
|
|
end endgenerate // axi_full_ruser_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) && C_HAS_AXI_RUSER == 0) begin : axi_full_nruser_output
|
|
|
|
assign S_AXI_RUSER = 0;
|
|
|
|
end endgenerate // axi_full_nruser_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : axi_rid
|
|
|
|
assign S_AXI_RID = rdch_dout[C_DIN_WIDTH_RDCH-1:RID_OFFSET];
|
|
|
|
end endgenerate // axi_rid
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) && C_HAS_AXI_ID == 0) begin : naxi_rid
|
|
|
|
assign S_AXI_RID = 0;
|
|
|
|
end endgenerate // naxi_rid
|
|
|
|
|
|
|
|
generate if (IS_AXI_LITE_RACH == 1 || (IS_AXI_LITE == 1 && C_RACH_TYPE == 1)) begin : axi_lite_rach_output1
|
|
|
|
assign rach_din = {S_AXI_ARADDR, S_AXI_ARPROT};
|
|
|
|
assign M_AXI_ARADDR = rach_dout[C_DIN_WIDTH_RACH-1:ARADDR_OFFSET];
|
|
|
|
assign M_AXI_ARPROT = rach_dout[ARADDR_OFFSET-1:ARPROT_OFFSET];
|
|
|
|
end endgenerate // axi_lite_rach_output
|
|
|
|
|
|
|
|
generate if (IS_AXI_LITE_RDCH == 1 || (IS_AXI_LITE == 1 && C_RDCH_TYPE == 1)) begin : axi_lite_rdch_output1
|
|
|
|
assign rdch_din = {M_AXI_RDATA, M_AXI_RRESP};
|
|
|
|
assign S_AXI_RDATA = rdch_dout[C_DIN_WIDTH_RDCH-1:RDATA_OFFSET];
|
|
|
|
assign S_AXI_RRESP = rdch_dout[RDATA_OFFSET-1:RRESP_OFFSET];
|
|
|
|
end endgenerate // axi_lite_rdch_output
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_HAS_AXI_ARUSER == 1) begin : grach_din1
|
|
|
|
assign rach_din[ARREGION_OFFSET-1:ARUSER_OFFSET] = S_AXI_ARUSER;
|
|
|
|
end endgenerate // grach_din1
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : grach_din2
|
|
|
|
assign rach_din[C_DIN_WIDTH_RACH-1:ARID_OFFSET] = S_AXI_ARID;
|
|
|
|
end endgenerate // grach_din2
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RACH == 1 || (IS_AXI_FULL == 1 && C_RACH_TYPE == 1)) && C_AXI_TYPE == 1) begin
|
|
|
|
assign rach_din[ARQOS_OFFSET-1:ARREGION_OFFSET] = S_AXI_ARREGION;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) && C_HAS_AXI_RUSER == 1) begin : grdch_din1
|
|
|
|
assign rdch_din[RRESP_OFFSET-1:RUSER_OFFSET] = M_AXI_RUSER;
|
|
|
|
end endgenerate // grdch_din1
|
|
|
|
|
|
|
|
generate if ((IS_AXI_FULL_RDCH == 1 || (IS_AXI_FULL == 1 && C_RDCH_TYPE == 1)) && C_HAS_AXI_ID == 1) begin : grdch_din2
|
|
|
|
assign rdch_din[C_DIN_WIDTH_RDCH-1:RID_OFFSET] = M_AXI_RID;
|
|
|
|
end endgenerate // grdch_din2
|
|
|
|
|
|
|
|
//end of axi_read_channel
|
|
|
|
|
|
|
|
generate if (C_INTERFACE_TYPE == 1 && C_USE_COMMON_UNDERFLOW == 1) begin : gaxi_comm_uf
|
|
|
|
assign UNDERFLOW = (C_HAS_AXI_WR_CHANNEL == 1 && C_HAS_AXI_RD_CHANNEL == 1) ? (axi_wr_underflow_i || axi_rd_underflow_i) :
|
|
|
|
(C_HAS_AXI_WR_CHANNEL == 1 && C_HAS_AXI_RD_CHANNEL == 0) ? axi_wr_underflow_i :
|
|
|
|
(C_HAS_AXI_WR_CHANNEL == 0 && C_HAS_AXI_RD_CHANNEL == 1) ? axi_rd_underflow_i : 0;
|
|
|
|
end endgenerate // gaxi_comm_uf
|
|
|
|
|
|
|
|
generate if (C_INTERFACE_TYPE == 1 && C_USE_COMMON_OVERFLOW == 1) begin : gaxi_comm_of
|
|
|
|
assign OVERFLOW = (C_HAS_AXI_WR_CHANNEL == 1 && C_HAS_AXI_RD_CHANNEL == 1) ? (axi_wr_overflow_i || axi_rd_overflow_i) :
|
|
|
|
(C_HAS_AXI_WR_CHANNEL == 1 && C_HAS_AXI_RD_CHANNEL == 0) ? axi_wr_overflow_i :
|
|
|
|
(C_HAS_AXI_WR_CHANNEL == 0 && C_HAS_AXI_RD_CHANNEL == 1) ? axi_rd_overflow_i : 0;
|
|
|
|
end endgenerate // gaxi_comm_of
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Pass Through Logic or Wiring Logic
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Pass Through Logic for Read Channel
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Wiring logic for Write Address Channel
|
|
|
|
generate if (C_WACH_TYPE == 2) begin : gwach_pass_through
|
|
|
|
assign M_AXI_AWID = S_AXI_AWID;
|
|
|
|
assign M_AXI_AWADDR = S_AXI_AWADDR;
|
|
|
|
assign M_AXI_AWLEN = S_AXI_AWLEN;
|
|
|
|
assign M_AXI_AWSIZE = S_AXI_AWSIZE;
|
|
|
|
assign M_AXI_AWBURST = S_AXI_AWBURST;
|
|
|
|
assign M_AXI_AWLOCK = S_AXI_AWLOCK;
|
|
|
|
assign M_AXI_AWCACHE = S_AXI_AWCACHE;
|
|
|
|
assign M_AXI_AWPROT = S_AXI_AWPROT;
|
|
|
|
assign M_AXI_AWQOS = S_AXI_AWQOS;
|
|
|
|
assign M_AXI_AWREGION = S_AXI_AWREGION;
|
|
|
|
assign M_AXI_AWUSER = S_AXI_AWUSER;
|
|
|
|
assign S_AXI_AWREADY = M_AXI_AWREADY;
|
|
|
|
assign M_AXI_AWVALID = S_AXI_AWVALID;
|
|
|
|
end endgenerate // gwach_pass_through;
|
|
|
|
|
|
|
|
// Wiring logic for Write Data Channel
|
|
|
|
generate if (C_WDCH_TYPE == 2) begin : gwdch_pass_through
|
|
|
|
assign M_AXI_WID = S_AXI_WID;
|
|
|
|
assign M_AXI_WDATA = S_AXI_WDATA;
|
|
|
|
assign M_AXI_WSTRB = S_AXI_WSTRB;
|
|
|
|
assign M_AXI_WLAST = S_AXI_WLAST;
|
|
|
|
assign M_AXI_WUSER = S_AXI_WUSER;
|
|
|
|
assign S_AXI_WREADY = M_AXI_WREADY;
|
|
|
|
assign M_AXI_WVALID = S_AXI_WVALID;
|
|
|
|
end endgenerate // gwdch_pass_through;
|
|
|
|
|
|
|
|
// Wiring logic for Write Response Channel
|
|
|
|
generate if (C_WRCH_TYPE == 2) begin : gwrch_pass_through
|
|
|
|
assign S_AXI_BID = M_AXI_BID;
|
|
|
|
assign S_AXI_BRESP = M_AXI_BRESP;
|
|
|
|
assign S_AXI_BUSER = M_AXI_BUSER;
|
|
|
|
assign M_AXI_BREADY = S_AXI_BREADY;
|
|
|
|
assign S_AXI_BVALID = M_AXI_BVALID;
|
|
|
|
end endgenerate // gwrch_pass_through;
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Pass Through Logic for Read Channel
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Wiring logic for Read Address Channel
|
|
|
|
generate if (C_RACH_TYPE == 2) begin : grach_pass_through
|
|
|
|
assign M_AXI_ARID = S_AXI_ARID;
|
|
|
|
assign M_AXI_ARADDR = S_AXI_ARADDR;
|
|
|
|
assign M_AXI_ARLEN = S_AXI_ARLEN;
|
|
|
|
assign M_AXI_ARSIZE = S_AXI_ARSIZE;
|
|
|
|
assign M_AXI_ARBURST = S_AXI_ARBURST;
|
|
|
|
assign M_AXI_ARLOCK = S_AXI_ARLOCK;
|
|
|
|
assign M_AXI_ARCACHE = S_AXI_ARCACHE;
|
|
|
|
assign M_AXI_ARPROT = S_AXI_ARPROT;
|
|
|
|
assign M_AXI_ARQOS = S_AXI_ARQOS;
|
|
|
|
assign M_AXI_ARREGION = S_AXI_ARREGION;
|
|
|
|
assign M_AXI_ARUSER = S_AXI_ARUSER;
|
|
|
|
assign S_AXI_ARREADY = M_AXI_ARREADY;
|
|
|
|
assign M_AXI_ARVALID = S_AXI_ARVALID;
|
|
|
|
end endgenerate // grach_pass_through;
|
|
|
|
|
|
|
|
// Wiring logic for Read Data Channel
|
|
|
|
generate if (C_RDCH_TYPE == 2) begin : grdch_pass_through
|
|
|
|
assign S_AXI_RID = M_AXI_RID;
|
|
|
|
assign S_AXI_RLAST = M_AXI_RLAST;
|
|
|
|
assign S_AXI_RUSER = M_AXI_RUSER;
|
|
|
|
assign S_AXI_RDATA = M_AXI_RDATA;
|
|
|
|
assign S_AXI_RRESP = M_AXI_RRESP;
|
|
|
|
assign S_AXI_RVALID = M_AXI_RVALID;
|
|
|
|
assign M_AXI_RREADY = S_AXI_RREADY;
|
|
|
|
end endgenerate // grdch_pass_through;
|
|
|
|
|
|
|
|
// Wiring logic for AXI Streaming
|
|
|
|
generate if (C_AXIS_TYPE == 2) begin : gaxis_pass_through
|
|
|
|
assign M_AXIS_TDATA = S_AXIS_TDATA;
|
|
|
|
assign M_AXIS_TSTRB = S_AXIS_TSTRB;
|
|
|
|
assign M_AXIS_TKEEP = S_AXIS_TKEEP;
|
|
|
|
assign M_AXIS_TID = S_AXIS_TID;
|
|
|
|
assign M_AXIS_TDEST = S_AXIS_TDEST;
|
|
|
|
assign M_AXIS_TUSER = S_AXIS_TUSER;
|
|
|
|
assign M_AXIS_TLAST = S_AXIS_TLAST;
|
|
|
|
assign S_AXIS_TREADY = M_AXIS_TREADY;
|
|
|
|
assign M_AXIS_TVALID = S_AXIS_TVALID;
|
|
|
|
end endgenerate // gaxis_pass_through;
|
|
|
|
|
|
|
|
|
|
|
|
endmodule //FIFO_GENERATOR_v12_0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Declaration of top-level module for Conventional FIFO
|
|
|
|
******************************************************************************/
|
|
|
|
module FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
#(
|
|
|
|
parameter C_COMMON_CLOCK = 0,
|
|
|
|
parameter C_COUNT_TYPE = 0,
|
|
|
|
parameter C_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_DEFAULT_VALUE = "",
|
|
|
|
parameter C_DIN_WIDTH = 8,
|
|
|
|
parameter C_DOUT_RST_VAL = "",
|
|
|
|
parameter C_DOUT_WIDTH = 8,
|
|
|
|
parameter C_ENABLE_RLOCS = 0,
|
|
|
|
parameter C_FAMILY = "virtex7", //Not allowed in Verilog model
|
|
|
|
parameter C_FULL_FLAGS_RST_VAL = 1,
|
|
|
|
parameter C_HAS_ALMOST_EMPTY = 0,
|
|
|
|
parameter C_HAS_ALMOST_FULL = 0,
|
|
|
|
parameter C_HAS_BACKUP = 0,
|
|
|
|
parameter C_HAS_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_INT_CLK = 0,
|
|
|
|
parameter C_HAS_MEMINIT_FILE = 0,
|
|
|
|
parameter C_HAS_OVERFLOW = 0,
|
|
|
|
parameter C_HAS_RD_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_RD_RST = 0,
|
|
|
|
parameter C_HAS_RST = 0,
|
|
|
|
parameter C_HAS_SRST = 0,
|
|
|
|
parameter C_HAS_UNDERFLOW = 0,
|
|
|
|
parameter C_HAS_VALID = 0,
|
|
|
|
parameter C_HAS_WR_ACK = 0,
|
|
|
|
parameter C_HAS_WR_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_WR_RST = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE = 0,
|
|
|
|
parameter C_INIT_WR_PNTR_VAL = 0,
|
|
|
|
parameter C_MEMORY_TYPE = 1,
|
|
|
|
parameter C_MIF_FILE_NAME = "",
|
|
|
|
parameter C_OPTIMIZATION_MODE = 0,
|
|
|
|
parameter C_OVERFLOW_LOW = 0,
|
|
|
|
parameter C_PRELOAD_LATENCY = 1,
|
|
|
|
parameter C_PRELOAD_REGS = 0,
|
|
|
|
parameter C_PRIM_FIFO_TYPE = "",
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE = 0,
|
|
|
|
parameter C_RD_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_RD_DEPTH = 256,
|
|
|
|
parameter C_RD_FREQ = 1,
|
|
|
|
parameter C_RD_PNTR_WIDTH = 8,
|
|
|
|
parameter C_UNDERFLOW_LOW = 0,
|
|
|
|
parameter C_USE_DOUT_RST = 0,
|
|
|
|
parameter C_USE_ECC = 0,
|
|
|
|
parameter C_USE_EMBEDDED_REG = 0,
|
|
|
|
parameter C_USE_FIFO16_FLAGS = 0,
|
|
|
|
parameter C_USE_FWFT_DATA_COUNT = 0,
|
|
|
|
parameter C_VALID_LOW = 0,
|
|
|
|
parameter C_WR_ACK_LOW = 0,
|
|
|
|
parameter C_WR_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_WR_DEPTH = 256,
|
|
|
|
parameter C_WR_FREQ = 1,
|
|
|
|
parameter C_WR_PNTR_WIDTH = 8,
|
|
|
|
parameter C_WR_RESPONSE_LATENCY = 1,
|
|
|
|
parameter C_MSGON_VAL = 1,
|
|
|
|
parameter C_ENABLE_RST_SYNC = 1,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE = 0,
|
|
|
|
parameter C_FIFO_TYPE = 0,
|
|
|
|
parameter C_SYNCHRONIZER_STAGE = 2,
|
|
|
|
parameter C_AXI_TYPE = 0
|
|
|
|
)
|
|
|
|
|
|
|
|
(
|
|
|
|
input BACKUP,
|
|
|
|
input BACKUP_MARKER,
|
|
|
|
input CLK,
|
|
|
|
input RST,
|
|
|
|
input SRST,
|
|
|
|
input WR_CLK,
|
|
|
|
input WR_RST,
|
|
|
|
input RD_CLK,
|
|
|
|
input RD_RST,
|
|
|
|
input [C_DIN_WIDTH-1:0] DIN,
|
|
|
|
input WR_EN,
|
|
|
|
input RD_EN,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE,
|
|
|
|
input INT_CLK,
|
|
|
|
input INJECTDBITERR,
|
|
|
|
input INJECTSBITERR,
|
|
|
|
|
|
|
|
output [C_DOUT_WIDTH-1:0] DOUT,
|
|
|
|
output FULL,
|
|
|
|
output ALMOST_FULL,
|
|
|
|
output WR_ACK,
|
|
|
|
output OVERFLOW,
|
|
|
|
output EMPTY,
|
|
|
|
output ALMOST_EMPTY,
|
|
|
|
output VALID,
|
|
|
|
output UNDERFLOW,
|
|
|
|
output [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT,
|
|
|
|
output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT,
|
|
|
|
output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT,
|
|
|
|
output PROG_FULL,
|
|
|
|
output PROG_EMPTY,
|
|
|
|
output SBITERR,
|
|
|
|
output DBITERR,
|
|
|
|
output wr_rst_busy,
|
|
|
|
output rd_rst_busy,
|
|
|
|
output wr_rst_i_out,
|
|
|
|
output rd_rst_i_out
|
|
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Definition of Parameters
|
|
|
|
******************************************************************************
|
|
|
|
* C_COMMON_CLOCK : Common Clock (1), Independent Clocks (0)
|
|
|
|
* C_COUNT_TYPE : *not used
|
|
|
|
* C_DATA_COUNT_WIDTH : Width of DATA_COUNT bus
|
|
|
|
* C_DEFAULT_VALUE : *not used
|
|
|
|
* C_DIN_WIDTH : Width of DIN bus
|
|
|
|
* C_DOUT_RST_VAL : Reset value of DOUT
|
|
|
|
* C_DOUT_WIDTH : Width of DOUT bus
|
|
|
|
* C_ENABLE_RLOCS : *not used
|
|
|
|
* C_FAMILY : not used in bhv model
|
|
|
|
* C_FULL_FLAGS_RST_VAL : Full flags rst val (0 or 1)
|
|
|
|
* C_HAS_ALMOST_EMPTY : 1=Core has ALMOST_EMPTY flag
|
|
|
|
* C_HAS_ALMOST_FULL : 1=Core has ALMOST_FULL flag
|
|
|
|
* C_HAS_BACKUP : *not used
|
|
|
|
* C_HAS_DATA_COUNT : 1=Core has DATA_COUNT bus
|
|
|
|
* C_HAS_INT_CLK : not used in bhv model
|
|
|
|
* C_HAS_MEMINIT_FILE : *not used
|
|
|
|
* C_HAS_OVERFLOW : 1=Core has OVERFLOW flag
|
|
|
|
* C_HAS_RD_DATA_COUNT : 1=Core has RD_DATA_COUNT bus
|
|
|
|
* C_HAS_RD_RST : *not used
|
|
|
|
* C_HAS_RST : 1=Core has Async Rst
|
|
|
|
* C_HAS_SRST : 1=Core has Sync Rst
|
|
|
|
* C_HAS_UNDERFLOW : 1=Core has UNDERFLOW flag
|
|
|
|
* C_HAS_VALID : 1=Core has VALID flag
|
|
|
|
* C_HAS_WR_ACK : 1=Core has WR_ACK flag
|
|
|
|
* C_HAS_WR_DATA_COUNT : 1=Core has WR_DATA_COUNT bus
|
|
|
|
* C_HAS_WR_RST : *not used
|
|
|
|
* C_IMPLEMENTATION_TYPE : 0=Common-Clock Bram/Dram
|
|
|
|
* 1=Common-Clock ShiftRam
|
|
|
|
* 2=Indep. Clocks Bram/Dram
|
|
|
|
* 3=Virtex-4 Built-in
|
|
|
|
* 4=Virtex-5 Built-in
|
|
|
|
* C_INIT_WR_PNTR_VAL : *not used
|
|
|
|
* C_MEMORY_TYPE : 1=Block RAM
|
|
|
|
* 2=Distributed RAM
|
|
|
|
* 3=Shift RAM
|
|
|
|
* 4=Built-in FIFO
|
|
|
|
* C_MIF_FILE_NAME : *not used
|
|
|
|
* C_OPTIMIZATION_MODE : *not used
|
|
|
|
* C_OVERFLOW_LOW : 1=OVERFLOW active low
|
|
|
|
* C_PRELOAD_LATENCY : Latency of read: 0, 1, 2
|
|
|
|
* C_PRELOAD_REGS : 1=Use output registers
|
|
|
|
* C_PRIM_FIFO_TYPE : not used in bhv model
|
|
|
|
* C_PROG_EMPTY_THRESH_ASSERT_VAL: PROG_EMPTY assert threshold
|
|
|
|
* C_PROG_EMPTY_THRESH_NEGATE_VAL: PROG_EMPTY negate threshold
|
|
|
|
* C_PROG_EMPTY_TYPE : 0=No programmable empty
|
|
|
|
* 1=Single prog empty thresh constant
|
|
|
|
* 2=Multiple prog empty thresh constants
|
|
|
|
* 3=Single prog empty thresh input
|
|
|
|
* 4=Multiple prog empty thresh inputs
|
|
|
|
* C_PROG_FULL_THRESH_ASSERT_VAL : PROG_FULL assert threshold
|
|
|
|
* C_PROG_FULL_THRESH_NEGATE_VAL : PROG_FULL negate threshold
|
|
|
|
* C_PROG_FULL_TYPE : 0=No prog full
|
|
|
|
* 1=Single prog full thresh constant
|
|
|
|
* 2=Multiple prog full thresh constants
|
|
|
|
* 3=Single prog full thresh input
|
|
|
|
* 4=Multiple prog full thresh inputs
|
|
|
|
* C_RD_DATA_COUNT_WIDTH : Width of RD_DATA_COUNT bus
|
|
|
|
* C_RD_DEPTH : Depth of read interface (2^N)
|
|
|
|
* C_RD_FREQ : not used in bhv model
|
|
|
|
* C_RD_PNTR_WIDTH : always log2(C_RD_DEPTH)
|
|
|
|
* C_UNDERFLOW_LOW : 1=UNDERFLOW active low
|
|
|
|
* C_USE_DOUT_RST : 1=Resets DOUT on RST
|
|
|
|
* C_USE_ECC : Used for error injection purpose
|
|
|
|
* C_USE_EMBEDDED_REG : 1=Use BRAM embedded output register
|
|
|
|
* C_USE_FIFO16_FLAGS : not used in bhv model
|
|
|
|
* C_USE_FWFT_DATA_COUNT : 1=Use extra logic for FWFT data count
|
|
|
|
* C_VALID_LOW : 1=VALID active low
|
|
|
|
* C_WR_ACK_LOW : 1=WR_ACK active low
|
|
|
|
* C_WR_DATA_COUNT_WIDTH : Width of WR_DATA_COUNT bus
|
|
|
|
* C_WR_DEPTH : Depth of write interface (2^N)
|
|
|
|
* C_WR_FREQ : not used in bhv model
|
|
|
|
* C_WR_PNTR_WIDTH : always log2(C_WR_DEPTH)
|
|
|
|
* C_WR_RESPONSE_LATENCY : *not used
|
|
|
|
* C_MSGON_VAL : *not used by bhv model
|
|
|
|
* C_ENABLE_RST_SYNC : 0 = Use WR_RST & RD_RST
|
|
|
|
* 1 = Use RST
|
|
|
|
* C_ERROR_INJECTION_TYPE : 0 = No error injection
|
|
|
|
* 1 = Single bit error injection only
|
|
|
|
* 2 = Double bit error injection only
|
|
|
|
* 3 = Single and double bit error injection
|
|
|
|
******************************************************************************
|
|
|
|
* Definition of Ports
|
|
|
|
******************************************************************************
|
|
|
|
* BACKUP : Not used
|
|
|
|
* BACKUP_MARKER: Not used
|
|
|
|
* CLK : Clock
|
|
|
|
* DIN : Input data bus
|
|
|
|
* PROG_EMPTY_THRESH : Threshold for Programmable Empty Flag
|
|
|
|
* PROG_EMPTY_THRESH_ASSERT: Threshold for Programmable Empty Flag
|
|
|
|
* PROG_EMPTY_THRESH_NEGATE: Threshold for Programmable Empty Flag
|
|
|
|
* PROG_FULL_THRESH : Threshold for Programmable Full Flag
|
|
|
|
* PROG_FULL_THRESH_ASSERT : Threshold for Programmable Full Flag
|
|
|
|
* PROG_FULL_THRESH_NEGATE : Threshold for Programmable Full Flag
|
|
|
|
* RD_CLK : Read Domain Clock
|
|
|
|
* RD_EN : Read enable
|
|
|
|
* RD_RST : Read Reset
|
|
|
|
* RST : Asynchronous Reset
|
|
|
|
* SRST : Synchronous Reset
|
|
|
|
* WR_CLK : Write Domain Clock
|
|
|
|
* WR_EN : Write enable
|
|
|
|
* WR_RST : Write Reset
|
|
|
|
* INT_CLK : Internal Clock
|
|
|
|
* INJECTSBITERR: Inject Signle bit error
|
|
|
|
* INJECTDBITERR: Inject Double bit error
|
|
|
|
* ALMOST_EMPTY : One word remaining in FIFO
|
|
|
|
* ALMOST_FULL : One empty space remaining in FIFO
|
|
|
|
* DATA_COUNT : Number of data words in fifo( synchronous to CLK)
|
|
|
|
* DOUT : Output data bus
|
|
|
|
* EMPTY : Empty flag
|
|
|
|
* FULL : Full flag
|
|
|
|
* OVERFLOW : Last write rejected
|
|
|
|
* PROG_EMPTY : Programmable Empty Flag
|
|
|
|
* PROG_FULL : Programmable Full Flag
|
|
|
|
* RD_DATA_COUNT: Number of data words in fifo (synchronous to RD_CLK)
|
|
|
|
* UNDERFLOW : Last read rejected
|
|
|
|
* VALID : Last read acknowledged, DOUT bus VALID
|
|
|
|
* WR_ACK : Last write acknowledged
|
|
|
|
* WR_DATA_COUNT: Number of data words in fifo (synchronous to WR_CLK)
|
|
|
|
* SBITERR : Single Bit ECC Error Detected
|
|
|
|
* DBITERR : Double Bit ECC Error Detected
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//- Internal Signals for delayed input signals
|
|
|
|
//- All the input signals except Clock are delayed by 100 ps and then given to
|
|
|
|
//- the models.
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
reg rst_delayed ;
|
|
|
|
reg empty_fb ;
|
|
|
|
reg srst_delayed ;
|
|
|
|
reg wr_rst_delayed ;
|
|
|
|
reg rd_rst_delayed ;
|
|
|
|
reg wr_en_delayed ;
|
|
|
|
reg rd_en_delayed ;
|
|
|
|
reg [C_DIN_WIDTH-1:0] din_delayed ;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] prog_empty_thresh_delayed ;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] prog_empty_thresh_assert_delayed ;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] prog_empty_thresh_negate_delayed ;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] prog_full_thresh_delayed ;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] prog_full_thresh_assert_delayed ;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] prog_full_thresh_negate_delayed ;
|
|
|
|
reg injectdbiterr_delayed ;
|
|
|
|
reg injectsbiterr_delayed ;
|
|
|
|
wire empty_p0_out;
|
|
|
|
|
|
|
|
always @* rst_delayed <= #`TCQ RST ;
|
|
|
|
always @* empty_fb <= #`TCQ empty_p0_out ;
|
|
|
|
always @* srst_delayed <= #`TCQ SRST ;
|
|
|
|
always @* wr_rst_delayed <= #`TCQ WR_RST ;
|
|
|
|
always @* rd_rst_delayed <= #`TCQ RD_RST ;
|
|
|
|
always @* din_delayed <= #`TCQ DIN ;
|
|
|
|
always @* wr_en_delayed <= #`TCQ WR_EN ;
|
|
|
|
always @* rd_en_delayed <= #`TCQ RD_EN ;
|
|
|
|
always @* prog_empty_thresh_delayed <= #`TCQ PROG_EMPTY_THRESH ;
|
|
|
|
always @* prog_empty_thresh_assert_delayed <= #`TCQ PROG_EMPTY_THRESH_ASSERT ;
|
|
|
|
always @* prog_empty_thresh_negate_delayed <= #`TCQ PROG_EMPTY_THRESH_NEGATE ;
|
|
|
|
always @* prog_full_thresh_delayed <= #`TCQ PROG_FULL_THRESH ;
|
|
|
|
always @* prog_full_thresh_assert_delayed <= #`TCQ PROG_FULL_THRESH_ASSERT ;
|
|
|
|
always @* prog_full_thresh_negate_delayed <= #`TCQ PROG_FULL_THRESH_NEGATE ;
|
|
|
|
always @* injectdbiterr_delayed <= #`TCQ INJECTDBITERR ;
|
|
|
|
always @* injectsbiterr_delayed <= #`TCQ INJECTSBITERR ;
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Derived parameters
|
|
|
|
****************************************************************************/
|
|
|
|
//There are 2 Verilog behavioral models
|
|
|
|
// 0 = Common-Clock FIFO/ShiftRam FIFO
|
|
|
|
// 1 = Independent Clocks FIFO
|
|
|
|
// 2 = Low Latency Synchronous FIFO
|
|
|
|
// 3 = Low Latency Asynchronous FIFO
|
|
|
|
localparam C_VERILOG_IMPL = (C_FIFO_TYPE == 3) ? 2 :
|
|
|
|
(C_IMPLEMENTATION_TYPE == 2) ? 1 : 0;
|
|
|
|
localparam IS_8SERIES = (C_FAMILY == "virtexu" || C_FAMILY == "kintexu" || C_FAMILY == "artixu" || C_FAMILY == "virtexum" || C_FAMILY == "zynque") ? 1 : 0;
|
|
|
|
|
|
|
|
//Internal reset signals
|
|
|
|
reg rd_rst_asreg = 0;
|
|
|
|
reg rd_rst_asreg_d1 = 0;
|
|
|
|
reg rd_rst_asreg_d2 = 0;
|
|
|
|
reg rd_rst_asreg_d3 = 0;
|
|
|
|
reg rd_rst_reg = 0;
|
|
|
|
wire rd_rst_comb;
|
|
|
|
reg wr_rst_d0 = 0;
|
|
|
|
reg wr_rst_d1 = 0;
|
|
|
|
reg wr_rst_d2 = 0;
|
|
|
|
reg rd_rst_d0 = 0;
|
|
|
|
reg rd_rst_d1 = 0;
|
|
|
|
reg rd_rst_d2 = 0;
|
|
|
|
reg rd_rst_d3 = 0;
|
|
|
|
reg wrrst_done = 0;
|
|
|
|
reg rdrst_done = 0;
|
|
|
|
reg wr_rst_asreg = 0;
|
|
|
|
reg wr_rst_asreg_d1 = 0;
|
|
|
|
reg wr_rst_asreg_d2 = 0;
|
|
|
|
reg wr_rst_asreg_d3 = 0;
|
|
|
|
reg rd_rst_wr_d0 = 0;
|
|
|
|
reg rd_rst_wr_d1 = 0;
|
|
|
|
reg rd_rst_wr_d2 = 0;
|
|
|
|
reg wr_rst_reg = 0;
|
|
|
|
reg rst_active_i = 1'b1;
|
|
|
|
reg rst_delayed_d1 = 1'b1;
|
|
|
|
reg rst_delayed_d2 = 1'b1;
|
|
|
|
wire wr_rst_comb;
|
|
|
|
wire wr_rst_i;
|
|
|
|
wire rd_rst_i;
|
|
|
|
wire rst_i;
|
|
|
|
|
|
|
|
//Internal reset signals
|
|
|
|
reg rst_asreg = 0;
|
|
|
|
reg srst_asreg = 0;
|
|
|
|
reg rst_asreg_d1 = 0;
|
|
|
|
reg rst_asreg_d2 = 0;
|
|
|
|
reg srst_asreg_d1 = 0;
|
|
|
|
reg srst_asreg_d2 = 0;
|
|
|
|
reg rst_reg = 0;
|
|
|
|
reg srst_reg = 0;
|
|
|
|
wire rst_comb;
|
|
|
|
wire srst_comb;
|
|
|
|
reg rst_full_gen_i = 0;
|
|
|
|
reg rst_full_ff_i = 0;
|
|
|
|
|
|
|
|
wire RD_CLK_P0_IN;
|
|
|
|
wire RST_P0_IN;
|
|
|
|
wire RD_EN_FIFO_IN;
|
|
|
|
wire RD_EN_P0_IN;
|
|
|
|
|
|
|
|
wire ALMOST_EMPTY_FIFO_OUT;
|
|
|
|
wire ALMOST_FULL_FIFO_OUT;
|
|
|
|
wire [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT_FIFO_OUT;
|
|
|
|
wire [C_DOUT_WIDTH-1:0] DOUT_FIFO_OUT;
|
|
|
|
wire EMPTY_FIFO_OUT;
|
|
|
|
wire FULL_FIFO_OUT;
|
|
|
|
wire OVERFLOW_FIFO_OUT;
|
|
|
|
wire PROG_EMPTY_FIFO_OUT;
|
|
|
|
wire PROG_FULL_FIFO_OUT;
|
|
|
|
wire VALID_FIFO_OUT;
|
|
|
|
wire [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT_FIFO_OUT;
|
|
|
|
wire UNDERFLOW_FIFO_OUT;
|
|
|
|
wire WR_ACK_FIFO_OUT;
|
|
|
|
wire [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT_FIFO_OUT;
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Internal Signals
|
|
|
|
// The core uses either the internal_ wires or the preload0_ wires depending
|
|
|
|
// on whether the core uses Preload0 or not.
|
|
|
|
// When using preload0, the internal signals connect the internal core to
|
|
|
|
// the preload logic, and the external core's interfaces are tied to the
|
|
|
|
// preload0 signals from the preload logic.
|
|
|
|
//***************************************************************************
|
|
|
|
wire [C_DOUT_WIDTH-1:0] DATA_P0_OUT;
|
|
|
|
wire VALID_P0_OUT;
|
|
|
|
wire EMPTY_P0_OUT;
|
|
|
|
wire ALMOSTEMPTY_P0_OUT;
|
|
|
|
reg EMPTY_P0_OUT_Q;
|
|
|
|
reg ALMOSTEMPTY_P0_OUT_Q;
|
|
|
|
wire UNDERFLOW_P0_OUT;
|
|
|
|
wire RDEN_P0_OUT;
|
|
|
|
wire [C_DOUT_WIDTH-1:0] DATA_P0_IN;
|
|
|
|
wire EMPTY_P0_IN;
|
|
|
|
reg [31:0] DATA_COUNT_FWFT;
|
|
|
|
reg SS_FWFT_WR ;
|
|
|
|
reg SS_FWFT_RD ;
|
|
|
|
|
|
|
|
wire sbiterr_fifo_out;
|
|
|
|
wire dbiterr_fifo_out;
|
|
|
|
wire inject_sbit_err;
|
|
|
|
wire inject_dbit_err;
|
|
|
|
|
|
|
|
// Assign 0 if not selected to avoid 'X' propogation to S/DBITERR.
|
|
|
|
assign inject_sbit_err = ((C_ERROR_INJECTION_TYPE == 1) || (C_ERROR_INJECTION_TYPE == 3)) ?
|
|
|
|
injectsbiterr_delayed : 0;
|
|
|
|
assign inject_dbit_err = ((C_ERROR_INJECTION_TYPE == 2) || (C_ERROR_INJECTION_TYPE == 3)) ?
|
|
|
|
injectdbiterr_delayed : 0;
|
|
|
|
|
|
|
|
assign wr_rst_i_out = wr_rst_i;
|
|
|
|
assign rd_rst_i_out = rd_rst_i;
|
|
|
|
|
|
|
|
// Choose the behavioral model to instantiate based on the C_VERILOG_IMPL
|
|
|
|
// parameter (1=Independent Clocks, 0=Common Clock)
|
|
|
|
|
|
|
|
localparam FULL_FLAGS_RST_VAL = (C_HAS_SRST == 1) ? 0 : C_FULL_FLAGS_RST_VAL;
|
|
|
|
generate
|
|
|
|
case (C_VERILOG_IMPL)
|
|
|
|
0 : begin : block1
|
|
|
|
//Common Clock Behavioral Model
|
|
|
|
fifo_generator_v12_0_bhv_ver_ss
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_DATA_COUNT_WIDTH),
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH),
|
|
|
|
.C_DOUT_RST_VAL (C_DOUT_RST_VAL),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (FULL_FLAGS_RST_VAL),
|
|
|
|
.C_HAS_ALMOST_EMPTY (C_HAS_ALMOST_EMPTY),
|
|
|
|
.C_HAS_ALMOST_FULL ((C_AXI_TYPE == 0 && C_FIFO_TYPE == 1) ? 1 : C_HAS_ALMOST_FULL),
|
|
|
|
.C_HAS_DATA_COUNT (C_HAS_DATA_COUNT),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_HAS_RD_DATA_COUNT (C_HAS_RD_DATA_COUNT),
|
|
|
|
.C_HAS_RST (C_HAS_RST),
|
|
|
|
.C_HAS_SRST (C_HAS_SRST),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_HAS_VALID (C_HAS_VALID),
|
|
|
|
.C_HAS_WR_ACK (C_HAS_WR_ACK),
|
|
|
|
.C_HAS_WR_DATA_COUNT (C_HAS_WR_DATA_COUNT),
|
|
|
|
.C_IMPLEMENTATION_TYPE (C_IMPLEMENTATION_TYPE),
|
|
|
|
.C_MEMORY_TYPE (C_MEMORY_TYPE),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
.C_PRELOAD_LATENCY (C_PRELOAD_LATENCY),
|
|
|
|
.C_PRELOAD_REGS (C_PRELOAD_REGS),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_EMPTY_THRESH_NEGATE_VAL (C_PROG_EMPTY_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_FULL_THRESH_NEGATE_VAL (C_PROG_FULL_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_RD_DATA_COUNT_WIDTH),
|
|
|
|
.C_RD_DEPTH (C_RD_DEPTH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_RD_PNTR_WIDTH),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_USE_EMBEDDED_REG (C_USE_EMBEDDED_REG),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (C_USE_FWFT_DATA_COUNT),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_DATA_COUNT_WIDTH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH),
|
|
|
|
.C_USE_ECC (C_USE_ECC),
|
|
|
|
.C_ENABLE_RST_SYNC (C_ENABLE_RST_SYNC),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE),
|
|
|
|
.C_FIFO_TYPE (C_FIFO_TYPE)
|
|
|
|
)
|
|
|
|
gen_ss
|
|
|
|
(
|
|
|
|
.CLK (CLK),
|
|
|
|
.RST (rst_i),
|
|
|
|
.SRST (srst_delayed),
|
|
|
|
.RST_FULL_GEN (rst_full_gen_i),
|
|
|
|
.RST_FULL_FF (rst_full_ff_i),
|
|
|
|
.DIN (din_delayed),
|
|
|
|
.WR_EN (wr_en_delayed),
|
|
|
|
.RD_EN (RD_EN_FIFO_IN),
|
|
|
|
.RD_EN_USER (rd_en_delayed),
|
|
|
|
.USER_EMPTY_FB (empty_fb),
|
|
|
|
.PROG_EMPTY_THRESH (prog_empty_thresh_delayed),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT (prog_empty_thresh_assert_delayed),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE (prog_empty_thresh_negate_delayed),
|
|
|
|
.PROG_FULL_THRESH (prog_full_thresh_delayed),
|
|
|
|
.PROG_FULL_THRESH_ASSERT (prog_full_thresh_assert_delayed),
|
|
|
|
.PROG_FULL_THRESH_NEGATE (prog_full_thresh_negate_delayed),
|
|
|
|
.INJECTSBITERR (inject_sbit_err),
|
|
|
|
.INJECTDBITERR (inject_dbit_err),
|
|
|
|
.DOUT (DOUT_FIFO_OUT),
|
|
|
|
.FULL (FULL_FIFO_OUT),
|
|
|
|
.ALMOST_FULL (ALMOST_FULL_FIFO_OUT),
|
|
|
|
.WR_ACK (WR_ACK_FIFO_OUT),
|
|
|
|
.OVERFLOW (OVERFLOW_FIFO_OUT),
|
|
|
|
.EMPTY (EMPTY_FIFO_OUT),
|
|
|
|
.ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT),
|
|
|
|
.VALID (VALID_FIFO_OUT),
|
|
|
|
.UNDERFLOW (UNDERFLOW_FIFO_OUT),
|
|
|
|
.DATA_COUNT (DATA_COUNT_FIFO_OUT),
|
|
|
|
.RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT),
|
|
|
|
.WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT),
|
|
|
|
.PROG_FULL (PROG_FULL_FIFO_OUT),
|
|
|
|
.PROG_EMPTY (PROG_EMPTY_FIFO_OUT),
|
|
|
|
.WR_RST_BUSY (wr_rst_busy),
|
|
|
|
.RD_RST_BUSY (rd_rst_busy),
|
|
|
|
.SBITERR (sbiterr_fifo_out),
|
|
|
|
.DBITERR (dbiterr_fifo_out)
|
|
|
|
);
|
|
|
|
end
|
|
|
|
1 : begin : block1
|
|
|
|
//Independent Clocks Behavioral Model
|
|
|
|
fifo_generator_v12_0_bhv_ver_as
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_DATA_COUNT_WIDTH),
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH),
|
|
|
|
.C_DOUT_RST_VAL (C_DOUT_RST_VAL),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (C_FULL_FLAGS_RST_VAL),
|
|
|
|
.C_HAS_ALMOST_EMPTY (C_HAS_ALMOST_EMPTY),
|
|
|
|
.C_HAS_ALMOST_FULL (C_HAS_ALMOST_FULL),
|
|
|
|
.C_HAS_DATA_COUNT (C_HAS_DATA_COUNT),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_HAS_RD_DATA_COUNT (C_HAS_RD_DATA_COUNT),
|
|
|
|
.C_HAS_RST (C_HAS_RST),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_HAS_VALID (C_HAS_VALID),
|
|
|
|
.C_HAS_WR_ACK (C_HAS_WR_ACK),
|
|
|
|
.C_HAS_WR_DATA_COUNT (C_HAS_WR_DATA_COUNT),
|
|
|
|
.C_IMPLEMENTATION_TYPE (C_IMPLEMENTATION_TYPE),
|
|
|
|
.C_MEMORY_TYPE (C_MEMORY_TYPE),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
.C_PRELOAD_LATENCY (C_PRELOAD_LATENCY),
|
|
|
|
.C_PRELOAD_REGS (C_PRELOAD_REGS),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_EMPTY_THRESH_NEGATE_VAL (C_PROG_EMPTY_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_FULL_THRESH_NEGATE_VAL (C_PROG_FULL_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_RD_DATA_COUNT_WIDTH),
|
|
|
|
.C_RD_DEPTH (C_RD_DEPTH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_RD_PNTR_WIDTH),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_USE_EMBEDDED_REG (C_USE_EMBEDDED_REG),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (C_USE_FWFT_DATA_COUNT),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_DATA_COUNT_WIDTH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH),
|
|
|
|
.C_USE_ECC (C_USE_ECC),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
.C_ENABLE_RST_SYNC (C_ENABLE_RST_SYNC),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE)
|
|
|
|
)
|
|
|
|
gen_as
|
|
|
|
(
|
|
|
|
.WR_CLK (WR_CLK),
|
|
|
|
.RD_CLK (RD_CLK),
|
|
|
|
.RST (rst_i),
|
|
|
|
.RST_FULL_GEN (rst_full_gen_i),
|
|
|
|
.RST_FULL_FF (rst_full_ff_i),
|
|
|
|
.WR_RST (wr_rst_i),
|
|
|
|
.RD_RST (rd_rst_i),
|
|
|
|
.DIN (din_delayed),
|
|
|
|
.WR_EN (wr_en_delayed),
|
|
|
|
.RD_EN (RD_EN_FIFO_IN),
|
|
|
|
.RD_EN_USER (rd_en_delayed),
|
|
|
|
.PROG_EMPTY_THRESH (prog_empty_thresh_delayed),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT (prog_empty_thresh_assert_delayed),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE (prog_empty_thresh_negate_delayed),
|
|
|
|
.PROG_FULL_THRESH (prog_full_thresh_delayed),
|
|
|
|
.PROG_FULL_THRESH_ASSERT (prog_full_thresh_assert_delayed),
|
|
|
|
.PROG_FULL_THRESH_NEGATE (prog_full_thresh_negate_delayed),
|
|
|
|
.INJECTSBITERR (inject_sbit_err),
|
|
|
|
.INJECTDBITERR (inject_dbit_err),
|
|
|
|
.USER_EMPTY_FB (EMPTY_P0_OUT),
|
|
|
|
.DOUT (DOUT_FIFO_OUT),
|
|
|
|
.FULL (FULL_FIFO_OUT),
|
|
|
|
.ALMOST_FULL (ALMOST_FULL_FIFO_OUT),
|
|
|
|
.WR_ACK (WR_ACK_FIFO_OUT),
|
|
|
|
.OVERFLOW (OVERFLOW_FIFO_OUT),
|
|
|
|
.EMPTY (EMPTY_FIFO_OUT),
|
|
|
|
.ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT),
|
|
|
|
.VALID (VALID_FIFO_OUT),
|
|
|
|
.UNDERFLOW (UNDERFLOW_FIFO_OUT),
|
|
|
|
.RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT),
|
|
|
|
.WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT),
|
|
|
|
.PROG_FULL (PROG_FULL_FIFO_OUT),
|
|
|
|
.PROG_EMPTY (PROG_EMPTY_FIFO_OUT),
|
|
|
|
.SBITERR (sbiterr_fifo_out),
|
|
|
|
.DBITERR (dbiterr_fifo_out)
|
|
|
|
);
|
|
|
|
end
|
|
|
|
|
|
|
|
2 : begin : ll_afifo_inst
|
|
|
|
fifo_generator_v12_0_beh_ver_ll_afifo
|
|
|
|
#(
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH),
|
|
|
|
.C_DOUT_RST_VAL (C_DOUT_RST_VAL),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (C_FULL_FLAGS_RST_VAL),
|
|
|
|
.C_HAS_RD_DATA_COUNT (C_HAS_RD_DATA_COUNT),
|
|
|
|
.C_HAS_WR_DATA_COUNT (C_HAS_WR_DATA_COUNT),
|
|
|
|
.C_RD_DEPTH (C_RD_DEPTH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_RD_PNTR_WIDTH),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_DATA_COUNT_WIDTH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH),
|
|
|
|
.C_FIFO_TYPE (C_FIFO_TYPE)
|
|
|
|
)
|
|
|
|
gen_ll_afifo
|
|
|
|
(
|
|
|
|
.DIN (din_delayed),
|
|
|
|
.RD_CLK (RD_CLK),
|
|
|
|
.RD_EN (rd_en_delayed),
|
|
|
|
.WR_RST (wr_rst_i),
|
|
|
|
.RD_RST (rd_rst_i),
|
|
|
|
.WR_CLK (WR_CLK),
|
|
|
|
.WR_EN (wr_en_delayed),
|
|
|
|
.DOUT (DOUT),
|
|
|
|
.EMPTY (EMPTY),
|
|
|
|
.FULL (FULL)
|
|
|
|
);
|
|
|
|
end
|
|
|
|
default : begin : block1
|
|
|
|
//Independent Clocks Behavioral Model
|
|
|
|
fifo_generator_v12_0_bhv_ver_as
|
|
|
|
#(
|
|
|
|
.C_FAMILY (C_FAMILY),
|
|
|
|
.C_DATA_COUNT_WIDTH (C_DATA_COUNT_WIDTH),
|
|
|
|
.C_DIN_WIDTH (C_DIN_WIDTH),
|
|
|
|
.C_DOUT_RST_VAL (C_DOUT_RST_VAL),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_FULL_FLAGS_RST_VAL (C_FULL_FLAGS_RST_VAL),
|
|
|
|
.C_HAS_ALMOST_EMPTY (C_HAS_ALMOST_EMPTY),
|
|
|
|
.C_HAS_ALMOST_FULL (C_HAS_ALMOST_FULL),
|
|
|
|
.C_HAS_DATA_COUNT (C_HAS_DATA_COUNT),
|
|
|
|
.C_HAS_OVERFLOW (C_HAS_OVERFLOW),
|
|
|
|
.C_HAS_RD_DATA_COUNT (C_HAS_RD_DATA_COUNT),
|
|
|
|
.C_HAS_RST (C_HAS_RST),
|
|
|
|
.C_HAS_UNDERFLOW (C_HAS_UNDERFLOW),
|
|
|
|
.C_HAS_VALID (C_HAS_VALID),
|
|
|
|
.C_HAS_WR_ACK (C_HAS_WR_ACK),
|
|
|
|
.C_HAS_WR_DATA_COUNT (C_HAS_WR_DATA_COUNT),
|
|
|
|
.C_IMPLEMENTATION_TYPE (C_IMPLEMENTATION_TYPE),
|
|
|
|
.C_MEMORY_TYPE (C_MEMORY_TYPE),
|
|
|
|
.C_OVERFLOW_LOW (C_OVERFLOW_LOW),
|
|
|
|
.C_PRELOAD_LATENCY (C_PRELOAD_LATENCY),
|
|
|
|
.C_PRELOAD_REGS (C_PRELOAD_REGS),
|
|
|
|
.C_PROG_EMPTY_THRESH_ASSERT_VAL (C_PROG_EMPTY_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_EMPTY_THRESH_NEGATE_VAL (C_PROG_EMPTY_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_EMPTY_TYPE (C_PROG_EMPTY_TYPE),
|
|
|
|
.C_PROG_FULL_THRESH_ASSERT_VAL (C_PROG_FULL_THRESH_ASSERT_VAL),
|
|
|
|
.C_PROG_FULL_THRESH_NEGATE_VAL (C_PROG_FULL_THRESH_NEGATE_VAL),
|
|
|
|
.C_PROG_FULL_TYPE (C_PROG_FULL_TYPE),
|
|
|
|
.C_RD_DATA_COUNT_WIDTH (C_RD_DATA_COUNT_WIDTH),
|
|
|
|
.C_RD_DEPTH (C_RD_DEPTH),
|
|
|
|
.C_RD_PNTR_WIDTH (C_RD_PNTR_WIDTH),
|
|
|
|
.C_UNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_USE_EMBEDDED_REG (C_USE_EMBEDDED_REG),
|
|
|
|
.C_USE_FWFT_DATA_COUNT (C_USE_FWFT_DATA_COUNT),
|
|
|
|
.C_VALID_LOW (C_VALID_LOW),
|
|
|
|
.C_WR_ACK_LOW (C_WR_ACK_LOW),
|
|
|
|
.C_WR_DATA_COUNT_WIDTH (C_WR_DATA_COUNT_WIDTH),
|
|
|
|
.C_WR_DEPTH (C_WR_DEPTH),
|
|
|
|
.C_WR_PNTR_WIDTH (C_WR_PNTR_WIDTH),
|
|
|
|
.C_USE_ECC (C_USE_ECC),
|
|
|
|
.C_SYNCHRONIZER_STAGE (C_SYNCHRONIZER_STAGE),
|
|
|
|
.C_ENABLE_RST_SYNC (C_ENABLE_RST_SYNC),
|
|
|
|
.C_ERROR_INJECTION_TYPE (C_ERROR_INJECTION_TYPE)
|
|
|
|
)
|
|
|
|
gen_as
|
|
|
|
(
|
|
|
|
.WR_CLK (WR_CLK),
|
|
|
|
.RD_CLK (RD_CLK),
|
|
|
|
.RST (rst_i),
|
|
|
|
.RST_FULL_GEN (rst_full_gen_i),
|
|
|
|
.RST_FULL_FF (rst_full_ff_i),
|
|
|
|
.WR_RST (wr_rst_i),
|
|
|
|
.RD_RST (rd_rst_i),
|
|
|
|
.DIN (din_delayed),
|
|
|
|
.WR_EN (wr_en_delayed),
|
|
|
|
.RD_EN (RD_EN_FIFO_IN),
|
|
|
|
.RD_EN_USER (rd_en_delayed),
|
|
|
|
.PROG_EMPTY_THRESH (prog_empty_thresh_delayed),
|
|
|
|
.PROG_EMPTY_THRESH_ASSERT (prog_empty_thresh_assert_delayed),
|
|
|
|
.PROG_EMPTY_THRESH_NEGATE (prog_empty_thresh_negate_delayed),
|
|
|
|
.PROG_FULL_THRESH (prog_full_thresh_delayed),
|
|
|
|
.PROG_FULL_THRESH_ASSERT (prog_full_thresh_assert_delayed),
|
|
|
|
.PROG_FULL_THRESH_NEGATE (prog_full_thresh_negate_delayed),
|
|
|
|
.INJECTSBITERR (inject_sbit_err),
|
|
|
|
.INJECTDBITERR (inject_dbit_err),
|
|
|
|
.USER_EMPTY_FB (EMPTY_P0_OUT),
|
|
|
|
.DOUT (DOUT_FIFO_OUT),
|
|
|
|
.FULL (FULL_FIFO_OUT),
|
|
|
|
.ALMOST_FULL (ALMOST_FULL_FIFO_OUT),
|
|
|
|
.WR_ACK (WR_ACK_FIFO_OUT),
|
|
|
|
.OVERFLOW (OVERFLOW_FIFO_OUT),
|
|
|
|
.EMPTY (EMPTY_FIFO_OUT),
|
|
|
|
.ALMOST_EMPTY (ALMOST_EMPTY_FIFO_OUT),
|
|
|
|
.VALID (VALID_FIFO_OUT),
|
|
|
|
.UNDERFLOW (UNDERFLOW_FIFO_OUT),
|
|
|
|
.RD_DATA_COUNT (RD_DATA_COUNT_FIFO_OUT),
|
|
|
|
.WR_DATA_COUNT (WR_DATA_COUNT_FIFO_OUT),
|
|
|
|
.PROG_FULL (PROG_FULL_FIFO_OUT),
|
|
|
|
.PROG_EMPTY (PROG_EMPTY_FIFO_OUT),
|
|
|
|
.SBITERR (sbiterr_fifo_out),
|
|
|
|
.DBITERR (dbiterr_fifo_out)
|
|
|
|
);
|
|
|
|
end
|
|
|
|
|
|
|
|
endcase
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
|
|
// Connect Internal Signals
|
|
|
|
// (Signals labeled internal_*)
|
|
|
|
// In the normal case, these signals tie directly to the FIFO's inputs and
|
|
|
|
// outputs.
|
|
|
|
// In the case of Preload Latency 0 or 1, there are intermediate
|
|
|
|
// signals between the internal FIFO and the preload logic.
|
|
|
|
//**************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// If First-Word Fall-Through, instantiate
|
|
|
|
// the preload0 (FWFT) module
|
|
|
|
//***********************************************
|
|
|
|
wire rd_en_to_fwft_fifo;
|
|
|
|
wire sbiterr_fwft;
|
|
|
|
wire dbiterr_fwft;
|
|
|
|
wire [C_DOUT_WIDTH-1:0] dout_fwft;
|
|
|
|
wire empty_fwft;
|
|
|
|
wire rd_en_fifo_in;
|
|
|
|
wire stage2_reg_en_i;
|
|
|
|
wire [1:0] valid_stages_i;
|
|
|
|
wire rst_fwft;
|
|
|
|
//wire empty_p0_out;
|
|
|
|
reg [C_SYNCHRONIZER_STAGE-1:0] pkt_empty_sync = 'b1;
|
|
|
|
|
|
|
|
localparam IS_FWFT = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ? 1 : 0;
|
|
|
|
localparam IS_PKT_FIFO = (C_FIFO_TYPE == 1) ? 1 : 0;
|
|
|
|
localparam IS_AXIS_PKT_FIFO = (C_FIFO_TYPE == 1 && C_AXI_TYPE == 0) ? 1 : 0;
|
|
|
|
assign rst_fwft = (C_COMMON_CLOCK == 0) ? rd_rst_i : (C_HAS_RST == 1) ? rst_i : 1'b0;
|
|
|
|
|
|
|
|
generate if (IS_FWFT == 1 && C_FIFO_TYPE != 3) begin : block2
|
|
|
|
|
|
|
|
|
|
|
|
fifo_generator_v12_0_bhv_ver_preload0
|
|
|
|
#(
|
|
|
|
.C_DOUT_RST_VAL (C_DOUT_RST_VAL),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_HAS_RST (C_HAS_RST),
|
|
|
|
.C_ENABLE_RST_SYNC (C_ENABLE_RST_SYNC),
|
|
|
|
.C_HAS_SRST (C_HAS_SRST),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_USE_ECC (C_USE_ECC),
|
|
|
|
.C_USERVALID_LOW (C_VALID_LOW),
|
|
|
|
.C_USERUNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_MEMORY_TYPE (C_MEMORY_TYPE),
|
|
|
|
.C_FIFO_TYPE (C_FIFO_TYPE)
|
|
|
|
)
|
|
|
|
fgpl0
|
|
|
|
(
|
|
|
|
.RD_CLK (RD_CLK_P0_IN),
|
|
|
|
.RD_RST (RST_P0_IN),
|
|
|
|
.SRST (srst_delayed),
|
|
|
|
.WR_RST_BUSY (wr_rst_busy),
|
|
|
|
.RD_RST_BUSY (rd_rst_busy),
|
|
|
|
.RD_EN (RD_EN_P0_IN),
|
|
|
|
.FIFOEMPTY (EMPTY_P0_IN),
|
|
|
|
.FIFODATA (DATA_P0_IN),
|
|
|
|
.FIFOSBITERR (sbiterr_fifo_out),
|
|
|
|
.FIFODBITERR (dbiterr_fifo_out),
|
|
|
|
// Output
|
|
|
|
.USERDATA (dout_fwft),
|
|
|
|
.USERVALID (VALID_P0_OUT),
|
|
|
|
.USEREMPTY (empty_fwft),
|
|
|
|
.USERALMOSTEMPTY (ALMOSTEMPTY_P0_OUT),
|
|
|
|
.USERUNDERFLOW (UNDERFLOW_P0_OUT),
|
|
|
|
.RAMVALID (),
|
|
|
|
.FIFORDEN (rd_en_fifo_in),
|
|
|
|
.USERSBITERR (sbiterr_fwft),
|
|
|
|
.USERDBITERR (dbiterr_fwft),
|
|
|
|
.STAGE2_REG_EN (stage2_reg_en_i),
|
|
|
|
.VALID_STAGES (valid_stages_i)
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// Connect inputs to preload (FWFT) module
|
|
|
|
//***********************************************
|
|
|
|
//Connect the RD_CLK of the Preload (FWFT) module to CLK if we
|
|
|
|
// have a common-clock FIFO, or RD_CLK if we have an
|
|
|
|
// independent clock FIFO
|
|
|
|
assign RD_CLK_P0_IN = ((C_VERILOG_IMPL == 0) ? CLK : RD_CLK);
|
|
|
|
assign RST_P0_IN = (C_COMMON_CLOCK == 0) ? rd_rst_i : (C_HAS_RST == 1) ? rst_i : 0;
|
|
|
|
assign RD_EN_P0_IN = (C_FIFO_TYPE != 1) ? rd_en_delayed : rd_en_to_fwft_fifo;
|
|
|
|
assign EMPTY_P0_IN = EMPTY_FIFO_OUT;
|
|
|
|
assign DATA_P0_IN = DOUT_FIFO_OUT;
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// Connect outputs from preload (FWFT) module
|
|
|
|
//***********************************************
|
|
|
|
assign VALID = VALID_P0_OUT ;
|
|
|
|
assign ALMOST_EMPTY = ALMOSTEMPTY_P0_OUT;
|
|
|
|
assign UNDERFLOW = UNDERFLOW_P0_OUT ;
|
|
|
|
|
|
|
|
assign RD_EN_FIFO_IN = rd_en_fifo_in;
|
|
|
|
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// Create DATA_COUNT from First-Word Fall-Through
|
|
|
|
// data count
|
|
|
|
//***********************************************
|
|
|
|
assign DATA_COUNT = (C_USE_FWFT_DATA_COUNT == 0)? DATA_COUNT_FIFO_OUT:
|
|
|
|
(C_DATA_COUNT_WIDTH>C_RD_PNTR_WIDTH) ? DATA_COUNT_FWFT[C_RD_PNTR_WIDTH:0] :
|
|
|
|
DATA_COUNT_FWFT[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH-C_DATA_COUNT_WIDTH+1];
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// Create DATA_COUNT from First-Word Fall-Through
|
|
|
|
// data count
|
|
|
|
//***********************************************
|
|
|
|
always @ (posedge RD_CLK_P0_IN or posedge RST_P0_IN) begin
|
|
|
|
if (RST_P0_IN) begin
|
|
|
|
EMPTY_P0_OUT_Q <= #`TCQ 1;
|
|
|
|
ALMOSTEMPTY_P0_OUT_Q <= #`TCQ 1;
|
|
|
|
end else begin
|
|
|
|
EMPTY_P0_OUT_Q <= #`TCQ empty_p0_out;
|
|
|
|
// EMPTY_P0_OUT_Q <= #`TCQ EMPTY_FIFO_OUT;
|
|
|
|
ALMOSTEMPTY_P0_OUT_Q <= #`TCQ ALMOSTEMPTY_P0_OUT;
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// logic for common-clock data count when FWFT is selected
|
|
|
|
//***********************************************
|
|
|
|
initial begin
|
|
|
|
SS_FWFT_RD = 1'b0;
|
|
|
|
DATA_COUNT_FWFT = 0 ;
|
|
|
|
SS_FWFT_WR = 1'b0 ;
|
|
|
|
end //initial
|
|
|
|
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// common-clock data count is implemented as an
|
|
|
|
// up-down counter. SS_FWFT_WR and SS_FWFT_RD
|
|
|
|
// are the up/down enables for the counter.
|
|
|
|
//***********************************************
|
|
|
|
always @ (RD_EN or VALID_P0_OUT or WR_EN or FULL_FIFO_OUT or empty_p0_out) begin
|
|
|
|
if (C_VALID_LOW == 1) begin
|
|
|
|
SS_FWFT_RD = (C_FIFO_TYPE != 1) ? (RD_EN && ~VALID_P0_OUT) : (~empty_p0_out && RD_EN && ~VALID_P0_OUT) ;
|
|
|
|
end else begin
|
|
|
|
SS_FWFT_RD = (C_FIFO_TYPE != 1) ? (RD_EN && VALID_P0_OUT) : (~empty_p0_out && RD_EN && VALID_P0_OUT) ;
|
|
|
|
end
|
|
|
|
SS_FWFT_WR = (WR_EN && (~FULL_FIFO_OUT)) ;
|
|
|
|
end
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// common-clock data count is implemented as an
|
|
|
|
// up-down counter for FWFT. This always block
|
|
|
|
// calculates the counter.
|
|
|
|
//***********************************************
|
|
|
|
always @ (posedge RD_CLK_P0_IN or posedge RST_P0_IN) begin
|
|
|
|
if (RST_P0_IN) begin
|
|
|
|
DATA_COUNT_FWFT <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
//if (srst_delayed && (C_HAS_SRST == 1) ) begin
|
|
|
|
if ((srst_delayed | wr_rst_busy | rd_rst_busy) && (C_HAS_SRST == 1) ) begin
|
|
|
|
DATA_COUNT_FWFT <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
case ( {SS_FWFT_WR, SS_FWFT_RD})
|
|
|
|
2'b00: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT ;
|
|
|
|
2'b01: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT - 1 ;
|
|
|
|
2'b10: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT + 1 ;
|
|
|
|
2'b11: DATA_COUNT_FWFT <= #`TCQ DATA_COUNT_FWFT ;
|
|
|
|
endcase
|
|
|
|
end //if SRST
|
|
|
|
end //IF RST
|
|
|
|
end //always
|
|
|
|
|
|
|
|
end endgenerate // : block2
|
|
|
|
|
|
|
|
// AXI Streaming Packet FIFO
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pkt_count = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pkt_count = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pkt_count_plus1 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pkt_count_reg = 0;
|
|
|
|
reg partial_packet = 0;
|
|
|
|
reg stage1_eop_d1 = 0;
|
|
|
|
reg rd_en_fifo_in_d1 = 0;
|
|
|
|
reg eop_at_stage2 = 0;
|
|
|
|
reg ram_pkt_empty = 0;
|
|
|
|
reg ram_pkt_empty_d1 = 0;
|
|
|
|
|
|
|
|
wire [C_DOUT_WIDTH-1:0] dout_p0_out;
|
|
|
|
wire packet_empty_wr;
|
|
|
|
wire wr_rst_fwft_pkt_fifo;
|
|
|
|
wire dummy_wr_eop;
|
|
|
|
wire ram_wr_en_pkt_fifo;
|
|
|
|
wire wr_eop;
|
|
|
|
wire ram_rd_en_compare;
|
|
|
|
wire stage1_eop;
|
|
|
|
wire pkt_ready_to_read;
|
|
|
|
wire rd_en_2_stage2;
|
|
|
|
|
|
|
|
// Generate Dummy WR_EOP for partial packet (Only for AXI Streaming)
|
|
|
|
// When Packet EMPTY is high, and FIFO is full, then generate the dummy WR_EOP
|
|
|
|
// When dummy WR_EOP is high, mask the actual EOP to avoid double increment of
|
|
|
|
// write packet count
|
|
|
|
generate if (IS_FWFT == 1 && IS_AXIS_PKT_FIFO == 1) begin // gdummy_wr_eop
|
|
|
|
always @ (posedge wr_rst_fwft_pkt_fifo or posedge WR_CLK) begin
|
|
|
|
if (wr_rst_fwft_pkt_fifo)
|
|
|
|
partial_packet <= 1'b0;
|
|
|
|
else begin
|
|
|
|
if (srst_delayed | wr_rst_busy | rd_rst_busy)
|
|
|
|
partial_packet <= #`TCQ 1'b0;
|
|
|
|
else if (ALMOST_FULL_FIFO_OUT && ram_wr_en_pkt_fifo && packet_empty_wr && (~din_delayed[0]))
|
|
|
|
partial_packet <= #`TCQ 1'b1;
|
|
|
|
else if (partial_packet && din_delayed[0] && ram_wr_en_pkt_fifo)
|
|
|
|
partial_packet <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate // gdummy_wr_eop
|
|
|
|
|
|
|
|
generate if (IS_FWFT == 1 && IS_PKT_FIFO == 1) begin // gpkt_fifo_fwft
|
|
|
|
assign wr_rst_fwft_pkt_fifo = (C_COMMON_CLOCK == 0) ? wr_rst_i : (C_HAS_RST == 1) ? rst_i:1'b0;
|
|
|
|
assign dummy_wr_eop = ALMOST_FULL_FIFO_OUT && ram_wr_en_pkt_fifo && packet_empty_wr && (~din_delayed[0]) && (~partial_packet);
|
|
|
|
assign packet_empty_wr = (C_COMMON_CLOCK == 1) ? empty_p0_out : pkt_empty_sync[C_SYNCHRONIZER_STAGE-1];
|
|
|
|
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft) begin
|
|
|
|
stage1_eop_d1 <= 1'b0;
|
|
|
|
rd_en_fifo_in_d1 <= 1'b0;
|
|
|
|
end else begin
|
|
|
|
if (srst_delayed | wr_rst_busy | rd_rst_busy) begin
|
|
|
|
stage1_eop_d1 <= #`TCQ 1'b0;
|
|
|
|
rd_en_fifo_in_d1 <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
stage1_eop_d1 <= #`TCQ stage1_eop;
|
|
|
|
rd_en_fifo_in_d1 <= #`TCQ rd_en_fifo_in;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assign stage1_eop = (rd_en_fifo_in_d1) ? DOUT_FIFO_OUT[0] : stage1_eop_d1;
|
|
|
|
assign ram_wr_en_pkt_fifo = wr_en_delayed && (~FULL_FIFO_OUT);
|
|
|
|
assign wr_eop = ram_wr_en_pkt_fifo && ((din_delayed[0] && (~partial_packet)) || dummy_wr_eop);
|
|
|
|
assign ram_rd_en_compare = stage2_reg_en_i && stage1_eop;
|
|
|
|
|
|
|
|
|
|
|
|
fifo_generator_v12_0_bhv_ver_preload0
|
|
|
|
#(
|
|
|
|
.C_DOUT_RST_VAL (C_DOUT_RST_VAL),
|
|
|
|
.C_DOUT_WIDTH (C_DOUT_WIDTH),
|
|
|
|
.C_HAS_RST (C_HAS_RST),
|
|
|
|
.C_HAS_SRST (C_HAS_SRST),
|
|
|
|
.C_USE_DOUT_RST (C_USE_DOUT_RST),
|
|
|
|
.C_USE_ECC (C_USE_ECC),
|
|
|
|
.C_USERVALID_LOW (C_VALID_LOW),
|
|
|
|
.C_USERUNDERFLOW_LOW (C_UNDERFLOW_LOW),
|
|
|
|
.C_ENABLE_RST_SYNC (C_ENABLE_RST_SYNC),
|
|
|
|
.C_MEMORY_TYPE (C_MEMORY_TYPE),
|
|
|
|
.C_FIFO_TYPE (2) // Enable low latency fwft logic
|
|
|
|
)
|
|
|
|
pkt_fifo_fwft
|
|
|
|
(
|
|
|
|
.RD_CLK (RD_CLK_P0_IN),
|
|
|
|
.RD_RST (rst_fwft),
|
|
|
|
.SRST (srst_delayed),
|
|
|
|
.WR_RST_BUSY (wr_rst_busy),
|
|
|
|
.RD_RST_BUSY (rd_rst_busy),
|
|
|
|
.RD_EN (rd_en_delayed),
|
|
|
|
.FIFOEMPTY (pkt_ready_to_read),
|
|
|
|
.FIFODATA (dout_fwft),
|
|
|
|
.FIFOSBITERR (sbiterr_fwft),
|
|
|
|
.FIFODBITERR (dbiterr_fwft),
|
|
|
|
// Output
|
|
|
|
.USERDATA (dout_p0_out),
|
|
|
|
.USERVALID (),
|
|
|
|
.USEREMPTY (empty_p0_out),
|
|
|
|
.USERALMOSTEMPTY (),
|
|
|
|
.USERUNDERFLOW (),
|
|
|
|
.RAMVALID (),
|
|
|
|
.FIFORDEN (rd_en_2_stage2),
|
|
|
|
.USERSBITERR (SBITERR),
|
|
|
|
.USERDBITERR (DBITERR),
|
|
|
|
.STAGE2_REG_EN (),
|
|
|
|
.VALID_STAGES ()
|
|
|
|
);
|
|
|
|
|
|
|
|
assign pkt_ready_to_read = ~(!(ram_pkt_empty || empty_fwft) && ((valid_stages_i[0] && valid_stages_i[1]) || eop_at_stage2));
|
|
|
|
assign rd_en_to_fwft_fifo = ~empty_fwft && rd_en_2_stage2;
|
|
|
|
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft)
|
|
|
|
eop_at_stage2 <= 1'b0;
|
|
|
|
else if (stage2_reg_en_i)
|
|
|
|
eop_at_stage2 <= #`TCQ stage1_eop;
|
|
|
|
end
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Write and Read Packet Count
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
always @ (posedge wr_rst_fwft_pkt_fifo or posedge WR_CLK) begin
|
|
|
|
if (wr_rst_fwft_pkt_fifo)
|
|
|
|
wr_pkt_count <= 0;
|
|
|
|
else if (srst_delayed | wr_rst_busy | rd_rst_busy)
|
|
|
|
wr_pkt_count <= #`TCQ 0;
|
|
|
|
else if (wr_eop)
|
|
|
|
wr_pkt_count <= #`TCQ wr_pkt_count + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
end endgenerate // gpkt_fifo_fwft
|
|
|
|
|
|
|
|
assign DOUT = (C_FIFO_TYPE != 1) ? dout_fwft : dout_p0_out;
|
|
|
|
assign EMPTY = (C_FIFO_TYPE != 1) ? empty_fwft : empty_p0_out;
|
|
|
|
|
|
|
|
generate if (IS_FWFT == 1 && IS_PKT_FIFO == 1 && C_COMMON_CLOCK == 1) begin // grss_pkt_cnt
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft) begin
|
|
|
|
rd_pkt_count <= 0;
|
|
|
|
rd_pkt_count_plus1 <= 1;
|
|
|
|
end else if (srst_delayed | wr_rst_busy | rd_rst_busy) begin
|
|
|
|
rd_pkt_count <= #`TCQ 0;
|
|
|
|
rd_pkt_count_plus1 <= #`TCQ 1;
|
|
|
|
end else if (stage2_reg_en_i && stage1_eop) begin
|
|
|
|
rd_pkt_count <= #`TCQ rd_pkt_count + 1;
|
|
|
|
rd_pkt_count_plus1 <= #`TCQ rd_pkt_count_plus1 + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft) begin
|
|
|
|
ram_pkt_empty <= 1'b1;
|
|
|
|
ram_pkt_empty_d1 <= 1'b1;
|
|
|
|
end else if (SRST | wr_rst_busy | rd_rst_busy) begin
|
|
|
|
ram_pkt_empty <= #`TCQ 1'b1;
|
|
|
|
ram_pkt_empty_d1 <= #`TCQ 1'b1;
|
|
|
|
end else if ((rd_pkt_count == wr_pkt_count) && wr_eop) begin
|
|
|
|
ram_pkt_empty <= #`TCQ 1'b0;
|
|
|
|
ram_pkt_empty_d1 <= #`TCQ 1'b0;
|
|
|
|
end else if (ram_pkt_empty_d1 && rd_en_to_fwft_fifo) begin
|
|
|
|
ram_pkt_empty <= #`TCQ 1'b1;
|
|
|
|
end else if ((rd_pkt_count_plus1 == wr_pkt_count) && ~wr_eop && ~ALMOST_FULL_FIFO_OUT && ram_rd_en_compare) begin
|
|
|
|
ram_pkt_empty_d1 <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate //grss_pkt_cnt
|
|
|
|
|
|
|
|
localparam SYNC_STAGE_WIDTH = (C_SYNCHRONIZER_STAGE+1)*C_WR_PNTR_WIDTH;
|
|
|
|
reg [SYNC_STAGE_WIDTH-1:0] wr_pkt_count_q = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pkt_count_b2g = 0;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] wr_pkt_count_rd;
|
|
|
|
generate if (IS_FWFT == 1 && IS_PKT_FIFO == 1 && C_COMMON_CLOCK == 0) begin // gras_pkt_cnt
|
|
|
|
// Delay the write packet count in write clock domain to accomodate the binary to gray conversion delay
|
|
|
|
always @ (posedge wr_rst_fwft_pkt_fifo or posedge WR_CLK) begin
|
|
|
|
if (wr_rst_fwft_pkt_fifo)
|
|
|
|
wr_pkt_count_b2g <= 0;
|
|
|
|
else
|
|
|
|
wr_pkt_count_b2g <= #`TCQ wr_pkt_count;
|
|
|
|
end
|
|
|
|
|
|
|
|
// Synchronize the delayed write packet count in read domain, and also compensate the gray to binay conversion delay
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft)
|
|
|
|
wr_pkt_count_q <= 0;
|
|
|
|
else
|
|
|
|
wr_pkt_count_q <= #`TCQ {wr_pkt_count_q[SYNC_STAGE_WIDTH-C_WR_PNTR_WIDTH-1:0],wr_pkt_count_b2g};
|
|
|
|
end
|
|
|
|
|
|
|
|
always @* begin
|
|
|
|
if (stage1_eop)
|
|
|
|
rd_pkt_count <= rd_pkt_count_reg + 1;
|
|
|
|
else
|
|
|
|
rd_pkt_count <= rd_pkt_count_reg;
|
|
|
|
end
|
|
|
|
|
|
|
|
assign wr_pkt_count_rd = wr_pkt_count_q[SYNC_STAGE_WIDTH-1:SYNC_STAGE_WIDTH-C_WR_PNTR_WIDTH];
|
|
|
|
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft)
|
|
|
|
rd_pkt_count_reg <= 0;
|
|
|
|
else if (rd_en_fifo_in)
|
|
|
|
rd_pkt_count_reg <= #`TCQ rd_pkt_count;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge rst_fwft or posedge RD_CLK_P0_IN) begin
|
|
|
|
if (rst_fwft) begin
|
|
|
|
ram_pkt_empty <= 1'b1;
|
|
|
|
ram_pkt_empty_d1 <= 1'b1;
|
|
|
|
end else if (rd_pkt_count != wr_pkt_count_rd) begin
|
|
|
|
ram_pkt_empty <= #`TCQ 1'b0;
|
|
|
|
ram_pkt_empty_d1 <= #`TCQ 1'b0;
|
|
|
|
end else if (ram_pkt_empty_d1 && rd_en_to_fwft_fifo) begin
|
|
|
|
ram_pkt_empty <= #`TCQ 1'b1;
|
|
|
|
end else if ((rd_pkt_count == wr_pkt_count_rd) && stage2_reg_en_i) begin
|
|
|
|
ram_pkt_empty_d1 <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// Synchronize the empty in write domain
|
|
|
|
always @ (posedge wr_rst_fwft_pkt_fifo or posedge WR_CLK) begin
|
|
|
|
if (wr_rst_fwft_pkt_fifo)
|
|
|
|
pkt_empty_sync <= 'b1;
|
|
|
|
else
|
|
|
|
pkt_empty_sync <= #`TCQ {pkt_empty_sync[C_SYNCHRONIZER_STAGE-2:0], empty_p0_out};
|
|
|
|
end
|
|
|
|
|
|
|
|
end endgenerate //gras_pkt_cnt
|
|
|
|
|
|
|
|
generate if (IS_FWFT == 0 || C_FIFO_TYPE == 3) begin : STD_FIFO
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// If NOT First-Word Fall-Through, wire the outputs
|
|
|
|
// of the internal _ss or _as FIFO directly to the
|
|
|
|
// output, and do not instantiate the preload0
|
|
|
|
// module.
|
|
|
|
//***********************************************
|
|
|
|
|
|
|
|
assign RD_CLK_P0_IN = 0;
|
|
|
|
assign RST_P0_IN = 0;
|
|
|
|
assign RD_EN_P0_IN = 0;
|
|
|
|
|
|
|
|
assign RD_EN_FIFO_IN = rd_en_delayed;
|
|
|
|
|
|
|
|
assign DOUT = DOUT_FIFO_OUT;
|
|
|
|
assign DATA_P0_IN = 0;
|
|
|
|
assign VALID = VALID_FIFO_OUT;
|
|
|
|
assign EMPTY = EMPTY_FIFO_OUT;
|
|
|
|
assign ALMOST_EMPTY = ALMOST_EMPTY_FIFO_OUT;
|
|
|
|
assign EMPTY_P0_IN = 0;
|
|
|
|
assign UNDERFLOW = UNDERFLOW_FIFO_OUT;
|
|
|
|
assign DATA_COUNT = DATA_COUNT_FIFO_OUT;
|
|
|
|
assign SBITERR = sbiterr_fifo_out;
|
|
|
|
assign DBITERR = dbiterr_fifo_out;
|
|
|
|
|
|
|
|
end endgenerate // STD_FIFO
|
|
|
|
|
|
|
|
generate if (IS_FWFT == 1 && C_FIFO_TYPE != 1) begin : NO_PKT_FIFO
|
|
|
|
assign empty_p0_out = empty_fwft;
|
|
|
|
assign SBITERR = sbiterr_fwft;
|
|
|
|
assign DBITERR = dbiterr_fwft;
|
|
|
|
assign DOUT = dout_fwft;
|
|
|
|
assign RD_EN_P0_IN = (C_FIFO_TYPE != 1) ? rd_en_delayed : rd_en_to_fwft_fifo;
|
|
|
|
|
|
|
|
end endgenerate // NO_PKT_FIFO
|
|
|
|
|
|
|
|
//***********************************************
|
|
|
|
// Connect user flags to internal signals
|
|
|
|
//***********************************************
|
|
|
|
|
|
|
|
//If we are using extra logic for the FWFT data count, then override the
|
|
|
|
//RD_DATA_COUNT output when we are EMPTY or ALMOST_EMPTY.
|
|
|
|
//RD_DATA_COUNT is 0 when EMPTY and 1 when ALMOST_EMPTY.
|
|
|
|
generate
|
|
|
|
if (C_USE_FWFT_DATA_COUNT==1 && (C_RD_DATA_COUNT_WIDTH>C_RD_PNTR_WIDTH) ) begin : block3
|
|
|
|
if (C_COMMON_CLOCK == 0) begin : block_ic
|
|
|
|
assign RD_DATA_COUNT = (EMPTY_P0_OUT_Q | RST_P0_IN) ? 0 : (ALMOSTEMPTY_P0_OUT_Q ? 1 : RD_DATA_COUNT_FIFO_OUT);
|
|
|
|
end //block_ic
|
|
|
|
else begin
|
|
|
|
assign RD_DATA_COUNT = RD_DATA_COUNT_FIFO_OUT;
|
|
|
|
end
|
|
|
|
end //block3
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//If we are using extra logic for the FWFT data count, then override the
|
|
|
|
//RD_DATA_COUNT output when we are EMPTY or ALMOST_EMPTY.
|
|
|
|
//Due to asymmetric ports, RD_DATA_COUNT is 0 when EMPTY or ALMOST_EMPTY.
|
|
|
|
generate
|
|
|
|
if (C_USE_FWFT_DATA_COUNT==1 && (C_RD_DATA_COUNT_WIDTH <=C_RD_PNTR_WIDTH) ) begin : block30
|
|
|
|
if (C_COMMON_CLOCK == 0) begin : block_ic
|
|
|
|
assign RD_DATA_COUNT = (EMPTY_P0_OUT_Q | RST_P0_IN) ? 0 : (ALMOSTEMPTY_P0_OUT_Q ? 0 : RD_DATA_COUNT_FIFO_OUT);
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
assign RD_DATA_COUNT = RD_DATA_COUNT_FIFO_OUT;
|
|
|
|
end
|
|
|
|
end //block30
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//If we are not using extra logic for the FWFT data count,
|
|
|
|
//then connect RD_DATA_COUNT to the RD_DATA_COUNT from the
|
|
|
|
//internal FIFO instance
|
|
|
|
generate
|
|
|
|
if (C_USE_FWFT_DATA_COUNT==0 ) begin : block31
|
|
|
|
assign RD_DATA_COUNT = RD_DATA_COUNT_FIFO_OUT;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//Always connect WR_DATA_COUNT to the WR_DATA_COUNT from the internal
|
|
|
|
//FIFO instance
|
|
|
|
generate
|
|
|
|
if (C_USE_FWFT_DATA_COUNT==1) begin : block4
|
|
|
|
assign WR_DATA_COUNT = WR_DATA_COUNT_FIFO_OUT;
|
|
|
|
end
|
|
|
|
else begin : block4
|
|
|
|
assign WR_DATA_COUNT = WR_DATA_COUNT_FIFO_OUT;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
//Connect other flags to the internal FIFO instance
|
|
|
|
assign FULL = FULL_FIFO_OUT;
|
|
|
|
assign ALMOST_FULL = ALMOST_FULL_FIFO_OUT;
|
|
|
|
assign WR_ACK = WR_ACK_FIFO_OUT;
|
|
|
|
assign OVERFLOW = OVERFLOW_FIFO_OUT;
|
|
|
|
assign PROG_FULL = PROG_FULL_FIFO_OUT;
|
|
|
|
assign PROG_EMPTY = PROG_EMPTY_FIFO_OUT;
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* find_log2
|
|
|
|
* Returns the 'log2' value for the input value for the supported ratios
|
|
|
|
***************************************************************************/
|
|
|
|
function integer find_log2;
|
|
|
|
input integer int_val;
|
|
|
|
integer i,j;
|
|
|
|
begin
|
|
|
|
i = 1;
|
|
|
|
j = 0;
|
|
|
|
for (i = 1; i < int_val; i = i*2) begin
|
|
|
|
j = j + 1;
|
|
|
|
end
|
|
|
|
find_log2 = j;
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Internal reset logic
|
|
|
|
**************************************************************************/
|
|
|
|
assign wr_rst_i = (C_HAS_RST == 1 || C_ENABLE_RST_SYNC == 0) ? wr_rst_reg : 0;
|
|
|
|
assign rd_rst_i = (C_HAS_RST == 1 || C_ENABLE_RST_SYNC == 0) ? rd_rst_reg : 0;
|
|
|
|
assign rst_i = C_HAS_RST ? rst_reg : 0;
|
|
|
|
|
|
|
|
wire rst_2_sync;
|
|
|
|
wire clk_2_sync = (C_COMMON_CLOCK == 1) ? CLK : WR_CLK;
|
|
|
|
generate
|
|
|
|
if (C_ENABLE_RST_SYNC == 0) begin : gnrst_sync
|
|
|
|
always @* begin
|
|
|
|
wr_rst_reg <= wr_rst_delayed;
|
|
|
|
rd_rst_reg <= rd_rst_delayed;
|
|
|
|
rst_reg <= 1'b0;
|
|
|
|
srst_reg <= 1'b0;
|
|
|
|
end
|
|
|
|
assign rst_2_sync = wr_rst_delayed;
|
|
|
|
assign wr_rst_busy = 1'b0;
|
|
|
|
assign rd_rst_busy = 1'b0;
|
|
|
|
end else if (C_HAS_RST == 1 && C_COMMON_CLOCK == 0) begin : g7s_ic_rst
|
|
|
|
assign wr_rst_comb = !wr_rst_asreg_d2 && wr_rst_asreg;
|
|
|
|
assign rd_rst_comb = !rd_rst_asreg_d2 && rd_rst_asreg;
|
|
|
|
assign rst_2_sync = rst_delayed;
|
|
|
|
assign wr_rst_busy = 1'b0;
|
|
|
|
assign rd_rst_busy = 1'b0;
|
|
|
|
|
|
|
|
always @(posedge WR_CLK or posedge rst_delayed) begin
|
|
|
|
if (rst_delayed == 1'b1) begin
|
|
|
|
wr_rst_asreg <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if (wr_rst_asreg_d1 == 1'b1) begin
|
|
|
|
wr_rst_asreg <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
wr_rst_asreg <= #`TCQ wr_rst_asreg;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge WR_CLK) begin
|
|
|
|
wr_rst_asreg_d1 <= #`TCQ wr_rst_asreg;
|
|
|
|
wr_rst_asreg_d2 <= #`TCQ wr_rst_asreg_d1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge WR_CLK or posedge wr_rst_comb) begin
|
|
|
|
if (wr_rst_comb == 1'b1) begin
|
|
|
|
wr_rst_reg <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
wr_rst_reg <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge RD_CLK or posedge rst_delayed) begin
|
|
|
|
if (rst_delayed == 1'b1) begin
|
|
|
|
rd_rst_asreg <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if (rd_rst_asreg_d1 == 1'b1) begin
|
|
|
|
rd_rst_asreg <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
rd_rst_asreg <= #`TCQ rd_rst_asreg;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge RD_CLK) begin
|
|
|
|
rd_rst_asreg_d1 <= #`TCQ rd_rst_asreg;
|
|
|
|
rd_rst_asreg_d2 <= #`TCQ rd_rst_asreg_d1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge RD_CLK or posedge rd_rst_comb) begin
|
|
|
|
if (rd_rst_comb == 1'b1) begin
|
|
|
|
rd_rst_reg <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
rd_rst_reg <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end else if (C_HAS_RST == 1 && C_COMMON_CLOCK == 1) begin : g7s_cc_rst
|
|
|
|
assign rst_comb = !rst_asreg_d2 && rst_asreg;
|
|
|
|
assign rst_2_sync = rst_delayed;
|
|
|
|
assign wr_rst_busy = 1'b0;
|
|
|
|
assign rd_rst_busy = 1'b0;
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge rst_delayed) begin
|
|
|
|
if (rst_delayed == 1'b1) begin
|
|
|
|
rst_asreg <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if (rst_asreg_d1 == 1'b1) begin
|
|
|
|
rst_asreg <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
rst_asreg <= #`TCQ rst_asreg;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
rst_asreg_d1 <= #`TCQ rst_asreg;
|
|
|
|
rst_asreg_d2 <= #`TCQ rst_asreg_d1;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge rst_comb) begin
|
|
|
|
if (rst_comb == 1'b1) begin
|
|
|
|
rst_reg <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
rst_reg <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end else if (IS_8SERIES == 1 && C_HAS_SRST == 1 && C_COMMON_CLOCK == 1) begin : g8s_cc_rst
|
|
|
|
assign wr_rst_busy = (C_MEMORY_TYPE != 4) ? rst_reg : rst_active_i;
|
|
|
|
assign rd_rst_busy = rst_reg;
|
|
|
|
assign rst_2_sync = srst_delayed;
|
|
|
|
always @* rst_full_ff_i <= rst_reg;
|
|
|
|
always @* rst_full_gen_i <= C_FULL_FLAGS_RST_VAL == 1 ? rst_active_i : 0;
|
|
|
|
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
rst_delayed_d1 <= #`TCQ srst_delayed;
|
|
|
|
rst_delayed_d2 <= #`TCQ rst_delayed_d1;
|
|
|
|
if (rst_reg || rst_delayed_d2) begin
|
|
|
|
rst_active_i <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
rst_active_i <= #`TCQ rst_reg;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if (~rst_reg && srst_delayed) begin
|
|
|
|
rst_reg <= #`TCQ 1'b1;
|
|
|
|
end else if (rst_reg) begin
|
|
|
|
rst_reg <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
rst_reg <= #`TCQ rst_reg;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
assign wr_rst_busy = 1'b0;
|
|
|
|
assign rd_rst_busy = 1'b0;
|
|
|
|
end
|
|
|
|
// end g8s_cc_rst
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
reg rst_d1 = 1'b0;
|
|
|
|
reg rst_d2 = 1'b0;
|
|
|
|
reg rst_d3 = 1'b0;
|
|
|
|
reg rst_d4 = 1'b0;
|
|
|
|
generate
|
|
|
|
if ((C_HAS_RST == 1 || C_HAS_SRST == 1 || C_ENABLE_RST_SYNC == 0) && C_FULL_FLAGS_RST_VAL == 1) begin : grstd1
|
|
|
|
// RST_FULL_GEN replaces the reset falling edge detection used to de-assert
|
|
|
|
// FULL, ALMOST_FULL & PROG_FULL flags if C_FULL_FLAGS_RST_VAL = 1.
|
|
|
|
|
|
|
|
// RST_FULL_FF goes to the reset pin of the final flop of FULL, ALMOST_FULL &
|
|
|
|
// PROG_FULL
|
|
|
|
|
|
|
|
always @ (posedge rst_2_sync or posedge clk_2_sync) begin
|
|
|
|
if (rst_2_sync) begin
|
|
|
|
rst_d1 <= 1'b1;
|
|
|
|
rst_d2 <= 1'b1;
|
|
|
|
rst_d3 <= 1'b1;
|
|
|
|
rst_d4 <= 1'b0;
|
|
|
|
end else begin
|
|
|
|
if (srst_delayed) begin
|
|
|
|
rst_d1 <= #`TCQ 1'b1;
|
|
|
|
rst_d2 <= #`TCQ 1'b1;
|
|
|
|
rst_d3 <= #`TCQ 1'b1;
|
|
|
|
rst_d4 <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
rst_d1 <= #`TCQ 1'b0;
|
|
|
|
rst_d2 <= #`TCQ rst_d1;
|
|
|
|
rst_d3 <= #`TCQ rst_d2;
|
|
|
|
rst_d4 <= #`TCQ rst_d3;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always @* rst_full_ff_i <= (C_HAS_SRST == 0) ? rst_d2 : 1'b0 ;
|
|
|
|
always @* rst_full_gen_i <= rst_d4;
|
|
|
|
|
|
|
|
end else if ((C_HAS_RST == 1 || C_HAS_SRST == 1 || C_ENABLE_RST_SYNC == 0) && C_FULL_FLAGS_RST_VAL == 0) begin : gnrst_full
|
|
|
|
always @* rst_full_ff_i <= (C_COMMON_CLOCK == 0) ? wr_rst_i : rst_i;
|
|
|
|
end
|
|
|
|
endgenerate // grstd1
|
|
|
|
|
|
|
|
endmodule //FIFO_GENERATOR_v12_0_CONV_VER
|
|
|
|
|
|
|
|
|
|
|
|
module fifo_generator_v12_0_sync_stage
|
|
|
|
#(
|
|
|
|
parameter C_WIDTH = 10
|
|
|
|
)
|
|
|
|
(
|
|
|
|
input RST,
|
|
|
|
input CLK,
|
|
|
|
input [C_WIDTH-1:0] DIN,
|
|
|
|
output reg [C_WIDTH-1:0] DOUT = 0
|
|
|
|
);
|
|
|
|
always @ (posedge RST or posedge CLK) begin
|
|
|
|
if (RST)
|
|
|
|
DOUT <= 0;
|
|
|
|
else
|
|
|
|
DOUT <= #`TCQ DIN;
|
|
|
|
end
|
|
|
|
endmodule // fifo_generator_v12_0_sync_stage
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Declaration of Independent-Clocks FIFO Module
|
|
|
|
******************************************************************************/
|
|
|
|
module fifo_generator_v12_0_bhv_ver_as
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Declare user parameters and their defaults
|
|
|
|
***************************************************************************/
|
|
|
|
#(
|
|
|
|
parameter C_FAMILY = "virtex7",
|
|
|
|
parameter C_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_DIN_WIDTH = 8,
|
|
|
|
parameter C_DOUT_RST_VAL = "",
|
|
|
|
parameter C_DOUT_WIDTH = 8,
|
|
|
|
parameter C_FULL_FLAGS_RST_VAL = 1,
|
|
|
|
parameter C_HAS_ALMOST_EMPTY = 0,
|
|
|
|
parameter C_HAS_ALMOST_FULL = 0,
|
|
|
|
parameter C_HAS_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_OVERFLOW = 0,
|
|
|
|
parameter C_HAS_RD_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_RST = 0,
|
|
|
|
parameter C_HAS_UNDERFLOW = 0,
|
|
|
|
parameter C_HAS_VALID = 0,
|
|
|
|
parameter C_HAS_WR_ACK = 0,
|
|
|
|
parameter C_HAS_WR_DATA_COUNT = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE = 0,
|
|
|
|
parameter C_MEMORY_TYPE = 1,
|
|
|
|
parameter C_OVERFLOW_LOW = 0,
|
|
|
|
parameter C_PRELOAD_LATENCY = 1,
|
|
|
|
parameter C_PRELOAD_REGS = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE = 0,
|
|
|
|
parameter C_RD_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_RD_DEPTH = 256,
|
|
|
|
parameter C_RD_PNTR_WIDTH = 8,
|
|
|
|
parameter C_UNDERFLOW_LOW = 0,
|
|
|
|
parameter C_USE_DOUT_RST = 0,
|
|
|
|
parameter C_USE_EMBEDDED_REG = 0,
|
|
|
|
parameter C_USE_FWFT_DATA_COUNT = 0,
|
|
|
|
parameter C_VALID_LOW = 0,
|
|
|
|
parameter C_WR_ACK_LOW = 0,
|
|
|
|
parameter C_WR_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_WR_DEPTH = 256,
|
|
|
|
parameter C_WR_PNTR_WIDTH = 8,
|
|
|
|
parameter C_USE_ECC = 0,
|
|
|
|
parameter C_ENABLE_RST_SYNC = 1,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE = 0,
|
|
|
|
parameter C_SYNCHRONIZER_STAGE = 2
|
|
|
|
)
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Declare Input and Output Ports
|
|
|
|
***************************************************************************/
|
|
|
|
(
|
|
|
|
input [C_DIN_WIDTH-1:0] DIN,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE,
|
|
|
|
input RD_CLK,
|
|
|
|
input RD_EN,
|
|
|
|
input RD_EN_USER,
|
|
|
|
input RST,
|
|
|
|
input RST_FULL_GEN,
|
|
|
|
input RST_FULL_FF,
|
|
|
|
input WR_RST,
|
|
|
|
input RD_RST,
|
|
|
|
input WR_CLK,
|
|
|
|
input WR_EN,
|
|
|
|
input INJECTDBITERR,
|
|
|
|
input INJECTSBITERR,
|
|
|
|
input USER_EMPTY_FB,
|
|
|
|
output reg ALMOST_EMPTY = 1'b1,
|
|
|
|
output reg ALMOST_FULL = C_FULL_FLAGS_RST_VAL,
|
|
|
|
output [C_DOUT_WIDTH-1:0] DOUT,
|
|
|
|
output reg EMPTY = 1'b1,
|
|
|
|
output reg FULL = C_FULL_FLAGS_RST_VAL,
|
|
|
|
output OVERFLOW,
|
|
|
|
output PROG_EMPTY,
|
|
|
|
output PROG_FULL,
|
|
|
|
output VALID,
|
|
|
|
output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT,
|
|
|
|
output UNDERFLOW,
|
|
|
|
output WR_ACK,
|
|
|
|
output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT,
|
|
|
|
output SBITERR,
|
|
|
|
output DBITERR
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
reg [C_RD_PNTR_WIDTH:0] rd_data_count_int = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH:0] wr_data_count_int = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH:0] wdc_fwft_ext_as = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Parameters used as constants
|
|
|
|
**************************************************************************/
|
|
|
|
localparam IS_8SERIES = (C_FAMILY == "virtexu" || C_FAMILY == "kintexu" || C_FAMILY == "artixu" || C_FAMILY == "virtexum" || C_FAMILY == "zynque") ? 1 : 0;
|
|
|
|
//When RST is present, set FULL reset value to '1'.
|
|
|
|
//If core has no RST, make sure FULL powers-on as '0'.
|
|
|
|
localparam C_DEPTH_RATIO_WR =
|
|
|
|
(C_WR_DEPTH>C_RD_DEPTH) ? (C_WR_DEPTH/C_RD_DEPTH) : 1;
|
|
|
|
localparam C_DEPTH_RATIO_RD =
|
|
|
|
(C_RD_DEPTH>C_WR_DEPTH) ? (C_RD_DEPTH/C_WR_DEPTH) : 1;
|
|
|
|
localparam C_FIFO_WR_DEPTH = C_WR_DEPTH - 1;
|
|
|
|
localparam C_FIFO_RD_DEPTH = C_RD_DEPTH - 1;
|
|
|
|
|
|
|
|
// C_DEPTH_RATIO_WR | C_DEPTH_RATIO_RD | C_PNTR_WIDTH | EXTRA_WORDS_DC
|
|
|
|
// -----------------|------------------|-----------------|---------------
|
|
|
|
// 1 | 8 | C_RD_PNTR_WIDTH | 2
|
|
|
|
// 1 | 4 | C_RD_PNTR_WIDTH | 2
|
|
|
|
// 1 | 2 | C_RD_PNTR_WIDTH | 2
|
|
|
|
// 1 | 1 | C_WR_PNTR_WIDTH | 2
|
|
|
|
// 2 | 1 | C_WR_PNTR_WIDTH | 4
|
|
|
|
// 4 | 1 | C_WR_PNTR_WIDTH | 8
|
|
|
|
// 8 | 1 | C_WR_PNTR_WIDTH | 16
|
|
|
|
|
|
|
|
localparam C_PNTR_WIDTH = (C_WR_PNTR_WIDTH>=C_RD_PNTR_WIDTH) ? C_WR_PNTR_WIDTH : C_RD_PNTR_WIDTH;
|
|
|
|
wire [C_PNTR_WIDTH:0] EXTRA_WORDS_DC = (C_DEPTH_RATIO_WR == 1) ? 2 : (2 * C_DEPTH_RATIO_WR/C_DEPTH_RATIO_RD);
|
|
|
|
|
|
|
|
localparam [31:0] reads_per_write = C_DIN_WIDTH/C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
localparam [31:0] log2_reads_per_write = log2_val(reads_per_write);
|
|
|
|
|
|
|
|
localparam [31:0] writes_per_read = C_DOUT_WIDTH/C_DIN_WIDTH;
|
|
|
|
|
|
|
|
localparam [31:0] log2_writes_per_read = log2_val(writes_per_read);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* FIFO Contents Tracking and Data Count Calculations
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
// Memory which will be used to simulate a FIFO
|
|
|
|
reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0];
|
|
|
|
// Local parameters used to determine whether to inject ECC error or not
|
|
|
|
localparam SYMMETRIC_PORT = (C_DIN_WIDTH == C_DOUT_WIDTH) ? 1 : 0;
|
|
|
|
localparam ERR_INJECTION = (C_ERROR_INJECTION_TYPE != 0) ? 1 : 0;
|
|
|
|
localparam ENABLE_ERR_INJECTION = C_USE_ECC && SYMMETRIC_PORT && ERR_INJECTION;
|
|
|
|
// Array that holds the error injection type (single/double bit error) on
|
|
|
|
// a specific write operation, which is returned on read to corrupt the
|
|
|
|
// output data.
|
|
|
|
reg [1:0] ecc_err[C_WR_DEPTH-1:0];
|
|
|
|
|
|
|
|
//The amount of data stored in the FIFO at any time is given
|
|
|
|
// by num_wr_bits (in the WR_CLK domain) and num_rd_bits (in the RD_CLK
|
|
|
|
// domain.
|
|
|
|
//num_wr_bits is calculated by considering the total words in the FIFO,
|
|
|
|
// and the state of the read pointer (which may not have yet crossed clock
|
|
|
|
// domains.)
|
|
|
|
//num_rd_bits is calculated by considering the total words in the FIFO,
|
|
|
|
// and the state of the write pointer (which may not have yet crossed clock
|
|
|
|
// domains.)
|
|
|
|
reg [31:0] num_wr_bits;
|
|
|
|
reg [31:0] num_rd_bits;
|
|
|
|
reg [31:0] next_num_wr_bits;
|
|
|
|
reg [31:0] next_num_rd_bits;
|
|
|
|
|
|
|
|
//The write pointer - tracks write operations
|
|
|
|
// (Works opposite to core: wr_ptr is a DOWN counter)
|
|
|
|
reg [31:0] wr_ptr;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr = 0; // UP counter: Rolls back to 0 when reaches to max value.
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd1 = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd2 = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd3 = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] adj_wr_pntr_rd;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd = 0;
|
|
|
|
wire wr_rst_i = WR_RST;
|
|
|
|
reg wr_rst_d1 =0;
|
|
|
|
|
|
|
|
//The read pointer - tracks read operations
|
|
|
|
// (rd_ptr Works opposite to core: rd_ptr is a DOWN counter)
|
|
|
|
reg [31:0] rd_ptr;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr = 0; // UP counter: Rolls back to 0 when reaches to max value.
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr1 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr2 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr3 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr4 = 0;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] adj_rd_pntr_wr;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr = 0;
|
|
|
|
wire rd_rst_i = RD_RST;
|
|
|
|
wire ram_rd_en;
|
|
|
|
wire empty_int;
|
|
|
|
wire almost_empty_int;
|
|
|
|
wire ram_wr_en;
|
|
|
|
wire full_int;
|
|
|
|
wire almost_full_int;
|
|
|
|
reg ram_rd_en_d1 = 1'b0;
|
|
|
|
|
|
|
|
|
|
|
|
// Delayed ram_rd_en is needed only for STD Embedded register option
|
|
|
|
generate
|
|
|
|
if (C_PRELOAD_LATENCY == 2) begin : grd_d
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i)
|
|
|
|
ram_rd_en_d1 <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
ram_rd_en_d1 <= #`TCQ ram_rd_en;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
// Write pointer adjustment based on pointers width for EMPTY/ALMOST_EMPTY generation
|
2015-11-13 16:25:38 -05:00
|
|
|
//ANDREAS: NOP
|
2015-11-12 09:57:55 -05:00
|
|
|
generate
|
|
|
|
if (C_RD_PNTR_WIDTH > C_WR_PNTR_WIDTH) begin : rdg // Read depth greater than write depth
|
|
|
|
assign adj_wr_pntr_rd[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr_rd;
|
|
|
|
assign adj_wr_pntr_rd[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1:0] = 0;
|
|
|
|
end else begin : rdl // Read depth lesser than or equal to write depth
|
|
|
|
assign adj_wr_pntr_rd = wr_pntr_rd[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH];
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
// Generate Empty and Almost Empty
|
|
|
|
// ram_rd_en used to determine EMPTY should depend on the EMPTY.
|
|
|
|
assign ram_rd_en = RD_EN & !EMPTY;
|
|
|
|
assign empty_int = ((adj_wr_pntr_rd == rd_pntr) || (ram_rd_en && (adj_wr_pntr_rd == (rd_pntr+1'h1))));
|
|
|
|
assign almost_empty_int = ((adj_wr_pntr_rd == (rd_pntr+1'h1)) || (ram_rd_en && (adj_wr_pntr_rd == (rd_pntr+2'h2))));
|
|
|
|
|
|
|
|
// Register Empty and Almost Empty
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i)
|
|
|
|
begin
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
EMPTY <= #`TCQ 1'b1;
|
|
|
|
ALMOST_EMPTY <= #`TCQ 1'b1;
|
|
|
|
rd_data_count_int <= #`TCQ {C_RD_PNTR_WIDTH{1'b0}};
|
|
|
|
end else begin
|
|
|
|
rd_data_count_int <= #`TCQ {(adj_wr_pntr_rd[C_RD_PNTR_WIDTH-1:0] - rd_pntr[C_RD_PNTR_WIDTH-1:0]), 1'b0};
|
|
|
|
|
|
|
|
if (empty_int)
|
|
|
|
EMPTY <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
EMPTY <= #`TCQ 1'b0;
|
|
|
|
|
|
|
|
if (!EMPTY) begin
|
|
|
|
if (almost_empty_int)
|
|
|
|
ALMOST_EMPTY <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
ALMOST_EMPTY <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end // rd_rst_i
|
|
|
|
end // always
|
|
|
|
|
|
|
|
// Read pointer adjustment based on pointers width for EMPTY/ALMOST_EMPTY generation
|
|
|
|
generate
|
|
|
|
if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : wdg // Write depth greater than read depth
|
|
|
|
assign adj_rd_pntr_wr[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH] = rd_pntr_wr;
|
|
|
|
assign adj_rd_pntr_wr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1:0] = 0;
|
|
|
|
end else begin : wdl // Write depth lesser than or equal to read depth
|
|
|
|
assign adj_rd_pntr_wr = rd_pntr_wr[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH];
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
// Generate FULL and ALMOST_FULL
|
|
|
|
// ram_wr_en used to determine FULL should depend on the FULL.
|
|
|
|
assign ram_wr_en = WR_EN & !FULL;
|
|
|
|
assign full_int = ((adj_rd_pntr_wr == (wr_pntr+1'h1)) || (ram_wr_en && (adj_rd_pntr_wr == (wr_pntr+2'h2))));
|
|
|
|
assign almost_full_int = ((adj_rd_pntr_wr == (wr_pntr+2'h2)) || (ram_wr_en && (adj_rd_pntr_wr == (wr_pntr+3'h3))));
|
|
|
|
|
|
|
|
// Register FULL and ALMOST_FULL Empty
|
|
|
|
always @ (posedge WR_CLK or posedge RST_FULL_FF)
|
|
|
|
begin
|
|
|
|
if (RST_FULL_FF) begin
|
|
|
|
FULL <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
ALMOST_FULL <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
end else begin
|
|
|
|
if (full_int) begin
|
|
|
|
FULL <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
FULL <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
|
|
|
|
if (RST_FULL_GEN) begin
|
|
|
|
ALMOST_FULL <= #`TCQ 1'b0;
|
|
|
|
end else if (!FULL) begin
|
|
|
|
if (almost_full_int)
|
|
|
|
ALMOST_FULL <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
ALMOST_FULL <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end // wr_rst_i
|
|
|
|
end // always
|
|
|
|
always @ (posedge WR_CLK or posedge wr_rst_i)
|
|
|
|
begin
|
|
|
|
if (wr_rst_i) begin
|
|
|
|
wr_data_count_int <= #`TCQ {C_WR_DATA_COUNT_WIDTH{1'b0}};
|
|
|
|
end else begin
|
|
|
|
wr_data_count_int <= #`TCQ {(wr_pntr[C_WR_PNTR_WIDTH-1:0] - adj_rd_pntr_wr[C_WR_PNTR_WIDTH-1:0]), 1'b0};
|
|
|
|
end // wr_rst_i
|
|
|
|
end // always
|
|
|
|
|
|
|
|
// Determine which stage in FWFT registers are valid
|
|
|
|
reg stage1_valid = 0;
|
|
|
|
reg stage2_valid = 0;
|
|
|
|
generate
|
|
|
|
if (C_PRELOAD_LATENCY == 0) begin : grd_fwft_proc
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
stage1_valid <= #`TCQ 0;
|
|
|
|
stage2_valid <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
if (!stage1_valid && !stage2_valid) begin
|
|
|
|
if (!EMPTY)
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
end else if (stage1_valid && !stage2_valid) begin
|
|
|
|
if (EMPTY) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end else if (!stage1_valid && stage2_valid) begin
|
|
|
|
if (EMPTY && RD_EN_USER) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b0;
|
|
|
|
end else if (!EMPTY && RD_EN_USER) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b0;
|
|
|
|
end else if (!EMPTY && !RD_EN_USER) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end else if (stage1_valid && stage2_valid) begin
|
|
|
|
if (EMPTY && RD_EN_USER) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end // rd_rst_i
|
|
|
|
end // always
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//Pointers passed into opposite clock domain
|
|
|
|
reg [31:0] wr_ptr_rdclk;
|
|
|
|
reg [31:0] wr_ptr_rdclk_next;
|
|
|
|
reg [31:0] rd_ptr_wrclk;
|
|
|
|
reg [31:0] rd_ptr_wrclk_next;
|
|
|
|
|
|
|
|
//Amount of data stored in the FIFO scaled to the narrowest (deepest) port
|
|
|
|
// (Do not include data in FWFT stages)
|
|
|
|
//Used to calculate PROG_EMPTY.
|
|
|
|
wire [31:0] num_read_words_pe =
|
|
|
|
num_rd_bits/(C_DOUT_WIDTH/C_DEPTH_RATIO_WR);
|
|
|
|
|
|
|
|
//Amount of data stored in the FIFO scaled to the narrowest (deepest) port
|
|
|
|
// (Do not include data in FWFT stages)
|
|
|
|
//Used to calculate PROG_FULL.
|
|
|
|
wire [31:0] num_write_words_pf =
|
|
|
|
num_wr_bits/(C_DIN_WIDTH/C_DEPTH_RATIO_RD);
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
* Read Data Count
|
|
|
|
*************************/
|
|
|
|
|
|
|
|
reg [31:0] num_read_words_dc;
|
|
|
|
reg [C_RD_DATA_COUNT_WIDTH-1:0] num_read_words_sized_i;
|
|
|
|
|
|
|
|
always @(num_rd_bits) begin
|
|
|
|
if (C_USE_FWFT_DATA_COUNT) begin
|
|
|
|
|
|
|
|
//If using extra logic for FWFT Data Counts,
|
|
|
|
// then scale FIFO contents to read domain,
|
|
|
|
// and add two read words for FWFT stages
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_read_words_dc = (num_rd_bits/C_DOUT_WIDTH+2);
|
|
|
|
|
|
|
|
//Trim the read words for use with RD_DATA_COUNT
|
|
|
|
num_read_words_sized_i =
|
|
|
|
num_read_words_dc[C_RD_PNTR_WIDTH : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH+1];
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
//If not using extra logic for FWFT Data Counts,
|
|
|
|
// then scale FIFO contents to read domain.
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_read_words_dc = num_rd_bits/C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Trim the read words for use with RD_DATA_COUNT
|
|
|
|
num_read_words_sized_i =
|
|
|
|
num_read_words_dc[C_RD_PNTR_WIDTH-1 : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH];
|
|
|
|
|
|
|
|
end //if (C_USE_FWFT_DATA_COUNT)
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
* Write Data Count
|
|
|
|
*************************/
|
|
|
|
|
|
|
|
reg [31:0] num_write_words_dc;
|
|
|
|
reg [C_WR_DATA_COUNT_WIDTH-1:0] num_write_words_sized_i;
|
|
|
|
|
|
|
|
always @(num_wr_bits) begin
|
|
|
|
if (C_USE_FWFT_DATA_COUNT) begin
|
|
|
|
|
|
|
|
//Calculate the Data Count value for the number of write words,
|
|
|
|
// when using First-Word Fall-Through with extra logic for Data
|
|
|
|
// Counts. This takes into consideration the number of words that
|
|
|
|
// are expected to be stored in the FWFT register stages (it always
|
|
|
|
// assumes they are filled).
|
|
|
|
//This value is scaled to the Write Domain.
|
|
|
|
//The expression (((A-1)/B))+1 divides A/B, but takes the
|
|
|
|
// ceiling of the result.
|
|
|
|
//When num_wr_bits==0, set the result manually to prevent
|
|
|
|
// division errors.
|
|
|
|
//EXTRA_WORDS_DC is the number of words added to write_words
|
|
|
|
// due to FWFT.
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_write_words_dc = (num_wr_bits==0) ? EXTRA_WORDS_DC : (((num_wr_bits-1)/C_DIN_WIDTH)+1) + EXTRA_WORDS_DC ;
|
|
|
|
|
|
|
|
//Trim the write words for use with WR_DATA_COUNT
|
|
|
|
num_write_words_sized_i =
|
|
|
|
num_write_words_dc[C_WR_PNTR_WIDTH : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH+1];
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
//Calculate the Data Count value for the number of write words, when NOT
|
|
|
|
// using First-Word Fall-Through with extra logic for Data Counts. This
|
|
|
|
// calculates only the number of words in the internal FIFO.
|
|
|
|
//The expression (((A-1)/B))+1 divides A/B, but takes the
|
|
|
|
// ceiling of the result.
|
|
|
|
//This value is scaled to the Write Domain.
|
|
|
|
//When num_wr_bits==0, set the result manually to prevent
|
|
|
|
// division errors.
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_write_words_dc = (num_wr_bits==0) ? 0 : ((num_wr_bits-1)/C_DIN_WIDTH)+1;
|
|
|
|
|
|
|
|
//Trim the read words for use with RD_DATA_COUNT
|
|
|
|
num_write_words_sized_i =
|
|
|
|
num_write_words_dc[C_WR_PNTR_WIDTH-1 : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH];
|
|
|
|
|
|
|
|
end //if (C_USE_FWFT_DATA_COUNT)
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Internal registers and wires
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
//Temporary signals used for calculating the model's outputs. These
|
|
|
|
//are only used in the assign statements immediately following wire,
|
|
|
|
//parameter, and function declarations.
|
|
|
|
wire [C_DOUT_WIDTH-1:0] ideal_dout_out;
|
|
|
|
wire valid_i;
|
|
|
|
wire valid_out;
|
|
|
|
wire underflow_i;
|
|
|
|
|
|
|
|
//Ideal FIFO signals. These are the raw output of the behavioral model,
|
|
|
|
//which behaves like an ideal FIFO.
|
|
|
|
reg [1:0] err_type = 0;
|
|
|
|
reg [1:0] err_type_d1 = 0;
|
|
|
|
reg [C_DOUT_WIDTH-1:0] ideal_dout = 0;
|
|
|
|
reg [C_DOUT_WIDTH-1:0] ideal_dout_d1 = 0;
|
|
|
|
reg ideal_wr_ack = 0;
|
|
|
|
reg ideal_valid = 0;
|
|
|
|
reg ideal_overflow = C_OVERFLOW_LOW;
|
|
|
|
reg ideal_underflow = C_UNDERFLOW_LOW;
|
|
|
|
reg ideal_prog_full = 0;
|
|
|
|
reg ideal_prog_empty = 1;
|
|
|
|
reg [C_WR_DATA_COUNT_WIDTH-1 : 0] ideal_wr_count = 0;
|
|
|
|
reg [C_RD_DATA_COUNT_WIDTH-1 : 0] ideal_rd_count = 0;
|
|
|
|
|
|
|
|
//Assorted reg values for delayed versions of signals
|
|
|
|
reg valid_d1 = 0;
|
|
|
|
|
|
|
|
|
|
|
|
//user specified value for reseting the size of the fifo
|
|
|
|
reg [C_DOUT_WIDTH-1:0] dout_reset_val = 0;
|
|
|
|
|
|
|
|
//temporary registers for WR_RESPONSE_LATENCY feature
|
|
|
|
|
|
|
|
integer tmp_wr_listsize;
|
|
|
|
integer tmp_rd_listsize;
|
|
|
|
|
|
|
|
//Signal for registered version of prog full and empty
|
|
|
|
|
|
|
|
//Threshold values for Programmable Flags
|
|
|
|
integer prog_empty_actual_thresh_assert;
|
|
|
|
integer prog_empty_actual_thresh_negate;
|
|
|
|
integer prog_full_actual_thresh_assert;
|
|
|
|
integer prog_full_actual_thresh_negate;
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Function Declarations
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* write_fifo
|
|
|
|
* This task writes a word to the FIFO memory and updates the
|
|
|
|
* write pointer.
|
|
|
|
* FIFO size is relative to write domain.
|
|
|
|
***************************************************************************/
|
|
|
|
task write_fifo;
|
|
|
|
begin
|
2015-11-13 16:25:38 -05:00
|
|
|
//ANDREAS:$display("writing %x %d %m", DIN,wr_pntr);
|
2015-11-12 09:57:55 -05:00
|
|
|
memory[wr_ptr] <= DIN;
|
2015-11-13 16:25:38 -05:00
|
|
|
wr_pntr <= #`TCQ wr_pntr + 1;
|
2015-11-12 09:57:55 -05:00
|
|
|
// Store the type of error injection (double/single) on write
|
|
|
|
case (C_ERROR_INJECTION_TYPE)
|
|
|
|
3: ecc_err[wr_ptr] <= {INJECTDBITERR,INJECTSBITERR};
|
|
|
|
2: ecc_err[wr_ptr] <= {INJECTDBITERR,1'b0};
|
|
|
|
1: ecc_err[wr_ptr] <= {1'b0,INJECTSBITERR};
|
|
|
|
default: ecc_err[wr_ptr] <= 0;
|
|
|
|
endcase
|
|
|
|
// (Works opposite to core: wr_ptr is a DOWN counter)
|
|
|
|
if (wr_ptr == 0) begin
|
|
|
|
wr_ptr <= C_WR_DEPTH - 1;
|
|
|
|
end else begin
|
|
|
|
wr_ptr <= wr_ptr - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endtask // write_fifo
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* read_fifo
|
|
|
|
* This task reads a word from the FIFO memory and updates the read
|
|
|
|
* pointer. It's output is the ideal_dout bus.
|
|
|
|
* FIFO size is relative to write domain.
|
|
|
|
***************************************************************************/
|
|
|
|
task read_fifo;
|
|
|
|
integer i;
|
|
|
|
reg [C_DOUT_WIDTH-1:0] tmp_dout;
|
|
|
|
reg [C_DIN_WIDTH-1:0] memory_read;
|
|
|
|
reg [31:0] tmp_rd_ptr;
|
|
|
|
reg [31:0] rd_ptr_high;
|
|
|
|
reg [31:0] rd_ptr_low;
|
|
|
|
reg [1:0] tmp_ecc_err;
|
|
|
|
begin
|
|
|
|
rd_pntr <= #`TCQ rd_pntr + 1;
|
|
|
|
// output is wider than input
|
|
|
|
if (reads_per_write == 0) begin
|
|
|
|
tmp_dout = 0;
|
|
|
|
tmp_rd_ptr = (rd_ptr << log2_writes_per_read)+(writes_per_read-1);
|
|
|
|
for (i = writes_per_read - 1; i >= 0; i = i - 1) begin
|
|
|
|
tmp_dout = tmp_dout << C_DIN_WIDTH;
|
|
|
|
tmp_dout = tmp_dout | memory[tmp_rd_ptr];
|
|
|
|
|
|
|
|
// (Works opposite to core: rd_ptr is a DOWN counter)
|
|
|
|
if (tmp_rd_ptr == 0) begin
|
|
|
|
tmp_rd_ptr = C_WR_DEPTH - 1;
|
|
|
|
end else begin
|
|
|
|
tmp_rd_ptr = tmp_rd_ptr - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// output is symmetric
|
|
|
|
end else if (reads_per_write == 1) begin
|
|
|
|
tmp_dout = memory[rd_ptr][C_DIN_WIDTH-1:0];
|
|
|
|
// Retreive the error injection type. Based on the error injection type
|
|
|
|
// corrupt the output data.
|
|
|
|
tmp_ecc_err = ecc_err[rd_ptr];
|
|
|
|
if (ENABLE_ERR_INJECTION && C_DIN_WIDTH == C_DOUT_WIDTH) begin
|
|
|
|
if (tmp_ecc_err[1]) begin // Corrupt the output data only for double bit error
|
|
|
|
if (C_DOUT_WIDTH == 1) begin
|
2015-11-13 16:25:38 -05:00
|
|
|
$display("FAILURE : Data width must be >= 2 for double bit error injection.");
|
2015-11-12 09:57:55 -05:00
|
|
|
$finish;
|
|
|
|
end else if (C_DOUT_WIDTH == 2)
|
|
|
|
tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2]};
|
|
|
|
else
|
|
|
|
tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2],(tmp_dout << 2)};
|
|
|
|
end else begin
|
|
|
|
tmp_dout = tmp_dout[C_DOUT_WIDTH-1:0];
|
|
|
|
end
|
|
|
|
err_type <= {tmp_ecc_err[1], tmp_ecc_err[0] & !tmp_ecc_err[1]};
|
|
|
|
end else begin
|
|
|
|
err_type <= 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
// input is wider than output
|
|
|
|
end else begin
|
|
|
|
rd_ptr_high = rd_ptr >> log2_reads_per_write;
|
|
|
|
rd_ptr_low = rd_ptr & (reads_per_write - 1);
|
|
|
|
memory_read = memory[rd_ptr_high];
|
|
|
|
tmp_dout = memory_read >> (rd_ptr_low*C_DOUT_WIDTH);
|
|
|
|
end
|
|
|
|
ideal_dout <= tmp_dout;
|
|
|
|
|
|
|
|
// (Works opposite to core: rd_ptr is a DOWN counter)
|
|
|
|
if (rd_ptr == 0) begin
|
|
|
|
rd_ptr <= C_RD_DEPTH - 1;
|
|
|
|
end else begin
|
|
|
|
rd_ptr <= rd_ptr - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endtask
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* log2_val
|
|
|
|
* Returns the 'log2' value for the input value for the supported ratios
|
|
|
|
***************************************************************************/
|
|
|
|
function [31:0] log2_val;
|
|
|
|
input [31:0] binary_val;
|
|
|
|
|
|
|
|
begin
|
|
|
|
if (binary_val == 8) begin
|
|
|
|
log2_val = 3;
|
|
|
|
end else if (binary_val == 4) begin
|
|
|
|
log2_val = 2;
|
|
|
|
end else begin
|
|
|
|
log2_val = 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* hexstr_conv
|
|
|
|
* Converts a string of type hex to a binary value (for C_DOUT_RST_VAL)
|
|
|
|
***********************************************************************/
|
|
|
|
function [C_DOUT_WIDTH-1:0] hexstr_conv;
|
|
|
|
input [(C_DOUT_WIDTH*8)-1:0] def_data;
|
|
|
|
|
|
|
|
integer index,i,j;
|
|
|
|
reg [3:0] bin;
|
|
|
|
|
|
|
|
begin
|
|
|
|
index = 0;
|
|
|
|
hexstr_conv = 'b0;
|
|
|
|
for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 )
|
|
|
|
begin
|
|
|
|
case (def_data[7:0])
|
|
|
|
8'b00000000 :
|
|
|
|
begin
|
|
|
|
bin = 4'b0000;
|
|
|
|
i = -1;
|
|
|
|
end
|
|
|
|
8'b00110000 : bin = 4'b0000;
|
|
|
|
8'b00110001 : bin = 4'b0001;
|
|
|
|
8'b00110010 : bin = 4'b0010;
|
|
|
|
8'b00110011 : bin = 4'b0011;
|
|
|
|
8'b00110100 : bin = 4'b0100;
|
|
|
|
8'b00110101 : bin = 4'b0101;
|
|
|
|
8'b00110110 : bin = 4'b0110;
|
|
|
|
8'b00110111 : bin = 4'b0111;
|
|
|
|
8'b00111000 : bin = 4'b1000;
|
|
|
|
8'b00111001 : bin = 4'b1001;
|
|
|
|
8'b01000001 : bin = 4'b1010;
|
|
|
|
8'b01000010 : bin = 4'b1011;
|
|
|
|
8'b01000011 : bin = 4'b1100;
|
|
|
|
8'b01000100 : bin = 4'b1101;
|
|
|
|
8'b01000101 : bin = 4'b1110;
|
|
|
|
8'b01000110 : bin = 4'b1111;
|
|
|
|
8'b01100001 : bin = 4'b1010;
|
|
|
|
8'b01100010 : bin = 4'b1011;
|
|
|
|
8'b01100011 : bin = 4'b1100;
|
|
|
|
8'b01100100 : bin = 4'b1101;
|
|
|
|
8'b01100101 : bin = 4'b1110;
|
|
|
|
8'b01100110 : bin = 4'b1111;
|
|
|
|
default :
|
|
|
|
begin
|
|
|
|
bin = 4'bx;
|
|
|
|
end
|
|
|
|
endcase
|
|
|
|
for( j=0; j<4; j=j+1)
|
|
|
|
begin
|
|
|
|
if ((index*4)+j < C_DOUT_WIDTH)
|
|
|
|
begin
|
|
|
|
hexstr_conv[(index*4)+j] = bin[j];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
index = index + 1;
|
|
|
|
def_data = def_data >> 8;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Initialize Signals for clean power-on simulation
|
|
|
|
*************************************************************************/
|
|
|
|
initial begin
|
|
|
|
num_wr_bits = 0;
|
|
|
|
num_rd_bits = 0;
|
|
|
|
next_num_wr_bits = 0;
|
|
|
|
next_num_rd_bits = 0;
|
|
|
|
rd_ptr = C_RD_DEPTH - 1;
|
|
|
|
wr_ptr = C_WR_DEPTH - 1;
|
|
|
|
wr_pntr = 0;
|
|
|
|
rd_pntr = 0;
|
|
|
|
rd_ptr_wrclk = rd_ptr;
|
|
|
|
wr_ptr_rdclk = wr_ptr;
|
|
|
|
dout_reset_val = hexstr_conv(C_DOUT_RST_VAL);
|
|
|
|
ideal_dout = dout_reset_val;
|
|
|
|
err_type = 0;
|
|
|
|
ideal_dout_d1 = dout_reset_val;
|
|
|
|
ideal_wr_ack = 1'b0;
|
|
|
|
ideal_valid = 1'b0;
|
|
|
|
valid_d1 = 1'b0;
|
|
|
|
ideal_overflow = C_OVERFLOW_LOW;
|
|
|
|
ideal_underflow = C_UNDERFLOW_LOW;
|
|
|
|
ideal_wr_count = 0;
|
|
|
|
ideal_rd_count = 0;
|
|
|
|
ideal_prog_full = 1'b0;
|
|
|
|
ideal_prog_empty = 1'b1;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Connect the module inputs and outputs to the internal signals of the
|
|
|
|
* behavioral model.
|
|
|
|
*************************************************************************/
|
|
|
|
//Inputs
|
|
|
|
/*
|
|
|
|
wire [C_DIN_WIDTH-1:0] DIN;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE;
|
|
|
|
wire RD_CLK;
|
|
|
|
wire RD_EN;
|
|
|
|
wire RST;
|
|
|
|
wire WR_CLK;
|
|
|
|
wire WR_EN;
|
|
|
|
*/
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Dout may change behavior based on latency
|
|
|
|
//***************************************************************************
|
|
|
|
assign ideal_dout_out[C_DOUT_WIDTH-1:0] = (C_PRELOAD_LATENCY==2 &&
|
|
|
|
(C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))?
|
|
|
|
ideal_dout_d1: ideal_dout;
|
|
|
|
assign DOUT[C_DOUT_WIDTH-1:0] = ideal_dout_out;
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Assign SBITERR and DBITERR based on latency
|
|
|
|
//***************************************************************************
|
|
|
|
assign SBITERR = (C_ERROR_INJECTION_TYPE == 1 || C_ERROR_INJECTION_TYPE == 3) &&
|
|
|
|
(C_PRELOAD_LATENCY == 2 &&
|
|
|
|
(C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ?
|
|
|
|
err_type_d1[0]: err_type[0];
|
|
|
|
assign DBITERR = (C_ERROR_INJECTION_TYPE == 2 || C_ERROR_INJECTION_TYPE == 3) &&
|
|
|
|
(C_PRELOAD_LATENCY==2 && (C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ?
|
|
|
|
err_type_d1[1]: err_type[1];
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Overflow may be active-low
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_OVERFLOW==1) begin : blockOF1
|
|
|
|
assign OVERFLOW = ideal_overflow ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
assign PROG_EMPTY = ideal_prog_empty;
|
|
|
|
assign PROG_FULL = ideal_prog_full;
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Valid may change behavior based on latency or active-low
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_VALID==1) begin : blockVL1
|
|
|
|
assign valid_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & ~EMPTY) : ideal_valid;
|
|
|
|
assign valid_out = (C_PRELOAD_LATENCY==2 &&
|
|
|
|
(C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))?
|
|
|
|
valid_d1: valid_i;
|
|
|
|
assign VALID = valid_out ? !C_VALID_LOW : C_VALID_LOW;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Underflow may change behavior based on latency or active-low
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_UNDERFLOW==1) begin : blockUF1
|
|
|
|
assign underflow_i = (C_PRELOAD_LATENCY==0) ? (RD_EN & EMPTY) : ideal_underflow;
|
|
|
|
assign UNDERFLOW = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Write acknowledge may be active low
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_WR_ACK==1) begin : blockWK1
|
|
|
|
assign WR_ACK = ideal_wr_ack ? !C_WR_ACK_LOW : C_WR_ACK_LOW;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Generate RD_DATA_COUNT if Use Extra Logic option is selected
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_WR_DATA_COUNT == 1 && C_USE_FWFT_DATA_COUNT == 1) begin : wdc_fwft_ext
|
|
|
|
|
|
|
|
reg [C_PNTR_WIDTH-1:0] adjusted_wr_pntr = 0;
|
|
|
|
reg [C_PNTR_WIDTH-1:0] adjusted_rd_pntr = 0;
|
|
|
|
wire [C_PNTR_WIDTH-1:0] diff_wr_rd_tmp;
|
|
|
|
wire [C_PNTR_WIDTH:0] diff_wr_rd;
|
|
|
|
reg [C_PNTR_WIDTH:0] wr_data_count_i = 0;
|
|
|
|
always @* begin
|
|
|
|
if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin
|
|
|
|
adjusted_wr_pntr = wr_pntr;
|
|
|
|
adjusted_rd_pntr = 0;
|
|
|
|
adjusted_rd_pntr[C_PNTR_WIDTH-1:C_PNTR_WIDTH-C_RD_PNTR_WIDTH] = rd_pntr_wr;
|
|
|
|
end else if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin
|
|
|
|
adjusted_rd_pntr = rd_pntr_wr;
|
|
|
|
adjusted_wr_pntr = 0;
|
|
|
|
adjusted_wr_pntr[C_PNTR_WIDTH-1:C_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr;
|
|
|
|
end else begin
|
|
|
|
adjusted_wr_pntr = wr_pntr;
|
|
|
|
adjusted_rd_pntr = rd_pntr_wr;
|
|
|
|
end
|
|
|
|
end // always @*
|
|
|
|
|
|
|
|
assign diff_wr_rd_tmp = adjusted_wr_pntr - adjusted_rd_pntr;
|
|
|
|
assign diff_wr_rd = {1'b0,diff_wr_rd_tmp};
|
|
|
|
|
|
|
|
always @ (posedge wr_rst_i or posedge WR_CLK)
|
|
|
|
begin
|
|
|
|
if (wr_rst_i)
|
|
|
|
wr_data_count_i <= #`TCQ 0;
|
|
|
|
else
|
|
|
|
wr_data_count_i <= #`TCQ diff_wr_rd + EXTRA_WORDS_DC;
|
|
|
|
end // always @ (posedge WR_CLK or posedge WR_CLK)
|
|
|
|
|
|
|
|
always @* begin
|
|
|
|
if (C_WR_PNTR_WIDTH >= C_RD_PNTR_WIDTH)
|
|
|
|
wdc_fwft_ext_as = wr_data_count_i[C_PNTR_WIDTH:0];
|
|
|
|
else
|
|
|
|
wdc_fwft_ext_as = wr_data_count_i[C_PNTR_WIDTH:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH];
|
|
|
|
end // always @*
|
|
|
|
end // wdc_fwft_ext
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Generate RD_DATA_COUNT if Use Extra Logic option is selected
|
|
|
|
//***************************************************************************
|
|
|
|
reg [C_RD_PNTR_WIDTH:0] rdc_fwft_ext_as = 0;
|
|
|
|
|
|
|
|
generate
|
|
|
|
if (C_HAS_RD_DATA_COUNT == 1 && C_USE_FWFT_DATA_COUNT == 1) begin : rdc_fwft_ext
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] adjusted_wr_pntr_rd = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] diff_rd_wr_tmp;
|
|
|
|
wire [C_RD_PNTR_WIDTH:0] diff_rd_wr;
|
|
|
|
always @* begin
|
|
|
|
if (C_RD_PNTR_WIDTH > C_WR_PNTR_WIDTH) begin
|
|
|
|
adjusted_wr_pntr_rd = 0;
|
|
|
|
adjusted_wr_pntr_rd[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr_rd;
|
|
|
|
end else begin
|
|
|
|
adjusted_wr_pntr_rd = wr_pntr_rd[C_WR_PNTR_WIDTH-1:C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH];
|
|
|
|
end
|
|
|
|
end // always @*
|
|
|
|
|
|
|
|
assign diff_rd_wr_tmp = adjusted_wr_pntr_rd - rd_pntr;
|
|
|
|
assign diff_rd_wr = {1'b0,diff_rd_wr_tmp};
|
|
|
|
|
|
|
|
always @ (posedge rd_rst_i or posedge RD_CLK)
|
|
|
|
begin
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
rdc_fwft_ext_as <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
if (!stage2_valid)
|
|
|
|
rdc_fwft_ext_as <= #`TCQ 0;
|
|
|
|
else if (!stage1_valid && stage2_valid)
|
|
|
|
rdc_fwft_ext_as <= #`TCQ 1;
|
|
|
|
else
|
|
|
|
rdc_fwft_ext_as <= #`TCQ diff_rd_wr + 2'h2;
|
|
|
|
end
|
|
|
|
end // always @ (posedge WR_CLK or posedge WR_CLK)
|
|
|
|
end // rdc_fwft_ext
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Assign the read data count value only if it is selected,
|
|
|
|
// otherwise output zeros.
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_RD_DATA_COUNT == 1) begin : grdc
|
|
|
|
assign RD_DATA_COUNT[C_RD_DATA_COUNT_WIDTH-1:0] = C_USE_FWFT_DATA_COUNT ?
|
|
|
|
rdc_fwft_ext_as[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH+1-C_RD_DATA_COUNT_WIDTH] :
|
|
|
|
rd_data_count_int[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH+1-C_RD_DATA_COUNT_WIDTH];
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate
|
|
|
|
if (C_HAS_RD_DATA_COUNT == 0) begin : gnrdc
|
|
|
|
assign RD_DATA_COUNT[C_RD_DATA_COUNT_WIDTH-1:0] = {C_RD_DATA_COUNT_WIDTH{1'b0}};
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Assign the write data count value only if it is selected,
|
|
|
|
// otherwise output zeros
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_WR_DATA_COUNT == 1) begin : gwdc
|
|
|
|
assign WR_DATA_COUNT[C_WR_DATA_COUNT_WIDTH-1:0] = (C_USE_FWFT_DATA_COUNT == 1) ?
|
|
|
|
wdc_fwft_ext_as[C_WR_PNTR_WIDTH:C_WR_PNTR_WIDTH+1-C_WR_DATA_COUNT_WIDTH] :
|
|
|
|
wr_data_count_int[C_WR_PNTR_WIDTH:C_WR_PNTR_WIDTH+1-C_WR_DATA_COUNT_WIDTH];
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate
|
|
|
|
if (C_HAS_WR_DATA_COUNT == 0) begin : gnwdc
|
|
|
|
assign WR_DATA_COUNT[C_WR_DATA_COUNT_WIDTH-1:0] = {C_WR_DATA_COUNT_WIDTH{1'b0}};
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Assorted registers for delayed versions of signals
|
|
|
|
**************************************************************************/
|
|
|
|
//Capture delayed version of valid
|
|
|
|
generate
|
|
|
|
if (C_HAS_VALID==1) begin : blockVL2
|
|
|
|
always @(posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i == 1'b1) begin
|
|
|
|
valid_d1 <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
valid_d1 <= #`TCQ valid_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//Capture delayed version of dout
|
|
|
|
always @(posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i == 1'b1) begin
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0)
|
|
|
|
err_type_d1 <= #`TCQ 0;
|
|
|
|
end else if (ram_rd_en_d1) begin
|
|
|
|
ideal_dout_d1 <= #`TCQ ideal_dout;
|
|
|
|
err_type_d1 <= #`TCQ err_type;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Overflow and Underflow Flag calculation
|
|
|
|
* (handled separately because they don't support rst)
|
|
|
|
**************************************************************************/
|
|
|
|
generate
|
|
|
|
if (C_HAS_OVERFLOW == 1 && IS_8SERIES == 0) begin : g7s_ovflw
|
|
|
|
always @(posedge WR_CLK) begin
|
|
|
|
ideal_overflow <= #`TCQ WR_EN & FULL;
|
|
|
|
end
|
|
|
|
end else if (C_HAS_OVERFLOW == 1 && IS_8SERIES == 1) begin : g8s_ovflw
|
|
|
|
always @(posedge WR_CLK) begin
|
|
|
|
//ideal_overflow <= #`TCQ WR_EN & (FULL | wr_rst_i);
|
|
|
|
ideal_overflow <= #`TCQ WR_EN & (FULL );
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate
|
|
|
|
if (C_HAS_UNDERFLOW == 1 && IS_8SERIES == 0) begin : g7s_unflw
|
|
|
|
always @(posedge RD_CLK) begin
|
|
|
|
ideal_underflow <= #`TCQ EMPTY & RD_EN;
|
|
|
|
end
|
|
|
|
end else if (C_HAS_UNDERFLOW == 1 && IS_8SERIES == 1) begin : g8s_unflw
|
|
|
|
always @(posedge RD_CLK) begin
|
|
|
|
ideal_underflow <= #`TCQ (EMPTY) & RD_EN;
|
|
|
|
//ideal_underflow <= #`TCQ (rd_rst_i | EMPTY) & RD_EN;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Write/Read Pointer Synchronization
|
|
|
|
**************************************************************************/
|
|
|
|
localparam NO_OF_SYNC_STAGE_INC_G2B = C_SYNCHRONIZER_STAGE + 1;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] wr_pntr_sync_stgs [0:NO_OF_SYNC_STAGE_INC_G2B];
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] rd_pntr_sync_stgs [0:NO_OF_SYNC_STAGE_INC_G2B];
|
|
|
|
genvar gss;
|
|
|
|
|
|
|
|
generate for (gss = 1; gss <= NO_OF_SYNC_STAGE_INC_G2B; gss = gss + 1) begin : Sync_stage_inst
|
|
|
|
fifo_generator_v12_0_sync_stage
|
|
|
|
#(
|
|
|
|
.C_WIDTH (C_WR_PNTR_WIDTH)
|
|
|
|
)
|
|
|
|
rd_stg_inst
|
|
|
|
(
|
|
|
|
.RST (rd_rst_i),
|
|
|
|
.CLK (RD_CLK),
|
|
|
|
.DIN (wr_pntr_sync_stgs[gss-1]),
|
|
|
|
.DOUT (wr_pntr_sync_stgs[gss])
|
|
|
|
);
|
|
|
|
|
|
|
|
fifo_generator_v12_0_sync_stage
|
|
|
|
#(
|
|
|
|
.C_WIDTH (C_RD_PNTR_WIDTH)
|
|
|
|
)
|
|
|
|
wr_stg_inst
|
|
|
|
(
|
|
|
|
.RST (wr_rst_i),
|
|
|
|
.CLK (WR_CLK),
|
|
|
|
.DIN (rd_pntr_sync_stgs[gss-1]),
|
|
|
|
.DOUT (rd_pntr_sync_stgs[gss])
|
|
|
|
);
|
|
|
|
end endgenerate // Sync_stage_inst
|
|
|
|
|
|
|
|
assign wr_pntr_sync_stgs[0] = wr_pntr_rd1;
|
|
|
|
assign rd_pntr_sync_stgs[0] = rd_pntr_wr1;
|
|
|
|
always@* begin
|
|
|
|
wr_pntr_rd <= wr_pntr_sync_stgs[NO_OF_SYNC_STAGE_INC_G2B];
|
|
|
|
rd_pntr_wr <= rd_pntr_sync_stgs[NO_OF_SYNC_STAGE_INC_G2B];
|
|
|
|
end
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Write Domain Logic
|
|
|
|
**************************************************************************/
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] diff_pntr = 0;
|
|
|
|
always @(posedge WR_CLK or posedge wr_rst_i) begin : gen_fifo_w
|
|
|
|
|
|
|
|
/****** Reset fifo (case 1)***************************************/
|
|
|
|
if (wr_rst_i == 1'b1) begin
|
|
|
|
num_wr_bits <= #`TCQ 0;
|
|
|
|
next_num_wr_bits = #`TCQ 0;
|
|
|
|
wr_ptr <= #`TCQ C_WR_DEPTH - 1;
|
|
|
|
rd_ptr_wrclk <= #`TCQ C_RD_DEPTH - 1;
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
ideal_wr_count <= #`TCQ 0;
|
|
|
|
tmp_wr_listsize = #`TCQ 0;
|
|
|
|
rd_ptr_wrclk_next <= #`TCQ 0;
|
|
|
|
wr_pntr <= #`TCQ 0;
|
|
|
|
wr_pntr_rd1 <= #`TCQ 0;
|
|
|
|
|
|
|
|
end else begin //wr_rst_i==0
|
|
|
|
wr_pntr_rd1 <= #`TCQ wr_pntr;
|
|
|
|
|
|
|
|
//Determine the current number of words in the FIFO
|
|
|
|
tmp_wr_listsize = (C_DEPTH_RATIO_RD > 1) ? num_wr_bits/C_DOUT_WIDTH :
|
|
|
|
num_wr_bits/C_DIN_WIDTH;
|
|
|
|
rd_ptr_wrclk_next = rd_ptr;
|
|
|
|
if (rd_ptr_wrclk < rd_ptr_wrclk_next) begin
|
|
|
|
next_num_wr_bits = num_wr_bits -
|
|
|
|
C_DOUT_WIDTH*(rd_ptr_wrclk + C_RD_DEPTH
|
|
|
|
- rd_ptr_wrclk_next);
|
|
|
|
end else begin
|
|
|
|
next_num_wr_bits = num_wr_bits -
|
|
|
|
C_DOUT_WIDTH*(rd_ptr_wrclk - rd_ptr_wrclk_next);
|
|
|
|
end
|
|
|
|
|
|
|
|
//If this is a write, handle the write by adding the value
|
|
|
|
// to the linked list, and updating all outputs appropriately
|
|
|
|
if (WR_EN == 1'b1) begin
|
|
|
|
if (FULL == 1'b1) begin
|
|
|
|
|
|
|
|
//If the FIFO is full, do NOT perform the write,
|
|
|
|
// update flags accordingly
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD
|
|
|
|
>= C_FIFO_WR_DEPTH) begin
|
|
|
|
//write unsuccessful - do not change contents
|
|
|
|
|
|
|
|
//Do not acknowledge the write
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
//Reminder that FIFO is still full
|
|
|
|
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is one from full, but reporting full
|
|
|
|
end else
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD ==
|
|
|
|
C_FIFO_WR_DEPTH-1) begin
|
|
|
|
//No change to FIFO
|
|
|
|
|
|
|
|
//Write not successful
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
//With DEPTH-1 words in the FIFO, it is almost_full
|
|
|
|
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
|
|
|
|
|
|
|
|
//If the FIFO is completely empty, but it is
|
|
|
|
// reporting FULL for some reason (like reset)
|
|
|
|
end else
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD <=
|
|
|
|
C_FIFO_WR_DEPTH-2) begin
|
|
|
|
//No change to FIFO
|
|
|
|
|
|
|
|
//Write not successful
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
//FIFO is really not close to full, so change flag status.
|
|
|
|
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
end //(tmp_wr_listsize == 0)
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
//If the FIFO is full, do NOT perform the write,
|
|
|
|
// update flags accordingly
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD >=
|
|
|
|
C_FIFO_WR_DEPTH) begin
|
|
|
|
//write unsuccessful - do not change contents
|
|
|
|
|
|
|
|
//Do not acknowledge the write
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
//Reminder that FIFO is still full
|
|
|
|
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is one from full
|
|
|
|
end else
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD ==
|
|
|
|
C_FIFO_WR_DEPTH-1) begin
|
2015-11-13 16:25:38 -05:00
|
|
|
|
2015-11-12 09:57:55 -05:00
|
|
|
//Add value on DIN port to FIFO
|
|
|
|
write_fifo;
|
|
|
|
next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH;
|
|
|
|
|
|
|
|
//Write successful, so issue acknowledge
|
|
|
|
// and no error
|
|
|
|
ideal_wr_ack <= #`TCQ 1;
|
|
|
|
//This write is CAUSING the FIFO to go full
|
|
|
|
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is 2 from full
|
|
|
|
end else
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD ==
|
|
|
|
C_FIFO_WR_DEPTH-2) begin
|
|
|
|
//Add value on DIN port to FIFO
|
2015-11-13 16:25:38 -05:00
|
|
|
$display("two from full");
|
2015-11-12 09:57:55 -05:00
|
|
|
write_fifo;
|
|
|
|
next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH;
|
|
|
|
//Write successful, so issue acknowledge
|
|
|
|
// and no error
|
|
|
|
ideal_wr_ack <= #`TCQ 1;
|
|
|
|
//Still 2 from full
|
|
|
|
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is not close to being full
|
|
|
|
end else
|
|
|
|
if ((tmp_wr_listsize + C_DEPTH_RATIO_RD - 1)/C_DEPTH_RATIO_RD <
|
|
|
|
C_FIFO_WR_DEPTH-2) begin
|
|
|
|
//Add value on DIN port to FIFO
|
|
|
|
write_fifo;
|
|
|
|
next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH;
|
|
|
|
//Write successful, so issue acknowledge
|
|
|
|
// and no error
|
|
|
|
ideal_wr_ack <= #`TCQ 1;
|
|
|
|
//Not even close to full.
|
|
|
|
|
|
|
|
ideal_wr_count <= num_write_words_sized_i;
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end else begin //(WR_EN == 1'b1)
|
|
|
|
|
|
|
|
//If user did not attempt a write, then do not
|
|
|
|
// give ack or err
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
end
|
|
|
|
num_wr_bits <= #`TCQ next_num_wr_bits;
|
|
|
|
rd_ptr_wrclk <= #`TCQ rd_ptr;
|
|
|
|
|
|
|
|
end //wr_rst_i==0
|
|
|
|
end // gen_fifo_w
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Programmable FULL flags
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] pf_thr_assert_val;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] pf_thr_negate_val;
|
|
|
|
|
|
|
|
generate if (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) begin : FWFT
|
|
|
|
assign pf_thr_assert_val = C_PROG_FULL_THRESH_ASSERT_VAL - EXTRA_WORDS_DC;
|
|
|
|
assign pf_thr_negate_val = C_PROG_FULL_THRESH_NEGATE_VAL - EXTRA_WORDS_DC;
|
|
|
|
end else begin // STD
|
|
|
|
assign pf_thr_assert_val = C_PROG_FULL_THRESH_ASSERT_VAL;
|
|
|
|
assign pf_thr_negate_val = C_PROG_FULL_THRESH_NEGATE_VAL;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
always @(posedge WR_CLK or posedge wr_rst_i) begin
|
|
|
|
|
|
|
|
if (wr_rst_i == 1'b1) begin
|
|
|
|
diff_pntr <= 0;
|
|
|
|
end else begin
|
|
|
|
if (ram_wr_en)
|
|
|
|
diff_pntr <= #`TCQ (wr_pntr - adj_rd_pntr_wr + 2'h1);
|
|
|
|
else if (!ram_wr_en)
|
|
|
|
diff_pntr <= #`TCQ (wr_pntr - adj_rd_pntr_wr);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
always @(posedge WR_CLK or posedge RST_FULL_FF) begin : gen_pf
|
|
|
|
|
|
|
|
if (RST_FULL_FF == 1'b1) begin
|
|
|
|
ideal_prog_full <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
//Single Programmable Full Constant Threshold
|
|
|
|
else if (C_PROG_FULL_TYPE == 1) begin
|
|
|
|
if (FULL == 0) begin
|
|
|
|
if (diff_pntr >= pf_thr_assert_val)
|
|
|
|
ideal_prog_full <= #`TCQ 1;
|
|
|
|
else
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
end else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
//Two Programmable Full Constant Thresholds
|
|
|
|
end else if (C_PROG_FULL_TYPE == 2) begin
|
|
|
|
if (FULL == 0) begin
|
|
|
|
if (diff_pntr >= pf_thr_assert_val)
|
|
|
|
ideal_prog_full <= #`TCQ 1;
|
|
|
|
else if (diff_pntr < pf_thr_negate_val)
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
end else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
//Single Programmable Full Threshold Input
|
|
|
|
end else if (C_PROG_FULL_TYPE == 3) begin
|
|
|
|
if (FULL == 0) begin
|
|
|
|
if (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) begin // FWFT
|
|
|
|
if (diff_pntr >= (PROG_FULL_THRESH - EXTRA_WORDS_DC))
|
|
|
|
ideal_prog_full <= #`TCQ 1;
|
|
|
|
else
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
end else begin // STD
|
|
|
|
if (diff_pntr >= PROG_FULL_THRESH)
|
|
|
|
ideal_prog_full <= #`TCQ 1;
|
|
|
|
else
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
end
|
|
|
|
end else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
//Two Programmable Full Threshold Inputs
|
|
|
|
end else if (C_PROG_FULL_TYPE == 4) begin
|
|
|
|
if (FULL == 0) begin
|
|
|
|
if (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) begin // FWFT
|
|
|
|
if (diff_pntr >= (PROG_FULL_THRESH_ASSERT - EXTRA_WORDS_DC))
|
|
|
|
ideal_prog_full <= #`TCQ 1;
|
|
|
|
else if (diff_pntr < (PROG_FULL_THRESH_NEGATE - EXTRA_WORDS_DC))
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
end else begin // STD
|
|
|
|
if (diff_pntr >= PROG_FULL_THRESH_ASSERT)
|
|
|
|
ideal_prog_full <= #`TCQ 1;
|
|
|
|
else if (diff_pntr < PROG_FULL_THRESH_NEGATE)
|
|
|
|
ideal_prog_full <= #`TCQ 0;
|
|
|
|
else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
end
|
|
|
|
end else
|
|
|
|
ideal_prog_full <= #`TCQ ideal_prog_full;
|
|
|
|
end // C_PROG_FULL_TYPE
|
|
|
|
|
|
|
|
end //wr_rst_i==0
|
|
|
|
end //
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Read Domain Logic
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************
|
|
|
|
* Programmable EMPTY flags
|
|
|
|
*********************************************************/
|
|
|
|
//Determine the Assert and Negate thresholds for Programmable Empty
|
|
|
|
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] pe_thr_assert_val;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] pe_thr_negate_val;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] diff_pntr_rd = 0;
|
|
|
|
|
|
|
|
always @(posedge RD_CLK or posedge rd_rst_i) begin : gen_pe
|
|
|
|
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
diff_pntr_rd <= #`TCQ 0;
|
|
|
|
ideal_prog_empty <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if (ram_rd_en)
|
|
|
|
diff_pntr_rd <= #`TCQ (adj_wr_pntr_rd - rd_pntr) - 1'h1;
|
|
|
|
else if (!ram_rd_en)
|
|
|
|
diff_pntr_rd <= #`TCQ (adj_wr_pntr_rd - rd_pntr);
|
|
|
|
else
|
|
|
|
diff_pntr_rd <= #`TCQ diff_pntr_rd;
|
|
|
|
|
|
|
|
if (C_PROG_EMPTY_TYPE == 1) begin
|
|
|
|
if (EMPTY == 0) begin
|
|
|
|
if (diff_pntr_rd <= pe_thr_assert_val)
|
|
|
|
ideal_prog_empty <= #`TCQ 1;
|
|
|
|
else
|
|
|
|
ideal_prog_empty <= #`TCQ 0;
|
|
|
|
end else
|
|
|
|
ideal_prog_empty <= #`TCQ ideal_prog_empty;
|
|
|
|
end else if (C_PROG_EMPTY_TYPE == 2) begin
|
|
|
|
if (EMPTY == 0) begin
|
|
|
|
if (diff_pntr_rd <= pe_thr_assert_val)
|
|
|
|
ideal_prog_empty <= #`TCQ 1;
|
|
|
|
else if (diff_pntr_rd > pe_thr_negate_val)
|
|
|
|
ideal_prog_empty <= #`TCQ 0;
|
|
|
|
else
|
|
|
|
ideal_prog_empty <= #`TCQ ideal_prog_empty;
|
|
|
|
end else
|
|
|
|
ideal_prog_empty <= #`TCQ ideal_prog_empty;
|
|
|
|
end else if (C_PROG_EMPTY_TYPE == 3) begin
|
|
|
|
if (EMPTY == 0) begin
|
|
|
|
if (diff_pntr_rd <= pe_thr_assert_val)
|
|
|
|
ideal_prog_empty <= #`TCQ 1;
|
|
|
|
else
|
|
|
|
ideal_prog_empty <= #`TCQ 0;
|
|
|
|
end else
|
|
|
|
ideal_prog_empty <= #`TCQ ideal_prog_empty;
|
|
|
|
end else if (C_PROG_EMPTY_TYPE == 4) begin
|
|
|
|
if (EMPTY == 0) begin
|
|
|
|
if (diff_pntr_rd <= pe_thr_assert_val)
|
|
|
|
ideal_prog_empty <= #`TCQ 1;
|
|
|
|
else if (diff_pntr_rd > pe_thr_negate_val)
|
|
|
|
ideal_prog_empty <= #`TCQ 0;
|
|
|
|
else
|
|
|
|
ideal_prog_empty <= #`TCQ ideal_prog_empty;
|
|
|
|
end else
|
|
|
|
ideal_prog_empty <= #`TCQ ideal_prog_empty;
|
|
|
|
end //C_PROG_EMPTY_TYPE
|
|
|
|
end
|
|
|
|
end // gen_pe
|
|
|
|
|
|
|
|
generate if (C_PROG_EMPTY_TYPE == 3) begin : single_pe_thr_input
|
|
|
|
assign pe_thr_assert_val = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ?
|
|
|
|
PROG_EMPTY_THRESH - 2'h2 : PROG_EMPTY_THRESH;
|
|
|
|
end endgenerate // single_pe_thr_input
|
|
|
|
|
|
|
|
generate if (C_PROG_EMPTY_TYPE == 4) begin : multiple_pe_thr_input
|
|
|
|
assign pe_thr_assert_val = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ?
|
|
|
|
PROG_EMPTY_THRESH_ASSERT - 2'h2 : PROG_EMPTY_THRESH_ASSERT;
|
|
|
|
assign pe_thr_negate_val = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ?
|
|
|
|
PROG_EMPTY_THRESH_NEGATE - 2'h2 : PROG_EMPTY_THRESH_NEGATE;
|
|
|
|
end endgenerate // multiple_pe_thr_input
|
|
|
|
|
|
|
|
generate if (C_PROG_EMPTY_TYPE < 3) begin : single_multiple_pe_thr_const
|
|
|
|
assign pe_thr_assert_val = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ?
|
|
|
|
C_PROG_EMPTY_THRESH_ASSERT_VAL - 2'h2 : C_PROG_EMPTY_THRESH_ASSERT_VAL;
|
|
|
|
assign pe_thr_negate_val = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ?
|
|
|
|
C_PROG_EMPTY_THRESH_NEGATE_VAL - 2'h2 : C_PROG_EMPTY_THRESH_NEGATE_VAL;
|
|
|
|
end endgenerate // single_multiple_pe_thr_const
|
|
|
|
|
|
|
|
// block memory has a synchronous reset
|
|
|
|
always @(posedge RD_CLK) begin : gen_fifo_blkmemdout
|
|
|
|
// make it consistent with the core.
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0 && C_MEMORY_TYPE < 2)
|
|
|
|
err_type <= #`TCQ 0;
|
|
|
|
|
|
|
|
// BRAM resets synchronously
|
|
|
|
if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE < 2) begin
|
|
|
|
ideal_dout <= #`TCQ dout_reset_val;
|
|
|
|
ideal_dout_d1 <= #`TCQ dout_reset_val;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
|
|
|
|
always @(posedge RD_CLK or posedge rd_rst_i) begin : gen_fifo_r
|
|
|
|
|
|
|
|
/****** Reset fifo (case 1)***************************************/
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
num_rd_bits <= #`TCQ 0;
|
|
|
|
next_num_rd_bits = #`TCQ 0;
|
|
|
|
rd_ptr <= #`TCQ C_RD_DEPTH -1;
|
|
|
|
rd_pntr <= #`TCQ 0;
|
|
|
|
rd_pntr_wr1 <= #`TCQ 0;
|
|
|
|
wr_ptr_rdclk <= #`TCQ C_WR_DEPTH -1;
|
|
|
|
|
|
|
|
// DRAM resets asynchronously
|
|
|
|
if (C_MEMORY_TYPE == 2 && C_USE_DOUT_RST == 1)
|
|
|
|
ideal_dout <= #`TCQ dout_reset_val;
|
|
|
|
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0)
|
|
|
|
err_type <= #`TCQ 0;
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
ideal_rd_count <= #`TCQ 0;
|
|
|
|
|
|
|
|
end else begin //rd_rst_i==0
|
|
|
|
|
|
|
|
rd_pntr_wr1 <= #`TCQ rd_pntr;
|
|
|
|
|
|
|
|
//Determine the current number of words in the FIFO
|
|
|
|
tmp_rd_listsize = (C_DEPTH_RATIO_WR > 1) ? num_rd_bits/C_DIN_WIDTH :
|
|
|
|
num_rd_bits/C_DOUT_WIDTH;
|
|
|
|
wr_ptr_rdclk_next = wr_ptr;
|
|
|
|
|
|
|
|
if (wr_ptr_rdclk < wr_ptr_rdclk_next) begin
|
|
|
|
next_num_rd_bits = num_rd_bits +
|
|
|
|
C_DIN_WIDTH*(wr_ptr_rdclk +C_WR_DEPTH
|
|
|
|
- wr_ptr_rdclk_next);
|
|
|
|
end else begin
|
|
|
|
next_num_rd_bits = num_rd_bits +
|
|
|
|
C_DIN_WIDTH*(wr_ptr_rdclk - wr_ptr_rdclk_next);
|
|
|
|
end
|
|
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
// Read Operation - Read Latency 1
|
|
|
|
/*****************************************************************/
|
|
|
|
if (C_PRELOAD_LATENCY==1 || C_PRELOAD_LATENCY==2) begin
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
|
|
|
|
if (ram_rd_en == 1'b1) begin
|
|
|
|
|
|
|
|
if (EMPTY == 1'b1) begin
|
|
|
|
|
|
|
|
//If the FIFO is completely empty, and is reporting empty
|
|
|
|
if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0)
|
|
|
|
begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Reminder that FIFO is still empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
end // if (tmp_rd_listsize <= 0)
|
|
|
|
|
|
|
|
//If the FIFO is one from empty, but it is reporting empty
|
|
|
|
else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1)
|
|
|
|
begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Note that FIFO is no longer empty, but is almost empty (has one word left)
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize == 1)
|
|
|
|
|
|
|
|
//If the FIFO is two from empty, and is reporting empty
|
|
|
|
else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2)
|
|
|
|
begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Fifo has two words, so is neither empty or almost empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize == 2)
|
|
|
|
|
|
|
|
//If the FIFO is not close to empty, but is reporting that it is
|
|
|
|
// Treat the FIFO as empty this time, but unset EMPTY flags.
|
|
|
|
if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && (tmp_rd_listsize/C_DEPTH_RATIO_WR<C_FIFO_RD_DEPTH))
|
|
|
|
begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Note that the FIFO is No Longer Empty or Almost Empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1))
|
|
|
|
end // else: if(ideal_empty == 1'b1)
|
|
|
|
|
|
|
|
else //if (ideal_empty == 1'b0)
|
|
|
|
begin
|
|
|
|
|
|
|
|
//If the FIFO is completely full, and we are successfully reading from it
|
|
|
|
if (tmp_rd_listsize/C_DEPTH_RATIO_WR >= C_FIFO_RD_DEPTH)
|
|
|
|
begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Not close to empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize == C_FIFO_RD_DEPTH)
|
|
|
|
|
|
|
|
//If the FIFO is not close to being empty
|
|
|
|
else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) && (tmp_rd_listsize/C_DEPTH_RATIO_WR<=C_FIFO_RD_DEPTH))
|
|
|
|
begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Not close to empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1))
|
|
|
|
|
|
|
|
//If the FIFO is two from empty
|
|
|
|
else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2)
|
|
|
|
begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Fifo is not yet empty. It is going almost_empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize == 2)
|
|
|
|
|
|
|
|
//If the FIFO is one from empty
|
|
|
|
else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR == 1))
|
|
|
|
begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Note that FIFO is GOING empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize == 1)
|
|
|
|
|
|
|
|
|
|
|
|
//If the FIFO is completely empty
|
|
|
|
else if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0)
|
|
|
|
begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize <= 0)
|
|
|
|
|
|
|
|
end // if (ideal_empty == 1'b0)
|
|
|
|
|
|
|
|
end //(RD_EN == 1'b1)
|
|
|
|
|
|
|
|
else //if (RD_EN == 1'b0)
|
|
|
|
begin
|
|
|
|
//If user did not attempt a read, do not give an ack or err
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // else: !if(RD_EN == 1'b1)
|
|
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
// Read Operation - Read Latency 0
|
|
|
|
/*****************************************************************/
|
|
|
|
end else if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0) begin
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
if (ram_rd_en == 1'b1) begin
|
|
|
|
|
|
|
|
if (EMPTY == 1'b1) begin
|
|
|
|
|
|
|
|
//If the FIFO is completely empty, and is reporting empty
|
|
|
|
if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Reminder that FIFO is still empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is one from empty, but it is reporting empty
|
|
|
|
end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Note that FIFO is no longer empty, but is almost empty (has one word left)
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is two from empty, and is reporting empty
|
|
|
|
end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Fifo has two words, so is neither empty or almost empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is not close to empty, but is reporting that it is
|
|
|
|
// Treat the FIFO as empty this time, but unset EMPTY flags.
|
|
|
|
end else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) &&
|
|
|
|
(tmp_rd_listsize/C_DEPTH_RATIO_WR<C_FIFO_RD_DEPTH)) begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Note that the FIFO is No Longer Empty or Almost Empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if ((tmp_rd_listsize > 2) && (tmp_rd_listsize<=C_FIFO_RD_DEPTH-1))
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
//If the FIFO is completely full, and we are successfully reading from it
|
|
|
|
if (tmp_rd_listsize/C_DEPTH_RATIO_WR >= C_FIFO_RD_DEPTH) begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Not close to empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is not close to being empty
|
|
|
|
end else if ((tmp_rd_listsize/C_DEPTH_RATIO_WR > 2) &&
|
|
|
|
(tmp_rd_listsize/C_DEPTH_RATIO_WR<=C_FIFO_RD_DEPTH)) begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Not close to empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is two from empty
|
|
|
|
end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 2) begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Fifo is not yet empty. It is going almost_empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is one from empty
|
|
|
|
end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR == 1) begin
|
|
|
|
//Read the value from the FIFO
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
//Note that FIFO is GOING empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
//If the FIFO is completely empty
|
|
|
|
end else if (tmp_rd_listsize/C_DEPTH_RATIO_WR <= 0) begin
|
|
|
|
//Do not change the contents of the FIFO
|
|
|
|
|
|
|
|
//Do not acknowledge the read from empty FIFO
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
//Reminder that FIFO is still empty
|
|
|
|
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize <= 0)
|
|
|
|
|
|
|
|
end // if (ideal_empty == 1'b0)
|
|
|
|
|
|
|
|
end else begin//(RD_EN == 1'b0)
|
|
|
|
|
|
|
|
|
|
|
|
//If user did not attempt a read, do not give an ack or err
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // else: !if(RD_EN == 1'b1)
|
|
|
|
end //if (C_PRELOAD_REGS==1 && C_PRELOAD_LATENCY==0)
|
|
|
|
|
|
|
|
num_rd_bits <= #`TCQ next_num_rd_bits;
|
|
|
|
wr_ptr_rdclk <= #`TCQ wr_ptr;
|
|
|
|
end //rd_rst_i==0
|
|
|
|
end //always
|
|
|
|
|
|
|
|
endmodule // fifo_generator_v12_0_bhv_ver_as
|
|
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Declaration of Low Latency Asynchronous FIFO
|
|
|
|
******************************************************************************/
|
|
|
|
module fifo_generator_v12_0_beh_ver_ll_afifo
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Declare user parameters and their defaults
|
|
|
|
***************************************************************************/
|
|
|
|
#(
|
|
|
|
parameter C_DIN_WIDTH = 8,
|
|
|
|
parameter C_DOUT_RST_VAL = "",
|
|
|
|
parameter C_DOUT_WIDTH = 8,
|
|
|
|
parameter C_FULL_FLAGS_RST_VAL = 1,
|
|
|
|
parameter C_HAS_RD_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_WR_DATA_COUNT = 0,
|
|
|
|
parameter C_RD_DEPTH = 256,
|
|
|
|
parameter C_RD_PNTR_WIDTH = 8,
|
|
|
|
parameter C_USE_DOUT_RST = 0,
|
|
|
|
parameter C_WR_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_WR_DEPTH = 256,
|
|
|
|
parameter C_WR_PNTR_WIDTH = 8,
|
|
|
|
parameter C_FIFO_TYPE = 0
|
|
|
|
)
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Declare Input and Output Ports
|
|
|
|
***************************************************************************/
|
|
|
|
(
|
|
|
|
input [C_DIN_WIDTH-1:0] DIN,
|
|
|
|
input RD_CLK,
|
|
|
|
input RD_EN,
|
|
|
|
input WR_RST,
|
|
|
|
input RD_RST,
|
|
|
|
input WR_CLK,
|
|
|
|
input WR_EN,
|
|
|
|
output reg [C_DOUT_WIDTH-1:0] DOUT = 0,
|
|
|
|
output reg EMPTY = 1'b1,
|
|
|
|
output reg FULL = C_FULL_FLAGS_RST_VAL
|
|
|
|
);
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Low Latency Asynchronous FIFO
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Memory which will be used to simulate a FIFO
|
|
|
|
reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0];
|
|
|
|
integer i;
|
|
|
|
initial begin
|
|
|
|
for (i = 0; i < C_WR_DEPTH; i = i + 1)
|
|
|
|
memory[i] = 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_ll_afifo = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] rd_pntr_ll_afifo;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_ll_afifo_q = 0;
|
|
|
|
reg ll_afifo_full = 1'b0;
|
|
|
|
reg ll_afifo_empty = 1'b1;
|
|
|
|
wire write_allow;
|
|
|
|
wire read_allow;
|
|
|
|
|
|
|
|
assign write_allow = WR_EN & ~ll_afifo_full;
|
|
|
|
assign read_allow = RD_EN & ~ll_afifo_empty;
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Write Pointer Generation
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge WR_CLK or posedge WR_RST) begin
|
|
|
|
if (WR_RST)
|
|
|
|
wr_pntr_ll_afifo <= 0;
|
|
|
|
else if (write_allow)
|
|
|
|
wr_pntr_ll_afifo <= #`TCQ wr_pntr_ll_afifo + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Read Pointer Generation
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge RD_CLK or posedge RD_RST) begin
|
|
|
|
if (RD_RST)
|
|
|
|
rd_pntr_ll_afifo_q <= 0;
|
|
|
|
else
|
|
|
|
rd_pntr_ll_afifo_q <= #`TCQ rd_pntr_ll_afifo;
|
|
|
|
end
|
|
|
|
assign rd_pntr_ll_afifo = read_allow ? rd_pntr_ll_afifo_q + 1 : rd_pntr_ll_afifo_q;
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Fill the Memory
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge WR_CLK) begin
|
|
|
|
if (write_allow)
|
|
|
|
memory[wr_pntr_ll_afifo] <= #`TCQ DIN;
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate DOUT
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge RD_CLK) begin
|
|
|
|
DOUT <= #`TCQ memory[rd_pntr_ll_afifo];
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate EMPTY
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge RD_CLK or posedge RD_RST) begin
|
|
|
|
if (RD_RST)
|
|
|
|
ll_afifo_empty <= 1'b1;
|
|
|
|
else
|
|
|
|
ll_afifo_empty <= ((wr_pntr_ll_afifo == rd_pntr_ll_afifo_q) |
|
|
|
|
(read_allow & (wr_pntr_ll_afifo == (rd_pntr_ll_afifo_q + 2'h1))));
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate FULL
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge WR_CLK or posedge WR_RST) begin
|
|
|
|
if (WR_RST)
|
|
|
|
ll_afifo_full <= 1'b1;
|
|
|
|
else
|
|
|
|
ll_afifo_full <= ((rd_pntr_ll_afifo_q == (wr_pntr_ll_afifo + 2'h1)) |
|
|
|
|
(write_allow & (rd_pntr_ll_afifo_q == (wr_pntr_ll_afifo + 2'h2))));
|
|
|
|
end
|
|
|
|
|
|
|
|
always @* begin
|
|
|
|
FULL <= ll_afifo_full;
|
|
|
|
EMPTY <= ll_afifo_empty;
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule // fifo_generator_v12_0_beh_ver_ll_afifo
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* Declaration of top-level module
|
|
|
|
******************************************************************************/
|
|
|
|
module fifo_generator_v12_0_bhv_ver_ss
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Declare user parameters and their defaults
|
|
|
|
*************************************************************************/
|
|
|
|
#(
|
|
|
|
parameter C_FAMILY = "virtex7",
|
|
|
|
parameter C_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_DIN_WIDTH = 8,
|
|
|
|
parameter C_DOUT_RST_VAL = "",
|
|
|
|
parameter C_DOUT_WIDTH = 8,
|
|
|
|
parameter C_FULL_FLAGS_RST_VAL = 1,
|
|
|
|
parameter C_HAS_ALMOST_EMPTY = 0,
|
|
|
|
parameter C_HAS_ALMOST_FULL = 0,
|
|
|
|
parameter C_HAS_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_OVERFLOW = 0,
|
|
|
|
parameter C_HAS_RD_DATA_COUNT = 0,
|
|
|
|
parameter C_HAS_RST = 0,
|
|
|
|
parameter C_HAS_SRST = 0,
|
|
|
|
parameter C_HAS_UNDERFLOW = 0,
|
|
|
|
parameter C_HAS_VALID = 0,
|
|
|
|
parameter C_HAS_WR_ACK = 0,
|
|
|
|
parameter C_HAS_WR_DATA_COUNT = 0,
|
|
|
|
parameter C_IMPLEMENTATION_TYPE = 0,
|
|
|
|
parameter C_MEMORY_TYPE = 1,
|
|
|
|
parameter C_OVERFLOW_LOW = 0,
|
|
|
|
parameter C_PRELOAD_LATENCY = 1,
|
|
|
|
parameter C_PRELOAD_REGS = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_EMPTY_TYPE = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_ASSERT_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_THRESH_NEGATE_VAL = 0,
|
|
|
|
parameter C_PROG_FULL_TYPE = 0,
|
|
|
|
parameter C_RD_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_RD_DEPTH = 256,
|
|
|
|
parameter C_RD_PNTR_WIDTH = 8,
|
|
|
|
parameter C_UNDERFLOW_LOW = 0,
|
|
|
|
parameter C_USE_DOUT_RST = 0,
|
|
|
|
parameter C_USE_EMBEDDED_REG = 0,
|
|
|
|
parameter C_USE_FWFT_DATA_COUNT = 0,
|
|
|
|
parameter C_VALID_LOW = 0,
|
|
|
|
parameter C_WR_ACK_LOW = 0,
|
|
|
|
parameter C_WR_DATA_COUNT_WIDTH = 2,
|
|
|
|
parameter C_WR_DEPTH = 256,
|
|
|
|
parameter C_WR_PNTR_WIDTH = 8,
|
|
|
|
parameter C_USE_ECC = 0,
|
|
|
|
parameter C_ENABLE_RST_SYNC = 1,
|
|
|
|
parameter C_ERROR_INJECTION_TYPE = 0,
|
|
|
|
parameter C_FIFO_TYPE = 0
|
|
|
|
)
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Declare Input and Output Ports
|
|
|
|
*************************************************************************/
|
|
|
|
(
|
|
|
|
//Inputs
|
|
|
|
input CLK,
|
|
|
|
input [C_DIN_WIDTH-1:0] DIN,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT,
|
|
|
|
input [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT,
|
|
|
|
input [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE,
|
|
|
|
input RD_EN,
|
|
|
|
input RD_EN_USER,
|
|
|
|
input USER_EMPTY_FB,
|
|
|
|
input RST,
|
|
|
|
input RST_FULL_GEN,
|
|
|
|
input RST_FULL_FF,
|
|
|
|
input SRST,
|
|
|
|
input WR_EN,
|
|
|
|
input INJECTDBITERR,
|
|
|
|
input INJECTSBITERR,
|
|
|
|
input WR_RST_BUSY,
|
|
|
|
input RD_RST_BUSY,
|
|
|
|
|
|
|
|
//Outputs
|
|
|
|
output ALMOST_EMPTY,
|
|
|
|
output ALMOST_FULL,
|
|
|
|
output reg [C_DATA_COUNT_WIDTH-1:0] DATA_COUNT = 0,
|
|
|
|
output [C_DOUT_WIDTH-1:0] DOUT,
|
|
|
|
output EMPTY,
|
|
|
|
output FULL,
|
|
|
|
output OVERFLOW,
|
|
|
|
output [C_RD_DATA_COUNT_WIDTH-1:0] RD_DATA_COUNT,
|
|
|
|
output [C_WR_DATA_COUNT_WIDTH-1:0] WR_DATA_COUNT,
|
|
|
|
output PROG_EMPTY,
|
|
|
|
output PROG_FULL,
|
|
|
|
output VALID,
|
|
|
|
output UNDERFLOW,
|
|
|
|
output WR_ACK,
|
|
|
|
output SBITERR,
|
|
|
|
output DBITERR
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
reg [C_RD_PNTR_WIDTH:0] rd_data_count_int = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH:0] wr_data_count_int = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH:0] rd_data_count_i_ss;
|
|
|
|
wire [C_WR_PNTR_WIDTH:0] wr_data_count_i_ss;
|
|
|
|
reg [C_WR_PNTR_WIDTH:0] wdc_fwft_ext_as = 0;
|
|
|
|
/***************************************************************************
|
|
|
|
* Parameters used as constants
|
|
|
|
**************************************************************************/
|
|
|
|
localparam IS_8SERIES = (C_FAMILY == "virtexu" || C_FAMILY == "kintexu" || C_FAMILY == "artixu" || C_FAMILY == "virtexum" || C_FAMILY == "zynque") ? 1 : 0;
|
|
|
|
localparam C_DEPTH_RATIO_WR =
|
|
|
|
(C_WR_DEPTH>C_RD_DEPTH) ? (C_WR_DEPTH/C_RD_DEPTH) : 1;
|
|
|
|
localparam C_DEPTH_RATIO_RD =
|
|
|
|
(C_RD_DEPTH>C_WR_DEPTH) ? (C_RD_DEPTH/C_WR_DEPTH) : 1;
|
|
|
|
//localparam C_FIFO_WR_DEPTH = C_WR_DEPTH - 1;
|
|
|
|
//localparam C_FIFO_RD_DEPTH = C_RD_DEPTH - 1;
|
|
|
|
localparam C_GRTR_PNTR_WIDTH = (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) ? C_WR_PNTR_WIDTH : C_RD_PNTR_WIDTH ;
|
|
|
|
|
|
|
|
|
|
|
|
// C_DEPTH_RATIO_WR | C_DEPTH_RATIO_RD | C_PNTR_WIDTH | EXTRA_WORDS_DC
|
|
|
|
// -----------------|------------------|-----------------|---------------
|
|
|
|
// 1 | 8 | C_RD_PNTR_WIDTH | 2
|
|
|
|
// 1 | 4 | C_RD_PNTR_WIDTH | 2
|
|
|
|
// 1 | 2 | C_RD_PNTR_WIDTH | 2
|
|
|
|
// 1 | 1 | C_WR_PNTR_WIDTH | 2
|
|
|
|
// 2 | 1 | C_WR_PNTR_WIDTH | 4
|
|
|
|
// 4 | 1 | C_WR_PNTR_WIDTH | 8
|
|
|
|
// 8 | 1 | C_WR_PNTR_WIDTH | 16
|
|
|
|
|
|
|
|
localparam C_PNTR_WIDTH = (C_WR_PNTR_WIDTH>=C_RD_PNTR_WIDTH) ? C_WR_PNTR_WIDTH : C_RD_PNTR_WIDTH;
|
|
|
|
wire [C_PNTR_WIDTH:0] EXTRA_WORDS_DC = (C_DEPTH_RATIO_WR == 1) ? 2 : (2 * C_DEPTH_RATIO_WR/C_DEPTH_RATIO_RD);
|
|
|
|
wire [C_WR_PNTR_WIDTH:0] EXTRA_WORDS_PF = (C_DEPTH_RATIO_WR == 1) ? 2 : (2 * C_DEPTH_RATIO_WR/C_DEPTH_RATIO_RD);
|
|
|
|
//wire [C_RD_PNTR_WIDTH:0] EXTRA_WORDS_PE = (C_DEPTH_RATIO_RD == 1) ? 2 : (2 * C_DEPTH_RATIO_RD/C_DEPTH_RATIO_WR);
|
|
|
|
localparam EXTRA_WORDS_PF_PARAM = (C_DEPTH_RATIO_WR == 1) ? 2 : (2 * C_DEPTH_RATIO_WR/C_DEPTH_RATIO_RD);
|
|
|
|
//localparam EXTRA_WORDS_PE_PARAM = (C_DEPTH_RATIO_RD == 1) ? 2 : (2 * C_DEPTH_RATIO_RD/C_DEPTH_RATIO_WR);
|
|
|
|
|
|
|
|
localparam [31:0] reads_per_write = C_DIN_WIDTH/C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
localparam [31:0] log2_reads_per_write = log2_val(reads_per_write);
|
|
|
|
|
|
|
|
localparam [31:0] writes_per_read = C_DOUT_WIDTH/C_DIN_WIDTH;
|
|
|
|
|
|
|
|
localparam [31:0] log2_writes_per_read = log2_val(writes_per_read);
|
|
|
|
|
|
|
|
|
|
|
|
//When RST is present, set FULL reset value to '1'.
|
|
|
|
//If core has no RST, make sure FULL powers-on as '0'.
|
|
|
|
//The reset value assignments for FULL, ALMOST_FULL, and PROG_FULL are not
|
|
|
|
//changed for v3.2(IP2_Im). When the core has Sync Reset, C_HAS_SRST=1 and C_HAS_RST=0.
|
|
|
|
// Therefore, during SRST, all the FULL flags reset to 0.
|
|
|
|
localparam C_HAS_FAST_FIFO = 0;
|
|
|
|
localparam C_FIFO_WR_DEPTH = C_WR_DEPTH;
|
|
|
|
localparam C_FIFO_RD_DEPTH = C_RD_DEPTH;
|
|
|
|
// Local parameters used to determine whether to inject ECC error or not
|
|
|
|
localparam SYMMETRIC_PORT = (C_DIN_WIDTH == C_DOUT_WIDTH) ? 1 : 0;
|
|
|
|
localparam ERR_INJECTION = (C_ERROR_INJECTION_TYPE != 0) ? 1 : 0;
|
|
|
|
localparam ENABLE_ERR_INJECTION = C_USE_ECC && SYMMETRIC_PORT && ERR_INJECTION;
|
|
|
|
localparam C_DATA_WIDTH = (ENABLE_ERR_INJECTION == 1) ? (C_DIN_WIDTH+2) : C_DIN_WIDTH;
|
|
|
|
localparam IS_ASYMMETRY = (C_DIN_WIDTH == C_DOUT_WIDTH) ? 0 : 1;
|
|
|
|
localparam LESSER_WIDTH = (C_RD_PNTR_WIDTH > C_WR_PNTR_WIDTH) ? C_WR_PNTR_WIDTH : C_RD_PNTR_WIDTH;
|
|
|
|
localparam [C_RD_PNTR_WIDTH-1 : 0] DIFF_MAX_RD = {C_RD_PNTR_WIDTH{1'b1}};
|
|
|
|
localparam [C_WR_PNTR_WIDTH-1 : 0] DIFF_MAX_WR = {C_WR_PNTR_WIDTH{1'b1}};
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* FIFO Contents Tracking and Data Count Calculations
|
|
|
|
*************************************************************************/
|
|
|
|
// Memory which will be used to simulate a FIFO
|
|
|
|
reg [C_DIN_WIDTH-1:0] memory[C_WR_DEPTH-1:0];
|
|
|
|
reg [1:0] ecc_err[C_WR_DEPTH-1:0];
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Internal Registers and wires
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
//Temporary signals used for calculating the model's outputs. These
|
|
|
|
//are only used in the assign statements immediately following wire,
|
|
|
|
//parameter, and function declarations.
|
|
|
|
wire underflow_i;
|
|
|
|
wire valid_i;
|
|
|
|
wire valid_out;
|
|
|
|
reg [31:0] num_wr_bits;
|
|
|
|
reg [31:0] num_rd_bits;
|
|
|
|
reg [31:0] next_num_wr_bits;
|
|
|
|
reg [31:0] next_num_rd_bits;
|
|
|
|
|
|
|
|
//The write pointer - tracks write operations
|
|
|
|
// (Works opposite to core: wr_ptr is a DOWN counter)
|
|
|
|
reg [31:0] wr_ptr;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd1 = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd2 = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd3 = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr_rd = 0;
|
|
|
|
reg wr_rst_d1 =0;
|
|
|
|
|
|
|
|
//The read pointer - tracks read operations
|
|
|
|
// (rd_ptr Works opposite to core: rd_ptr is a DOWN counter)
|
|
|
|
reg [31:0] rd_ptr;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr1 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr2 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr3 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr4 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr_wr = 0;
|
|
|
|
|
|
|
|
wire ram_rd_en;
|
|
|
|
wire empty_int;
|
|
|
|
wire almost_empty_int;
|
|
|
|
wire ram_wr_en;
|
|
|
|
wire full_int;
|
|
|
|
wire almost_full_int;
|
|
|
|
reg ram_rd_en_reg = 1'b0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Ideal FIFO signals. These are the raw output of the behavioral model,
|
|
|
|
//which behaves like an ideal FIFO.
|
|
|
|
reg [1:0] err_type = 0;
|
|
|
|
reg [1:0] err_type_d1 = 0;
|
|
|
|
reg [C_DOUT_WIDTH-1:0] ideal_dout = 0;
|
|
|
|
reg [C_DOUT_WIDTH-1:0] ideal_dout_d1 = 0;
|
|
|
|
wire [C_DOUT_WIDTH-1:0] ideal_dout_out;
|
|
|
|
wire fwft_enabled;
|
|
|
|
reg ideal_wr_ack = 0;
|
|
|
|
reg ideal_valid = 0;
|
|
|
|
reg ideal_overflow = C_OVERFLOW_LOW;
|
|
|
|
reg ideal_underflow = C_UNDERFLOW_LOW;
|
|
|
|
|
|
|
|
reg full_i = C_FULL_FLAGS_RST_VAL;
|
|
|
|
reg full_i_temp = 0;
|
|
|
|
reg empty_i = 1;
|
|
|
|
reg almost_full_i = 0;
|
|
|
|
reg almost_empty_i = 1;
|
|
|
|
reg prog_full_i = 0;
|
|
|
|
reg prog_empty_i = 1;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] wr_pntr = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] rd_pntr = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] adj_wr_pntr_rd;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] adj_rd_pntr_wr;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] diff_count = 0;
|
|
|
|
|
|
|
|
reg write_allow_q = 0;
|
|
|
|
reg read_allow_q = 0;
|
|
|
|
reg valid_d1 = 0;
|
|
|
|
wire rst_i;
|
|
|
|
wire srst_i;
|
|
|
|
|
|
|
|
//user specified value for reseting the size of the fifo
|
|
|
|
reg [C_DOUT_WIDTH-1:0] dout_reset_val = 0;
|
|
|
|
|
|
|
|
reg [31:0] wr_ptr_rdclk;
|
|
|
|
reg [31:0] wr_ptr_rdclk_next;
|
|
|
|
reg [31:0] rd_ptr_wrclk;
|
|
|
|
reg [31:0] rd_ptr_wrclk_next;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Function Declarations
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* hexstr_conv
|
|
|
|
* Converts a string of type hex to a binary value (for C_DOUT_RST_VAL)
|
|
|
|
***************************************************************************/
|
|
|
|
function [C_DOUT_WIDTH-1:0] hexstr_conv;
|
|
|
|
input [(C_DOUT_WIDTH*8)-1:0] def_data;
|
|
|
|
|
|
|
|
integer index,i,j;
|
|
|
|
reg [3:0] bin;
|
|
|
|
|
|
|
|
begin
|
|
|
|
index = 0;
|
|
|
|
hexstr_conv = 'b0;
|
|
|
|
for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 ) begin
|
|
|
|
case (def_data[7:0])
|
|
|
|
8'b00000000 : begin
|
|
|
|
bin = 4'b0000;
|
|
|
|
i = -1;
|
|
|
|
end
|
|
|
|
8'b00110000 : bin = 4'b0000;
|
|
|
|
8'b00110001 : bin = 4'b0001;
|
|
|
|
8'b00110010 : bin = 4'b0010;
|
|
|
|
8'b00110011 : bin = 4'b0011;
|
|
|
|
8'b00110100 : bin = 4'b0100;
|
|
|
|
8'b00110101 : bin = 4'b0101;
|
|
|
|
8'b00110110 : bin = 4'b0110;
|
|
|
|
8'b00110111 : bin = 4'b0111;
|
|
|
|
8'b00111000 : bin = 4'b1000;
|
|
|
|
8'b00111001 : bin = 4'b1001;
|
|
|
|
8'b01000001 : bin = 4'b1010;
|
|
|
|
8'b01000010 : bin = 4'b1011;
|
|
|
|
8'b01000011 : bin = 4'b1100;
|
|
|
|
8'b01000100 : bin = 4'b1101;
|
|
|
|
8'b01000101 : bin = 4'b1110;
|
|
|
|
8'b01000110 : bin = 4'b1111;
|
|
|
|
8'b01100001 : bin = 4'b1010;
|
|
|
|
8'b01100010 : bin = 4'b1011;
|
|
|
|
8'b01100011 : bin = 4'b1100;
|
|
|
|
8'b01100100 : bin = 4'b1101;
|
|
|
|
8'b01100101 : bin = 4'b1110;
|
|
|
|
8'b01100110 : bin = 4'b1111;
|
|
|
|
default : begin
|
|
|
|
bin = 4'bx;
|
|
|
|
end
|
|
|
|
endcase
|
|
|
|
for( j=0; j<4; j=j+1) begin
|
|
|
|
if ((index*4)+j < C_DOUT_WIDTH) begin
|
|
|
|
hexstr_conv[(index*4)+j] = bin[j];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
index = index + 1;
|
|
|
|
def_data = def_data >> 8;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
/**************************************************************************
|
|
|
|
* log2_val
|
|
|
|
* Returns the 'log2' value for the input value for the supported ratios
|
|
|
|
***************************************************************************/
|
|
|
|
function [31:0] log2_val;
|
|
|
|
input [31:0] binary_val;
|
|
|
|
|
|
|
|
begin
|
|
|
|
if (binary_val == 8) begin
|
|
|
|
log2_val = 3;
|
|
|
|
end else if (binary_val == 4) begin
|
|
|
|
log2_val = 2;
|
|
|
|
end else begin
|
|
|
|
log2_val = 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
reg ideal_prog_full = 0;
|
|
|
|
reg ideal_prog_empty = 1;
|
|
|
|
reg [C_WR_DATA_COUNT_WIDTH-1 : 0] ideal_wr_count = 0;
|
|
|
|
reg [C_RD_DATA_COUNT_WIDTH-1 : 0] ideal_rd_count = 0;
|
|
|
|
|
|
|
|
//Assorted reg values for delayed versions of signals
|
|
|
|
//reg valid_d1 = 0;
|
|
|
|
|
|
|
|
|
|
|
|
//user specified value for reseting the size of the fifo
|
|
|
|
//reg [C_DOUT_WIDTH-1:0] dout_reset_val = 0;
|
|
|
|
|
|
|
|
//temporary registers for WR_RESPONSE_LATENCY feature
|
|
|
|
|
|
|
|
integer tmp_wr_listsize;
|
|
|
|
integer tmp_rd_listsize;
|
|
|
|
|
|
|
|
//Signal for registered version of prog full and empty
|
|
|
|
|
|
|
|
//Threshold values for Programmable Flags
|
|
|
|
integer prog_empty_actual_thresh_assert;
|
|
|
|
integer prog_empty_actual_thresh_negate;
|
|
|
|
integer prog_full_actual_thresh_assert;
|
|
|
|
integer prog_full_actual_thresh_negate;
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* write_fifo
|
|
|
|
* This task writes a word to the FIFO memory and updates the
|
|
|
|
* write pointer.
|
|
|
|
* FIFO size is relative to write domain.
|
|
|
|
***************************************************************************/
|
|
|
|
task write_fifo;
|
|
|
|
begin
|
|
|
|
memory[wr_ptr] <= DIN;
|
|
|
|
wr_pntr <= #`TCQ wr_pntr + 1;
|
|
|
|
// Store the type of error injection (double/single) on write
|
|
|
|
case (C_ERROR_INJECTION_TYPE)
|
|
|
|
3: ecc_err[wr_ptr] <= {INJECTDBITERR,INJECTSBITERR};
|
|
|
|
2: ecc_err[wr_ptr] <= {INJECTDBITERR,1'b0};
|
|
|
|
1: ecc_err[wr_ptr] <= {1'b0,INJECTSBITERR};
|
|
|
|
default: ecc_err[wr_ptr] <= 0;
|
|
|
|
endcase
|
|
|
|
// (Works opposite to core: wr_ptr is a DOWN counter)
|
|
|
|
if (wr_ptr == 0) begin
|
|
|
|
wr_ptr <= C_WR_DEPTH - 1;
|
|
|
|
end else begin
|
|
|
|
wr_ptr <= wr_ptr - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endtask // write_fifo
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* read_fifo
|
|
|
|
* This task reads a word from the FIFO memory and updates the read
|
|
|
|
* pointer. It's output is the ideal_dout bus.
|
|
|
|
* FIFO size is relative to write domain.
|
|
|
|
***************************************************************************/
|
|
|
|
task read_fifo;
|
|
|
|
integer i;
|
|
|
|
reg [C_DOUT_WIDTH-1:0] tmp_dout;
|
|
|
|
reg [C_DIN_WIDTH-1:0] memory_read;
|
|
|
|
reg [31:0] tmp_rd_ptr;
|
|
|
|
reg [31:0] rd_ptr_high;
|
|
|
|
reg [31:0] rd_ptr_low;
|
|
|
|
reg [1:0] tmp_ecc_err;
|
|
|
|
begin
|
|
|
|
rd_pntr <= #`TCQ rd_pntr + 1;
|
|
|
|
|
|
|
|
// output is wider than input
|
|
|
|
if (reads_per_write == 0) begin
|
|
|
|
tmp_dout = 0;
|
|
|
|
tmp_rd_ptr = (rd_ptr << log2_writes_per_read)+(writes_per_read-1);
|
|
|
|
for (i = writes_per_read - 1; i >= 0; i = i - 1) begin
|
|
|
|
tmp_dout = tmp_dout << C_DIN_WIDTH;
|
|
|
|
tmp_dout = tmp_dout | memory[tmp_rd_ptr];
|
|
|
|
|
|
|
|
// (Works opposite to core: rd_ptr is a DOWN counter)
|
|
|
|
if (tmp_rd_ptr == 0) begin
|
|
|
|
tmp_rd_ptr = C_WR_DEPTH - 1;
|
|
|
|
end else begin
|
|
|
|
tmp_rd_ptr = tmp_rd_ptr - 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// output is symmetric
|
|
|
|
end else if (reads_per_write == 1) begin
|
|
|
|
tmp_dout = memory[rd_ptr][C_DIN_WIDTH-1:0];
|
|
|
|
// Retreive the error injection type. Based on the error injection type
|
|
|
|
// corrupt the output data.
|
|
|
|
tmp_ecc_err = ecc_err[rd_ptr];
|
|
|
|
if (ENABLE_ERR_INJECTION && C_DIN_WIDTH == C_DOUT_WIDTH) begin
|
|
|
|
if (tmp_ecc_err[1]) begin // Corrupt the output data only for double bit error
|
|
|
|
if (C_DOUT_WIDTH == 1) begin
|
|
|
|
$display("FAILURE : Data width must be >= 2 for double bit error injection.");
|
|
|
|
$finish;
|
|
|
|
end else if (C_DOUT_WIDTH == 2)
|
|
|
|
tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2]};
|
|
|
|
else
|
|
|
|
tmp_dout = {~tmp_dout[C_DOUT_WIDTH-1],~tmp_dout[C_DOUT_WIDTH-2],(tmp_dout << 2)};
|
|
|
|
end else begin
|
|
|
|
tmp_dout = tmp_dout[C_DOUT_WIDTH-1:0];
|
|
|
|
end
|
|
|
|
err_type <= {tmp_ecc_err[1], tmp_ecc_err[0] & !tmp_ecc_err[1]};
|
|
|
|
end else begin
|
|
|
|
err_type <= 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
// input is wider than output
|
|
|
|
end else begin
|
|
|
|
rd_ptr_high = rd_ptr >> log2_reads_per_write;
|
|
|
|
rd_ptr_low = rd_ptr & (reads_per_write - 1);
|
|
|
|
memory_read = memory[rd_ptr_high];
|
|
|
|
tmp_dout = memory_read >> (rd_ptr_low*C_DOUT_WIDTH);
|
|
|
|
end
|
|
|
|
ideal_dout <= tmp_dout;
|
|
|
|
|
|
|
|
// (Works opposite to core: rd_ptr is a DOWN counter)
|
|
|
|
if (rd_ptr == 0) begin
|
|
|
|
rd_ptr <= C_RD_DEPTH - 1;
|
|
|
|
end else begin
|
|
|
|
rd_ptr <= rd_ptr - 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
endtask
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Initialize Signals for clean power-on simulation
|
|
|
|
*************************************************************************/
|
|
|
|
initial begin
|
|
|
|
num_wr_bits = 0;
|
|
|
|
num_rd_bits = 0;
|
|
|
|
next_num_wr_bits = 0;
|
|
|
|
next_num_rd_bits = 0;
|
|
|
|
rd_ptr = C_RD_DEPTH - 1;
|
|
|
|
wr_ptr = C_WR_DEPTH - 1;
|
|
|
|
wr_pntr = 0;
|
|
|
|
rd_pntr = 0;
|
|
|
|
rd_ptr_wrclk = rd_ptr;
|
|
|
|
wr_ptr_rdclk = wr_ptr;
|
|
|
|
dout_reset_val = hexstr_conv(C_DOUT_RST_VAL);
|
|
|
|
ideal_dout = dout_reset_val;
|
|
|
|
err_type = 0;
|
|
|
|
ideal_dout_d1 = dout_reset_val;
|
|
|
|
ideal_wr_ack = 1'b0;
|
|
|
|
ideal_valid = 1'b0;
|
|
|
|
valid_d1 = 1'b0;
|
|
|
|
ideal_overflow = C_OVERFLOW_LOW;
|
|
|
|
ideal_underflow = C_UNDERFLOW_LOW;
|
|
|
|
ideal_wr_count = 0;
|
|
|
|
ideal_rd_count = 0;
|
|
|
|
ideal_prog_full = 1'b0;
|
|
|
|
ideal_prog_empty = 1'b1;
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Connect the module inputs and outputs to the internal signals of the
|
|
|
|
* behavioral model.
|
|
|
|
*************************************************************************/
|
|
|
|
//Inputs
|
|
|
|
/*
|
|
|
|
wire CLK;
|
|
|
|
wire [C_DIN_WIDTH-1:0] DIN;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_ASSERT;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] PROG_EMPTY_THRESH_NEGATE;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_ASSERT;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] PROG_FULL_THRESH_NEGATE;
|
|
|
|
wire RD_EN;
|
|
|
|
wire RST;
|
|
|
|
wire WR_EN;
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Assign ALMOST_EPMTY
|
|
|
|
generate if (C_HAS_ALMOST_EMPTY == 1) begin : gae
|
|
|
|
assign ALMOST_EMPTY = almost_empty_i;
|
|
|
|
end else begin : gnae
|
|
|
|
assign ALMOST_EMPTY = 0;
|
|
|
|
end endgenerate // gae
|
|
|
|
|
|
|
|
// Assign ALMOST_FULL
|
|
|
|
generate if (C_HAS_ALMOST_FULL==1) begin : gaf
|
|
|
|
assign ALMOST_FULL = almost_full_i;
|
|
|
|
end else begin : gnaf
|
|
|
|
assign ALMOST_FULL = 0;
|
|
|
|
end endgenerate // gaf
|
|
|
|
|
|
|
|
// Dout may change behavior based on latency
|
|
|
|
assign fwft_enabled = (C_PRELOAD_LATENCY == 0 && C_PRELOAD_REGS == 1)?
|
|
|
|
1: 0;
|
|
|
|
assign ideal_dout_out= ((C_USE_EMBEDDED_REG==1 && (fwft_enabled == 0)) &&
|
|
|
|
(C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1))?
|
|
|
|
ideal_dout_d1: ideal_dout;
|
|
|
|
assign DOUT = ideal_dout_out;
|
|
|
|
|
|
|
|
// Assign SBITERR and DBITERR based on latency
|
|
|
|
assign SBITERR = (C_ERROR_INJECTION_TYPE == 1 || C_ERROR_INJECTION_TYPE == 3) &&
|
|
|
|
((C_USE_EMBEDDED_REG==1 && (fwft_enabled == 0)) &&
|
|
|
|
(C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ?
|
|
|
|
err_type_d1[0]: err_type[0];
|
|
|
|
assign DBITERR = (C_ERROR_INJECTION_TYPE == 2 || C_ERROR_INJECTION_TYPE == 3) &&
|
|
|
|
((C_USE_EMBEDDED_REG==1 && (fwft_enabled == 0)) &&
|
|
|
|
(C_MEMORY_TYPE==0 || C_MEMORY_TYPE==1)) ?
|
|
|
|
err_type_d1[1]: err_type[1];
|
|
|
|
|
|
|
|
assign EMPTY = empty_i;
|
|
|
|
assign FULL = full_i;
|
|
|
|
|
|
|
|
//Overflow may be active-low
|
|
|
|
generate if (C_HAS_OVERFLOW==1) begin : gof
|
|
|
|
assign OVERFLOW = ideal_overflow ? !C_OVERFLOW_LOW : C_OVERFLOW_LOW;
|
|
|
|
end else begin : gnof
|
|
|
|
assign OVERFLOW = 0;
|
|
|
|
end endgenerate // gof
|
|
|
|
|
|
|
|
assign PROG_EMPTY = prog_empty_i;
|
|
|
|
assign PROG_FULL = prog_full_i;
|
|
|
|
|
|
|
|
//Valid may change behavior based on latency or active-low
|
|
|
|
generate if (C_HAS_VALID==1) begin : gvalid
|
|
|
|
assign valid_i = (C_PRELOAD_LATENCY == 0) ? (RD_EN & ~EMPTY) : ideal_valid;
|
|
|
|
assign valid_out = (C_PRELOAD_LATENCY == 2 && C_MEMORY_TYPE < 2) ?
|
|
|
|
valid_d1 : valid_i;
|
|
|
|
assign VALID = valid_out ? !C_VALID_LOW : C_VALID_LOW;
|
|
|
|
end else begin : gnvalid
|
|
|
|
assign VALID = 0;
|
|
|
|
end endgenerate // gvalid
|
|
|
|
|
|
|
|
//Trim data count differently depending on set widths
|
|
|
|
generate if (C_HAS_DATA_COUNT == 1) begin : gdc
|
|
|
|
always @* begin
|
|
|
|
diff_count <= wr_pntr - rd_pntr;
|
|
|
|
if (C_DATA_COUNT_WIDTH > C_RD_PNTR_WIDTH) begin
|
|
|
|
DATA_COUNT[C_RD_PNTR_WIDTH-1:0] <= diff_count;
|
|
|
|
DATA_COUNT[C_DATA_COUNT_WIDTH-1] <= 1'b0 ;
|
|
|
|
end else begin
|
|
|
|
DATA_COUNT <= diff_count[C_RD_PNTR_WIDTH-1:C_RD_PNTR_WIDTH-C_DATA_COUNT_WIDTH];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
// end else begin : gndc
|
|
|
|
// always @* DATA_COUNT <= 0;
|
|
|
|
end endgenerate // gdc
|
|
|
|
|
|
|
|
//Underflow may change behavior based on latency or active-low
|
|
|
|
generate if (C_HAS_UNDERFLOW==1) begin : guf
|
|
|
|
assign underflow_i = ideal_underflow;
|
|
|
|
assign UNDERFLOW = underflow_i ? !C_UNDERFLOW_LOW : C_UNDERFLOW_LOW;
|
|
|
|
end else begin : gnuf
|
|
|
|
assign UNDERFLOW = 0;
|
|
|
|
end endgenerate // guf
|
|
|
|
|
|
|
|
|
|
|
|
//Write acknowledge may be active low
|
|
|
|
generate if (C_HAS_WR_ACK==1) begin : gwr_ack
|
|
|
|
assign WR_ACK = ideal_wr_ack ? !C_WR_ACK_LOW : C_WR_ACK_LOW;
|
|
|
|
end else begin : gnwr_ack
|
|
|
|
assign WR_ACK = 0;
|
|
|
|
end endgenerate // gwr_ack
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Internal reset logic
|
|
|
|
****************************************************************************/
|
|
|
|
assign srst_i = C_HAS_SRST ? SRST : 0;
|
|
|
|
assign srst_wrst_busy = C_HAS_SRST ? (SRST || WR_RST_BUSY) : 0;
|
|
|
|
assign srst_rrst_busy = C_HAS_SRST ? (SRST || RD_RST_BUSY) : 0;
|
|
|
|
assign rst_i = C_HAS_RST ? RST : 0;
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Assorted registers for delayed versions of signals
|
|
|
|
**************************************************************************/
|
|
|
|
//Capture delayed version of valid
|
|
|
|
generate if (C_HAS_VALID == 1) begin : blockVL20
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i == 1'b1) begin
|
|
|
|
valid_d1 <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
if (srst_rrst_busy) begin
|
|
|
|
valid_d1 <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
valid_d1 <= #`TCQ valid_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end // always @ (posedge CLK or posedge rst_i)
|
|
|
|
end endgenerate // blockVL20
|
|
|
|
|
|
|
|
// Determine which stage in FWFT registers are valid
|
|
|
|
reg stage1_valid = 0;
|
|
|
|
reg stage2_valid = 0;
|
|
|
|
generate
|
|
|
|
if (C_PRELOAD_LATENCY == 0) begin : grd_fwft_proc
|
|
|
|
always @ (posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i) begin
|
|
|
|
stage1_valid <= #`TCQ 0;
|
|
|
|
stage2_valid <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
if (!stage1_valid && !stage2_valid) begin
|
|
|
|
if (!EMPTY)
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
end else if (stage1_valid && !stage2_valid) begin
|
|
|
|
if (EMPTY) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end else if (!stage1_valid && stage2_valid) begin
|
|
|
|
if (EMPTY && RD_EN) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b0;
|
|
|
|
end else if (!EMPTY && RD_EN) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b0;
|
|
|
|
end else if (!EMPTY && !RD_EN) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end else if (stage1_valid && stage2_valid) begin
|
|
|
|
if (EMPTY && RD_EN) begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b1;
|
|
|
|
stage2_valid <= #`TCQ 1'b1;
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
stage1_valid <= #`TCQ 1'b0;
|
|
|
|
stage2_valid <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
end // rd_rst_i
|
|
|
|
end // always
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Assign the read data count value only if it is selected,
|
|
|
|
// otherwise output zeros.
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_RD_DATA_COUNT == 1 && C_USE_FWFT_DATA_COUNT ==1) begin : grdc
|
|
|
|
assign RD_DATA_COUNT[C_RD_DATA_COUNT_WIDTH-1:0] = rd_data_count_i_ss[C_RD_PNTR_WIDTH:C_RD_PNTR_WIDTH+1-C_RD_DATA_COUNT_WIDTH];
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate
|
|
|
|
if (C_HAS_RD_DATA_COUNT == 0) begin : gnrdc
|
|
|
|
assign RD_DATA_COUNT[C_RD_DATA_COUNT_WIDTH-1:0] = {C_RD_DATA_COUNT_WIDTH{1'b0}};
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Assign the write data count value only if it is selected,
|
|
|
|
// otherwise output zeros
|
|
|
|
//***************************************************************************
|
|
|
|
generate
|
|
|
|
if (C_HAS_WR_DATA_COUNT == 1 && C_USE_FWFT_DATA_COUNT == 1) begin : gwdc
|
|
|
|
assign WR_DATA_COUNT[C_WR_DATA_COUNT_WIDTH-1:0] = wr_data_count_i_ss[C_WR_PNTR_WIDTH:C_WR_PNTR_WIDTH+1-C_WR_DATA_COUNT_WIDTH] ;
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
generate
|
|
|
|
if (C_HAS_WR_DATA_COUNT == 0) begin : gnwdc
|
|
|
|
assign WR_DATA_COUNT[C_WR_DATA_COUNT_WIDTH-1:0] = {C_WR_DATA_COUNT_WIDTH{1'b0}};
|
|
|
|
end
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// block memory has a synchronous reset
|
|
|
|
generate if (C_MEMORY_TYPE < 2) begin : gen_fifo_blkmemdout_emb
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
// BRAM resets synchronously
|
|
|
|
// make it consistent with the core.
|
|
|
|
if ((rst_i || srst_rrst_busy) && (C_USE_DOUT_RST == 1))
|
|
|
|
ideal_dout_d1 <= #`TCQ dout_reset_val;
|
|
|
|
end //always
|
|
|
|
end endgenerate // gen_fifo_blkmemdout_emb
|
|
|
|
|
|
|
|
reg ram_rd_en_d1 = 1'b0;
|
|
|
|
//Capture delayed version of dout
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i == 1'b1) begin
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0)
|
|
|
|
err_type_d1 <= #`TCQ 0;
|
|
|
|
|
|
|
|
// DRAM and SRAM reset asynchronously
|
|
|
|
if ((C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3) && C_USE_DOUT_RST == 1)
|
|
|
|
ideal_dout_d1 <= #`TCQ dout_reset_val;
|
|
|
|
|
|
|
|
ram_rd_en_d1 <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
ram_rd_en_d1 <= #`TCQ RD_EN & ~EMPTY;
|
|
|
|
if (srst_rrst_busy) begin
|
|
|
|
ram_rd_en_d1 <= #`TCQ 1'b0;
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0)
|
|
|
|
err_type_d1 <= #`TCQ 0;
|
|
|
|
// Reset DRAM and SRAM based FIFO, BRAM based FIFO is reset above
|
|
|
|
if ((C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3) && C_USE_DOUT_RST == 1)
|
|
|
|
ideal_dout_d1 <= #`TCQ dout_reset_val;
|
|
|
|
end else if (ram_rd_en_d1) begin
|
|
|
|
ideal_dout_d1 <= #`TCQ ideal_dout;
|
|
|
|
err_type_d1 <= #`TCQ err_type;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Overflow and Underflow Flag calculation
|
|
|
|
* (handled separately because they don't support rst)
|
|
|
|
**************************************************************************/
|
|
|
|
generate if (C_HAS_OVERFLOW == 1 && IS_8SERIES == 0) begin : g7s_ovflw
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
ideal_overflow <= #`TCQ WR_EN & full_i;
|
|
|
|
end
|
|
|
|
end else if (C_HAS_OVERFLOW == 1 && IS_8SERIES == 1) begin : g8s_ovflw
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
//ideal_overflow <= #`TCQ WR_EN & (rst_i | full_i);
|
|
|
|
ideal_overflow <= #`TCQ WR_EN & (WR_RST_BUSY | full_i);
|
|
|
|
end
|
|
|
|
end endgenerate // blockOF20
|
|
|
|
|
|
|
|
generate if (C_HAS_UNDERFLOW == 1 && IS_8SERIES == 0) begin : g7s_unflw
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
ideal_underflow <= #`TCQ empty_i & RD_EN;
|
|
|
|
end
|
|
|
|
end else if (C_HAS_UNDERFLOW == 1 && IS_8SERIES == 1) begin : g8s_unflw
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
//ideal_underflow <= #`TCQ (rst_i | empty_i) & RD_EN;
|
|
|
|
ideal_underflow <= #`TCQ (RD_RST_BUSY | empty_i) & RD_EN;
|
|
|
|
end
|
|
|
|
end endgenerate // blockUF20
|
|
|
|
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
* Read Data Count
|
|
|
|
*************************/
|
|
|
|
|
|
|
|
reg [31:0] num_read_words_dc;
|
|
|
|
reg [C_RD_DATA_COUNT_WIDTH-1:0] num_read_words_sized_i;
|
|
|
|
|
|
|
|
always @(num_rd_bits) begin
|
|
|
|
if (C_USE_FWFT_DATA_COUNT) begin
|
|
|
|
|
|
|
|
//If using extra logic for FWFT Data Counts,
|
|
|
|
// then scale FIFO contents to read domain,
|
|
|
|
// and add two read words for FWFT stages
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_read_words_dc = (num_rd_bits/C_DOUT_WIDTH+2);
|
|
|
|
|
|
|
|
//Trim the read words for use with RD_DATA_COUNT
|
|
|
|
num_read_words_sized_i =
|
|
|
|
num_read_words_dc[C_RD_PNTR_WIDTH : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH+1];
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
//If not using extra logic for FWFT Data Counts,
|
|
|
|
// then scale FIFO contents to read domain.
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_read_words_dc = num_rd_bits/C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Trim the read words for use with RD_DATA_COUNT
|
|
|
|
num_read_words_sized_i =
|
|
|
|
num_read_words_dc[C_RD_PNTR_WIDTH-1 : C_RD_PNTR_WIDTH-C_RD_DATA_COUNT_WIDTH];
|
|
|
|
|
|
|
|
end //if (C_USE_FWFT_DATA_COUNT)
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
/**************************
|
|
|
|
* Write Data Count
|
|
|
|
*************************/
|
|
|
|
|
|
|
|
reg [31:0] num_write_words_dc;
|
|
|
|
reg [C_WR_DATA_COUNT_WIDTH-1:0] num_write_words_sized_i;
|
|
|
|
|
|
|
|
always @(num_wr_bits) begin
|
|
|
|
if (C_USE_FWFT_DATA_COUNT) begin
|
|
|
|
|
|
|
|
//Calculate the Data Count value for the number of write words,
|
|
|
|
// when using First-Word Fall-Through with extra logic for Data
|
|
|
|
// Counts. This takes into consideration the number of words that
|
|
|
|
// are expected to be stored in the FWFT register stages (it always
|
|
|
|
// assumes they are filled).
|
|
|
|
//This value is scaled to the Write Domain.
|
|
|
|
//The expression (((A-1)/B))+1 divides A/B, but takes the
|
|
|
|
// ceiling of the result.
|
|
|
|
//When num_wr_bits==0, set the result manually to prevent
|
|
|
|
// division errors.
|
|
|
|
//EXTRA_WORDS_DC is the number of words added to write_words
|
|
|
|
// due to FWFT.
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_write_words_dc = (num_wr_bits==0) ? EXTRA_WORDS_DC : (((num_wr_bits-1)/C_DIN_WIDTH)+1) + EXTRA_WORDS_DC ;
|
|
|
|
|
|
|
|
//Trim the write words for use with WR_DATA_COUNT
|
|
|
|
num_write_words_sized_i =
|
|
|
|
num_write_words_dc[C_WR_PNTR_WIDTH : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH+1];
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
|
|
|
|
//Calculate the Data Count value for the number of write words, when NOT
|
|
|
|
// using First-Word Fall-Through with extra logic for Data Counts. This
|
|
|
|
// calculates only the number of words in the internal FIFO.
|
|
|
|
//The expression (((A-1)/B))+1 divides A/B, but takes the
|
|
|
|
// ceiling of the result.
|
|
|
|
//This value is scaled to the Write Domain.
|
|
|
|
//When num_wr_bits==0, set the result manually to prevent
|
|
|
|
// division errors.
|
|
|
|
//This value is only a temporary value and not used in the code.
|
|
|
|
num_write_words_dc = (num_wr_bits==0) ? 0 : ((num_wr_bits-1)/C_DIN_WIDTH)+1;
|
|
|
|
|
|
|
|
//Trim the read words for use with RD_DATA_COUNT
|
|
|
|
num_write_words_sized_i =
|
|
|
|
num_write_words_dc[C_WR_PNTR_WIDTH-1 : C_WR_PNTR_WIDTH-C_WR_DATA_COUNT_WIDTH];
|
|
|
|
|
|
|
|
end //if (C_USE_FWFT_DATA_COUNT)
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Write and Read Logic
|
|
|
|
************************************************************************/
|
|
|
|
wire write_allow;
|
|
|
|
wire read_allow;
|
|
|
|
wire read_allow_dc;
|
|
|
|
wire write_only;
|
|
|
|
wire read_only;
|
|
|
|
//wire write_only_q;
|
|
|
|
reg write_only_q;
|
|
|
|
//wire read_only_q;
|
|
|
|
reg read_only_q;
|
|
|
|
reg full_reg;
|
|
|
|
reg rst_full_ff_reg1;
|
|
|
|
reg rst_full_ff_reg2;
|
|
|
|
wire ram_full_comb;
|
|
|
|
wire carry;
|
|
|
|
|
|
|
|
assign write_allow = WR_EN & ~full_i;
|
|
|
|
assign read_allow = RD_EN & ~empty_i;
|
|
|
|
assign read_allow_dc = RD_EN_USER & ~USER_EMPTY_FB;
|
|
|
|
//assign write_only = write_allow & ~read_allow;
|
|
|
|
//assign write_only_q = write_allow_q;
|
|
|
|
//assign read_only = read_allow & ~write_allow;
|
|
|
|
//assign read_only_q = read_allow_q ;
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] diff_pntr;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] diff_pntr_pe;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] diff_pntr_reg1 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH-1:0] diff_pntr_pe_reg1 = 0;
|
|
|
|
reg [C_RD_PNTR_WIDTH:0] diff_pntr_pe_asym = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH:0] adj_wr_pntr_rd_asym ;
|
|
|
|
wire [C_RD_PNTR_WIDTH:0] rd_pntr_asym;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] diff_pntr_reg2 = 0;
|
|
|
|
reg [C_WR_PNTR_WIDTH-1:0] diff_pntr_pe_reg2 = 0;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] diff_pntr_pe_max;
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] diff_pntr_max;
|
|
|
|
|
|
|
|
assign diff_pntr_pe_max = DIFF_MAX_RD;
|
|
|
|
assign diff_pntr_max = DIFF_MAX_WR;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generate if (IS_ASYMMETRY == 0) begin : diff_pntr_sym
|
|
|
|
assign write_only = write_allow & ~read_allow;
|
|
|
|
assign read_only = read_allow & ~write_allow;
|
|
|
|
end endgenerate
|
|
|
|
generate if ( IS_ASYMMETRY == 1 && C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin : wr_grt_rd
|
|
|
|
assign read_only = read_allow & &(rd_pntr[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0]) & ~write_allow;
|
|
|
|
assign write_only = write_allow & ~(read_allow & &(rd_pntr[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0]));
|
|
|
|
end endgenerate
|
|
|
|
generate if (IS_ASYMMETRY ==1 && C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : rd_grt_wr
|
|
|
|
assign read_only = read_allow & ~(write_allow & &(wr_pntr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0]));
|
|
|
|
assign write_only = write_allow & &(wr_pntr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0]) & ~read_allow;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Write and Read pointer generation
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i) begin
|
|
|
|
wr_pntr <= 0;
|
|
|
|
rd_pntr <= 0;
|
|
|
|
end else begin
|
|
|
|
if (srst_i || srst_wrst_busy || srst_rrst_busy ) begin
|
|
|
|
if (srst_wrst_busy)
|
|
|
|
wr_pntr <= #`TCQ 0;
|
|
|
|
if (srst_rrst_busy)
|
|
|
|
rd_pntr <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
if (write_allow) wr_pntr <= #`TCQ wr_pntr + 1;
|
|
|
|
if (read_allow) rd_pntr <= #`TCQ rd_pntr + 1;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
generate if (C_FIFO_TYPE == 2) begin : gll_dm_dout
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if (write_allow) begin
|
|
|
|
if (ENABLE_ERR_INJECTION == 1)
|
|
|
|
memory[wr_pntr] <= #`TCQ {INJECTDBITERR,INJECTSBITERR,DIN};
|
|
|
|
else
|
|
|
|
memory[wr_pntr] <= #`TCQ DIN;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
reg [C_DATA_WIDTH-1:0] dout_tmp_q;
|
|
|
|
reg [C_DATA_WIDTH-1:0] dout_tmp = 0;
|
|
|
|
reg [C_DATA_WIDTH-1:0] dout_tmp1 = 0;
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
dout_tmp_q <= #`TCQ ideal_dout;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
always @* begin
|
|
|
|
if (read_allow)
|
|
|
|
ideal_dout <= memory[rd_pntr];
|
|
|
|
else
|
|
|
|
ideal_dout <= dout_tmp_q;
|
|
|
|
end
|
|
|
|
end endgenerate // gll_dm_dout
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Write Domain Logic
|
|
|
|
**************************************************************************/
|
|
|
|
assign ram_rd_en = RD_EN & !EMPTY;
|
|
|
|
|
|
|
|
//reg [C_WR_PNTR_WIDTH-1:0] diff_pntr = 0;
|
|
|
|
generate if (C_FIFO_TYPE != 2) begin : gnll_din
|
|
|
|
always @(posedge CLK or posedge rst_i) begin : gen_fifo_w
|
|
|
|
|
|
|
|
/****** Reset fifo (case 1)***************************************/
|
|
|
|
if (rst_i == 1'b1) begin
|
|
|
|
num_wr_bits <= #`TCQ 0;
|
|
|
|
next_num_wr_bits = #`TCQ 0;
|
|
|
|
wr_ptr <= #`TCQ C_WR_DEPTH - 1;
|
|
|
|
rd_ptr_wrclk <= #`TCQ C_RD_DEPTH - 1;
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
ideal_wr_count <= #`TCQ 0;
|
|
|
|
tmp_wr_listsize = #`TCQ 0;
|
|
|
|
rd_ptr_wrclk_next <= #`TCQ 0;
|
|
|
|
wr_pntr <= #`TCQ 0;
|
|
|
|
wr_pntr_rd1 <= #`TCQ 0;
|
|
|
|
|
|
|
|
end else begin //rst_i==0
|
|
|
|
if (srst_wrst_busy) begin
|
|
|
|
num_wr_bits <= #`TCQ 0;
|
|
|
|
next_num_wr_bits = #`TCQ 0;
|
|
|
|
wr_ptr <= #`TCQ C_WR_DEPTH - 1;
|
|
|
|
rd_ptr_wrclk <= #`TCQ C_RD_DEPTH - 1;
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
ideal_wr_count <= #`TCQ 0;
|
|
|
|
tmp_wr_listsize = #`TCQ 0;
|
|
|
|
rd_ptr_wrclk_next <= #`TCQ 0;
|
|
|
|
wr_pntr <= #`TCQ 0;
|
|
|
|
wr_pntr_rd1 <= #`TCQ 0;
|
|
|
|
end else begin//srst_i=0
|
|
|
|
|
|
|
|
wr_pntr_rd1 <= #`TCQ wr_pntr;
|
|
|
|
|
|
|
|
//Determine the current number of words in the FIFO
|
|
|
|
tmp_wr_listsize = (C_DEPTH_RATIO_RD > 1) ? num_wr_bits/C_DOUT_WIDTH :
|
|
|
|
num_wr_bits/C_DIN_WIDTH;
|
|
|
|
rd_ptr_wrclk_next = rd_ptr;
|
|
|
|
if (rd_ptr_wrclk < rd_ptr_wrclk_next) begin
|
|
|
|
next_num_wr_bits = num_wr_bits -
|
|
|
|
C_DOUT_WIDTH*(rd_ptr_wrclk + C_RD_DEPTH
|
|
|
|
- rd_ptr_wrclk_next);
|
|
|
|
end else begin
|
|
|
|
next_num_wr_bits = num_wr_bits -
|
|
|
|
C_DOUT_WIDTH*(rd_ptr_wrclk - rd_ptr_wrclk_next);
|
|
|
|
end
|
|
|
|
|
|
|
|
if (WR_EN == 1'b1) begin
|
|
|
|
if (FULL == 1'b1) begin
|
|
|
|
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
//Reminder that FIFO is still full
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
|
|
|
|
end else begin
|
|
|
|
write_fifo;
|
|
|
|
next_num_wr_bits = next_num_wr_bits + C_DIN_WIDTH;
|
|
|
|
//Write successful, so issue acknowledge
|
|
|
|
// and no error
|
|
|
|
ideal_wr_ack <= #`TCQ 1;
|
|
|
|
//Not even close to full.
|
|
|
|
ideal_wr_count <= num_write_words_sized_i;
|
|
|
|
|
|
|
|
//end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end else begin //(WR_EN == 1'b1)
|
|
|
|
|
|
|
|
//If user did not attempt a write, then do not
|
|
|
|
// give ack or err
|
|
|
|
ideal_wr_ack <= #`TCQ 0;
|
|
|
|
ideal_wr_count <= #`TCQ num_write_words_sized_i;
|
|
|
|
end
|
|
|
|
num_wr_bits <= #`TCQ next_num_wr_bits;
|
|
|
|
rd_ptr_wrclk <= #`TCQ rd_ptr;
|
|
|
|
|
|
|
|
end //srst_i==0
|
|
|
|
end //wr_rst_i==0
|
|
|
|
end // gen_fifo_w
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_FIFO_TYPE < 2 && C_MEMORY_TYPE < 2) begin : gnll_dm_dout
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if (rst_i || srst_rrst_busy) begin
|
|
|
|
if (C_USE_DOUT_RST == 1)
|
|
|
|
ideal_dout <= #`TCQ dout_reset_val;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_FIFO_TYPE != 2) begin : gnll_dout
|
|
|
|
always @(posedge CLK or posedge rst_i) begin : gen_fifo_r
|
|
|
|
|
|
|
|
/****** Reset fifo (case 1)***************************************/
|
|
|
|
if (rst_i) begin
|
|
|
|
num_rd_bits <= #`TCQ 0;
|
|
|
|
next_num_rd_bits = #`TCQ 0;
|
|
|
|
rd_ptr <= #`TCQ C_RD_DEPTH -1;
|
|
|
|
rd_pntr <= #`TCQ 0;
|
|
|
|
//rd_pntr_wr1 <= #`TCQ 0;
|
|
|
|
wr_ptr_rdclk <= #`TCQ C_WR_DEPTH -1;
|
|
|
|
|
|
|
|
// DRAM resets asynchronously
|
|
|
|
if (C_FIFO_TYPE < 2 && (C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3 )&& C_USE_DOUT_RST == 1)
|
|
|
|
ideal_dout <= #`TCQ dout_reset_val;
|
|
|
|
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0)
|
|
|
|
err_type <= #`TCQ 0;
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
ideal_rd_count <= #`TCQ 0;
|
|
|
|
|
|
|
|
end else begin //rd_rst_i==0
|
|
|
|
if (srst_rrst_busy) begin
|
|
|
|
num_rd_bits <= #`TCQ 0;
|
|
|
|
next_num_rd_bits = #`TCQ 0;
|
|
|
|
rd_ptr <= #`TCQ C_RD_DEPTH -1;
|
|
|
|
rd_pntr <= #`TCQ 0;
|
|
|
|
//rd_pntr_wr1 <= #`TCQ 0;
|
|
|
|
wr_ptr_rdclk <= #`TCQ C_WR_DEPTH -1;
|
|
|
|
|
|
|
|
// DRAM resets synchronously
|
|
|
|
if (C_FIFO_TYPE < 2 && (C_MEMORY_TYPE == 2 || C_MEMORY_TYPE == 3 )&& C_USE_DOUT_RST == 1)
|
|
|
|
ideal_dout <= #`TCQ dout_reset_val;
|
|
|
|
|
|
|
|
// Reset err_type only if ECC is not selected
|
|
|
|
if (C_USE_ECC == 0)
|
|
|
|
err_type <= #`TCQ 0;
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
ideal_rd_count <= #`TCQ 0;
|
|
|
|
end //srst_i
|
|
|
|
else begin
|
|
|
|
|
|
|
|
//rd_pntr_wr1 <= #`TCQ rd_pntr;
|
|
|
|
|
|
|
|
//Determine the current number of words in the FIFO
|
|
|
|
tmp_rd_listsize = (C_DEPTH_RATIO_WR > 1) ? num_rd_bits/C_DIN_WIDTH :
|
|
|
|
num_rd_bits/C_DOUT_WIDTH;
|
|
|
|
wr_ptr_rdclk_next = wr_ptr;
|
|
|
|
|
|
|
|
if (wr_ptr_rdclk < wr_ptr_rdclk_next) begin
|
|
|
|
next_num_rd_bits = num_rd_bits +
|
|
|
|
C_DIN_WIDTH*(wr_ptr_rdclk +C_WR_DEPTH
|
|
|
|
- wr_ptr_rdclk_next);
|
|
|
|
end else begin
|
|
|
|
next_num_rd_bits = num_rd_bits +
|
|
|
|
C_DIN_WIDTH*(wr_ptr_rdclk - wr_ptr_rdclk_next);
|
|
|
|
end
|
|
|
|
|
|
|
|
if (RD_EN == 1'b1) begin
|
|
|
|
|
|
|
|
if (EMPTY == 1'b1) begin
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
read_fifo;
|
|
|
|
next_num_rd_bits = next_num_rd_bits - C_DOUT_WIDTH;
|
|
|
|
|
|
|
|
//Acknowledge the read from the FIFO, no error
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
ideal_rd_count <= #`TCQ num_read_words_sized_i;
|
|
|
|
|
|
|
|
end // if (tmp_rd_listsize == 2)
|
|
|
|
end
|
|
|
|
|
|
|
|
num_rd_bits <= #`TCQ next_num_rd_bits;
|
|
|
|
wr_ptr_rdclk <= #`TCQ wr_ptr;
|
|
|
|
end //s_rst_i==0
|
|
|
|
end //rd_rst_i==0
|
|
|
|
end //always
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate diff_pntr for PROG_FULL generation
|
|
|
|
// Generate diff_pntr_pe for PROG_EMPTY generation
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
generate if ((C_PROG_FULL_TYPE != 0 || C_PROG_EMPTY_TYPE != 0) && IS_ASYMMETRY == 0) begin : reg_write_allow
|
|
|
|
always @(posedge CLK ) begin
|
|
|
|
if (rst_i) begin
|
|
|
|
write_only_q <= 1'b0;
|
|
|
|
read_only_q <= 1'b0;
|
|
|
|
diff_pntr_reg1 <= 0;
|
|
|
|
diff_pntr_pe_reg1 <= 0;
|
|
|
|
diff_pntr_reg2 <= 0;
|
|
|
|
diff_pntr_pe_reg2 <= 0;
|
|
|
|
end else begin
|
|
|
|
if (srst_i || srst_wrst_busy || srst_rrst_busy) begin
|
|
|
|
if (srst_rrst_busy) begin
|
|
|
|
read_only_q <= #`TCQ 1'b0;
|
|
|
|
diff_pntr_pe_reg1 <= #`TCQ 0;
|
|
|
|
diff_pntr_pe_reg2 <= #`TCQ 0;
|
|
|
|
end
|
|
|
|
if (srst_wrst_busy) begin
|
|
|
|
write_only_q <= #`TCQ 1'b0;
|
|
|
|
diff_pntr_reg1 <= #`TCQ 0;
|
|
|
|
diff_pntr_reg2 <= #`TCQ 0;
|
|
|
|
end
|
|
|
|
end else begin
|
|
|
|
write_only_q <= #`TCQ write_only;
|
|
|
|
read_only_q <= #`TCQ read_only;
|
|
|
|
diff_pntr_reg2 <= #`TCQ diff_pntr_reg1;
|
|
|
|
diff_pntr_pe_reg2 <= #`TCQ diff_pntr_pe_reg1;
|
|
|
|
|
|
|
|
// Add 1 to the difference pointer value when only write happens.
|
|
|
|
if (write_only)
|
|
|
|
diff_pntr_reg1 <= #`TCQ wr_pntr - adj_rd_pntr_wr + 1;
|
|
|
|
else
|
|
|
|
diff_pntr_reg1 <= #`TCQ wr_pntr - adj_rd_pntr_wr;
|
|
|
|
|
|
|
|
// Add 1 to the difference pointer value when write or both write & read or no write & read happen.
|
|
|
|
if (read_only)
|
|
|
|
diff_pntr_pe_reg1 <= #`TCQ adj_wr_pntr_rd - rd_pntr - 1;
|
|
|
|
else
|
|
|
|
diff_pntr_pe_reg1 <= #`TCQ adj_wr_pntr_rd - rd_pntr;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assign diff_pntr_pe = diff_pntr_pe_reg1;
|
|
|
|
assign diff_pntr = diff_pntr_reg1;
|
|
|
|
end endgenerate // reg_write_allow
|
|
|
|
|
|
|
|
generate if ((C_PROG_FULL_TYPE != 0 || C_PROG_EMPTY_TYPE != 0) && IS_ASYMMETRY == 1) begin : reg_write_allow_asym
|
|
|
|
assign adj_wr_pntr_rd_asym[C_RD_PNTR_WIDTH:0] = {adj_wr_pntr_rd,1'b1};
|
|
|
|
assign rd_pntr_asym[C_RD_PNTR_WIDTH:0] = {~rd_pntr,1'b1};
|
|
|
|
always @(posedge CLK ) begin
|
|
|
|
if (rst_i) begin
|
|
|
|
diff_pntr_pe_asym <= 0;
|
|
|
|
diff_pntr_reg1 <= 0;
|
|
|
|
full_reg <= 0;
|
|
|
|
rst_full_ff_reg1 <= 1;
|
|
|
|
rst_full_ff_reg2 <= 1;
|
|
|
|
diff_pntr_pe_reg1 <= 0;
|
|
|
|
end else begin
|
|
|
|
if (srst_i || srst_wrst_busy || srst_rrst_busy) begin
|
|
|
|
if (srst_wrst_busy)
|
|
|
|
diff_pntr_reg1 <= #`TCQ 0;
|
|
|
|
if (srst_rrst_busy)
|
|
|
|
full_reg <= #`TCQ 0;
|
|
|
|
rst_full_ff_reg1 <= #`TCQ 1;
|
|
|
|
rst_full_ff_reg2 <= #`TCQ 1;
|
|
|
|
diff_pntr_pe_asym <= #`TCQ 0;
|
|
|
|
diff_pntr_pe_reg1 <= #`TCQ 0;
|
|
|
|
end else begin
|
|
|
|
diff_pntr_pe_asym <= #`TCQ adj_wr_pntr_rd_asym + rd_pntr_asym;
|
|
|
|
full_reg <= #`TCQ full_i;
|
|
|
|
rst_full_ff_reg1 <= #`TCQ RST_FULL_FF;
|
|
|
|
rst_full_ff_reg2 <= #`TCQ rst_full_ff_reg1;
|
|
|
|
if (~full_i) begin
|
|
|
|
diff_pntr_reg1 <= #`TCQ wr_pntr - adj_rd_pntr_wr;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assign carry = (~(|(diff_pntr_pe_asym [C_RD_PNTR_WIDTH : 1])));
|
|
|
|
assign diff_pntr_pe = (full_reg && ~rst_full_ff_reg2 && carry ) ? diff_pntr_pe_max : diff_pntr_pe_asym[C_RD_PNTR_WIDTH:1];
|
|
|
|
assign diff_pntr = diff_pntr_reg1;
|
|
|
|
end endgenerate // reg_write_allow_asym
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate FULL flag
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire comp0;
|
|
|
|
wire comp1;
|
|
|
|
wire going_full;
|
|
|
|
wire leaving_full;
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : gpad
|
|
|
|
assign adj_rd_pntr_wr [C_WR_PNTR_WIDTH-1 : C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH] = rd_pntr;
|
|
|
|
assign adj_rd_pntr_wr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0] = 0;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH <= C_RD_PNTR_WIDTH) begin : gtrim
|
|
|
|
assign adj_rd_pntr_wr = rd_pntr[C_RD_PNTR_WIDTH-1 : C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
assign comp1 = (adj_rd_pntr_wr == (wr_pntr + 1'b1));
|
|
|
|
assign comp0 = (adj_rd_pntr_wr == wr_pntr);
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH == C_RD_PNTR_WIDTH) begin : gf_wp_eq_rp
|
|
|
|
assign going_full = (comp1 & write_allow & ~read_allow);
|
|
|
|
assign leaving_full = (comp0 & read_allow) | RST_FULL_GEN;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
// Write data width is bigger than read data width
|
|
|
|
// Write depth is smaller than read depth
|
|
|
|
// One write could be equal to 2 or 4 or 8 reads
|
|
|
|
generate if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin : gf_asym
|
|
|
|
assign going_full = (comp1 & write_allow & (~ (read_allow & &(rd_pntr[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0]))));
|
|
|
|
assign leaving_full = (comp0 & read_allow & &(rd_pntr[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0])) | RST_FULL_GEN;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : gf_wp_gt_rp
|
|
|
|
assign going_full = (comp1 & write_allow & ~read_allow);
|
|
|
|
assign leaving_full =(comp0 & read_allow) | RST_FULL_GEN;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
assign ram_full_comb = going_full | (~leaving_full & full_i);
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge RST_FULL_FF) begin
|
|
|
|
if (RST_FULL_FF)
|
|
|
|
full_i <= C_FULL_FLAGS_RST_VAL;
|
|
|
|
else if (srst_wrst_busy)
|
|
|
|
full_i <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
else
|
|
|
|
full_i <= #`TCQ ram_full_comb;
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate EMPTY flag
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire ecomp0;
|
|
|
|
wire ecomp1;
|
|
|
|
wire going_empty;
|
|
|
|
wire leaving_empty;
|
|
|
|
wire ram_empty_comb;
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_RD_PNTR_WIDTH > C_WR_PNTR_WIDTH) begin : pad
|
|
|
|
assign adj_wr_pntr_rd [C_RD_PNTR_WIDTH-1 : C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH] = wr_pntr;
|
|
|
|
assign adj_wr_pntr_rd[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0] = 0;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_RD_PNTR_WIDTH <= C_WR_PNTR_WIDTH) begin : trim
|
|
|
|
assign adj_wr_pntr_rd = wr_pntr[C_WR_PNTR_WIDTH-1 : C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH];
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
assign ecomp1 = (adj_wr_pntr_rd == (rd_pntr + 1'b1));
|
|
|
|
assign ecomp0 = (adj_wr_pntr_rd == rd_pntr);
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH == C_RD_PNTR_WIDTH) begin : ge_wp_eq_rp
|
|
|
|
assign going_empty = (ecomp1 & ~write_allow & read_allow);
|
|
|
|
assign leaving_empty = (ecomp0 & write_allow);
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : ge_wp_gt_rp
|
|
|
|
assign going_empty = (ecomp1 & read_allow & (~(write_allow & &(wr_pntr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0]))));
|
|
|
|
assign leaving_empty = (ecomp0 & write_allow & &(wr_pntr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0]));
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin : ge_wp_lt_rp
|
|
|
|
assign going_empty = (ecomp1 & ~write_allow & read_allow);
|
|
|
|
assign leaving_empty =(ecomp0 & write_allow);
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assign ram_empty_comb = going_empty | (~leaving_empty & empty_i);
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i)
|
|
|
|
empty_i <= 1'b1;
|
|
|
|
else if (srst_rrst_busy)
|
|
|
|
empty_i <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
empty_i <= #`TCQ ram_empty_comb;
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate Read and write data counts for asymmetic common clock
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
reg [C_GRTR_PNTR_WIDTH :0] count_dc = 0;
|
|
|
|
wire [C_GRTR_PNTR_WIDTH :0] ratio;
|
|
|
|
wire decr_by_one;
|
|
|
|
wire incr_by_ratio;
|
|
|
|
wire incr_by_one;
|
|
|
|
wire decr_by_ratio;
|
|
|
|
|
|
|
|
localparam IS_FWFT = (C_PRELOAD_REGS == 1 && C_PRELOAD_LATENCY == 0) ? 1 : 0;
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin : rd_depth_gt_wr
|
|
|
|
assign ratio = C_DEPTH_RATIO_RD;
|
|
|
|
assign decr_by_one = (IS_FWFT == 1)? read_allow_dc : read_allow;
|
|
|
|
assign incr_by_ratio = write_allow;
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i)
|
|
|
|
count_dc <= #`TCQ 0;
|
|
|
|
else if (srst_wrst_busy)
|
|
|
|
count_dc <= #`TCQ 0;
|
|
|
|
else begin
|
|
|
|
if (decr_by_one) begin
|
|
|
|
if (!incr_by_ratio)
|
|
|
|
count_dc <= #`TCQ count_dc - 1;
|
|
|
|
else
|
|
|
|
count_dc <= #`TCQ count_dc - 1 + ratio ;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (!incr_by_ratio)
|
|
|
|
count_dc <= #`TCQ count_dc ;
|
|
|
|
else
|
|
|
|
count_dc <= #`TCQ count_dc + ratio ;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assign rd_data_count_i_ss[C_RD_PNTR_WIDTH : 0] = count_dc;
|
|
|
|
assign wr_data_count_i_ss[C_WR_PNTR_WIDTH : 0] = count_dc[C_RD_PNTR_WIDTH : C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH];
|
|
|
|
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : wr_depth_gt_rd
|
|
|
|
assign ratio = C_DEPTH_RATIO_WR;
|
|
|
|
assign incr_by_one = write_allow;
|
|
|
|
assign decr_by_ratio = (IS_FWFT == 1)? read_allow_dc : read_allow;
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i)
|
|
|
|
count_dc <= #`TCQ 0;
|
|
|
|
else if (srst_wrst_busy)
|
|
|
|
count_dc <= #`TCQ 0;
|
|
|
|
else begin
|
|
|
|
if (incr_by_one) begin
|
|
|
|
if (!decr_by_ratio)
|
|
|
|
count_dc <= #`TCQ count_dc + 1;
|
|
|
|
else
|
|
|
|
count_dc <= #`TCQ count_dc + 1 - ratio ;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (!decr_by_ratio)
|
|
|
|
count_dc <= #`TCQ count_dc ;
|
|
|
|
else
|
|
|
|
count_dc <= #`TCQ count_dc - ratio ;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assign wr_data_count_i_ss[C_WR_PNTR_WIDTH : 0] = count_dc;
|
|
|
|
assign rd_data_count_i_ss[C_RD_PNTR_WIDTH : 0] = count_dc[C_WR_PNTR_WIDTH : C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH];
|
|
|
|
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate WR_ACK flag
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i)
|
|
|
|
ideal_wr_ack <= 1'b0;
|
|
|
|
else if (srst_wrst_busy)
|
|
|
|
ideal_wr_ack <= #`TCQ 1'b0;
|
|
|
|
else if (WR_EN & ~full_i)
|
|
|
|
ideal_wr_ack <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
ideal_wr_ack <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate VALID flag
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i)
|
|
|
|
ideal_valid <= 1'b0;
|
|
|
|
else if (srst_rrst_busy)
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
else if (RD_EN & ~empty_i)
|
|
|
|
ideal_valid <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
ideal_valid <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate ALMOST_FULL flag
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//generate if (C_HAS_ALMOST_FULL == 1 || C_PROG_FULL_TYPE > 2 || C_PROG_EMPTY_TYPE > 2) begin : gaf_ss
|
|
|
|
|
|
|
|
wire fcomp2;
|
|
|
|
wire going_afull;
|
|
|
|
wire leaving_afull;
|
|
|
|
wire ram_afull_comb;
|
|
|
|
|
|
|
|
|
|
|
|
assign fcomp2 = (adj_rd_pntr_wr == (wr_pntr + 2'h2));
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH == C_RD_PNTR_WIDTH) begin : gaf_wp_eq_rp
|
|
|
|
assign going_afull = (fcomp2 & write_allow & ~read_allow);
|
|
|
|
assign leaving_afull = (comp1 & read_allow & ~write_allow) | RST_FULL_GEN;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
// Write data width is bigger than read data width
|
|
|
|
// Write depth is smaller than read depth
|
|
|
|
// One write could be equal to 2 or 4 or 8 reads
|
|
|
|
generate if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin : gaf_asym
|
|
|
|
assign going_afull = (fcomp2 & write_allow & (~ (read_allow & &(rd_pntr[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0]))));
|
|
|
|
assign leaving_afull = (comp1 & (~write_allow) & read_allow & &(rd_pntr[C_RD_PNTR_WIDTH-C_WR_PNTR_WIDTH-1 : 0])) | RST_FULL_GEN;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : gaf_wp_gt_rp
|
|
|
|
assign going_afull = (fcomp2 & write_allow & ~read_allow);
|
|
|
|
assign leaving_afull =((comp0 | comp1 | fcomp2) & read_allow) | RST_FULL_GEN;
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
assign ram_afull_comb = going_afull | (~leaving_afull & almost_full_i);
|
|
|
|
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge RST_FULL_FF) begin
|
|
|
|
if (RST_FULL_FF)
|
|
|
|
almost_full_i <= C_FULL_FLAGS_RST_VAL;
|
|
|
|
else if (srst_wrst_busy)
|
|
|
|
almost_full_i <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
else
|
|
|
|
almost_full_i <= #`TCQ ram_afull_comb;
|
|
|
|
end
|
|
|
|
// end endgenerate // gaf_ss
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate ALMOST_EMPTY flag
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//generate if (C_HAS_ALMOST_EMPTY == 1) begin : gae_ss
|
|
|
|
|
|
|
|
wire ecomp2;
|
|
|
|
wire going_aempty;
|
|
|
|
wire leaving_aempty;
|
|
|
|
wire ram_aempty_comb;
|
|
|
|
|
|
|
|
assign ecomp2 = (adj_wr_pntr_rd == (rd_pntr + 2'h2));
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH == C_RD_PNTR_WIDTH) begin : gae_wp_eq_rp
|
|
|
|
assign going_aempty = (ecomp2 & ~write_allow & read_allow);
|
|
|
|
assign leaving_aempty = (ecomp1 & write_allow & ~read_allow);
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH > C_RD_PNTR_WIDTH) begin : gae_wp_gt_rp
|
|
|
|
assign going_aempty = (ecomp2 & read_allow & (~(write_allow & &(wr_pntr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0]))));
|
|
|
|
assign leaving_aempty = (ecomp1 & ~read_allow & write_allow & &(wr_pntr[C_WR_PNTR_WIDTH-C_RD_PNTR_WIDTH-1 : 0]));
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
generate if (C_WR_PNTR_WIDTH < C_RD_PNTR_WIDTH) begin : gae_wp_lt_rp
|
|
|
|
assign going_aempty = (ecomp2 & ~write_allow & read_allow);
|
|
|
|
assign leaving_aempty =((ecomp2 | ecomp1 |ecomp0) & write_allow);
|
|
|
|
end endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
assign ram_aempty_comb = going_aempty | (~leaving_aempty & almost_empty_i);
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
if (rst_i)
|
|
|
|
almost_empty_i <= 1'b1;
|
|
|
|
else if (srst_rrst_busy)
|
|
|
|
almost_empty_i <= #`TCQ 1'b1;
|
|
|
|
else
|
|
|
|
almost_empty_i <= #`TCQ ram_aempty_comb;
|
|
|
|
end
|
|
|
|
// end endgenerate // gae_ss
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_FULL
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
localparam C_PF_ASSERT_VAL = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
C_PROG_FULL_THRESH_ASSERT_VAL - EXTRA_WORDS_PF_PARAM : // FWFT
|
|
|
|
C_PROG_FULL_THRESH_ASSERT_VAL; // STD
|
|
|
|
localparam C_PF_NEGATE_VAL = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
C_PROG_FULL_THRESH_NEGATE_VAL - EXTRA_WORDS_PF_PARAM: // FWFT
|
|
|
|
C_PROG_FULL_THRESH_NEGATE_VAL; // STD
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_FULL for single programmable threshold constant
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] temp = C_PF_ASSERT_VAL;
|
|
|
|
generate if (C_PROG_FULL_TYPE == 1) begin : single_pf_const
|
|
|
|
always @(posedge CLK or posedge RST_FULL_FF) begin
|
|
|
|
if (RST_FULL_FF && C_HAS_RST)
|
|
|
|
prog_full_i <= C_FULL_FLAGS_RST_VAL;
|
|
|
|
else begin
|
|
|
|
if (srst_wrst_busy)
|
|
|
|
prog_full_i <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (diff_pntr == C_PF_ASSERT_VAL && write_only_q)
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr == C_PF_ASSERT_VAL && read_only_q)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (~RST_FULL_GEN ) begin
|
|
|
|
if (diff_pntr>= C_PF_ASSERT_VAL )
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if ((diff_pntr) < C_PF_ASSERT_VAL )
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate // single_pf_const
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_FULL for multiple programmable threshold constants
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
generate if (C_PROG_FULL_TYPE == 2) begin : multiple_pf_const
|
|
|
|
always @(posedge CLK or posedge RST_FULL_FF) begin
|
|
|
|
//if (RST_FULL_FF)
|
|
|
|
if (RST_FULL_FF && C_HAS_RST)
|
|
|
|
prog_full_i <= C_FULL_FLAGS_RST_VAL;
|
|
|
|
else begin
|
|
|
|
if (srst_wrst_busy)
|
|
|
|
prog_full_i <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (diff_pntr == C_PF_ASSERT_VAL && write_only_q)
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr == C_PF_NEGATE_VAL && read_only_q)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (~RST_FULL_GEN ) begin
|
|
|
|
if (diff_pntr >= C_PF_ASSERT_VAL )
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr < C_PF_NEGATE_VAL)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate //multiple_pf_const
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_FULL for single programmable threshold input port
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] pf3_assert_val = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
PROG_FULL_THRESH - EXTRA_WORDS_PF: // FWFT
|
|
|
|
PROG_FULL_THRESH; // STD
|
|
|
|
generate if (C_PROG_FULL_TYPE == 3) begin : single_pf_input
|
|
|
|
|
|
|
|
always @(posedge CLK or posedge RST_FULL_FF) begin//0
|
|
|
|
//if (RST_FULL_FF)
|
|
|
|
if (RST_FULL_FF && C_HAS_RST)
|
|
|
|
prog_full_i <= C_FULL_FLAGS_RST_VAL;
|
|
|
|
else begin //1
|
|
|
|
if (srst_wrst_busy)
|
|
|
|
prog_full_i <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin//2
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (~almost_full_i) begin//3
|
|
|
|
if (diff_pntr > pf3_assert_val)
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr == pf3_assert_val) begin//4
|
|
|
|
if (read_only_q)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
end else//4
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
end else//3
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end //2
|
|
|
|
else begin//5
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (~full_i ) begin//6
|
|
|
|
if (diff_pntr >= pf3_assert_val )
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr < pf3_assert_val) begin//7
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
end//7
|
|
|
|
end//6
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end//5
|
|
|
|
end//1
|
|
|
|
end//0
|
|
|
|
end endgenerate //single_pf_input
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_FULL for multiple programmable threshold input ports
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] pf_assert_val = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
(PROG_FULL_THRESH_ASSERT -EXTRA_WORDS_PF) : // FWFT
|
|
|
|
PROG_FULL_THRESH_ASSERT; // STD
|
|
|
|
wire [C_WR_PNTR_WIDTH-1:0] pf_negate_val = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
(PROG_FULL_THRESH_NEGATE -EXTRA_WORDS_PF) : // FWFT
|
|
|
|
PROG_FULL_THRESH_NEGATE; // STD
|
|
|
|
|
|
|
|
generate if (C_PROG_FULL_TYPE == 4) begin : multiple_pf_inputs
|
|
|
|
always @(posedge CLK or posedge RST_FULL_FF) begin
|
|
|
|
if (RST_FULL_FF && C_HAS_RST)
|
|
|
|
prog_full_i <= C_FULL_FLAGS_RST_VAL;
|
|
|
|
else begin
|
|
|
|
if (srst_wrst_busy)
|
|
|
|
prog_full_i <= #`TCQ C_FULL_FLAGS_RST_VAL;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (~almost_full_i) begin
|
|
|
|
if (diff_pntr >= pf_assert_val)
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if ((diff_pntr == pf_negate_val && read_only_q) ||
|
|
|
|
diff_pntr < pf_negate_val)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (RST_FULL_GEN)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else if (~full_i ) begin
|
|
|
|
if (diff_pntr >= pf_assert_val )
|
|
|
|
prog_full_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr < pf_negate_val)
|
|
|
|
prog_full_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
prog_full_i <= #`TCQ prog_full_i;
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate //multiple_pf_inputs
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_EMPTY
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
localparam C_PE_ASSERT_VAL = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
C_PROG_EMPTY_THRESH_ASSERT_VAL - 2: // FWFT
|
|
|
|
C_PROG_EMPTY_THRESH_ASSERT_VAL; // STD
|
|
|
|
localparam C_PE_NEGATE_VAL = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
C_PROG_EMPTY_THRESH_NEGATE_VAL - 2: // FWFT
|
|
|
|
C_PROG_EMPTY_THRESH_NEGATE_VAL; // STD
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_EMPTY for single programmable threshold constant
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
generate if (C_PROG_EMPTY_TYPE == 1) begin : single_pe_const
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
//if (rst_i)
|
|
|
|
if (rst_i && C_HAS_RST)
|
|
|
|
prog_empty_i <= 1'b1;
|
|
|
|
else begin
|
|
|
|
if (srst_rrst_busy)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (diff_pntr_pe == C_PE_ASSERT_VAL && read_only_q)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe == C_PE_ASSERT_VAL && write_only_q)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (~rst_i ) begin
|
|
|
|
if (diff_pntr_pe <= C_PE_ASSERT_VAL)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe > C_PE_ASSERT_VAL)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate // single_pe_const
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_EMPTY for multiple programmable threshold constants
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
generate if (C_PROG_EMPTY_TYPE == 2) begin : multiple_pe_const
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
//if (rst_i)
|
|
|
|
if (rst_i && C_HAS_RST)
|
|
|
|
prog_empty_i <= 1'b1;
|
|
|
|
else begin
|
|
|
|
if (srst_rrst_busy)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (diff_pntr_pe == C_PE_ASSERT_VAL && read_only_q)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe == C_PE_NEGATE_VAL && write_only_q)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (~rst_i ) begin
|
|
|
|
if (diff_pntr_pe <= C_PE_ASSERT_VAL )
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe > C_PE_NEGATE_VAL)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end endgenerate //multiple_pe_const
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_EMPTY for single programmable threshold input port
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] pe3_assert_val = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
(PROG_EMPTY_THRESH -2) : // FWFT
|
|
|
|
PROG_EMPTY_THRESH; // STD
|
|
|
|
generate if (C_PROG_EMPTY_TYPE == 3) begin : single_pe_input
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
//if (rst_i)
|
|
|
|
if (rst_i && C_HAS_RST)
|
|
|
|
prog_empty_i <= 1'b1;
|
|
|
|
else begin
|
|
|
|
if (srst_rrst_busy)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (~almost_full_i) begin
|
|
|
|
if (diff_pntr_pe < pe3_assert_val)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe == pe3_assert_val) begin
|
|
|
|
if (write_only_q)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
end else
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
end else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (diff_pntr_pe <= pe3_assert_val )
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe > pe3_assert_val)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end endgenerate // single_pe_input
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Generate PROG_EMPTY for multiple programmable threshold input ports
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] pe4_assert_val = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
(PROG_EMPTY_THRESH_ASSERT - 2) : // FWFT
|
|
|
|
PROG_EMPTY_THRESH_ASSERT; // STD
|
|
|
|
wire [C_RD_PNTR_WIDTH-1:0] pe4_negate_val = (C_PRELOAD_LATENCY == 0) ?
|
|
|
|
(PROG_EMPTY_THRESH_NEGATE - 2) : // FWFT
|
|
|
|
PROG_EMPTY_THRESH_NEGATE; // STD
|
|
|
|
generate if (C_PROG_EMPTY_TYPE == 4) begin : multiple_pe_inputs
|
|
|
|
always @(posedge CLK or posedge rst_i) begin
|
|
|
|
//if (rst_i)
|
|
|
|
if (rst_i && C_HAS_RST)
|
|
|
|
prog_empty_i <= 1'b1;
|
|
|
|
else begin
|
|
|
|
if (srst_rrst_busy)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (IS_ASYMMETRY == 0) begin
|
|
|
|
if (~almost_full_i) begin
|
|
|
|
if (diff_pntr_pe <= pe4_assert_val)
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (((diff_pntr_pe == pe4_negate_val) && write_only_q) ||
|
|
|
|
(diff_pntr_pe > pe4_negate_val)) begin
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
end else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
if (diff_pntr_pe <= pe4_assert_val )
|
|
|
|
prog_empty_i <= #`TCQ 1'b1;
|
|
|
|
else if (diff_pntr_pe > pe4_negate_val)
|
|
|
|
prog_empty_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
prog_empty_i <= #`TCQ prog_empty_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end endgenerate // multiple_pe_inputs
|
|
|
|
|
|
|
|
endmodule // fifo_generator_v12_0_bhv_ver_ss
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* First-Word Fall-Through module (preload 0)
|
|
|
|
**************************************************************************/
|
|
|
|
module fifo_generator_v12_0_bhv_ver_preload0
|
|
|
|
#(
|
|
|
|
parameter C_DOUT_RST_VAL = "",
|
|
|
|
parameter C_DOUT_WIDTH = 8,
|
|
|
|
parameter C_HAS_RST = 0,
|
|
|
|
parameter C_ENABLE_RST_SYNC = 0,
|
|
|
|
parameter C_HAS_SRST = 0,
|
|
|
|
parameter C_USE_DOUT_RST = 0,
|
|
|
|
parameter C_USE_ECC = 0,
|
|
|
|
parameter C_USERVALID_LOW = 0,
|
|
|
|
parameter C_USERUNDERFLOW_LOW = 0,
|
|
|
|
parameter C_MEMORY_TYPE = 0,
|
|
|
|
parameter C_FIFO_TYPE = 0
|
|
|
|
)
|
|
|
|
(
|
|
|
|
//Inputs
|
|
|
|
input RD_CLK,
|
|
|
|
input RD_RST,
|
|
|
|
input SRST,
|
|
|
|
input WR_RST_BUSY,
|
|
|
|
input RD_RST_BUSY,
|
|
|
|
input RD_EN,
|
|
|
|
input FIFOEMPTY,
|
|
|
|
input [C_DOUT_WIDTH-1:0] FIFODATA,
|
|
|
|
input FIFOSBITERR,
|
|
|
|
input FIFODBITERR,
|
|
|
|
|
|
|
|
//Outputs
|
|
|
|
output reg [C_DOUT_WIDTH-1:0] USERDATA,
|
|
|
|
output USERVALID,
|
|
|
|
output USERUNDERFLOW,
|
|
|
|
output USEREMPTY,
|
|
|
|
output USERALMOSTEMPTY,
|
|
|
|
output RAMVALID,
|
|
|
|
output FIFORDEN,
|
|
|
|
output reg USERSBITERR,
|
|
|
|
output reg USERDBITERR,
|
|
|
|
output reg STAGE2_REG_EN,
|
|
|
|
output [1:0] VALID_STAGES
|
|
|
|
);
|
|
|
|
|
|
|
|
//Internal signals
|
|
|
|
wire preloadstage1;
|
|
|
|
wire preloadstage2;
|
|
|
|
reg ram_valid_i;
|
|
|
|
reg read_data_valid_i;
|
|
|
|
wire ram_regout_en;
|
|
|
|
wire ram_rd_en;
|
|
|
|
reg empty_i = 1'b1;
|
|
|
|
reg empty_q = 1'b1;
|
|
|
|
reg rd_en_q = 1'b0;
|
|
|
|
reg almost_empty_i = 1'b1;
|
|
|
|
reg almost_empty_q = 1'b1;
|
|
|
|
wire rd_rst_i;
|
|
|
|
wire srst_i;
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* FUNCTIONS
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* hexstr_conv
|
|
|
|
* Converts a string of type hex to a binary value (for C_DOUT_RST_VAL)
|
|
|
|
***********************************************************************/
|
|
|
|
function [C_DOUT_WIDTH-1:0] hexstr_conv;
|
|
|
|
input [(C_DOUT_WIDTH*8)-1:0] def_data;
|
|
|
|
|
|
|
|
integer index,i,j;
|
|
|
|
reg [3:0] bin;
|
|
|
|
|
|
|
|
begin
|
|
|
|
index = 0;
|
|
|
|
hexstr_conv = 'b0;
|
|
|
|
for( i=C_DOUT_WIDTH-1; i>=0; i=i-1 )
|
|
|
|
begin
|
|
|
|
case (def_data[7:0])
|
|
|
|
8'b00000000 :
|
|
|
|
begin
|
|
|
|
bin = 4'b0000;
|
|
|
|
i = -1;
|
|
|
|
end
|
|
|
|
8'b00110000 : bin = 4'b0000;
|
|
|
|
8'b00110001 : bin = 4'b0001;
|
|
|
|
8'b00110010 : bin = 4'b0010;
|
|
|
|
8'b00110011 : bin = 4'b0011;
|
|
|
|
8'b00110100 : bin = 4'b0100;
|
|
|
|
8'b00110101 : bin = 4'b0101;
|
|
|
|
8'b00110110 : bin = 4'b0110;
|
|
|
|
8'b00110111 : bin = 4'b0111;
|
|
|
|
8'b00111000 : bin = 4'b1000;
|
|
|
|
8'b00111001 : bin = 4'b1001;
|
|
|
|
8'b01000001 : bin = 4'b1010;
|
|
|
|
8'b01000010 : bin = 4'b1011;
|
|
|
|
8'b01000011 : bin = 4'b1100;
|
|
|
|
8'b01000100 : bin = 4'b1101;
|
|
|
|
8'b01000101 : bin = 4'b1110;
|
|
|
|
8'b01000110 : bin = 4'b1111;
|
|
|
|
8'b01100001 : bin = 4'b1010;
|
|
|
|
8'b01100010 : bin = 4'b1011;
|
|
|
|
8'b01100011 : bin = 4'b1100;
|
|
|
|
8'b01100100 : bin = 4'b1101;
|
|
|
|
8'b01100101 : bin = 4'b1110;
|
|
|
|
8'b01100110 : bin = 4'b1111;
|
|
|
|
default :
|
|
|
|
begin
|
|
|
|
bin = 4'bx;
|
|
|
|
end
|
|
|
|
endcase
|
|
|
|
for( j=0; j<4; j=j+1)
|
|
|
|
begin
|
|
|
|
if ((index*4)+j < C_DOUT_WIDTH)
|
|
|
|
begin
|
|
|
|
hexstr_conv[(index*4)+j] = bin[j];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
index = index + 1;
|
|
|
|
def_data = def_data >> 8;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
|
|
//*************************************************************************
|
|
|
|
// Set power-on states for regs
|
|
|
|
//*************************************************************************
|
|
|
|
initial begin
|
|
|
|
ram_valid_i = 1'b0;
|
|
|
|
read_data_valid_i = 1'b0;
|
|
|
|
USERDATA = hexstr_conv(C_DOUT_RST_VAL);
|
|
|
|
USERSBITERR = 1'b0;
|
|
|
|
USERDBITERR = 1'b0;
|
|
|
|
end //initial
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// connect up optional reset
|
|
|
|
//***************************************************************************
|
|
|
|
assign rd_rst_i = (C_HAS_RST == 1 || C_ENABLE_RST_SYNC == 0) ? RD_RST : 0;
|
|
|
|
assign srst_i = C_HAS_SRST ? SRST || WR_RST_BUSY || RD_RST_BUSY : 0;
|
|
|
|
|
|
|
|
localparam INVALID = 0;
|
|
|
|
localparam STAGE1_VALID = 2;
|
|
|
|
localparam STAGE2_VALID = 1;
|
|
|
|
localparam BOTH_STAGES_VALID = 3;
|
|
|
|
|
|
|
|
reg [1:0] curr_fwft_state = INVALID;
|
|
|
|
reg [1:0] next_fwft_state = INVALID;
|
|
|
|
|
|
|
|
generate if (C_FIFO_TYPE != 2) begin : gnll_fifo
|
|
|
|
|
|
|
|
always @* begin
|
|
|
|
case (curr_fwft_state)
|
|
|
|
INVALID: begin
|
|
|
|
if (~FIFOEMPTY)
|
|
|
|
next_fwft_state <= STAGE1_VALID;
|
|
|
|
else
|
|
|
|
next_fwft_state <= INVALID;
|
|
|
|
end
|
|
|
|
STAGE1_VALID: begin
|
|
|
|
if (FIFOEMPTY)
|
|
|
|
next_fwft_state <= STAGE2_VALID;
|
|
|
|
else
|
|
|
|
next_fwft_state <= BOTH_STAGES_VALID;
|
|
|
|
end
|
|
|
|
STAGE2_VALID: begin
|
|
|
|
if (FIFOEMPTY && RD_EN)
|
|
|
|
next_fwft_state <= INVALID;
|
|
|
|
else if (~FIFOEMPTY && RD_EN)
|
|
|
|
next_fwft_state <= STAGE1_VALID;
|
|
|
|
else if (~FIFOEMPTY && ~RD_EN)
|
|
|
|
next_fwft_state <= BOTH_STAGES_VALID;
|
|
|
|
else
|
|
|
|
next_fwft_state <= STAGE2_VALID;
|
|
|
|
end
|
|
|
|
BOTH_STAGES_VALID: begin
|
|
|
|
if (FIFOEMPTY && RD_EN)
|
|
|
|
next_fwft_state <= STAGE2_VALID;
|
|
|
|
else if (~FIFOEMPTY && RD_EN)
|
|
|
|
next_fwft_state <= BOTH_STAGES_VALID;
|
|
|
|
else
|
|
|
|
next_fwft_state <= BOTH_STAGES_VALID;
|
|
|
|
end
|
|
|
|
default: next_fwft_state <= INVALID;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge rd_rst_i or posedge RD_CLK) begin
|
|
|
|
if (rd_rst_i)
|
|
|
|
curr_fwft_state <= INVALID;
|
|
|
|
else if (srst_i)
|
|
|
|
curr_fwft_state <= #`TCQ INVALID;
|
|
|
|
else
|
|
|
|
curr_fwft_state <= #`TCQ next_fwft_state;
|
|
|
|
end
|
|
|
|
|
|
|
|
always @* begin
|
|
|
|
case (curr_fwft_state)
|
|
|
|
INVALID: STAGE2_REG_EN <= 1'b0;
|
|
|
|
STAGE1_VALID: STAGE2_REG_EN <= 1'b1;
|
|
|
|
STAGE2_VALID: STAGE2_REG_EN <= 1'b0;
|
|
|
|
BOTH_STAGES_VALID: STAGE2_REG_EN <= RD_EN;
|
|
|
|
default: STAGE2_REG_EN <= 1'b0;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
|
|
|
assign VALID_STAGES = curr_fwft_state;
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// preloadstage2 indicates that stage2 needs to be updated. This is true
|
|
|
|
// whenever read_data_valid is false, and RAM_valid is true.
|
|
|
|
//***************************************************************************
|
|
|
|
assign preloadstage2 = ram_valid_i & (~read_data_valid_i | RD_EN);
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// preloadstage1 indicates that stage1 needs to be updated. This is true
|
|
|
|
// whenever the RAM has data (RAM_EMPTY is false), and either RAM_Valid is
|
|
|
|
// false (indicating that Stage1 needs updating), or preloadstage2 is active
|
|
|
|
// (indicating that Stage2 is going to update, so Stage1, therefore, must
|
|
|
|
// also be updated to keep it valid.
|
|
|
|
//***************************************************************************
|
|
|
|
assign preloadstage1 = ((~ram_valid_i | preloadstage2) & ~FIFOEMPTY);
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Calculate RAM_REGOUT_EN
|
|
|
|
// The output registers are controlled by the ram_regout_en signal.
|
|
|
|
// These registers should be updated either when the output in Stage2 is
|
|
|
|
// invalid (preloadstage2), OR when the user is reading, in which case the
|
|
|
|
// Stage2 value will go invalid unless it is replenished.
|
|
|
|
//***************************************************************************
|
|
|
|
assign ram_regout_en = preloadstage2;
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Calculate RAM_RD_EN
|
|
|
|
// RAM_RD_EN will be asserted whenever the RAM needs to be read in order to
|
|
|
|
// update the value in Stage1.
|
|
|
|
// One case when this happens is when preloadstage1=true, which indicates
|
|
|
|
// that the data in Stage1 or Stage2 is invalid, and needs to automatically
|
|
|
|
// be updated.
|
|
|
|
// The other case is when the user is reading from the FIFO, which
|
|
|
|
// guarantees that Stage1 or Stage2 will be invalid on the next clock
|
|
|
|
// cycle, unless it is replinished by data from the memory. So, as long
|
|
|
|
// as the RAM has data in it, a read of the RAM should occur.
|
|
|
|
//***************************************************************************
|
|
|
|
assign ram_rd_en = (RD_EN & ~FIFOEMPTY) | preloadstage1;
|
|
|
|
end endgenerate // gnll_fifo
|
|
|
|
|
|
|
|
reg curr_state = 0;
|
|
|
|
reg next_state = 0;
|
|
|
|
reg leaving_empty_fwft = 0;
|
|
|
|
reg going_empty_fwft = 0;
|
|
|
|
reg empty_i_q = 0;
|
|
|
|
reg ram_rd_en_fwft = 0;
|
|
|
|
generate if (C_FIFO_TYPE == 2) begin : gll_fifo
|
|
|
|
always @* begin // FSM fo FWFT
|
|
|
|
case (curr_state)
|
|
|
|
1'b0: begin
|
|
|
|
if (~FIFOEMPTY)
|
|
|
|
next_state <= 1'b1;
|
|
|
|
else
|
|
|
|
next_state <= 1'b0;
|
|
|
|
end
|
|
|
|
1'b1: begin
|
|
|
|
if (FIFOEMPTY && RD_EN)
|
|
|
|
next_state <= 1'b0;
|
|
|
|
else
|
|
|
|
next_state <= 1'b1;
|
|
|
|
end
|
|
|
|
default: next_state <= 1'b0;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
empty_i <= 1'b1;
|
|
|
|
empty_i_q <= 1'b1;
|
|
|
|
curr_state <= 1'b0;
|
|
|
|
ram_valid_i <= 1'b0;
|
|
|
|
end else if (srst_i) begin
|
|
|
|
empty_i <= #`TCQ 1'b1;
|
|
|
|
empty_i_q <= #`TCQ 1'b1;
|
|
|
|
curr_state <= #`TCQ 1'b0;
|
|
|
|
ram_valid_i <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
empty_i <= #`TCQ going_empty_fwft | (~leaving_empty_fwft & empty_i);
|
|
|
|
empty_i_q <= #`TCQ FIFOEMPTY;
|
|
|
|
curr_state <= #`TCQ next_state;
|
|
|
|
ram_valid_i <= #`TCQ next_state;
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
|
|
|
|
wire fe_of_empty;
|
|
|
|
assign fe_of_empty = empty_i_q & ~FIFOEMPTY;
|
|
|
|
|
|
|
|
always @* begin // Finding leaving empty
|
|
|
|
case (curr_state)
|
|
|
|
1'b0: leaving_empty_fwft <= fe_of_empty;
|
|
|
|
1'b1: leaving_empty_fwft <= 1'b1;
|
|
|
|
default: leaving_empty_fwft <= 1'b0;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
|
|
|
always @* begin // Finding going empty
|
|
|
|
case (curr_state)
|
|
|
|
1'b1: going_empty_fwft <= FIFOEMPTY & RD_EN;
|
|
|
|
default: going_empty_fwft <= 1'b0;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
|
|
|
always @* begin // Generating FWFT rd_en
|
|
|
|
case (curr_state)
|
|
|
|
1'b0: ram_rd_en_fwft <= ~FIFOEMPTY;
|
|
|
|
1'b1: ram_rd_en_fwft <= ~FIFOEMPTY & RD_EN;
|
|
|
|
default: ram_rd_en_fwft <= 1'b0;
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
|
|
|
assign ram_regout_en = ram_rd_en_fwft;
|
|
|
|
assign ram_rd_en = ram_rd_en_fwft;
|
|
|
|
end endgenerate // gll_fifo
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Calculate RAMVALID_P0_OUT
|
|
|
|
// RAMVALID_P0_OUT indicates that the data in Stage1 is valid.
|
|
|
|
//
|
|
|
|
// If the RAM is being read from on this clock cycle (ram_rd_en=1), then
|
|
|
|
// RAMVALID_P0_OUT is certainly going to be true.
|
|
|
|
// If the RAM is not being read from, but the output registers are being
|
|
|
|
// updated to fill Stage2 (ram_regout_en=1), then Stage1 will be emptying,
|
|
|
|
// therefore causing RAMVALID_P0_OUT to be false.
|
|
|
|
// Otherwise, RAMVALID_P0_OUT will remain unchanged.
|
|
|
|
//***************************************************************************
|
|
|
|
// PROCESS regout_valid
|
|
|
|
generate if (C_FIFO_TYPE < 2) begin : gnll_fifo_ram_valid
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
// asynchronous reset (active high)
|
|
|
|
ram_valid_i <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
if (srst_i) begin
|
|
|
|
// synchronous reset (active high)
|
|
|
|
ram_valid_i <= #`TCQ 1'b0;
|
|
|
|
end else begin
|
|
|
|
if (ram_rd_en == 1'b1) begin
|
|
|
|
ram_valid_i <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if (ram_regout_en == 1'b1)
|
|
|
|
ram_valid_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
ram_valid_i <= #`TCQ ram_valid_i;
|
|
|
|
end
|
|
|
|
end //srst_i
|
|
|
|
end //rd_rst_i
|
|
|
|
end //always
|
|
|
|
end endgenerate // gnll_fifo_ram_valid
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Calculate READ_DATA_VALID
|
|
|
|
// READ_DATA_VALID indicates whether the value in Stage2 is valid or not.
|
|
|
|
// Stage2 has valid data whenever Stage1 had valid data and
|
|
|
|
// ram_regout_en_i=1, such that the data in Stage1 is propogated
|
|
|
|
// into Stage2.
|
|
|
|
//***************************************************************************
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i)
|
|
|
|
read_data_valid_i <= #`TCQ 1'b0;
|
|
|
|
else if (srst_i)
|
|
|
|
read_data_valid_i <= #`TCQ 1'b0;
|
|
|
|
else
|
|
|
|
read_data_valid_i <= #`TCQ ram_valid_i | (read_data_valid_i & ~RD_EN);
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
|
|
// Calculate EMPTY
|
|
|
|
// Defined as the inverse of READ_DATA_VALID
|
|
|
|
//
|
|
|
|
// Description:
|
|
|
|
//
|
|
|
|
// If read_data_valid_i indicates that the output is not valid,
|
|
|
|
// and there is no valid data on the output of the ram to preload it
|
|
|
|
// with, then we will report empty.
|
|
|
|
//
|
|
|
|
// If there is no valid data on the output of the ram and we are
|
|
|
|
// reading, then the FIFO will go empty.
|
|
|
|
//
|
|
|
|
//**************************************************************************
|
|
|
|
generate if (C_FIFO_TYPE < 2) begin : gnll_fifo_empty
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i) begin
|
|
|
|
if (rd_rst_i) begin
|
|
|
|
// asynchronous reset (active high)
|
|
|
|
empty_i <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if (srst_i) begin
|
|
|
|
// synchronous reset (active high)
|
|
|
|
empty_i <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
// rising clock edge
|
|
|
|
empty_i <= #`TCQ (~ram_valid_i & ~read_data_valid_i) | (~ram_valid_i & RD_EN);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
end endgenerate // gnll_fifo_empty
|
|
|
|
|
|
|
|
// Register RD_EN from user to calculate USERUNDERFLOW.
|
|
|
|
// Register empty_i to calculate USERUNDERFLOW.
|
|
|
|
always @ (posedge RD_CLK) begin
|
|
|
|
rd_en_q <= #`TCQ RD_EN;
|
|
|
|
empty_q <= #`TCQ empty_i;
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
// Calculate user_almost_empty
|
|
|
|
// user_almost_empty is defined such that, unless more words are written
|
|
|
|
// to the FIFO, the next read will cause the FIFO to go EMPTY.
|
|
|
|
//
|
|
|
|
// In most cases, whenever the output registers are updated (due to a user
|
|
|
|
// read or a preload condition), then user_almost_empty will update to
|
|
|
|
// whatever RAM_EMPTY is.
|
|
|
|
//
|
|
|
|
// The exception is when the output is valid, the user is not reading, and
|
|
|
|
// Stage1 is not empty. In this condition, Stage1 will be preloaded from the
|
|
|
|
// memory, so we need to make sure user_almost_empty deasserts properly under
|
|
|
|
// this condition.
|
|
|
|
//***************************************************************************
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i)
|
|
|
|
begin
|
|
|
|
if (rd_rst_i) begin // asynchronous reset (active high)
|
|
|
|
almost_empty_i <= #`TCQ 1'b1;
|
|
|
|
almost_empty_q <= #`TCQ 1'b1;
|
|
|
|
end else begin // rising clock edge
|
|
|
|
if (srst_i) begin // synchronous reset (active high)
|
|
|
|
almost_empty_i <= #`TCQ 1'b1;
|
|
|
|
almost_empty_q <= #`TCQ 1'b1;
|
|
|
|
end else begin
|
|
|
|
if ((ram_regout_en) | (~FIFOEMPTY & read_data_valid_i & ~RD_EN)) begin
|
|
|
|
almost_empty_i <= #`TCQ FIFOEMPTY;
|
|
|
|
end
|
|
|
|
almost_empty_q <= #`TCQ empty_i;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
assign USEREMPTY = empty_i;
|
|
|
|
assign USERALMOSTEMPTY = almost_empty_i;
|
|
|
|
assign FIFORDEN = ram_rd_en;
|
|
|
|
assign RAMVALID = ram_valid_i;
|
|
|
|
assign USERVALID = C_USERVALID_LOW ? ~read_data_valid_i : read_data_valid_i;
|
|
|
|
assign USERUNDERFLOW = C_USERUNDERFLOW_LOW ? ~(empty_q & rd_en_q) : empty_q & rd_en_q;
|
|
|
|
|
|
|
|
// BRAM resets synchronously
|
|
|
|
always @ (posedge RD_CLK)
|
|
|
|
begin
|
|
|
|
if (rd_rst_i || srst_i) begin
|
|
|
|
if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE < 2)
|
|
|
|
USERDATA <= #`TCQ hexstr_conv(C_DOUT_RST_VAL);
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
|
|
|
|
|
|
|
|
always @ (posedge RD_CLK or posedge rd_rst_i)
|
|
|
|
begin
|
|
|
|
if (rd_rst_i) begin //asynchronous reset (active high)
|
|
|
|
if (C_USE_ECC == 0) begin // Reset S/DBITERR only if ECC is OFF
|
|
|
|
USERSBITERR <= #`TCQ 0;
|
|
|
|
USERDBITERR <= #`TCQ 0;
|
|
|
|
end
|
|
|
|
// DRAM resets asynchronously
|
|
|
|
if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE == 2) //asynchronous reset (active high)
|
|
|
|
USERDATA <= #`TCQ hexstr_conv(C_DOUT_RST_VAL);
|
|
|
|
end else begin // rising clock edge
|
|
|
|
if (srst_i) begin
|
|
|
|
if (C_USE_ECC == 0) begin // Reset S/DBITERR only if ECC is OFF
|
|
|
|
USERSBITERR <= #`TCQ 0;
|
|
|
|
USERDBITERR <= #`TCQ 0;
|
|
|
|
end
|
|
|
|
if (C_USE_DOUT_RST == 1 && C_MEMORY_TYPE == 2)
|
|
|
|
USERDATA <= #`TCQ hexstr_conv(C_DOUT_RST_VAL);
|
|
|
|
end else begin
|
|
|
|
if (ram_regout_en) begin
|
|
|
|
USERDATA <= #`TCQ FIFODATA;
|
|
|
|
USERSBITERR <= #`TCQ FIFOSBITERR;
|
|
|
|
USERDBITERR <= #`TCQ FIFODBITERR;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end //always
|
|
|
|
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Register Slice
|
|
|
|
// Register one AXI channel on forward and/or reverse signal path
|
|
|
|
//
|
|
|
|
// Verilog-standard: Verilog 2001
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Structure:
|
|
|
|
// reg_slice
|
|
|
|
//
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
module fifo_generator_v12_0_axic_reg_slice #
|
|
|
|
(
|
|
|
|
parameter C_FAMILY = "virtex7",
|
|
|
|
parameter C_DATA_WIDTH = 32,
|
|
|
|
parameter C_REG_CONFIG = 32'h00000000
|
|
|
|
)
|
|
|
|
(
|
|
|
|
// System Signals
|
|
|
|
input wire ACLK,
|
|
|
|
input wire ARESET,
|
|
|
|
|
|
|
|
// Slave side
|
|
|
|
input wire [C_DATA_WIDTH-1:0] S_PAYLOAD_DATA,
|
|
|
|
input wire S_VALID,
|
|
|
|
output wire S_READY,
|
|
|
|
|
|
|
|
// Master side
|
|
|
|
output wire [C_DATA_WIDTH-1:0] M_PAYLOAD_DATA,
|
|
|
|
output wire M_VALID,
|
|
|
|
input wire M_READY
|
|
|
|
);
|
|
|
|
|
|
|
|
generate
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Both FWD and REV mode
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
if (C_REG_CONFIG == 32'h00000000)
|
|
|
|
begin
|
|
|
|
reg [1:0] state;
|
|
|
|
localparam [1:0]
|
|
|
|
ZERO = 2'b10,
|
|
|
|
ONE = 2'b11,
|
|
|
|
TWO = 2'b01;
|
|
|
|
|
|
|
|
reg [C_DATA_WIDTH-1:0] storage_data1 = 0;
|
|
|
|
reg [C_DATA_WIDTH-1:0] storage_data2 = 0;
|
|
|
|
reg load_s1;
|
|
|
|
wire load_s2;
|
|
|
|
wire load_s1_from_s2;
|
|
|
|
reg s_ready_i; //local signal of output
|
|
|
|
wire m_valid_i; //local signal of output
|
|
|
|
|
|
|
|
// assign local signal to its output signal
|
|
|
|
assign S_READY = s_ready_i;
|
|
|
|
assign M_VALID = m_valid_i;
|
|
|
|
|
|
|
|
reg areset_d1; // Reset delay register
|
|
|
|
always @(posedge ACLK) begin
|
|
|
|
areset_d1 <= ARESET;
|
|
|
|
end
|
|
|
|
|
|
|
|
// Load storage1 with either slave side data or from storage2
|
|
|
|
always @(posedge ACLK)
|
|
|
|
begin
|
|
|
|
if (load_s1)
|
|
|
|
if (load_s1_from_s2)
|
|
|
|
storage_data1 <= storage_data2;
|
|
|
|
else
|
|
|
|
storage_data1 <= S_PAYLOAD_DATA;
|
|
|
|
end
|
|
|
|
|
|
|
|
// Load storage2 with slave side data
|
|
|
|
always @(posedge ACLK)
|
|
|
|
begin
|
|
|
|
if (load_s2)
|
|
|
|
storage_data2 <= S_PAYLOAD_DATA;
|
|
|
|
end
|
|
|
|
|
|
|
|
assign M_PAYLOAD_DATA = storage_data1;
|
|
|
|
|
|
|
|
// Always load s2 on a valid transaction even if it's unnecessary
|
|
|
|
assign load_s2 = S_VALID & s_ready_i;
|
|
|
|
|
|
|
|
// Loading s1
|
|
|
|
always @ *
|
|
|
|
begin
|
|
|
|
if ( ((state == ZERO) && (S_VALID == 1)) || // Load when empty on slave transaction
|
|
|
|
// Load when ONE if we both have read and write at the same time
|
|
|
|
((state == ONE) && (S_VALID == 1) && (M_READY == 1)) ||
|
|
|
|
// Load when TWO and we have a transaction on Master side
|
|
|
|
((state == TWO) && (M_READY == 1)))
|
|
|
|
load_s1 = 1'b1;
|
|
|
|
else
|
|
|
|
load_s1 = 1'b0;
|
|
|
|
end // always @ *
|
|
|
|
|
|
|
|
assign load_s1_from_s2 = (state == TWO);
|
|
|
|
|
|
|
|
// State Machine for handling output signals
|
|
|
|
always @(posedge ACLK) begin
|
|
|
|
if (ARESET) begin
|
|
|
|
s_ready_i <= 1'b0;
|
|
|
|
state <= ZERO;
|
|
|
|
end else if (areset_d1) begin
|
|
|
|
s_ready_i <= 1'b1;
|
|
|
|
end else begin
|
|
|
|
case (state)
|
|
|
|
// No transaction stored locally
|
|
|
|
ZERO: if (S_VALID) state <= ONE; // Got one so move to ONE
|
|
|
|
|
|
|
|
// One transaction stored locally
|
|
|
|
ONE: begin
|
|
|
|
if (M_READY & ~S_VALID) state <= ZERO; // Read out one so move to ZERO
|
|
|
|
if (~M_READY & S_VALID) begin
|
|
|
|
state <= TWO; // Got another one so move to TWO
|
|
|
|
s_ready_i <= 1'b0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
// TWO transaction stored locally
|
|
|
|
TWO: if (M_READY) begin
|
|
|
|
state <= ONE; // Read out one so move to ONE
|
|
|
|
s_ready_i <= 1'b1;
|
|
|
|
end
|
|
|
|
endcase // case (state)
|
|
|
|
end
|
|
|
|
end // always @ (posedge ACLK)
|
|
|
|
|
|
|
|
assign m_valid_i = state[0];
|
|
|
|
|
|
|
|
end // if (C_REG_CONFIG == 1)
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// 1-stage pipeline register with bubble cycle, both FWD and REV pipelining
|
|
|
|
// Operates same as 1-deep FIFO
|
|
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
else if (C_REG_CONFIG == 32'h00000001)
|
|
|
|
begin
|
|
|
|
reg [C_DATA_WIDTH-1:0] storage_data1 = 0;
|
|
|
|
reg s_ready_i; //local signal of output
|
|
|
|
reg m_valid_i; //local signal of output
|
|
|
|
|
|
|
|
// assign local signal to its output signal
|
|
|
|
assign S_READY = s_ready_i;
|
|
|
|
assign M_VALID = m_valid_i;
|
|
|
|
|
|
|
|
reg areset_d1; // Reset delay register
|
|
|
|
always @(posedge ACLK) begin
|
|
|
|
areset_d1 <= ARESET;
|
|
|
|
end
|
|
|
|
|
|
|
|
// Load storage1 with slave side data
|
|
|
|
always @(posedge ACLK)
|
|
|
|
begin
|
|
|
|
if (ARESET) begin
|
|
|
|
s_ready_i <= 1'b0;
|
|
|
|
m_valid_i <= 1'b0;
|
|
|
|
end else if (areset_d1) begin
|
|
|
|
s_ready_i <= 1'b1;
|
|
|
|
end else if (m_valid_i & M_READY) begin
|
|
|
|
s_ready_i <= 1'b1;
|
|
|
|
m_valid_i <= 1'b0;
|
|
|
|
end else if (S_VALID & s_ready_i) begin
|
|
|
|
s_ready_i <= 1'b0;
|
|
|
|
m_valid_i <= 1'b1;
|
|
|
|
end
|
|
|
|
if (~m_valid_i) begin
|
|
|
|
storage_data1 <= S_PAYLOAD_DATA;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
assign M_PAYLOAD_DATA = storage_data1;
|
|
|
|
end // if (C_REG_CONFIG == 7)
|
|
|
|
|
|
|
|
else begin : default_case
|
|
|
|
// Passthrough
|
|
|
|
assign M_PAYLOAD_DATA = S_PAYLOAD_DATA;
|
|
|
|
assign M_VALID = S_VALID;
|
|
|
|
assign S_READY = M_READY;
|
|
|
|
end
|
|
|
|
|
|
|
|
endgenerate
|
|
|
|
endmodule // reg_slice
|