axi_dmac: preparation work for reporting length of partial transfers

Length of partial transfers are stored in a queue for SW reads.
The presence of partial transfer is indicated by a status bit.

The reporting can be enabled by a control bit.

The progress of any transfer can be followed by a debug register.
main
Laszlo Nagy 2018-08-10 15:47:21 +01:00 committed by Laszlo Nagy
parent 0203cd6981
commit eb40b42c88
16 changed files with 619 additions and 70 deletions

View File

@ -37,6 +37,7 @@ module dmac_2d_transfer #(
parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_AXI_ADDR_WIDTH = 32,
parameter DMA_LENGTH_WIDTH = 24, parameter DMA_LENGTH_WIDTH = 24,
parameter BYTES_PER_BURST_WIDTH = 7,
parameter BYTES_PER_BEAT_WIDTH_SRC = 3, parameter BYTES_PER_BEAT_WIDTH_SRC = 3,
parameter BYTES_PER_BEAT_WIDTH_DEST = 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_dest_stride,
input [DMA_LENGTH_WIDTH-1:0] req_src_stride, input [DMA_LENGTH_WIDTH-1:0] req_src_stride,
input req_sync_transfer_start, input req_sync_transfer_start,
output reg req_eot,
input req_last, 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, output reg out_req_valid,
input out_req_ready, input out_req_ready,
output [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] out_req_dest_address, 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 [DMA_LENGTH_WIDTH-1:0] out_req_length,
output reg out_req_sync_transfer_start, output reg out_req_sync_transfer_start,
output out_req_last, 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; 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; req_id <= req_id + 1'b1;
end 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; eot_id <= eot_id + 1'b1;
req_eot <= last_req[eot_id]; req_eot <= last_req[eot_id];
end else begin end else begin
@ -111,6 +123,31 @@ always @(posedge req_aclk) begin
end end
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 always @(posedge req_aclk) begin
if (req_ready == 1'b1 && req_valid == 1'b1) begin if (req_ready == 1'b1 && req_valid == 1'b1) begin
dest_address <= req_dest_address; dest_address <= req_dest_address;

View File

@ -16,6 +16,7 @@ GENERIC_DEPS += axi_dmac_regmap_request.v
GENERIC_DEPS += axi_dmac_reset_manager.v GENERIC_DEPS += axi_dmac_reset_manager.v
GENERIC_DEPS += axi_dmac_resize_dest.v GENERIC_DEPS += axi_dmac_resize_dest.v
GENERIC_DEPS += axi_dmac_resize_src.v GENERIC_DEPS += axi_dmac_resize_src.v
GENERIC_DEPS += axi_dmac_response_manager.v
GENERIC_DEPS += axi_dmac_transfer.v GENERIC_DEPS += axi_dmac_transfer.v
GENERIC_DEPS += axi_register_slice.v GENERIC_DEPS += axi_register_slice.v
GENERIC_DEPS += data_mover.v GENERIC_DEPS += data_mover.v
@ -46,6 +47,7 @@ XILINX_LIB_DEPS += util_axis_fifo
XILINX_LIB_DEPS += util_cdc XILINX_LIB_DEPS += util_cdc
ALTERA_DEPS += ../util_axis_fifo/util_axis_fifo.v 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 += ../util_cdc/sync_bits.v
ALTERA_DEPS += axi_dmac_constr.sdc ALTERA_DEPS += axi_dmac_constr.sdc
ALTERA_DEPS += axi_dmac_hw.tcl ALTERA_DEPS += axi_dmac_hw.tcl

View File

@ -285,6 +285,19 @@ localparam DMA_LENGTH_ALIGN =
BYTES_PER_BEAT_WIDTH_DEST < BYTES_PER_BEAT_WIDTH_SRC ? BYTES_PER_BEAT_WIDTH_DEST < BYTES_PER_BEAT_WIDTH_SRC ?
BYTES_PER_BEAT_WIDTH_SRC : BYTES_PER_BEAT_WIDTH_DEST; 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 // ID signals from the DMAC, just for debugging
wire [ID_WIDTH-1:0] dest_request_id; wire [ID_WIDTH-1:0] dest_request_id;
wire [ID_WIDTH-1:0] dest_data_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; assign m_src_axi_arlock = 'h0;
wire up_req_eot; 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_enable;
wire ctrl_pause; wire ctrl_pause;
@ -358,6 +375,7 @@ axi_dmac_regmap #(
.DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS),
.BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST),
.BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), .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_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH),
.DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH),
.DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN),
@ -410,6 +428,10 @@ axi_dmac_regmap #(
// DMA response interface // DMA response interface
.response_eot(up_req_eot), .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 // Debug interface
.dbg_dest_addr(m_dest_axi_awaddr), .dbg_dest_addr(m_dest_axi_awaddr),
@ -425,6 +447,7 @@ axi_dmac_transfer #(
.DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH),
.BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST),
.BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), .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_DEST(DMA_TYPE_DEST),
.DMA_TYPE_SRC(DMA_TYPE_SRC), .DMA_TYPE_SRC(DMA_TYPE_SRC),
.DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH),
@ -459,6 +482,10 @@ axi_dmac_transfer #(
.req_last(up_dma_req_last), .req_last(up_dma_req_last),
.req_eot(up_req_eot), .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_aclk(m_dest_axi_aclk),
.m_dest_axi_aresetn(m_dest_axi_aresetn), .m_dest_axi_aresetn(m_dest_axi_aresetn),

View File

@ -39,6 +39,8 @@ module axi_dmac_burst_memory #(
parameter ID_WIDTH = 3, parameter ID_WIDTH = 3,
parameter MAX_BYTES_PER_BURST = 128, parameter MAX_BYTES_PER_BURST = 128,
parameter ASYNC_CLK = 1, 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 parameter ENABLE_DIAGNOSTICS_IF = 0
) ( ) (
input src_clk, input src_clk,
@ -47,6 +49,8 @@ module axi_dmac_burst_memory #(
input src_data_valid, input src_data_valid,
input [DATA_WIDTH_SRC-1:0] src_data, input [DATA_WIDTH_SRC-1:0] src_data,
input src_data_last, 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, 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 [DATA_WIDTH_DEST-1:0] dest_data,
output dest_data_last, 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, output [ID_WIDTH-1:0] dest_request_id,
input [ID_WIDTH-1:0] dest_data_request_id, input [ID_WIDTH-1:0] dest_data_request_id,
output [ID_WIDTH-1:0] dest_data_response_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 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 * 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 * 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 dest_id_reduced_msb = 1'b0;
reg [ID_WIDTH-1:0] dest_id = 'h0; 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_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_valid = 1'b0;
reg dest_mem_data_valid = 1'b0; reg dest_mem_data_valid = 1'b0;
reg dest_mem_data_last = 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_beat;
wire src_last_beat; wire src_last_beat;
@ -193,7 +215,7 @@ end
always @(posedge src_clk) begin always @(posedge src_clk) begin
if (src_last_beat == 1'b1) 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
end end
@ -271,7 +293,7 @@ end
always @(posedge dest_clk) begin always @(posedge dest_clk) begin
if (dest_burst_valid == 1'b1 && dest_burst_ready == 1'b1) 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
end end
@ -290,6 +312,58 @@ always @(posedge dest_clk) begin
end end
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 #( axi_dmac_resize_src #(
.DATA_WIDTH_SRC (DATA_WIDTH_SRC), .DATA_WIDTH_SRC (DATA_WIDTH_SRC),
.DATA_WIDTH_MEM (DATA_WIDTH) .DATA_WIDTH_MEM (DATA_WIDTH)

View File

@ -3,6 +3,7 @@
set_false_path -to [get_registers *axi_dmac*cdc_sync_stage1*] 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*cdc_sync_fifo_ram*]
set_false_path -from [get_registers *axi_dmac*eot_mem*] set_false_path -from [get_registers *axi_dmac*eot_mem*]
set_false_path -from [get_registers *axi_dmac*bl_mem*]
# Burst memory # Burst memory
set_false_path -from [get_registers *axi_dmac*burst_len_mem*] set_false_path -from [get_registers *axi_dmac*burst_len_mem*]

View File

@ -18,6 +18,7 @@ ad_ip_files axi_dmac [list \
$ad_hdl_dir/library/util_cdc/sync_bits.v \ $ad_hdl_dir/library/util_cdc/sync_bits.v \
$ad_hdl_dir/library/common/up_axi.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/util_axis_fifo.v \
$ad_hdl_dir/library/util_axis_fifo/address_sync.v \
$ad_hdl_dir/library/common/ad_mem.v \ $ad_hdl_dir/library/common/ad_mem.v \
inc_id.vh \ inc_id.vh \
resp.vh \ resp.vh \
@ -27,6 +28,7 @@ ad_ip_files axi_dmac [list \
axi_dmac_reset_manager.v \ axi_dmac_reset_manager.v \
axi_dmac_resize_dest.v \ axi_dmac_resize_dest.v \
axi_dmac_resize_src.v \ axi_dmac_resize_src.v \
axi_dmac_response_manager.v \
axi_dmac_transfer.v \ axi_dmac_transfer.v \
address_generator.v \ address_generator.v \
data_mover.v \ data_mover.v \

View File

@ -15,6 +15,7 @@ adi_ip_files axi_dmac [list \
"axi_dmac_reset_manager.v" \ "axi_dmac_reset_manager.v" \
"axi_dmac_resize_dest.v" \ "axi_dmac_resize_dest.v" \
"axi_dmac_resize_src.v" \ "axi_dmac_resize_src.v" \
"axi_dmac_response_manager.v" \
"axi_dmac_transfer.v" \ "axi_dmac_transfer.v" \
"address_generator.v" \ "address_generator.v" \
"data_mover.v" \ "data_mover.v" \

View File

@ -38,6 +38,7 @@ module axi_dmac_regmap #(
parameter DISABLE_DEBUG_REGISTERS = 0, parameter DISABLE_DEBUG_REGISTERS = 0,
parameter BYTES_PER_BEAT_WIDTH_DEST = 1, parameter BYTES_PER_BEAT_WIDTH_DEST = 1,
parameter BYTES_PER_BEAT_WIDTH_SRC = 1, parameter BYTES_PER_BEAT_WIDTH_SRC = 1,
parameter BYTES_PER_BURST_WIDTH = 7,
parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_AXI_ADDR_WIDTH = 32,
parameter DMA_LENGTH_WIDTH = 24, parameter DMA_LENGTH_WIDTH = 24,
parameter DMA_LENGTH_ALIGN = 3, parameter DMA_LENGTH_ALIGN = 3,
@ -95,6 +96,10 @@ module axi_dmac_regmap #(
// DMA response interface // 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 response_ready,
// Debug interface // Debug interface
input [DMA_AXI_ADDR_WIDTH-1:0] dbg_src_addr, input [DMA_AXI_ADDR_WIDTH-1:0] dbg_src_addr,
@ -104,7 +109,7 @@ module axi_dmac_regmap #(
input [31:0] dbg_ids1 input [31:0] dbg_ids1
); );
localparam PCORE_VERSION = 'h00040161; localparam PCORE_VERSION = 'h00040261;
// Register interface signals // Register interface signals
reg [31:0] up_rdata = 32'h00; reg [31:0] up_rdata = 32'h00;
@ -209,6 +214,7 @@ axi_dmac_regmap_request #(
.DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS), .DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS),
.BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST), .BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST),
.BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC), .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_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH),
.DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH), .DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH),
.DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN), .DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN),
@ -224,6 +230,7 @@ axi_dmac_regmap_request #(
.up_eot(up_eot), .up_eot(up_eot),
.up_wreq(up_wreq), .up_wreq(up_wreq),
.up_rreq(up_rreq),
.up_waddr(up_waddr), .up_waddr(up_waddr),
.up_wdata(up_wdata), .up_wdata(up_wdata),
.up_raddr(up_raddr), .up_raddr(up_raddr),
@ -242,7 +249,11 @@ axi_dmac_regmap_request #(
.request_sync_transfer_start(request_sync_transfer_start), .request_sync_transfer_start(request_sync_transfer_start),
.request_last(request_last), .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 #( up_axi #(

View File

@ -37,6 +37,7 @@ module axi_dmac_regmap_request #(
parameter DISABLE_DEBUG_REGISTERS = 0, parameter DISABLE_DEBUG_REGISTERS = 0,
parameter BYTES_PER_BEAT_WIDTH_DEST = 1, parameter BYTES_PER_BEAT_WIDTH_DEST = 1,
parameter BYTES_PER_BEAT_WIDTH_SRC = 1, parameter BYTES_PER_BEAT_WIDTH_SRC = 1,
parameter BYTES_PER_BURST_WIDTH = 7,
parameter DMA_AXI_ADDR_WIDTH = 32, parameter DMA_AXI_ADDR_WIDTH = 32,
parameter DMA_LENGTH_WIDTH = 24, parameter DMA_LENGTH_WIDTH = 24,
parameter DMA_LENGTH_ALIGN = 3, parameter DMA_LENGTH_ALIGN = 3,
@ -55,6 +56,7 @@ module axi_dmac_regmap_request #(
// Register map interface // Register map interface
input up_wreq, input up_wreq,
input up_rreq,
input [8:0] up_waddr, input [8:0] up_waddr,
input [31:0] up_wdata, input [31:0] up_wdata,
input [8:0] up_raddr, input [8:0] up_raddr,
@ -76,9 +78,16 @@ module axi_dmac_regmap_request #(
output request_last, output request_last,
// DMA response interface // 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 // DMA transfer signals
reg up_dma_req_valid = 1'b0; reg up_dma_req_valid = 1'b0;
wire up_dma_req_ready; 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 [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_cyclic = DMA_CYCLIC ? 1'b1 : 1'b0;
reg up_dma_last = 1'b1; 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_dest_address = up_dma_dest_address;
assign request_src_address = up_dma_src_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_req_valid <= 1'b0;
up_dma_cyclic <= DMA_CYCLIC ? 1'b1 : 1'b0; up_dma_cyclic <= DMA_CYCLIC ? 1'b1 : 1'b0;
up_dma_last <= 1'b1; up_dma_last <= 1'b1;
up_dma_enable_tlen_reporting <= 1'b0;
end else begin end else begin
if (ctrl_enable == 1'b1) begin if (ctrl_enable == 1'b1) begin
if (up_wreq == 1'b1 && up_waddr == 9'h102) begin if (up_wreq == 1'b1 && up_waddr == 9'h102) begin
@ -123,6 +147,7 @@ always @(posedge clk) begin
9'h103: begin 9'h103: begin
if (DMA_CYCLIC) up_dma_cyclic <= up_wdata[0]; if (DMA_CYCLIC) up_dma_cyclic <= up_wdata[0];
up_dma_last <= up_wdata[1]; up_dma_last <= up_wdata[1];
up_dma_enable_tlen_reporting <= up_wdata[2];
end end
9'h104: up_dma_dest_address <= up_wdata[DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST]; 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]; 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) case (up_raddr)
9'h101: up_rdata <= up_transfer_id; 9'h101: up_rdata <= up_transfer_id;
9'h102: up_rdata <= up_dma_req_valid; 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'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'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'h106: up_rdata <= up_dma_x_length;
9'h107: up_rdata <= request_y_length; 9'h107: up_rdata <= request_y_length;
9'h108: up_rdata <= request_dest_stride; 9'h108: up_rdata <= request_dest_stride;
9'h109: up_rdata <= request_src_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'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; default: up_rdata <= 32'h00;
endcase endcase
end end
@ -180,7 +209,7 @@ endgenerate
// In cyclic mode the same transfer is submitted over and over again // 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_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 request_valid = up_dma_req_valid;
assign up_dma_req_ready = request_ready; assign up_dma_req_ready = request_ready;
@ -204,4 +233,74 @@ always @(posedge clk) begin
end end
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 endmodule

View File

@ -72,8 +72,12 @@ end else begin
valid <= 1'b0; valid <= 1'b0;
mask <= 'h1; mask <= 'h1;
end else if (src_data_valid == 1'b1) begin end else if (src_data_valid == 1'b1) begin
valid <= mask[RATIO-1]; valid <= mask[RATIO-1] || src_data_last;
mask <= {mask[RATIO-2:0],mask[RATIO-1]}; if (src_data_last) begin
mask <= 'h1;
end else begin
mask <= {mask[RATIO-2:0],mask[RATIO-1]};
end
end else begin end else begin
valid <= 1'b0; valid <= 1'b0;
end end

View File

@ -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:
// <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
//
// 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

View File

@ -49,6 +49,7 @@ module axi_dmac_transfer #(
parameter AXI_SLICE_DEST = 0, parameter AXI_SLICE_DEST = 0,
parameter AXI_SLICE_SRC = 0, parameter AXI_SLICE_SRC = 0,
parameter MAX_BYTES_PER_BURST = 128, parameter MAX_BYTES_PER_BURST = 128,
parameter BYTES_PER_BURST_WIDTH = 7,
parameter FIFO_SIZE = 8, parameter FIFO_SIZE = 8,
parameter ID_WIDTH = $clog2(FIFO_SIZE*2), parameter ID_WIDTH = $clog2(FIFO_SIZE*2),
parameter AXI_LENGTH_WIDTH_SRC = 8, parameter AXI_LENGTH_WIDTH_SRC = 8,
@ -74,6 +75,10 @@ module axi_dmac_transfer #(
input req_last, input req_last,
output req_eot, 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 // Master AXI interface
input m_dest_axi_aclk, 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_DEST] dma_req_dest_address;
wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] dma_req_src_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 [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_req_eot;
wire dma_response_valid;
wire dma_response_ready;
wire dma_response_partial;
wire dma_req_sync_transfer_start; wire dma_req_sync_transfer_start;
wire dma_req_last; wire dma_req_last;
@ -196,6 +205,7 @@ wire src_enabled;
wire req_valid_gated; wire req_valid_gated;
wire req_ready_gated; wire req_ready_gated;
axi_dmac_reset_manager #( axi_dmac_reset_manager #(
.ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC), .ASYNC_CLK_REQ_SRC (ASYNC_CLK_REQ_SRC),
.ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST), .ASYNC_CLK_SRC_DEST (ASYNC_CLK_SRC_DEST),
@ -240,6 +250,7 @@ generate if (DMA_2D_TRANSFER == 1) begin
dmac_2d_transfer #( dmac_2d_transfer #(
.DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH), .DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH),
.DMA_LENGTH_WIDTH (DMA_LENGTH_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_DEST (BYTES_PER_BEAT_WIDTH_DEST),
.BYTES_PER_BEAT_WIDTH_SRC (BYTES_PER_BEAT_WIDTH_SRC) .BYTES_PER_BEAT_WIDTH_SRC (BYTES_PER_BEAT_WIDTH_SRC)
) i_2d_transfer ( ) i_2d_transfer (
@ -247,6 +258,10 @@ dmac_2d_transfer #(
.req_aresetn (req_resetn), .req_aresetn (req_resetn),
.req_eot (req_eot), .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_valid (req_valid_gated),
.req_ready (req_ready_gated), .req_ready (req_ready_gated),
@ -266,8 +281,12 @@ dmac_2d_transfer #(
.out_req_length (dma_req_length), .out_req_length (dma_req_length),
.out_req_sync_transfer_start (dma_req_sync_transfer_start), .out_req_sync_transfer_start (dma_req_sync_transfer_start),
.out_req_last (dma_req_last), .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 end else begin
@ -283,6 +302,10 @@ assign dma_req_last = req_last;
/* Response */ /* Response */
assign req_eot = dma_req_eot; 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 end endgenerate
@ -301,6 +324,7 @@ dmac_request_arb #(
.AXI_SLICE_DEST (AXI_SLICE_DEST), .AXI_SLICE_DEST (AXI_SLICE_DEST),
.AXI_SLICE_SRC (AXI_SLICE_SRC), .AXI_SLICE_SRC (AXI_SLICE_SRC),
.MAX_BYTES_PER_BURST (MAX_BYTES_PER_BURST), .MAX_BYTES_PER_BURST (MAX_BYTES_PER_BURST),
.BYTES_PER_BURST_WIDTH (BYTES_PER_BURST_WIDTH),
.FIFO_SIZE (FIFO_SIZE), .FIFO_SIZE (FIFO_SIZE),
.ID_WIDTH (ID_WIDTH), .ID_WIDTH (ID_WIDTH),
.AXI_LENGTH_WIDTH_DEST (AXI_LENGTH_WIDTH_DEST), .AXI_LENGTH_WIDTH_DEST (AXI_LENGTH_WIDTH_DEST),
@ -319,6 +343,10 @@ dmac_request_arb #(
.req_sync_transfer_start (dma_req_sync_transfer_start), .req_sync_transfer_start (dma_req_sync_transfer_start),
.eot (dma_req_eot), .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), .req_enable (req_enable),

View File

@ -65,6 +65,7 @@ module dmac_data_mover #(
output m_axi_valid, output m_axi_valid,
output [DATA_WIDTH-1:0] m_axi_data, output [DATA_WIDTH-1:0] m_axi_data,
output m_axi_last, output m_axi_last,
output m_axi_partial_burst,
input req_valid, input req_valid,
output req_ready, output req_ready,
@ -140,9 +141,12 @@ generate if (ALLOW_ABORT == 1) begin
end end
assign transfer_abort_s = transfer_abort; 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 end else begin
assign transfer_abort_s = 1'b0; assign transfer_abort_s = 1'b0;
assign m_axi_partial_burst = 1'b0;
end endgenerate end endgenerate
/* /*

View File

@ -40,6 +40,8 @@ module dmac_dest_mm_axi #(
parameter DMA_ADDR_WIDTH = 32, parameter DMA_ADDR_WIDTH = 32,
parameter BYTES_PER_BEAT_WIDTH = $clog2(DMA_DATA_WIDTH/8), parameter BYTES_PER_BEAT_WIDTH = $clog2(DMA_DATA_WIDTH/8),
parameter BEATS_PER_BURST_WIDTH = 4, 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)( parameter AXI_LENGTH_WIDTH = 8)(
input m_axi_aclk, input m_axi_aclk,
@ -60,6 +62,8 @@ module dmac_dest_mm_axi #(
input response_ready, input response_ready,
output [1:0] response_resp, output [1:0] response_resp,
output response_resp_eot, 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, input [ID_WIDTH-1:0] request_id,
output [ID_WIDTH-1:0] response_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 [DMA_DATA_WIDTH-1:0] fifo_data,
input fifo_last, 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 // Write address
input m_axi_awready, input m_axi_awready,
output m_axi_awvalid, output m_axi_awvalid,
@ -165,4 +173,17 @@ dmac_response_handler #(
.resp_eot(response_resp_eot) .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 endmodule

View File

@ -48,6 +48,7 @@ module dmac_request_arb #(
parameter AXI_SLICE_DEST = 0, parameter AXI_SLICE_DEST = 0,
parameter AXI_SLICE_SRC = 0, parameter AXI_SLICE_SRC = 0,
parameter MAX_BYTES_PER_BURST = 128, parameter MAX_BYTES_PER_BURST = 128,
parameter BYTES_PER_BURST_WIDTH = 7,
parameter FIFO_SIZE = 8, parameter FIFO_SIZE = 8,
parameter ID_WIDTH = $clog2(FIFO_SIZE*2), parameter ID_WIDTH = $clog2(FIFO_SIZE*2),
parameter AXI_LENGTH_WIDTH_SRC = 8, parameter AXI_LENGTH_WIDTH_SRC = 8,
@ -65,7 +66,11 @@ module dmac_request_arb #(
input req_xlast, input req_xlast,
input req_sync_transfer_start, 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 // Master AXI interface
input m_dest_axi_aclk, 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 // Bytes per burst is the same for both dest and src, but bytes per beat may
// differ, so beats per burst may also differ // 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_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 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; localparam BURSTS_PER_TRANSFER_WIDTH = DMA_LENGTH_WIDTH - BYTES_PER_BURST_WIDTH;
reg eot_mem_src[0:2**ID_WIDTH-1]; reg eot_mem_src[0:2**ID_WIDTH-1];
reg eot_mem_dest[0:2**ID_WIDTH-1]; reg eot_mem_dest[0:2**ID_WIDTH-1];
wire request_eot; wire request_eot;
@ -224,9 +219,10 @@ wire dest_req_xlast;
wire dest_response_valid; wire dest_response_valid;
wire dest_response_ready; wire dest_response_ready;
wire dest_response_empty;
wire [1:0] dest_response_resp; wire [1:0] dest_response_resp;
wire dest_response_resp_eot; 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_request_id;
wire [ID_WIDTH-1:0] dest_data_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 src_valid;
wire [DMA_DATA_WIDTH_SRC-1:0] src_data; wire [DMA_DATA_WIDTH_SRC-1:0] src_data;
wire src_last; wire src_last;
wire src_partial_burst;
wire src_fifo_valid; wire src_fifo_valid;
wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data; wire [DMA_DATA_WIDTH_SRC-1:0] src_fifo_data;
wire src_fifo_last; wire src_fifo_last;
wire src_fifo_partial_burst;
wire response_dest_valid;
wire response_dest_ready = 1'b1;
wire [1:0] response_dest_resp;
wire response_dest_resp_eot;
wire src_bl_valid; wire src_bl_valid;
wire src_bl_ready; wire src_bl_ready;
wire [BEATS_PER_BURST_WIDTH_SRC-1:0] src_burst_length; 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 /* Unused for now
wire response_src_valid; wire response_src_valid;
wire response_src_ready = 1'b1; wire response_src_ready = 1'b1;
@ -299,14 +297,6 @@ begin
eot_mem_dest[source_id] <= source_eot; eot_mem_dest[source_id] <= source_eot;
end 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 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), .DMA_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH),
.BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST), .BEATS_PER_BURST_WIDTH(BEATS_PER_BURST_WIDTH_DEST),
.BYTES_PER_BEAT_WIDTH(BYTES_PER_BEAT_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) .AXI_LENGTH_WIDTH(AXI_LENGTH_WIDTH_DEST)
) i_dest_dma_mm ( ) i_dest_dma_mm (
.m_axi_aclk(m_dest_axi_aclk), .m_axi_aclk(m_dest_axi_aclk),
@ -353,6 +345,8 @@ dmac_dest_mm_axi #(
.response_ready(dest_response_ready), .response_ready(dest_response_ready),
.response_resp(dest_response_resp), .response_resp(dest_response_resp),
.response_resp_eot(dest_response_resp_eot), .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), .request_id(dest_request_id),
.response_id(dest_response_id), .response_id(dest_response_id),
@ -367,6 +361,11 @@ dmac_dest_mm_axi #(
.fifo_data(dest_data), .fifo_data(dest_data),
.fifo_last(dest_last), .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_awready(m_axi_awready),
.m_axi_awvalid(m_axi_awvalid), .m_axi_awvalid(m_axi_awvalid),
.m_axi_awaddr(m_axi_awaddr), .m_axi_awaddr(m_axi_awaddr),
@ -441,6 +440,9 @@ assign m_axi_bready = 1'b0;
assign src_bl_ready = 1'b1; assign src_bl_ready = 1'b1;
assign dest_response_partial = 1'b0;
assign dest_response_data_burst_length = 'h0;
end end
if (DMA_TYPE_DEST == DMA_TYPE_STREAM_AXI) begin 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_address_id = 'h00;
assign dbg_dest_data_id = data_id; assign dbg_dest_data_id = data_id;
dmac_dest_axi_stream #( dmac_dest_axi_stream #(
.ID_WIDTH(ID_WIDTH), .ID_WIDTH(ID_WIDTH),
.S_AXIS_DATA_WIDTH(DMA_DATA_WIDTH_DEST), .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_address_id = src_address_id;
assign dbg_src_data_id = src_data_id; assign dbg_src_data_id = src_data_id;
assign src_partial_burst = 1'b0;
dmac_src_mm_axi #( dmac_src_mm_axi #(
.ID_WIDTH(ID_WIDTH), .ID_WIDTH(ID_WIDTH),
.DMA_DATA_WIDTH(DMA_DATA_WIDTH_SRC), .DMA_DATA_WIDTH(DMA_DATA_WIDTH_SRC),
@ -697,6 +702,7 @@ dmac_src_axi_stream #(
.fifo_valid(src_valid), .fifo_valid(src_valid),
.fifo_data(src_data), .fifo_data(src_data),
.fifo_last(src_last), .fifo_last(src_last),
.fifo_partial_burst(src_partial_burst),
.s_axis_valid(s_axis_valid), .s_axis_valid(s_axis_valid),
.s_axis_ready(s_axis_ready), .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_valid = 1'b0;
assign src_response_resp = 2'b0; assign src_response_resp = 2'b0;
*/ */
assign src_partial_burst = 1'b0;
dmac_src_fifo_inf #( dmac_src_fifo_inf #(
.ID_WIDTH(ID_WIDTH), .ID_WIDTH(ID_WIDTH),
@ -828,7 +835,7 @@ sync_bits #(
); );
axi_register_slice #( axi_register_slice #(
.DATA_WIDTH(DMA_DATA_WIDTH_SRC + 1), .DATA_WIDTH(DMA_DATA_WIDTH_SRC + 2),
.FORWARD_REGISTERED(AXI_SLICE_SRC), .FORWARD_REGISTERED(AXI_SLICE_SRC),
.BACKWARD_REGISTERED(0) .BACKWARD_REGISTERED(0)
) i_src_slice ( ) i_src_slice (
@ -836,10 +843,10 @@ axi_register_slice #(
.resetn(src_resetn), .resetn(src_resetn),
.s_axi_valid(src_valid), .s_axi_valid(src_valid),
.s_axi_ready(), .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_valid(src_fifo_valid),
.m_axi_ready(1'b1), /* No backpressure */ .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 #( axi_dmac_burst_memory #(
@ -848,6 +855,8 @@ axi_dmac_burst_memory #(
.ID_WIDTH(ID_WIDTH), .ID_WIDTH(ID_WIDTH),
.MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST), .MAX_BYTES_PER_BURST(MAX_BYTES_PER_BURST),
.ASYNC_CLK(ASYNC_CLK_SRC_DEST), .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) .ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF)
) i_store_and_forward ( ) i_store_and_forward (
.src_clk(src_clk), .src_clk(src_clk),
@ -855,6 +864,8 @@ axi_dmac_burst_memory #(
.src_data_valid(src_fifo_valid), .src_data_valid(src_fifo_valid),
.src_data(src_fifo_data), .src_data(src_fifo_data),
.src_data_last(src_fifo_last), .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), .src_data_request_id(src_data_request_id),
@ -865,6 +876,11 @@ axi_dmac_burst_memory #(
.dest_data(dest_fifo_data), .dest_data(dest_fifo_data),
.dest_data_last(dest_fifo_last), .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_request_id(dest_request_id),
.dest_data_request_id(dest_data_request_id), .dest_data_request_id(dest_data_request_id),
.dest_data_response_id(dest_data_response_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 /* Unused for now
util_axis_fifo #( util_axis_fifo #(
.DATA_WIDTH(2), .DATA_WIDTH(2),
@ -1050,4 +1044,31 @@ dmac_request_generator #(
.eot(request_eot) .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 endmodule

View File

@ -67,6 +67,7 @@ module dmac_src_axi_stream #(
output fifo_valid, output fifo_valid,
output [S_AXIS_DATA_WIDTH-1:0] fifo_data, output [S_AXIS_DATA_WIDTH-1:0] fifo_data,
output fifo_last, output fifo_last,
output fifo_partial_burst,
input req_valid, input req_valid,
output req_ready, output req_ready,
@ -113,7 +114,8 @@ dmac_data_mover # (
.m_axi_valid(fifo_valid), .m_axi_valid(fifo_valid),
.m_axi_data(fifo_data), .m_axi_data(fifo_data),
.m_axi_last(fifo_last) .m_axi_last(fifo_last),
.m_axi_partial_burst(fifo_partial_burst)
); );
endmodule endmodule