axi_dmac: Rework transfer shutdown

The DMAC allows a transfer to be aborted. When a transfer is aborted the
DMAC shuts down as fast as possible while still completing any pending
transactions as required by the protocol specifications of the port. E.g.
for AXI-MM this means to complete all outstanding bursts.

Once the DMAC has entered an idle state a special synchronization signal is
send to all modules. This synchronization signal instructs them to flush
the pipeline and remove any stale data and metadata associated with the
aborted transfer. Once all data has been flushed the DMAC enters the
shutdown state and is ready for the next transfer.

In addition each module has a reset that resets the modules state and is
used at system startup to bring them into a consistent state.

Re-work the shutdown process to instead of flushing the pipeline re-use the
startup reset signal also for shutdown.

To manage the reset signal generation introduce the reset manager module.
It contains a state machine that will assert the reset signals in the
correct order and for the appropriate duration in case of a transfer
shutdown.

The reset signal is asserted in all domains until it has been asserted for
at least 4 clock cycles in the slowest domain. This ensures that the reset
signal is not de-asserted in the faster domains before the slower domains
have had a chance to process the reset signal.

In addition the reset signal is de-asserted in the opposite direction of
the data flow. This ensures that the data sink is ready to receive data
before the data source can start sending data. This simplifies the internal
handshaking.

This approach has multiple advantages.
 * Issuing a reset and removing all state takes less time than
   explicitly flushing one sample per clock cycle at a time.
 * It simplifies the logic in the faster clock domains at the expense of
   more complicated logic in the slower control clock domain. This allows
   for higher fMax on the data paths.
 * Less signals to synchronize from the control domain to the data domains

The implementation of the pause mode has also slightly changed. Pause is
now a simple disable of the data domains. When the transfer is resumed
after a pause the data domains are re-enabled and continue at their
previous state.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
main
Lars-Peter Clausen 2017-09-21 16:02:44 +02:00 committed by Lars-Peter Clausen
parent 95c98c634e
commit 02bc91ad3a
27 changed files with 710 additions and 395 deletions

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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[*]}]

View File

@ -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}]
<: } :>

View File

@ -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 \

View File

@ -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" \

View File

@ -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
);

View File

@ -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:
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
//
// 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

View File

@ -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

View File

@ -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;

View File

@ -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),

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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(),

View File

@ -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),

View File

@ -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),

View File

@ -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"

View File

@ -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),

View File

@ -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"

View File

@ -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),

View File

@ -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

View File

@ -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:
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
//
// 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