diff --git a/docs/library/axi_dmac/index.rst b/docs/library/axi_dmac/index.rst index 7389ddaeca..9b2ad03322 100644 --- a/docs/library/axi_dmac/index.rst +++ b/docs/library/axi_dmac/index.rst @@ -140,6 +140,8 @@ Configuration Parameters * - ENABLE_DIAGNOSTICS_IF - Add insight into internal operation of the core, for debug purposes only. + * - SG_DELAYED_INPUT + - Read one set of data at a time to prevent IRQ overlap for partial transfers. Interface -------------------------------------------------------------------------------- @@ -771,6 +773,16 @@ Scatter-Gather Datapath Width The scatter-gather dedicated interface ``m_sg_axi`` currently supports only 64-bit transfers. ``DMA_DATA_WIDTH_SG`` can only be set to 64. +Scatter-Gather Delayed Input +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the ``SG_DELAYED_INPUT`` HDL synthesis configuration parameter is set, the +DMA is set to accept one packet on the input interface and wait for the +interrupt to be acknowledged. This feature was specifically created for cases +where ``PARTIAL_REPORTING_EN`` is enabled. In these cases multiple interrupts +are not overlapping if multiple packets arrive before the previous IRQ is +acknowledged. This enables the user to process each interrupt request seprately. + Software Support -------------------------------------------------------------------------------- diff --git a/docs/regmap/adi_regmap_dmac.txt b/docs/regmap/adi_regmap_dmac.txt index c9081732a8..892e4b460f 100644 --- a/docs/regmap/adi_regmap_dmac.txt +++ b/docs/regmap/adi_regmap_dmac.txt @@ -19,13 +19,13 @@ RO ENDFIELD FIELD -[15:8] 0x00000005 +[15:8] 0x00000006 VERSION_MINOR RO ENDFIELD FIELD -[7:0] 0x00000063 +[7:0] 0x00000000 VERSION_PATCH RO ENDFIELD diff --git a/library/axi_dmac/axi_dmac.v b/library/axi_dmac/axi_dmac.v index f74569752b..609832acfb 100644 --- a/library/axi_dmac/axi_dmac.v +++ b/library/axi_dmac/axi_dmac.v @@ -73,7 +73,8 @@ module axi_dmac #( parameter ALLOW_ASYM_MEM = 0, parameter CACHE_COHERENT = 0, parameter [3:0] AXI_AXCACHE = 4'b0011, - parameter [2:0] AXI_AXPROT = 3'b000 + parameter [2:0] AXI_AXPROT = 3'b000, + parameter SG_DELAYED_INPUT = 0 ) ( // Slave AXI interface @@ -546,7 +547,8 @@ module axi_dmac #( .ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF), .ALLOW_ASYM_MEM(ALLOW_ASYM_MEM), .AXI_AXCACHE(AXI_AXCACHE), - .AXI_AXPROT(AXI_AXPROT) + .AXI_AXPROT(AXI_AXPROT), + .SG_DELAYED_INPUT(SG_DELAYED_INPUT) ) i_transfer ( .ctrl_clk(s_axi_aclk), .ctrl_resetn(s_axi_aresetn), @@ -555,6 +557,8 @@ module axi_dmac #( .ctrl_pause(ctrl_pause), .ctrl_hwdesc(ctrl_hwdesc), + .irq(irq), + .req_valid(up_dma_req_valid), .req_ready(up_dma_req_ready), .req_dest_address(up_dma_req_dest_address), diff --git a/library/axi_dmac/axi_dmac_constr.ttcl b/library/axi_dmac/axi_dmac_constr.ttcl index e90fe6ba29..9a8bf9209f 100644 --- a/library/axi_dmac/axi_dmac_constr.ttcl +++ b/library/axi_dmac/axi_dmac_constr.ttcl @@ -15,6 +15,7 @@ <: set async_src_sg [getBooleanValue "ASYNC_CLK_SRC_SG"] :> <: set async_dest_sg [getBooleanValue "ASYNC_CLK_DEST_SG"] :> <: set sg_enabled [getBooleanValue "DMA_SG_TRANSFER"] :> +<: set sg_delayed_input [getBooleanValue "SG_DELAYED_INPUT"] :> <: set disable_debug_registers [getBooleanValue "DISABLE_DEBUG_REGISTERS"] :> set req_clk_ports_base {s_axi_aclk} @@ -287,6 +288,12 @@ set_false_path \ set_false_path \ -to [get_pins -hierarchical * -filter {NAME=~*i_raddr_sync_gray/cdc_sync_stage1_reg[*]/D}] +<: if {$async_req_sg && $sg_delayed_input} { :> +set_max_delay -datapath_only \ + -from [get_clocks -of_objects [get_ports $req_clk_ports_base]] \ + -to [get_cells -hier -filter {NAME =~ *sync_bits_irq/cdc_sync_stage1_reg* && IS_SEQUENTIAL}] \ + [get_property -min PERIOD [get_clocks -of_objects [get_ports $req_clk_ports_base]]] +<: } :> <: } :> # Reset signals set_false_path -quiet \ diff --git a/library/axi_dmac/axi_dmac_ip.tcl b/library/axi_dmac/axi_dmac_ip.tcl index 32745c1e99..57842329d5 100644 --- a/library/axi_dmac/axi_dmac_ip.tcl +++ b/library/axi_dmac/axi_dmac_ip.tcl @@ -281,6 +281,7 @@ foreach {k v} { \ "DISABLE_DEBUG_REGISTERS" "false" \ "ENABLE_DIAGNOSTICS_IF" "false" \ "CACHE_COHERENT" "false" \ + "SG_DELAYED_INPUT" "false" \ } { \ set_property -dict [list \ "value_format" "bool" \ @@ -454,24 +455,38 @@ set_property -dict [list \ set p [ipgui::get_guiparamspec -name "DMA_SG_TRANSFER" -component $cc] ipgui::move_param -component $cc -order 1 $p -parent $feature_group +set_property -dict [list \ + "tooltip" "Scatter-Gather Transfer Support" \ +] $p set_property -dict [list \ "display_name" "SG Transfer Support" \ + "enablement_tcl_expr" "\$DMA_TYPE_SRC == 0 || \$DMA_TYPE_DEST == 0" \ +] [ipx::get_user_parameters DMA_SG_TRANSFER -of_objects $cc] + +set p [ipgui::get_guiparamspec -name "SG_DELAYED_INPUT" -component $cc] +ipgui::move_param -component $cc -order 2 $p -parent $feature_group +set_property -dict [list \ + "tooltip" "Read one set of data at a time to prevent IRQ overlap for partial transfers" \ ] $p +set_property -dict [list \ + "display_name" "SG Slow Transfer Support" \ + "enablement_tcl_expr" "\$DMA_SG_TRANSFER == true" \ +] [ipx::get_user_parameters SG_DELAYED_INPUT -of_objects $cc] set p [ipgui::get_guiparamspec -name "DMA_2D_TRANSFER" -component $cc] -ipgui::move_param -component $cc -order 2 $p -parent $feature_group +ipgui::move_param -component $cc -order 3 $p -parent $feature_group set_property -dict [list \ "display_name" "2D Transfer Support" \ ] $p set p [ipgui::get_guiparamspec -name "SYNC_TRANSFER_START" -component $cc] -ipgui::move_param -component $cc -order 3 $p -parent $feature_group +ipgui::move_param -component $cc -order 4 $p -parent $feature_group set_property -dict [list \ "display_name" "Transfer Start Synchronization Support" \ ] $p set p [ipgui::get_guiparamspec -name "CACHE_COHERENT" -component $cc] -ipgui::move_param -component $cc -order 4 $p -parent $feature_group +ipgui::move_param -component $cc -order 5 $p -parent $feature_group set_property -dict [list \ "tooltip" "Assume DMA ports ensure cache coherence (e.g. Ultrascale HPC port)" \ ] $p @@ -510,14 +525,22 @@ set_property -dict [list \ set p [ipgui::get_guiparamspec -name "ASYNC_CLK_SRC_SG" -component $cc] ipgui::move_param -component $cc -order 4 $p -parent $clk_group set_property -dict [list \ - "display_name" "Source and Scatter-Gather Clock Asynchronous" \ + "tooltip" "Source and Scatter-Gather Clock Asynchronous" \ ] $p +set_property -dict [list \ + "display_name" "Source and Scatter-Gather Clock Asynchronous" \ + "enablement_tcl_expr" "\$DMA_SG_TRANSFER == true" \ +] [ipx::get_user_parameters ASYNC_CLK_SRC_SG -of_objects $cc] set p [ipgui::get_guiparamspec -name "ASYNC_CLK_DEST_SG" -component $cc] ipgui::move_param -component $cc -order 5 $p -parent $clk_group set_property -dict [list \ - "display_name" "Destination and Scatter-Gather Clock Asynchronous" \ + "tooltip" "Destination and Scatter-Gather Clock Asynchronous" \ ] $p +set_property -dict [list \ + "display_name" "Destination and Scatter-Gather Clock Asynchronous" \ + "enablement_tcl_expr" "\$DMA_SG_TRANSFER == true" \ +] [ipx::get_user_parameters ASYNC_CLK_DEST_SG -of_objects $cc] set dbg_group [ipgui::add_group -name {Debug} -component $cc \ -parent $page0 -display_name {Debug}] diff --git a/library/axi_dmac/axi_dmac_pkg_sv.ttcl b/library/axi_dmac/axi_dmac_pkg_sv.ttcl index 32daa4a278..e16ffb8106 100644 --- a/library/axi_dmac/axi_dmac_pkg_sv.ttcl +++ b/library/axi_dmac/axi_dmac_pkg_sv.ttcl @@ -40,6 +40,7 @@ <: set disable_debug_registers [get_property MODELPARAM_VALUE.DISABLE_DEBUG_REGISTERS] :> <: set enable_diagnostics_if [get_property MODELPARAM_VALUE.ENABLE_DIAGNOSTICS_IF] :> <: set cache_coherent [get_property MODELPARAM_VALUE.CACHE_COHERENT] :> +<: set sg_delayed_input [get_property MODELPARAM_VALUE.SG_DELAYED_INPUT] :> <: proc b2i {b} { if {$b==true} {return 1} else {return 0}} :> /////////////////////////////////////////////////////////////////////////// @@ -84,6 +85,7 @@ package <=: ComponentName :>_pkg; parameter <=: ComponentName :>_DISABLE_DEBUG_REGISTERS = <=: b2i $disable_debug_registers :>; parameter <=: ComponentName :>_ENABLE_DIAGNOSTICS_IF = <=: b2i $enable_diagnostics_if :>; parameter <=: ComponentName :>_CACHE_COHERENT = <=: b2i $cache_coherent :>; + parameter <=: ComponentName :>_SG_DELAYED_INPUT = <=: b2i $sg_delayed_input :>; ////////////////////////////////////////////////////////////////////////// endpackage : <=: ComponentName :>_pkg diff --git a/library/axi_dmac/axi_dmac_regmap.v b/library/axi_dmac/axi_dmac_regmap.v index c0fb5e5590..3cd3cfb403 100644 --- a/library/axi_dmac/axi_dmac_regmap.v +++ b/library/axi_dmac/axi_dmac_regmap.v @@ -123,7 +123,7 @@ module axi_dmac_regmap #( input [31:0] dbg_ids1 ); - localparam PCORE_VERSION = 'h00040563; + localparam PCORE_VERSION = 'h00040600; localparam HAS_ADDR_HIGH = DMA_AXI_ADDR_WIDTH > 32; localparam ADDR_LOW_MSB = HAS_ADDR_HIGH ? 31 : DMA_AXI_ADDR_WIDTH-1; diff --git a/library/axi_dmac/axi_dmac_transfer.v b/library/axi_dmac/axi_dmac_transfer.v index 7be69fa871..83d55ffa3c 100644 --- a/library/axi_dmac/axi_dmac_transfer.v +++ b/library/axi_dmac/axi_dmac_transfer.v @@ -66,7 +66,8 @@ module axi_dmac_transfer #( parameter ENABLE_DIAGNOSTICS_IF = 0, parameter ALLOW_ASYM_MEM = 0, parameter [3:0] AXI_AXCACHE = 4'b0011, - parameter [2:0] AXI_AXPROT = 3'b000 + parameter [2:0] AXI_AXPROT = 3'b000, + parameter SG_DELAYED_INPUT = 0 ) ( input ctrl_clk, input ctrl_resetn, @@ -75,6 +76,8 @@ module axi_dmac_transfer #( input ctrl_pause, input ctrl_hwdesc, + input irq, + input req_valid, output req_ready, @@ -261,6 +264,9 @@ module axi_dmac_transfer #( wire abort_req; wire dma_eot; + wire s_axis_ready_t; + wire s_axis_valid_t; + axi_dmac_reset_manager #( .ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC), .ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST), @@ -312,6 +318,43 @@ module axi_dmac_transfer #( assign req_sg_desc_id = ctrl_hwdesc ? dma_sg_hwdesc_id : 'h00; assign dma_sg_in_req_valid = ctrl_hwdesc ? req_valid_gated : 1'b0; + generate if ((DMA_SG_TRANSFER == 1) && (SG_DELAYED_INPUT == 1)) begin + + wire irq_cdc; + reg irq_d = 1'b0; + reg packet_received = 1'b0; + + sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (1) + ) sync_bits_irq ( + .in_bits (irq), + .out_clk (s_axis_aclk), + .out_resetn (1'b1), + .out_bits (irq_cdc)); + + always @(posedge s_axis_aclk) begin + irq_d <= irq_cdc; + end + + always @(posedge s_axis_aclk) begin + if (s_axis_last && s_axis_valid && s_axis_ready) + packet_received <= 1'b1; + else + if (!irq_cdc && irq_d) + packet_received <= 1'b0; + end + + assign s_axis_ready = (packet_received) ? 1'b0 : s_axis_ready_t; + assign s_axis_valid_t = (packet_received) ? 1'b0 : s_axis_valid; + + end else begin + + assign s_axis_ready = s_axis_ready_t; + assign s_axis_valid_t = s_axis_valid; + + end endgenerate + /* SG Interface */ generate if (DMA_SG_TRANSFER == 1) begin @@ -582,8 +625,8 @@ module axi_dmac_transfer #( .m_axi_rresp (m_axi_rresp), .s_axis_aclk (s_axis_aclk), - .s_axis_ready (s_axis_ready), - .s_axis_valid (s_axis_valid), + .s_axis_ready (s_axis_ready_t), + .s_axis_valid (s_axis_valid_t), .s_axis_data (s_axis_data), .s_axis_user (s_axis_user), .s_axis_last (s_axis_last),