mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
5083 lines
221 KiB
Systemverilog
5083 lines
221 KiB
Systemverilog
|
//------------------------------------------------------------------------------
|
||
|
// (c) Copyright 2016 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_fifo_base # (
|
||
|
|
||
|
// Common module parameters
|
||
|
parameter integer COMMON_CLOCK = 1,
|
||
|
parameter integer RELATED_CLOCKS = 0,
|
||
|
parameter integer FIFO_MEMORY_TYPE = 0,
|
||
|
parameter integer ECC_MODE = 0,
|
||
|
parameter integer SIM_ASSERT_CHK = 0,
|
||
|
parameter integer CASCADE_HEIGHT = 0,
|
||
|
|
||
|
parameter integer FIFO_WRITE_DEPTH = 2048,
|
||
|
parameter integer WRITE_DATA_WIDTH = 32,
|
||
|
parameter integer WR_DATA_COUNT_WIDTH = 12,
|
||
|
parameter integer PROG_FULL_THRESH = 10,
|
||
|
parameter USE_ADV_FEATURES = "0707",
|
||
|
|
||
|
parameter READ_MODE = 0,
|
||
|
parameter FIFO_READ_LATENCY = 1,
|
||
|
parameter integer READ_DATA_WIDTH = WRITE_DATA_WIDTH,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH = 12,
|
||
|
parameter integer PROG_EMPTY_THRESH = 10,
|
||
|
parameter DOUT_RESET_VALUE = "",
|
||
|
parameter integer CDC_DEST_SYNC_FF = 2,
|
||
|
parameter integer FULL_RESET_VALUE = 0,
|
||
|
parameter integer REMOVE_WR_RD_PROT_LOGIC = 0,
|
||
|
|
||
|
parameter integer WAKEUP_TIME = 0,
|
||
|
parameter integer VERSION = 1
|
||
|
|
||
|
) (
|
||
|
|
||
|
// Common module ports
|
||
|
input wire sleep,
|
||
|
input wire rst,
|
||
|
|
||
|
// Write Domain ports
|
||
|
input wire wr_clk,
|
||
|
input wire wr_en,
|
||
|
input wire [WRITE_DATA_WIDTH-1:0] din,
|
||
|
output wire full,
|
||
|
output wire full_n,
|
||
|
output wire prog_full,
|
||
|
output wire [WR_DATA_COUNT_WIDTH-1:0] wr_data_count,
|
||
|
output wire overflow,
|
||
|
output wire wr_rst_busy,
|
||
|
output wire almost_full,
|
||
|
output wire wr_ack,
|
||
|
|
||
|
// Read Domain ports
|
||
|
input wire rd_clk,
|
||
|
input wire rd_en,
|
||
|
output wire [READ_DATA_WIDTH-1:0] dout,
|
||
|
output wire empty,
|
||
|
output wire prog_empty,
|
||
|
output wire [RD_DATA_COUNT_WIDTH-1:0] rd_data_count,
|
||
|
output wire underflow,
|
||
|
output wire rd_rst_busy,
|
||
|
output wire almost_empty,
|
||
|
output wire data_valid,
|
||
|
|
||
|
// ECC Related ports
|
||
|
input wire injectsbiterr,
|
||
|
input wire injectdbiterr,
|
||
|
output wire sbiterr,
|
||
|
output wire dbiterr
|
||
|
);
|
||
|
|
||
|
function integer clog2;
|
||
|
input integer value;
|
||
|
begin
|
||
|
value = value-1;
|
||
|
for (clog2=0; value>0; clog2=clog2+1)
|
||
|
value = value>>1;
|
||
|
end
|
||
|
endfunction
|
||
|
// Function to convert ASCII value to binary
|
||
|
function [3:0] str2bin;
|
||
|
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])
|
||
|
str2bin = str_val_ascii[3:0];
|
||
|
else begin
|
||
|
str2bin [3] = 1'b1;
|
||
|
str2bin [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
||
|
str2bin [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
||
|
str2bin [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 [15:0] hstr2bin;
|
||
|
input [16*8-1 : 0] hstr_val;
|
||
|
integer rst_loop_a;
|
||
|
localparam integer rsta_loop_iter = 16;
|
||
|
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] = str2bin(hstr_val[(rst_loop_a*8)-1 -: 8]);
|
||
|
end
|
||
|
return rst_val_conv_a_i[15:0];
|
||
|
endfunction
|
||
|
|
||
|
|
||
|
localparam invalid = 0;
|
||
|
localparam stage1_valid = 2;
|
||
|
localparam stage2_valid = 1;
|
||
|
localparam both_stages_valid = 3;
|
||
|
|
||
|
reg [1:0] curr_fwft_state = invalid;
|
||
|
reg [1:0] next_fwft_state;// = invalid;
|
||
|
|
||
|
|
||
|
|
||
|
localparam FIFO_MEM_TYPE = FIFO_MEMORY_TYPE;
|
||
|
localparam RD_MODE = READ_MODE;
|
||
|
localparam ENABLE_ECC = (ECC_MODE == 1) ? 3 : 0;
|
||
|
localparam FIFO_READ_DEPTH = FIFO_WRITE_DEPTH*WRITE_DATA_WIDTH/READ_DATA_WIDTH;
|
||
|
localparam FIFO_SIZE = FIFO_WRITE_DEPTH*WRITE_DATA_WIDTH;
|
||
|
localparam WR_WIDTH_LOG = clog2(WRITE_DATA_WIDTH);
|
||
|
localparam WR_DEPTH_LOG = clog2(FIFO_WRITE_DEPTH);
|
||
|
localparam WR_PNTR_WIDTH = clog2(FIFO_WRITE_DEPTH);
|
||
|
localparam RD_PNTR_WIDTH = clog2(FIFO_READ_DEPTH);
|
||
|
localparam FULL_RST_VAL = FULL_RESET_VALUE == 0 ? 1'b0 : 1'b1;
|
||
|
localparam WR_RD_RATIO = (WR_PNTR_WIDTH > RD_PNTR_WIDTH) ? (WR_PNTR_WIDTH-RD_PNTR_WIDTH) : 0;
|
||
|
localparam READ_MODE_LL = (READ_MODE == 0) ? 0 : 1;
|
||
|
localparam PF_THRESH_ADJ = (READ_MODE == 0) ? PROG_FULL_THRESH :
|
||
|
PROG_FULL_THRESH - (2*(2**WR_RD_RATIO));
|
||
|
localparam PE_THRESH_ADJ = (READ_MODE_LL == 1 && FIFO_MEMORY_TYPE != 4) ? PROG_EMPTY_THRESH - 2'h2 : PROG_EMPTY_THRESH;
|
||
|
|
||
|
localparam PF_THRESH_MIN = 3+(READ_MODE_LL*2*(((FIFO_WRITE_DEPTH-1)/FIFO_READ_DEPTH)+1))+(COMMON_CLOCK?0:CDC_DEST_SYNC_FF);
|
||
|
localparam PF_THRESH_MAX = (FIFO_WRITE_DEPTH-3)-(READ_MODE_LL*2*(((FIFO_WRITE_DEPTH-1)/FIFO_READ_DEPTH)+1));
|
||
|
localparam PE_THRESH_MIN = 3+(READ_MODE_LL*2);
|
||
|
localparam PE_THRESH_MAX = (FIFO_READ_DEPTH-3)-(READ_MODE_LL*2);
|
||
|
localparam WR_DC_WIDTH_EXT = clog2(FIFO_WRITE_DEPTH)+1;
|
||
|
localparam RD_DC_WIDTH_EXT = clog2(FIFO_READ_DEPTH)+1;
|
||
|
localparam RD_LATENCY = (READ_MODE == 2) ? 1 : (READ_MODE == 1) ? 2 : FIFO_READ_LATENCY;
|
||
|
localparam WIDTH_RATIO = (READ_DATA_WIDTH > WRITE_DATA_WIDTH) ? (READ_DATA_WIDTH/WRITE_DATA_WIDTH) : (WRITE_DATA_WIDTH/READ_DATA_WIDTH);
|
||
|
|
||
|
localparam [15:0] EN_ADV_FEATURE = hstr2bin(USE_ADV_FEATURES);
|
||
|
|
||
|
localparam EN_OF = EN_ADV_FEATURE[0]; //EN_ADV_FLAGS_WR[0] ? 1 : 0;
|
||
|
localparam EN_PF = EN_ADV_FEATURE[1]; //EN_ADV_FLAGS_WR[1] ? 1 : 0;
|
||
|
localparam EN_WDC = EN_ADV_FEATURE[2]; //EN_ADV_FLAGS_WR[2] ? 1 : 0;
|
||
|
localparam EN_AF = EN_ADV_FEATURE[3]; //EN_ADV_FLAGS_WR[3] ? 1 : 0;
|
||
|
localparam EN_WACK = EN_ADV_FEATURE[4]; //EN_ADV_FLAGS_WR[4] ? 1 : 0;
|
||
|
localparam FG_EQ_ASYM_DOUT = EN_ADV_FEATURE[5]; //EN_ADV_FLAGS_WR[5] ? 1 : 0;
|
||
|
localparam EN_UF = EN_ADV_FEATURE[8]; //EN_ADV_FLAGS_RD[0] ? 1 : 0;
|
||
|
localparam EN_PE = EN_ADV_FEATURE[9]; //EN_ADV_FLAGS_RD[1] ? 1 : 0;
|
||
|
localparam EN_RDC = EN_ADV_FEATURE[10]; //EN_ADV_FLAGS_RD[2] ? 1 : 0;
|
||
|
localparam EN_AE = EN_ADV_FEATURE[11]; //EN_ADV_FLAGS_RD[3] ? 1 : 0;
|
||
|
localparam EN_DVLD = EN_ADV_FEATURE[12]; //EN_ADV_FLAGS_RD[4] ? 1 : 0;
|
||
|
|
||
|
wire wrst_busy;
|
||
|
wire [WR_PNTR_WIDTH-1:0] wr_pntr;
|
||
|
wire [WR_PNTR_WIDTH:0] wr_pntr_ext;
|
||
|
wire [WR_PNTR_WIDTH-1:0] wr_pntr_rd_cdc;
|
||
|
wire [WR_PNTR_WIDTH:0] wr_pntr_rd_cdc_dc;
|
||
|
wire [WR_PNTR_WIDTH-1:0] wr_pntr_rd;
|
||
|
wire [WR_PNTR_WIDTH:0] wr_pntr_rd_dc;
|
||
|
wire [WR_PNTR_WIDTH-1:0] rd_pntr_wr_adj;
|
||
|
wire [WR_PNTR_WIDTH:0] rd_pntr_wr_adj_dc;
|
||
|
wire [WR_PNTR_WIDTH-1:0] wr_pntr_plus1;
|
||
|
wire [WR_PNTR_WIDTH-1:0] wr_pntr_plus2;
|
||
|
wire [WR_PNTR_WIDTH-1:0] wr_pntr_plus3;
|
||
|
wire [WR_PNTR_WIDTH:0] wr_pntr_plus1_pf;
|
||
|
wire [WR_PNTR_WIDTH:0] rd_pntr_wr_adj_inv_pf;
|
||
|
reg [WR_PNTR_WIDTH:0] diff_pntr_pf_q = {WR_PNTR_WIDTH{1'b0}};
|
||
|
wire [WR_PNTR_WIDTH-1:0] diff_pntr_pf;
|
||
|
wire [RD_PNTR_WIDTH-1:0] rd_pntr;
|
||
|
wire [RD_PNTR_WIDTH:0] rd_pntr_ext;
|
||
|
wire [RD_PNTR_WIDTH-1:0] rd_pntr_wr_cdc;
|
||
|
wire [RD_PNTR_WIDTH-1:0] rd_pntr_wr;
|
||
|
wire [RD_PNTR_WIDTH:0] rd_pntr_wr_cdc_dc;
|
||
|
wire [RD_PNTR_WIDTH:0] rd_pntr_wr_dc;
|
||
|
wire [RD_PNTR_WIDTH-1:0] wr_pntr_rd_adj;
|
||
|
wire [RD_PNTR_WIDTH:0] wr_pntr_rd_adj_dc;
|
||
|
wire [RD_PNTR_WIDTH-1:0] rd_pntr_plus1;
|
||
|
wire [RD_PNTR_WIDTH-1:0] rd_pntr_plus2;
|
||
|
wire invalid_state;
|
||
|
wire valid_fwft;
|
||
|
wire ram_valid_fwft;
|
||
|
wire going_empty;
|
||
|
wire leaving_empty;
|
||
|
wire going_aempty;
|
||
|
wire leaving_aempty;
|
||
|
reg ram_empty_i = 1'b1;
|
||
|
reg ram_aempty_i = 1'b1;
|
||
|
wire empty_i;
|
||
|
wire going_full;
|
||
|
wire leaving_full;
|
||
|
wire going_afull;
|
||
|
wire leaving_afull;
|
||
|
reg prog_full_i = FULL_RST_VAL;
|
||
|
reg ram_full_i = FULL_RST_VAL;
|
||
|
reg ram_afull_i = FULL_RST_VAL;
|
||
|
reg ram_full_n = ~FULL_RST_VAL;
|
||
|
wire ram_wr_en_i;
|
||
|
wire ram_rd_en_i;
|
||
|
reg wr_ack_i = 1'b0;
|
||
|
wire rd_en_i;
|
||
|
reg rd_en_fwft;
|
||
|
wire ram_regce;
|
||
|
wire ram_regce_pipe;
|
||
|
wire [READ_DATA_WIDTH-1:0] dout_i;
|
||
|
reg empty_fwft_i = 1'b1;
|
||
|
reg aempty_fwft_i = 1'b1;
|
||
|
reg empty_fwft_fb = 1'b1;
|
||
|
reg overflow_i = 1'b0;
|
||
|
reg underflow_i = 1'b0;
|
||
|
reg data_valid_fwft = 1'b0;
|
||
|
reg data_valid_std = 1'b0;
|
||
|
wire data_vld_std;
|
||
|
wire wrp_gt_rdp_and_red;
|
||
|
wire wrp_lt_rdp_and_red;
|
||
|
reg ram_wr_en_pf_q = 1'b0;
|
||
|
reg ram_rd_en_pf_q = 1'b0;
|
||
|
wire ram_wr_en_pf;
|
||
|
wire ram_rd_en_pf;
|
||
|
wire wr_pntr_plus1_pf_carry;
|
||
|
wire rd_pntr_wr_adj_pf_carry;
|
||
|
wire write_allow;
|
||
|
wire read_allow;
|
||
|
wire read_only;
|
||
|
wire write_only;
|
||
|
reg write_only_q;
|
||
|
reg read_only_q;
|
||
|
reg [RD_PNTR_WIDTH-1:0] diff_pntr_pe_reg1;
|
||
|
reg [RD_PNTR_WIDTH-1:0] diff_pntr_pe_reg2;
|
||
|
reg [RD_PNTR_WIDTH-1:0] diff_pntr_pe = 'b0;
|
||
|
reg prog_empty_i = 1'b1;
|
||
|
reg ram_empty_i_d1 = 1'b1;
|
||
|
wire fe_of_empty;
|
||
|
// function to validate the write depth value
|
||
|
function logic dpth_pwr_2;
|
||
|
input integer fifo_depth;
|
||
|
integer log2_of_depth; // correcponding to the default value of 2k depth
|
||
|
log2_of_depth = clog2(fifo_depth);
|
||
|
if (fifo_depth == 2 ** log2_of_depth)
|
||
|
dpth_pwr_2 = 1;
|
||
|
else
|
||
|
dpth_pwr_2 = 0;
|
||
|
return dpth_pwr_2;
|
||
|
endfunction
|
||
|
|
||
|
initial begin : config_drc
|
||
|
reg drc_err_flag;
|
||
|
drc_err_flag = 0;
|
||
|
#1;
|
||
|
|
||
|
if (COMMON_CLOCK == 0 && FIFO_MEM_TYPE == 3) begin
|
||
|
$error("[%s %0d-%0d] UltraRAM cannot be used as asynchronous FIFO because it has only one clock support %m", "XPM_FIFO", 1, 1);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (COMMON_CLOCK == 1 && RELATED_CLOCKS == 1) begin
|
||
|
$error("[%s %0d-%0d] Related Clocks cannot be used in synchronous FIFO because it is applicable only for asynchronous FIFO %m", "XPM_FIFO", 1, 2);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if(!(FIFO_WRITE_DEPTH > 15 && FIFO_WRITE_DEPTH <= 4*1024*1024)) begin
|
||
|
$error("[%s %0d-%0d] FIFO_WRITE_DEPTH (%0d) value specified is not within the supported ranges. Miniumum supported depth is 16, and the maximum supported depth is 4*1024*1024 locations. %m", "XPM_FIFO", 1, 3, FIFO_WRITE_DEPTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if(!dpth_pwr_2(FIFO_WRITE_DEPTH) && (FIFO_WRITE_DEPTH > 15 && FIFO_WRITE_DEPTH <= 4*1024*1024)) begin
|
||
|
$error("[%s %0d-%0d] FIFO_WRITE_DEPTH (%0d) value specified is non-power of 2, but this release of XPM_FIFO supports configurations having the fifo write depth set to power of 2. %m", "XPM_FIFO", 1, 4, FIFO_WRITE_DEPTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (CDC_DEST_SYNC_FF < 2 || CDC_DEST_SYNC_FF > 8) begin
|
||
|
$error("[%s %0d-%0d] CDC_DEST_SYNC_FF (%0d) value is specified for this configuration, but this beta release of XPM_FIFO supports CDC_DEST_SYNC_FF values in between 2 and 8. %m", "XPM_FIFO", 1, 5,CDC_DEST_SYNC_FF);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (CDC_DEST_SYNC_FF != 2 && RELATED_CLOCKS == 1) begin
|
||
|
$error("[%s %0d-%0d] CDC_DEST_SYNC_FF (%0d) value is specified for this configuration, but CDC_DEST_SYNC_FF value can not be modified from default value when RELATED_CLOCKS parameter is set to 1. %m", "XPM_FIFO", 1, 6,CDC_DEST_SYNC_FF);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (FIFO_WRITE_DEPTH == 16 && CDC_DEST_SYNC_FF > 4) begin
|
||
|
$error("[%s %0d-%0d] CDC_DEST_SYNC_FF = %0d and FIFO_WRITE_DEPTH = %0d. This is invalid combination. Either FIFO_WRITE_DEPTH should be increased or CDC_DEST_SYNC_FF should be reduced. %m", "XPM_FIFO", 1, 7,CDC_DEST_SYNC_FF, FIFO_WRITE_DEPTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (EN_ADV_FEATURE[7:5] != 3'h0) begin
|
||
|
$error("[%s %0d-%0d] USE_ADV_FEATURES[7:5] = %0h. This is a reserved field and must be set to 0s. %m", "XPM_FIFO", 1, 8, EN_ADV_FEATURE[7:5]);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (EN_ADV_FEATURE[15:14] != 3'h0) begin
|
||
|
$error("[%s %0d-%0d] USE_ADV_FEATURES[15:13] = %0h. This is a reserved field and must be set to 0s. %m", "XPM_FIFO", 1, 9, EN_ADV_FEATURE[15:13]);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
// if(WIDTH_RATIO > 32) begin
|
||
|
// $error("[%s %0d-%0d] The ratio between WRITE_DATA_WIDTH (%0d) and READ_DATA_WIDTH (%0d) is greater than 32, but this release of XPM_FIFO supports configurations having the ratio between data widths must be less than 32. %m", "XPM_FIFO", 1, 10, WRITE_DATA_WIDTH, READ_DATA_WIDTH);
|
||
|
// drc_err_flag = 1;
|
||
|
// end
|
||
|
if (WR_WIDTH_LOG+WR_DEPTH_LOG > 30) begin
|
||
|
$error("[%s %0d-%0d] The specified Width(%0d) and Depth(%0d) exceeds the maximum supported FIFO SIZE. Please reduce either FIFO Width or Depth. %m", "XPM_FIFO", 1, 10, WRITE_DATA_WIDTH,FIFO_WRITE_DEPTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if(FIFO_READ_DEPTH < 16) begin
|
||
|
$error("[%s %0d-%0d] Write Width is %0d Read Width is %0d and Write Depth is %0d, this results in the Read Depth(%0d) less than 16. This is an invalid combination, Ensure the depth on both sides is minimum 16. %m", "XPM_FIFO", 1, 11, WRITE_DATA_WIDTH, READ_DATA_WIDTH, FIFO_WRITE_DEPTH, FIFO_READ_DEPTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
// Range Checks
|
||
|
if (COMMON_CLOCK > 1) begin
|
||
|
$error("[%s %0d-%0d] COMMON_CLOCK (%s) value is outside of legal range. %m", "XPM_FIFO", 10, 1, COMMON_CLOCK);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (FIFO_MEMORY_TYPE > 3) begin
|
||
|
$error("[%s %0d-%0d] FIFO_MEMORY_TYPE (%s) value is outside of legal range. %m", "XPM_FIFO", 10, 2, FIFO_MEMORY_TYPE);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (READ_MODE > 2) begin
|
||
|
$error("[%s %0d-%0d] READ_MODE (%s) value is outside of legal range. %m", "XPM_FIFO", 10, 3, READ_MODE);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (ECC_MODE > 1) begin
|
||
|
$error("[%s %0d-%0d] ECC_MODE (%s) value is outside of legal range. %m", "XPM_FIFO", 10, 4, 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. WAKEUP_TIME should be either 0 or 2. %m", "XPM_FIFO", 10, 5, WAKEUP_TIME);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (!(VERSION == 0)) begin
|
||
|
$error("[%s %0d-%0d] VERSION (%0d) value is outside of legal range. %m", "XPM_FIFO", 10, 6, VERSION);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (!(WRITE_DATA_WIDTH > 0)) begin
|
||
|
$error("[%s %0d-%0d] WRITE_DATA_WIDTH (%0d) value is outside of legal range. %m", "XPM_FIFO", 15, 2, WRITE_DATA_WIDTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (!(READ_DATA_WIDTH > 0)) begin
|
||
|
$error("[%s %0d-%0d] READ_DATA_WIDTH (%0d) value is outside of legal range. %m", "XPM_FIFO", 15, 3, READ_DATA_WIDTH);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (EN_PF == 1 && ((PROG_FULL_THRESH < PF_THRESH_MIN) || (PROG_FULL_THRESH > PF_THRESH_MAX))) begin
|
||
|
$error("[%s %0d-%0d] Programmable Full flag is enabled, but PROG_FULL_THRESH (%0d) value is outside of legal range. PROG_FULL_THRESH value must be between %0d and %0d. %m", "XPM_FIFO", 15, 4, PROG_FULL_THRESH, PF_THRESH_MIN, PF_THRESH_MAX);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (EN_PE == 1 && (WIDTH_RATIO <= 32) && ((PROG_EMPTY_THRESH < PE_THRESH_MIN) || (PROG_EMPTY_THRESH > PE_THRESH_MAX))) begin
|
||
|
$error("[%s %0d-%0d] Programmable Empty flag is enabled, but PROG_EMPTY_THRESH (%0d) value is outside of legal range. PROG_EMPTY_THRESH value must be between %0d and %0d. %m", "XPM_FIFO", 15, 5, PROG_EMPTY_THRESH, PE_THRESH_MIN, PE_THRESH_MAX);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
if (EN_WDC == 1 && ((WR_DATA_COUNT_WIDTH < 0) || (WR_DATA_COUNT_WIDTH > WR_DC_WIDTH_EXT))) begin
|
||
|
$error("[%s %0d-%0d] Write Data Count is enabled, but WR_DATA_COUNT_WIDTH (%0d) value is outside of legal range. WR_DATA_COUNT_WIDTH value must be between %0d and %0d. %m", "XPM_FIFO", 15, 6, WR_DATA_COUNT_WIDTH, 0, WR_DC_WIDTH_EXT);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
|
||
|
if (EN_RDC == 1 && ((RD_DATA_COUNT_WIDTH < 0) || (RD_DATA_COUNT_WIDTH > RD_DC_WIDTH_EXT))) begin
|
||
|
$error("[%s %0d-%0d] Read Data Count is enabled, but RD_DATA_COUNT_WIDTH (%0d) value is outside of legal range. RD_DATA_COUNT_WIDTH value must be between %0d and %0d. %m", "XPM_FIFO", 15, 7, RD_DATA_COUNT_WIDTH, 0, RD_DC_WIDTH_EXT);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
//DRCs on Low Latency FWFT mode
|
||
|
if (READ_MODE == 2 && FIFO_MEMORY_TYPE != 1) begin
|
||
|
$error("[%s %0d-%0d] XPM_FIFO does not support Read Mode (Low Latency FWFT) for FIFO_MEMORY_TYPE other than lutram/distributed. %m", "XPM_FIFO", 16, 2);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
if (READ_MODE == 2 && EN_ADV_FEATURE != 16'h0) begin
|
||
|
$error("[%s %0d-%0d] USE_ADV_FEATURES = %0h. XPM_FIFO does not support Advanced Features in Low Latency FWFT mode. %m", "XPM_FIFO", 16, 3, EN_ADV_FEATURE);
|
||
|
drc_err_flag = 1;
|
||
|
end
|
||
|
|
||
|
// Infos
|
||
|
|
||
|
// Warnings
|
||
|
if (drc_err_flag == 1)
|
||
|
#1 $finish;
|
||
|
end : config_drc
|
||
|
|
||
|
wire wr_en_i;
|
||
|
wire wr_rst_i;
|
||
|
wire rd_rst_i;
|
||
|
reg rd_rst_d2 = 1'b0;
|
||
|
wire rst_d1;
|
||
|
wire rst_d2;
|
||
|
wire clr_full;
|
||
|
wire empty_fwft_d1;
|
||
|
wire leaving_empty_fwft_fe;
|
||
|
wire leaving_empty_fwft_re;
|
||
|
wire le_fwft_re;
|
||
|
wire le_fwft_fe;
|
||
|
wire [1:0] extra_words_fwft;
|
||
|
wire le_fwft_re_wr;
|
||
|
wire le_fwft_fe_wr;
|
||
|
|
||
|
generate
|
||
|
|
||
|
xpm_fifo_rst # (COMMON_CLOCK, CDC_DEST_SYNC_FF, SIM_ASSERT_CHK)
|
||
|
xpm_fifo_rst_inst (rst, wr_clk, rd_clk, wr_rst_i, rd_rst_i, wrst_busy, rd_rst_busy);
|
||
|
assign wr_rst_busy = wrst_busy | rst_d1;
|
||
|
|
||
|
xpm_fifo_reg_bit #(0)
|
||
|
rst_d1_inst (1'b0, wr_clk, wrst_busy, rst_d1);
|
||
|
xpm_fifo_reg_bit #(0)
|
||
|
rst_d2_inst (1'b0, wr_clk, rst_d1, rst_d2);
|
||
|
|
||
|
assign clr_full = ~wrst_busy & rst_d1 & ~rst;
|
||
|
assign rd_en_i = (RD_MODE == 0) ? rd_en : rd_en_fwft;
|
||
|
|
||
|
if (REMOVE_WR_RD_PROT_LOGIC == 1) begin : ngen_wr_rd_prot
|
||
|
assign ram_wr_en_i = wr_en;
|
||
|
assign ram_rd_en_i = rd_en_i;
|
||
|
end : ngen_wr_rd_prot
|
||
|
else begin : gen_wr_rd_prot
|
||
|
assign ram_wr_en_i = wr_en & ~ram_full_i & ~(wrst_busy|rst_d1);
|
||
|
assign ram_rd_en_i = rd_en_i & ~ram_empty_i;
|
||
|
end : gen_wr_rd_prot
|
||
|
|
||
|
// Write pointer generation
|
||
|
xpm_counter_updn # (WR_PNTR_WIDTH+1, 0)
|
||
|
wrp_inst (wrst_busy, wr_clk, ram_wr_en_i, ram_wr_en_i, 1'b0, wr_pntr_ext);
|
||
|
assign wr_pntr = wr_pntr_ext[WR_PNTR_WIDTH-1:0];
|
||
|
|
||
|
xpm_counter_updn # (WR_PNTR_WIDTH, 1)
|
||
|
wrpp1_inst (wrst_busy, wr_clk, ram_wr_en_i, ram_wr_en_i, 1'b0, wr_pntr_plus1);
|
||
|
|
||
|
xpm_counter_updn # (WR_PNTR_WIDTH, 2)
|
||
|
wrpp2_inst (wrst_busy, wr_clk, ram_wr_en_i, ram_wr_en_i, 1'b0, wr_pntr_plus2);
|
||
|
|
||
|
if (EN_AF == 1) begin : gaf_wptr_p3
|
||
|
xpm_counter_updn # (WR_PNTR_WIDTH, 3)
|
||
|
wrpp3_inst (wrst_busy, wr_clk, ram_wr_en_i, ram_wr_en_i, 1'b0, wr_pntr_plus3);
|
||
|
end : gaf_wptr_p3
|
||
|
|
||
|
// Read pointer generation
|
||
|
xpm_counter_updn # (RD_PNTR_WIDTH+1, 0)
|
||
|
rdp_inst (rd_rst_i, rd_clk, ram_rd_en_i, ram_rd_en_i, 1'b0, rd_pntr_ext);
|
||
|
assign rd_pntr = rd_pntr_ext[RD_PNTR_WIDTH-1:0];
|
||
|
|
||
|
xpm_counter_updn # (RD_PNTR_WIDTH, 1)
|
||
|
rdpp1_inst (rd_rst_i, rd_clk, ram_rd_en_i, ram_rd_en_i, 1'b0, rd_pntr_plus1);
|
||
|
|
||
|
if (EN_AE == 1) begin : gae_rptr_p2
|
||
|
xpm_counter_updn # (RD_PNTR_WIDTH, 2)
|
||
|
rdpp2_inst (rd_rst_i, rd_clk, ram_rd_en_i, ram_rd_en_i, 1'b0, rd_pntr_plus2);
|
||
|
end : gae_rptr_p2
|
||
|
|
||
|
assign full = ram_full_i;
|
||
|
assign full_n = ram_full_n;
|
||
|
assign almost_full = EN_AF == 1 ? ram_afull_i : 1'b0;
|
||
|
assign wr_ack = EN_WACK == 1 ? wr_ack_i : 1'b0;
|
||
|
if (EN_WACK == 1) begin : gwack
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (rst | wr_rst_i | wrst_busy)
|
||
|
wr_ack_i <= 1'b0;
|
||
|
else
|
||
|
wr_ack_i <= ram_wr_en_i;
|
||
|
end
|
||
|
end : gwack
|
||
|
|
||
|
assign prog_full = EN_PF == 1 ? (PROG_FULL_THRESH > 0) ? prog_full_i : 1'b0 : 1'b0;
|
||
|
assign prog_empty = EN_PE == 1 ? (PROG_EMPTY_THRESH > 0) ? prog_empty_i : 1'b1 : 1'b0;
|
||
|
|
||
|
assign empty_i = (RD_MODE == 0)? ram_empty_i : empty_fwft_i;
|
||
|
assign empty = empty_i;
|
||
|
assign almost_empty = EN_AE == 1 ? (RD_MODE == 0) ? ram_aempty_i : aempty_fwft_i : 1'b0;
|
||
|
|
||
|
assign data_valid = EN_DVLD == 1 ? (RD_MODE == 0) ? data_valid_std : data_valid_fwft : 1'b0;
|
||
|
if (EN_DVLD == 1) begin : gdvld
|
||
|
assign data_vld_std = (RD_MODE == 0) ? (FIFO_READ_LATENCY == 1) ? ram_rd_en_i: ram_regce_pipe : ram_regce;
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i)
|
||
|
data_valid_std <= 1'b0;
|
||
|
else
|
||
|
data_valid_std <= data_vld_std;
|
||
|
end
|
||
|
end : gdvld
|
||
|
|
||
|
// Simple dual port RAM instantiation for non-Built-in FIFO
|
||
|
if (FIFO_MEMORY_TYPE < 4) begin : gen_sdpram
|
||
|
|
||
|
// Reset is not supported when ECC is enabled by the BRAM/URAM primitives
|
||
|
wire rst_int;
|
||
|
if(ECC_MODE !=0) begin : gnd_rst
|
||
|
assign rst_int = 0;
|
||
|
end : gnd_rst
|
||
|
else begin : rst_gen
|
||
|
assign rst_int = rd_rst_i;
|
||
|
end : rst_gen
|
||
|
// ----------------------------------------------------------------------
|
||
|
// Base module instantiation with simple dual port RAM configuration
|
||
|
// ----------------------------------------------------------------------
|
||
|
localparam USE_DRAM_CONSTRAINT = (COMMON_CLOCK == 0 && FIFO_MEMORY_TYPE == 1) ? 1 : 0;
|
||
|
localparam WR_MODE_B = (FIFO_MEMORY_TYPE == 1 || FIFO_MEMORY_TYPE == 3) ? 1 : 2;
|
||
|
xpm_memory_base # (
|
||
|
|
||
|
// Common module parameters
|
||
|
.MEMORY_TYPE (1 ),
|
||
|
.MEMORY_SIZE (FIFO_SIZE ),
|
||
|
.MEMORY_PRIMITIVE (FIFO_MEMORY_TYPE ),
|
||
|
.CLOCKING_MODE (COMMON_CLOCK ? 0 : 1 ),
|
||
|
.ECC_MODE (ENABLE_ECC ),
|
||
|
.USE_MEM_INIT (0 ),
|
||
|
.MEMORY_INIT_FILE ("none" ),
|
||
|
.MEMORY_INIT_PARAM ("" ),
|
||
|
.WAKEUP_TIME (WAKEUP_TIME ),
|
||
|
.MESSAGE_CONTROL (0 ),
|
||
|
.VERSION (0 ),
|
||
|
.MEMORY_OPTIMIZATION ("true" ),
|
||
|
.AUTO_SLEEP_TIME (0 ),
|
||
|
.USE_EMBEDDED_CONSTRAINT (USE_DRAM_CONSTRAINT ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
|
||
|
// Port A module parameters
|
||
|
.WRITE_DATA_WIDTH_A (WRITE_DATA_WIDTH ),
|
||
|
.READ_DATA_WIDTH_A (WRITE_DATA_WIDTH ),
|
||
|
.BYTE_WRITE_WIDTH_A (WRITE_DATA_WIDTH ),
|
||
|
.ADDR_WIDTH_A (WR_PNTR_WIDTH ),
|
||
|
.READ_RESET_VALUE_A ("0" ),
|
||
|
.READ_LATENCY_A (2 ),
|
||
|
.WRITE_MODE_A (2 ),
|
||
|
|
||
|
// Port B module parameters
|
||
|
.WRITE_DATA_WIDTH_B (READ_DATA_WIDTH ),
|
||
|
.READ_DATA_WIDTH_B (READ_DATA_WIDTH ),
|
||
|
.BYTE_WRITE_WIDTH_B (READ_DATA_WIDTH ),
|
||
|
.ADDR_WIDTH_B (RD_PNTR_WIDTH ),
|
||
|
.READ_RESET_VALUE_B (DOUT_RESET_VALUE ),
|
||
|
.READ_LATENCY_B (RD_LATENCY ),
|
||
|
.WRITE_MODE_B (WR_MODE_B )
|
||
|
) xpm_memory_base_inst (
|
||
|
|
||
|
// Common module ports
|
||
|
.sleep (sleep ),
|
||
|
|
||
|
// Port A module ports
|
||
|
.clka (wr_clk ),
|
||
|
.rsta (1'b0 ),
|
||
|
.ena (ram_wr_en_i ),
|
||
|
.regcea (1'b0 ),
|
||
|
.wea (ram_wr_en_i ),
|
||
|
.addra (wr_pntr ),
|
||
|
.dina (din ),
|
||
|
.injectsbiterra (injectsbiterr ),
|
||
|
.injectdbiterra (injectdbiterr ),
|
||
|
.douta ( ),
|
||
|
.sbiterra ( ),
|
||
|
.dbiterra ( ),
|
||
|
|
||
|
// Port B module ports
|
||
|
.clkb (rd_clk ),
|
||
|
.rstb (rst_int ),
|
||
|
.enb (ram_rd_en_i ),
|
||
|
.regceb (READ_MODE == 0 ? ram_regce_pipe: ram_regce),
|
||
|
.web (1'b0 ),
|
||
|
.addrb (rd_pntr ),
|
||
|
.dinb ({READ_DATA_WIDTH{1'b0}} ),
|
||
|
.injectsbiterrb (1'b0 ),
|
||
|
.injectdbiterrb (1'b0 ),
|
||
|
.doutb (dout_i ),
|
||
|
.sbiterrb (sbiterr ),
|
||
|
.dbiterrb (dbiterr )
|
||
|
);
|
||
|
end : gen_sdpram
|
||
|
|
||
|
if (WR_PNTR_WIDTH == RD_PNTR_WIDTH) begin : wrp_eq_rdp
|
||
|
assign wr_pntr_rd_adj = wr_pntr_rd[WR_PNTR_WIDTH-1:WR_PNTR_WIDTH-RD_PNTR_WIDTH];
|
||
|
assign wr_pntr_rd_adj_dc = wr_pntr_rd_dc[WR_PNTR_WIDTH:WR_PNTR_WIDTH-RD_PNTR_WIDTH];
|
||
|
assign rd_pntr_wr_adj = rd_pntr_wr[RD_PNTR_WIDTH-1:RD_PNTR_WIDTH-WR_PNTR_WIDTH];
|
||
|
assign rd_pntr_wr_adj_dc = rd_pntr_wr_dc[RD_PNTR_WIDTH:RD_PNTR_WIDTH-WR_PNTR_WIDTH];
|
||
|
end : wrp_eq_rdp
|
||
|
|
||
|
if (WR_PNTR_WIDTH > RD_PNTR_WIDTH) begin : wrp_gt_rdp
|
||
|
assign wr_pntr_rd_adj = wr_pntr_rd[WR_PNTR_WIDTH-1:WR_PNTR_WIDTH-RD_PNTR_WIDTH];
|
||
|
assign wr_pntr_rd_adj_dc = wr_pntr_rd_dc[WR_PNTR_WIDTH:WR_PNTR_WIDTH-RD_PNTR_WIDTH];
|
||
|
assign rd_pntr_wr_adj[WR_PNTR_WIDTH-1:WR_PNTR_WIDTH-RD_PNTR_WIDTH] = rd_pntr_wr;
|
||
|
assign rd_pntr_wr_adj[WR_PNTR_WIDTH-RD_PNTR_WIDTH-1:0] = {(WR_PNTR_WIDTH-RD_PNTR_WIDTH){1'b0}};
|
||
|
assign rd_pntr_wr_adj_dc[WR_PNTR_WIDTH:WR_PNTR_WIDTH-RD_PNTR_WIDTH] = rd_pntr_wr_dc;
|
||
|
assign rd_pntr_wr_adj_dc[WR_PNTR_WIDTH-RD_PNTR_WIDTH-1:0] = {(WR_PNTR_WIDTH-RD_PNTR_WIDTH){1'b0}};
|
||
|
end : wrp_gt_rdp
|
||
|
|
||
|
if (WR_PNTR_WIDTH < RD_PNTR_WIDTH) begin : wrp_lt_rdp
|
||
|
assign wr_pntr_rd_adj[RD_PNTR_WIDTH-1:RD_PNTR_WIDTH-WR_PNTR_WIDTH] = wr_pntr_rd;
|
||
|
assign wr_pntr_rd_adj[RD_PNTR_WIDTH-WR_PNTR_WIDTH-1:0] = {(RD_PNTR_WIDTH-WR_PNTR_WIDTH){1'b0}};
|
||
|
assign wr_pntr_rd_adj_dc[RD_PNTR_WIDTH:RD_PNTR_WIDTH-WR_PNTR_WIDTH] = wr_pntr_rd_dc;
|
||
|
assign wr_pntr_rd_adj_dc[RD_PNTR_WIDTH-WR_PNTR_WIDTH-1:0] = {(RD_PNTR_WIDTH-WR_PNTR_WIDTH){1'b0}};
|
||
|
assign rd_pntr_wr_adj = rd_pntr_wr[RD_PNTR_WIDTH-1:RD_PNTR_WIDTH-WR_PNTR_WIDTH];
|
||
|
assign rd_pntr_wr_adj_dc = rd_pntr_wr_dc[RD_PNTR_WIDTH:RD_PNTR_WIDTH-WR_PNTR_WIDTH];
|
||
|
end : wrp_lt_rdp
|
||
|
|
||
|
if (COMMON_CLOCK == 0 && RELATED_CLOCKS == 0) begin : gen_cdc_pntr
|
||
|
// Synchronize the write pointer in rd_clk domain
|
||
|
xpm_cdc_gray #(
|
||
|
.DEST_SYNC_FF (CDC_DEST_SYNC_FF),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.WIDTH (WR_PNTR_WIDTH))
|
||
|
|
||
|
wr_pntr_cdc_inst (
|
||
|
.src_clk (wr_clk),
|
||
|
.src_in_bin (wr_pntr),
|
||
|
.dest_clk (rd_clk),
|
||
|
.dest_out_bin (wr_pntr_rd_cdc));
|
||
|
|
||
|
// Register the output of XPM_CDC_GRAY on read side
|
||
|
xpm_fifo_reg_vec #(WR_PNTR_WIDTH)
|
||
|
wpr_gray_reg (rd_rst_i, rd_clk, wr_pntr_rd_cdc, wr_pntr_rd);
|
||
|
|
||
|
// Synchronize the extended write pointer in rd_clk domain
|
||
|
xpm_cdc_gray #(
|
||
|
.DEST_SYNC_FF (READ_MODE == 0 ? CDC_DEST_SYNC_FF : CDC_DEST_SYNC_FF+2),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.WIDTH (WR_PNTR_WIDTH+1))
|
||
|
wr_pntr_cdc_dc_inst (
|
||
|
.src_clk (wr_clk),
|
||
|
.src_in_bin (wr_pntr_ext),
|
||
|
.dest_clk (rd_clk),
|
||
|
.dest_out_bin (wr_pntr_rd_cdc_dc));
|
||
|
|
||
|
// Register the output of XPM_CDC_GRAY on read side
|
||
|
xpm_fifo_reg_vec #(WR_PNTR_WIDTH+1)
|
||
|
wpr_gray_reg_dc (rd_rst_i, rd_clk, wr_pntr_rd_cdc_dc, wr_pntr_rd_dc);
|
||
|
|
||
|
// Synchronize the read pointer in wr_clk domain
|
||
|
xpm_cdc_gray #(
|
||
|
.DEST_SYNC_FF (CDC_DEST_SYNC_FF),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.WIDTH (RD_PNTR_WIDTH))
|
||
|
rd_pntr_cdc_inst (
|
||
|
.src_clk (rd_clk),
|
||
|
.src_in_bin (rd_pntr),
|
||
|
.dest_clk (wr_clk),
|
||
|
.dest_out_bin (rd_pntr_wr_cdc));
|
||
|
|
||
|
// Register the output of XPM_CDC_GRAY on write side
|
||
|
xpm_fifo_reg_vec #(RD_PNTR_WIDTH)
|
||
|
rpw_gray_reg (wrst_busy, wr_clk, rd_pntr_wr_cdc, rd_pntr_wr);
|
||
|
|
||
|
// Synchronize the read pointer, subtracted by the extra word read for FWFT, in wr_clk domain
|
||
|
xpm_cdc_gray #(
|
||
|
.DEST_SYNC_FF (CDC_DEST_SYNC_FF),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.WIDTH (RD_PNTR_WIDTH+1))
|
||
|
rd_pntr_cdc_dc_inst (
|
||
|
.src_clk (rd_clk),
|
||
|
.src_in_bin (rd_pntr_ext-extra_words_fwft),
|
||
|
.dest_clk (wr_clk),
|
||
|
.dest_out_bin (rd_pntr_wr_cdc_dc));
|
||
|
|
||
|
// Register the output of XPM_CDC_GRAY on write side
|
||
|
xpm_fifo_reg_vec #(RD_PNTR_WIDTH+1)
|
||
|
rpw_gray_reg_dc (wrst_busy, wr_clk, rd_pntr_wr_cdc_dc, rd_pntr_wr_dc);
|
||
|
|
||
|
end : gen_cdc_pntr
|
||
|
|
||
|
if (RELATED_CLOCKS == 1) begin : gen_pntr_pf_rc
|
||
|
xpm_fifo_reg_vec #(RD_PNTR_WIDTH)
|
||
|
rpw_rc_reg (wrst_busy, wr_clk, rd_pntr, rd_pntr_wr);
|
||
|
|
||
|
xpm_fifo_reg_vec #(WR_PNTR_WIDTH)
|
||
|
wpr_rc_reg (rd_rst_i, rd_clk, wr_pntr, wr_pntr_rd);
|
||
|
|
||
|
xpm_fifo_reg_vec #(WR_PNTR_WIDTH+1)
|
||
|
wpr_rc_reg_dc (rd_rst_i, rd_clk, wr_pntr_ext, wr_pntr_rd_dc);
|
||
|
|
||
|
xpm_fifo_reg_vec #(RD_PNTR_WIDTH+1)
|
||
|
rpw_rc_reg_dc (wrst_busy, wr_clk, (rd_pntr_ext-extra_words_fwft), rd_pntr_wr_dc);
|
||
|
end : gen_pntr_pf_rc
|
||
|
|
||
|
if (COMMON_CLOCK == 0 || RELATED_CLOCKS == 1) begin : gen_pf_ic_rc
|
||
|
|
||
|
assign going_empty = ((wr_pntr_rd_adj == rd_pntr_plus1) & ram_rd_en_i);
|
||
|
assign leaving_empty = ((wr_pntr_rd_adj == rd_pntr));
|
||
|
assign going_aempty = ((wr_pntr_rd_adj == rd_pntr_plus2) & ram_rd_en_i);
|
||
|
assign leaving_aempty = ((wr_pntr_rd_adj == rd_pntr_plus1));
|
||
|
|
||
|
assign going_full = ((rd_pntr_wr_adj == wr_pntr_plus2) & ram_wr_en_i);
|
||
|
assign leaving_full = ((rd_pntr_wr_adj == wr_pntr_plus1));
|
||
|
assign going_afull = ((rd_pntr_wr_adj == wr_pntr_plus3) & ram_wr_en_i);
|
||
|
assign leaving_afull = ((rd_pntr_wr_adj == wr_pntr_plus2));
|
||
|
|
||
|
// Empty flag generation
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
ram_empty_i <= 1'b1;
|
||
|
end else begin
|
||
|
ram_empty_i <= going_empty | leaving_empty;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if (EN_AE == 1) begin : gae_ic_std
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
ram_aempty_i <= 1'b1;
|
||
|
end else if (~ram_empty_i) begin
|
||
|
ram_aempty_i <= going_aempty | leaving_aempty;
|
||
|
end
|
||
|
end
|
||
|
end : gae_ic_std
|
||
|
|
||
|
// Full flag generation
|
||
|
if (FULL_RST_VAL == 1) begin : gen_full_rst_val
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_full_i <= FULL_RST_VAL;
|
||
|
ram_full_n <= ~FULL_RST_VAL;
|
||
|
end else begin
|
||
|
if (clr_full) begin
|
||
|
ram_full_i <= 1'b0;
|
||
|
ram_full_n <= 1'b1;
|
||
|
end else begin
|
||
|
ram_full_i <= going_full | leaving_full;
|
||
|
ram_full_n <= ~(going_full | leaving_full);
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end : gen_full_rst_val
|
||
|
else begin : ngen_full_rst_val
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_full_i <= 1'b0;
|
||
|
ram_full_n <= 1'b1;
|
||
|
end else begin
|
||
|
ram_full_i <= going_full | leaving_full;
|
||
|
ram_full_n <= ~(going_full | leaving_full);
|
||
|
end
|
||
|
end
|
||
|
end : ngen_full_rst_val
|
||
|
|
||
|
if (EN_AF == 1) begin : gaf_ic
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_afull_i <= FULL_RST_VAL;
|
||
|
end else if (~rst) begin
|
||
|
if (clr_full) begin
|
||
|
ram_afull_i <= 1'b0;
|
||
|
end else if (~ram_full_i) begin
|
||
|
ram_afull_i <= going_afull | leaving_afull;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end : gaf_ic
|
||
|
|
||
|
// synthesis translate_off
|
||
|
`ifndef DISABLE_XPM_ASSERTIONS
|
||
|
if (SIM_ASSERT_CHK == 1) begin: assert_wr_rd_en
|
||
|
always @ (posedge rd_clk) begin
|
||
|
assert (!$isunknown(rd_en)) else $warning ("Input port 'rd_en' has unknown value 'X' or 'Z' at %0t. This may cause full/empty to be 'X' or 'Z' in simulation. Ensure 'rd_en' has a valid value ('0' or '1')",$time);
|
||
|
end
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
assert (!$isunknown(wr_en)) else $warning ("Input port 'wr_en' has unknown value 'X' or 'Z' at %0t. This may cause full/empty to be 'X' or 'Z' in simulation. Ensure 'wr_en' has a valid value ('0' or '1')",$time);
|
||
|
end
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
assert (!$isunknown(wr_en)) else $warning ("Input port 'wr_en' has unknown value 'X' or 'Z' at %0t. This may cause full/empty to be 'X' or 'Z' in simulation. Ensure 'wr_en' has a valid value ('0' or '1')",$time);
|
||
|
end
|
||
|
|
||
|
end : assert_wr_rd_en
|
||
|
`endif
|
||
|
// synthesis translate_on
|
||
|
|
||
|
// Programmable Full flag generation
|
||
|
if (EN_PF == 1) begin : gpf_ic
|
||
|
assign wr_pntr_plus1_pf = {wr_pntr_plus1,wr_pntr_plus1_pf_carry};
|
||
|
assign rd_pntr_wr_adj_inv_pf = {~rd_pntr_wr_adj,rd_pntr_wr_adj_pf_carry};
|
||
|
|
||
|
// PF carry generation
|
||
|
assign wr_pntr_plus1_pf_carry = ram_wr_en_i;
|
||
|
assign rd_pntr_wr_adj_pf_carry = ram_wr_en_i;
|
||
|
|
||
|
// PF diff pointer generation
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
diff_pntr_pf_q <= {WR_PNTR_WIDTH{1'b0}};
|
||
|
else
|
||
|
diff_pntr_pf_q <= wr_pntr_plus1_pf + rd_pntr_wr_adj_inv_pf;
|
||
|
end
|
||
|
assign diff_pntr_pf = diff_pntr_pf_q[WR_PNTR_WIDTH:1];
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
prog_full_i <= FULL_RST_VAL;
|
||
|
else if (clr_full)
|
||
|
prog_full_i <= 1'b0;
|
||
|
else if (~ram_full_i) begin
|
||
|
if (diff_pntr_pf >= PF_THRESH_ADJ)
|
||
|
prog_full_i <= 1'b1;
|
||
|
else
|
||
|
prog_full_i <= 1'b0;
|
||
|
end else
|
||
|
prog_full_i <= prog_full_i;
|
||
|
end
|
||
|
end : gpf_ic
|
||
|
|
||
|
/*********************************************************
|
||
|
* Programmable EMPTY flags
|
||
|
*********************************************************/
|
||
|
//Determine the Assert and Negate thresholds for Programmable Empty
|
||
|
if (EN_PE == 1) begin : gpe_ic
|
||
|
|
||
|
always @(posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
diff_pntr_pe <= 0;
|
||
|
prog_empty_i <= 1'b1;
|
||
|
end else begin
|
||
|
if (ram_rd_en_i)
|
||
|
diff_pntr_pe <= (wr_pntr_rd_adj - rd_pntr) - 1'h1;
|
||
|
else
|
||
|
diff_pntr_pe <= (wr_pntr_rd_adj - rd_pntr);
|
||
|
|
||
|
if (~empty_i) begin
|
||
|
if (diff_pntr_pe <= PE_THRESH_ADJ)
|
||
|
prog_empty_i <= 1'b1;
|
||
|
else
|
||
|
prog_empty_i <= 1'b0;
|
||
|
end else
|
||
|
prog_empty_i <= prog_empty_i;
|
||
|
end
|
||
|
end
|
||
|
end : gpe_ic
|
||
|
end : gen_pf_ic_rc
|
||
|
|
||
|
if (COMMON_CLOCK == 1 && RELATED_CLOCKS == 0) begin : gen_pntr_flags_cc
|
||
|
assign wr_pntr_rd = wr_pntr;
|
||
|
assign rd_pntr_wr = rd_pntr;
|
||
|
assign wr_pntr_rd_dc = wr_pntr_ext;
|
||
|
assign rd_pntr_wr_dc = rd_pntr_ext-extra_words_fwft;
|
||
|
assign write_allow = ram_wr_en_i & ~ram_full_i;
|
||
|
assign read_allow = ram_rd_en_i & ~empty_i;
|
||
|
|
||
|
if (WR_PNTR_WIDTH == RD_PNTR_WIDTH) begin : wrp_eq_rdp
|
||
|
assign ram_wr_en_pf = ram_wr_en_i;
|
||
|
assign ram_rd_en_pf = ram_rd_en_i;
|
||
|
|
||
|
assign going_empty = ((wr_pntr_rd_adj == rd_pntr_plus1) & ~ram_wr_en_i & ram_rd_en_i);
|
||
|
assign leaving_empty = ((wr_pntr_rd_adj == rd_pntr) & ram_wr_en_i);
|
||
|
assign going_aempty = ((wr_pntr_rd_adj == rd_pntr_plus2) & ~ram_wr_en_i & ram_rd_en_i);
|
||
|
assign leaving_aempty = ((wr_pntr_rd_adj == rd_pntr_plus1) & ram_wr_en_i & ~ram_rd_en_i);
|
||
|
|
||
|
assign going_full = ((rd_pntr_wr_adj == wr_pntr_plus1) & ram_wr_en_i & ~ram_rd_en_i);
|
||
|
assign leaving_full = ((rd_pntr_wr_adj == wr_pntr) & ram_rd_en_i);
|
||
|
assign going_afull = ((rd_pntr_wr_adj == wr_pntr_plus2) & ram_wr_en_i & ~ram_rd_en_i);
|
||
|
assign leaving_afull = ((rd_pntr_wr_adj == wr_pntr_plus1) & ram_rd_en_i & ~ram_wr_en_i);
|
||
|
|
||
|
assign write_only = write_allow & ~read_allow;
|
||
|
assign read_only = read_allow & ~write_allow;
|
||
|
|
||
|
end : wrp_eq_rdp
|
||
|
|
||
|
if (WR_PNTR_WIDTH > RD_PNTR_WIDTH) begin : wrp_gt_rdp
|
||
|
assign wrp_gt_rdp_and_red = &wr_pntr_rd[WR_PNTR_WIDTH-RD_PNTR_WIDTH-1:0];
|
||
|
|
||
|
assign going_empty = ((wr_pntr_rd_adj == rd_pntr_plus1) & ~(ram_wr_en_i & wrp_gt_rdp_and_red) & ram_rd_en_i);
|
||
|
assign leaving_empty = ((wr_pntr_rd_adj == rd_pntr) & (ram_wr_en_i & wrp_gt_rdp_and_red));
|
||
|
assign going_aempty = ((wr_pntr_rd_adj == rd_pntr_plus2) & ~(ram_wr_en_i & wrp_gt_rdp_and_red) & ram_rd_en_i);
|
||
|
assign leaving_aempty = ((wr_pntr_rd_adj == rd_pntr_plus1) & (ram_wr_en_i & wrp_gt_rdp_and_red) & ~ram_rd_en_i);
|
||
|
|
||
|
assign going_full = ((rd_pntr_wr_adj == wr_pntr_plus1) & ram_wr_en_i & ~ram_rd_en_i);
|
||
|
assign leaving_full = ((rd_pntr_wr_adj == wr_pntr) & ram_rd_en_i);
|
||
|
assign going_afull = ((rd_pntr_wr_adj == wr_pntr_plus2) & ram_wr_en_i & ~ram_rd_en_i);
|
||
|
assign leaving_afull = (((rd_pntr_wr_adj == wr_pntr) | (rd_pntr_wr_adj == wr_pntr_plus1) | (rd_pntr_wr_adj == wr_pntr_plus2)) & ram_rd_en_i);
|
||
|
|
||
|
assign ram_wr_en_pf = ram_wr_en_i & wrp_gt_rdp_and_red;
|
||
|
assign ram_rd_en_pf = ram_rd_en_i;
|
||
|
|
||
|
assign read_only = read_allow & (~(write_allow & (&wr_pntr[WR_PNTR_WIDTH-RD_PNTR_WIDTH-1 : 0])));
|
||
|
assign write_only = write_allow & (&wr_pntr[WR_PNTR_WIDTH-RD_PNTR_WIDTH-1 : 0]) & ~read_allow;
|
||
|
|
||
|
|
||
|
end : wrp_gt_rdp
|
||
|
|
||
|
if (WR_PNTR_WIDTH < RD_PNTR_WIDTH) begin : wrp_lt_rdp
|
||
|
assign wrp_lt_rdp_and_red = &rd_pntr_wr[RD_PNTR_WIDTH-WR_PNTR_WIDTH-1:0];
|
||
|
|
||
|
assign going_empty = ((wr_pntr_rd_adj == rd_pntr_plus1) & ~ram_wr_en_i & ram_rd_en_i);
|
||
|
assign leaving_empty = ((wr_pntr_rd_adj == rd_pntr) & ram_wr_en_i);
|
||
|
assign going_aempty = ((wr_pntr_rd_adj == rd_pntr_plus2) & ~ram_wr_en_i & ram_rd_en_i);
|
||
|
assign leaving_aempty = (((wr_pntr_rd_adj == rd_pntr) | (wr_pntr_rd_adj == rd_pntr_plus1) | (wr_pntr_rd_adj == rd_pntr_plus2)) & ram_wr_en_i);
|
||
|
|
||
|
assign going_full = ((rd_pntr_wr_adj == wr_pntr_plus1) & ~(ram_rd_en_i & wrp_lt_rdp_and_red) & ram_wr_en_i);
|
||
|
assign leaving_full = ((rd_pntr_wr_adj == wr_pntr) & (ram_rd_en_i & wrp_lt_rdp_and_red));
|
||
|
assign going_afull = ((rd_pntr_wr_adj == wr_pntr_plus2) & ~(ram_rd_en_i & wrp_lt_rdp_and_red) & ram_wr_en_i);
|
||
|
assign leaving_afull = ((rd_pntr_wr_adj == wr_pntr_plus1) & ~ram_wr_en_i & (ram_rd_en_i & wrp_lt_rdp_and_red));
|
||
|
|
||
|
assign ram_wr_en_pf = ram_wr_en_i;
|
||
|
assign ram_rd_en_pf = ram_rd_en_i & wrp_lt_rdp_and_red;
|
||
|
|
||
|
assign read_only = read_allow & (&rd_pntr[RD_PNTR_WIDTH-WR_PNTR_WIDTH-1 : 0]) & ~write_allow;
|
||
|
assign write_only = write_allow & (~(read_allow & (&rd_pntr[RD_PNTR_WIDTH-WR_PNTR_WIDTH-1 : 0])));
|
||
|
end : wrp_lt_rdp
|
||
|
|
||
|
// Empty flag generation
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
ram_empty_i <= 1'b1;
|
||
|
end else begin
|
||
|
ram_empty_i <= going_empty | (~leaving_empty & ram_empty_i);
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if (EN_AE == 1) begin : gae_cc_std
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
ram_aempty_i <= 1'b1;
|
||
|
end else begin
|
||
|
ram_aempty_i <= going_aempty | (~leaving_aempty & ram_aempty_i);
|
||
|
end
|
||
|
end
|
||
|
end : gae_cc_std
|
||
|
|
||
|
// Full flag generation
|
||
|
if (FULL_RST_VAL == 1) begin : gen_full_rst_val
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_full_i <= FULL_RST_VAL;
|
||
|
ram_full_n <= ~FULL_RST_VAL;
|
||
|
end else begin
|
||
|
if (clr_full) begin
|
||
|
ram_full_i <= 1'b0;
|
||
|
ram_full_n <= 1'b1;
|
||
|
end else begin
|
||
|
ram_full_i <= going_full | (~leaving_full & ram_full_i);
|
||
|
ram_full_n <= ~(going_full | (~leaving_full & ram_full_i));
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end : gen_full_rst_val
|
||
|
else begin : ngen_full_rst_val
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_full_i <= 1'b0;
|
||
|
ram_full_n <= 1'b1;
|
||
|
end else begin
|
||
|
ram_full_i <= going_full | (~leaving_full & ram_full_i);
|
||
|
ram_full_n <= ~(going_full | (~leaving_full & ram_full_i));
|
||
|
end
|
||
|
end
|
||
|
end : ngen_full_rst_val
|
||
|
|
||
|
if (EN_AF == 1) begin : gaf_cc
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_afull_i <= FULL_RST_VAL;
|
||
|
end else if (~rst) begin
|
||
|
if (clr_full) begin
|
||
|
ram_afull_i <= 1'b0;
|
||
|
end else begin
|
||
|
ram_afull_i <= going_afull | (~leaving_afull & ram_afull_i);
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end : gaf_cc
|
||
|
// Programmable Full flag generation
|
||
|
if ((WR_PNTR_WIDTH == RD_PNTR_WIDTH) && (RELATED_CLOCKS == 0)) begin : wrp_eq_rdp_pf_cc
|
||
|
if (EN_PF == 1) begin : gpf_cc_sym
|
||
|
|
||
|
assign wr_pntr_plus1_pf = {wr_pntr_plus1,wr_pntr_plus1_pf_carry};
|
||
|
assign rd_pntr_wr_adj_inv_pf = {~rd_pntr_wr_adj,rd_pntr_wr_adj_pf_carry};
|
||
|
|
||
|
// Delayed write/read enable for PF generation
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy) begin
|
||
|
ram_wr_en_pf_q <= 1'b0;
|
||
|
ram_rd_en_pf_q <= 1'b0;
|
||
|
end else begin
|
||
|
ram_wr_en_pf_q <= ram_wr_en_pf;
|
||
|
ram_rd_en_pf_q <= ram_rd_en_pf;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
// PF carry generation
|
||
|
assign wr_pntr_plus1_pf_carry = ram_wr_en_i & ~ram_rd_en_pf;
|
||
|
assign rd_pntr_wr_adj_pf_carry = ram_wr_en_i & ~ram_rd_en_pf;
|
||
|
|
||
|
// PF diff pointer generation
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
diff_pntr_pf_q <= {WR_PNTR_WIDTH{1'b0}};
|
||
|
else
|
||
|
diff_pntr_pf_q <= wr_pntr_plus1_pf + rd_pntr_wr_adj_inv_pf;
|
||
|
end
|
||
|
assign diff_pntr_pf = diff_pntr_pf_q[WR_PNTR_WIDTH:1];
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
prog_full_i <= FULL_RST_VAL;
|
||
|
else if (clr_full)
|
||
|
prog_full_i <= 1'b0;
|
||
|
else if ((diff_pntr_pf == PF_THRESH_ADJ) & ram_wr_en_pf_q & ~ram_rd_en_pf_q)
|
||
|
prog_full_i <= 1'b1;
|
||
|
else if ((diff_pntr_pf == PF_THRESH_ADJ) & ~ram_wr_en_pf_q & ram_rd_en_pf_q)
|
||
|
prog_full_i <= 1'b0;
|
||
|
else
|
||
|
prog_full_i <= prog_full_i;
|
||
|
end
|
||
|
end : gpf_cc_sym
|
||
|
|
||
|
if (EN_PE == 1) begin : gpe_cc_sym
|
||
|
always @(posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
read_only_q <= 1'b0;
|
||
|
write_only_q <= 1'b0;
|
||
|
diff_pntr_pe <= 0;
|
||
|
end
|
||
|
else begin
|
||
|
read_only_q <= read_only;
|
||
|
write_only_q <= write_only;
|
||
|
// Add 1 to the difference pointer value when write or both write & read or no write & read happen.
|
||
|
if (read_only)
|
||
|
diff_pntr_pe <= wr_pntr_rd_adj - rd_pntr - 1;
|
||
|
else
|
||
|
diff_pntr_pe <= wr_pntr_rd_adj - rd_pntr;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @(posedge rd_clk) begin
|
||
|
if (rd_rst_i)
|
||
|
prog_empty_i <= 1'b1;
|
||
|
else begin
|
||
|
if (diff_pntr_pe == PE_THRESH_ADJ && read_only_q)
|
||
|
prog_empty_i <= 1'b1;
|
||
|
else if (diff_pntr_pe == PE_THRESH_ADJ && write_only_q)
|
||
|
prog_empty_i <= 1'b0;
|
||
|
else
|
||
|
prog_empty_i <= prog_empty_i;
|
||
|
end
|
||
|
end
|
||
|
end : gpe_cc_sym
|
||
|
end : wrp_eq_rdp_pf_cc
|
||
|
|
||
|
if ((WR_PNTR_WIDTH != RD_PNTR_WIDTH) && (RELATED_CLOCKS == 0)) begin : wrp_neq_rdp_pf_cc
|
||
|
if (EN_PF == 1) begin : gpf_cc_asym
|
||
|
// PF diff pointer generation
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
diff_pntr_pf_q <= {WR_PNTR_WIDTH{1'b0}};
|
||
|
else if (~ram_full_i)
|
||
|
diff_pntr_pf_q[WR_PNTR_WIDTH:1] <= wr_pntr + ~rd_pntr_wr_adj + 1;
|
||
|
end
|
||
|
assign diff_pntr_pf = diff_pntr_pf_q[WR_PNTR_WIDTH:1];
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
prog_full_i <= FULL_RST_VAL;
|
||
|
else if (clr_full)
|
||
|
prog_full_i <= 1'b0;
|
||
|
else if (~ram_full_i) begin
|
||
|
if (diff_pntr_pf >= PF_THRESH_ADJ)
|
||
|
prog_full_i <= 1'b1;
|
||
|
else if (diff_pntr_pf < PF_THRESH_ADJ)
|
||
|
prog_full_i <= 1'b0;
|
||
|
else
|
||
|
prog_full_i <= prog_full_i;
|
||
|
end
|
||
|
end
|
||
|
end : gpf_cc_asym
|
||
|
if (EN_PE == 1) begin : gpe_cc_asym
|
||
|
// Programmanble Empty flag Generation
|
||
|
// Diff pointer Generation
|
||
|
localparam [RD_PNTR_WIDTH-1 : 0] DIFF_MAX_RD = {RD_PNTR_WIDTH{1'b1}};
|
||
|
wire [RD_PNTR_WIDTH-1:0] diff_pntr_pe_max;
|
||
|
wire carry;
|
||
|
reg [RD_PNTR_WIDTH : 0] diff_pntr_pe_asym = 'b0;
|
||
|
wire [RD_PNTR_WIDTH : 0] wr_pntr_rd_adj_asym;
|
||
|
wire [RD_PNTR_WIDTH : 0] rd_pntr_asym;
|
||
|
reg full_reg;
|
||
|
reg rst_full_ff_reg1;
|
||
|
reg rst_full_ff_reg2;
|
||
|
|
||
|
assign diff_pntr_pe_max = DIFF_MAX_RD;
|
||
|
assign wr_pntr_rd_adj_asym[RD_PNTR_WIDTH:0] = {wr_pntr_rd_adj,1'b1};
|
||
|
assign rd_pntr_asym[RD_PNTR_WIDTH:0] = {~rd_pntr,1'b1};
|
||
|
|
||
|
always @(posedge rd_clk ) begin
|
||
|
if (rd_rst_i) begin
|
||
|
diff_pntr_pe_asym <= 0;
|
||
|
full_reg <= 0;
|
||
|
rst_full_ff_reg1 <= 1;
|
||
|
rst_full_ff_reg2 <= 1;
|
||
|
diff_pntr_pe_reg1 <= 0;
|
||
|
end else begin
|
||
|
diff_pntr_pe_asym <= wr_pntr_rd_adj_asym + rd_pntr_asym;
|
||
|
full_reg <= ram_full_i;
|
||
|
rst_full_ff_reg1 <= FULL_RST_VAL;
|
||
|
rst_full_ff_reg2 <= rst_full_ff_reg1;
|
||
|
end
|
||
|
end
|
||
|
wire [RD_PNTR_WIDTH-1:0] diff_pntr_pe_i;
|
||
|
assign carry = (~(|(diff_pntr_pe_asym [RD_PNTR_WIDTH : 1])));
|
||
|
assign diff_pntr_pe_i = (full_reg && ~rst_d2 && carry ) ? diff_pntr_pe_max : diff_pntr_pe_asym[RD_PNTR_WIDTH:1];
|
||
|
|
||
|
always @(posedge rd_clk) begin
|
||
|
if (rd_rst_i)
|
||
|
prog_empty_i <= 1'b1;
|
||
|
else begin
|
||
|
if (diff_pntr_pe_i <= PE_THRESH_ADJ)
|
||
|
prog_empty_i <= 1'b1;
|
||
|
else if (diff_pntr_pe_i > PE_THRESH_ADJ)
|
||
|
prog_empty_i <= 1'b0;
|
||
|
else
|
||
|
prog_empty_i <= prog_empty_i;
|
||
|
end
|
||
|
end
|
||
|
end : gpe_cc_asym
|
||
|
end : wrp_neq_rdp_pf_cc
|
||
|
|
||
|
end : gen_pntr_flags_cc
|
||
|
|
||
|
if (READ_MODE == 0 && FIFO_READ_LATENCY > 1) begin : gen_regce_std
|
||
|
xpm_reg_pipe_bit #(FIFO_READ_LATENCY-1, 0)
|
||
|
regce_pipe_inst (rd_rst_i, rd_clk, ram_rd_en_i, ram_regce_pipe);
|
||
|
end : gen_regce_std
|
||
|
if (!(READ_MODE == 0 && FIFO_READ_LATENCY > 1)) begin : gnen_regce_std
|
||
|
assign ram_regce_pipe = 1'b0;
|
||
|
end : gnen_regce_std
|
||
|
|
||
|
if (!((READ_MODE == 1 || READ_MODE == 2)&& FIFO_MEMORY_TYPE != 4)) begin : gn_fwft
|
||
|
assign invalid_state = 1'b0;
|
||
|
end : gn_fwft
|
||
|
//if (READ_MODE == 1 && FIFO_MEMORY_TYPE != 4) begin : gen_fwft
|
||
|
if (READ_MODE != 0 && FIFO_MEMORY_TYPE != 4) begin : gen_fwft
|
||
|
// First word fall through logic
|
||
|
|
||
|
//localparam invalid = 0;
|
||
|
//localparam stage1_valid = 2;
|
||
|
//localparam stage2_valid = 1;
|
||
|
//localparam both_stages_valid = 3;
|
||
|
|
||
|
//reg [1:0] curr_fwft_state = invalid;
|
||
|
//reg [1:0] next_fwft_state;// = invalid;
|
||
|
wire next_fwft_state_d1;
|
||
|
assign invalid_state = ~|curr_fwft_state;
|
||
|
assign valid_fwft = next_fwft_state_d1;
|
||
|
assign ram_valid_fwft = curr_fwft_state[1];
|
||
|
|
||
|
xpm_fifo_reg_bit #(0)
|
||
|
next_state_d1_inst (1'b0, rd_clk, next_fwft_state[0], next_fwft_state_d1);
|
||
|
//FSM : To generate the enable, clock enable for xpm_memory and to generate
|
||
|
//empty signal
|
||
|
//FSM : Next state Assignment
|
||
|
if (READ_MODE == 1) begin : gen_fwft_ns
|
||
|
always @(curr_fwft_state or ram_empty_i or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid: begin
|
||
|
if (~ram_empty_i)
|
||
|
next_fwft_state = stage1_valid;
|
||
|
else
|
||
|
next_fwft_state = invalid;
|
||
|
end
|
||
|
stage1_valid: begin
|
||
|
if (ram_empty_i)
|
||
|
next_fwft_state = stage2_valid;
|
||
|
else
|
||
|
next_fwft_state = both_stages_valid;
|
||
|
end
|
||
|
stage2_valid: begin
|
||
|
if (ram_empty_i && rd_en)
|
||
|
next_fwft_state = invalid;
|
||
|
else if (~ram_empty_i && rd_en)
|
||
|
next_fwft_state = stage1_valid;
|
||
|
else if (~ram_empty_i && ~rd_en)
|
||
|
next_fwft_state = both_stages_valid;
|
||
|
else
|
||
|
next_fwft_state = stage2_valid;
|
||
|
end
|
||
|
both_stages_valid: begin
|
||
|
if (ram_empty_i && rd_en)
|
||
|
next_fwft_state = stage2_valid;
|
||
|
else if (~ram_empty_i && rd_en)
|
||
|
next_fwft_state = both_stages_valid;
|
||
|
else
|
||
|
next_fwft_state = both_stages_valid;
|
||
|
end
|
||
|
default: next_fwft_state = invalid;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ns
|
||
|
if (READ_MODE == 2) begin : gen_fwft_ns_ll
|
||
|
always @(curr_fwft_state or ram_empty_i or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid: begin
|
||
|
if (~ram_empty_i)
|
||
|
next_fwft_state = stage1_valid;
|
||
|
else
|
||
|
next_fwft_state = invalid;
|
||
|
end
|
||
|
stage1_valid: begin
|
||
|
if (ram_empty_i && rd_en)
|
||
|
next_fwft_state = invalid;
|
||
|
else
|
||
|
next_fwft_state = stage1_valid;
|
||
|
end
|
||
|
default: next_fwft_state = invalid;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ns_ll
|
||
|
// FSM : current state assignment
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i)
|
||
|
curr_fwft_state <= invalid;
|
||
|
else
|
||
|
curr_fwft_state <= next_fwft_state;
|
||
|
end
|
||
|
|
||
|
reg ram_regout_en;
|
||
|
|
||
|
// FSM(output assignments) : clock enable generation for xpm_memory
|
||
|
if (READ_MODE == 1) begin : gen_fwft_ro
|
||
|
always @(curr_fwft_state or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid: ram_regout_en = 1'b0;
|
||
|
stage1_valid: ram_regout_en = 1'b1;
|
||
|
stage2_valid: ram_regout_en = 1'b0;
|
||
|
both_stages_valid: ram_regout_en = rd_en;
|
||
|
default: ram_regout_en = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ro
|
||
|
if (READ_MODE == 2) begin : gen_fwft_ro_ll
|
||
|
always @(curr_fwft_state or rd_en or ram_empty_i or fe_of_empty) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid: ram_regout_en = fe_of_empty;
|
||
|
stage1_valid: ram_regout_en = rd_en & !ram_empty_i;
|
||
|
default: ram_regout_en = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ro_ll
|
||
|
|
||
|
// FSM(output assignments) : rd_en (enable) signal generation for xpm_memory
|
||
|
if (READ_MODE == 1) begin : gen_fwft_re
|
||
|
always @(curr_fwft_state or ram_empty_i or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid :
|
||
|
if (~ram_empty_i)
|
||
|
rd_en_fwft = 1'b1;
|
||
|
else
|
||
|
rd_en_fwft = 1'b0;
|
||
|
stage1_valid :
|
||
|
if (~ram_empty_i)
|
||
|
rd_en_fwft = 1'b1;
|
||
|
else
|
||
|
rd_en_fwft = 1'b0;
|
||
|
stage2_valid :
|
||
|
if (~ram_empty_i)
|
||
|
rd_en_fwft = 1'b1;
|
||
|
else
|
||
|
rd_en_fwft = 1'b0;
|
||
|
both_stages_valid :
|
||
|
if (~ram_empty_i && rd_en)
|
||
|
rd_en_fwft = 1'b1;
|
||
|
else
|
||
|
rd_en_fwft = 1'b0;
|
||
|
default :
|
||
|
rd_en_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_re
|
||
|
if (READ_MODE == 2) begin : gen_fwft_re_ll
|
||
|
always @(curr_fwft_state or ram_empty_i or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid :
|
||
|
if (~ram_empty_i)
|
||
|
rd_en_fwft = 1'b1;
|
||
|
else
|
||
|
rd_en_fwft = 1'b0;
|
||
|
stage1_valid :
|
||
|
if (~ram_empty_i && rd_en)
|
||
|
rd_en_fwft = 1'b1;
|
||
|
else
|
||
|
rd_en_fwft = 1'b0;
|
||
|
default :
|
||
|
rd_en_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_re_ll
|
||
|
// assingment to control regce xpm_memory
|
||
|
assign ram_regce = ram_regout_en;
|
||
|
|
||
|
reg going_empty_fwft;
|
||
|
reg leaving_empty_fwft;
|
||
|
|
||
|
if (READ_MODE == 1) begin : gen_fwft_ge
|
||
|
always @(curr_fwft_state or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
stage2_valid : going_empty_fwft = rd_en;
|
||
|
default : going_empty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @(curr_fwft_state or rd_en) begin
|
||
|
case (curr_fwft_state)
|
||
|
stage1_valid : leaving_empty_fwft = 1'b1;
|
||
|
default : leaving_empty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ge
|
||
|
if (READ_MODE == 2) begin : gen_fwft_ge_ll
|
||
|
always @(curr_fwft_state or rd_en or ram_empty_i) begin
|
||
|
case (curr_fwft_state)
|
||
|
stage1_valid : going_empty_fwft = rd_en & ram_empty_i;
|
||
|
default : going_empty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
ram_empty_i_d1 <= 1'b1;
|
||
|
end else begin
|
||
|
ram_empty_i_d1 <= ram_empty_i;
|
||
|
end
|
||
|
end
|
||
|
assign fe_of_empty = ram_empty_i_d1 & !ram_empty_i;
|
||
|
|
||
|
always @(curr_fwft_state or fe_of_empty) begin
|
||
|
case (curr_fwft_state)
|
||
|
invalid : leaving_empty_fwft = fe_of_empty;
|
||
|
stage1_valid : leaving_empty_fwft = 1'b1;
|
||
|
default : leaving_empty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ge_ll
|
||
|
|
||
|
// fwft empty signal generation
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
empty_fwft_i <= 1'b1;
|
||
|
empty_fwft_fb <= 1'b1;
|
||
|
end else begin
|
||
|
empty_fwft_i <= going_empty_fwft | (~ leaving_empty_fwft & empty_fwft_fb);
|
||
|
empty_fwft_fb <= going_empty_fwft | (~ leaving_empty_fwft & empty_fwft_fb);
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if (EN_AE == 1) begin : gae_fwft
|
||
|
reg going_aempty_fwft;
|
||
|
reg leaving_aempty_fwft;
|
||
|
|
||
|
if (READ_MODE == 1) begin : gen_fwft_ae
|
||
|
always @(curr_fwft_state or rd_en or ram_empty_i) begin
|
||
|
case (curr_fwft_state)
|
||
|
both_stages_valid : going_aempty_fwft = rd_en & ram_empty_i;
|
||
|
default : going_aempty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ae
|
||
|
if (READ_MODE == 2) begin : gen_fwft_ae_ll
|
||
|
always @(curr_fwft_state or rd_en or ram_empty_i) begin
|
||
|
case (curr_fwft_state)
|
||
|
stage1_valid : going_aempty_fwft = !rd_en & ram_empty_i;
|
||
|
default : going_aempty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
end : gen_fwft_ae_ll
|
||
|
|
||
|
always @(curr_fwft_state or rd_en or ram_empty_i) begin
|
||
|
case (curr_fwft_state)
|
||
|
stage1_valid : leaving_aempty_fwft = ~ram_empty_i;
|
||
|
stage2_valid : leaving_aempty_fwft = ~(rd_en | ram_empty_i);
|
||
|
default : leaving_aempty_fwft = 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
aempty_fwft_i <= 1'b1;
|
||
|
end else begin
|
||
|
aempty_fwft_i <= going_aempty_fwft | (~ leaving_aempty_fwft & aempty_fwft_i);
|
||
|
end
|
||
|
end
|
||
|
end : gae_fwft
|
||
|
|
||
|
if (EN_DVLD == 1) begin : gdvld_fwft
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i) begin
|
||
|
data_valid_fwft <= 1'b0;
|
||
|
end else begin
|
||
|
data_valid_fwft <= ~(going_empty_fwft | (~ leaving_empty_fwft & empty_fwft_fb));
|
||
|
end
|
||
|
end
|
||
|
end : gdvld_fwft
|
||
|
|
||
|
xpm_fifo_reg_bit #(0)
|
||
|
empty_fwft_d1_inst (1'b0, rd_clk, leaving_empty_fwft, empty_fwft_d1);
|
||
|
|
||
|
wire ge_fwft_d1;
|
||
|
xpm_fifo_reg_bit #(0)
|
||
|
ge_fwft_d1_inst (1'b0, rd_clk, going_empty_fwft, ge_fwft_d1);
|
||
|
|
||
|
wire count_up ;
|
||
|
wire count_down;
|
||
|
wire count_en ;
|
||
|
wire count_rst ;
|
||
|
assign count_up = (next_fwft_state == 2'b10 && ~|curr_fwft_state) | (curr_fwft_state == 2'b10 && &next_fwft_state) | (curr_fwft_state == 2'b01 && &next_fwft_state);
|
||
|
assign count_down = (next_fwft_state == 2'b01 && &curr_fwft_state) | (curr_fwft_state == 2'b01 && ~|next_fwft_state);
|
||
|
assign count_en = count_up | count_down;
|
||
|
assign count_rst = (rd_rst_i | (~|curr_fwft_state & ~|next_fwft_state));
|
||
|
|
||
|
xpm_counter_updn # (2, 0)
|
||
|
rdpp1_inst (count_rst, rd_clk, count_en, count_up, count_down, extra_words_fwft);
|
||
|
|
||
|
|
||
|
end : gen_fwft
|
||
|
|
||
|
if (READ_MODE == 0) begin : ngen_fwft
|
||
|
assign le_fwft_re = 1'b0;
|
||
|
assign le_fwft_fe = 1'b0;
|
||
|
assign extra_words_fwft = 2'h0;
|
||
|
end : ngen_fwft
|
||
|
|
||
|
// output data bus assignment
|
||
|
if (FG_EQ_ASYM_DOUT == 0) begin : nfg_eq_asym_dout
|
||
|
assign dout = dout_i;
|
||
|
end : nfg_eq_asym_dout
|
||
|
|
||
|
// Overflow and Underflow flag generation
|
||
|
if (EN_UF == 1) begin : guf
|
||
|
always @ (posedge rd_clk) begin
|
||
|
underflow_i <= (rd_rst_i | empty_i) & rd_en;
|
||
|
end
|
||
|
assign underflow = underflow_i;
|
||
|
end : guf
|
||
|
if (EN_UF == 0) begin : gnuf
|
||
|
assign underflow = 1'b0;
|
||
|
end : gnuf
|
||
|
|
||
|
if (EN_OF == 1) begin : gof
|
||
|
always @ (posedge wr_clk) begin
|
||
|
overflow_i <= (wrst_busy | rst_d1 | ram_full_i) & wr_en;
|
||
|
end
|
||
|
assign overflow = overflow_i;
|
||
|
end : gof
|
||
|
if (EN_OF == 0) begin : gnof
|
||
|
assign overflow = 1'b0;
|
||
|
end : gnof
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Write Data Count for Independent Clocks FIFO
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
if (EN_WDC == 1) begin : gwdc
|
||
|
reg [WR_DC_WIDTH_EXT-1:0] wr_data_count_i;
|
||
|
wire [WR_DC_WIDTH_EXT-1:0] diff_wr_rd_pntr;
|
||
|
assign diff_wr_rd_pntr = wr_pntr_ext-rd_pntr_wr_adj_dc;
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (wrst_busy)
|
||
|
wr_data_count_i <= {WR_DC_WIDTH_EXT{1'b0}};
|
||
|
else
|
||
|
wr_data_count_i <= diff_wr_rd_pntr;
|
||
|
end
|
||
|
assign wr_data_count = wr_data_count_i[WR_DC_WIDTH_EXT-1:WR_DC_WIDTH_EXT-WR_DATA_COUNT_WIDTH];
|
||
|
end : gwdc
|
||
|
if (EN_WDC == 0) begin : gnwdc
|
||
|
assign wr_data_count = {WR_DC_WIDTH_EXT{1'b0}};
|
||
|
end : gnwdc
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Read Data Count for Independent Clocks FIFO
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
if (EN_RDC == 1) begin : grdc
|
||
|
reg [RD_DC_WIDTH_EXT-1:0] rd_data_count_i;
|
||
|
wire [RD_DC_WIDTH_EXT-1:0] diff_wr_rd_pntr_rdc;
|
||
|
assign diff_wr_rd_pntr_rdc = wr_pntr_rd_adj_dc-rd_pntr_ext+extra_words_fwft;
|
||
|
always @ (posedge rd_clk) begin
|
||
|
if (rd_rst_i | invalid_state)
|
||
|
rd_data_count_i <= {RD_DC_WIDTH_EXT{1'b0}};
|
||
|
else
|
||
|
rd_data_count_i <= diff_wr_rd_pntr_rdc;
|
||
|
end
|
||
|
assign rd_data_count = rd_data_count_i[RD_DC_WIDTH_EXT-1:RD_DC_WIDTH_EXT-RD_DATA_COUNT_WIDTH];
|
||
|
end : grdc
|
||
|
if (EN_RDC == 0) begin : gnrdc
|
||
|
assign rd_data_count = {RD_DC_WIDTH_EXT{1'b0}};
|
||
|
end : gnrdc
|
||
|
|
||
|
endgenerate
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Simulation constructs
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// synthesis translate_off
|
||
|
|
||
|
`ifndef DISABLE_XPM_ASSERTIONS
|
||
|
initial begin
|
||
|
#1;
|
||
|
if (SIM_ASSERT_CHK == 1)
|
||
|
`ifdef OBSOLETE
|
||
|
$warning("Vivado Simulator does not currently support the SystemVerilog Assertion syntax used within XPM_FIFO. \
|
||
|
Messages related to potential misuse will not be reported.");
|
||
|
`else
|
||
|
$warning("SIM_ASSERT_CHK (%0d) specifies simulation message reporting, messages related to potential misuse \
|
||
|
will be reported.", SIM_ASSERT_CHK);
|
||
|
`endif
|
||
|
end
|
||
|
|
||
|
`ifndef OBSOLETE
|
||
|
if (SIM_ASSERT_CHK == 1) begin : rst_usage
|
||
|
//Checks for valid conditions in which the src_send signal can toggle (based on src_rcv value)
|
||
|
//Start new handshake after previous handshake completes.
|
||
|
assume property (@(posedge wr_clk )
|
||
|
(($past(rst) == 0) && (rst == 1)) |-> ##1 $rose(wrst_busy))
|
||
|
else
|
||
|
$error("[%s %s-%0d] New reset (rst transitioning to 1) at %0t shouldn't occur until the previous reset \
|
||
|
sequence completes (wrst_busy must be 0). This reset is ignored. Please refer to the \
|
||
|
XPM_FIFO documentation in the libraries guide.", "XPM_FIFO_RESET", "S", 1, $time);
|
||
|
end : rst_usage
|
||
|
|
||
|
if (SIM_ASSERT_CHK == 1 && FULL_RESET_VALUE == 1) begin : rst_full_usage
|
||
|
assert property (@(posedge wr_clk )
|
||
|
$rose(wrst_busy) |-> ##1 $rose(full))
|
||
|
else
|
||
|
$error("[%s %s-%0d] FULL_RESET_VALUE is set to %0d. Full flag is not 1 or transitioning to 1 at %0t.", "FULL_RESET_VALUE", "S", 2, FULL_RESET_VALUE, $time);
|
||
|
|
||
|
assert property (@(posedge wr_clk )
|
||
|
$fell(wrst_busy) |-> ##1 $fell(full))
|
||
|
else
|
||
|
$error("[%s %s-%0d] After reset removal, full flag is not transitioning to 0 at %0t.", "FULL_CHECK", "S", 3, $time);
|
||
|
|
||
|
end : rst_full_usage
|
||
|
|
||
|
if (SIM_ASSERT_CHK == 1) begin : rst_empty_chk
|
||
|
assert property (@(posedge rd_clk )
|
||
|
($rose(rd_rst_busy) || (empty && $rose(rd_rst_busy))) |-> ##1 $rose(empty))
|
||
|
else
|
||
|
$error("[%s %s-%0d] Reset is applied, but empty flag is not 1 or transitioning to 1 at %0t.", "EMPTY_CHECK", "S", 4, $time);
|
||
|
|
||
|
end : rst_empty_chk
|
||
|
|
||
|
if (SIM_ASSERT_CHK == 1) begin : sleep_chk
|
||
|
assert property (@(posedge wr_clk )
|
||
|
($fell(sleep) |-> !wr_en[*WAKEUP_TIME]))
|
||
|
else
|
||
|
$error("[%s %s-%0d] 'sleep' is deasserted at %0t, but wr_en must be low for %0d wr_clk cycles after %0t", "SLEEP_CHECK", "S", 6, $time, WAKEUP_TIME, $time);
|
||
|
|
||
|
assert property (@(posedge rd_clk )
|
||
|
($fell(sleep) |-> !rd_en[*WAKEUP_TIME]))
|
||
|
else
|
||
|
$error("[%s %s-%0d] 'sleep' is deasserted at %0t, but rd_en must be low for %0d rd_clk cycles after %0t", "SLEEP_CHECK", "S", 7, $time, WAKEUP_TIME, $time);
|
||
|
end : sleep_chk
|
||
|
|
||
|
if (SIM_ASSERT_CHK == 1) begin : flag_chk
|
||
|
|
||
|
assert property (@(posedge wr_clk ) (!overflow)) else $warning("[%s %s-%0d] Overflow detected at %0t", "OVERFLOW_CHECK", "S", 8, $time);
|
||
|
|
||
|
assert property (@(posedge rd_clk ) (!underflow)) else $warning("[%s %s-%0d] Underflow detected at %0t", "UNDERFLOW_CHECK", "S", 9, $time);
|
||
|
|
||
|
end : flag_chk
|
||
|
|
||
|
`endif
|
||
|
`endif
|
||
|
|
||
|
// synthesis translate_on
|
||
|
endmodule : xpm_fifo_base
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
module xpm_fifo_rst # (
|
||
|
parameter integer COMMON_CLOCK = 1,
|
||
|
parameter integer CDC_DEST_SYNC_FF = 2,
|
||
|
parameter integer SIM_ASSERT_CHK = 0
|
||
|
|
||
|
) (
|
||
|
input wire rst,
|
||
|
input wire wr_clk,
|
||
|
input wire rd_clk,
|
||
|
output wire wr_rst,
|
||
|
output wire rd_rst,
|
||
|
output wire wr_rst_busy,
|
||
|
output wire rd_rst_busy
|
||
|
);
|
||
|
reg [1:0] power_on_rst = 2'h3;
|
||
|
wire rst_i;
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Reset Logic
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
//Keeping the power on reset to work even when the input reset(to xpm_fifo) is not applied or not using
|
||
|
always @ (posedge wr_clk) begin
|
||
|
power_on_rst <= {power_on_rst[0], 1'b0};
|
||
|
end
|
||
|
assign rst_i = power_on_rst[1] | rst;
|
||
|
|
||
|
// Write and read reset generation for common clock FIFO
|
||
|
if (COMMON_CLOCK == 1) begin : gen_rst_cc
|
||
|
reg [2:0] fifo_wr_rst_cc = 3'b00;
|
||
|
assign wr_rst = fifo_wr_rst_cc[2];
|
||
|
assign rd_rst = fifo_wr_rst_cc[2];
|
||
|
assign rd_rst_busy = fifo_wr_rst_cc[2];
|
||
|
assign wr_rst_busy = fifo_wr_rst_cc[2];
|
||
|
|
||
|
// synthesis translate_off
|
||
|
`ifndef DISABLE_XPM_ASSERTIONS
|
||
|
if (SIM_ASSERT_CHK == 1) begin: assert_rst
|
||
|
always @ (posedge wr_clk) begin
|
||
|
assert (!$isunknown(rst)) else $warning ("Input port 'rst' has unknown value 'X' or 'Z' at %0t. This may cause the outputs of FIFO to be 'X' or 'Z' in simulation. Ensure 'rst' has a valid value ('0' or '1')",$time);
|
||
|
end
|
||
|
end : assert_rst
|
||
|
`endif
|
||
|
// synthesis translate_on
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (rst_i) begin
|
||
|
fifo_wr_rst_cc <= 3'h7;
|
||
|
end else begin
|
||
|
fifo_wr_rst_cc <= {fifo_wr_rst_cc[1:0],1'b0};
|
||
|
end
|
||
|
end
|
||
|
end : gen_rst_cc
|
||
|
|
||
|
// Write and read reset generation for independent clock FIFO
|
||
|
if (COMMON_CLOCK == 0) begin : gen_rst_ic
|
||
|
wire fifo_wr_rst_rd;
|
||
|
wire fifo_rd_rst_wr_i;
|
||
|
reg fifo_wr_rst_i = 1'b0;
|
||
|
reg wr_rst_busy_i = 1'b0;
|
||
|
reg fifo_rd_rst_i = 1'b0;
|
||
|
reg fifo_rd_rst_ic = 1'b0;
|
||
|
reg fifo_wr_rst_ic = 1'b0;
|
||
|
reg wr_rst_busy_ic = 1'b0;
|
||
|
reg rst_seq_reentered = 1'b0;
|
||
|
|
||
|
assign wr_rst = fifo_wr_rst_ic | wr_rst_busy_ic;
|
||
|
assign rd_rst = fifo_rd_rst_ic;
|
||
|
assign rd_rst_busy = fifo_rd_rst_ic;
|
||
|
assign wr_rst_busy = wr_rst_busy_ic;
|
||
|
|
||
|
(* fsm_safe_state = "default_state" *) enum logic [2:0] {WRST_IDLE = 3'b000,
|
||
|
WRST_IN = 3'b010,
|
||
|
WRST_OUT = 3'b111,
|
||
|
WRST_EXIT = 3'b110,
|
||
|
WRST_GO2IDLE = 3'b100} curr_wrst_state = WRST_IDLE, next_wrst_state = WRST_IDLE;
|
||
|
|
||
|
(* fsm_safe_state = "default_state" *) enum logic [1:0] {RRST_IDLE = 2'b00,
|
||
|
RRST_IN = 2'b10,
|
||
|
RRST_OUT = 2'b11,
|
||
|
RRST_EXIT = 2'b01} curr_rrst_state = RRST_IDLE, next_rrst_state = RRST_IDLE;
|
||
|
|
||
|
// synthesis translate_off
|
||
|
`ifndef DISABLE_XPM_ASSERTIONS
|
||
|
if (SIM_ASSERT_CHK == 1) begin: assert_rst
|
||
|
always @ (posedge wr_clk) begin
|
||
|
assert (!$isunknown(rst)) else $warning ("Input port 'rst' has unknown value 'X' or 'Z' at %0t. This may cause the outputs of FIFO to be 'X' or 'Z' in simulation. Ensure 'rst' has a valid value ('0' or '1')",$time);
|
||
|
end
|
||
|
end : assert_rst
|
||
|
`endif
|
||
|
|
||
|
// synthesis translate_on
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
if (rst_i) begin
|
||
|
rst_seq_reentered <= 1'b0;
|
||
|
end else begin
|
||
|
if (curr_wrst_state == WRST_GO2IDLE) begin
|
||
|
rst_seq_reentered <= 1'b1;
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @* begin
|
||
|
case (curr_wrst_state)
|
||
|
WRST_IDLE: begin
|
||
|
if (rst_i)
|
||
|
next_wrst_state <= WRST_IN;
|
||
|
else
|
||
|
next_wrst_state <= WRST_IDLE;
|
||
|
end
|
||
|
WRST_IN: begin
|
||
|
if (rst_i)
|
||
|
next_wrst_state <= WRST_IN;
|
||
|
else if (fifo_rd_rst_wr_i)
|
||
|
next_wrst_state <= WRST_OUT;
|
||
|
else
|
||
|
next_wrst_state <= WRST_IN;
|
||
|
end
|
||
|
WRST_OUT: begin
|
||
|
if (rst_i)
|
||
|
next_wrst_state <= WRST_IN;
|
||
|
else if (~fifo_rd_rst_wr_i)
|
||
|
next_wrst_state <= WRST_EXIT;
|
||
|
else
|
||
|
next_wrst_state <= WRST_OUT;
|
||
|
end
|
||
|
WRST_EXIT: begin
|
||
|
if (rst_i)
|
||
|
next_wrst_state <= WRST_IN;
|
||
|
else if (~rst & ~rst_seq_reentered)
|
||
|
next_wrst_state <= WRST_GO2IDLE;
|
||
|
else if (rst_seq_reentered)
|
||
|
next_wrst_state <= WRST_IDLE;
|
||
|
else
|
||
|
next_wrst_state <= WRST_EXIT;
|
||
|
end
|
||
|
WRST_GO2IDLE: begin
|
||
|
next_wrst_state <= WRST_IN;
|
||
|
end
|
||
|
default: next_wrst_state <= WRST_IDLE;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @ (posedge wr_clk) begin
|
||
|
curr_wrst_state <= next_wrst_state;
|
||
|
fifo_wr_rst_ic <= fifo_wr_rst_i;
|
||
|
wr_rst_busy_ic <= wr_rst_busy_i;
|
||
|
end
|
||
|
|
||
|
always @* begin
|
||
|
case (curr_wrst_state)
|
||
|
WRST_IDLE : fifo_wr_rst_i = rst_i;
|
||
|
WRST_IN : fifo_wr_rst_i = 1'b1;
|
||
|
WRST_OUT : fifo_wr_rst_i = 1'b0;
|
||
|
WRST_EXIT : fifo_wr_rst_i = 1'b0;
|
||
|
WRST_GO2IDLE : fifo_wr_rst_i = 1'b1;
|
||
|
default: fifo_wr_rst_i = fifo_wr_rst_ic;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @* begin
|
||
|
case (curr_wrst_state)
|
||
|
WRST_IDLE: wr_rst_busy_i = rst_i;
|
||
|
WRST_IN : wr_rst_busy_i = 1'b1;
|
||
|
WRST_OUT : wr_rst_busy_i = 1'b1;
|
||
|
WRST_EXIT: wr_rst_busy_i = 1'b1;
|
||
|
default: wr_rst_busy_i = wr_rst_busy_ic;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @* begin
|
||
|
case (curr_rrst_state)
|
||
|
RRST_IDLE: begin
|
||
|
if (fifo_wr_rst_rd)
|
||
|
next_rrst_state <= RRST_IN;
|
||
|
else
|
||
|
next_rrst_state <= RRST_IDLE;
|
||
|
end
|
||
|
RRST_IN : next_rrst_state <= RRST_OUT;
|
||
|
RRST_OUT : begin
|
||
|
if (~fifo_wr_rst_rd)
|
||
|
next_rrst_state <= RRST_EXIT;
|
||
|
else
|
||
|
next_rrst_state <= RRST_OUT;
|
||
|
end
|
||
|
RRST_EXIT: next_rrst_state <= RRST_IDLE;
|
||
|
default: next_rrst_state <= RRST_IDLE;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
always @ (posedge rd_clk) begin
|
||
|
curr_rrst_state <= next_rrst_state;
|
||
|
fifo_rd_rst_ic <= fifo_rd_rst_i;
|
||
|
end
|
||
|
|
||
|
always @* begin
|
||
|
case (curr_rrst_state)
|
||
|
RRST_IDLE: fifo_rd_rst_i <= fifo_wr_rst_rd;
|
||
|
RRST_IN : fifo_rd_rst_i <= 1'b1;
|
||
|
RRST_OUT : fifo_rd_rst_i <= 1'b1;
|
||
|
RRST_EXIT: fifo_rd_rst_i <= 1'b0;
|
||
|
default: fifo_rd_rst_i <= 1'b0;
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
// Synchronize the wr_rst (fifo_wr_rst_ic) in read clock domain
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (CDC_DEST_SYNC_FF),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0),
|
||
|
.VERSION (0))
|
||
|
wrst_rd_inst (
|
||
|
.src_rst (fifo_wr_rst_ic),
|
||
|
.dest_clk (rd_clk),
|
||
|
.dest_rst (fifo_wr_rst_rd));
|
||
|
|
||
|
// Synchronize the rd_rst (fifo_rd_rst_ic) in write clock domain
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (CDC_DEST_SYNC_FF),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0),
|
||
|
.VERSION (0))
|
||
|
rrst_wr_inst (
|
||
|
.src_rst (fifo_rd_rst_ic),
|
||
|
.dest_clk (wr_clk),
|
||
|
.dest_rst (fifo_rd_rst_wr_i));
|
||
|
end : gen_rst_ic
|
||
|
endmodule : xpm_fifo_rst
|
||
|
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Up-Down Counter
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
module xpm_counter_updn # (
|
||
|
parameter integer COUNTER_WIDTH = 4,
|
||
|
parameter integer RESET_VALUE = 0
|
||
|
|
||
|
) (
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
input wire cnt_en,
|
||
|
input wire cnt_up,
|
||
|
input wire cnt_down,
|
||
|
output wire [COUNTER_WIDTH-1:0] count_value
|
||
|
);
|
||
|
reg [COUNTER_WIDTH-1:0] count_value_i = RESET_VALUE;
|
||
|
assign count_value = count_value_i;
|
||
|
always @ (posedge clk) begin
|
||
|
if (rst) begin
|
||
|
count_value_i <= RESET_VALUE;
|
||
|
end else if (cnt_en) begin
|
||
|
count_value_i <= count_value_i + cnt_up - cnt_down;
|
||
|
end
|
||
|
end
|
||
|
endmodule : xpm_counter_updn
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
module xpm_fifo_reg_vec # (
|
||
|
parameter integer REG_WIDTH = 4
|
||
|
|
||
|
) (
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
input wire [REG_WIDTH-1:0] reg_in,
|
||
|
output wire [REG_WIDTH-1:0] reg_out
|
||
|
);
|
||
|
reg [REG_WIDTH-1:0] reg_out_i = {REG_WIDTH{1'b0}};
|
||
|
always @ (posedge clk) begin
|
||
|
if (rst)
|
||
|
reg_out_i <= {REG_WIDTH{1'b0}};
|
||
|
else
|
||
|
reg_out_i <= reg_in;
|
||
|
end
|
||
|
assign reg_out = reg_out_i;
|
||
|
endmodule : xpm_fifo_reg_vec
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
module xpm_fifo_reg_bit # (
|
||
|
parameter integer RST_VALUE = 0
|
||
|
|
||
|
) (
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
input wire d_in,
|
||
|
output reg d_out = RST_VALUE
|
||
|
);
|
||
|
always @ (posedge clk) begin
|
||
|
if (rst)
|
||
|
d_out <= RST_VALUE;
|
||
|
else
|
||
|
d_out <= d_in;
|
||
|
end
|
||
|
endmodule : xpm_fifo_reg_bit
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
module xpm_reg_pipe_bit # (
|
||
|
parameter integer PIPE_STAGES = 1,
|
||
|
parameter integer RST_VALUE = 0
|
||
|
|
||
|
) (
|
||
|
input wire rst,
|
||
|
input wire clk,
|
||
|
input wire pipe_in,
|
||
|
output wire pipe_out
|
||
|
);
|
||
|
wire pipe_stage_ff [PIPE_STAGES:0];
|
||
|
|
||
|
assign pipe_stage_ff[0] = pipe_in;
|
||
|
|
||
|
for (genvar pipestage = 0; pipestage < PIPE_STAGES ;pipestage = pipestage + 1) begin : gen_pipe_bit
|
||
|
xpm_fifo_reg_bit #(RST_VALUE)
|
||
|
pipe_bit_inst (rst, clk, pipe_stage_ff[pipestage], pipe_stage_ff[pipestage+1]);
|
||
|
end : gen_pipe_bit
|
||
|
|
||
|
assign pipe_out = pipe_stage_ff[PIPE_STAGES];
|
||
|
endmodule : xpm_reg_pipe_bit
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
|
||
|
(* XPM_MODULE = "TRUE", KEEP_HIERARCHY = "SOFT" *)
|
||
|
module xpm_fifo_sync # (
|
||
|
|
||
|
// Common module parameters
|
||
|
parameter FIFO_MEMORY_TYPE = "auto",
|
||
|
parameter ECC_MODE = "no_ecc",
|
||
|
parameter integer SIM_ASSERT_CHK = 0,
|
||
|
parameter integer CASCADE_HEIGHT = 0,
|
||
|
|
||
|
parameter integer FIFO_WRITE_DEPTH = 2048,
|
||
|
parameter integer WRITE_DATA_WIDTH = 32,
|
||
|
parameter integer WR_DATA_COUNT_WIDTH = 1,
|
||
|
parameter integer PROG_FULL_THRESH = 10,
|
||
|
parameter integer FULL_RESET_VALUE = 0,
|
||
|
parameter USE_ADV_FEATURES = "0707",
|
||
|
|
||
|
parameter READ_MODE = "std",
|
||
|
parameter integer FIFO_READ_LATENCY = 1,
|
||
|
parameter integer READ_DATA_WIDTH = WRITE_DATA_WIDTH,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH = 1,
|
||
|
parameter integer PROG_EMPTY_THRESH = 10,
|
||
|
parameter DOUT_RESET_VALUE = "0",
|
||
|
|
||
|
parameter WAKEUP_TIME = 0
|
||
|
|
||
|
) (
|
||
|
|
||
|
// Common module ports
|
||
|
input wire sleep,
|
||
|
input wire rst,
|
||
|
|
||
|
// Write Domain ports
|
||
|
input wire wr_clk,
|
||
|
input wire wr_en,
|
||
|
input wire [WRITE_DATA_WIDTH-1:0] din,
|
||
|
output wire full,
|
||
|
output wire prog_full,
|
||
|
output wire [WR_DATA_COUNT_WIDTH-1:0] wr_data_count,
|
||
|
output wire overflow,
|
||
|
output wire wr_rst_busy,
|
||
|
output wire almost_full,
|
||
|
output wire wr_ack,
|
||
|
|
||
|
// Read Domain ports
|
||
|
input wire rd_en,
|
||
|
output wire [READ_DATA_WIDTH-1:0] dout,
|
||
|
output wire empty,
|
||
|
output wire prog_empty,
|
||
|
output wire [RD_DATA_COUNT_WIDTH-1:0] rd_data_count,
|
||
|
output wire underflow,
|
||
|
output wire rd_rst_busy,
|
||
|
output wire almost_empty,
|
||
|
output wire data_valid,
|
||
|
|
||
|
// ECC Related ports
|
||
|
input wire injectsbiterr,
|
||
|
input wire injectdbiterr,
|
||
|
output wire sbiterr,
|
||
|
output wire dbiterr
|
||
|
);
|
||
|
// Function to convert ASCII value to binary
|
||
|
function [3:0] str2bin;
|
||
|
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])
|
||
|
str2bin = str_val_ascii[3:0];
|
||
|
else begin
|
||
|
str2bin [3] = 1'b1;
|
||
|
str2bin [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
||
|
str2bin [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
||
|
str2bin [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 [15:0] hstr2bin;
|
||
|
input [16*8-1 : 0] hstr_val;
|
||
|
integer rst_loop_a;
|
||
|
localparam integer rsta_loop_iter = 16;
|
||
|
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] = str2bin(hstr_val[(rst_loop_a*8)-1 -: 8]);
|
||
|
end
|
||
|
return rst_val_conv_a_i[15:0];
|
||
|
endfunction
|
||
|
|
||
|
localparam [15:0] EN_ADV_FEATURE_SYNC = hstr2bin(USE_ADV_FEATURES);
|
||
|
|
||
|
// Define local parameters for mapping with base file
|
||
|
localparam integer P_FIFO_MEMORY_TYPE = ( (FIFO_MEMORY_TYPE == "lutram" || FIFO_MEMORY_TYPE == "LUTRAM" || FIFO_MEMORY_TYPE == "distributed" || FIFO_MEMORY_TYPE == "DISTRIBUTED" ) ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE == "bram" || FIFO_MEMORY_TYPE == "BRAM" || FIFO_MEMORY_TYPE == "block" || FIFO_MEMORY_TYPE == "BLOCK") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE == "uram" || FIFO_MEMORY_TYPE == "URAM" || FIFO_MEMORY_TYPE == "ultra" || FIFO_MEMORY_TYPE == "ULTRA") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE == "builtin" || FIFO_MEMORY_TYPE == "BUILTIN" ) ? 4 : 0))));
|
||
|
|
||
|
localparam integer P_COMMON_CLOCK = 1;
|
||
|
|
||
|
localparam integer P_ECC_MODE = ( (ECC_MODE == "no_ecc" || ECC_MODE == "NO_ECC" ) ? 0 : 1);
|
||
|
|
||
|
localparam integer P_READ_MODE = ( (READ_MODE == "std" || READ_MODE == "STD" ) ? 0 :
|
||
|
( (READ_MODE == "fwft" || READ_MODE == "FWFT") ? 1 :
|
||
|
( (READ_MODE == "low_latency_fwft" || READ_MODE == "Low_Latency_FWFT") ? 2 : 3)));
|
||
|
|
||
|
|
||
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == "disable_sleep" || WAKEUP_TIME == "DISABLE_SLEEP" ) ? 0 : 2);
|
||
|
|
||
|
initial begin : config_drc_sync
|
||
|
reg drc_err_flag_sync;
|
||
|
drc_err_flag_sync = 0;
|
||
|
#1;
|
||
|
if (EN_ADV_FEATURE_SYNC[13] != 1'b0) begin
|
||
|
$error("[%s %0d-%0d] USE_ADV_FEATURES[13] = %0b. This is a reserved field and must be set to 0. %m", "XPM_FIFO_SYNC", 1, 1, EN_ADV_FEATURE_SYNC[13]);
|
||
|
drc_err_flag_sync = 1;
|
||
|
end
|
||
|
|
||
|
if (drc_err_flag_sync == 1)
|
||
|
#1 $finish;
|
||
|
end : config_drc_sync
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Generate the instantiation of the appropriate XPM module
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
assign rd_rst_busy = wr_rst_busy;
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE ),
|
||
|
.ECC_MODE (P_ECC_MODE ),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_WRITE_DEPTH ),
|
||
|
.WRITE_DATA_WIDTH (WRITE_DATA_WIDTH ),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH ),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH ),
|
||
|
.FULL_RESET_VALUE (FULL_RESET_VALUE ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES ),
|
||
|
.READ_MODE (P_READ_MODE ),
|
||
|
.FIFO_READ_LATENCY (FIFO_READ_LATENCY ),
|
||
|
.READ_DATA_WIDTH (READ_DATA_WIDTH ),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH ),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH ),
|
||
|
.DOUT_RESET_VALUE (DOUT_RESET_VALUE ),
|
||
|
.CDC_DEST_SYNC_FF (2 ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (WAKEUP_TIME ),
|
||
|
.VERSION (0 )
|
||
|
|
||
|
) xpm_fifo_base_inst (
|
||
|
.sleep (sleep),
|
||
|
.rst (rst),
|
||
|
.wr_clk (wr_clk),
|
||
|
.wr_en (wr_en),
|
||
|
.din (din),
|
||
|
.full (full),
|
||
|
.full_n (),
|
||
|
.prog_full (prog_full),
|
||
|
.wr_data_count (wr_data_count),
|
||
|
.overflow (overflow),
|
||
|
.wr_rst_busy (wr_rst_busy),
|
||
|
.almost_full (almost_full),
|
||
|
.wr_ack (wr_ack),
|
||
|
.rd_clk (wr_clk),
|
||
|
.rd_en (rd_en),
|
||
|
.dout (dout),
|
||
|
.empty (empty),
|
||
|
.prog_empty (prog_empty),
|
||
|
.rd_data_count (rd_data_count),
|
||
|
.underflow (underflow),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (almost_empty),
|
||
|
.data_valid (data_valid),
|
||
|
.injectsbiterr (injectsbiterr),
|
||
|
.injectdbiterr (injectdbiterr),
|
||
|
.sbiterr (sbiterr),
|
||
|
.dbiterr (dbiterr)
|
||
|
);
|
||
|
|
||
|
endmodule : xpm_fifo_sync
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
|
||
|
(* XPM_MODULE = "TRUE", DONT_TOUCH = "TRUE" *)
|
||
|
module xpm_fifo_async # (
|
||
|
|
||
|
// Common module parameters
|
||
|
parameter FIFO_MEMORY_TYPE = "auto",
|
||
|
parameter ECC_MODE = "no_ecc",
|
||
|
parameter integer RELATED_CLOCKS = 0,
|
||
|
parameter integer SIM_ASSERT_CHK = 0,
|
||
|
parameter integer CASCADE_HEIGHT = 0,
|
||
|
|
||
|
parameter integer FIFO_WRITE_DEPTH = 2048,
|
||
|
parameter integer WRITE_DATA_WIDTH = 32,
|
||
|
parameter integer WR_DATA_COUNT_WIDTH = 1,
|
||
|
parameter integer PROG_FULL_THRESH = 10,
|
||
|
parameter integer FULL_RESET_VALUE = 0,
|
||
|
parameter USE_ADV_FEATURES = "0707",
|
||
|
|
||
|
parameter READ_MODE = "std",
|
||
|
parameter integer FIFO_READ_LATENCY = 1,
|
||
|
parameter integer READ_DATA_WIDTH = WRITE_DATA_WIDTH,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH = 1,
|
||
|
parameter integer PROG_EMPTY_THRESH = 10,
|
||
|
parameter DOUT_RESET_VALUE = "0",
|
||
|
parameter integer CDC_SYNC_STAGES = 2,
|
||
|
|
||
|
parameter WAKEUP_TIME = 0
|
||
|
) (
|
||
|
|
||
|
// Common module ports
|
||
|
input wire sleep,
|
||
|
input wire rst,
|
||
|
|
||
|
// Write Domain ports
|
||
|
input wire wr_clk,
|
||
|
input wire wr_en,
|
||
|
input wire [WRITE_DATA_WIDTH-1:0] din,
|
||
|
output wire full,
|
||
|
output wire prog_full,
|
||
|
output wire [WR_DATA_COUNT_WIDTH-1:0] wr_data_count,
|
||
|
output wire overflow,
|
||
|
output wire wr_rst_busy,
|
||
|
output wire almost_full,
|
||
|
output wire wr_ack,
|
||
|
|
||
|
// Read Domain ports
|
||
|
input wire rd_clk,
|
||
|
input wire rd_en,
|
||
|
output wire [READ_DATA_WIDTH-1:0] dout,
|
||
|
output wire empty,
|
||
|
output wire prog_empty,
|
||
|
output wire [RD_DATA_COUNT_WIDTH-1:0] rd_data_count,
|
||
|
output wire underflow,
|
||
|
output wire rd_rst_busy,
|
||
|
output wire almost_empty,
|
||
|
output wire data_valid,
|
||
|
|
||
|
// ECC Related ports
|
||
|
input wire injectsbiterr,
|
||
|
input wire injectdbiterr,
|
||
|
output wire sbiterr,
|
||
|
output wire dbiterr
|
||
|
);
|
||
|
// Function to convert ASCII value to binary
|
||
|
function [3:0] str2bin;
|
||
|
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])
|
||
|
str2bin = str_val_ascii[3:0];
|
||
|
else begin
|
||
|
str2bin [3] = 1'b1;
|
||
|
str2bin [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
||
|
str2bin [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
||
|
str2bin [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 [15:0] hstr2bin;
|
||
|
input [16*8-1 : 0] hstr_val;
|
||
|
integer rst_loop_a;
|
||
|
localparam integer rsta_loop_iter = 16;
|
||
|
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] = str2bin(hstr_val[(rst_loop_a*8)-1 -: 8]);
|
||
|
end
|
||
|
return rst_val_conv_a_i[15:0];
|
||
|
endfunction
|
||
|
|
||
|
localparam [15:0] EN_ADV_FEATURE_ASYNC = hstr2bin(USE_ADV_FEATURES);
|
||
|
|
||
|
// Define local parameters for mapping with base file
|
||
|
localparam integer P_FIFO_MEMORY_TYPE = ( (FIFO_MEMORY_TYPE == "lutram" || FIFO_MEMORY_TYPE == "LUTRAM" || FIFO_MEMORY_TYPE == "distributed" || FIFO_MEMORY_TYPE == "DISTRIBUTED" ) ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE == "bram" || FIFO_MEMORY_TYPE == "BRAM" || FIFO_MEMORY_TYPE == "block" || FIFO_MEMORY_TYPE == "BLOCK") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE == "uram" || FIFO_MEMORY_TYPE == "URAM" || FIFO_MEMORY_TYPE == "ultra" || FIFO_MEMORY_TYPE == "ULTRA") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE == "builtin" || FIFO_MEMORY_TYPE == "BUILTIN" ) ? 4 : 0))));
|
||
|
|
||
|
localparam integer P_COMMON_CLOCK = 0;
|
||
|
|
||
|
localparam integer P_ECC_MODE = ( (ECC_MODE == "no_ecc" || ECC_MODE == "NO_ECC" ) ? 0 : 1);
|
||
|
|
||
|
localparam integer P_READ_MODE = ( (READ_MODE == "std" || READ_MODE == "STD" ) ? 0 :
|
||
|
( (READ_MODE == "fwft" || READ_MODE == "FWFT") ? 1 :
|
||
|
( (READ_MODE == "low_latency_fwft" || READ_MODE == "Low_Latency_FWFT") ? 2 : 3)));
|
||
|
|
||
|
localparam integer P_WAKEUP_TIME = ( (WAKEUP_TIME == "disable_sleep" || WAKEUP_TIME == "DISABLE_SLEEP" ) ? 0 : 2);
|
||
|
|
||
|
initial begin : config_drc_async
|
||
|
reg drc_err_flag_async;
|
||
|
drc_err_flag_async = 0;
|
||
|
#1;
|
||
|
if (EN_ADV_FEATURE_ASYNC[13] != 1'b0) begin
|
||
|
$error("[%s %0d-%0d] USE_ADV_FEATURES[13] = %0b. This is a reserved field and must be set to 0. %m", "XPM_FIFO_ASYNC", 1, 1, EN_ADV_FEATURE_ASYNC[13]);
|
||
|
drc_err_flag_async = 1;
|
||
|
end
|
||
|
|
||
|
if (drc_err_flag_async == 1)
|
||
|
#1 $finish;
|
||
|
end : config_drc_async
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Generate the instantiation of the appropriate XPM module
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
generate if (P_FIFO_MEMORY_TYPE != 3) begin : gnuram_async_fifo
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (RELATED_CLOCKS ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE ),
|
||
|
.ECC_MODE (P_ECC_MODE ),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_WRITE_DEPTH ),
|
||
|
.WRITE_DATA_WIDTH (WRITE_DATA_WIDTH ),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH ),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH ),
|
||
|
.FULL_RESET_VALUE (FULL_RESET_VALUE ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES ),
|
||
|
.READ_MODE (P_READ_MODE ),
|
||
|
.FIFO_READ_LATENCY (FIFO_READ_LATENCY ),
|
||
|
.READ_DATA_WIDTH (READ_DATA_WIDTH ),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH ),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH ),
|
||
|
.DOUT_RESET_VALUE (DOUT_RESET_VALUE ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (WAKEUP_TIME ),
|
||
|
.VERSION (0 )
|
||
|
|
||
|
) xpm_fifo_base_inst (
|
||
|
.sleep (sleep),
|
||
|
.rst (rst),
|
||
|
.wr_clk (wr_clk),
|
||
|
.wr_en (wr_en),
|
||
|
.din (din),
|
||
|
.full (full),
|
||
|
.full_n (),
|
||
|
.prog_full (prog_full),
|
||
|
.wr_data_count (wr_data_count),
|
||
|
.overflow (overflow),
|
||
|
.wr_rst_busy (wr_rst_busy),
|
||
|
.almost_full (almost_full),
|
||
|
.wr_ack (wr_ack),
|
||
|
.rd_clk (rd_clk),
|
||
|
.rd_en (rd_en),
|
||
|
.dout (dout),
|
||
|
.empty (empty),
|
||
|
.prog_empty (prog_empty),
|
||
|
.rd_data_count (rd_data_count),
|
||
|
.underflow (underflow),
|
||
|
.rd_rst_busy (rd_rst_busy),
|
||
|
.almost_empty (almost_empty),
|
||
|
.data_valid (data_valid),
|
||
|
.injectsbiterr (injectsbiterr),
|
||
|
.injectdbiterr (injectdbiterr),
|
||
|
.sbiterr (sbiterr),
|
||
|
.dbiterr (dbiterr)
|
||
|
);
|
||
|
end endgenerate // gnuram_async_fifo
|
||
|
endmodule : xpm_fifo_async
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
|
||
|
(* XPM_MODULE = "TRUE", DONT_TOUCH = "TRUE" *)
|
||
|
module xpm_fifo_axis # (
|
||
|
|
||
|
// Common module parameters
|
||
|
parameter CLOCKING_MODE = "common_clock",
|
||
|
parameter FIFO_MEMORY_TYPE = "auto",
|
||
|
parameter PACKET_FIFO = "false",
|
||
|
parameter integer FIFO_DEPTH = 2048,
|
||
|
parameter integer TDATA_WIDTH = 32,
|
||
|
parameter integer TID_WIDTH = 1,
|
||
|
parameter integer TDEST_WIDTH = 1,
|
||
|
parameter integer TUSER_WIDTH = 1,
|
||
|
parameter integer SIM_ASSERT_CHK = 0,
|
||
|
parameter integer CASCADE_HEIGHT = 0,
|
||
|
|
||
|
parameter ECC_MODE = "no_ecc",
|
||
|
parameter integer RELATED_CLOCKS = 0,
|
||
|
parameter USE_ADV_FEATURES = "1000",
|
||
|
parameter integer WR_DATA_COUNT_WIDTH = 1,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH = 1,
|
||
|
parameter integer PROG_FULL_THRESH = 10,
|
||
|
parameter integer PROG_EMPTY_THRESH = 10,
|
||
|
parameter integer CDC_SYNC_STAGES = 2
|
||
|
|
||
|
|
||
|
) (
|
||
|
|
||
|
// Common module ports
|
||
|
input wire s_aresetn,
|
||
|
input wire s_aclk,
|
||
|
input wire m_aclk,
|
||
|
|
||
|
// AXI Streaming Slave Signals (Write side)
|
||
|
input wire s_axis_tvalid,
|
||
|
output wire s_axis_tready,
|
||
|
input wire [TDATA_WIDTH-1:0] s_axis_tdata,
|
||
|
input wire [TDATA_WIDTH/8-1:0] s_axis_tstrb,
|
||
|
input wire [TDATA_WIDTH/8-1:0] s_axis_tkeep,
|
||
|
input wire s_axis_tlast,
|
||
|
input wire [TID_WIDTH-1:0] s_axis_tid,
|
||
|
input wire [TDEST_WIDTH-1:0] s_axis_tdest,
|
||
|
input wire [TUSER_WIDTH-1:0] s_axis_tuser,
|
||
|
|
||
|
// AXI Streaming Master Signals (Read side)
|
||
|
output wire m_axis_tvalid,
|
||
|
input wire m_axis_tready,
|
||
|
output wire [TDATA_WIDTH-1:0] m_axis_tdata,
|
||
|
output wire [TDATA_WIDTH/8-1:0] m_axis_tstrb,
|
||
|
output wire [TDATA_WIDTH/8-1:0] m_axis_tkeep,
|
||
|
output wire m_axis_tlast,
|
||
|
output wire [TID_WIDTH-1:0] m_axis_tid,
|
||
|
output wire [TDEST_WIDTH-1:0] m_axis_tdest,
|
||
|
output wire [TUSER_WIDTH-1:0] m_axis_tuser,
|
||
|
|
||
|
// AXI Streaming Sideband Signals
|
||
|
output wire prog_full_axis,
|
||
|
output wire [WR_DATA_COUNT_WIDTH-1:0] wr_data_count_axis,
|
||
|
output wire almost_full_axis,
|
||
|
output wire prog_empty_axis,
|
||
|
output wire [RD_DATA_COUNT_WIDTH-1:0] rd_data_count_axis,
|
||
|
output wire almost_empty_axis,
|
||
|
|
||
|
// ECC Related ports
|
||
|
input wire injectsbiterr_axis,
|
||
|
input wire injectdbiterr_axis,
|
||
|
output wire sbiterr_axis,
|
||
|
output wire dbiterr_axis
|
||
|
);
|
||
|
|
||
|
function integer clog2;
|
||
|
input integer value;
|
||
|
begin
|
||
|
value = value-1;
|
||
|
for (clog2=0; value>0; clog2=clog2+1)
|
||
|
value = value>>1;
|
||
|
end
|
||
|
endfunction
|
||
|
// Function to convert ASCII value to binary
|
||
|
function [3:0] str2bin;
|
||
|
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])
|
||
|
str2bin = str_val_ascii[3:0];
|
||
|
else begin
|
||
|
str2bin [3] = 1'b1;
|
||
|
str2bin [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
||
|
str2bin [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
||
|
str2bin [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 [15:0] hstr2bin;
|
||
|
input [16*8-1 : 0] hstr_val;
|
||
|
integer rst_loop_a;
|
||
|
localparam integer rsta_loop_iter = 16;
|
||
|
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] = str2bin(hstr_val[(rst_loop_a*8)-1 -: 8]);
|
||
|
end
|
||
|
return rst_val_conv_a_i[15:0];
|
||
|
endfunction
|
||
|
|
||
|
//Function to convert binary to ASCII value
|
||
|
function [7:0] bin2str;
|
||
|
input [3:0] bin_val;
|
||
|
if( bin_val > 4'h9) begin
|
||
|
bin2str [7:4] = 4'h4;
|
||
|
bin2str [3] = 1'b0;
|
||
|
bin2str [2:0] = bin_val[2:0]-1'b1;
|
||
|
end
|
||
|
else begin
|
||
|
bin2str [7:4] = 4'h3;
|
||
|
bin2str [3:0] = bin_val;
|
||
|
end
|
||
|
endfunction
|
||
|
|
||
|
// Function that parses the complete binary value to string
|
||
|
function [31:0] bin2hstr;
|
||
|
input [15 : 0] bin_val;
|
||
|
integer str_pos;
|
||
|
localparam integer str_max_bits = 32;
|
||
|
for (str_pos=1; str_pos <= str_max_bits/8; str_pos = str_pos+1) begin
|
||
|
bin2hstr[(str_pos*8)-1 -: 8] = bin2str(bin_val[(str_pos*4)-1 -: 4]);
|
||
|
end
|
||
|
endfunction
|
||
|
|
||
|
|
||
|
localparam [15:0] EN_ADV_FEATURE_AXIS = hstr2bin(USE_ADV_FEATURES);
|
||
|
localparam EN_ALMOST_FULL_INT = (PACKET_FIFO == "true") ? 1'b1 : EN_ADV_FEATURE_AXIS[3];
|
||
|
localparam EN_ALMOST_EMPTY_INT = (PACKET_FIFO == "true") ? 1'b1 : EN_ADV_FEATURE_AXIS[11];
|
||
|
localparam EN_DATA_VALID_INT = 1'b1;
|
||
|
localparam [15:0] EN_ADV_FEATURE_AXIS_INT = {EN_ADV_FEATURE_AXIS[15:13], EN_DATA_VALID_INT, EN_ALMOST_EMPTY_INT, EN_ADV_FEATURE_AXIS[10:4], EN_ALMOST_FULL_INT, EN_ADV_FEATURE_AXIS[2:0]};
|
||
|
localparam USE_ADV_FEATURES_INT = bin2hstr(EN_ADV_FEATURE_AXIS_INT);
|
||
|
|
||
|
|
||
|
localparam PKT_SIZE_LT8 = EN_ADV_FEATURE_AXIS[13];
|
||
|
|
||
|
localparam LOG_DEPTH_AXIS = clog2(FIFO_DEPTH);
|
||
|
localparam TDATA_OFFSET = TDATA_WIDTH;
|
||
|
localparam TSTRB_OFFSET = TDATA_OFFSET+(TDATA_WIDTH/8);
|
||
|
localparam TKEEP_OFFSET = TSTRB_OFFSET+(TDATA_WIDTH/8);
|
||
|
localparam TID_OFFSET = TID_WIDTH > 0 ? TKEEP_OFFSET+TID_WIDTH : TKEEP_OFFSET;
|
||
|
localparam TDEST_OFFSET = TDEST_WIDTH > 0 ? TID_OFFSET+TDEST_WIDTH : TID_OFFSET;
|
||
|
localparam TUSER_OFFSET = TUSER_WIDTH > 0 ? TDEST_OFFSET+TUSER_WIDTH : TDEST_OFFSET;
|
||
|
localparam AXIS_DATA_WIDTH = TUSER_OFFSET+1;
|
||
|
|
||
|
// Define local parameters for mapping with base file
|
||
|
|
||
|
localparam integer P_COMMON_CLOCK = ( (CLOCKING_MODE == "common_clock" || CLOCKING_MODE == "COMMON_CLOCK" || CLOCKING_MODE == "COMMON" || CLOCKING_MODE == "common") ? 1 :
|
||
|
( (CLOCKING_MODE == "independent_clock" || CLOCKING_MODE == "INDEPENDENT_CLOCK" || CLOCKING_MODE == "INDEPENDENT" || CLOCKING_MODE == "independent") ? 0 : 1));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE = ( (FIFO_MEMORY_TYPE == "lutram" || FIFO_MEMORY_TYPE == "LUTRAM" || FIFO_MEMORY_TYPE == "distributed" || FIFO_MEMORY_TYPE == "DISTRIBUTED" ) ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE == "bram" || FIFO_MEMORY_TYPE == "BRAM" || FIFO_MEMORY_TYPE == "block" || FIFO_MEMORY_TYPE == "BLOCK") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE == "uram" || FIFO_MEMORY_TYPE == "URAM" || FIFO_MEMORY_TYPE == "ultra" || FIFO_MEMORY_TYPE == "ULTRA") ? 3 : 0)));
|
||
|
|
||
|
localparam integer P_ECC_MODE = ( (ECC_MODE == "no_ecc" || ECC_MODE == "NO_ECC" ) ? 0 : 1);
|
||
|
localparam integer P_PKT_MODE = PACKET_FIFO == "true" ? 1 : 0;
|
||
|
localparam AXIS_FINAL_DATA_WIDTH = P_ECC_MODE == 0 ? AXIS_DATA_WIDTH : (((AXIS_DATA_WIDTH/64)*64) + ((AXIS_DATA_WIDTH%64 == 0) ? 0 : 64));
|
||
|
localparam TUSER_MAX_WIDTH = 4096 - (TDEST_OFFSET+1);
|
||
|
|
||
|
wire rst_axis;
|
||
|
wire data_valid_axis;
|
||
|
wire rd_rst_busy_axis;
|
||
|
wire [AXIS_FINAL_DATA_WIDTH-1:0] axis_din;
|
||
|
wire [AXIS_FINAL_DATA_WIDTH-1:0] axis_dout;
|
||
|
|
||
|
initial begin : config_drc_axis
|
||
|
reg drc_err_flag_axis;
|
||
|
drc_err_flag_axis = 0;
|
||
|
#1;
|
||
|
|
||
|
if (AXIS_FINAL_DATA_WIDTH > 4096) begin
|
||
|
$error("[%s %0d-%0d] Total width (sum of TDATA, TID, TDEST, TKEEP, TSTRB, TUSER and TLAST) of AXI Stream FIFO (%0d) exceeds the maximum supported width (%0d). Please reduce the width of TDATA or TID or TDEST or TUSER %m", "XPM_FIFO_AXIS", 20, 2, AXIS_FINAL_DATA_WIDTH, 4096);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
if ((TDATA_WIDTH%8 != 0) || TDATA_WIDTH < 8 || TDATA_WIDTH > 2048) begin
|
||
|
$error("[%s %0d-%0d] TDATA_WIDTH (%0d) value is outside of legal range. TDATA_WIDTH value must be between %0d and %0d, and it must be multiples of 8. %m", "XPM_FIFO_AXIS", 20, 3, TDATA_WIDTH, 8, 2048);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
if (TID_WIDTH < 1 || TID_WIDTH > 32) begin
|
||
|
$error("[%s %0d-%0d] TID_WIDTH (%0d) value is outside of legal range. TID_WIDTH value must be between %0d and %0d, and it must be multiples of 8. %m", "XPM_FIFO_AXIS", 20, 4, TID_WIDTH, 1, 32);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
if (TDEST_WIDTH < 1 || TDEST_WIDTH > 32) begin
|
||
|
$error("[%s %0d-%0d] TDEST_WIDTH (%0d) value is outside of legal range. TDEST_WIDTH value must be between %0d and %0d, and it must be multiples of 8. %m", "XPM_FIFO_AXIS", 20, 5, TDEST_WIDTH, 1, 32);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
if (TUSER_WIDTH < 1 || TUSER_WIDTH > TUSER_MAX_WIDTH) begin
|
||
|
$error("[%s %0d-%0d] TUSER_WIDTH (%0d) value is outside of legal range. TUSER_WIDTH value must be between %0d and %0d, and it must be multiples of 8. %m", "XPM_FIFO_AXIS", 20, 6, TUSER_WIDTH, 1, TUSER_MAX_WIDTH);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
if (RELATED_CLOCKS == 1 && P_PKT_MODE != 1'b0) begin
|
||
|
$error("[%s %0d-%0d] RELATED_CLOCKS (%0d) value is outside of legal range. RELATED_CLOCKS value must be 0 when PACKET_FIFO is set to %s. %m", "XPM_FIFO_AXIS", 20, 7, RELATED_CLOCKS, RELATED_CLOCKS);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
if (EN_ADV_FEATURE_AXIS[13] == 1'b1 && (P_PKT_MODE != 1'b1 || P_COMMON_CLOCK != 1'b0)) begin
|
||
|
$error("[%s %0d-%0d] USE_ADV_FEATURES[13] (%0b) value is outside of legal range. USE_ADV_FEATURES[13] can be set to 1 only for packet mode in asynchronous AXI-Stream FIFO. %m", "XPM_FIFO_AXIS", 20, 8, EN_ADV_FEATURE_AXIS[13]);
|
||
|
drc_err_flag_axis = 1;
|
||
|
end
|
||
|
|
||
|
// Infos
|
||
|
if (P_PKT_MODE == 1'b1 && EN_ADV_FEATURE_AXIS[3] != 1'b1)
|
||
|
$info("[%s %0d-%0d] Almost full flag option is not enabled (USE_ADV_FEATURES[3] = %0b) but Packet FIFO mode requires almost_full to be enabled. XPM_FIFO_AXIS enables the Almost full flag automatically. You may ignore almost_full port if not required %m", "XPM_FIFO_AXIS", 21, 1, EN_ADV_FEATURE_AXIS[3]);
|
||
|
|
||
|
if (P_PKT_MODE == 1'b1 && EN_ADV_FEATURE_AXIS[11] != 1'b1)
|
||
|
$info("[%s %0d-%0d] Almost empty flag option is not enabled (USE_ADV_FEATURES[11] = %0b) but Packet FIFO mode requires almost_empty to be enabled. XPM_FIFO_AXIS enables the Almost empty flag automatically. You may ignore almost_empty port if not required %m", "XPM_FIFO_AXIS", 21, 1, EN_ADV_FEATURE_AXIS[11]);
|
||
|
|
||
|
if (drc_err_flag_axis == 1)
|
||
|
#1 $finish;
|
||
|
end : config_drc_axis
|
||
|
|
||
|
generate
|
||
|
if (P_ECC_MODE == 0) begin : axis_necc
|
||
|
assign axis_din = ({s_axis_tlast, s_axis_tuser, s_axis_tdest, s_axis_tid, s_axis_tkeep, s_axis_tstrb, s_axis_tdata});
|
||
|
end // axis_necc
|
||
|
|
||
|
if (P_ECC_MODE == 1) begin : axis_ecc
|
||
|
assign axis_din = ({{(AXIS_FINAL_DATA_WIDTH - AXIS_DATA_WIDTH){1'b0}},s_axis_tlast, s_axis_tuser, s_axis_tdest, s_axis_tid, s_axis_tkeep, s_axis_tstrb, s_axis_tdata});
|
||
|
end // axis_ecc
|
||
|
|
||
|
assign m_axis_tlast = axis_dout[AXIS_DATA_WIDTH-1];
|
||
|
assign m_axis_tuser = axis_dout[TUSER_OFFSET-1:TDEST_OFFSET];
|
||
|
assign m_axis_tdest = axis_dout[TDEST_OFFSET-1:TID_OFFSET];
|
||
|
assign m_axis_tid = axis_dout[TID_OFFSET-1:TKEEP_OFFSET];
|
||
|
assign m_axis_tkeep = axis_dout[TKEEP_OFFSET-1:TSTRB_OFFSET];
|
||
|
assign m_axis_tstrb = axis_dout[TSTRB_OFFSET-1:TDATA_OFFSET];
|
||
|
assign m_axis_tdata = axis_dout[TDATA_OFFSET-1:0];
|
||
|
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
// Generate the instantiation of the appropriate XPM module
|
||
|
// -------------------------------------------------------------------------------------------------------------------
|
||
|
if (EN_ADV_FEATURE_AXIS[15] == 1'b0) begin : gaxis_rst_sync
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (P_COMMON_CLOCK?4:CDC_SYNC_STAGES),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0)
|
||
|
) xpm_cdc_sync_rst_inst (
|
||
|
.src_rst (~s_aresetn),
|
||
|
.dest_clk (s_aclk),
|
||
|
.dest_rst (rst_axis)
|
||
|
);
|
||
|
end // gaxis_rst_sync
|
||
|
if (EN_ADV_FEATURE_AXIS[15] == 1'b1) begin : gnaxis_rst_sync
|
||
|
assign rst_axis = s_aresetn;
|
||
|
end // gnaxis_rst_sync
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (RELATED_CLOCKS ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE ),
|
||
|
.ECC_MODE (P_ECC_MODE ),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH ),
|
||
|
.WRITE_DATA_WIDTH (AXIS_FINAL_DATA_WIDTH ),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH ),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH ),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES_INT ),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (AXIS_FINAL_DATA_WIDTH ),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH ),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH ),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_inst (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axis),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (s_axis_tvalid),
|
||
|
.din (axis_din),
|
||
|
.full (),
|
||
|
.full_n (s_axis_tready),
|
||
|
.prog_full (prog_full_axis),
|
||
|
.wr_data_count (wr_data_count_axis),
|
||
|
.overflow (),
|
||
|
.wr_rst_busy (),
|
||
|
.almost_full (almost_full_axis),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (P_COMMON_CLOCK?s_aclk:m_aclk),
|
||
|
.rd_en (m_axis_tvalid&m_axis_tready),
|
||
|
.dout (axis_dout),
|
||
|
.empty (),
|
||
|
.prog_empty (prog_empty_axis),
|
||
|
.rd_data_count (rd_data_count_axis),
|
||
|
.underflow (),
|
||
|
.rd_rst_busy (rd_rst_busy_axis),
|
||
|
.almost_empty (almost_empty_axis),
|
||
|
.data_valid (data_valid_axis),
|
||
|
.injectsbiterr (injectsbiterr_axis),
|
||
|
.injectdbiterr (injectdbiterr_axis),
|
||
|
.sbiterr (sbiterr_axis),
|
||
|
.dbiterr (dbiterr_axis)
|
||
|
);
|
||
|
reg axis_pkt_read = 1'b0;
|
||
|
reg axis_wr_eop_d1 = 1'b0;
|
||
|
wire axis_wr_eop;
|
||
|
wire axis_rd_eop;
|
||
|
integer axis_pkt_cnt;
|
||
|
|
||
|
if (P_PKT_MODE == 0) begin : gaxis_npkt_fifo
|
||
|
assign m_axis_tvalid = data_valid_axis;
|
||
|
end // gaxis_npkt_fifo
|
||
|
|
||
|
if (P_PKT_MODE == 1 && P_COMMON_CLOCK == 1) begin : gaxis_pkt_fifo_cc
|
||
|
assign axis_wr_eop = s_axis_tvalid & s_axis_tready & s_axis_tlast;
|
||
|
assign axis_rd_eop = m_axis_tvalid & m_axis_tready & m_axis_tlast & axis_pkt_read;
|
||
|
assign m_axis_tvalid = data_valid_axis & axis_pkt_read;
|
||
|
|
||
|
always @ (posedge s_aclk) begin
|
||
|
if (rst_axis)
|
||
|
axis_pkt_read <= 1'b0;
|
||
|
else if (axis_rd_eop && (axis_pkt_cnt == 1) && ~axis_wr_eop_d1)
|
||
|
axis_pkt_read <= 1'b0;
|
||
|
else if ((axis_pkt_cnt > 0) || (almost_full_axis && data_valid_axis))
|
||
|
axis_pkt_read <= 1'b1;
|
||
|
end
|
||
|
|
||
|
always @ (posedge s_aclk) begin
|
||
|
if (rst_axis)
|
||
|
axis_wr_eop_d1 <= 1'b0;
|
||
|
else
|
||
|
axis_wr_eop_d1 <= axis_wr_eop;
|
||
|
end
|
||
|
|
||
|
always @ (posedge s_aclk) begin
|
||
|
if (rst_axis)
|
||
|
axis_pkt_cnt <= 0;
|
||
|
else if (axis_wr_eop_d1 && ~axis_rd_eop)
|
||
|
axis_pkt_cnt <= axis_pkt_cnt + 1;
|
||
|
else if (axis_rd_eop && ~axis_wr_eop_d1)
|
||
|
axis_pkt_cnt <= axis_pkt_cnt - 1;
|
||
|
end
|
||
|
end // gaxis_pkt_fifo_cc
|
||
|
|
||
|
if (P_PKT_MODE == 1 && P_COMMON_CLOCK == 0) begin : gaxis_pkt_fifo_ic
|
||
|
wire [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt_rd_lt8_0;
|
||
|
wire [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt_rd_lt8_1;
|
||
|
wire [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt_rd_lt8_2;
|
||
|
wire [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt_rd;
|
||
|
reg [LOG_DEPTH_AXIS-1 : 0] axis_wpkt_cnt = 0;
|
||
|
reg [LOG_DEPTH_AXIS-1 : 0] axis_rpkt_cnt = 0;
|
||
|
wire [LOG_DEPTH_AXIS : 0] adj_axis_wpkt_cnt_rd_pad;
|
||
|
wire [LOG_DEPTH_AXIS : 0] rpkt_inv_pad;
|
||
|
wire [LOG_DEPTH_AXIS-1 : 0] diff_pkt_cnt;
|
||
|
reg [LOG_DEPTH_AXIS : 0] diff_pkt_cnt_pad = 0;
|
||
|
reg adj_axis_wpkt_cnt_rd_pad_0 = 0;
|
||
|
reg rpkt_inv_pad_0 = 0;
|
||
|
wire axis_af_rd ;
|
||
|
|
||
|
assign axis_wr_eop = s_axis_tvalid & s_axis_tready & s_axis_tlast;
|
||
|
assign axis_rd_eop = m_axis_tvalid & m_axis_tready & m_axis_tlast & axis_pkt_read;
|
||
|
assign m_axis_tvalid = data_valid_axis & axis_pkt_read;
|
||
|
|
||
|
always @ (posedge m_aclk) begin
|
||
|
if (rd_rst_busy_axis)
|
||
|
axis_pkt_read <= 1'b0;
|
||
|
else if (axis_rd_eop && (diff_pkt_cnt == 1))
|
||
|
axis_pkt_read <= 1'b0;
|
||
|
else if ((diff_pkt_cnt > 0) || (axis_af_rd && data_valid_axis))
|
||
|
axis_pkt_read <= 1'b1;
|
||
|
end
|
||
|
|
||
|
always @ (posedge s_aclk) begin
|
||
|
if (rst_axis)
|
||
|
axis_wpkt_cnt <= 1'b0;
|
||
|
else if (axis_wr_eop)
|
||
|
axis_wpkt_cnt <= axis_wpkt_cnt + 1;
|
||
|
end
|
||
|
|
||
|
xpm_cdc_gray #(
|
||
|
.DEST_SYNC_FF (CDC_SYNC_STAGES),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.REG_OUTPUT (1),
|
||
|
.WIDTH (LOG_DEPTH_AXIS))
|
||
|
|
||
|
wpkt_cnt_cdc_inst (
|
||
|
.src_clk (s_aclk),
|
||
|
.src_in_bin (axis_wpkt_cnt),
|
||
|
.dest_clk (m_aclk),
|
||
|
.dest_out_bin (axis_wpkt_cnt_rd_lt8_0));
|
||
|
|
||
|
if (PKT_SIZE_LT8 == 1) begin : pkt_lt8
|
||
|
xpm_fifo_reg_vec #(LOG_DEPTH_AXIS)
|
||
|
wpkt_cnt_rd_dly_inst1 (rd_rst_busy_axis, m_aclk, axis_wpkt_cnt_rd_lt8_0, axis_wpkt_cnt_rd_lt8_1);
|
||
|
xpm_fifo_reg_vec #(LOG_DEPTH_AXIS)
|
||
|
wpkt_cnt_rd_dly_inst2 (rd_rst_busy_axis, m_aclk, axis_wpkt_cnt_rd_lt8_1, axis_wpkt_cnt_rd_lt8_2);
|
||
|
xpm_fifo_reg_vec #(LOG_DEPTH_AXIS)
|
||
|
wpkt_cnt_rd_dly_inst3 (rd_rst_busy_axis, m_aclk, axis_wpkt_cnt_rd_lt8_2, axis_wpkt_cnt_rd);
|
||
|
end else begin : pkt_nlt8
|
||
|
assign axis_wpkt_cnt_rd = axis_wpkt_cnt_rd_lt8_0;
|
||
|
end
|
||
|
|
||
|
xpm_cdc_single #(
|
||
|
.DEST_SYNC_FF (CDC_SYNC_STAGES),
|
||
|
.SRC_INPUT_REG (0),
|
||
|
.INIT_SYNC_FF (1))
|
||
|
|
||
|
af_axis_cdc_inst (
|
||
|
.src_clk (s_aclk),
|
||
|
.src_in (almost_full_axis),
|
||
|
.dest_clk (m_aclk),
|
||
|
.dest_out (axis_af_rd));
|
||
|
|
||
|
always @ (posedge m_aclk) begin
|
||
|
if (rd_rst_busy_axis)
|
||
|
axis_rpkt_cnt <= 1'b0;
|
||
|
else if (axis_rd_eop)
|
||
|
axis_rpkt_cnt <= axis_rpkt_cnt + 1;
|
||
|
end
|
||
|
|
||
|
// Take the difference of write and read packet count using 1's complement
|
||
|
assign adj_axis_wpkt_cnt_rd_pad[LOG_DEPTH_AXIS : 1] = axis_wpkt_cnt_rd;
|
||
|
assign rpkt_inv_pad[LOG_DEPTH_AXIS : 1] = ~axis_rpkt_cnt;
|
||
|
assign adj_axis_wpkt_cnt_rd_pad[0] = adj_axis_wpkt_cnt_rd_pad_0;
|
||
|
assign rpkt_inv_pad[0] = rpkt_inv_pad_0;
|
||
|
|
||
|
|
||
|
always @ ( axis_rd_eop ) begin
|
||
|
if (!axis_rd_eop) begin
|
||
|
adj_axis_wpkt_cnt_rd_pad_0 <= 1'b1;
|
||
|
rpkt_inv_pad_0 <= 1'b1;
|
||
|
end else begin
|
||
|
adj_axis_wpkt_cnt_rd_pad_0 <= 1'b0;
|
||
|
rpkt_inv_pad_0 <= 1'b0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @ (posedge m_aclk) begin
|
||
|
if (rd_rst_busy_axis)
|
||
|
diff_pkt_cnt_pad <= 1'b0;
|
||
|
else
|
||
|
diff_pkt_cnt_pad <= adj_axis_wpkt_cnt_rd_pad + rpkt_inv_pad ;
|
||
|
end
|
||
|
|
||
|
assign diff_pkt_cnt = diff_pkt_cnt_pad [LOG_DEPTH_AXIS : 1] ;
|
||
|
|
||
|
end // gaxis_pkt_fifo_ic
|
||
|
endgenerate
|
||
|
|
||
|
endmodule : xpm_fifo_axis
|
||
|
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
//********************************************************************************************************************
|
||
|
|
||
|
|
||
|
(* XPM_MODULE = "TRUE", KEEP_HIERARCHY = "SOFT" *)
|
||
|
module xpm_fifo_axif
|
||
|
#(
|
||
|
parameter integer AXI_ID_WIDTH = 1,
|
||
|
parameter integer AXI_ADDR_WIDTH = 32,
|
||
|
parameter integer AXI_DATA_WIDTH = 32,
|
||
|
parameter integer AXI_LEN_WIDTH = 8,
|
||
|
parameter integer AXI_ARUSER_WIDTH = 1,
|
||
|
parameter integer AXI_AWUSER_WIDTH = 1,
|
||
|
parameter integer AXI_WUSER_WIDTH = 1,
|
||
|
parameter integer AXI_BUSER_WIDTH = 1,
|
||
|
parameter integer AXI_RUSER_WIDTH = 1,
|
||
|
parameter CLOCKING_MODE = "common",
|
||
|
parameter integer SIM_ASSERT_CHK = 0,
|
||
|
parameter integer CASCADE_HEIGHT = 0,
|
||
|
parameter integer CDC_SYNC_STAGES = 2,
|
||
|
parameter integer EN_RESET_SYNCHRONIZER = 0,
|
||
|
parameter PACKET_FIFO = "false",
|
||
|
parameter FIFO_MEMORY_TYPE_WACH = "lutram",
|
||
|
parameter FIFO_MEMORY_TYPE_WDCH = "bram",
|
||
|
parameter FIFO_MEMORY_TYPE_WRCH = "lutram",
|
||
|
parameter FIFO_MEMORY_TYPE_RACH = "lutram",
|
||
|
parameter FIFO_MEMORY_TYPE_RDCH = "bram",
|
||
|
parameter integer FIFO_DEPTH_WACH = 16,
|
||
|
parameter integer FIFO_DEPTH_WDCH = 16,
|
||
|
parameter integer FIFO_DEPTH_WRCH = 2048,
|
||
|
parameter integer FIFO_DEPTH_RACH = 16,
|
||
|
parameter integer FIFO_DEPTH_RDCH = 2048,
|
||
|
parameter ECC_MODE_WDCH = "no_ecc",
|
||
|
parameter ECC_MODE_RDCH = "no_ecc",
|
||
|
parameter USE_ADV_FEATURES_WDCH = "1000",
|
||
|
parameter USE_ADV_FEATURES_RDCH = "1000",
|
||
|
parameter integer WR_DATA_COUNT_WIDTH_WDCH = 10,
|
||
|
parameter integer WR_DATA_COUNT_WIDTH_RDCH = 10,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH_WDCH = 10,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH_RDCH = 10,
|
||
|
parameter integer PROG_FULL_THRESH_WDCH = 10,
|
||
|
parameter integer PROG_FULL_THRESH_RDCH = 10,
|
||
|
parameter integer PROG_EMPTY_THRESH_WDCH = 10,
|
||
|
parameter integer PROG_EMPTY_THRESH_RDCH = 10
|
||
|
|
||
|
)
|
||
|
(
|
||
|
// AXI Global Signal
|
||
|
input wire m_aclk,
|
||
|
input wire s_aclk,
|
||
|
input wire s_aresetn,
|
||
|
|
||
|
// AXI Full/Lite Slave Write Channel (write side)
|
||
|
input wire [AXI_ID_WIDTH-1:0] s_axi_awid,
|
||
|
input wire [AXI_ADDR_WIDTH-1:0] s_axi_awaddr,
|
||
|
input wire [AXI_LEN_WIDTH-1:0] s_axi_awlen,
|
||
|
input wire [3-1:0] s_axi_awsize,
|
||
|
input wire [2-1:0] s_axi_awburst,
|
||
|
input wire [2-1:0] s_axi_awlock,
|
||
|
input wire [4-1:0] s_axi_awcache,
|
||
|
input wire [3-1:0] s_axi_awprot,
|
||
|
input wire [4-1:0] s_axi_awqos,
|
||
|
input wire [4-1:0] s_axi_awregion,
|
||
|
input wire [AXI_AWUSER_WIDTH-1:0] s_axi_awuser,
|
||
|
input wire s_axi_awvalid,
|
||
|
output wire s_axi_awready,
|
||
|
input wire [AXI_DATA_WIDTH-1:0] s_axi_wdata,
|
||
|
input wire [AXI_DATA_WIDTH/8-1:0] s_axi_wstrb,
|
||
|
input wire s_axi_wlast,
|
||
|
input wire [AXI_WUSER_WIDTH-1:0] s_axi_wuser,
|
||
|
input wire s_axi_wvalid,
|
||
|
output wire s_axi_wready,
|
||
|
output wire [AXI_ID_WIDTH-1:0] s_axi_bid,
|
||
|
output wire [2-1:0] s_axi_bresp,
|
||
|
output wire [AXI_BUSER_WIDTH-1:0] s_axi_buser,
|
||
|
output wire s_axi_bvalid,
|
||
|
input wire s_axi_bready,
|
||
|
|
||
|
// AXI Full/Lite Master Write Channel (read side)
|
||
|
output wire [AXI_ID_WIDTH-1:0] m_axi_awid,
|
||
|
output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
||
|
output wire [AXI_LEN_WIDTH-1:0] m_axi_awlen,
|
||
|
output wire [3-1:0] m_axi_awsize,
|
||
|
output wire [2-1:0] m_axi_awburst,
|
||
|
output wire [2-1:0] m_axi_awlock,
|
||
|
output wire [4-1:0] m_axi_awcache,
|
||
|
output wire [3-1:0] m_axi_awprot,
|
||
|
output wire [4-1:0] m_axi_awqos,
|
||
|
output wire [4-1:0] m_axi_awregion,
|
||
|
output wire [AXI_AWUSER_WIDTH-1:0] m_axi_awuser,
|
||
|
output wire m_axi_awvalid,
|
||
|
input wire m_axi_awready,
|
||
|
output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
||
|
output wire [AXI_DATA_WIDTH/8-1:0] m_axi_wstrb,
|
||
|
output wire m_axi_wlast,
|
||
|
output wire [AXI_WUSER_WIDTH-1:0] m_axi_wuser,
|
||
|
output wire m_axi_wvalid,
|
||
|
input wire m_axi_wready,
|
||
|
input wire [AXI_ID_WIDTH-1:0] m_axi_bid,
|
||
|
input wire [2-1:0] m_axi_bresp,
|
||
|
input wire [AXI_BUSER_WIDTH-1:0] m_axi_buser,
|
||
|
input wire m_axi_bvalid,
|
||
|
output wire m_axi_bready,
|
||
|
|
||
|
// AXI Full/Lite Slave Read Channel (write side)
|
||
|
input wire [AXI_ID_WIDTH-1:0] s_axi_arid,
|
||
|
input wire [AXI_ADDR_WIDTH-1:0] s_axi_araddr,
|
||
|
input wire [AXI_LEN_WIDTH-1:0] s_axi_arlen,
|
||
|
input wire [3-1:0] s_axi_arsize,
|
||
|
input wire [2-1:0] s_axi_arburst,
|
||
|
input wire [2-1:0] s_axi_arlock,
|
||
|
input wire [4-1:0] s_axi_arcache,
|
||
|
input wire [3-1:0] s_axi_arprot,
|
||
|
input wire [4-1:0] s_axi_arqos,
|
||
|
input wire [4-1:0] s_axi_arregion,
|
||
|
input wire [AXI_ARUSER_WIDTH-1:0] s_axi_aruser,
|
||
|
input wire s_axi_arvalid,
|
||
|
output wire s_axi_arready,
|
||
|
output wire [AXI_ID_WIDTH-1:0] s_axi_rid,
|
||
|
output wire [AXI_DATA_WIDTH-1:0] s_axi_rdata,
|
||
|
output wire [2-1:0] s_axi_rresp,
|
||
|
output wire s_axi_rlast,
|
||
|
output wire [AXI_RUSER_WIDTH-1:0] s_axi_ruser,
|
||
|
output wire s_axi_rvalid,
|
||
|
input wire s_axi_rready,
|
||
|
|
||
|
// AXI Full/Lite Master Read Channel (read side)
|
||
|
output wire [AXI_ID_WIDTH-1:0] m_axi_arid,
|
||
|
output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
||
|
output wire [AXI_LEN_WIDTH-1:0] m_axi_arlen,
|
||
|
output wire [3-1:0] m_axi_arsize,
|
||
|
output wire [2-1:0] m_axi_arburst,
|
||
|
output wire [2-1:0] m_axi_arlock,
|
||
|
output wire [4-1:0] m_axi_arcache,
|
||
|
output wire [3-1:0] m_axi_arprot,
|
||
|
output wire [4-1:0] m_axi_arqos,
|
||
|
output wire [4-1:0] m_axi_arregion,
|
||
|
output wire [AXI_ARUSER_WIDTH-1:0] m_axi_aruser,
|
||
|
output wire m_axi_arvalid,
|
||
|
input wire m_axi_arready,
|
||
|
input wire [AXI_ID_WIDTH-1:0] m_axi_rid,
|
||
|
input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
||
|
input wire [2-1:0] m_axi_rresp,
|
||
|
input wire m_axi_rlast,
|
||
|
input wire [AXI_RUSER_WIDTH-1:0] m_axi_ruser,
|
||
|
input wire m_axi_rvalid,
|
||
|
output wire m_axi_rready,
|
||
|
|
||
|
// AXI4-Full Sideband Signals
|
||
|
output wire prog_full_wdch,
|
||
|
output wire prog_empty_wdch,
|
||
|
output wire [WR_DATA_COUNT_WIDTH_WDCH-1:0] wr_data_count_wdch,
|
||
|
output wire [RD_DATA_COUNT_WIDTH_WDCH-1:0] rd_data_count_wdch,
|
||
|
output wire prog_full_rdch,
|
||
|
output wire prog_empty_rdch,
|
||
|
output wire [WR_DATA_COUNT_WIDTH_RDCH-1:0] wr_data_count_rdch,
|
||
|
output wire [RD_DATA_COUNT_WIDTH_RDCH-1:0] rd_data_count_rdch,
|
||
|
|
||
|
// ECC Related ports
|
||
|
input wire injectsbiterr_wdch,
|
||
|
input wire injectdbiterr_wdch,
|
||
|
output wire sbiterr_wdch,
|
||
|
output wire dbiterr_wdch,
|
||
|
input wire injectsbiterr_rdch,
|
||
|
input wire injectdbiterr_rdch,
|
||
|
output wire sbiterr_rdch,
|
||
|
output wire dbiterr_rdch
|
||
|
|
||
|
);
|
||
|
|
||
|
|
||
|
// Function to convert ASCII value to binary
|
||
|
function [3:0] str2bin;
|
||
|
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])
|
||
|
str2bin = str_val_ascii[3:0];
|
||
|
else begin
|
||
|
str2bin [3] = 1'b1;
|
||
|
str2bin [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
||
|
str2bin [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
||
|
str2bin [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 [15:0] hstr2bin;
|
||
|
input [16*8-1 : 0] hstr_val;
|
||
|
integer rst_loop_a;
|
||
|
localparam integer rsta_loop_iter = 16;
|
||
|
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] = str2bin(hstr_val[(rst_loop_a*8)-1 -: 8]);
|
||
|
end
|
||
|
return rst_val_conv_a_i[15:0];
|
||
|
endfunction
|
||
|
|
||
|
//Function to convert binary to ASCII value
|
||
|
function [7:0] bin2str;
|
||
|
input [3:0] bin_val;
|
||
|
if( bin_val > 4'h9) begin
|
||
|
bin2str [7:4] = 4'h4;
|
||
|
bin2str [3] = 1'b0;
|
||
|
bin2str [2:0] = bin_val[2:0]-1'b1;
|
||
|
end
|
||
|
else begin
|
||
|
bin2str [7:4] = 4'h3;
|
||
|
bin2str [3:0] = bin_val;
|
||
|
end
|
||
|
endfunction
|
||
|
|
||
|
// Function that parses the complete binary value to string
|
||
|
function [31:0] bin2hstr;
|
||
|
input [15 : 0] bin_val;
|
||
|
integer str_pos;
|
||
|
localparam integer str_max_bits = 32;
|
||
|
for (str_pos=1; str_pos <= str_max_bits/8; str_pos = str_pos+1) begin
|
||
|
bin2hstr[(str_pos*8)-1 -: 8] = bin2str(bin_val[(str_pos*4)-1 -: 4]);
|
||
|
end
|
||
|
endfunction
|
||
|
|
||
|
//WDCH advanced features parameter conversion
|
||
|
localparam [15:0] EN_ADV_FEATURE_WDCH = hstr2bin(USE_ADV_FEATURES_WDCH);
|
||
|
localparam EN_ALMOST_FULL_INT_WDCH = (PACKET_FIFO == "true") ? 1'b1 : EN_ADV_FEATURE_WDCH[3];
|
||
|
localparam EN_ALMOST_EMPTY_INT_WDCH = (PACKET_FIFO == "true") ? 1'b1 : EN_ADV_FEATURE_WDCH[11];
|
||
|
localparam EN_DATA_VALID_INT = 1'b1;
|
||
|
localparam [15:0] EN_ADV_FEATURE_WDCH_INT = {EN_ADV_FEATURE_WDCH[15:13], EN_DATA_VALID_INT, EN_ALMOST_EMPTY_INT_WDCH, EN_ADV_FEATURE_WDCH[10:4], EN_ALMOST_FULL_INT_WDCH, EN_ADV_FEATURE_WDCH[2:0]};
|
||
|
localparam USE_ADV_FEATURES_WDCH_INT = bin2hstr(EN_ADV_FEATURE_WDCH_INT);
|
||
|
|
||
|
|
||
|
//RDCH advanced features parameter conversion
|
||
|
localparam [15:0] EN_ADV_FEATURE_RDCH = hstr2bin(USE_ADV_FEATURES_RDCH);
|
||
|
localparam EN_ALMOST_FULL_INT_RDCH = (PACKET_FIFO == "true") ? 1'b1 : EN_ADV_FEATURE_RDCH[3];
|
||
|
localparam EN_ALMOST_EMPTY_INT_RDCH = (PACKET_FIFO == "true") ? 1'b1 : EN_ADV_FEATURE_RDCH[11];
|
||
|
localparam [15:0] EN_ADV_FEATURE_RDCH_INT = {EN_ADV_FEATURE_RDCH[15:13], EN_DATA_VALID_INT, EN_ALMOST_EMPTY_INT_RDCH, EN_ADV_FEATURE_RDCH[10:4], EN_ALMOST_FULL_INT_RDCH, EN_ADV_FEATURE_RDCH[2:0]};
|
||
|
localparam USE_ADV_FEATURES_RDCH_INT = bin2hstr(EN_ADV_FEATURE_RDCH_INT);
|
||
|
|
||
|
|
||
|
localparam C_AXI_LOCK_WIDTH = 2;
|
||
|
// AXI Channel Type
|
||
|
// WACH --> Write Address Channel
|
||
|
// WDCH --> Write Data Channel
|
||
|
// WRCH --> Write Response Channel
|
||
|
// RACH --> Read Address Channel
|
||
|
// RDCH --> Read Data Channel
|
||
|
localparam C_WACH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logic
|
||
|
localparam C_WDCH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
localparam C_WRCH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
localparam C_RACH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
localparam C_RDCH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
|
||
|
// Input Data Width
|
||
|
// Accumulation of all AXI input signal's width
|
||
|
localparam C_DIN_WIDTH_WACH = AXI_ID_WIDTH+AXI_ADDR_WIDTH+AXI_AWUSER_WIDTH+AXI_LEN_WIDTH+C_AXI_LOCK_WIDTH+20;
|
||
|
localparam C_DIN_WIDTH_WDCH = AXI_DATA_WIDTH/8+AXI_DATA_WIDTH+AXI_WUSER_WIDTH+1;
|
||
|
localparam C_DIN_WIDTH_WRCH = AXI_ID_WIDTH+AXI_BUSER_WIDTH+2;
|
||
|
localparam C_DIN_WIDTH_RACH = AXI_ID_WIDTH+AXI_ADDR_WIDTH+AXI_ARUSER_WIDTH+AXI_LEN_WIDTH+C_AXI_LOCK_WIDTH+20;
|
||
|
localparam C_DIN_WIDTH_RDCH = AXI_ID_WIDTH+AXI_DATA_WIDTH+AXI_RUSER_WIDTH+3;
|
||
|
|
||
|
|
||
|
// Define local parameters for mapping with base file
|
||
|
localparam integer P_COMMON_CLOCK = ( (CLOCKING_MODE == "common_clock" || CLOCKING_MODE == "COMMON_CLOCK" || CLOCKING_MODE == "COMMON" || CLOCKING_MODE == "common") ? 1 :
|
||
|
( (CLOCKING_MODE == "independent_clock" || CLOCKING_MODE == "INDEPENDENT_CLOCK" || CLOCKING_MODE == "INDEPENDENT" || CLOCKING_MODE == "independent") ? 0 : 2));
|
||
|
|
||
|
localparam integer P_ECC_MODE_WDCH = ( (ECC_MODE_WDCH == "no_ecc" || ECC_MODE_WDCH == "NO_ECC" ) ? 0 : 1);
|
||
|
localparam integer P_ECC_MODE_RDCH = ( (ECC_MODE_RDCH == "no_ecc" || ECC_MODE_RDCH == "NO_ECC" ) ? 0 : 1);
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_WACH = ( (FIFO_MEMORY_TYPE_WACH == "lutram" || FIFO_MEMORY_TYPE_WACH == "LUTRAM" || FIFO_MEMORY_TYPE_WACH == "distributed" || FIFO_MEMORY_TYPE_WACH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_WACH == "blockram" || FIFO_MEMORY_TYPE_WACH == "BLOCKRAM" || FIFO_MEMORY_TYPE_WACH == "bram" || FIFO_MEMORY_TYPE_WACH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_WACH == "ultraram" || FIFO_MEMORY_TYPE_WACH == "ULTRARAM" || FIFO_MEMORY_TYPE_WACH == "uram" || FIFO_MEMORY_TYPE_WACH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_WACH == "builtin" || FIFO_MEMORY_TYPE_WACH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_WDCH = ( (FIFO_MEMORY_TYPE_WDCH == "lutram" || FIFO_MEMORY_TYPE_WDCH == "LUTRAM" || FIFO_MEMORY_TYPE_WDCH == "distributed" || FIFO_MEMORY_TYPE_WDCH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_WDCH == "blockram" || FIFO_MEMORY_TYPE_WDCH == "BLOCKRAM" || FIFO_MEMORY_TYPE_WDCH == "bram" || FIFO_MEMORY_TYPE_WDCH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_WDCH == "ultraram" || FIFO_MEMORY_TYPE_WDCH == "ULTRARAM" || FIFO_MEMORY_TYPE_WDCH == "uram" || FIFO_MEMORY_TYPE_WDCH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_WDCH == "builtin" || FIFO_MEMORY_TYPE_WDCH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_WRCH = ( (FIFO_MEMORY_TYPE_WRCH == "lutram" || FIFO_MEMORY_TYPE_WRCH == "LUTRAM" || FIFO_MEMORY_TYPE_WRCH == "distributed" || FIFO_MEMORY_TYPE_WRCH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_WRCH == "blockram" || FIFO_MEMORY_TYPE_WRCH == "BLOCKRAM" || FIFO_MEMORY_TYPE_WRCH == "bram" || FIFO_MEMORY_TYPE_WRCH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_WRCH == "ultraram" || FIFO_MEMORY_TYPE_WRCH == "ULTRARAM" || FIFO_MEMORY_TYPE_WRCH == "uram" || FIFO_MEMORY_TYPE_WRCH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_WRCH == "builtin" || FIFO_MEMORY_TYPE_WRCH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_RACH = ( (FIFO_MEMORY_TYPE_RACH == "lutram" || FIFO_MEMORY_TYPE_RACH == "LUTRAM" || FIFO_MEMORY_TYPE_RACH == "distributed" || FIFO_MEMORY_TYPE_RACH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_RACH == "blockram" || FIFO_MEMORY_TYPE_RACH == "BLOCKRAM" || FIFO_MEMORY_TYPE_RACH == "bram" || FIFO_MEMORY_TYPE_RACH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_RACH == "ultraram" || FIFO_MEMORY_TYPE_RACH == "ULTRARAM" || FIFO_MEMORY_TYPE_RACH == "uram" || FIFO_MEMORY_TYPE_RACH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_RACH == "builtin" || FIFO_MEMORY_TYPE_RACH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_RDCH = ( (FIFO_MEMORY_TYPE_RDCH == "lutram" || FIFO_MEMORY_TYPE_RDCH == "LUTRAM" || FIFO_MEMORY_TYPE_RDCH == "distributed" || FIFO_MEMORY_TYPE_RDCH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_RDCH == "blockram" || FIFO_MEMORY_TYPE_RDCH == "BLOCKRAM" || FIFO_MEMORY_TYPE_RDCH == "bram" || FIFO_MEMORY_TYPE_RDCH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_RDCH == "ultraram" || FIFO_MEMORY_TYPE_RDCH == "ULTRARAM" || FIFO_MEMORY_TYPE_RDCH == "uram" || FIFO_MEMORY_TYPE_RDCH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_RDCH == "builtin" || FIFO_MEMORY_TYPE_RDCH == "BUILTIN") ? 4 : 0))));
|
||
|
|
||
|
|
||
|
localparam C_DIN_WIDTH_WDCH_ECC = (P_ECC_MODE_WDCH == 0) ? C_DIN_WIDTH_WDCH : ((C_DIN_WIDTH_WDCH%64 == 0) ? C_DIN_WIDTH_WDCH : (64*(C_DIN_WIDTH_WDCH/64+1)));
|
||
|
localparam C_DIN_WIDTH_RDCH_ECC = (P_ECC_MODE_RDCH == 0) ? C_DIN_WIDTH_RDCH : ((C_DIN_WIDTH_RDCH%64 == 0) ? C_DIN_WIDTH_RDCH : (64*(C_DIN_WIDTH_RDCH/64+1)));
|
||
|
|
||
|
|
||
|
wire wr_rst_busy_wach;
|
||
|
wire wr_rst_busy_wdch;
|
||
|
wire wr_rst_busy_wrch;
|
||
|
wire wr_rst_busy_rach;
|
||
|
wire wr_rst_busy_rdch;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
localparam C_AXI_SIZE_WIDTH = 3;
|
||
|
localparam C_AXI_BURST_WIDTH = 2;
|
||
|
localparam C_AXI_CACHE_WIDTH = 4;
|
||
|
localparam C_AXI_PROT_WIDTH = 3;
|
||
|
localparam C_AXI_QOS_WIDTH = 4;
|
||
|
localparam C_AXI_REGION_WIDTH = 4;
|
||
|
localparam C_AXI_BRESP_WIDTH = 2;
|
||
|
localparam C_AXI_RRESP_WIDTH = 2;
|
||
|
|
||
|
|
||
|
wire inverted_reset = ~s_aresetn;
|
||
|
wire rst_axif_sclk;
|
||
|
wire rst_axif_mclk;
|
||
|
wire m_aclk_int;
|
||
|
assign m_aclk_int = P_COMMON_CLOCK ? s_aclk : m_aclk;
|
||
|
|
||
|
generate
|
||
|
if (EN_RESET_SYNCHRONIZER == 1) begin : gen_sync_reset
|
||
|
//Reset Synchronizer
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (P_COMMON_CLOCK ? 4 : CDC_SYNC_STAGES),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0)
|
||
|
) xpm_cdc_sync_rst_sclk_inst (
|
||
|
.src_rst (~s_aresetn),
|
||
|
.dest_clk (s_aclk),
|
||
|
.dest_rst (rst_axif_sclk)
|
||
|
);
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (P_COMMON_CLOCK ? 4 : CDC_SYNC_STAGES),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0)
|
||
|
) xpm_cdc_sync_rst_mclk_inst (
|
||
|
.src_rst (~s_aresetn),
|
||
|
.dest_clk (m_aclk_int),
|
||
|
.dest_rst (rst_axif_mclk)
|
||
|
);
|
||
|
end // gen_sync_reset
|
||
|
if (EN_RESET_SYNCHRONIZER == 0) begin : gen_async_reset
|
||
|
assign rst_axif_sclk = inverted_reset;
|
||
|
assign rst_axif_mclk = inverted_reset;
|
||
|
|
||
|
end // gen_async_reset
|
||
|
endgenerate
|
||
|
|
||
|
|
||
|
//###########################################################################
|
||
|
// AXI FULL Write Channel (axi_write_channel)
|
||
|
//###########################################################################
|
||
|
|
||
|
|
||
|
localparam IS_AXI_FULL_WACH = ((C_WACH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_FULL_WDCH = ((C_WDCH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_FULL_WRCH = ((C_WRCH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_FULL_RACH = ((C_RACH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_FULL_RDCH = ((C_RDCH_TYPE == 0)) ? 1 : 0;
|
||
|
|
||
|
localparam IS_WR_ADDR_CH = (IS_AXI_FULL_WACH == 1) ? 1 : 0;
|
||
|
localparam IS_WR_DATA_CH = (IS_AXI_FULL_WDCH == 1) ? 1 : 0;
|
||
|
localparam IS_WR_RESP_CH = (IS_AXI_FULL_WRCH == 1) ? 1 : 0;
|
||
|
localparam IS_RD_ADDR_CH = (IS_AXI_FULL_RACH == 1) ? 1 : 0;
|
||
|
localparam IS_RD_DATA_CH = (IS_AXI_FULL_RDCH == 1) ? 1 : 0;
|
||
|
|
||
|
localparam AWID_OFFSET = C_DIN_WIDTH_WACH - AXI_ID_WIDTH ;
|
||
|
localparam AWADDR_OFFSET = AWID_OFFSET - AXI_ADDR_WIDTH;
|
||
|
localparam AWLEN_OFFSET = AWADDR_OFFSET - AXI_LEN_WIDTH ;
|
||
|
localparam AWSIZE_OFFSET = AWLEN_OFFSET - C_AXI_SIZE_WIDTH ;
|
||
|
localparam AWBURST_OFFSET = AWSIZE_OFFSET - C_AXI_BURST_WIDTH ;
|
||
|
localparam AWLOCK_OFFSET = AWBURST_OFFSET - C_AXI_LOCK_WIDTH ;
|
||
|
localparam AWCACHE_OFFSET = AWLOCK_OFFSET - C_AXI_CACHE_WIDTH ;
|
||
|
localparam AWPROT_OFFSET = AWCACHE_OFFSET - C_AXI_PROT_WIDTH;
|
||
|
localparam AWQOS_OFFSET = AWPROT_OFFSET - C_AXI_QOS_WIDTH;
|
||
|
localparam AWREGION_OFFSET = AWQOS_OFFSET - C_AXI_REGION_WIDTH ;
|
||
|
localparam AWUSER_OFFSET = AWREGION_OFFSET-AXI_AWUSER_WIDTH ;
|
||
|
|
||
|
localparam WID_OFFSET = C_DIN_WIDTH_WDCH;
|
||
|
localparam WDATA_OFFSET = WID_OFFSET - AXI_DATA_WIDTH;
|
||
|
localparam WSTRB_OFFSET = WDATA_OFFSET - AXI_DATA_WIDTH/8;
|
||
|
localparam WUSER_OFFSET = WSTRB_OFFSET-AXI_WUSER_WIDTH ;
|
||
|
|
||
|
localparam BID_OFFSET = C_DIN_WIDTH_WRCH - AXI_ID_WIDTH ;
|
||
|
localparam BRESP_OFFSET = BID_OFFSET - C_AXI_BRESP_WIDTH;
|
||
|
localparam BUSER_OFFSET = BRESP_OFFSET-AXI_BUSER_WIDTH;
|
||
|
|
||
|
|
||
|
wire [C_DIN_WIDTH_WACH-1:0] wach_din ;
|
||
|
wire [C_DIN_WIDTH_WACH-1:0] wach_dout ;
|
||
|
wire [C_DIN_WIDTH_WACH-1:0] wach_dout_pkt ;
|
||
|
wire wach_full ;
|
||
|
wire wach_almost_full ;
|
||
|
wire wach_prog_full ;
|
||
|
wire wach_empty ;
|
||
|
wire wach_almost_empty ;
|
||
|
wire wach_prog_empty ;
|
||
|
wire [C_DIN_WIDTH_WDCH_ECC-1:0] wdch_din ;
|
||
|
wire [C_DIN_WIDTH_WDCH_ECC-1:0] wdch_dout ;
|
||
|
wire wdch_full ;
|
||
|
wire wdch_almost_full ;
|
||
|
wire wdch_prog_full ;
|
||
|
wire wdch_empty ;
|
||
|
wire wdch_almost_empty ;
|
||
|
wire wdch_prog_empty ;
|
||
|
wire [C_DIN_WIDTH_WRCH-1:0] wrch_din ;
|
||
|
wire [C_DIN_WIDTH_WRCH-1:0] wrch_dout ;
|
||
|
wire wrch_full ;
|
||
|
wire wrch_almost_full ;
|
||
|
wire wrch_prog_full ;
|
||
|
wire wrch_empty ;
|
||
|
wire wrch_almost_empty ;
|
||
|
wire wrch_prog_empty ;
|
||
|
wire axi_aw_underflow_i;
|
||
|
wire axi_w_underflow_i ;
|
||
|
wire axi_b_underflow_i ;
|
||
|
wire axi_aw_overflow_i ;
|
||
|
wire axi_w_overflow_i ;
|
||
|
wire axi_b_overflow_i ;
|
||
|
wire wach_s_axi_awready;
|
||
|
wire wach_m_axi_awvalid;
|
||
|
wire wach_rd_en ;
|
||
|
wire wdch_s_axi_wready ;
|
||
|
wire wdch_m_axi_wvalid ;
|
||
|
wire wdch_wr_en ;
|
||
|
wire wdch_rd_en ;
|
||
|
wire wrch_s_axi_bvalid ;
|
||
|
wire wrch_m_axi_bready ;
|
||
|
wire txn_count_up ;
|
||
|
wire txn_count_down ;
|
||
|
wire awvalid_en ;
|
||
|
wire awvalid_pkt ;
|
||
|
wire awready_pkt ;
|
||
|
integer wr_pkt_count ;
|
||
|
wire wach_re ;
|
||
|
wire wdch_we ;
|
||
|
wire wdch_re ;
|
||
|
|
||
|
generate if (IS_WR_ADDR_CH == 1) begin : axi_write_address_channel
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign wach_re = (PACKET_FIFO == "true") ? awready_pkt & awvalid_en : m_axi_awready;
|
||
|
assign wach_rd_en = wach_re;
|
||
|
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_WACH),
|
||
|
.ECC_MODE (0),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_WACH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_WACH ),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES ("0101"),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_WACH ),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_wach_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axif_sclk),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (s_axi_awvalid),
|
||
|
.din (wach_din),
|
||
|
.full (wach_full),
|
||
|
.full_n (),
|
||
|
.prog_full (),
|
||
|
.wr_data_count (),
|
||
|
.overflow (axi_aw_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_wach),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (m_aclk_int),
|
||
|
.rd_en (wach_rd_en),
|
||
|
.dout (wach_dout_pkt),
|
||
|
.empty (wach_empty),
|
||
|
.prog_empty (),
|
||
|
.rd_data_count (),
|
||
|
.underflow (axi_aw_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (1'b0),
|
||
|
.injectdbiterr (1'b0),
|
||
|
.sbiterr (),
|
||
|
.dbiterr ()
|
||
|
);
|
||
|
|
||
|
assign wach_s_axi_awready = (FIFO_MEMORY_TYPE_WACH == "lutram") ? ~(wach_full | wr_rst_busy_wach) : ~wach_full;
|
||
|
assign wach_m_axi_awvalid = ~wach_empty;
|
||
|
assign s_axi_awready = wach_s_axi_awready;
|
||
|
|
||
|
|
||
|
end endgenerate // axi_write_address_channel
|
||
|
|
||
|
|
||
|
generate if (PACKET_FIFO == "true") begin : axi_mm_pkt_fifo_wr
|
||
|
|
||
|
xpm_fifo_axi_reg_slice
|
||
|
#(
|
||
|
.C_DATA_WIDTH (C_DIN_WIDTH_WACH),
|
||
|
.C_REG_CONFIG (1)
|
||
|
)
|
||
|
wach_pkt_reg_slice_inst
|
||
|
(
|
||
|
// System Signals
|
||
|
.ACLK (s_aclk),
|
||
|
.ARESET (rst_axif_sclk),
|
||
|
|
||
|
// Slave side
|
||
|
.S_PAYLOAD_DATA (wach_dout_pkt),
|
||
|
.S_VALID (awvalid_pkt),
|
||
|
.S_READY (awready_pkt),
|
||
|
|
||
|
// Master side
|
||
|
.M_PAYLOAD_DATA (wach_dout),
|
||
|
.M_VALID (m_axi_awvalid),
|
||
|
.M_READY (m_axi_awready)
|
||
|
);
|
||
|
|
||
|
assign awvalid_pkt = wach_m_axi_awvalid && awvalid_en;
|
||
|
|
||
|
assign txn_count_up = wdch_s_axi_wready && wdch_wr_en && wdch_din[0];
|
||
|
assign txn_count_down = wach_m_axi_awvalid && awready_pkt && awvalid_en;
|
||
|
|
||
|
always@(posedge s_aclk ) begin
|
||
|
if(rst_axif_sclk == 1) begin
|
||
|
wr_pkt_count <= 0;
|
||
|
end else begin
|
||
|
if(txn_count_up == 1 && txn_count_down == 0) begin
|
||
|
wr_pkt_count <= wr_pkt_count + 1;
|
||
|
end else if(txn_count_up == 0 && txn_count_down == 1) begin
|
||
|
wr_pkt_count <= wr_pkt_count - 1;
|
||
|
end
|
||
|
end
|
||
|
end //Always end
|
||
|
assign awvalid_en = (wr_pkt_count > 0)? 1:0;
|
||
|
end endgenerate
|
||
|
|
||
|
generate if (PACKET_FIFO == "false") begin : axi_mm_fifo_wr
|
||
|
assign awvalid_en = 1;
|
||
|
assign wach_dout = wach_dout_pkt;
|
||
|
assign m_axi_awvalid = wach_m_axi_awvalid;
|
||
|
end
|
||
|
endgenerate
|
||
|
|
||
|
|
||
|
|
||
|
generate if (IS_WR_DATA_CH == 1) begin : axi_write_data_channel
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
assign wdch_we = wdch_s_axi_wready & s_axi_wvalid ;
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign wdch_re = wdch_m_axi_wvalid & m_axi_wready ;
|
||
|
assign wdch_wr_en = wdch_we;
|
||
|
assign wdch_rd_en = wdch_re;
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_WDCH),
|
||
|
.ECC_MODE (P_ECC_MODE_WDCH),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_WDCH),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_WDCH_ECC),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH_WDCH),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH_WDCH),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES_WDCH_INT),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_WDCH_ECC),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH_WDCH),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH_WDCH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_wdch_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axif_sclk),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (wdch_wr_en),
|
||
|
.din (wdch_din),
|
||
|
.full (wdch_full),
|
||
|
.full_n (),
|
||
|
.prog_full (prog_full_wdch),
|
||
|
.wr_data_count (wr_data_count_wdch),
|
||
|
.overflow (axi_w_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_wdch),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (m_aclk_int),
|
||
|
.rd_en (wdch_rd_en),
|
||
|
.dout (wdch_dout),
|
||
|
.empty (wdch_empty),
|
||
|
.prog_empty (prog_empty_wdch),
|
||
|
.rd_data_count (rd_data_count_wdch),
|
||
|
.underflow (axi_w_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (injectsbiterr_wdch),
|
||
|
.injectdbiterr (injectdbiterr_wdch),
|
||
|
.sbiterr (sbiterr_wdch),
|
||
|
.dbiterr (dbiterr_wdch)
|
||
|
);
|
||
|
|
||
|
|
||
|
assign wdch_s_axi_wready = (FIFO_MEMORY_TYPE_WDCH == "lutram") ? ~(wdch_full | wr_rst_busy_wdch) : ~wdch_full;
|
||
|
assign wdch_m_axi_wvalid = ~wdch_empty;
|
||
|
assign s_axi_wready = wdch_s_axi_wready;
|
||
|
assign m_axi_wvalid = wdch_m_axi_wvalid;
|
||
|
|
||
|
|
||
|
end endgenerate // axi_write_data_channel
|
||
|
|
||
|
|
||
|
generate if (IS_WR_RESP_CH == 1) begin : axi_write_resp_channel
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_WRCH),
|
||
|
.ECC_MODE (0),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_WRCH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_WRCH),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES ("0101"),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_WRCH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_wrch_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axif_mclk),
|
||
|
.wr_clk (m_aclk_int),
|
||
|
.wr_en (m_axi_bvalid),
|
||
|
.din (wrch_din),
|
||
|
.full (wrch_full),
|
||
|
.full_n (),
|
||
|
.prog_full (),
|
||
|
.wr_data_count (),
|
||
|
.overflow (axi_b_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_wrch),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (s_aclk),
|
||
|
.rd_en (s_axi_bready),
|
||
|
.dout (wrch_dout),
|
||
|
.empty (wrch_empty),
|
||
|
.prog_empty (),
|
||
|
.rd_data_count (),
|
||
|
.underflow (axi_b_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (1'b0),
|
||
|
.injectdbiterr (1'b0),
|
||
|
.sbiterr (),
|
||
|
.dbiterr ()
|
||
|
);
|
||
|
|
||
|
assign wrch_s_axi_bvalid = ~wrch_empty;
|
||
|
assign wrch_m_axi_bready = (FIFO_MEMORY_TYPE_WRCH == "lutram") ? ~(wrch_full | wr_rst_busy_wrch) : ~wrch_full;
|
||
|
assign s_axi_bvalid = wrch_s_axi_bvalid;
|
||
|
assign m_axi_bready = wrch_m_axi_bready;
|
||
|
|
||
|
end endgenerate // axi_write_resp_channel
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
generate if (IS_AXI_FULL_WACH == 1 || (C_WACH_TYPE == 1)) begin : axi_wach_output
|
||
|
assign m_axi_awaddr = wach_dout[AWID_OFFSET-1:AWADDR_OFFSET];
|
||
|
assign m_axi_awlen = wach_dout[AWADDR_OFFSET-1:AWLEN_OFFSET];
|
||
|
assign m_axi_awsize = wach_dout[AWLEN_OFFSET-1:AWSIZE_OFFSET];
|
||
|
assign m_axi_awburst = wach_dout[AWSIZE_OFFSET-1:AWBURST_OFFSET];
|
||
|
assign m_axi_awlock = wach_dout[AWBURST_OFFSET-1:AWLOCK_OFFSET];
|
||
|
assign m_axi_awcache = wach_dout[AWLOCK_OFFSET-1:AWCACHE_OFFSET];
|
||
|
assign m_axi_awprot = wach_dout[AWCACHE_OFFSET-1:AWPROT_OFFSET];
|
||
|
assign m_axi_awqos = wach_dout[AWPROT_OFFSET-1:AWQOS_OFFSET];
|
||
|
assign wach_din[AWID_OFFSET-1:AWADDR_OFFSET] = s_axi_awaddr;
|
||
|
assign wach_din[AWADDR_OFFSET-1:AWLEN_OFFSET] = s_axi_awlen;
|
||
|
assign wach_din[AWLEN_OFFSET-1:AWSIZE_OFFSET] = s_axi_awsize;
|
||
|
assign wach_din[AWSIZE_OFFSET-1:AWBURST_OFFSET] = s_axi_awburst;
|
||
|
assign wach_din[AWBURST_OFFSET-1:AWLOCK_OFFSET] = s_axi_awlock;
|
||
|
assign wach_din[AWLOCK_OFFSET-1:AWCACHE_OFFSET] = s_axi_awcache;
|
||
|
assign wach_din[AWCACHE_OFFSET-1:AWPROT_OFFSET] = s_axi_awprot;
|
||
|
assign wach_din[AWPROT_OFFSET-1:AWQOS_OFFSET] = s_axi_awqos;
|
||
|
end endgenerate // axi_wach_output
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WACH == 1 || (C_WACH_TYPE == 1))) begin : axi_awregion
|
||
|
assign m_axi_awregion = wach_dout[AWQOS_OFFSET-1:AWREGION_OFFSET];
|
||
|
end endgenerate // axi_awregion
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WACH == 1 || (C_WACH_TYPE == 1))) begin : axi_awuser
|
||
|
assign m_axi_awuser = wach_dout[AWREGION_OFFSET-1:AWUSER_OFFSET];
|
||
|
end endgenerate // axi_awuser
|
||
|
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WACH == 1 || (C_WACH_TYPE == 1))) begin : axi_awid
|
||
|
assign m_axi_awid = wach_dout[C_DIN_WIDTH_WACH-1:AWID_OFFSET];
|
||
|
end endgenerate //axi_awid
|
||
|
|
||
|
generate if (IS_AXI_FULL_WDCH == 1 || (C_WDCH_TYPE == 1)) begin : axi_wdch_output
|
||
|
assign m_axi_wdata = wdch_dout[WID_OFFSET-1:WDATA_OFFSET];
|
||
|
assign m_axi_wstrb = wdch_dout[WDATA_OFFSET-1:WSTRB_OFFSET];
|
||
|
assign m_axi_wlast = wdch_dout[0];
|
||
|
assign wdch_din[WID_OFFSET-1:WDATA_OFFSET] = s_axi_wdata;
|
||
|
assign wdch_din[WDATA_OFFSET-1:WSTRB_OFFSET] = s_axi_wstrb;
|
||
|
assign wdch_din[0] = s_axi_wlast;
|
||
|
end endgenerate // axi_wdch_output
|
||
|
|
||
|
// generate if ((IS_AXI_FULL_WDCH == 1 || (C_WDCH_TYPE == 1)) ) begin
|
||
|
// assign m_axi_wid = 0;
|
||
|
// end endgenerate
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WDCH == 1 || (C_WDCH_TYPE == 1))) begin
|
||
|
assign m_axi_wuser = wdch_dout[WSTRB_OFFSET-1:WUSER_OFFSET];
|
||
|
end endgenerate
|
||
|
|
||
|
generate if (IS_AXI_FULL_WRCH == 1 || (C_WRCH_TYPE == 1)) begin : axi_wrch_output
|
||
|
assign s_axi_bresp = wrch_dout[BID_OFFSET-1:BRESP_OFFSET];
|
||
|
assign wrch_din[BID_OFFSET-1:BRESP_OFFSET] = m_axi_bresp;
|
||
|
end endgenerate // axi_wrch_output
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WRCH == 1 || (C_WRCH_TYPE == 1))) begin : axi_buser
|
||
|
assign s_axi_buser = wrch_dout[BRESP_OFFSET-1:BUSER_OFFSET];
|
||
|
end endgenerate // axi_buser
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WRCH == 1 || ( C_WRCH_TYPE == 1))) begin : axi_bid
|
||
|
assign s_axi_bid = wrch_dout[C_DIN_WIDTH_WRCH-1:BID_OFFSET];
|
||
|
end endgenerate // axi_bid
|
||
|
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WACH == 1 || ( C_WACH_TYPE == 1))) begin : gwach_din1
|
||
|
assign wach_din[AWREGION_OFFSET-1:AWUSER_OFFSET] = s_axi_awuser;
|
||
|
end endgenerate // gwach_din1
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WACH == 1 || ( C_WACH_TYPE == 1))) begin : gwach_din2
|
||
|
assign wach_din[C_DIN_WIDTH_WACH-1:AWID_OFFSET] = s_axi_awid;
|
||
|
end endgenerate // gwach_din2
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WACH == 1 || ( C_WACH_TYPE == 1))) begin : gwach_din3
|
||
|
assign wach_din[AWQOS_OFFSET-1:AWREGION_OFFSET] = s_axi_awregion;
|
||
|
end endgenerate // gwach_din3
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WDCH == 1 || ( C_WDCH_TYPE == 1))) begin : gwdch_din1
|
||
|
assign wdch_din[WSTRB_OFFSET-1:WUSER_OFFSET] = s_axi_wuser;
|
||
|
end endgenerate // gwdch_din1
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WRCH == 1 || ( C_WRCH_TYPE == 1))) begin : gwrch_din1
|
||
|
assign wrch_din[BRESP_OFFSET-1:BUSER_OFFSET] = m_axi_buser;
|
||
|
end endgenerate // gwrch_din1
|
||
|
|
||
|
generate if ((IS_AXI_FULL_WRCH == 1 || ( C_WRCH_TYPE == 1))) begin : gwrch_din2
|
||
|
assign wrch_din[C_DIN_WIDTH_WRCH-1:BID_OFFSET] = m_axi_bid;
|
||
|
end endgenerate // gwrch_din2
|
||
|
|
||
|
//end of axi_write_channel
|
||
|
|
||
|
//###########################################################################
|
||
|
// AXI FULL Read Channel (axi_read_channel)
|
||
|
//###########################################################################
|
||
|
wire [C_DIN_WIDTH_RACH-1:0] rach_din ;
|
||
|
wire [C_DIN_WIDTH_RACH-1:0] rach_dout ;
|
||
|
wire [C_DIN_WIDTH_RACH-1:0] rach_dout_pkt ;
|
||
|
wire rach_full ;
|
||
|
wire rach_almost_full ;
|
||
|
wire rach_prog_full ;
|
||
|
wire rach_empty ;
|
||
|
wire rach_almost_empty ;
|
||
|
wire rach_prog_empty ;
|
||
|
wire [C_DIN_WIDTH_RDCH_ECC-1:0] rdch_din ;
|
||
|
wire [C_DIN_WIDTH_RDCH_ECC-1:0] rdch_dout ;
|
||
|
wire rdch_full ;
|
||
|
wire rdch_almost_full ;
|
||
|
wire rdch_prog_full ;
|
||
|
wire rdch_empty ;
|
||
|
wire rdch_almost_empty ;
|
||
|
wire rdch_prog_empty ;
|
||
|
wire axi_ar_underflow_i ;
|
||
|
wire axi_r_underflow_i ;
|
||
|
wire axi_ar_overflow_i ;
|
||
|
wire axi_r_overflow_i ;
|
||
|
wire rach_s_axi_arready ;
|
||
|
wire rach_m_axi_arvalid ;
|
||
|
wire rach_rd_en ;
|
||
|
wire rdch_m_axi_rready ;
|
||
|
wire rdch_s_axi_rvalid ;
|
||
|
wire rdch_wr_en ;
|
||
|
wire rdch_rd_en ;
|
||
|
wire arvalid_pkt ;
|
||
|
wire arready_pkt ;
|
||
|
wire arvalid_en ;
|
||
|
wire rdch_rd_ok ;
|
||
|
wire accept_next_pkt ;
|
||
|
integer rdch_free_space ;
|
||
|
integer rdch_commited_space ;
|
||
|
wire rach_re ;
|
||
|
wire rdch_we ;
|
||
|
wire rdch_re ;
|
||
|
|
||
|
localparam ARID_OFFSET = C_DIN_WIDTH_RACH - AXI_ID_WIDTH ;
|
||
|
localparam ARADDR_OFFSET = ARID_OFFSET - AXI_ADDR_WIDTH;
|
||
|
localparam ARLEN_OFFSET = ARADDR_OFFSET - AXI_LEN_WIDTH ;
|
||
|
localparam ARSIZE_OFFSET = ARLEN_OFFSET - C_AXI_SIZE_WIDTH ;
|
||
|
localparam ARBURST_OFFSET = ARSIZE_OFFSET - C_AXI_BURST_WIDTH ;
|
||
|
localparam ARLOCK_OFFSET = ARBURST_OFFSET - C_AXI_LOCK_WIDTH ;
|
||
|
localparam ARCACHE_OFFSET = ARLOCK_OFFSET - C_AXI_CACHE_WIDTH ;
|
||
|
localparam ARPROT_OFFSET = ARCACHE_OFFSET - C_AXI_PROT_WIDTH;
|
||
|
localparam ARQOS_OFFSET = ARPROT_OFFSET - C_AXI_QOS_WIDTH;
|
||
|
localparam ARREGION_OFFSET = ARQOS_OFFSET - C_AXI_REGION_WIDTH ;
|
||
|
localparam ARUSER_OFFSET = ARREGION_OFFSET-AXI_ARUSER_WIDTH;
|
||
|
|
||
|
localparam RID_OFFSET = C_DIN_WIDTH_RDCH - AXI_ID_WIDTH ;
|
||
|
localparam RDATA_OFFSET = RID_OFFSET - AXI_DATA_WIDTH;
|
||
|
localparam RRESP_OFFSET = RDATA_OFFSET - C_AXI_RRESP_WIDTH;
|
||
|
localparam RUSER_OFFSET = RRESP_OFFSET-AXI_RUSER_WIDTH;
|
||
|
|
||
|
generate begin : xpm_fifo_rd_chnl
|
||
|
if (IS_RD_ADDR_CH == 1) begin : axi_read_addr_channel
|
||
|
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign rach_re = (PACKET_FIFO == "true") ? arready_pkt & arvalid_en : m_axi_arready;
|
||
|
assign rach_rd_en = rach_re;
|
||
|
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_RACH),
|
||
|
.ECC_MODE (0),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_RACH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES ("0101"),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_rach_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axif_sclk),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (s_axi_arvalid),
|
||
|
.din (rach_din),
|
||
|
.full (rach_full),
|
||
|
.full_n (),
|
||
|
.prog_full (),
|
||
|
.wr_data_count (),
|
||
|
.overflow (axi_ar_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_rach),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (m_aclk_int),
|
||
|
.rd_en (rach_rd_en),
|
||
|
.dout (rach_dout_pkt),
|
||
|
.empty (rach_empty),
|
||
|
.prog_empty (),
|
||
|
.rd_data_count (),
|
||
|
.underflow (axi_ar_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (1'b0),
|
||
|
.injectdbiterr (1'b0),
|
||
|
.sbiterr (),
|
||
|
.dbiterr ()
|
||
|
);
|
||
|
|
||
|
|
||
|
assign rach_s_axi_arready = (FIFO_MEMORY_TYPE_RACH == "lutram") ? ~(rach_full | wr_rst_busy_rach) : ~rach_full;
|
||
|
assign rach_m_axi_arvalid = ~rach_empty;
|
||
|
assign s_axi_arready = rach_s_axi_arready;
|
||
|
|
||
|
|
||
|
end : axi_read_addr_channel
|
||
|
|
||
|
|
||
|
// Register Slice for Read Address Channel for MM Packet FIFO
|
||
|
if (C_RACH_TYPE == 0 && (PACKET_FIFO == "true")) begin : grach_reg_slice_mm_pkt_fifo
|
||
|
|
||
|
xpm_fifo_axi_reg_slice
|
||
|
#(
|
||
|
.C_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
||
|
.C_REG_CONFIG (1)
|
||
|
)
|
||
|
reg_slice_mm_pkt_fifo_inst
|
||
|
(
|
||
|
// System Signals
|
||
|
.ACLK (s_aclk),
|
||
|
.ARESET (rst_axif_sclk),
|
||
|
|
||
|
// Slave side
|
||
|
.S_PAYLOAD_DATA (rach_dout_pkt),
|
||
|
.S_VALID (arvalid_pkt),
|
||
|
.S_READY (arready_pkt),
|
||
|
|
||
|
// Master side
|
||
|
.M_PAYLOAD_DATA (rach_dout),
|
||
|
.M_VALID (m_axi_arvalid),
|
||
|
.M_READY (m_axi_arready)
|
||
|
);
|
||
|
end : grach_reg_slice_mm_pkt_fifo
|
||
|
|
||
|
|
||
|
if (C_RACH_TYPE == 0 && (PACKET_FIFO == "false")) begin : grach_m_axi_arvalid
|
||
|
assign m_axi_arvalid = rach_m_axi_arvalid;
|
||
|
assign rach_dout = rach_dout_pkt;
|
||
|
end : grach_m_axi_arvalid
|
||
|
|
||
|
|
||
|
if (PACKET_FIFO == "true") begin : axi_mm_pkt_fifo_rd
|
||
|
assign rdch_rd_ok = rdch_s_axi_rvalid && rdch_rd_en;
|
||
|
assign arvalid_pkt = rach_m_axi_arvalid && arvalid_en;
|
||
|
assign accept_next_pkt = rach_m_axi_arvalid && arready_pkt && arvalid_en;
|
||
|
|
||
|
always@(posedge s_aclk ) begin
|
||
|
if(rst_axif_sclk) begin
|
||
|
rdch_commited_space <= 0;
|
||
|
end else begin
|
||
|
if(rdch_rd_ok && !accept_next_pkt) begin
|
||
|
rdch_commited_space <= rdch_commited_space-1;
|
||
|
end else if(!rdch_rd_ok && accept_next_pkt) begin
|
||
|
rdch_commited_space <= rdch_commited_space+(rach_dout_pkt[ARADDR_OFFSET-1:ARLEN_OFFSET]+1);
|
||
|
end else if(rdch_rd_ok && accept_next_pkt) begin
|
||
|
rdch_commited_space <= rdch_commited_space+(rach_dout_pkt[ARADDR_OFFSET-1:ARLEN_OFFSET]);
|
||
|
end
|
||
|
end
|
||
|
end //Always end
|
||
|
|
||
|
always@(*) begin
|
||
|
rdch_free_space <= (FIFO_DEPTH_RDCH -(rdch_commited_space+rach_dout_pkt[ARADDR_OFFSET-1:ARLEN_OFFSET]+1));
|
||
|
end
|
||
|
|
||
|
assign arvalid_en = (rdch_free_space >= 0)? 1:0;
|
||
|
end : axi_mm_pkt_fifo_rd
|
||
|
|
||
|
if (PACKET_FIFO == "false") begin : axi_mm_fifo_rd
|
||
|
assign arvalid_en = 1;
|
||
|
end :axi_mm_fifo_rd
|
||
|
|
||
|
if (IS_RD_DATA_CH == 1) begin : axi_read_data_channel
|
||
|
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
assign rdch_we = rdch_m_axi_rready & m_axi_rvalid ;
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign rdch_re = rdch_s_axi_rvalid & s_axi_rready;
|
||
|
assign rdch_wr_en = rdch_we;
|
||
|
assign rdch_rd_en = rdch_re;
|
||
|
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_RDCH),
|
||
|
.ECC_MODE (P_ECC_MODE_RDCH ),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_RDCH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_RDCH_ECC),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH_RDCH),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH_RDCH ),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES_RDCH_INT),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_RDCH_ECC),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH_RDCH),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH_RDCH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_rdch_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axif_mclk),
|
||
|
.wr_clk (m_aclk_int),
|
||
|
.wr_en (rdch_wr_en),
|
||
|
.din (rdch_din),
|
||
|
.full (rdch_full),
|
||
|
.full_n (),
|
||
|
.prog_full (prog_full_rdch),
|
||
|
.wr_data_count (wr_data_count_rdch),
|
||
|
.overflow (axi_r_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_rdch),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (s_aclk),
|
||
|
.rd_en (rdch_rd_en),
|
||
|
.dout (rdch_dout),
|
||
|
.empty (rdch_empty),
|
||
|
.prog_empty (prog_empty_rdch),
|
||
|
.rd_data_count (rd_data_count_rdch),
|
||
|
.underflow (axi_r_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (injectsbiterr_rdch),
|
||
|
.injectdbiterr (injectdbiterr_rdch),
|
||
|
.sbiterr (sbiterr_rdch),
|
||
|
.dbiterr (dbiterr_rdch)
|
||
|
);
|
||
|
|
||
|
assign rdch_s_axi_rvalid = ~rdch_empty;
|
||
|
assign rdch_m_axi_rready = (FIFO_MEMORY_TYPE_RDCH == "lutram") ? ~(rdch_full | wr_rst_busy_rdch) : ~rdch_full;
|
||
|
assign s_axi_rvalid = rdch_s_axi_rvalid;
|
||
|
assign m_axi_rready = rdch_m_axi_rready;
|
||
|
|
||
|
end :axi_read_data_channel
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
if (IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1)) begin : axi_full_rach_output
|
||
|
assign m_axi_araddr = rach_dout[ARID_OFFSET-1:ARADDR_OFFSET];
|
||
|
assign m_axi_arlen = rach_dout[ARADDR_OFFSET-1:ARLEN_OFFSET];
|
||
|
assign m_axi_arsize = rach_dout[ARLEN_OFFSET-1:ARSIZE_OFFSET];
|
||
|
assign m_axi_arburst = rach_dout[ARSIZE_OFFSET-1:ARBURST_OFFSET];
|
||
|
assign m_axi_arlock = rach_dout[ARBURST_OFFSET-1:ARLOCK_OFFSET];
|
||
|
assign m_axi_arcache = rach_dout[ARLOCK_OFFSET-1:ARCACHE_OFFSET];
|
||
|
assign m_axi_arprot = rach_dout[ARCACHE_OFFSET-1:ARPROT_OFFSET];
|
||
|
assign m_axi_arqos = rach_dout[ARPROT_OFFSET-1:ARQOS_OFFSET];
|
||
|
assign rach_din[ARID_OFFSET-1:ARADDR_OFFSET] = s_axi_araddr;
|
||
|
assign rach_din[ARADDR_OFFSET-1:ARLEN_OFFSET] = s_axi_arlen;
|
||
|
assign rach_din[ARLEN_OFFSET-1:ARSIZE_OFFSET] = s_axi_arsize;
|
||
|
assign rach_din[ARSIZE_OFFSET-1:ARBURST_OFFSET] = s_axi_arburst;
|
||
|
assign rach_din[ARBURST_OFFSET-1:ARLOCK_OFFSET] = s_axi_arlock;
|
||
|
assign rach_din[ARLOCK_OFFSET-1:ARCACHE_OFFSET] = s_axi_arcache;
|
||
|
assign rach_din[ARCACHE_OFFSET-1:ARPROT_OFFSET] = s_axi_arprot;
|
||
|
assign rach_din[ARPROT_OFFSET-1:ARQOS_OFFSET] = s_axi_arqos;
|
||
|
end : axi_full_rach_output
|
||
|
|
||
|
if ((IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1))) begin : axi_arregion
|
||
|
assign m_axi_arregion = rach_dout[ARQOS_OFFSET-1:ARREGION_OFFSET];
|
||
|
end : axi_arregion
|
||
|
|
||
|
if ((IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1))) begin : axi_aruser
|
||
|
assign m_axi_aruser = rach_dout[ARREGION_OFFSET-1:ARUSER_OFFSET];
|
||
|
end : axi_aruser
|
||
|
|
||
|
if ((IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1))) begin : axi_arid
|
||
|
assign m_axi_arid = rach_dout[C_DIN_WIDTH_RACH-1:ARID_OFFSET];
|
||
|
end : axi_arid
|
||
|
|
||
|
if (IS_AXI_FULL_RDCH == 1 || ( C_RDCH_TYPE == 1)) begin : axi_full_rdch_output
|
||
|
assign s_axi_rdata = rdch_dout[RID_OFFSET-1:RDATA_OFFSET];
|
||
|
assign s_axi_rresp = rdch_dout[RDATA_OFFSET-1:RRESP_OFFSET];
|
||
|
assign s_axi_rlast = rdch_dout[0];
|
||
|
assign rdch_din[RID_OFFSET-1:RDATA_OFFSET] = m_axi_rdata;
|
||
|
assign rdch_din[RDATA_OFFSET-1:RRESP_OFFSET] = m_axi_rresp;
|
||
|
assign rdch_din[0] = m_axi_rlast;
|
||
|
end : axi_full_rdch_output
|
||
|
|
||
|
if ((IS_AXI_FULL_RDCH == 1 || ( C_RDCH_TYPE == 1))) begin : axi_full_ruser_output
|
||
|
assign s_axi_ruser = rdch_dout[RRESP_OFFSET-1:RUSER_OFFSET];
|
||
|
end : axi_full_ruser_output
|
||
|
|
||
|
if ((IS_AXI_FULL_RDCH == 1 || ( C_RDCH_TYPE == 1))) begin : axi_rid
|
||
|
assign s_axi_rid = rdch_dout[C_DIN_WIDTH_RDCH-1:RID_OFFSET];
|
||
|
end : axi_rid
|
||
|
|
||
|
|
||
|
if ((IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1))) begin : grach_din1
|
||
|
assign rach_din[ARREGION_OFFSET-1:ARUSER_OFFSET] = s_axi_aruser;
|
||
|
end : grach_din1
|
||
|
|
||
|
if ((IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1))) begin : grach_din2
|
||
|
assign rach_din[C_DIN_WIDTH_RACH-1:ARID_OFFSET] = s_axi_arid;
|
||
|
end : grach_din2
|
||
|
|
||
|
if ((IS_AXI_FULL_RACH == 1 || ( C_RACH_TYPE == 1))) begin
|
||
|
assign rach_din[ARQOS_OFFSET-1:ARREGION_OFFSET] = s_axi_arregion;
|
||
|
end
|
||
|
|
||
|
if ((IS_AXI_FULL_RDCH == 1 || ( C_RDCH_TYPE == 1))) begin : grdch_din1
|
||
|
assign rdch_din[RRESP_OFFSET-1:RUSER_OFFSET] = m_axi_ruser;
|
||
|
end : grdch_din1
|
||
|
|
||
|
if ((IS_AXI_FULL_RDCH == 1 || ( C_RDCH_TYPE == 1))) begin : grdch_din2
|
||
|
assign rdch_din[C_DIN_WIDTH_RDCH-1:RID_OFFSET] = m_axi_rid;
|
||
|
end : grdch_din2
|
||
|
|
||
|
//end of axi_read_channel
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Pass Through Logic or Wiring Logic
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Pass Through Logic for Read Channel
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
// Wiring logic for Write Address Channel
|
||
|
if (C_WACH_TYPE == 2) begin : gwach_pass_through
|
||
|
assign m_axi_awid = s_axi_awid;
|
||
|
assign m_axi_awaddr = s_axi_awaddr;
|
||
|
assign m_axi_awlen = s_axi_awlen;
|
||
|
assign m_axi_awsize = s_axi_awsize;
|
||
|
assign m_axi_awburst = s_axi_awburst;
|
||
|
assign m_axi_awlock = s_axi_awlock;
|
||
|
assign m_axi_awcache = s_axi_awcache;
|
||
|
assign m_axi_awprot = s_axi_awprot;
|
||
|
assign m_axi_awqos = s_axi_awqos;
|
||
|
assign m_axi_awregion = s_axi_awregion;
|
||
|
assign m_axi_awuser = s_axi_awuser;
|
||
|
assign s_axi_awready = m_axi_awready;
|
||
|
assign m_axi_awvalid = s_axi_awvalid;
|
||
|
end //: gwach_pass_through;
|
||
|
|
||
|
// Wiring logic for Write Data Channel
|
||
|
if (C_WDCH_TYPE == 2) begin : gwdch_pass_through
|
||
|
// assign m_axi_wid = s_axi_wid;
|
||
|
assign m_axi_wdata = s_axi_wdata;
|
||
|
assign m_axi_wstrb = s_axi_wstrb;
|
||
|
assign m_axi_wlast = s_axi_wlast;
|
||
|
assign m_axi_wuser = s_axi_wuser;
|
||
|
assign s_axi_wready = m_axi_wready;
|
||
|
assign m_axi_wvalid = s_axi_wvalid;
|
||
|
end //: gwdch_pass_through;
|
||
|
|
||
|
// Wiring logic for Write Response Channel
|
||
|
if (C_WRCH_TYPE == 2) begin : gwrch_pass_through
|
||
|
assign s_axi_bid = m_axi_bid;
|
||
|
assign s_axi_bresp = m_axi_bresp;
|
||
|
assign s_axi_buser = m_axi_buser;
|
||
|
assign m_axi_bready = s_axi_bready;
|
||
|
assign s_axi_bvalid = m_axi_bvalid;
|
||
|
end //: gwrch_pass_through;
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Pass Through Logic for Read Channel
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
// Wiring logic for Read Address Channel
|
||
|
if (C_RACH_TYPE == 2) begin : grach_pass_through
|
||
|
assign m_axi_arid = s_axi_arid;
|
||
|
assign m_axi_araddr = s_axi_araddr;
|
||
|
assign m_axi_arlen = s_axi_arlen;
|
||
|
assign m_axi_arsize = s_axi_arsize;
|
||
|
assign m_axi_arburst = s_axi_arburst;
|
||
|
assign m_axi_arlock = s_axi_arlock;
|
||
|
assign m_axi_arcache = s_axi_arcache;
|
||
|
assign m_axi_arprot = s_axi_arprot;
|
||
|
assign m_axi_arqos = s_axi_arqos;
|
||
|
assign m_axi_arregion = s_axi_arregion;
|
||
|
assign m_axi_aruser = s_axi_aruser;
|
||
|
assign s_axi_arready = m_axi_arready;
|
||
|
assign m_axi_arvalid = s_axi_arvalid;
|
||
|
end //: grach_pass_through;
|
||
|
|
||
|
// Wiring logic for Read Data Channel
|
||
|
if (C_RDCH_TYPE == 2) begin : grdch_pass_through
|
||
|
assign s_axi_rid = m_axi_rid;
|
||
|
assign s_axi_rlast = m_axi_rlast;
|
||
|
assign s_axi_ruser = m_axi_ruser;
|
||
|
assign s_axi_rdata = m_axi_rdata;
|
||
|
assign s_axi_rresp = m_axi_rresp;
|
||
|
assign s_axi_rvalid = m_axi_rvalid;
|
||
|
assign m_axi_rready = s_axi_rready;
|
||
|
end //: grdch_pass_through;
|
||
|
|
||
|
end : xpm_fifo_rd_chnl
|
||
|
endgenerate
|
||
|
|
||
|
|
||
|
endmodule //xpm_fifo_axif
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Declaration of top-level module
|
||
|
******************************************************************************/
|
||
|
(* XPM_MODULE = "TRUE", KEEP_HIERARCHY = "SOFT" *)
|
||
|
module xpm_fifo_axil
|
||
|
#(
|
||
|
//-----------------------------------------------------------------------
|
||
|
// Generic Declarations
|
||
|
//-----------------------------------------------------------------------
|
||
|
parameter integer AXI_ADDR_WIDTH = 32,
|
||
|
parameter integer AXI_DATA_WIDTH = 32,
|
||
|
parameter CLOCKING_MODE = "common",
|
||
|
parameter integer SIM_ASSERT_CHK = 0,
|
||
|
parameter integer CASCADE_HEIGHT = 0,
|
||
|
parameter integer CDC_SYNC_STAGES = 2,
|
||
|
parameter integer EN_RESET_SYNCHRONIZER = 0,
|
||
|
parameter FIFO_MEMORY_TYPE_WACH = "lutram",
|
||
|
parameter FIFO_MEMORY_TYPE_WDCH = "bram",
|
||
|
parameter FIFO_MEMORY_TYPE_WRCH = "lutram",
|
||
|
parameter FIFO_MEMORY_TYPE_RACH = "lutram",
|
||
|
parameter FIFO_MEMORY_TYPE_RDCH = "bram",
|
||
|
parameter integer FIFO_DEPTH_WACH = 16,
|
||
|
parameter integer FIFO_DEPTH_WDCH = 16,
|
||
|
parameter integer FIFO_DEPTH_WRCH = 2048,
|
||
|
parameter integer FIFO_DEPTH_RACH = 16,
|
||
|
parameter integer FIFO_DEPTH_RDCH = 2048,
|
||
|
parameter ECC_MODE_WDCH = "no_ecc",
|
||
|
parameter ECC_MODE_RDCH = "no_ecc",
|
||
|
parameter USE_ADV_FEATURES_WDCH = "1000",
|
||
|
parameter USE_ADV_FEATURES_RDCH = "1000",
|
||
|
parameter integer WR_DATA_COUNT_WIDTH_WDCH = 10,
|
||
|
parameter integer WR_DATA_COUNT_WIDTH_RDCH = 10,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH_WDCH = 10,
|
||
|
parameter integer RD_DATA_COUNT_WIDTH_RDCH = 10,
|
||
|
parameter integer PROG_FULL_THRESH_WDCH = 10,
|
||
|
parameter integer PROG_FULL_THRESH_RDCH = 10,
|
||
|
parameter integer PROG_EMPTY_THRESH_WDCH = 10,
|
||
|
parameter integer PROG_EMPTY_THRESH_RDCH = 10
|
||
|
|
||
|
|
||
|
)
|
||
|
|
||
|
(
|
||
|
// AXI Global Signal
|
||
|
input wire m_aclk,
|
||
|
input wire s_aclk,
|
||
|
input wire s_aresetn,
|
||
|
|
||
|
// AXI Full/Lite Slave Write Channel (write side)
|
||
|
input wire [AXI_ADDR_WIDTH-1:0] s_axi_awaddr,
|
||
|
input wire [3-1:0] s_axi_awprot,
|
||
|
input wire s_axi_awvalid,
|
||
|
output wire s_axi_awready,
|
||
|
input wire [AXI_DATA_WIDTH-1:0] s_axi_wdata,
|
||
|
input wire [AXI_DATA_WIDTH/8-1:0] s_axi_wstrb,
|
||
|
input wire s_axi_wvalid,
|
||
|
output wire s_axi_wready,
|
||
|
output wire [2-1:0] s_axi_bresp,
|
||
|
output wire s_axi_bvalid,
|
||
|
input wire s_axi_bready,
|
||
|
|
||
|
// AXI Full/Lite Master Write Channel (read side)
|
||
|
output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
||
|
output wire [3-1:0] m_axi_awprot,
|
||
|
output wire m_axi_awvalid,
|
||
|
input wire m_axi_awready,
|
||
|
output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
||
|
output wire [AXI_DATA_WIDTH/8-1:0] m_axi_wstrb,
|
||
|
output wire m_axi_wvalid,
|
||
|
input wire m_axi_wready,
|
||
|
input wire [2-1:0] m_axi_bresp,
|
||
|
input wire m_axi_bvalid,
|
||
|
output wire m_axi_bready,
|
||
|
|
||
|
// AXI Full/Lite Slave Read Channel (write side)
|
||
|
input wire [AXI_ADDR_WIDTH-1:0] s_axi_araddr,
|
||
|
input wire [3-1:0] s_axi_arprot,
|
||
|
input wire s_axi_arvalid,
|
||
|
output wire s_axi_arready,
|
||
|
output wire [AXI_DATA_WIDTH-1:0] s_axi_rdata,
|
||
|
output wire [2-1:0] s_axi_rresp,
|
||
|
output wire s_axi_rvalid,
|
||
|
input wire s_axi_rready,
|
||
|
|
||
|
// AXI Full/Lite Master Read Channel (read side)
|
||
|
output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
||
|
output wire [3-1:0] m_axi_arprot,
|
||
|
output wire m_axi_arvalid,
|
||
|
input wire m_axi_arready,
|
||
|
input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
||
|
input wire [2-1:0] m_axi_rresp,
|
||
|
input wire m_axi_rvalid,
|
||
|
output wire m_axi_rready,
|
||
|
|
||
|
// AXI4-Full Sideband Signals
|
||
|
output wire prog_full_wdch,
|
||
|
output wire prog_empty_wdch,
|
||
|
output wire [WR_DATA_COUNT_WIDTH_WDCH-1:0] wr_data_count_wdch,
|
||
|
output wire [RD_DATA_COUNT_WIDTH_WDCH-1:0] rd_data_count_wdch,
|
||
|
output wire prog_full_rdch,
|
||
|
output wire prog_empty_rdch,
|
||
|
output wire [WR_DATA_COUNT_WIDTH_RDCH-1:0] wr_data_count_rdch,
|
||
|
output wire [RD_DATA_COUNT_WIDTH_RDCH-1:0] rd_data_count_rdch,
|
||
|
|
||
|
// ECC Related ports
|
||
|
input wire injectsbiterr_wdch,
|
||
|
input wire injectdbiterr_wdch,
|
||
|
output wire sbiterr_wdch,
|
||
|
output wire dbiterr_wdch,
|
||
|
input wire injectsbiterr_rdch,
|
||
|
input wire injectdbiterr_rdch,
|
||
|
output wire sbiterr_rdch,
|
||
|
output wire dbiterr_rdch
|
||
|
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
// Function to convert ASCII value to binary
|
||
|
function [3:0] str2bin;
|
||
|
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])
|
||
|
str2bin = str_val_ascii[3:0];
|
||
|
else begin
|
||
|
str2bin [3] = 1'b1;
|
||
|
str2bin [2] = str_val_ascii[2] | (str_val_ascii[1] & str_val_ascii[0]);
|
||
|
str2bin [1] = str_val_ascii[0] ^ str_val_ascii[1];
|
||
|
str2bin [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 [15:0] hstr2bin;
|
||
|
input [16*8-1 : 0] hstr_val;
|
||
|
integer rst_loop_a;
|
||
|
localparam integer rsta_loop_iter = 16;
|
||
|
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] = str2bin(hstr_val[(rst_loop_a*8)-1 -: 8]);
|
||
|
end
|
||
|
return rst_val_conv_a_i[15:0];
|
||
|
endfunction
|
||
|
|
||
|
//Function to convert binary to ASCII value
|
||
|
function [7:0] bin2str;
|
||
|
input [3:0] bin_val;
|
||
|
if( bin_val > 4'h9) begin
|
||
|
bin2str [7:4] = 4'h4;
|
||
|
bin2str [3] = 1'b0;
|
||
|
bin2str [2:0] = bin_val[2:0]-1'b1;
|
||
|
end
|
||
|
else begin
|
||
|
bin2str [7:4] = 4'h3;
|
||
|
bin2str [3:0] = bin_val;
|
||
|
end
|
||
|
endfunction
|
||
|
|
||
|
// Function that parses the complete binary value to string
|
||
|
function [31:0] bin2hstr;
|
||
|
input [15 : 0] bin_val;
|
||
|
integer str_pos;
|
||
|
localparam integer str_max_bits = 32;
|
||
|
for (str_pos=1; str_pos <= str_max_bits/8; str_pos = str_pos+1) begin
|
||
|
bin2hstr[(str_pos*8)-1 -: 8] = bin2str(bin_val[(str_pos*4)-1 -: 4]);
|
||
|
end
|
||
|
endfunction
|
||
|
|
||
|
//WDCH advanced features parameter conversion
|
||
|
localparam [15:0] EN_ADV_FEATURE_WDCH = hstr2bin(USE_ADV_FEATURES_WDCH);
|
||
|
localparam EN_DATA_VALID_INT = 1'b1;
|
||
|
localparam [15:0] EN_ADV_FEATURE_WDCH_INT = {EN_ADV_FEATURE_WDCH[15:13], EN_DATA_VALID_INT, EN_ADV_FEATURE_WDCH[11:0]};
|
||
|
localparam USE_ADV_FEATURES_WDCH_INT = bin2hstr(EN_ADV_FEATURE_WDCH_INT);
|
||
|
|
||
|
|
||
|
//RDCH advanced features parameter conversion
|
||
|
localparam [15:0] EN_ADV_FEATURE_RDCH = hstr2bin(USE_ADV_FEATURES_RDCH);
|
||
|
localparam [15:0] EN_ADV_FEATURE_RDCH_INT = {EN_ADV_FEATURE_RDCH[15:13], EN_DATA_VALID_INT, EN_ADV_FEATURE_RDCH[11:0]};
|
||
|
localparam USE_ADV_FEATURES_RDCH_INT = bin2hstr(EN_ADV_FEATURE_RDCH_INT);
|
||
|
|
||
|
|
||
|
localparam C_WACH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logic
|
||
|
localparam C_WDCH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
localparam C_WRCH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
localparam C_RACH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
localparam C_RDCH_TYPE = 0; // 0 = FIFO, 1 = Register Slice, 2 = Pass Through Logie
|
||
|
|
||
|
// Input Data Width
|
||
|
// Accumulation of all AXI input signal's width
|
||
|
localparam C_DIN_WIDTH_WACH = AXI_ADDR_WIDTH+3;
|
||
|
localparam C_DIN_WIDTH_WDCH = AXI_DATA_WIDTH/8+AXI_DATA_WIDTH;
|
||
|
localparam C_DIN_WIDTH_WRCH = 2;
|
||
|
localparam C_DIN_WIDTH_RACH = AXI_ADDR_WIDTH+3;
|
||
|
localparam C_DIN_WIDTH_RDCH = AXI_DATA_WIDTH+2;
|
||
|
|
||
|
|
||
|
// Define local parameters for mapping with base file
|
||
|
localparam integer P_COMMON_CLOCK = ( (CLOCKING_MODE == "common_clock" || CLOCKING_MODE == "COMMON_CLOCK" || CLOCKING_MODE == "COMMON" || CLOCKING_MODE == "common") ? 1 :
|
||
|
( (CLOCKING_MODE == "independent_clock" || CLOCKING_MODE == "INDEPENDENT_CLOCK" || CLOCKING_MODE == "INDEPENDENT" || CLOCKING_MODE == "independent") ? 0 : 2));
|
||
|
|
||
|
localparam integer P_ECC_MODE_WDCH = ( (ECC_MODE_WDCH == "no_ecc" || ECC_MODE_WDCH == "NO_ECC" ) ? 0 : 1);
|
||
|
localparam integer P_ECC_MODE_RDCH = ( (ECC_MODE_RDCH == "no_ecc" || ECC_MODE_RDCH == "NO_ECC" ) ? 0 : 1);
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_WACH = ( (FIFO_MEMORY_TYPE_WACH == "lutram" || FIFO_MEMORY_TYPE_WACH == "LUTRAM" || FIFO_MEMORY_TYPE_WACH == "distributed" || FIFO_MEMORY_TYPE_WACH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_WACH == "blockram" || FIFO_MEMORY_TYPE_WACH == "BLOCKRAM" || FIFO_MEMORY_TYPE_WACH == "bram" || FIFO_MEMORY_TYPE_WACH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_WACH == "ultraram" || FIFO_MEMORY_TYPE_WACH == "ULTRARAM" || FIFO_MEMORY_TYPE_WACH == "uram" || FIFO_MEMORY_TYPE_WACH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_WACH == "builtin" || FIFO_MEMORY_TYPE_WACH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_WDCH = ( (FIFO_MEMORY_TYPE_WDCH == "lutram" || FIFO_MEMORY_TYPE_WDCH == "LUTRAM" || FIFO_MEMORY_TYPE_WDCH == "distributed" || FIFO_MEMORY_TYPE_WDCH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_WDCH == "blockram" || FIFO_MEMORY_TYPE_WDCH == "BLOCKRAM" || FIFO_MEMORY_TYPE_WDCH == "bram" || FIFO_MEMORY_TYPE_WDCH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_WDCH == "ultraram" || FIFO_MEMORY_TYPE_WDCH == "ULTRARAM" || FIFO_MEMORY_TYPE_WDCH == "uram" || FIFO_MEMORY_TYPE_WDCH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_WDCH == "builtin" || FIFO_MEMORY_TYPE_WDCH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_WRCH = ( (FIFO_MEMORY_TYPE_WRCH == "lutram" || FIFO_MEMORY_TYPE_WRCH == "LUTRAM" || FIFO_MEMORY_TYPE_WRCH == "distributed" || FIFO_MEMORY_TYPE_WRCH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_WRCH == "blockram" || FIFO_MEMORY_TYPE_WRCH == "BLOCKRAM" || FIFO_MEMORY_TYPE_WRCH == "bram" || FIFO_MEMORY_TYPE_WRCH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_WRCH == "ultraram" || FIFO_MEMORY_TYPE_WRCH == "ULTRARAM" || FIFO_MEMORY_TYPE_WRCH == "uram" || FIFO_MEMORY_TYPE_WRCH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_WRCH == "builtin" || FIFO_MEMORY_TYPE_WRCH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_RACH = ( (FIFO_MEMORY_TYPE_RACH == "lutram" || FIFO_MEMORY_TYPE_RACH == "LUTRAM" || FIFO_MEMORY_TYPE_RACH == "distributed" || FIFO_MEMORY_TYPE_RACH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_RACH == "blockram" || FIFO_MEMORY_TYPE_RACH == "BLOCKRAM" || FIFO_MEMORY_TYPE_RACH == "bram" || FIFO_MEMORY_TYPE_RACH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_RACH == "ultraram" || FIFO_MEMORY_TYPE_RACH == "ULTRARAM" || FIFO_MEMORY_TYPE_RACH == "uram" || FIFO_MEMORY_TYPE_RACH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_RACH == "builtin" || FIFO_MEMORY_TYPE_RACH == "BUILTIN") ? 4 : 0))));
|
||
|
localparam integer P_FIFO_MEMORY_TYPE_RDCH = ( (FIFO_MEMORY_TYPE_RDCH == "lutram" || FIFO_MEMORY_TYPE_RDCH == "LUTRAM" || FIFO_MEMORY_TYPE_RDCH == "distributed" || FIFO_MEMORY_TYPE_RDCH == "DISTRIBUTED") ? 1 :
|
||
|
( (FIFO_MEMORY_TYPE_RDCH == "blockram" || FIFO_MEMORY_TYPE_RDCH == "BLOCKRAM" || FIFO_MEMORY_TYPE_RDCH == "bram" || FIFO_MEMORY_TYPE_RDCH == "BRAM") ? 2 :
|
||
|
( (FIFO_MEMORY_TYPE_RDCH == "ultraram" || FIFO_MEMORY_TYPE_RDCH == "ULTRARAM" || FIFO_MEMORY_TYPE_RDCH == "uram" || FIFO_MEMORY_TYPE_RDCH == "URAM") ? 3 :
|
||
|
( (FIFO_MEMORY_TYPE_RDCH == "builtin" || FIFO_MEMORY_TYPE_RDCH == "BUILTIN") ? 4 : 0))));
|
||
|
|
||
|
localparam C_DIN_WIDTH_WDCH_ECC = (P_ECC_MODE_WDCH == 0) ? C_DIN_WIDTH_WDCH : ((C_DIN_WIDTH_WDCH%64 == 0) ? C_DIN_WIDTH_WDCH : (64*(C_DIN_WIDTH_WDCH/64+1)));
|
||
|
localparam C_DIN_WIDTH_RDCH_ECC = (P_ECC_MODE_RDCH == 0) ? C_DIN_WIDTH_RDCH : ((C_DIN_WIDTH_RDCH%64 == 0) ? C_DIN_WIDTH_RDCH : (64*(C_DIN_WIDTH_RDCH/64+1)));
|
||
|
|
||
|
|
||
|
|
||
|
wire wr_rst_busy_wach;
|
||
|
wire wr_rst_busy_wdch;
|
||
|
wire wr_rst_busy_wrch;
|
||
|
wire wr_rst_busy_rach;
|
||
|
wire wr_rst_busy_rdch;
|
||
|
|
||
|
|
||
|
|
||
|
localparam C_AXI_PROT_WIDTH = 3;
|
||
|
localparam C_AXI_BRESP_WIDTH = 2;
|
||
|
localparam C_AXI_RRESP_WIDTH = 2;
|
||
|
|
||
|
|
||
|
wire inverted_reset = ~s_aresetn;
|
||
|
wire rst_axil_sclk;
|
||
|
wire rst_axil_mclk;
|
||
|
wire m_aclk_int;
|
||
|
assign m_aclk_int = P_COMMON_CLOCK ? s_aclk : m_aclk;
|
||
|
|
||
|
generate
|
||
|
if (EN_RESET_SYNCHRONIZER == 1) begin : gen_sync_reset
|
||
|
//Reset Synchronizer
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (P_COMMON_CLOCK ? 4 : CDC_SYNC_STAGES),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0)
|
||
|
) xpm_cdc_sync_rst_sclk_inst (
|
||
|
.src_rst (~s_aresetn),
|
||
|
.dest_clk (s_aclk),
|
||
|
.dest_rst (rst_axil_sclk)
|
||
|
);
|
||
|
xpm_cdc_sync_rst #(
|
||
|
.DEST_SYNC_FF (P_COMMON_CLOCK ? 4 : CDC_SYNC_STAGES),
|
||
|
.INIT (0),
|
||
|
.INIT_SYNC_FF (1),
|
||
|
.SIM_ASSERT_CHK (0)
|
||
|
) xpm_cdc_sync_rst_mclk_inst (
|
||
|
.src_rst (~s_aresetn),
|
||
|
.dest_clk (m_aclk_int),
|
||
|
.dest_rst (rst_axil_mclk)
|
||
|
);
|
||
|
end // gen_sync_reset
|
||
|
if (EN_RESET_SYNCHRONIZER == 0) begin : gen_async_reset
|
||
|
assign rst_axil_sclk = inverted_reset;
|
||
|
assign rst_axil_mclk = inverted_reset;
|
||
|
|
||
|
end // gen_async_reset
|
||
|
endgenerate
|
||
|
|
||
|
//###########################################################################
|
||
|
// AXI FULL Write Channel (axi_write_channel)
|
||
|
//###########################################################################
|
||
|
|
||
|
|
||
|
|
||
|
localparam IS_AXI_LITE_WACH = ((C_WACH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_LITE_WDCH = ((C_WDCH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_LITE_WRCH = ((C_WRCH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_LITE_RACH = ((C_RACH_TYPE == 0)) ? 1 : 0;
|
||
|
localparam IS_AXI_LITE_RDCH = ((C_RDCH_TYPE == 0)) ? 1 : 0;
|
||
|
|
||
|
localparam IS_WR_ADDR_CH = ((IS_AXI_LITE_WACH == 1)) ? 1 : 0;
|
||
|
localparam IS_WR_DATA_CH = ((IS_AXI_LITE_WDCH == 1)) ? 1 : 0;
|
||
|
localparam IS_WR_RESP_CH = ((IS_AXI_LITE_WRCH == 1)) ? 1 : 0;
|
||
|
localparam IS_RD_ADDR_CH = ((IS_AXI_LITE_RACH == 1)) ? 1 : 0;
|
||
|
localparam IS_RD_DATA_CH = ((IS_AXI_LITE_RDCH == 1)) ? 1 : 0;
|
||
|
|
||
|
localparam AWADDR_OFFSET = C_DIN_WIDTH_WACH - AXI_ADDR_WIDTH;
|
||
|
localparam AWPROT_OFFSET = AWADDR_OFFSET - C_AXI_PROT_WIDTH;
|
||
|
|
||
|
localparam WDATA_OFFSET = C_DIN_WIDTH_WDCH - AXI_DATA_WIDTH;
|
||
|
localparam WSTRB_OFFSET = WDATA_OFFSET - AXI_DATA_WIDTH/8;
|
||
|
|
||
|
localparam BRESP_OFFSET = C_DIN_WIDTH_WRCH - C_AXI_BRESP_WIDTH;
|
||
|
|
||
|
|
||
|
wire [C_DIN_WIDTH_WACH-1:0] wach_din ;
|
||
|
wire [C_DIN_WIDTH_WACH-1:0] wach_dout ;
|
||
|
wire [C_DIN_WIDTH_WACH-1:0] wach_dout_pkt ;
|
||
|
wire wach_full ;
|
||
|
wire wach_almost_full ;
|
||
|
wire wach_prog_full ;
|
||
|
wire wach_empty ;
|
||
|
wire wach_almost_empty ;
|
||
|
wire wach_prog_empty ;
|
||
|
wire [C_DIN_WIDTH_WDCH_ECC-1:0] wdch_din ;
|
||
|
wire [C_DIN_WIDTH_WDCH_ECC-1:0] wdch_dout ;
|
||
|
wire wdch_full ;
|
||
|
wire wdch_almost_full ;
|
||
|
wire wdch_prog_full ;
|
||
|
wire wdch_empty ;
|
||
|
wire wdch_almost_empty ;
|
||
|
wire wdch_prog_empty ;
|
||
|
wire [C_DIN_WIDTH_WRCH-1:0] wrch_din ;
|
||
|
wire [C_DIN_WIDTH_WRCH-1:0] wrch_dout ;
|
||
|
wire wrch_full ;
|
||
|
wire wrch_almost_full ;
|
||
|
wire wrch_prog_full ;
|
||
|
wire wrch_empty ;
|
||
|
wire wrch_almost_empty ;
|
||
|
wire wrch_prog_empty ;
|
||
|
wire axi_aw_underflow_i;
|
||
|
wire axi_w_underflow_i ;
|
||
|
wire axi_b_underflow_i ;
|
||
|
wire axi_aw_overflow_i ;
|
||
|
wire axi_w_overflow_i ;
|
||
|
wire axi_b_overflow_i ;
|
||
|
wire wach_s_axi_awready;
|
||
|
wire wach_m_axi_awvalid;
|
||
|
wire wach_rd_en ;
|
||
|
wire wdch_s_axi_wready ;
|
||
|
wire wdch_m_axi_wvalid ;
|
||
|
wire wdch_wr_en ;
|
||
|
wire wdch_rd_en ;
|
||
|
wire wrch_s_axi_bvalid ;
|
||
|
wire wrch_m_axi_bready ;
|
||
|
wire txn_count_up ;
|
||
|
wire txn_count_down ;
|
||
|
wire awvalid_en ;
|
||
|
wire awvalid_pkt ;
|
||
|
wire awready_pkt ;
|
||
|
integer wr_pkt_count ;
|
||
|
wire wach_re ;
|
||
|
wire wdch_we ;
|
||
|
wire wdch_re ;
|
||
|
|
||
|
generate if (IS_WR_ADDR_CH == 1) begin : axi_write_address_channel
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign wach_re = m_axi_awready;
|
||
|
assign wach_rd_en = wach_re;
|
||
|
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_WACH),
|
||
|
.ECC_MODE (0),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_WACH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_WACH ),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES ("0101"),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_WACH ),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_wach_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axil_sclk),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (s_axi_awvalid),
|
||
|
.din (wach_din),
|
||
|
.full (wach_full),
|
||
|
.full_n (),
|
||
|
.prog_full (),
|
||
|
.wr_data_count (),
|
||
|
.overflow (axi_aw_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_wach),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (m_aclk_int),
|
||
|
.rd_en (wach_rd_en),
|
||
|
.dout (wach_dout_pkt),
|
||
|
.empty (wach_empty),
|
||
|
.prog_empty (),
|
||
|
.rd_data_count (),
|
||
|
.underflow (axi_aw_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (1'b0),
|
||
|
.injectdbiterr (1'b0),
|
||
|
.sbiterr (),
|
||
|
.dbiterr ()
|
||
|
);
|
||
|
|
||
|
assign wach_s_axi_awready = (FIFO_MEMORY_TYPE_WACH == "lutram") ? ~(wach_full | wr_rst_busy_wach) : ~wach_full;
|
||
|
assign wach_m_axi_awvalid = ~wach_empty;
|
||
|
assign s_axi_awready = wach_s_axi_awready;
|
||
|
|
||
|
|
||
|
end endgenerate // axi_write_address_channel
|
||
|
|
||
|
assign awvalid_en = 1;
|
||
|
assign wach_dout = wach_dout_pkt;
|
||
|
assign m_axi_awvalid = wach_m_axi_awvalid;
|
||
|
|
||
|
generate if (IS_WR_DATA_CH == 1) begin : axi_write_data_channel
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
assign wdch_we = wdch_s_axi_wready & s_axi_wvalid ;
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign wdch_re = wdch_m_axi_wvalid & m_axi_wready ;
|
||
|
assign wdch_wr_en = wdch_we;
|
||
|
assign wdch_rd_en = wdch_re;
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_WDCH),
|
||
|
.ECC_MODE (P_ECC_MODE_WDCH),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_WDCH),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_WDCH_ECC),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH_WDCH),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH_WDCH),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES_WDCH_INT),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_WDCH_ECC),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH_WDCH),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH_WDCH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_wdch_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axil_sclk),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (wdch_wr_en),
|
||
|
.din (wdch_din),
|
||
|
.full (wdch_full),
|
||
|
.full_n (),
|
||
|
.prog_full (prog_full_wdch),
|
||
|
.wr_data_count (wr_data_count_wdch),
|
||
|
.overflow (axi_w_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_wdch),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (m_aclk_int),
|
||
|
.rd_en (wdch_rd_en),
|
||
|
.dout (wdch_dout),
|
||
|
.empty (wdch_empty),
|
||
|
.prog_empty (prog_empty_wdch),
|
||
|
.rd_data_count (rd_data_count_wdch),
|
||
|
.underflow (axi_w_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (injectsbiterr_wdch),
|
||
|
.injectdbiterr (injectdbiterr_wdch),
|
||
|
.sbiterr (sbiterr_wdch),
|
||
|
.dbiterr (dbiterr_wdch)
|
||
|
);
|
||
|
|
||
|
|
||
|
assign wdch_s_axi_wready = (FIFO_MEMORY_TYPE_WDCH == "lutram") ? ~(wdch_full | wr_rst_busy_wdch) : ~wdch_full;
|
||
|
assign wdch_m_axi_wvalid = ~wdch_empty;
|
||
|
assign s_axi_wready = wdch_s_axi_wready;
|
||
|
assign m_axi_wvalid = wdch_m_axi_wvalid;
|
||
|
|
||
|
end endgenerate // axi_write_data_channel
|
||
|
|
||
|
|
||
|
generate if (IS_WR_RESP_CH == 1) begin : axi_write_resp_channel
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_WRCH),
|
||
|
.ECC_MODE (0),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_WRCH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_WRCH),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES ("0101"),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_WRCH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_wrch_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axil_mclk),
|
||
|
.wr_clk (m_aclk_int),
|
||
|
.wr_en (m_axi_bvalid),
|
||
|
.din (wrch_din),
|
||
|
.full (wrch_full),
|
||
|
.full_n (),
|
||
|
.prog_full (),
|
||
|
.wr_data_count (),
|
||
|
.overflow (axi_b_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_wrch),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (s_aclk),
|
||
|
.rd_en (s_axi_bready),
|
||
|
.dout (wrch_dout),
|
||
|
.empty (wrch_empty),
|
||
|
.prog_empty (),
|
||
|
.rd_data_count (),
|
||
|
.underflow (axi_b_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (1'b0),
|
||
|
.injectdbiterr (1'b0),
|
||
|
.sbiterr (),
|
||
|
.dbiterr ()
|
||
|
);
|
||
|
|
||
|
assign wrch_s_axi_bvalid = ~wrch_empty;
|
||
|
assign wrch_m_axi_bready = (FIFO_MEMORY_TYPE_WRCH == "lutram") ? ~(wrch_full | wr_rst_busy_wrch) : ~wrch_full;
|
||
|
assign s_axi_bvalid = wrch_s_axi_bvalid;
|
||
|
assign m_axi_bready = wrch_m_axi_bready;
|
||
|
|
||
|
end endgenerate // axi_write_resp_channel
|
||
|
|
||
|
|
||
|
|
||
|
generate if (IS_AXI_LITE_WACH == 1 || (C_WACH_TYPE == 1)) begin : axi_wach_output1
|
||
|
assign wach_din = {s_axi_awaddr, s_axi_awprot};
|
||
|
assign m_axi_awaddr = wach_dout[C_DIN_WIDTH_WACH-1:AWADDR_OFFSET];
|
||
|
assign m_axi_awprot = wach_dout[AWADDR_OFFSET-1:AWPROT_OFFSET];
|
||
|
end endgenerate // axi_wach_output1
|
||
|
|
||
|
generate if (IS_AXI_LITE_WDCH == 1 || (C_WDCH_TYPE == 1)) begin : axi_wdch_output1
|
||
|
assign wdch_din = {s_axi_wdata, s_axi_wstrb};
|
||
|
assign m_axi_wdata = wdch_dout[C_DIN_WIDTH_WDCH-1:WDATA_OFFSET];
|
||
|
assign m_axi_wstrb = wdch_dout[WDATA_OFFSET-1:WSTRB_OFFSET];
|
||
|
end endgenerate // axi_wdch_output1
|
||
|
|
||
|
generate if (IS_AXI_LITE_WRCH == 1 || (C_WRCH_TYPE == 1)) begin : axi_wrch_output1
|
||
|
assign wrch_din = m_axi_bresp;
|
||
|
assign s_axi_bresp = wrch_dout[C_DIN_WIDTH_WRCH-1:BRESP_OFFSET];
|
||
|
end endgenerate // axi_wrch_output1
|
||
|
|
||
|
|
||
|
//end of axi_write_channel
|
||
|
|
||
|
//###########################################################################
|
||
|
// AXI FULL Read Channel (axi_read_channel)
|
||
|
//###########################################################################
|
||
|
wire [C_DIN_WIDTH_RACH-1:0] rach_din ;
|
||
|
wire [C_DIN_WIDTH_RACH-1:0] rach_dout ;
|
||
|
wire [C_DIN_WIDTH_RACH-1:0] rach_dout_pkt ;
|
||
|
wire rach_full ;
|
||
|
wire rach_almost_full ;
|
||
|
wire rach_prog_full ;
|
||
|
wire rach_empty ;
|
||
|
wire rach_almost_empty ;
|
||
|
wire rach_prog_empty ;
|
||
|
wire [C_DIN_WIDTH_RDCH_ECC-1:0] rdch_din ;
|
||
|
wire [C_DIN_WIDTH_RDCH_ECC-1:0] rdch_dout ;
|
||
|
wire rdch_full ;
|
||
|
wire rdch_almost_full ;
|
||
|
wire rdch_prog_full ;
|
||
|
wire rdch_empty ;
|
||
|
wire rdch_almost_empty ;
|
||
|
wire rdch_prog_empty ;
|
||
|
wire axi_ar_underflow_i ;
|
||
|
wire axi_r_underflow_i ;
|
||
|
wire axi_ar_overflow_i ;
|
||
|
wire axi_r_overflow_i ;
|
||
|
wire rach_s_axi_arready ;
|
||
|
wire rach_m_axi_arvalid ;
|
||
|
wire rach_rd_en ;
|
||
|
wire rdch_m_axi_rready ;
|
||
|
wire rdch_s_axi_rvalid ;
|
||
|
wire rdch_wr_en ;
|
||
|
wire rdch_rd_en ;
|
||
|
wire arvalid_pkt ;
|
||
|
wire arready_pkt ;
|
||
|
wire arvalid_en ;
|
||
|
wire rdch_rd_ok ;
|
||
|
wire accept_next_pkt ;
|
||
|
integer rdch_free_space ;
|
||
|
integer rdch_commited_space ;
|
||
|
wire rach_re ;
|
||
|
wire rdch_we ;
|
||
|
wire rdch_re ;
|
||
|
|
||
|
localparam ARADDR_OFFSET = C_DIN_WIDTH_RACH - AXI_ADDR_WIDTH;
|
||
|
localparam ARPROT_OFFSET = ARADDR_OFFSET - C_AXI_PROT_WIDTH;
|
||
|
|
||
|
localparam RDATA_OFFSET = C_DIN_WIDTH_RDCH - AXI_DATA_WIDTH;
|
||
|
localparam RRESP_OFFSET = RDATA_OFFSET - C_AXI_RRESP_WIDTH;
|
||
|
|
||
|
|
||
|
generate if (IS_RD_ADDR_CH == 1) begin : axi_read_addr_channel
|
||
|
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign rach_re = m_axi_arready;
|
||
|
assign rach_rd_en = rach_re;
|
||
|
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_RACH),
|
||
|
.ECC_MODE (0),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_RACH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES ("0101"),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_RACH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_rach_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axil_sclk),
|
||
|
.wr_clk (s_aclk),
|
||
|
.wr_en (s_axi_arvalid),
|
||
|
.din (rach_din),
|
||
|
.full (rach_full),
|
||
|
.full_n (),
|
||
|
.prog_full (),
|
||
|
.wr_data_count (),
|
||
|
.overflow (axi_ar_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_rach),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (m_aclk_int),
|
||
|
.rd_en (rach_rd_en),
|
||
|
.dout (rach_dout_pkt),
|
||
|
.empty (rach_empty),
|
||
|
.prog_empty (),
|
||
|
.rd_data_count (),
|
||
|
.underflow (axi_ar_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (1'b0),
|
||
|
.injectdbiterr (1'b0),
|
||
|
.sbiterr (),
|
||
|
.dbiterr ()
|
||
|
);
|
||
|
|
||
|
assign rach_s_axi_arready = (FIFO_MEMORY_TYPE_RACH == "lutram") ? ~(rach_full | wr_rst_busy_rach) : ~rach_full;
|
||
|
assign rach_m_axi_arvalid = ~rach_empty;
|
||
|
assign s_axi_arready = rach_s_axi_arready;
|
||
|
|
||
|
end endgenerate // axi_read_addr_channel
|
||
|
|
||
|
|
||
|
generate if (C_RACH_TYPE == 0) begin : grach_m_axi_arvalid
|
||
|
assign m_axi_arvalid = rach_m_axi_arvalid;
|
||
|
assign rach_dout = rach_dout_pkt;
|
||
|
end endgenerate // grach_m_axi_arvalid
|
||
|
|
||
|
assign arvalid_en = 1;
|
||
|
|
||
|
generate if (IS_RD_DATA_CH == 1) begin : axi_read_data_channel
|
||
|
|
||
|
// Write protection when almost full or prog_full is high
|
||
|
assign rdch_we = rdch_m_axi_rready & m_axi_rvalid ;
|
||
|
|
||
|
// Read protection when almost empty or prog_empty is high
|
||
|
assign rdch_re = rdch_s_axi_rvalid & s_axi_rready;
|
||
|
assign rdch_wr_en = rdch_we;
|
||
|
assign rdch_rd_en = rdch_re;
|
||
|
|
||
|
|
||
|
xpm_fifo_base # (
|
||
|
.COMMON_CLOCK (P_COMMON_CLOCK ),
|
||
|
.RELATED_CLOCKS (0 ),
|
||
|
.FIFO_MEMORY_TYPE (P_FIFO_MEMORY_TYPE_RDCH),
|
||
|
.ECC_MODE (P_ECC_MODE_RDCH ),
|
||
|
.SIM_ASSERT_CHK (SIM_ASSERT_CHK ),
|
||
|
.CASCADE_HEIGHT (CASCADE_HEIGHT ),
|
||
|
.FIFO_WRITE_DEPTH (FIFO_DEPTH_RDCH ),
|
||
|
.WRITE_DATA_WIDTH (C_DIN_WIDTH_RDCH_ECC),
|
||
|
.WR_DATA_COUNT_WIDTH (WR_DATA_COUNT_WIDTH_RDCH),
|
||
|
.PROG_FULL_THRESH (PROG_FULL_THRESH_RDCH ),
|
||
|
.FULL_RESET_VALUE (1 ),
|
||
|
.USE_ADV_FEATURES (USE_ADV_FEATURES_RDCH_INT),
|
||
|
.READ_MODE (1 ),
|
||
|
.FIFO_READ_LATENCY (0 ),
|
||
|
.READ_DATA_WIDTH (C_DIN_WIDTH_RDCH_ECC),
|
||
|
.RD_DATA_COUNT_WIDTH (RD_DATA_COUNT_WIDTH_RDCH),
|
||
|
.PROG_EMPTY_THRESH (PROG_EMPTY_THRESH_RDCH),
|
||
|
.DOUT_RESET_VALUE ("" ),
|
||
|
.CDC_DEST_SYNC_FF (CDC_SYNC_STAGES ),
|
||
|
.REMOVE_WR_RD_PROT_LOGIC (0 ),
|
||
|
.WAKEUP_TIME (0 ),
|
||
|
.VERSION (0 )
|
||
|
) xpm_fifo_base_rdch_dut (
|
||
|
.sleep (1'b0),
|
||
|
.rst (rst_axil_mclk),
|
||
|
.wr_clk (m_aclk_int),
|
||
|
.wr_en (rdch_wr_en),
|
||
|
.din (rdch_din),
|
||
|
.full (rdch_full),
|
||
|
.full_n (),
|
||
|
.prog_full (prog_full_rdch),
|
||
|
.wr_data_count (wr_data_count_rdch),
|
||
|
.overflow (axi_r_overflow_i),
|
||
|
.wr_rst_busy (wr_rst_busy_rdch),
|
||
|
.almost_full (),
|
||
|
.wr_ack (),
|
||
|
.rd_clk (s_aclk),
|
||
|
.rd_en (rdch_rd_en),
|
||
|
.dout (rdch_dout),
|
||
|
.empty (rdch_empty),
|
||
|
.prog_empty (prog_empty_rdch),
|
||
|
.rd_data_count (rd_data_count_rdch),
|
||
|
.underflow (axi_r_underflow_i),
|
||
|
.rd_rst_busy (),
|
||
|
.almost_empty (),
|
||
|
.data_valid (),
|
||
|
.injectsbiterr (injectsbiterr_rdch),
|
||
|
.injectdbiterr (injectdbiterr_rdch),
|
||
|
.sbiterr (sbiterr_rdch),
|
||
|
.dbiterr (dbiterr_rdch)
|
||
|
);
|
||
|
|
||
|
assign rdch_s_axi_rvalid = ~rdch_empty;
|
||
|
assign rdch_m_axi_rready = (FIFO_MEMORY_TYPE_RDCH == "lutram") ? ~(rdch_full | wr_rst_busy_rdch) : ~rdch_full;
|
||
|
assign s_axi_rvalid = rdch_s_axi_rvalid;
|
||
|
assign m_axi_rready = rdch_m_axi_rready;
|
||
|
|
||
|
|
||
|
end endgenerate //axi_read_data_channel
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
generate if (IS_AXI_LITE_RACH == 1 || (C_RACH_TYPE == 1)) begin : axi_lite_rach_output1
|
||
|
assign rach_din = {s_axi_araddr, s_axi_arprot};
|
||
|
assign m_axi_araddr = rach_dout[C_DIN_WIDTH_RACH-1:ARADDR_OFFSET];
|
||
|
assign m_axi_arprot = rach_dout[ARADDR_OFFSET-1:ARPROT_OFFSET];
|
||
|
end endgenerate // axi_lite_rach_output
|
||
|
|
||
|
generate if (IS_AXI_LITE_RDCH == 1 || (C_RDCH_TYPE == 1)) begin : axi_lite_rdch_output1
|
||
|
assign rdch_din = {m_axi_rdata, m_axi_rresp};
|
||
|
assign s_axi_rdata = rdch_dout[C_DIN_WIDTH_RDCH-1:RDATA_OFFSET];
|
||
|
assign s_axi_rresp = rdch_dout[RDATA_OFFSET-1:RRESP_OFFSET];
|
||
|
end endgenerate // axi_lite_rdch_output
|
||
|
|
||
|
|
||
|
//end of axi_read_channel
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Pass Through Logic or Wiring Logic
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Pass Through Logic for Read Channel
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
// Wiring logic for Write Address Channel
|
||
|
generate if (C_WACH_TYPE == 2) begin : gwach_pass_through
|
||
|
assign m_axi_awaddr = s_axi_awaddr;
|
||
|
assign m_axi_awprot = s_axi_awprot;
|
||
|
assign s_axi_awready = m_axi_awready;
|
||
|
assign m_axi_awvalid = s_axi_awvalid;
|
||
|
end endgenerate // gwach_pass_through;
|
||
|
|
||
|
// Wiring logic for Write Data Channel
|
||
|
generate if (C_WDCH_TYPE == 2) begin : gwdch_pass_through
|
||
|
assign m_axi_wdata = s_axi_wdata;
|
||
|
assign m_axi_wstrb = s_axi_wstrb;
|
||
|
assign s_axi_wready = m_axi_wready;
|
||
|
assign m_axi_wvalid = s_axi_wvalid;
|
||
|
end endgenerate // gwdch_pass_through;
|
||
|
|
||
|
// Wiring logic for Write Response Channel
|
||
|
generate if (C_WRCH_TYPE == 2) begin : gwrch_pass_through
|
||
|
assign s_axi_bresp = m_axi_bresp;
|
||
|
assign m_axi_bready = s_axi_bready;
|
||
|
assign s_axi_bvalid = m_axi_bvalid;
|
||
|
end endgenerate // gwrch_pass_through;
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Pass Through Logic for Read Channel
|
||
|
//-------------------------------------------------------------------------
|
||
|
|
||
|
// Wiring logic for Read Address Channel
|
||
|
generate if (C_RACH_TYPE == 2) begin : grach_pass_through
|
||
|
assign m_axi_araddr = s_axi_araddr;
|
||
|
assign m_axi_arprot = s_axi_arprot;
|
||
|
assign s_axi_arready = m_axi_arready;
|
||
|
assign m_axi_arvalid = s_axi_arvalid;
|
||
|
end endgenerate // grach_pass_through;
|
||
|
|
||
|
// Wiring logic for Read Data Channel
|
||
|
generate if (C_RDCH_TYPE == 2) begin : grdch_pass_through
|
||
|
assign s_axi_rdata = m_axi_rdata;
|
||
|
assign s_axi_rresp = m_axi_rresp;
|
||
|
assign s_axi_rvalid = m_axi_rvalid;
|
||
|
assign m_axi_rready = s_axi_rready;
|
||
|
end endgenerate // grdch_pass_through;
|
||
|
|
||
|
|
||
|
endmodule //xpm_fifo_axil
|
||
|
|
||
|
module xpm_fifo_axi_reg_slice #
|
||
|
(
|
||
|
parameter C_DATA_WIDTH = 32,
|
||
|
parameter C_REG_CONFIG = 32'h00000000
|
||
|
)
|
||
|
(
|
||
|
// System Signals
|
||
|
input wire ACLK,
|
||
|
input wire ARESET,
|
||
|
|
||
|
// Slave side
|
||
|
input wire [C_DATA_WIDTH-1:0] S_PAYLOAD_DATA,
|
||
|
input wire S_VALID,
|
||
|
output wire S_READY,
|
||
|
|
||
|
// Master side
|
||
|
output wire [C_DATA_WIDTH-1:0] M_PAYLOAD_DATA,
|
||
|
output wire M_VALID,
|
||
|
input wire M_READY
|
||
|
);
|
||
|
|
||
|
localparam RST_SYNC_STAGES = 5;
|
||
|
localparam RST_BUSY_LEN = 6;
|
||
|
reg [1:0] arst_sync_wr = 2'b11;
|
||
|
reg [RST_BUSY_LEN-1:0] sckt_wr_rst_cc = 0;
|
||
|
wire sync_reset;
|
||
|
wire extnd_reset;
|
||
|
|
||
|
|
||
|
always @(posedge ARESET or posedge ACLK) begin
|
||
|
if (ARESET)
|
||
|
arst_sync_wr <= 2'b11;
|
||
|
else
|
||
|
arst_sync_wr <= {arst_sync_wr[0], 1'b0};
|
||
|
end
|
||
|
|
||
|
always @(posedge ACLK) begin
|
||
|
sckt_wr_rst_cc <= {sckt_wr_rst_cc[RST_BUSY_LEN-2:0], arst_sync_wr[1]};
|
||
|
end
|
||
|
|
||
|
assign sync_reset = |sckt_wr_rst_cc[RST_BUSY_LEN-5:0] | arst_sync_wr[1];
|
||
|
assign extnd_reset = |sckt_wr_rst_cc | arst_sync_wr[1];
|
||
|
generate
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Both FWD and REV mode
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
if (C_REG_CONFIG == 32'h00000000)
|
||
|
begin
|
||
|
reg [1:0] state;
|
||
|
localparam [1:0]
|
||
|
ZERO = 2'b10,
|
||
|
ONE = 2'b11,
|
||
|
TWO = 2'b01;
|
||
|
|
||
|
reg [C_DATA_WIDTH-1:0] storage_data1 = 0;
|
||
|
reg [C_DATA_WIDTH-1:0] storage_data2 = 0;
|
||
|
reg load_s1;
|
||
|
wire load_s2;
|
||
|
wire load_s1_from_s2;
|
||
|
reg s_ready_i; //local signal of output
|
||
|
wire m_valid_i; //local signal of output
|
||
|
|
||
|
// assign local signal to its output signal
|
||
|
assign S_READY = s_ready_i;
|
||
|
assign M_VALID = m_valid_i;
|
||
|
|
||
|
reg areset_d1; // Reset delay register
|
||
|
always @(posedge ACLK) begin
|
||
|
areset_d1 <= extnd_reset;
|
||
|
end
|
||
|
|
||
|
// Load storage1 with either slave side data or from storage2
|
||
|
always @(posedge ACLK)
|
||
|
begin
|
||
|
if (load_s1)
|
||
|
if (load_s1_from_s2)
|
||
|
storage_data1 <= storage_data2;
|
||
|
else
|
||
|
storage_data1 <= S_PAYLOAD_DATA;
|
||
|
end
|
||
|
|
||
|
// Load storage2 with slave side data
|
||
|
always @(posedge ACLK)
|
||
|
begin
|
||
|
if (load_s2)
|
||
|
storage_data2 <= S_PAYLOAD_DATA;
|
||
|
end
|
||
|
|
||
|
assign M_PAYLOAD_DATA = storage_data1;
|
||
|
|
||
|
// Always load s2 on a valid transaction even if it's unnecessary
|
||
|
assign load_s2 = S_VALID & s_ready_i;
|
||
|
|
||
|
// Loading s1
|
||
|
always @ *
|
||
|
begin
|
||
|
if ( ((state == ZERO) && (S_VALID == 1)) || // Load when empty on slave transaction
|
||
|
// Load when ONE if we both have read and write at the same time
|
||
|
((state == ONE) && (S_VALID == 1) && (M_READY == 1)) ||
|
||
|
// Load when TWO and we have a transaction on Master side
|
||
|
((state == TWO) && (M_READY == 1)))
|
||
|
load_s1 = 1'b1;
|
||
|
else
|
||
|
load_s1 = 1'b0;
|
||
|
end // always @ *
|
||
|
|
||
|
assign load_s1_from_s2 = (state == TWO);
|
||
|
|
||
|
// State Machine for handling output signals
|
||
|
always @(posedge ACLK) begin
|
||
|
if (sync_reset || extnd_reset) begin
|
||
|
s_ready_i <= 1'b0;
|
||
|
state <= ZERO;
|
||
|
end else if (areset_d1 && ~extnd_reset) begin
|
||
|
s_ready_i <= 1'b1;
|
||
|
end else begin
|
||
|
case (state)
|
||
|
// No transaction stored locally
|
||
|
ZERO: if (S_VALID) state <= ONE; // Got one so move to ONE
|
||
|
|
||
|
// One transaction stored locally
|
||
|
ONE: begin
|
||
|
if (M_READY & ~S_VALID) state <= ZERO; // Read out one so move to ZERO
|
||
|
if (~M_READY & S_VALID) begin
|
||
|
state <= TWO; // Got another one so move to TWO
|
||
|
s_ready_i <= 1'b0;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
// TWO transaction stored locally
|
||
|
TWO: if (M_READY) begin
|
||
|
state <= ONE; // Read out one so move to ONE
|
||
|
s_ready_i <= 1'b1;
|
||
|
end
|
||
|
endcase // case (state)
|
||
|
end
|
||
|
end // always @ (posedge ACLK)
|
||
|
|
||
|
assign m_valid_i = state[0];
|
||
|
|
||
|
end // if (C_REG_CONFIG == 1)
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// 1-stage pipeline register with bubble cycle, both FWD and REV pipelining
|
||
|
// Operates same as 1-deep FIFO
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
else if (C_REG_CONFIG == 32'h00000001)
|
||
|
begin
|
||
|
reg [C_DATA_WIDTH-1:0] storage_data1 = 0;
|
||
|
reg s_ready_i; //local signal of output
|
||
|
reg m_valid_i; //local signal of output
|
||
|
|
||
|
// assign local signal to its output signal
|
||
|
assign S_READY = s_ready_i;
|
||
|
assign M_VALID = m_valid_i;
|
||
|
|
||
|
reg areset_d1; // Reset delay register
|
||
|
always @(posedge ACLK) begin
|
||
|
areset_d1 <= extnd_reset;
|
||
|
end
|
||
|
|
||
|
// Load storage1 with slave side data
|
||
|
always @(posedge ACLK)
|
||
|
begin
|
||
|
if (sync_reset || extnd_reset) begin
|
||
|
s_ready_i <= 1'b0;
|
||
|
m_valid_i <= 1'b0;
|
||
|
end else if (areset_d1 && ~extnd_reset) begin
|
||
|
s_ready_i <= 1'b1;
|
||
|
end else if (m_valid_i & M_READY) begin
|
||
|
s_ready_i <= 1'b1;
|
||
|
m_valid_i <= 1'b0;
|
||
|
end else if (S_VALID & s_ready_i) begin
|
||
|
s_ready_i <= 1'b0;
|
||
|
m_valid_i <= 1'b1;
|
||
|
end
|
||
|
if (~m_valid_i) begin
|
||
|
storage_data1 <= S_PAYLOAD_DATA;
|
||
|
end
|
||
|
end
|
||
|
assign M_PAYLOAD_DATA = storage_data1;
|
||
|
end // if (C_REG_CONFIG == 7)
|
||
|
|
||
|
else begin : default_case
|
||
|
// Passthrough
|
||
|
assign M_PAYLOAD_DATA = S_PAYLOAD_DATA;
|
||
|
assign M_VALID = S_VALID;
|
||
|
assign S_READY = M_READY;
|
||
|
end
|
||
|
|
||
|
endgenerate
|
||
|
endmodule // reg_slice
|
||
|
`default_nettype wire
|