data_offload: Refactor core

Deprecate unused parameters.

Change to MEM_SIZE_LOG2, to support only power of 2 storage sizes for
now. However in the future we might want to add support for non pow2
sizes so register map is not changed.

Change transfer length to -1 value to spare logic.

Change FIFO interface to AXIS to have backpressure, this allows the
implementation of data movement logic in the storage unit and let the
FSM handle high level control an synchronization and control the storage
unit through a control interface.

Refactor FSM to have preparation states where slow storages can be
configured and started ahead of the data handling.

Make bypasss FIFO optional since in some cases causes timing failures
due the missing output register of the memory. This can be targeted in
a later commit.

Hook up underflow/overflow to regmap useful in case of external memory
where rate drops due misconfiguration can be detected.

Cleanup for verilator.

Scripting:
Add HBM and DDR external memory support using util_hbm IP
Replace asym_block_ram with util_do_ram IP
main
Laszlo Nagy 2022-02-24 13:44:05 +02:00 committed by Laszlo Nagy
parent 35d32e0143
commit c3ae609bc8
10 changed files with 631 additions and 945 deletions

View File

@ -16,7 +16,12 @@ GENERIC_DEPS += data_offload_regmap.v
XILINX_DEPS += data_offload_ip.tcl XILINX_DEPS += data_offload_ip.tcl
XILINX_DEPS += data_offload_sv.ttcl XILINX_DEPS += data_offload_sv.ttcl
XILINX_DEPS += ../interfaces/if_do_ctrl.xml
XILINX_DEPS += ../interfaces/if_do_ctrl_rtl.xml
XILINX_LIB_DEPS += util_axis_fifo_asym XILINX_LIB_DEPS += util_axis_fifo_asym
XILINX_LIB_DEPS += util_cdc XILINX_LIB_DEPS += util_cdc
XILINX_INTERFACE_DEPS += interfaces
include ../scripts/library.mk include ../scripts/library.mk

View File

@ -59,17 +59,14 @@ URAM, external memory etc.)
|----------------------|:-----------:|:----------:|:---------------------------:| |----------------------|:-----------:|:----------:|:---------------------------:|
|ID | integer | 0 | Instance ID number | |ID | integer | 0 | Instance ID number |
|MEM_TYPE | [ 0:0] | 0 | Define the used storage type: FPGA RAM - 0; external DDR - 1 | |MEM_TYPE | [ 0:0] | 0 | Define the used storage type: FPGA RAM - 0; external DDR - 1 |
|MEM_SIZE | [31:0] | 1024 | Define the size of the storage element | |MEM_SIZE_LOG2 | integer | 10 | Log2 value of storage size, defines the width of transfer length control signals. |
|MEMC_UIF_DATA_WIDTH | [ 0:0] | 512 | The valid data depends on the DDRx memory controller IP. |
|TX_OR_RXN_PATH | [ 0:0] | 1 | If set TX path enabled, otherwise RX | |TX_OR_RXN_PATH | [ 0:0] | 1 | If set TX path enabled, otherwise RX |
|SRC_DATA_WIDTH | integer | 64 | The data width of the source interface | |SRC_DATA_WIDTH | integer | 64 | The data width of the source interface |
|SRC_RAW_DATA_EN | [ 0:0] | 0 | Enable if the data path does extend samples to 16 bits | |DST_DATA_WIDTH | integer | 124 | The data width of the destination interface |
|SRC_ADDR_WIDTH | integer | 8 | The address width of the source interface, should be defined relative to the MEM_SIZE (MEM_SIZE/SRC_DATA_WIDTH/8) |
|DST_ADDR_WIDTH | integer | 7 | The address width of the source interface, should be defined relative to the MEM_SIZE (MEM_SIZE/DST_DATA_WIDTH/8) |
|DST_DATA_WIDTH | integer | 64 | The data width of the destination interface |
|DST_RAW_DATA_EN | [ 0:0] | 0 | Enable if the data path does extend samples to 16 bits |
|DST_CYCLIC_EN | [ 0:0] | 0 | Enables CYCLIC mode for destinations like DAC | |DST_CYCLIC_EN | [ 0:0] | 0 | Enables CYCLIC mode for destinations like DAC |
|AUTO_BRINUP | [ 0:0] | 0 | If enabled the IP runs automatically after bootup | |AUTO_BRINGUP | [ 0:0] | 1 | If enabled the IP runs automatically after bootup |
|SYNC_EXT_ADD_INTERNAL_CDC | [ 0:0] | 1 | If enabled the external sync pin is synchronized to the internal clock domain with a CDC. |
|HAS_BYPASS | [ 0:0] | 1 | If set to zero the bypass FIFO is not implemented. |
## Interfaces ## Interfaces
@ -141,9 +138,9 @@ input s_axi_rready
**NOTE**: To simplify the design both the source and destination data interface is **NOTE**: To simplify the design both the source and destination data interface is
an AXI4 streaming interface. A FIFO write (ADC) interface can be treated as AXI4 an AXI4 streaming interface. A FIFO write (ADC) interface can be treated as AXI4
stream where only the master controles the data rate (s_axis_ready is always asserted), stream where only the master controls the data rate (s_axis_ready is always asserted),
and a FIFO read (DAC) interface can be treated as an AXI4 stream where only the slave and a FIFO read (DAC) interface can be treated as an AXI4 stream where only the slave
controles the data rate. (m_axis_valid is always asserted). controls the data rate. (m_axis_valid is always asserted).
#### AXI4 Stream interface (S_AXIS | M_AXIS) #### AXI4 Stream interface (S_AXIS | M_AXIS)
@ -178,76 +175,23 @@ and **axis_tkeep** will be used to indicate a partial last beat. This informatio
should be transferred from the source domain to the sink domain, so we can read should be transferred from the source domain to the sink domain, so we can read
back the data from memory correctly. back the data from memory correctly.
#### FIFO source and destination interface to the storage unit #### AXIS source and destination interface to the storage unit
This is non-blocking (no back-pressure) interface for the storage unit, This is blocking (back-pressure) interface for the storage unit,
having an address bus too, so an ad_mem module can be connected directly to controller IP. with similar behavior of main AXIS data interfaces.
```verilog
// This is a FIFO source interface - it's clocked on the source clock (s_axis_aclk)
// Reset signal
output fifo_src_resetn
// write enable signal
output fifo_src_wen
// address bus for internal memory
output [SRC_ADDR_WIDTH-1:0] fifo_src_waddr
// source data bus
output [SRC_DATA_WIDTH-1:0] fifo_src_wdata
// write last, indicates the last valid transfer
output fifo_src_wlast
```
```verilog
// This is a FIFO destination interface - it's clocked on the destination clock (m_axis_aclk)
// Reset signal
output fifo_dst_resetn
// read enable signal
output fifo_dst_ren
// indicate if the storage is ready to accept read requests
output fifo_dst_ready,
// address bus for internal memory
output [DST_ADDR_WIDTH-1:0] fifo_dst_raddr
// destination data bus
output [DST_DATA_WIDTH-1:0] fifo_dst_rdata
```
```verilog
// This is a Slave FIFO Read interface
// device digital interface clock, or core clock
input fifo_rd_clk
// enables the channel -- in our case this is redundant -- maybe we do neet to use it at all
input fifo_rd_enable
// validates the data on the bus, it's driven by the device indicates when the core latches the data
input fifo_rd_valid
// primary payload, its data width is equal with the channel's data width
output [DATA_WIDTH-1:0] fifo_rd_data
// indicates an underflow, the source (offload FIFO in this case) can not produce the data fast enough
output fifo_rd_unf
```
### Initialization request interface ### Initialization request interface
Define a simple request/acknowledge interface to initialize the memory: Define a simple request interface to initialize the memory:
* The request will comes from the system and will put the data offload FSM * The request will comes from the system and will put the data offload FSM
into a standby/ready state. into a standby/ready state.
* Both RX and TX path should have a separate initialization request interface.
* Acknowledge will be asserted by the data offload IP as the FSM is ready to
receive data. (from TX_DMA or ADC)
* In case of ADC: after the acknowledge samples will be stored into the memory
using one of the SYNC modes.
* In case of the DAC: after acknowledge data from the DMA will be stored into
the memory. Acknowledge will stay asserted until one of the SYNC mode is used,
after that the source interface of the IP will stay in busy state. (all the DMA
transfers will be blocked)
#### Synchronization modes #### Synchronization modes
* **AUTOMATIC** * **AUTOMATIC**
* ADC: As the acknowledge of the initialization interface is asserted, the * ADC: The IP will start to fill up the buffer with samples as soon as possible.
IP will start to fill up the buffer with samples.
* DAC: As the DMA will send a valid last, the FSM will start to send the * DAC: As the DMA will send a valid last, the FSM will start to send the
stored data to the device. stored data to the device.
@ -274,13 +218,14 @@ into or from the memory.
| 0x0002 | 0x0008 | | `SCRATCH` | RW | SYS | Scratch register | | 0x0002 | 0x0008 | | `SCRATCH` | RW | SYS | Scratch register |
| 0x0003 | 0x000C | | `IDENTIFICATION` | RO | SYS | Peripheral identification. Default value: 0x44414F46 - ('D','A','O','F') | | 0x0003 | 0x000C | | `IDENTIFICATION` | RO | SYS | Peripheral identification. Default value: 0x44414F46 - ('D','A','O','F') |
| 0x0004 | 0x0010 | | `SYNTHESIS_CONFIG` | RO | SYS | Core configuration registers | | 0x0004 | 0x0010 | | `SYNTHESIS_CONFIG` | RO | SYS | Core configuration registers |
| | | [13: 8] | `MEM_SIZE_LOG2` | | | Log2 of memory size in bytes |
| | | [ 2: 2] | `HAS_BYPASS` | | | If not set the bypass logic is not implemented. |
| | | [ 1: 1] | `TX_OR_RXN_PATH` | | | RX Path => 0, TX => 1 | | | | [ 1: 1] | `TX_OR_RXN_PATH` | | | RX Path => 0, TX => 1 |
| | | [ 0: 0] | `MEMORY_TYPE` | | | The used storage type (embedded => 0 or external => 1) | | | | [ 0: 0] | `MEMORY_TYPE` | | | The used storage type (embedded => 0 or external => 1) |
| 0x0005 | 0x0014 | | `MEMORY_SIZE_LSB` | RO | SYS | 32bits LSB of the memory size register |
| 0x0006 | 0x0018 | | `MEMORY_SIZE_MSB` | RO | SYS | 2bits MSB of the memory size register |
| | | [ 1: 0] | `MEMORY_SIZE_MSB` | | | |
| 0x0007 | 0x001C | | `TRANSFER_LENGTH` | RW | SRC | Transfer length | | 0x0007 | 0x001C | | `TRANSFER_LENGTH` | RW | SRC | Transfer length |
| 0x0020 | 0x0080 | | `MEM_PHY_STATE` | RO | DDR | Status bits of the memory controller IP | | 0x0020 | 0x0080 | | `MEM_PHY_STATE` | RO | DDR | Status bits of the memory controller IP |
| | | [ 5: 5] | `UNDERFLOW` | RW1C | | Indicates that storage could not handle data rate during play. Available when core is in TX mode.|
| | | [ 4: 4] | `OVERFLOW` | RW1C | | Indicates that storage could not handle data rate during capture. Available when core is in RX mode. |
| | | [ 0: 0] | `CALIB_COMPLETE` | | | Indicates that the memory initialization and calibration have completed successfully | | | | [ 0: 0] | `CALIB_COMPLETE` | | | Indicates that the memory initialization and calibration have completed successfully |
| 0x0021 | 0x0084 | | `RESETN_OFFLOAD` | RW | DST/SRC | Reset all the internal address registers and state machines | | 0x0021 | 0x0084 | | `RESETN_OFFLOAD` | RW | DST/SRC | Reset all the internal address registers and state machines |
| | | [ 0: 0] | `RESETN` | | | | | | | [ 0: 0] | `RESETN` | | | |
@ -292,10 +237,8 @@ into or from the memory.
| 0x0041 | 0x0104 | | `SYNC_CONFIG` | RW | SRC | Synchronization setup | | 0x0041 | 0x0104 | | `SYNC_CONFIG` | RW | SRC | Synchronization setup |
| | | [ 1: 0] | `SYNC_CONFIG` | | | Auto - '0'; hardware - '1'; software - '2' | | | | [ 1: 0] | `SYNC_CONFIG` | | | Auto - '0'; hardware - '1'; software - '2' |
| 0x0080 | 0x0200 | | `FSM_DBG` | RO | | Debug register for the offload FSM | | 0x0080 | 0x0200 | | `FSM_DBG` | RO | | Debug register for the offload FSM |
| | | [ 5: 4] | `FSM_STATE_READ` | | SRC | The current state of the read-offload state machine | | | | [11: 8] | `FSM_STATE_READ` | | SRC | The current state of the read-offload state machine |
| | | [ 1: 0] | `FSM_STATE_WRITE` | | DST | The current state of the write-offload state machine | | | | [ 4: 0] | `FSM_STATE_WRITE` | | DST | The current state of the write-offload state machine |
| 0x0081 | 0x0204 | | `SAMPLE_COUNT_LSB` | RO | SRC | Stored sample count (32 LSB) |
| 0x0082 | 0x0208 | | `SAMPLE_COUNT_MSB` | RO | SRC | Stored sample count (32 MSB) |
## Clock tree ## Clock tree

View File

@ -38,25 +38,19 @@ module data_offload #(
parameter ID = 0, parameter ID = 0,
parameter [ 0:0] MEM_TYPE = 1'b0, // 1'b0 -FPGA RAM; 1'b1 - external memory parameter [ 0:0] MEM_TYPE = 1'b0, // 1'b0 -FPGA RAM; 1'b1 - external memory
parameter [33:0] MEM_SIZE = 1024, // memory size in bytes -1 - max 16 GB parameter MEM_SIZE_LOG2 = 10, // log2 of memory size in bytes
parameter MEMC_UIF_DATA_WIDTH = 512,
parameter MEMC_UIF_ADDRESS_WIDTH = 31,
parameter [31:0] MEMC_BADDRESS = 32'h00000000,
parameter TX_OR_RXN_PATH = 0, // if set IP is used in TX path, other wise in RX path parameter TX_OR_RXN_PATH = 0, // if set IP is used in TX path, other wise in RX path
parameter SRC_DATA_WIDTH = 64, parameter SRC_DATA_WIDTH = 64,
parameter SRC_RAW_DATA_EN = 1'b0,
parameter SRC_ADDR_WIDTH = 8,
parameter DST_ADDR_WIDTH = 7,
parameter DST_DATA_WIDTH = 128, parameter DST_DATA_WIDTH = 128,
parameter DST_RAW_DATA_EN = 1'b0, // TBD
parameter DST_CYCLIC_EN = 1'b0, // 1'b1 - CYCLIC mode enabled; 1'b0 - CYCLIC mode disabled parameter DST_CYCLIC_EN = 1'b0, // 1'b1 - CYCLIC mode enabled; 1'b0 - CYCLIC mode disabled
parameter AUTO_BRINGUP = 1, parameter AUTO_BRINGUP = 1,
parameter SYNC_EXT_ADD_INTERNAL_CDC = 1) ( parameter SYNC_EXT_ADD_INTERNAL_CDC = 1,
parameter HAS_BYPASS = 1
) (
// AXI4 Slave for configuration // AXI4 Slave for configuration
@ -86,6 +80,7 @@ module data_offload #(
input s_axis_aclk, input s_axis_aclk,
input s_axis_aresetn, input s_axis_aresetn,
output s_axis_ready, output s_axis_ready,
input s_axis_valid, input s_axis_valid,
input [SRC_DATA_WIDTH-1:0] s_axis_data, input [SRC_DATA_WIDTH-1:0] s_axis_data,
@ -97,6 +92,7 @@ module data_offload #(
input m_axis_aclk, input m_axis_aclk,
input m_axis_aresetn, input m_axis_aresetn,
input m_axis_ready, input m_axis_ready,
output m_axis_valid, output m_axis_valid,
output [DST_DATA_WIDTH-1:0] m_axis_data, output [DST_DATA_WIDTH-1:0] m_axis_data,
@ -106,23 +102,43 @@ module data_offload #(
// initialization request interface // initialization request interface
input init_req, input init_req,
output init_ack,
input sync_ext, input sync_ext,
// FIFO interface - Memory UI // AXIS - Memory UI to storage
output fifo_src_wen, // AXI stream master for source stream to storage (BRAM/URAM/DDR/HBM)
output fifo_src_resetn, // runs on s_axis_aclk and s_axis_aresetn
output [SRC_ADDR_WIDTH-1:0] fifo_src_waddr, input m_storage_axis_ready,
output [SRC_DATA_WIDTH-1:0] fifo_src_wdata, output m_storage_axis_valid,
output fifo_src_wlast, output [SRC_DATA_WIDTH-1:0] m_storage_axis_data,
output m_storage_axis_last,
output [SRC_DATA_WIDTH/8-1:0] m_storage_axis_tkeep,
output fifo_dst_ren, // AXI stream slave for destination stream from storage (BRAM/URAM/DDR/HBM)
input fifo_dst_ready, // runs on m_axis_aclk and m_axis_aresetn
output fifo_dst_resetn, output s_storage_axis_ready,
output [DST_ADDR_WIDTH-1:0] fifo_dst_raddr, input s_storage_axis_valid,
input [DST_DATA_WIDTH-1:0] fifo_dst_rdata, input [DST_DATA_WIDTH-1:0] s_storage_axis_data,
input s_storage_axis_last,
input [DST_DATA_WIDTH/8-1:0] s_storage_axis_tkeep,
// Control interface for storage for m_storage_axis interface
output wr_request_enable,
output wr_request_valid,
input wr_request_ready,
output [MEM_SIZE_LOG2-1:0] wr_request_length,
input [MEM_SIZE_LOG2-1:0] wr_response_measured_length,
input wr_response_eot,
input wr_overflow,
// Control interface for storage for s_storage_axis interface
output rd_request_enable,
output rd_request_valid,
input rd_request_ready,
output reg [MEM_SIZE_LOG2-1:0] rd_request_length,
input rd_response_eot,
input rd_underflow,
// Status and monitor // Status and monitor
@ -154,138 +170,82 @@ module data_offload #(
wire src_clk; wire src_clk;
wire src_rstn; wire src_rstn;
wire src_valid_out_s;
wire [SRC_ADDR_WIDTH-1:0] src_wr_addr_s;
wire src_wr_ready_s;
wire src_wr_last_s;
wire [SRC_DATA_WIDTH/8-1:0] src_wr_tkeep_s;
wire dst_clk; wire dst_clk;
wire dst_rstn; wire dst_rstn;
wire [DST_ADDR_WIDTH-1:0] dst_raddr_s;
wire [DST_DATA_WIDTH-1:0] dst_mem_data_s;
wire src_bypass_s; wire src_bypass_s;
wire dst_bypass_s; wire dst_bypass_s;
wire oneshot_s; wire oneshot_s;
wire [63:0] sample_count_s;
wire [ 1:0] sync_config_s; wire [ 1:0] sync_config_s;
wire sync_int_s; wire sync_int_s;
wire valid_bypass_s; wire valid_bypass_s;
wire [DST_DATA_WIDTH-1:0] data_bypass_s; wire [DST_DATA_WIDTH-1:0] data_bypass_s;
wire ready_bypass_s; wire ready_bypass_s;
wire [ 1:0] src_fsm_status_s; wire [ 4:0] src_fsm_status_s;
wire [ 1:0] dst_fsm_status_s; wire [ 3:0] dst_fsm_status_s;
wire m_axis_valid_s;
wire m_axis_last_s;
wire [DST_DATA_WIDTH-1:0] m_axis_data_s;
wire dst_mem_valid_s;
wire dst_mem_valid_int_s;
wire m_axis_reset_int_s;
wire [33:0] src_transfer_length_s; wire [MEM_SIZE_LOG2-1:0] src_transfer_length_s;
wire src_wr_last_int_s; wire [MEM_SIZE_LOG2-1:0] rd_wr_response_measured_length;
wire [33:0] src_wr_last_beat_s; wire rd_ml_valid;
wire rd_ready;
wire int_not_full; wire rd_ml_ready;
wire wr_ready;
assign src_clk = s_axis_aclk; assign src_clk = s_axis_aclk;
assign dst_clk = m_axis_aclk; assign dst_clk = m_axis_aclk;
// internal registers // internal registers
reg [33:0] src_data_counter = 0;
reg dst_mem_valid_d = 1'b0;
generate
if (TX_OR_RXN_PATH) begin
assign src_wr_last_s = s_axis_last;
assign src_wr_tkeep_s = s_axis_tkeep;
assign m_axis_reset_int_s = ~dst_rstn;
end else begin
assign src_wr_last_s = src_wr_last_int_s;
assign src_wr_tkeep_s = {(SRC_DATA_WIDTH/8){1'b1}};
assign m_axis_reset_int_s = ~dst_rstn | ~init_req;
end
endgenerate
assign fifo_src_wlast = src_wr_last_s;
// Offload FSM and control // Offload FSM and control
data_offload_fsm #( data_offload_fsm #(
.TX_OR_RXN_PATH (TX_OR_RXN_PATH), .TX_OR_RXN_PATH (TX_OR_RXN_PATH),
.WR_ADDRESS_WIDTH (SRC_ADDR_WIDTH), .SYNC_EXT_ADD_INTERNAL_CDC (SYNC_EXT_ADD_INTERNAL_CDC))
.WR_DATA_WIDTH (SRC_DATA_WIDTH),
.RD_ADDRESS_WIDTH (DST_ADDR_WIDTH),
.RD_DATA_WIDTH (DST_DATA_WIDTH),
.SYNC_EXT_ADD_INTERNAL_CDC (SYNC_EXT_ADD_INTERNAL_CDC ))
i_data_offload_fsm ( i_data_offload_fsm (
.up_clk (up_clk), .up_clk (up_clk),
.wr_clk (src_clk), .wr_clk (src_clk),
.wr_resetn_in (src_rstn), .wr_resetn_in (src_rstn),
.wr_resetn_out (fifo_src_resetn), .wr_request_enable (wr_request_enable),
.wr_valid_in (s_axis_valid), .wr_request_valid (wr_request_valid),
.wr_valid_out (fifo_src_wen), .wr_request_ready (wr_request_ready),
.wr_ready (src_wr_ready_s), .wr_response_eot (wr_response_eot),
.wr_addr (fifo_src_waddr), .wr_ready (wr_ready),
.wr_last (src_wr_last_s),
.wr_tkeep (src_wr_tkeep_s),
.rd_clk (dst_clk), .rd_clk (dst_clk),
.rd_resetn_in (dst_rstn), .rd_resetn_in (dst_rstn),
.rd_resetn_out (fifo_dst_resetn), .rd_request_enable (rd_request_enable),
.rd_ready (fifo_dst_ready_int_s), .rd_request_valid (rd_request_valid),
.rd_valid (dst_mem_valid_s), .rd_request_ready (rd_request_ready),
.rd_addr (fifo_dst_raddr), .rd_response_eot (rd_response_eot),
.rd_last (), .rd_ready (rd_ready),
.rd_tkeep (m_axis_tkeep), .rd_valid (s_storage_axis_valid),
.rd_ml_valid (rd_ml_valid),
.rd_ml_ready (rd_ml_ready),
.rd_oneshot (oneshot_s), .rd_oneshot (oneshot_s),
.wr_bypass (src_bypass_s),
.init_req (init_req), .init_req (init_req),
.init_ack (init_ack),
.sync_config (sync_config_s), .sync_config (sync_config_s),
.sync_external (sync_ext), .sync_external (sync_ext),
.sync_internal (sync_int_s), .sync_internal (sync_int_s),
.wr_fsm_state (src_fsm_status_s), .wr_fsm_state_out (src_fsm_status_s),
.rd_fsm_state (dst_fsm_status_s), .rd_fsm_state_out (dst_fsm_status_s)
.sample_count (sample_count_s)
); );
// In case of external memory, read back can not start right after the write assign m_axis_valid = rd_ready & ((dst_bypass_s) ? valid_bypass_s : s_storage_axis_valid);
// was finished (because of the CDC FIFOs and the latency of the EMIF // For DAC paths set zero as IDLE data on the axis bus, avoid repeating last
// interface) // sample.
generate assign m_axis_data = TX_OR_RXN_PATH[0] & ~m_axis_valid ? {DST_DATA_WIDTH{1'b0}} :
if (MEM_TYPE == 1'b1) begin (dst_bypass_s) ? data_bypass_s : s_storage_axis_data;
assign dst_mem_valid_int_s = dst_mem_valid_s; assign m_axis_last = (dst_bypass_s) ? 1'b0 : s_storage_axis_last;
end else begin assign m_axis_tkeep = (dst_bypass_s) ? {DST_DATA_WIDTH/8{1'b1}} : s_storage_axis_tkeep;
// Compensate the 1 cycle READ latency of the BRAM
always @(posedge m_axis_aclk) begin
dst_mem_valid_d <= dst_mem_valid_s;
end
assign dst_mem_valid_int_s = dst_mem_valid_d;
end
endgenerate
assign fifo_dst_ready_int_s = fifo_dst_ready & int_not_full; assign s_axis_ready = wr_ready & ((src_bypass_s) ? ready_bypass_s : m_storage_axis_ready);
assign fifo_src_wdata = s_axis_data; assign m_storage_axis_valid = s_axis_valid & wr_ready;
assign fifo_dst_ren = dst_mem_valid_s; assign m_storage_axis_data = s_axis_data;
assign m_storage_axis_last = s_axis_last;
assign m_storage_axis_tkeep = s_axis_tkeep;
ad_axis_inf_rx #( assign s_storage_axis_ready = rd_ready & m_axis_ready;
.DATA_WIDTH (DST_DATA_WIDTH))
i_rx_axis_inf (
.clk (m_axis_aclk),
.rst (m_axis_reset_int_s),
.valid (dst_mem_valid_int_s),
.data (fifo_dst_rdata),
.last (1'b0),
.inf_valid (m_axis_valid_s),
.inf_last (m_axis_last_s),
.inf_data (m_axis_data_s),
.inf_ready (m_axis_ready),
.int_not_full(int_not_full));
assign m_axis_valid = (dst_bypass_s) ? valid_bypass_s : m_axis_valid_s;
assign m_axis_data = (dst_bypass_s) ? data_bypass_s : m_axis_data_s;
assign m_axis_last = (dst_bypass_s) ? 1'b0 : m_axis_last_s;
assign s_axis_ready = (src_bypass_s) ? ready_bypass_s : src_wr_ready_s;
// Bypass module instance -- the same FIFO, just a smaller depth // Bypass module instance -- the same FIFO, just a smaller depth
// NOTE: Generating an overflow is making sense just in BYPASS mode, and // NOTE: Generating an overflow is making sense just in BYPASS mode, and
@ -304,6 +264,8 @@ module data_offload #(
.m_axis_tlast (), .m_axis_tlast (),
.m_axis_empty (), .m_axis_empty (),
.m_axis_almost_empty (), .m_axis_almost_empty (),
.m_axis_tkeep (),
.m_axis_level (),
.s_axis_aclk (s_axis_aclk), .s_axis_aclk (s_axis_aclk),
.s_axis_aresetn (src_rstn), .s_axis_aresetn (src_rstn),
.s_axis_ready (ready_bypass_s), .s_axis_ready (ready_bypass_s),
@ -311,7 +273,9 @@ module data_offload #(
.s_axis_data (s_axis_data), .s_axis_data (s_axis_data),
.s_axis_tlast (), .s_axis_tlast (),
.s_axis_full (), .s_axis_full (),
.s_axis_almost_full () .s_axis_almost_full (),
.s_axis_tkeep (),
.s_axis_room ()
); );
// register map // register map
@ -319,10 +283,11 @@ module data_offload #(
data_offload_regmap #( data_offload_regmap #(
.ID (ID), .ID (ID),
.MEM_TYPE (MEM_TYPE), .MEM_TYPE (MEM_TYPE),
.MEM_SIZE (MEM_SIZE), .MEM_SIZE_LOG2 (MEM_SIZE_LOG2),
.TX_OR_RXN_PATH (TX_OR_RXN_PATH), .TX_OR_RXN_PATH (TX_OR_RXN_PATH),
.AUTO_BRINGUP (AUTO_BRINGUP)) .AUTO_BRINGUP (AUTO_BRINGUP),
i_regmap ( .HAS_BYPASS (HAS_BYPASS)
) i_regmap (
.up_clk (up_clk), .up_clk (up_clk),
.up_rstn (up_rstn), .up_rstn (up_rstn),
.up_rreq (up_rreq_s), .up_rreq (up_rreq_s),
@ -343,11 +308,12 @@ module data_offload #(
.oneshot (oneshot_s), .oneshot (oneshot_s),
.sync (sync_int_s), .sync (sync_int_s),
.sync_config (sync_config_s), .sync_config (sync_config_s),
.src_transfer_length (src_transfer_length_s), .src_transfer_length (wr_request_length),
.dst_transfer_length (),
.src_fsm_status (src_fsm_status_s), .src_fsm_status (src_fsm_status_s),
.dst_fsm_status (dst_fsm_status_s), .dst_fsm_status (dst_fsm_status_s),
.sample_count_msb (sample_count_s[63:32]), .src_overflow (wr_overflow),
.sample_count_lsb (sample_count_s[31: 0]) .dst_underflow (rd_underflow)
); );
// axi interface wrapper // axi interface wrapper
@ -386,30 +352,39 @@ module data_offload #(
.up_rdata (up_rdata_s), .up_rdata (up_rdata_s),
.up_rack (up_rack_s)); .up_rack (up_rack_s));
/* Beat counter on the source interface // Measured length handshake CDC
* util_axis_fifo #(
* The storage unit can have size of a couple of Gbyte, which in case of an RX .DATA_WIDTH(MEM_SIZE_LOG2),
* path would mean to fill up all that memory space before pushing over the .ADDRESS_WIDTH(0),
* stream to the RX DMA. (ADC can not generate a tlast) To make things more .ASYNC_CLK(1)
* practical, user can set an arbitrary transfer length using the ) i_measured_length_cdc (
* transfer_length register, which will be used to generate an internal tlast .s_axis_aclk(s_axis_aclk),
* signal for the source FSM. If the register is set to zero, all the memory .s_axis_aresetn(s_axis_aresetn),
* will be filled up, before passing control to the destination FSM. .s_axis_valid(wr_response_eot),
* .s_axis_ready(),
*/ .s_axis_full(),
.s_axis_data(wr_response_measured_length),
.s_axis_room(),
.s_axis_tkeep(),
.s_axis_tlast(),
.s_axis_almost_full(),
always @(posedge s_axis_aclk) begin .m_axis_aclk(m_axis_aclk),
if (fifo_src_resetn == 1'b0) begin // counter should reset when source FMS resets .m_axis_aresetn(m_axis_aresetn),
src_data_counter <= 0; .m_axis_valid(rd_ml_valid),
end else begin .m_axis_ready(rd_ml_ready),
if (fifo_src_wen & src_wr_ready_s) begin .m_axis_data(rd_wr_response_measured_length),
src_data_counter <= src_data_counter + 1'b1; .m_axis_level(),
end .m_axis_empty(),
end .m_axis_tkeep(),
.m_axis_tlast(),
.m_axis_almost_empty()
);
always @(posedge m_axis_aclk) begin
if (rd_ml_valid & rd_ml_ready)
rd_request_length <= rd_wr_response_measured_length;
end end
// transfer length is in bytes, but counter monitors the source data beats
assign src_wr_last_beat_s = (src_transfer_length_s == 'h0) ? MEM_SIZE[33:SRC_BEAT_BYTE]-1 : src_transfer_length_s[33:SRC_BEAT_BYTE]-1;
assign src_wr_last_int_s = (src_data_counter == src_wr_last_beat_s) ? 1'b1 : 1'b0;
endmodule endmodule

View File

@ -6,6 +6,7 @@
<: set mem_type [getBooleanValue "MEM_TYPE"] :> <: set mem_type [getBooleanValue "MEM_TYPE"] :>
<: set tx_enable [getBooleanValue "TX_OR_RXN_PATH"] :> <: set tx_enable [getBooleanValue "TX_OR_RXN_PATH"] :>
<: set internal_cdc [getBooleanValue "SYNC_EXT_ADD_INTERNAL_CDC"] :> <: set internal_cdc [getBooleanValue "SYNC_EXT_ADD_INTERNAL_CDC"] :>
<: set has_bypass [getBooleanValue "HAS_BYPASS"] :>
## for all synchronization registers from util_cdc modules ## for all synchronization registers from util_cdc modules
set_property ASYNC_REG TRUE \ set_property ASYNC_REG TRUE \
@ -13,7 +14,7 @@ set_property ASYNC_REG TRUE \
[get_cells -hier {*cdc_sync_stage2_reg*}] [get_cells -hier {*cdc_sync_stage2_reg*}]
## For RX in case of BRAMs ## For RX in case of BRAMs
<: if { $tx_enable == 0 } { :> <: if { !$tx_enable } { :>
<: if { $internal_cdc } { :> <: if { $internal_cdc } { :>
set_false_path \ set_false_path \
@ -32,22 +33,10 @@ set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/out_toggle_d1_reg/C}] \ -from [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/i_sync_in/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/i_sync_in/cdc_sync_stage1_reg[*]/D}]
<: if { !$mem_type } { :>
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*adc_init_sync.i_rd_init_ack_sync/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*adc_init_sync.i_rd_init_ack_sync/i_sync_out/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*adc_init_sync.i_rd_init_ack_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*adc_init_sync.i_rd_init_ack_sync/i_sync_in/cdc_sync_stage1_reg[*]/D}]
<: } :>
<: } :> <: } :>
## For TX in case of BRAMs ## For TX in case of BRAMs
<: if { $tx_enable == 1 } { :> <: if { $tx_enable } { :>
<: if { $internal_cdc } { :> <: if { $internal_cdc } { :>
set_false_path \ set_false_path \
@ -55,23 +44,11 @@ set_false_path \
<: } :> <: } :>
<: if { !$mem_type } { :>
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*dac_init_sync.i_wr_init_ack_sync/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*dac_init_sync.i_wr_init_ack_sync/i_sync_out/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*dac_init_sync.i_wr_init_ack_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*dac_init_sync.i_wr_init_ack_sync/i_sync_in/cdc_sync_stage1_reg[*]/D}]
<: } :>
<: } :> <: } :>
## For external DDRx memory ## For external DDRx memory
<: if { $mem_type == 1 } { :> <: if { $mem_type } { :>
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_ddr_calib_done_sync/cdc_sync_stage1_reg[0]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_ddr_calib_done_sync/cdc_sync_stage1_reg[0]/D}]
@ -80,18 +57,6 @@ set_false_path \
## Common constraints ## Common constraints
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_xfer_status/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_xfer_status/i_sync_out/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_xfer_status/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_xfer_status/i_sync_in/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_cells -hierarchical * -filter {NAME=~*/i_xfer_status/cdc_hold_reg[*]}] \
-to [get_cells -hierarchical * -filter {NAME=~*/i_xfer_status/out_data_reg[*]}]
set_false_path \ set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_dst_fsm_status/in_toggle_d1_reg/C}] \ -from [get_pins -hierarchical * -filter {NAME=~*/i_dst_fsm_status/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_dst_fsm_status/i_sync_out/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*/i_dst_fsm_status/i_sync_out/cdc_sync_stage1_reg[*]/D}]
@ -124,22 +89,6 @@ set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_wr_empty_sync/out_toggle_d1_reg/C}] \ -from [get_pins -hierarchical * -filter {NAME=~*/i_wr_empty_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_wr_empty_sync/i_sync_in/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*/i_wr_empty_sync/i_sync_in/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_rd_full_sync/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_rd_full_sync/i_sync_out/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_rd_full_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_rd_full_sync/i_sync_in/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_rd_wr_last_sync/out_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_rd_wr_last_sync/i_sync_in/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*/i_rd_wr_last_sync/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*/i_rd_wr_last_sync/i_sync_out/cdc_sync_stage1_reg[*]/D}]
set_false_path \ set_false_path \
-from [get_pins -hierarchical * -filter {NAME=~*i_sync_xfer_control/in_toggle_d1_reg/C}] \ -from [get_pins -hierarchical * -filter {NAME=~*i_sync_xfer_control/in_toggle_d1_reg/C}] \
-to [get_pins -hierarchical * -filter {NAME=~*i_sync_xfer_control/i_sync_out/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_sync_xfer_control/i_sync_out/cdc_sync_stage1_reg[*]/D}]
@ -153,20 +102,13 @@ set_false_path \
-to [get_cells -hierarchical * -filter {NAME=~*i_sync_xfer_control/out_data_reg[*]}] -to [get_cells -hierarchical * -filter {NAME=~*i_sync_xfer_control/out_data_reg[*]}]
<: if { $tx_enable } { :>
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_rd_init_req_sync/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_rd_init_req_sync/cdc_sync_stage1_reg[*]/D}]
<: } else { :>
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_wr_init_req_sync/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_wr_init_req_sync/cdc_sync_stage1_reg[*]/D}]
<: } :>
set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_wr_oneshot_sync/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*/i_rd_last_address/cdc_sync_stage1_reg[*]/D}]
set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*/i_rd_last_keep/cdc_sync_stage1_reg[*]/D}]
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_src_xfer_control/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_src_xfer_control/cdc_sync_stage1_reg[*]/D}]
@ -177,10 +119,48 @@ set_false_path \
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_dst_oneshot_sync/cdc_sync_stage1_reg[0]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_dst_oneshot_sync/cdc_sync_stage1_reg[0]/D}]
## Constraints for the bypass module
# measured transfer length util_axis_fifo
set src_clk [get_clocks -of_objects [get_ports s_axis_aclk]]
set dest_clk [get_clocks -of_objects [get_ports m_axis_aclk]]
set_max_delay -quiet -datapath_only \
-from $src_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_measured_length_cdc/zerodeep.i_waddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $src_clk]
set_max_delay -quiet -datapath_only \
-from $dest_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_measured_length_cdc/zerodeep.i_raddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \
-filter {NAME =~ *i_measured_length_cdc* && IS_SEQUENTIAL}] \
-to $dest_clk \
[get_property -min PERIOD $dest_clk]
## Constraints for the bypass module
<: if { $has_bypass } { :>
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_waddr_sync_gray/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_waddr_sync_gray/cdc_sync_stage1_reg[*]/D}]
set_false_path \ set_false_path \
-to [get_pins -hierarchical * -filter {NAME=~*i_raddr_sync_gray/cdc_sync_stage1_reg[*]/D}] -to [get_pins -hierarchical * -filter {NAME=~*i_raddr_sync_gray/cdc_sync_stage1_reg[*]/D}]
<: } :>
## Constraints for the overflow/underflow status
<: if { $tx_enable } { :>
set flow_cdc i_rd_underflow_sync
<: } else { :>
set flow_cdc i_wr_overflow_sync
<: } :>
set_false_path \
-from [get_pins -hierarchical * -filter NAME=~*/$flow_cdc/in_toggle_d1_reg/C] \
-to [get_pins -hierarchical * -filter NAME=~*/$flow_cdc/i_sync_out/cdc_sync_stage1_reg[*]/D]
set_false_path \
-from [get_pins -hierarchical * -filter NAME=~*/$flow_cdc/out_toggle_d1_reg/C] \
-to [get_pins -hierarchical * -filter NAME=~*/$flow_cdc/i_sync_in/cdc_sync_stage1_reg[*]/D]

View File

@ -41,61 +41,75 @@
module data_offload_fsm #( module data_offload_fsm #(
parameter TX_OR_RXN_PATH = 0, parameter TX_OR_RXN_PATH = 0,
parameter WR_ADDRESS_WIDTH = 4,
parameter WR_DATA_WIDTH = 128,
parameter RD_ADDRESS_WIDTH = 4,
parameter RD_DATA_WIDTH = 128,
parameter SYNC_EXT_ADD_INTERNAL_CDC = 1) ( parameter SYNC_EXT_ADD_INTERNAL_CDC = 1) (
input up_clk, input up_clk,
// Control interface for storage for m_storage_axis interface
output reg wr_request_enable = 1'b0,
output wr_request_valid,
input wr_request_ready,
input wr_response_eot,
// Control interface for storage for s_storage_axis interface
output reg rd_request_enable = 1'b0,
output rd_request_valid,
input rd_request_ready,
input rd_response_eot,
input rd_ml_valid,
output rd_ml_ready,
// Data path gating
output wr_ready,
output rd_ready,
input rd_valid,
// write control interface // write control interface
input wr_clk, input wr_clk,
input wr_resetn_in, input wr_resetn_in,
output reg wr_resetn_out, input wr_bypass,
input wr_valid_in,
output wr_valid_out,
output wr_ready,
output reg [WR_ADDRESS_WIDTH-1:0] wr_addr,
input wr_last,
input [WR_DATA_WIDTH/8-1:0] wr_tkeep,
// read control interface // read control interface
input rd_clk, input rd_clk,
input rd_resetn_in, input rd_resetn_in,
output reg rd_resetn_out,
input rd_ready,
output reg rd_valid = 1'b0,
output reg [RD_ADDRESS_WIDTH-1:0] rd_addr,
output rd_last,
output reg [RD_DATA_WIDTH/8-1:0] rd_tkeep,
input rd_oneshot, // 0 - CYCLIC; 1 - ONE_SHOT; input rd_oneshot, // 0 - CYCLIC; 1 - ONE_SHOT;
// Synchronization interface - synchronous to the device clock (ADC or DAC) // Synchronization interface - synchronous to the external DMA clock
input init_req, input init_req,
output init_ack,
input [ 1:0] sync_config, input [ 1:0] sync_config,
input sync_external, input sync_external,
input sync_internal, input sync_internal,
// FSM debug // FSM debug
output [ 1:0] wr_fsm_state, output [ 4:0] wr_fsm_state_out,
output [ 1:0] rd_fsm_state, output [ 3:0] rd_fsm_state_out
output reg [63:0] sample_count
); );
// FSM states // FSM states
localparam WR_IDLE = 2'b00; localparam WR_STATE_IDLE = 5'b00001;
localparam WR_SYNC = 2'b01; localparam WR_STATE_PRE_WR = 5'b00010;
localparam WR_WRITE_TO_MEM = 2'b11; localparam WR_STATE_SYNC = 5'b00100;
localparam WR_WAIT_TO_END = 2'b10; localparam WR_STATE_WR = 5'b01000;
localparam WR_STATE_WAIT_RD = 5'b10000;
localparam RD_IDLE = 2'b00; localparam WR_BIT_IDLE = 0;
localparam RD_SYNC = 2'b01; localparam WR_BIT_PRE_WR = 1;
localparam RD_READ_FROM_MEM = 2'b11; localparam WR_BIT_SYNC = 2;
localparam WR_BIT_WR = 3;
localparam RD_STATE_IDLE = 4'b0001;
localparam RD_STATE_PRE_RD = 4'b0010;
localparam RD_STATE_SYNC = 4'b0100;
localparam RD_STATE_RD = 4'b1000;
localparam RD_BIT_IDLE = 0;
localparam RD_BIT_PRE_RD = 1;
localparam RD_BIT_SYNC = 2;
localparam RD_BIT_RD = 3;
// Synchronization options // Synchronization options
@ -103,352 +117,173 @@ module data_offload_fsm #(
localparam HARDWARE = 2'b01; localparam HARDWARE = 2'b01;
localparam SOFTWARE = 2'b10; localparam SOFTWARE = 2'b10;
// helper parameters for last address, tkeep conversion
localparam LSB = (WR_ADDRESS_WIDTH > RD_ADDRESS_WIDTH) ? WR_ADDRESS_WIDTH - RD_ADDRESS_WIDTH :
RD_ADDRESS_WIDTH - WR_ADDRESS_WIDTH;
localparam POW2_LSB = 1 << LSB;
// internal registers // internal registers
reg rd_cyclic_en = 1'b0;
reg [WR_ADDRESS_WIDTH-1:0] wr_last_addr;
reg [WR_DATA_WIDTH/8-1:0] wr_last_keep;
reg [RD_DATA_WIDTH/8-1:0] rd_tkeep_last;
reg [RD_ADDRESS_WIDTH-1:0] rd_last_addr;
reg rd_isempty;
reg rd_init_req_d;
reg wr_init_req_d;
reg wr_ready_d;
// internal signals // internal signals
wire wr_sync_external_s;
wire wr_init_req_s;
wire wr_rd_response_eot;
wire rd_sync_external_s;
wire rd_last_eot;
wire rd_init_req_s;
wire wr_almost_full; reg [4:0] wr_fsm_state = WR_STATE_IDLE;
wire wr_init_req_s; reg [4:0] wr_fsm_next_state;
wire wr_init_req_pos_s; reg [3:0] rd_fsm_state = RD_STATE_IDLE;
wire wr_init_ack_s; reg [3:0] rd_fsm_next_state;
wire rd_isfull_s; reg [1:0] rd_outstanding = 2'd0;
wire wr_isempty_s;
wire rd_empty_s;
wire rd_wr_last_s;
wire rd_init_req_s;
wire rd_init_req_neg_s;
wire rd_init_ack_s;
wire [WR_ADDRESS_WIDTH-1:0] rd_wr_last_addr_s;
wire [WR_DATA_WIDTH/8-1:0] rd_wr_last_tkeep_s;
wire wr_sync_external_s;
wire rd_sync_external_s;
wire wr_oneshot;
(* DONT_TOUCH = "TRUE" *) reg [1:0] wr_fsm_state = 2'b00; assign wr_fsm_state_out = wr_fsm_state;
(* DONT_TOUCH = "TRUE" *) reg [1:0] rd_fsm_state = 2'b00; assign rd_fsm_state_out = rd_fsm_state;
// Mealy state machine for write control always @(*) begin
always @(posedge wr_clk) begin wr_fsm_next_state = wr_fsm_state;
if (wr_resetn_in == 1'b0) begin case (wr_fsm_state)
wr_fsm_state <= WR_IDLE; WR_STATE_IDLE:
end else begin if (wr_init_req_s & ~wr_bypass) begin
case (wr_fsm_state) wr_fsm_next_state = WR_STATE_PRE_WR;
end
WR_IDLE: begin WR_STATE_PRE_WR:
if (wr_init_req_s) begin if (wr_request_ready) begin
wr_fsm_state <= (TX_OR_RXN_PATH) ? WR_WRITE_TO_MEM : WR_SYNC; wr_fsm_next_state = TX_OR_RXN_PATH ? WR_STATE_WR : WR_STATE_SYNC;
end else begin end
wr_fsm_state <= WR_IDLE; WR_STATE_SYNC:
case (sync_config)
AUTOMATIC:
wr_fsm_next_state = WR_STATE_WR;
HARDWARE:
if (wr_sync_external_s) begin
wr_fsm_next_state = WR_STATE_WR;
end end
end SOFTWARE:
if (sync_internal) begin
WR_SYNC: begin wr_fsm_next_state = WR_STATE_WR;
// do not lock the FSM if something goes wrong
if (TX_OR_RXN_PATH) begin
wr_fsm_state <= WR_WRITE_TO_MEM;
end else begin // SOURCE_IS_BACK_END
case (sync_config)
AUTOMATIC: begin
wr_fsm_state <= WR_WRITE_TO_MEM;
end
HARDWARE: begin
if (wr_sync_external_s) begin
wr_fsm_state <= WR_WRITE_TO_MEM;
end
end
SOFTWARE: begin
if (sync_internal) begin
wr_fsm_state <= WR_WRITE_TO_MEM;
end
end
default: begin
wr_fsm_state <= WR_WRITE_TO_MEM;
end
endcase
end end
end default:
wr_fsm_next_state = WR_STATE_WR;
WR_WRITE_TO_MEM: begin endcase
if ((wr_full || wr_last) && wr_valid_out) begin WR_STATE_WR:
wr_fsm_state <= WR_WAIT_TO_END; if (wr_response_eot) begin
end else begin wr_fsm_next_state = WR_STATE_WAIT_RD;
wr_fsm_state <= WR_WRITE_TO_MEM; end
end WR_STATE_WAIT_RD:
end if (wr_rd_response_eot) begin
wr_fsm_next_state = WR_STATE_IDLE;
WR_WAIT_TO_END: begin end
if (wr_isempty_s && (wr_oneshot || wr_init_req_s)) begin default:
wr_fsm_state <= WR_IDLE; wr_fsm_next_state = WR_STATE_IDLE;
end else begin endcase
wr_fsm_state <= WR_WAIT_TO_END;
end
end
default: wr_fsm_state <= WR_IDLE;
endcase
end
end
// the initialization interface (init_req) is edge sensitive
always @(posedge wr_clk) begin
wr_init_req_d <= wr_init_req_s;
end
assign wr_init_req_pos_s = ~wr_init_req_d & wr_init_req_s;
// status bits
assign wr_almost_full = (wr_addr == {{(WR_ADDRESS_WIDTH-1){1'b1}}, 1'b0}) ? 1'b1 : 1'b0;
assign wr_full = &wr_addr;
// generate INIT acknowledge signal in WRITE domain (in case of ADCs)
assign wr_init_ack_s = (wr_fsm_state == WR_SYNC) ? 1'b1 : 1'b0;
// write address generation
always @(posedge wr_clk) begin
if ((wr_resetn_in == 1'b0) || (wr_fsm_state == WR_IDLE)) begin
wr_addr <= 'b0;
end else begin
if (wr_valid_out) begin
wr_addr <= wr_addr + 1'b1;
end
end
end
// reset the storage unit's FMS before each transfer
always @(posedge wr_clk) begin
if ((wr_resetn_in == 1'b0) || (wr_fsm_state == WR_IDLE)) begin
wr_resetn_out <= 1'b0;
end else begin
wr_resetn_out <= 1'b1;
end
end end
always @(posedge wr_clk) begin always @(posedge wr_clk) begin
if (wr_resetn_in == 1'b0) begin if (wr_resetn_in == 1'b0) begin
wr_last_addr <= {WR_ADDRESS_WIDTH{1'b1}}; wr_fsm_state <= WR_STATE_IDLE;
end else begin end else begin
wr_last_addr <= (wr_valid_out) ? wr_addr : wr_last_addr; wr_fsm_state <= wr_fsm_next_state;
end end
end end
always @(posedge wr_clk) begin always @(*) begin
if (wr_resetn_in == 1'b0) begin rd_fsm_next_state = rd_fsm_state;
wr_last_keep <= {WR_DATA_WIDTH/8{1'b1}}; case (rd_fsm_state)
end else begin RD_STATE_IDLE:
if (wr_last) begin if (rd_ml_valid) begin
// if the SOURCE is at back-end, the interface is FIFO, set the tkeep rd_fsm_next_state = RD_STATE_PRE_RD;
// to its default end
wr_last_keep <= (TX_OR_RXN_PATH) ? wr_tkeep : {WR_DATA_WIDTH/8{1'b1}}; RD_STATE_PRE_RD:
end if (rd_request_ready) begin
end rd_fsm_next_state = TX_OR_RXN_PATH ? RD_STATE_SYNC : RD_STATE_RD;
end end
RD_STATE_SYNC:
always @(posedge wr_clk) begin if (rd_valid) // Wait until storage is valid
wr_ready_d <= wr_ready && !(wr_valid_in && wr_last); case (sync_config)
end AUTOMATIC:
rd_fsm_next_state = RD_STATE_RD;
// flush out the DMA if the transfer is bigger than the storage size HARDWARE:
assign wr_ready = ((wr_fsm_state == WR_WRITE_TO_MEM) || if (rd_sync_external_s) begin
(TX_OR_RXN_PATH && ((wr_fsm_state == WR_WAIT_TO_END) && wr_ready_d))) ? 1'b1 : 1'b0; rd_fsm_next_state = RD_STATE_RD;
// write control
assign wr_valid_out = (wr_fsm_state == WR_WRITE_TO_MEM) & wr_valid_in;
// sample counter for debug purposes, the value of the counter resets at
// every new incoming request
always @(posedge wr_clk) begin
if (wr_init_req_pos_s == 1'b1) begin
sample_count <= 64'b0;
end else begin
if (wr_ready && wr_valid_in) begin
sample_count <= sample_count + 1'b1;
end
end
end
// Mealy state machine for read control
always @(posedge rd_clk) begin
if (rd_resetn_in == 1'b0) begin
rd_fsm_state <= RD_IDLE;
end else begin
case (rd_fsm_state)
RD_IDLE: begin
if (((!TX_OR_RXN_PATH) & rd_isfull_s) || (rd_wr_last_s)) begin
if (TX_OR_RXN_PATH) begin
rd_fsm_state <= RD_SYNC;
end else begin
rd_fsm_state <= RD_READ_FROM_MEM;
end end
end else begin SOFTWARE:
rd_fsm_state <= RD_IDLE; if (sync_internal) begin
end rd_fsm_next_state = RD_STATE_RD;
end
RD_SYNC : begin
// do not lock the FSM if something goes wrong
if (!TX_OR_RXN_PATH) begin
rd_fsm_state <= RD_READ_FROM_MEM;
end else begin // TX_OR_RXN_PATH
case (sync_config)
AUTOMATIC: begin
rd_fsm_state <= RD_READ_FROM_MEM;
end
HARDWARE: begin
if (rd_sync_external_s) begin
rd_fsm_state <= RD_READ_FROM_MEM;
end
end
SOFTWARE: begin
if (sync_internal) begin
rd_fsm_state <= RD_READ_FROM_MEM;
end
end
default: begin
rd_fsm_state <= RD_READ_FROM_MEM;
end
endcase
end
end
// read until empty or next init_req
RD_READ_FROM_MEM : begin
if (rd_empty_s && rd_ready) begin
if (rd_init_req_s || (rd_oneshot && rd_last)) begin
rd_fsm_state <= RD_IDLE;
end else if (TX_OR_RXN_PATH && sync_config && (!rd_oneshot)) begin
rd_fsm_state <= RD_SYNC;
end else begin
rd_fsm_state <= RD_READ_FROM_MEM;
end end
end else begin default:
rd_fsm_state <= RD_READ_FROM_MEM; rd_fsm_next_state = RD_STATE_RD;
end endcase
RD_STATE_RD:
if (rd_last_eot) begin
rd_fsm_next_state = (rd_cyclic_en == 1'b0) ? RD_STATE_IDLE :
(TX_OR_RXN_PATH & (sync_config != AUTOMATIC)) ? RD_STATE_SYNC :
RD_STATE_RD;
end end
default:
default : rd_fsm_state <= RD_IDLE; rd_fsm_next_state = RD_STATE_IDLE;
endcase endcase
end
end
// the initialization interface (init_req) is edge sensitive
// TODO: This should be redefined! Will work only of init_req is active
// during the whole DMA transfer (use xfer_req for driving init_req)
always @(posedge rd_clk) begin
rd_init_req_d <= rd_init_req_s;
end
assign rd_init_req_neg_s = rd_init_req_d & ~rd_init_req_s;
// generate INIT acknowledge signal in WRITE domain (in case of ADCs)
assign rd_init_ack_s = (rd_fsm_state == RD_SYNC) ? 1'b1 : 1'b0;
// Reset the storage unit's FSM before each transfer
always @(posedge rd_clk) begin
if ((rd_resetn_in == 1'b0) || (rd_fsm_state == RD_IDLE)) begin
rd_resetn_out <= 1'b0;
end else begin
rd_resetn_out <= 1'b1;
end
end
// read address generation
always @(posedge rd_clk) begin
if (rd_fsm_state != RD_READ_FROM_MEM) begin
rd_addr <= 'b0;
end else begin
if (rd_valid) begin
if (rd_oneshot)
rd_addr <= (rd_last_addr == rd_addr) ? rd_addr : rd_addr + 1'b1;
else
rd_addr <= (rd_last_addr == rd_addr) ? {RD_ADDRESS_WIDTH{1'b0}} : rd_addr + 1'b1;
end
end
end
assign rd_empty_s = (rd_addr == rd_last_addr) ? 1'b1 : 1'b0;
assign rd_last = rd_oneshot & rd_empty_s;
always @(posedge rd_clk) begin
if (rd_resetn_in == 1'b0) begin
rd_isempty <= 1'b0;
end else begin
rd_isempty <= rd_empty_s;
end
end end
always @(posedge rd_clk) begin always @(posedge rd_clk) begin
if (rd_resetn_in == 1'b0) begin if (rd_resetn_in == 1'b0) begin
rd_valid <= 1'b0; rd_fsm_state <= RD_STATE_IDLE;
end else begin end else begin
if ((rd_ready) && (rd_fsm_state == RD_READ_FROM_MEM) && !(rd_valid && rd_last && rd_oneshot)) begin rd_fsm_state <= rd_fsm_next_state;
rd_valid <= 1'b1;
end else begin
rd_valid <= 1'b0;
end
end end
end end
always @(posedge rd_clk) begin
if (rd_resetn_in == 1'b0)
rd_outstanding <= 2'b0;
else if (rd_request_ready & rd_request_valid & ~rd_response_eot)
rd_outstanding <= rd_outstanding + 2'd1;
else if (~(rd_request_ready & rd_request_valid) & (rd_response_eot & rd_fsm_state[RD_BIT_RD]))
rd_outstanding <= rd_outstanding - 2'd1;
end
assign rd_last_eot = (rd_outstanding == 1) & (rd_response_eot & rd_fsm_state[RD_BIT_RD]) & !(rd_request_ready & rd_request_valid);
always @(posedge rd_clk) begin
if (rd_init_req_s) begin
rd_cyclic_en <= 1'b0;
end else if (rd_fsm_state[RD_BIT_PRE_RD]) begin
rd_cyclic_en <= ~rd_oneshot;
end
end
assign rd_ready = rd_fsm_state[RD_BIT_RD];
assign wr_ready = wr_fsm_state[WR_BIT_WR];
assign wr_request_valid = wr_fsm_state[WR_BIT_PRE_WR];
assign rd_request_valid = rd_fsm_state[RD_BIT_PRE_RD] | rd_cyclic_en;
always @(posedge rd_clk) begin
if (rd_resetn_in == 1'b0 || (~rd_init_req_s & ~TX_OR_RXN_PATH[0]))
rd_request_enable <= 1'b0;
else
rd_request_enable <= 1'b1;
end
always @(posedge wr_clk) begin
if (wr_resetn_in == 1'b0)
wr_request_enable <= 1'b0;
else
wr_request_enable <= 1'b1;
end
assign rd_ml_ready = rd_fsm_state[RD_BIT_IDLE];
// CDC circuits // CDC circuits
sync_event #( sync_event #(
.NUM_OF_EVENTS (1), .NUM_OF_EVENTS (1),
.ASYNC_CLK (1)) .ASYNC_CLK (1))
i_wr_empty_sync ( i_wr_empty_sync (
.in_clk (rd_clk), .in_clk (rd_clk),
.in_event (rd_isempty), .in_event (rd_last_eot && rd_fsm_state[RD_BIT_RD]),
.out_clk (wr_clk), .out_clk (wr_clk),
.out_event (wr_isempty_s) .out_event (wr_rd_response_eot)
);
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK(1))
i_rd_full_sync (
.in_clk (wr_clk),
.in_event (wr_almost_full),
.out_clk (rd_clk),
.out_event (rd_isfull_s)
);
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_rd_wr_last_sync (
.in_clk (wr_clk),
.in_event ((wr_last & wr_valid_in)),
.out_clk (rd_clk),
.out_event (rd_wr_last_s)
); );
sync_bits #( sync_bits #(
.NUM_OF_BITS (1), .NUM_OF_BITS (1),
.ASYNC_CLK (1)) .ASYNC_CLK (TX_OR_RXN_PATH[0]))
i_wr_oneshot_sync (
.in_bits (rd_oneshot),
.out_clk (wr_clk),
.out_resetn (1'b1),
.out_bits (wr_oneshot)
);
sync_bits #(
.NUM_OF_BITS (1),
.ASYNC_CLK (1))
i_rd_init_req_sync ( i_rd_init_req_sync (
.in_bits (init_req), .in_bits (init_req),
.out_clk (rd_clk), .out_clk (rd_clk),
@ -458,7 +293,7 @@ module data_offload_fsm #(
sync_bits #( sync_bits #(
.NUM_OF_BITS (1), .NUM_OF_BITS (1),
.ASYNC_CLK (1)) .ASYNC_CLK (~TX_OR_RXN_PATH[0]))
i_wr_init_req_sync ( i_wr_init_req_sync (
.in_bits (init_req), .in_bits (init_req),
.out_clk (wr_clk), .out_clk (wr_clk),
@ -466,102 +301,6 @@ module data_offload_fsm #(
.out_bits (wr_init_req_s) .out_bits (wr_init_req_s)
); );
generate if (TX_OR_RXN_PATH == 0) begin : adc_init_sync
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_rd_init_ack_sync (
.in_clk (wr_clk),
.in_event (wr_init_ack_s),
.out_clk (rd_clk),
.out_event (init_ack)
);
end else begin : dac_init_sync
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_wr_init_ack_sync (
.in_clk (rd_clk),
.in_event (rd_init_ack_s),
.out_clk (wr_clk),
.out_event (init_ack)
);
end
endgenerate
// convert write address and last/keep to read address and last/keep
sync_bits #(
.NUM_OF_BITS (WR_ADDRESS_WIDTH),
.ASYNC_CLK (1))
i_rd_last_address (
.in_bits (wr_last_addr),
.out_clk (rd_clk),
.out_resetn (1'b1),
.out_bits (rd_wr_last_addr_s)
);
sync_bits #(
.NUM_OF_BITS (WR_DATA_WIDTH/8),
.ASYNC_CLK (1))
i_rd_last_keep (
.in_bits (wr_last_keep),
.out_clk (rd_clk),
.out_resetn (1'b1),
.out_bits (rd_wr_last_tkeep_s)
);
// upsizing - WR_DATA_WIDTH < RD_DATA_WIDTH
generate if (WR_ADDRESS_WIDTH > RD_ADDRESS_WIDTH) begin
always @(posedge rd_clk) begin
rd_last_addr <= rd_wr_last_addr_s[WR_ADDRESS_WIDTH-1 : LSB];
end
// the read tkeep will be wider than the write tkeep, and its value
// depends on when the write tlast was asserted
always @(posedge rd_clk) begin :tkeep_gen
integer i;
for (i = 0; i < POW2_LSB; i = i + 1) begin : a_tkeep
if (rd_last_addr[LSB-1:0] < i)
rd_tkeep_last[(i+1)*WR_DATA_WIDTH/8-1 -: WR_DATA_WIDTH/8] <= {WR_DATA_WIDTH/8{1'b0}};
else
rd_tkeep_last[(i+1)*WR_DATA_WIDTH/8-1 -: WR_DATA_WIDTH/8] <= (i == 0) ? rd_wr_last_tkeep_s : {WR_DATA_WIDTH/8{1'b1}};
end
end
end else if (WR_ADDRESS_WIDTH < RD_ADDRESS_WIDTH) begin // downsizing - WR_DATA_WIDTH > RD_DATA_WIDTH or equal
always @(posedge rd_clk) begin
rd_tkeep_last <= rd_wr_last_tkeep_s[RD_DATA_WIDTH/8-1 : 0];
rd_last_addr <= {rd_wr_last_addr_s, {LSB{1'b1}}};
end
end else begin
always @(posedge rd_clk) begin
rd_tkeep_last <= rd_wr_last_tkeep_s;
rd_last_addr <= rd_wr_last_addr_s;
end
end
endgenerate
always @(posedge rd_clk) begin
if (rd_fsm_state == RD_IDLE) begin
rd_tkeep <= {(RD_DATA_WIDTH/8){1'b1}};
end else begin
if (rd_empty_s && rd_ready)
rd_tkeep <= rd_tkeep_last;
else if (rd_ready)
rd_tkeep <= {(RD_DATA_WIDTH/8){1'b1}};
end
end
// When SYNC_EXT_ADD_INTERNAL_CDC is deasserted, one of these signals will end // When SYNC_EXT_ADD_INTERNAL_CDC is deasserted, one of these signals will end
// up being synchronized to the "wrong" clock domain. This shouldn't matter // up being synchronized to the "wrong" clock domain. This shouldn't matter
// because the incorrectly synchronized signal is guarded by a synthesis constant. // because the incorrectly synchronized signal is guarded by a synthesis constant.

View File

@ -41,7 +41,6 @@ adi_add_bus "m_axis" "master" \
{"m_axis_data" "TDATA"} \ {"m_axis_data" "TDATA"} \
{"m_axis_last" "TLAST"} \ {"m_axis_last" "TLAST"} \
{"m_axis_tkeep" "TKEEP"} ] {"m_axis_tkeep" "TKEEP"} ]
adi_add_bus_clock "m_axis_aclk" "m_axis" "m_axis_aresetn"
## source interface (e.g. TX_DMA or ADC core) ## source interface (e.g. TX_DMA or ADC core)
@ -54,14 +53,75 @@ adi_add_bus "s_axis" "slave" \
{"s_axis_data" "TDATA"} \ {"s_axis_data" "TDATA"} \
{"s_axis_last" "TLAST"} \ {"s_axis_last" "TLAST"} \
{"s_axis_tkeep" "TKEEP"} ] {"s_axis_tkeep" "TKEEP"} ]
adi_add_bus_clock "s_axis_aclk" "s_axis" "s_axis_aresetn"
adi_add_bus "wr_ctrl" "master" \
"analog.com:interface:if_do_ctrl_rtl:1.0" \
"analog.com:interface:if_do_ctrl:1.0" \
[list {"wr_request_enable" "request_enable"} \
{"wr_request_valid" "request_valid"} \
{"wr_request_ready" "request_ready"} \
{"wr_request_length" "request_length"} \
{"wr_response_measured_length" "response_measured_length"} \
{"wr_response_eot" "response_eot"} \
{"wr_overflow" "status_overflow"} \
]
adi_add_bus "rd_ctrl" "master" \
"analog.com:interface:if_do_ctrl_rtl:1.0" \
"analog.com:interface:if_do_ctrl:1.0" \
[list {"rd_request_enable" "request_enable"} \
{"rd_request_valid" "request_valid"} \
{"rd_request_ready" "request_ready"} \
{"rd_request_length" "request_length"} \
{"rd_response_eot" "response_eot"} \
{"rd_underflow" "status_underflow"} \
]
adi_add_bus "s_storage_axis" "slave" \
"xilinx.com:interface:axis_rtl:1.0" \
"xilinx.com:interface:axis:1.0" \
[list {"s_storage_axis_ready" "TREADY"} \
{"s_storage_axis_valid" "TVALID"} \
{"s_storage_axis_data" "TDATA"} \
{"s_storage_axis_tkeep" "TKEEP"} \
{"s_storage_axis_last" "TLAST"}]
adi_add_bus "m_storage_axis" "master" \
"xilinx.com:interface:axis_rtl:1.0" \
"xilinx.com:interface:axis:1.0" \
[list {"m_storage_axis_ready" "TREADY"} \
{"m_storage_axis_valid" "TVALID"} \
{"m_storage_axis_data" "TDATA"} \
{"m_storage_axis_tkeep" "TKEEP"} \
{"m_storage_axis_last" "TLAST"}]
adi_add_bus_clock "m_axis_aclk" "s_storage_axis:m_axis" "m_axis_aresetn"
adi_add_bus_clock "s_axis_aclk" "m_storage_axis:s_axis" "s_axis_aresetn"
set cc [ipx::current_core] set cc [ipx::current_core]
set_property -dict [list \
enablement_resolve_type dependent \
driver_value 0 \
enablement_dependency {MEM_TYPE == 1} \
] \
[ipx::get_ports ddr_calib_done -of_objects $cc]
set_property -dict [list \
driver_value 0 \
] \
[ipx::get_ports wr_overflow -of_objects $cc]
set_property -dict [list \
driver_value 0 \
] \
[ipx::get_ports rd_underflow -of_objects $cc]
## Parameter validations ## Parameter validations
## MEM_TPYE ## MEM_TPYE
set_property -dict [list \ set_property -dict [list \
"value_format" "long" \
"value_validation_type" "pairs" \ "value_validation_type" "pairs" \
"value_validation_pairs" { \ "value_validation_pairs" { \
"Internal memory" "0" \ "Internal memory" "0" \
@ -70,6 +130,11 @@ set_property -dict [list \
] \ ] \
[ipx::get_user_parameters MEM_TYPE -of_objects $cc] [ipx::get_user_parameters MEM_TYPE -of_objects $cc]
set_property -dict [list \
"value_format" "long" \
] \
[ipx::get_hdl_parameters MEM_TYPE -of_objects $cc]
set_property -dict [list \ set_property -dict [list \
"value_validation_type" "pairs" \ "value_validation_type" "pairs" \
"value_validation_pairs" { \ "value_validation_pairs" { \
@ -79,42 +144,53 @@ set_property -dict [list \
] \ ] \
[ipx::get_user_parameters TX_OR_RXN_PATH -of_objects $cc] [ipx::get_user_parameters TX_OR_RXN_PATH -of_objects $cc]
## MEMC_UIF_DATA_WIDTH
set_property -dict [list \ set_property -dict [list \
"value_validation_type" "list" \ "value_validation_type" "pairs" \
"value_validation_list" "64 128 256 512 1024" \ "value" "10" \
"value_validation_pairs" {\
"1kB" "10" \
"2kB" "11" \
"4kB" "12" \
"8kB" "13" \
"16kB" "14" \
"32kB" "15" \
"64kB" "16" \
"128kB" "17" \
"256kB" "18" \
"512kB" "19" \
"1MB" "20" \
"2MB" "21" \
"4MB" "22" \
"8MB" "23" \
"16MB" "24" \
"32MB" "25" \
"64MB" "26" \
"128MB" "27" \
"256MB" "28" \
"512MB" "29" \
"1GB" "30" \
"2GB" "31" \
"4GB" "32" \
"8GB" "33" \
"16GB" "34" \
} \
] \ ] \
[ipx::get_user_parameters MEMC_UIF_DATA_WIDTH -of_objects $cc] [ipx::get_user_parameters MEM_SIZE_LOG2 -of_objects $cc]
## MEMC_UIF_ADDRESS_WIDTH
set_property -dict [list \
"value_validation_type" "range_long" \
"value_validation_range_minimum" "8" \
"value_validation_range_maximum" "31" \
] \
[ipx::get_user_parameters MEMC_UIF_ADDRESS_WIDTH -of_objects $cc]
## MEM_SIZE - 8GB??
set_property -dict [list \
"value_validation_type" "range_long" \
"value_validation_range_minimum" "2" \
"value_validation_range_maximum" "8589934592" \
] \
[ipx::get_user_parameters MEM_SIZE -of_objects $cc]
## Boolean parameters ## Boolean parameters
foreach {k v} { \ foreach {k v} { \
"SRC_RAW_DATA_EN" "false" \ "HAS_BYPASS" "true" \
"DST_RAW_DATA_EN" "false" \
"DST_CYCLIC_EN" "true" \ "DST_CYCLIC_EN" "true" \
"SYNC_EXT_ADD_INTERNAL_CDC" "true" \ "SYNC_EXT_ADD_INTERNAL_CDC" "true" \
} { \ } { \
set_property -dict [list \ set_property -dict [list \
"value_format" "bool" \
"value_format" "bool" \ "value_format" "bool" \
"value" $v \ "value" $v \
] \ ] \
[ipx::get_user_parameters $k -of_objects $cc] [ipx::get_user_parameters $k -of_objects $cc]
set_property -dict [list \ set_property -dict [list \
"value_format" "bool" \
"value_format" "bool" \ "value_format" "bool" \
"value" $v \ "value" $v \
] \ ] \
@ -152,34 +228,11 @@ set_property -dict [list \
"display_name" "Storage Type" \ "display_name" "Storage Type" \
] [ipgui::get_guiparamspec -name "MEM_TYPE" -component $cc] ] [ipgui::get_guiparamspec -name "MEM_TYPE" -component $cc]
ipgui::add_param -name "MEM_SIZE" -component $cc -parent $general_group ipgui::add_param -name "MEM_SIZE_LOG2" -component $cc -parent $general_group
set_property -dict [list \ set_property -dict [list \
"display_name" "Storage Size" \ "display_name" "Storage Size" \
] [ipgui::get_guiparamspec -name "MEM_SIZE" -component $cc] "tooltip" "Log2 value of Storage Size in bytes" \
] [ipgui::get_guiparamspec -name "MEM_SIZE_LOG2" -component $cc]
## DDR controller's user interface related configurations
set m_controller_group [ipgui::add_group -name "DDR Controller Interface Configuration" -component $cc \
-parent $page0 -display_name "DDR Controller Interface Configuration" ]
ipgui::add_param -name "MEMC_UIF_DATA_WIDTH" -component $cc -parent $m_controller_group
set_property -dict [list \
"widget" "comboBox" \
"display_name" "Interface data width" \
] [ipgui::get_guiparamspec -name "MEMC_UIF_DATA_WIDTH" -component $cc]
set_property enablement_tcl_expr {$MEM_TYPE == 1} [ipx::get_user_parameters MEMC_UIF_DATA_WIDTH -of_objects $cc]
ipgui::add_param -name "MEMC_UIF_ADDRESS_WIDTH" -component $cc -parent $m_controller_group
set_property -dict [list \
"widget" "comboBox" \
"display_name" "Interface address width" \
] [ipgui::get_guiparamspec -name "MEMC_UIF_ADDRESS_WIDTH" -component $cc]
set_property enablement_tcl_expr {$MEM_TYPE == 1} [ipx::get_user_parameters MEMC_UIF_ADDRESS_WIDTH -of_objects $cc]
ipgui::add_param -name "MEMC_BADDRESS" -component $cc -parent $m_controller_group
set_property -dict [list \
"display_name" "PL DDR base address" \
] [ipgui::get_guiparamspec -name "MEMC_BADDRESS" -component $cc]
set_property enablement_tcl_expr {$MEM_TYPE == 1} [ipx::get_user_parameters MEMC_BADDRESS -of_objects $cc]
## Transmit and receive endpoints ## Transmit and receive endpoints
set source_group [ipgui::add_group -name "Source Endpoint Configuration" -component $cc \ set source_group [ipgui::add_group -name "Source Endpoint Configuration" -component $cc \
@ -194,37 +247,19 @@ set_property -dict [list \
"display_name" "Source Interface data width" \ "display_name" "Source Interface data width" \
] [ipgui::get_guiparamspec -name "SRC_DATA_WIDTH" -component $cc] ] [ipgui::get_guiparamspec -name "SRC_DATA_WIDTH" -component $cc]
ipgui::add_param -name "SRC_ADDR_WIDTH" -component $cc -parent $source_group
set_property -dict [list \
"display_name" "Source Interface address width" \
] [ipgui::get_guiparamspec -name "SRC_ADDR_WIDTH" -component $cc]
ipgui::add_param -name "DST_DATA_WIDTH" -component $cc -parent $destination_group ipgui::add_param -name "DST_DATA_WIDTH" -component $cc -parent $destination_group
set_property -dict [list \ set_property -dict [list \
"display_name" "Destination Interface data width" \ "display_name" "Destination Interface data width" \
] [ipgui::get_guiparamspec -name "DST_DATA_WIDTH" -component $cc] ] [ipgui::get_guiparamspec -name "DST_DATA_WIDTH" -component $cc]
ipgui::add_param -name "DST_ADDR_WIDTH" -component $cc -parent $destination_group
set_property -dict [list \
"display_name" "Destination Interface address width" \
] [ipgui::get_guiparamspec -name "DST_ADDR_WIDTH" -component $cc]
## Other features ## Other features
set features_group [ipgui::add_group -name "Features" -component $cc \ set features_group [ipgui::add_group -name "Features" -component $cc \
-parent $page0 -display_name "Features" ] -parent $page0 -display_name "Features" ]
ipgui::add_param -name "HAS_BYPASS" -component $cc -parent $features_group
ipgui::add_param -name "SRC_RAW_DATA_EN" -component $cc -parent $features_group
set_property -dict [list \ set_property -dict [list \
"display_name" "Source Raw Data Enable" \ "display_name" "Internal Bypass Data Path Enabled" \
] [ipgui::get_guiparamspec -name "SRC_RAW_DATA_EN" -component $cc] ] [ipgui::get_guiparamspec -name "HAS_BYPASS" -component $cc]
set_property enablement_tcl_expr {$TX_OR_RXN_PATH == 0} [ipx::get_user_parameters SRC_RAW_DATA_EN -of_objects $cc]
ipgui::add_param -name "DST_RAW_DATA_EN" -component $cc -parent $features_group
set_property -dict [list \
"display_name" "Destionation Raw Data Enable" \
] [ipgui::get_guiparamspec -name "DST_RAW_DATA_EN" -component $cc]
set_property enablement_tcl_expr {$TX_OR_RXN_PATH == 1} [ipx::get_user_parameters DST_RAW_DATA_EN -of_objects $cc]
ipgui::add_param -name "DST_CYCLIC_EN" -component $cc -parent $features_group ipgui::add_param -name "DST_CYCLIC_EN" -component $cc -parent $features_group
set_property -dict [list \ set_property -dict [list \
@ -241,3 +276,4 @@ set_property -dict [list \
ipx::create_xgui_files $cc ipx::create_xgui_files $cc
ipx::save_core [ipx::current_core] ipx::save_core [ipx::current_core]

View File

@ -38,9 +38,11 @@ module data_offload_regmap #(
parameter ID = 0, parameter ID = 0,
parameter [ 0:0] MEM_TYPE = 1'b0, parameter [ 0:0] MEM_TYPE = 1'b0,
parameter [33:0] MEM_SIZE = 1024, parameter MEM_SIZE_LOG2 = 10,
parameter TX_OR_RXN_PATH = 0, parameter TX_OR_RXN_PATH = 0,
parameter AUTO_BRINGUP = 0) ( parameter AUTO_BRINGUP = 0,
parameter HAS_BYPASS = 1
) (
// microprocessor interface // microprocessor interface
input up_clk, input up_clk,
@ -77,14 +79,15 @@ module data_offload_regmap #(
output sync, output sync,
output [ 1:0] sync_config, output [ 1:0] sync_config,
output reg [33:0] src_transfer_length, output [MEM_SIZE_LOG2-1:0] src_transfer_length,
output [MEM_SIZE_LOG2-1:0] dst_transfer_length,
// FSM control and status // FSM control and status
input [ 1:0] src_fsm_status, input [ 4:0] src_fsm_status,
input [ 1:0] dst_fsm_status, input [ 3:0] dst_fsm_status,
input [31:0] sample_count_msb, input src_overflow,
input [31:0] sample_count_lsb input dst_underflow
); );
@ -93,6 +96,8 @@ module data_offload_regmap #(
localparam [31:0] CORE_VERSION = 32'h00010061; // 1.00.a localparam [31:0] CORE_VERSION = 32'h00010061; // 1.00.a
localparam [31:0] CORE_MAGIC = 32'h44414F46; // DAOF localparam [31:0] CORE_MAGIC = 32'h44414F46; // DAOF
localparam [33:0] MEM_SIZE = 1 << MEM_SIZE_LOG2;
// internal registers // internal registers
reg [31:0] up_scratch = 'd0; reg [31:0] up_scratch = 'd0;
@ -101,18 +106,20 @@ module data_offload_regmap #(
reg up_sync = 'd0; reg up_sync = 'd0;
reg [ 1:0] up_sync_config = 'd0; reg [ 1:0] up_sync_config = 'd0;
reg up_oneshot = 1'b0; reg up_oneshot = 1'b0;
reg [33:0] up_transfer_length = 'd0; reg [MEM_SIZE_LOG2-1:0] up_transfer_length = 'd0;
reg up_src_overflow = 1'b0;
reg up_dst_underflow = 1'b0;
//internal signals //internal signals
wire up_ddr_calib_done_s; wire up_ddr_calib_done_s;
wire [ 1:0] up_wr_fsm_status_s; wire [ 4:0] up_wr_fsm_status_s;
wire [ 1:0] up_rd_fsm_status_s; wire [ 3:0] up_rd_fsm_status_s;
wire [31:0] up_sample_count_msb_s;
wire [31:0] up_sample_count_lsb_s;
wire src_sw_resetn_s; wire src_sw_resetn_s;
wire dst_sw_resetn_s; wire dst_sw_resetn_s;
wire [33:0] src_transfer_length_s; wire [33:0] src_transfer_length_s;
wire up_src_overflow_set_s;
wire up_dst_underflow_set_s;
// write interface // write interface
always @(posedge up_clk) begin always @(posedge up_clk) begin
@ -124,34 +131,47 @@ module data_offload_regmap #(
up_bypass <= 'd0; up_bypass <= 'd0;
up_sync <= 'd0; up_sync <= 'd0;
up_sync_config <= 'd0; up_sync_config <= 'd0;
up_transfer_length <= 34'h0; up_transfer_length <= {MEM_SIZE_LOG2{1'b1}};
up_src_overflow <= 1'b0;
up_dst_underflow <= 1'b0;
end else begin end else begin
up_wack <= up_wreq; up_wack <= up_wreq;
/* Scratch Register */ /* Scratch Register */
if ((up_wreq == 1'b1) && (up_waddr[11:0] == 14'h02)) begin if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h02)) begin
up_scratch <= up_wdata; up_scratch <= up_wdata;
end end
/* Transfer Length Register */ /* Transfer Length Register */
if ((up_wreq == 1'b1) && (up_waddr[11:0] == 14'h07)) begin if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h07)) begin
up_transfer_length <= {up_wdata[27:0], 6'b0}; up_transfer_length <= {up_wdata[MEM_SIZE_LOG2-7:0], {6{1'b1}}};
end
/* Memory interface status register */
if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h20) && up_wdata[4]) begin
up_src_overflow <= 1'b0;
end else if (up_src_overflow_set_s) begin
up_src_overflow <= 1'b1;
end
if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h20) && up_wdata[5]) begin
up_dst_underflow <= 1'b0;
end else if (up_dst_underflow_set_s) begin
up_dst_underflow <= 1'b1;
end end
/* Reset Offload Register */ /* Reset Offload Register */
if ((up_wreq == 1'b1) && (up_waddr[11:0] == 14'h21)) begin if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h21)) begin
up_sw_resetn <= up_wdata[0]; up_sw_resetn <= up_wdata[0];
end end
/* Control Register */ /* Control Register */
if ((up_wreq == 1'b1) && (up_waddr[11:0] == 14'h22)) begin if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h22)) begin
up_oneshot <= up_wdata[1]; up_oneshot <= up_wdata[1];
up_bypass <= up_wdata[0]; up_bypass <= up_wdata[0] & HAS_BYPASS;
end end
/* SYNC Offload Register - self cleared, one pulse signal */ /* SYNC Offload Register - self cleared, one pulse signal */
if ((up_wreq == 1'b1) && (up_waddr[11:0] == 14'h40)) begin if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h40)) begin
up_sync <= up_wdata[0]; up_sync <= up_wdata[0];
end else begin end else begin
up_sync <= 1'b0; up_sync <= 1'b0;
end end
/* SYNC RX Configuration Register */ /* SYNC RX Configuration Register */
if ((up_wreq == 1'b1) && (up_waddr[11:0] == 14'h41)) begin if ((up_wreq == 1'b1) && (up_waddr[13:0] == 14'h41)) begin
up_sync_config <= up_wdata[1:0]; up_sync_config <= up_wdata[1:0];
end end
end end
@ -161,7 +181,7 @@ module data_offload_regmap #(
always @(posedge up_clk) begin always @(posedge up_clk) begin
if (up_rstn == 1'b0) begin if (up_rstn == 1'b0) begin
up_rack <= 1'b0; up_rack <= 1'b0;
up_rdata <= 14'b0; up_rdata <= 32'b0;
end else begin end else begin
up_rack <= up_rreq; up_rack <= up_rreq;
case(up_raddr) case(up_raddr)
@ -183,7 +203,8 @@ module data_offload_regmap #(
/* Configuration Register */ /* Configuration Register */
14'h004: up_rdata <= { 14'h004: up_rdata <= {
30'b0, 29'b0,
/* 2 */ HAS_BYPASS[0],
/* 1 */ TX_OR_RXN_PATH[0], /* 1 */ TX_OR_RXN_PATH[0],
/* 0 */ MEM_TYPE[0] /* 0 */ MEM_TYPE[0]
}; };
@ -197,13 +218,19 @@ module data_offload_regmap #(
}; };
/* Configuration data transfer length */ /* Configuration data transfer length */
14'h007: up_rdata <= {4'b0, up_transfer_length[33:6]}; 14'h007: up_rdata <= {
{32-(MEM_SIZE_LOG2-6){1'b0}},
up_transfer_length[MEM_SIZE_LOG2-1:6]
};
/* 0x08-0x1f reserved for future use */ /* 0x08-0x1f reserved for future use */
/* Memory Physical Interface Status */ /* Memory Physical Interface Status */
14'h020: up_rdata <= { 14'h020: up_rdata <= {
31'b0, 26'b0,
up_dst_underflow,
up_src_overflow,
3'b0,
/* 0 */ up_ddr_calib_done_s /* 0 */ up_ddr_calib_done_s
}; };
/* Reset Offload Register */ /* Reset Offload Register */
@ -233,17 +260,11 @@ module data_offload_regmap #(
/* FMS Debug Register */ /* FMS Debug Register */
14'h080: up_rdata <= { 14'h080: up_rdata <= {
24'b0, 20'b0,
/* 07-06 */ 2'b0, /* 11-08 */ up_rd_fsm_status_s,
/* 05-04 */ up_rd_fsm_status_s, 3'b0,
/* 03-02 */ 2'b0, /* 04-00 */ up_wr_fsm_status_s
/* 01-00 */ up_wr_fsm_status_s
}; };
/* Sample Count LSB Register */
14'h081: up_rdata <= up_sample_count_lsb_s;
/* Sample Count MSB Register */
14'h082: up_rdata <= up_sample_count_msb_s;
default: up_rdata <= 32'h00000000; default: up_rdata <= 32'h00000000;
endcase endcase
@ -253,7 +274,7 @@ module data_offload_regmap #(
// Clock Domain Crossing Logic for reset, control and status signals // Clock Domain Crossing Logic for reset, control and status signals
sync_data #( sync_data #(
.NUM_OF_BITS (2), .NUM_OF_BITS (4),
.ASYNC_CLK (1)) .ASYNC_CLK (1))
i_dst_fsm_status ( i_dst_fsm_status (
.in_clk (dst_clk), .in_clk (dst_clk),
@ -263,7 +284,7 @@ module data_offload_regmap #(
); );
sync_data #( sync_data #(
.NUM_OF_BITS (2), .NUM_OF_BITS (5),
.ASYNC_CLK (1)) .ASYNC_CLK (1))
i_src_fsm_status ( i_src_fsm_status (
.in_clk (src_clk), .in_clk (src_clk),
@ -272,18 +293,6 @@ module data_offload_regmap #(
.out_data (up_wr_fsm_status_s) .out_data (up_wr_fsm_status_s)
); );
sync_data #(
.NUM_OF_BITS (64),
.ASYNC_CLK (1))
i_xfer_status (
.in_clk (src_clk),
.in_data ({sample_count_msb,
sample_count_lsb}),
.out_clk (up_clk),
.out_data ({up_sample_count_msb_s,
up_sample_count_lsb_s})
);
generate generate
if (TX_OR_RXN_PATH) begin : sync_tx_path if (TX_OR_RXN_PATH) begin : sync_tx_path
@ -357,22 +366,55 @@ module data_offload_regmap #(
); );
sync_data #( sync_data #(
.NUM_OF_BITS (34), .NUM_OF_BITS (MEM_SIZE_LOG2),
.ASYNC_CLK (1)) .ASYNC_CLK (1))
i_sync_src_transfer_length ( i_sync_src_transfer_length (
.in_clk (up_clk), .in_clk (up_clk),
.in_data (up_transfer_length), .in_data (up_transfer_length),
.out_clk (src_clk), .out_clk (src_clk),
.out_data (src_transfer_length_s) .out_data (src_transfer_length)
);
sync_data #(
.NUM_OF_BITS (MEM_SIZE_LOG2),
.ASYNC_CLK (1))
i_sync_dst_transfer_length (
.in_clk (up_clk),
.in_data (up_transfer_length),
.out_clk (dst_clk),
.out_data (dst_transfer_length)
); );
always @(posedge src_clk) begin always @(posedge src_clk) begin
src_sw_resetn <= src_sw_resetn_s; src_sw_resetn <= src_sw_resetn_s;
src_transfer_length <= src_transfer_length_s;
end end
always @(posedge dst_clk) begin always @(posedge dst_clk) begin
dst_sw_resetn <= dst_sw_resetn_s; dst_sw_resetn <= dst_sw_resetn_s;
end end
generate if (TX_OR_RXN_PATH == 0) begin
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_wr_overflow_sync (
.in_clk (src_clk),
.in_event (src_overflow),
.out_clk (up_clk),
.out_event (up_src_overflow_set_s)
);
assign up_dst_underflow_set_s = 1'b0;
end else begin
sync_event #(
.NUM_OF_EVENTS (1),
.ASYNC_CLK (1))
i_rd_underflow_sync (
.in_clk (dst_clk),
.in_event (dst_underflow),
.out_clk (up_clk),
.out_event (up_dst_underflow_set_s)
);
assign up_src_overflow_set_s = 1'b0;
end
endgenerate
endmodule endmodule

View File

@ -5,17 +5,10 @@
<: setFileExtension ".sv" :> <: setFileExtension ".sv" :>
<: set id [get_property MODELPARAM_VALUE.ID] :> <: set id [get_property MODELPARAM_VALUE.ID] :>
<: set mem_type [get_property MODELPARAM_VALUE.MEM_TYPE] :> <: set mem_type [get_property MODELPARAM_VALUE.MEM_TYPE] :>
<: set mem_size [get_property MODELPARAM_VALUE.MEM_SIZE] :> <: set mem_size_log2 [get_property MODELPARAM_VALUE.MEM_SIZE_LOG2] :>
<: set memc_uif_data_width [get_property MODELPARAM_VALUE.MEMC_UIF_DATA_WIDTH] :>
<: set memc_uif_address_width [get_property MODELPARAM_VALUE.MEMC_UIF_ADDRESS_WIDTH] :>
<: set memc_baddress [get_property MODELPARAM_VALUE.MEMC_BADDRESS] :>
<: set tx_or_rxn_path [get_property MODELPARAM_VALUE.TX_OR_RXN_PATH] :> <: set tx_or_rxn_path [get_property MODELPARAM_VALUE.TX_OR_RXN_PATH] :>
<: set src_data_width [get_property MODELPARAM_VALUE.src_data_width] :> <: set src_data_width [get_property MODELPARAM_VALUE.src_data_width] :>
<: set src_raw_data_en [get_property MODELPARAM_VALUE.src_raw_data_en] :>
<: set src_addr_width [get_property MODELPARAM_VALUE.src_addr_width] :>
<: set dst_data_width [get_property MODELPARAM_VALUE.dst_data_width] :> <: set dst_data_width [get_property MODELPARAM_VALUE.dst_data_width] :>
<: set dst_raw_data_en [get_property MODELPARAM_VALUE.dst_raw_data_en] :>
<: set dst_addr_width [get_property MODELPARAM_VALUE.dst_addr_width] :>
<: set dst_cyclic_en [get_property MODELPARAM_VALUE.dst_cyclic_en] :> <: set dst_cyclic_en [get_property MODELPARAM_VALUE.dst_cyclic_en] :>
// boolean to intiger // boolean to intiger
@ -37,17 +30,10 @@ package <=: ComponentName :>_pkg;
parameter <=: ComponentName :>_ID = <=: $id :>; parameter <=: ComponentName :>_ID = <=: $id :>;
parameter <=: ComponentName :>_MEM_TYPE = <=: $mem_type :>; parameter <=: ComponentName :>_MEM_TYPE = <=: $mem_type :>;
parameter <=: ComponentName :>_MEM_SIZE = <=: $mem_size :>; parameter <=: ComponentName :>_MEM_SIZE_LOG2 = <=: $mem_size_log2 :>;
parameter <=: ComponentName :>_MEMC_UIF_DATA_WIDTH = <=: $memc_uif_data_width :>;
parameter <=: ComponentName :>_MEMC_UIF_ADDRESS_WIDTH = <=: $memc_uif_address_width :>;
parameter <=: ComponentName :>_MEMC_BADDRESS = <=: h2vh $memc_baddress :>;
parameter <=: ComponentName :>_TX_OR_RXN_PATH = <=: b2i $tx_or_rxn_path :>; parameter <=: ComponentName :>_TX_OR_RXN_PATH = <=: b2i $tx_or_rxn_path :>;
parameter <=: ComponentName :>_SRC_DATA_WIDTH = <=: b2i $src_data_width :>; parameter <=: ComponentName :>_SRC_DATA_WIDTH = <=: b2i $src_data_width :>;
parameter <=: ComponentName :>_SRC_RAW_DATA_WIDTH = <=: b2i $src_raw_data_en :>;
parameter <=: ComponentName :>_SRC_ADDR_WIDTH = <=: b2i $src_addr_width :>;
parameter <=: ComponentName :>_DST_DATA_WIDTH = <=: b2i $dst_data_width :>; parameter <=: ComponentName :>_DST_DATA_WIDTH = <=: b2i $dst_data_width :>;
parameter <=: ComponentName :>_DST_RAW_DATA_WIDTH = <=: b2i $dst_raw_data_en :>;
parameter <=: ComponentName :>_DST_ADDR_WIDTH = <=: b2i $dst_addr_width :>;
parameter <=: ComponentName :>_DST_CYCLIC_EN = <=: b2i $dst_cyclic_en :>; parameter <=: ComponentName :>_DST_CYCLIC_EN = <=: b2i $dst_cyclic_en :>;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -12,7 +12,7 @@
viewBox="0 0 800.00001 500.00001" viewBox="0 0 800.00001 500.00001"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="1.0.2 (e86c870879, 2021-01-15, custom)" inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="generic_bd.svg"> sodipodi:docname="generic_bd.svg">
<defs <defs
id="defs4"> id="defs4">
@ -294,17 +294,17 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="0.98994949" inkscape:zoom="1.4"
inkscape:cx="306.64583" inkscape:cx="316.268"
inkscape:cy="264.01023" inkscape:cy="214.56695"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
units="px" units="px"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1010" inkscape:window-height="968"
inkscape:window-x="-7" inkscape:window-x="-4"
inkscape:window-y="-7" inkscape:window-y="-4"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:document-rotation="0" /> inkscape:document-rotation="0" />
<metadata <metadata
@ -428,18 +428,18 @@
style="font-size:15px;line-height:1.25">AXI_MM</tspan></text> style="font-size:15px;line-height:1.25">AXI_MM</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:21.3333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" style="font-style:normal;font-weight:normal;font-size:21.33329964px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="205.43683" x="214.00826"
y="728.12866" y="713.12866"
id="text2292"><tspan id="text2292"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan2290" id="tspan2290"
x="205.43683" x="214.00826"
y="728.12866" y="732.00366"
style="text-align:center;text-anchor:middle" /><tspan style="text-align:center;text-anchor:middle" /><tspan
sodipodi:role="line" sodipodi:role="line"
x="205.43683" x="214.00826"
y="754.79529" y="758.67023"
id="tspan2294" id="tspan2294"
style="text-align:center;text-anchor:middle">SOURCE</tspan></text> style="text-align:center;text-anchor:middle">SOURCE</tspan></text>
<text <text
@ -461,18 +461,18 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:21.3333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" style="font-style:normal;font-weight:normal;font-size:21.33329964px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="607.05249" x="608.48108"
y="724.40942" y="708.69513"
id="text2292-9"><tspan id="text2292-9"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan2290-3" id="tspan2290-3"
x="607.05249" x="608.48108"
y="724.40942" y="727.57013"
style="text-align:center;text-anchor:middle" /><tspan style="text-align:center;text-anchor:middle" /><tspan
sodipodi:role="line" sodipodi:role="line"
x="607.05249" x="608.48108"
y="751.07605" y="754.23669"
id="tspan2294-9" id="tspan2294-9"
style="text-align:center;text-anchor:middle">DESTINATION</tspan></text> style="text-align:center;text-anchor:middle">DESTINATION</tspan></text>
<path <path
@ -490,25 +490,25 @@
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="304.78723" x="298.78723"
y="907.06915" y="907.06915"
id="text5814-3"><tspan id="text5814-3"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan5816-8" id="tspan5816-8"
x="304.78723" x="298.78723"
y="907.06915" y="907.06915"
style="font-size:15px;line-height:1.25">FIFO_WR</tspan></text> style="font-size:10.66666698px;line-height:0">M_STORAGE_AXIS</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="409.59558" x="407.59558"
y="907.33258" y="907.33258"
id="text5814-3-0"><tspan id="text5814-3-0"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan5816-8-3" id="tspan5816-8-3"
x="409.59558" x="407.59558"
y="907.33258" y="907.33258"
style="font-size:15px;line-height:1.25">FIFO_RD</tspan></text> style="font-size:10.66666698px;line-height:1.25">S_STORAGE_AXIS</tspan></text>
<rect <rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4733-3-2" id="rect4733-3-2"

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -5,8 +5,8 @@ proc ad_data_offload_create {instance_name
mem_size mem_size
source_dwidth source_dwidth
destination_dwidth destination_dwidth
{ddr_data_width 0} {axi_data_width 256}
{ddr_addr_width 0} {axi_addr_width 32}
{shared_devclk 0}} { {shared_devclk 0}} {
global ad_hdl_dir global ad_hdl_dir
@ -31,7 +31,6 @@ proc ad_data_offload_create {instance_name
create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:axis_rtl:1.0 m_axis create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:axis_rtl:1.0 m_axis
create_bd_pin -dir I init_req create_bd_pin -dir I init_req
create_bd_pin -dir O init_ack
create_bd_pin -dir I sync_ext create_bd_pin -dir I sync_ext
set source_addresses [expr ($mem_size * 8) / $source_dwidth] set source_addresses [expr ($mem_size * 8) / $source_dwidth]
@ -44,13 +43,11 @@ proc ad_data_offload_create {instance_name
########################################################################### ###########################################################################
ad_ip_instance data_offload i_data_offload [list \ ad_ip_instance data_offload i_data_offload [list \
MEM_TYPE $mem_type \ MEM_TYPE [expr $mem_type == 0 ? 0 : 1] \
MEM_SIZE $mem_size \ MEM_SIZE_LOG2 [log2 $mem_size] \
TX_OR_RXN_PATH $datapath_type \ TX_OR_RXN_PATH $datapath_type \
SRC_DATA_WIDTH $source_dwidth \ SRC_DATA_WIDTH $source_dwidth \
SRC_ADDR_WIDTH $source_awidth \
DST_DATA_WIDTH $destination_dwidth \ DST_DATA_WIDTH $destination_dwidth \
DST_ADDR_WIDTH $destination_awidth \
DST_CYCLIC_EN $datapath_type \ DST_CYCLIC_EN $datapath_type \
SYNC_EXT_ADD_INTERNAL_CDC [expr {!$shared_devclk}] \ SYNC_EXT_ADD_INTERNAL_CDC [expr {!$shared_devclk}] \
] ]
@ -60,65 +57,49 @@ proc ad_data_offload_create {instance_name
# Internal storage instance (BRAMs) # Internal storage instance (BRAMs)
########################################################################### ###########################################################################
## Add the memory module source into the project file set ad_ip_instance util_do_ram storage_unit [list \
if {[get_files -quiet "ad_mem_asym.v"] == ""} {
add_files -norecurse -fileset sources_1 "$ad_hdl_dir/library/common/ad_mem_asym.v"
}
create_bd_cell -type module -reference ad_mem_asym storage_unit
set_property -dict [list \
CONFIG.A_DATA_WIDTH $source_dwidth \
CONFIG.A_ADDRESS_WIDTH $source_awidth \
CONFIG.B_DATA_WIDTH $destination_dwidth \
CONFIG.B_ADDRESS_WIDTH $destination_awidth \
CONFIG.CASCADE_HEIGHT 1 \
] [get_bd_cells storage_unit]
ad_connect storage_unit/clka i_data_offload/s_axis_aclk
ad_connect storage_unit/wea i_data_offload/fifo_src_wen
ad_connect storage_unit/addra i_data_offload/fifo_src_waddr
ad_connect storage_unit/dina i_data_offload/fifo_src_wdata
ad_connect storage_unit/clkb i_data_offload/m_axis_aclk
ad_connect storage_unit/reb i_data_offload/fifo_dst_ren
ad_connect storage_unit/addrb i_data_offload/fifo_dst_raddr
ad_connect storage_unit/doutb i_data_offload/fifo_dst_rdata
ad_connect i_data_offload/fifo_dst_ready VCC ; ## BRAM is always ready
ad_connect i_data_offload/ddr_calib_done VCC
} elseif {$mem_type == 1} {
###########################################################################
# Bridge instance for the external DDR4 memory contreller
# NOTE: The MIG instantiation should be in project's system_bd.tcl file
###########################################################################
ad_ip_instance util_fifo2axi_bridge fifo2axi_bridge [list \
SRC_DATA_WIDTH $source_dwidth \ SRC_DATA_WIDTH $source_dwidth \
SRC_ADDR_WIDTH $source_awidth \
DST_DATA_WIDTH $destination_dwidth \ DST_DATA_WIDTH $destination_dwidth \
DST_ADDR_WIDTH $destination_awidth \ LENGTH_WIDTH [log2 $mem_size] \
AXI_DATA_WIDTH $ddr_data_width \
AXI_ADDR_WIDTH $ddr_addr_width \
AXI_ADDRESS 0x00000000 \
AXI_ADDRESS_LIMIT [format 0x%X [expr int([expr { pow(2, 30) }]) - 1]] \
REMOVE_NULL_BEAT_EN $datapath_type \
] ]
ad_connect fifo2axi_bridge/fifo_src_clk i_data_offload/s_axis_aclk } elseif {$mem_type == 1 || $mem_type == 2} {
ad_connect fifo2axi_bridge/fifo_src_resetn i_data_offload/fifo_src_resetn ###########################################################################
ad_connect fifo2axi_bridge/fifo_src_wen i_data_offload/fifo_src_wen # Bridge instance for the external DDR (1) / HBM(2) memory contreller
ad_connect fifo2axi_bridge/fifo_src_waddr i_data_offload/fifo_src_waddr # NOTE: The DDR/HBM instantiation should be in project's system_bd.tcl file
ad_connect fifo2axi_bridge/fifo_src_wdata i_data_offload/fifo_src_wdata ###########################################################################
ad_connect fifo2axi_bridge/fifo_src_wlast i_data_offload/fifo_src_wlast source $ad_hdl_dir/library/util_hbm/scripts/adi_util_hbm.tcl
ad_connect fifo2axi_bridge/fifo_dst_clk i_data_offload/m_axis_aclk ad_create_util_hbm storage_unit \
ad_connect fifo2axi_bridge/fifo_dst_resetn i_data_offload/fifo_dst_resetn $datapath_type \
ad_connect fifo2axi_bridge/fifo_dst_ren i_data_offload/fifo_dst_ren $source_dwidth \
ad_connect fifo2axi_bridge/fifo_dst_raddr i_data_offload/fifo_dst_raddr $destination_dwidth \
ad_connect fifo2axi_bridge/fifo_dst_rdata i_data_offload/fifo_dst_rdata $mem_size \
ad_connect fifo2axi_bridge/fifo_dst_ready i_data_offload/fifo_dst_ready $axi_data_width \
$mem_type
if {$mem_type == 1} {
ad_ip_parameter storage_unit CONFIG.AXI_PROTOCOL 0
} else {
ad_ip_parameter storage_unit CONFIG.AXI_PROTOCOL 1
}
} }
###########################################################################
# Connect Storage to Data Offload
###########################################################################
ad_connect storage_unit/wr_ctrl i_data_offload/wr_ctrl
ad_connect storage_unit/rd_ctrl i_data_offload/rd_ctrl
ad_connect storage_unit/s_axis i_data_offload/m_storage_axis
ad_connect storage_unit/m_axis i_data_offload/s_storage_axis
ad_connect storage_unit/s_axis_aclk s_axis_aclk
ad_connect storage_unit/s_axis_aresetn s_axis_aresetn
ad_connect storage_unit/m_axis_aclk m_axis_aclk
ad_connect storage_unit/m_axis_aresetn m_axis_aresetn
########################################################################### ###########################################################################
# Internal connections # Internal connections
########################################################################### ###########################################################################
@ -135,7 +116,6 @@ proc ad_data_offload_create {instance_name
ad_connect m_axis i_data_offload/m_axis ad_connect m_axis i_data_offload/m_axis
ad_connect init_req i_data_offload/init_req ad_connect init_req i_data_offload/init_req
ad_connect init_ack i_data_offload/init_ack
ad_connect sync_ext i_data_offload/sync_ext ad_connect sync_ext i_data_offload/sync_ext
current_bd_instance / current_bd_instance /