From 681b619fff04b0c6266ca9850cf289149d4e3152 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Fri, 27 Jul 2018 15:06:53 +0100 Subject: [PATCH] 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. --- library/axi_dmac/address_generator.v | 32 ++++++- library/axi_dmac/axi_dmac_constr.ttcl | 53 +++++++---- library/axi_dmac/data_mover.v | 22 +++++ library/axi_dmac/dest_axi_mm.v | 10 +- library/axi_dmac/dest_axi_stream.v | 1 - library/axi_dmac/request_arb.v | 131 ++++++++++++++++++++------ library/axi_dmac/src_axi_mm.v | 37 +++++++- library/axi_dmac/src_axi_stream.v | 8 ++ library/axi_dmac/src_fifo_inf.v | 8 ++ 9 files changed, 248 insertions(+), 54 deletions(-) diff --git a/library/axi_dmac/address_generator.v b/library/axi_dmac/address_generator.v index 27513a2c8..02ffcc1fb 100644 --- a/library/axi_dmac/address_generator.v +++ b/library/axi_dmac/address_generator.v @@ -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 diff --git a/library/axi_dmac/axi_dmac_constr.ttcl b/library/axi_dmac/axi_dmac_constr.ttcl index abc762751..b73011fae 100644 --- a/library/axi_dmac/axi_dmac_constr.ttcl +++ b/library/axi_dmac/axi_dmac_constr.ttcl @@ -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 \ diff --git a/library/axi_dmac/data_mover.v b/library/axi_dmac/data_mover.v index 192030489..b1f3970f9 100644 --- a/library/axi_dmac/data_mover.v +++ b/library/axi_dmac/data_mover.v @@ -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; diff --git a/library/axi_dmac/dest_axi_mm.v b/library/axi_dmac/dest_axi_mm.v index 9a8a22811..5609a0220 100644 --- a/library/axi_dmac/dest_axi_mm.v +++ b/library/axi_dmac/dest_axi_mm.v @@ -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), diff --git a/library/axi_dmac/dest_axi_stream.v b/library/axi_dmac/dest_axi_stream.v index 078f1323b..261c93b53 100644 --- a/library/axi_dmac/dest_axi_stream.v +++ b/library/axi_dmac/dest_axi_stream.v @@ -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, diff --git a/library/axi_dmac/request_arb.v b/library/axi_dmac/request_arb.v index f952ba536..337e4ef23 100644 --- a/library/axi_dmac/request_arb.v +++ b/library/axi_dmac/request_arb.v @@ -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), diff --git a/library/axi_dmac/src_axi_mm.v b/library/axi_dmac/src_axi_mm.v index 347fbb109..4e1930b03 100644 --- a/library/axi_dmac/src_axi_mm.v +++ b/library/axi_dmac/src_axi_mm.v @@ -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), diff --git a/library/axi_dmac/src_axi_stream.v b/library/axi_dmac/src_axi_stream.v index 7ed016668..523dc57da 100644 --- a/library/axi_dmac/src_axi_stream.v +++ b/library/axi_dmac/src_axi_stream.v @@ -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), diff --git a/library/axi_dmac/src_fifo_inf.v b/library/axi_dmac/src_fifo_inf.v index c8c7146c1..70d1b188b 100644 --- a/library/axi_dmac/src_fifo_inf.v +++ b/library/axi_dmac/src_fifo_inf.v @@ -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),