axi_dmac: wire destination descriptor through source

Drive the descriptor from the source side to destination
so we can abort consecutive transfers in case TLAST asserts.

For AXIS count the length of the burst and pass that value to the
destination instead the programmed one. This is useful when the
streams aborts early by asserting the TLAST. We want to notify the
destination with the right number of beats received.

For FIFO source interface reuse the same logic due the small footprint
even if the stream does not got interrupted in that case.
For MM source interface wire the burst length from the request side to
destination.
main
Laszlo Nagy 2018-07-27 15:06:53 +01:00 committed by Laszlo Nagy
parent 0e8515a90b
commit 681b619fff
9 changed files with 248 additions and 54 deletions

View File

@ -48,11 +48,14 @@ module dmac_address_generator #(
input req_valid,
output reg req_ready,
input [DMA_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH] req_address,
input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
output reg [ID_WIDTH-1:0] id,
input [ID_WIDTH-1:0] request_id,
input bl_valid,
output reg bl_ready,
input [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,
input eot,
input enable,
@ -105,6 +108,12 @@ always @(posedge clk) begin
end
end
always @(posedge clk) begin
if (bl_valid == 1'b1 && bl_ready == 1'b1) begin
last_burst_len <= measured_last_burst_length;
end
end
always @(posedge clk) begin
if (addr_valid == 1'b0) begin
last <= eot;
@ -119,12 +128,26 @@ end
always @(posedge clk) begin
if (req_ready == 1'b1) begin
address <= req_address;
last_burst_len <= req_last_burst_length;
end else if (addr_valid == 1'b1 && addr_ready == 1'b1) begin
address <= address + MAX_BEATS_PER_BURST;
end
end
always @(posedge clk) begin
if (resetn == 1'b0) begin
bl_ready <= 1'b1;
end else begin
if (bl_ready == 1'b1) begin
bl_ready <= ~bl_valid;
end else if (addr_valid == 1'b0 && eot == 1'b1) begin
// assert bl_ready only when the addr_valid asserts in the next cycle
if (id != request_id && enable == 1'b1) begin
bl_ready <= 1'b1;
end
end
end
end
always @(posedge clk) begin
if (resetn == 1'b0) begin
req_ready <= 1'b1;
@ -136,7 +159,10 @@ always @(posedge clk) begin
addr_valid <= 1'b0;
req_ready <= last;
end else if (id != request_id && enable == 1'b1) begin
addr_valid <= 1'b1;
// if eot wait until the last_burst_len gets synced over
if (eot == 1'b0 || (eot == 1'b1 && bl_ready == 1'b0)) begin
addr_valid <= 1'b1;
end
end
end
end

View File

@ -78,24 +78,6 @@ set_false_path -quiet \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_sync_control_dest* && IS_SEQUENTIAL}]
set_max_delay -quiet -datapath_only \
-from $req_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_dest_req_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $req_clk]
set_max_delay -quiet -datapath_only \
-from $dest_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_dest_req_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \
-filter {NAME =~ *i_dest_req_fifo* && IS_SEQUENTIAL}] \
-to $dest_clk \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from $dest_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
@ -147,6 +129,41 @@ set_max_delay -quiet -datapath_only \
-to $dest_clk \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from $src_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_dest_req_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $src_clk]
set_max_delay -quiet -datapath_only \
-from $dest_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_dest_req_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \
-filter {NAME =~ *i_dest_req_fifo* && IS_SEQUENTIAL}] \
-to $dest_clk \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from $src_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_src_dest_bl_fifo/i_waddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $src_clk]
set_max_delay -quiet -datapath_only \
-from $dest_clk \
-to [get_cells -quiet -hier *cdc_sync_stage1_reg* \
-filter {NAME =~ *i_src_dest_bl_fifo/i_raddr_sync* && IS_SEQUENTIAL}] \
[get_property -min PERIOD $dest_clk]
set_max_delay -quiet -datapath_only \
-from [get_cells -quiet -hier *cdc_sync_fifo_ram_reg* \
-filter {NAME =~ *i_src_dest_bl_fifo* && IS_SEQUENTIAL}] \
-to $dest_clk \
[get_property -min PERIOD $dest_clk]
<: } :>
# Reset signals
set_false_path -quiet \

View File

@ -47,6 +47,10 @@ module dmac_data_mover #(
output [ID_WIDTH-1:0] response_id,
input eot,
output reg bl_valid = 'b0,
input bl_ready,
output reg [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,
output xfer_req,
output s_axi_ready,
@ -72,6 +76,7 @@ localparam BEAT_COUNTER_MAX = {BEATS_PER_BURST_WIDTH{1'b1}};
reg [BEATS_PER_BURST_WIDTH-1:0] last_burst_length = 'h00;
reg [BEATS_PER_BURST_WIDTH-1:0] beat_counter = 'h00;
reg [BEATS_PER_BURST_WIDTH-1:0] beat_counter_minus_one = 'h0;
reg [ID_WIDTH-1:0] id = 'h00;
reg [ID_WIDTH-1:0] id_next = 'h00;
@ -168,6 +173,23 @@ always @(posedge clk) begin
last_burst_length <= req_last_burst_length;
end
always @(posedge clk) begin
if (req_ready) begin
beat_counter_minus_one <= 'h0;
end else if (m_axi_valid == 1'b1) begin
beat_counter_minus_one <= beat_counter;
end
end
always @(posedge clk) begin
if (last_load) begin
bl_valid <= 1'b1;
measured_last_burst_length <= beat_counter_minus_one;
end else if (bl_ready) begin
bl_valid <= 1'b0;
end
end
always @(posedge clk) begin
if (resetn == 1'b0) begin
active <= 1'b0;

View File

@ -48,7 +48,10 @@ module dmac_dest_mm_axi #(
input req_valid,
output req_ready,
input [DMA_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH] req_address,
input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
input bl_valid,
output bl_ready,
input [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,
input enable,
output enabled,
@ -115,7 +118,10 @@ dmac_address_generator #(
.req_valid(req_valid),
.req_ready(req_ready),
.req_address(req_address),
.req_last_burst_length(req_last_burst_length),
.bl_valid(bl_valid),
.bl_ready(bl_ready),
.measured_last_burst_length(measured_last_burst_length),
.eot(address_eot),

View File

@ -63,7 +63,6 @@ module dmac_dest_axi_stream #(
input req_valid,
output req_ready,
input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length,
input req_xlast,
output response_valid,

View File

@ -209,15 +209,14 @@ wire enabled_dest;
wire req_gen_valid;
wire req_gen_ready;
wire req_dest_valid;
wire req_dest_ready;
wire src_dest_valid;
wire src_dest_ready;
wire req_src_valid;
wire req_src_ready;
wire dest_req_valid;
wire dest_req_ready;
wire [DMA_ADDRESS_WIDTH_DEST-1:0] dest_req_address;
wire [BEATS_PER_BURST_WIDTH_DEST-1:0] dest_req_last_burst_length;
wire [DMA_ADDRESS_WIDTH_DEST-1:0] dest_req_dest_address;
wire dest_req_xlast;
wire dest_response_valid;
@ -242,7 +241,8 @@ wire dest_fifo_last;
wire src_req_valid;
wire src_req_ready;
wire [DMA_ADDRESS_WIDTH_SRC-1:0] src_req_address;
wire [DMA_ADDRESS_WIDTH_DEST-1:0] src_req_dest_address;
wire [DMA_ADDRESS_WIDTH_SRC-1:0] src_req_src_address;
wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_req_last_burst_length;
wire src_req_sync_transfer_start;
wire src_req_xlast;
@ -271,6 +271,10 @@ wire response_dest_ready = 1'b1;
wire [1:0] response_dest_resp;
wire response_dest_resp_eot;
wire src_bl_valid;
wire src_bl_ready;
wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_burst_length;
/* Unused for now
wire response_src_valid;
wire response_src_ready = 1'b1;
@ -298,6 +302,11 @@ end
generate if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin
wire dest_bl_valid;
wire dest_bl_ready;
wire [BEATS_PER_BURST_WIDTH_DEST-1:0] dest_burst_length;
wire [BEATS_PER_BURST_WIDTH_SRC-1:0] dest_src_burst_length;
assign dest_clk = m_dest_axi_aclk;
assign dest_ext_resetn = m_dest_axi_aresetn;
@ -326,8 +335,11 @@ dmac_dest_mm_axi #(
.req_valid(dest_req_valid),
.req_ready(dest_req_ready),
.req_address(dest_req_address),
.req_last_burst_length(dest_req_last_burst_length),
.req_address(dest_req_dest_address),
.bl_valid(dest_bl_valid),
.bl_ready(dest_bl_ready),
.measured_last_burst_length(dest_burst_length),
.response_valid(dest_response_valid),
.response_ready(dest_response_ready),
@ -366,6 +378,42 @@ dmac_dest_mm_axi #(
.m_axi_bready(m_axi_bready)
);
util_axis_fifo #(
.DATA_WIDTH(BEATS_PER_BURST_WIDTH_SRC),
.ADDRESS_WIDTH(0),
.ASYNC_CLK(ASYNC_CLK_SRC_DEST)
) i_src_dest_bl_fifo (
.s_axis_aclk(src_clk),
.s_axis_aresetn(src_resetn),
.s_axis_valid(src_bl_valid),
.s_axis_ready(src_bl_ready),
.s_axis_empty(),
.s_axis_data(src_burst_length),
.s_axis_room(),
.m_axis_aclk(dest_clk),
.m_axis_aresetn(dest_resetn),
.m_axis_valid(dest_bl_valid),
.m_axis_ready(dest_bl_ready),
.m_axis_data(dest_src_burst_length),
.m_axis_level()
);
// Adapt burst length from source width to destination width by either
// truncation or completion with ones.
if (BEATS_PER_BURST_WIDTH_SRC == BEATS_PER_BURST_WIDTH_DEST) begin
assign dest_burst_length = dest_src_burst_length;
end
if (BEATS_PER_BURST_WIDTH_SRC < BEATS_PER_BURST_WIDTH_DEST) begin
assign dest_burst_length = {dest_src_burst_length,
{BEATS_PER_BURST_WIDTH_DEST - BEATS_PER_BURST_WIDTH_SRC{1'b1}}};
end
if (BEATS_PER_BURST_WIDTH_SRC > BEATS_PER_BURST_WIDTH_DEST) begin
assign dest_burst_length = dest_src_burst_length[BEATS_PER_BURST_WIDTH_SRC-1 -: BEATS_PER_BURST_WIDTH_DEST];
end
end else begin
assign m_axi_awvalid = 1'b0;
@ -383,6 +431,8 @@ assign m_axi_wlast = 1'b0;
assign m_axi_bready = 1'b0;
assign src_bl_ready = 1'b1;
end
if (DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin
@ -413,7 +463,6 @@ dmac_dest_axi_stream #(
.req_valid(dest_req_valid),
.req_ready(dest_req_ready),
.req_last_burst_length(dest_req_last_burst_length),
.req_xlast(dest_req_xlast),
.response_valid(dest_response_valid),
@ -537,9 +586,13 @@ dmac_src_mm_axi #(
.req_valid(src_req_valid),
.req_ready(src_req_ready),
.req_address(src_req_address),
.req_address(src_req_src_address),
.req_last_burst_length(src_req_last_burst_length),
.bl_valid(src_bl_valid),
.bl_ready(src_bl_ready),
.measured_last_burst_length(src_burst_length),
/* TODO
.response_valid(src_response_valid),
.response_ready(src_response_ready),
@ -623,6 +676,10 @@ dmac_src_axi_stream #(
.eot(src_eot),
.bl_valid(src_bl_valid),
.bl_ready(src_bl_ready),
.measured_last_burst_length(src_burst_length),
.fifo_valid(src_valid),
.fifo_data(src_data),
.fifo_last(src_last),
@ -678,6 +735,10 @@ dmac_src_fifo_inf #(
.eot(src_eot),
.bl_valid(src_bl_valid),
.bl_ready(src_bl_ready),
.measured_last_burst_length(src_burst_length),
.fifo_valid(src_valid),
.fifo_data(src_data),
.fifo_last(src_last),
@ -816,7 +877,7 @@ axi_register_slice #(
);
splitter #(
.NUM_M(3)
.NUM_M(2)
) i_req_splitter (
.clk(req_clk),
.resetn(req_resetn),
@ -824,30 +885,27 @@ splitter #(
.s_ready(req_ready),
.m_valid({
req_gen_valid,
req_dest_valid,
req_src_valid
}),
.m_ready({
req_gen_ready,
req_dest_ready,
req_src_ready
})
);
util_axis_fifo #(
.DATA_WIDTH(DMA_ADDRESS_WIDTH_DEST + BEATS_PER_BURST_WIDTH_DEST + 1),
.DATA_WIDTH(DMA_ADDRESS_WIDTH_DEST + 1),
.ADDRESS_WIDTH(0),
.ASYNC_CLK(ASYNC_CLK_DEST_REQ)
.ASYNC_CLK(ASYNC_CLK_SRC_DEST)
) i_dest_req_fifo (
.s_axis_aclk(req_clk),
.s_axis_aresetn(req_resetn),
.s_axis_valid(req_dest_valid),
.s_axis_ready(req_dest_ready),
.s_axis_aclk(src_clk),
.s_axis_aresetn(src_resetn),
.s_axis_valid(src_dest_valid),
.s_axis_ready(src_dest_ready),
.s_axis_empty(),
.s_axis_data({
req_dest_address,
req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST],
req_xlast
src_req_dest_address,
src_req_xlast
}),
.s_axis_room(),
@ -856,15 +914,14 @@ util_axis_fifo #(
.m_axis_valid(dest_req_valid),
.m_axis_ready(dest_req_ready),
.m_axis_data({
dest_req_address,
dest_req_last_burst_length,
dest_req_dest_address,
dest_req_xlast
}),
.m_axis_level()
);
util_axis_fifo #(
.DATA_WIDTH(DMA_ADDRESS_WIDTH_SRC + BEATS_PER_BURST_WIDTH_SRC + 2),
.DATA_WIDTH(DMA_ADDRESS_WIDTH_DEST + DMA_ADDRESS_WIDTH_SRC + BEATS_PER_BURST_WIDTH_SRC + 2),
.ADDRESS_WIDTH(0),
.ASYNC_CLK(ASYNC_CLK_REQ_SRC)
) i_src_req_fifo (
@ -874,6 +931,7 @@ util_axis_fifo #(
.s_axis_ready(req_src_ready),
.s_axis_empty(),
.s_axis_data({
req_dest_address,
req_src_address,
req_length[BYTES_PER_BURST_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC],
req_sync_transfer_start,
@ -883,10 +941,11 @@ util_axis_fifo #(
.m_axis_aclk(src_clk),
.m_axis_aresetn(src_resetn),
.m_axis_valid(src_req_valid),
.m_axis_ready(src_req_ready),
.m_axis_valid(src_req_spltr_valid),
.m_axis_ready(src_req_spltr_ready),
.m_axis_data({
src_req_address,
src_req_dest_address,
src_req_src_address,
src_req_last_burst_length,
src_req_sync_transfer_start,
src_req_xlast
@ -894,6 +953,23 @@ util_axis_fifo #(
.m_axis_level()
);
splitter #(
.NUM_M(2)
) i_src_splitter (
.clk(src_clk),
.resetn(src_resetn),
.s_valid(src_req_spltr_valid),
.s_ready(src_req_spltr_ready),
.m_valid({
src_req_valid,
src_dest_valid
}),
.m_ready({
src_req_ready,
src_dest_ready
})
);
util_axis_fifo #(
.DATA_WIDTH(1),
.ADDRESS_WIDTH(0),
@ -915,6 +991,7 @@ util_axis_fifo #(
.m_axis_level()
);
/* Unused for now
util_axis_fifo #(
.DATA_WIDTH(2),

View File

@ -53,6 +53,9 @@ module dmac_src_mm_axi #(
input enable,
output reg enabled = 1'b0,
output bl_valid,
input bl_ready,
output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,
/*
output response_valid,
input response_ready,
@ -93,10 +96,35 @@ module dmac_src_mm_axi #(
reg [ID_WIDTH-1:0] id = 'h00;
wire address_enabled;
wire req_ready_ag;
wire req_valid_ag;
wire bl_ready_ag;
wire bl_valid_ag;
assign data_id = id;
assign response_id = id;
assign measured_last_burst_length = req_last_burst_length;
splitter #(
.NUM_M(3)
) i_req_splitter (
.clk(m_axi_aclk),
.resetn(m_axi_aresetn),
.s_valid(req_valid),
.s_ready(req_ready),
.m_valid({
bl_valid,
bl_valid_ag,
req_valid_ag
}),
.m_ready({
bl_ready,
bl_ready_ag,
req_ready_ag
})
);
dmac_address_generator #(
.ID_WIDTH(ID_WIDTH),
.BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH),
@ -114,10 +142,13 @@ dmac_address_generator #(
.request_id(request_id),
.id(address_id),
.req_valid(req_valid),
.req_ready(req_ready),
.req_valid(req_valid_ag),
.req_ready(req_ready_ag),
.req_address(req_address),
.req_last_burst_length(req_last_burst_length),
.bl_valid(bl_valid_ag),
.bl_ready(bl_ready_ag),
.measured_last_burst_length(req_last_burst_length),
.eot(address_eot),

View File

@ -50,6 +50,10 @@ module dmac_src_axi_stream #(
output [ID_WIDTH-1:0] response_id,
input eot,
output bl_valid,
input bl_ready,
output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,
output s_axis_ready,
input s_axis_valid,
input [S_AXIS_DATA_WIDTH-1:0] s_axis_data,
@ -85,6 +89,10 @@ dmac_data_mover # (
.response_id(response_id),
.eot(eot),
.bl_valid(bl_valid),
.bl_ready(bl_ready),
.measured_last_burst_length(measured_last_burst_length),
.req_valid(req_valid),
.req_ready(req_ready),
.req_last_burst_length(req_last_burst_length),

View File

@ -49,6 +49,10 @@ module dmac_src_fifo_inf #(
output [ID_WIDTH-1:0] response_id,
input eot,
output bl_valid,
input bl_ready,
output [BEATS_PER_BURST_WIDTH-1:0] measured_last_burst_length,
input en,
input [DATA_WIDTH-1:0] din,
output reg overflow,
@ -95,6 +99,10 @@ dmac_data_mover # (
.response_id(response_id),
.eot(eot),
.bl_valid(bl_valid),
.bl_ready(bl_ready),
.measured_last_burst_length(measured_last_burst_length),
.req_valid(req_valid),
.req_ready(req_ready),
.req_last_burst_length(req_last_burst_length),