data_offload: Improve external synchronization
This commit adds a new synthesis option to the design, that controls whether an internal clock domain crossing will be generated. Disabling this option allows you to use a synchronization signal that is synchronized to the write clock domain externally, and possibly shared between multiple devices. The default value retains the old behavior. Signed-off-by: David Winter <david.winter@analog.com>main
parent
0372ce1821
commit
7423ecae14
|
@ -55,7 +55,8 @@ module data_offload #(
|
||||||
parameter DST_RAW_DATA_EN = 1'b0, // TBD
|
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) (
|
||||||
|
|
||||||
// AXI4 Slave for configuration
|
// AXI4 Slave for configuration
|
||||||
|
|
||||||
|
@ -215,8 +216,10 @@ module data_offload #(
|
||||||
.WR_ADDRESS_WIDTH (SRC_ADDR_WIDTH),
|
.WR_ADDRESS_WIDTH (SRC_ADDR_WIDTH),
|
||||||
.WR_DATA_WIDTH (SRC_DATA_WIDTH),
|
.WR_DATA_WIDTH (SRC_DATA_WIDTH),
|
||||||
.RD_ADDRESS_WIDTH (DST_ADDR_WIDTH),
|
.RD_ADDRESS_WIDTH (DST_ADDR_WIDTH),
|
||||||
.RD_DATA_WIDTH (DST_DATA_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),
|
||||||
.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_resetn_out (fifo_src_resetn),
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<: setFileProcessingOrder late :>
|
<: setFileProcessingOrder late :>
|
||||||
<: 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"] :>
|
||||||
|
|
||||||
## 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 \
|
||||||
|
@ -14,9 +15,23 @@ set_property ASYNC_REG TRUE \
|
||||||
## For RX in case of BRAMs
|
## For RX in case of BRAMs
|
||||||
<: if { $tx_enable == 0 } { :>
|
<: if { $tx_enable == 0 } { :>
|
||||||
|
|
||||||
|
<: if { $internal_cdc } { :>
|
||||||
|
set_false_path \
|
||||||
|
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_wr_sync/cdc_sync_stage1_reg[*]/D}]
|
||||||
|
<: } :>
|
||||||
|
|
||||||
set_false_path \
|
set_false_path \
|
||||||
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_wr_sync/cdc_sync_stage1_reg[*]/D}]
|
-from [get_cells -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/cdc_hold_reg[*]}] \
|
||||||
|
-to [get_cells -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/out_data_reg[*]}]
|
||||||
|
|
||||||
|
set_false_path \
|
||||||
|
-from [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/in_toggle_d1_reg/C}] \
|
||||||
|
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/i_sync_out/cdc_sync_stage1_reg[*]/D}]
|
||||||
|
|
||||||
|
set_false_path \
|
||||||
|
-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}]
|
||||||
|
|
||||||
<: if { !$mem_type } { :>
|
<: if { !$mem_type } { :>
|
||||||
|
|
||||||
set_false_path \
|
set_false_path \
|
||||||
|
@ -34,9 +49,12 @@ set_false_path \
|
||||||
## For TX in case of BRAMs
|
## For TX in case of BRAMs
|
||||||
<: if { $tx_enable == 1 } { :>
|
<: if { $tx_enable == 1 } { :>
|
||||||
|
|
||||||
|
<: if { $internal_cdc } { :>
|
||||||
set_false_path \
|
set_false_path \
|
||||||
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_rd_sync/cdc_sync_stage1_reg[*]/D}]
|
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_rd_sync/cdc_sync_stage1_reg[*]/D}]
|
||||||
|
<: } :>
|
||||||
|
|
||||||
|
|
||||||
<: if { !$mem_type } { :>
|
<: if { !$mem_type } { :>
|
||||||
|
|
||||||
set_false_path \
|
set_false_path \
|
||||||
|
@ -52,21 +70,9 @@ set_false_path \
|
||||||
<: } :>
|
<: } :>
|
||||||
|
|
||||||
## For external DDRx memory
|
## For external DDRx memory
|
||||||
|
|
||||||
<: if { $mem_type == 1 } { :>
|
<: if { $mem_type == 1 } { :>
|
||||||
|
|
||||||
set_false_path \
|
|
||||||
-from [get_cells -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/cdc_hold_reg[*]}] \
|
|
||||||
-to [get_cells -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/out_data_reg[*]}]
|
|
||||||
|
|
||||||
set_false_path \
|
|
||||||
-from [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/in_toggle_d1_reg/C}] \
|
|
||||||
-to [get_pins -hierarchical * -filter {NAME=~*/i_sync_src_transfer_length/i_sync_out/cdc_sync_stage1_reg[*]/D}]
|
|
||||||
|
|
||||||
set_false_path \
|
|
||||||
-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}]
|
|
||||||
|
|
||||||
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}]
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,10 @@ module data_offload_fsm #(
|
||||||
parameter WR_ADDRESS_WIDTH = 4,
|
parameter WR_ADDRESS_WIDTH = 4,
|
||||||
parameter WR_DATA_WIDTH = 128,
|
parameter WR_DATA_WIDTH = 128,
|
||||||
parameter RD_ADDRESS_WIDTH = 4,
|
parameter RD_ADDRESS_WIDTH = 4,
|
||||||
parameter RD_DATA_WIDTH = 128)(
|
parameter RD_DATA_WIDTH = 128,
|
||||||
|
parameter SYNC_EXT_ADD_INTERNAL_CDC = 1) (
|
||||||
|
|
||||||
|
input up_clk,
|
||||||
|
|
||||||
// write control interface
|
// write control interface
|
||||||
input wr_clk,
|
input wr_clk,
|
||||||
|
@ -132,8 +135,6 @@ module data_offload_fsm #(
|
||||||
wire rd_init_ack_s;
|
wire rd_init_ack_s;
|
||||||
wire [WR_ADDRESS_WIDTH-1:0] rd_wr_last_addr_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_DATA_WIDTH/8-1:0] rd_wr_last_tkeep_s;
|
||||||
wire wr_sync_internal_s;
|
|
||||||
wire rd_sync_internal_s;
|
|
||||||
wire wr_sync_external_s;
|
wire wr_sync_external_s;
|
||||||
wire rd_sync_external_s;
|
wire rd_sync_external_s;
|
||||||
wire wr_oneshot;
|
wire wr_oneshot;
|
||||||
|
@ -171,7 +172,7 @@ module data_offload_fsm #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
SOFTWARE: begin
|
SOFTWARE: begin
|
||||||
if (wr_sync_internal_s) begin
|
if (sync_internal) begin
|
||||||
wr_fsm_state <= WR_WRITE_TO_MEM;
|
wr_fsm_state <= WR_WRITE_TO_MEM;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -256,7 +257,7 @@ module data_offload_fsm #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge wr_clk) begin
|
always @(posedge wr_clk) begin
|
||||||
wr_ready_d <= wr_ready;
|
wr_ready_d <= wr_ready;
|
||||||
end
|
end
|
||||||
|
@ -315,7 +316,7 @@ module data_offload_fsm #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
SOFTWARE: begin
|
SOFTWARE: begin
|
||||||
if (rd_sync_internal_s) begin
|
if (sync_internal) begin
|
||||||
rd_fsm_state <= RD_READ_FROM_MEM;
|
rd_fsm_state <= RD_READ_FROM_MEM;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -555,24 +556,27 @@ module data_offload_fsm #(
|
||||||
end
|
end
|
||||||
end
|
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
|
||||||
|
// because the incorrectly synchronized signal is guarded by a synthesis constant.
|
||||||
sync_bits #(
|
sync_bits #(
|
||||||
.NUM_OF_BITS (2),
|
.NUM_OF_BITS (1),
|
||||||
.ASYNC_CLK (1))
|
.ASYNC_CLK (SYNC_EXT_ADD_INTERNAL_CDC))
|
||||||
i_sync_wr_sync (
|
i_sync_wr_sync (
|
||||||
.in_bits ({ sync_internal, sync_external }),
|
.in_bits ({ sync_external }),
|
||||||
.out_clk (wr_clk),
|
.out_clk (wr_clk),
|
||||||
.out_resetn (1'b1),
|
.out_resetn (1'b1),
|
||||||
.out_bits ({ wr_sync_internal_s, wr_sync_external_s })
|
.out_bits ({ wr_sync_external_s })
|
||||||
);
|
);
|
||||||
|
|
||||||
sync_bits #(
|
sync_bits #(
|
||||||
.NUM_OF_BITS (2),
|
.NUM_OF_BITS (1),
|
||||||
.ASYNC_CLK (1))
|
.ASYNC_CLK (SYNC_EXT_ADD_INTERNAL_CDC))
|
||||||
i_sync_rd_sync (
|
i_sync_rd_sync (
|
||||||
.in_bits ({ sync_internal, sync_external }),
|
.in_bits ({ sync_external }),
|
||||||
.out_clk (rd_clk),
|
.out_clk (rd_clk),
|
||||||
.out_resetn (1'b1),
|
.out_resetn (1'b1),
|
||||||
.out_bits ({ rd_sync_internal_s, rd_sync_external_s })
|
.out_bits ({ rd_sync_external_s })
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -105,6 +105,7 @@ foreach {k v} { \
|
||||||
"SRC_RAW_DATA_EN" "false" \
|
"SRC_RAW_DATA_EN" "false" \
|
||||||
"DST_RAW_DATA_EN" "false" \
|
"DST_RAW_DATA_EN" "false" \
|
||||||
"DST_CYCLIC_EN" "true" \
|
"DST_CYCLIC_EN" "true" \
|
||||||
|
"SYNC_EXT_ADD_INTERNAL_CDC" "true" \
|
||||||
} { \
|
} { \
|
||||||
set_property -dict [list \
|
set_property -dict [list \
|
||||||
"value_format" "bool" \
|
"value_format" "bool" \
|
||||||
|
@ -229,6 +230,11 @@ set_property -dict [list \
|
||||||
] [ipgui::get_guiparamspec -name "DST_CYCLIC_EN" -component $cc]
|
] [ipgui::get_guiparamspec -name "DST_CYCLIC_EN" -component $cc]
|
||||||
set_property enablement_tcl_expr {$TX_OR_RXN_PATH == 1} [ipx::get_user_parameters DST_CYCLIC_EN -of_objects $cc]
|
set_property enablement_tcl_expr {$TX_OR_RXN_PATH == 1} [ipx::get_user_parameters DST_CYCLIC_EN -of_objects $cc]
|
||||||
|
|
||||||
|
ipgui::add_param -name "SYNC_EXT_ADD_INTERNAL_CDC" -component $cc -parent $features_group
|
||||||
|
set_property -dict [list \
|
||||||
|
"display_name" "Generate CDC Circuit for sync_ext" \
|
||||||
|
] [ipgui::get_guiparamspec -name "SYNC_EXT_ADD_INTERNAL_CDC" -component $cc]
|
||||||
|
|
||||||
## Create and save the XGUI file
|
## Create and save the XGUI file
|
||||||
ipx::create_xgui_files $cc
|
ipx::create_xgui_files $cc
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
|
|
||||||
proc ad_data_offload_create {instance_name datapath_type mem_type mem_size source_dwidth destination_dwidth {ddr_data_width 0} {ddr_addr_width 0}} {
|
proc ad_data_offload_create {instance_name
|
||||||
|
datapath_type
|
||||||
|
mem_type
|
||||||
|
mem_size
|
||||||
|
source_dwidth
|
||||||
|
destination_dwidth
|
||||||
|
{ddr_data_width 0}
|
||||||
|
{ddr_addr_width 0}
|
||||||
|
{shared_devclk 0}} {
|
||||||
|
|
||||||
global ad_hdl_dir
|
global ad_hdl_dir
|
||||||
global sys_cpu_resetn
|
global sys_cpu_resetn
|
||||||
|
@ -44,6 +52,7 @@ proc ad_data_offload_create {instance_name datapath_type mem_type mem_size sourc
|
||||||
DST_DATA_WIDTH $destination_dwidth \
|
DST_DATA_WIDTH $destination_dwidth \
|
||||||
DST_ADDR_WIDTH $destination_awidth \
|
DST_ADDR_WIDTH $destination_awidth \
|
||||||
DST_CYCLIC_EN $datapath_type \
|
DST_CYCLIC_EN $datapath_type \
|
||||||
|
SYNC_EXT_ADD_INTERNAL_CDC [expr {!$shared_devclk}] \
|
||||||
]
|
]
|
||||||
|
|
||||||
if {$mem_type == 0} {
|
if {$mem_type == 0} {
|
||||||
|
|
Loading…
Reference in New Issue