From 5af371db6be3d7a8801eee7f57d765bf1fabe72a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 15 Sep 2015 18:58:40 +0200 Subject: [PATCH] axi_dmac: Generate per core instance constraint file When having multiple DMA cores sharing the same constraint file Vivado seems to apply the constraints from the first core to all the other cores when re-running synthesis and implementation from within the Vivado GUI. This causes wrong timing constraints if the DMA cores have different configurations. To avoid this issue use a TTCL template that generates a custom constraint file for each DMA core instance. This also allows us to drop the asynchronous clock detection hack from the constraint file and move it to the template and only generate the CDC constraints if the clock domains are asynchronous. Signed-off-by: Lars-Peter Clausen --- library/axi_dmac/Makefile | 2 +- library/axi_dmac/axi_dmac_constr.ttcl | 164 +++++++++++++++++++++ library/axi_dmac/axi_dmac_constr.xdc | 197 -------------------------- library/axi_dmac/axi_dmac_ip.tcl | 4 +- 4 files changed, 167 insertions(+), 200 deletions(-) create mode 100644 library/axi_dmac/axi_dmac_constr.ttcl delete mode 100644 library/axi_dmac/axi_dmac_constr.xdc diff --git a/library/axi_dmac/Makefile b/library/axi_dmac/Makefile index 211223fdb..a8eb95a83 100644 --- a/library/axi_dmac/Makefile +++ b/library/axi_dmac/Makefile @@ -26,7 +26,7 @@ M_DEPS += src_fifo_inf.v M_DEPS += splitter.v M_DEPS += response_generator.v M_DEPS += axi_dmac.v -M_DEPS += axi_dmac_constr.xdc +M_DEPS += axi_dmac_constr.ttcl M_DEPS += ../util_axis_resize/util_axis_resize.xpr M_DEPS += ../util_axis_fifo/util_axis_fifo.xpr diff --git a/library/axi_dmac/axi_dmac_constr.ttcl b/library/axi_dmac/axi_dmac_constr.ttcl new file mode 100644 index 000000000..796d513cd --- /dev/null +++ b/library/axi_dmac/axi_dmac_constr.ttcl @@ -0,0 +1,164 @@ +<: set ComponentName [getComponentNameString] :> +<: setOutputDirectory "./" :> +<: setFileName [ttcl_add $ComponentName "_constr"] :> +<: setFileExtension ".xdc" :> +<: setFileProcessingOrder late :> +<: set async_dest_req [getBooleanValue "C_CLKS_ASYNC_DEST_REQ"] :> +<: set async_req_src [getBooleanValue "C_CLKS_ASYNC_REQ_SRC"] :> +<: set async_src_dest [getBooleanValue "C_CLKS_ASYNC_SRC_DEST"] :> + +set req_clk [get_clocks -of_objects [get_ports s_axi_aclk]] +set src_clk [get_clocks -of_objects [get_ports -quiet {fifo_wr_clk s_axis_aclk m_src_axi_aclk}]] +set dest_clk [get_clocks -of_objects [get_ports -quiet {fifo_rd_clk m_axis_aclk m_dest_axi_aclk}]] + +set_property ASYNC_REG TRUE \ + [get_cells -quiet -hier *cdc_sync_stage1_reg*] \ + [get_cells -quiet -hier *cdc_sync_stage2_reg*] + +<: if {$async_req_src} { :> +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_src_request_id* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $req_clk] + +set_false_path -quiet \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_status_src* && PRIMITIVE_SUBGROUP == flop}] + +set_false_path -quiet \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_control_src* && PRIMITIVE_SUBGROUP == flop}] + +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_src_req_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $req_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_src_req_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_src_req_fifo* && PRIMITIVE_SUBGROUP == flop}] \ + -to $src_clk \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *eot_mem_reg* \ + -filter {NAME =~ *i_request_arb* && PRIMITIVE_SUBGROUP == flop}] \ + -to $src_clk \ + [get_property -min PERIOD $src_clk] + +<: } :> +<: if {$async_dest_req} { :> +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_req_response_id* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $dest_clk] + +set_false_path -quiet \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_status_dest* && PRIMITIVE_SUBGROUP == flop}] + +set_false_path -quiet \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_control_dest* && PRIMITIVE_SUBGROUP == flop}] + +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_req_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $req_clk] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_req_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [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_dest_req_fifo* && PRIMITIVE_SUBGROUP == flop}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_response_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $dest_clk] + +set_max_delay -quiet -datapath_only \ + -from $req_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_dest_response_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $req_clk] +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ + -filter {NAME =~ *i_dest_response_fifo* && PRIMITIVE_SUBGROUP == flop}] \ + -to $req_clk \ + [get_property -min PERIOD $req_clk] + +set_max_delay -quiet -datapath_only \ + -from [get_cells -quiet -hier *eot_mem_reg* \ + -filter {NAME =~ *i_request_arb* && PRIMITIVE_SUBGROUP == flop}] \ + -to $dest_clk \ + [get_property -min PERIOD $dest_clk] + +<: } :> +<: if {$async_src_dest} { :> +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_sync_dest_request_id* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $src_clk] + +set_max_delay -quiet -datapath_only \ + -from $src_clk \ + -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ + -filter {NAME =~ *i_fifo/i_address_gray/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [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_fifo/i_address_gray/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ + [get_property -min PERIOD $dest_clk] + +# Not sure why, but it seems the built-in constraints for the RAM36B are wrong +set_max_delay -quiet -datapath_only \ + -from $dest_clk \ + -to [get_pins -hier *ram_reg*/REGCEB -filter {NAME =~ *i_fifo*}] \ + [get_property -min PERIOD $dest_clk] + +<: } :> +# Reset signals +set_false_path -quiet \ + -from $req_clk \ + -to [get_pins -quiet -hier *reset_shift_reg*/PRE] + +# Ignore timing for debug signals to register map +set_false_path -quiet \ + -from [get_cells -quiet -hier *cdc_sync_stage2_reg* \ + -filter {name =~ *i_sync_src_request_id* && primitive_subgroup == flop}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *cdc_sync_stage2_reg* \ + -filter {name =~ *i_sync_dest_request_id* && primitive_subgroup == flop}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *id_reg* -filter {name =~ *i_request_arb* && primitive_subgroup == flop}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *address_reg* -filter {name =~ *i_addr_gen* && primitive_subgroup == flop}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] diff --git a/library/axi_dmac/axi_dmac_constr.xdc b/library/axi_dmac/axi_dmac_constr.xdc deleted file mode 100644 index e3e8e0ac1..000000000 --- a/library/axi_dmac/axi_dmac_constr.xdc +++ /dev/null @@ -1,197 +0,0 @@ - -set req_clk [get_clocks -of_objects [get_ports s_axi_aclk]] -set src_clk [get_clocks -of_objects [get_ports -quiet {fifo_wr_clk s_axis_aclk m_src_axi_aclk}]] -set dest_clk [get_clocks -of_objects [get_ports -quiet {fifo_rd_clk m_axis_aclk m_dest_axi_aclk}]] - -# if ... else does not work in xdc files, but expr, well ok... -set async_src_to_req_clk [expr {$req_clk != $src_clk ? $src_clk : {}}] -set async_req_to_src_clk [expr {$req_clk != $src_clk ? $req_clk : {}}] -set async_dest_to_req_clk [expr {$req_clk != $dest_clk ? $dest_clk : {}}] -set async_req_to_dest_clk [expr {$req_clk != $dest_clk ? $req_clk : {}}] -set async_dest_to_src_clk [expr {$src_clk != $dest_clk ? $dest_clk : {}}] -set async_src_to_dest_clk [expr {$src_clk != $dest_clk ? $src_clk : {}}] - -set_property ASYNC_REG TRUE \ - [get_cells -quiet -hier *cdc_sync_stage1_reg*] \ - [get_cells -quiet -hier *cdc_sync_stage2_reg*] - -#proc get_flops {name inst} { -# return [get_cells -hier $name \ -# -filter [format {NAME =~ *%s* && PRIMITIVE_SUBGROUP == flop} $name]] -#} -# -#proc set_single_bit_cdc_constraints {name clk} { -# set_false_path -from $clk -to [get_flops *cdc_sync_stage1_reg* ${name}] -#} -# -#proc set_multi_bit_cdc_constraints {name clk} { -# set_max_delay -from $clk -to [get_flops *cdc_sync_stage1_reg* ${name}] \ -# [get_property PERIOD $clk] -datapath_only -#} -# -#proc set_fifo_cdc_constraints {name clk_a clk_b} { -# set_multi_bit_cdc_constraints ${name}/i_waddr_sync $clk_a -# set_multi_bit_cdc_constraints ${name}/i_raddr_sync $clk_b -# set_max_delay -from [get_flops *cdc_sync_fifo_ram_reg* ${name}] -to $clk_b [get_property PERIOD $clk_b] -datapath_only -#} - -#set_multi_bit_constraints i_sync_src_request_id $req_clk -#set_multi_bit_constraints i_sync_dest_request_id $src_clk -#set_multi_bit_constraints i_sync_req_response_id $dest_clk - -set_max_delay -quiet \ - -from $async_req_to_src_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_src_request_id* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $req_clk] -datapath_only -set_max_delay -quiet \ - -from $async_src_to_dest_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_dest_request_id* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $src_clk] -datapath_only -set_max_delay -quiet \ - -from $async_dest_to_req_clk \ - -to [get_cells -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_req_response_id* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $dest_clk] -datapath_only - -#set_single_bit_cdc_constraints i_sync_status_src $src_clk -#set_single_bit_cdc_constraints i_sync_control_src $req_clk -#set_single_bit_cdc_constraints i_sync_status_dest $dest_clk -#set_single_bit_cdc_constraints i_sync_control_dest $req_clk - -set_false_path -quiet \ - -from $async_src_to_req_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_status_src* && PRIMITIVE_SUBGROUP == flop}] -set_false_path -quiet \ - -from $async_req_to_src_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_control_src* && PRIMITIVE_SUBGROUP == flop}] -set_false_path -quiet \ - -from $async_dest_to_req_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_status_dest* && PRIMITIVE_SUBGROUP == flop}] -set_false_path -quiet \ - -from $async_req_to_dest_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_sync_control_dest* && PRIMITIVE_SUBGROUP == flop}] - -#set_fifo_cdc_constraints i_dest_req_fifo $req_clk $dest_clk -#set_fifo_cdc_constraints i_dest_response_fifo $dest_clk $req_clk -#set_fifo_cdc_constraints i_src_req_fifo $req_clk $src_clk -#set_fifo_cdc_constraints i_src_response_fifo $src_clk $req_clk - -set_max_delay -quiet \ - -from $async_req_to_dest_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_dest_req_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $req_clk] -datapath_only -set_max_delay -quiet \ - -from $async_dest_to_req_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_dest_req_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $dest_clk] -datapath_only -set_max_delay -quiet \ - -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ - -filter {NAME =~ *i_dest_req_fifo* && PRIMITIVE_SUBGROUP == flop}] \ - -to $async_dest_to_req_clk \ - [get_property PERIOD $dest_clk] -datapath_only - -set_max_delay -quiet \ - -from $async_dest_to_req_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_dest_response_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $dest_clk] -datapath_only -set_max_delay -quiet \ - -from $async_req_to_dest_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_dest_response_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $req_clk] -datapath_only -set_max_delay -quiet \ - -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ - -filter {NAME =~ *i_dest_response_fifo* && PRIMITIVE_SUBGROUP == flop}] \ - -to $async_req_to_dest_clk \ - [get_property PERIOD $req_clk] -datapath_only - -set_max_delay -quiet \ - -from $async_req_to_src_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_src_req_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $req_clk] -datapath_only -set_max_delay -quiet \ - -from $async_src_to_req_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_src_req_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $src_clk] -datapath_only -set_max_delay -quiet \ - -from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \ - -filter {NAME =~ *i_src_req_fifo* && PRIMITIVE_SUBGROUP == flop}] \ - -to $async_src_to_req_clk \ - [get_property PERIOD $src_clk] -datapath_only - -#set_max_delay \ -# -from $src_clk \ -# -to [get_cells -hier *cdc_sync_stage1_reg* \ -# -filter {NAME =~ *i_src_response_fifo/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ -# [get_property PERIOD $src_clk] -datapath_only -#set_max_delay \ -# -from $req_clk \ -# -to [get_cells -hier *cdc_sync_stage1_reg* \ -# -filter {NAME =~ *i_src_response_fifo/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ -# [get_property PERIOD $req_clk] -datapath_only -#set_max_delay \ -# -from [get_cells -hier *cdc_sync_fifo_ram_reg* \ -# -filter {NAME =~ *i_src_response_fifo* && PRIMITIVE_SUBGROUP == flop}] \ -# -to $req_clk \ -# [get_property PERIOD $req_clk] -datapath_only - -#set_max_delay -from [get_flops *eot_mem_reg* i_request_arb] -to $src_clk [get_property PERIOD $src_clk] -datapath_only -#set_max_delay -from [get_flops *eot_mem_reg* i_request_arb] -to $dest_clk [get_property PERIOD $dest_clk] -datapath_only -set_max_delay -quiet \ - -from [get_cells -quiet -hier *eot_mem_reg* \ - -filter {NAME =~ *i_request_arb* && PRIMITIVE_SUBGROUP == flop}] \ - -to $async_src_to_req_clk [get_property PERIOD $src_clk] -datapath_only -set_max_delay -quiet \ - -from [get_cells -quiet -hier *eot_mem_reg* \ - -filter {NAME =~ *i_request_arb* && PRIMITIVE_SUBGROUP == flop}] \ - -to $async_dest_to_req_clk [get_property PERIOD $dest_clk] -datapath_only - -#set_fifo_cdc_constraints i_fifo $src_clk $dest_clk -set_max_delay -quiet \ - -from $async_src_to_dest_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_fifo/i_address_gray/i_waddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $src_clk] -datapath_only -set_max_delay -quiet \ - -from $async_dest_to_src_clk \ - -to [get_cells -quiet -hier *cdc_sync_stage1_reg* \ - -filter {NAME =~ *i_fifo/i_address_gray/i_raddr_sync* && PRIMITIVE_SUBGROUP == flop}] \ - [get_property PERIOD $dest_clk] -datapath_only - -# Reset signals -set_false_path -quiet \ - -from $req_clk \ - -to [get_pins -quiet -hier *reset_shift_reg*/PRE] - -# Not sure why, but it seems the built-in constraints for the RAM36B are wrong -set_max_delay -quiet \ - -from $async_dest_to_src_clk \ - -to [get_pins -hier *ram_reg*/REGCEB -filter {NAME =~ *i_fifo*}] \ - [get_property PERIOD $dest_clk] -datapath_only - -# Ignore timing for debug signals to register map -set_false_path -quiet \ - -from [get_cells -quiet -hier *cdc_sync_stage2_reg* \ - -filter {name =~ *i_sync_src_request_id* && primitive_subgroup == flop}] \ - -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] -set_false_path -quiet \ - -from [get_cells -quiet -hier *cdc_sync_stage2_reg* \ - -filter {name =~ *i_sync_dest_request_id* && primitive_subgroup == flop}] \ - -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] -set_false_path -quiet \ - -from [get_cells -quiet -hier *id_reg* -filter {name =~ *i_request_arb* && primitive_subgroup == flop}] \ - -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] -set_false_path -quiet \ - -from [get_cells -quiet -hier *address_reg* -filter {name =~ *i_addr_gen* && primitive_subgroup == flop}] \ - -to [get_cells -quiet -hier *up_rdata_reg* -filter {primitive_subgroup == flop}] diff --git a/library/axi_dmac/axi_dmac_ip.tcl b/library/axi_dmac/axi_dmac_ip.tcl index 2edd47838..3080d92bb 100644 --- a/library/axi_dmac/axi_dmac_ip.tcl +++ b/library/axi_dmac/axi_dmac_ip.tcl @@ -23,10 +23,10 @@ adi_ip_files axi_dmac [list \ "splitter.v" \ "response_generator.v" \ "axi_dmac.v" \ - "axi_dmac_constr.xdc" ] + "axi_dmac_constr.ttcl" ] adi_ip_properties axi_dmac -adi_ip_constraints axi_dmac "axi_dmac_constr.xdc" "late" +adi_ip_ttcl axi_dmac "axi_dmac_constr.ttcl" adi_ip_add_core_dependencies { \ analog.com:user:util_axis_resize:1.0 \