fpga: Add X440/FBX support
Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Wade Fife <wade.fife@ni.com> Co-authored-by: Ryan Marlow <ryan@lmarlow.com> Original-commit: 596760a12e4834e47589c12f8a4fd083aa2f7c25
This commit is contained in:
committed by
Aki Tomita
co-authored by
Martin Braun
Wade Fife
Ryan Marlow
parent
a405111ce7
commit
5cadf901c7
@@ -1,34 +1,44 @@
|
||||
//
|
||||
// Copyright 2019 Ettus Research, A National Instruments Company
|
||||
// Copyright 2023 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: sim_axi_ram
|
||||
//
|
||||
// Description:
|
||||
// Description:
|
||||
//
|
||||
// Simulation model for a basic AXI4 memory mapped memory. A few notes on its
|
||||
// Simulation model for a basic AXI4 memory mapped memory. A few notes on its
|
||||
// behavior:
|
||||
//
|
||||
// - This model does not reorder requests (regardless of WID/RID). All
|
||||
// - This model does not reorder requests (regardless of WID/RID). All
|
||||
// requests are evaluated strictly in order.
|
||||
// - The only supported response is OKAY
|
||||
// - This model supports misaligned memory accesses, which cause a
|
||||
// - This model supports misaligned memory accesses, which cause a
|
||||
// simulation warning.
|
||||
// - A reset does not clear the memory contents
|
||||
// - The memory itself is implemented using an associative array (sparse
|
||||
// - The memory itself is implemented using an associative array (sparse
|
||||
// matrix) so that large memories can be supported.
|
||||
// - This model is half duplex, meaning read and write data transfers won't
|
||||
// happen at the same time. A new data transfer won't begin until the
|
||||
// previous one has completed.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// - AWIDTH : Address width of the memory to model
|
||||
// - DWIDTH : Data width of the memory to model
|
||||
// - IDWIDTH : Width of ID ports of the AXI bus
|
||||
// - BIG_ENDIAN : Endianness of the memory model (0 = little, 1 = big)
|
||||
// - STALL_PROB : Default probability of a channel stalling (0 to 99)
|
||||
// - NO_4KB_LIMIT : Allow bursts to cross 4 KiB boundaries
|
||||
//
|
||||
|
||||
module sim_axi_ram #(
|
||||
parameter AWIDTH = 32,
|
||||
parameter DWIDTH = 64,
|
||||
parameter IDWIDTH = 2,
|
||||
parameter BIG_ENDIAN = 0,
|
||||
parameter STALL_PROB = 25
|
||||
parameter AWIDTH = 32,
|
||||
parameter DWIDTH = 64,
|
||||
parameter IDWIDTH = 2,
|
||||
parameter BIG_ENDIAN = 0,
|
||||
parameter STALL_PROB = 25,
|
||||
parameter NO_4KB_LIMIT = 0
|
||||
) (
|
||||
input logic s_aclk,
|
||||
input logic s_aresetn,
|
||||
@@ -82,7 +92,7 @@ module sim_axi_ram #(
|
||||
//---------------------------------------------------------------------------
|
||||
// Data Types
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
typedef enum logic [1:0] { FIXED, INCR, WRAP } burst_t;
|
||||
typedef enum logic [1:0] { OKAY, EXOKAY, SLVERR, DECERR } resp_t;
|
||||
|
||||
@@ -95,7 +105,7 @@ module sim_axi_ram #(
|
||||
burst_t burst;
|
||||
} req_t;
|
||||
|
||||
// Make the address type an extra bit wide so that we can detect
|
||||
// Make the address type an extra bit wide so that we can detect
|
||||
// out-of-bounds accesses easily.
|
||||
typedef bit [AWIDTH:0] addr_t;
|
||||
|
||||
@@ -160,7 +170,7 @@ module sim_axi_ram #(
|
||||
rdata_stall_prob = probability;
|
||||
endfunction : set_read_stall_prob
|
||||
|
||||
// Set Write Address Channel stall probability
|
||||
// Set Write Address Channel stall probability
|
||||
function void set_waddr_stall_prob(int probability);
|
||||
assert(probability >= 0 && probability <= 100) else begin
|
||||
$error("Probability must be from 0 to 100");
|
||||
@@ -200,7 +210,7 @@ module sim_axi_ram #(
|
||||
rdata_stall_prob = probability;
|
||||
endfunction : set_rdata_stall_prob
|
||||
|
||||
// Get Write Address Channel stall probability
|
||||
// Get Write Address Channel stall probability
|
||||
function int get_waddr_stall_prob();
|
||||
return waddr_stall_prob;
|
||||
endfunction : get_waddr_stall_prob
|
||||
@@ -313,13 +323,13 @@ module sim_axi_ram #(
|
||||
assert ($cast(burst, s_axi_awburst)) else begin
|
||||
$fatal(1, "Invalid AWBURST value");
|
||||
end
|
||||
assert ((s_axi_awaddr & MASK_4K) ==
|
||||
((s_axi_awaddr + (s_axi_awlen+1)*(2**s_axi_awsize) - 1) & MASK_4K)) else begin
|
||||
assert (NO_4KB_LIMIT || ((s_axi_awaddr & MASK_4K) ==
|
||||
((s_axi_awaddr + (s_axi_awlen+1)*(2**s_axi_awsize) - 1) & MASK_4K))) else begin
|
||||
$fatal(1, "Memory write burst crosses 4 KiB boundary");
|
||||
end
|
||||
|
||||
if (DEBUG) begin
|
||||
$display("WRITE REQ: id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m",
|
||||
$display("WRITE REQ: id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m",
|
||||
req.id, req.addr, req.len, req.size, req.burst.name, $realtime);
|
||||
end
|
||||
|
||||
@@ -370,13 +380,13 @@ module sim_axi_ram #(
|
||||
assert ($cast(burst, s_axi_awburst)) else begin
|
||||
$fatal(1, "Invalid ARBURST value");
|
||||
end
|
||||
assert ((s_axi_araddr & MASK_4K) ==
|
||||
((s_axi_araddr + (s_axi_arlen+1)*(2**s_axi_arsize) - 1) & MASK_4K)) else begin
|
||||
assert (NO_4KB_LIMIT || ((s_axi_araddr & MASK_4K) ==
|
||||
((s_axi_araddr + (s_axi_arlen+1)*(2**s_axi_arsize) - 1) & MASK_4K))) else begin
|
||||
$fatal(1, "Memory read burst crosses 4 KiB boundary");
|
||||
end
|
||||
|
||||
if (DEBUG) begin
|
||||
$display("READ REQ: id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m",
|
||||
$display("READ REQ: id=%X, addr=%X, len=%X, size=%X, burst=%s, %t, %m",
|
||||
req.id, req.addr, req.len, req.size, req.burst.name, $realtime);
|
||||
end
|
||||
|
||||
@@ -437,7 +447,7 @@ module sim_axi_ram #(
|
||||
addr = req.addr;
|
||||
end
|
||||
INCR : begin
|
||||
// If the address rolls over, we've reached the end of the
|
||||
// If the address rolls over, we've reached the end of the
|
||||
// memory and we should stop here.
|
||||
addr = req.addr + i*req.size;
|
||||
if (addr < req.addr) break;
|
||||
@@ -451,7 +461,7 @@ module sim_axi_ram #(
|
||||
write_mem(addr, req.size, s_axi_wdata, s_axi_wstrb);
|
||||
|
||||
if (DEBUG) begin
|
||||
$display("WRITE: count=%3X, ADDR=%X, DATA=%X, SIZE=%X, STRB=%X, %t, %m",
|
||||
$display("WRITE: count=%3X, ADDR=%X, DATA=%X, SIZE=%X, STRB=%X, %t, %m",
|
||||
i, addr, s_axi_wdata, req.size, s_axi_wstrb, $realtime);
|
||||
end
|
||||
|
||||
@@ -474,9 +484,9 @@ module sim_axi_ram #(
|
||||
// Enqueue write response
|
||||
write_resp.put(req);
|
||||
|
||||
// Make sure WLAST asserted for the last word. If not we report an error.
|
||||
// Per the AXI4 standard, "a slave is not required to use the WLAST
|
||||
// signal" because "a slave can calculate the last write data transfer
|
||||
// Make sure WLAST asserted for the last word. If not we report an error.
|
||||
// Per the AXI4 standard, "a slave is not required to use the WLAST
|
||||
// signal" because "a slave can calculate the last write data transfer
|
||||
// from the burst length AWLEN".
|
||||
if (s_axi_wlast != 1'b1) begin
|
||||
$error("WLAST not asserted on last word of burst");
|
||||
@@ -598,7 +608,7 @@ module sim_axi_ram #(
|
||||
addr = req.addr;
|
||||
end
|
||||
INCR : begin
|
||||
// If the address rolls over, we've reached the end of the memory
|
||||
// If the address rolls over, we've reached the end of the memory
|
||||
// and we should stop here.
|
||||
addr = req.addr + i*req.size;
|
||||
if (addr < req.addr) break;
|
||||
|
||||
@@ -168,8 +168,12 @@ module axis_replay #(
|
||||
// The lower MEM_ALIGN bits for all memory byte addresses should be 0.
|
||||
localparam MEM_ALIGN = $clog2(MEM_DATA_W / 8);
|
||||
//
|
||||
// AXI alignment requirement (4096 bytes) in MEM_DATA_W-bit words
|
||||
localparam AXI_ALIGNMENT = 4096 / BYTES_PER_WORD;
|
||||
// Burst length in bytes
|
||||
localparam BURST_LENGTH = 2**MEM_COUNT_W * BYTES_PER_WORD;
|
||||
//
|
||||
// AXI alignment requirement (normally 4096 bytes) in MEM_DATA_W-bit words
|
||||
localparam AXI_ALIGNMENT = (BURST_LENGTH <= 4096) ? 4096 / BYTES_PER_WORD :
|
||||
BURST_LENGTH / BYTES_PER_WORD;
|
||||
|
||||
// Memory Buffering Parameters
|
||||
//
|
||||
|
||||
@@ -15,26 +15,30 @@
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// THIS_PORTID : Control crossbar port to which this block is connected
|
||||
// CHDR_W : AXIS-CHDR data bus width
|
||||
// MTU : Maximum transmission unit (i.e., maximum packet size in
|
||||
// CHDR words is 2**MTU).
|
||||
// NUM_PORTS : Number of replay instances to instantiate. Each one will
|
||||
// have its own register set and memory interface.
|
||||
// MEM_DATA_W : Data width to use for the memory interface.
|
||||
// MEM_ADDR_W : Byte address width to use for the memory interface.
|
||||
// THIS_PORTID : Control crossbar port to which this block is connected
|
||||
// CHDR_W : AXIS-CHDR data bus width
|
||||
// MTU : Maximum transmission unit (i.e., maximum packet size in
|
||||
// CHDR words is 2**MTU).
|
||||
// NUM_PORTS : Number of replay instances to instantiate. Each one will
|
||||
// have its own register set and memory interface.
|
||||
// MEM_DATA_W : Data width to use for the memory interface.
|
||||
// MEM_ADDR_W : Byte address width to use for the memory interface.
|
||||
// BURST_LENGTH : Burst length to use in bytes. Must not exceed 256 words. It
|
||||
// can be larger than the 4096-byte limit of AXI, but this
|
||||
// might not be compatible with all memories.
|
||||
//
|
||||
|
||||
`default_nettype none
|
||||
|
||||
|
||||
module rfnoc_block_replay #(
|
||||
parameter [9:0] THIS_PORTID = 10'd0,
|
||||
parameter CHDR_W = 64,
|
||||
parameter [5:0] MTU = 10,
|
||||
parameter NUM_PORTS = 1,
|
||||
parameter MEM_DATA_W = 64,
|
||||
parameter MEM_ADDR_W = 30
|
||||
parameter [9:0] THIS_PORTID = 10'd0,
|
||||
parameter CHDR_W = 64,
|
||||
parameter [5:0] MTU = 10,
|
||||
parameter NUM_PORTS = 1,
|
||||
parameter MEM_DATA_W = 64,
|
||||
parameter MEM_ADDR_W = 30,
|
||||
parameter BURST_LENGTH = MEM_DATA_W/8 * 256
|
||||
) (
|
||||
//---------------------------------------------------------------------------
|
||||
// AXIS-CHDR Port
|
||||
@@ -323,11 +327,10 @@ module rfnoc_block_replay #(
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Width of memory transfer count. This controls the maximum burst length
|
||||
// supported by the Replay block. For AXI compatibility, it must be 8 or less
|
||||
// and should not represent more than 4 KiB. Here we set it to 2 KiB by
|
||||
// default.
|
||||
localparam MEM_COUNT_W = (MEM_DATA_W <= 64) ? 8 : // Max width allowed
|
||||
$clog2(2048 / (MEM_DATA_W/8)); // 2 KiB
|
||||
// supported by the Replay block. For AXI, it must not exceed 8 and it should
|
||||
// be no more than 4096 unless supported by the memory being used.
|
||||
localparam DESIRED_MEM_COUNT_W = $clog2(BURST_LENGTH / (MEM_DATA_W/8));
|
||||
localparam MEM_COUNT_W = (DESIRED_MEM_COUNT_W > 8) ? 8 : DESIRED_MEM_COUNT_W;
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
|
||||
@@ -209,7 +209,8 @@ module rfnoc_block_replay_tb#(
|
||||
.DWIDTH (MEM_DATA_W),
|
||||
.IDWIDTH (1),
|
||||
.BIG_ENDIAN (0),
|
||||
.STALL_PROB (STALL_PROB)
|
||||
.STALL_PROB (STALL_PROB),
|
||||
.NO_4KB_LIMIT(MEM_DATA_W/8 * 256 > 4096)
|
||||
) sim_axi_ram_i (
|
||||
.s_aclk (mem_clk),
|
||||
.s_aresetn (~mem_rst),
|
||||
|
||||
Reference in New Issue
Block a user