From c4cb3dfb377e64114f037e5310d05e7c09285c1d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 28 May 2018 12:50:53 +0200 Subject: [PATCH] axi_dmac: Move transfer abort logic to data mover The transfer abort logic in the src_axi_stream module is making some assumptions about the internal timings of the data mover module. Move this logic inside the data mover module. This will make it easier to update the internal logic without having to update other modules. Signed-off-by: Lars-Peter Clausen --- library/axi_dmac/data_mover.v | 58 +++++++++++++++++++++++++------ library/axi_dmac/src_axi_stream.v | 50 +++++--------------------- library/axi_dmac/src_fifo_inf.v | 4 ++- 3 files changed, 58 insertions(+), 54 deletions(-) diff --git a/library/axi_dmac/data_mover.v b/library/axi_dmac/data_mover.v index b76a8dc4a..6255013fd 100644 --- a/library/axi_dmac/data_mover.v +++ b/library/axi_dmac/data_mover.v @@ -37,7 +37,8 @@ module dmac_data_mover #( parameter ID_WIDTH = 3, parameter DATA_WIDTH = 64, - parameter BEATS_PER_BURST_WIDTH = 4) ( + parameter BEATS_PER_BURST_WIDTH = 4, + parameter ALLOW_ABORT = 0) ( input clk, input resetn, @@ -51,6 +52,7 @@ module dmac_data_mover #( output s_axi_ready, input s_axi_valid, input [DATA_WIDTH-1:0] s_axi_data, + input s_axi_last, input s_axi_sync, output m_axi_valid, @@ -60,7 +62,8 @@ module dmac_data_mover #( input req_valid, output req_ready, input [BEATS_PER_BURST_WIDTH-1:0] req_last_burst_length, - input req_sync_transfer_start + input req_sync_transfer_start, + input req_xlast ); localparam BEAT_COUNTER_MAX = {BEATS_PER_BURST_WIDTH{1'b1}}; @@ -81,7 +84,7 @@ reg needs_sync = 1'b0; wire has_sync = ~needs_sync | s_axi_sync; wire s_axi_sync_valid = has_sync & s_axi_valid; -wire s_axi_beat = s_axi_sync_valid & s_axi_ready; +wire transfer_abort_s; wire last_load; wire last; @@ -92,18 +95,51 @@ assign response_id = id; assign last = eot ? last_eot : last_non_eot; -assign s_axi_ready = pending_burst & active; -assign m_axi_valid = s_axi_sync_valid & pending_burst & active; -assign m_axi_data = s_axi_data; +assign s_axi_ready = (pending_burst & active) & ~transfer_abort_s; +assign m_axi_valid = (s_axi_sync_valid | transfer_abort_s) & pending_burst & active; +assign m_axi_data = transfer_abort_s == 1'b1 ? {DATA_WIDTH{1'b0}} : s_axi_data; assign m_axi_last = last; -assign m_axi_eot = last & eot; + +generate if (ALLOW_ABORT == 1) begin + reg transfer_abort = 1'b0; + reg req_xlast_d = 1'b0; + + /* + * A 'last' on the external interface indicates the end of an packet. If such a + * 'last' indicator is observed before the end of the current transfer stop + * accepting data on the external interface and complete the current transfer by + * writing zeros to the buffer. + */ + always @(posedge clk) begin + if (resetn == 1'b0) begin + transfer_abort <= 1'b0; + end else if (m_axi_valid == 1'b1) begin + if (last == 1'b1 && eot == 1'b1 && req_xlast_d == 1'b1) begin + transfer_abort <= 1'b0; + end else if (s_axi_last == 1'b1) begin + transfer_abort <= 1'b1; + end + end + end + + always @(posedge clk) begin + if (req_ready == 1'b1) begin + req_xlast_d <= req_xlast; + end + end + + assign transfer_abort_s = transfer_abort; + +end else begin + assign transfer_abort_s = 1'b0; +end endgenerate /* * If req_sync_transfer_start is set all incoming beats will be skipped until * one has s_axi_sync set. This will be the first beat that is passsed through. */ always @(posedge clk) begin - if (s_axi_beat == 1'b1) + if (m_axi_valid == 1'b1) begin needs_sync <= 1'b0; end else if (req_ready == 1'b1) begin needs_sync <= req_sync_transfer_start; @@ -112,7 +148,7 @@ end // If we want to support zero delay between transfers we have to assert // req_ready on the same cycle on which the last load happens. -assign last_load = s_axi_beat && last_eot && eot; +assign last_load = m_axi_valid && last_eot && eot; assign req_ready = last_load || ~active; always @(posedge clk) begin @@ -120,7 +156,7 @@ always @(posedge clk) begin last_eot <= req_last_burst_length == 'h0; last_non_eot <= 1'b0; beat_counter <= 'h1; - end else if (s_axi_beat == 1'b1) begin + end else if (m_axi_valid == 1'b1) begin last_eot <= beat_counter == last_burst_length; last_non_eot <= beat_counter == BEAT_COUNTER_MAX; beat_counter <= beat_counter + 1'b1; @@ -144,7 +180,7 @@ end always @(*) begin - if (s_axi_beat == 1'b1 && last == 1'b1) + if (m_axi_valid == 1'b1 && last == 1'b1) id_next <= inc_id(id); else id_next <= id; diff --git a/library/axi_dmac/src_axi_stream.v b/library/axi_dmac/src_axi_stream.v index 132e63136..7ed016668 100644 --- a/library/axi_dmac/src_axi_stream.v +++ b/library/axi_dmac/src_axi_stream.v @@ -68,48 +68,13 @@ module dmac_src_axi_stream #( input req_xlast ); -reg transfer_abort = 1'b0; -reg req_xlast_d = 1'b0; - -wire [S_AXIS_DATA_WIDTH-1:0] data; -wire data_valid; -wire data_ready; -wire fifo_eot; - assign enabled = enable; -assign data = transfer_abort == 1'b1 ? {S_AXIS_DATA_WIDTH{1'b0}} : s_axis_data; -assign data_valid = s_axis_valid | transfer_abort; -assign s_axis_ready = data_ready & ~transfer_abort; - -/* - * A 'last' on the external interface indicates the end of an packet. If such a - * 'last' indicator is observed before the end of the current transfer stop - * accepting data on the external interface and complete the current transfer by - * writing zeros to the buffer. - */ -always @(posedge s_axis_aclk) begin - if (s_axis_aresetn == 1'b0) begin - transfer_abort <= 1'b0; - end else if (data_ready == 1'b1 && data_valid == 1'b1) begin - if (fifo_eot == 1'b1 && req_xlast_d == 1'b1) begin - transfer_abort <= 1'b0; - end else if (s_axis_last == 1'b1) begin - transfer_abort <= 1'b1; - end - end -end - -always @(posedge s_axis_aclk) begin - if(req_ready == 1'b1) begin - req_xlast_d <= req_xlast; - end -end - dmac_data_mover # ( .ID_WIDTH(ID_WIDTH), .DATA_WIDTH(S_AXIS_DATA_WIDTH), - .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH) + .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH), + .ALLOW_ABORT(1) ) i_data_mover ( .clk(s_axis_aclk), .resetn(s_axis_aresetn), @@ -124,16 +89,17 @@ dmac_data_mover # ( .req_ready(req_ready), .req_last_burst_length(req_last_burst_length), .req_sync_transfer_start(req_sync_transfer_start), + .req_xlast(req_xlast), - .s_axi_ready(data_ready), - .s_axi_valid(data_valid), - .s_axi_data(data), + .s_axi_valid(s_axis_valid), + .s_axi_ready(s_axis_ready), + .s_axi_data(s_axis_data), + .s_axi_last(s_axis_last), .s_axi_sync(s_axis_user[0]), .m_axi_valid(fifo_valid), .m_axi_data(fifo_data), - .m_axi_last(fifo_last), - .m_axi_eot(fifo_eot) + .m_axi_last(fifo_last) ); endmodule diff --git a/library/axi_dmac/src_fifo_inf.v b/library/axi_dmac/src_fifo_inf.v index bcc68602c..c8c7146c1 100644 --- a/library/axi_dmac/src_fifo_inf.v +++ b/library/axi_dmac/src_fifo_inf.v @@ -98,12 +98,14 @@ dmac_data_mover # ( .req_valid(req_valid), .req_ready(req_ready), .req_last_burst_length(req_last_burst_length), - .req_sync_transfer_start(req_sync_transer_start), + .req_sync_transfer_start(req_sync_transfer_start), + .req_xlast(1'b0), .s_axi_ready(ready), .s_axi_valid(valid), .s_axi_data(din), .s_axi_sync(sync), + .s_axi_last(1'b0), .m_axi_valid(fifo_valid), .m_axi_data(fifo_data),