Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add broadcast mode to DMA #425

Open
wants to merge 39 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3a64725
external dma slots + interfaced fifo example
Oct 19, 2023
f802d4a
typo + copyright update + DMA driver symbols
Oct 19, 2023
2d74f5a
Merge branch 'esl-epfl:main' into main
grinningmosfet Oct 19, 2023
4e0265f
better warning in iffifo_gen.sh
Oct 19, 2023
80230dc
Merge branch 'main' of https://github.com/grinningmosfet/x-heep into …
Oct 19, 2023
a28b550
replace window interface by registers
Oct 20, 2023
e2ada1a
revert i2s, swap 0/1 by TX/RX, iffifo fifo instance typo
Oct 23, 2023
ad9da35
typo
Oct 23, 2023
895153c
swap fifo, adapt example
Oct 24, 2023
9678953
improve interrupts handling
Oct 24, 2023
906362e
status register + interrupts
Oct 25, 2023
192f13e
Merge branch 'esl-epfl:main' into main
grinningmosfet Oct 25, 2023
f15c86a
fix interrupts
Oct 28, 2023
22d02a4
typo
Oct 28, 2023
c79cba0
typos
Oct 28, 2023
eaa058e
merge examples
Oct 28, 2023
a6bb239
implement broadcast dma mode + typos
Oct 31, 2023
b93aa45
implement broadcast dma mode
Oct 31, 2023
f3e91f1
add broadcast destination pointer, increment and slots registers
Oct 31, 2023
9164cb8
add dma broadcast example
Oct 31, 2023
cc3579f
broadcast mode implementation
Nov 1, 2023
96e6f6d
Merge branch 'esl-epfl:main' into main
grinningmosfet Nov 1, 2023
2a8ed5d
Merge branch 'esl-epfl:main' into dma-broadcast
grinningmosfet Nov 1, 2023
7e001cd
Merge branch 'esl-epfl:main' into main
grinningmosfet Nov 20, 2023
998bb84
Merge branch 'esl-epfl:main' into dma-broadcast
grinningmosfet Nov 20, 2023
70c6e84
minor changes
Nov 20, 2023
a2d367d
fix dma indent
Nov 20, 2023
c6eebeb
minor changes
Nov 20, 2023
852292e
verible
Nov 20, 2023
74c16f9
typo
Nov 21, 2023
4cc540b
minor changes
Nov 22, 2023
24a09e1
typo
Nov 22, 2023
ab39ff5
Merge branch 'esl-epfl:main' into main
grinningmosfet Nov 22, 2023
6ba74ec
Merge pull request #2 from grinningmosfet/main
grinningmosfet Nov 22, 2023
64a5dc1
add non-word DU and broadcast tests
Nov 22, 2023
c0e687d
clean example
Nov 22, 2023
c3e8751
Merge branch 'esl-epfl:main' into dma-broadcast
grinningmosfet Nov 29, 2023
3b20b8e
code review: dma refactor
Nov 29, 2023
1ff00cc
minoor fixes
Nov 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions hw/ip/dma/data/dma.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
{ bits: "31:0", name: "PTR_OUT", desc: "Output data pointer (word aligned)" }
]
},
{ name: "ADDR_PTR",
desc: "Addess data pointer (word aligned)",
{ name: "ADDR_BCST_PTR",
desc: "Addess/Broadcast data pointer (word aligned)",
swaccess: "rw",
hwaccess: "hro",
fields: [
{ bits: "31:0", name: "PTR_ADDR", desc: "Address data pointer (word aligned) - used only in Address mode" }
{ bits: "31:0", name: "PTR_ADDR", desc: "Address/Broadcast data pointer (word aligned) - used only in Address and Broadcast modes" }
]
},
{ name: "SIZE",
Expand Down Expand Up @@ -68,6 +68,11 @@
name: "DST_PTR_INC",
desc: "Destination pointer increment",
resval:4
},
{ bits: "23:16",
name: "BCST_PTR_INC",
desc: "Broadcast pointer increment",
resval:4
}
]
},
Expand All @@ -87,6 +92,22 @@
}
]
},
{ name: "BSLOT",
desc: '''The DMA will wait for the signal
connected to the selected trigger_slots to be high
on the read and write side respectivly''',
swaccess: "rw",
hwaccess: "hro",
resval: 0,
fields: [
{ bits: "15:0", name: "BX_TRIGGER_SLOT",
desc: "Broadcast slot selection mask"
},
{ bits: "31:16", name: "DX_TRIGGER_SLOT",
desc: "Dummy slot selection mask"
}
]
},
{ name: "DATA_TYPE",
desc: '''Width/type of the data to transfer''',
swaccess: "rw",
Expand Down Expand Up @@ -115,6 +136,7 @@
{ value: "0", name: "LINEAR_MODE", desc: "Transfers data linearly"},
{ value: "1", name: "CIRCULAR_MODE", desc: "Transfers data in circular mode"},
{ value: "2", name: "ADDRESS_MODE" , desc: "Transfers data using as destination address the data from ADD_PTR"},
{ value: "3", name: "BROADCAST_MODE" , desc: "Equivalent to LINEAR_MODE but writing at two destinations simultaneously"},
]
}
]
Expand Down
159 changes: 143 additions & 16 deletions hw/ip/dma/rtl/dma.sv
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ module dma #(
logic [ 31:0] addr_ptr_reg;
grinningmosfet marked this conversation as resolved.
Show resolved Hide resolved
logic [ 31:0] read_ptr_valid_reg;
logic [ 31:0] write_ptr_reg;
logic [ 31:0] bcst_ptr_reg;
logic [ 31:0] write_address;
logic [ 31:0] bcst_address;
logic [ 31:0] dma_cnt;
logic [ 31:0] dma_addr_cnt;
logic [ 2:0] dma_cnt_dec;
Expand Down Expand Up @@ -77,6 +79,8 @@ module dma #(
logic data_addr_in_rvalid;
logic [ 31:0] data_addr_in_rdata;

logic [ 31:0] data_addr_in_wdata;

logic data_out_req;
logic data_out_we;
logic [ 3:0] data_out_be;
Expand Down Expand Up @@ -105,12 +109,16 @@ module dma #(
logic [31:0] fifo_addr_output;

logic [ 3:0] byte_enable_out;
logic [ 3:0] bcst_byte_enable_out;

logic circular_mode;
logic address_mode;
logic broadcast_mode;

logic dma_start_pending;

logic broadcast_pop, latched_data_out_gnt, latched_data_addr_in;

enum {
DMA_READY,
DMA_STARTING,
Expand All @@ -132,6 +140,7 @@ module dma #(
}
dma_write_fsm_state, dma_write_fsm_n_state;

// READ channel
assign dma_read_ch0_req_o.req = data_in_req;
assign dma_read_ch0_req_o.we = data_in_we;
assign dma_read_ch0_req_o.be = data_in_be;
Expand All @@ -142,16 +151,18 @@ module dma #(
assign data_in_rvalid = dma_read_ch0_resp_i.rvalid;
assign data_in_rdata = dma_read_ch0_resp_i.rdata;

// ADDRESS channel
assign dma_addr_ch0_req_o.req = data_addr_in_req;
assign dma_addr_ch0_req_o.we = data_addr_in_we;
assign dma_addr_ch0_req_o.be = data_addr_in_be;
assign dma_addr_ch0_req_o.addr = data_addr_in_addr;
assign dma_addr_ch0_req_o.wdata = 32'h0;
assign dma_addr_ch0_req_o.wdata = data_addr_in_wdata;

assign data_addr_in_gnt = dma_addr_ch0_resp_i.gnt;
assign data_addr_in_rvalid = dma_addr_ch0_resp_i.rvalid;
assign data_addr_in_rdata = dma_addr_ch0_resp_i.rdata;

// WRITE channel
assign dma_write_ch0_req_o.req = data_out_req;
assign dma_write_ch0_req_o.we = data_out_we;
assign dma_write_ch0_req_o.be = data_out_be;
Expand All @@ -177,8 +188,10 @@ module dma #(

assign circular_mode = reg2hw.mode.q == 1;
assign address_mode = reg2hw.mode.q == 2;
assign broadcast_mode = reg2hw.mode.q == 3;

assign write_address = address_mode ? fifo_addr_output : write_ptr_reg;
assign bcst_address = bcst_ptr_reg;

assign wait_for_rx = |(reg2hw.slot.rx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i));
assign wait_for_tx = |(reg2hw.slot.tx_trigger_slot.q[SLOT_NUM-1:0] & (~trigger_slot_i));
Expand Down Expand Up @@ -260,7 +273,7 @@ module dma #(
addr_ptr_reg <= '0;
end else begin
if (dma_start == 1'b1 && address_mode) begin
addr_ptr_reg <= reg2hw.addr_ptr.q;
addr_ptr_reg <= reg2hw.addr_bcst_ptr.q;
end else if (data_addr_in_gnt == 1'b1 && address_mode) begin
addr_ptr_reg <= addr_ptr_reg + 32'h4; //always continuos in 32b
end
Expand Down Expand Up @@ -293,6 +306,19 @@ module dma #(
end
end

// Store broadcast output data pointer and increment everytime write request is granted
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_bcst_ptr_out_reg
if (~rst_ni) begin
bcst_ptr_reg <= '0;
end else begin
if (dma_start == 1'b1) begin
bcst_ptr_reg <= reg2hw.addr_bcst_ptr.q;
end else if (data_addr_in_gnt == 1'b1) begin
bcst_ptr_reg <= bcst_ptr_reg + {24'h0, reg2hw.ptr_inc.bcst_ptr_inc.q};
grinningmosfet marked this conversation as resolved.
Show resolved Hide resolved
end
end
end

// Store dma transfer size and decrement it everytime input data rvalid is asserted
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_dma_cnt_reg
if (~rst_ni) begin
Expand Down Expand Up @@ -352,6 +378,31 @@ module dma #(
; // case (data_type)
end

always_comb begin : proc_byte_enable_out_broadcast
case (data_type) // Data type 00 Word, 01 Half word, 11,10 byte
2'b00: bcst_byte_enable_out = 4'b1111; // Writing a word (32 bits)

2'b01: begin // Writing a half-word (16 bits)
case (bcst_address[1])
1'b0: bcst_byte_enable_out = 4'b0011;
1'b1: bcst_byte_enable_out = 4'b1100;
endcase
; // case(write_address[1:0])
end

2'b10, 2'b11: begin // Writing a byte (8 bits)
case (bcst_address[1:0])
2'b00: bcst_byte_enable_out = 4'b0001;
2'b01: bcst_byte_enable_out = 4'b0010;
2'b10: bcst_byte_enable_out = 4'b0100;
2'b11: bcst_byte_enable_out = 4'b1000;
endcase
; // case(write_address[1:0])
end
endcase
; // case (data_type)
end

// Output data shift
always_comb begin : proc_output_data

Expand All @@ -374,6 +425,35 @@ module dma #(
endcase
end

// Output data shift (broadcast)
always_comb begin : proc_output_data_broadcast

if (broadcast_mode) begin

data_addr_in_wdata[7:0] = fifo_output[7:0];
data_addr_in_wdata[15:8] = fifo_output[15:8];
data_addr_in_wdata[23:16] = fifo_output[23:16];
data_addr_in_wdata[31:24] = fifo_output[31:24];

case (write_address[1:0])
2'b00: ;

2'b01: data_addr_in_wdata[15:8] = fifo_output[7:0];

2'b10: begin
data_addr_in_wdata[23:16] = fifo_output[7:0];
data_addr_in_wdata[31:24] = fifo_output[15:8];
end

2'b11: data_addr_in_wdata[31:24] = fifo_output[7:0];
endcase

end else begin
data_addr_in_wdata = 32'd0;
end

end

assign fifo_addr_input = data_addr_in_rdata; //never misaligned, always 32b

// Input data shift: shift the input data to be on the LSB of the fifo
Expand Down Expand Up @@ -460,7 +540,7 @@ module dma #(
endcase
end

// Read address master FSM
// Read address master & Write broadcast master FSM
always_comb begin : proc_dma_addr_read_fsm_logic

dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE;
Expand All @@ -476,26 +556,45 @@ module dma #(

DMA_READ_FSM_IDLE: begin
// Wait for start signal
if (dma_start == 1'b1 && address_mode) begin
if (address_mode && dma_start == 1'b1) begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_ON;
fifo_addr_flush = 1'b1;
end else if (broadcast_mode && dma_start == 1'b1) begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_ON;
end else begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE;
end
end
// Read one word
DMA_READ_FSM_ON: begin
// If all input data read exit
if (|dma_addr_cnt == 1'b0) begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE;
end else begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_ON;
// Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1).
if (fifo_addr_full == 1'b0 && fifo_addr_alm_full == 1'b0) begin
data_addr_in_req = 1'b1;
data_addr_in_we = 1'b0;
data_addr_in_be = 4'b1111; // always read all bytes
data_addr_in_addr = addr_ptr_reg;
if (address_mode) begin
// If all input data read exit
if (|dma_addr_cnt == 1'b0) begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_IDLE;
end else begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_ON;
// Wait if fifo is full, almost full (last data), or if the SPI RX does not have valid data (only in SPI mode 1).
if (fifo_addr_full == 1'b0 && fifo_addr_alm_full == 1'b0) begin
data_addr_in_req = 1'b1;
data_addr_in_we = 1'b0;
data_addr_in_be = 4'b1111; // always read all bytes
data_addr_in_addr = addr_ptr_reg;
end
end
end
if (broadcast_mode) begin
// If all input data read exit
if (fifo_empty == 1'b1 && dma_read_fsm_state == DMA_READ_FSM_IDLE) begin
dma_read_addr_fsm_n_state = dma_done ? DMA_READ_FSM_IDLE : DMA_READ_FSM_ON;
end else begin
dma_read_addr_fsm_n_state = DMA_READ_FSM_ON;
// Wait if fifo is empty or if the SPI TX is not ready for new data (only in SPI mode 2).
if (fifo_empty == 1'b0 && wait_for_tx == 1'b0 && fifo_addr_empty_check == 1'b0) begin
data_addr_in_req = 1'b1;
data_addr_in_we = 1'b1;
data_addr_in_be = bcst_byte_enable_out;
data_addr_in_addr = bcst_address;
grinningmosfet marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
end
Expand Down Expand Up @@ -559,7 +658,7 @@ module dma #(
.push_i(data_in_rvalid),
// as long as the queue is not empty we can pop new elements
.data_o(fifo_output),
.pop_i(data_out_gnt)
.pop_i((!broadcast_mode && data_out_gnt) || (broadcast_mode && broadcast_pop))
);

fifo_v3 #(
Expand Down Expand Up @@ -594,6 +693,34 @@ module dma #(
.devmode_i(1'b1)
);

always_ff @(posedge clk_i, negedge rst_ni) begin
grinningmosfet marked this conversation as resolved.
Show resolved Hide resolved
if (~rst_ni) begin
broadcast_pop <= 0;
latched_data_out_gnt <= 0;
latched_data_addr_in <= 0;
end else begin

if (data_out_gnt) begin
latched_data_out_gnt <= 1;
end

if (data_addr_in_gnt) begin
latched_data_addr_in <= 1;
end

if ( (data_out_gnt || latched_data_out_gnt) && (data_addr_in_gnt || latched_data_addr_in) ) begin
broadcast_pop <= 1;
latched_data_addr_in <= 0;
latched_data_out_gnt <= 0;
end

if (broadcast_pop == 1) begin
broadcast_pop <= 0;
end

end
end

// WINDOW EVENT
// Count gnt write transaction and generate event pulse if WINDOW_SIZE is reached
assign dma_window_event = |reg2hw.window_size.q & data_out_gnt & (window_counter + 'h1 >= reg2hw.window_size.q);
Expand Down
Loading
Loading