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 IPmain
parent
35d32e0143
commit
c3ae609bc8
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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_almost_full;
|
|
||||||
wire wr_init_req_s;
|
|
||||||
wire wr_init_req_pos_s;
|
|
||||||
wire wr_init_ack_s;
|
|
||||||
wire rd_isfull_s;
|
|
||||||
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 wr_sync_external_s;
|
||||||
|
wire wr_init_req_s;
|
||||||
|
wire wr_rd_response_eot;
|
||||||
wire rd_sync_external_s;
|
wire rd_sync_external_s;
|
||||||
wire wr_oneshot;
|
wire rd_last_eot;
|
||||||
|
wire rd_init_req_s;
|
||||||
|
|
||||||
(* DONT_TOUCH = "TRUE" *) reg [1:0] wr_fsm_state = 2'b00;
|
reg [4:0] wr_fsm_state = WR_STATE_IDLE;
|
||||||
(* DONT_TOUCH = "TRUE" *) reg [1:0] rd_fsm_state = 2'b00;
|
reg [4:0] wr_fsm_next_state;
|
||||||
|
reg [3:0] rd_fsm_state = RD_STATE_IDLE;
|
||||||
|
reg [3:0] rd_fsm_next_state;
|
||||||
|
reg [1:0] rd_outstanding = 2'd0;
|
||||||
|
|
||||||
// Mealy state machine for write control
|
assign wr_fsm_state_out = wr_fsm_state;
|
||||||
always @(posedge wr_clk) begin
|
assign rd_fsm_state_out = rd_fsm_state;
|
||||||
if (wr_resetn_in == 1'b0) begin
|
|
||||||
wr_fsm_state <= WR_IDLE;
|
always @(*) begin
|
||||||
end else begin
|
wr_fsm_next_state = wr_fsm_state;
|
||||||
case (wr_fsm_state)
|
case (wr_fsm_state)
|
||||||
|
WR_STATE_IDLE:
|
||||||
WR_IDLE: begin
|
if (wr_init_req_s & ~wr_bypass) begin
|
||||||
if (wr_init_req_s) begin
|
wr_fsm_next_state = WR_STATE_PRE_WR;
|
||||||
wr_fsm_state <= (TX_OR_RXN_PATH) ? WR_WRITE_TO_MEM : WR_SYNC;
|
|
||||||
end else begin
|
|
||||||
wr_fsm_state <= WR_IDLE;
|
|
||||||
end
|
end
|
||||||
|
WR_STATE_PRE_WR:
|
||||||
|
if (wr_request_ready) begin
|
||||||
|
wr_fsm_next_state = TX_OR_RXN_PATH ? WR_STATE_WR : WR_STATE_SYNC;
|
||||||
end
|
end
|
||||||
|
WR_STATE_SYNC:
|
||||||
WR_SYNC: begin
|
|
||||||
// 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)
|
case (sync_config)
|
||||||
AUTOMATIC: begin
|
AUTOMATIC:
|
||||||
wr_fsm_state <= WR_WRITE_TO_MEM;
|
wr_fsm_next_state = WR_STATE_WR;
|
||||||
end
|
HARDWARE:
|
||||||
HARDWARE: begin
|
|
||||||
if (wr_sync_external_s) begin
|
if (wr_sync_external_s) begin
|
||||||
wr_fsm_state <= WR_WRITE_TO_MEM;
|
wr_fsm_next_state = WR_STATE_WR;
|
||||||
end
|
end
|
||||||
end
|
SOFTWARE:
|
||||||
SOFTWARE: begin
|
|
||||||
if (sync_internal) begin
|
if (sync_internal) begin
|
||||||
wr_fsm_state <= WR_WRITE_TO_MEM;
|
wr_fsm_next_state = WR_STATE_WR;
|
||||||
end
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
wr_fsm_state <= WR_WRITE_TO_MEM;
|
|
||||||
end
|
end
|
||||||
|
default:
|
||||||
|
wr_fsm_next_state = WR_STATE_WR;
|
||||||
endcase
|
endcase
|
||||||
|
WR_STATE_WR:
|
||||||
|
if (wr_response_eot) begin
|
||||||
|
wr_fsm_next_state = WR_STATE_WAIT_RD;
|
||||||
end
|
end
|
||||||
|
WR_STATE_WAIT_RD:
|
||||||
|
if (wr_rd_response_eot) begin
|
||||||
|
wr_fsm_next_state = WR_STATE_IDLE;
|
||||||
end
|
end
|
||||||
|
default:
|
||||||
WR_WRITE_TO_MEM: begin
|
wr_fsm_next_state = WR_STATE_IDLE;
|
||||||
if ((wr_full || wr_last) && wr_valid_out) begin
|
|
||||||
wr_fsm_state <= WR_WAIT_TO_END;
|
|
||||||
end else begin
|
|
||||||
wr_fsm_state <= WR_WRITE_TO_MEM;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
WR_WAIT_TO_END: begin
|
|
||||||
if (wr_isempty_s && (wr_oneshot || wr_init_req_s)) begin
|
|
||||||
wr_fsm_state <= WR_IDLE;
|
|
||||||
end else begin
|
|
||||||
wr_fsm_state <= WR_WAIT_TO_END;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default: wr_fsm_state <= WR_IDLE;
|
|
||||||
endcase
|
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}};
|
|
||||||
end else begin
|
|
||||||
if (wr_last) begin
|
|
||||||
// if the SOURCE is at back-end, the interface is FIFO, set the tkeep
|
|
||||||
// to its default
|
|
||||||
wr_last_keep <= (TX_OR_RXN_PATH) ? wr_tkeep : {WR_DATA_WIDTH/8{1'b1}};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge wr_clk) begin
|
|
||||||
wr_ready_d <= wr_ready && !(wr_valid_in && wr_last);
|
|
||||||
end
|
|
||||||
|
|
||||||
// flush out the DMA if the transfer is bigger than the storage size
|
|
||||||
assign wr_ready = ((wr_fsm_state == WR_WRITE_TO_MEM) ||
|
|
||||||
(TX_OR_RXN_PATH && ((wr_fsm_state == WR_WAIT_TO_END) && wr_ready_d))) ? 1'b1 : 1'b0;
|
|
||||||
|
|
||||||
// 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)
|
case (rd_fsm_state)
|
||||||
|
RD_STATE_IDLE:
|
||||||
RD_IDLE: begin
|
if (rd_ml_valid) begin
|
||||||
if (((!TX_OR_RXN_PATH) & rd_isfull_s) || (rd_wr_last_s)) begin
|
rd_fsm_next_state = RD_STATE_PRE_RD;
|
||||||
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
|
RD_STATE_PRE_RD:
|
||||||
rd_fsm_state <= RD_IDLE;
|
if (rd_request_ready) begin
|
||||||
|
rd_fsm_next_state = TX_OR_RXN_PATH ? RD_STATE_SYNC : RD_STATE_RD;
|
||||||
end
|
end
|
||||||
end
|
RD_STATE_SYNC:
|
||||||
|
if (rd_valid) // Wait until storage is valid
|
||||||
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)
|
case (sync_config)
|
||||||
AUTOMATIC: begin
|
AUTOMATIC:
|
||||||
rd_fsm_state <= RD_READ_FROM_MEM;
|
rd_fsm_next_state = RD_STATE_RD;
|
||||||
end
|
HARDWARE:
|
||||||
HARDWARE: begin
|
|
||||||
if (rd_sync_external_s) begin
|
if (rd_sync_external_s) begin
|
||||||
rd_fsm_state <= RD_READ_FROM_MEM;
|
rd_fsm_next_state = RD_STATE_RD;
|
||||||
end
|
end
|
||||||
end
|
SOFTWARE:
|
||||||
SOFTWARE: begin
|
|
||||||
if (sync_internal) begin
|
if (sync_internal) begin
|
||||||
rd_fsm_state <= RD_READ_FROM_MEM;
|
rd_fsm_next_state = RD_STATE_RD;
|
||||||
end
|
end
|
||||||
|
default:
|
||||||
|
rd_fsm_next_state = RD_STATE_RD;
|
||||||
|
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: begin
|
default:
|
||||||
rd_fsm_state <= RD_READ_FROM_MEM;
|
rd_fsm_next_state = RD_STATE_IDLE;
|
||||||
end
|
|
||||||
endcase
|
endcase
|
||||||
end
|
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 else begin
|
|
||||||
rd_fsm_state <= RD_READ_FROM_MEM;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default : rd_fsm_state <= RD_IDLE;
|
|
||||||
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
|
always @(posedge rd_clk) begin
|
||||||
rd_init_req_d <= rd_init_req_s;
|
if (rd_resetn_in == 1'b0) begin
|
||||||
end
|
rd_fsm_state <= RD_STATE_IDLE;
|
||||||
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
|
end else begin
|
||||||
rd_resetn_out <= 1'b1;
|
rd_fsm_state <= rd_fsm_next_state;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// read address generation
|
|
||||||
always @(posedge rd_clk) begin
|
always @(posedge rd_clk) begin
|
||||||
if (rd_fsm_state != RD_READ_FROM_MEM) begin
|
if (rd_resetn_in == 1'b0)
|
||||||
rd_addr <= 'b0;
|
rd_outstanding <= 2'b0;
|
||||||
end else begin
|
else if (rd_request_ready & rd_request_valid & ~rd_response_eot)
|
||||||
if (rd_valid) begin
|
rd_outstanding <= rd_outstanding + 2'd1;
|
||||||
if (rd_oneshot)
|
else if (~(rd_request_ready & rd_request_valid) & (rd_response_eot & rd_fsm_state[RD_BIT_RD]))
|
||||||
rd_addr <= (rd_last_addr == rd_addr) ? rd_addr : rd_addr + 1'b1;
|
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
|
else
|
||||||
rd_addr <= (rd_last_addr == rd_addr) ? {RD_ADDRESS_WIDTH{1'b0}} : rd_addr + 1'b1;
|
rd_request_enable <= 1'b1;
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assign rd_empty_s = (rd_addr == rd_last_addr) ? 1'b1 : 1'b0;
|
always @(posedge wr_clk) begin
|
||||||
assign rd_last = rd_oneshot & rd_empty_s;
|
if (wr_resetn_in == 1'b0)
|
||||||
always @(posedge rd_clk) begin
|
wr_request_enable <= 1'b0;
|
||||||
if (rd_resetn_in == 1'b0) begin
|
else
|
||||||
rd_isempty <= 1'b0;
|
wr_request_enable <= 1'b1;
|
||||||
end else begin
|
|
||||||
rd_isempty <= rd_empty_s;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge rd_clk) begin
|
assign rd_ml_ready = rd_fsm_state[RD_BIT_IDLE];
|
||||||
if (rd_resetn_in == 1'b0) begin
|
|
||||||
rd_valid <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
if ((rd_ready) && (rd_fsm_state == RD_READ_FROM_MEM) && !(rd_valid && rd_last && rd_oneshot)) begin
|
|
||||||
rd_valid <= 1'b1;
|
|
||||||
end else begin
|
|
||||||
rd_valid <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 :>;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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 |
|
@ -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 /
|
||||||
|
|
Loading…
Reference in New Issue