Skip to content

Commit f41391f

Browse files
committed
axi_dmac: Add support for DMA Scatter-Gather
This commit introduces a different interface to submit transfers, using DMA descriptors. The structure of the DMA descriptor is as follows: struct dma_desc { u32 flags, u32 id, u64 dest_addr, u64 src_addr, u64 next_sg_addr, u32 y_len, u32 x_len, u32 src_stride, u32 dst_stride, }; The 'flags' field currently offers two control bits: - bit 0: if set, the transfer will complete after this last descriptor is processed, and the DMA core will go back to idle state; if cleared, the next DMA descriptor pointed to by 'next_sg_addr' will be loaded. - bit 1: if set, an end-of-transfer interrupt will be raised after the memory segment pointed to by this descriptor has been transferred. The 'id' field corresponds to an identifier of the descriptor. The 'dest_addr' and 'src_addr' contain the destination and source addresses to use for the transfer, respectively. The 'x_len' field contains the number of bytes to transfer, minus one. The 'y_len', 'src_stride' and 'dst_stride' fields are only useful for 2D transfers, and should be set to zero if 2D transfers are not required. To start a transfer, the address of the first DMA descriptor must be written to register 0x47c and the HWDESC bit of CONTROL register must be set. The Scatter-Gather transfer is queued similarly to the simple transfers, by writing 1 in TRANSFER_SUBMIT. The Scatter-Gather interface has a dedicated AXI-MM bus configured for read transfers, with its own dedicated clock, which can be asynchronous. The Scatter-Gather reset is generated by the reset manager to reset the logic after completing any pending transactions on the bus. When the Scatter-Gather is enabled during runtime, the legacy cyclic functionality of the DMA is disabled. Signed-off-by: Ionut Podgoreanu <ionut.podgoreanu@analog.com>
1 parent 0f87d84 commit f41391f

14 files changed

+1051
-94
lines changed

library/axi_dmac/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ GENERIC_DEPS += dest_axi_mm.v
2424
GENERIC_DEPS += dest_axi_stream.v
2525
GENERIC_DEPS += dest_fifo_inf.v
2626
GENERIC_DEPS += dmac_2d_transfer.v
27+
GENERIC_DEPS += dmac_sg.v
2728
GENERIC_DEPS += inc_id.vh
2829
GENERIC_DEPS += request_arb.v
2930
GENERIC_DEPS += request_generator.v
@@ -52,6 +53,7 @@ INTEL_DEPS += ../util_axis_fifo/util_axis_fifo.v
5253
INTEL_DEPS += ../util_axis_fifo/util_axis_fifo_address_generator.v
5354
INTEL_DEPS += ../util_cdc/sync_bits.v
5455
INTEL_DEPS += ../util_cdc/sync_event.v
56+
INTEL_DEPS += ../util_cdc/sync_gray.v
5557
INTEL_DEPS += axi_dmac_constr.sdc
5658
INTEL_DEPS += axi_dmac_hw.tcl
5759

library/axi_dmac/axi_dmac.v

Lines changed: 122 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,31 @@ module axi_dmac #(
4040
parameter ID = 0,
4141
parameter DMA_DATA_WIDTH_SRC = 64,
4242
parameter DMA_DATA_WIDTH_DEST = 64,
43+
parameter DMA_DATA_WIDTH_SG = 64,
4344
parameter DMA_LENGTH_WIDTH = 24,
4445
parameter DMA_2D_TRANSFER = 0,
46+
parameter DMA_SG_TRANSFER = 0,
4547
parameter ASYNC_CLK_REQ_SRC = 1,
4648
parameter ASYNC_CLK_SRC_DEST = 1,
4749
parameter ASYNC_CLK_DEST_REQ = 1,
50+
parameter ASYNC_CLK_REQ_SG = 1,
51+
parameter ASYNC_CLK_SRC_SG = 1,
52+
parameter ASYNC_CLK_DEST_SG = 1,
4853
parameter AXI_SLICE_DEST = 0,
4954
parameter AXI_SLICE_SRC = 0,
5055
parameter SYNC_TRANSFER_START = 0,
5156
parameter CYCLIC = 1,
5257
parameter DMA_AXI_PROTOCOL_DEST = 0,
5358
parameter DMA_AXI_PROTOCOL_SRC = 0,
59+
parameter DMA_AXI_PROTOCOL_SG = 0,
5460
parameter DMA_TYPE_DEST = 0,
5561
parameter DMA_TYPE_SRC = 2,
5662
parameter DMA_AXI_ADDR_WIDTH = 32,
5763
parameter MAX_BYTES_PER_BURST = 128,
5864
parameter FIFO_SIZE = 8, // In bursts
5965
parameter AXI_ID_WIDTH_SRC = 1,
6066
parameter AXI_ID_WIDTH_DEST = 1,
67+
parameter AXI_ID_WIDTH_SG = 1,
6168
parameter DMA_AXIS_ID_W = 8,
6269
parameter DMA_AXIS_DEST_W = 4,
6370
parameter DISABLE_DEBUG_REGISTERS = 0,
@@ -187,6 +194,52 @@ module axi_dmac #(
187194
output [AXI_ID_WIDTH_SRC-1:0] m_src_axi_wid,
188195
input [AXI_ID_WIDTH_SRC-1:0] m_src_axi_bid,
189196

197+
// Master AXI interface
198+
input m_sg_axi_aclk,
199+
input m_sg_axi_aresetn,
200+
201+
// Read address
202+
input m_sg_axi_arready,
203+
output m_sg_axi_arvalid,
204+
output [DMA_AXI_ADDR_WIDTH-1:0] m_sg_axi_araddr,
205+
output [7-(4*DMA_AXI_PROTOCOL_SG):0] m_sg_axi_arlen,
206+
output [ 2:0] m_sg_axi_arsize,
207+
output [ 1:0] m_sg_axi_arburst,
208+
output [ 2:0] m_sg_axi_arprot,
209+
output [ 3:0] m_sg_axi_arcache,
210+
output [AXI_ID_WIDTH_SG-1:0] m_sg_axi_arid,
211+
output [DMA_AXI_PROTOCOL_SG:0] m_sg_axi_arlock,
212+
213+
// Read data and response
214+
input [DMA_DATA_WIDTH_SG-1:0] m_sg_axi_rdata,
215+
output m_sg_axi_rready,
216+
input m_sg_axi_rvalid,
217+
input [ 1:0] m_sg_axi_rresp,
218+
input [AXI_ID_WIDTH_SG-1:0] m_sg_axi_rid,
219+
input m_sg_axi_rlast,
220+
221+
// Unused write interface
222+
output m_sg_axi_awvalid,
223+
output [DMA_AXI_ADDR_WIDTH-1:0] m_sg_axi_awaddr,
224+
output [7-(4*DMA_AXI_PROTOCOL_SG):0] m_sg_axi_awlen,
225+
output [ 2:0] m_sg_axi_awsize,
226+
output [ 1:0] m_sg_axi_awburst,
227+
output [ 3:0] m_sg_axi_awcache,
228+
output [ 2:0] m_sg_axi_awprot,
229+
input m_sg_axi_awready,
230+
output m_sg_axi_wvalid,
231+
output [DMA_DATA_WIDTH_SG-1:0] m_sg_axi_wdata,
232+
output [(DMA_DATA_WIDTH_SG/8)-1:0] m_sg_axi_wstrb,
233+
output m_sg_axi_wlast,
234+
input m_sg_axi_wready,
235+
input m_sg_axi_bvalid,
236+
input [ 1:0] m_sg_axi_bresp,
237+
output m_sg_axi_bready,
238+
output [AXI_ID_WIDTH_SG-1:0] m_sg_axi_awid,
239+
output [DMA_AXI_PROTOCOL_SG:0] m_sg_axi_awlock,
240+
output [AXI_ID_WIDTH_SG-1:0] m_sg_axi_wid,
241+
input [AXI_ID_WIDTH_SG-1:0] m_sg_axi_bid,
242+
190243
// Slave streaming AXI interface
191244
input s_axis_aclk,
192245
output s_axis_ready,
@@ -257,6 +310,14 @@ module axi_dmac #(
257310
DMA_DATA_WIDTH_SRC > 32 ? 3 :
258311
DMA_DATA_WIDTH_SRC > 16 ? 2 :
259312
DMA_DATA_WIDTH_SRC > 8 ? 1 : 0;
313+
localparam BYTES_PER_BEAT_WIDTH_SG = DMA_DATA_WIDTH_SG > 1024 ? 8 :
314+
DMA_DATA_WIDTH_SG > 512 ? 7 :
315+
DMA_DATA_WIDTH_SG > 256 ? 6 :
316+
DMA_DATA_WIDTH_SG > 128 ? 5 :
317+
DMA_DATA_WIDTH_SG > 64 ? 4 :
318+
DMA_DATA_WIDTH_SG > 32 ? 3 :
319+
DMA_DATA_WIDTH_SG > 16 ? 2 :
320+
DMA_DATA_WIDTH_SG > 8 ? 1 : 0;
260321
localparam ID_WIDTH = (FIFO_SIZE) > 64 ? 8 :
261322
(FIFO_SIZE) > 32 ? 7 :
262323
(FIFO_SIZE) > 16 ? 6 :
@@ -331,45 +392,22 @@ module axi_dmac #(
331392
wire [31:0] dbg_ids0;
332393
wire [31:0] dbg_ids1;
333394

334-
assign m_dest_axi_araddr = 'd0;
335-
assign m_dest_axi_arlen = 'd0;
336-
assign m_dest_axi_arsize = 'd0;
337-
assign m_dest_axi_arburst = 'd0;
338-
assign m_dest_axi_arcache = 'd0;
339-
assign m_dest_axi_arprot = 'd0;
340-
assign m_dest_axi_awid = 'h0;
341-
assign m_dest_axi_awlock = 'h0;
342-
assign m_dest_axi_wid = 'h0;
343-
assign m_dest_axi_arid = 'h0;
344-
assign m_dest_axi_arlock = 'h0;
345-
assign m_src_axi_awaddr = 'd0;
346-
assign m_src_axi_awlen = 'd0;
347-
assign m_src_axi_awsize = 'd0;
348-
assign m_src_axi_awburst = 'd0;
349-
assign m_src_axi_awcache = 'd0;
350-
assign m_src_axi_awprot = 'd0;
351-
assign m_src_axi_wdata = 'd0;
352-
assign m_src_axi_wstrb = 'd0;
353-
assign m_src_axi_wlast = 'd0;
354-
assign m_src_axi_awid = 'h0;
355-
assign m_src_axi_awlock = 'h0;
356-
assign m_src_axi_wid = 'h0;
357-
assign m_src_axi_arid = 'h0;
358-
assign m_src_axi_arlock = 'h0;
359-
360395
wire up_req_eot;
396+
wire [31:0] up_req_sg_desc_id;
361397
wire [BYTES_PER_BURST_WIDTH-1:0] up_req_measured_burst_length;
362398
wire up_response_partial;
363399
wire up_response_valid;
364400
wire up_response_ready;
365401

366402
wire ctrl_enable;
367403
wire ctrl_pause;
404+
wire ctrl_hwdesc;
368405

369406
wire up_dma_req_valid;
370407
wire up_dma_req_ready;
371408
wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_DEST] up_dma_req_dest_address;
372409
wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SRC] up_dma_req_src_address;
410+
wire [DMA_AXI_ADDR_WIDTH-1:BYTES_PER_BEAT_WIDTH_SG] up_dma_req_sg_address;
373411
wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_x_length;
374412
wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_y_length;
375413
wire [DMA_LENGTH_WIDTH-1:0] up_dma_req_dest_stride;
@@ -396,6 +434,7 @@ module axi_dmac #(
396434
.DISABLE_DEBUG_REGISTERS(DISABLE_DEBUG_REGISTERS),
397435
.BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST),
398436
.BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC),
437+
.BYTES_PER_BEAT_WIDTH_SG(BYTES_PER_BEAT_WIDTH_SG),
399438
.BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH),
400439
.DMA_TYPE_DEST(DMA_TYPE_DEST),
401440
.DMA_TYPE_SRC(DMA_TYPE_SRC),
@@ -406,6 +445,7 @@ module axi_dmac #(
406445
.HAS_DEST_ADDR(HAS_DEST_ADDR),
407446
.HAS_SRC_ADDR(HAS_SRC_ADDR),
408447
.DMA_2D_TRANSFER(DMA_2D_TRANSFER),
448+
.DMA_SG_TRANSFER(DMA_SG_TRANSFER),
409449
.SYNC_TRANSFER_START(SYNC_TRANSFER_START),
410450
.CACHE_COHERENT_DEST(CACHE_COHERENT_DEST)
411451
) i_regmap (
@@ -438,12 +478,14 @@ module axi_dmac #(
438478
// Control interface
439479
.ctrl_enable(ctrl_enable),
440480
.ctrl_pause(ctrl_pause),
481+
.ctrl_hwdesc(ctrl_hwdesc),
441482

442483
// Request interface
443484
.request_valid(up_dma_req_valid),
444485
.request_ready(up_dma_req_ready),
445486
.request_dest_address(up_dma_req_dest_address),
446487
.request_src_address(up_dma_req_src_address),
488+
.request_sg_address(up_dma_req_sg_address),
447489
.request_x_length(up_dma_req_x_length),
448490
.request_y_length(up_dma_req_y_length),
449491
.request_dest_stride(up_dma_req_dest_stride),
@@ -453,6 +495,7 @@ module axi_dmac #(
453495

454496
// DMA response interface
455497
.response_eot(up_req_eot),
498+
.response_sg_desc_id(up_req_sg_desc_id),
456499
.response_measured_burst_length(up_req_measured_burst_length),
457500
.response_partial(up_response_partial),
458501
.response_valid(up_response_valid),
@@ -468,25 +511,30 @@ module axi_dmac #(
468511
axi_dmac_transfer #(
469512
.DMA_DATA_WIDTH_SRC(DMA_DATA_WIDTH_SRC),
470513
.DMA_DATA_WIDTH_DEST(DMA_DATA_WIDTH_DEST),
514+
.DMA_DATA_WIDTH_SG(DMA_DATA_WIDTH_SG),
471515
.DMA_LENGTH_WIDTH(DMA_LENGTH_WIDTH),
472516
.DMA_LENGTH_ALIGN(DMA_LENGTH_ALIGN),
473517
.BYTES_PER_BEAT_WIDTH_DEST(BYTES_PER_BEAT_WIDTH_DEST),
474518
.BYTES_PER_BEAT_WIDTH_SRC(BYTES_PER_BEAT_WIDTH_SRC),
519+
.BYTES_PER_BEAT_WIDTH_SG(BYTES_PER_BEAT_WIDTH_SG),
475520
.BYTES_PER_BURST_WIDTH(BYTES_PER_BURST_WIDTH),
476521
.DMA_TYPE_DEST(DMA_TYPE_DEST),
477522
.DMA_TYPE_SRC(DMA_TYPE_SRC),
478523
.DMA_AXI_ADDR_WIDTH(DMA_AXI_ADDR_WIDTH),
479524
.DMA_2D_TRANSFER(DMA_2D_TRANSFER),
525+
.DMA_SG_TRANSFER(DMA_SG_TRANSFER),
480526
.ASYNC_CLK_REQ_SRC(ASYNC_CLK_REQ_SRC),
481527
.ASYNC_CLK_SRC_DEST(ASYNC_CLK_SRC_DEST),
482528
.ASYNC_CLK_DEST_REQ(ASYNC_CLK_DEST_REQ),
529+
.ASYNC_CLK_REQ_SG(ASYNC_CLK_REQ_SG),
483530
.AXI_SLICE_DEST(AXI_SLICE_DEST),
484531
.AXI_SLICE_SRC(AXI_SLICE_SRC),
485532
.MAX_BYTES_PER_BURST(REAL_MAX_BYTES_PER_BURST),
486533
.FIFO_SIZE(FIFO_SIZE),
487534
.ID_WIDTH(ID_WIDTH),
488535
.AXI_LENGTH_WIDTH_SRC(8-(4*DMA_AXI_PROTOCOL_SRC)),
489536
.AXI_LENGTH_WIDTH_DEST(8-(4*DMA_AXI_PROTOCOL_DEST)),
537+
.AXI_LENGTH_WIDTH_SG(8-(4*DMA_AXI_PROTOCOL_SG)),
490538
.ENABLE_DIAGNOSTICS_IF(ENABLE_DIAGNOSTICS_IF),
491539
.ALLOW_ASYM_MEM(ALLOW_ASYM_MEM),
492540
.CACHE_COHERENT_DEST(CACHE_COHERENT_DEST)
@@ -496,11 +544,13 @@ module axi_dmac #(
496544

497545
.ctrl_enable(ctrl_enable),
498546
.ctrl_pause(ctrl_pause),
547+
.ctrl_hwdesc(ctrl_hwdesc),
499548

500549
.req_valid(up_dma_req_valid),
501550
.req_ready(up_dma_req_ready),
502551
.req_dest_address(up_dma_req_dest_address),
503552
.req_src_address(up_dma_req_src_address),
553+
.req_sg_address(up_dma_req_sg_address),
504554
.req_x_length(up_dma_req_x_length),
505555
.req_y_length(up_dma_req_y_length),
506556
.req_dest_stride(up_dma_req_dest_stride),
@@ -509,6 +559,7 @@ module axi_dmac #(
509559
.req_last(up_dma_req_last),
510560

511561
.req_eot(up_req_eot),
562+
.req_sg_desc_id(up_req_sg_desc_id),
512563
.req_measured_burst_length(up_req_measured_burst_length),
513564
.req_response_partial(up_response_partial),
514565
.req_response_valid(up_response_valid),
@@ -518,6 +569,8 @@ module axi_dmac #(
518569
.m_dest_axi_aresetn(m_dest_axi_aresetn),
519570
.m_src_axi_aclk(m_src_axi_aclk),
520571
.m_src_axi_aresetn(m_src_axi_aresetn),
572+
.m_sg_axi_aclk(m_sg_axi_aclk),
573+
.m_sg_axi_aresetn(m_sg_axi_aresetn),
521574

522575
.m_axi_awaddr(m_dest_axi_awaddr),
523576
.m_axi_awlen(m_dest_axi_awlen),
@@ -553,6 +606,21 @@ module axi_dmac #(
553606
.m_axi_rlast(m_src_axi_rlast),
554607
.m_axi_rresp(m_src_axi_rresp),
555608

609+
.m_sg_axi_arready(m_sg_axi_arready),
610+
.m_sg_axi_arvalid(m_sg_axi_arvalid),
611+
.m_sg_axi_araddr(m_sg_axi_araddr),
612+
.m_sg_axi_arlen(m_sg_axi_arlen),
613+
.m_sg_axi_arsize(m_sg_axi_arsize),
614+
.m_sg_axi_arburst(m_sg_axi_arburst),
615+
.m_sg_axi_arprot(m_sg_axi_arprot),
616+
.m_sg_axi_arcache(m_sg_axi_arcache),
617+
618+
.m_sg_axi_rdata(m_sg_axi_rdata),
619+
.m_sg_axi_rready(m_sg_axi_rready),
620+
.m_sg_axi_rvalid(m_sg_axi_rvalid),
621+
.m_sg_axi_rlast(m_sg_axi_rlast),
622+
.m_sg_axi_rresp(m_sg_axi_rresp),
623+
556624
.s_axis_aclk(s_axis_aclk),
557625
.s_axis_ready(s_axis_ready),
558626
.s_axis_valid(s_axis_valid),
@@ -603,21 +671,47 @@ module axi_dmac #(
603671
assign m_dest_axi_arburst = 'h0;
604672
assign m_dest_axi_arcache = 'h0;
605673
assign m_dest_axi_arprot = 'h0;
674+
assign m_dest_axi_awid = 'h0;
675+
assign m_dest_axi_awlock = 'h0;
676+
assign m_dest_axi_wid = 'h0;
677+
assign m_dest_axi_arid = 'h0;
678+
assign m_dest_axi_arlock = 'h0;
606679

607680
assign m_src_axi_awvalid = 1'b0;
608681
assign m_src_axi_wvalid = 1'b0;
609682
assign m_src_axi_bready = 1'b0;
610-
assign m_src_axi_awvalid = 'h0;
611683
assign m_src_axi_awaddr = 'h0;
612684
assign m_src_axi_awlen = 'h0;
613685
assign m_src_axi_awsize = 'h0;
614686
assign m_src_axi_awburst = 'h0;
615687
assign m_src_axi_awcache = 'h0;
616688
assign m_src_axi_awprot = 'h0;
617-
assign m_src_axi_wvalid = 'h0;
618689
assign m_src_axi_wdata = 'h0;
619690
assign m_src_axi_wstrb = 'h0;
620691
assign m_src_axi_wlast = 'h0;
692+
assign m_src_axi_awid = 'h0;
693+
assign m_src_axi_awlock = 'h0;
694+
assign m_src_axi_wid = 'h0;
695+
assign m_src_axi_arid = 'h0;
696+
assign m_src_axi_arlock = 'h0;
697+
698+
assign m_sg_axi_awvalid = 1'b0;
699+
assign m_sg_axi_wvalid = 1'b0;
700+
assign m_sg_axi_bready = 1'b0;
701+
assign m_sg_axi_awaddr = 'h0;
702+
assign m_sg_axi_awlen = 'h0;
703+
assign m_sg_axi_awsize = 'h0;
704+
assign m_sg_axi_awburst = 'h0;
705+
assign m_sg_axi_awcache = 'h0;
706+
assign m_sg_axi_awprot = 'h0;
707+
assign m_sg_axi_wdata = 'h0;
708+
assign m_sg_axi_wstrb = 'h0;
709+
assign m_sg_axi_wlast = 'h0;
710+
assign m_sg_axi_awid = 'h0;
711+
assign m_sg_axi_awlock = 'h0;
712+
assign m_sg_axi_wid = 'h0;
713+
assign m_sg_axi_arid = 'h0;
714+
assign m_sg_axi_arlock = 'h0;
621715

622716
assign m_axis_keep = {DMA_DATA_WIDTH_DEST/8{1'b1}};
623717
assign m_axis_strb = {DMA_DATA_WIDTH_DEST/8{1'b1}};

0 commit comments

Comments
 (0)