From 5e1100ee7724e537d37215a2a8163488ca91b9cf Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Nov 2018 10:41:04 +0000 Subject: [PATCH] axi_dmac: patch for partial 2D transfer support This patch addresses the following issue: In 2D mode when consecutive partial transfers occur, and the latter is very short, will interfere with the completion mechanism of the first transfer leading to uncompleted segments and unreported partial transfers. --- library/axi_dmac/axi_dmac_response_manager.v | 34 ++++++++++++++++---- library/axi_dmac/request_arb.v | 7 +++- library/axi_dmac/request_generator.v | 9 ++++-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/library/axi_dmac/axi_dmac_response_manager.v b/library/axi_dmac/axi_dmac_response_manager.v index f08a131be..956839682 100644 --- a/library/axi_dmac/axi_dmac_response_manager.v +++ b/library/axi_dmac/axi_dmac_response_manager.v @@ -66,6 +66,7 @@ module axi_dmac_response_manager #( // Interface to requester side input completion_req_valid, + output reg completion_req_ready = 1'b1, input completion_req_last, input [1:0] completion_transfer_id ); @@ -104,6 +105,8 @@ wire [1:0] response_dest_resp; wire response_dest_resp_eot; wire [BYTES_PER_BURST_WIDTH-1:0] response_dest_data_burst_length; +wire completion_req; + reg [1:0] to_complete_count = 'h0; reg [1:0] transfer_id = 'h0; reg completion_req_last_found = 1'b0; @@ -192,7 +195,11 @@ always @(*) begin end STATE_WRITE_RESPR: begin if (response_ready == 1'b1) begin - nx_state = STATE_IDLE; + if (|to_complete_count && transfer_id == completion_transfer_id) begin + nx_state = STATE_ZERO_COMPL; + end else begin + nx_state = STATE_IDLE; + end end end STATE_ZERO_COMPL: begin @@ -225,20 +232,33 @@ end assign do_compl = (state == STATE_WRITE_ZRCMPL) && response_ready; -// Once the last completion request from request generator is received +// Once the last completion request from request generator is received // we can wait for completions from the destination side always @(posedge req_clk) begin if (req_resetn == 1'b0) begin completion_req_last_found <= 1'b0; - end else if (completion_req_valid) begin + end else if (completion_req) begin completion_req_last_found <= completion_req_last; end else if (state ==STATE_ZERO_COMPL && ~(|to_complete_count)) begin completion_req_last_found <= 1'b0; end end +// Once the last completion is received wit until all completions are done +always @(posedge req_clk) begin + if (req_resetn == 1'b0) begin + completion_req_ready <= 1'b1; + end else if (completion_req_valid && completion_req_last) begin + completion_req_ready <= 1'b0; + end else if (to_complete_count == 0) begin + completion_req_ready <= 1'b1; + end +end + +assign completion_req = completion_req_ready && completion_req_valid; + // Track transfers so we can tell when did the destination completed all its -// transfers +// transfers always @(posedge req_clk) begin if (req_resetn == 1'b0) begin transfer_id <= 'h0; @@ -247,13 +267,13 @@ always @(posedge req_clk) begin end end -// Count how many transfers we need to complete +// Count how many transfers we need to complete always @(posedge req_clk) begin if (req_resetn == 1'b0) begin to_complete_count <= 'h0; - end else if (completion_req_valid & ~do_compl) begin + end else if (completion_req & ~do_compl) begin to_complete_count <= to_complete_count + 1; - end else if (~completion_req_valid & do_compl) begin + end else if (~completion_req & do_compl) begin to_complete_count <= to_complete_count - 1; end end diff --git a/library/axi_dmac/request_arb.v b/library/axi_dmac/request_arb.v index 0e69fd1e5..728d5b8ac 100644 --- a/library/axi_dmac/request_arb.v +++ b/library/axi_dmac/request_arb.v @@ -296,9 +296,11 @@ wire src_dest_valid_hs_masked; wire src_dest_ready_hs; wire req_rewind_req_valid; +wire req_rewind_req_ready; wire [ID_WIDTH+3-1:0] req_rewind_req_data; wire completion_req_valid; +wire completion_req_ready; wire completion_req_last; wire [1:0] completion_transfer_id; @@ -772,7 +774,7 @@ util_axis_fifo #( .m_axis_aclk(req_clk), .m_axis_aresetn(req_resetn), .m_axis_valid(req_rewind_req_valid), - .m_axis_ready(1'b1), + .m_axis_ready(req_rewind_req_ready), .m_axis_data(req_rewind_req_data), .m_axis_level() ); @@ -1137,12 +1139,14 @@ dmac_request_generator #( .response_id(response_id), .rewind_req_valid(req_rewind_req_valid), + .rewind_req_ready(req_rewind_req_ready), .rewind_req_data(req_rewind_req_data), .rewind_state(rewind_state), .abort_req(abort_req), .completion_req_valid(completion_req_valid), + .completion_req_ready(completion_req_ready), .completion_req_last(completion_req_last), .completion_transfer_id(completion_transfer_id), @@ -1182,6 +1186,7 @@ axi_dmac_response_manager #( .response_ready(response_ready), .completion_req_valid(completion_req_valid), + .completion_req_ready(completion_req_ready), .completion_req_last(completion_req_last), .completion_transfer_id(completion_transfer_id) diff --git a/library/axi_dmac/request_generator.v b/library/axi_dmac/request_generator.v index 75bd7774a..d32f02ee0 100644 --- a/library/axi_dmac/request_generator.v +++ b/library/axi_dmac/request_generator.v @@ -47,12 +47,14 @@ module dmac_request_generator #( input [ID_WIDTH-1:0] response_id, input rewind_req_valid, + output rewind_req_ready, input [ID_WIDTH+3-1:0] rewind_req_data, output rewind_state, output abort_req, output reg completion_req_valid = 1'b0, + input completion_req_ready, output completion_req_last, output [1:0] completion_transfer_id, @@ -172,14 +174,14 @@ always @(*) begin nx_completion_req_valid = 0; case (state) STATE_IDLE: begin - if (rewind_req_valid == 1'b1) begin + if (rewind_req_valid == 1'b1 && rewind_req_ready == 1'b1) begin nx_state = STATE_REWIND_ID; end else if (req_valid == 1'b1) begin nx_state = STATE_GEN_ID; end end STATE_GEN_ID: begin - if (rewind_req_valid == 1'b1) begin + if (rewind_req_valid == 1'b1 && rewind_req_ready == 1'b1) begin nx_state = STATE_REWIND_ID; end else if (eot == 1'b1 && incr_en == 1'b1) begin nx_state = STATE_IDLE; @@ -233,7 +235,7 @@ always @(posedge clk) begin end always @(posedge clk) begin - if (rewind_req_valid == 1'b1) begin + if (rewind_req_valid == 1'b1 && rewind_req_ready == 1'b1) begin {rew_transfer_id, rew_req_xlast, rew_id} <= rewind_req_data; end end @@ -249,6 +251,7 @@ assign completion_req_last = cur_req_xlast; assign completion_transfer_id = rew_transfer_id; assign rewind_state = (state == STATE_REWIND_ID); +assign rewind_req_ready = completion_req_ready; assign abort_req = (state == STATE_REWIND_ID) && !rew_req_xlast && !cur_req_xlast;