diff --git a/library/axi_dmac/2d_transfer.v b/library/axi_dmac/2d_transfer.v index 3da9045a8..341273690 100644 --- a/library/axi_dmac/2d_transfer.v +++ b/library/axi_dmac/2d_transfer.v @@ -37,6 +37,7 @@ module dmac_2d_transfer #( parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_LENGTH_WIDTH = 24, + parameter BYTES_PER_BURST_WIDTH = 7, parameter BYTES_PER_BEAT_WIDTH_SRC = 3, parameter BYTES_PER_BEAT_WIDTH_DEST = 3)( @@ -53,9 +54,14 @@ module dmac_2d_transfer #( input [DMA_LENGTH_WIDTH-1:0] req_dest_stride, input [DMA_LENGTH_WIDTH-1:0] req_src_stride, input req_sync_transfer_start, - output reg req_eot, input req_last, + output reg req_eot, + output reg [BYTES_PER_BURST_WIDTH-1:0] req_measured_burst_length, + output reg req_response_partial, + output reg req_response_valid, + input req_response_ready, + output reg out_req_valid, input out_req_ready, output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] out_req_dest_address, @@ -63,7 +69,13 @@ module dmac_2d_transfer #( output [DMA_LENGTH_WIDTH-1:0] out_req_length, output reg out_req_sync_transfer_start, output out_req_last, - input out_eot + + input out_eot, + input [BYTES_PER_BURST_WIDTH-1:0] out_measured_burst_length, + input out_response_partial, + input out_response_valid, + output reg out_response_ready = 1'b1 + ); reg [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] dest_address = 'h00; @@ -96,7 +108,7 @@ always @(posedge req_aclk) begin req_id <= req_id + 1'b1; end - if (out_eot == 1'b1) begin + if (out_eot == 1'b1 && out_response_valid == 1'b1 && out_response_ready == 1'b1) begin eot_id <= eot_id + 1'b1; req_eot <= last_req[eot_id]; end else begin @@ -111,6 +123,31 @@ always @(posedge req_aclk) begin end end +always @(posedge req_aclk) begin + if (out_response_valid == 1'b1 && out_response_ready == 1'b1) begin + req_measured_burst_length <= out_measured_burst_length; + req_response_partial <= out_response_partial; + end +end + +always @(posedge req_aclk) begin + if (out_response_valid == 1'b1 && out_response_ready == 1'b1) begin + req_response_valid <= 1'b1; + end else if (req_response_ready == 1'b1) begin + req_response_valid <= 1'b0; + end +end + +always @(posedge req_aclk) begin + if (req_aresetn == 1'b0) begin + out_response_ready <= 1'b1; + end else if (out_response_ready == 1'b1) begin + out_response_ready <= ~out_response_valid; + end else if (req_response_ready == 1'b1) begin + out_response_ready <= 1'b1; + end +end + always @(posedge req_aclk) begin if (req_ready == 1'b1 && req_valid == 1'b1) begin dest_address <= req_dest_address; diff --git a/library/axi_dmac/Makefile b/library/axi_dmac/Makefile index 57860f2ba..c8e5969e7 100644 --- a/library/axi_dmac/Makefile +++ b/library/axi_dmac/Makefile @@ -16,6 +16,7 @@ GENERIC_DEPS += axi_dmac_regmap_request.v GENERIC_DEPS += axi_dmac_reset_manager.v GENERIC_DEPS += axi_dmac_resize_dest.v GENERIC_DEPS += axi_dmac_resize_src.v +GENERIC_DEPS += axi_dmac_response_manager.v GENERIC_DEPS += axi_dmac_transfer.v GENERIC_DEPS += axi_register_slice.v GENERIC_DEPS += data_mover.v @@ -46,6 +47,7 @@ XILINX_LIB_DEPS += util_axis_fifo XILINX_LIB_DEPS += util_cdc ALTERA_DEPS += ../util_axis_fifo/util_axis_fifo.v +ALTERA_DEPS += ../util_axis_fifo/address_sync.v ALTERA_DEPS += ../util_cdc/sync_bits.v ALTERA_DEPS += axi_dmac_constr.sdc ALTERA_DEPS += axi_dmac_hw.tcl diff --git a/library/axi_dmac/axi_dmac.v b/library/axi_dmac/axi_dmac.v index 7bd44b27a..faa11cdf9 100644 --- a/library/axi_dmac/axi_dmac.v +++ b/library/axi_dmac/axi_dmac.v @@ -285,6 +285,19 @@ localparam DMA_LENGTH_ALIGN = BYTES_PER_BEAT_WIDTH_DEST < BYTES_PER_BEAT_WIDTH_SRC ? BYTES_PER_BEAT_WIDTH_SRC : BYTES_PER_BEAT_WIDTH_DEST; +localparam BYTES_PER_BURST_WIDTH = + REAL_MAX_BYTES_PER_BURST > 2048 ? 12 : + REAL_MAX_BYTES_PER_BURST > 1024 ? 11 : + REAL_MAX_BYTES_PER_BURST > 512 ? 10 : + REAL_MAX_BYTES_PER_BURST > 256 ? 9 : + REAL_MAX_BYTES_PER_BURST > 128 ? 8 : + REAL_MAX_BYTES_PER_BURST > 64 ? 7 : + REAL_MAX_BYTES_PER_BURST > 32 ? 6 : + REAL_MAX_BYTES_PER_BURST > 16 ? 5 : + REAL_MAX_BYTES_PER_BURST > 8 ? 4 : + REAL_MAX_BYTES_PER_BURST > 4 ? 3 : + REAL_MAX_BYTES_PER_BURST > 2 ? 2 : 1; + // ID signals from the DMAC, just for debugging wire [ID_WIDTH-1:0] dest_request_id; wire [ID_WIDTH-1:0] dest_data_id; @@ -325,6 +338,10 @@ assign m_src_axi_arid = 'h0; assign m_src_axi_arlock = 'h0; wire up_req_eot; +wire [BYTES_PER_BURST_WIDTH-1:0] up_req_measured_burst_length; +wire up_response_partial; +wire up_response_valid; +wire up_response_ready; wire ctrl_enable; wire ctrl_pause; @@ -358,6 +375,7 @@ axi_dmac_regmap #( .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), @@ -410,6 +428,10 @@ axi_dmac_regmap #( // DMA response interface .response_eot(up_req_eot), + .response_measured_burst_length(up_req_measured_burst_length), + .response_partial(up_response_partial), + .response_valid(up_response_valid), + .response_ready(up_response_ready), // Debug interface .dbg_dest_addr(m_dest_axi_awaddr), @@ -425,6 +447,7 @@ axi_dmac_transfer #( .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), .DMA_TYPE_DEST(DMA_TYPE_DEST), .DMA_TYPE_SRC(DMA_TYPE_SRC), .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), @@ -459,6 +482,10 @@ axi_dmac_transfer #( .req_last(up_dma_req_last), .req_eot(up_req_eot), + .req_measured_burst_length(up_req_measured_burst_length), + .req_response_partial(up_response_partial), + .req_response_valid(up_response_valid), + .req_response_ready(up_response_ready), .m_dest_axi_aclk(m_dest_axi_aclk), .m_dest_axi_aresetn(m_dest_axi_aresetn), diff --git a/library/axi_dmac/axi_dmac_burst_memory.v b/library/axi_dmac/axi_dmac_burst_memory.v index f4039e9cb..853fb0784 100644 --- a/library/axi_dmac/axi_dmac_burst_memory.v +++ b/library/axi_dmac/axi_dmac_burst_memory.v @@ -39,6 +39,8 @@ module axi_dmac_burst_memory #( parameter ID_WIDTH = 3, parameter MAX_BYTES_PER_BURST = 128, parameter ASYNC_CLK = 1, + parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DATA_WIDTH_SRC/8), + parameter BYTES_PER_BURST_WIDTH = $clog2(MAX_BYTES_PER_BURST), parameter ENABLE_DIAGNOSTICS_IF = 0 ) ( input src_clk, @@ -47,6 +49,8 @@ module axi_dmac_burst_memory #( input src_data_valid, input [DATA_WIDTH_SRC-1:0] src_data, input src_data_last, + input [BYTES_PER_BEAT_WIDTH_SRC-1:0] src_data_valid_bytes, + input src_data_partial_burst, output [ID_WIDTH-1:0] src_data_request_id, @@ -58,6 +62,11 @@ module axi_dmac_burst_memory #( output [DATA_WIDTH_DEST-1:0] dest_data, output dest_data_last, + output [BYTES_PER_BURST_WIDTH-1:0] dest_burst_info_length, + output dest_burst_info_partial, + output [ID_WIDTH-1:0] dest_burst_info_id, + output reg dest_burst_info_write = 1'b0, + output [ID_WIDTH-1:0] dest_request_id, input [ID_WIDTH-1:0] dest_data_request_id, output [ID_WIDTH-1:0] dest_data_response_id, @@ -83,6 +92,16 @@ localparam ADDRESS_WIDTH = BURST_LEN_WIDTH + ID_WIDTH - 1; localparam AUX_FIFO_SIZE = 2**(ID_WIDTH-1); +localparam DEST_SRC_RATIO = DATA_WIDTH_DEST/DATA_WIDTH_SRC; + +localparam DEST_SRC_RATIO_WIDTH = DEST_SRC_RATIO > 64 ? 7 : + DEST_SRC_RATIO > 32 ? 6 : + DEST_SRC_RATIO > 16 ? 5 : + DEST_SRC_RATIO > 8 ? 4 : + DEST_SRC_RATIO > 4 ? 3 : + DEST_SRC_RATIO > 2 ? 2 : + DEST_SRC_RATIO > 1 ? 1 : 0; + /* * The burst memory is separated into 2**(ID_WIDTH-1) segments. Each segment can * hold up to BURST_LEN beats. The addresses that are used to access the memory @@ -117,12 +136,15 @@ reg dest_id_reduced_msb_next = 1'b0; reg dest_id_reduced_msb = 1'b0; reg [ID_WIDTH-1:0] dest_id = 'h0; reg [BURST_LEN_WIDTH-1:0] dest_beat_counter = 'h00; -reg [BURST_LEN_WIDTH-1:0] dest_burst_len = 'h00; +wire [BURST_LEN_WIDTH-1:0] dest_burst_len; reg dest_valid = 1'b0; reg dest_mem_data_valid = 1'b0; reg dest_mem_data_last = 1'b0; -reg [BURST_LEN_WIDTH-1:0] burst_len_mem[0:AUX_FIFO_SIZE-1]; +reg [BYTES_PER_BURST_WIDTH+1-1:0] burst_len_mem[0:AUX_FIFO_SIZE-1]; + +wire [BYTES_PER_BURST_WIDTH+1-1:0] src_burst_len_data; +reg [BYTES_PER_BURST_WIDTH+1-1:0] dest_burst_len_data = 'h00; wire src_beat; wire src_last_beat; @@ -193,7 +215,7 @@ end always @(posedge src_clk) begin if (src_last_beat == 1'b1) begin - burst_len_mem[src_id_reduced] <= src_beat_counter; + burst_len_mem[src_id_reduced] <= src_burst_len_data; end end @@ -271,7 +293,7 @@ end always @(posedge dest_clk) begin if (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1) begin - dest_burst_len <= burst_len_mem[dest_id_reduced_next]; + dest_burst_len_data <= burst_len_mem[dest_id_reduced_next]; end end @@ -290,6 +312,58 @@ always @(posedge dest_clk) begin end end +assign dest_burst_info_length = dest_burst_len_data[BYTES_PER_BURST_WIDTH-1:0]; +assign dest_burst_info_partial = dest_burst_len_data[BYTES_PER_BURST_WIDTH]; +assign dest_burst_info_id = dest_id; + +always @(posedge dest_clk) begin + dest_burst_info_write <= (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1); +end + +// If destination is wider track the number of source beats in a destination +// beat in case the stream is not destination width aligned. +generate if (DATA_WIDTH_SRC < DATA_WIDTH_DEST) begin + + reg [DEST_SRC_RATIO_WIDTH-1:0] src_num_beats = {DEST_SRC_RATIO_WIDTH{1'b1}}; + reg [BYTES_PER_BEAT_WIDTH_SRC-1:0] src_data_valid_bytes_d = 'h00; + reg src_data_partial_burst_d = 'h0; + + // This counter will hold the number of source beat in a destination beat + // minus one + always @(posedge src_clk) begin + if (src_mem_data_last == 1'b1 && src_mem_data_valid == 1'b1) begin + if (src_data_valid) begin + src_num_beats <= {DEST_SRC_RATIO_WIDTH{1'b0}}; + end else begin + src_num_beats <= {DEST_SRC_RATIO_WIDTH{1'b1}}; + end + end else if (src_data_valid) begin + src_num_beats <= src_num_beats + 1'b1; + end + end + + // Compensate the delay through the resize block + always @(posedge src_clk) begin + if (src_data_valid == 1'b1) begin + src_data_valid_bytes_d <= src_data_valid_bytes; + src_data_partial_burst_d <= src_data_partial_burst; + end + end + + assign src_burst_len_data = {src_data_partial_burst_d, + src_beat_counter, + src_num_beats, + src_data_valid_bytes_d}; +end else begin + + assign src_burst_len_data = {src_data_partial_burst, + src_beat_counter, + src_data_valid_bytes}; +end +endgenerate + +assign dest_burst_len = dest_burst_len_data[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH]; + axi_dmac_resize_src #( .DATA_WIDTH_SRC (DATA_WIDTH_SRC), .DATA_WIDTH_MEM (DATA_WIDTH) diff --git a/library/axi_dmac/axi_dmac_constr.sdc b/library/axi_dmac/axi_dmac_constr.sdc index a706cb8fb..2e4829794 100644 --- a/library/axi_dmac/axi_dmac_constr.sdc +++ b/library/axi_dmac/axi_dmac_constr.sdc @@ -3,6 +3,7 @@ set_false_path -to [get_registers *axi_dmac*cdc_sync_stage1*] set_false_path -from [get_registers *axi_dmac*cdc_sync_fifo_ram*] set_false_path -from [get_registers *axi_dmac*eot_mem*] +set_false_path -from [get_registers *axi_dmac*bl_mem*] # Burst memory set_false_path -from [get_registers *axi_dmac*burst_len_mem*] diff --git a/library/axi_dmac/axi_dmac_hw.tcl b/library/axi_dmac/axi_dmac_hw.tcl index 216bed9be..d6aed7bbe 100644 --- a/library/axi_dmac/axi_dmac_hw.tcl +++ b/library/axi_dmac/axi_dmac_hw.tcl @@ -18,6 +18,7 @@ ad_ip_files axi_dmac [list \ $ad_hdl_dir/library/util_cdc/sync_bits.v \ $ad_hdl_dir/library/common/up_axi.v \ $ad_hdl_dir/library/util_axis_fifo/util_axis_fifo.v \ + $ad_hdl_dir/library/util_axis_fifo/address_sync.v \ $ad_hdl_dir/library/common/ad_mem.v \ inc_id.vh \ resp.vh \ @@ -27,6 +28,7 @@ ad_ip_files axi_dmac [list \ axi_dmac_reset_manager.v \ axi_dmac_resize_dest.v \ axi_dmac_resize_src.v \ + axi_dmac_response_manager.v \ axi_dmac_transfer.v \ address_generator.v \ data_mover.v \ diff --git a/library/axi_dmac/axi_dmac_ip.tcl b/library/axi_dmac/axi_dmac_ip.tcl index bd89260df..2e07e200b 100644 --- a/library/axi_dmac/axi_dmac_ip.tcl +++ b/library/axi_dmac/axi_dmac_ip.tcl @@ -15,6 +15,7 @@ adi_ip_files axi_dmac [list \ "axi_dmac_reset_manager.v" \ "axi_dmac_resize_dest.v" \ "axi_dmac_resize_src.v" \ + "axi_dmac_response_manager.v" \ "axi_dmac_transfer.v" \ "address_generator.v" \ "data_mover.v" \ diff --git a/library/axi_dmac/axi_dmac_regmap.v b/library/axi_dmac/axi_dmac_regmap.v index 01616205c..de117bd46 100644 --- a/library/axi_dmac/axi_dmac_regmap.v +++ b/library/axi_dmac/axi_dmac_regmap.v @@ -38,6 +38,7 @@ module axi_dmac_regmap #( parameter DISABLE_DEBUG_REGISTERS = 0, parameter BYTES_PER_BEAT_WIDTH_DEST = 1, parameter BYTES_PER_BEAT_WIDTH_SRC = 1, + parameter BYTES_PER_BURST_WIDTH = 7, parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_LENGTH_WIDTH = 24, parameter DMA_LENGTH_ALIGN = 3, @@ -95,6 +96,10 @@ module axi_dmac_regmap #( // DMA response interface input response_eot, + input [BYTES_PER_BURST_WIDTH-1:0] response_measured_burst_length, + input response_partial, + input response_valid, + output response_ready, // Debug interface input [DMA_AXI_ADDR_WIDTH-1:0] dbg_src_addr, @@ -104,7 +109,7 @@ module axi_dmac_regmap #( input [31:0] dbg_ids1 ); -localparam PCORE_VERSION = 'h00040161; +localparam PCORE_VERSION = 'h00040261; // Register interface signals reg [31:0] up_rdata = 32'h00; @@ -209,6 +214,7 @@ axi_dmac_regmap_request #( .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), @@ -224,6 +230,7 @@ axi_dmac_regmap_request #( .up_eot(up_eot), .up_wreq(up_wreq), + .up_rreq(up_rreq), .up_waddr(up_waddr), .up_wdata(up_wdata), .up_raddr(up_raddr), @@ -242,7 +249,11 @@ axi_dmac_regmap_request #( .request_sync_transfer_start(request_sync_transfer_start), .request_last(request_last), - .response_eot(response_eot) + .response_eot(response_eot), + .response_measured_burst_length(response_measured_burst_length), + .response_partial(response_partial), + .response_valid(response_valid), + .response_ready(response_ready) ); up_axi #( diff --git a/library/axi_dmac/axi_dmac_regmap_request.v b/library/axi_dmac/axi_dmac_regmap_request.v index 03ddb3cbe..b2d487140 100644 --- a/library/axi_dmac/axi_dmac_regmap_request.v +++ b/library/axi_dmac/axi_dmac_regmap_request.v @@ -37,6 +37,7 @@ module axi_dmac_regmap_request #( parameter DISABLE_DEBUG_REGISTERS = 0, parameter BYTES_PER_BEAT_WIDTH_DEST = 1, parameter BYTES_PER_BEAT_WIDTH_SRC = 1, + parameter BYTES_PER_BURST_WIDTH = 7, parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_LENGTH_WIDTH = 24, parameter DMA_LENGTH_ALIGN = 3, @@ -55,6 +56,7 @@ module axi_dmac_regmap_request #( // Register map interface input up_wreq, + input up_rreq, input [8:0] up_waddr, input [31:0] up_wdata, input [8:0] up_raddr, @@ -76,9 +78,16 @@ module axi_dmac_regmap_request #( output request_last, // DMA response interface - input response_eot + input response_eot, + input [BYTES_PER_BURST_WIDTH-1:0] response_measured_burst_length, + input response_partial, + input response_valid, + output reg response_ready = 1'b1 + ); +localparam MEASURED_LENGTH_WIDTH = (DMA_2D_TRANSFER == 1) ? 32 : DMA_LENGTH_WIDTH; + // DMA transfer signals reg up_dma_req_valid = 1'b0; wire up_dma_req_ready; @@ -92,6 +101,20 @@ reg [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] up_dma_src_address = 'h00; reg [DMA_LENGTH_WIDTH-1:0] up_dma_x_length = {DMA_LENGTH_ALIGN{1'b1}}; reg up_dma_cyclic = DMA_CYCLIC ? 1'b1 : 1'b0; reg up_dma_last = 1'b1; +reg up_dma_enable_tlen_reporting = 1'b0; + +wire up_tlf_s_ready; +reg up_tlf_s_valid = 1'b0; + +wire [MEASURED_LENGTH_WIDTH+2-1:0] up_tlf_data; +wire up_tlf_valid; +wire up_tlf_rd; +reg up_partial_length_valid = 1'b0; + +reg [MEASURED_LENGTH_WIDTH-1:0] up_measured_transfer_length = 'h0; +reg up_clear_tl = 1'b0; +reg [1:0] up_transfer_id_eot_d = 'h0; +wire up_bl_partial; assign request_dest_address = up_dma_dest_address; assign request_src_address = up_dma_src_address; @@ -107,6 +130,7 @@ always @(posedge clk) begin up_dma_req_valid <= 1'b0; up_dma_cyclic <= DMA_CYCLIC ? 1'b1 : 1'b0; up_dma_last <= 1'b1; + up_dma_enable_tlen_reporting <= 1'b0; end else begin if (ctrl_enable == 1'b1) begin if (up_wreq == 1'b1 && up_waddr == 9'h102) begin @@ -123,6 +147,7 @@ always @(posedge clk) begin 9'h103: begin if (DMA_CYCLIC) up_dma_cyclic <= up_wdata[0]; up_dma_last <= up_wdata[1]; + up_dma_enable_tlen_reporting <= up_wdata[2]; end 9'h104: up_dma_dest_address <= up_wdata[DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST]; 9'h105: up_dma_src_address <= up_wdata[DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC]; @@ -136,15 +161,19 @@ always @(*) begin case (up_raddr) 9'h101: up_rdata <= up_transfer_id; 9'h102: up_rdata <= up_dma_req_valid; - 9'h103: up_rdata <= {30'h00, up_dma_last, up_dma_cyclic}; // Flags + 9'h103: up_rdata <= {29'h00, up_dma_enable_tlen_reporting, up_dma_last, up_dma_cyclic}; // Flags 9'h104: up_rdata <= HAS_DEST_ADDR ? {up_dma_dest_address,{BYTES_PER_BEAT_WIDTH_DEST{1'b0}}} : 'h00; 9'h105: up_rdata <= HAS_SRC_ADDR ? {up_dma_src_address,{BYTES_PER_BEAT_WIDTH_SRC{1'b0}}} : 'h00; 9'h106: up_rdata <= up_dma_x_length; 9'h107: up_rdata <= request_y_length; 9'h108: up_rdata <= request_dest_stride; 9'h109: up_rdata <= request_src_stride; - 9'h10a: up_rdata <= up_transfer_done_bitmap; + 9'h10a: up_rdata <= {up_partial_length_valid,27'b0,up_transfer_done_bitmap}; 9'h10b: up_rdata <= up_transfer_id_eot; + 9'h10c: up_rdata <= 32'h0; + 9'h112: up_rdata <= up_measured_transfer_length; + 9'h113: up_rdata <= up_tlf_data[MEASURED_LENGTH_WIDTH-1 : 0]; // Length + 9'h114: up_rdata <= up_tlf_data[MEASURED_LENGTH_WIDTH+: 2]; // ID default: up_rdata <= 32'h00; endcase end @@ -180,7 +209,7 @@ endgenerate // In cyclic mode the same transfer is submitted over and over again assign up_sot = up_dma_cyclic ? 1'b0 : up_dma_req_valid & up_dma_req_ready; -assign up_eot = up_dma_cyclic ? 1'b0 : response_eot; +assign up_eot = up_dma_cyclic ? 1'b0 : response_eot & response_valid & response_ready; assign request_valid = up_dma_req_valid; assign up_dma_req_ready = request_ready; @@ -204,4 +233,74 @@ always @(posedge clk) begin end end +assign up_tlf_rd = up_rreq && up_raddr == 'h114; +assign up_bl_partial = response_valid & response_ready & response_partial & up_dma_enable_tlen_reporting; + +always @(posedge clk) begin + if (ctrl_enable == 1'b0) begin + up_partial_length_valid <= 1'b0; + end else begin + if (up_bl_partial == 1'b1) begin + up_partial_length_valid <= 1'b1; + end else if (up_tlf_rd == 1'b1) begin + up_partial_length_valid <= 1'b0; + end else if (up_tlf_valid == 1'b1) begin + up_partial_length_valid <= 1'b1; + end + end +end + +always @(posedge clk) +begin + if (response_valid == 1'b1 & response_ready == 1'b1) begin + up_measured_transfer_length <= up_measured_transfer_length + response_measured_burst_length + 1'b1; + up_transfer_id_eot_d <= up_transfer_id_eot; + end else if (up_clear_tl == 1'b1) begin + up_measured_transfer_length <= 'h0; + end +end + +always @(posedge clk) +begin + if (ctrl_enable == 1'b0) begin + response_ready <= 1'b1; + end else if (response_ready == 1'b1) begin + response_ready <= ~response_valid; + end else if (up_tlf_s_ready == 1'b1) begin + response_ready <= 1'b1; + end +end + +always @(posedge clk) +begin + if (response_valid == 1'b1 && response_ready == 1'b1) begin + up_tlf_s_valid <= up_bl_partial; + up_clear_tl <= up_eot; + end else if (up_tlf_s_ready == 1'b1) begin + up_tlf_s_valid <= 1'b0; + end +end + +// Buffer the length and transfer ID of partial transfers +util_axis_fifo #( + .DATA_WIDTH(MEASURED_LENGTH_WIDTH + 2), + .ADDRESS_WIDTH(2), + .ASYNC_CLK(0) +) i_transfer_lenghts_fifo ( + .s_axis_aclk(clk), + .s_axis_aresetn(ctrl_enable), + .s_axis_valid(up_tlf_s_valid), + .s_axis_ready(up_tlf_s_ready), + .s_axis_empty(), + .s_axis_data({up_transfer_id_eot_d, up_measured_transfer_length}), + .s_axis_room(), + + .m_axis_aclk(clk), + .m_axis_aresetn(ctrl_enable), + .m_axis_valid(up_tlf_valid), + .m_axis_ready(up_tlf_rd & up_tlf_valid), + .m_axis_data(up_tlf_data), + .m_axis_level() +); + endmodule diff --git a/library/axi_dmac/axi_dmac_resize_src.v b/library/axi_dmac/axi_dmac_resize_src.v index 22351ec57..408acb64c 100644 --- a/library/axi_dmac/axi_dmac_resize_src.v +++ b/library/axi_dmac/axi_dmac_resize_src.v @@ -72,8 +72,12 @@ end else begin valid <= 1'b0; mask <= 'h1; end else if (src_data_valid == 1'b1) begin - valid <= mask[RATIO-1]; - mask <= {mask[RATIO-2:0],mask[RATIO-1]}; + valid <= mask[RATIO-1] || src_data_last; + if (src_data_last) begin + mask <= 'h1; + end else begin + mask <= {mask[RATIO-2:0],mask[RATIO-1]}; + end end else begin valid <= 1'b0; end diff --git a/library/axi_dmac/axi_dmac_response_manager.v b/library/axi_dmac/axi_dmac_response_manager.v new file mode 100644 index 000000000..1550de812 --- /dev/null +++ b/library/axi_dmac/axi_dmac_response_manager.v @@ -0,0 +1,215 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsibilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +module axi_dmac_response_manager #( + parameter DMA_DATA_WIDTH_SRC = 64, + parameter DMA_DATA_WIDTH_DEST = 64, + parameter DMA_LENGTH_WIDTH = 24, + parameter BYTES_PER_BURST_WIDTH = 7, + parameter BYTES_PER_BEAT_WIDTH_SRC = $clog2(DMA_DATA_WIDTH_SRC/8), + parameter ASYNC_CLK_DEST_REQ = 1 +)( + // Interface to destination side + input dest_clk, + input dest_resetn, + + input dest_response_valid, + output dest_response_ready, + input [1:0] dest_response_resp, + input dest_response_partial, + input dest_response_resp_eot, + input [BYTES_PER_BURST_WIDTH-1:0] dest_response_data_burst_length, + + // Interface to processor + input req_clk, + input req_resetn, + + output response_eot, + output reg [BYTES_PER_BURST_WIDTH-1:0] measured_burst_length = 'h0, + output response_partial, + output reg response_valid = 1'b0, + input response_ready + + // Interface to requester side +); + +localparam STATE_IDLE = 2'h0; +localparam STATE_ACC = 2'h1; +localparam STATE_WRITE_RESPR = 2'h2; + +reg [1:0] state = STATE_IDLE; +reg [1:0] nx_state; + +localparam DEST_SRC_RATIO = DMA_DATA_WIDTH_DEST/DMA_DATA_WIDTH_SRC; + +localparam DEST_SRC_RATIO_WIDTH = DEST_SRC_RATIO > 64 ? 7 : + DEST_SRC_RATIO > 32 ? 6 : + DEST_SRC_RATIO > 16 ? 5 : + DEST_SRC_RATIO > 8 ? 4 : + DEST_SRC_RATIO > 4 ? 3 : + DEST_SRC_RATIO > 2 ? 2 : + DEST_SRC_RATIO > 1 ? 1 : 0; + +localparam BYTES_PER_BEAT_WIDTH = DEST_SRC_RATIO_WIDTH + BYTES_PER_BEAT_WIDTH_SRC; +localparam BURST_LEN_WIDTH = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH; + +wire do_acc_st; +reg req_eot = 1'b0; +reg req_response_partial = 1'b0; +reg [BYTES_PER_BURST_WIDTH-1:0] req_response_dest_data_burst_length = 'h0; + +wire response_dest_valid; +reg response_dest_ready = 1'b1; +wire [1:0] response_dest_resp; +wire response_dest_resp_eot; +wire [BYTES_PER_BURST_WIDTH-1:0] response_dest_data_burst_length; + +wire [BURST_LEN_WIDTH-1:0] burst_lenght; +reg [BURST_LEN_WIDTH-1:0] burst_pointer_end; + +util_axis_fifo #( + .DATA_WIDTH(BYTES_PER_BURST_WIDTH+1+1), + .ADDRESS_WIDTH(0), + .ASYNC_CLK(ASYNC_CLK_DEST_REQ) +) i_dest_response_fifo ( + .s_axis_aclk(dest_clk), + .s_axis_aresetn(dest_resetn), + .s_axis_valid(dest_response_valid), + .s_axis_ready(dest_response_ready), + .s_axis_empty(), + .s_axis_data({dest_response_data_burst_length, + dest_response_partial, + dest_response_resp_eot}), + .s_axis_room(), + + .m_axis_aclk(req_clk), + .m_axis_aresetn(req_resetn), + .m_axis_valid(response_dest_valid), + .m_axis_ready(response_dest_ready), + .m_axis_data({response_dest_data_burst_length, + response_dest_partial, + response_dest_resp_eot}), + .m_axis_level() +); + +always @(posedge req_clk) +begin + if (response_dest_valid & response_dest_ready) begin + req_eot <= response_dest_resp_eot; + req_response_partial <= response_dest_partial; + req_response_dest_data_burst_length <= response_dest_data_burst_length; + end +end + +always @(posedge req_clk) +begin + if (req_resetn == 1'b0) begin + response_dest_ready <= 1'b1; + end else begin + response_dest_ready <= (nx_state == STATE_IDLE); + end +end + +assign response_eot = (state == STATE_WRITE_RESPR) ? req_eot : 1'b1; +assign response_partial = (state == STATE_WRITE_RESPR) ? req_response_partial : 1'b0; + +always @(posedge req_clk) +begin + if (req_resetn == 1'b0) begin + response_valid <= 1'b0; + end else begin + if (nx_state == STATE_WRITE_RESPR) begin + response_valid <= 1'b1; + end else if (response_ready == 1'b1) begin + response_valid <= 1'b0; + end + end +end + +// transform the free running pointer from burst memory into burst length +assign burst_lenght = req_response_dest_data_burst_length[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH] - + burst_pointer_end - 1'b1; + +always @(posedge req_clk) +begin + if (req_resetn == 1'b0) begin + burst_pointer_end <= {BURST_LEN_WIDTH{1'b1}}; + end else if (state == STATE_ACC) begin + burst_pointer_end <= req_response_dest_data_burst_length[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH]; + end +end + +always @(posedge req_clk) +begin + if (state == STATE_ZERO_COMPL) begin + measured_burst_length <= {BYTES_PER_BURST_WIDTH{1'b1}}; + end else if (state == STATE_ACC) begin + measured_burst_length[BYTES_PER_BURST_WIDTH-1 -: BURST_LEN_WIDTH] <= burst_lenght; + measured_burst_length[BYTES_PER_BEAT_WIDTH-1 : 0] <= + req_response_dest_data_burst_length[BYTES_PER_BEAT_WIDTH-1: 0]; + end +end + +always @(*) begin + nx_state = state; + case (state) + STATE_IDLE: begin + if (response_dest_valid == 1'b1) begin + nx_state = STATE_ACC; + end + end + STATE_ACC: begin + nx_state = STATE_WRITE_RESPR; + end + STATE_WRITE_RESPR: begin + if (response_ready == 1'b1) begin + nx_state = STATE_IDLE; + end + end + default: begin + nx_state = STATE_IDLE; + end + endcase +end + +always @(posedge req_clk) begin + if (req_resetn == 1'b0) begin + state <= STATE_IDLE; + end else begin + state <= nx_state; + end +end + +endmodule diff --git a/library/axi_dmac/axi_dmac_transfer.v b/library/axi_dmac/axi_dmac_transfer.v index 3560a2242..21e78338e 100644 --- a/library/axi_dmac/axi_dmac_transfer.v +++ b/library/axi_dmac/axi_dmac_transfer.v @@ -49,6 +49,7 @@ module axi_dmac_transfer #( parameter AXI_SLICE_DEST = 0, parameter AXI_SLICE_SRC = 0, parameter MAX_BYTES_PER_BURST = 128, + parameter BYTES_PER_BURST_WIDTH = 7, parameter FIFO_SIZE = 8, parameter ID_WIDTH = $clog2(FIFO_SIZE*2), parameter AXI_LENGTH_WIDTH_SRC = 8, @@ -74,6 +75,10 @@ module axi_dmac_transfer #( input req_last, output req_eot, + output [BYTES_PER_BURST_WIDTH-1:0] req_measured_burst_length, + output req_response_partial, + output req_response_valid, + input req_response_ready, // Master AXI interface input m_dest_axi_aclk, @@ -172,7 +177,11 @@ wire dma_req_ready; wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] dma_req_dest_address; wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] dma_req_src_address; wire [DMA_LENGTH_WIDTH-1:0] dma_req_length; +wire [BYTES_PER_BURST_WIDTH-1:0] dma_req_measured_burst_length; wire dma_req_eot; +wire dma_response_valid; +wire dma_response_ready; +wire dma_response_partial; wire dma_req_sync_transfer_start; wire dma_req_last; @@ -196,6 +205,7 @@ wire src_enabled; wire req_valid_gated; wire req_ready_gated; + axi_dmac_reset_manager #( .ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC), .ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST), @@ -240,6 +250,7 @@ generate if (DMA_2D_TRANSFER == 1) begin dmac_2d_transfer #( .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .DMA_LENGTH_WIDTH (DMA_LENGTH_WIDTH), + .BYTES_PER_BURST_WIDTH (BYTES_PER_BURST_WIDTH), .BYTES_PER_BEAT_WIDTH_DEST (BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_SRC (BYTES_PER_BEAT_WIDTH_SRC) ) i_2d_transfer ( @@ -247,6 +258,10 @@ dmac_2d_transfer #( .req_aresetn (req_resetn), .req_eot (req_eot), + .req_measured_burst_length (req_measured_burst_length), + .req_response_partial (req_response_partial), + .req_response_valid (req_response_valid), + .req_response_ready (req_response_ready), .req_valid (req_valid_gated), .req_ready (req_ready_gated), @@ -266,8 +281,12 @@ dmac_2d_transfer #( .out_req_length (dma_req_length), .out_req_sync_transfer_start (dma_req_sync_transfer_start), .out_req_last (dma_req_last), - .out_eot (dma_req_eot) -); + .out_eot (dma_req_eot), + .out_measured_burst_length (dma_req_measured_burst_length), + .out_response_partial (dma_response_partial), + .out_response_valid (dma_response_valid), + .out_response_ready (dma_response_ready) + ); end else begin @@ -283,6 +302,10 @@ assign dma_req_last = req_last; /* Response */ assign req_eot = dma_req_eot; +assign req_measured_burst_length = dma_req_measured_burst_length; +assign req_response_partial = dma_response_partial; +assign req_response_valid = dma_response_valid; +assign dma_response_ready = req_response_ready; end endgenerate @@ -301,6 +324,7 @@ dmac_request_arb #( .AXI_SLICE_DEST (AXI_SLICE_DEST), .AXI_SLICE_SRC (AXI_SLICE_SRC), .MAX_BYTES_PER_BURST (MAX_BYTES_PER_BURST), + .BYTES_PER_BURST_WIDTH (BYTES_PER_BURST_WIDTH), .FIFO_SIZE (FIFO_SIZE), .ID_WIDTH (ID_WIDTH), .AXI_LENGTH_WIDTH_DEST (AXI_LENGTH_WIDTH_DEST), @@ -319,6 +343,10 @@ dmac_request_arb #( .req_sync_transfer_start (dma_req_sync_transfer_start), .eot (dma_req_eot), + .measured_burst_length(dma_req_measured_burst_length), + .response_partial (dma_response_partial), + .response_valid (dma_response_valid), + .response_ready (dma_response_ready), .req_enable (req_enable), diff --git a/library/axi_dmac/data_mover.v b/library/axi_dmac/data_mover.v index 95c186d2a..fcd61d4c6 100644 --- a/library/axi_dmac/data_mover.v +++ b/library/axi_dmac/data_mover.v @@ -65,6 +65,7 @@ module dmac_data_mover #( output m_axi_valid, output [DATA_WIDTH-1:0] m_axi_data, output m_axi_last, + output m_axi_partial_burst, input req_valid, output req_ready, @@ -140,9 +141,12 @@ generate if (ALLOW_ABORT == 1) begin end assign transfer_abort_s = transfer_abort; + assign m_axi_partial_burst = (transfer_abort == 1'b0) && (s_axi_last == 1'b1) && + !(last == 1'b1 && eot == 1'b1 && req_xlast_d == 1'b1); end else begin assign transfer_abort_s = 1'b0; + assign m_axi_partial_burst = 1'b0; end endgenerate /* diff --git a/library/axi_dmac/dest_axi_mm.v b/library/axi_dmac/dest_axi_mm.v index 5609a0220..a38d0c51f 100644 --- a/library/axi_dmac/dest_axi_mm.v +++ b/library/axi_dmac/dest_axi_mm.v @@ -40,6 +40,8 @@ module dmac_dest_mm_axi #( parameter DMA_ADDR_WIDTH = 32, parameter BYTES_PER_BEAT_WIDTH = $clog2(DMA_DATA_WIDTH/8), parameter BEATS_PER_BURST_WIDTH = 4, + parameter MAX_BYTES_PER_BURST = 128, + parameter BYTES_PER_BURST_WIDTH = $clog2(MAX_BYTES_PER_BURST), parameter AXI_LENGTH_WIDTH = 8)( input m_axi_aclk, @@ -60,6 +62,8 @@ module dmac_dest_mm_axi #( input response_ready, output [1:0] response_resp, output response_resp_eot, + output response_resp_partial, + output [BYTES_PER_BURST_WIDTH-1:0] response_data_burst_length, input [ID_WIDTH-1:0] request_id, output [ID_WIDTH-1:0] response_id, @@ -73,6 +77,10 @@ module dmac_dest_mm_axi #( input [DMA_DATA_WIDTH-1:0] fifo_data, input fifo_last, + input [BYTES_PER_BURST_WIDTH-1:0] dest_burst_info_length, + input dest_burst_info_partial, + input [ID_WIDTH-1:0] dest_burst_info_id, + input dest_burst_info_write, // Write address input m_axi_awready, output m_axi_awvalid, @@ -165,4 +173,17 @@ dmac_response_handler #( .resp_eot(response_resp_eot) ); +reg [BYTES_PER_BURST_WIDTH+1-1:0] bl_mem [0:2**(ID_WIDTH)-1]; + +assign {response_resp_partial, + response_data_burst_length} = bl_mem[response_id]; + +always @(posedge m_axi_aclk) begin + if (dest_burst_info_write) begin + bl_mem[dest_burst_info_id] <= {dest_burst_info_partial, + dest_burst_info_length}; + end +end + + endmodule diff --git a/library/axi_dmac/request_arb.v b/library/axi_dmac/request_arb.v index b1f27489f..acc8e0f75 100644 --- a/library/axi_dmac/request_arb.v +++ b/library/axi_dmac/request_arb.v @@ -48,6 +48,7 @@ module dmac_request_arb #( parameter AXI_SLICE_DEST = 0, parameter AXI_SLICE_SRC = 0, parameter MAX_BYTES_PER_BURST = 128, + parameter BYTES_PER_BURST_WIDTH = 7, parameter FIFO_SIZE = 8, parameter ID_WIDTH = $clog2(FIFO_SIZE*2), parameter AXI_LENGTH_WIDTH_SRC = 8, @@ -65,7 +66,11 @@ module dmac_request_arb #( input req_xlast, input req_sync_transfer_start, - output reg eot, + output eot, + output [BYTES_PER_BURST_WIDTH-1:0] measured_burst_length, + output response_partial, + output response_valid, + input response_ready, // Master AXI interface input m_dest_axi_aclk, @@ -181,23 +186,13 @@ localparam DMA_ADDRESS_WIDTH_SRC = DMA_AXI_ADDR_WIDTH - BYTES_PER_BEAT_WIDTH_SRC // Bytes per burst is the same for both dest and src, but bytes per beat may // differ, so beats per burst may also differ -localparam BYTES_PER_BURST_WIDTH = - MAX_BYTES_PER_BURST > 2048 ? 12 : - MAX_BYTES_PER_BURST > 1024 ? 11 : - MAX_BYTES_PER_BURST > 512 ? 10 : - MAX_BYTES_PER_BURST > 256 ? 9 : - MAX_BYTES_PER_BURST > 128 ? 8 : - MAX_BYTES_PER_BURST > 64 ? 7 : - MAX_BYTES_PER_BURST > 32 ? 6 : - MAX_BYTES_PER_BURST > 16 ? 5 : - MAX_BYTES_PER_BURST > 8 ? 4 : - MAX_BYTES_PER_BURST > 4 ? 3 : - MAX_BYTES_PER_BURST > 2 ? 2 : 1; + localparam BEATS_PER_BURST_WIDTH_SRC = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH_SRC; localparam BEATS_PER_BURST_WIDTH_DEST = BYTES_PER_BURST_WIDTH - BYTES_PER_BEAT_WIDTH_DEST; localparam BURSTS_PER_TRANSFER_WIDTH = DMA_LENGTH_WIDTH - BYTES_PER_BURST_WIDTH; + reg eot_mem_src[0:2**ID_WIDTH-1]; reg eot_mem_dest[0:2**ID_WIDTH-1]; wire request_eot; @@ -224,9 +219,10 @@ wire dest_req_xlast; wire dest_response_valid; wire dest_response_ready; -wire dest_response_empty; wire [1:0] dest_response_resp; wire dest_response_resp_eot; +wire [BYTES_PER_BURST_WIDTH-1:0] dest_response_data_burst_length; +wire dest_response_partial; wire [ID_WIDTH-1:0] dest_request_id; wire [ID_WIDTH-1:0] dest_data_request_id; @@ -265,19 +261,21 @@ wire [ID_WIDTH-1:0] src_response_id; wire src_valid; wire [DMA_DATA_WIDTH_SRC-1:0] src_data; wire src_last; +wire src_partial_burst; wire src_fifo_valid; wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data; wire src_fifo_last; - -wire response_dest_valid; -wire response_dest_ready = 1'b1; -wire [1:0] response_dest_resp; -wire response_dest_resp_eot; +wire src_fifo_partial_burst; wire src_bl_valid; wire src_bl_ready; wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_burst_length; +wire [BYTES_PER_BURST_WIDTH-1:0] dest_burst_info_length; +wire dest_burst_info_partial; +wire [ID_WIDTH-1:0] dest_burst_info_id; +wire dest_burst_info_write; + /* Unused for now wire response_src_valid; wire response_src_ready = 1'b1; @@ -299,14 +297,6 @@ begin eot_mem_dest[source_id] <= source_eot; end -always @(posedge req_clk) -begin - if (req_resetn == 1'b0) begin - eot <= 1'b0; - end else begin - eot <= response_dest_valid & response_dest_ready & response_dest_resp_eot; - end -end generate if (DMA_TYPE_DEST == DMA_TYPE_MM_AXI) begin @@ -333,6 +323,8 @@ dmac_dest_mm_axi #( .DMA_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_WIDTH_DEST), + .MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), .AXI_LENGTH_WIDTH(AXI_LENGTH_WIDTH_DEST) ) i_dest_dma_mm ( .m_axi_aclk(m_dest_axi_aclk), @@ -353,6 +345,8 @@ dmac_dest_mm_axi #( .response_ready(dest_response_ready), .response_resp(dest_response_resp), .response_resp_eot(dest_response_resp_eot), + .response_resp_partial(dest_response_partial), + .response_data_burst_length(dest_response_data_burst_length), .request_id(dest_request_id), .response_id(dest_response_id), @@ -367,6 +361,11 @@ dmac_dest_mm_axi #( .fifo_data(dest_data), .fifo_last(dest_last), + .dest_burst_info_length(dest_burst_info_length), + .dest_burst_info_partial(dest_burst_info_partial), + .dest_burst_info_id(dest_burst_info_id), + .dest_burst_info_write(dest_burst_info_write), + .m_axi_awready(m_axi_awready), .m_axi_awvalid(m_axi_awvalid), .m_axi_awaddr(m_axi_awaddr), @@ -441,6 +440,9 @@ assign m_axi_bready = 1'b0; assign src_bl_ready = 1'b1; +assign dest_response_partial = 1'b0; +assign dest_response_data_burst_length = 'h0; + end if (DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin @@ -458,6 +460,7 @@ assign dest_data_request_id = dest_request_id; assign dbg_dest_address_id = 'h00; assign dbg_dest_data_id = data_id; + dmac_dest_axi_stream #( .ID_WIDTH(ID_WIDTH), .S_AXIS_DATA_WIDTH(DMA_DATA_WIDTH_DEST), @@ -581,6 +584,8 @@ wire src_address_eot = eot_mem_src[src_address_id]; assign dbg_src_address_id = src_address_id; assign dbg_src_data_id = src_data_id; +assign src_partial_burst = 1'b0; + dmac_src_mm_axi #( .ID_WIDTH(ID_WIDTH), .DMA_DATA_WIDTH(DMA_DATA_WIDTH_SRC), @@ -697,6 +702,7 @@ dmac_src_axi_stream #( .fifo_valid(src_valid), .fifo_data(src_data), .fifo_last(src_last), + .fifo_partial_burst(src_partial_burst), .s_axis_valid(s_axis_valid), .s_axis_ready(s_axis_ready), @@ -730,6 +736,7 @@ assign dbg_src_data_id = 'h00; assign src_response_valid = 1'b0; assign src_response_resp = 2'b0; */ +assign src_partial_burst = 1'b0; dmac_src_fifo_inf #( .ID_WIDTH(ID_WIDTH), @@ -828,7 +835,7 @@ sync_bits #( ); axi_register_slice #( - .DATA_WIDTH(DMA_DATA_WIDTH_SRC + 1), + .DATA_WIDTH(DMA_DATA_WIDTH_SRC + 2), .FORWARD_REGISTERED(AXI_SLICE_SRC), .BACKWARD_REGISTERED(0) ) i_src_slice ( @@ -836,10 +843,10 @@ axi_register_slice #( .resetn(src_resetn), .s_axi_valid(src_valid), .s_axi_ready(), - .s_axi_data({src_data,src_last}), + .s_axi_data({src_data,src_last,src_partial_burst}), .m_axi_valid(src_fifo_valid), .m_axi_ready(1'b1), /* No backpressure */ - .m_axi_data({src_fifo_data,src_fifo_last}) + .m_axi_data({src_fifo_data,src_fifo_last,src_fifo_partial_burst}) ); axi_dmac_burst_memory #( @@ -848,6 +855,8 @@ axi_dmac_burst_memory #( .ID_WIDTH(ID_WIDTH), .MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST), .ASYNC_CLK(ASYNC_CLK_SRC_DEST), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), .ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF) ) i_store_and_forward ( .src_clk(src_clk), @@ -855,6 +864,8 @@ axi_dmac_burst_memory #( .src_data_valid(src_fifo_valid), .src_data(src_fifo_data), .src_data_last(src_fifo_last), + .src_data_valid_bytes({BYTES_PER_BEAT_WIDTH_SRC{1'b1}}), + .src_data_partial_burst(src_fifo_partial_burst), .src_data_request_id(src_data_request_id), @@ -865,6 +876,11 @@ axi_dmac_burst_memory #( .dest_data(dest_fifo_data), .dest_data_last(dest_fifo_last), + .dest_burst_info_length(dest_burst_info_length), + .dest_burst_info_partial(dest_burst_info_partial), + .dest_burst_info_id(dest_burst_info_id), + .dest_burst_info_write(dest_burst_info_write), + .dest_request_id(dest_request_id), .dest_data_request_id(dest_data_request_id), .dest_data_response_id(dest_data_response_id), @@ -987,28 +1003,6 @@ splitter #( }) ); -util_axis_fifo #( - .DATA_WIDTH(1), - .ADDRESS_WIDTH(0), - .ASYNC_CLK(ASYNC_CLK_DEST_REQ) -) i_dest_response_fifo ( - .s_axis_aclk(dest_clk), - .s_axis_aresetn(dest_resetn), - .s_axis_valid(dest_response_valid), - .s_axis_ready(dest_response_ready), - .s_axis_empty(dest_response_empty), - .s_axis_data(dest_response_resp_eot), - .s_axis_room(), - - .m_axis_aclk(req_clk), - .m_axis_aresetn(req_resetn), - .m_axis_valid(response_dest_valid), - .m_axis_ready(response_dest_ready), - .m_axis_data(response_dest_resp_eot), - .m_axis_level() -); - - /* Unused for now util_axis_fifo #( .DATA_WIDTH(2), @@ -1050,4 +1044,31 @@ dmac_request_generator #( .eot(request_eot) ); +axi_dmac_response_manager #( + .DMA_DATA_WIDTH_SRC(DMA_DATA_WIDTH_SRC), + .DMA_DATA_WIDTH_DEST(DMA_DATA_WIDTH_DEST), + .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), + .BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH), + .BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), + .ASYNC_CLK_DEST_REQ(ASYNC_CLK_DEST_REQ) +) i_response_manager( + .dest_clk(dest_clk), + .dest_resetn(dest_resetn), + .dest_response_valid(dest_response_valid), + .dest_response_ready(dest_response_ready), + .dest_response_resp(dest_response_resp), + .dest_response_partial(dest_response_partial), + .dest_response_resp_eot(dest_response_resp_eot), + .dest_response_data_burst_length(dest_response_data_burst_length), + + .req_clk(req_clk), + .req_resetn(req_resetn), + .response_eot(eot), + .measured_burst_length(measured_burst_length), + .response_partial(response_partial), + .response_valid(response_valid), + .response_ready(response_ready) +); + + endmodule diff --git a/library/axi_dmac/src_axi_stream.v b/library/axi_dmac/src_axi_stream.v index f6cd55a8e..864757663 100644 --- a/library/axi_dmac/src_axi_stream.v +++ b/library/axi_dmac/src_axi_stream.v @@ -67,6 +67,7 @@ module dmac_src_axi_stream #( output fifo_valid, output [S_AXIS_DATA_WIDTH-1:0] fifo_data, output fifo_last, + output fifo_partial_burst, input req_valid, output req_ready, @@ -113,7 +114,8 @@ dmac_data_mover # ( .m_axi_valid(fifo_valid), .m_axi_data(fifo_data), - .m_axi_last(fifo_last) + .m_axi_last(fifo_last), + .m_axi_partial_burst(fifo_partial_burst) ); endmodule