From 6da9c65a08af334f13fd1ded1ca4c05573bf4da8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 29 Jan 2014 13:35:17 +0100 Subject: [PATCH] axi_dmac: Add support for zero latency transfer switching Right now there is always a period of one clock cycle where we can not transfer any data when switching between two transfers. This patch modifies the data mover to allow for zero latency. This fixes problems on the FMCOMMS1 platform Signed-off-by: Lars-Peter Clausen --- library/axi_dmac/data_mover.v | 51 +++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/library/axi_dmac/data_mover.v b/library/axi_dmac/data_mover.v index e72568f6a..1ef496710 100644 --- a/library/axi_dmac/data_mover.v +++ b/library/axi_dmac/data_mover.v @@ -58,7 +58,7 @@ module dmac_data_mover ( output m_axi_last, input req_valid, - output reg req_ready, + output req_ready, input [3:0] req_last_burst_length ); @@ -72,20 +72,25 @@ reg [3:0] last_burst_length; reg [C_ID_WIDTH-1:0] id = 'h00; reg [C_ID_WIDTH-1:0] id_next; reg [3:0] beat_counter = 'h00; -wire [3:0] beat_counter_next; wire last; +wire last_load; reg pending_burst; +reg active; assign response_id = id; -assign beat_counter_next = s_axi_ready && s_axi_valid ? beat_counter + 1'b1 : beat_counter; assign last = beat_counter == (eot ? last_burst_length : 4'hf); -assign s_axi_ready = m_axi_ready & pending_burst & ~req_ready; -assign m_axi_valid = s_axi_valid & pending_burst & ~req_ready; +assign s_axi_ready = m_axi_ready & pending_burst & active; +assign m_axi_valid = s_axi_valid & pending_burst & active; assign m_axi_data = s_axi_data; assign m_axi_last = last; +// 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_ready && s_axi_valid && last && eot; +assign req_ready = last_load || ~active; + always @(posedge clk) begin if (resetn == 1'b0) begin enabled <= 1'b0; @@ -111,20 +116,31 @@ end always @(posedge clk) begin if (resetn == 1'b0) begin beat_counter <= 'h0; - req_ready <= 1'b1; + end else begin + if (req_ready && req_valid) begin + beat_counter <= 'h0; + end else if (s_axi_ready && s_axi_valid) begin + beat_counter <= beat_counter + 1'b1; + end + end +end + +always @(posedge clk) begin + if (req_ready && req_valid) begin + last_burst_length <= req_last_burst_length; + end +end + +always @(posedge clk) begin + if (resetn == 1'b0) begin + active <= 1'b0; end else begin if (~enabled) begin - req_ready <= 1'b1; - end else if (req_ready) begin - if (req_valid && enabled) begin - last_burst_length <= req_last_burst_length; - req_ready <= 1'b0; - beat_counter <= 'h0; - end - end else if (s_axi_ready && s_axi_valid) begin - if (last && eot) - req_ready <= 1'b1; - beat_counter <= beat_counter + 1'b1; + active <= 1'b0; + end else if (req_ready && req_valid) begin + active <= 1'b1; + end else if (last_load) begin + active <= 1'b0; end end end @@ -141,6 +157,7 @@ end always @(posedge clk) begin if (resetn == 1'b0) begin id <= 'h0; + pending_burst <= 1'b0; end else begin id <= id_next; pending_burst <= id_next != request_id;