diff --git a/library/axi_dmac/Makefile b/library/axi_dmac/Makefile index 1b88639a50..7cc298a460 100644 --- a/library/axi_dmac/Makefile +++ b/library/axi_dmac/Makefile @@ -11,6 +11,7 @@ GENERIC_DEPS += address_generator.v GENERIC_DEPS += axi_dmac.v GENERIC_DEPS += axi_dmac_regmap.v GENERIC_DEPS += axi_dmac_regmap_request.v +GENERIC_DEPS += axi_dmac_reset_manager.v GENERIC_DEPS += axi_dmac_transfer.v GENERIC_DEPS += axi_register_slice.v GENERIC_DEPS += data_mover.v diff --git a/library/axi_dmac/address_generator.v b/library/axi_dmac/address_generator.v index c9bcf2f109..f94fb50753 100644 --- a/library/axi_dmac/address_generator.v +++ b/library/axi_dmac/address_generator.v @@ -52,7 +52,6 @@ module dmac_address_generator #( output reg [ID_WIDTH-1:0] id, input [ID_WIDTH-1:0] request_id, - input sync_id, input eot, @@ -99,21 +98,21 @@ reg last = 1'b0; always @(posedge clk) begin if (resetn == 1'b0) begin enabled <= 1'b0; - end else begin - if (enable) - enabled <= 1'b1; - else if (~addr_valid) - enabled <= 1'b0; + end else if (enable == 1'b1) begin + enabled <= 1'b1; + end else if (addr_valid == 1'b0) begin + enabled <= 1'b0; end end always @(posedge clk) begin if (addr_valid == 1'b0) begin last <= eot; - if (eot == 1'b1) + if (eot == 1'b1) begin length <= last_burst_len; - else + end else begin length <= MAX_LENGTH; + end end end @@ -131,34 +130,26 @@ always @(posedge clk) begin req_ready <= 1'b1; addr_valid <= 1'b0; end else begin - if (~enabled) begin - req_ready <= 1'b1; - end else if (req_ready) begin - if (req_valid && enable) begin - req_ready <= 1'b0; - end - end else begin - if (addr_valid && addr_ready) begin - addr_valid <= 1'b0; - if (last) - req_ready <= 1'b1; - end else if (id != request_id && enable) begin - addr_valid <= 1'b1; - end + if (req_ready == 1'b1) begin + req_ready <= ~req_valid; + end else if (addr_valid == 1'b1 && addr_ready == 1'b1) begin + addr_valid <= 1'b0; + req_ready <= last; + end else if (id != request_id && enable == 1'b1) begin + addr_valid <= 1'b1; end end end always @(posedge clk) begin - if (resetn == 1'b0) begin - id <='h0; - addr_valid_d1 <= 1'b0; - end else begin - addr_valid_d1 <= addr_valid; - if ((addr_valid && ~addr_valid_d1) || - (sync_id && id != request_id)) - id <= inc_id(id); + addr_valid_d1 <= addr_valid; +end +always @(posedge clk) begin + if (resetn == 1'b0) begin + id <= 'h0; + end else if (addr_valid == 1'b1 && addr_valid_d1 == 1'b0) begin + id <= inc_id(id); end end diff --git a/library/axi_dmac/axi_dmac.v b/library/axi_dmac/axi_dmac.v index fe559ef251..1193b83c23 100644 --- a/library/axi_dmac/axi_dmac.v +++ b/library/axi_dmac/axi_dmac.v @@ -285,7 +285,7 @@ wire [ID_WIDTH-1:0] src_request_id; wire [ID_WIDTH-1:0] src_data_id; wire [ID_WIDTH-1:0] src_address_id; wire [ID_WIDTH-1:0] src_response_id; -wire [7:0] dbg_status; +wire [11:0] dbg_status; wire [31:0] dbg_ids0; wire [31:0] dbg_ids1; @@ -430,11 +430,11 @@ axi_dmac_transfer #( .AXI_LENGTH_WIDTH_SRC(8-(4*DMA_AXI_PROTOCOL_SRC)), .AXI_LENGTH_WIDTH_DEST(8-(4*DMA_AXI_PROTOCOL_DEST)) ) i_transfer ( - .req_clk(s_axi_aclk), - .req_resetn(s_axi_aresetn), + .ctrl_clk(s_axi_aclk), + .ctrl_resetn(s_axi_aresetn), - .enable(ctrl_enable), - .pause(ctrl_pause), + .ctrl_enable(ctrl_enable), + .ctrl_pause(ctrl_pause), .req_valid(up_dma_req_valid), .req_ready(up_dma_req_ready), diff --git a/library/axi_dmac/axi_dmac_constr.sdc b/library/axi_dmac/axi_dmac_constr.sdc index 18167798d8..b9a05e28c5 100644 --- a/library/axi_dmac/axi_dmac_constr.sdc +++ b/library/axi_dmac/axi_dmac_constr.sdc @@ -3,10 +3,28 @@ set_false_path -to [get_registers *axi_dmac*cdc_sync_stage1*] set_false_path -from [get_registers *axi_dmac*cdc_sync_fifo_ram*] set_false_path -from [get_registers *axi_dmac*eot_mem*] -set_false_path -to [get_registers *axi_dmac*reset_shift*] + +# Reset manager +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|do_reset}] \ + -to [get_pins -compatibility_mode {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[*]|clrn}] + +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[0]}] \ + -to [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[3]}] + +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_async[0]}] \ + -to [get_pins -compatibility_mode {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync_in|clrn}] + +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync[0]}] \ + -to [get_pins -compatibility_mode {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync_in|clrn}] # Debug signals set_false_path -from [get_registers *axi_dmac*|*i_request_arb*|cdc_sync_stage2*] -to [get_registers *axi_dmac*up_rdata*] set_false_path -from [get_registers *axi_dmac*|*i_request_arb*|*id*] -to [get_registers *axi_dmac*up_rdata*] set_false_path -from [get_registers *axi_dmac*|*i_request_arb*|address*] -to [get_registers *axi_dmac*up_rdata*] - +set_false_path \ + -from [get_registers {*|axi_dmac_transfer:i_transfer|axi_dmac_reset_manager:i_reset_manager|reset_gen[*].reset_sync[0]}] \ + -to [get_registers {*|axi_dmac_regmap:i_regmap|up_rdata[*]}] diff --git a/library/axi_dmac/axi_dmac_constr.ttcl b/library/axi_dmac/axi_dmac_constr.ttcl index eb6563c593..fb3cb041b2 100644 --- a/library/axi_dmac/axi_dmac_constr.ttcl +++ b/library/axi_dmac/axi_dmac_constr.ttcl @@ -143,8 +143,37 @@ set_max_delay -quiet -datapath_only \ <: } :> # Reset signals set_false_path -quiet \ - -from $req_clk \ - -to [get_pins -quiet -hier *reset_shift_reg*/PRE] + -from [get_cells -quiet -hier *do_reset_reg* \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_pins -quiet -hier *reset_async_reg*/PRE] + +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_async_reg[0] \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *reset_async_reg[3]* \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] + +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_async_reg[0] \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_pins -quiet -hier *reset_sync_in_reg*/PRE \ + -filter {NAME =~ *i_reset_manager*}] + +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_sync_reg[0] \ + -filter {NAME =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_pins -quiet -hier *reset_sync_in_reg*/PRE \ + -filter {NAME =~ *i_reset_manager*}] + +set_property -dict { \ + SHREG_EXTRACT NO \ + ASYNC_REG TRUE \ + } [get_cells -quiet -hier *reset_shift_reg*] + +set_property -dict { \ + SHREG_EXTRACT NO \ + ASYNC_REG TRUE \ + } [get_cells -quiet -hier *reset_sync_reg*] # Ignore timing for debug signals to register map <: if {!$disable_debug_registers} { :> @@ -162,4 +191,7 @@ set_false_path -quiet \ set_false_path -quiet \ -from [get_cells -quiet -hier *address_reg* -filter {name =~ *i_addr_gen* && IS_SEQUENTIAL}] \ -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] +set_false_path -quiet \ + -from [get_cells -quiet -hier *reset_sync_reg* -filter {name =~ *i_reset_manager* && IS_SEQUENTIAL}] \ + -to [get_cells -quiet -hier *up_rdata_reg* -filter {IS_SEQUENTIAL}] <: } :> diff --git a/library/axi_dmac/axi_dmac_hw.tcl b/library/axi_dmac/axi_dmac_hw.tcl index e47bd33cfe..15665f5fba 100644 --- a/library/axi_dmac/axi_dmac_hw.tcl +++ b/library/axi_dmac/axi_dmac_hw.tcl @@ -28,6 +28,7 @@ ad_ip_files axi_dmac [list \ resp.h \ axi_dmac_regmap.v \ axi_dmac_regmap_request.v \ + axi_dmac_reset_manager.v \ axi_dmac_transfer.v \ address_generator.v \ data_mover.v \ diff --git a/library/axi_dmac/axi_dmac_ip.tcl b/library/axi_dmac/axi_dmac_ip.tcl index a23ca9a587..04e7b1cc09 100644 --- a/library/axi_dmac/axi_dmac_ip.tcl +++ b/library/axi_dmac/axi_dmac_ip.tcl @@ -10,6 +10,7 @@ adi_ip_files axi_dmac [list \ "resp.h" \ "axi_dmac_regmap.v" \ "axi_dmac_regmap_request.v" \ + "axi_dmac_reset_manager.v" \ "axi_dmac_transfer.v" \ "address_generator.v" \ "data_mover.v" \ diff --git a/library/axi_dmac/axi_dmac_regmap.v b/library/axi_dmac/axi_dmac_regmap.v index d8ac2e177c..17237abbf7 100644 --- a/library/axi_dmac/axi_dmac_regmap.v +++ b/library/axi_dmac/axi_dmac_regmap.v @@ -98,7 +98,7 @@ module axi_dmac_regmap #( // Debug interface input [DMA_AXI_ADDR_WIDTH-1:0] dbg_src_addr, input [DMA_AXI_ADDR_WIDTH-1:0] dbg_dest_addr, - input [7:0] dbg_status, + input [11:0] dbg_status, input [31:0] dbg_ids0, input [31:0] dbg_ids1 ); diff --git a/library/axi_dmac/axi_dmac_reset_manager.v b/library/axi_dmac/axi_dmac_reset_manager.v new file mode 100644 index 0000000000..5f75b73491 --- /dev/null +++ b/library/axi_dmac/axi_dmac_reset_manager.v @@ -0,0 +1,302 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +module axi_dmac_reset_manager #( + parameter ASYNC_CLK_REQ_SRC = 1, + parameter ASYNC_CLK_SRC_DEST = 1, + parameter ASYNC_CLK_DEST_REQ = 1 +) ( + input clk, + input resetn, + + input ctrl_enable, + input ctrl_pause, + + output req_resetn, + output req_enable, + input req_enabled, + + input dest_clk, + input dest_ext_resetn, + output dest_resetn, + output dest_enable, + input dest_enabled, + + input src_clk, + input src_ext_resetn, + output src_resetn, + output src_enable, + input src_enabled, + + output [11:0] dbg_status +); + +/* + * TODO: + * If an external reset is asserted for a domain that domain will go into reset + * immediately. If a transfer is currently active the transfer will be aborted + * and other domains will be shutdown gracefully. The reset manager will stay in + * the shutdown state until all external resets have been de-asserted. + */ + +localparam STATE_DO_RESET = 3'h0; +localparam STATE_RESET = 3'h1; +localparam STATE_DISABLED = 3'h2; +localparam STATE_STARTUP = 3'h3; +localparam STATE_ENABLED = 3'h4; +localparam STATE_SHUTDOWN = 3'h5; + +reg [2:0] state = 3'b000; +reg needs_reset = 1'b0; +reg do_reset = 1'b0; +reg do_enable = 1'b0; + +wire enabled_dest; +wire enabled_src; + +wire enabled_all; +wire disabled_all; + +assign enabled_all = req_enabled & enabled_src & enabled_dest; +assign disabled_all = ~(req_enabled | enabled_src | enabled_dest); + +assign req_enable = do_enable; + +assign dbg_status = {needs_reset,req_resetn,src_resetn,dest_resetn,1'b0,req_enabled,enabled_src,enabled_dest,1'b0,state}; + +always @(posedge clk) begin + if (state == STATE_DO_RESET) begin + do_reset <= 1'b1; + end else begin + do_reset <= 1'b0; + end +end + +always @(posedge clk) begin + if (state == STATE_STARTUP || state == STATE_ENABLED) begin + do_enable <= 1'b1; + end else begin + do_enable <= 1'b0; + end +end + +/* + * If ctrl_enable goes from 1 to 0 a shutdown procedure is initiated. During the + * shutdown procedure all domains are signaled that a shutdown should occur. The + * domains will then complete any active transactions that are required to + * complete according to the interface semantics. Once a domain has completed + * its transactions it will indicate that it has been shutdown. Once all domains + * indicate that they have been disabled a reset pulse will be generated to all + * domains to clear all residual state. The reset pulse is long enough so that it + * is active in all domains for at least 4 clock cycles. + * + * Once the reset signal is de-asserted the DMA is in an idle state and can be + * enabled again. If the DMA receives a enable while it is performing a shutdown + * sequence it will only be re-enabled once the shutdown sequence has + * successfully completed. + * + * If ctrl_pause is asserted all domains will be disabled. But there will be no + * reset, so when the ctrl_pause signal is de-asserted again the DMA will resume + * with its previous state. + * + */ + +/* + * If ctrl_enable goes low, even for a single clock cycle, we want to go through + * a full reset sequence. This might happen when the state machine is busy, e.g. + * going through a startup sequence. To avoid missing the event store it for + * later. + */ +always @(posedge clk) begin + if (state == STATE_RESET) begin + needs_reset <= 1'b0; + end else if (ctrl_enable == 1'b0) begin + needs_reset <= 1'b1; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + state <= STATE_DO_RESET; + end else begin + case (state) + STATE_DO_RESET: begin + state <= STATE_RESET; + end + STATE_RESET: begin + /* + * Wait for the reset sequence to complete. Stay in this state when + * ctrl_enable == 1'b0, otherwise we'd go through the reset sequence + * again and again. + */ + if (ctrl_enable == 1'b1 && req_resetn == 1'b1) begin + state <= STATE_DISABLED; + end + end + STATE_DISABLED: begin + if (needs_reset == 1'b1) begin + state <= STATE_DO_RESET; + end else if (ctrl_pause == 1'b0) begin + state <= STATE_STARTUP; + end + end + STATE_STARTUP: begin + /* Wait for all domains to be ready */ + if (enabled_all == 1'b1) begin + state <= STATE_ENABLED; + end + end + STATE_ENABLED: begin + if (needs_reset == 1'b1 || ctrl_pause == 1'b1) begin + state <= STATE_SHUTDOWN; + end + end + STATE_SHUTDOWN: begin + /* Wait for all domains to complete outstanding transactions */ + if (disabled_all == 1'b1) begin + state <= STATE_DISABLED; + end + end + endcase + end +end + +/* + * Chain the reset through all clock domains. This makes sure that is asserted + * for at least 4 clock cycles of the slowest domain, no matter what. If + * successive domains have the same clock they'll share their reset signal. + */ + +wire [3:0] reset_async_chain; +wire [3:0] reset_sync_chain; +wire [2:0] reset_chain_clks = {clk, src_clk, dest_clk}; + +localparam GEN_ASYNC_RESET = { + ASYNC_CLK_REQ_SRC ? 1'b1 : 1'b0, + ASYNC_CLK_SRC_DEST ? 1'b1 : 1'b0, + 1'b1 +}; + +assign reset_async_chain[0] = 1'b0; +assign reset_sync_chain[0] = reset_async_chain[3]; + +generate +genvar i; + +for (i = 0; i < 3; i = i + 1) begin: reset_gen + + if (GEN_ASYNC_RESET[i] == 1'b1) begin + + reg [3:0] reset_async = 4'b1111; + reg [1:0] reset_sync = 2'b11; + reg reset_sync_in = 1'b1; + + always @(posedge reset_chain_clks[i] or posedge reset_sync_chain[i]) begin + if (reset_sync_chain[i] == 1'b1) begin + reset_sync_in <= 1'b1; + end else begin + reset_sync_in <= reset_async[0]; + end + end + + always @(posedge reset_chain_clks[i] or posedge do_reset) begin + if (do_reset == 1'b1) begin + reset_async <= 4'b1111; + end else begin + reset_async <= {reset_async_chain[i], reset_async[3:1]}; + end + end + + always @(posedge reset_chain_clks[i]) begin + reset_sync <= {reset_sync_in,reset_sync[1]}; + end + + assign reset_async_chain[i+1] = reset_async[0]; + assign reset_sync_chain[i+1] = reset_sync[0]; + + end else begin + assign reset_async_chain[i+1] = reset_async_chain[i]; + assign reset_sync_chain[i+1] = reset_sync_chain[i]; + end +end + +endgenerate + +/* De-assertions in the opposite direction of the data flow: dest, src, request */ +assign dest_resetn = ~reset_sync_chain[1]; +assign src_resetn = ~reset_sync_chain[2]; +assign req_resetn = ~reset_sync_chain[3]; + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_DEST_REQ) +) i_sync_control_dest ( + .out_clk (dest_clk), + .out_resetn (1'b1), + .in (do_enable), + .out (dest_enable) +); + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_DEST_REQ) +) i_sync_status_dest ( + .out_clk (clk), + .out_resetn (1'b1), + .in (dest_enabled), + .out (enabled_dest) +); + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_REQ_SRC) +) i_sync_control_src ( + .out_clk (src_clk), + .out_resetn (1'b1), + .in (do_enable), + .out (src_enable) +); + +sync_bits #( + .NUM_OF_BITS (1), + .ASYNC_CLK (ASYNC_CLK_REQ_SRC) +) i_sync_status_src ( + .out_clk (clk), + .out_resetn (1'b1), + .in (src_enabled), + .out (enabled_src) +); + +endmodule diff --git a/library/axi_dmac/axi_dmac_transfer.v b/library/axi_dmac/axi_dmac_transfer.v index ad6c88cd89..851abe2912 100644 --- a/library/axi_dmac/axi_dmac_transfer.v +++ b/library/axi_dmac/axi_dmac_transfer.v @@ -54,8 +54,11 @@ module axi_dmac_transfer #( parameter AXI_LENGTH_WIDTH_SRC = 8, parameter AXI_LENGTH_WIDTH_DEST = 8 ) ( - input req_clk, - input req_resetn, + input ctrl_clk, + input ctrl_resetn, + + input ctrl_enable, + input ctrl_pause, input req_valid, output req_ready, @@ -71,9 +74,6 @@ module axi_dmac_transfer #( output req_eot, - input enable, - input pause, - // Master AXI interface input m_dest_axi_aclk, input m_dest_axi_aresetn, @@ -124,6 +124,7 @@ module axi_dmac_transfer #( input s_axis_valid, input [DMA_DATA_WIDTH_SRC-1:0] s_axis_data, input [0:0] s_axis_user, + input s_axis_last, output s_axis_xfer_req, // Master streaming AXI interface @@ -158,7 +159,7 @@ module axi_dmac_transfer #( output [ID_WIDTH-1:0] dbg_src_address_id, output [ID_WIDTH-1:0] dbg_src_data_id, output [ID_WIDTH-1:0] dbg_src_response_id, - output [7:0] dbg_status + output [11:0] dbg_status ); wire dma_req_valid; @@ -170,6 +171,65 @@ wire dma_req_eot; wire dma_req_sync_transfer_start; wire dma_req_last; +wire req_clk = ctrl_clk; +wire req_resetn; + +wire req_enable; + +wire dest_clk; +wire dest_ext_resetn; +wire dest_resetn; +wire dest_enable; +wire dest_enabled; + +wire src_clk; +wire src_ext_resetn; +wire src_resetn; +wire src_enable; +wire src_enabled; + +wire req_valid_gated; +wire req_ready_gated; + +axi_dmac_reset_manager #( + .ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC), + .ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST), + .ASYNC_CLK_DEST_REQ (ASYNC_CLK_DEST_REQ) +) i_reset_manager ( + .clk (ctrl_clk), + .resetn (ctrl_resetn), + + .ctrl_enable (ctrl_enable), + .ctrl_pause (ctrl_pause), + + .req_resetn (req_resetn), + .req_enable (req_enable), + .req_enabled (req_enable), + + .dest_clk (dest_clk), + .dest_ext_resetn (dest_ext_resetn), + .dest_resetn (dest_resetn), + .dest_enable (dest_enable), + .dest_enabled (dest_enabled), + + .src_clk (src_clk), + .src_ext_resetn (src_ext_resetn), + .src_resetn (src_resetn), + .src_enable (src_enable), + .src_enabled (src_enabled), + + .dbg_status (dbg_status) +); + +/* + * Things become a lot easier if we gate incoming requests in a central place + * before they are propagated downstream. Otherwise we'd need to take special + * care to not accidentally accept requests while the DMA is going through a + * shutdown and reset phase. + */ +assign req_valid_gated = req_enable & req_valid; +assign req_ready = req_enable & req_ready_gated; + generate if (DMA_2D_TRANSFER == 1) begin dmac_2d_transfer #( @@ -182,8 +242,8 @@ dmac_2d_transfer #( .req_eot (req_eot), - .req_valid (req_valid), - .req_ready (req_ready), + .req_valid (req_valid_gated), + .req_ready (req_ready_gated), .req_dest_address (req_dest_address), .req_src_address (req_src_address), .req_x_length (req_x_length), @@ -205,13 +265,17 @@ assign dma_req_last = 1'b0; end else begin -assign dma_req_valid = req_valid; -assign req_ready = dma_req_ready; +/* Request */ +assign dma_req_valid = req_valid_gated; +assign req_ready_gated = dma_req_ready; + assign dma_req_dest_address = req_dest_address; assign dma_req_src_address = req_src_address; assign dma_req_length = req_x_length; assign dma_req_sync_transfer_start = req_sync_transfer_start; assign dma_req_last = req_last; + +/* Response */ assign req_eot = dma_req_eot; end endgenerate @@ -236,11 +300,8 @@ dmac_request_arb #( .AXI_LENGTH_WIDTH_DEST (AXI_LENGTH_WIDTH_DEST), .AXI_LENGTH_WIDTH_SRC (AXI_LENGTH_WIDTH_SRC) ) i_request_arb ( - .req_aclk (req_clk), - .req_aresetn (req_resetn), - - .enable (enable), - .pause (pause), + .req_clk (req_clk), + .req_resetn (req_resetn), .req_valid (dma_req_valid), .req_ready (dma_req_ready), @@ -252,32 +313,46 @@ dmac_request_arb #( .eot (dma_req_eot), + .req_enable (req_enable), + + .dest_clk (dest_clk), + .dest_ext_resetn (dest_ext_resetn), + .dest_resetn (dest_resetn), + .dest_enable (dest_enable), + .dest_enabled (dest_enabled), + + .src_clk (src_clk), + .src_ext_resetn (src_ext_resetn), + .src_resetn (src_resetn), + .src_enable (src_enable), + .src_enabled (src_enabled), + .m_dest_axi_aclk (m_dest_axi_aclk), .m_dest_axi_aresetn (m_dest_axi_aresetn), .m_src_axi_aclk (m_src_axi_aclk), .m_src_axi_aresetn (m_src_axi_aresetn), + .m_axi_awvalid (m_axi_awvalid), + .m_axi_awready (m_axi_awready), .m_axi_awaddr (m_axi_awaddr), .m_axi_awlen (m_axi_awlen), .m_axi_awsize (m_axi_awsize), .m_axi_awburst (m_axi_awburst), .m_axi_awprot (m_axi_awprot), .m_axi_awcache (m_axi_awcache), - .m_axi_awvalid (m_axi_awvalid), - .m_axi_awready (m_axi_awready), + .m_axi_wvalid (m_axi_wvalid), + .m_axi_wready (m_axi_wready), .m_axi_wdata (m_axi_wdata), .m_axi_wstrb (m_axi_wstrb), - .m_axi_wready (m_axi_wready), - .m_axi_wvalid (m_axi_wvalid), .m_axi_wlast (m_axi_wlast), .m_axi_bvalid (m_axi_bvalid), - .m_axi_bresp (m_axi_bresp), .m_axi_bready (m_axi_bready), + .m_axi_bresp (m_axi_bresp), - .m_axi_arready (m_axi_arready), .m_axi_arvalid (m_axi_arvalid), + .m_axi_arready (m_axi_arready), .m_axi_araddr (m_axi_araddr), .m_axi_arlen (m_axi_arlen), .m_axi_arsize (m_axi_arsize), @@ -285,9 +360,9 @@ dmac_request_arb #( .m_axi_arprot (m_axi_arprot), .m_axi_arcache (m_axi_arcache), - .m_axi_rdata (m_axi_rdata), .m_axi_rready (m_axi_rready), .m_axi_rvalid (m_axi_rvalid), + .m_axi_rdata (m_axi_rdata), .m_axi_rresp (m_axi_rresp), .s_axis_aclk (s_axis_aclk), @@ -295,6 +370,7 @@ dmac_request_arb #( .s_axis_valid (s_axis_valid), .s_axis_data (s_axis_data), .s_axis_user (s_axis_user), + .s_axis_last (s_axis_last), .s_axis_xfer_req (s_axis_xfer_req), .m_axis_aclk (m_axis_aclk), @@ -325,8 +401,7 @@ dmac_request_arb #( .dbg_src_request_id (dbg_src_request_id), .dbg_src_address_id (dbg_src_address_id), .dbg_src_data_id (dbg_src_data_id), - .dbg_src_response_id (dbg_src_response_id), - .dbg_status (dbg_status) + .dbg_src_response_id (dbg_src_response_id) ); endmodule diff --git a/library/axi_dmac/data_mover.v b/library/axi_dmac/data_mover.v index fb058ddab4..296628e656 100644 --- a/library/axi_dmac/data_mover.v +++ b/library/axi_dmac/data_mover.v @@ -46,7 +46,6 @@ module dmac_data_mover #( input [ID_WIDTH-1:0] request_id, output [ID_WIDTH-1:0] response_id, - input sync_id, input eot, input enable, @@ -141,19 +140,18 @@ always @(posedge clk) begin end always @(posedge clk) begin - if (enabled == 1'b0 || resetn == 1'b0) begin + if (resetn == 1'b0) begin active <= 1'b0; - end else if (req_valid) begin + end else if (req_valid == 1'b1) begin active <= 1'b1; - end else if (last_load) begin + end else if (last_load == 1'b1) begin active <= 1'b0; end end always @(*) begin - if ((s_axi_ready && s_axi_valid && last) || - (sync_id && pending_burst)) + if (s_axi_ready == 1'b1 && s_axi_valid == 1'b1 && last == 1'b1) id_next <= inc_id(id); else id_next <= id; diff --git a/library/axi_dmac/dest_axi_mm.v b/library/axi_dmac/dest_axi_mm.v index bed45ecb5a..08de9e6d65 100644 --- a/library/axi_dmac/dest_axi_mm.v +++ b/library/axi_dmac/dest_axi_mm.v @@ -52,8 +52,6 @@ module dmac_dest_mm_axi #( input enable, output enabled, - input sync_id, - output sync_id_ret, output response_valid, input response_ready, @@ -103,10 +101,6 @@ wire data_req_ready; wire address_enabled; wire data_enabled; -assign sync_id_ret = sync_id; - -wire _fifo_ready; -assign fifo_ready = _fifo_ready | ~enabled; splitter #( .NUM_M(2) @@ -141,7 +135,6 @@ dmac_address_generator #( .id(address_id), .request_id(request_id), - .sync_id(sync_id), .req_valid(address_req_valid), .req_ready(address_req_ready), @@ -175,7 +168,6 @@ dmac_data_mover # ( .request_id(address_id), .response_id(data_id), - .sync_id(sync_id), .eot(data_eot), .req_valid(data_req_valid), @@ -183,7 +175,7 @@ dmac_data_mover # ( .req_last_burst_length(req_last_burst_length), .s_axi_valid(fifo_valid), - .s_axi_ready(_fifo_ready), + .s_axi_ready(fifo_ready), .s_axi_data(fifo_data), .m_axi_valid(m_axi_wvalid), .m_axi_ready(m_axi_wready), @@ -207,7 +199,6 @@ dmac_response_handler #( .id(response_id), .request_id(data_id), - .sync_id(sync_id), .eot(response_eot), diff --git a/library/axi_dmac/dest_axi_stream.v b/library/axi_dmac/dest_axi_stream.v index 3157fafba0..0cf38053a9 100644 --- a/library/axi_dmac/dest_axi_stream.v +++ b/library/axi_dmac/dest_axi_stream.v @@ -44,8 +44,6 @@ module dmac_dest_axi_stream #( input enable, output enabled, - input sync_id, - output sync_id_ret, output xfer_req, input [ID_WIDTH-1:0] request_id, @@ -77,9 +75,7 @@ module dmac_dest_axi_stream #( reg req_xlast_d = 1'b0; -assign sync_id_ret = sync_id; wire data_enabled; -wire _fifo_ready; wire m_axis_last_s; always @(posedge s_axis_aclk) begin @@ -102,7 +98,6 @@ dmac_data_mover # ( .enable(enable), .enabled(data_enabled), - .sync_id(sync_id), .xfer_req(xfer_req), .request_id(request_id), @@ -117,7 +112,7 @@ dmac_data_mover # ( .m_axi_valid(m_axis_valid), .m_axi_data(m_axis_data), .m_axi_last(m_axis_last_s), - .s_axi_ready(_fifo_ready), + .s_axi_ready(fifo_ready), .s_axi_valid(fifo_valid), .s_axi_data(fifo_data) ); @@ -130,7 +125,6 @@ dmac_response_generator # ( .enable(data_enabled), .enabled(enabled), - .sync_id(sync_id), .request_id(data_id), .response_id(response_id), @@ -143,6 +137,4 @@ dmac_response_generator # ( .resp_resp(response_resp) ); -assign fifo_ready = _fifo_ready | ~enabled; - endmodule diff --git a/library/axi_dmac/dest_fifo_inf.v b/library/axi_dmac/dest_fifo_inf.v index cfb6ffafcb..ed6e4b91ba 100644 --- a/library/axi_dmac/dest_fifo_inf.v +++ b/library/axi_dmac/dest_fifo_inf.v @@ -44,8 +44,6 @@ module dmac_dest_fifo_inf #( input enable, output enabled, - input sync_id, - output sync_id_ret, input [ID_WIDTH-1:0] request_id, output [ID_WIDTH-1:0] response_id, @@ -74,12 +72,8 @@ module dmac_dest_fifo_inf #( output [1:0] response_resp ); -assign sync_id_ret = sync_id; wire data_enabled; -wire _fifo_ready; -assign fifo_ready = _fifo_ready | ~enabled; - wire [DATA_WIDTH-1:0] dout_s; wire data_ready; wire data_valid; @@ -97,7 +91,6 @@ dmac_data_mover # ( .enable(enable), .enabled(data_enabled), - .sync_id(sync_id), .xfer_req(xfer_req), .request_id(request_id), @@ -108,7 +101,7 @@ dmac_data_mover # ( .req_ready(req_ready), .req_last_burst_length(req_last_burst_length), - .s_axi_ready(_fifo_ready), + .s_axi_ready(fifo_ready), .s_axi_valid(fifo_valid), .s_axi_data(fifo_data), .m_axi_ready(data_ready), @@ -136,7 +129,6 @@ dmac_response_generator # ( .enable(data_enabled), .enabled(enabled), - .sync_id(sync_id), .request_id(data_id), .response_id(response_id), diff --git a/library/axi_dmac/request_arb.v b/library/axi_dmac/request_arb.v index 4cf1763209..029db8e94f 100644 --- a/library/axi_dmac/request_arb.v +++ b/library/axi_dmac/request_arb.v @@ -34,7 +34,6 @@ // *************************************************************************** module dmac_request_arb #( - parameter DMA_DATA_WIDTH_SRC = 64, parameter DMA_DATA_WIDTH_DEST = 64, parameter DMA_LENGTH_WIDTH = 24, @@ -54,8 +53,8 @@ module dmac_request_arb #( parameter AXI_LENGTH_WIDTH_SRC = 8, parameter AXI_LENGTH_WIDTH_DEST = 8)( - input req_aclk, - input req_aresetn, + input req_clk, + input req_resetn, input req_valid, output req_ready, @@ -67,9 +66,6 @@ module dmac_request_arb #( output reg eot, - input enable, - input pause, - // Master AXI interface input m_dest_axi_aclk, input m_dest_axi_aresetn, @@ -155,7 +151,20 @@ module dmac_request_arb #( output [ID_WIDTH-1:0] dbg_src_address_id, output [ID_WIDTH-1:0] dbg_src_data_id, output [ID_WIDTH-1:0] dbg_src_response_id, - output [7:0] dbg_status + + input req_enable, + + output dest_clk, + input dest_resetn, + output dest_ext_resetn, + input dest_enable, + output dest_enabled, + + output src_clk, + input src_resetn, + output src_ext_resetn, + input src_enable, + output src_enabled ); localparam DMA_TYPE_MM_AXI = 0; @@ -197,30 +206,14 @@ wire [ID_WIDTH-1:0] response_id; wire enabled_src; wire enabled_dest; -wire sync_id; -wire sync_id_ret_dest; -wire sync_id_ret_src; - -wire dest_enable; -wire dest_enabled; -wire dest_sync_id; -wire dest_sync_id_ret; -wire src_enable; -wire src_enabled; -wire src_sync_id; -wire src_sync_id_ret; wire req_gen_valid; wire req_gen_ready; wire req_dest_valid; wire req_dest_ready; -wire req_dest_empty; wire req_src_valid; wire req_src_ready; -wire req_src_empty; -wire dest_clk; -wire dest_resetn; wire dest_req_valid; wire dest_req_ready; wire [DMA_ADDRESS_WIDTH_DEST-1:0] dest_req_address; @@ -246,8 +239,6 @@ wire dest_fifo_valid; wire dest_fifo_ready; wire [DMA_DATA_WIDTH-1:0] dest_fifo_data; -wire src_clk; -wire src_resetn; wire src_req_valid; wire src_req_ready; wire [DMA_ADDRESS_WIDTH_SRC-1:0] src_req_address; @@ -274,9 +265,6 @@ wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data; wire src_fifo_repacked_valid; wire src_fifo_repacked_ready; wire [DMA_DATA_WIDTH-1:0] src_fifo_repacked_data; -wire src_fifo_empty; - -wire fifo_empty; wire response_dest_valid; wire response_dest_ready = 1'b1; @@ -294,109 +282,24 @@ assign dbg_dest_response_id = dest_response_id; assign dbg_src_request_id = src_request_id; assign dbg_src_response_id = src_response_id; -assign sync_id = ~enabled_dest && ~enabled_src && request_id != response_id; - -reg enabled; -reg do_enable; - -// Enable src and dest if we are in sync -always @(posedge req_aclk) -begin - if (req_aresetn == 1'b0) begin - do_enable <= 1'b0; - end else begin - if (enable) begin - // First make sure we are fully disabled - if (~sync_id_ret_dest && ~sync_id_ret_src && - response_id == request_id && ~enabled_dest && ~enabled_src && - req_dest_empty && req_src_empty && fifo_empty) - do_enable <= 1'b1; - end else begin - do_enable <= 1'b0; - end - end -end - -// Flag enabled once both src and dest are enabled -always @(posedge req_aclk) -begin - if (req_aresetn == 1'b0) begin - enabled <= 1'b0; - end else begin - if (do_enable == 1'b0) - enabled <= 1'b0; - else if (enabled_dest && enabled_src) - enabled <= 1'b1; - end -end - -assign dbg_status = {do_enable, enabled, enabled_dest, enabled_src, fifo_empty, - sync_id, sync_id_ret_dest, sync_id_ret_src}; - -always @(posedge req_aclk) +always @(posedge req_clk) begin eot_mem[request_id] <= request_eot; end -always @(posedge req_aclk) +always @(posedge req_clk) begin - if (req_aresetn == 1'b0) begin + if (req_resetn == 1'b0) begin eot <= 1'b0; end else begin eot <= response_dest_valid & response_dest_ready & response_dest_resp_eot; end end -generate if (ASYNC_CLK_REQ_SRC) begin - -wire src_async_resetn_source; - -if (DMA_TYPE_SRC == DMA_TYPE_MM_AXI) begin -assign src_async_resetn_source = m_src_axi_aresetn; -end else begin -assign src_async_resetn_source = req_aresetn; -end - -reg [2:0] src_reset_shift = 3'b111; -assign src_resetn = ~src_reset_shift[2]; - -always @(negedge src_async_resetn_source or posedge src_clk) begin - if (src_async_resetn_source == 1'b0) - src_reset_shift <= 3'b111; - else - src_reset_shift <= {src_reset_shift[1:0], 1'b0}; -end - -end else begin -assign src_resetn = req_aresetn; -end endgenerate - -generate if (ASYNC_CLK_DEST_REQ) begin -wire dest_async_resetn_source; - -if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin -assign dest_async_resetn_source = m_dest_axi_aresetn; -end else begin -assign dest_async_resetn_source = req_aresetn; -end - -reg [2:0] dest_reset_shift = 3'b111; -assign dest_resetn = ~dest_reset_shift[2]; - -always @(negedge dest_async_resetn_source or posedge dest_clk) begin - if (dest_async_resetn_source == 1'b0) - dest_reset_shift <= 3'b111; - else - dest_reset_shift <= {dest_reset_shift[1:0], 1'b0}; -end - -end else begin -assign dest_resetn = req_aresetn; -end endgenerate - generate if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin assign dest_clk = m_dest_axi_aclk; +assign dest_ext_resetn = m_dest_axi_aresetn; wire [ID_WIDTH-1:0] dest_data_id; wire [ID_WIDTH-1:0] dest_address_id; @@ -433,8 +336,6 @@ dmac_dest_mm_axi #( .request_id(dest_request_id), .response_id(dest_response_id), - .sync_id(dest_sync_id), - .sync_id_ret(dest_sync_id_ret), .data_id(dest_data_id), .address_id(dest_address_id), @@ -488,6 +389,7 @@ end if (DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin assign dest_clk = m_axis_aclk; +assign dest_ext_resetn = 1'b1; wire [ID_WIDTH-1:0] data_id; @@ -521,8 +423,6 @@ dmac_dest_axi_stream #( .request_id(dest_request_id), .response_id(dest_response_id), .data_id(data_id), - .sync_id(dest_sync_id), - .sync_id_ret(dest_sync_id_ret), .xfer_req(m_axis_xfer_req), .data_eot(data_eot), @@ -550,6 +450,7 @@ end if (DMA_TYPE_DEST == DMA_TYPE_FIFO) begin assign dest_clk = fifo_rd_clk; +assign dest_ext_resetn = 1'b1; wire [ID_WIDTH-1:0] data_id; @@ -582,8 +483,6 @@ dmac_dest_fifo_inf #( .request_id(dest_request_id), .response_id(dest_response_id), .data_id(data_id), - .sync_id(dest_sync_id), - .sync_id_ret(dest_sync_id_ret), .data_eot(data_eot), .response_eot(response_eot), @@ -611,6 +510,7 @@ end endgenerate generate if (DMA_TYPE_SRC == DMA_TYPE_MM_AXI) begin assign src_clk = m_src_axi_aclk; +assign src_ext_resetn = m_src_axi_aresetn; wire [ID_WIDTH-1:0] src_data_id; wire [ID_WIDTH-1:0] src_address_id; @@ -633,8 +533,6 @@ dmac_src_mm_axi #( .enable(src_enable), .enabled(src_enabled), - .sync_id(src_sync_id), - .sync_id_ret(src_sync_id_ret), .req_valid(src_req_valid), .req_ready(src_req_ready), @@ -690,6 +588,7 @@ end if (DMA_TYPE_SRC == DMA_TYPE_STREAM_AXI) begin assign src_clk = s_axis_aclk; +assign src_ext_resetn = 1'b1; wire src_eot = eot_mem[src_response_id]; @@ -711,8 +610,6 @@ dmac_src_axi_stream #( .enable(src_enable), .enabled(src_enabled), - .sync_id(src_sync_id), - .sync_id_ret(src_sync_id_ret), .req_valid(src_req_valid), .req_ready(src_req_ready), @@ -747,6 +644,7 @@ end if (DMA_TYPE_SRC == DMA_TYPE_FIFO) begin assign src_clk = fifo_wr_clk; +assign src_ext_resetn = 1'b1; wire src_eot = eot_mem[src_response_id]; @@ -768,8 +666,6 @@ dmac_src_fifo_inf #( .enable(src_enable), .enabled(src_enabled), - .sync_id(src_sync_id), - .sync_id_ret(src_sync_id_ret), .req_valid(src_req_valid), .req_ready(src_req_ready), @@ -804,7 +700,7 @@ sync_bits #( .ASYNC_CLK(ASYNC_CLK_REQ_SRC) ) i_sync_src_request_id ( .out_clk(src_clk), - .out_resetn(src_resetn), + .out_resetn(1'b1), .in(request_id), .out(src_request_id) ); @@ -814,7 +710,7 @@ sync_bits #( .ASYNC_CLK(ASYNC_CLK_SRC_DEST) ) i_sync_dest_request_id ( .out_clk(dest_clk), - .out_resetn(dest_resetn), + .out_resetn(1'b1), .in(src_response_id), .out(dest_request_id) ); @@ -823,8 +719,8 @@ sync_bits #( .NUM_OF_BITS(ID_WIDTH), .ASYNC_CLK(ASYNC_CLK_DEST_REQ) ) i_sync_req_response_id ( - .out_clk(req_aclk), - .out_resetn(req_aresetn), + .out_clk(req_clk), + .out_resetn(1'b1), .in(dest_response_id), .out(response_id) ); @@ -849,7 +745,7 @@ util_axis_resize #( .MASTER_DATA_WIDTH(DMA_DATA_WIDTH) ) i_src_repack ( .clk(src_clk), - .resetn(src_resetn & ~src_sync_id), + .resetn(src_resetn), .s_valid(src_fifo_valid), .s_ready(src_fifo_ready), .s_data(src_fifo_data), @@ -868,7 +764,7 @@ util_axis_fifo #( .s_axis_valid(src_fifo_repacked_valid), .s_axis_ready(src_fifo_repacked_ready), .s_axis_data(src_fifo_repacked_data), - .s_axis_empty(src_fifo_empty), + .s_axis_empty(), .s_axis_room(), .m_axis_aclk(dest_clk), @@ -884,7 +780,7 @@ util_axis_resize #( .MASTER_DATA_WIDTH(DMA_DATA_WIDTH_DEST) ) i_dest_repack ( .clk(dest_clk), - .resetn(dest_resetn & ~dest_sync_id), + .resetn(dest_resetn), .s_valid(dest_fifo_valid), .s_ready(dest_fifo_ready), .s_data(dest_fifo_data), @@ -926,33 +822,13 @@ axi_register_slice #( .m_axi_data(dest_data) ); - -// We do not accept any requests until all components are enabled -reg _req_valid = 1'b0; -wire _req_ready; - -always @(posedge req_aclk) -begin - if (req_aresetn == 1'b0) begin - _req_valid <= 1'b0; - end else begin - if (_req_valid == 1'b1 && _req_ready == 1'b1) begin - _req_valid <= 1'b0; - end else if (req_valid == 1'b1 && enabled == 1'b1) begin - _req_valid <= 1'b1; - end - end -end - -assign req_ready = _req_ready & _req_valid & enable; - splitter #( .NUM_M(3) ) i_req_splitter ( - .clk(req_aclk), - .resetn(req_aresetn), - .s_valid(_req_valid), - .s_ready(_req_ready), + .clk(req_clk), + .resetn(req_resetn), + .s_valid(req_valid), + .s_ready(req_ready), .m_valid({ req_gen_valid, req_dest_valid, @@ -970,11 +846,11 @@ util_axis_fifo #( .ADDRESS_WIDTH(0), .ASYNC_CLK(ASYNC_CLK_DEST_REQ) ) i_dest_req_fifo ( - .s_axis_aclk(req_aclk), - .s_axis_aresetn(req_aresetn), + .s_axis_aclk(req_clk), + .s_axis_aresetn(req_resetn), .s_axis_valid(req_dest_valid), .s_axis_ready(req_dest_ready), - .s_axis_empty(req_dest_empty), + .s_axis_empty(), .s_axis_data({ req_dest_address, req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST], @@ -999,11 +875,11 @@ util_axis_fifo #( .ADDRESS_WIDTH(0), .ASYNC_CLK(ASYNC_CLK_REQ_SRC) ) i_src_req_fifo ( - .s_axis_aclk(req_aclk), - .s_axis_aresetn(req_aresetn), + .s_axis_aclk(req_clk), + .s_axis_aresetn(req_resetn), .s_axis_valid(req_src_valid), .s_axis_ready(req_src_ready), - .s_axis_empty(req_src_empty), + .s_axis_empty(), .s_axis_data({ req_src_address, req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC], @@ -1038,8 +914,8 @@ util_axis_fifo #( .s_axis_data(dest_response_resp_eot), .s_axis_room(), - .m_axis_aclk(req_aclk), - .m_axis_aresetn(req_aresetn), + .m_axis_aclk(req_clk), + .m_axis_aresetn(req_resetn), .m_axis_valid(response_dest_valid), .m_axis_ready(response_dest_ready), .m_axis_data(response_dest_resp_eot), @@ -1058,8 +934,8 @@ util_axis_fifo #( .s_axis_ready(src_response_ready), .s_axis_empty(src_response_empty), .s_axis_data(src_response_resp), - .m_axis_aclk(req_aclk), - .m_axis_aresetn(req_aresetn), + .m_axis_aclk(req_clk), + .m_axis_aresetn(req_resetn), .m_axis_valid(response_src_valid), .m_axis_ready(response_src_ready), .m_axis_data(response_src_resp) @@ -1072,8 +948,8 @@ dmac_request_generator #( .ID_WIDTH(ID_WIDTH), .BURSTS_PER_TRANSFER_WIDTH(BURSTS_PER_TRANSFER_WIDTH) ) i_req_gen ( - .req_aclk(req_aclk), - .req_aresetn(req_aresetn), + .clk(req_clk), + .resetn(req_resetn), .request_id(request_id), .response_id(response_id), @@ -1082,50 +958,9 @@ dmac_request_generator #( .req_ready(req_gen_ready), .req_burst_count(req_length[DMA_LENGTH_WIDTH-1:BYTES_PER_BURST_WIDTH]), - .enable(do_enable), - .pause(pause), + .enable(req_enable), .eot(request_eot) ); -sync_bits #( - .NUM_OF_BITS(2), - .ASYNC_CLK(ASYNC_CLK_DEST_REQ) -) i_sync_control_dest ( - .out_clk(dest_clk), - .out_resetn(dest_resetn), - .in({do_enable, sync_id}), - .out({dest_enable, dest_sync_id}) -); - -sync_bits #( - .NUM_OF_BITS(2), - .ASYNC_CLK(ASYNC_CLK_DEST_REQ) -) i_sync_status_dest ( - .out_clk(req_aclk), - .out_resetn(req_aresetn), - .in({dest_enabled | ~dest_response_empty, dest_sync_id_ret}), - .out({enabled_dest, sync_id_ret_dest}) -); - -sync_bits #( - .NUM_OF_BITS(2), - .ASYNC_CLK(ASYNC_CLK_REQ_SRC) -) i_sync_control_src ( - .out_clk(src_clk), - .out_resetn(src_resetn), - .in({do_enable, sync_id}), - .out({src_enable, src_sync_id}) -); - -sync_bits #( - .NUM_OF_BITS(3), - .ASYNC_CLK(ASYNC_CLK_REQ_SRC) -) i_sync_status_src ( - .out_clk(req_aclk), - .out_resetn(req_aresetn), - .in({src_enabled /* | ~src_response_empty*/, src_sync_id_ret, src_fifo_empty}), - .out({enabled_src, sync_id_ret_src, fifo_empty}) -); - endmodule diff --git a/library/axi_dmac/request_generator.v b/library/axi_dmac/request_generator.v index 627fe9837f..3e33c615ef 100644 --- a/library/axi_dmac/request_generator.v +++ b/library/axi_dmac/request_generator.v @@ -38,8 +38,8 @@ module dmac_request_generator #( parameter ID_WIDTH = 3, parameter BURSTS_PER_TRANSFER_WIDTH = 17)( - input req_aclk, - input req_aresetn, + input clk, + input resetn, output [ID_WIDTH-1:0] request_id, input [ID_WIDTH-1:0] response_id, @@ -49,7 +49,6 @@ module dmac_request_generator #( input [BURSTS_PER_TRANSFER_WIDTH-1:0] req_burst_count, input enable, - input pause, output eot ); @@ -70,31 +69,25 @@ wire [ID_WIDTH-1:0] id_next = inc_id(id); assign eot = burst_count == 'h00; assign request_id = id; -always @(posedge req_aclk) begin +always @(posedge clk) begin if (req_ready == 1'b1) begin burst_count <= req_burst_count; - end else if (response_id != id_next && pause == 1'b0) begin + end else if (response_id != id_next && enable == 1'b1) begin burst_count <= burst_count - 1'b1; end end -always @(posedge req_aclk) -begin - if (req_aresetn == 1'b0) begin +always @(posedge clk) begin + if (resetn == 1'b0) begin id <= 'h0; req_ready <= 1'b1; - end else if (enable == 1'b0) begin - req_ready <= 1'b1; - end else begin - if (req_ready) begin - if (req_valid && enable) begin - req_ready <= 1'b0; - end - end else if (response_id != id_next && ~pause) begin - if (eot) - req_ready <= 1'b1; - id <= id_next; + end else if (req_ready == 1'b1) begin + req_ready <= ~req_valid; + end else if (response_id != id_next && enable == 1'b1) begin + if (eot == 1'b1) begin + req_ready <= 1'b1; end + id <= id_next; end end diff --git a/library/axi_dmac/response_generator.v b/library/axi_dmac/response_generator.v index 846c7e6fe0..6ed50c0f65 100644 --- a/library/axi_dmac/response_generator.v +++ b/library/axi_dmac/response_generator.v @@ -45,7 +45,6 @@ module dmac_response_generator #( input [ID_WIDTH-1:0] request_id, output reg [ID_WIDTH-1:0] response_id, - input sync_id, input eot, @@ -67,21 +66,18 @@ assign resp_valid = request_id != response_id && enabled; always @(posedge clk) begin if (resetn == 1'b0) begin enabled <= 1'b0; - end else begin - if (enable) - enabled <= 1'b1; - else if (request_id == response_id) - enabled <= 1'b0; + end else if (enable == 1'b1) begin + enabled <= 1'b1; + end else if (request_id == response_id) begin + enabled <= 1'b0; end end always @(posedge clk) begin if (resetn == 1'b0) begin response_id <= 'h0; - end else begin - if ((resp_valid && resp_ready) || - (sync_id && response_id != request_id)) - response_id <= inc_id(response_id); + end else if (resp_valid == 1'b1 && resp_ready == 1'b1) begin + response_id <= inc_id(response_id); end end diff --git a/library/axi_dmac/response_handler.v b/library/axi_dmac/response_handler.v index a28430b590..5e3184fb91 100644 --- a/library/axi_dmac/response_handler.v +++ b/library/axi_dmac/response_handler.v @@ -46,7 +46,6 @@ module dmac_response_handler #( output reg [ID_WIDTH-1:0] id, input [ID_WIDTH-1:0] request_id, - input sync_id, input enable, output reg enabled, @@ -65,7 +64,7 @@ module dmac_response_handler #( assign resp_resp = bresp; assign resp_eot = eot; -wire active = id != request_id && enabled; +wire active = id != request_id; assign bready = active && resp_ready; assign resp_valid = active && bvalid; @@ -74,10 +73,9 @@ assign resp_valid = active && bvalid; always @(posedge clk) begin if (resetn == 1'b0) begin enabled <= 1'b0; - end else begin - if (enable) + end else if (enable == 1'b1) begin enabled <= 1'b1; - else if (request_id == id) + end else if (request_id == id) begin enabled <= 1'b0; end end @@ -85,10 +83,8 @@ end always @(posedge clk) begin if (resetn == 1'b0) begin id <= 'h0; - end else begin - if ((bready && bvalid) || - (sync_id && id != request_id)) - id <= inc_id(id); + end else if (bready == 1'b1 && bvalid == 1'b1) begin + id <= inc_id(id); end end diff --git a/library/axi_dmac/src_axi_mm.v b/library/axi_dmac/src_axi_mm.v index d869b38e73..e926969056 100644 --- a/library/axi_dmac/src_axi_mm.v +++ b/library/axi_dmac/src_axi_mm.v @@ -52,8 +52,6 @@ module dmac_src_mm_axi #( input enable, output enabled, - input sync_id, - output sync_id_ret, /* output response_valid, @@ -97,7 +95,6 @@ wire address_req_ready; wire data_req_valid; wire data_req_ready; -assign sync_id_ret = sync_id; assign response_id = data_id; splitter #( @@ -130,7 +127,6 @@ dmac_address_generator #( .enable(enable), .enabled(address_enabled), - .sync_id(sync_id), .request_id(request_id), .id(address_id), @@ -162,7 +158,6 @@ dmac_data_mover # ( .enable(address_enabled), .enabled(enabled), - .sync_id(sync_id), .xfer_req(), diff --git a/library/axi_dmac/src_axi_stream.v b/library/axi_dmac/src_axi_stream.v index a2a89525bc..221d407ee8 100644 --- a/library/axi_dmac/src_axi_stream.v +++ b/library/axi_dmac/src_axi_stream.v @@ -45,8 +45,6 @@ module dmac_src_axi_stream #( input enable, output enabled, - input sync_id, - output sync_id_ret, input [ID_WIDTH-1:0] request_id, output [ID_WIDTH-1:0] response_id, @@ -81,21 +79,16 @@ wire data_valid; wire data_ready; wire fifo_last; -assign sync_id_ret = sync_id; assign data = transfer_abort == 1'b1 ? {S_AXIS_DATA_WIDTH{1'b0}} : s_axis_data; assign data_valid = (s_axis_valid & has_sync) | transfer_abort; assign s_axis_ready = data_ready & ~transfer_abort; always @(posedge s_axis_aclk) begin - if (s_axis_aresetn == 1'b0) begin + if (s_axis_valid && s_axis_ready && sync) begin needs_sync <= 1'b0; - end else begin - if (s_axis_valid && s_axis_ready && sync) begin - needs_sync <= 1'b0; - end else if (req_valid && req_ready) begin - needs_sync <= req_sync_transfer_start; - end + end else if (req_valid && req_ready) begin + needs_sync <= req_sync_transfer_start; end end @@ -135,7 +128,6 @@ dmac_data_mover # ( .enable(enable), .enabled(enabled), - .sync_id(sync_id), .xfer_req(s_axis_xfer_req), diff --git a/library/axi_dmac/src_fifo_inf.v b/library/axi_dmac/src_fifo_inf.v index f3513abc4d..f3e38a48e7 100644 --- a/library/axi_dmac/src_fifo_inf.v +++ b/library/axi_dmac/src_fifo_inf.v @@ -44,8 +44,6 @@ module dmac_src_fifo_inf #( input enable, output enabled, - input sync_id, - output sync_id_ret, input [ID_WIDTH-1:0] request_id, output [ID_WIDTH-1:0] response_id, @@ -75,32 +73,22 @@ wire sync_valid = en & ready & has_sync; always @(posedge clk) begin - if (resetn == 1'b0) begin + if (ready && en && sync) begin needs_sync <= 1'b0; - end else begin - if (ready && en && sync) begin - needs_sync <= 1'b0; - end else if (req_valid && req_ready) begin - needs_sync <= req_sync_transfer_start; - end + end else if (req_valid && req_ready) begin + needs_sync <= req_sync_transfer_start; end end always @(posedge clk) begin - if (resetn == 1'b0) begin - overflow <= 1'b0; + if (enable) begin + overflow <= en & ~ready; end else begin - if (enable) begin - overflow <= en & ~ready; - end else begin - overflow <= en; - end + overflow <= en; end end -assign sync_id_ret = sync_id; - dmac_data_mover # ( .ID_WIDTH(ID_WIDTH), .DATA_WIDTH(DATA_WIDTH), @@ -112,7 +100,6 @@ dmac_data_mover # ( .enable(enable), .enabled(enabled), - .sync_id(sync_id), .xfer_req(xfer_req), diff --git a/library/axi_dmac/tb/dma_read_tb b/library/axi_dmac/tb/dma_read_tb index 65bad0287f..678f2f8bdc 100755 --- a/library/axi_dmac/tb/dma_read_tb +++ b/library/axi_dmac/tb/dma_read_tb @@ -3,7 +3,7 @@ SOURCE="dma_read_tb.v" SOURCE+=" axi_read_slave.v axi_slave.v" SOURCE+=" ../axi_dmac_transfer.v ../2d_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" -SOURCE+=" ../data_mover.v ../axi_register_slice.v" +SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" SOURCE+=" ../dest_fifo_inf.v" SOURCE+=" ../src_axi_mm.v ../address_generator.v ../response_generator.v" SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v ../../util_axis_fifo/address_gray_pipelined.v" diff --git a/library/axi_dmac/tb/dma_read_tb.v b/library/axi_dmac/tb/dma_read_tb.v index ba07beea4d..567468ecf5 100644 --- a/library/axi_dmac/tb/dma_read_tb.v +++ b/library/axi_dmac/tb/dma_read_tb.v @@ -123,11 +123,11 @@ module dmac_dma_read_tb; .m_axi_rdata(rdata), .m_axi_rresp(rresp), - .req_clk(clk), - .req_resetn(resetn), + .ctrl_clk(clk), + .ctrl_resetn(resetn), - .enable(1'b1), - .pause(1'b0), + .ctrl_enable(1'b1), + .ctrl_pause(1'b0), .req_eot(eot), diff --git a/library/axi_dmac/tb/dma_write_tb b/library/axi_dmac/tb/dma_write_tb index 20ed5e90bf..e15494094a 100755 --- a/library/axi_dmac/tb/dma_write_tb +++ b/library/axi_dmac/tb/dma_write_tb @@ -3,7 +3,7 @@ SOURCE="dma_write_tb.v" SOURCE+=" axi_write_slave.v axi_slave.v" SOURCE+=" ../axi_dmac_transfer.v ../2d_transfer.v ../request_arb.v ../request_generator.v ../splitter.v" -SOURCE+=" ../data_mover.v ../axi_register_slice.v" +SOURCE+=" ../axi_dmac_reset_manager.v ../data_mover.v ../axi_register_slice.v" SOURCE+=" ../src_fifo_inf.v" SOURCE+=" ../dest_axi_mm.v ../response_handler.v ../address_generator.v" SOURCE+=" ../../util_axis_fifo/util_axis_fifo.v ../../util_axis_fifo/address_gray_pipelined.v" diff --git a/library/axi_dmac/tb/dma_write_tb.v b/library/axi_dmac/tb/dma_write_tb.v index 374bd7df4b..0dfc9fda98 100644 --- a/library/axi_dmac/tb/dma_write_tb.v +++ b/library/axi_dmac/tb/dma_write_tb.v @@ -125,11 +125,11 @@ module dmac_dma_write_tb; .m_axi_bready(bready), .m_axi_bresp(bresp), - .req_clk(clk), - .req_resetn(resetn), + .ctrl_clk(clk), + .ctrl_resetn(resetn), - .enable(1'b1), - .pause(1'b0), + .ctrl_enable(1'b1), + .ctrl_pause(1'b0), .req_eot(eot), diff --git a/library/axi_dmac/tb/reset_manager_tb b/library/axi_dmac/tb/reset_manager_tb new file mode 100755 index 0000000000..cd656cdbaa --- /dev/null +++ b/library/axi_dmac/tb/reset_manager_tb @@ -0,0 +1,8 @@ +#!/bin/bash + +SOURCE="$0.v" +SOURCE+=" ../axi_dmac_reset_manager.v" +SOURCE+=" ../../util_cdc/sync_bits.v" + +cd `dirname $0` +source run_tb.sh diff --git a/library/axi_dmac/tb/reset_manager_tb.v b/library/axi_dmac/tb/reset_manager_tb.v new file mode 100644 index 0000000000..9fd6562371 --- /dev/null +++ b/library/axi_dmac/tb/reset_manager_tb.v @@ -0,0 +1,119 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +module dmac_reset_manager_tb; + parameter VCD_FILE = {`__FILE__,"cd"}; + + `define TIMEOUT 1000000 + `include "tb_base.v" + + + reg clk_a = 1'b0; + reg clk_b = 1'b0; + reg clk_c = 1'b0; + + reg [5:0] resetn_shift = 'h0; + + reg [10:0] counter = 'h00; + + reg ctrl_enable = 1'b0; + reg ctrl_pause = 1'b0; + + always #10 clk_a <= ~clk_a; + always #3 clk_b <= ~clk_b; + always #7 clk_c <= ~clk_c; + + always @(posedge clk_a) begin + counter <= counter + 1'b1; + if (counter == 'h60 || counter == 'h150 || counter == 'h185) begin + ctrl_enable <= 1'b1; + end else if (counter == 'h100 || counter == 'h110 || counter == 'h180) begin + ctrl_enable <= 1'b0; + end + + if (counter == 'h160) begin + ctrl_pause = 1'b1; + end else if (counter == 'h190) begin + ctrl_pause = 1'b0; + end + end + + reg [15:0] req_enabled_shift; + wire req_enable; + wire req_enabled = req_enabled_shift[15]; + + reg [15:0] dest_enabled_shift; + wire dest_enable; + wire dest_enabled = dest_enabled_shift[15]; + + reg [15:0] src_enabled_shift; + wire src_enable; + wire src_enabled = src_enabled_shift[15]; + + + always @(posedge clk_a) begin + req_enabled_shift <= {req_enabled_shift[14:0],req_enable}; + end + + always @(posedge clk_b) begin + dest_enabled_shift <= {dest_enabled_shift[14:0],dest_enable}; + end + + always @(posedge clk_c) begin + src_enabled_shift <= {src_enabled_shift[14:0],src_enable}; + end + + axi_dmac_reset_manager i_reset_manager ( + .clk(clk_a), + .resetn(resetn), + + .ctrl_pause(ctrl_pause), + .ctrl_enable(ctrl_enable), + + .req_enable(req_enable), + .req_enabled(req_enabled), + + .dest_clk(clk_b), + .dest_ext_resetn(1'b0), + .dest_enable(dest_enable), + .dest_enabled(dest_enabled), + + .src_clk(clk_c), + .src_ext_resetn(1'b0), + .src_enable(src_enable), + .src_enabled(src_enabled) + ); + +endmodule