mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
9135 lines
468 KiB
Systemverilog
9135 lines
468 KiB
Systemverilog
//------------------------------------------------------------------------------
|
|
// (c) Copyright 2015 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.
|
|
//------------------------------------------------------------------------------
|
|
|
|
// ***************************
|
|
// * DO NOT MODIFY THIS FILE *
|
|
// ***************************
|
|
|
|
`timescale 1ps/1ps
|
|
`default_nettype none
|
|
|
|
(* XPM_MODULE = "TRUE", KEEP_HIERARCHY = "SOFT" *)
|
|
module xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_TYPE = 2,
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter integer MEMORY_PRIMITIVE = 0,
|
|
parameter integer CLOCKING_MODE = 0,
|
|
parameter integer ECC_MODE = 0,
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer WAKEUP_TIME = 0,
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter integer VERSION = 0,
|
|
parameter integer USE_EMBEDDED_CONSTRAINT = 0,
|
|
parameter integer CASCADE_HEIGHT = 0,
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer WRITE_PROTECT = 1,
|
|
// Port A module parameters
|
|
parameter integer WRITE_DATA_WIDTH_A = 32,
|
|
parameter integer READ_DATA_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer BYTE_WRITE_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter integer WRITE_MODE_A = 2,
|
|
parameter RST_MODE_A = "SYNC",
|
|
|
|
// Port B module parameters
|
|
parameter integer WRITE_DATA_WIDTH_B = WRITE_DATA_WIDTH_A,
|
|
parameter integer READ_DATA_WIDTH_B = WRITE_DATA_WIDTH_B,
|
|
parameter integer BYTE_WRITE_WIDTH_B = WRITE_DATA_WIDTH_B,
|
|
parameter integer ADDR_WIDTH_B = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B),
|
|
parameter READ_RESET_VALUE_B = "0",
|
|
parameter integer READ_LATENCY_B = READ_LATENCY_A,
|
|
parameter integer WRITE_MODE_B = WRITE_MODE_A,
|
|
parameter RST_MODE_B = "SYNC"
|
|
) (
|
|
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire [WRITE_DATA_WIDTH_A-1:0] dina,
|
|
input wire injectsbiterra,
|
|
input wire injectdbiterra,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
output wire sbiterra,
|
|
output wire dbiterra,
|
|
|
|
// Port B module ports
|
|
input wire clkb,
|
|
input wire rstb,
|
|
input wire enb,
|
|
input wire regceb,
|
|
input wire [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web,
|
|
input wire [ADDR_WIDTH_B-1:0] addrb,
|
|
input wire [WRITE_DATA_WIDTH_B-1:0] dinb,
|
|
input wire injectsbiterrb,
|
|
input wire injectdbiterrb,
|
|
output wire [READ_DATA_WIDTH_B-1:0] doutb,
|
|
output wire sbiterrb,
|
|
output wire dbiterrb
|
|
);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Macro definitions
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Define macros for parameter value size comparisons
|
|
`define MAX(a,b) {(a) > (b) ? (a) : (b)}
|
|
`define MIN(a,b) {(a) < (b) ? (a) : (b)}
|
|
|
|
// Define macros to simplify variable vector slicing
|
|
`define ONE_ROW_OF_DIN row*P_MIN_WIDTH_DATA +: P_MIN_WIDTH_DATA
|
|
`define ONE_COL_OF_DINA col*P_WIDTH_COL_WRITE_A +: P_WIDTH_COL_WRITE_A
|
|
`define ONE_COL_OF_DINB col*P_WIDTH_COL_WRITE_B +: P_WIDTH_COL_WRITE_B
|
|
`define ONE_ROW_COL_OF_DINA (row*P_MIN_WIDTH_DATA+col*P_WIDTH_COL_WRITE_A) +: P_WIDTH_COL_WRITE_A
|
|
`define ONE_ROW_COL_OF_DINB (row*P_MIN_WIDTH_DATA+col*P_WIDTH_COL_WRITE_B) +: P_WIDTH_COL_WRITE_B
|
|
|
|
// Define macros to meaningfully designate the memory type and primitive
|
|
`define MEM_TYPE_RAM_SP (MEMORY_TYPE == 0)
|
|
`define MEM_TYPE_RAM_SDP (MEMORY_TYPE == 1)
|
|
`define MEM_TYPE_RAM_TDP (MEMORY_TYPE == 2)
|
|
`define MEM_TYPE_ROM_SP (MEMORY_TYPE == 3)
|
|
`define MEM_TYPE_ROM_DP (MEMORY_TYPE == 4)
|
|
`define MEM_TYPE_RAM (`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_SDP || `MEM_TYPE_RAM_TDP)
|
|
`define MEM_TYPE_ROM (`MEM_TYPE_ROM_SP || `MEM_TYPE_ROM_DP)
|
|
`define MEM_PRIM_AUTO (MEMORY_PRIMITIVE == 0)
|
|
`define MEM_PRIM_DISTRIBUTED (MEMORY_PRIMITIVE == 1)
|
|
`define MEM_PRIM_BLOCK (MEMORY_PRIMITIVE == 2)
|
|
`define MEM_PRIM_ULTRA (MEMORY_PRIMITIVE == 3)
|
|
`define MEM_PRIM_MIXED (MEMORY_PRIMITIVE == 4)
|
|
`define WRITE_PROT_ENABLED (WRITE_PROTECT == 1)
|
|
`define WRITE_PROT_DISABLED (WRITE_PROTECT == 0)
|
|
|
|
// Define macros to meaningfully designate port A characteristics
|
|
`define MEM_PORTA_WRITE (`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_SDP || `MEM_TYPE_RAM_TDP)
|
|
`define MEM_PORTA_READ (`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_TDP || `MEM_TYPE_ROM)
|
|
`define MEM_PORTA_WF (WRITE_MODE_A == 0)
|
|
`define MEM_PORTA_RF (WRITE_MODE_A == 1)
|
|
`define MEM_PORTA_NC (WRITE_MODE_A == 2)
|
|
`define MEM_PORTA_WR_NARROW (P_NUM_ROWS_WRITE_A == 1)
|
|
`define MEM_PORTA_WR_WIDE (P_NUM_ROWS_WRITE_A > 1)
|
|
`define MEM_PORTA_WR_WORD (P_ENABLE_BYTE_WRITE_A == 0)
|
|
`define MEM_PORTA_WR_BYTE (P_ENABLE_BYTE_WRITE_A == 1)
|
|
`define MEM_PORTA_RD_NARROW (P_NUM_ROWS_READ_A == 1)
|
|
`define MEM_PORTA_RD_WIDE (P_NUM_ROWS_READ_A > 1)
|
|
`define MEM_PORTA_RD_COMB (READ_LATENCY_A == 0)
|
|
`define MEM_PORTA_RD_REG (READ_LATENCY_A == 1)
|
|
`define MEM_PORTA_RD_PIPE (READ_LATENCY_A > 1)
|
|
|
|
// Define macros to meaningfully designate port B characteristics
|
|
`define MEM_PORTB_WRITE (`MEM_TYPE_RAM_TDP && !`MEM_PRIM_DISTRIBUTED)
|
|
`define MEM_PORTB_READ (`MEM_TYPE_RAM_SDP || `MEM_TYPE_RAM_TDP || `MEM_TYPE_ROM_DP)
|
|
`define MEM_PORTB_WF (WRITE_MODE_B == 0)
|
|
`define MEM_PORTB_RF (WRITE_MODE_B == 1)
|
|
`define MEM_PORTB_NC (WRITE_MODE_B == 2)
|
|
`define MEM_PORTB_WR_NARROW (P_NUM_ROWS_WRITE_B == 1)
|
|
`define MEM_PORTB_WR_WIDE (P_NUM_ROWS_WRITE_B > 1)
|
|
`define MEM_PORTB_WR_WORD (P_ENABLE_BYTE_WRITE_B == 0)
|
|
`define MEM_PORTB_WR_BYTE (P_ENABLE_BYTE_WRITE_B == 1)
|
|
`define MEM_PORTB_RD_NARROW (P_NUM_ROWS_READ_B == 1)
|
|
`define MEM_PORTB_RD_WIDE (P_NUM_ROWS_READ_B > 1)
|
|
`define MEM_PORTB_RD_COMB (READ_LATENCY_B == 0)
|
|
`define MEM_PORTB_RD_REG (READ_LATENCY_B == 1)
|
|
`define MEM_PORTB_RD_PIPE (READ_LATENCY_B > 1)
|
|
`define MEM_PORTB_URAM_LAT (READ_LATENCY_B > 2)
|
|
|
|
// Define macros to meaningfully designate other code characteristics
|
|
`define COMMON_CLOCK (CLOCKING_MODE == 0)
|
|
`define INDEPENDENT_CLOCKS (CLOCKING_MODE == 1)
|
|
`define NO_MEMORY_INIT ((MEMORY_INIT_FILE == "none" || MEMORY_INIT_FILE == "NONE" || MEMORY_INIT_FILE == "None") && (MEMORY_INIT_PARAM == "" || MEMORY_INIT_PARAM == "0"))
|
|
`define REPORT_MESSAGES (MESSAGE_CONTROL == 1)
|
|
`define NO_MESSAGES (MESSAGE_CONTROL == 0)
|
|
`define EN_INIT_MESSAGE (USE_MEM_INIT == 1)
|
|
`define MEM_PORTA_ASYM_BWE ((WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A) && (WRITE_DATA_WIDTH_A > BYTE_WRITE_WIDTH_A) && (`MEM_PORTA_WRITE && `MEM_PORTA_READ))
|
|
`define MEM_PORTB_ASYM_BWE ((WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B) && (WRITE_DATA_WIDTH_B > BYTE_WRITE_WIDTH_B) && (`MEM_PORTB_WRITE && `MEM_PORTB_READ))
|
|
`define MEM_ACRSS_PORT_ASYM_BWE ((((WRITE_DATA_WIDTH_A != WRITE_DATA_WIDTH_B) && `MEM_PORTA_WRITE && `MEM_PORTB_WRITE) || ((WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) && `MEM_PORTA_WRITE && `MEM_PORTB_READ)) && ((WRITE_DATA_WIDTH_A > BYTE_WRITE_WIDTH_A) || (WRITE_DATA_WIDTH_B > BYTE_WRITE_WIDTH_B)))
|
|
`define MEM_PORT_ASYM_BWE (`MEM_PORTA_ASYM_BWE || `MEM_PORTB_ASYM_BWE || `MEM_ACRSS_PORT_ASYM_BWE)
|
|
|
|
`define MEM_PORTA_ASYM ((WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A) && (`MEM_PORTA_WRITE && `MEM_PORTA_READ))
|
|
`define MEM_PORTB_ASYM ((WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B) && (`MEM_PORTB_WRITE && `MEM_PORTB_READ))
|
|
`define MEM_ACRSS_PORT_ASYM ((((WRITE_DATA_WIDTH_A != WRITE_DATA_WIDTH_B) && `MEM_PORTA_WRITE && `MEM_PORTB_WRITE) || ((WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) && `MEM_PORTA_WRITE && `MEM_PORTB_READ)) )
|
|
`define MEM_PORT_ASYM (`MEM_PORTA_ASYM || `MEM_PORTB_ASYM || `MEM_ACRSS_PORT_ASYM)
|
|
|
|
`define ROM_MEMORY_OPT (MEMORY_OPTIMIZATION == "true")
|
|
|
|
// Define macros to meaningfully designate power saving features
|
|
`define SLEEP_MODE (WAKEUP_TIME == 2)
|
|
|
|
// Define macros to meaningfully designate collision safety
|
|
`define IS_COLLISION_A_SAFE ((`MEM_TYPE_RAM_SDP || `MEM_TYPE_RAM_TDP) && (`MEM_PORTA_RF && `COMMON_CLOCK))
|
|
`define IS_COLLISION_B_SAFE (`MEM_TYPE_RAM_TDP && (`MEM_PORTB_RF && `COMMON_CLOCK))
|
|
`define IS_COLLISION_SAFE ((`MEM_TYPE_RAM_TDP && `IS_COLLISION_A_SAFE && `IS_COLLISION_B_SAFE) || (`MEM_TYPE_RAM_SDP && `IS_COLLISION_A_SAFE))
|
|
|
|
// Define Macros related to ECC
|
|
`define NO_ECC (ECC_MODE == 0)
|
|
`define ENC_ONLY (ECC_MODE == 1)
|
|
`define DEC_ONLY (ECC_MODE == 2)
|
|
`define BOTH_ENC_DEC (ECC_MODE == 3)
|
|
|
|
// Macro that prevents the templates to synthesis for the configurations
|
|
// that does not have the synthesis supported coding styles e.g black box
|
|
// approach for asymmetry with byte write enable
|
|
`define DISABLE_SYNTH_TEMPL (`MEM_PORT_ASYM_BWE)
|
|
|
|
// Auto sleep mode related parameters
|
|
`define MEM_AUTO_SLP_EN (`MEM_PRIM_ULTRA && (AUTO_SLEEP_TIME != 0))
|
|
|
|
//Asynchronous Reset for dout
|
|
`define ASYNC_RESET_A (RST_MODE_A == "ASYNC")
|
|
`define ASYNC_RESET_B (RST_MODE_B == "ASYNC")
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Local parameter definitions
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Define local parameters for memory declaration pragmas
|
|
localparam P_MEMORY_PRIMITIVE = `MEM_PRIM_DISTRIBUTED ? "distributed" :
|
|
(`MEM_PRIM_BLOCK ? "block" :
|
|
(`MEM_PRIM_ULTRA ? "ultra" :
|
|
(`MEM_PRIM_MIXED ? "mixed" : "auto")));
|
|
|
|
// Define local parameters for memory array sizing
|
|
localparam integer P_MIN_WIDTH_DATA_A = `MEM_TYPE_RAM_SDP ? WRITE_DATA_WIDTH_A :
|
|
(`MEM_TYPE_ROM ? READ_DATA_WIDTH_A :
|
|
`MIN(WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A));
|
|
localparam integer P_MIN_WIDTH_DATA_B = `MEM_TYPE_RAM_SDP || `MEM_TYPE_ROM_DP ? READ_DATA_WIDTH_B :
|
|
(`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM_SP ? P_MIN_WIDTH_DATA_A :
|
|
`MIN(WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_B));
|
|
localparam integer P_MIN_WIDTH_DATA = `MIN(P_MIN_WIDTH_DATA_A, P_MIN_WIDTH_DATA_B);
|
|
localparam integer P_MIN_WIDTH_DATA_ECC = `NO_ECC ? P_MIN_WIDTH_DATA : `BOTH_ENC_DEC ? P_MIN_WIDTH_DATA+((WRITE_DATA_WIDTH_A/64)*8) : (`DEC_ONLY && `MEM_PORTA_WRITE) ? WRITE_DATA_WIDTH_A : (`DEC_ONLY && `MEM_PORTA_READ) ? P_MIN_WIDTH_DATA+((READ_DATA_WIDTH_A/64)*8) : (`ENC_ONLY && `MEM_PORTA_READ) ? READ_DATA_WIDTH_A : READ_DATA_WIDTH_B;
|
|
localparam integer P_MAX_DEPTH_DATA = `BOTH_ENC_DEC ? MEMORY_SIZE/P_MIN_WIDTH_DATA : MEMORY_SIZE/P_MIN_WIDTH_DATA_ECC;
|
|
localparam P_ECC_MODE = `BOTH_ENC_DEC ? "both_encode_and_decode" : `DEC_ONLY ? "decode_only" : `ENC_ONLY ? "encode_only" : "no_ecc";
|
|
localparam P_MEMORY_OPT = (!(`ROM_MEMORY_OPT) && `MEM_TYPE_ROM) ? "no" : "yes";
|
|
|
|
// Define local parameters for write and read data sizing
|
|
// When ECC is enabled, Byte writes and Asymmetry are not allowed
|
|
localparam integer P_WIDTH_COL_WRITE_A = `MIN(BYTE_WRITE_WIDTH_A, P_MIN_WIDTH_DATA);
|
|
localparam integer P_WIDTH_COL_WRITE_B = `MIN(BYTE_WRITE_WIDTH_B, P_MIN_WIDTH_DATA);
|
|
localparam integer P_NUM_COLS_WRITE_A = !(`NO_ECC) ? 1 : P_MIN_WIDTH_DATA/P_WIDTH_COL_WRITE_A;
|
|
localparam integer P_NUM_COLS_WRITE_B = !(`NO_ECC) ? 1 : P_MIN_WIDTH_DATA/P_WIDTH_COL_WRITE_B;
|
|
localparam integer P_NUM_ROWS_WRITE_A = !(`NO_ECC) ? 1 : WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA;
|
|
localparam integer P_NUM_ROWS_WRITE_B = !(`NO_ECC) ? 1 : WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA;
|
|
localparam integer P_NUM_ROWS_READ_A = !(`NO_ECC) ? 1 : READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA;
|
|
localparam integer P_NUM_ROWS_READ_B = !(`NO_ECC) ? 1 : READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA;
|
|
localparam integer P_WIDTH_ADDR_WRITE_A = (`ENC_ONLY && `MEM_PORTB_READ) ? $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B) : (`ENC_ONLY && `MEM_PORTA_READ) ? $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A) : $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A);
|
|
localparam integer P_WIDTH_ADDR_WRITE_B = `DEC_ONLY ? $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A) : $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B);
|
|
localparam integer P_WIDTH_ADDR_READ_A = (`ENC_ONLY && `MEM_PORTB_READ) ? $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B) : (`ENC_ONLY && `MEM_PORTA_READ) ? $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A) : $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A);
|
|
localparam integer P_WIDTH_ADDR_READ_B = `DEC_ONLY ? $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A) : $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B);
|
|
localparam integer P_WIDTH_ADDR_LSB_WRITE_A = $clog2(P_NUM_ROWS_WRITE_A);
|
|
localparam integer P_WIDTH_ADDR_LSB_WRITE_B = $clog2(P_NUM_ROWS_WRITE_B);
|
|
localparam integer P_WIDTH_ADDR_LSB_READ_A = $clog2(P_NUM_ROWS_READ_A);
|
|
localparam integer P_WIDTH_ADDR_LSB_READ_B = $clog2(P_NUM_ROWS_READ_B);
|
|
|
|
// Define local parameters for other code characteristics
|
|
localparam integer P_ENABLE_BYTE_WRITE_A = !(`NO_ECC) ? 0 : WRITE_DATA_WIDTH_A > BYTE_WRITE_WIDTH_A ? 1 : 0;
|
|
localparam integer P_ENABLE_BYTE_WRITE_B = !(`NO_ECC) ? 0 : WRITE_DATA_WIDTH_B > BYTE_WRITE_WIDTH_B ? 1 : 0;
|
|
|
|
// Define local parameters for SDP write mode
|
|
localparam P_SDP_WRITE_MODE = (`MEM_PRIM_BLOCK && `MEM_PORTB_NC && `MEM_TYPE_RAM_SDP) ? "no" : "yes";
|
|
|
|
// Define local parameters for reset value conversions
|
|
localparam integer rsta_loop_iter = (READ_DATA_WIDTH_A < 4) ? 4 : (READ_DATA_WIDTH_A%4) ? (READ_DATA_WIDTH_A + (4-READ_DATA_WIDTH_A%4)) : READ_DATA_WIDTH_A;
|
|
localparam integer rstb_loop_iter = (READ_DATA_WIDTH_B < 4) ? 4 : (READ_DATA_WIDTH_B%4) ? (READ_DATA_WIDTH_B + (4-READ_DATA_WIDTH_B%4)) : READ_DATA_WIDTH_B;
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Configuration DRCs
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
initial begin : config_drc
|
|
reg drc_err_flag;
|
|
drc_err_flag = 0;
|
|
#1;
|
|
|
|
// notification and restrictions
|
|
if (1)
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_A (%0d) for this configuration which uses port A write and read operations, but this release of XPM_MEMORY requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 1, 2, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this configuration which uses port B write and read operations, but this release of XPM_MEMORY requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 1, 3, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_TYPE_RAM_SDP && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this simple dual port RAM configuration with memory primitive set to distributed RAM, but this release of XPM_MEMORY requires symmetric write and read data widths when memory primitive set to distributed RAM. %m", "XPM_MEMORY", 1, 13, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_TYPE_RAM_TDP && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this true dual port RAM configuration with memory primitive set to distributed RAM, but this release of XPM_MEMORY requires symmetric write and read data widths when memory primitive set to distributed RAM. %m", "XPM_MEMORY", 1, 14, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_TYPE_ROM_DP && READ_DATA_WIDTH_A != READ_DATA_WIDTH_B) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this dual port ROM configuration , but this release of XPM_MEMORY requires symmetric read data widths when memory type is set to dual port ROM. %m", "XPM_MEMORY", 1, 15, READ_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (CASCADE_HEIGHT > 64 && `MEM_PRIM_ULTRA) begin
|
|
$error("[%s %0d-%0d] XPM_MEMORY does not support CASCADE_HEIGHT (%0d) greater than 64 for Ultra RAM configurations. %m", "XPM_MEMORY", 1, 16, CASCADE_HEIGHT);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (CASCADE_HEIGHT > 16 && `MEM_PRIM_BLOCK) begin
|
|
$error("[%s %0d-%0d] XPM_MEMORY does not support CASCADE_HEIGHT (%0d) greater than 16 for Block RAM configurations. %m", "XPM_MEMORY", 1, 16, CASCADE_HEIGHT);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!`NO_ECC && !`NO_MEMORY_INIT) begin
|
|
$error("[%s %0d-%0d] Memory initialization is specified for this configuration with ECC (%0d) enabled, but this release of XPM_MEMORY does not support ECC with memory Initialization . %m", "XPM_MEMORY", 1, 18, ECC_MODE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!`NO_ECC && `MEM_TYPE_ROM) begin
|
|
$error("[%s %0d-%0d] Memory type is set to ROM for this configuration with ECC (%0d) enabled, but this release of XPM_MEMORY does not support ECC with memory Initialization . %m", "XPM_MEMORY", 1, 19, ECC_MODE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORT_ASYM_BWE && !`NO_MEMORY_INIT) begin
|
|
$error("[%s %0d-%0d] Asymmetry with Byte Write Enable is specified with Memory initialization, but this release of XPM_MEMORY does not support Memory initialization with Asymmetric Byte Write Enable. %m", "XPM_MEMORY", 1, 21);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORT_ASYM_BWE && `MEM_PRIM_ULTRA && (`SLEEP_MODE || `MEM_AUTO_SLP_EN)) begin
|
|
$error("[%s %0d-%0d] The configuration has UltraRAM,Asymmetric ports with Byte Write Enable with Sleep Mode or Auto Sleep Mode enabled, but this release of XPM_MEMORY does not support the specified configuration. %m", "XPM_MEMORY", 1, 20);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if ((`MEM_PRIM_AUTO || `MEM_PRIM_BLOCK || `MEM_PRIM_ULTRA) && USE_EMBEDDED_CONSTRAINT) begin
|
|
$error("[%s %0d-%0d] USE_EMBEDDED_CONSTRAINT is set to (%0d), but Embedded Constraint is supported only for distributed RAM with separate write and read clocks. %m", "XPM_MEMORY", 1, 22, USE_EMBEDDED_CONSTRAINT);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if ((`MEM_PORT_ASYM_BWE && `MEM_TYPE_RAM_SDP && `MEM_PORTA_WR_BYTE && (WRITE_DATA_WIDTH_B%BYTE_WRITE_WIDTH_A != 0)) || (`MEM_PORT_ASYM_BWE && `MEM_TYPE_RAM_TDP && `MEM_PORTA_WR_BYTE && (BYTE_WRITE_WIDTH_B%BYTE_WRITE_WIDTH_A != 0)) || (`MEM_PORT_ASYM_BWE && `MEM_TYPE_RAM_TDP && `MEM_PORTB_WR_BYTE && (BYTE_WRITE_WIDTH_A%BYTE_WRITE_WIDTH_B != 0))) begin
|
|
$error("[%s %0d-%0d] Asymmetry with Byte Write Enable is specified, but the write data width and byte write width of port A and port B are not compatible. If byte write is enabled on port A, then data width of port B must be divisible by Port A byte write width, and vice versa. %m", "XPM_MEMORY", 1, 23);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_AUTO_SLP_EN && `MEM_TYPE_RAM_SDP && `MEM_PORTB_WF && (READ_LATENCY_B < 4) ) begin
|
|
$error("[%s %0d-%0d] This configuration has Simple Dual Port RAM, UltraRAM, Write First Mode with Non-Zero Auto Sleep value and READ_LATENCY_B (%0d) value less than 4. But in this release of XPM_MEMORY does not support READ_LATENCY_B value less than 4 for the specified configuration. %m", "XPM_MEMORY", 1, 24, READ_LATENCY_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_AUTO_SLP_EN && `MEM_TYPE_RAM_SDP && `MEM_PORTB_RF && (READ_LATENCY_B < 3)) begin
|
|
$error("[%s %0d-%0d] This configuration has Simple Dual Port RAM, UltraRAM, Read First Mode with Non-Zero Auto Sleep value and READ_LATENCY_B (%0d) value less than 3. But in this release of XPM_MEMORY does not support READ_LATENCY_B value less than 3 for the specified configuration. %m", "XPM_MEMORY", 1, 25, READ_LATENCY_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_AUTO_SLP_EN && `MEM_TYPE_RAM_SP && (READ_LATENCY_A < 3)) begin
|
|
$error("[%s %0d-%0d] This configuration has Single Port RAM, UltraRAM with Non-Zero Auto Sleep value and READ_LATENCY_A (%0d) value less than 3. But in this release of XPM_MEMORY does not support READ_LATENCY_A value less than 3 for the specified configuration. %m", "XPM_MEMORY", 1, 26, READ_LATENCY_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_AUTO_SLP_EN && `MEM_TYPE_RAM_TDP && (READ_LATENCY_A < 3)) begin
|
|
$error("[%s %0d-%0d] This configuration has True Dual Port RAM, UltraRAM with Non-Zero Auto Sleep value and READ_LATENCY_A (%0d) value less than 3. But in this release of XPM_MEMORY does not support READ_LATENCY_A value less than 3 for the specified configuration. %m", "XPM_MEMORY", 1, 27, READ_LATENCY_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_AUTO_SLP_EN && `MEM_TYPE_RAM_TDP && (READ_LATENCY_B < 3)) begin
|
|
$error("[%s %0d-%0d] This configuration has True Dual Port RAM, UltraRAM with Non-Zero Auto Sleep value and READ_LATENCY_B (%0d) value less than 3. But in this release of XPM_MEMORY does not support READ_LATENCY_B value less than 3 for the specified configuration. %m", "XPM_MEMORY", 1, 28, READ_LATENCY_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if ((WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) && `MEM_TYPE_RAM_SDP && `MEM_PORTB_WF) begin
|
|
$error("[%s %0d-%0d] This configuration has Simple Dual Port RAM, Port-B Write First Mode with WRITE_DATA_WIDTH_A (%0d) not equal to READ_DATA_WIDTH_B (%0d). But in this release of XPM_MEMORY does not support the specified configuration. %m", "XPM_MEMORY", 1, 29, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
|
|
// Range checks
|
|
if (!(MEMORY_TYPE == 0 || MEMORY_TYPE == 1 || MEMORY_TYPE == 2 || MEMORY_TYPE == 3 || MEMORY_TYPE == 4)) begin
|
|
$error("[%s %0d-%0d] MEMORY_TYPE (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 1, MEMORY_TYPE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(MEMORY_SIZE > 0)) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 2, MEMORY_SIZE);
|
|
drc_err_flag = 1;
|
|
end
|
|
//if ((MEMORY_SIZE > 150994944 )) begin
|
|
// $error("[%s %0d-%0d] MEMORY_SIZE (%0d) value exceeds the maximum supported size. %m", "XPM_MEMORY", 10, 11, MEMORY_SIZE);
|
|
// drc_err_flag = 1;
|
|
//end
|
|
if (!(MEMORY_PRIMITIVE == 0 || MEMORY_PRIMITIVE == 1 || MEMORY_PRIMITIVE == 2 || MEMORY_PRIMITIVE == 3 || MEMORY_PRIMITIVE == 4)) begin
|
|
$error("[%s %0d-%0d] MEMORY_PRIMITIVE (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 3, MEMORY_PRIMITIVE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(CLOCKING_MODE == 0 || CLOCKING_MODE == 1)) begin
|
|
$error("[%s %0d-%0d] CLOCKING_MODE (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 4, CLOCKING_MODE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(ECC_MODE == 0 || ECC_MODE == 1 || ECC_MODE == 2 || ECC_MODE == 3)) begin
|
|
$error("[%s %0d-%0d] ECC_MODE (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 5, ECC_MODE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(WAKEUP_TIME == 0 || WAKEUP_TIME == 2)) begin
|
|
$error("[%s %0d-%0d] WAKEUP_TIME (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 7, WAKEUP_TIME);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(MESSAGE_CONTROL == 0 || MESSAGE_CONTROL == 1)) begin
|
|
$error("[%s %0d-%0d] MESSAGE_CONTROL (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 8, MESSAGE_CONTROL);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(VERSION == 0)) begin
|
|
$error("[%s %0d-%0d] VERSION (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 9, VERSION);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(AUTO_SLEEP_TIME == 0 || (AUTO_SLEEP_TIME >=3 && AUTO_SLEEP_TIME < 16))) begin
|
|
$error("[%s %0d-%0d] AUTO_SLEEP_TIME (%0d) value is outside of legal range. %m", "XPM_MEMORY", 10, 10, AUTO_SLEEP_TIME);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(WRITE_DATA_WIDTH_A > 0)) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) value is outside of legal range. %m", "XPM_MEMORY", 15, 1, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(READ_DATA_WIDTH_A > 0)) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) value is outside of legal range. %m", "XPM_MEMORY", 15, 2, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(BYTE_WRITE_WIDTH_A == 8 || BYTE_WRITE_WIDTH_A == 9 || BYTE_WRITE_WIDTH_A == WRITE_DATA_WIDTH_A)) begin
|
|
$error("[%s %0d-%0d] BYTE_WRITE_WIDTH_A (%0d) value is outside of legal range. %m", "XPM_MEMORY", 15, 3, BYTE_WRITE_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(ADDR_WIDTH_A > 0)) begin
|
|
$error("[%s %0d-%0d] ADDR_WIDTH_A (%0d) value is outside of legal range. %m", "XPM_MEMORY", 15, 4, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(READ_LATENCY_A >= 0)) begin
|
|
$error("[%s %0d-%0d] READ_LATENCY_A (%0d) value is outside of legal range. %m", "XPM_MEMORY", 15, 6, READ_LATENCY_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(WRITE_MODE_A == 0 || WRITE_MODE_A == 1 || WRITE_MODE_A == 2)) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_A (%0d) value is outside of legal range. %m", "XPM_MEMORY", 15, 7, WRITE_MODE_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(WRITE_DATA_WIDTH_B > 0)) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) value is outside of legal range. %m", "XPM_MEMORY", 16, 1, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(READ_DATA_WIDTH_B > 0)) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_B (%0d) value is outside of legal range. %m", "XPM_MEMORY", 16, 2, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(BYTE_WRITE_WIDTH_B == 8 || BYTE_WRITE_WIDTH_B == 9 || BYTE_WRITE_WIDTH_B == WRITE_DATA_WIDTH_B)) begin
|
|
$error("[%s %0d-%0d] BYTE_WRITE_WIDTH_B (%0d) value is outside of legal range. %m", "XPM_MEMORY", 16, 3, BYTE_WRITE_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(ADDR_WIDTH_B > 0)) begin
|
|
$error("[%s %0d-%0d] ADDR_WIDTH_B (%0d) value is outside of legal range. %m", "XPM_MEMORY", 16, 4, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(READ_LATENCY_B >= 0)) begin
|
|
$error("[%s %0d-%0d] READ_LATENCY_B (%0d) value is outside of legal range. %m", "XPM_MEMORY", 16, 6, READ_LATENCY_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (!(WRITE_MODE_B == 0 || WRITE_MODE_B == 1 || WRITE_MODE_B == 2)) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) value is outside of legal range. %m", "XPM_MEMORY", 16, 7, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// Infos
|
|
if (`MEM_PRIM_AUTO)
|
|
$info("[%s %0d-%0d] MEMORY_PRIMITIVE (%0d) instructs Vivado Synthesis to choose the memory primitive type. Depending on their values, other XPM_MEMORY parameters may preclude the choice of certain memory primitive types. Review XPM_MEMORY documentation and parameter values to understand any limitations, or set MEMORY_PRIMITIVE to a different value. %m", "XPM_MEMORY", 20, 1, MEMORY_PRIMITIVE);
|
|
if (`NO_MEMORY_INIT && !`MEM_PRIM_ULTRA && `EN_INIT_MESSAGE)
|
|
$info("[%s %0d-%0d] MEMORY_INIT_FILE (%0s), MEMORY_INIT_PARAM together specify no memory initialization. Initial memory contents will be all 0's. %m", "XPM_MEMORY", 20, 2, MEMORY_INIT_FILE,MEMORY_INIT_PARAM);
|
|
if (`COMMON_CLOCK && `MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP)
|
|
$info("[%s %0d-%0d] XPM_MEMORY behaviorally models the port operation ordering of true dual port UltraRAM configurations by slightly delaying the common clock for port B operations only. Refer to UltraRAM documentation for details. %m", "XPM_MEMORY", 20, 3);
|
|
if (AUTO_SLEEP_TIME != 0 && `MEM_PRIM_ULTRA) begin
|
|
$info("[%s %0d-%0d] Non-zero AUTO_SLEEP_TIME (%0d) is specifed for this configuration, An input pipeline having the number of register stages equal to AUTO_SLEEP_TIME will be introduced on all the input control/data signals path except for the port-enables(en[a|b]) and reset(rst[a|b]). %m", "XPM_MEMORY", 20, 4, AUTO_SLEEP_TIME);
|
|
end
|
|
|
|
// Warnings
|
|
if (`MEM_TYPE_ROM && `NO_MEMORY_INIT)
|
|
$warning("[%s %0d-%0d] MEMORY_INIT_FILE (%0s) specifies no memory initialization file for this ROM configuration, which will result in an empty memory that may be optimized away. %m", "XPM_MEMORY", 30, 1, MEMORY_INIT_FILE);
|
|
if (`MEM_TYPE_ROM && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A)
|
|
$warning("[%s %0d-%0d] Non-default WRITE_DATA_WIDTH_A (%0d) value ignored for ROM configurations because write operations are not used. %m", "XPM_MEMORY", 30, 2, WRITE_DATA_WIDTH_A);
|
|
if (`MEM_TYPE_RAM_SDP && READ_DATA_WIDTH_A != WRITE_DATA_WIDTH_A)
|
|
$warning("[%s %0d-%0d] Non-default READ_DATA_WIDTH_A (%0d) value ignored for simple dual port RAM configurations because port A read operations are not used. %m", "XPM_MEMORY", 30, 3, READ_DATA_WIDTH_A);
|
|
if (`MEM_TYPE_ROM && BYTE_WRITE_WIDTH_A != WRITE_DATA_WIDTH_A)
|
|
$warning("[%s %0d-%0d] Non-default BYTE_WRITE_WIDTH_A (%0d) value ignored for ROM configurations because write operations are not used. %m", "XPM_MEMORY", 30, 4, BYTE_WRITE_WIDTH_A);
|
|
if (`MEM_TYPE_RAM_SDP && READ_RESET_VALUE_A != "0")
|
|
$warning("[%s %0d-%0d] Non-default READ_RESET_VALUE_A value ignored for simple dual port RAM configurations because port A read operations are not used. %m", "XPM_MEMORY", 30, 5);
|
|
if (`MEM_TYPE_RAM_SDP && READ_LATENCY_A != 2)
|
|
$warning("[%s %0d-%0d] Non-default READ_LATENCY_A (%0d) value ignored for simple dual port RAM configurations because port A read operations are not used. %m", "XPM_MEMORY", 30, 6, READ_LATENCY_A);
|
|
if (`MEM_TYPE_RAM_SP && WRITE_DATA_WIDTH_B != WRITE_DATA_WIDTH_A)
|
|
$warning("[%s %0d-%0d] Non-default WRITE_DATA_WIDTH_B (%0d) value ignored for single port RAM configurations because port B write operations are not used. %m", "XPM_MEMORY", 30, 7, WRITE_DATA_WIDTH_B);
|
|
if ((`MEM_TYPE_RAM_SDP || (`MEM_TYPE_RAM_TDP && `MEM_PRIM_DISTRIBUTED) || `MEM_TYPE_ROM) && WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B)
|
|
$warning("[%s %0d-%0d] Non-default WRITE_DATA_WIDTH_B (%0d) value ignored for simple dual port RAM, dual port distributed RAM, or ROM configurations because port B write operations are not used. %m", "XPM_MEMORY", 30, 8, WRITE_DATA_WIDTH_B);
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM_SP) && READ_DATA_WIDTH_B != READ_DATA_WIDTH_A)
|
|
$warning("[%s %0d-%0d] Non-default READ_DATA_WIDTH_B (%0d) value ignored for single port RAM or single port ROM configurations because port B is not used. %m", "XPM_MEMORY", 30, 9, READ_DATA_WIDTH_B);
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_SDP || (`MEM_TYPE_RAM_TDP && `MEM_PRIM_DISTRIBUTED) || `MEM_TYPE_ROM) && BYTE_WRITE_WIDTH_B != WRITE_DATA_WIDTH_B)
|
|
$warning("[%s %0d-%0d] Non-default BYTE_WRITE_WIDTH_B (%0d) value ignored for single port RAM, simple dual port RAM, dual port distributed RAM, or ROM configurations because port B write operations are not used. %m", "XPM_MEMORY", 30, 10, BYTE_WRITE_WIDTH_B);
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM_SP) && ADDR_WIDTH_B != $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B))
|
|
$warning("[%s %0d-%0d] Non-default ADDR_WIDTH_B (%0d) value ignored for single port RAM or single port ROM configurations because port B is not used. %m", "XPM_MEMORY", 30, 11, ADDR_WIDTH_B);
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM_SP) && READ_RESET_VALUE_B != "0")
|
|
$warning("[%s %0d-%0d] Non-default READ_RESET_VALUE_B value ignored for single port RAM or single port ROM configurations because port B is not used. %m", "XPM_MEMORY", 30, 12);
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM_SP) && READ_LATENCY_B != READ_LATENCY_A)
|
|
$warning("[%s %0d-%0d] Non-default READ_LATENCY_B (%0d) value ignored for single port RAM or single port ROM configurations because port B is not used. %m", "XPM_MEMORY", 30, 13, READ_LATENCY_B);
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM) && WRITE_MODE_B != WRITE_MODE_A)
|
|
$warning("[%s %0d-%0d] Non-default WRITE_MODE_B (%0d) value ignored for single port RAM or ROM configurations because port B write operations are not used. %m", "XPM_MEMORY", 30, 14, WRITE_MODE_B);
|
|
if (`MEM_TYPE_RAM_TDP && `MEM_PRIM_DISTRIBUTED)
|
|
$warning("[%s %0d-%0d] MEMORY_TYPE (%0d) and MEMORY_PRIMITIVE (%0d) together specify a true dual port distributed RAM, which will be mapped to a dual port RAM structure using port A and B read interfaces but a single port A write interface, leaving the port B write interface unused. %m", "XPM_MEMORY", 30, 15, MEMORY_TYPE, MEMORY_PRIMITIVE);
|
|
if (`MEM_PORTA_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A) < ADDR_WIDTH_A)
|
|
$warning("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the addressable range exceeds the memory size for this configuration which uses port A write operations. %m", "XPM_MEMORY", 30, 16, MEMORY_SIZE, WRITE_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
if (`MEM_PORTA_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A) < ADDR_WIDTH_A)
|
|
$warning("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the addressable range exceeds the memory size for this configuration which uses port A read operations. %m", "XPM_MEMORY", 30, 17, MEMORY_SIZE, READ_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
if (`MEM_PORTB_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B) < ADDR_WIDTH_B)
|
|
$warning("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the addressable range exceeds the memory size for this configuration which uses port B write operations. %m", "XPM_MEMORY", 30, 18, MEMORY_SIZE, WRITE_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
if (`MEM_PORTB_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B) < ADDR_WIDTH_B)
|
|
$warning("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the addressable range exceeds the memory size for this configuration which uses port B read operations. %m", "XPM_MEMORY", 30, 19, MEMORY_SIZE, READ_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A)
|
|
$warning("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_A (%0d) for this distributed RAM configuration configuration which uses port A write and read operations, resulting in inefficient use of memory resources. %m", "XPM_MEMORY", 30, 20, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A);
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_READ && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B)
|
|
$warning("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this distributed RAM configuration configuration which uses port A write and port B read operations, resulting in inefficient use of memory resources. %m", "XPM_MEMORY", 30, 21, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
if (`MEM_PORTA_READ && `MEM_PORTB_READ && `MEM_PRIM_DISTRIBUTED && READ_DATA_WIDTH_A != READ_DATA_WIDTH_B)
|
|
$warning("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this distributed memory configuration which uses port A and port B read operations, resulting in inefficient use of memory resources. %m", "XPM_MEMORY", 30, 22, READ_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
if (`MEM_PORTA_READ && `MEM_PORTA_RD_COMB && READ_RESET_VALUE_A != "0")
|
|
$warning("[%s %0d-%0d] Non-default READ_RESET_VALUE_A value ignored for this configuration which uses port A read operations, because READ_LATENCY_A (%0d) specifies a combinatorial read output. %m", "XPM_MEMORY", 30, 23, READ_LATENCY_A);
|
|
if (`MEM_PORTB_READ && `MEM_PORTB_RD_COMB && READ_RESET_VALUE_B != "0")
|
|
$warning("[%s %0d-%0d] Non-default READ_RESET_VALUE_B value ignored for this configuration which uses port B read operations, because READ_LATENCY_B (%0d) specifies a combinatorial read output. %m", "XPM_MEMORY", 30, 24, READ_LATENCY_B);
|
|
if (`REPORT_MESSAGES && (`MEM_TYPE_RAM_SDP || `MEM_TYPE_RAM_TDP) && !(`MEM_PRIM_DISTRIBUTED || `MEM_PRIM_ULTRA))
|
|
$warning("[%s %0d-%0d] MESSAGE_CONTROL (%0d) specifies simulation message reporting, but any potential collisions reported for this configuration should be further investigated in netlist timing simulations for improved accuracy. %m", "XPM_MEMORY", 30, 25, MESSAGE_CONTROL);
|
|
if (WRITE_DATA_WIDTH_A > 4608 || READ_DATA_WIDTH_A > 4608)
|
|
$warning("[%s %0d-%0d] This configuration has WRITE_DATA_WIDTH_A of (%0d) and READ_DATA_WIDTH_A of (%0d), but in this release of XPM_MEMORY, the configurations having write/read data widths greater than 4608 are not completely verified. %m", "XPM_MEMORY", 30, 26, WRITE_DATA_WIDTH_A,READ_DATA_WIDTH_A);
|
|
if (WRITE_DATA_WIDTH_B > 4608 || READ_DATA_WIDTH_B > 4608)
|
|
$warning("[%s %0d-%0d] This configuration has WRITE_DATA_WIDTH_B of (%0d) and READ_DATA_WIDTH_B (%0d), but in this release of XPM_MEMORY, the configurations having write/read data widths greater than 4608 are not completely verified. %m", "XPM_MEMORY", 30, 27 , WRITE_DATA_WIDTH_B,READ_DATA_WIDTH_B);
|
|
if ( `MEM_TYPE_RAM_TDP && (BYTE_WRITE_WIDTH_A == 8 || BYTE_WRITE_WIDTH_A == 9) && (READ_DATA_WIDTH_B == BYTE_WRITE_WIDTH_B && WRITE_DATA_WIDTH_B == BYTE_WRITE_WIDTH_B) && (READ_DATA_WIDTH_B % BYTE_WRITE_WIDTH_A != 0 || WRITE_DATA_WIDTH_B % BYTE_WRITE_WIDTH_A != 0))
|
|
$warning("[%s %0d-%0d] This configuration has byte wide writes on port-A and port-B does not have byte wide writes, but in this release of XPM_MEMORY, the configurations having byte wide writes on one port and other port not having byte wide writes is not completely verified. %m", "XPM_MEMORY", 30, 28);
|
|
if ( `MEM_TYPE_RAM_TDP && (BYTE_WRITE_WIDTH_B == 8 || BYTE_WRITE_WIDTH_B == 9) && (READ_DATA_WIDTH_A == BYTE_WRITE_WIDTH_A && WRITE_DATA_WIDTH_A == BYTE_WRITE_WIDTH_A) && (READ_DATA_WIDTH_A % BYTE_WRITE_WIDTH_B != 0 || WRITE_DATA_WIDTH_A % BYTE_WRITE_WIDTH_B != 0))
|
|
$warning("[%s %0d-%0d] This configuration has byte wide writes on port-B and port-A does not have byte wide writes, but in this release of XPM_MEMORY, the configurations having byte wide writes on one port and other port not having byte wide writes is not completely verified. %m", "XPM_MEMORY", 30, 29);
|
|
if (AUTO_SLEEP_TIME != 0 && `MEM_PORTA_READ && READ_LATENCY_A == 2)
|
|
$warning("[%s %0d-%0d] The configuration specified is having non-zero Auto Sleep latency value with READ_LATENCY_A parameter value set to 2; There could be simulation mismatches between behavioral and post-synthesis simulations, please run netlist simulations for improved accuracy. %m", "XPM_MEMORY", 30, 30);
|
|
if (AUTO_SLEEP_TIME != 0 && `MEM_PORTB_READ && READ_LATENCY_B == 2)
|
|
$warning("[%s %0d-%0d] The configuration specified is having non-zero Auto Sleep latency value with READ_LATENCY_B parameter value set to 2; There could be simulation mismatches between behavioral and post-synthesis simulations, please run netlist simulations for improved accuracy. %m", "XPM_MEMORY", 30, 31);
|
|
|
|
// Errors
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_ROM_SP) && `INDEPENDENT_CLOCKS) begin
|
|
$error("[%s %0d-%0d] CLOCKING_MODE (%0d) specifies independent clocks, but single port RAM or single port ROM configurations require a common clock. %m", "XPM_MEMORY", 40, 2, CLOCKING_MODE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PRIM_ULTRA && `INDEPENDENT_CLOCKS) begin
|
|
$error("[%s %0d-%0d] CLOCKING_MODE (%0d) specifies independent clocks, but UltraRAM configurations require a common clock. %m", "XPM_MEMORY", 40, 3, CLOCKING_MODE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && (`MEM_PRIM_BLOCK || `MEM_PRIM_ULTRA) && `MEM_PORTA_RD_COMB) begin
|
|
$error("[%s %0d-%0d] READ_LATENCY_A (%0d) specifies a combinatorial read output for this configuration which uses port A read operations, but at least one register stage is required for block memory or UltraRAM configurations. %m", "XPM_MEMORY", 40, 5, READ_LATENCY_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && (`MEM_PRIM_BLOCK || `MEM_PRIM_ULTRA) && `MEM_PORTB_RD_COMB) begin
|
|
$error("[%s %0d-%0d] READ_LATENCY_B (%0d) specifies a combinatorial read output for this configuration which uses port B read operations, but at least one register stage is required for block memory or UltraRAM configurations. %m", "XPM_MEMORY", 40, 6, READ_LATENCY_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_SDP && `MEM_PRIM_ULTRA && !`MEM_PORTB_RF && !`MEM_PORTB_WF) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) specifies no-change mode, but simple dual port RAM configurations targeting UltraRAM can only mimic read-first mode or write-first mode behaviour for port B. Please change WRITE_MODE_B to either read-first mode or write-first mode. %m", "XPM_MEMORY", 40, 8, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_SDP && `MEM_PRIM_ULTRA && `MEM_PORTB_WF && !`MEM_PORTB_URAM_LAT) begin
|
|
$error("[%s %0d-%0d] READ_LATENCY_B (%0d) specifies fewer than 3 stages, but simple dual port RAM configurations targeting UltraRAM and using write-first mode for port B must use a read latency of at least 3 for port B. %m", "XPM_MEMORY", 40, 9, READ_LATENCY_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_ROM && !`MEM_PORTA_RF) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_A (%0d) specifies write-first mode or no-change mode, but ROM configurations must use read-first mode for port A. %m", "XPM_MEMORY", 40, 10, WRITE_MODE_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_ROM_DP && !`MEM_PORTB_RF) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) specifies write-first mode or no-change mode, but dual port ROM configurations must use read-first mode for port B. %m", "XPM_MEMORY", 40, 11, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if ((`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_TDP) && `MEM_PRIM_DISTRIBUTED && !`MEM_PORTA_RF) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_A (%0d) specifies write-first mode or no-change mode, but single port and dual port distributed RAM configurations must use read-first mode for port A. %m", "XPM_MEMORY", 40, 12, WRITE_MODE_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_TDP && `MEM_PRIM_DISTRIBUTED && !`MEM_PORTB_RF) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) specifies write-first mode or no-change mode, but dual port distributed RAM configurations must use read-first mode for port B. %m", "XPM_MEMORY", 40, 13, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_TDP && `MEM_PRIM_ULTRA && !`MEM_PORTA_NC) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_A (%0d) specifies read-first mode or write-first mode, but true dual port UltraRAM configurations must use no-change mode for port A. %m", "XPM_MEMORY", 40, 14, WRITE_MODE_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_TDP && `MEM_PRIM_ULTRA && !`MEM_PORTB_NC) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) specifies read-first mode or write-first mode, but true dual port UltraRAM configurations must use no-change mode for port B. %m", "XPM_MEMORY", 40, 15, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && MEMORY_SIZE % WRITE_DATA_WIDTH_A != 0 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of WRITE_DATA_WIDTH_A (%0d) for this configuration which uses port A write operations. %m", "XPM_MEMORY", 40, 16, MEMORY_SIZE, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && MEMORY_SIZE % READ_DATA_WIDTH_A != 0 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of READ_DATA_WIDTH_A (%0d) for this configuration which uses port A read operations. %m", "XPM_MEMORY", 40, 17, MEMORY_SIZE, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && MEMORY_SIZE % WRITE_DATA_WIDTH_B != 0 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of WRITE_DATA_WIDTH_B (%0d) for this configuration which uses port B write operations. %m", "XPM_MEMORY", 40, 18, MEMORY_SIZE, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && MEMORY_SIZE % READ_DATA_WIDTH_B != 0 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of READ_DATA_WIDTH_B (%0d) for this configuration which uses port B read operations. %m", "XPM_MEMORY", 40, 19, MEMORY_SIZE, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A) > ADDR_WIDTH_A && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port A write operations. %m", "XPM_MEMORY", 40, 20, MEMORY_SIZE, WRITE_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A) > ADDR_WIDTH_A && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port A read operations. %m", "XPM_MEMORY", 40, 21, MEMORY_SIZE, READ_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && MEMORY_SIZE/WRITE_DATA_WIDTH_A < 2 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and WRITE_DATA_WIDTH_A (%0d) imply that the memory is not at least two words from the perspective of port A write operations. %m", "XPM_MEMORY", 40, 22, MEMORY_SIZE, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && MEMORY_SIZE/READ_DATA_WIDTH_A < 2 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and READ_DATA_WIDTH_A (%0d) imply that the memory is not at least two words from the perspective of port A read operations. %m", "XPM_MEMORY", 40, 23, MEMORY_SIZE, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B) > ADDR_WIDTH_B && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port B write operations. %m", "XPM_MEMORY", 40, 24, MEMORY_SIZE, WRITE_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B) > ADDR_WIDTH_B && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port B read operations. %m", "XPM_MEMORY", 40, 25, MEMORY_SIZE, READ_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && MEMORY_SIZE/WRITE_DATA_WIDTH_B < 2 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and WRITE_DATA_WIDTH_B (%0d) imply that the memory is not at least two words from the perspective of port B write operations. %m", "XPM_MEMORY", 40, 26, MEMORY_SIZE, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && MEMORY_SIZE/READ_DATA_WIDTH_B < 2 && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and READ_DATA_WIDTH_B (%0d) imply that the memory is not at least two words from the perspective of port B read operations. %m", "XPM_MEMORY", 40, 27, MEMORY_SIZE, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `MEM_PRIM_ULTRA && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_A (%0d) for this configuration which uses port A write and read operations, but symmetric port widths are required for UltraRAM configurations. %m", "XPM_MEMORY", 40, 28, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && `MEM_PRIM_ULTRA && WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B && `NO_ECC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this configuration which uses port B write and read operations, but symmetric port widths are required for UltraRAM configurations. %m", "XPM_MEMORY", 40, 31, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && `MEM_PRIM_ULTRA && rst_val_conv_a(READ_RESET_VALUE_A) != 0) begin
|
|
$error("[%s %0d-%0d] READ_RESET_VALUE_A is nonzero for this configuration which uses port A read operations, but UltraRAM configurations require a zero-valued output register reset. %m", "XPM_MEMORY", 40, 33);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && `MEM_PRIM_ULTRA && rst_val_conv_b(READ_RESET_VALUE_B) != 0) begin
|
|
$error("[%s %0d-%0d] READ_RESET_VALUE_B is nonzero for this configuration which uses port B read operations, but UltraRAM configurations require a zero-valued output register reset. %m", "XPM_MEMORY", 40, 34);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `NO_ECC && !(WRITE_DATA_WIDTH_A == 32*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_A == 16*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_A == 8*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_A == 4*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_A == 2*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_A || 32*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_A || 16*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_A || 8*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_A || 4*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_A || 2*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_A)) begin
|
|
$error("[%s %0d-%0d] The ratio of WRITE_DATA_WIDTH_A (%0d) to READ_DATA_WIDTH_A (%0d) is not within the legal range of 32, 16, 8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, or 1/32 for this configuration which uses port A write and read operations. %m", "XPM_MEMORY", 40, 35, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_READ && `NO_ECC && !(WRITE_DATA_WIDTH_A == 32*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_A == 16*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_A == 8*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_A == 4*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_A == 2*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B || 32*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B || 16*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B || 8*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B || 4*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B || 2*WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B)) begin
|
|
$error("[%s %0d-%0d] The ratio of WRITE_DATA_WIDTH_A (%0d) to READ_DATA_WIDTH_B (%0d) is not within the legal range of 32, 16, 8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, or 1/32 for this configuration which uses port A write and port B read operations. %m", "XPM_MEMORY", 40, 36, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTA_READ && `NO_ECC && !(WRITE_DATA_WIDTH_B == 32*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_B == 16*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_B == 8*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_B == 4*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_B == 2*READ_DATA_WIDTH_A || WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_A || 32*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_A || 16*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_A || 8*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_A || 4*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_A || 2*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_A)) begin
|
|
$error("[%s %0d-%0d] The ratio of WRITE_DATA_WIDTH_B (%0d) to READ_DATA_WIDTH_A (%0d) is not within the legal range of 32, 16, 8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, or 1/32 for this configuration which uses port B write and port A read operations. %m", "XPM_MEMORY", 40, 37, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && `NO_ECC && !(WRITE_DATA_WIDTH_B == 32*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_B == 16*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_B == 8*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_B == 4*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_B == 2*READ_DATA_WIDTH_B || WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_B || 32*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_B || 16*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_B || 8*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_B || 4*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_B || 2*WRITE_DATA_WIDTH_B == READ_DATA_WIDTH_B)) begin
|
|
$error("[%s %0d-%0d] The ratio of WRITE_DATA_WIDTH_B (%0d) to READ_DATA_WIDTH_B (%0d) is not within the legal range of 32, 16, 8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, or 1/32 for this configuration which uses port B write and read operations. %m", "XPM_MEMORY", 40, 38, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && `MEM_PORTB_READ && `NO_ECC && !(READ_DATA_WIDTH_A == 32*READ_DATA_WIDTH_A || READ_DATA_WIDTH_A == 16*READ_DATA_WIDTH_A || READ_DATA_WIDTH_A == 8*READ_DATA_WIDTH_A || READ_DATA_WIDTH_A == 4*READ_DATA_WIDTH_A || READ_DATA_WIDTH_A == 2*READ_DATA_WIDTH_A || READ_DATA_WIDTH_A == READ_DATA_WIDTH_A || 32*READ_DATA_WIDTH_A == READ_DATA_WIDTH_A || 16*READ_DATA_WIDTH_A == READ_DATA_WIDTH_A || 8*READ_DATA_WIDTH_A == READ_DATA_WIDTH_A || 4*READ_DATA_WIDTH_A == READ_DATA_WIDTH_A || 2*READ_DATA_WIDTH_A == READ_DATA_WIDTH_A)) begin
|
|
$error("[%s %0d-%0d] The ratio of READ_DATA_WIDTH_A (%0d) to READ_DATA_WIDTH_B (%0d) is not within the legal range of 32, 16, 8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16, or 1/32 for this configuration which uses port A and port B read operations. %m", "XPM_MEMORY", 40, 39, READ_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && WRITE_DATA_WIDTH_A % BYTE_WRITE_WIDTH_A != 0) begin
|
|
$error("[%s %0d-%0d] BYTE_WRITE_WIDTH_A (%0d) does not result in an integer number of bytes within the specified WRITE_DATA_WIDTH_A (%0d) for this configuration which uses port A write operations. %m", "XPM_MEMORY", 40, 40, BYTE_WRITE_WIDTH_A, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && WRITE_DATA_WIDTH_B % BYTE_WRITE_WIDTH_B != 0) begin
|
|
$error("[%s %0d-%0d] BYTE_WRITE_WIDTH_B (%0d) does not result in an integer number of bytes within the specified WRITE_DATA_WIDTH_B (%0d) for this configuration which uses port B write operations. %m", "XPM_MEMORY", 40, 41, BYTE_WRITE_WIDTH_B, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (32'(MEMORY_INIT_FILE) == ".coe" || 32'(MEMORY_INIT_FILE) == ".COE") begin
|
|
$error("[%s %0d-%0d] MEMORY_INIT_FILE (%0s) specifies a file with a .coe extension, but XPM_MEMORY does not support the COE file format. %m", "XPM_MEMORY", 40, 43, MEMORY_INIT_FILE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if ( (`MEM_PRIM_AUTO || `MEM_PRIM_DISTRIBUTED) && (WAKEUP_TIME != 0)) begin
|
|
$error("[%s %0d-%0d] Wake up time of (%0d) is not valid when the Memory Primitive is set to %d.", "XPM_MEMORY", 40, 42, WAKEUP_TIME,MEMORY_PRIMITIVE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_A (%0d) for this configuration which uses port A write and read operations, but symmetric port widths are required for Distributed RAM configurations. %m", "XPM_MEMORY", 40, 44, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_READ && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this configuration which uses port A write and port B read operations, but symmetric port widths are required for Distributed RAM configurations. %m", "XPM_MEMORY", 40, 45, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTA_READ && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_A) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) does not equal READ_DATA_WIDTH_A (%0d) for this configuration which uses port B write and port A read operations, but symmetric port widths are required for Distributed RAM configurations. %m", "XPM_MEMORY", 40, 46, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && `MEM_PRIM_DISTRIBUTED && WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this configuration which uses port B write and read operations, but symmetric port widths are required for Distributed RAM configurations. %m", "XPM_MEMORY", 40, 47, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if ((MEMORY_INIT_FILE != "none" && MEMORY_INIT_FILE != "NONE" && MEMORY_INIT_FILE != "None") && MEMORY_SIZE > 192*1024*1024) begin
|
|
$error("[%s %0d-%0d] Memory size of (%0d) is specified for this configuration with memory initialization, but XPM_MEMORY supports initialization up to 5 million bits only. %m", "XPM_MEMORY", 40, 48, MEMORY_SIZE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_SDP && `MEM_PRIM_DISTRIBUTED && !`MEM_PORTB_RF) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) specifies write-first or no-change mode , but Simple Dual port distributed RAM configurations must use read-first mode for port B. %m", "XPM_MEMORY", 40, 49, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_TYPE_RAM_SDP && `MEM_PRIM_BLOCK && !(`MEM_PORTB_RF || `MEM_PORTB_NC)) begin
|
|
$error("[%s %0d-%0d] WRITE_MODE_B (%0d) specifies write-first mode , but Simple Dual port block RAM configurations must use read-first mode for port B. %m", "XPM_MEMORY", 40, 50, WRITE_MODE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if ((MEMORY_INIT_PARAM != "" && MEMORY_INIT_PARAM != "0") && MEMORY_SIZE > 4*1024) begin
|
|
$error("[%s %0d-%0d] Memory size of (%0d) is specified for this configuration with memory initialization through parameter, but XPM_MEMORY supports initialization through parameter up to memory size of 4k bits only. %m", "XPM_MEMORY", 40, 51, MEMORY_SIZE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_WRITE && `MEM_PORTA_WR_BYTE && `MEM_PORTB_WR_BYTE && (BYTE_WRITE_WIDTH_A != BYTE_WRITE_WIDTH_B)) begin
|
|
$error("[%s %0d-%0d] BYTE_WRITE_WIDTH_A (%0d) does not equal BYTE_WRITE_WIDTH_B (%0d) for this configuration which uses port A byte wide write and port B byte wide write operations, but symmetric byte write widths are required for this configuration. %m", "XPM_MEMORY", 40, 52, BYTE_WRITE_WIDTH_A, BYTE_WRITE_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(32'(MEMORY_INIT_FILE) == ".mem" || 32'(MEMORY_INIT_FILE) == ".MEM") && (MEMORY_INIT_FILE != "none" && MEMORY_INIT_FILE != "NONE" && MEMORY_INIT_FILE != "None") ) begin
|
|
$error("[%s %0d-%0d] MEMORY_INIT_FILE (%0s) specified a file without .mem extension, but XPM_MEMORY supports Initialization files with MEM file format only. %m", "XPM_MEMORY", 40, 53, MEMORY_INIT_FILE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// DRCs related to ECC
|
|
if (!(`NO_ECC) && !(`MEM_PRIM_BLOCK || `MEM_PRIM_ULTRA)) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) parameter is set to a non-zero value and the MEMORY_PRIMITIVE(%0d) specified is other than BlockRAM or UltraRAM, but ECC feature is supported only when the MEMORY_PRIMITIVE is set to either BlockRAM or UltraRAM . %m", "XPM_MEMORY", 41, 1, ECC_MODE, MEMORY_PRIMITIVE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(`NO_ECC) && `MEM_PRIM_BLOCK && !`MEM_TYPE_RAM_SDP) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) parameter is set to a non-zero value, MEMORY_PRIMITIVE(%0d) set to BlockRAM and MEMORY_TYPE(%0d) specified is other than Simple Dual port RAM , but ECC feature is supported only when the MEMORY_TYPE is set to simple Dual port RAM . %m", "XPM_MEMORY", 41, 2, ECC_MODE, MEMORY_PRIMITIVE, MEMORY_TYPE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(`NO_ECC) && `MEM_PRIM_ULTRA && !(`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_SDP || `MEM_TYPE_RAM_TDP)) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) parameter is set to a non-zero value, MEMORY_PRIMITIVE(%0d) set to ultraRAM and MEMORY_TYPE(%0d) specified is other than Simple Dual port RAM , but ECC feature is supported only when the MEMORY_TYPE is set to simple Dual port RAM . %m", "XPM_MEMORY", 41, 3, ECC_MODE, MEMORY_PRIMITIVE, MEMORY_TYPE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// Both_Enc_Dec
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `MEM_PRIM_ULTRA && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_A && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_A (%0d) for this configuration which uses port A write and read operations with ECC mode(both encode and decode) enabled, but this configuration requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 41, 4, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && `MEM_PRIM_ULTRA && WRITE_DATA_WIDTH_B != READ_DATA_WIDTH_B && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this configuration which uses port B write and read operations with ECC(both encode and decode) enabled, but this configuration requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 41, 5, WRITE_DATA_WIDTH_B, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_READ && `MEM_TYPE_RAM_SDP && WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B (%0d) for this configuration which uses port A write and port B read operations with ECC(both encode and decode) enabled, but this configuration requires symmetric write and read data widths across each enabled port. %m", "XPM_MEMORY", 41, 6, WRITE_DATA_WIDTH_A, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORTA_WRITE && WRITE_DATA_WIDTH_A%64 != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) is not a multiple of 64 for this configuration which uses port A write with ECC mode(both encode and decode) enabled, but this configuration requires write ddata width to be multiple of 64. %m", "XPM_MEMORY", 41, 7, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && READ_DATA_WIDTH_A%64 != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) is not a multiple of 64 for this configuration which uses port A write with ECC mode(both encode and decode) enabled, but this configuration requires write ddata width to be multiple of 64. %m", "XPM_MEMORY", 41, 8, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && WRITE_DATA_WIDTH_B%64 != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) is not a multiple of 64 for this configuration which uses port A write with ECC mode(both encode and decode) enabled, but this configuration requires write ddata width to be multiple of 64. %m", "XPM_MEMORY", 41, 9, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && READ_DATA_WIDTH_B%64 != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_B (%0d) is not a multiple of 64 for this configuration which uses port A write with ECC mode(both encode and decode) enabled, but this configuration requires write ddata width to be multiple of 64. %m", "XPM_MEMORY", 41, 10, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORTA_WRITE && MEMORY_SIZE % WRITE_DATA_WIDTH_A != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of WRITE_DATA_WIDTH_A (%0d) for this configuration which uses port A write operations. %m", "XPM_MEMORY", 41, 11, MEMORY_SIZE, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && MEMORY_SIZE % READ_DATA_WIDTH_A != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of READ_DATA_WIDTH_A (%0d) for this configuration which uses port A read operations. %m", "XPM_MEMORY", 41, 12, MEMORY_SIZE, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && MEMORY_SIZE % WRITE_DATA_WIDTH_B != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of WRITE_DATA_WIDTH_B (%0d) for this configuration which uses port B write operations. %m", "XPM_MEMORY", 41, 13, MEMORY_SIZE, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && MEMORY_SIZE % READ_DATA_WIDTH_B != 0 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of READ_DATA_WIDTH_B (%0d) for this configuration which uses port B read operations. %m", "XPM_MEMORY", 41, 14, MEMORY_SIZE, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A) > ADDR_WIDTH_A && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port A write operations. %m", "XPM_MEMORY", 41, 15, MEMORY_SIZE, WRITE_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A) > ADDR_WIDTH_A && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port A read operations. %m", "XPM_MEMORY", 41, 16, MEMORY_SIZE, READ_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && MEMORY_SIZE/WRITE_DATA_WIDTH_A < 2 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and WRITE_DATA_WIDTH_A (%0d) imply that the memory is not at least two words from the perspective of port A write operations. %m", "XPM_MEMORY", 41, 17, MEMORY_SIZE, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && MEMORY_SIZE/READ_DATA_WIDTH_A < 2 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and READ_DATA_WIDTH_A (%0d) imply that the memory is not at least two words from the perspective of port A read operations. %m", "XPM_MEMORY", 41, 18, MEMORY_SIZE, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B) > ADDR_WIDTH_B && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port B write operations. %m", "XPM_MEMORY", 41, 19, MEMORY_SIZE, WRITE_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B) > ADDR_WIDTH_B && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port B read operations. %m", "XPM_MEMORY", 41, 20, MEMORY_SIZE, READ_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && MEMORY_SIZE/WRITE_DATA_WIDTH_B < 2 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and WRITE_DATA_WIDTH_B (%0d) imply that the memory is not at least two words from the perspective of port B write operations. %m", "XPM_MEMORY", 41, 21, MEMORY_SIZE, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && MEMORY_SIZE/READ_DATA_WIDTH_B < 2 && `BOTH_ENC_DEC) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and READ_DATA_WIDTH_B (%0d) imply that the memory is not at least two words from the perspective of port B read operations. %m", "XPM_MEMORY", 41, 22, MEMORY_SIZE, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// Enc_Only
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `MEM_PRIM_ULTRA && READ_DATA_WIDTH_A != (WRITE_DATA_WIDTH_A + (WRITE_DATA_WIDTH_A/64)*8) && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) does not equal WRITE_DATA_WIDTH_A + number of syndrome bits (%0d) for this configuration which uses port A write and read operations with ECC mode(encode only) enabled, but this configuration requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 41, 50, READ_DATA_WIDTH_A, (WRITE_DATA_WIDTH_A + (WRITE_DATA_WIDTH_A/64)*8));
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && `MEM_PRIM_ULTRA && READ_DATA_WIDTH_B != (WRITE_DATA_WIDTH_B + (WRITE_DATA_WIDTH_B/64)*8) && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_B (%0d) does not equal WRITE_DATA_WIDTH_B + number of syndrome bits (%0d) for this configuration which uses port B write and read operations with ECC(encode only) enabled, but this configuration requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 41, 51, READ_DATA_WIDTH_B, (WRITE_DATA_WIDTH_B + (WRITE_DATA_WIDTH_B/64)*8));
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_READ && `MEM_TYPE_RAM_SDP && READ_DATA_WIDTH_B != (WRITE_DATA_WIDTH_A + (WRITE_DATA_WIDTH_A/64)*8) && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_B (%0d) does not equal WRITE_DATA_WIDTH_A + number of syndrome bits (%0d) for this configuration which uses port A write and port B read operations with ECC(encode only) enabled, but this configuration requires symmetric write and read data widths across each enabled port. %m", "XPM_MEMORY", 41, 52, READ_DATA_WIDTH_B, (WRITE_DATA_WIDTH_A + (WRITE_DATA_WIDTH_A/64)*8));
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORTA_WRITE && WRITE_DATA_WIDTH_A%64 != 0 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) is not a multiple of 64 for this configuration which uses port A write with ECC mode(encode only) enabled, but this configuration requires write data width to be multiple of 64. %m", "XPM_MEMORY", 41, 53, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && READ_DATA_WIDTH_A%72 != 0 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) is not a multiple of 72 for this configuration which uses port A read with ECC mode(encode only) enabled, but this configuration requires read data width to be multiple of 72. %m", "XPM_MEMORY", 41, 54, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && WRITE_DATA_WIDTH_B%64 != 0 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) is not a multiple of 64 for this configuration which uses port B write with ECC mode(encode only) enabled, but this configuration requires write data width to be multiple of 64. %m", "XPM_MEMORY", 41, 55, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && READ_DATA_WIDTH_B%72 != 0 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_B (%0d) is not a multiple of 72 for this configuration which uses port B read with ECC mode(encode only) enabled, but this configuration requires write data width to be multiple of 72. %m", "XPM_MEMORY", 41, 56, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORTA_READ && MEMORY_SIZE % READ_DATA_WIDTH_A != 0 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of READ_DATA_WIDTH_A (%0d) for this configuration which uses port A read operations. %m", "XPM_MEMORY", 41, 57, MEMORY_SIZE, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && MEMORY_SIZE % READ_DATA_WIDTH_B != 0 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of READ_DATA_WIDTH_B (%0d) for this configuration which uses port B read operations. %m", "XPM_MEMORY", 41, 58, MEMORY_SIZE, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A) > ADDR_WIDTH_A && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port A read operations. %m", "XPM_MEMORY", 41, 59, MEMORY_SIZE, READ_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && MEMORY_SIZE/READ_DATA_WIDTH_A < 2 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and READ_DATA_WIDTH_A (%0d) imply that the memory is not at least two words from the perspective of port A read operations. %m", "XPM_MEMORY", 41, 60, MEMORY_SIZE, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B) > ADDR_WIDTH_B && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), READ_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port B read operations. %m", "XPM_MEMORY", 41, 62, MEMORY_SIZE, READ_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && MEMORY_SIZE/READ_DATA_WIDTH_B < 2 && `ENC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and READ_DATA_WIDTH_B (%0d) imply that the memory is not at least two words from the perspective of port B read operations. %m", "XPM_MEMORY", 41, 63, MEMORY_SIZE, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// Dec_Only
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTA_READ && `MEM_PRIM_ULTRA && WRITE_DATA_WIDTH_A != (READ_DATA_WIDTH_A + (READ_DATA_WIDTH_A/64)*8) && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_A + number of syndrome bits (%0d) for this configuration which uses port A write and read operations with ECC mode(decode only) enabled, but this configuration requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 41, 100, WRITE_DATA_WIDTH_A, (READ_DATA_WIDTH_A + (READ_DATA_WIDTH_A/64)*8));
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && `MEM_PORTB_READ && `MEM_PRIM_ULTRA && WRITE_DATA_WIDTH_B != (READ_DATA_WIDTH_B + (READ_DATA_WIDTH_B/64)*8) && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) does not equal READ_DATA_WIDTH_B + number of syndrome bits (%0d) for this configuration which uses port B write and read operations with ECC(decode only) enabled, but this configuration requires symmetric write and read data widths within each enabled port. %m", "XPM_MEMORY", 41, 101, WRITE_DATA_WIDTH_B, (READ_DATA_WIDTH_B + (READ_DATA_WIDTH_B/64)*8));
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && `MEM_PORTB_READ && `MEM_TYPE_RAM_SDP && WRITE_DATA_WIDTH_A != (READ_DATA_WIDTH_B + (READ_DATA_WIDTH_B/64)*8) && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) does not equal READ_DATA_WIDTH_B + number of syndrome bits (%0d) for this configuration which uses port A write and port B read operations with ECC(decode only) enabled, but this configuration requires symmetric write and read data widths across each enabled port. %m", "XPM_MEMORY", 41, 102, WRITE_DATA_WIDTH_A, (READ_DATA_WIDTH_B + (READ_DATA_WIDTH_B/64)*8));
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORTA_WRITE && WRITE_DATA_WIDTH_A%72 != 0 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_A (%0d) is not a multiple of 72 for this configuration which uses port A write with ECC mode(decode only) enabled, but this configuration requires write data width to be multiple of 72. %m", "XPM_MEMORY", 41, 103, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_READ && READ_DATA_WIDTH_A%64 != 0 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_A (%0d) is not a multiple of 64 for this configuration which uses port A read with ECC mode(decode only) enabled, but this configuration requires write data width to be multiple of 64. %m", "XPM_MEMORY", 41, 104, READ_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && WRITE_DATA_WIDTH_B%72 != 0 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH_B (%0d) is not a multiple of 72 for this configuration which uses port B write with ECC mode(decode only) enabled, but this configuration requires write data width to be multiple of 72. %m", "XPM_MEMORY", 41, 105, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_READ && READ_DATA_WIDTH_B%64 != 0 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] READ_DATA_WIDTH_B (%0d) is not a multiple of 64 for this configuration which uses port B write with ECC mode(decode only) enabled, but this configuration requires write data width to be multiple of 64. %m", "XPM_MEMORY", 41, 106, READ_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PORTA_WRITE && MEMORY_SIZE % WRITE_DATA_WIDTH_A != 0 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of WRITE_DATA_WIDTH_A (%0d) for this configuration which uses port A write operations. %m", "XPM_MEMORY", 41, 107, MEMORY_SIZE, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && MEMORY_SIZE % WRITE_DATA_WIDTH_B != 0 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) is not an integer multiple of WRITE_DATA_WIDTH_B (%0d) for this configuration which uses port B write operations. %m", "XPM_MEMORY", 41, 108, MEMORY_SIZE, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A) > ADDR_WIDTH_A && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_A (%0d), and ADDR_WIDTH_A (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port A write operations. %m", "XPM_MEMORY", 41, 109, MEMORY_SIZE, WRITE_DATA_WIDTH_A, ADDR_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTA_WRITE && MEMORY_SIZE/WRITE_DATA_WIDTH_A < 2 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and WRITE_DATA_WIDTH_A (%0d) imply that the memory is not at least two words from the perspective of port A write operations. %m", "XPM_MEMORY", 41, 110, MEMORY_SIZE, WRITE_DATA_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B) > ADDR_WIDTH_B && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d), WRITE_DATA_WIDTH_B (%0d), and ADDR_WIDTH_B (%0d) together imply that the memory size exceeds its addressable range for this configuration which uses port B write operations. %m", "XPM_MEMORY", 41, 111, MEMORY_SIZE, WRITE_DATA_WIDTH_B, ADDR_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (`MEM_PORTB_WRITE && MEMORY_SIZE/WRITE_DATA_WIDTH_B < 2 && `DEC_ONLY) begin
|
|
$error("[%s %0d-%0d] MEMORY_SIZE (%0d) and WRITE_DATA_WIDTH_B (%0d) imply that the memory is not at least two words from the perspective of port B write operations. %m", "XPM_MEMORY", 41, 112, MEMORY_SIZE, WRITE_DATA_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(`NO_ECC) && `MEM_PORTA_WRITE && (WRITE_DATA_WIDTH_A != BYTE_WRITE_WIDTH_A)) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) parameter is set to a non-zero value, WRITE_DATA_WIDTH_A(%0d) is not equal to BYTE_WRITE_WIDTH_A(%0d) specified, but byte wide write operations are not allowed when ECC feature is enabled . %m", "XPM_MEMORY", 41, 113, ECC_MODE, WRITE_DATA_WIDTH_A, BYTE_WRITE_WIDTH_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(`NO_ECC) && `MEM_PORTB_WRITE && (WRITE_DATA_WIDTH_B != BYTE_WRITE_WIDTH_B)) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) parameter is set to a non-zero value, WRITE_DATA_WIDTH_B(%0d) is not equal to BYTE_WRITE_WIDTH_B(%0d) specified, but byte wide write operations are not allowed when ECC feature is enabled . %m", "XPM_MEMORY", 41, 114, ECC_MODE, WRITE_DATA_WIDTH_B, BYTE_WRITE_WIDTH_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(`NO_ECC) && `MEM_PORTA_READ && rst_val_conv_a(READ_RESET_VALUE_A) != 0) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) enabled and non-zero READ_RESET_VALUE_A (%0h) value is specified, but non-zero reset value is not supported when ECC_MODE is enabled. %m", "XPM_MEMORY", 41, 115, ECC_MODE, READ_RESET_VALUE_A);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (!(`NO_ECC) && `MEM_PORTB_READ && rst_val_conv_b(READ_RESET_VALUE_B) != 0) begin
|
|
$error("[%s %0d-%0d] The configuration specified has ECC_MODE(%0d) enabled and non-zero READ_RESET_VALUE_B (%0h) value is specified, but non-zero reset value is not supported when ECC_MODE is enabled. %m", "XPM_MEMORY", 41, 116, ECC_MODE, READ_RESET_VALUE_B);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// DRCs related to Auto Sleep
|
|
if (AUTO_SLEEP_TIME != 0 && !`MEM_PRIM_ULTRA) begin
|
|
$error("[%s %0d-%0d] AUTO_SLEEP_TIME (%0d) value specified is non-zero for this configuration which has MEMORY_PRIMITIVE (%0d) value other than ultraRAM, but the auto sleep feature is supported only by UltraRAM primitive. %m", "XPM_MEMORY", 40, 52, AUTO_SLEEP_TIME,MEMORY_PRIMITIVE);
|
|
drc_err_flag = 1;
|
|
end
|
|
if (AUTO_SLEEP_TIME != 0 && WAKEUP_TIME != 0) begin
|
|
$error("[%s %0d-%0d] The configuration specified has non-zero AUTO_SLEEP_TIME (%0d) and WAKEUP_TIME (%0d), but both of these features cannot co-exist. %m", "XPM_MEMORY", 40, 53, AUTO_SLEEP_TIME,WAKEUP_TIME);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// DRCs related to Reset Mode
|
|
if (`ASYNC_RESET_A && !(`MEM_PRIM_BLOCK || `MEM_PRIM_ULTRA)) begin
|
|
$error("[%s %0d-%0d] The configuration specified has RST_MODE_A parameter is set ASYNC and the MEMORY_PRIMITIVE(%0d) specified is other than BlockRAM or UltraRAM, but Asynchronous Reset is supported only when the MEMORY_PRIMITIVE is set to either BlockRAM or UltraRAM . %m", "XPM_MEMORY", 40, 54, MEMORY_PRIMITIVE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`ASYNC_RESET_B && !(`MEM_PRIM_BLOCK || `MEM_PRIM_ULTRA)) begin
|
|
$error("[%s %0d-%0d] The configuration specified has RST_MODE_B parameter is set ASYNC and the MEMORY_PRIMITIVE(%0d) specified is other than BlockRAM or UltraRAM, but Asynchronous Reset is supported only when the MEMORY_PRIMITIVE is set to either BlockRAM or UltraRAM . %m", "XPM_MEMORY", 40, 54, MEMORY_PRIMITIVE);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// DRCs related to Read Reset Value
|
|
if (`ASYNC_RESET_A && (READ_RESET_VALUE_A != "0")) begin
|
|
$error("[%s %0d-%0d] The configuration specified has RST_MODE_A parameter is set ASYNC and the READ_RESET_VALUE_A specified is Non-Zero value, but Non-Zero Reset value not allowed when RST_MODE_A is Asynchronous. %m", "XPM_MEMORY", 40, 55);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`ASYNC_RESET_B && (READ_RESET_VALUE_B != "0")) begin
|
|
$error("[%s %0d-%0d] The configuration specified has RST_MODE_B parameter is set ASYNC and the READ_RESET_VALUE_B specified is Non-Zero value, but Non-Zero Reset value not allowed when RST_MODE_B is Asynchronous. %m", "XPM_MEMORY", 40, 56);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
// DRCs related to Mixed Mode Primitives
|
|
if (`MEM_PRIM_MIXED && (!`NO_ECC || AUTO_SLEEP_TIME != 0)) begin
|
|
$error("[%s %0d-%0d] ECC and Auto Sleep features not supported for Mixed Mode Primitives. %m", "XPM_MEMORY", 4, 1);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PRIM_MIXED && (`MEM_TYPE_ROM_SP || `MEM_TYPE_ROM_DP)) begin
|
|
$error("[%s %0d-%0d] Mixed Mode Primitives does not support ROM configurations. %m", "XPM_MEMORY", 4, 2);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PRIM_MIXED && ((`MEM_PORTA_WRITE && `MEM_PORTA_NC) || (`MEM_PORTB_WRITE && `MEM_PORTB_NC))) begin
|
|
$error("[%s %0d-%0d] Mixed Mode Primitives does not support No_Change on Write Mode. %m", "XPM_MEMORY", 4, 3);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (`MEM_PRIM_MIXED && ((`MEM_TYPE_RAM_TDP && (WRITE_DATA_WIDTH_A != WRITE_DATA_WIDTH_B)) || (`MEM_TYPE_RAM_SDP && (WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B)))) begin
|
|
$error("[%s %0d-%0d] Mixed Mode Primitives does not support Asymmetric Data Width. %m", "XPM_MEMORY", 4, 4);
|
|
drc_err_flag = 1;
|
|
end
|
|
|
|
if (drc_err_flag == 1)
|
|
#1 $finish;
|
|
end : config_drc
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Memory array declaration and initialization
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
(* ram_style = P_MEMORY_PRIMITIVE,
|
|
rom_style = P_MEMORY_PRIMITIVE,
|
|
rw_addr_collision = P_SDP_WRITE_MODE,
|
|
ram_ecc = P_ECC_MODE,
|
|
cascade_height = CASCADE_HEIGHT,
|
|
ram_optimization = P_MEMORY_OPT *) reg [P_MIN_WIDTH_DATA_ECC-1:0] mem [0:P_MAX_DEPTH_DATA-1];
|
|
|
|
// Initialization through parameter
|
|
// Parameter and variable declarations
|
|
localparam NUM_CHAR_LOC = (MEMORY_INIT_PARAM == "" || MEMORY_INIT_PARAM == "0") ? 0 : (P_MIN_WIDTH_DATA%4 == 0) ? (P_MIN_WIDTH_DATA/4) : ((P_MIN_WIDTH_DATA/4)+1);
|
|
localparam MAX_NUM_CHAR = (MEMORY_INIT_PARAM == "" || MEMORY_INIT_PARAM == "0") ? 0 : P_MAX_DEPTH_DATA * NUM_CHAR_LOC + P_MAX_DEPTH_DATA;
|
|
// constants declared to eliminate the eloboration warnings in modelsim, vcs and ies
|
|
localparam P_MIN_WIDTH_DATA_SHFT = (P_MIN_WIDTH_DATA <= 4) ? 5 : P_MIN_WIDTH_DATA;
|
|
localparam P_MIN_WIDTH_DATA_LDW = (P_MIN_WIDTH_DATA <= 4) ? P_MIN_WIDTH_DATA : 4;
|
|
integer num_char_in_param=0;
|
|
|
|
// Function to calculate the number of characters in the string
|
|
function integer num_char_init;
|
|
input [(MAX_NUM_CHAR+1)*8-1:0] str_i;
|
|
num_char_init = 0;
|
|
for(integer char_cnt=0; char_cnt<=MAX_NUM_CHAR; char_cnt=char_cnt+1)
|
|
begin
|
|
if(str_i[(char_cnt*8)+7 -: 8] != "")
|
|
num_char_init = num_char_init+1;
|
|
end
|
|
endfunction
|
|
|
|
// Function that parses the string and returns the initialized array to the memory
|
|
function [P_MAX_DEPTH_DATA-1:0] [P_MIN_WIDTH_DATA-1:0] init_param_memory;
|
|
input [(MAX_NUM_CHAR+1)*8-1:0] mem_init_param_reg;
|
|
reg [3:0] ascii_to_binary_reg;
|
|
reg [P_MIN_WIDTH_DATA-1:0] conv_bin_val;
|
|
integer mem_location;
|
|
integer num_char;
|
|
conv_bin_val = {P_MIN_WIDTH_DATA{1'b0}};
|
|
mem_location = 0;
|
|
num_char = 0;
|
|
for (integer init_char=MAX_NUM_CHAR+1; init_char>0; init_char = init_char-1) begin : ascii_to_bin_loop
|
|
if((mem_init_param_reg[(init_char*8)-1 -: 8] == 8'h2c) || (mem_init_param_reg[(init_char*8)-1 -: 8] == 8'h3b) ||
|
|
(mem_init_param_reg[(init_char*8)-1 -: 8] == 8'h00)) begin
|
|
ascii_to_binary_reg = 4'h0;
|
|
if (num_char > 0) // Check at least for one valid character before encountering the delimiter or NULL
|
|
begin
|
|
init_param_memory[mem_location] = conv_bin_val[P_MIN_WIDTH_DATA-1:0];
|
|
mem_location = mem_location+1;
|
|
end
|
|
conv_bin_val = {P_MIN_WIDTH_DATA{1'b0}};
|
|
num_char = 0;
|
|
end
|
|
else if(mem_init_param_reg[(init_char*8)-1 -: 8] != 8'h00) begin
|
|
ascii_to_binary_reg = str_val_binary(mem_init_param_reg[(init_char*8)-1 -: 8]);
|
|
if (P_MIN_WIDTH_DATA <= 4)
|
|
conv_bin_val = ascii_to_binary_reg[P_MIN_WIDTH_DATA_LDW-1:0]; // converted 4-bit value from ASCII
|
|
else begin
|
|
conv_bin_val = {conv_bin_val[P_MIN_WIDTH_DATA_SHFT-5:0], ascii_to_binary_reg}; // Store the converted value in shift register
|
|
//conv_bin_val = conv_bin_val<<4 | ascii_to_binary_reg; // Store the converted value in shift register
|
|
end
|
|
num_char = num_char+1; // Increment number of characters parsed
|
|
if(num_char > NUM_CHAR_LOC)
|
|
$error("Number of characters given in the Initialization string exceeded the memory width, Please enter a valid string");
|
|
end
|
|
end : ascii_to_bin_loop
|
|
endfunction
|
|
|
|
generate
|
|
if(IGNORE_INIT_SYNTH == 0) begin : gen_no_ignore_init_synth
|
|
// Initialize memory array to the data file content if file name is specified, or to all zeroes if it is not specified
|
|
initial begin
|
|
if (`NO_MEMORY_INIT) begin : init_zeroes
|
|
integer initword;
|
|
for (initword=0; initword<P_MAX_DEPTH_DATA; initword=initword+1) begin
|
|
mem[initword] = {P_MIN_WIDTH_DATA{1'b0}};
|
|
end
|
|
end : init_zeroes
|
|
else if (!(MEMORY_INIT_PARAM == "0" || MEMORY_INIT_PARAM == "")) begin : init_param
|
|
reg [P_MAX_DEPTH_DATA-1:0] [P_MIN_WIDTH_DATA-1:0] mem_param;
|
|
num_char_in_param = num_char_init(MEMORY_INIT_PARAM);
|
|
assert (num_char_in_param <= MAX_NUM_CHAR) // Check if the string length exceeds the depth of the memory size
|
|
else
|
|
$error("No.of characters given in the Initialization Parameter string exceeds the Memory Size");
|
|
mem_param = init_param_memory({MEMORY_INIT_PARAM, 8'h0}); //Append NULL to identify the end of string
|
|
for(integer mem_location=0; mem_location<P_MAX_DEPTH_DATA; mem_location=mem_location+1)
|
|
mem[mem_location] = mem_param[mem_location]; //assign the initial value to the memory
|
|
end : init_param
|
|
else begin : init_datafile
|
|
#10;
|
|
$readmemh(MEMORY_INIT_FILE, mem, 0, P_MAX_DEPTH_DATA-1);
|
|
end : init_datafile
|
|
end
|
|
end : gen_no_ignore_init_synth
|
|
if(IGNORE_INIT_SYNTH == 1) begin : gen_ignore_init_synth
|
|
// Initialize memory array to the data file content if file name is specified, or to all zeroes if it is not specified
|
|
initial begin
|
|
if (`NO_MEMORY_INIT) begin : init_zeroes
|
|
integer initword;
|
|
for (initword=0; initword<P_MAX_DEPTH_DATA; initword=initword+1) begin
|
|
mem[initword] = {P_MIN_WIDTH_DATA{1'b0}};
|
|
end
|
|
end : init_zeroes
|
|
else if (!(MEMORY_INIT_PARAM == "0" || MEMORY_INIT_PARAM == "")) begin : init_param
|
|
reg [P_MAX_DEPTH_DATA-1:0] [P_MIN_WIDTH_DATA-1:0] mem_param;
|
|
num_char_in_param = num_char_init(MEMORY_INIT_PARAM);
|
|
assert (num_char_in_param <= MAX_NUM_CHAR) // Check if the string length exceeds the depth of the memory size
|
|
else
|
|
$error("No.of characters given in the Initialization Parameter string exceeds the Memory Size");
|
|
mem_param = init_param_memory({MEMORY_INIT_PARAM, 8'h0}); //Append NULL to identify the end of string
|
|
for(integer mem_location=0; mem_location<P_MAX_DEPTH_DATA; mem_location=mem_location+1)
|
|
mem[mem_location] = mem_param[mem_location]; //assign the initial value to the memory
|
|
end : init_param
|
|
// synthesis translate_off
|
|
else begin : init_datafile
|
|
#10;
|
|
$readmemh(MEMORY_INIT_FILE, mem, 0, P_MAX_DEPTH_DATA-1);
|
|
end : init_datafile
|
|
// synthesis translate_on
|
|
end
|
|
end : gen_ignore_init_synth
|
|
endgenerate
|
|
|
|
generate
|
|
// Function to convert ASCII value to binary
|
|
function [3:0] str_val_binary;
|
|
input [7:0] str_val_ascii;
|
|
if((str_val_ascii == 8'h30) || (str_val_ascii == 8'h31) ||
|
|
(str_val_ascii == 8'h32) || (str_val_ascii == 8'h33) ||
|
|
(str_val_ascii == 8'h34) || (str_val_ascii == 8'h35) ||
|
|
(str_val_ascii == 8'h36) || (str_val_ascii == 8'h37) ||
|
|
(str_val_ascii == 8'h38) || (str_val_ascii == 8'h39) ||
|
|
(str_val_ascii == 8'h41) || (str_val_ascii == 8'h42) ||
|
|
(str_val_ascii == 8'h43) || (str_val_ascii == 8'h44) ||
|
|
(str_val_ascii == 8'h45) || (str_val_ascii == 8'h46) ||
|
|
(str_val_ascii == 8'h61) || (str_val_ascii == 8'h62) ||
|
|
(str_val_ascii == 8'h63) || (str_val_ascii == 8'h64) ||
|
|
(str_val_ascii == 8'h65) || (str_val_ascii == 8'h66) ||
|
|
(str_val_ascii == 8'h00)) begin
|
|
if (!str_val_ascii[6])
|
|
str_val_binary = str_val_ascii[3:0];
|
|
else begin
|
|
str_val_binary [3] = 1'b1;
|
|
str_val_binary [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
|
str_val_binary [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
|
str_val_binary [0] = !str_val_ascii[0];
|
|
end
|
|
end
|
|
else
|
|
$error("Found Invalid character while parsing the string, please cross check the value specified for either READ_RESET_VALUE_A|B or MEMORY_INIT_PARAM (if initialization of memory through parameter is used). XPM_MEMORY supports strings (hex) that contains characters 0-9, A-F and a-f.");
|
|
endfunction
|
|
// Function that parses the complete reset value string
|
|
function logic [READ_DATA_WIDTH_A-1 :0] rst_val_conv_a;
|
|
input [READ_DATA_WIDTH_A*8-1 : 0] rst_val_reg_a;
|
|
integer rst_loop_a;
|
|
logic [rsta_loop_iter-1 : 0] rst_val_conv_a_i;
|
|
for (rst_loop_a=1; rst_loop_a <= rsta_loop_iter/4; rst_loop_a = rst_loop_a+1) begin
|
|
rst_val_conv_a_i[(rst_loop_a*4)-1 -: 4] = str_val_binary(rst_val_reg_a[(rst_loop_a*8)-1 -: 8]);
|
|
end
|
|
return rst_val_conv_a_i[READ_DATA_WIDTH_A-1 :0];
|
|
endfunction
|
|
|
|
function logic [READ_DATA_WIDTH_B-1 :0] rst_val_conv_b;
|
|
input [READ_DATA_WIDTH_B*8-1 : 0] rst_val_reg_b;
|
|
integer rst_loop_b;
|
|
logic [rstb_loop_iter-1 : 0] rst_val_conv_b_i;
|
|
for (rst_loop_b=1; rst_loop_b<= rstb_loop_iter/4; rst_loop_b = rst_loop_b+1) begin
|
|
rst_val_conv_b_i[(rst_loop_b*4)-1 -: 4] = str_val_binary(rst_val_reg_b[(rst_loop_b*8)-1 -: 8]);
|
|
end
|
|
return rst_val_conv_b_i[READ_DATA_WIDTH_B-1 :0];
|
|
endfunction
|
|
|
|
wire [READ_DATA_WIDTH_A-1 : 0] douta_bb;
|
|
wire [READ_DATA_WIDTH_B-1 : 0] doutb_bb;
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Auto Sleep delays for port-A
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
wire ena_i;
|
|
wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea_i;
|
|
wire [P_WIDTH_ADDR_WRITE_A-1:0] addra_i;
|
|
wire [WRITE_DATA_WIDTH_A-1:0] dina_i;
|
|
wire ena_o_pipe_ctrl;
|
|
wire regcea_i;
|
|
|
|
if(`MEM_AUTO_SLP_EN) begin : gen_auto_slp_dly_a
|
|
reg [P_WIDTH_ADDR_WRITE_A-1:0] addra_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
|
|
// Check if write operation is allowed on Port-A, if yes then
|
|
// generate the pipeline register stages on write enable and input data
|
|
if (`MEM_PORTA_WRITE) begin : gen_aslp_wr_a
|
|
reg [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
reg [WRITE_DATA_WIDTH_A-1:0] dina_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the wea and dina pipelines
|
|
initial begin
|
|
integer aslp_initstage_a;
|
|
for (aslp_initstage_a=0; aslp_initstage_a < AUTO_SLEEP_TIME; aslp_initstage_a=aslp_initstage_a+1) begin : for_wr_en_pipe_init
|
|
wea_aslp_pipe[aslp_initstage_a] = {(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A){1'b0}};
|
|
dina_aslp_pipe[aslp_initstage_a] = {WRITE_DATA_WIDTH_A{1'b0}};
|
|
end : for_wr_en_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clka) begin
|
|
wea_aslp_pipe[0] <= wea;
|
|
dina_aslp_pipe[0] <= dina;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clka) begin
|
|
wea_aslp_pipe[aslp_stage] <= wea_aslp_pipe[aslp_stage-1];
|
|
dina_aslp_pipe[aslp_stage] <= dina_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the last stage register outputs to appropriate internal signals
|
|
assign wea_i = wea_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
assign dina_i = dina_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_wr_a
|
|
// If write operation is not allowed, then connect the write control signals
|
|
// to zero
|
|
else begin : gnd_wr_a_ctrls
|
|
assign wea_i = {(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A){1'b0}};
|
|
assign dina_i = {(WRITE_DATA_WIDTH_A){1'b0}};
|
|
end : gnd_wr_a_ctrls
|
|
// Generate the pipeline register stages on addra
|
|
// Initialize the addra pipeline
|
|
initial begin
|
|
integer aslp_initstage_a;
|
|
for (aslp_initstage_a=0; aslp_initstage_a < AUTO_SLEEP_TIME; aslp_initstage_a=aslp_initstage_a+1) begin : for_addr_pipe_init
|
|
addra_aslp_pipe[aslp_initstage_a] = {P_WIDTH_ADDR_WRITE_A{1'b0}};
|
|
end : for_addr_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clka) begin
|
|
addra_aslp_pipe[0] <= addra;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clka) begin
|
|
addra_aslp_pipe[aslp_stage] <= addra_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the last stage register outputs to internal address
|
|
assign addra_i = addra_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
// Check if Read Operations are allowed on Port-A and if output pipeline
|
|
// exists
|
|
if(`MEM_PORTA_READ) begin : gen_aslp_rd_a
|
|
if(READ_LATENCY_A >= 2) begin : gen_aslp_dly_regce
|
|
reg regcea_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the regcea pipeline
|
|
initial begin
|
|
integer aslp_initstage_a;
|
|
for (aslp_initstage_a=0; aslp_initstage_a < AUTO_SLEEP_TIME; aslp_initstage_a=aslp_initstage_a+1) begin : for_regce_pipe_init
|
|
regcea_aslp_pipe[aslp_initstage_a] = 1'b0;
|
|
end : for_regce_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clka) begin
|
|
regcea_aslp_pipe[0] <= regcea;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clka) begin
|
|
regcea_aslp_pipe[aslp_stage] <= regcea_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the final pipeline output to internal regce
|
|
assign regcea_i = regcea_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_dly_regce
|
|
else begin : gnd_regce_ctrl
|
|
// If there are no output pipe lines, then connect to zero
|
|
assign regcea_i = 1'b0;
|
|
end : gnd_regce_ctrl
|
|
if(READ_LATENCY_A > 2) begin : gen_aslp_dly_out_pipe
|
|
reg ena_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the ena pipeline
|
|
initial begin
|
|
integer aslp_initstage_a;
|
|
for (aslp_initstage_a=0; aslp_initstage_a < AUTO_SLEEP_TIME; aslp_initstage_a=aslp_initstage_a+1) begin : for_en_pipe_init
|
|
ena_aslp_pipe[aslp_initstage_a] = 1'b0;
|
|
end : for_en_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clka) begin
|
|
ena_aslp_pipe[0] <= ena;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clka) begin
|
|
ena_aslp_pipe[aslp_stage] <= ena_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the final pipeline output to internal enable that controls the
|
|
// output pipeline
|
|
assign ena_o_pipe_ctrl = ena_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_dly_out_pipe
|
|
else begin : gnd_pipe_en_ctrl
|
|
// If there are no output pipe lines, then connect to zero
|
|
assign ena_o_pipe_ctrl = 0;
|
|
end : gnd_pipe_en_ctrl
|
|
end : gen_aslp_rd_a
|
|
end : gen_auto_slp_dly_a
|
|
else begin : gen_nauto_slp_dly_a
|
|
// connect all the internal control signals to the ports when auto sleep is
|
|
// not enabled
|
|
assign addra_i = addra;
|
|
assign wea_i = wea;
|
|
assign dina_i = dina;
|
|
assign ena_o_pipe_ctrl = ena;
|
|
assign regcea_i = regcea;
|
|
end : gen_nauto_slp_dly_a
|
|
// Enable needs to reach URAM early compared to other inputs in Auto Sleep
|
|
// Mode, so no pipe line stages on enable irrespective auto sleep mode
|
|
// enabled/disabled
|
|
assign ena_i = ena;
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Port A write
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
// If the memory is any type of RAM, generate a port A write process
|
|
if (`MEM_PORTA_WRITE && !`DISABLE_SYNTH_TEMPL) begin : gen_wr_a
|
|
wire [P_WIDTH_ADDR_WRITE_A-1:0] addra_int = addra_i;
|
|
|
|
// Synchronous port A write; word-wide write; port width is the narrowest of the data ports
|
|
if (`MEM_PORTA_WR_WORD && `MEM_PORTA_WR_NARROW && `WRITE_PROT_ENABLED) begin : gen_word_narrow
|
|
always @(posedge clka) begin
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
mem[addra_int] <= dina_i;
|
|
end
|
|
end
|
|
end : gen_word_narrow
|
|
else if (`MEM_PORTA_WR_WORD && `MEM_PORTA_WR_NARROW && `WRITE_PROT_DISABLED) begin : gen_word_narrow_wp
|
|
always @(posedge clka) begin
|
|
if (wea_i)
|
|
mem[addra_int] <= dina_i;
|
|
end
|
|
end : gen_word_narrow_wp
|
|
|
|
// Synchronous port A write; word-wide write; port width is wider than at least one other data port;
|
|
// not generated in port A write-first read with wide data width special case
|
|
else if (`MEM_PORTA_WR_WORD && `MEM_PORTA_WR_WIDE &&
|
|
!((`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_TDP) && `MEM_PORTA_WF && `MEM_PORTA_RD_WIDE) && `WRITE_PROT_ENABLED) begin : gen_word_wide
|
|
always @(posedge clka) begin : wr_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
mem[{addra_int, addralsb}] <= dina_i[`ONE_ROW_OF_DIN];
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_sync
|
|
end : gen_word_wide
|
|
else if (`MEM_PORTA_WR_WORD && `MEM_PORTA_WR_WIDE &&
|
|
!((`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_TDP) && `MEM_PORTA_WF && `MEM_PORTA_RD_WIDE) && `WRITE_PROT_DISABLED) begin : gen_word_wide_wp
|
|
always @(posedge clka) begin : wr_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (wea_i)
|
|
mem[{addra_int, addralsb}] <= dina_i[`ONE_ROW_OF_DIN];
|
|
end : for_mem_rows
|
|
end : wr_sync
|
|
end : gen_word_wide_wp
|
|
|
|
// Synchronous port A write-first read; port width is wider than at least one other data port; no output pipeline;
|
|
// write and read combined special case
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_REG && `WRITE_PROT_ENABLED) begin : gen_wf_wide_reg
|
|
always @(posedge clka) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
mem[{addra_int, addralsb}] <= dina_i[`ONE_ROW_OF_DIN];
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end : gen_wf_wide_reg
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_REG && `WRITE_PROT_DISABLED) begin : gen_wf_wide_reg_wp
|
|
always @(posedge clka) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (wea_i)
|
|
mem[{addra_int, addralsb}] <= dina_i[`ONE_ROW_OF_DIN];
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end : gen_wf_wide_reg_wp
|
|
|
|
// Synchronous port A write; byte-wide write; port width is the narrowest of the data ports
|
|
else if (`MEM_PORTA_WR_BYTE && `MEM_PORTA_WR_NARROW && `WRITE_PROT_ENABLED) begin : gen_byte_narrow
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin : for_mem_cols
|
|
always @(posedge clka) begin : wr_sync
|
|
if (ena_i) begin
|
|
if (wea_i[col])
|
|
mem[addra_int][`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
end
|
|
end : wr_sync
|
|
end : for_mem_cols
|
|
end : gen_byte_narrow
|
|
else if (`MEM_PORTA_WR_BYTE && `MEM_PORTA_WR_NARROW && `WRITE_PROT_DISABLED) begin : gen_byte_narrow_wp
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin : for_mem_cols
|
|
always @(posedge clka) begin : wr_sync
|
|
if (wea_i[col])
|
|
mem[addra_int][`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
end : wr_sync
|
|
end : for_mem_cols
|
|
end : gen_byte_narrow_wp
|
|
// Error Injection in ECC modes ("Both encode and Decode" mode and "Encode_only" modes)
|
|
// Append required synthesis attributes
|
|
if(`BOTH_ENC_DEC || `ENC_ONLY) begin : err_inj_ecc
|
|
(* keep = "yes", xpm_ecc_inject_sbiterr = "yes" *) wire injectsbiterra_i;
|
|
(* keep = "yes", xpm_ecc_inject_dbiterr = "yes" *) wire injectdbiterra_i;
|
|
|
|
// Declare injecterr inputs to synth ANDed with LSB data
|
|
(* keep = "yes" *) wire inj_sbiterra_to_synth;
|
|
(* keep = "yes" *) wire inj_dbiterra_to_synth;
|
|
if(`MEM_AUTO_SLP_EN) begin : gen_aslp_dly_inj_err
|
|
// Auto Sleep pipe line delays on the error inject signals
|
|
reg injsbiterra_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
reg injdbiterra_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the inject error signal's pipe-lines
|
|
initial begin
|
|
integer aslp_initstage_a;
|
|
for (aslp_initstage_a=0; aslp_initstage_a<AUTO_SLEEP_TIME; aslp_initstage_a=aslp_initstage_a+1) begin : for_injerr_pipe_init
|
|
injsbiterra_aslp_pipe[aslp_initstage_a] = 1'b0;
|
|
injdbiterra_aslp_pipe[aslp_initstage_a] = 1'b0;
|
|
end : for_injerr_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clka)
|
|
begin
|
|
injsbiterra_aslp_pipe[0] <= injectsbiterra;
|
|
injdbiterra_aslp_pipe[0] <= injectdbiterra;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clka) begin
|
|
injsbiterra_aslp_pipe[aslp_stage] <= injsbiterra_aslp_pipe[aslp_stage-1];
|
|
injdbiterra_aslp_pipe[aslp_stage] <= injdbiterra_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
assign injectsbiterra_i = injsbiterra_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
assign injectdbiterra_i = injdbiterra_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_dly_inj_err
|
|
else begin : gen_naslp_dly_inj_err
|
|
assign injectsbiterra_i = injectsbiterra;
|
|
assign injectdbiterra_i = injectdbiterra;
|
|
end : gen_naslp_dly_inj_err
|
|
//Assignment to error Injection signals passed to synthesis
|
|
assign inj_sbiterra_to_synth = injectsbiterra_i & dina_i[0];
|
|
assign inj_dbiterra_to_synth = injectdbiterra_i & dina_i[0];
|
|
end : err_inj_ecc
|
|
|
|
end : gen_wr_a
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Port B write
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Auto Sleep delays for port-B
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
wire enb_i;
|
|
wire [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web_i;
|
|
wire [P_WIDTH_ADDR_WRITE_B-1:0] addrb_i;
|
|
wire [WRITE_DATA_WIDTH_B-1:0] dinb_i;
|
|
wire enb_o_pipe_ctrl;
|
|
wire regceb_i;
|
|
if(`MEM_AUTO_SLP_EN && (`MEM_PORTB_WRITE || `MEM_PORTB_READ)) begin : gen_auto_slp_dly_b
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
wire clkb_int;
|
|
|
|
// In true dual port UltraRAM configurations, use the port A clock delayed by a small amount to model the port B
|
|
// synchronous processes; although both ports share a common clock, port B operations occur after port A operations
|
|
if (`COMMON_CLOCK && `MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin : gen_uram_tdp_common_clock
|
|
assign clkb_int = clka;
|
|
end : gen_uram_tdp_common_clock
|
|
|
|
// In all other common clocking configurations, use the port A clock for port B synchronous processes
|
|
else if (`COMMON_CLOCK) begin : gen_common_clock
|
|
assign clkb_int = clka;
|
|
end : gen_common_clock
|
|
|
|
// In independent clocking configurations, use the port B clock for port B synchronous processes
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_independent_clocks
|
|
assign clkb_int = clkb;
|
|
end : gen_independent_clocks
|
|
|
|
// Check if write operation is allowed on Port-B, if yes then
|
|
// generate the pipeline register stages on write enable and input data
|
|
if(`MEM_PORTB_WRITE) begin : gen_aslp_wr_b
|
|
reg [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
reg [WRITE_DATA_WIDTH_B-1:0] dinb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the web and dinb pipelines
|
|
initial begin
|
|
integer aslp_initstage_b;
|
|
for (aslp_initstage_b=0; aslp_initstage_b<AUTO_SLEEP_TIME; aslp_initstage_b=aslp_initstage_b+1) begin : for_wr_en_pipe_init
|
|
web_aslp_pipe[aslp_initstage_b] = {(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B){1'b0}};
|
|
dinb_aslp_pipe[aslp_initstage_b] = {WRITE_DATA_WIDTH_B{1'b0}};
|
|
end : for_wr_en_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clkb_int) begin
|
|
web_aslp_pipe[0] <= web;
|
|
dinb_aslp_pipe[0] <= dinb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clkb_int) begin
|
|
web_aslp_pipe[aslp_stage] <= web_aslp_pipe[aslp_stage-1];
|
|
dinb_aslp_pipe[aslp_stage] <= dinb_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the last stage register outputs to appropriate internal signals
|
|
assign web_i = web_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
assign dinb_i = dinb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_wr_b
|
|
// If write operation is not allowed, then connect the write control signals
|
|
// to zero
|
|
else begin : gnd_wr_b_ctrls
|
|
assign web_i = {(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B){1'b0}};
|
|
assign dinb_i = {(WRITE_DATA_WIDTH_B){1'b0}};
|
|
end : gnd_wr_b_ctrls
|
|
if(`MEM_PORTB_WRITE || `MEM_PORTB_READ) begin : gen_aslp_addr_b
|
|
// Generate the pipeline register stages on addrb
|
|
// Initialize the addrb pipelines
|
|
initial begin
|
|
integer aslp_initstage_b;
|
|
for (aslp_initstage_b=0; aslp_initstage_b<AUTO_SLEEP_TIME; aslp_initstage_b=aslp_initstage_b+1) begin : for_addr_pipe_init
|
|
addrb_aslp_pipe[aslp_initstage_b] = {P_WIDTH_ADDR_WRITE_B{1'b0}};
|
|
end : for_addr_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clkb_int)
|
|
begin
|
|
addrb_aslp_pipe[0] <= addrb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clkb_int) begin
|
|
addrb_aslp_pipe[aslp_stage] <= addrb_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the last stage register outputs to internal address
|
|
assign addrb_i = addrb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_addr_b
|
|
else begin : gnd_addr_dly
|
|
// If write operation is not allowed, then connect the internal address to zero
|
|
assign addrb_i = {P_WIDTH_ADDR_WRITE_B{1'b0}};
|
|
end : gnd_addr_dly
|
|
// Check if read operation is not allowed, then connect the write control signals
|
|
// to zero
|
|
if(`MEM_PORTB_READ) begin : gen_aslp_rd_b
|
|
if(READ_LATENCY_B >= 2) begin : gen_aslp_dly_regce
|
|
reg regceb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the regceb pipelines
|
|
initial begin
|
|
integer aslp_initstage_b;
|
|
for (aslp_initstage_b=0; aslp_initstage_b<AUTO_SLEEP_TIME; aslp_initstage_b=aslp_initstage_b+1) begin : for_regce_pipe_init
|
|
regceb_aslp_pipe[aslp_initstage_b] = 1'b0;
|
|
end : for_regce_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clkb_int) begin
|
|
regceb_aslp_pipe[0] <= regceb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clkb_int) begin
|
|
regceb_aslp_pipe[aslp_stage] <= regceb_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the last stage register outputs to internal regce
|
|
assign regceb_i = regceb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_dly_regce
|
|
else begin : gnd_regce_ctrl
|
|
// If there is no output pipeline, then connect regce to zero
|
|
assign regceb_i = 0;
|
|
end : gnd_regce_ctrl
|
|
if(READ_LATENCY_B > 2) begin : gen_aslp_dly_out_pipe
|
|
reg enb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the enb pipelines
|
|
initial begin
|
|
integer aslp_initstage_b;
|
|
for (aslp_initstage_b=0; aslp_initstage_b<AUTO_SLEEP_TIME; aslp_initstage_b=aslp_initstage_b+1) begin : for_en_pipe_init
|
|
enb_aslp_pipe[aslp_initstage_b] = 1'b0;
|
|
end : for_en_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clkb_int) begin
|
|
enb_aslp_pipe[0] <= enb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clkb_int) begin
|
|
enb_aslp_pipe[aslp_stage] <= enb_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign the last stage register outputs to internal enable that controls
|
|
// the output pipeline
|
|
assign enb_o_pipe_ctrl = enb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_dly_out_pipe
|
|
else begin : gnd_pipe_en_ctrl
|
|
// If there is no output pipeline, then connect enable to zero
|
|
assign enb_o_pipe_ctrl = 1'b0;
|
|
end : gnd_pipe_en_ctrl
|
|
end : gen_aslp_rd_b
|
|
end : gen_auto_slp_dly_b
|
|
else begin : gen_nauto_slp_dly_b
|
|
// connect all the internal control signals to the ports when auto sleep is
|
|
// not enabled
|
|
assign web_i = web;
|
|
assign dinb_i = dinb;
|
|
assign addrb_i = addrb;
|
|
assign enb_o_pipe_ctrl = enb;
|
|
assign regceb_i = regceb;
|
|
end : gen_nauto_slp_dly_b
|
|
// Enable needs to reach URAM early compared to other inputs in Auto Sleep
|
|
// Mode, so no pipe line stages on enable irrespective auto sleep mode
|
|
// enabled/disabled
|
|
assign enb_i = enb;
|
|
|
|
// If the memory type is true dual port RAM, generate a port B write process
|
|
if (`MEM_PORTB_WRITE && !`DISABLE_SYNTH_TEMPL) begin : gen_wr_b
|
|
wire clkb_int;
|
|
wire [P_WIDTH_ADDR_WRITE_B-1:0] addrb_int = addrb_i;
|
|
|
|
// In true dual port UltraRAM configurations, use the port A clock delayed by a small amount to model the port B
|
|
// synchronous processes; although both ports share a common clock, port B operations occur after port A operations
|
|
if (`COMMON_CLOCK && `MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin : gen_uram_tdp_common_clock
|
|
assign clkb_int = clka;
|
|
end : gen_uram_tdp_common_clock
|
|
|
|
// In all other common clocking configurations, use the port A clock for port B synchronous processes
|
|
else if (`COMMON_CLOCK) begin : gen_common_clock
|
|
assign clkb_int = clka;
|
|
end : gen_common_clock
|
|
|
|
// In independent clocking configurations, use the port B clock for port B synchronous processes
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_independent_clocks
|
|
assign clkb_int = clkb;
|
|
end : gen_independent_clocks
|
|
|
|
// Synchronous port B write; word-wide write; port width is the narrowest of the data ports
|
|
if (`MEM_PORTB_WR_WORD && `MEM_PORTB_WR_NARROW && `WRITE_PROT_ENABLED) begin : gen_word_narrow
|
|
always @(posedge clkb_int) begin
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
mem[addrb_int] <= dinb_i;
|
|
end
|
|
end
|
|
end : gen_word_narrow
|
|
else if (`MEM_PORTB_WR_WORD && `MEM_PORTB_WR_NARROW && `WRITE_PROT_DISABLED) begin : gen_word_narrow_wp
|
|
always @(posedge clkb_int) begin
|
|
if (web_i)
|
|
mem[addrb_int] <= dinb_i;
|
|
end
|
|
end : gen_word_narrow_wp
|
|
|
|
// Synchronous port B write; word-wide write; port width is wider than at least one other data port;
|
|
// not generated in port B write-first read with wide data width special case
|
|
else if (`MEM_PORTB_WR_WORD && `MEM_PORTB_WR_WIDE &&
|
|
!(`MEM_TYPE_RAM_TDP && `MEM_PORTB_WF && `MEM_PORTB_RD_WIDE) && `WRITE_PROT_ENABLED) begin : gen_word_wide
|
|
always @(posedge clkb_int) begin : wr_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
mem[{addrb_int, addrblsb}] <= dinb_i[`ONE_ROW_OF_DIN];
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_sync
|
|
end : gen_word_wide
|
|
else if (`MEM_PORTB_WR_WORD && `MEM_PORTB_WR_WIDE &&
|
|
!(`MEM_TYPE_RAM_TDP && `MEM_PORTB_WF && `MEM_PORTB_RD_WIDE) && `WRITE_PROT_DISABLED) begin : gen_word_wide_wp
|
|
always @(posedge clkb_int) begin : wr_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (web_i)
|
|
mem[{addrb_int, addrblsb}] <= dinb_i[`ONE_ROW_OF_DIN];
|
|
end : for_mem_rows
|
|
end : wr_sync
|
|
end : gen_word_wide_wp
|
|
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_REG && `WRITE_PROT_ENABLED) begin : gen_wf_wide_reg
|
|
always @(posedge clkb_int) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
mem[{addrb_int, addrblsb}] <= dinb_i[`ONE_ROW_OF_DIN];
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end : gen_wf_wide_reg
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_REG && `WRITE_PROT_DISABLED) begin : gen_wf_wide_reg_wp
|
|
always @(posedge clkb_int) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (web_i)
|
|
mem[{addrb_int, addrblsb}] <= dinb_i[`ONE_ROW_OF_DIN];
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end : gen_wf_wide_reg_wp
|
|
|
|
// Synchronous port B write; byte-wide write; port width is the narrowest of the data ports
|
|
else if (`MEM_PORTB_WR_BYTE && `MEM_PORTB_WR_NARROW && `WRITE_PROT_ENABLED) begin : gen_byte_narrow
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin : for_mem_cols
|
|
always @(posedge clkb_int) begin : wr_sync
|
|
if (enb_i) begin
|
|
if (web_i[col])
|
|
mem[addrb_int][`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
end
|
|
end : wr_sync
|
|
end : for_mem_cols
|
|
end : gen_byte_narrow
|
|
else if (`MEM_PORTB_WR_BYTE && `MEM_PORTB_WR_NARROW && `WRITE_PROT_DISABLED) begin : gen_byte_narrow_wp
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin : for_mem_cols
|
|
always @(posedge clkb_int) begin : wr_sync
|
|
if (web_i[col])
|
|
mem[addrb_int][`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
end : wr_sync
|
|
end : for_mem_cols
|
|
end : gen_byte_narrow_wp
|
|
// Error Injection in ECC modes ("Both encode and Decode" mode and "Encode_only" modes)
|
|
// Append required synthesis attributes
|
|
if(`BOTH_ENC_DEC || `ENC_ONLY) begin : err_inj_ecc
|
|
(* keep = "yes", xpm_ecc_inject_sbiterr = "yes" *) reg injectsbiterrb_i;
|
|
(* keep = "yes", xpm_ecc_inject_dbiterr = "yes" *) reg injectdbiterrb_i;
|
|
|
|
// Declare injecterr inputs to synth ANDed with LSB data
|
|
(* keep = "yes" *) wire inj_sbiterrb_to_synth;
|
|
(* keep = "yes" *) wire inj_dbiterrb_to_synth;
|
|
if(`MEM_AUTO_SLP_EN) begin : gen_aslp_dly_inj_err
|
|
// Auto Sleep pipe line delays on the error inject signals
|
|
reg injsbiterrb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
reg injdbiterrb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
|
|
// Initialize the error injection pipelines
|
|
initial begin
|
|
integer aslp_initstage_b;
|
|
for (aslp_initstage_b=0; aslp_initstage_b<AUTO_SLEEP_TIME; aslp_initstage_b=aslp_initstage_b+1) begin : for_injerr_pipe_init
|
|
injsbiterrb_aslp_pipe[aslp_initstage_b] = 1'b0;
|
|
injdbiterrb_aslp_pipe[aslp_initstage_b] = 1'b0;
|
|
end : for_injerr_pipe_init
|
|
end
|
|
// Connect the user inputs to the pipeline
|
|
always @(posedge clkb_int) begin
|
|
injsbiterrb_aslp_pipe[0] <= injectsbiterrb;
|
|
injdbiterrb_aslp_pipe[0] <= injectdbiterrb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clkb_int) begin
|
|
injsbiterrb_aslp_pipe[aslp_stage] <= injsbiterrb_aslp_pipe[aslp_stage-1];
|
|
injdbiterrb_aslp_pipe[aslp_stage] <= injdbiterrb_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
assign injectsbiterrb_i = injsbiterrb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
assign injectdbiterrb_i = injdbiterrb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_dly_inj_err
|
|
else begin : gen_naslp_dly_inj_err
|
|
assign injectsbiterrb_i = injectsbiterrb;
|
|
assign injectdbiterrb_i = injectdbiterrb;
|
|
end : gen_naslp_dly_inj_err
|
|
//Assignment to error Injection signals passed to synthesis
|
|
assign inj_sbiterrb_to_synth = injectsbiterrb_i & dinb_i[0];
|
|
assign inj_dbiterrb_to_synth = injectdbiterrb_i & dinb_i[0];
|
|
end : err_inj_ecc
|
|
end : gen_wr_b
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Black Box Instantiation
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
if(`DISABLE_SYNTH_TEMPL) begin : gen_blk_box
|
|
// Delayed ports(with auto sleep latency) are not connected to this module, as this module is used
|
|
// for asymmetry and URAM does not support asymmetry
|
|
if(`COMMON_CLOCK) begin : gen_bb_sync
|
|
asym_bwe_bb # (
|
|
// Common module parameters
|
|
.MEMORY_TYPE (MEMORY_TYPE ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (MEMORY_PRIMITIVE ),
|
|
.CLOCKING_MODE (0 ), // Common Clock
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.WAKEUP_TIME (WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH_A),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (BYTE_WRITE_WIDTH_A),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (WRITE_MODE_A ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (WRITE_DATA_WIDTH_B),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.BYTE_WRITE_WIDTH_B (BYTE_WRITE_WIDTH_B),
|
|
.ADDR_WIDTH_B (ADDR_WIDTH_B ),
|
|
.READ_RESET_VALUE_B (READ_RESET_VALUE_B),
|
|
.READ_LATENCY_B (READ_LATENCY_B ),
|
|
.WRITE_MODE_B (WRITE_MODE_B ),
|
|
.RST_MODE_B (RST_MODE_B )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (wea ),
|
|
.addra (addra ),
|
|
.dina (dina ),
|
|
.douta (douta_bb ),
|
|
|
|
// Port B module ports
|
|
.clkb (clka ),
|
|
.rstb (rstb ),
|
|
.enb (enb ),
|
|
.regceb (regceb ),
|
|
.web (web ),
|
|
.addrb (addrb ),
|
|
.dinb (dinb ),
|
|
.doutb (doutb_bb )
|
|
);
|
|
end : gen_bb_sync
|
|
else begin : gen_bb_async
|
|
asym_bwe_bb # (
|
|
// Common module parameters
|
|
.MEMORY_TYPE (MEMORY_TYPE ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (MEMORY_PRIMITIVE ),
|
|
.CLOCKING_MODE (1 ), // Independent Clock
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.WAKEUP_TIME (WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH_A),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (BYTE_WRITE_WIDTH_A),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (WRITE_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (WRITE_DATA_WIDTH_B),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.BYTE_WRITE_WIDTH_B (BYTE_WRITE_WIDTH_B),
|
|
.ADDR_WIDTH_B (ADDR_WIDTH_B ),
|
|
.READ_RESET_VALUE_B (READ_RESET_VALUE_B),
|
|
.READ_LATENCY_B (READ_LATENCY_B ),
|
|
.WRITE_MODE_B (WRITE_MODE_B )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (wea ),
|
|
.addra (addra ),
|
|
.dina (dina ),
|
|
.douta (douta_bb ),
|
|
|
|
// Port B module ports
|
|
.clkb (clkb ),
|
|
.rstb (rstb ),
|
|
.enb (enb ),
|
|
.regceb (regceb ),
|
|
.web (web ),
|
|
.addrb (addrb ),
|
|
.dinb (dinb ),
|
|
.doutb (doutb_bb )
|
|
);
|
|
end : gen_bb_async
|
|
end : gen_blk_box
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Port A read
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
// If the memory type is single port RAM, true dual port RAM, or any ROM, generate a port A read process
|
|
if (`MEM_PORTA_READ) begin : gen_rd_a
|
|
localparam READ_DATA_WIDTH_A_ECC = `NO_ECC ? READ_DATA_WIDTH_A : P_MIN_WIDTH_DATA_ECC;
|
|
wire [P_WIDTH_ADDR_READ_A-1:0] addra_int = addra_i;
|
|
reg [READ_DATA_WIDTH_A_ECC-1:0] douta_reg;
|
|
localparam logic [READ_DATA_WIDTH_A_ECC-1:0] rsta_val = `ASYNC_RESET_A ? {READ_DATA_WIDTH_A_ECC{1'b0}} : rst_val_conv_a(READ_RESET_VALUE_A);
|
|
reg sbiterra_i = 1'b0 ;
|
|
reg dbiterra_i = 1'b0 ;
|
|
|
|
initial begin
|
|
if (`MEM_PORTA_RD_REG) begin : init_rstval
|
|
douta_reg = rsta_val;
|
|
end : init_rstval
|
|
else if (`MEM_PORTA_RD_PIPE && `MEM_PORTA_NC) begin : init_rstval_NC
|
|
douta_reg = rsta_val;
|
|
end : init_rstval_NC
|
|
else if (`MEM_PORTA_RD_PIPE && (`MEM_PORTA_WF || `MEM_PORTA_RF)) begin : init_zero
|
|
douta_reg = {READ_DATA_WIDTH_A_ECC{1'b0}};
|
|
end : init_zero
|
|
end
|
|
if (!`DISABLE_SYNTH_TEMPL) begin : gen_rd_a_synth_template
|
|
// Asynchronous port A read; port width is the narrowest of the data ports; no output pipeline
|
|
if (`MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_COMB) begin : gen_narrow_comb
|
|
always @(*) begin
|
|
douta_reg = mem[addra_int];
|
|
end
|
|
end : gen_narrow_comb
|
|
|
|
// Asynchronous port A read; port width is wider than at least one other data port; no output pipeline
|
|
else if (`MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_COMB) begin : gen_wide_comb
|
|
always @(*) begin : rd_comb
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
douta_reg[`ONE_ROW_OF_DIN] = mem[{addra_int, addralsb}];
|
|
end : for_mem_rows
|
|
end : rd_comb
|
|
end : gen_wide_comb
|
|
|
|
// Synchronous port A write-first read; port width is the narrowest of the data ports; no output pipeline
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_REG && `MEM_PORTA_WR_WORD) begin : gen_wf_narrow_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin
|
|
if (rsta)
|
|
douta_reg <= rsta_val;
|
|
else begin
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
douta_reg <= dina_i;
|
|
else
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin
|
|
if (rsta)
|
|
douta_reg <= rsta_val;
|
|
else begin
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
douta_reg <= dina_i;
|
|
else
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : gen_wf_narrow_reg
|
|
|
|
// Synchronous port A write-first read; port width is the narrowest of the data ports; no output pipeline;
|
|
// symmetric byte-wide write special case
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_REG &&
|
|
`MEM_PORTA_WR_NARROW && `MEM_PORTA_WR_BYTE) begin : gen_wf_narrow_reg_sym_byte
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin : for_mem_cols
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : wr_sync
|
|
if (rsta)
|
|
douta_reg[`ONE_COL_OF_DINA] <= rsta_val[`ONE_COL_OF_DINA];
|
|
else begin
|
|
if (ena_i) begin
|
|
if (wea_i[col])
|
|
douta_reg[`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
else
|
|
douta_reg[`ONE_COL_OF_DINA] <= mem[addra_int][`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end : wr_sync
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : wr_sync
|
|
if (rsta)
|
|
douta_reg[`ONE_COL_OF_DINA] <= rsta_val[`ONE_COL_OF_DINA];
|
|
else begin
|
|
if (ena_i) begin
|
|
if (wea_i[col])
|
|
douta_reg[`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
else
|
|
douta_reg[`ONE_COL_OF_DINA] <= mem[addra_int][`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end : wr_sync
|
|
end
|
|
end : for_mem_cols
|
|
end : gen_wf_narrow_reg_sym_byte
|
|
|
|
// Synchronous port A write-first read; port width is the narrowest of the data ports; output pipeline
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_PIPE && `MEM_PORTA_WR_WORD) begin : gen_wf_narrow_pipe
|
|
always @(posedge clka) begin
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
douta_reg <= dina_i;
|
|
else
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end : gen_wf_narrow_pipe
|
|
|
|
// Synchronous port A write-first read; port width is the narrowest of the data ports; output pipeline;
|
|
// symmetric byte-wide write special case
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_PIPE &&
|
|
`MEM_PORTA_WR_NARROW && `MEM_PORTA_WR_BYTE) begin : gen_wf_narrow_pipe_sym_byte
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin : for_mem_cols
|
|
always @(posedge clka) begin : wr_sync
|
|
if (ena_i) begin
|
|
if (wea_i[col])
|
|
douta_reg[`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
else
|
|
douta_reg[`ONE_COL_OF_DINA] <= mem[addra_int][`ONE_COL_OF_DINA];
|
|
end
|
|
end : wr_sync
|
|
end : for_mem_cols
|
|
end : gen_wf_narrow_pipe_sym_byte
|
|
|
|
// Synchronous port A write-first read; port width is wider than at least one other data port; no output pipeline;
|
|
// write and read combined special case
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_REG) begin : gen_wf_wide_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (rsta)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= rsta_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= dina_i[`ONE_ROW_OF_DIN];
|
|
else
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (rsta)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= rsta_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= dina_i[`ONE_ROW_OF_DIN];
|
|
else
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end
|
|
end : gen_wf_wide_reg
|
|
|
|
// Synchronous port A write-first read; port width is wider than at least one other data port; output pipeline;
|
|
// write and read combined special case
|
|
else if (`MEM_PORTA_WF && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_PIPE) begin : gen_wf_wide_pipe
|
|
always @(posedge clka) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (ena_i) begin
|
|
if (wea_i)
|
|
mem[{addra_int, addralsb}] = dina_i[`ONE_ROW_OF_DIN];
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end : gen_wf_wide_pipe
|
|
|
|
// Synchronous port A read-first read; port width is the narrowest of the data ports; no output pipeline
|
|
else if (`MEM_PORTA_RF && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_REG) begin : gen_rf_narrow_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin
|
|
if (rsta)
|
|
douta_reg <= rsta_val;
|
|
else begin
|
|
if (ena_i)
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin
|
|
if (rsta)
|
|
douta_reg <= rsta_val;
|
|
else begin
|
|
if (ena_i)
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end
|
|
end : gen_rf_narrow_reg
|
|
|
|
// Synchronous port A read-first read; port width is the narrowest of the data ports; output pipeline
|
|
else if (`MEM_PORTA_RF && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_PIPE) begin : gen_rf_narrow_pipe
|
|
always @(posedge clka) begin
|
|
if (ena_i)
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end : gen_rf_narrow_pipe
|
|
|
|
// Synchronous port A read-first read; port width is wider than at least one other data port; no output pipeline
|
|
else if (`MEM_PORTA_RF && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_REG) begin : gen_rf_wide_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (rsta)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= rsta_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (ena_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (rsta)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= rsta_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (ena_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
end : gen_rf_wide_reg
|
|
|
|
// Synchronous port A read-first read; port width is wider than at least one other data port; output pipeline
|
|
else if (`MEM_PORTA_RF && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_PIPE) begin : gen_rf_wide_pipe
|
|
always @(posedge clka) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (ena_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end : gen_rf_wide_pipe
|
|
|
|
// Synchronous port A no-change read; port width is the narrowest of the data ports; no output pipeline
|
|
else if (`MEM_PORTA_NC && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_REG) begin : gen_nc_narrow_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin
|
|
if (rsta)
|
|
douta_reg <= rsta_val;
|
|
else begin
|
|
if (ena_i) begin
|
|
if (~|wea_i)
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin
|
|
if (rsta)
|
|
douta_reg <= rsta_val;
|
|
else begin
|
|
if (ena_i) begin
|
|
if (~|wea_i)
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : gen_nc_narrow_reg
|
|
|
|
// Synchronous port A no-change read; port width is the narrowest of the data ports; output pipeline
|
|
else if (`MEM_PORTA_NC && `MEM_PORTA_RD_NARROW && `MEM_PORTA_RD_PIPE) begin : gen_nc_narrow_pipe
|
|
always @(posedge clka) begin
|
|
if (ena_i) begin
|
|
if (~|wea_i)
|
|
douta_reg <= mem[addra_int];
|
|
end
|
|
end
|
|
end : gen_nc_narrow_pipe
|
|
|
|
// Synchronous port A no-change read; port width is wider than at least one other data port; no output pipeline
|
|
else if (`MEM_PORTA_NC && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_REG) begin : gen_nc_wide_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (rsta)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= rsta_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (ena_i) begin
|
|
if (~|wea_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (rsta)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= rsta_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (ena_i) begin
|
|
if (~|wea_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
end : gen_nc_wide_reg
|
|
|
|
// Synchronous port A no-change read; port width is wider than at least one other data port; output pipeline
|
|
else if (`MEM_PORTA_NC && `MEM_PORTA_RD_WIDE && `MEM_PORTA_RD_PIPE) begin : gen_nc_wide_pipe
|
|
always @(posedge clka) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin : for_mem_rows
|
|
addralsb = row;
|
|
if (ena_i) begin
|
|
if (~|wea_i)
|
|
douta_reg[`ONE_ROW_OF_DIN] <= mem[{addra_int, addralsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end : gen_nc_wide_pipe
|
|
end : gen_rd_a_synth_template
|
|
else begin : gen_rd_a_synth_black_box
|
|
always @(*) begin
|
|
douta_reg = douta_bb;
|
|
end
|
|
end : gen_rd_a_synth_black_box
|
|
|
|
// If no output pipeline is used, then the enabled read process directly drives the data output port
|
|
if (`MEM_PORTA_RD_COMB || `MEM_PORTA_RD_REG) begin : gen_douta
|
|
assign douta = douta_reg;
|
|
end : gen_douta
|
|
|
|
// If an output pipeline is used, generate it
|
|
else if (`MEM_PORTA_RD_PIPE) begin : gen_douta_pipe
|
|
reg ena_pipe [READ_LATENCY_A-2:0];
|
|
reg [READ_DATA_WIDTH_A_ECC-1:0] douta_pipe [READ_LATENCY_A-2:0];
|
|
|
|
always @(posedge clka) begin
|
|
ena_pipe[0] <= ena_o_pipe_ctrl;
|
|
end
|
|
|
|
// Initialize the final output pipeline stage to the specified reset value, and all prior stages to zero
|
|
initial begin
|
|
integer initstage;
|
|
for (initstage=0; initstage<READ_LATENCY_A-1; initstage=initstage+1) begin : for_pipe_init
|
|
if (initstage < READ_LATENCY_A-2 && (`MEM_PORTA_WF || `MEM_PORTA_RF)) begin : init_zero
|
|
douta_pipe[initstage] = {READ_DATA_WIDTH_A{1'b0}};
|
|
end : init_zero
|
|
else if (initstage < READ_LATENCY_A-2 && `MEM_PORTA_NC) begin : init_rstval_NC
|
|
douta_pipe[initstage] = rsta_val;
|
|
end : init_rstval_NC
|
|
else begin : init_rstval
|
|
douta_pipe[initstage] = rsta_val;
|
|
end : init_rstval
|
|
end : for_pipe_init
|
|
end
|
|
|
|
// If two stages are used, the synchronous read output drives the final pipeline stage
|
|
if (READ_LATENCY_A == 2) begin : gen_stage
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin
|
|
if (rsta)
|
|
douta_pipe[0] <= rsta_val;
|
|
else begin
|
|
if (regcea_i)
|
|
douta_pipe[0] <= douta_reg;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin
|
|
if (rsta)
|
|
douta_pipe[0] <= rsta_val;
|
|
else begin
|
|
if (regcea_i)
|
|
douta_pipe[0] <= douta_reg;
|
|
end
|
|
end
|
|
end
|
|
end : gen_stage
|
|
|
|
// If more than two stages are used, loops generate all pipeline stages except the first and last
|
|
else if (READ_LATENCY_A > 2) begin : gen_stages
|
|
always @(posedge clka) begin
|
|
if (ena_pipe[0])
|
|
douta_pipe[0] <= douta_reg;
|
|
end
|
|
|
|
for (genvar estage=1; estage<READ_LATENCY_A-1; estage=estage+1) begin : gen_epipe
|
|
always @(posedge clka) begin
|
|
ena_pipe[estage] <= ena_pipe[estage-1];
|
|
end
|
|
end : gen_epipe
|
|
|
|
for (genvar dstage=1; dstage<READ_LATENCY_A-2; dstage=dstage+1) begin : gen_dpipe
|
|
always @(posedge clka) begin
|
|
if (ena_pipe[dstage])
|
|
douta_pipe[dstage] <= douta_pipe[dstage-1];
|
|
end
|
|
end : gen_dpipe
|
|
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin
|
|
if (rsta)
|
|
douta_pipe[READ_LATENCY_A-2] <= rsta_val;
|
|
else begin
|
|
if (regcea_i)
|
|
douta_pipe[READ_LATENCY_A-2] <= douta_pipe[READ_LATENCY_A-3];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin
|
|
if (rsta)
|
|
douta_pipe[READ_LATENCY_A-2] <= rsta_val;
|
|
else begin
|
|
if (regcea_i)
|
|
douta_pipe[READ_LATENCY_A-2] <= douta_pipe[READ_LATENCY_A-3];
|
|
end
|
|
end
|
|
end
|
|
end : gen_stages
|
|
|
|
// The final pipeline stage drives the data output port
|
|
assign douta = douta_pipe[READ_LATENCY_A-2];
|
|
end : gen_douta_pipe
|
|
if(ECC_MODE == 2 || ECC_MODE == 3) begin : pipeline_ecc_status
|
|
// Error status signals (should be pipelined along with the data)
|
|
if (`MEM_PORTA_READ && (`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO)) begin : status_out_proc_a
|
|
// ECC status signal declarations
|
|
(* keep = "yes", xpm_ecc_sbiterr = "yes"*) wire sbiterra_ram;
|
|
(* keep = "yes", xpm_ecc_dbiterr = "yes"*) wire dbiterra_ram;
|
|
reg sbiterra_in_pipe;
|
|
reg dbiterra_in_pipe;
|
|
|
|
// WRITE_FIRST Mode
|
|
if (`MEM_PORTA_WF && `MEM_PORTA_RD_REG) begin : ecc_status_wf_reg
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
sbiterra_in_pipe <= 1'b0;
|
|
dbiterra_in_pipe <= 1'b0;
|
|
end
|
|
else if (ena_i) begin
|
|
sbiterra_in_pipe <= sbiterra_ram;
|
|
dbiterra_in_pipe <= dbiterra_ram;
|
|
end
|
|
end
|
|
end : ecc_status_wf_reg
|
|
|
|
if (`MEM_PORTA_WF && `MEM_PORTA_RD_PIPE) begin : ecc_status_wf_pipe
|
|
always @(posedge clka) begin
|
|
if (ena_i) begin
|
|
sbiterra_in_pipe <= sbiterra_ram;
|
|
dbiterra_in_pipe <= dbiterra_ram;
|
|
end
|
|
end
|
|
end : ecc_status_wf_pipe
|
|
|
|
// READ_FIRST Mode
|
|
if (`MEM_PORTA_RF && `MEM_PORTA_RD_REG) begin : ecc_status_rf_reg
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
sbiterra_in_pipe <= 1'b0;
|
|
dbiterra_in_pipe <= 1'b0;
|
|
end
|
|
else if (ena_i) begin
|
|
sbiterra_in_pipe <= sbiterra_ram;
|
|
dbiterra_in_pipe <= dbiterra_ram;
|
|
end
|
|
end
|
|
end : ecc_status_rf_reg
|
|
|
|
if (`MEM_PORTA_RF && `MEM_PORTA_RD_PIPE) begin : ecc_status_rf_pipe
|
|
always @(posedge clka) begin
|
|
if (ena_i) begin
|
|
sbiterra_in_pipe <= sbiterra_ram;
|
|
dbiterra_in_pipe <= dbiterra_ram;
|
|
end
|
|
end
|
|
end : ecc_status_rf_pipe
|
|
|
|
// NO_CHANGE Mode
|
|
if (`MEM_PORTA_NC && `MEM_PORTA_RD_REG) begin : ecc_status_nc_reg
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
sbiterra_in_pipe <= 1'b0;
|
|
dbiterra_in_pipe <= 1'b0;
|
|
end
|
|
else if (ena_i) begin
|
|
if(~(|wea_i)) begin
|
|
sbiterra_in_pipe <= sbiterra_ram;
|
|
dbiterra_in_pipe <= dbiterra_ram;
|
|
end
|
|
end
|
|
end
|
|
end : ecc_status_nc_reg
|
|
|
|
if (`MEM_PORTA_NC && `MEM_PORTA_RD_PIPE) begin : ecc_status_nc_pipe
|
|
always @(posedge clka) begin
|
|
if (ena_i) begin
|
|
if(~(|wea_i)) begin
|
|
sbiterra_in_pipe <= sbiterra_ram;
|
|
dbiterra_in_pipe <= dbiterra_ram;
|
|
end
|
|
end
|
|
end
|
|
end : ecc_status_nc_pipe
|
|
|
|
if (READ_LATENCY_A >= 2) begin : ecc_status_a_pipe
|
|
reg sbiterra_pipe [READ_LATENCY_A-2:0];
|
|
reg dbiterra_pipe [READ_LATENCY_A-2:0];
|
|
if (READ_LATENCY_A == 2) begin : RL_2_dly_err_status
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
sbiterra_i <= 1'b0;
|
|
dbiterra_i <= 1'b0;
|
|
end
|
|
else if (regcea_i) begin
|
|
sbiterra_i <= sbiterra_in_pipe;
|
|
dbiterra_i <= dbiterra_in_pipe;
|
|
end
|
|
end
|
|
end : RL_2_dly_err_status
|
|
|
|
if (READ_LATENCY_A > 2) begin : RL_gr_2_dly_err_status
|
|
reg ena_ecc_pipe [READ_LATENCY_A-2:0];
|
|
always @(posedge clka) begin
|
|
ena_ecc_pipe[0] <= ena_o_pipe_ctrl;
|
|
end
|
|
|
|
for (genvar ecc_estage_a=1; ecc_estage_a<READ_LATENCY_A-1; ecc_estage_a=ecc_estage_a+1) begin : gen_epipe
|
|
always @(posedge clka) begin
|
|
ena_ecc_pipe[ecc_estage_a] <= ena_ecc_pipe[ecc_estage_a-1];
|
|
end
|
|
end : gen_epipe
|
|
|
|
always @(posedge clka) begin
|
|
if(ena_ecc_pipe[0]) begin
|
|
sbiterra_pipe[0] <= sbiterra_in_pipe;
|
|
dbiterra_pipe[0] <= dbiterra_in_pipe;
|
|
end
|
|
end
|
|
for (genvar ecc_errstage_a=1; ecc_errstage_a<READ_LATENCY_A-2; ecc_errstage_a=ecc_errstage_a+1) begin : porta_gen_ecc_epipe
|
|
always @(posedge clka) begin
|
|
if (ena_ecc_pipe[ecc_errstage_a]) begin
|
|
sbiterra_pipe[ecc_errstage_a] <= sbiterra_pipe[ecc_errstage_a-1];
|
|
dbiterra_pipe[ecc_errstage_a] <= dbiterra_pipe[ecc_errstage_a-1];
|
|
end
|
|
end
|
|
end : porta_gen_ecc_epipe
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
sbiterra_i <= 1'b0;
|
|
dbiterra_i <= 1'b0;
|
|
end
|
|
else if (regcea_i) begin
|
|
sbiterra_i <= sbiterra_pipe[READ_LATENCY_A-3];
|
|
dbiterra_i <= dbiterra_pipe[READ_LATENCY_A-3];
|
|
end
|
|
end
|
|
end : RL_gr_2_dly_err_status
|
|
end : ecc_status_a_pipe
|
|
else begin :ecc_status_a_reg
|
|
always @(*) begin
|
|
sbiterra_i = sbiterra_in_pipe;
|
|
dbiterra_i = dbiterra_in_pipe;
|
|
end
|
|
end : ecc_status_a_reg
|
|
end : status_out_proc_a
|
|
end : pipeline_ecc_status
|
|
else begin : no_ecc_err_status
|
|
// always_comb begin
|
|
// sbiterra_i = 0;
|
|
// dbiterra_i = 0;
|
|
// end
|
|
end : no_ecc_err_status
|
|
// Assign Output signals
|
|
assign sbiterra = sbiterra_i;
|
|
assign dbiterra = dbiterra_i;
|
|
end : gen_rd_a
|
|
|
|
// If a port A read process is not generated, drive the data output port to a constant zero
|
|
else begin : gen_no_rd_a
|
|
assign douta = {READ_DATA_WIDTH_A{1'b0}};
|
|
assign sbiterra = 1'b0;
|
|
assign dbiterra = 1'b0;
|
|
end : gen_no_rd_a
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Port B read
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
// If the memory type is simple dual port RAM, true dual port RAM, or dual port ROM, generate a port B read process
|
|
if (`MEM_PORTB_READ) begin : gen_rd_b
|
|
wire clkb_int;
|
|
|
|
// In true dual port UltraRAM configurations, use the port A clock delayed by a small amount to model the port B
|
|
// synchronous processes; although both ports share a common clock, port B operations occur after port A operations
|
|
if (`COMMON_CLOCK && `MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin : gen_uram_tdp_common_clock
|
|
assign clkb_int = clka;
|
|
end : gen_uram_tdp_common_clock
|
|
|
|
// In all other common clocking configurations, use the port A clock for port B synchronous processes
|
|
else if (`COMMON_CLOCK) begin : gen_common_clock
|
|
assign clkb_int = clka;
|
|
end : gen_common_clock
|
|
|
|
// In independent clocking configurations, use the port B clock for port B synchronous processes
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_independent_clocks
|
|
assign clkb_int = clkb;
|
|
end : gen_independent_clocks
|
|
|
|
localparam READ_DATA_WIDTH_B_ECC = `NO_ECC ? READ_DATA_WIDTH_B : P_MIN_WIDTH_DATA_ECC;
|
|
wire [P_WIDTH_ADDR_READ_B-1:0] addrb_int = addrb_i;
|
|
localparam EMB_XDC = USE_EMBEDDED_CONSTRAINT ? "yes" : "no";
|
|
(* dram_emb_xdc = EMB_XDC *) reg [READ_DATA_WIDTH_B_ECC-1:0] doutb_reg;
|
|
localparam logic [READ_DATA_WIDTH_B_ECC-1:0] rstb_val = `ASYNC_RESET_B ? {READ_DATA_WIDTH_B_ECC{1'b0}} : rst_val_conv_b(READ_RESET_VALUE_B);
|
|
// ECC error status signals
|
|
reg sbiterrb_i = 1'b0 ;
|
|
reg dbiterrb_i = 1'b0 ;
|
|
|
|
// Initialize doutb_reg to the specified reset value if it is the only output register, or to zero if an output
|
|
// pipeline is used
|
|
initial begin
|
|
if (`MEM_PORTB_RD_REG) begin : init_rstval
|
|
doutb_reg = rstb_val;
|
|
end : init_rstval
|
|
else if (`MEM_PORTB_RD_PIPE && `MEM_PORTB_NC) begin : init_rstval_NC
|
|
doutb_reg = rstb_val;
|
|
end : init_rstval_NC
|
|
else if (`MEM_PORTB_RD_PIPE && (`MEM_PORTB_WF || `MEM_PORTB_RF)) begin : init_zero
|
|
doutb_reg = {READ_DATA_WIDTH_B_ECC{1'b0}};
|
|
end : init_zero
|
|
end
|
|
if (!`DISABLE_SYNTH_TEMPL) begin : gen_rd_b_synth_template
|
|
// Asynchronous port B read; port width is the narrowest of the data ports; no output pipeline
|
|
if (`MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_COMB) begin : gen_narrow_comb
|
|
always @(*) begin
|
|
doutb_reg = mem[addrb_int];
|
|
end
|
|
end : gen_narrow_comb
|
|
|
|
// Asynchronous port B read; port width is wider than at least one other data port; no output pipeline
|
|
else if (`MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_COMB) begin : gen_wide_comb
|
|
always @(*) begin : rd_comb
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
doutb_reg[`ONE_ROW_OF_DIN] = mem[{addrb_int, addrblsb}];
|
|
end : for_mem_rows
|
|
end : rd_comb
|
|
end : gen_wide_comb
|
|
|
|
// Synchronous port B write-first read; port width is the narrowest of the data ports; no output pipeline
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_REG && `MEM_PORTB_WR_WORD) begin : gen_wf_narrow_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_reg <= rstb_val;
|
|
else begin
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
doutb_reg <= dinb_i;
|
|
else
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_reg <= rstb_val;
|
|
else begin
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
doutb_reg <= dinb_i;
|
|
else
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : gen_wf_narrow_reg
|
|
|
|
// Synchronous port B write-first read; port width is the narrowest of the data ports; no output pipeline;
|
|
// symmetric byte-wide write special case
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_REG &&
|
|
`MEM_PORTB_WR_NARROW && `MEM_PORTB_WR_BYTE) begin : gen_wf_narrow_reg_sym_byte
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin : for_mem_cols
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin : wr_sync
|
|
if (rstb)
|
|
doutb_reg[`ONE_COL_OF_DINB] <= rstb_val[`ONE_COL_OF_DINB];
|
|
else begin
|
|
if (enb_i) begin
|
|
if (web_i[col])
|
|
doutb_reg[`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
else
|
|
doutb_reg[`ONE_COL_OF_DINB] <= mem[addrb_int][`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end : wr_sync
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin : wr_sync
|
|
if (rstb)
|
|
doutb_reg[`ONE_COL_OF_DINB] <= rstb_val[`ONE_COL_OF_DINB];
|
|
else begin
|
|
if (enb_i) begin
|
|
if (web_i[col])
|
|
doutb_reg[`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
else
|
|
doutb_reg[`ONE_COL_OF_DINB] <= mem[addrb_int][`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end : wr_sync
|
|
end
|
|
end : for_mem_cols
|
|
end : gen_wf_narrow_reg_sym_byte
|
|
|
|
// Synchronous port B write-first read; port width is the narrowest of the data ports; output pipeline;
|
|
// UltraRAM simple dual port RAM special case
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_PIPE &&
|
|
`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_SDP) begin : gen_wf_narrow_pipe_ultra_sdp
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_reg = {P_WIDTH_ADDR_WRITE_B{1'b0}};
|
|
always @(posedge clkb_int) begin
|
|
addrb_reg <= addrb_int;
|
|
end
|
|
always @(*) begin
|
|
doutb_reg = mem[addrb_reg];
|
|
end
|
|
end : gen_wf_narrow_pipe_ultra_sdp
|
|
|
|
// Synchronous port B write-first read; port width is the wider of the data ports; output pipeline;
|
|
// UltraRAM simple dual port RAM special case
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_PIPE &&
|
|
`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_SDP) begin : gen_wf_wide_pipe_ultra_sdp
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_reg = {P_WIDTH_ADDR_WRITE_B{1'b0}};
|
|
always @(posedge clkb_int) begin
|
|
addrb_reg <= addrb_int;
|
|
end
|
|
always @(*) begin : rd_comb
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
doutb_reg[`ONE_ROW_OF_DIN] = mem[{addrb_reg, addrblsb}];
|
|
end : for_mem_rows
|
|
end : rd_comb
|
|
end : gen_wf_wide_pipe_ultra_sdp
|
|
|
|
|
|
// Synchronous port B write-first read; port width is the narrowest of the data ports; output pipeline
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_PIPE && `MEM_PORTB_WR_WORD) begin : gen_wf_narrow_pipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
doutb_reg <= dinb_i;
|
|
else
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end : gen_wf_narrow_pipe
|
|
|
|
// Synchronous port B write-first read; port width is the narrowest of the data ports; output pipeline;
|
|
// symmetric byte-wide write special case
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_PIPE &&
|
|
`MEM_PORTB_WR_NARROW && `MEM_PORTB_WR_BYTE) begin : gen_wf_narrow_pipe_sym_byte
|
|
for (genvar col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin : for_mem_cols
|
|
always @(posedge clkb_int) begin : wr_sync
|
|
if (enb_i) begin
|
|
if (web_i[col])
|
|
doutb_reg[`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
else
|
|
doutb_reg[`ONE_COL_OF_DINB] <= mem[addrb_int][`ONE_COL_OF_DINB];
|
|
end
|
|
end : wr_sync
|
|
end : for_mem_cols
|
|
end : gen_wf_narrow_pipe_sym_byte
|
|
|
|
// Synchronous port B write-first read; port width is wider than at least one other data port; no output pipeline;
|
|
// write and read combined special case
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_REG) begin : gen_wf_wide_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (rstb)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= rstb_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= dinb_i[`ONE_ROW_OF_DIN];
|
|
else
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (rstb)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= rstb_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= dinb_i[`ONE_ROW_OF_DIN];
|
|
else
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end
|
|
end : gen_wf_wide_reg
|
|
|
|
// Synchronous port B write-first read; port width is wider than at least one other data port; output pipeline;
|
|
// write and read combined special case
|
|
else if (`MEM_PORTB_WF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_PIPE) begin : gen_wf_wide_pipe
|
|
always @(posedge clkb_int) begin : wr_rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (enb_i) begin
|
|
if (web_i)
|
|
mem[{addrb_int, addrblsb}] = dinb_i[`ONE_ROW_OF_DIN];
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : wr_rd_sync
|
|
end : gen_wf_wide_pipe
|
|
|
|
// Synchronous port B read-first read; port width is the narrowest of the data ports; no output pipeline
|
|
else if (`MEM_PORTB_RF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_REG) begin : gen_rf_narrow_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_reg <= rstb_val;
|
|
else begin
|
|
if (enb_i)
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_reg <= rstb_val;
|
|
else begin
|
|
if (enb_i)
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end
|
|
end : gen_rf_narrow_reg
|
|
|
|
// Synchronous port B read-first read; port width is the narrowest of the data ports; output pipeline
|
|
else if (`MEM_PORTB_RF && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_PIPE) begin : gen_rf_narrow_pipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_i)
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end : gen_rf_narrow_pipe
|
|
|
|
// Synchronous port B read-first read; port width is wider than at least one other data port; no output pipeline
|
|
else if (`MEM_PORTB_RF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_REG) begin : gen_rf_wide_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (rstb)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= rstb_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (enb_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (rstb)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= rstb_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (enb_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
end : gen_rf_wide_reg
|
|
|
|
// Synchronous port B read-first read; port width is wider than at least one other data port; output pipeline
|
|
else if (`MEM_PORTB_RF && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_PIPE) begin : gen_rf_wide_pipe
|
|
always @(posedge clkb_int) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (enb_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end : gen_rf_wide_pipe
|
|
|
|
// Synchronous port B no-change read; port width is the narrowest of the data ports; no output pipeline
|
|
else if (`MEM_PORTB_NC && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_REG) begin : gen_nc_narrow_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_reg <= rstb_val;
|
|
else begin
|
|
if (enb_i) begin
|
|
if (~|web_i)
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_reg <= rstb_val;
|
|
else begin
|
|
if (enb_i) begin
|
|
if (~|web_i)
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : gen_nc_narrow_reg
|
|
|
|
// Synchronous port B no-change read; port width is the narrowest of the data ports; output pipeline
|
|
else if (`MEM_PORTB_NC && `MEM_PORTB_RD_NARROW && `MEM_PORTB_RD_PIPE) begin : gen_nc_narrow_pipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_i) begin
|
|
if (~|web_i)
|
|
doutb_reg <= mem[addrb_int];
|
|
end
|
|
end
|
|
end : gen_nc_narrow_pipe
|
|
|
|
// Synchronous port B no-change read; port width is wider than at least one other data port; no output pipeline
|
|
else if (`MEM_PORTB_NC && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_REG) begin : gen_nc_wide_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (rstb)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= rstb_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (enb_i) begin
|
|
if (~|web_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (rstb)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= rstb_val[`ONE_ROW_OF_DIN];
|
|
else begin
|
|
if (enb_i) begin
|
|
if (~|web_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end
|
|
end : gen_nc_wide_reg
|
|
|
|
// Synchronous port B no-change read; port width is wider than at least one other data port; output pipeline
|
|
else if (`MEM_PORTB_NC && `MEM_PORTB_RD_WIDE && `MEM_PORTB_RD_PIPE) begin : gen_nc_wide_pipe
|
|
always @(posedge clkb_int) begin : rd_sync
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
if (enb_i) begin
|
|
if (~|web_i)
|
|
doutb_reg[`ONE_ROW_OF_DIN] <= mem[{addrb_int, addrblsb}];
|
|
end
|
|
end : for_mem_rows
|
|
end : rd_sync
|
|
end : gen_nc_wide_pipe
|
|
end : gen_rd_b_synth_template
|
|
else begin : gen_rd_b_synth_black_box
|
|
always @(*) begin
|
|
doutb_reg = doutb_bb;
|
|
end
|
|
end : gen_rd_b_synth_black_box
|
|
// If no output pipeline is used, then the enabled read process directly drives the data output port
|
|
if (`MEM_PORTB_RD_COMB || `MEM_PORTB_RD_REG) begin : gen_doutb
|
|
assign doutb = doutb_reg;
|
|
end : gen_doutb
|
|
|
|
// If an output pipeline is used, generate it
|
|
else if (`MEM_PORTB_RD_PIPE) begin : gen_doutb_pipe
|
|
reg enb_pipe [READ_LATENCY_B-2:0];
|
|
reg [READ_DATA_WIDTH_B_ECC-1:0] doutb_pipe [READ_LATENCY_B-2:0];
|
|
|
|
always @(posedge clkb_int) begin
|
|
enb_pipe[0] <= enb_o_pipe_ctrl;
|
|
end
|
|
|
|
// Initialize the final output pipeline stage to the specified reset value, and all prior stages to zero
|
|
initial begin
|
|
integer initstage;
|
|
for (initstage=0; initstage<READ_LATENCY_B-1; initstage=initstage+1) begin : for_pipe_init
|
|
if (initstage < READ_LATENCY_B-2 && (`MEM_PORTB_WF || `MEM_PORTB_RF)) begin : init_zero
|
|
doutb_pipe[initstage] = {READ_DATA_WIDTH_B_ECC{1'b0}};
|
|
end : init_zero
|
|
else if (initstage < READ_LATENCY_B-2 && `MEM_PORTB_NC ) begin : init_rstval_NC
|
|
doutb_pipe[initstage] = rstb_val;
|
|
end : init_rstval_NC
|
|
else begin : init_rstval
|
|
doutb_pipe[initstage] = rstb_val;
|
|
end : init_rstval
|
|
end : for_pipe_init
|
|
end
|
|
|
|
// If two stages are used, the synchronous read output drives the final pipeline stage
|
|
if (READ_LATENCY_B == 2) begin : gen_stage
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_pipe[0] <= rstb_val;
|
|
else begin
|
|
if (regceb_i)
|
|
doutb_pipe[0] <= doutb_reg;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_pipe[0] <= rstb_val;
|
|
else begin
|
|
if (regceb_i)
|
|
doutb_pipe[0] <= doutb_reg;
|
|
end
|
|
end
|
|
end
|
|
end : gen_stage
|
|
|
|
// If more than two stages are used, loops generate all pipeline stages except the first and last
|
|
else if (READ_LATENCY_B > 2) begin : gen_stages
|
|
always @(posedge clkb_int) begin
|
|
if (enb_pipe[0])
|
|
doutb_pipe[0] <= doutb_reg;
|
|
end
|
|
|
|
for (genvar estage=1; estage<READ_LATENCY_B-1; estage=estage+1) begin : gen_epipe
|
|
always @(posedge clkb_int) begin
|
|
enb_pipe[estage] <= enb_pipe[estage-1];
|
|
end
|
|
end : gen_epipe
|
|
|
|
for (genvar dstage=1; dstage<READ_LATENCY_B-2; dstage=dstage+1) begin : gen_dpipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_pipe[dstage])
|
|
doutb_pipe[dstage] <= doutb_pipe[dstage-1];
|
|
end
|
|
end : gen_dpipe
|
|
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_pipe[READ_LATENCY_B-2] <= rstb_val;
|
|
else begin
|
|
if (regceb_i)
|
|
doutb_pipe[READ_LATENCY_B-2] <= doutb_pipe[READ_LATENCY_B-3];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int) begin
|
|
if (rstb)
|
|
doutb_pipe[READ_LATENCY_B-2] <= rstb_val;
|
|
else begin
|
|
if (regceb_i)
|
|
doutb_pipe[READ_LATENCY_B-2] <= doutb_pipe[READ_LATENCY_B-3];
|
|
end
|
|
end
|
|
end
|
|
end : gen_stages
|
|
|
|
// The final pipeline stage drives the data output port
|
|
assign doutb = doutb_pipe[READ_LATENCY_B-2];
|
|
end : gen_doutb_pipe
|
|
|
|
if(ECC_MODE == 2 || ECC_MODE == 3) begin : pipeline_ecc_status
|
|
(* keep = "yes", xpm_ecc_sbiterr = "yes"*) wire sbiterrb_ram;
|
|
(* keep = "yes", xpm_ecc_dbiterr = "yes"*) wire dbiterrb_ram;
|
|
reg sbiterrb_in_pipe;
|
|
reg dbiterrb_in_pipe;
|
|
|
|
// WRITE_FIRST Mode
|
|
// This mode is allowed only for Ultra RAM + SDP + RL > 3
|
|
if (`MEM_PORTB_WF) begin : ecc_status_wf_reg
|
|
always @(*) begin
|
|
sbiterrb_in_pipe <= sbiterrb_ram;
|
|
dbiterrb_in_pipe <= dbiterrb_ram;
|
|
end
|
|
end : ecc_status_wf_reg
|
|
|
|
// READ_FIRST Mode
|
|
if (`MEM_PORTB_RF && `MEM_PORTB_RD_REG) begin : ecc_status_rf_reg
|
|
always @(posedge clkb_int) begin
|
|
if(rstb) begin
|
|
sbiterrb_in_pipe <= 1'b0;
|
|
dbiterrb_in_pipe <= 1'b0;
|
|
end
|
|
else if (enb_i) begin
|
|
sbiterrb_in_pipe <= sbiterrb_ram;
|
|
dbiterrb_in_pipe <= dbiterrb_ram;
|
|
end
|
|
end
|
|
end : ecc_status_rf_reg
|
|
|
|
if (`MEM_PORTB_RF && `MEM_PORTB_RD_PIPE) begin : ecc_status_rf_pipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_i) begin
|
|
sbiterrb_in_pipe <= sbiterrb_ram;
|
|
dbiterrb_in_pipe <= dbiterrb_ram;
|
|
end
|
|
end
|
|
end : ecc_status_rf_pipe
|
|
|
|
// NO_CHANGE Mode
|
|
if (`MEM_PORTB_NC && `MEM_PORTB_RD_REG) begin : ecc_status_nc_reg
|
|
always @(posedge clkb_int) begin
|
|
if(rstb) begin
|
|
sbiterrb_in_pipe <= 1'b0;
|
|
dbiterrb_in_pipe <= 1'b0;
|
|
end
|
|
else if (enb_i) begin
|
|
if(~(|web_i)) begin
|
|
sbiterrb_in_pipe <= sbiterrb_ram;
|
|
dbiterrb_in_pipe <= dbiterrb_ram;
|
|
end
|
|
end
|
|
end
|
|
end : ecc_status_nc_reg
|
|
|
|
if (`MEM_PORTB_NC && `MEM_PORTB_RD_PIPE) begin : ecc_status_nc_pipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_i) begin
|
|
if(~(|web_i)) begin
|
|
sbiterrb_in_pipe <= sbiterrb_ram;
|
|
dbiterrb_in_pipe <= dbiterrb_ram;
|
|
end
|
|
end
|
|
end
|
|
end : ecc_status_nc_pipe
|
|
|
|
// Error status signals (should be pipelined along with the data)
|
|
if (READ_LATENCY_B >= 2) begin : ecc_status_b_pipe
|
|
reg sbiterrb_pipe [READ_LATENCY_B-2:0];
|
|
reg dbiterrb_pipe [READ_LATENCY_B-2:0];
|
|
|
|
if (READ_LATENCY_B == 2) begin : RL_2_dly_err_status
|
|
always @(posedge clkb_int) begin
|
|
if(rstb) begin
|
|
sbiterrb_i <= 1'b0;
|
|
dbiterrb_i <= 1'b0;
|
|
end
|
|
else if (regceb_i) begin
|
|
sbiterrb_i <= sbiterrb_in_pipe;
|
|
dbiterrb_i <= dbiterrb_in_pipe;
|
|
end
|
|
end
|
|
end : RL_2_dly_err_status
|
|
|
|
if (READ_LATENCY_B > 2) begin : RL_gr_2_dly_err_status
|
|
reg enb_ecc_pipe [READ_LATENCY_B-2:0];
|
|
always @(posedge clkb_int) begin
|
|
enb_ecc_pipe[0] <= enb_o_pipe_ctrl;
|
|
end
|
|
|
|
for (genvar ecc_estage_b=1; ecc_estage_b<READ_LATENCY_B-1; ecc_estage_b=ecc_estage_b+1) begin : gen_epipe
|
|
always @(posedge clkb_int) begin
|
|
enb_ecc_pipe[ecc_estage_b] <= enb_ecc_pipe[ecc_estage_b-1];
|
|
end
|
|
end : gen_epipe
|
|
|
|
always @(posedge clkb_int) begin
|
|
if (enb_ecc_pipe[0]) begin
|
|
sbiterrb_pipe[0] <= sbiterrb_in_pipe;
|
|
dbiterrb_pipe[0] <= dbiterrb_in_pipe;
|
|
end
|
|
end
|
|
for (genvar ecc_errstage_b=1; ecc_errstage_b<READ_LATENCY_B-2; ecc_errstage_b=ecc_errstage_b+1) begin : portb_gen_ecc_epipe
|
|
always @(posedge clkb_int) begin
|
|
if (enb_ecc_pipe[ecc_errstage_b]) begin
|
|
sbiterrb_pipe[ecc_errstage_b] <= sbiterrb_pipe[ecc_errstage_b-1];
|
|
dbiterrb_pipe[ecc_errstage_b] <= dbiterrb_pipe[ecc_errstage_b-1];
|
|
end
|
|
end
|
|
end : portb_gen_ecc_epipe
|
|
always @(posedge clkb_int) begin
|
|
if(rstb) begin
|
|
sbiterrb_i <= 1'b0;
|
|
dbiterrb_i <= 1'b0;
|
|
end
|
|
else if (regceb_i) begin
|
|
sbiterrb_i <= sbiterrb_pipe[READ_LATENCY_B-3];
|
|
dbiterrb_i <= dbiterrb_pipe[READ_LATENCY_B-3];
|
|
end
|
|
end
|
|
end : RL_gr_2_dly_err_status
|
|
end : ecc_status_b_pipe
|
|
else begin :ecc_status_b_reg
|
|
always @(*) begin
|
|
sbiterrb_i = sbiterrb_in_pipe;
|
|
dbiterrb_i = dbiterrb_in_pipe;
|
|
end
|
|
end : ecc_status_b_reg
|
|
end : pipeline_ecc_status
|
|
else begin : no_ecc_err_status
|
|
// always_comb begin
|
|
// sbiterrb_i = 0;
|
|
// dbiterrb_i = 0;
|
|
// end
|
|
end : no_ecc_err_status
|
|
// Assign to output signals
|
|
assign sbiterrb = sbiterrb_i;
|
|
assign dbiterrb = dbiterrb_i;
|
|
end : gen_rd_b
|
|
|
|
// If a port B read process is not generated, drive the data output port to a constant zero
|
|
else begin : gen_no_rd_b
|
|
assign doutb = {READ_DATA_WIDTH_B{1'b0}};
|
|
assign sbiterrb = 1'b0;
|
|
assign dbiterrb = 1'b0;
|
|
end : gen_no_rd_b
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Simulation constructs
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// synthesis translate_off
|
|
// Param to enable or disable the cover points/assertion checks
|
|
|
|
// Sleep related signals shall be used across the simulation model,
|
|
// so declaring them globally
|
|
reg sleep_int_a = 0; // sleep port registered on Port-A clock
|
|
reg sleep_int_b = 0; // sleep port registered on Port-B clock
|
|
wire [ADDR_WIDTH_A-1:0] addra_aslp_sim; // Delayed address in auto sleep mode that is
|
|
// used to check out of range addressing
|
|
wire [ADDR_WIDTH_B-1:0] addrb_aslp_sim;
|
|
|
|
// Internal wires to accomodate Auto sleep mode delays if enabled
|
|
wire injectsbiterra_sim;
|
|
wire injectdbiterra_sim;
|
|
wire injectsbiterrb_sim;
|
|
wire injectdbiterrb_sim;
|
|
|
|
initial begin
|
|
#1;
|
|
if (`REPORT_MESSAGES && (!`MEM_TYPE_RAM_TDP || !`MEM_TYPE_RAM_SDP || `MEM_PRIM_DISTRIBUTED || `MEM_PRIM_ULTRA))
|
|
$warning("MESSAGE_CONTROL (%0d) specifies simulation message reporting, but this release of XPM_MEMORY only reports messages for true dual port RAM and simple dual port RAM configurations which specify auto or block memory primitive types.", MESSAGE_CONTROL);
|
|
if (`REPORT_MESSAGES && (`MEM_TYPE_RAM_TDP || `MEM_TYPE_RAM_SDP) && !(`MEM_PRIM_DISTRIBUTED || `MEM_PRIM_ULTRA))
|
|
`ifdef OBSOLETE
|
|
$warning("Vivado Simulator does not currently support the SystemVerilog Assertion syntax used within XPM_MEMORY. Memory collisions will not be reported.");
|
|
`else
|
|
$info("MESSAGE_CONTROL (%0d) specifies simulation message reporting, this release of XPM_MEMORY reports messages for potential write-write and write-read collisions in this configuration.", MESSAGE_CONTROL);
|
|
`endif
|
|
end
|
|
|
|
// Simulation assertions warn of the effects when potential write-write, write-read collisions occur and illegal access to memory
|
|
`ifndef OBSOLETE
|
|
|
|
// The below message is to catch the out-of range address access for a write
|
|
// operation.
|
|
|
|
if (`REPORT_MESSAGES && `MEM_PORTA_WRITE && AUTO_SLEEP_TIME == 0 && !(`DISABLE_SYNTH_TEMPL)) begin : illegal_wr_ena
|
|
assert property (@(posedge clka)
|
|
!(ena === 1 && |wea && (addra > gen_wr_a.addra_int) ))
|
|
else
|
|
$warning("XPM_MEMORY_OUT_OF_RANGE_WRITE_ACCESS : Write Operation on Port-A to an out-of-range address at time %0t; Actual Address --> %0h , effective address is %0h.There is a chance that data at the effective address location may get written in the synthesis netlist, and there by the simulation mismatch can occur between behavioral model and netlist simulations", $time,addra,gen_wr_a.addra_int);
|
|
end : illegal_wr_ena
|
|
|
|
if (`REPORT_MESSAGES && `MEM_PORTB_WRITE && AUTO_SLEEP_TIME == 0 && !(`DISABLE_SYNTH_TEMPL)) begin : illegal_wr_enb
|
|
assert property (@(posedge gen_wr_b.clkb_int)
|
|
!(enb === 1 && |web && (addrb > gen_wr_b.addrb_int) ))
|
|
else
|
|
$warning("XPM_MEMORY_OUT_OF_RANGE_WRITE_ACCESS : Write Operation on Port-B to an out-of-range address at time %0t; Actual Address --> %0h , effective address is %0h.There is a chance that data at the effective address location may get written in the synthesis netlist, and there by the simulation mismatch can occur between behavioral model and netlist simulations", $time,addrb,gen_wr_b.addrb_int);
|
|
end : illegal_wr_enb
|
|
|
|
// In ECC Reset is not supported and these messages are not guarded under
|
|
// MESSAGE_CONTROL param, as these are critical.
|
|
|
|
if (!(`NO_ECC) && `MEM_PORTA_READ) begin : illegal_rsta_in_ecc
|
|
assert property (@(posedge clka)
|
|
!(rsta))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_RESET_IN_ECC_MODE : Attempt to reset the data output through Port-A at time %0t when ECC is enabled ; reset operation is not supported when ECC is enabled.", $time);
|
|
end : illegal_rsta_in_ecc
|
|
|
|
if (!(`NO_ECC) && `MEM_PORTB_READ) begin : illegal_rstb_in_ecc
|
|
assert property (@(posedge gen_rd_b.clkb_int)
|
|
!(rstb))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_RESET_IN_ECC_MODE : Attempt to reset the data output through Port-B at time %0t when ECC is enabled ; reset operation is not supported when ECC is enabled.", $time);
|
|
end : illegal_rstb_in_ecc
|
|
|
|
if (`REPORT_MESSAGES) begin : gen_assert_illegal_mem_access_w
|
|
// Assertion to catch illegal write access to the memory through port-B when
|
|
// the memory type is set to simple Dual port RAM
|
|
if (`MEM_TYPE_RAM_SDP) begin : illegal_mem_access_w_sdp
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_WRITE_SDP : Attempt to write to memory through Port-B at address 0x%0h at time %0t when the memory type is set to simple dual port RAM ; data outputs and memory content may be corrupted.", addrb, $time);
|
|
end : illegal_mem_access_w_sdp
|
|
// Assertion to catch illegal write access to the memory through port-A when
|
|
// the memory type is set to single port ROM/Dual Port ROM
|
|
if (`MEM_TYPE_ROM) begin : illegal_mem_access_w_rom
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_WRITE_ROM: Attempt to write to memory through Port-A at address 0x%0h at time %0t for ROM configuration ; data outputs and memory content may be corrupted.", addra, $time);
|
|
end : illegal_mem_access_w_rom
|
|
// Assertion to catch illegal write access to the memory through port-B when
|
|
// the memory type is set to Dual Port ROM
|
|
if (`MEM_TYPE_ROM_DP) begin : illegal_mem_access_w_dprom
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_WRITE_ROM: Attempt to write to memory through Port-B at address 0x%0h at time %0t for ROM configuration ; data outputs and memory content may be corrupted.", addrb, $time);
|
|
end : illegal_mem_access_w_dprom
|
|
|
|
// Assertion to catch illegal REGCE assertion after Reset
|
|
|
|
if(`MEM_PORTA_READ && `MEM_PORTA_RD_PIPE && `REPORT_MESSAGES) begin : illegal_regcea_after_rsta
|
|
reg flag_rst_regce_a = 1'b0;
|
|
// flag generation to capture the reset to valid enable duration
|
|
always @(posedge clka)
|
|
begin
|
|
if (rsta)
|
|
flag_rst_regce_a <= 1'b1;
|
|
else begin
|
|
if (gen_rd_a.gen_douta_pipe.ena_pipe[READ_LATENCY_A-2])
|
|
flag_rst_regce_a <= 1'b0;
|
|
end
|
|
end
|
|
// Assertion
|
|
assert property (@(posedge clka)
|
|
!(~rsta && regcea && flag_rst_regce_a))
|
|
else
|
|
$warning("regcea asserted at address 0x%0h at time %0t after reset without a valid read happened to the memory ; reset value on the output port maynot be preserved.", addra, $time);
|
|
end : illegal_regcea_after_rsta
|
|
|
|
if(`MEM_PORTB_READ && `MEM_PORTB_RD_PIPE && `REPORT_MESSAGES) begin : illegal_regcea_after_rstb
|
|
reg flag_rst_regce_b = 1'b0;
|
|
// flag generation to capture the reset to valid enable duration
|
|
always @(posedge clkb)
|
|
begin
|
|
if (rstb)
|
|
flag_rst_regce_b <= 1'b1;
|
|
else begin
|
|
if (gen_rd_b.gen_doutb_pipe.enb_pipe[READ_LATENCY_B-2])
|
|
flag_rst_regce_b <= 1'b0;
|
|
end
|
|
end
|
|
// Assertion
|
|
assert property (@(posedge clkb)
|
|
!(~rstb && regceb && flag_rst_regce_b))
|
|
else
|
|
$warning("regceb asserted at address 0x%0h at time %0t after reset without a valid read happened to the memory ; reset value on the output port maynot be preserved.", addrb, $time);
|
|
end : illegal_regcea_after_rstb
|
|
|
|
// Decode only mode can not have error injection
|
|
if (`DEC_ONLY) begin : illegal_injerr_dec_only
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_ERR_INJ_ASSRT: Attempt to inject single bit error into the memory through Port-A at address 0x%0h at time %0t in Decode only mode configuration ; Error injection is not allowed in Decode only mode.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_ERR_INJ_ASSRT: Attempt to inject double bit error into the memory through Port-A at address 0x%0h at time %0t in Decode only mode configuration ; Error injection is not allowed in Decode only mode.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_ERR_INJ_ASSRT: Attempt to inject single bit error into the memory through Port-B at address 0x%0h at time %0t in Decode only mode configuration ; Error injection is not allowed in Decode only mode.", addrb, $time);
|
|
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb))
|
|
else
|
|
$warning("XPM_MEMORY_ILLEGAL_ERR_INJ_ASSRT: Attempt to inject double bit error into the memory through Port-B at address 0x%0h at time %0t in Decode only mode configuration ; Error injection is not allowed in Decode only mode.", addrb, $time);
|
|
|
|
end : illegal_injerr_dec_only
|
|
|
|
end : gen_assert_illegal_mem_access_w
|
|
|
|
if ((`MEM_TYPE_RAM_TDP || `MEM_TYPE_RAM_SDP) && !(`MEM_PRIM_DISTRIBUTED || `MEM_PRIM_ULTRA)) begin : gen_assert_coll_ww
|
|
|
|
// When port A and port B use independent clocks, capture write transactions to detect collisions
|
|
reg wra = 1'b0;
|
|
reg wrb = 1'b0;
|
|
reg rda_cap = 1'b0;
|
|
reg rdb_cap = 1'b0;
|
|
reg [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea_cap = 'b0;
|
|
reg [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web_cap = 'b0;
|
|
reg [P_WIDTH_ADDR_WRITE_A-1:0] addra_cap = 'b0;
|
|
reg [P_WIDTH_ADDR_WRITE_A-1:0] addra_rd_cap = 'b0;
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_cap = 'b0;
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_rd_cap = 'b0;
|
|
|
|
/**************************************************************************************************
|
|
| Collision Minimum and Maximum window requirements |
|
|
| Minimum window requirement = 50 ps |
|
|
| Maximum window requirement --> |
|
|
| If the clock period is >= 3000 ps, then the window is 3000 ps |
|
|
| If the clock period is >50 ps < 3000 ps, then the window is "Clock period" ps |
|
|
**************************************************************************************************/
|
|
integer t_half_period_a = 3000;
|
|
integer t_half_period_b = 3000;
|
|
reg clk_prd_det_a = 0;
|
|
reg clk_prd_det_b = 0;
|
|
// Determine the clock periods
|
|
initial begin
|
|
@(posedge clka);
|
|
t_half_period_a = $time/1.0;
|
|
@ (negedge clka) t_half_period_a = $time/1.0 - t_half_period_a;
|
|
clk_prd_det_a <= 1;
|
|
end
|
|
initial begin
|
|
@(posedge clkb);
|
|
t_half_period_b = $time/1.0;
|
|
@ (negedge clkb) t_half_period_b = $time/1.0 - t_half_period_b;
|
|
clk_prd_det_b <= 1;
|
|
end
|
|
|
|
integer col_win_max = 0;
|
|
|
|
always @(clka or clkb) begin
|
|
if(~(clk_prd_det_a && clk_prd_det_b)) begin
|
|
if(t_half_period_a > 1500 && t_half_period_b > 1500)
|
|
col_win_max = 3000;
|
|
else if(t_half_period_a <= 1500 && t_half_period_a <= t_half_period_b)
|
|
col_win_max = 2 * t_half_period_a;
|
|
else if(t_half_period_b <= 1500 && t_half_period_b <= t_half_period_a)
|
|
col_win_max = 2 * t_half_period_b;
|
|
else
|
|
col_win_max = 500;
|
|
end
|
|
end
|
|
|
|
reg col_win_wr_a = 'b0;
|
|
reg col_win_rd_a = 'b0;
|
|
|
|
always @(posedge clka) begin
|
|
if(ena) begin
|
|
if(|wea) begin
|
|
col_win_wr_a <= 1'b1;
|
|
col_win_wr_a <= #(col_win_max) 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge clka) begin
|
|
if(ena) begin
|
|
if(~(|wea)) begin
|
|
col_win_rd_a <= 1'b1;
|
|
col_win_rd_a <= #(col_win_max) 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
reg col_win_wr_b = 'b0;
|
|
reg col_win_rd_b = 'b0;
|
|
|
|
always @(posedge clkb) begin
|
|
if(enb) begin
|
|
if(|web) begin
|
|
col_win_wr_b <= 1'b1;
|
|
col_win_wr_b <= #(col_win_max) 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge clkb) begin
|
|
if(enb) begin
|
|
if(~(|web)) begin
|
|
col_win_rd_b <= 1'b1;
|
|
col_win_rd_b <= #(col_win_max) 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
if (`INDEPENDENT_CLOCKS) begin : gen_wr_cap
|
|
|
|
// Capture port A write transactions for one port A clock cycle, for purposes of detecting a collision at clock B
|
|
always @(posedge clka) begin
|
|
if (ena && |wea) begin
|
|
wra <= 1'b1;
|
|
wea_cap <= wea;
|
|
addra_cap <= addra_i;
|
|
end
|
|
else
|
|
wra <= 1'b0;
|
|
end
|
|
|
|
// Capture port A read transactions for one port A clock cycle, for purposes of detecting a collision at clock B
|
|
always @(posedge clka) begin
|
|
rda_cap <= (ena && ~(|wea));
|
|
if(ena && ~(|wea))
|
|
addra_rd_cap <= addra_i;
|
|
end
|
|
|
|
// Capture port B write transactions for one port B clock cycle, for purposes of detecting a collision at clock A
|
|
always @(posedge clkb) begin
|
|
if (enb && |web) begin
|
|
wrb <= 1'b1;
|
|
web_cap <= web;
|
|
addrb_cap <= addrb_i;
|
|
end
|
|
else
|
|
wrb <= 1'b0;
|
|
end
|
|
|
|
// Capture port B read transactions for one port B clock cycle, for purposes of detecting a collision at clock A
|
|
always @(posedge clkb) begin
|
|
rdb_cap <= (enb && ~(|web));
|
|
if(enb && ~(|web))
|
|
addrb_rd_cap <= addrb_i;
|
|
end
|
|
|
|
end : gen_wr_cap
|
|
|
|
if(`REPORT_MESSAGES) begin : gen_coll_msgs
|
|
// Port A and port B write data widths are symmetric
|
|
if (WRITE_DATA_WIDTH_A == WRITE_DATA_WIDTH_B) begin : gen_wdw_sym
|
|
|
|
// Port A and port B write enable widths are symmetric
|
|
if (BYTE_WRITE_WIDTH_A == BYTE_WRITE_WIDTH_B) begin : gen_we_sym
|
|
|
|
// Port A and port B use a common clock
|
|
if (`COMMON_CLOCK) begin : gen_clock
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && |(wea & web)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at time %0t (address location --> %0d); data outputs and memory content may be corrupted.", $time,addra);
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (|wea && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-A, Read happened through --> Port-B at address location %0d).", $time,addra);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (~(|wea) && |web )))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-B, Read happened through --> Port-A at address location %0d).", $time,addrb);
|
|
end : col_unsafe
|
|
|
|
end : gen_clock
|
|
|
|
// Port A and port B use independent clocks
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_clocks
|
|
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(wra) |-> !((addrb == addra_cap) && |(web & wea_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(wrb) |-> !((addra == addrb_cap) && |(wea & web_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(rda_cap) |-> !((addrb == addra_rd_cap) && (~(|wea_cap) && |web)))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clkb)
|
|
enb && ~(|web) && $rose(wra) |-> !((addrb == addra_cap) && (|wea_cap && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(rdb_cap) |-> !((addra == addrb_rd_cap) && (|wea && ~(|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && ~(|wea) && $rose(wra) |-> !((addra == addrb_cap) && (~(|wea) && (|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
end : col_unsafe
|
|
|
|
end : gen_clocks
|
|
end : gen_we_sym
|
|
|
|
// Port A write enable is wider than port B write enable
|
|
else if (WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A > 1) begin : gen_we_wide_a
|
|
|
|
// Port A and port B use a common clock
|
|
if (`COMMON_CLOCK) begin : gen_clock
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && |(wea & {(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A){web}})))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at time %0t (address location --> %0d); data outputs and memory content may be corrupted.", $time,addra);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (|wea && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-A, Read happened through --> Port-B at address location %0d).", $time,addra);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (~(|wea) && |web )))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-B, Read happened through --> Port-A at address location %0d).", $time,addrb);
|
|
end : col_unsafe
|
|
|
|
end : gen_clock
|
|
|
|
// Port A and port B use independent clocks
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_clocks
|
|
assert property (@(posedge clkb)
|
|
enb && web && $rose(wra) |-> !((addrb == addra_cap) && |({(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A){web}} & wea_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(wrb) |-> !((addra == addrb_cap) && |(wea & {(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A){web_cap}})))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(rda_cap) |-> !((addrb == addra_rd_cap) && (~(|wea_cap) && |web)))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clkb)
|
|
enb && ~(|web) && $rose(wra) |-> !((addrb == addra_cap) && (|wea_cap && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(rdb_cap) |-> !((addra == addrb_rd_cap) && (|wea && ~(|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && ~(|wea) && $rose(wra) |-> !((addra == addrb_cap) && (~(|wea) && (|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
end : col_unsafe
|
|
|
|
end : gen_clocks
|
|
end : gen_we_wide_a
|
|
|
|
// Port B write enable is wider than port A write enable
|
|
else if (WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B > 1) begin : gen_we_wide_b
|
|
|
|
// Port A and port B use a common clock
|
|
if (`COMMON_CLOCK) begin : gen_clock
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && |({(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B){wea}} & web)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at time %0t (address location --> %0d); data outputs and memory content may be corrupted.", $time,addra);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (|wea && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-A, Read happened through --> Port-B at address location %0d).", $time,addra);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (~(|wea) && |web )))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-B, Read happened through --> Port-A at address location %0d).", $time,addrb);
|
|
end : col_unsafe
|
|
end : gen_clock
|
|
|
|
// Port A and port B use independent clocks
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_clocks
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(wra) |-> !((addrb == addra_cap) && |(web & {(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B){wea_cap}})))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(wrb) |-> !((addra == addrb_cap) && |({(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B){wea}} & web_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(rda_cap) |-> !((addrb == addra_rd_cap) && (~(|wea_cap) && |web)))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clkb)
|
|
enb && ~(|web) && $rose(wra) |-> !((addrb == addra_cap) && (|wea_cap && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(rdb_cap) |-> !((addra == addrb_rd_cap) && (|wea && ~(|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && ~(|wea) && $rose(wra) |-> !((addra == addrb_cap) && (~(|wea) && (|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
end : col_unsafe
|
|
|
|
end : gen_clocks
|
|
end : gen_we_wide_b
|
|
end : gen_wdw_sym
|
|
|
|
// Port A write data is wider than port B write data
|
|
else if (WRITE_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin : gen_wdw_wide_a
|
|
|
|
// Port A and port B use a common clock
|
|
if (`COMMON_CLOCK) begin : gen_clock
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) && |(wea & web)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at time %0t (address location --> %0d); data outputs and memory content may be corrupted.", $time,addra);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (|wea && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-A, Read happened through --> Port-B at address location %0d).", $time,addra);
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (~(|wea) && |web )))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-B, Read happened through --> Port-A at address location %0d).", $time,addrb);
|
|
|
|
end : col_unsafe
|
|
end : gen_clock
|
|
|
|
// Port A and port B use independent clocks
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_clocks
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(wra) |-> !((addra_cap == addrb >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) && |(web & wea_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at port A address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(wrb) |-> !((addra == addrb_cap >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) && |(wea & web_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at port B address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(rda_cap) |-> !((addra_rd_cap == addrb >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) && (~(|wea_cap) && |web)))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at port A address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(rdb_cap) |-> !((addra == addrb_rd_cap >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) && (|wea && ~(|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at port B address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
assert property (@(posedge clkb)
|
|
enb && ~(|web) && $rose(wra) |-> !((addrb >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A == addra_cap) && (|wea_cap && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && ~(|wea) && $rose(wra) |-> !((addra == addrb_cap >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) && (~(|wea) && (|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
end : col_unsafe
|
|
|
|
end : gen_clocks
|
|
end : gen_wdw_wide_a
|
|
|
|
// Port B write data is wider than port A write data
|
|
else if (WRITE_DATA_WIDTH_B > WRITE_DATA_WIDTH_A) begin : gen_wdw_wide_b
|
|
|
|
// Port A and port B use a common clock
|
|
if (`COMMON_CLOCK) begin : gen_clock
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addrb == addra >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) && |(wea & web)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at time %0t (address location --> %0d); data outputs and memory content may be corrupted.", $time,addra);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (|wea && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-A, Read happened through --> Port-B at address location %0d).", $time,addra);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && enb |-> !((addra == addrb) && (~(|wea) && |web )))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at time %0t; data outputs and memory content may be corrupted (Write happened through --> Port-B, Read happened through --> Port-A at address location %0d).", $time,addrb);
|
|
end : col_unsafe
|
|
|
|
end : gen_clock
|
|
|
|
// Port A and port B use independent clocks
|
|
else if (`INDEPENDENT_CLOCKS) begin : gen_clocks
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(wra) |-> !((addrb == addra_cap >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) && |(web & wea_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at port A address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(wrb) |-> !((addrb_cap == addra >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) && |(wea & web_cap)))
|
|
else
|
|
$warning("COLLISION: potential write-write collision to memory at port B address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
if (!`IS_COLLISION_SAFE) begin : col_unsafe
|
|
assert property (@(posedge clkb)
|
|
enb && |web && $rose(rda_cap) |-> !((addrb == addra_rd_cap >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) && (~(|wea_cap) && |web)))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at port A address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
assert property (@(posedge clka)
|
|
ena && |wea && $rose(rdb_cap) |-> !((addrb_rd_cap == addra >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) && (|wea && ~(|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at port B address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
|
|
assert property (@(posedge clkb)
|
|
enb && ~(|web) && $rose(wra) |-> !((addrb == addra_cap >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) && (|wea_cap && ~(|web))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addra_cap, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
ena && ~(|wea) && $rose(wra) |-> !((addra >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B == addrb_cap) && (~(|wea) && (|web_cap))))
|
|
else
|
|
$warning("COLLISION: potential write-read collision to memory at address 0x%0h at time %0t; data outputs and memory content may be corrupted.", addrb_cap, $time);
|
|
end : col_unsafe
|
|
|
|
end : gen_clocks
|
|
end : gen_wdw_wide_b
|
|
end : gen_coll_msgs
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// code is for Common clock and symmetric case
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
if (`COMMON_CLOCK && (((WRITE_DATA_WIDTH_A == WRITE_DATA_WIDTH_B) && (WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B) && (READ_DATA_WIDTH_A == WRITE_DATA_WIDTH_B) && `NO_ECC) || !`NO_ECC)) begin : sync_clk_sym
|
|
reg wr_wr_col = 0;
|
|
always @(ena or enb or addra_i or addrb_i or wea or web or dina_i or dinb_i) begin
|
|
if ((ena == 1'b1 && enb == 1'b1)) begin
|
|
if (addra_i == addrb_i) begin
|
|
if(|wea && |web) begin
|
|
force dina_i = {WRITE_DATA_WIDTH_A{1'bX}};
|
|
force dinb_i = {WRITE_DATA_WIDTH_B{1'bX}};
|
|
wr_wr_col <= 1'b1;
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
release dinb_i;
|
|
wr_wr_col <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
release dinb_i;
|
|
wr_wr_col <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
release dinb_i;
|
|
wr_wr_col <= 1'b0;
|
|
end
|
|
end
|
|
|
|
if (`MEM_PORTB_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_b_coll
|
|
always @(posedge clka) begin
|
|
if (enb == 1'b1) begin
|
|
if (ena == 1'b1 && (addra_i == addrb_i)) begin
|
|
if((|wea & ~(|web)) || wr_wr_col) begin
|
|
if(READ_LATENCY_B == 1) begin
|
|
force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
end
|
|
else begin
|
|
#1ps force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
end
|
|
end
|
|
else begin
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
end
|
|
else begin
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
end
|
|
end
|
|
end : gen_rd_b_coll
|
|
|
|
if (`MEM_PORTA_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_a_coll
|
|
always @(posedge clka) begin
|
|
if (ena == 1'b1) begin
|
|
if (enb == 1'b1 && (addra_i == addrb_i)) begin
|
|
if((~(|wea) & |web) || wr_wr_col)begin
|
|
if (READ_LATENCY_A == 1) begin
|
|
force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
else begin
|
|
#1ps force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
end
|
|
else begin
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
else begin
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
end
|
|
end : gen_rd_a_coll
|
|
end : sync_clk_sym
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// code is for Common clock, Asymmetric case
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
if (`COMMON_CLOCK && `NO_ECC && ((WRITE_DATA_WIDTH_A != WRITE_DATA_WIDTH_B) || (WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) || (READ_DATA_WIDTH_A != WRITE_DATA_WIDTH_B))) begin : sync_clk_asym
|
|
reg wr_wr_col_asym = 0;
|
|
always @(ena or enb or wea or web or addra_i or addrb_i) begin
|
|
if (ena & enb) begin
|
|
if(|wea && |web) begin
|
|
if(WRITE_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if (addra_i == addrb_i >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A)
|
|
begin
|
|
wr_wr_col_asym <= 1'b1;
|
|
end
|
|
else begin
|
|
wr_wr_col_asym <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
if (addrb_i == addra_i >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B)
|
|
begin
|
|
wr_wr_col_asym <= 1'b1;
|
|
end
|
|
else begin
|
|
wr_wr_col_asym <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
wr_wr_col_asym <= 1'b0;
|
|
end
|
|
end
|
|
else
|
|
wr_wr_col_asym <= 1'b0;
|
|
end
|
|
|
|
// write-write collision modeling
|
|
// 1. check if both ports are writing and the address is equal
|
|
// 2. always allow the wider port to write to the memory
|
|
// 3. write enable of the narrower port has to be forced to 0
|
|
// 4. assert the status signal to indicate wr-wr collision
|
|
// 5. <TBD> check if both ports are writing same data
|
|
|
|
always @(ena or enb or wea or web or addra_i or addrb_i) begin
|
|
if(ena & enb) begin
|
|
if(|wea && |web) begin
|
|
if(WRITE_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if (addra_i == addrb_i >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A)
|
|
force dina_i = {WRITE_DATA_WIDTH_A{1'bX}};
|
|
else
|
|
release dina_i;
|
|
end
|
|
end
|
|
else
|
|
release dina_i;
|
|
end
|
|
else
|
|
release dina_i;
|
|
end
|
|
|
|
always @(ena or enb or wea or web or addra_i or addrb_i) begin
|
|
if(ena & enb) begin
|
|
if(|wea && |web) begin
|
|
if(WRITE_DATA_WIDTH_A < WRITE_DATA_WIDTH_B) begin
|
|
if (addrb_i == addra_i >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B)
|
|
force dinb_i = {WRITE_DATA_WIDTH_B{1'bX}};
|
|
else
|
|
release dinb_i;
|
|
end
|
|
end
|
|
else
|
|
release dinb_i;
|
|
end
|
|
else
|
|
release dinb_i;
|
|
end
|
|
|
|
always @(ena or enb or wea or web or addra_i or addrb_i) begin
|
|
if(ena & enb) begin
|
|
if(|wea && |web) begin
|
|
if(WRITE_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if (addra_i == addrb_i >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A)
|
|
force web_i = 'b0;
|
|
else
|
|
release web_i;
|
|
end
|
|
end
|
|
else
|
|
release web_i;
|
|
end
|
|
else
|
|
release web_i;
|
|
end
|
|
|
|
always @(ena or enb or wea or web or addra_i or addrb_i) begin
|
|
if(ena & enb) begin
|
|
if(|wea && |web) begin
|
|
if(WRITE_DATA_WIDTH_A < WRITE_DATA_WIDTH_B) begin
|
|
if (addrb_i == addra_i >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B)
|
|
force wea_i = 'b0;
|
|
else
|
|
release wea_i;
|
|
end
|
|
end
|
|
else
|
|
release wea_i;
|
|
end
|
|
else
|
|
release wea_i;
|
|
end
|
|
|
|
if (`MEM_PORTB_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_b_coll
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
if (enb == 1'b1) begin
|
|
if (ena == 1'b1) begin
|
|
if((|wea && ~(|web)) || wr_wr_col_asym) begin
|
|
if(WRITE_DATA_WIDTH_A > READ_DATA_WIDTH_B) begin
|
|
if (addra_i == addrb_i >> P_WIDTH_ADDR_READ_B-P_WIDTH_ADDR_WRITE_A) begin
|
|
if (READ_LATENCY_B == 1)
|
|
force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
else
|
|
#1ps force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
else begin
|
|
if (addrb_i == addra_i >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_READ_B) begin
|
|
if (READ_LATENCY_B == 1)
|
|
force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
else
|
|
#1ps force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg; // write enable condition fails
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg; // ena is 0
|
|
end
|
|
end
|
|
end : gen_rd_b_coll
|
|
|
|
if (`MEM_PORTA_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_a_coll
|
|
always @(posedge clka) begin
|
|
if (ena == 1'b1) begin
|
|
if (enb == 1'b1) begin
|
|
if((~(|wea) && |web) || wr_wr_col_asym) begin
|
|
if(READ_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if (addra_i == addrb_i >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_READ_A) begin
|
|
if (READ_LATENCY_A == 1)
|
|
force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
else
|
|
#1ps force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
else begin
|
|
if (addrb_i == addra_i >> P_WIDTH_ADDR_READ_A-P_WIDTH_ADDR_WRITE_B) begin
|
|
if(READ_LATENCY_A == 1)
|
|
force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
else
|
|
#1ps force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
end : gen_rd_a_coll
|
|
|
|
end : sync_clk_asym
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// code is for Independant clock, symmetric case
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
if (`INDEPENDENT_CLOCKS && (((WRITE_DATA_WIDTH_A == WRITE_DATA_WIDTH_B) && (WRITE_DATA_WIDTH_A == READ_DATA_WIDTH_B) && (READ_DATA_WIDTH_A == WRITE_DATA_WIDTH_B) && `NO_ECC) || !`NO_ECC)) begin : async_clk_sym
|
|
reg wr_wr_col_asym_a = 0;
|
|
reg wr_wr_col_asym_b = 0;
|
|
|
|
always @(ena or enb or wea or web or addra_i or addrb_i or wra or wrb or addra_cap or addrb_cap or col_win_wr_b or col_win_wr_a or dinb_i or dina_i)
|
|
begin
|
|
if(enb == 1'b1) begin
|
|
if(wra == 1'b1 && addrb_i == addra_cap && col_win_wr_a) begin
|
|
if(|web) begin
|
|
force dinb_i = {WRITE_DATA_WIDTH_B{1'bX}};
|
|
wr_wr_col_asym_b <= 1'b1;
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
always @(ena or enb or wea or web or addra_i or addrb_i or wra or wrb or addra_cap or addrb_cap or col_win_wr_b or col_win_wr_a or dinb_i or dina_i)
|
|
begin
|
|
if(ena == 1'b1) begin
|
|
if(wrb == 1'b1 && addra_i == addrb_cap && col_win_wr_b) begin
|
|
if(|wea) begin
|
|
force dina_i = {WRITE_DATA_WIDTH_A{1'bX}};
|
|
wr_wr_col_asym_a <= 1'b1;
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
|
|
if (`MEM_PORTB_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_b_coll
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
if (enb == 1'b1) begin
|
|
if ( (wra == 1'b1 && addrb_i == addra_cap && ~(|web) && col_win_wr_a ) || (wr_wr_col_asym_a | wr_wr_col_asym_b)) begin
|
|
if(READ_LATENCY_B == 1) begin
|
|
force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
|
|
end
|
|
else begin
|
|
#1ps force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
|
|
end
|
|
end
|
|
else begin
|
|
release gen_rd_b.doutb_reg;
|
|
|
|
end
|
|
end
|
|
end
|
|
end : gen_rd_b_coll
|
|
|
|
if (`MEM_PORTA_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_a_coll
|
|
always @(posedge clka) begin
|
|
if (ena == 1'b1) begin
|
|
if ( ((wrb == 1'b1 && addra_i == addrb_cap && ~(|wea) && col_win_wr_b) || (wr_wr_col_asym_a | wr_wr_col_asym_b))) begin
|
|
if(READ_LATENCY_A == 1)
|
|
force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
else
|
|
#1ps force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
end : gen_rd_a_coll
|
|
|
|
end : async_clk_sym
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// code is for Independant clock, Asymmetric case
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
if (`INDEPENDENT_CLOCKS && `NO_ECC && ((WRITE_DATA_WIDTH_A != WRITE_DATA_WIDTH_B) && (WRITE_DATA_WIDTH_A != READ_DATA_WIDTH_B) && (READ_DATA_WIDTH_A != WRITE_DATA_WIDTH_B))) begin : async_clk_asym
|
|
reg wr_wr_col_asym_a = 0;
|
|
reg wr_wr_col_asym_b = 0;
|
|
|
|
always @(ena or enb or wra or wrb or addra_i or addrb_i or addra_cap or addrb_cap or wea or web or col_win_wr_b or col_win_wr_a or dina_i or dinb_i) begin
|
|
if (ena == 1'b1) begin
|
|
if(wrb == 1'b1) begin
|
|
if(WRITE_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if (addra_i == addrb_cap >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) begin
|
|
if(|wea && col_win_wr_b) begin
|
|
force dina_i = {WRITE_DATA_WIDTH_A{1'bX}};
|
|
wr_wr_col_asym_a <= 1'b1;
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
if (addrb_cap == addra_i >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) begin
|
|
if(|wea && col_win_wr_b) begin
|
|
force dina_i = {WRITE_DATA_WIDTH_A{1'bX}};
|
|
wr_wr_col_asym_a <= 1'b1;
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dina_i;
|
|
wr_wr_col_asym_a <= 1'b0;
|
|
end
|
|
end
|
|
|
|
always @(ena or enb or wra or wrb or addra_i or addrb_i or addra_cap or addrb_cap or wea or web or col_win_wr_b or col_win_wr_a or dina_i or dinb_i) begin
|
|
if (enb == 1'b1) begin
|
|
if(wra == 1'b1) begin
|
|
if(WRITE_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if (addra_cap == addrb_i >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_WRITE_A) begin
|
|
if(|web && col_win_wr_a) begin
|
|
force dinb_i = {WRITE_DATA_WIDTH_B{1'bX}};
|
|
wr_wr_col_asym_b <= 1'b1;
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
if (addrb_i == addra_cap >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_WRITE_B) begin
|
|
if(|web && col_win_wr_a) begin
|
|
force dinb_i = {WRITE_DATA_WIDTH_B{1'bX}};
|
|
wr_wr_col_asym_b <= 1'b1;
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
release dinb_i;
|
|
wr_wr_col_asym_b <= 1'b0;
|
|
end
|
|
end
|
|
|
|
// As Assymetry Internal to port is not allowed, Limiting the comparision to
|
|
// across ports (WRITE_DATA_WIDTH_A = READ_DATA_WIDTH_A and READ_DATA_WIDTH_B = WRITE_DATA_WIDTH_B)
|
|
if (`MEM_PORTA_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_a_coll
|
|
always @(posedge clka) begin
|
|
if (ena == 1'b1 ) begin
|
|
if(wrb == 1'b1 && ~(|wea)) begin
|
|
if(READ_DATA_WIDTH_A > WRITE_DATA_WIDTH_B) begin
|
|
if ((addra_i == addrb_cap >> P_WIDTH_ADDR_WRITE_B-P_WIDTH_ADDR_READ_A && col_win_wr_b) || (wr_wr_col_asym_a | wr_wr_col_asym_b)) begin
|
|
if (READ_LATENCY_A == 1)
|
|
force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
else
|
|
#1ps force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
else begin
|
|
if ((addrb_cap == addra_i >> P_WIDTH_ADDR_READ_A-P_WIDTH_ADDR_WRITE_B && col_win_wr_b) || (wr_wr_col_asym_a | wr_wr_col_asym_b)) begin
|
|
if (READ_LATENCY_A == 1)
|
|
force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
else
|
|
#1ps force gen_rd_a.douta_reg = {READ_DATA_WIDTH_A{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
else
|
|
release gen_rd_a.douta_reg;
|
|
end
|
|
end
|
|
end : gen_rd_a_coll
|
|
|
|
if (`MEM_PORTB_READ && !(`IS_COLLISION_SAFE)) begin : gen_rd_b_coll
|
|
always @(posedge clkb) begin
|
|
if (enb == 1'b1) begin
|
|
if( wra == 1'b1 && ~(|web) ) begin
|
|
if(WRITE_DATA_WIDTH_A > READ_DATA_WIDTH_B) begin
|
|
if ((addra_cap == addrb_i >> P_WIDTH_ADDR_READ_B-P_WIDTH_ADDR_WRITE_A && col_win_wr_a) || (wr_wr_col_asym_a | wr_wr_col_asym_b)) begin
|
|
if(READ_LATENCY_B == 1)
|
|
force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
else
|
|
#1ps force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
else begin
|
|
if ((addrb_i == addra_cap >> P_WIDTH_ADDR_WRITE_A-P_WIDTH_ADDR_READ_B && col_win_wr_a) || (wr_wr_col_asym_a | wr_wr_col_asym_b)) begin
|
|
if(READ_LATENCY_B == 1)
|
|
force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
else
|
|
#1ps force gen_rd_b.doutb_reg = {READ_DATA_WIDTH_B{1'bX}};
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
end
|
|
else
|
|
release gen_rd_b.doutb_reg;
|
|
end
|
|
end
|
|
end : gen_rd_b_coll
|
|
end : async_clk_asym
|
|
end : gen_assert_coll_ww
|
|
|
|
`endif
|
|
|
|
// Sleep Mode behaviour Model
|
|
|
|
if (`SLEEP_MODE && !`MEM_AUTO_SLP_EN) begin : gen_dyn_power_saving_mode
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Wakeup_time modeling //
|
|
// SLEEP --- 2 clocks //
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
reg [9:0] sleep_edg_det_a;
|
|
wire de_activate_slp_mode_a; //falling edge of sleep port + wakeup_time w.r.to Port-A clock
|
|
|
|
// Initialize the variables
|
|
initial begin
|
|
sleep_edg_det_a = 'b0;
|
|
sleep_int_a = 1'b0;
|
|
end
|
|
// Shift register to continuously monitor the transitions on sleep port
|
|
always @(posedge clka) begin : sleep_sync_clka
|
|
sleep_edg_det_a <= {sleep_edg_det_a[8:0],sleep};
|
|
end : sleep_sync_clka
|
|
|
|
// Sleep Falling edge detection
|
|
if (`SLEEP_MODE)
|
|
assign de_activate_slp_mode_a = (sleep_edg_det_a[2:0] == 3'b100)? 1'b1 : 1'b0;
|
|
else
|
|
assign de_activate_slp_mode_a = 1'b1;
|
|
|
|
// Generate the Active sleep duration including the wake up time
|
|
always @(*)
|
|
begin
|
|
if(sleep == 1'b1)
|
|
sleep_int_a = 1'b1;
|
|
else if(de_activate_slp_mode_a == 1'b1)
|
|
#2 sleep_int_a = 1'b0;
|
|
end
|
|
|
|
// Check if port-A write is allowed
|
|
if (`MEM_PORTA_WRITE ) begin : gen_dyn_pwr_save_wr_a
|
|
// ignore write operation during sleep mode
|
|
always @(sleep_int_a or sleep_int_b)
|
|
begin : proc_force_dina
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1)
|
|
force mem = mem; // mem array is un-changed
|
|
else
|
|
release mem;
|
|
end : proc_force_dina
|
|
// Assertion to detect the write operation during sleep mode
|
|
assert property (@(posedge clka)
|
|
~(sleep_int_a === 1'b1 && ena === 1'b1 && |wea))
|
|
else
|
|
$warning("WRITE on Port A attempted while in SLEEP mode at time %t", $time);
|
|
end : gen_dyn_pwr_save_wr_a
|
|
|
|
// Check if Read on Port-A is allowed
|
|
if (`MEM_PORTA_READ ) begin : gen_dyn_pwr_save_rd_a
|
|
// Assertion to detect the read operation during sleep mode
|
|
assert property (@(posedge clka)
|
|
~(sleep_int_a === 1'b1 && ena === 1'b1 && ~(|wea) ))
|
|
else
|
|
$warning("READ on Port A attempted while in SLEEP mode at time %t", $time);
|
|
|
|
// When in Latch Mode
|
|
if (`MEM_PORTA_RD_REG) begin : gen_sleep_a_latch_mode
|
|
always @(posedge clka) begin : pwr_sav_mode_rd_det_a
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1) begin
|
|
if (ena == 1'b1 ) begin
|
|
if (`MEM_PORTA_WF) begin
|
|
if(|wea)
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}};
|
|
else
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}}; end
|
|
else if (`MEM_PORTA_RF)
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}};
|
|
else begin
|
|
if(|wea)
|
|
force douta = douta;
|
|
else
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}};
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if(`MEM_PORTA_NC) begin
|
|
if(~(|wea) & ena)
|
|
release douta;
|
|
end
|
|
else begin
|
|
if(ena)
|
|
release douta;
|
|
end
|
|
end
|
|
end : pwr_sav_mode_rd_det_a
|
|
end : gen_sleep_a_latch_mode
|
|
|
|
// If pipe line stages are enabled
|
|
if (`MEM_PORTA_RD_PIPE) begin : gen_sleep_a_reg_mode
|
|
reg ena_pipe_sleep [READ_LATENCY_A-2:0];
|
|
reg ena_pipe_dup [READ_LATENCY_A-2:0];
|
|
reg wea_pipe_sleep [READ_LATENCY_A-2:0];
|
|
reg wea_pipe_dup [READ_LATENCY_A-2:0];
|
|
// Capture the READ operations during and after sleep modes
|
|
always @(posedge clka) begin
|
|
if(sleep_int_a == 1'b1 || sleep_int_b == 1'b1) begin
|
|
ena_pipe_sleep[0] <= ena; // Capture all READ operations during sleep
|
|
ena_pipe_dup[0] <= 1'b0;
|
|
wea_pipe_sleep[0] <= |wea; // Capture all WRITE operations during sleep
|
|
wea_pipe_dup[0] <= 1'b0;
|
|
end
|
|
else begin
|
|
ena_pipe_sleep[0] <= 1'b0;
|
|
ena_pipe_dup[0] <= ena; // Capture All valid READ Operations
|
|
wea_pipe_sleep[0] <= 1'b0;
|
|
wea_pipe_dup[0] <= |wea; // Capture All valid WRITE Operations
|
|
end
|
|
end
|
|
|
|
// If more than two stages are used, loops generate all pipeline stages except the first and last
|
|
if (READ_LATENCY_A > 2) begin : porta_slp_gen_estages
|
|
for (genvar slp_estage=1; slp_estage<READ_LATENCY_A-1; slp_estage=slp_estage+1) begin : porta_gen_slp_epipe
|
|
always @(posedge clka) begin
|
|
ena_pipe_sleep[slp_estage] <= ena_pipe_sleep[slp_estage-1];
|
|
ena_pipe_dup[slp_estage] <= ena_pipe_dup[slp_estage-1];
|
|
wea_pipe_sleep[slp_estage] <= wea_pipe_sleep[slp_estage-1];
|
|
wea_pipe_dup[slp_estage] <= wea_pipe_dup[slp_estage-1];
|
|
end
|
|
end : porta_gen_slp_epipe
|
|
end : porta_slp_gen_estages
|
|
|
|
// Flag asserts when the Read during sleep arrives to the last pipeline stage
|
|
// and de-asserts when the valid read arrives to the last pipeline stage
|
|
reg last_pipe_en_ctrl_a;
|
|
reg rda_happened;
|
|
initial begin
|
|
last_pipe_en_ctrl_a = 1'b0;
|
|
rda_happened = 1'b0;
|
|
end
|
|
|
|
always @(*)
|
|
begin
|
|
if (ena_pipe_sleep[READ_LATENCY_A-2]) begin
|
|
last_pipe_en_ctrl_a = 1'b1;
|
|
if(~wea_pipe_sleep[READ_LATENCY_A-2])
|
|
rda_happened = 1'b1;
|
|
end
|
|
else if(ena_pipe_dup[READ_LATENCY_A-2]) begin
|
|
last_pipe_en_ctrl_a = 1'b0;
|
|
rda_happened = 1'b0;
|
|
end
|
|
end
|
|
|
|
// If READ_LATENCY_A > 2
|
|
// Force DOUT depending on the latency and the WRITE_MODE
|
|
if ( READ_LATENCY_A >= 2) begin : gen_sleep_porta_highr_Latncy
|
|
always @(posedge clka) begin : sleep_porta_rd_highr_Latncy_force
|
|
if (last_pipe_en_ctrl_a && regcea) begin
|
|
if (`MEM_PORTA_WF) begin
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}};
|
|
end
|
|
else if (`MEM_PORTA_RF)
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}};
|
|
else begin
|
|
if(rda_happened)
|
|
force douta = {READ_DATA_WIDTH_A{1'bx}};
|
|
else if(ena_pipe_sleep[READ_LATENCY_A-2] & wea_pipe_sleep[READ_LATENCY_A-2])
|
|
force douta = douta;
|
|
end
|
|
end
|
|
end : sleep_porta_rd_highr_Latncy_force
|
|
|
|
always @(posedge clka) begin : sleep_porta_rd_highr_Latncy_release
|
|
if(~last_pipe_en_ctrl_a) begin
|
|
// when all the reads of sleep are over, check if there is a
|
|
// valid regcea and pipe lined enable (not sleep enable)
|
|
if (rsta) release douta;
|
|
else begin
|
|
if (regcea) begin
|
|
if(`MEM_PORTA_NC) begin
|
|
if(!wea_pipe_dup[READ_LATENCY_A-2] && ena_pipe_dup[READ_LATENCY_A-2])
|
|
release douta;
|
|
end
|
|
else // not No_change
|
|
release douta;
|
|
end // release when there is a valid READ
|
|
end
|
|
end
|
|
end : sleep_porta_rd_highr_Latncy_release
|
|
end : gen_sleep_porta_highr_Latncy
|
|
end : gen_sleep_a_reg_mode
|
|
end : gen_dyn_pwr_save_rd_a
|
|
|
|
if (`MEM_PORTB_READ ) begin : gen_dyn_pwr_save_b
|
|
// Internal Signal Declarations
|
|
reg [9:0] sleep_edg_det_b;
|
|
reg de_activate_slp_mode_b; //falling edge of sleep port + wakeup_time w.r.to Port-B clock
|
|
|
|
// Initialize all the internal signals
|
|
initial begin
|
|
sleep_int_b = 1'b0;
|
|
sleep_edg_det_b = 'b0;
|
|
end
|
|
|
|
//Effective Sleep Mode Duration identification
|
|
always @(posedge gen_rd_b.clkb_int)
|
|
begin : sleep_sync_clkb
|
|
sleep_edg_det_b <= {sleep_edg_det_b[8:0],sleep};
|
|
end : sleep_sync_clkb
|
|
|
|
if (`SLEEP_MODE)
|
|
assign de_activate_slp_mode_b = (sleep_edg_det_b[2:0] == 3'b100)? 1'b1 : 1'b0;
|
|
else
|
|
assign de_activate_slp_mode_b = 1'b1;
|
|
|
|
always @(*)
|
|
begin
|
|
if(sleep == 1'b1)
|
|
sleep_int_b = 1'b1;
|
|
else if(de_activate_slp_mode_b == 1'b1)
|
|
#2 sleep_int_b = 1'b0;
|
|
end
|
|
|
|
// Check if Port-B write is allowed
|
|
if (`MEM_PORTB_WRITE ) begin : gen_dyn_pwr_save_wr_b
|
|
// Assertions to detect the READ and WRITE operations during sleep mode
|
|
assert property (@(posedge gen_rd_b.clkb_int)
|
|
~(sleep_int_b === 1'b1 && enb === 1'b1 && |web))
|
|
else
|
|
$warning("WRITE on Port B attempted while in SLEEP mode at time %t", $time);
|
|
end : gen_dyn_pwr_save_wr_b
|
|
|
|
assert property (@(posedge gen_rd_b.clkb_int)
|
|
~(sleep_int_b === 1'b1 && enb === 1'b1 && ~(|web)))
|
|
else
|
|
$warning("READ on Port B attempted while in SLEEP mode at time %t", $time);
|
|
// Forcing DOUTB when in latch mode
|
|
if (`MEM_PORTB_RD_REG) begin : gen_sleep_b_latch_mode
|
|
|
|
always @(posedge gen_rd_b.clkb_int) begin : pwr_sav_mode_rd_det_b
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1) begin
|
|
if (enb == 1'b1 ) begin
|
|
if (`MEM_PORTB_WF) begin
|
|
if(|web)
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}};
|
|
else
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}}; end
|
|
else if (`MEM_PORTB_RF)
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}};
|
|
else begin
|
|
if(|web)
|
|
force doutb = doutb;
|
|
else
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}};
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if(`MEM_PORTB_NC) begin
|
|
if(~(|web) & enb)
|
|
release doutb;
|
|
end
|
|
else begin
|
|
if(enb)
|
|
release doutb;
|
|
end
|
|
end
|
|
end : pwr_sav_mode_rd_det_b
|
|
end : gen_sleep_b_latch_mode
|
|
|
|
if (`MEM_PORTB_RD_PIPE) begin : gen_sleep_b_reg_mode
|
|
// Internal Signal Declaration
|
|
reg enb_pipe_sleep [READ_LATENCY_B-2:0];
|
|
reg enb_pipe_dup [READ_LATENCY_B-2:0];
|
|
reg web_pipe_sleep [READ_LATENCY_B-2:0];
|
|
reg web_pipe_dup [READ_LATENCY_B-2:0];
|
|
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
if(sleep_int_a === 1'b1 || sleep_int_b === 1'b1)
|
|
begin
|
|
enb_pipe_sleep[0] <= enb; // Capture all READ operations during sleep
|
|
enb_pipe_dup[0] <= 1'b0;
|
|
web_pipe_sleep[0] <= |web; // Capture all WRITE operations during sleep
|
|
web_pipe_dup[0] <= 1'b0;
|
|
end
|
|
else
|
|
begin
|
|
enb_pipe_sleep[0] <= 1'b0;
|
|
enb_pipe_dup[0] <= enb; // Capture All valid READ Operations
|
|
web_pipe_sleep[0] <= 1'b0;
|
|
web_pipe_dup[0] <= |web; // Capture All valid WRITE Operations
|
|
end
|
|
end
|
|
|
|
// If more than two stages are used, loops generate all pipeline stages except the first and last
|
|
if (READ_LATENCY_B > 2) begin : portb_slp_gen_estages
|
|
for (genvar portb_slp_estage=1; portb_slp_estage<READ_LATENCY_B-1; portb_slp_estage=portb_slp_estage+1) begin : portb_gen_slp_epipe
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
enb_pipe_sleep[portb_slp_estage] <= enb_pipe_sleep[portb_slp_estage-1];
|
|
enb_pipe_dup[portb_slp_estage] <= enb_pipe_dup[portb_slp_estage-1];
|
|
web_pipe_sleep[portb_slp_estage] <= web_pipe_sleep[portb_slp_estage-1];
|
|
web_pipe_dup[portb_slp_estage] <= web_pipe_dup[portb_slp_estage-1];
|
|
end
|
|
end : portb_gen_slp_epipe
|
|
end : portb_slp_gen_estages
|
|
|
|
reg last_pipe_en_ctrl_b;
|
|
reg rdb_happened;
|
|
initial begin
|
|
last_pipe_en_ctrl_b = 1'b0;
|
|
rdb_happened = 1'b0;
|
|
end
|
|
|
|
always @(*)
|
|
begin
|
|
if (enb_pipe_sleep[READ_LATENCY_B-2]) begin
|
|
last_pipe_en_ctrl_b = 1'b1;
|
|
if(~web_pipe_sleep[READ_LATENCY_B-2])
|
|
rdb_happened = 1'b1;
|
|
end
|
|
else if(enb_pipe_dup[READ_LATENCY_B-2]) begin
|
|
last_pipe_en_ctrl_b = 1'b0;
|
|
rdb_happened = 1'b0;
|
|
end
|
|
end
|
|
|
|
// Forcing DOUTB depending on the READ latency and WRITE_MODE
|
|
if ( READ_LATENCY_B >= 2) begin : gen_sleep_portb_highr_Latncy
|
|
always @(posedge gen_rd_b.clkb_int) begin : sleep_portb_rd_highr_Latncy_force
|
|
if(last_pipe_en_ctrl_b && regceb) begin
|
|
if (`MEM_PORTB_WF) begin
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}};
|
|
end
|
|
else if (`MEM_PORTB_RF)
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}};
|
|
else begin
|
|
if(rdb_happened)
|
|
force doutb = {READ_DATA_WIDTH_B{1'bx}};
|
|
else if(enb_pipe_sleep[READ_LATENCY_B-2] & web_pipe_sleep[READ_LATENCY_B-2])
|
|
force doutb = doutb;
|
|
end
|
|
end
|
|
end : sleep_portb_rd_highr_Latncy_force
|
|
|
|
always @(posedge gen_rd_b.clkb_int) begin : sleep_portb_rd_highr_Latncy_release
|
|
if (~last_pipe_en_ctrl_b) begin
|
|
// when all the reads of sleep are over, check if there is a
|
|
// valid regceb and pipe lined enable (not sleep enable)
|
|
if (rstb) release doutb;
|
|
else begin
|
|
if (regceb) begin
|
|
if(`MEM_PORTB_NC) begin
|
|
if(!web_pipe_dup[READ_LATENCY_B-2] && enb_pipe_dup[READ_LATENCY_B-2])
|
|
release doutb;
|
|
end
|
|
else // not No_change
|
|
release doutb;
|
|
end // release when there is a valid READ
|
|
end
|
|
end
|
|
end : sleep_portb_rd_highr_Latncy_release
|
|
end : gen_sleep_portb_highr_Latncy
|
|
end : gen_sleep_b_reg_mode
|
|
end : gen_dyn_pwr_save_b
|
|
|
|
end : gen_dyn_power_saving_mode
|
|
|
|
if(`MEM_AUTO_SLP_EN) begin : gen_auto_slp_dly_sim
|
|
reg [ADDR_WIDTH_A-1:0] addra_aslp_pipe_sim [AUTO_SLEEP_TIME-1:0];
|
|
reg [ADDR_WIDTH_B-1:0] addrb_aslp_pipe_sim [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the address pipeline
|
|
initial begin
|
|
integer initstage_a;
|
|
integer initstage_b;
|
|
for (initstage_a=0; initstage_a<AUTO_SLEEP_TIME; initstage_a=initstage_a+1) begin : for_addra_pipe_init
|
|
addra_aslp_pipe_sim[initstage_a] = {ADDR_WIDTH_A{1'b0}};
|
|
end : for_addra_pipe_init
|
|
for (initstage_b=0; initstage_b<AUTO_SLEEP_TIME; initstage_b=initstage_b+1) begin : for_addrb_pipe_init
|
|
addrb_aslp_pipe_sim[initstage_b] = {ADDR_WIDTH_B{1'b0}};
|
|
end : for_addrb_pipe_init
|
|
end
|
|
|
|
// port-a complete address delays for simulation
|
|
always @(posedge clka) begin
|
|
addra_aslp_pipe_sim[0] <= addra;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe_a
|
|
always @(posedge clka) begin
|
|
addra_aslp_pipe_sim[aslp_stage] <= addra_aslp_pipe_sim[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe_a
|
|
assign addra_aslp_sim= addra_aslp_pipe_sim[AUTO_SLEEP_TIME-1];
|
|
|
|
if (`MEM_PORTB_READ ) begin : gen_addrb_sim_dly
|
|
// port-b complete address delays for simulation
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
addrb_aslp_pipe_sim[0] <= addrb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe_b
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
addrb_aslp_pipe_sim[aslp_stage] <= addrb_aslp_pipe_sim[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe_b
|
|
assign addrb_aslp_sim= addrb_aslp_pipe_sim[AUTO_SLEEP_TIME-1];
|
|
end : gen_addrb_sim_dly
|
|
if(`MEM_PORTA_WRITE && (`BOTH_ENC_DEC || `ENC_ONLY)) begin : gen_aslp_inj_err_a_sim
|
|
// Force the error injection signals
|
|
assign injectsbiterra_sim = gen_wr_a.err_inj_ecc.gen_aslp_dly_inj_err.injsbiterra_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
assign injectdbiterra_sim = gen_wr_a.err_inj_ecc.gen_aslp_dly_inj_err.injdbiterra_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_inj_err_a_sim
|
|
else begin : gen_aslp_no_inj_err_a_sim
|
|
assign injectsbiterra_sim = 1'b0;
|
|
assign injectdbiterra_sim = 1'b0;
|
|
end : gen_aslp_no_inj_err_a_sim
|
|
|
|
if(`MEM_PORTB_WRITE && `MEM_PRIM_ULTRA && (`BOTH_ENC_DEC || `ENC_ONLY)) begin : gen_aslp_inj_err_b_sim
|
|
// Force the error injection signals
|
|
assign injectsbiterrb_sim = gen_wr_b.err_inj_ecc.gen_aslp_dly_inj_err.injsbiterrb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
assign injectdbiterrb_sim = gen_wr_b.err_inj_ecc.gen_aslp_dly_inj_err.injdbiterrb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end : gen_aslp_inj_err_b_sim
|
|
else begin : gen_aslp_no_inj_err_b_sim
|
|
assign injectsbiterrb_sim = 1'b0;
|
|
assign injectdbiterrb_sim = 1'b0;
|
|
end : gen_aslp_no_inj_err_b_sim
|
|
|
|
end : gen_auto_slp_dly_sim
|
|
else begin : gen_nauto_slp_dly_sim
|
|
assign addra_aslp_sim = addra;
|
|
assign addrb_aslp_sim = addrb;
|
|
assign injectsbiterra_sim = injectsbiterra;
|
|
assign injectdbiterra_sim = injectdbiterra;
|
|
assign injectsbiterrb_sim = injectsbiterrb;
|
|
assign injectdbiterrb_sim = injectdbiterrb;
|
|
end : gen_nauto_slp_dly_sim
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// ecc behavioral modeling
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// ecc behavioral modeling has to be done for the below 3 cases
|
|
// 1. when both encoder and decoder are enabled
|
|
// 2. when ecc encoder is enabled alone
|
|
// 3. when ecc decoder is enabled alone
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
/**ECC Behavioral Modeling when both Encoder and Decoder are enabled
|
|
This module need not code the parity calculations for encoding and decoding????
|
|
This module needs to model the Error Injection (data input and output
|
|
are expected to be multiple of 64 bits)
|
|
**/
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
if (ECC_MODE != 0) begin : ecc_behav_logic
|
|
localparam integer P_MIN_WIDTH_PARITY_ECC = (ECC_MODE == 3 && `NO_MEMORY_INIT) ? P_MIN_WIDTH_DATA : (ECC_MODE == 2) ? WRITE_DATA_WIDTH_A : P_MIN_WIDTH_DATA+((WRITE_DATA_WIDTH_A/64)*8);
|
|
// Memory Array Declaration for ECC
|
|
reg [P_MIN_WIDTH_PARITY_ECC-1:0] mem_ecc [0:P_MAX_DEPTH_DATA-1];
|
|
reg [READ_DATA_WIDTH_A-1:0] douta_int = 0;
|
|
reg [READ_DATA_WIDTH_B-1:0] doutb_int = 0;
|
|
reg sbiterra_int;
|
|
reg dbiterra_int;
|
|
reg sbiterrb_int;
|
|
reg dbiterrb_int;
|
|
|
|
function [7:0] fn_ecc_enc_dec (
|
|
input encode,
|
|
input [63:0] d_i,
|
|
input [7:0] dp_i
|
|
);
|
|
reg ecc_7;
|
|
begin
|
|
fn_ecc_enc_dec[0] = d_i[0] ^ d_i[1] ^ d_i[3] ^ d_i[4] ^ d_i[6] ^
|
|
d_i[8] ^ d_i[10] ^ d_i[11] ^ d_i[13] ^ d_i[15] ^
|
|
d_i[17] ^ d_i[19] ^ d_i[21] ^ d_i[23] ^ d_i[25] ^
|
|
d_i[26] ^ d_i[28] ^ d_i[30] ^ d_i[32] ^ d_i[34] ^
|
|
d_i[36] ^ d_i[38] ^ d_i[40] ^ d_i[42] ^ d_i[44] ^
|
|
d_i[46] ^ d_i[48] ^ d_i[50] ^ d_i[52] ^ d_i[54] ^
|
|
d_i[56] ^ d_i[57] ^ d_i[59] ^ d_i[61] ^ d_i[63];
|
|
|
|
fn_ecc_enc_dec[1] = d_i[0] ^ d_i[2] ^ d_i[3] ^ d_i[5] ^ d_i[6] ^
|
|
d_i[9] ^ d_i[10] ^ d_i[12] ^ d_i[13] ^ d_i[16] ^
|
|
d_i[17] ^ d_i[20] ^ d_i[21] ^ d_i[24] ^ d_i[25] ^
|
|
d_i[27] ^ d_i[28] ^ d_i[31] ^ d_i[32] ^ d_i[35] ^
|
|
d_i[36] ^ d_i[39] ^ d_i[40] ^ d_i[43] ^ d_i[44] ^
|
|
d_i[47] ^ d_i[48] ^ d_i[51] ^ d_i[52] ^ d_i[55] ^
|
|
d_i[56] ^ d_i[58] ^ d_i[59] ^ d_i[62] ^ d_i[63];
|
|
|
|
fn_ecc_enc_dec[2] = d_i[1] ^ d_i[2] ^ d_i[3] ^ d_i[7] ^ d_i[8] ^
|
|
d_i[9] ^ d_i[10] ^ d_i[14] ^ d_i[15] ^ d_i[16] ^
|
|
d_i[17] ^ d_i[22] ^ d_i[23] ^ d_i[24] ^ d_i[25] ^
|
|
d_i[29] ^ d_i[30] ^ d_i[31] ^ d_i[32] ^ d_i[37] ^
|
|
d_i[38] ^ d_i[39] ^ d_i[40] ^ d_i[45] ^ d_i[46] ^
|
|
d_i[47] ^ d_i[48] ^ d_i[53] ^ d_i[54] ^ d_i[55] ^
|
|
d_i[56] ^ d_i[60] ^ d_i[61] ^ d_i[62] ^ d_i[63];
|
|
|
|
fn_ecc_enc_dec[3] = d_i[4] ^ d_i[5] ^ d_i[6] ^ d_i[7] ^ d_i[8] ^
|
|
d_i[9] ^ d_i[10] ^ d_i[18] ^ d_i[19] ^ d_i[20] ^
|
|
d_i[21] ^ d_i[22] ^ d_i[23] ^ d_i[24] ^ d_i[25] ^
|
|
d_i[33] ^ d_i[34] ^ d_i[35] ^ d_i[36] ^ d_i[37] ^
|
|
d_i[38] ^ d_i[39] ^ d_i[40] ^ d_i[49] ^ d_i[50] ^
|
|
d_i[51] ^ d_i[52] ^ d_i[53] ^ d_i[54] ^ d_i[55] ^
|
|
d_i[56];
|
|
|
|
fn_ecc_enc_dec[4] = d_i[11] ^ d_i[12] ^ d_i[13] ^ d_i[14] ^ d_i[15] ^
|
|
d_i[16] ^ d_i[17] ^ d_i[18] ^ d_i[19] ^ d_i[20] ^
|
|
d_i[21] ^ d_i[22] ^ d_i[23] ^ d_i[24] ^ d_i[25] ^
|
|
d_i[41] ^ d_i[42] ^ d_i[43] ^ d_i[44] ^ d_i[45] ^
|
|
d_i[46] ^ d_i[47] ^ d_i[48] ^ d_i[49] ^ d_i[50] ^
|
|
d_i[51] ^ d_i[52] ^ d_i[53] ^ d_i[54] ^ d_i[55] ^
|
|
d_i[56];
|
|
|
|
fn_ecc_enc_dec[5] = d_i[26] ^ d_i[27] ^ d_i[28] ^ d_i[29] ^ d_i[30] ^
|
|
d_i[31] ^ d_i[32] ^ d_i[33] ^ d_i[34] ^ d_i[35] ^
|
|
d_i[36] ^ d_i[37] ^ d_i[38] ^ d_i[39] ^ d_i[40] ^
|
|
d_i[41] ^ d_i[42] ^ d_i[43] ^ d_i[44] ^ d_i[45] ^
|
|
d_i[46] ^ d_i[47] ^ d_i[48] ^ d_i[49] ^ d_i[50] ^
|
|
d_i[51] ^ d_i[52] ^ d_i[53] ^ d_i[54] ^ d_i[55] ^
|
|
d_i[56];
|
|
|
|
fn_ecc_enc_dec[6] = d_i[57] ^ d_i[58] ^ d_i[59] ^ d_i[60] ^ d_i[61] ^
|
|
d_i[62] ^ d_i[63];
|
|
|
|
ecc_7 = d_i[0] ^ d_i[1] ^ d_i[2] ^ d_i[3] ^ d_i[4] ^
|
|
d_i[5] ^ d_i[6] ^ d_i[7] ^ d_i[8] ^ d_i[9] ^
|
|
d_i[10] ^ d_i[11] ^ d_i[12] ^ d_i[13] ^ d_i[14] ^
|
|
d_i[15] ^ d_i[16] ^ d_i[17] ^ d_i[18] ^ d_i[19] ^
|
|
d_i[20] ^ d_i[21] ^ d_i[22] ^ d_i[23] ^ d_i[24] ^
|
|
d_i[25] ^ d_i[26] ^ d_i[27] ^ d_i[28] ^ d_i[29] ^
|
|
d_i[30] ^ d_i[31] ^ d_i[32] ^ d_i[33] ^ d_i[34] ^
|
|
d_i[35] ^ d_i[36] ^ d_i[37] ^ d_i[38] ^ d_i[39] ^
|
|
d_i[40] ^ d_i[41] ^ d_i[42] ^ d_i[43] ^ d_i[44] ^
|
|
d_i[45] ^ d_i[46] ^ d_i[47] ^ d_i[48] ^ d_i[49] ^
|
|
d_i[50] ^ d_i[51] ^ d_i[52] ^ d_i[53] ^ d_i[54] ^
|
|
d_i[55] ^ d_i[56] ^ d_i[57] ^ d_i[58] ^ d_i[59] ^
|
|
d_i[60] ^ d_i[61] ^ d_i[62] ^ d_i[63];
|
|
|
|
if (encode) begin
|
|
fn_ecc_enc_dec[7] = ecc_7 ^
|
|
fn_ecc_enc_dec[0] ^ fn_ecc_enc_dec[1] ^ fn_ecc_enc_dec[2] ^ fn_ecc_enc_dec[3] ^
|
|
fn_ecc_enc_dec[4] ^ fn_ecc_enc_dec[5] ^ fn_ecc_enc_dec[6];
|
|
end
|
|
else begin
|
|
fn_ecc_enc_dec[7] = ecc_7 ^
|
|
dp_i[0] ^ dp_i[1] ^ dp_i[2] ^ dp_i[3] ^
|
|
dp_i[4] ^ dp_i[5] ^ dp_i[6];
|
|
end
|
|
end
|
|
endfunction // fn_ecc_enc_dec
|
|
|
|
function [71:0] fn_correct_bit (
|
|
input [6:0] error_bit,
|
|
input [63:0] d_i,
|
|
input [7:0] dp_i
|
|
);
|
|
reg [71:0] cor_int;
|
|
begin
|
|
cor_int = {d_i[63:57], dp_i[6], d_i[56:26], dp_i[5], d_i[25:11], dp_i[4],
|
|
d_i[10:4], dp_i[3], d_i[3:1], dp_i[2], d_i[0], dp_i[1:0],
|
|
dp_i[7]};
|
|
cor_int[error_bit] = ~cor_int[error_bit];
|
|
fn_correct_bit = {cor_int[0], cor_int[64], cor_int[32], cor_int[16],
|
|
cor_int[8], cor_int[4], cor_int[2:1], cor_int[71:65],
|
|
cor_int[63:33], cor_int[31:17], cor_int[15:9],
|
|
cor_int[7:5], cor_int[3]};
|
|
end
|
|
endfunction // fn_correct_bit
|
|
|
|
|
|
`ifndef OBSOLETE
|
|
`ifndef DISABLE_XPM_ASSERTIONS
|
|
if(SIM_ASSERT_CHK == 1) begin : ecc_cover
|
|
// Assertions to catch some of the valid/mandatory configurations of ECC
|
|
if(`BOTH_ENC_DEC) begin : chk_vld_ecc_both_configs
|
|
// checks to see if error injection is covered
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration.", addrb, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && injectdbiterra && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_BOTH_ERR_INJ_ASSRT: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && injectdbiterrb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_BOTH_ERR_INJ_ASSRT: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration.", addrb, $time);
|
|
|
|
// checks to see if error injection is covered during reset
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_RST_ASSRT: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_RST_ASSRT: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_RST_ASSRT: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_RST_ASSRT: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset.", addrb, $time);
|
|
|
|
// Check if sleep port is asserted on both port-a and port-b
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode.", addrb, $time);
|
|
|
|
// checks to see if error injection is covered during sleep & reset
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted.", addrb, $time);
|
|
|
|
// Check if out-of range addresses are driven
|
|
// Check if the error injection is happening
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode and the address being out of range.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode and the address being out of range.", addrb, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset and the address being out of range.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during reset and the address being out of range.", addrb, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted and the address being out of range.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in both Encode and Decode mode configuration during sleep mode with reset asserted and the address being out of range.", addrb, $time);
|
|
end : chk_vld_ecc_both_configs
|
|
|
|
if(`ENC_ONLY) begin : chk_vld_ecc_enc_only_configs
|
|
// checks to see if error injection is covered
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration.", addrb, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && injectdbiterra && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_BOTH_ERR_INJ_ASSRT: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && injectdbiterrb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_BOTH_ERR_INJ_ASSRT: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration.", addrb, $time);
|
|
|
|
|
|
// checks to see if error injection is covered during reset
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_RST_ASSRT: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during reset.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_RST_ASSRT: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during reset.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_RST_ASSRT: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during reset.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_RST_ASSRT: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during reset.", addrb, $time);
|
|
|
|
// Check if sleep port is asserted on both port-a and port-b
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode.", addrb, $time);
|
|
|
|
// checks to see if error injection is covered during sleep & reset
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && rsta && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && rstb && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted.", addrb, $time);
|
|
|
|
// Check if out-of range addresses are driven
|
|
// Check if the error injection is happening
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode and the address being out of range.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode and the address being out of range.", addrb, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during reset and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during reset and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during reset and the address being out of range.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during reset and the address being out of range.", addrb, $time);
|
|
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectsbiterra && sleep && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && injectdbiterra && sleep && rsta && addra > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-A at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted and the address being out of range.", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectsbiterrb && sleep && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_INJ_ASSRT_SLEEP: single bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted and the address being out of range.", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(enb && |web && injectdbiterrb && sleep && rstb && addrb > P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_INJ_ASSRT_SLEEP: double bit error into the memory through Port-B at address 0x%0h at time %0t happened in encode only mode configuration during sleep mode with reset asserted and the address being out of range.", addrb, $time);
|
|
end : chk_vld_ecc_enc_only_configs
|
|
|
|
if(`DEC_ONLY) begin : chk_vld_ecc_dec_only_configs
|
|
// Decode only mode Checks
|
|
assert property (@(posedge clka)
|
|
!(sbiterra_int && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_STATUS: single bit error asserted through Port-A at address 0x%0h at time %0t in decode only mode configuration", addra, $time);
|
|
assert property (@(posedge clka)
|
|
!(dbiterra_int && addra <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_STATUS: single bit error asserted through Port-A at address 0x%0h at time %0t in decode only mode configuration", addra, $time);
|
|
assert property (@(posedge clkb)
|
|
!(sbiterrb_int && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_SINGLE_BIT_ERR_STATUS: single bit error asserted through Port-B at address 0x%0h at time %0t in decode only mode configuration", addrb, $time);
|
|
assert property (@(posedge clkb)
|
|
!(dbiterrb_int && addrb <= P_MAX_DEPTH_DATA))
|
|
else
|
|
$info("XPM_MEMORY_DOUBLE_BIT_ERR_STATUS: single bit error asserted through Port-B at address 0x%0h at time %0t in decode only mode configuration", addrb, $time);
|
|
end : chk_vld_ecc_dec_only_configs
|
|
|
|
// Check if there is a collision that happened during ECC mode w.r.t
|
|
// data and error status ports
|
|
end : ecc_cover
|
|
`endif
|
|
`endif
|
|
|
|
function [P_MIN_WIDTH_PARITY_ECC-1:0] ecc_init_mem_loc;
|
|
input [WRITE_DATA_WIDTH_A-1 : 0] data_in;
|
|
integer data_slice;
|
|
for (data_slice=1; data_slice <= WRITE_DATA_WIDTH_A/64; data_slice=data_slice+1) begin
|
|
//ecc_init_mem_loc[(72*data_slice)-9 : (72*data_slice)-72] = data_in[(64*data_slice)-1 : (data_slice-1)*64];
|
|
ecc_init_mem_loc[(72*data_slice)-9 -: 64] = data_in[(64*data_slice)-1 -: 64];
|
|
ecc_init_mem_loc[(72*data_slice)-1 -: 8] = fn_ecc_enc_dec(1'b1, data_in[(64*data_slice)-1 -: 64], 8'h00);
|
|
end
|
|
endfunction
|
|
|
|
// Memory Array Initialization
|
|
initial begin
|
|
if (`NO_MEMORY_INIT) begin : init_zeroes
|
|
integer ecc_initword;
|
|
for (ecc_initword=0; ecc_initword<P_MAX_DEPTH_DATA; ecc_initword=ecc_initword+1) begin
|
|
mem_ecc[ecc_initword] = {P_MIN_WIDTH_PARITY_ECC{1'b0}};
|
|
end
|
|
end : init_zeroes
|
|
else begin : init_datafile
|
|
if (ECC_MODE == 3 ) begin
|
|
$readmemh(MEMORY_INIT_FILE, mem_ecc, 0, P_MAX_DEPTH_DATA-1);
|
|
end else begin
|
|
$readmemh(MEMORY_INIT_FILE, mem_ecc, 0, P_MAX_DEPTH_DATA-1);
|
|
for(int i=0; i<P_MAX_DEPTH_DATA; i=i+1) begin
|
|
mem_ecc[i] = ecc_init_mem_loc(mem_ecc[i]);
|
|
end
|
|
end
|
|
end : init_datafile
|
|
end
|
|
|
|
reg [P_MIN_WIDTH_PARITY_ECC-1 : 0] din_to_mem_ecc_a;
|
|
reg [P_MIN_WIDTH_PARITY_ECC-1 : 0] din_to_mem_ecc_b;
|
|
|
|
if (ECC_MODE == 3 && `NO_MEMORY_INIT) begin : en_enc_dec
|
|
// memory declaration (aspect ratio is not supported when ECC Enabled)
|
|
// Actual Template needs to be supplied by synthesis team
|
|
reg [0:0] sbiterr_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [0:0] dbiterr_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [P_MIN_WIDTH_PARITY_ECC-1 : 0] din_to_mem_ecc_a_tdp_ultra;
|
|
initial begin
|
|
sbiterrb_int <= 1'b0;
|
|
dbiterrb_int <= 1'b0;
|
|
sbiterra_int <= 1'b0;
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
|
|
for (genvar data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin : ecc_data_calc_a
|
|
always @(posedge clka) begin : ecc_enc_only_data_wr
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (!(enb_i && |web_i && addrb_i == addra_i)) begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
mem_ecc[addra_i][(64*data_slice_a)-1 : (data_slice_a-1)*64] <= {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else
|
|
mem_ecc[addra_i][(64*data_slice_a)-1 : (data_slice_a-1)*64] <= dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
mem_ecc[addra_i][(64*data_slice_a)-1 : (data_slice_a-1)*64] <= {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else
|
|
mem_ecc[addra_i][(64*data_slice_a)-1 : (data_slice_a-1)*64] <= dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64];
|
|
end
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr
|
|
end : ecc_data_calc_a
|
|
|
|
always @(posedge clka) begin: store_injbiterra
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (!(enb_i && |web_i && addrb_i == addra_i)) begin
|
|
if(|wea_i) begin
|
|
if(injectsbiterra_sim == 1'b1)
|
|
sbiterr_status[addra_i] <= 1'b1;
|
|
else
|
|
sbiterr_status[addra_i] <= 1'b0;
|
|
if(injectdbiterra_sim == 1'b1)
|
|
dbiterr_status[addra_i] <= 1'b1;
|
|
else
|
|
dbiterr_status[addra_i] <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if(|wea_i) begin
|
|
if(injectsbiterra_sim == 1'b1)
|
|
sbiterr_status[addra_i] <= 1'b1;
|
|
else
|
|
sbiterr_status[addra_i] <= 1'b0;
|
|
if(injectdbiterra_sim == 1'b1)
|
|
dbiterr_status[addra_i] <= 1'b1;
|
|
else
|
|
dbiterr_status[addra_i] <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
end : store_injbiterra
|
|
|
|
if (`MEM_PORTB_WRITE && (`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO)) begin : ecc_both_data_wrb
|
|
for (genvar data_slice_b=1; data_slice_b <= WRITE_DATA_WIDTH_B/64; data_slice_b=data_slice_b+1) begin : ecc_data_calc_b
|
|
always @(posedge gen_wr_b.clkb_int) begin : ecc_enc_only_data_wr
|
|
if(enb_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|web_i) begin
|
|
if(injectdbiterrb_sim) begin
|
|
mem_ecc[addrb_i][(64*data_slice_b)-1 : (data_slice_b-1)*64] <= {dinb_i[(64*data_slice_b)-1],~dinb_i[(64*data_slice_b)-2] ,dinb_i[(64*data_slice_b)-3 : (64*data_slice_b)-33],~dinb_i[(64*data_slice_b)-34],dinb_i[(64*data_slice_b)-35 : (data_slice_b-1)*64]};
|
|
din_to_mem_ecc_b <= {dinb_i[(64*data_slice_b)-1],~dinb_i[(64*data_slice_b)-2] ,dinb_i[(64*data_slice_b)-3 : (64*data_slice_b)-33],~dinb_i[(64*data_slice_b)-34],dinb_i[(64*data_slice_b)-35 : (data_slice_b-1)*64]};
|
|
end
|
|
else begin
|
|
mem_ecc[addrb_i][(64*data_slice_b)-1 : (data_slice_b-1)*64] <= dinb_i[(64*data_slice_b)-1 : (data_slice_b-1)*64];
|
|
din_to_mem_ecc_b <= dinb_i[(64*data_slice_b)-1 : (data_slice_b-1)*64];
|
|
end
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr
|
|
end : ecc_data_calc_b
|
|
|
|
always @(posedge gen_wr_b.clkb_int) begin: errb_status_proc
|
|
if(enb_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if (|web_i) begin
|
|
if(injectsbiterrb_sim == 1'b1)
|
|
sbiterr_status[addrb_i] <= 1'b1;
|
|
else
|
|
sbiterr_status[addrb_i] <= 1'b0;
|
|
if(injectdbiterrb_sim == 1'b1)
|
|
dbiterr_status[addrb_i] <= 1'b1;
|
|
else
|
|
dbiterr_status[addrb_i] <= 1'b0;
|
|
end
|
|
end
|
|
end : errb_status_proc
|
|
end : ecc_both_data_wrb
|
|
|
|
// Single Bit Error Injection
|
|
// Error Injecting Position is dina|b[30] : Corrupted data need not be
|
|
// written to memory as the decoder will correct the data.
|
|
// Double Bit Error Injection
|
|
// Error Injecting bit-Positions are dina|b[30] and dina|b[62]
|
|
if ((`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO) && (`MEM_TYPE_RAM_SP || `MEM_TYPE_RAM_TDP)) begin : nc_rf_wf_porta
|
|
if (`MEM_PORTA_NC) begin : nc_prta
|
|
always @(posedge clka) begin: erra_status
|
|
if (sleep_int_a || sleep_int_b == 1'b1 || (addra_aslp_sim >= P_MAX_DEPTH_DATA)) begin
|
|
if(ena_i & ~(|wea_i)) begin
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rsta && READ_LATENCY_A ==1) begin
|
|
sbiterra_int <= 1'b0;
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
else if(ena_i) begin
|
|
if(~(|wea_i)) begin
|
|
if (sbiterr_status[addra_i] == 1'b1)
|
|
sbiterra_int <= 1'b1;
|
|
else
|
|
sbiterra_int <= 1'b0;
|
|
if (dbiterr_status[addra_i] == 1'b1)
|
|
dbiterra_int <= 1'b1;
|
|
else
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
end
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.sbiterra_in_pipe = sbiterra_int & ~dbiterra_int;
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.dbiterra_in_pipe = dbiterra_int;
|
|
end : erra_status
|
|
always @(posedge clka) begin
|
|
if(rsta && READ_LATENCY_A ==1)
|
|
deassign gen_rd_a.douta_reg;
|
|
else begin
|
|
if(addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(ena_i && ~(|wea_i) && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
douta_int <= mem_ecc[addra_i];
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
else begin
|
|
douta_int <= 'bX;
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
end
|
|
end : nc_prta
|
|
if (`MEM_PORTA_RF) begin : rf_prta
|
|
always @(posedge clka) begin: erra_status
|
|
if (sleep_int_a || sleep_int_b == 1'b1 || (addra_aslp_sim >= P_MAX_DEPTH_DATA)) begin
|
|
if(ena_i) begin
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rsta && READ_LATENCY_A ==1) begin
|
|
sbiterra_int <= 1'b0;
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
else if(ena_i) begin
|
|
if (sbiterr_status[addra_i] == 1'b1)
|
|
sbiterra_int <= 1'b1;
|
|
else
|
|
sbiterra_int <= 1'b0;
|
|
if (dbiterr_status[addra_i] == 1'b1)
|
|
dbiterra_int <= 1'b1;
|
|
else
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.sbiterra_in_pipe = sbiterra_int & ~dbiterra_int;
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.dbiterra_in_pipe = dbiterra_int;
|
|
end : erra_status
|
|
always @(posedge clka) begin
|
|
if(rsta && READ_LATENCY_A ==1)
|
|
deassign gen_rd_a.douta_reg;
|
|
else begin
|
|
if(addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
douta_int <= mem_ecc[addra_i];
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
else begin
|
|
douta_int <= 'bX;
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
end
|
|
end : rf_prta
|
|
|
|
if (`MEM_PORTA_WF) begin : wf_porta
|
|
always @(posedge clka) begin: erra_status
|
|
if (sleep_int_a || sleep_int_b == 1'b1 || (addra_aslp_sim >= P_MAX_DEPTH_DATA)) begin
|
|
if(ena_i) begin
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rsta && READ_LATENCY_A ==1) begin
|
|
sbiterra_int <= 1'b0;
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
else if(ena_i) begin
|
|
if(|wea_i) begin
|
|
if(injectsbiterra_sim)
|
|
sbiterra_int <= 1'b1;
|
|
else
|
|
sbiterra_int <= 1'b0;
|
|
if(injectdbiterra_sim)
|
|
dbiterra_int <= 1'b1;
|
|
else
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
else begin
|
|
if (sbiterr_status[addra_i] == 1'b1)
|
|
sbiterra_int <= 1'b1;
|
|
else
|
|
sbiterra_int <= 1'b0;
|
|
if (dbiterr_status[addra_i] == 1'b1)
|
|
dbiterra_int <= 1'b1;
|
|
else
|
|
dbiterra_int <= 1'b0;
|
|
end
|
|
end
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.sbiterra_in_pipe = sbiterra_int & ~dbiterra_int;
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.dbiterra_in_pipe = dbiterra_int;
|
|
end : erra_status
|
|
for (genvar data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin : ecc_data_calc_a
|
|
always @(*) begin : ecc_enc_only_data_wr
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
din_to_mem_ecc_a[(64*data_slice_a)-1 : (data_slice_a-1)*64] = {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr
|
|
end : ecc_data_calc_a
|
|
|
|
always @(posedge clka) begin
|
|
if(rsta && READ_LATENCY_A ==1)
|
|
deassign gen_rd_a.douta_reg;
|
|
else begin
|
|
if(addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
if(|wea_i) begin
|
|
if (injectdbiterra_sim)
|
|
douta_int <= din_to_mem_ecc_a;
|
|
else
|
|
douta_int <= dina_i;
|
|
end
|
|
else
|
|
douta_int <= mem_ecc[addra_i];
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
else begin
|
|
douta_int <= 'bX;
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
end
|
|
end : wf_porta
|
|
end : nc_rf_wf_porta
|
|
if (`MEM_PORTB_READ) begin : dbiterrb_data_gen_proc
|
|
// Only No_Change mode behavior is considered, as TDP + URAM supports
|
|
// no_change mode. This will work for BRAM as only SDP mode is supported
|
|
always @(posedge gen_rd_b.clkb_int) begin: sbiterrb_gen_proc
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1 || (addrb_aslp_sim >= P_MAX_DEPTH_DATA)) begin
|
|
if (enb_i & ~(|web_i)) begin
|
|
sbiterrb_int <= 1'bX;
|
|
dbiterrb_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rstb && READ_LATENCY_B ==1) begin
|
|
sbiterrb_int <= 1'b0;
|
|
dbiterrb_int <= 1'b0;
|
|
end
|
|
else if(enb_i & ~(|web_i)) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (ena_i && |wea_i && (addra_i == addrb_i) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(injectsbiterra_sim)
|
|
sbiterrb_int <= 1'b1;
|
|
else
|
|
sbiterrb_int <= 1'b0;
|
|
if(injectdbiterra_sim)
|
|
dbiterrb_int <= 1'b1;
|
|
else
|
|
dbiterrb_int <= 1'b0;
|
|
end
|
|
else begin
|
|
if (sbiterr_status[addrb_i] == 1'b1)
|
|
sbiterrb_int <= 1'b1;
|
|
else
|
|
sbiterrb_int <= 1'b0;
|
|
if (dbiterr_status[addrb_i] == 1'b1)
|
|
dbiterrb_int <= 1'b1;
|
|
else
|
|
dbiterrb_int <= 1'b0;
|
|
end
|
|
end
|
|
else begin
|
|
if (sbiterr_status[addrb_i] == 1'b1)
|
|
sbiterrb_int <= 1'b1;
|
|
else
|
|
sbiterrb_int <= 1'b0;
|
|
if (dbiterr_status[addrb_i] == 1'b1)
|
|
dbiterrb_int <= 1'b1;
|
|
else
|
|
dbiterrb_int <= 1'b0;
|
|
end
|
|
end
|
|
assign gen_rd_b.pipeline_ecc_status.sbiterrb_in_pipe = sbiterrb_int & ~dbiterrb_int;
|
|
assign gen_rd_b.pipeline_ecc_status.dbiterrb_in_pipe = dbiterrb_int;
|
|
end : sbiterrb_gen_proc
|
|
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin : tdp_ultra_wf_gen
|
|
for (genvar data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin : ecc_data_calc_a
|
|
always @(*) begin : ecc_enc_only_data_wr
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
din_to_mem_ecc_a_tdp_ultra[(64*data_slice_a)-1 : (data_slice_a-1)*64] = {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr
|
|
end : ecc_data_calc_a
|
|
end : tdp_ultra_wf_gen
|
|
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
if (rstb && READ_LATENCY_B == 1)
|
|
deassign gen_rd_b.doutb_reg;
|
|
else begin
|
|
if(addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(enb_i & ~(|web_i) && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
// If A is writing and B is reading then it should read the new data
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (ena_i && |wea_i && (addra_i == addrb_i) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(injectdbiterra_sim) begin
|
|
doutb_int <= din_to_mem_ecc_a_tdp_ultra;
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
else begin
|
|
doutb_int <= dina_i;
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
end
|
|
else begin
|
|
doutb_int <= mem_ecc[addrb_i];
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
end
|
|
else begin
|
|
doutb_int <= mem_ecc[addrb_i];
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
doutb_int <= 'bX;
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
end
|
|
end
|
|
end : dbiterrb_data_gen_proc
|
|
end : en_enc_dec
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
/**ECC Behavioral Modeling when Encoder only is enabled
|
|
This module need to perform the parity calculations on the data and write to the memroy
|
|
This module needs to model the Error Injection, corrupt the data and
|
|
write to the memory
|
|
Error status signals can never get asserted here
|
|
**/
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
if (ECC_MODE == 1 || (ECC_MODE == 3 && !(`NO_MEMORY_INIT))) begin : en_enc_only
|
|
|
|
// memory declaration (aspect ratio is not supported when ECC Enabled)
|
|
// Actual Template needs to be supplied by synthesis team
|
|
|
|
|
|
reg [0:0] sbiterr_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [0:0] dbiterr_status [0:P_MAX_DEPTH_DATA-1];
|
|
|
|
// Data is expected to be in the multiples of 64-bits
|
|
// Data - parity calculation can be continuously calculated
|
|
|
|
// The Implementation involves in 3 steps :
|
|
// 1. Memory Array in this case needs to be created with the width being
|
|
// multiple of 72 bits
|
|
// 2. Calculate the width of the vector comprising of data and parity
|
|
// 3. Have a generate statement to calculate the parity and assign to the
|
|
// din_to_mem_ecc vector
|
|
// 4. Have a generate statement to assign the data input to the proper
|
|
// segments of the din_to_mem_ecc vector
|
|
// 5. Assign the complete constructed data array to the memory
|
|
|
|
// Error Injection Implementation
|
|
// Memory needs to be corrupted for both Single and Double bit Error
|
|
// injection transactions here
|
|
|
|
for (genvar data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin : ecc_data_calc_a
|
|
always @(posedge clka) begin : ecc_enc_only_data_wr
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (!(enb_i && |web_i && addrb_i == addra_i)) begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
mem_ecc[addra_i][(72*data_slice_a)-9 : (72*data_slice_a)-72] <= {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else if(injectsbiterra_sim)
|
|
mem_ecc[addra_i][(72*data_slice_a)-9 : (72*data_slice_a)-72] <= {dina_i[(64*data_slice_a)-1 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else
|
|
mem_ecc[addra_i][(72*data_slice_a)-9 : (72*data_slice_a)-72] <= dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64];
|
|
mem_ecc[addra_i][(72*data_slice_a)-1 : (72*data_slice_a)-8] <= fn_ecc_enc_dec(1'b1, dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64], 8'h00);
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
mem_ecc[addra_i][(72*data_slice_a)-9 : (72*data_slice_a)-72] <= {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else if(injectsbiterra_sim)
|
|
mem_ecc[addra_i][(72*data_slice_a)-9 : (72*data_slice_a)-72] <= {dina_i[(64*data_slice_a)-1 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else
|
|
mem_ecc[addra_i][(72*data_slice_a)-9 : (72*data_slice_a)-72] <= dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64];
|
|
mem_ecc[addra_i][(72*data_slice_a)-1 : (72*data_slice_a)-8] <= fn_ecc_enc_dec(1'b1, dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64], 8'h00);
|
|
end
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr
|
|
end : ecc_data_calc_a
|
|
|
|
if (`MEM_PORTB_WRITE && (`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO)) begin : data_in_proc_b
|
|
for (genvar data_slice_b=1; data_slice_b <= WRITE_DATA_WIDTH_B/64; data_slice_b=data_slice_b+1) begin : ecc_data_calc_b
|
|
always @(posedge gen_wr_b.clkb_int) begin : ecc_enc_only_data_wr_b
|
|
if(enb_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|web_i) begin
|
|
if(injectdbiterrb_sim)
|
|
mem_ecc[addrb_i][(72*data_slice_b)-9 : (72*data_slice_b)-72] <= {dinb_i[(64*data_slice_b)-1],~dinb_i[(64*data_slice_b)-2] ,dinb_i[(64*data_slice_b)-3 : (64*data_slice_b)-33],~dinb_i[(64*data_slice_b)-34],dinb_i[(64*data_slice_b)-35 : (data_slice_b-1)*64]};
|
|
else if(injectsbiterrb_sim)
|
|
mem_ecc[addrb_i][(72*data_slice_b)-9 : (72*data_slice_b)-72] <= {dinb_i[(64*data_slice_b)-1 : (64*data_slice_b)-33],~dinb_i[(64*data_slice_b)-34],dinb_i[(64*data_slice_b)-35 : (data_slice_b-1)*64]};
|
|
else
|
|
mem_ecc[addrb_i][(72*data_slice_b)-9 : (72*data_slice_b)-72] <= dinb_i[(64*data_slice_b)-1 : (data_slice_b-1)*64];
|
|
mem_ecc[addrb_i][(72*data_slice_b)-1 : (72*data_slice_b)-8] <= fn_ecc_enc_dec(1'b1, dinb_i[(64*data_slice_b)-1 : (data_slice_b-1)*64], 8'h00);
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr_b
|
|
end : ecc_data_calc_b
|
|
end : data_in_proc_b
|
|
if (ECC_MODE == 1 && `MEM_PORTB_READ) begin : data_enc_only
|
|
always @(posedge gen_rd_b.clkb_int) begin: data_out_proc_b
|
|
if (rstb && READ_LATENCY_B == 1)
|
|
deassign gen_rd_b.doutb_reg;
|
|
else if(enb_i && ~(|web_i) && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (ena_i && |wea_i && (addra_i == addrb_i) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(injectdbiterra_sim) begin
|
|
for (integer data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin
|
|
din_to_mem_ecc_a[(72*data_slice_a)-9 -: 64] = {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 -: 31],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 -: 30]};
|
|
din_to_mem_ecc_a[(72*data_slice_a)-1 -: 8] = fn_ecc_enc_dec(1'b1, dina_i[(64*data_slice_a)-1 -: 64], 8'h00);
|
|
end
|
|
end
|
|
else if(injectsbiterra_sim) begin
|
|
for (integer data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin
|
|
din_to_mem_ecc_a[(72*data_slice_a)-9 -: 64] = {dina_i[(64*data_slice_a)-1 -:33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 -: 30]};
|
|
din_to_mem_ecc_a[(72*data_slice_a)-1 -: 8] = fn_ecc_enc_dec(1'b1, dina_i[(64*data_slice_a)-1 -: 64], 8'h00);
|
|
end
|
|
end
|
|
else begin
|
|
for (integer data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin
|
|
din_to_mem_ecc_a[(72*data_slice_a)-9 -: 64] = dina_i[(64*data_slice_a)-1 -: 64];
|
|
din_to_mem_ecc_a[(72*data_slice_a)-1 -: 8] = fn_ecc_enc_dec(1'b1, dina_i[(64*data_slice_a)-1 -: 64], 8'h00);
|
|
end
|
|
end
|
|
doutb_int <= din_to_mem_ecc_a;
|
|
end
|
|
else begin
|
|
if(addrb_aslp_sim < P_MAX_DEPTH_DATA)
|
|
doutb_int <= mem_ecc[addrb_i];
|
|
else
|
|
doutb_int <= 'bX;
|
|
end
|
|
end
|
|
else begin
|
|
if(addrb_aslp_sim < P_MAX_DEPTH_DATA)
|
|
doutb_int <= mem_ecc[addrb_i];
|
|
else
|
|
doutb_int <= 'bX;
|
|
end
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
end : data_out_proc_b
|
|
end : data_enc_only
|
|
|
|
if (`MEM_PORTA_READ && (`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO)) begin : data_out_proc_a
|
|
// Here the write mode can be Write First, Read First or No Change for
|
|
// SPRAM, and for TDP it is always No Change
|
|
if (`MEM_PORTA_RF) begin : rf_prta
|
|
always @(posedge clka) begin
|
|
if (rsta && READ_LATENCY_A == 1)
|
|
deassign gen_rd_a.douta_reg;
|
|
else if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
if(addra_aslp_sim < P_MAX_DEPTH_DATA)
|
|
douta_int <= mem_ecc[addra_i];
|
|
else
|
|
douta_int <= 'bX;
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
end : rf_prta
|
|
if (`MEM_PORTA_NC) begin : nc_prta
|
|
always @(posedge clka) begin
|
|
if (rsta && READ_LATENCY_A == 1)
|
|
deassign gen_rd_a.douta_reg;
|
|
else if(ena_i & ~(|wea_i) && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
if(addra_aslp_sim < P_MAX_DEPTH_DATA)
|
|
douta_int <= mem_ecc[addra_i];
|
|
else
|
|
douta_int <= 'bX;
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
end : nc_prta
|
|
if (`MEM_PORTA_WF) begin : wf_prta
|
|
for (genvar data_slice_a=1; data_slice_a <= WRITE_DATA_WIDTH_A/64; data_slice_a=data_slice_a+1) begin : ecc_data_calc_a
|
|
always @(*) begin : ecc_enc_only_data_wr
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|wea_i) begin
|
|
if(injectdbiterra_sim)
|
|
din_to_mem_ecc_a[(72*data_slice_a)-9 : (72*data_slice_a)-72] = {dina_i[(64*data_slice_a)-1],~dina_i[(64*data_slice_a)-2] ,dina_i[(64*data_slice_a)-3 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else if(injectsbiterra_sim)
|
|
din_to_mem_ecc_a[(72*data_slice_a)-9 : (72*data_slice_a)-72] = {dina_i[(64*data_slice_a)-1 : (64*data_slice_a)-33],~dina_i[(64*data_slice_a)-34],dina_i[(64*data_slice_a)-35 : (data_slice_a-1)*64]};
|
|
else
|
|
din_to_mem_ecc_a[(72*data_slice_a)-9 : (72*data_slice_a)-72] = dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64];
|
|
din_to_mem_ecc_a[(72*data_slice_a)-1 : (72*data_slice_a)-8] = fn_ecc_enc_dec(1'b1, dina_i[(64*data_slice_a)-1 : (data_slice_a-1)*64], 8'h00);
|
|
end
|
|
end
|
|
end : ecc_enc_only_data_wr
|
|
end : ecc_data_calc_a
|
|
always @(posedge clka) begin
|
|
if (rsta && READ_LATENCY_A == 1)
|
|
deassign gen_rd_a.douta_reg;
|
|
else if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))) begin
|
|
if (addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|wea_i)
|
|
douta_int <= din_to_mem_ecc_a;
|
|
else
|
|
douta_int <= mem_ecc[addra_i];
|
|
end
|
|
else begin
|
|
douta_int <= 'bX;
|
|
end
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
end
|
|
end : wf_prta
|
|
end : data_out_proc_a
|
|
end : en_enc_only
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
/**ECC Behavioral Modeling when Decoder only is enabled
|
|
This module need not perform the parity calculation as the parity needs to be supplied by the user
|
|
But, this needs to check the parity correctness and assert the error
|
|
status bits. (sbiterr and dbiterr status signals)
|
|
This module needs to model the Error Injection
|
|
**/
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
if ((ECC_MODE == 3 && !(`NO_MEMORY_INIT)) || ECC_MODE == 2) begin : en_dec_only
|
|
// memory declaration (aspect ratio is not supported when ECC Enabled)
|
|
reg [0:0] sbiterra_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [0:0] dbiterra_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [7:0] synda_i [(WRITE_DATA_WIDTH_A/72)-1:0];
|
|
reg [7:0] synda_calc [(WRITE_DATA_WIDTH_A/72)-1:0];
|
|
reg [(WRITE_DATA_WIDTH_A/72)-1:0] sbita_calc;
|
|
reg [(WRITE_DATA_WIDTH_A/72)-1:0] dbita_calc;
|
|
reg [WRITE_DATA_WIDTH_A-1 : 0] douta_frm_mem_ecc = 'b0;
|
|
reg [READ_DATA_WIDTH_A-1 : 0] douta_frm_mem_ecc_out = 'b0; // always to be in multiples of 64, data to be forced on to dout
|
|
|
|
reg [0:0] sbiterrb_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [0:0] dbiterrb_status [0:P_MAX_DEPTH_DATA-1];
|
|
reg [7:0] syndb_i [(WRITE_DATA_WIDTH_A/72)-1:0];
|
|
reg [7:0] syndb_calc [(WRITE_DATA_WIDTH_A/72)-1:0];
|
|
reg [(WRITE_DATA_WIDTH_A/72)-1:0] sbitb_calc;
|
|
reg [(WRITE_DATA_WIDTH_A/72)-1:0] dbitb_calc;
|
|
reg [WRITE_DATA_WIDTH_A-1 : 0] doutb_frm_mem_ecc = 'b0;
|
|
reg [READ_DATA_WIDTH_B-1 : 0] doutb_frm_mem_ecc_out = 'b0; // always to be in multiples of 64, data to be forced on to dout
|
|
|
|
initial begin
|
|
sbiterra_int <= 1'b0;
|
|
dbiterra_int <= 1'b0;
|
|
sbiterrb_int <= 1'b0;
|
|
dbiterrb_int <= 1'b0;
|
|
end
|
|
|
|
// Data is expected to be in the multiples of 72-bits
|
|
// Data - parity calculation can be continuously calculated
|
|
// and compare it with what user supplied
|
|
|
|
// The Implementation involves in 3 steps :
|
|
// 1. Memory Array in this case needs to be created with the width being
|
|
// multiple of 72 bits
|
|
// 2. write the data to the memory
|
|
// 3. Always Read the data from memory based on the address, and separate
|
|
// data and parity bits
|
|
// 4. calculate the parity bits on the data
|
|
// 5. compare the user supplied parity bits with calculated syndrome bits
|
|
|
|
// Data to be written to the memory array, no error injection in decode only mode
|
|
if(ECC_MODE == 2) begin :data_dec_only
|
|
always @(posedge clka) begin : ecc_dec_only_data_wr
|
|
if(ena_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (!(enb_i && |web_i && addrb_i == addra_i)) begin
|
|
if(|wea_i)
|
|
mem_ecc[addra_i] <= dina_i;
|
|
end
|
|
end
|
|
else begin
|
|
if(|wea_i)
|
|
mem_ecc[addra_i] <= dina_i;
|
|
end
|
|
end
|
|
end : ecc_dec_only_data_wr
|
|
if (`MEM_PORTB_WRITE && (`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO)) begin : data_in_proc_b
|
|
always @(posedge gen_wr_b.clkb_int) begin
|
|
if(enb_i && (~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) && addrb_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if(|web_i)
|
|
mem_ecc[addrb_i] <= dinb_i;
|
|
end
|
|
end
|
|
end : data_in_proc_b
|
|
end : data_dec_only
|
|
|
|
if (`MEM_PORTB_READ) begin : data_out_proc_b
|
|
for (genvar dat_par_slice_b=1; dat_par_slice_b <= WRITE_DATA_WIDTH_A/72; dat_par_slice_b = dat_par_slice_b+1) begin : ecc_par_calc_b
|
|
always @(*) begin
|
|
if (enb_i & ~|web_i) begin
|
|
if(`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP) begin
|
|
if (ena_i) begin
|
|
if(|wea_i && (addra_i == addrb_i))
|
|
doutb_frm_mem_ecc = dina_i;
|
|
else
|
|
doutb_frm_mem_ecc = mem_ecc[addrb_i];
|
|
end
|
|
else
|
|
doutb_frm_mem_ecc = mem_ecc[addrb_i];
|
|
end
|
|
else
|
|
doutb_frm_mem_ecc = mem_ecc[addrb_i];
|
|
syndb_i[dat_par_slice_b-1] = fn_ecc_enc_dec(1'b0, doutb_frm_mem_ecc[(72*dat_par_slice_b)-9 : (72*dat_par_slice_b)-72], doutb_frm_mem_ecc[(72*dat_par_slice_b)-1 : (72*dat_par_slice_b)-8]);
|
|
syndb_calc[dat_par_slice_b-1] = syndb_i[dat_par_slice_b-1] ^ doutb_frm_mem_ecc[(72*dat_par_slice_b)-1 : (72*dat_par_slice_b)-8];
|
|
sbitb_calc[dat_par_slice_b-1] = |syndb_calc[dat_par_slice_b-1] && syndb_calc[dat_par_slice_b-1][7];
|
|
dbitb_calc[dat_par_slice_b-1] = |syndb_calc[dat_par_slice_b-1] && ~syndb_calc[dat_par_slice_b-1][7];
|
|
if(sbitb_calc[dat_par_slice_b-1] && ~dbitb_calc[dat_par_slice_b-1])
|
|
doutb_frm_mem_ecc_out[(64*dat_par_slice_b)-1 : (64*dat_par_slice_b)-64] = fn_correct_bit(syndb_calc[dat_par_slice_b-1], doutb_frm_mem_ecc[(72*dat_par_slice_b)-9 : (72*dat_par_slice_b)-72],doutb_frm_mem_ecc[(72*dat_par_slice_b)-1 : (72*dat_par_slice_b)-8]);
|
|
else
|
|
doutb_frm_mem_ecc_out[(64*dat_par_slice_b)-1 : (64*dat_par_slice_b)-64] = doutb_frm_mem_ecc[(72*dat_par_slice_b)-9 : (72*dat_par_slice_b)-72];
|
|
end
|
|
end
|
|
end : ecc_par_calc_b
|
|
|
|
always @(posedge gen_rd_b.clkb_int) begin: data_gen_proc
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1) begin
|
|
if(enb_i & ~(|web_i)) begin
|
|
sbiterrb_int <= 1'bX;
|
|
dbiterrb_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rstb && READ_LATENCY_B == 1) begin
|
|
assign gen_rd_b.doutb_reg = gen_rd_b.rstb_val;
|
|
sbiterrb_int <= 0;
|
|
dbiterrb_int <= 0;
|
|
end
|
|
else if(enb_i & ~(|web_i)) begin
|
|
if (addrb_aslp_sim >= P_MAX_DEPTH_DATA) begin
|
|
doutb_int <= 'bX;
|
|
sbiterrb_int <= 1'bX;
|
|
dbiterrb_int <= 1'bX;
|
|
end
|
|
else begin
|
|
doutb_int <= doutb_frm_mem_ecc_out;
|
|
sbiterrb_int <= |sbitb_calc;
|
|
dbiterrb_int <= |dbitb_calc;
|
|
end
|
|
assign gen_rd_b.doutb_reg = doutb_int;
|
|
end
|
|
assign gen_rd_b.pipeline_ecc_status.sbiterrb_in_pipe = sbiterrb_int;
|
|
assign gen_rd_b.pipeline_ecc_status.dbiterrb_in_pipe = dbiterrb_int;
|
|
end : data_gen_proc
|
|
end : data_out_proc_b
|
|
|
|
if (`MEM_PORTA_READ && (`MEM_PRIM_ULTRA || `MEM_PRIM_AUTO)) begin : data_out_proc_a
|
|
for (genvar dat_par_slice_a=1; dat_par_slice_a <= WRITE_DATA_WIDTH_A/72; dat_par_slice_a = dat_par_slice_a+1) begin : ecc_par_calc_a
|
|
always @(*) begin
|
|
if (addra_aslp_sim < P_MAX_DEPTH_DATA) begin
|
|
if (ena_i) begin
|
|
if(`MEM_PORTA_WF) begin
|
|
if(|wea_i)
|
|
douta_frm_mem_ecc = dina_i;
|
|
else
|
|
douta_frm_mem_ecc = mem_ecc[addra_i];
|
|
end
|
|
else begin
|
|
douta_frm_mem_ecc = mem_ecc[addra_i];
|
|
end
|
|
synda_i[dat_par_slice_a-1] = fn_ecc_enc_dec(1'b0, douta_frm_mem_ecc[(72*dat_par_slice_a)-9 : (72*dat_par_slice_a)-72], douta_frm_mem_ecc[(72*dat_par_slice_a)-1 : (72*dat_par_slice_a)-8]);
|
|
synda_calc[dat_par_slice_a-1] = synda_i[dat_par_slice_a-1] ^ douta_frm_mem_ecc[(72*dat_par_slice_a)-1 : (72*dat_par_slice_a)-8];
|
|
sbita_calc[dat_par_slice_a-1] = |synda_calc[dat_par_slice_a-1] && synda_calc[dat_par_slice_a-1][7];
|
|
dbita_calc[dat_par_slice_a-1] = |synda_calc[dat_par_slice_a-1] && ~synda_calc[dat_par_slice_a-1][7];
|
|
if(sbita_calc[dat_par_slice_a-1] && ~dbita_calc[dat_par_slice_a-1])
|
|
douta_frm_mem_ecc_out[(64*dat_par_slice_a)-1 : (64*dat_par_slice_a)-64] = fn_correct_bit(synda_calc[dat_par_slice_a-1], douta_frm_mem_ecc[(72*dat_par_slice_a)-9 : (72*dat_par_slice_a)-72],douta_frm_mem_ecc[(72*dat_par_slice_a)-1 : (72*dat_par_slice_a)-8]);
|
|
else
|
|
douta_frm_mem_ecc_out[(64*dat_par_slice_a)-1 : (64*dat_par_slice_a)-64] = douta_frm_mem_ecc[(72*dat_par_slice_a)-9 : (72*dat_par_slice_a)-72];
|
|
end
|
|
end
|
|
else begin
|
|
douta_frm_mem_ecc_out = 'bX;
|
|
sbita_calc = 'bX;
|
|
dbita_calc = 'bX;
|
|
end
|
|
end
|
|
end : ecc_par_calc_a
|
|
|
|
if (`MEM_PORTA_RF || `MEM_PORTA_WF) begin : rf_prta
|
|
always @(posedge clka) begin: data_gen_proc
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1) begin
|
|
if (ena_i) begin
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rsta && READ_LATENCY_A == 1) begin
|
|
assign gen_rd_a.douta_reg = gen_rd_a.rsta_val;
|
|
sbiterra_int <= 0;
|
|
dbiterra_int <= 0;
|
|
end
|
|
else if(ena_i) begin
|
|
if (addra_aslp_sim >= P_MAX_DEPTH_DATA) begin
|
|
douta_int <= 'bX;
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
else begin
|
|
douta_int <= douta_frm_mem_ecc_out;
|
|
sbiterra_int <= |sbita_calc;
|
|
dbiterra_int <= |dbita_calc;
|
|
end
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.sbiterra_in_pipe = sbiterra_int;
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.dbiterra_in_pipe = dbiterra_int;
|
|
end : data_gen_proc
|
|
end : rf_prta
|
|
|
|
if (`MEM_PORTA_NC) begin : nc_prta
|
|
always @(posedge clka) begin: data_gen_proc
|
|
if (sleep_int_a == 1'b1 || sleep_int_b == 1'b1) begin
|
|
if(ena_i & ~(|wea_i)) begin
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
end
|
|
else if (rsta && READ_LATENCY_A == 1) begin
|
|
assign gen_rd_a.douta_reg = gen_rd_a.rsta_val;
|
|
sbiterra_int <= 0;
|
|
dbiterra_int <= 0;
|
|
end
|
|
else if(ena_i & ~(|wea_i)) begin
|
|
if (addra_aslp_sim >= P_MAX_DEPTH_DATA) begin
|
|
douta_int <= 'bX;
|
|
sbiterra_int <= 1'bX;
|
|
dbiterra_int <= 1'bX;
|
|
end
|
|
else begin
|
|
douta_int <= douta_frm_mem_ecc_out;
|
|
sbiterra_int <= |sbita_calc;
|
|
dbiterra_int <= |dbita_calc;
|
|
end
|
|
assign gen_rd_a.douta_reg = douta_int;
|
|
end
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.sbiterra_in_pipe = sbiterra_int;
|
|
assign gen_rd_a.pipeline_ecc_status.status_out_proc_a.dbiterra_in_pipe = dbiterra_int;
|
|
end : data_gen_proc
|
|
end : nc_prta
|
|
end : data_out_proc_a
|
|
end : en_dec_only
|
|
end : ecc_behav_logic
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Asymmetry with Byte Write Enable Across Ports Implementation
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
if (`DISABLE_SYNTH_TEMPL) begin : gen_beh_model_bbox
|
|
`ifndef OBSOLETE
|
|
`ifndef DISABLE_XPM_ASSERTIONS
|
|
initial begin
|
|
if(SIM_ASSERT_CHK == 1) begin : chk_vld_asym_bwe_only_configs
|
|
/*
|
|
Check for the following conditions,
|
|
1. Byte writes enabled on both ports with Byte size being 8,9
|
|
2. Byte writes are enabled on only one port and the other being word wide read
|
|
*/
|
|
if(`MEM_PORTA_WRITE && `MEM_PORTA_WR_BYTE && `MEM_TYPE_RAM_SDP) begin
|
|
$info("XPM_MEMORY_ASSYM_BWE-1: Configuration selected is having Byte writes on Port-A, and the Read side is word-wide Read (Memory type is set to SDP)");
|
|
end
|
|
|
|
if(`MEM_PORTA_WRITE && `MEM_PORTA_WR_BYTE && `MEM_TYPE_RAM_TDP) begin
|
|
$info("XPM_MEMORY_ASSYM_BWE-2: Configuration selected is having Byte writes on Port-A, and the Read side is word-wide Read (Memory type is set to TDP)");
|
|
end
|
|
|
|
if(`MEM_PORTA_WR_BYTE && `MEM_PORTB_WR_BYTE && BYTE_WRITE_WIDTH_A == 8 && `MEM_TYPE_RAM_TDP) begin
|
|
$info("XPM_MEMORY_ASSYM_BWE-3: Configuration selected is having Byte writes on Port-A and Port-B (Memory type is set to TDP, and byte size is 8)");
|
|
end
|
|
|
|
if(`MEM_PORTA_WR_BYTE && !`MEM_PORTB_WR_BYTE && `MEM_TYPE_RAM_TDP) begin
|
|
$info("XPM_MEMORY_ASSYM_BWE-4: Configuration selected is having Byte writes on Port-A and the Read side is word-wide Read on Port-B (Memory type is set to TDP)");
|
|
end
|
|
|
|
if(!`MEM_PORTA_WR_BYTE && `MEM_PORTB_WR_BYTE && `MEM_TYPE_RAM_TDP) begin
|
|
$info("XPM_MEMORY_ASSYM_BWE-5: Configuration selected is having Byte writes on Port-B and the Read side is word-wide Read on Port-A (Memory type is set to TDP)");
|
|
end
|
|
|
|
if(`MEM_PORTA_WR_BYTE && `MEM_PORTB_WR_BYTE && BYTE_WRITE_WIDTH_A == 9 && `MEM_TYPE_RAM_TDP) begin
|
|
$info("XPM_MEMORY_ASSYM_BWE-6: Configuration selected is having Byte writes (byte width is 9) on Port-A and Port-B (Memory type is set to TDP)");
|
|
end
|
|
end : chk_vld_asym_bwe_only_configs
|
|
end
|
|
`endif
|
|
`endif
|
|
|
|
localparam READ_DATA_WIDTH_A_ECC_ASYM = `NO_ECC ? READ_DATA_WIDTH_A : P_MIN_WIDTH_DATA_ECC;
|
|
localparam READ_DATA_WIDTH_B_ECC_ASYM = `NO_ECC ? READ_DATA_WIDTH_B : P_MIN_WIDTH_DATA_ECC;
|
|
localparam logic [READ_DATA_WIDTH_A_ECC_ASYM-1:0] rsta_val_asym = `ASYNC_RESET_A ? {READ_DATA_WIDTH_A_ECC_ASYM{1'b0}} : rst_val_conv_a(READ_RESET_VALUE_A);
|
|
localparam logic [READ_DATA_WIDTH_B_ECC_ASYM-1:0] rstb_val_asym = `ASYNC_RESET_B ? {READ_DATA_WIDTH_B_ECC_ASYM{1'b0}} : rst_val_conv_b(READ_RESET_VALUE_B);
|
|
|
|
if(`MEM_PORTA_WRITE) begin : gen_wr_a_asymbwe
|
|
if(`MEM_PORTA_WR_BYTE) begin : gen_wr_bwe
|
|
if(`MEM_PORTA_WR_NARROW) begin : gen_byte_narrow
|
|
reg [P_MIN_WIDTH_DATA_ECC-1:0] i_tmp_dat_storage_a = 0;
|
|
reg [READ_DATA_WIDTH_A-1:0] o_tmp_dat_storage_a = rsta_val_asym;
|
|
if(`MEM_PORTA_READ && `MEM_PORTA_WF) begin : port_a_write_read
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
i_tmp_dat_storage_a = mem[addra_i];
|
|
for(integer byte_cnt=1; byte_cnt<=P_NUM_COLS_WRITE_A; byte_cnt=byte_cnt+1) begin
|
|
if(wea_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_a[(byte_cnt*BYTE_WRITE_WIDTH_A)-1 -: BYTE_WRITE_WIDTH_A] = dina_i[(byte_cnt*BYTE_WRITE_WIDTH_A)-1 -: BYTE_WRITE_WIDTH_A];
|
|
end
|
|
end
|
|
mem[addra_i] <= i_tmp_dat_storage_a;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (|wea_i) begin
|
|
if (wea_i[col])
|
|
o_tmp_dat_storage_a[`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
else
|
|
o_tmp_dat_storage_a[`ONE_COL_OF_DINA] <= mem[addra_i][`ONE_COL_OF_DINA];
|
|
end else begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (|wea_i) begin
|
|
if (wea_i[col])
|
|
o_tmp_dat_storage_a[`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
else
|
|
o_tmp_dat_storage_a[`ONE_COL_OF_DINA] <= mem[addra_i][`ONE_COL_OF_DINA];
|
|
end else begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (|wea_i) begin
|
|
if (wea_i[col])
|
|
o_tmp_dat_storage_a[`ONE_COL_OF_DINA] <= dina_i[`ONE_COL_OF_DINA];
|
|
else
|
|
o_tmp_dat_storage_a[`ONE_COL_OF_DINA] <= mem[addra_i][`ONE_COL_OF_DINA];
|
|
end else begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : port_a_write_read
|
|
else begin : port_a_write_only
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
i_tmp_dat_storage_a = mem[addra_i];
|
|
for(integer byte_cnt=1; byte_cnt<=P_NUM_COLS_WRITE_A; byte_cnt=byte_cnt+1) begin
|
|
if(wea_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_a[(byte_cnt*BYTE_WRITE_WIDTH_A)-1 -: BYTE_WRITE_WIDTH_A] = dina_i[(byte_cnt*BYTE_WRITE_WIDTH_A)-1 -: BYTE_WRITE_WIDTH_A];
|
|
end
|
|
end
|
|
mem[addra_i] <= i_tmp_dat_storage_a;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : port_a_write_only
|
|
end : gen_byte_narrow
|
|
else if(`MEM_PORTA_WR_WIDE) begin : gen_byte_wide
|
|
reg [WRITE_DATA_WIDTH_A-1:0] i_tmp_dat_storage_a = 0;
|
|
wire [P_WIDTH_ADDR_WRITE_A-1:0] addra_effctv = addra_i;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addr_shft = 0;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addr_shft_rd = 0;
|
|
reg [READ_DATA_WIDTH_A-1:0] o_tmp_dat_storage_a = rsta_val_asym;
|
|
if(`MEM_PORTA_WF && `MEM_PORTA_READ) begin : port_a_write_read
|
|
always @(posedge clka) begin : wr_dat_tmp
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (wea_i[row*P_NUM_COLS_WRITE_A+col]) begin
|
|
i_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] = dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end else begin
|
|
i_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] = mem[{addra_i, addr_shft}][`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat_tmp
|
|
always @(posedge clka) begin : wr_dat
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & wea_i[row*P_NUM_COLS_WRITE_A+col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
mem[{addra_i, addr_shft}][`ONE_COL_OF_DINA] = dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (wea_i[row*P_NUM_COLS_WRITE_A+col]) begin
|
|
o_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] <= dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end else begin
|
|
o_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] <= mem[{addra_i, addr_shft}][`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (wea_i[row*P_NUM_COLS_WRITE_A+col]) begin
|
|
o_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] <= dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end else begin
|
|
o_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] <= mem[{addra_i, addr_shft}][`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (wea_i[row*P_NUM_COLS_WRITE_A+col]) begin
|
|
o_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] <= dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end else begin
|
|
o_tmp_dat_storage_a[`ONE_ROW_COL_OF_DINA] <= mem[{addra_i, addr_shft}][`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : port_a_write_read
|
|
else begin : port_a_write_only
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
i_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] = mem[{addra_effctv,addr_shft}];
|
|
end
|
|
for(integer byte_cnt=1; byte_cnt<=WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A; byte_cnt=byte_cnt+1) begin
|
|
if(wea_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_a[(byte_cnt*BYTE_WRITE_WIDTH_A)-1 -: BYTE_WRITE_WIDTH_A] = dina_i[(byte_cnt*BYTE_WRITE_WIDTH_A)-1 -: BYTE_WRITE_WIDTH_A];
|
|
end
|
|
end
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addra_effctv,addr_shft}] <= i_tmp_dat_storage_a[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : port_a_write_only
|
|
end : gen_byte_wide
|
|
end : gen_wr_bwe
|
|
else begin : gen_wr_word
|
|
if(`MEM_PORTA_WR_NARROW) begin : gen_word_narrow
|
|
reg [READ_DATA_WIDTH_A-1:0] o_tmp_dat_storage_a = rsta_val_asym;
|
|
if(`MEM_PORTA_READ && `MEM_PORTA_WF) begin : port_a_write_read
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
mem[addra_i] <= dina_i;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
if(ena_i && ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i)
|
|
o_tmp_dat_storage_a <= dina_i;
|
|
else
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
if(ena_i && ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i)
|
|
o_tmp_dat_storage_a <= dina_i;
|
|
else
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(ena_i && ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i)
|
|
o_tmp_dat_storage_a <= dina_i;
|
|
else
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : port_a_write_read
|
|
else begin : port_a_write_only
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
mem[addra_i] <= dina_i;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : port_a_write_only
|
|
end : gen_word_narrow
|
|
else if(`MEM_PORTA_WR_WIDE) begin : gen_word_wide
|
|
wire [P_WIDTH_ADDR_WRITE_A-1:0] addra_effctv = addra_i;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addr_shft = 0;
|
|
reg [READ_DATA_WIDTH_A-1:0] o_tmp_dat_storage_a = rsta_val_asym;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addr_shft_rd = 0;
|
|
|
|
if(`MEM_PORTA_READ && `MEM_PORTA_WF) begin : port_a_write_read
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addra_effctv,addr_shft}] <= dina_i[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i)
|
|
o_tmp_dat_storage_a <= dina_i;
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(rsta)
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i)
|
|
o_tmp_dat_storage_a <= dina_i;
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge clka) begin : wr_dat_rd
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i)
|
|
o_tmp_dat_storage_a <= dina_i;
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : port_a_write_read
|
|
else begin : port_a_write_only
|
|
always @(posedge clka) begin : wr_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|wea_i) begin
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addra_effctv,addr_shft}] <= dina_i[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : port_a_write_only
|
|
end : gen_word_wide
|
|
end : gen_wr_word
|
|
end : gen_wr_a_asymbwe
|
|
|
|
if(`MEM_PORTA_READ) begin : gen_rd_a_asymbwe
|
|
//initial douta_bb = rsta_val_asym;
|
|
if(`MEM_PORTA_RD_NARROW) begin : gen_rda_narrow
|
|
reg [READ_DATA_WIDTH_A-1:0] o_tmp_dat_storage_a = rsta_val_asym;
|
|
if(`MEM_PORTA_RF) begin : gen_narrow_rf
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_rf_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : rd_dat
|
|
if(rsta) begin
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
end
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : rd_dat
|
|
if(rsta) begin
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
end
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_rf_reg
|
|
else begin: gen_narrow_rf_pipe
|
|
always @(posedge clka) begin : rd_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : rd_dat
|
|
end : gen_narrow_rf_pipe
|
|
end : gen_narrow_rf
|
|
else if (`MEM_PORTA_NC) begin : gen_narrow_nc
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_nc_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : rd_dat
|
|
if(rsta) begin
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
end
|
|
else begin
|
|
if(ena_i & ~(|wea_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : rd_dat
|
|
if(rsta) begin
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
o_tmp_dat_storage_a <= rsta_val_asym;
|
|
end
|
|
else begin
|
|
if(ena_i & ~(|wea_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_nc_reg
|
|
else begin: gen_narrow_nc_pipe
|
|
always @(posedge clka) begin : rd_dat
|
|
if(ena_i & ~(|wea_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_a <= mem[addra_i];
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : rd_dat
|
|
end : gen_narrow_nc_pipe
|
|
end : gen_narrow_nc
|
|
end : gen_rda_narrow
|
|
else if(`MEM_PORTA_RD_WIDE) begin : gen_rda_wide
|
|
reg [READ_DATA_WIDTH_A-1:0] o_tmp_dat_storage_a = rsta_val_asym;
|
|
wire [P_WIDTH_ADDR_READ_A-1:0] addra_effctv = addra_i;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addr_shft = 0;
|
|
if(`MEM_PORTA_RF) begin : gen_narrow_rf
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_rf_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : rd_dat
|
|
if(rsta) begin
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
gen_rd_a.douta_reg <= rsta_val_asym;
|
|
end
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : rd_dat
|
|
if(rsta)
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_rf_reg
|
|
else begin: gen_narrow_rf_pipe
|
|
always @(posedge clka) begin : rd_dat
|
|
if(ena_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : rd_dat
|
|
end : gen_narrow_rf_pipe
|
|
end : gen_narrow_rf
|
|
else if (`MEM_PORTA_NC) begin : gen_narrow_nc
|
|
if(READ_LATENCY_A == 1) begin : gen_narrow_nc_reg
|
|
if(`ASYNC_RESET_A) begin
|
|
always @(posedge rsta or posedge clka) begin : rd_dat
|
|
if(rsta)
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(|wea_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge clka) begin : rd_dat
|
|
if(rsta)
|
|
assign gen_rd_a.douta_reg = rsta_val_asym;
|
|
else begin
|
|
if(ena_i & ~(|wea_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_nc_reg
|
|
else begin: gen_narrow_nc_pipe
|
|
always @(posedge clka) begin : rd_dat
|
|
if(ena_i & ~(|wea_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_A/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_a[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addra_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_a.douta_reg = o_tmp_dat_storage_a;
|
|
end : rd_dat
|
|
end : gen_narrow_nc_pipe
|
|
end : gen_narrow_nc
|
|
end : gen_rda_wide
|
|
end : gen_rd_a_asymbwe
|
|
|
|
if(`MEM_PORTB_WRITE) begin : gen_wr_b_asymbwe
|
|
if(`MEM_PORTB_WR_BYTE) begin : gen_wr_bwe
|
|
if(`MEM_PORTB_WR_NARROW) begin : gen_byte_narrow
|
|
reg [P_MIN_WIDTH_DATA_ECC-1:0] i_tmp_dat_storage_b = 0;
|
|
reg [READ_DATA_WIDTH_B-1:0] o_tmp_dat_storage_b = rstb_val_asym;
|
|
if(`MEM_PORTB_WF && `MEM_PORTB_READ) begin : portb_write_read
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
i_tmp_dat_storage_b = mem[addrb_i];
|
|
for(integer byte_cnt=1; byte_cnt<=P_NUM_COLS_WRITE_B; byte_cnt=byte_cnt+1) begin
|
|
if(web_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_b[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B] = dinb_i[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B];
|
|
end
|
|
end
|
|
mem[addrb_i] <= i_tmp_dat_storage_b;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (|web_i) begin
|
|
if (web_i[col])
|
|
o_tmp_dat_storage_b[`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
else
|
|
o_tmp_dat_storage_b[`ONE_COL_OF_DINB] <= mem[addrb_i][`ONE_COL_OF_DINB];
|
|
end else begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (|web_i) begin
|
|
if (web_i[col])
|
|
o_tmp_dat_storage_b[`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
else
|
|
o_tmp_dat_storage_b[`ONE_COL_OF_DINB] <= mem[addrb_i][`ONE_COL_OF_DINB];
|
|
end else begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (|web_i) begin
|
|
if (web_i[col])
|
|
o_tmp_dat_storage_b[`ONE_COL_OF_DINB] <= dinb_i[`ONE_COL_OF_DINB];
|
|
else
|
|
o_tmp_dat_storage_b[`ONE_COL_OF_DINB] <= mem[addrb_i][`ONE_COL_OF_DINB];
|
|
end else begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : portb_write_read
|
|
else begin : portb_write_only
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
i_tmp_dat_storage_b = mem[addrb_i];
|
|
for(integer byte_cnt=1; byte_cnt<=P_NUM_COLS_WRITE_B; byte_cnt=byte_cnt+1) begin
|
|
if(web_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_b[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B] = dinb_i[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B];
|
|
end
|
|
end
|
|
mem[addrb_i] <= i_tmp_dat_storage_b;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : portb_write_only
|
|
end : gen_byte_narrow
|
|
else if(`MEM_PORTB_WR_WIDE) begin : gen_byte_wide
|
|
reg [WRITE_DATA_WIDTH_B-1:0] i_tmp_dat_storage_b = 0;
|
|
reg [READ_DATA_WIDTH_B-1:0] o_tmp_dat_storage_b = rstb_val_asym;
|
|
wire [P_WIDTH_ADDR_WRITE_B-1:0] addrb_effctv = addrb_i;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addr_shft = 0;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addr_shft_rd = 0;
|
|
if(`MEM_PORTB_WF && `MEM_PORTB_READ) begin : portb_write_read
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
i_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] = mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
for(integer byte_cnt=1; byte_cnt<=WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B; byte_cnt=byte_cnt+1) begin
|
|
if(web_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_b[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B] = dinb_i[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B];
|
|
end
|
|
end
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addrb_effctv,addr_shft}] <= i_tmp_dat_storage_b[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (web_i[row*P_NUM_COLS_WRITE_B+col]) begin
|
|
o_tmp_dat_storage_b[`ONE_ROW_COL_OF_DINB] <= dinb_i[`ONE_ROW_COL_OF_DINB];
|
|
end else begin
|
|
o_tmp_dat_storage_b[`ONE_ROW_COL_OF_DINB] <= mem[{addrb_i, addr_shft}][`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (web_i[row*P_NUM_COLS_WRITE_B+col]) begin
|
|
o_tmp_dat_storage_b[`ONE_ROW_COL_OF_DINB] <= dinb_i[`ONE_ROW_COL_OF_DINB];
|
|
end else begin
|
|
o_tmp_dat_storage_b[`ONE_ROW_COL_OF_DINB] <= mem[{addrb_i, addr_shft}][`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for (integer row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addr_shft = row;
|
|
if (web_i[row*P_NUM_COLS_WRITE_B+col]) begin
|
|
o_tmp_dat_storage_b[`ONE_ROW_COL_OF_DINB] <= dinb_i[`ONE_ROW_COL_OF_DINB];
|
|
end else begin
|
|
o_tmp_dat_storage_b[`ONE_ROW_COL_OF_DINB] <= mem[{addrb_i, addr_shft}][`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : portb_write_read
|
|
else begin : portb_write_only
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
i_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] = mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
for(integer byte_cnt=1; byte_cnt<=WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B; byte_cnt=byte_cnt+1) begin
|
|
if(web_i[byte_cnt-1]) begin
|
|
i_tmp_dat_storage_b[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B] = dinb_i[(byte_cnt*BYTE_WRITE_WIDTH_B)-1 -: BYTE_WRITE_WIDTH_B];
|
|
end
|
|
end
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addrb_effctv,addr_shft}] <= i_tmp_dat_storage_b[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : portb_write_only
|
|
end : gen_byte_wide
|
|
end : gen_wr_bwe
|
|
else begin : gen_wr_word
|
|
if(`MEM_PORTB_WR_NARROW) begin : gen_word_narrow
|
|
reg [READ_DATA_WIDTH_B-1:0] o_tmp_dat_storage_b = rstb_val_asym;
|
|
if(`MEM_PORTB_WF && `MEM_PORTB_READ) begin : portb_write_read
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
mem[addrb_i] <= dinb_i;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i)
|
|
o_tmp_dat_storage_b <= dinb_i;
|
|
else
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i)
|
|
o_tmp_dat_storage_b <= dinb_i;
|
|
else
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i)
|
|
o_tmp_dat_storage_b <= dinb_i;
|
|
else
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : portb_write_read
|
|
else begin : portb_write_only
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
mem[addrb_i] <= dinb_i;
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : portb_write_only
|
|
end : gen_word_narrow
|
|
else if(`MEM_PORTB_WR_WIDE) begin : gen_word_wide
|
|
wire [P_WIDTH_ADDR_WRITE_B-1:0] addrb_effctv = addrb_i;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addr_shft = 0;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addr_shft_rd = 0;
|
|
reg [READ_DATA_WIDTH_B-1:0] o_tmp_dat_storage_b = rstb_val_asym;
|
|
if(`MEM_PORTB_WF && `MEM_PORTB_READ) begin : portb_write_read
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addrb_effctv,addr_shft}] <= dinb_i[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_wf_rd_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i)
|
|
o_tmp_dat_storage_b <= dinb_i;
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i)
|
|
o_tmp_dat_storage_b <= dinb_i;
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end
|
|
end : gen_narrow_wf_rd_reg
|
|
else begin: gen_narrow_wf_rd_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat_rd
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i)
|
|
o_tmp_dat_storage_b <= dinb_i;
|
|
else begin
|
|
for(integer word_cnt=1; word_cnt<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft_rd = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft_rd}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : wr_dat_rd
|
|
end : gen_narrow_wf_rd_pipe
|
|
end : portb_write_read
|
|
else begin : portb_write_only
|
|
always @(posedge gen_rd_b.clkb_int) begin : wr_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if(|web_i) begin
|
|
for(integer word_cnt_mem=1; word_cnt_mem<=WRITE_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt_mem=word_cnt_mem+1)
|
|
begin
|
|
addr_shft = word_cnt_mem-1;
|
|
mem[{addrb_effctv,addr_shft}] <= dinb_i[(word_cnt_mem*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC];
|
|
end
|
|
end
|
|
end
|
|
end : wr_dat
|
|
end : portb_write_only
|
|
end : gen_word_wide
|
|
end : gen_wr_word
|
|
end : gen_wr_b_asymbwe
|
|
|
|
if(`MEM_PORTB_READ) begin : gen_rd_b_asymbwe
|
|
//initial doutb_bb = rstb_val_asym;
|
|
if(`MEM_PORTB_RD_NARROW) begin : gen_rdb_narrow
|
|
reg [READ_DATA_WIDTH_B-1:0] o_tmp_dat_storage_b = rstb_val_asym;
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_reg = {P_WIDTH_ADDR_WRITE_B{1'b0}};
|
|
if(`MEM_PORTB_RF) begin : gen_narrow_rf
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_rf_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_rf_reg
|
|
else begin: gen_narrow_rf_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end : gen_narrow_rf_pipe
|
|
end : gen_narrow_rf
|
|
else if (`MEM_PORTB_NC) begin : gen_narrow_nc
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_nc_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_nc_reg
|
|
else begin: gen_narrow_nc_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end : gen_narrow_nc_pipe
|
|
end : gen_narrow_nc
|
|
else if (`MEM_PORTB_WF) begin : gen_narrow_wf
|
|
if (`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_SDP) begin : gen_wf_narrow_pipe_ultra_sdp
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_wf_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
o_tmp_dat_storage_b <= mem[addrb_i];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_wf_reg
|
|
else begin: gen_narrow_wf_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
addrb_reg <= addrb_i;
|
|
end
|
|
always @(*) begin
|
|
o_tmp_dat_storage_b = mem[addrb_reg];
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end
|
|
end : gen_narrow_wf_pipe
|
|
end : gen_wf_narrow_pipe_ultra_sdp
|
|
end : gen_narrow_wf
|
|
end : gen_rdb_narrow
|
|
else if(`MEM_PORTB_RD_WIDE) begin : gen_rdb_wide
|
|
reg [READ_DATA_WIDTH_B-1:0] o_tmp_dat_storage_b = rstb_val_asym;
|
|
reg [P_WIDTH_ADDR_WRITE_B-1:0] addrb_reg = {P_WIDTH_ADDR_WRITE_B{1'b0}};
|
|
wire [P_WIDTH_ADDR_READ_B-1:0] addrb_effctv = addrb_i;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addr_shft = 0;
|
|
if(`MEM_PORTB_RF) begin : gen_narrow_rf
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_rf_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_rf_reg
|
|
else begin: gen_narrow_rf_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(enb_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end : gen_narrow_rf_pipe
|
|
end : gen_narrow_rf
|
|
else if (`MEM_PORTB_NC) begin : gen_narrow_nc
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_nc_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_nc_reg
|
|
else begin: gen_narrow_nc_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end : gen_narrow_nc_pipe
|
|
end : gen_narrow_nc
|
|
else if (`MEM_PORTB_WF) begin : gen_narrow_wf
|
|
if (`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_SDP) begin : gen_wf_wide_pipe_ultra_sdp
|
|
if(READ_LATENCY_B == 1) begin : gen_narrow_wf_reg
|
|
if(`ASYNC_RESET_B) begin
|
|
always @(posedge rstb or posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
else begin
|
|
always @(posedge gen_rd_b.clkb_int) begin : rd_dat
|
|
if(rstb)
|
|
o_tmp_dat_storage_b <= rstb_val_asym;
|
|
else begin
|
|
if(enb_i & ~(|web_i) & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
for(integer word_cnt=1; word_cnt<=READ_DATA_WIDTH_B/P_MIN_WIDTH_DATA_ECC; word_cnt=word_cnt+1)
|
|
begin
|
|
addr_shft = word_cnt-1;
|
|
o_tmp_dat_storage_b[(word_cnt*P_MIN_WIDTH_DATA_ECC)-1 -: P_MIN_WIDTH_DATA_ECC] <= mem[{addrb_effctv,addr_shft}];
|
|
end
|
|
end
|
|
end
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_dat
|
|
end
|
|
end : gen_narrow_wf_reg
|
|
else begin: gen_narrow_wf_pipe
|
|
always @(posedge gen_rd_b.clkb_int) begin
|
|
addrb_reg <= addrb_i;
|
|
end
|
|
always @(*) begin : rd_comb
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb;
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin : for_mem_rows
|
|
addrblsb = row;
|
|
o_tmp_dat_storage_b[`ONE_ROW_OF_DIN] = mem[{addrb_reg, addrblsb}];
|
|
end : for_mem_rows
|
|
assign gen_rd_b.doutb_reg = o_tmp_dat_storage_b;
|
|
end : rd_comb
|
|
end : gen_narrow_wf_pipe
|
|
end : gen_wf_wide_pipe_ultra_sdp
|
|
end : gen_narrow_wf
|
|
end : gen_rdb_wide
|
|
end : gen_rd_b_asymbwe
|
|
end : gen_beh_model_bbox
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Auto Sleep Mode behavioral Modeling
|
|
// This involves the following steps:
|
|
// 1. Implement a counter to check the number of in-active cycles
|
|
// 2. If the Number of in-active cycles is greater than Auto sleep latency,
|
|
// then force the data output to 'x'
|
|
// 3. Sampling Enable has to happen on both the ports in case of TDP/SDP, if
|
|
// both ports are in-active, then only push the memory into Auto Sleep
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
if(`MEM_AUTO_SLP_EN) begin : gen_alsp_model
|
|
// Maximum Auto Sleep latency is 15, declare count of width 4, and width to be
|
|
// fine-tuned as per the latency
|
|
reg [3:0] ena_activity_cnt = 'b0;
|
|
reg [3:0] enb_activity_cnt = 'b0;
|
|
reg aslp_mode_active_a = 'b1;
|
|
reg aslp_mode_active_b = 'b1;
|
|
wire aslp_mode_active;
|
|
|
|
always @(posedge clka) begin
|
|
if(~ena) begin
|
|
if(ena_activity_cnt >= AUTO_SLEEP_TIME)
|
|
ena_activity_cnt <= ena_activity_cnt;
|
|
else
|
|
ena_activity_cnt <= ena_activity_cnt + 1'b1;
|
|
end
|
|
else
|
|
ena_activity_cnt <= 'b0;
|
|
end
|
|
// Enable pipe line Delay Enable by Auto Sleep Number of times
|
|
reg ena_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the ena pipeline
|
|
initial begin
|
|
integer aslp_initstage_a;
|
|
for (aslp_initstage_a=0; aslp_initstage_a < AUTO_SLEEP_TIME; aslp_initstage_a=aslp_initstage_a+1) begin : for_en_pipe_init
|
|
ena_aslp_pipe[aslp_initstage_a] = 1'b0;
|
|
end : for_en_pipe_init
|
|
end
|
|
|
|
// This code may needs to be mode up
|
|
always @(posedge clka)
|
|
begin
|
|
ena_aslp_pipe[0] <= ena;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge clka) begin
|
|
ena_aslp_pipe[aslp_stage] <= ena_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
|
|
|
|
always @(posedge clka) begin
|
|
if(ena_aslp_pipe[AUTO_SLEEP_TIME-2])
|
|
aslp_mode_active_a = 1'b0;
|
|
else begin
|
|
if(ena_aslp_pipe[AUTO_SLEEP_TIME-1] == 1'b0 && ena_activity_cnt >= AUTO_SLEEP_TIME)
|
|
aslp_mode_active_a <= 1'b1;
|
|
end
|
|
end
|
|
// Place Memory to Auto sleep only when there is no activity on both ports
|
|
assign aslp_mode_active = aslp_mode_active_a & aslp_mode_active_b;
|
|
|
|
// Assign delayed enable to "en_i" for the memory write to happen
|
|
always @(posedge clka) begin
|
|
force ena_i = ena_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end
|
|
if (READ_LATENCY_A == 1) begin : aslp_en_a
|
|
if(`ASYNC_RESET_A) begin : async_aslp_en_a
|
|
always @(posedge rsta or posedge clka) begin
|
|
if(rsta) begin
|
|
force douta = gen_rd_a.rsta_val;
|
|
end
|
|
else begin
|
|
if(aslp_mode_active) begin
|
|
force douta = 'bX;
|
|
end
|
|
else begin
|
|
if(`MEM_PORTA_NC) begin
|
|
if(ena_i & ~(|wea_i)) begin
|
|
release douta;
|
|
end
|
|
end
|
|
else begin
|
|
if(ena_i) begin
|
|
release douta;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : async_aslp_en_a
|
|
else begin : sync_aslp_en_a
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
force douta = gen_rd_a.rsta_val;
|
|
end
|
|
else begin
|
|
if(aslp_mode_active) begin
|
|
force douta = 'bX;
|
|
end
|
|
else begin
|
|
if(`MEM_PORTA_NC) begin
|
|
if(ena_i & ~(|wea_i)) begin
|
|
release douta;
|
|
end
|
|
end
|
|
else begin
|
|
if(ena_i) begin
|
|
release douta;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : sync_aslp_en_a
|
|
always @(posedge clka) begin
|
|
if(rsta) begin
|
|
force sbiterra = 1'b0;
|
|
force dbiterra = 1'b0;
|
|
end
|
|
else begin
|
|
if(aslp_mode_active) begin
|
|
force sbiterra = 'bX;
|
|
force dbiterra = 'bX;
|
|
end
|
|
else begin
|
|
if(`MEM_PORTA_NC) begin
|
|
if(ena_i & ~(|wea_i)) begin
|
|
release sbiterra;
|
|
release dbiterra;
|
|
end
|
|
end
|
|
else begin
|
|
if(ena_i) begin
|
|
release sbiterra;
|
|
release dbiterra;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : aslp_en_a
|
|
if(`MEM_PORTB_READ) begin : gen_aslp_b_rd
|
|
reg enb_aslp_pipe [AUTO_SLEEP_TIME-1:0];
|
|
// Initialize the enb pipelines
|
|
initial begin
|
|
integer aslp_initstage_b;
|
|
for (aslp_initstage_b=0; aslp_initstage_b<AUTO_SLEEP_TIME; aslp_initstage_b=aslp_initstage_b+1) begin : for_en_pipe_init
|
|
enb_aslp_pipe[aslp_initstage_b] = 1'b0;
|
|
end : for_en_pipe_init
|
|
end
|
|
|
|
always @(posedge gen_auto_slp_dly_b.clkb_int) begin
|
|
if(~enb) begin
|
|
if(enb_activity_cnt >= AUTO_SLEEP_TIME)
|
|
enb_activity_cnt <= enb_activity_cnt;
|
|
else
|
|
enb_activity_cnt <= enb_activity_cnt + 1'b1;
|
|
end
|
|
else
|
|
enb_activity_cnt <= 'b0;
|
|
end
|
|
|
|
always @(posedge gen_auto_slp_dly_b.clkb_int) begin
|
|
if(enb_aslp_pipe[AUTO_SLEEP_TIME-2])
|
|
aslp_mode_active_b = 1'b0;
|
|
else begin
|
|
if(enb_aslp_pipe[AUTO_SLEEP_TIME-1] == 1'b0 && enb_activity_cnt >= AUTO_SLEEP_TIME)
|
|
aslp_mode_active_b <= 1'b1;
|
|
end
|
|
end
|
|
// Delay the Enable, this code may needs to be mode up
|
|
always @(posedge gen_auto_slp_dly_b.clkb_int)
|
|
begin
|
|
enb_aslp_pipe[0] <= enb;
|
|
end
|
|
for (genvar aslp_stage=1; aslp_stage < AUTO_SLEEP_TIME; aslp_stage = aslp_stage+1) begin : gen_aslp_inp_pipe
|
|
always @(posedge gen_auto_slp_dly_b.clkb_int) begin
|
|
enb_aslp_pipe[aslp_stage] <= enb_aslp_pipe[aslp_stage-1];
|
|
end
|
|
end : gen_aslp_inp_pipe
|
|
// Assign delayed enable to "en_i" for the memory write to happen
|
|
always @(posedge gen_auto_slp_dly_b.clkb_int) begin
|
|
force enb_i = enb_aslp_pipe[AUTO_SLEEP_TIME-1];
|
|
end
|
|
if (READ_LATENCY_B == 1) begin : aslp_en_b
|
|
//always @(posedge gen_auto_slp_dly_b.clkb_int) begin
|
|
if(`ASYNC_RESET_B) begin : async_aslp_en_b
|
|
always @(posedge rstb or posedge clka) begin // sampling on clka to make to sure that both ports drive-x at the same time
|
|
if(rstb) begin
|
|
force doutb = gen_rd_b.rstb_val;
|
|
end
|
|
else begin
|
|
if(aslp_mode_active) begin
|
|
force doutb = 'bX;
|
|
end
|
|
else begin
|
|
if(`MEM_PORTB_NC) begin
|
|
if(enb_i & ~(|web_i)) begin
|
|
release doutb;
|
|
end
|
|
end
|
|
else begin
|
|
if(enb_i) begin
|
|
release doutb;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : async_aslp_en_b
|
|
else begin : sync_aslp_en_b
|
|
always @(posedge clka) begin // sampling on clka to make to sure that both ports drive-x at the same time
|
|
if(rstb) begin
|
|
force doutb = gen_rd_b.rstb_val;
|
|
end
|
|
else begin
|
|
if(aslp_mode_active) begin
|
|
force doutb = 'bX;
|
|
end
|
|
else begin
|
|
if(`MEM_PORTB_NC) begin
|
|
if(enb_i & ~(|web_i)) begin
|
|
release doutb;
|
|
end
|
|
end
|
|
else begin
|
|
if(enb_i) begin
|
|
release doutb;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : sync_aslp_en_b
|
|
always @(posedge clka) begin // sampling on clka to make to sure that both ports drive-x at the same time
|
|
if(rstb) begin
|
|
force sbiterrb = 1'b0;
|
|
force dbiterrb = 1'b0;
|
|
end
|
|
else begin
|
|
if(aslp_mode_active) begin
|
|
force sbiterrb = 'bX;
|
|
force dbiterrb = 'bX;
|
|
end
|
|
else begin
|
|
if(`MEM_PORTB_NC) begin
|
|
if(enb_i & ~(|web_i)) begin
|
|
release sbiterrb;
|
|
release dbiterrb;
|
|
end
|
|
end
|
|
else begin
|
|
if(enb_i) begin
|
|
release sbiterrb;
|
|
release dbiterrb;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end : aslp_en_b
|
|
end : gen_aslp_b_rd
|
|
|
|
`ifndef OBSOLETE
|
|
`ifndef DISABLE_XPM_ASSERTIONS
|
|
|
|
wire clkb_int;
|
|
if (`COMMON_CLOCK) begin
|
|
assign clkb_int = clka;
|
|
end
|
|
else if (`INDEPENDENT_CLOCKS) begin
|
|
assign clkb_int = clkb;
|
|
end
|
|
wire [P_WIDTH_ADDR_WRITE_A-1:0] effctv_addra_aslp = addra;
|
|
wire [P_WIDTH_ADDR_WRITE_B-1:0] effctv_addrb_aslp = addrb;
|
|
if (`REPORT_MESSAGES && `MEM_PORTA_WRITE) begin : illegal_wr_ena_aslp
|
|
assert property (@(posedge clka)
|
|
!(ena && |wea && (addra > effctv_addra_aslp) ))
|
|
else
|
|
$warning("XPM_MEMORY_OUT_OF_RANGE_WRITE_ACCESS : Write Operation on Port-A to an out-of-range address at time %0t; Actual Address --> %0h , effective address is %0h.There is a chance that data at the effective address location may get written in the synthesis netlist, and there by the simulation mismatch can occur between behavioral model and netlist simulations", $time,addra,effctv_addra_aslp);
|
|
end : illegal_wr_ena_aslp
|
|
|
|
if (`REPORT_MESSAGES && `MEM_PORTB_WRITE) begin : illegal_wr_enb_aslp
|
|
assert property (@(posedge clkb_int)
|
|
!(enb && |web && (addrb > effctv_addrb_aslp) ))
|
|
else
|
|
$warning("XPM_MEMORY_OUT_OF_RANGE_WRITE_ACCESS : Write Operation on Port-B to an out-of-range address at time %0t; Actual Address --> %0h , effective address is %0h.There is a chance that data at the effective address location may get written in the synthesis netlist, and there by the simulation mismatch can occur between behavioral model and netlist simulations", $time,addrb,effctv_addrb_aslp);
|
|
end : illegal_wr_enb_aslp
|
|
|
|
if (`REPORT_MESSAGES && `MEM_PORTA_WRITE && `MEM_PORTA_NC) begin : unsupported_wr_ena
|
|
assert property (@(posedge clka)
|
|
!(aslp_mode_active && ena && |wea))
|
|
else
|
|
$warning("XPM_MEMORY_WR_IN_ASLP_NC : Write Operation on Port-A at time %0t when in Auto Sleep mode and the write mode is set to No_Change, at address : addra(%h);behavioral and netlist simulation may not match for the data output corresponding to this write operation.", $time,addra);
|
|
end : unsupported_wr_ena
|
|
|
|
if (`REPORT_MESSAGES && `MEM_PORTB_WRITE && `MEM_PORTB_NC) begin : unsupported_wr_enb
|
|
assert property (@(posedge clkb_int)
|
|
!(aslp_mode_active && enb && |web))
|
|
else
|
|
$warning("XPM_MEMORY_WR_IN_ASLP_NC : Write Operation on Port-B at time %0t when in Auto Sleep mode and the write mode is set to No_Change, at address : addrb(%h); behavioral and netlist simulation may not match for the data output corresponding to this write operation.", $time,addrb);
|
|
end : unsupported_wr_enb
|
|
|
|
if(SIM_ASSERT_CHK == 1) begin : chk_vld_aslp_configs
|
|
if(`MEM_AUTO_SLP_EN && `MEM_PRIM_ULTRA) begin : assrt_chks_aslp
|
|
assert property (@(posedge clka)
|
|
!(ena_activity_cnt >= AUTO_SLEEP_TIME))
|
|
$info("XPM_MEMORY_ASLP_EN: ena is active, and the memory cannot enter Auto Sleep Mode");
|
|
else
|
|
$info("XPM_MEMORY_ASLP_EN: ena in-active (%t) for more than AUTO_SLEEP_TIME", $time);
|
|
|
|
if(`MEM_PORTB_READ || `MEM_PORTB_WRITE) begin : assrt_chks_aslp_b
|
|
assert property (@(posedge clkb)
|
|
!(enb_activity_cnt >= AUTO_SLEEP_TIME))
|
|
$info("XPM_MEMORY_ASLP_EN: enb is active, and the memory cannot enter Auto Sleep Mode");
|
|
else
|
|
$info("XPM_MEMORY_ASLP_EN: enb in-active (%t) for more than AUTO_SLEEP_TIME", $time);
|
|
assert property (@(posedge clka)
|
|
!(aslp_mode_active & (ena & ~enb)))
|
|
else
|
|
$info("XPM_MEMORY_ASLP_EN: Memory is in AUTO_SLEEP, and Port-A enable (ena) alone is asserted at time (%t) to bring the memory to active mode.", $time);
|
|
|
|
assert property (@(posedge clkb)
|
|
!(aslp_mode_active & (~ena & enb)))
|
|
else
|
|
$info("XPM_MEMORY_ASLP_EN: Memory is in AUTO_SLEEP, and Port-B enable (enb) alone is asserted at time (%t) to bring the memory to active mode.", $time);
|
|
end : assrt_chks_aslp_b
|
|
end : assrt_chks_aslp
|
|
end : chk_vld_aslp_configs
|
|
`endif
|
|
`endif
|
|
end : gen_alsp_model
|
|
|
|
// UltraRAM TDP mode Modeling
|
|
// below conditions to be taken care.
|
|
/** If both ports are executing read and write for the same address, :
|
|
//If port A is writing, port B is reading, then port B reads new data.
|
|
//If port A is reading, port B is writing, then port A reads the old data.
|
|
//If port A and B are writing, then port B write overwrites the port A write. At the end of the clock cycle, the memory stores port B write data.
|
|
**/
|
|
// <TBD> When the address does not overlap - then do we need to model any behavior?
|
|
|
|
if (`MEM_PRIM_ULTRA && `MEM_TYPE_RAM_TDP && `NO_ECC) begin : uram_tdp_model
|
|
|
|
reg [P_MIN_WIDTH_DATA-1:0] mem_col [0:P_MAX_DEPTH_DATA-1];
|
|
reg [READ_DATA_WIDTH_A-1 : 0] douta_col = 0;
|
|
reg [READ_DATA_WIDTH_B-1 : 0] doutb_col = 0;
|
|
wire [P_WIDTH_ADDR_WRITE_A-1:0] addra_int = addra_i;
|
|
wire [P_WIDTH_ADDR_WRITE_B-1:0] addrb_int ;
|
|
wire rstb_int;
|
|
wire enb_int;
|
|
wire [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web_int ;
|
|
wire [READ_DATA_WIDTH_B-1 : 0] dinb_int;
|
|
wire #1 clkb_int_i = gen_rd_b.clkb_int;
|
|
|
|
assign #2 addrb_int = addrb_i;
|
|
assign #2 rstb_int = rstb;
|
|
assign #2 enb_int = enb_i;
|
|
assign #2 web_int = web_i;
|
|
assign #2 dinb_int = dinb_i;
|
|
|
|
integer row;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_A-1:0] addralsb;
|
|
reg [P_WIDTH_ADDR_LSB_READ_A-1:0] addralsb_rd;
|
|
reg [P_WIDTH_ADDR_LSB_WRITE_B-1:0] addrblsb;
|
|
reg [P_WIDTH_ADDR_LSB_READ_B-1:0] addrblsb_rd;
|
|
// Memory Array Initialization
|
|
//initial begin
|
|
// integer col_initword;
|
|
// for (col_initword=0; col_initword<P_MAX_DEPTH_DATA; col_initword=col_initword+1) begin
|
|
// mem_col[col_initword] = {P_MIN_WIDTH_DATA{1'b0}};
|
|
// end
|
|
//end
|
|
|
|
// Initialize memory array to the data file content if file name is specified, or to all zeroes if it is not specified
|
|
initial begin
|
|
if (`NO_MEMORY_INIT) begin : init_zeroes_uram
|
|
integer initword;
|
|
for (initword=0; initword<P_MAX_DEPTH_DATA; initword=initword+1) begin
|
|
mem_col[initword] = {P_MIN_WIDTH_DATA{1'b0}};
|
|
end
|
|
end : init_zeroes_uram
|
|
else if (!(MEMORY_INIT_PARAM == "0" || MEMORY_INIT_PARAM == "")) begin : init_param_uram
|
|
reg [P_MAX_DEPTH_DATA-1:0] [P_MIN_WIDTH_DATA-1:0] mem_param;
|
|
num_char_in_param = num_char_init(MEMORY_INIT_PARAM);
|
|
assert (num_char_in_param <= MAX_NUM_CHAR) // Check if the string length exceeds the depth of the memory size
|
|
else
|
|
$error("No.of characters given in the Initialization Parameter string exceeds the Memory Size");
|
|
mem_param = init_param_memory({MEMORY_INIT_PARAM, 8'h0}); //Append NULL to identify the end of string
|
|
for(integer mem_location=0; mem_location<P_MAX_DEPTH_DATA; mem_location=mem_location+1)
|
|
mem_col[mem_location] = mem_param[mem_location]; //assign the initial value to the memory
|
|
end : init_param_uram
|
|
else begin : init_datafile_uram
|
|
#10;
|
|
$readmemh(MEMORY_INIT_FILE, mem_col, 0, P_MAX_DEPTH_DATA-1);
|
|
end : init_datafile_uram
|
|
end
|
|
|
|
// Synchronous port A write; byte-wide write; port width is the narrowest of the data ports
|
|
// For UltraRAM, there is no Asymmetry
|
|
//Port-A
|
|
if(`ASYNC_RESET_A) begin : async_rst_a
|
|
if(`MEM_PORTA_RD_REG) begin : async_rd_rl1
|
|
always @(posedge clka or posedge rsta) begin
|
|
if(rsta)
|
|
douta_col <= {READ_DATA_WIDTH_A{1'b0}};
|
|
else begin
|
|
if(ena_i & ~|wea_i) begin
|
|
if (`MEM_PORTA_NC && `MEM_PORTA_RD_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin
|
|
addralsb_rd = row;
|
|
douta_col[`ONE_ROW_OF_DIN] <= mem_col[{addra_i, addralsb_rd}];
|
|
end
|
|
end
|
|
else
|
|
douta_col <= mem_col[addra_i];
|
|
end
|
|
end
|
|
force gen_rd_a.douta_reg = douta_col;
|
|
end
|
|
end : async_rd_rl1
|
|
else begin : async_rd_rl_n
|
|
always @(posedge clka) begin
|
|
if(ena_i & ~|wea_i) begin
|
|
if (`MEM_PORTA_NC && `MEM_PORTA_RD_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin
|
|
addralsb_rd = row;
|
|
douta_col[`ONE_ROW_OF_DIN] <= mem_col[{addra_i, addralsb_rd}];
|
|
end
|
|
end
|
|
else
|
|
douta_col <= mem_col[addra_i];
|
|
end
|
|
force gen_rd_a.douta_reg = douta_col;
|
|
end
|
|
end : async_rd_rl_n
|
|
always @(posedge clka) begin
|
|
if(`MEM_PORTA_WR_BYTE) begin
|
|
if (`MEM_PORTA_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & wea_i[row*P_NUM_COLS_WRITE_A+col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addralsb = row;
|
|
mem_col[{addra_i, addralsb}][`ONE_COL_OF_DINA] = dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & wea_i[col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))
|
|
mem_col[addra_i][`ONE_COL_OF_DINA] = dina_i[`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if (ena_i & |wea_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (`MEM_PORTA_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
addralsb = row;
|
|
mem_col[{addra_i, addralsb}] = dina_i[`ONE_ROW_OF_DIN];
|
|
end
|
|
end
|
|
else
|
|
mem_col[addra_int] = dina_i;
|
|
end
|
|
end
|
|
end
|
|
end : async_rst_a
|
|
else begin : sync_rst_a
|
|
always @(posedge clka) begin
|
|
if(rsta && READ_LATENCY_A == 1)
|
|
douta_col <= {READ_DATA_WIDTH_A{1'b0}};
|
|
else begin
|
|
if(ena_i & ~|wea_i) begin
|
|
if (`MEM_PORTA_NC && `MEM_PORTA_RD_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_READ_A; row=row+1) begin
|
|
addralsb_rd = row;
|
|
douta_col[`ONE_ROW_OF_DIN] <= mem_col[{addra_i, addralsb_rd}];
|
|
end
|
|
end
|
|
else
|
|
douta_col <= mem_col[addra_i];
|
|
end
|
|
end
|
|
if(`MEM_PORTA_WR_BYTE) begin
|
|
if (`MEM_PORTA_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & wea_i[row*P_NUM_COLS_WRITE_A+col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addralsb = row;
|
|
mem_col[{addra_i, addralsb}][`ONE_COL_OF_DINA] = dina_i[`ONE_ROW_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_A; col=col+1) begin
|
|
if (ena_i & wea_i[col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))
|
|
mem_col[addra_i][`ONE_COL_OF_DINA] = dina_i[`ONE_COL_OF_DINA];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if (ena_i & |wea_i & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (`MEM_PORTA_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_A; row=row+1) begin
|
|
addralsb = row;
|
|
mem_col[{addra_i, addralsb}] = dina_i[`ONE_ROW_OF_DIN];
|
|
end
|
|
end
|
|
else
|
|
mem_col[addra_int] = dina_i;
|
|
end
|
|
end
|
|
force gen_rd_a.douta_reg = douta_col;
|
|
end
|
|
end : sync_rst_a
|
|
//Port-B
|
|
if(`ASYNC_RESET_B) begin
|
|
if(READ_LATENCY_B == 1) begin
|
|
always @(posedge clkb_int_i or posedge rstb_int) begin
|
|
if(rstb_int)
|
|
doutb_col <= {READ_DATA_WIDTH_B{1'b0}};
|
|
else begin
|
|
if(enb_int & ~|web_int) begin
|
|
if (`MEM_PORTB_NC && `MEM_PORTB_RD_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin
|
|
addrblsb_rd = row;
|
|
doutb_col[`ONE_ROW_OF_DIN] <= mem_col[{addrb_int, addrblsb_rd}];
|
|
end
|
|
end
|
|
else
|
|
doutb_col = mem_col[addrb_int];
|
|
end
|
|
end
|
|
force gen_rd_b.doutb_reg = doutb_col;
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int_i) begin
|
|
if(enb_int & ~|web_int) begin
|
|
if (`MEM_PORTB_NC && `MEM_PORTB_RD_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin
|
|
addrblsb_rd = row;
|
|
doutb_col[`ONE_ROW_OF_DIN] <= mem_col[{addrb_int, addrblsb_rd}];
|
|
end
|
|
end
|
|
else
|
|
doutb_col = mem_col[addrb_int];
|
|
end
|
|
force gen_rd_b.doutb_reg = doutb_col;
|
|
end
|
|
end
|
|
always @(posedge clkb_int_i) begin
|
|
if(`MEM_PORTB_WR_BYTE) begin
|
|
if (`MEM_PORTB_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_int & web_int[row*P_NUM_COLS_WRITE_B+col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addrblsb = row;
|
|
mem_col[{addrb_int, addrblsb}][`ONE_COL_OF_DINB] = dinb_int[`ONE_ROW_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_int & web_int[col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))
|
|
mem_col[addrb_int][`ONE_COL_OF_DINB] = dinb_int[`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if (enb_int & |web_int & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (`MEM_PORTB_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
addrblsb = row;
|
|
mem_col[{addrb_int, addrblsb}] = dinb_int[`ONE_ROW_OF_DIN];
|
|
end
|
|
end
|
|
else
|
|
mem_col[addrb_int] = dinb_int;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
always @(posedge clkb_int_i) begin
|
|
if(rstb_int && READ_LATENCY_B == 1)
|
|
doutb_col <= {READ_DATA_WIDTH_B{1'b0}};
|
|
else begin
|
|
if(enb_int & ~|web_int) begin
|
|
if (`MEM_PORTB_NC && `MEM_PORTB_RD_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_READ_B; row=row+1) begin
|
|
addrblsb_rd = row;
|
|
doutb_col[`ONE_ROW_OF_DIN] <= mem_col[{addrb_int, addrblsb_rd}];
|
|
end
|
|
end
|
|
else
|
|
doutb_col = mem_col[addrb_int];
|
|
end
|
|
end
|
|
if(`MEM_PORTB_WR_BYTE) begin
|
|
if (`MEM_PORTB_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_int & web_int[row*P_NUM_COLS_WRITE_B+col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
addrblsb = row;
|
|
mem_col[{addrb_int, addrblsb}][`ONE_COL_OF_DINB] = dinb_int[`ONE_ROW_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
for (integer col=0; col<P_NUM_COLS_WRITE_B; col=col+1) begin
|
|
if (enb_int & web_int[col] & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1))
|
|
mem_col[addrb_int][`ONE_COL_OF_DINB] = dinb_int[`ONE_COL_OF_DINB];
|
|
end
|
|
end
|
|
end
|
|
else begin
|
|
if (enb_int & |web_int & ~(sleep_int_a == 1'b1 || sleep_int_b == 1'b1)) begin
|
|
if (`MEM_PORTB_WR_WIDE ) begin
|
|
for (row=0; row<P_NUM_ROWS_WRITE_B; row=row+1) begin
|
|
addrblsb = row;
|
|
mem_col[{addrb_int, addrblsb}] = dinb_int[`ONE_ROW_OF_DIN];
|
|
end
|
|
end
|
|
else
|
|
mem_col[addrb_int] = dinb_int;
|
|
end
|
|
end
|
|
force gen_rd_b.doutb_reg = doutb_col;
|
|
end
|
|
end
|
|
end : uram_tdp_model
|
|
|
|
// synthesis translate_on
|
|
|
|
endgenerate
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Macro undefine
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
`undef MAX
|
|
`undef MIN
|
|
`undef ONE_ROW_OF_DIN
|
|
`undef ONE_COL_OF_DINA
|
|
`undef ONE_COL_OF_DINB
|
|
`undef MEM_TYPE_RAM_SP
|
|
`undef MEM_TYPE_RAM_SDP
|
|
`undef MEM_TYPE_RAM_TDP
|
|
`undef MEM_TYPE_ROM_SP
|
|
`undef MEM_TYPE_ROM_DP
|
|
`undef MEM_TYPE_RAM
|
|
`undef MEM_TYPE_ROM
|
|
`undef MEM_PRIM_AUTO
|
|
`undef MEM_PRIM_DISTRIBUTED
|
|
`undef MEM_PRIM_BLOCK
|
|
`undef MEM_PORTA_WRITE
|
|
`undef MEM_PORTA_READ
|
|
`undef MEM_PORTA_WF
|
|
`undef MEM_PORTA_RF
|
|
`undef MEM_PORTA_NC
|
|
`undef MEM_PORTA_WR_NARROW
|
|
`undef MEM_PORTA_WR_WIDE
|
|
`undef MEM_PORTA_WR_WORD
|
|
`undef MEM_PORTA_WR_BYTE
|
|
`undef MEM_PORTA_RD_NARROW
|
|
`undef MEM_PORTA_RD_WIDE
|
|
`undef MEM_PORTA_RD_COMB
|
|
`undef MEM_PORTA_RD_REG
|
|
`undef MEM_PORTA_RD_PIPE
|
|
`undef MEM_PORTB_WRITE
|
|
`undef MEM_PORTB_READ
|
|
`undef MEM_PORTB_WF
|
|
`undef MEM_PORTB_RF
|
|
`undef MEM_PORTB_NC
|
|
`undef MEM_PORTB_WR_NARROW
|
|
`undef MEM_PORTB_WR_WIDE
|
|
`undef MEM_PORTB_WR_WORD
|
|
`undef MEM_PORTB_WR_BYTE
|
|
`undef MEM_PORTB_RD_NARROW
|
|
`undef MEM_PORTB_RD_WIDE
|
|
`undef MEM_PORTB_RD_COMB
|
|
`undef MEM_PORTB_RD_REG
|
|
`undef MEM_PORTB_RD_PIPE
|
|
`undef COMMON_CLOCK
|
|
`undef INDEPENDENT_CLOCKS
|
|
`undef NO_MEMORY_INIT
|
|
`undef REPORT_MESSAGES
|
|
`undef NO_MESSAGES
|
|
`undef SLEEP_MODE
|
|
`undef IS_COLLISION_A_SAFE
|
|
`undef IS_COLLISION_B_SAFE
|
|
`undef IS_COLLISION_SAFE
|
|
`undef DISABLE_SYNTH_TEMPL
|
|
`undef NO_ECC
|
|
`undef ENC_ONLY
|
|
`undef DEC_ONLY
|
|
`undef BOTH_ENC_DEC
|
|
`undef MEM_PORTA_ASYM_BWE
|
|
`undef MEM_PORTB_ASYM_BWE
|
|
`undef MEM_ACRSS_PORT_ASYM_BWE
|
|
`undef MEM_PORT_ASYM_BWE
|
|
`undef MEM_PORTB_URAM_LAT
|
|
`undef EN_INIT_MESSAGE
|
|
`undef MEM_PRIM_ULTRA
|
|
`undef MEM_PRIM_MIXED
|
|
|
|
endmodule : xpm_memory_base
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE", black_box = "YES"*)
|
|
module asym_bwe_bb # (
|
|
// Common module parameters
|
|
parameter integer MEMORY_TYPE = 2,
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter integer MEMORY_PRIMITIVE = 0,
|
|
parameter integer CLOCKING_MODE = 0,
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer WAKEUP_TIME = 0,
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer WRITE_DATA_WIDTH_A = 32,
|
|
parameter integer READ_DATA_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer BYTE_WRITE_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter integer WRITE_MODE_A = 2,
|
|
parameter RST_MODE_A = "SYNC",
|
|
|
|
// Port B module parameters
|
|
parameter integer WRITE_DATA_WIDTH_B = WRITE_DATA_WIDTH_A,
|
|
parameter integer READ_DATA_WIDTH_B = WRITE_DATA_WIDTH_B,
|
|
parameter integer BYTE_WRITE_WIDTH_B = WRITE_DATA_WIDTH_B,
|
|
parameter integer ADDR_WIDTH_B = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B),
|
|
parameter READ_RESET_VALUE_B = "0",
|
|
parameter integer READ_LATENCY_B = READ_LATENCY_A,
|
|
parameter integer WRITE_MODE_B = WRITE_MODE_A,
|
|
parameter RST_MODE_B = "SYNC"
|
|
|
|
) (
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire [WRITE_DATA_WIDTH_A-1:0] dina,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
|
|
// Port B module ports
|
|
input wire clkb,
|
|
input wire rstb,
|
|
input wire enb,
|
|
input wire regceb,
|
|
input wire [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web,
|
|
input wire [ADDR_WIDTH_B-1:0] addrb,
|
|
input wire [WRITE_DATA_WIDTH_B-1:0] dinb,
|
|
output wire [READ_DATA_WIDTH_B-1:0] doutb
|
|
);
|
|
endmodule : asym_bwe_bb
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE" *)
|
|
module xpm_memory_dpdistram # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter CLOCKING_MODE = "common_clock",
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter integer USE_EMBEDDED_CONSTRAINT = 0,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer WRITE_DATA_WIDTH_A = 32,
|
|
parameter integer READ_DATA_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer BYTE_WRITE_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter RST_MODE_A = "SYNC",
|
|
|
|
// Port B module parameters
|
|
parameter integer READ_DATA_WIDTH_B = READ_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_B = $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B),
|
|
parameter READ_RESET_VALUE_B = "0",
|
|
parameter integer READ_LATENCY_B = READ_LATENCY_A,
|
|
parameter RST_MODE_B = "SYNC"
|
|
|
|
) (
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire [WRITE_DATA_WIDTH_A-1:0] dina,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
|
|
// Port B module ports
|
|
input wire clkb,
|
|
input wire rstb,
|
|
input wire enb,
|
|
input wire regceb,
|
|
input wire [ADDR_WIDTH_B-1:0] addrb,
|
|
output wire [READ_DATA_WIDTH_B-1:0] doutb
|
|
);
|
|
|
|
// Define local parameters for mapping with base file
|
|
|
|
localparam integer P_CLOCKING_MODE = ( (CLOCKING_MODE == 0 || CLOCKING_MODE == "common_clock" || CLOCKING_MODE == "COMMON_CLOCK" ) ? 0 :
|
|
( (CLOCKING_MODE == 1 || CLOCKING_MODE == "independent_clock" || CLOCKING_MODE == "INDEPENDENT_CLOCK") ? 1 : 0));
|
|
|
|
localparam integer P_MEMORY_OPTIMIZATION = (MEMORY_OPTIMIZATION == "false" ? 0 : 1);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Base module instantiation with dual port distributed RAM configuration
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
.MEMORY_OPTIMIZATION (MEMORY_OPTIMIZATION ),
|
|
.MEMORY_TYPE (2 ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (1 ),
|
|
.CLOCKING_MODE (P_CLOCKING_MODE ),
|
|
.ECC_MODE (0 ),
|
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.USE_MEM_INIT (USE_MEM_INIT ),
|
|
.USE_MEM_INIT_MMI (USE_MEM_INIT_MMI ),
|
|
.WAKEUP_TIME (0 ),
|
|
.AUTO_SLEEP_TIME (0 ),
|
|
.MESSAGE_CONTROL (MESSAGE_CONTROL ),
|
|
.VERSION (0 ),
|
|
.USE_EMBEDDED_CONSTRAINT (USE_EMBEDDED_CONSTRAINT ),
|
|
.IGNORE_INIT_SYNTH (IGNORE_INIT_SYNTH ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH_A),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (BYTE_WRITE_WIDTH_A),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (1 ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.BYTE_WRITE_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.ADDR_WIDTH_B (ADDR_WIDTH_B ),
|
|
.READ_RESET_VALUE_B (READ_RESET_VALUE_B),
|
|
.READ_LATENCY_B (READ_LATENCY_B ),
|
|
.WRITE_MODE_B (1 ),
|
|
.RST_MODE_B (RST_MODE_B )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (1'b0 ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (wea ),
|
|
.addra (addra ),
|
|
.dina (dina ),
|
|
.injectsbiterra (1'b0 ),
|
|
.injectdbiterra (1'b0 ),
|
|
.douta (douta ),
|
|
.sbiterra ( ),
|
|
.dbiterra ( ),
|
|
|
|
// Port B module ports
|
|
.clkb (clkb ),
|
|
.rstb (rstb ),
|
|
.enb (enb ),
|
|
.regceb (regceb ),
|
|
.web (1'b0 ),
|
|
.addrb (addrb ),
|
|
.dinb ({READ_DATA_WIDTH_B{1'b0}}),
|
|
.injectsbiterrb (1'b0 ),
|
|
.injectdbiterrb (1'b0 ),
|
|
.doutb (doutb ),
|
|
.sbiterrb ( ),
|
|
.dbiterrb ( )
|
|
);
|
|
|
|
endmodule : xpm_memory_dpdistram
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE" *)
|
|
module xpm_memory_dprom # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter MEMORY_PRIMITIVE = "auto",
|
|
parameter CLOCKING_MODE = "common_clock",
|
|
parameter ECC_MODE = "no_ecc",
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter WAKEUP_TIME = "disable_sleep",
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer CASCADE_HEIGHT = 0,
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer READ_DATA_WIDTH_A = 32,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter RST_MODE_A = "SYNC",
|
|
|
|
// Port B module parameters
|
|
parameter integer READ_DATA_WIDTH_B = READ_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_B = $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B),
|
|
parameter READ_RESET_VALUE_B = "0",
|
|
parameter integer READ_LATENCY_B = READ_LATENCY_A,
|
|
parameter RST_MODE_B = "SYNC"
|
|
) (
|
|
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire injectsbiterra,
|
|
input wire injectdbiterra,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
output wire sbiterra,
|
|
output wire dbiterra,
|
|
|
|
// Port B module ports
|
|
input wire clkb,
|
|
input wire rstb,
|
|
input wire enb,
|
|
input wire regceb,
|
|
input wire [ADDR_WIDTH_B-1:0] addrb,
|
|
input wire injectsbiterrb,
|
|
input wire injectdbiterrb,
|
|
output wire [READ_DATA_WIDTH_B-1:0] doutb,
|
|
output wire sbiterrb,
|
|
output wire dbiterrb
|
|
);
|
|
|
|
// Define local parameters for mapping with base file
|
|
localparam integer P_MEMORY_PRIMITIVE =
|
|
( (MEMORY_PRIMITIVE == 1 || MEMORY_PRIMITIVE == "lutram" || MEMORY_PRIMITIVE == "LUTRAM" || MEMORY_PRIMITIVE == "distributed" || MEMORY_PRIMITIVE == "DISTRIBUTED" ) ? 1 :
|
|
( (MEMORY_PRIMITIVE == 2 || MEMORY_PRIMITIVE == "blockram" || MEMORY_PRIMITIVE == "BLOCKRAM" || MEMORY_PRIMITIVE == "block" || MEMORY_PRIMITIVE == "BLOCK" ) ? 2 :
|
|
( (MEMORY_PRIMITIVE == 3 || MEMORY_PRIMITIVE == "ultraram" || MEMORY_PRIMITIVE == "ULTRARAM" || MEMORY_PRIMITIVE == "ultra" || MEMORY_PRIMITIVE == "ULTRA") ? 3 :
|
|
( (MEMORY_PRIMITIVE == 4 || MEMORY_PRIMITIVE == "mixedram" || MEMORY_PRIMITIVE == "MIXEDRAM" || MEMORY_PRIMITIVE == "mixed" || MEMORY_PRIMITIVE == "MIXED" ) ? 4 : 0))));
|
|
|
|
localparam integer P_CLOCKING_MODE = ( (CLOCKING_MODE == 0 || CLOCKING_MODE == "common_clock" || CLOCKING_MODE == "COMMON_CLOCK" ) ? 0 :
|
|
( (CLOCKING_MODE == 1 || CLOCKING_MODE == "independent_clock" || CLOCKING_MODE == "INDEPENDENT_CLOCK") ? 1 : 0));
|
|
|
|
localparam integer P_ECC_MODE = ( (ECC_MODE == 0 || ECC_MODE == "no_ecc" || ECC_MODE == "NO_ECC" ) ? 0 :
|
|
( (ECC_MODE == 1 || ECC_MODE == "encode_only" || ECC_MODE == "ENCODE_ONLY" ) ? 1 :
|
|
( (ECC_MODE == 2 || ECC_MODE == "decode_only" || ECC_MODE == "DECODE_ONLY" ) ? 2 :
|
|
( (ECC_MODE == 3 || ECC_MODE == "both_encode_and_decode" || ECC_MODE == "BOTH_ENCODE_AND_DECODE") ? 3 : 4))));
|
|
|
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == 2 || WAKEUP_TIME == "use_sleep_pin" || WAKEUP_TIME == "USE_SLEEP_PIN") ? 2 : 0 );
|
|
|
|
localparam integer P_MEMORY_OPTIMIZATION = (MEMORY_OPTIMIZATION == "false" ? 0 : 1);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Base module instantiation with dual port ROM configuration
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
.MEMORY_OPTIMIZATION (MEMORY_OPTIMIZATION ),
|
|
.MEMORY_TYPE (4 ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (P_MEMORY_PRIMITIVE),
|
|
.CLOCKING_MODE (P_CLOCKING_MODE ),
|
|
.ECC_MODE (P_ECC_MODE ),
|
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.USE_MEM_INIT (USE_MEM_INIT ),
|
|
.USE_MEM_INIT_MMI (USE_MEM_INIT_MMI ),
|
|
.WAKEUP_TIME (P_WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
.MESSAGE_CONTROL (MESSAGE_CONTROL ),
|
|
.VERSION (0 ),
|
|
.USE_EMBEDDED_CONSTRAINT (0 ),
|
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
|
.IGNORE_INIT_SYNTH (IGNORE_INIT_SYNTH ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (1 ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.BYTE_WRITE_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.ADDR_WIDTH_B (ADDR_WIDTH_B ),
|
|
.READ_RESET_VALUE_B (READ_RESET_VALUE_B),
|
|
.READ_LATENCY_B (READ_LATENCY_B ),
|
|
.WRITE_MODE_B (1 ),
|
|
.RST_MODE_B (RST_MODE_B )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (1'b0 ),
|
|
.addra (addra ),
|
|
.dina ({READ_DATA_WIDTH_A{1'b0}}),
|
|
.injectsbiterra (injectsbiterra ),
|
|
.injectdbiterra (injectdbiterra ),
|
|
.douta (douta ),
|
|
.sbiterra (sbiterra ),
|
|
.dbiterra (dbiterra ),
|
|
|
|
// Port B module ports
|
|
.clkb (clkb ),
|
|
.rstb (rstb ),
|
|
.enb (enb ),
|
|
.regceb (regceb ),
|
|
.web (1'b0 ),
|
|
.addrb (addrb ),
|
|
.dinb ({READ_DATA_WIDTH_B{1'b0}}),
|
|
.injectsbiterrb (injectsbiterrb ),
|
|
.injectdbiterrb (injectdbiterrb ),
|
|
.doutb (doutb ),
|
|
.sbiterrb (sbiterrb ),
|
|
.dbiterrb (dbiterrb )
|
|
);
|
|
|
|
endmodule : xpm_memory_dprom
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE" *)
|
|
module xpm_memory_sdpram # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter MEMORY_PRIMITIVE = "auto",
|
|
parameter CLOCKING_MODE = "common_clock",
|
|
parameter ECC_MODE = "no_ecc",
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter WAKEUP_TIME = "disable_sleep",
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter integer USE_EMBEDDED_CONSTRAINT = 0,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer CASCADE_HEIGHT = 0,
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer WRITE_PROTECT = 1,
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer WRITE_DATA_WIDTH_A = 32,
|
|
parameter integer BYTE_WRITE_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A),
|
|
parameter RST_MODE_A = "SYNC",
|
|
|
|
// Port B module parameters
|
|
parameter integer READ_DATA_WIDTH_B = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_B = $clog2(MEMORY_SIZE/READ_DATA_WIDTH_B),
|
|
parameter READ_RESET_VALUE_B = "0",
|
|
parameter integer READ_LATENCY_B = 2,
|
|
parameter WRITE_MODE_B = "no_change",
|
|
parameter RST_MODE_B = "SYNC"
|
|
|
|
) (
|
|
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire ena,
|
|
input wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire [WRITE_DATA_WIDTH_A-1:0] dina,
|
|
input wire injectsbiterra,
|
|
input wire injectdbiterra,
|
|
|
|
// Port B module ports
|
|
input wire clkb,
|
|
input wire rstb,
|
|
input wire enb,
|
|
input wire regceb,
|
|
input wire [ADDR_WIDTH_B-1:0] addrb,
|
|
output wire [READ_DATA_WIDTH_B-1:0] doutb,
|
|
output wire sbiterrb,
|
|
output wire dbiterrb
|
|
);
|
|
|
|
// Define local parameters for mapping with base file
|
|
localparam integer P_MEMORY_PRIMITIVE =
|
|
( (MEMORY_PRIMITIVE == 1 || MEMORY_PRIMITIVE == "LUTRAM" || MEMORY_PRIMITIVE == "lutram" || MEMORY_PRIMITIVE == "distributed" || MEMORY_PRIMITIVE == "DISTRIBUTED" ) ? 1 :
|
|
( (MEMORY_PRIMITIVE == 2 || MEMORY_PRIMITIVE == "BLOCKRAM" || MEMORY_PRIMITIVE == "blockram" || MEMORY_PRIMITIVE == "block" || MEMORY_PRIMITIVE == "BLOCK" ) ? 2 :
|
|
( (MEMORY_PRIMITIVE == 3 || MEMORY_PRIMITIVE == "ULTRARAM" || MEMORY_PRIMITIVE == "ultraram" || MEMORY_PRIMITIVE == "ultra" || MEMORY_PRIMITIVE == "ULTRA" ) ? 3 :
|
|
( (MEMORY_PRIMITIVE == 4 || MEMORY_PRIMITIVE == "mixedram" || MEMORY_PRIMITIVE == "MIXEDRAM" || MEMORY_PRIMITIVE == "mixed" || MEMORY_PRIMITIVE == "MIXED" ) ? 4 : 0))));
|
|
|
|
localparam integer P_CLOCKING_MODE = ( (CLOCKING_MODE == 0 || CLOCKING_MODE == "COMMON_CLOCK" || CLOCKING_MODE == "common_clock" )? 0 :
|
|
( (CLOCKING_MODE == 1 || CLOCKING_MODE == "INDEPENDENT_CLOCK" || CLOCKING_MODE == "independent_clock")? 1 : 0));
|
|
|
|
localparam integer P_ECC_MODE = ( (ECC_MODE == 0 || ECC_MODE == "NO_ECC" || ECC_MODE == "no_ecc" ) ? 0 :
|
|
( (ECC_MODE == 1 || ECC_MODE == "ENCODE_ONLY" || ECC_MODE == "encode_only" ) ? 1 :
|
|
( (ECC_MODE == 2 || ECC_MODE == "DECODE_ONLY" || ECC_MODE == "decode_only" ) ? 2 :
|
|
( (ECC_MODE == 3 || ECC_MODE == "BOTH_ENCODE_AND_DECODE" || ECC_MODE == "both_encode_and_decode") ? 3 : 4))));
|
|
|
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == 2 || WAKEUP_TIME == "use_sleep_pin" || WAKEUP_TIME == "USE_SLEEP_PIN") ? 2 : 0 );
|
|
|
|
localparam integer P_WRITE_MODE_B = ( (WRITE_MODE_B == 0 || WRITE_MODE_B == "WRITE_FIRST" || WRITE_MODE_B == "write_first") ? 0 :
|
|
( (WRITE_MODE_B == 1 || WRITE_MODE_B == "READ_FIRST" || WRITE_MODE_B == "read_first") ? 1 :
|
|
( (WRITE_MODE_B == 2 || WRITE_MODE_B == "NO_CHANGE" || WRITE_MODE_B == "no_change") ? 2 : 0)));
|
|
|
|
localparam integer P_MEMORY_OPTIMIZATION = (MEMORY_OPTIMIZATION == "false" ? 0 : 1);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Base module instantiation with simple dual port RAM configuration
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
.MEMORY_OPTIMIZATION (MEMORY_OPTIMIZATION ),
|
|
.MEMORY_TYPE (1 ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (P_MEMORY_PRIMITIVE ),
|
|
.CLOCKING_MODE (P_CLOCKING_MODE ),
|
|
.ECC_MODE (P_ECC_MODE ),
|
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.USE_MEM_INIT (USE_MEM_INIT ),
|
|
.USE_MEM_INIT_MMI (USE_MEM_INIT_MMI ),
|
|
.WAKEUP_TIME (P_WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
.MESSAGE_CONTROL (MESSAGE_CONTROL ),
|
|
.VERSION (0 ),
|
|
.USE_EMBEDDED_CONSTRAINT (USE_EMBEDDED_CONSTRAINT ),
|
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
|
.WRITE_PROTECT (WRITE_PROTECT ),
|
|
.IGNORE_INIT_SYNTH (IGNORE_INIT_SYNTH ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH_A ),
|
|
.READ_DATA_WIDTH_A (WRITE_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (BYTE_WRITE_WIDTH_A ),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A ("0" ),
|
|
.READ_LATENCY_A (2 ),
|
|
.WRITE_MODE_A (P_WRITE_MODE_B ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.BYTE_WRITE_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.ADDR_WIDTH_B (ADDR_WIDTH_B ),
|
|
.READ_RESET_VALUE_B (READ_RESET_VALUE_B ),
|
|
.READ_LATENCY_B (READ_LATENCY_B ),
|
|
.WRITE_MODE_B (P_WRITE_MODE_B ),
|
|
.RST_MODE_B (RST_MODE_B )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (1'b0 ),
|
|
.ena (ena ),
|
|
.regcea (1'b0 ),
|
|
.wea (wea ),
|
|
.addra (addra ),
|
|
.dina (dina ),
|
|
.injectsbiterra (injectsbiterra ),
|
|
.injectdbiterra (injectdbiterra ),
|
|
.douta ( ),
|
|
.sbiterra ( ),
|
|
.dbiterra ( ),
|
|
|
|
// Port B module ports
|
|
.clkb (clkb ),
|
|
.rstb (rstb ),
|
|
.enb (enb ),
|
|
.regceb (regceb ),
|
|
.web (1'b0 ),
|
|
.addrb (addrb ),
|
|
.dinb ({READ_DATA_WIDTH_B{1'b0}}),
|
|
.injectsbiterrb (1'b0 ),
|
|
.injectdbiterrb (1'b0 ),
|
|
.doutb (doutb ),
|
|
.sbiterrb (sbiterrb ),
|
|
.dbiterrb (dbiterrb )
|
|
);
|
|
|
|
endmodule : xpm_memory_sdpram
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE" *)
|
|
module xpm_memory_spram # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter MEMORY_PRIMITIVE = "auto",
|
|
parameter ECC_MODE = "no_ecc",
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter WAKEUP_TIME = "disable_sleep",
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer CASCADE_HEIGHT = 0,
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer WRITE_PROTECT = 1,
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer WRITE_DATA_WIDTH_A = 32,
|
|
parameter integer READ_DATA_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer BYTE_WRITE_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter WRITE_MODE_A = "read_first",
|
|
parameter RST_MODE_A = "SYNC"
|
|
|
|
) (
|
|
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire [WRITE_DATA_WIDTH_A-1:0] dina,
|
|
input wire injectsbiterra,
|
|
input wire injectdbiterra,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
output wire sbiterra,
|
|
output wire dbiterra
|
|
|
|
);
|
|
|
|
// Define local parameters for mapping with base file
|
|
localparam integer P_MEMORY_PRIMITIVE =
|
|
( (MEMORY_PRIMITIVE == 1 || MEMORY_PRIMITIVE == "LUTRAM" || MEMORY_PRIMITIVE == "lutram" || MEMORY_PRIMITIVE == "distributed" || MEMORY_PRIMITIVE == "DISTRIBUTED" ) ? 1 :
|
|
( (MEMORY_PRIMITIVE == 2 || MEMORY_PRIMITIVE == "BLOCKRAM" || MEMORY_PRIMITIVE == "blockram" || MEMORY_PRIMITIVE == "block" || MEMORY_PRIMITIVE == "BLOCK" ) ? 2 :
|
|
( (MEMORY_PRIMITIVE == 3 || MEMORY_PRIMITIVE == "ULTRARAM" || MEMORY_PRIMITIVE == "ultraram" || MEMORY_PRIMITIVE == "ultra" || MEMORY_PRIMITIVE == "ULTRA" ) ? 3 :
|
|
( (MEMORY_PRIMITIVE == 4 || MEMORY_PRIMITIVE == "mixedram" || MEMORY_PRIMITIVE == "MIXEDRAM" || MEMORY_PRIMITIVE == "mixed" || MEMORY_PRIMITIVE == "MIXED" ) ? 4 : 0))));
|
|
|
|
localparam integer P_CLOCKING_MODE = 0;
|
|
|
|
localparam integer P_ECC_MODE = ( (ECC_MODE == 0 || ECC_MODE == "NO_ECC" || ECC_MODE == "no_ecc") ? 0 :
|
|
( (ECC_MODE == 1 || ECC_MODE == "ENCODE_ONLY" || ECC_MODE == "encode_only") ? 1 :
|
|
( (ECC_MODE == 2 || ECC_MODE == "DECODE_ONLY" || ECC_MODE == "decode_only") ? 2 :
|
|
( (ECC_MODE == 3 || ECC_MODE == "BOTH_ENCODE_AND_DECODE" || ECC_MODE == "both_encode_and_decode") ? 3 : 4))));
|
|
|
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == 2 || WAKEUP_TIME == "use_sleep_pin" || WAKEUP_TIME == "USE_SLEEP_PIN") ? 2 : 0 ) ;
|
|
|
|
|
|
localparam integer P_WRITE_MODE_A = ( (WRITE_MODE_A == 0 || WRITE_MODE_A == "WRITE_FIRST" || WRITE_MODE_A == "write_first") ? 0 :
|
|
( (WRITE_MODE_A == 1 || WRITE_MODE_A == "READ_FIRST" || WRITE_MODE_A == "read_first") ? 1 :
|
|
( (WRITE_MODE_A == 2 || WRITE_MODE_A == "NO_CHANGE" || WRITE_MODE_A == "no_change") ? 2 : 0)));
|
|
|
|
localparam integer P_MEMORY_OPTIMIZATION = (MEMORY_OPTIMIZATION == "false" ? 0 : 1);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Base module instantiation with single port RAM configuration
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
.MEMORY_OPTIMIZATION (MEMORY_OPTIMIZATION ),
|
|
.MEMORY_TYPE (0 ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (P_MEMORY_PRIMITIVE ),
|
|
.CLOCKING_MODE (P_CLOCKING_MODE ),
|
|
.ECC_MODE (P_ECC_MODE ),
|
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.USE_MEM_INIT (USE_MEM_INIT ),
|
|
.USE_MEM_INIT_MMI (USE_MEM_INIT_MMI ),
|
|
.WAKEUP_TIME (P_WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
.MESSAGE_CONTROL (MESSAGE_CONTROL ),
|
|
.VERSION (0 ),
|
|
.USE_EMBEDDED_CONSTRAINT (0 ),
|
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
|
.WRITE_PROTECT (WRITE_PROTECT ),
|
|
.IGNORE_INIT_SYNTH (IGNORE_INIT_SYNTH ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH_A ),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (BYTE_WRITE_WIDTH_A ),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A ),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (P_WRITE_MODE_A ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (WRITE_DATA_WIDTH_A ),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_B (WRITE_DATA_WIDTH_A ),
|
|
.ADDR_WIDTH_B ($clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A)),
|
|
.READ_RESET_VALUE_B ("0" ),
|
|
.READ_LATENCY_B (READ_LATENCY_A ),
|
|
.WRITE_MODE_B (P_WRITE_MODE_A )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (wea ),
|
|
.addra (addra ),
|
|
.dina (dina ),
|
|
.injectsbiterra (injectsbiterra ),
|
|
.injectdbiterra (injectdbiterra ),
|
|
.douta (douta ),
|
|
.sbiterra (sbiterra ),
|
|
.dbiterra (dbiterra ),
|
|
|
|
// Port B module ports
|
|
.clkb (1'b0 ),
|
|
.rstb (1'b0 ),
|
|
.enb (1'b0 ),
|
|
.regceb (1'b0 ),
|
|
.web (1'b0 ),
|
|
.addrb ({$clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A){1'b0}}),
|
|
.dinb ({READ_DATA_WIDTH_A{1'b0}} ),
|
|
.injectsbiterrb (1'b0 ),
|
|
.injectdbiterrb (1'b0 ),
|
|
.doutb ( ),
|
|
.sbiterrb ( ),
|
|
.dbiterrb ( )
|
|
);
|
|
|
|
endmodule : xpm_memory_spram
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE" *)
|
|
module xpm_memory_sprom # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter MEMORY_PRIMITIVE = "auto",
|
|
parameter ECC_MODE = "no_ecc",
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter WAKEUP_TIME = "disable_sleep",
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer CASCADE_HEIGHT = 0,
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer READ_DATA_WIDTH_A = 32,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/READ_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter RST_MODE_A = "SYNC"
|
|
) (
|
|
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire injectsbiterra,
|
|
input wire injectdbiterra,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
output wire sbiterra,
|
|
output wire dbiterra
|
|
|
|
);
|
|
|
|
|
|
// Define local parameters for mapping with base file
|
|
localparam integer P_MEMORY_PRIMITIVE =
|
|
( (MEMORY_PRIMITIVE == 1 || MEMORY_PRIMITIVE == "lutram" || MEMORY_PRIMITIVE == "LUTRAM" || MEMORY_PRIMITIVE == "distributed" || MEMORY_PRIMITIVE == "DISTRIBUTED" ) ? 1 :
|
|
( (MEMORY_PRIMITIVE == 2 || MEMORY_PRIMITIVE == "blockram" || MEMORY_PRIMITIVE == "BLOCKRAM" || MEMORY_PRIMITIVE == "block" || MEMORY_PRIMITIVE == "BLOCK" ) ? 2 :
|
|
( (MEMORY_PRIMITIVE == 3 || MEMORY_PRIMITIVE == "ultraram" || MEMORY_PRIMITIVE == "ULTRARAM" || MEMORY_PRIMITIVE == "ultra" || MEMORY_PRIMITIVE == "ULTRA" ) ? 3 :
|
|
( (MEMORY_PRIMITIVE == 4 || MEMORY_PRIMITIVE == "mixedram" || MEMORY_PRIMITIVE == "MIXEDRAM" || MEMORY_PRIMITIVE == "mixed" || MEMORY_PRIMITIVE == "MIXED" ) ? 4 : 0))));
|
|
|
|
localparam integer P_CLOCKING_MODE = 0;
|
|
|
|
localparam integer P_ECC_MODE = ( (ECC_MODE == 0 || ECC_MODE == "no_ecc" || ECC_MODE == "NO_ECC" ) ? 0 :
|
|
( (ECC_MODE == 1 || ECC_MODE == "encode_only" || ECC_MODE == "ENCODE_ONLY" ) ? 1 :
|
|
( (ECC_MODE == 2 || ECC_MODE == "decode_only" || ECC_MODE == "DECODE_ONLY" ) ? 2 :
|
|
( (ECC_MODE == 3 || ECC_MODE == "both_encode_and_decode" || ECC_MODE == "BOTH_ENCODE_AND_DECODE") ? 3 : 4))));
|
|
|
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == 2 || WAKEUP_TIME == "use_sleep_pin" || WAKEUP_TIME == "USE_SLEEP_PIN") ? 2 : 0 );
|
|
|
|
localparam integer P_MEMORY_OPTIMIZATION = (MEMORY_OPTIMIZATION == "false" ? 0 : 1);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Base module instantiation with single port ROM configuration
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
.MEMORY_OPTIMIZATION (MEMORY_OPTIMIZATION ),
|
|
.MEMORY_TYPE (3 ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (P_MEMORY_PRIMITIVE ),
|
|
.CLOCKING_MODE (P_CLOCKING_MODE ),
|
|
.ECC_MODE (P_ECC_MODE ),
|
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.USE_MEM_INIT (USE_MEM_INIT ),
|
|
.USE_MEM_INIT_MMI (USE_MEM_INIT_MMI ),
|
|
.WAKEUP_TIME (P_WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
.MESSAGE_CONTROL (MESSAGE_CONTROL ),
|
|
.VERSION (0 ),
|
|
.USE_EMBEDDED_CONSTRAINT (0 ),
|
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
|
.IGNORE_INIT_SYNTH (IGNORE_INIT_SYNTH ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A ),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (1 ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (READ_DATA_WIDTH_A ),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_B (READ_DATA_WIDTH_A ),
|
|
.ADDR_WIDTH_B ($clog2(MEMORY_SIZE/READ_DATA_WIDTH_A)),
|
|
.READ_RESET_VALUE_B ("0" ),
|
|
.READ_LATENCY_B (READ_LATENCY_A ),
|
|
.WRITE_MODE_B (1 )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (1'b0 ),
|
|
.addra (addra ),
|
|
.dina ({READ_DATA_WIDTH_A{1'b0}} ),
|
|
.injectsbiterra (injectsbiterra ),
|
|
.injectdbiterra (injectdbiterra ),
|
|
.douta (douta ),
|
|
.sbiterra (sbiterra ),
|
|
.dbiterra (dbiterra ),
|
|
|
|
// Port B module ports
|
|
.clkb (1'b0 ),
|
|
.rstb (1'b0 ),
|
|
.enb (1'b0 ),
|
|
.regceb (1'b0 ),
|
|
.web (1'b0 ),
|
|
.addrb ({$clog2(MEMORY_SIZE/READ_DATA_WIDTH_A){1'b0}}),
|
|
.dinb ({READ_DATA_WIDTH_A{1'b0}} ),
|
|
.injectsbiterrb (1'b0 ),
|
|
.injectdbiterrb (1'b0 ),
|
|
.doutb ( ),
|
|
.sbiterrb ( ),
|
|
.dbiterrb ( )
|
|
);
|
|
|
|
endmodule : xpm_memory_sprom
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
(* XPM_MODULE = "TRUE" *)
|
|
module xpm_memory_tdpram # (
|
|
|
|
// Common module parameters
|
|
parameter integer MEMORY_SIZE = 2048,
|
|
parameter MEMORY_PRIMITIVE = "auto",
|
|
parameter CLOCKING_MODE = "common_clock",
|
|
parameter ECC_MODE = "no_ecc",
|
|
parameter MEMORY_INIT_FILE = "none",
|
|
parameter MEMORY_INIT_PARAM = "",
|
|
parameter integer USE_MEM_INIT = 1,
|
|
parameter integer USE_MEM_INIT_MMI = 0,
|
|
parameter WAKEUP_TIME = "disable_sleep",
|
|
parameter integer AUTO_SLEEP_TIME = 0,
|
|
parameter integer MESSAGE_CONTROL = 0,
|
|
parameter integer USE_EMBEDDED_CONSTRAINT = 0,
|
|
parameter MEMORY_OPTIMIZATION = "true",
|
|
parameter integer CASCADE_HEIGHT = 0,
|
|
parameter integer SIM_ASSERT_CHK = 0,
|
|
parameter integer WRITE_PROTECT = 1,
|
|
parameter integer IGNORE_INIT_SYNTH = 0,
|
|
|
|
// Port A module parameters
|
|
parameter integer WRITE_DATA_WIDTH_A = 32,
|
|
parameter integer READ_DATA_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer BYTE_WRITE_WIDTH_A = WRITE_DATA_WIDTH_A,
|
|
parameter integer ADDR_WIDTH_A = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_A),
|
|
parameter READ_RESET_VALUE_A = "0",
|
|
parameter integer READ_LATENCY_A = 2,
|
|
parameter WRITE_MODE_A = "no_change",
|
|
parameter RST_MODE_A = "SYNC",
|
|
|
|
// Port B module parameters
|
|
parameter integer WRITE_DATA_WIDTH_B = WRITE_DATA_WIDTH_A,
|
|
parameter integer READ_DATA_WIDTH_B = WRITE_DATA_WIDTH_B,
|
|
parameter integer BYTE_WRITE_WIDTH_B = WRITE_DATA_WIDTH_B,
|
|
parameter integer ADDR_WIDTH_B = $clog2(MEMORY_SIZE/WRITE_DATA_WIDTH_B),
|
|
parameter READ_RESET_VALUE_B = "0",
|
|
parameter integer READ_LATENCY_B = READ_LATENCY_A,
|
|
parameter WRITE_MODE_B = "no_change",
|
|
parameter RST_MODE_B = "SYNC"
|
|
) (
|
|
|
|
// Common module ports
|
|
input wire sleep,
|
|
|
|
// Port A module ports
|
|
input wire clka,
|
|
input wire rsta,
|
|
input wire ena,
|
|
input wire regcea,
|
|
input wire [(WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A)-1:0] wea,
|
|
input wire [ADDR_WIDTH_A-1:0] addra,
|
|
input wire [WRITE_DATA_WIDTH_A-1:0] dina,
|
|
input wire injectsbiterra,
|
|
input wire injectdbiterra,
|
|
output wire [READ_DATA_WIDTH_A-1:0] douta,
|
|
output wire sbiterra,
|
|
output wire dbiterra,
|
|
|
|
// Port B module ports
|
|
input wire clkb,
|
|
input wire rstb,
|
|
input wire enb,
|
|
input wire regceb,
|
|
input wire [(WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B)-1:0] web,
|
|
input wire [ADDR_WIDTH_B-1:0] addrb,
|
|
input wire [WRITE_DATA_WIDTH_B-1:0] dinb,
|
|
input wire injectsbiterrb,
|
|
input wire injectdbiterrb,
|
|
output wire [READ_DATA_WIDTH_B-1:0] doutb,
|
|
output wire sbiterrb,
|
|
output wire dbiterrb
|
|
);
|
|
|
|
// Define local parameters for mapping with base file
|
|
localparam integer P_MEMORY_PRIMITIVE =
|
|
( (MEMORY_PRIMITIVE == 1 || MEMORY_PRIMITIVE == "lutram" || MEMORY_PRIMITIVE == "LUTRAM" || MEMORY_PRIMITIVE == "distributed" || MEMORY_PRIMITIVE == "DISTRIBUTED" ) ? 1 :
|
|
( (MEMORY_PRIMITIVE == 2 || MEMORY_PRIMITIVE == "blockram" || MEMORY_PRIMITIVE == "BLOCKRAM" || MEMORY_PRIMITIVE == "block" || MEMORY_PRIMITIVE == "BLOCK" ) ? 2 :
|
|
( (MEMORY_PRIMITIVE == 3 || MEMORY_PRIMITIVE == "ultraram" || MEMORY_PRIMITIVE == "ULTRARAM" || MEMORY_PRIMITIVE == "ultra" || MEMORY_PRIMITIVE == "ULTRA" ) ? 3 :
|
|
( (MEMORY_PRIMITIVE == 4 || MEMORY_PRIMITIVE == "mixedram" || MEMORY_PRIMITIVE == "MIXEDRAM" || MEMORY_PRIMITIVE == "mixed" || MEMORY_PRIMITIVE == "MIXED" ) ? 4 : 0))));
|
|
|
|
localparam integer P_CLOCKING_MODE = ( (CLOCKING_MODE == 0 || CLOCKING_MODE == "common_clock" || CLOCKING_MODE == "COMMON_CLOCK" ) ? 0 :
|
|
( (CLOCKING_MODE == 1 || CLOCKING_MODE == "independent_clock" || CLOCKING_MODE == "INDEPENDENT_CLOCK") ? 1 : 0));
|
|
|
|
localparam integer P_ECC_MODE = ( (ECC_MODE == 0 || ECC_MODE == "no_ecc" || ECC_MODE == "NO_ECC" ) ? 0 :
|
|
( (ECC_MODE == 1 || ECC_MODE == "encode_only" || ECC_MODE == "ENCODE_ONLY" ) ? 1 :
|
|
( (ECC_MODE == 2 || ECC_MODE == "decode_only" || ECC_MODE == "DECODE_ONLY" ) ? 2 :
|
|
( (ECC_MODE == 3 || ECC_MODE == "both_encode_and_decode" || ECC_MODE == "BOTH_ENCODE_AND_DECODE") ? 3 : 4))));
|
|
|
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == 2 || WAKEUP_TIME == "use_sleep_pin" || WAKEUP_TIME == "USE_SLEEP_PIN") ? 2 : 0 );
|
|
|
|
localparam integer P_WRITE_MODE_A = ( (WRITE_MODE_A == 0 || WRITE_MODE_A == "write_first" || WRITE_MODE_A == "WRITE_FIRST") ? 0 :
|
|
( (WRITE_MODE_A == 1 || WRITE_MODE_A == "read_first" || WRITE_MODE_A == "READ_FIRST" ) ? 1 :
|
|
( (WRITE_MODE_A == 2 || WRITE_MODE_A == "no_change" || WRITE_MODE_A == "NO_CHANGE" ) ? 2 : 0)));
|
|
|
|
localparam integer P_WRITE_MODE_B = ( (WRITE_MODE_B == 0 || WRITE_MODE_B == "write_first" || WRITE_MODE_B == "WRITE_FIRST") ? 0 :
|
|
( (WRITE_MODE_B == 1 || WRITE_MODE_B == "read_first" || WRITE_MODE_B == "READ_FIRST" ) ? 1 :
|
|
( (WRITE_MODE_B == 2 || WRITE_MODE_B == "no_change" || WRITE_MODE_B == "NO_CHANGE" ) ? 2 : 0)));
|
|
|
|
localparam integer P_MEMORY_OPTIMIZATION = (MEMORY_OPTIMIZATION == "false" ? 0 : 1);
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
// Base module instantiation with true dual port RAM configuration
|
|
// -------------------------------------------------------------------------------------------------------------------
|
|
|
|
xpm_memory_base # (
|
|
|
|
// Common module parameters
|
|
.MEMORY_OPTIMIZATION (MEMORY_OPTIMIZATION ),
|
|
.MEMORY_TYPE (2 ),
|
|
.MEMORY_SIZE (MEMORY_SIZE ),
|
|
.MEMORY_PRIMITIVE (P_MEMORY_PRIMITIVE ),
|
|
.CLOCKING_MODE (P_CLOCKING_MODE ),
|
|
.ECC_MODE (P_ECC_MODE ),
|
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
|
.MEMORY_INIT_FILE (MEMORY_INIT_FILE ),
|
|
.MEMORY_INIT_PARAM (MEMORY_INIT_PARAM ),
|
|
.USE_MEM_INIT (USE_MEM_INIT ),
|
|
.USE_MEM_INIT_MMI (USE_MEM_INIT_MMI ),
|
|
.WAKEUP_TIME (P_WAKEUP_TIME ),
|
|
.AUTO_SLEEP_TIME (AUTO_SLEEP_TIME ),
|
|
.MESSAGE_CONTROL (MESSAGE_CONTROL ),
|
|
.VERSION (0 ),
|
|
.USE_EMBEDDED_CONSTRAINT (USE_EMBEDDED_CONSTRAINT ),
|
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
|
.WRITE_PROTECT (WRITE_PROTECT ),
|
|
.IGNORE_INIT_SYNTH (IGNORE_INIT_SYNTH ),
|
|
|
|
// Port A module parameters
|
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH_A),
|
|
.READ_DATA_WIDTH_A (READ_DATA_WIDTH_A ),
|
|
.BYTE_WRITE_WIDTH_A (BYTE_WRITE_WIDTH_A),
|
|
.ADDR_WIDTH_A (ADDR_WIDTH_A ),
|
|
.READ_RESET_VALUE_A (READ_RESET_VALUE_A),
|
|
.READ_LATENCY_A (READ_LATENCY_A ),
|
|
.WRITE_MODE_A (P_WRITE_MODE_A ),
|
|
.RST_MODE_A (RST_MODE_A ),
|
|
|
|
// Port B module parameters
|
|
.WRITE_DATA_WIDTH_B (WRITE_DATA_WIDTH_B),
|
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH_B ),
|
|
.BYTE_WRITE_WIDTH_B (BYTE_WRITE_WIDTH_B),
|
|
.ADDR_WIDTH_B (ADDR_WIDTH_B ),
|
|
.READ_RESET_VALUE_B (READ_RESET_VALUE_B),
|
|
.READ_LATENCY_B (READ_LATENCY_B ),
|
|
.WRITE_MODE_B (P_WRITE_MODE_B ),
|
|
.RST_MODE_B (RST_MODE_B )
|
|
) xpm_memory_base_inst (
|
|
|
|
// Common module ports
|
|
.sleep (sleep ),
|
|
|
|
// Port A module ports
|
|
.clka (clka ),
|
|
.rsta (rsta ),
|
|
.ena (ena ),
|
|
.regcea (regcea ),
|
|
.wea (wea ),
|
|
.addra (addra ),
|
|
.dina (dina ),
|
|
.injectsbiterra (injectsbiterra),
|
|
.injectdbiterra (injectdbiterra),
|
|
.douta (douta ),
|
|
.sbiterra (sbiterra ),
|
|
.dbiterra (dbiterra ),
|
|
|
|
// Port B module ports
|
|
.clkb (clkb ),
|
|
.rstb (rstb ),
|
|
.enb (enb ),
|
|
.regceb (regceb ),
|
|
.web (web ),
|
|
.addrb (addrb ),
|
|
.dinb (dinb ),
|
|
.injectsbiterrb (injectsbiterrb),
|
|
.injectdbiterrb (injectdbiterrb),
|
|
.doutb (doutb ),
|
|
.sbiterrb (sbiterrb ),
|
|
.dbiterrb (dbiterrb )
|
|
);
|
|
|
|
endmodule : xpm_memory_tdpram
|
|
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
//********************************************************************************************************************
|
|
|
|
`default_nettype wire
|