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.
main
Laszlo Nagy 2018-11-14 10:41:04 +00:00 committed by Laszlo Nagy
parent 68a5f2f86c
commit 5e1100ee77
3 changed files with 39 additions and 11 deletions

View File

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

View File

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

View File

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