From c48b378bcc390f2f71bb572e74176bf4bd36c4f5 Mon Sep 17 00:00:00 2001
From: stnolting <22944758+stnolting@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:14:01 +0200
Subject: [PATCH 1/6] [top] minor XBUS signal rearrangement
---
docs/datasheet/soc.adoc | 2 +-
rtl/core/neorv32_package.vhd | 4 ++--
rtl/core/neorv32_top.vhd | 2 +-
rtl/system_integration/neorv32_litex_core_complex.vhd | 2 +-
sim/neorv32_tb.vhd | 2 +-
sim/simple/neorv32_tb.simple.vhd | 2 +-
6 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/docs/datasheet/soc.adoc b/docs/datasheet/soc.adoc
index 8923de021..273ea45e0 100644
--- a/docs/datasheet/soc.adoc
+++ b/docs/datasheet/soc.adoc
@@ -87,12 +87,12 @@ Some interfaces (like the TWI and the 1-Wire bus) require tri-state drivers in t
| `jtag_tms_i` | 1 | in | `'L'` | mode select
5+^| **<<_processor_external_bus_interface_xbus>>**
| `xbus_adr_o` | 32 | out | - | destination address
-| `xbus_dat_i` | 32 | in | `'L'` | write data
| `xbus_dat_o` | 32 | out | - | read data
| `xbus_we_o` | 1 | out | - | write enable ('0' = read transfer)
| `xbus_sel_o` | 4 | out | - | byte enable
| `xbus_stb_o` | 1 | out | - | strobe
| `xbus_cyc_o` | 1 | out | - | valid cycle
+| `xbus_dat_i` | 32 | in | `'L'` | write data
| `xbus_ack_i` | 1 | in | `'L'` | transfer acknowledge
| `xbus_err_i` | 1 | in | `'L'` | transfer error
5+^| **<<_stream_link_interface_slink>>**
diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd
index f6ea707a1..0df921cdc 100644
--- a/rtl/core/neorv32_package.vhd
+++ b/rtl/core/neorv32_package.vhd
@@ -29,7 +29,7 @@ package neorv32_package is
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
- constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090803"; -- hardware version
+ constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090804"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
@@ -816,12 +816,12 @@ package neorv32_package is
jtag_tms_i : in std_ulogic := 'L';
-- External bus interface (available if XBUS_EN = true) --
xbus_adr_o : out std_ulogic_vector(31 downto 0);
- xbus_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
xbus_dat_o : out std_ulogic_vector(31 downto 0);
xbus_we_o : out std_ulogic;
xbus_sel_o : out std_ulogic_vector(03 downto 0);
xbus_stb_o : out std_ulogic;
xbus_cyc_o : out std_ulogic;
+ xbus_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
xbus_ack_i : in std_ulogic := 'L';
xbus_err_i : in std_ulogic := 'L';
-- Stream Link Interface (available if IO_SLINK_EN = true) --
diff --git a/rtl/core/neorv32_top.vhd b/rtl/core/neorv32_top.vhd
index 2540c38c9..2a7c015c6 100644
--- a/rtl/core/neorv32_top.vhd
+++ b/rtl/core/neorv32_top.vhd
@@ -149,12 +149,12 @@ entity neorv32_top is
-- External bus interface (available if XBUS_EN = true) --
xbus_adr_o : out std_ulogic_vector(31 downto 0); -- address
- xbus_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L'); -- read data
xbus_dat_o : out std_ulogic_vector(31 downto 0); -- write data
xbus_we_o : out std_ulogic; -- read/write
xbus_sel_o : out std_ulogic_vector(03 downto 0); -- byte enable
xbus_stb_o : out std_ulogic; -- strobe
xbus_cyc_o : out std_ulogic; -- valid cycle
+ xbus_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L'); -- read data
xbus_ack_i : in std_ulogic := 'L'; -- transfer acknowledge
xbus_err_i : in std_ulogic := 'L'; -- transfer error
diff --git a/rtl/system_integration/neorv32_litex_core_complex.vhd b/rtl/system_integration/neorv32_litex_core_complex.vhd
index a0571ffa2..f414c21c8 100644
--- a/rtl/system_integration/neorv32_litex_core_complex.vhd
+++ b/rtl/system_integration/neorv32_litex_core_complex.vhd
@@ -161,12 +161,12 @@ begin
jtag_tms_i => jtag_tms_i, -- mode select
-- External bus interface --
xbus_adr_o => wb_adr_o, -- address
- xbus_dat_i => wb_dat_i, -- read data
xbus_dat_o => wb_dat_o, -- write data
xbus_we_o => wb_we_o, -- read/write
xbus_sel_o => wb_sel_o, -- byte enable
xbus_stb_o => open, -- strobe
xbus_cyc_o => wb_cyc, -- valid cycle
+ xbus_dat_i => wb_dat_i, -- read data
xbus_ack_i => wb_ack_i, -- transfer acknowledge
xbus_err_i => wb_err_i, -- transfer error
-- CPU Interrupts --
diff --git a/sim/neorv32_tb.vhd b/sim/neorv32_tb.vhd
index 02f1d3405..6dcd0779d 100644
--- a/sim/neorv32_tb.vhd
+++ b/sim/neorv32_tb.vhd
@@ -295,12 +295,12 @@ begin
jtag_tms_i => '0', -- mode select
-- External bus interface (available if XBUS_EN = true) --
xbus_adr_o => wb_cpu.addr, -- address
- xbus_dat_i => wb_cpu.rdata, -- read data
xbus_dat_o => wb_cpu.wdata, -- write data
xbus_we_o => wb_cpu.we, -- read/write
xbus_sel_o => wb_cpu.sel, -- byte enable
xbus_stb_o => wb_cpu.stb, -- strobe
xbus_cyc_o => wb_cpu.cyc, -- valid cycle
+ xbus_dat_i => wb_cpu.rdata, -- read data
xbus_ack_i => wb_cpu.ack, -- transfer acknowledge
xbus_err_i => wb_cpu.err, -- transfer error
-- Stream Link Interface (available if IO_SLINK_EN = true) --
diff --git a/sim/simple/neorv32_tb.simple.vhd b/sim/simple/neorv32_tb.simple.vhd
index 0487ce781..7d880ebd6 100644
--- a/sim/simple/neorv32_tb.simple.vhd
+++ b/sim/simple/neorv32_tb.simple.vhd
@@ -271,12 +271,12 @@ begin
jtag_tms_i => '0', -- mode select
-- External bus interface (available if XBUS_EN = true) --
xbus_adr_o => wb_cpu.addr, -- address
- xbus_dat_i => wb_cpu.rdata, -- read data
xbus_dat_o => wb_cpu.wdata, -- write data
xbus_we_o => wb_cpu.we, -- read/write
xbus_sel_o => wb_cpu.sel, -- byte enable
xbus_stb_o => wb_cpu.stb, -- strobe
xbus_cyc_o => wb_cpu.cyc, -- valid cycle
+ xbus_dat_i => wb_cpu.rdata, -- read data
xbus_ack_i => wb_cpu.ack, -- transfer acknowledge
xbus_err_i => wb_cpu.err, -- transfer error
-- Stream Link Interface (available if IO_SLINK_EN = true) --
From cd2b92a8b01d9d838fe24bdecf8c2a47339d4b72 Mon Sep 17 00:00:00 2001
From: stnolting <22944758+stnolting@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:15:16 +0200
Subject: [PATCH 2/6] :warning: [DMA] use FIRQ select instead of FIRQ mask
---
rtl/core/neorv32_dma.vhd | 16 ++++++++--------
sw/lib/include/neorv32_dma.h | 20 ++++++++++----------
sw/lib/source/neorv32_dma.c | 8 ++++----
sw/svd/neorv32.svd | 6 +++---
4 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/rtl/core/neorv32_dma.vhd b/rtl/core/neorv32_dma.vhd
index 570eef261..3f5ba3504 100644
--- a/rtl/core/neorv32_dma.vhd
+++ b/rtl/core/neorv32_dma.vhd
@@ -50,8 +50,8 @@ architecture neorv32_dma_rtl of neorv32_dma is
constant ctrl_busy_c : natural := 10; -- r/-: DMA transfer in progress
constant ctrl_done_c : natural := 11; -- r/c: a DMA transfer was executed/attempted
--
- constant ctrl_firq_mask_lsb_c : natural := 16; -- r/w: FIRQ trigger mask LSB
- constant ctrl_firq_mask_msb_c : natural := 31; -- r/w: FIRQ trigger mask MSB
+ constant ctrl_firq_sel_lsb_c : natural := 16; -- r/w: FIRQ trigger select LSB
+ constant ctrl_firq_sel_msb_c : natural := 19; -- r/w: FIRQ trigger select MSB
-- transfer quantities --
constant qsel_b2b_c : std_ulogic_vector(1 downto 0) := "00"; -- byte to byte
@@ -64,7 +64,7 @@ architecture neorv32_dma_rtl of neorv32_dma is
enable : std_ulogic; -- DMA enabled when set
auto : std_ulogic; -- FIRQ-driven auto transfer
fence : std_ulogic; -- issue FENCE operation when DMA is done
- firq_mask : std_ulogic_vector(15 downto 0); -- FIRQ trigger mask
+ firq_sel : std_ulogic_vector(03 downto 0); -- FIRQ trigger select
src_base : std_ulogic_vector(31 downto 0); -- source base address
dst_base : std_ulogic_vector(31 downto 0); -- destination base address
num : std_ulogic_vector(23 downto 0); -- number of elements
@@ -116,7 +116,7 @@ begin
config.enable <= '0';
config.auto <= '0';
config.fence <= '0';
- config.firq_mask <= (others => '0');
+ config.firq_sel <= (others => '0');
config.src_base <= (others => '0');
config.dst_base <= (others => '0');
config.num <= (others => '0');
@@ -143,7 +143,7 @@ begin
config.auto <= bus_req_i.data(ctrl_auto_c);
config.fence <= bus_req_i.data(ctrl_fence_c);
config.done <= '0'; -- clear on write access
- config.firq_mask <= bus_req_i.data(ctrl_firq_mask_msb_c downto ctrl_firq_mask_lsb_c);
+ config.firq_sel <= bus_req_i.data(ctrl_firq_sel_msb_c downto ctrl_firq_sel_lsb_c);
end if;
if (bus_req_i.addr(3 downto 2) = "01") then -- source base address
config.src_base <= bus_req_i.data;
@@ -169,7 +169,7 @@ begin
bus_rsp_o.data(ctrl_error_wr_c) <= engine.err_wr;
bus_rsp_o.data(ctrl_busy_c) <= engine.busy;
bus_rsp_o.data(ctrl_done_c) <= config.done;
- bus_rsp_o.data(ctrl_firq_mask_msb_c downto ctrl_firq_mask_lsb_c) <= config.firq_mask;
+ bus_rsp_o.data(ctrl_firq_sel_msb_c downto ctrl_firq_sel_lsb_c) <= config.firq_sel;
when "01" => -- address of last read access
bus_rsp_o.data <= engine.src_addr;
when "10" => -- address of last write access
@@ -205,8 +205,8 @@ begin
end if;
end process automatic_trigger;
- -- logical OR of all enabled trigger FIRQs --
- match <= or_reduce_f(firq_buf and config.firq_mask);
+ -- select a single FIRQ --
+ match <= firq_buf(to_integer(unsigned(config.firq_sel)));
-- Bus Access Engine ----------------------------------------------------------------------
diff --git a/sw/lib/include/neorv32_dma.h b/sw/lib/include/neorv32_dma.h
index cdb4bfa6d..f02e17a80 100644
--- a/sw/lib/include/neorv32_dma.h
+++ b/sw/lib/include/neorv32_dma.h
@@ -60,17 +60,17 @@ typedef volatile struct __attribute__((packed,aligned(4))) {
/** DMA control and status register bits */
enum NEORV32_DMA_CTRL_enum {
- DMA_CTRL_EN = 0, /**< DMA control register(0) (r/w): DMA enable */
- DMA_CTRL_AUTO = 1, /**< DMA control register(1) (r/w): Automatic trigger mode enable */
- DMA_CTRL_FENCE = 2, /**< DMA control register(2) (r/w): Issue FENCE downstream operation when DMA transfer is completed */
+ DMA_CTRL_EN = 0, /**< DMA control register(0) (r/w): DMA enable */
+ DMA_CTRL_AUTO = 1, /**< DMA control register(1) (r/w): Automatic trigger mode enable */
+ DMA_CTRL_FENCE = 2, /**< DMA control register(2) (r/w): Issue FENCE downstream operation when DMA transfer is completed */
- DMA_CTRL_ERROR_RD = 8, /**< DMA control register(8) (r/-): Error during read access; SRC_BASE shows the faulting address */
- DMA_CTRL_ERROR_WR = 9, /**< DMA control register(9) (r/-): Error during write access; DST_BASE shows the faulting address */
- DMA_CTRL_BUSY = 10, /**< DMA control register(10) (r/-): DMA busy / transfer in progress */
- DMA_CTRL_DONE = 11, /**< DMA control register(11) (r/c): A transfer was executed when set */
+ DMA_CTRL_ERROR_RD = 8, /**< DMA control register(8) (r/-): Error during read access; SRC_BASE shows the faulting address */
+ DMA_CTRL_ERROR_WR = 9, /**< DMA control register(9) (r/-): Error during write access; DST_BASE shows the faulting address */
+ DMA_CTRL_BUSY = 10, /**< DMA control register(10) (r/-): DMA busy / transfer in progress */
+ DMA_CTRL_DONE = 11, /**< DMA control register(11) (r/c): A transfer was executed when set */
- DMA_CTRL_FIRQ_MASK_LSB = 16, /**< DMA control register(16) (r/w): FIRQ trigger mask LSB */
- DMA_CTRL_FIRQ_MASK_MSB = 31 /**< DMA control register(31) (r/w): FIRQ trigger mask MSB */
+ DMA_CTRL_FIRQ_SEL_LSB = 16, /**< DMA control register(16) (r/w): FIRQ trigger select LSB */
+ DMA_CTRL_FIRQ_SEL_MSB = 19 /**< DMA control register(19) (r/w): FIRQ trigger select MSB */
};
/** DMA transfer type bits */
@@ -127,7 +127,7 @@ void neorv32_dma_disable(void);
void neorv32_dma_fence_enable(void);
void neorv32_dma_fence_disable(void);
void neorv32_dma_transfer(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config);
-void neorv32_dma_transfer_auto(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config, uint32_t firq_mask);
+void neorv32_dma_transfer_auto(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config, int firq_sel);
int neorv32_dma_status(void);
int neorv32_dma_done(void);
/**@}*/
diff --git a/sw/lib/source/neorv32_dma.c b/sw/lib/source/neorv32_dma.c
index 67e900483..f2dcaa76e 100644
--- a/sw/lib/source/neorv32_dma.c
+++ b/sw/lib/source/neorv32_dma.c
@@ -121,14 +121,14 @@ void neorv32_dma_transfer(uint32_t base_src, uint32_t base_dst, uint32_t num, ui
* @param[in] base_dst Destination base address (has to be aligned to destination data type!).
* @param[in] num Number of elements to transfer (24-bit).
* @param[in] config Transfer type configuration/commands.
- * @param[in] firq_mask FIRQ trigger mask (#NEORV32_CSR_MIP_enum).
+ * @param[in] firq_sel FIRQ trigger select (#NEORV32_CSR_MIP_enum); only FIRQ0..FIRQ15 = 16..31.
**************************************************************************/
-void neorv32_dma_transfer_auto(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config, uint32_t firq_mask) {
+void neorv32_dma_transfer_auto(uint32_t base_src, uint32_t base_dst, uint32_t num, uint32_t config, int firq_sel) {
uint32_t tmp = NEORV32_DMA->CTRL;
tmp |= (uint32_t)(1 << DMA_CTRL_AUTO); // automatic transfer trigger
- tmp &= 0x0000ffffUL; // clear current FIRQ mask
- tmp |= firq_mask & 0xffff0000UL; // set new FIRQ mask
+ tmp &= ~(0xf << DMA_CTRL_FIRQ_SEL_LSB); // clear current FIRQ select
+ tmp |= (uint32_t)((firq_sel & 0xf) << DMA_CTRL_FIRQ_SEL_LSB); // set new FIRQ select
NEORV32_DMA->CTRL = tmp;
NEORV32_DMA->SRC_BASE = base_src;
diff --git a/sw/svd/neorv32.svd b/sw/svd/neorv32.svd
index 922897767..7431ce9b1 100644
--- a/sw/svd/neorv32.svd
+++ b/sw/svd/neorv32.svd
@@ -422,9 +422,9 @@
DMA transfer done; auto-clears on write access
- DMA_CTRL_FIRQ_MASK
- [31:16]
- FIRQ trigger mask
+ DMA_CTRL_FIRQ_SEL
+ [19:16]
+ FIRQ trigger select
From 9b473174400b39d3e7ad351d5136c3be32acc831 Mon Sep 17 00:00:00 2001
From: stnolting <22944758+stnolting@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:19:04 +0200
Subject: [PATCH 3/6] [changelog] add v1.9.8.4
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72b877431..aa7e409f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
| Date | Version | Comment | Link |
|:----:|:-------:|:--------|:----:|
+| 16.04.2024 | 1.9.8.4 | :warning: use a 4-bit FIRQ select instead of a 16-bit FIRQ mask for DMA auto-trigger configuration | [#877](https://github.com/stnolting/neorv32/pull/877) |
| 15.04.2024 | 1.9.8.3 | :warning: simplify XBUS gateway logic and configuration generics; only "pipelined Wishbone" protocol is supported now | [#876](https://github.com/stnolting/neorv32/pull/876) |
| 14.04.2024 | 1.9.8.2 | :warning: rename SLINK data interface registers; minor CPU control logic/area optimizations | [#874](https://github.com/stnolting/neorv32/pull/874) |
| 13.04.2024 | 1.9.8.1 | minor rtl code cleanups and optimizations | [#872](https://github.com/stnolting/neorv32/pull/872) |
From 65a9a1ca4dbc6302434441f5777ece19a29a19e3 Mon Sep 17 00:00:00 2001
From: stnolting <22944758+stnolting@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:30:24 +0200
Subject: [PATCH 4/6] [sw] update DMA example program
---
sw/example/demo_dma/main.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/sw/example/demo_dma/main.c b/sw/example/demo_dma/main.c
index 8556efb8d..94c90fe9b 100644
--- a/sw/example/demo_dma/main.c
+++ b/sw/example/demo_dma/main.c
@@ -155,6 +155,9 @@ int main() {
(dma_dst[3] != 0xffee1100)) {
neorv32_uart0_printf("Incorrect DST data!\n");
}
+ else {
+ neorv32_uart0_printf("Transfer succeeded!\n");
+ }
show_arrays();
@@ -199,6 +202,9 @@ int main() {
(dma_dst[3] != 0x66778899)) {
neorv32_uart0_printf("Incorrect DST data!\n");
}
+ else {
+ neorv32_uart0_printf("Transfer succeeded!\n");
+ }
show_arrays();
@@ -236,6 +242,9 @@ int main() {
(dma_dst[3] != 0x00000066)) {
neorv32_uart0_printf("Transfer failed!\n");
}
+ else {
+ neorv32_uart0_printf("Transfer succeeded!\n");
+ }
show_arrays();
@@ -262,11 +271,11 @@ int main() {
DMA_CMD_DST_INC; // auto-increment destination address
// configure automatic DMA transfer
- neorv32_dma_transfer_auto((uint32_t)(&dma_src[3]), // source array base address (data = 0xff)
- (uint32_t)(&dma_dst[0]), // destination array base address
- 16, // number of elements to transfer: 16
- cmd, // transfer type configuration
- 1 << GPTMR_FIRQ_PENDING); // trigger transfer on pending GPTMR interrupt
+ neorv32_dma_transfer_auto((uint32_t)(&dma_src[3]), // source array base address (data = 0xff)
+ (uint32_t)(&dma_dst[0]), // destination array base address
+ 16, // number of elements to transfer: 16
+ cmd, // transfer type configuration
+ GPTMR_FIRQ_PENDING); // trigger transfer on pending GPTMR interrupt
// sleep until interrupt (from DMA)
neorv32_cpu_sleep();
@@ -281,6 +290,9 @@ int main() {
(dma_dst[3] != 0xffffffff)) {
neorv32_uart0_printf("Transfer failed!\n");
}
+ else {
+ neorv32_uart0_printf("Transfer succeeded!\n");
+ }
show_arrays();
}
From fd59f246e4d8b11946c1e3bedfe0f0c9a98ed391 Mon Sep 17 00:00:00 2001
From: stnolting <22944758+stnolting@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:45:24 +0200
Subject: [PATCH 5/6] [sw] remove whitespaces
---
sw/lib/source/neorv32_dma.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/sw/lib/source/neorv32_dma.c b/sw/lib/source/neorv32_dma.c
index f2dcaa76e..f747c31c8 100644
--- a/sw/lib/source/neorv32_dma.c
+++ b/sw/lib/source/neorv32_dma.c
@@ -175,5 +175,4 @@ int neorv32_dma_done(void) {
else {
return 0; // no transfer executed
}
-
}
From 5dc46386914f52923e0de323717a2b74378e3dad Mon Sep 17 00:00:00 2001
From: stnolting <22944758+stnolting@users.noreply.github.com>
Date: Tue, 16 Apr 2024 21:48:10 +0200
Subject: [PATCH 6/6] [docs] update DMA auto-trigger section
---
docs/datasheet/soc_dma.adoc | 46 ++++++++++++++++++-------------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/docs/datasheet/soc_dma.adoc b/docs/datasheet/soc_dma.adoc
index b85052345..1ab388c26 100644
--- a/docs/datasheet/soc_dma.adoc
+++ b/docs/datasheet/soc_dma.adoc
@@ -5,12 +5,12 @@
[cols="<3,<3,<4"]
[frame="topbot",grid="none"]
|=======================
-| Hardware source file(s): | neorv32_dma.vhd |
-| Software driver file(s): | neorv32_dma.c |
-| | neorv32_dma.h |
-| Top entity port: | none |
-| Configuration generics: | `IO_DMA_EN` | implement DMA when `true`
-| CPU interrupts: | fast IRQ channel 10 | DMA transfer done (see <<_processor_interrupts>>)
+| Hardware source files: | neorv32_dma.vhd |
+| Software driver files: | neorv32_dma.c |
+| | neorv32_dma.h |
+| Top entity ports: | none |
+| Configuration generics: | `IO_DMA_EN` | implement DMA when `true`
+| CPU interrupts: | fast IRQ channel 10 | DMA transfer done (see <<_processor_interrupts>>)
|=======================
@@ -98,19 +98,18 @@ data quantity has to be set to **word** (32-bit) since all IO registers can only
**Automatic Trigger**
As an alternative to the manual trigger mode, the DMA can be configured to **automatic trigger mode** starting a pre-configured
-transfer if a specific processor-internal peripheral issues an interrupt request. The automatic trigger mode is enabled by
+transfer if a specific processor-internal peripheral issues a FIRQ interrupt request. The automatic trigger mode is enabled by
setting the `CTRL` register's `DMA_CTRL_AUTO` bit. In this configuration _no_ transfer is started when writing to the DMA's
`TTYPE` register.
-The actual trigger is configured via the control register `DMA_CTRL_FIRQ_MASK`. These bits reflect the state of the CPU's
-<<_mip>> CSR showing any pending fast interrupt requests (for a full list see <<_neorv32_specific_fast_interrupt_requests>>).
-The same bit definitions/locations as for the <<_mip>> and <<_mie>> CPU CSRs are used.
-If any of the enabled sources issues an interrupt the DMA will start the pre-configured transfer (note that all enabled
-sources are logically OR-ed).
+The actually triggering FIRQ channel is configured via the control register's `DMA_CTRL_FIRQ_SEL` bits. Writing a 0 will
+select FIRQ channel 0, writing a 1 will select FIRQ channel 1, and so on. See section <<_processor_interrupts>>
+for a list of all FIRQ channels and their according sources.
.FIRQ Trigger
[NOTE]
-The DMA transfer will start if a **rising edge** is detected on _any_ of the enabled FIRQ source channels.
+The DMA transfer will start if a **rising edge** is detected on the configured FIRQ channel. Hence, the DMA is triggered only
+once even if the selected FIRQ channel keeps pending.
**Memory Barrier / Fence Operation**
@@ -135,16 +134,17 @@ register).
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
-.10+<| `0xffffed00` .10+<| `CTRL` <|`0` `DMA_CTRL_EN` ^| r/w <| DMA module enable
- <|`1` `DMA_CTRL_AUTO` ^| r/w <| Enable automatic mode (FIRQ-triggered)
- <|`2` `DMA_CTRL_FENCE` ^| r/w <| Issue a downstream FENCE operation when DMA transfer completes (without errors)
- <|`7:3` _reserved_ ^| r/- <| reserved, read as zero
- <|`8` `DMA_CTRL_ERROR_RD` ^| r/- <| Error during read access, clears when starting a new transfer
- <|`9` `DMA_CTRL_ERROR_WR` ^| r/- <| Error during write access, clears when starting a new transfer
- <|`10` `DMA_CTRL_BUSY` ^| r/- <| DMA transfer in progress
- <|`11` `DMA_CTRL_DONE` ^| r/c <| Set if a transfer was executed; auto-clears on write-access
- <|`15:12` _reserved_ ^| r/- <| reserved, read as zero
- <|`31:16` `DMA_CTRL_FIRQ_MASK_MSB : DMA_CTRL_FIRQ_MASK_LSB` ^| r/w <| FIRQ trigger mask (same bits as in <<_mip>>)
+.11+<| `0xffffed00` .11+<| `CTRL` <|`0` `DMA_CTRL_EN` ^| r/w <| DMA module enable
+ <|`1` `DMA_CTRL_AUTO` ^| r/w <| Enable automatic mode (FIRQ-triggered)
+ <|`2` `DMA_CTRL_FENCE` ^| r/w <| Issue a downstream FENCE operation when DMA transfer completes (without errors)
+ <|`7:3` _reserved_ ^| r/- <| reserved, read as zero
+ <|`8` `DMA_CTRL_ERROR_RD` ^| r/- <| Error during read access, clears when starting a new transfer
+ <|`9` `DMA_CTRL_ERROR_WR` ^| r/- <| Error during write access, clears when starting a new transfer
+ <|`10` `DMA_CTRL_BUSY` ^| r/- <| DMA transfer in progress
+ <|`11` `DMA_CTRL_DONE` ^| r/c <| Set if a transfer was executed; auto-clears on write-access
+ <|`15:12` _reserved_ ^| r/- <| reserved, read as zero
+ <|`19:16` `DMA_CTRL_FIRQ_SEL_MSB : DMA_CTRL_FIRQ_SEL_LSB` ^| r/w <| FIRQ trigger select (FIRQ0=0 ... FIRQ15=15)
+ <|`31:20` _reserved_ ^| r/- <| reserved, read as zero
| `0xffffed04` | `SRC_BASE` |`31:0` | r/w | Source base address (shows the last-accessed source address when read)
| `0xffffed08` | `DST_BASE` |`31:0` | r/w | Destination base address (shows the last-accessed destination address when read)
.6+<| `0xffffed0c` .6+<| `TTYPE` <|`23:0` `DMA_TTYPE_NUM_MSB : DMA_TTYPE_NUM_LSB` ^| r/w <| Number of elements to transfer (shows the last-transferred element index when read)