Skip to content

Commit 3b24880

Browse files
authored
🐛 [dma] fix byte-enable signal for byte-reads (#1346)
2 parents 7eff93a + a8c22ba commit 3b24880

File tree

3 files changed

+58
-38
lines changed

3 files changed

+58
-38
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
2929

3030
| Date | Version | Comment | Ticket |
3131
|:----:|:-------:|:--------|:------:|
32+
| 20.08.2025 | 1.11.9.9 | :bug: fix DMA's byte-enable signal generation during byte-accesses | [#1346](https://github.com/stnolting/neorv32/pull/1346) |
3233
| 19.08.2025 | 1.11.9.8 | simplify CPU front-end's IPB; code cleanups and logic optimization | [#1345](https://github.com/stnolting/neorv32/pull/1345) |
3334
| 17.08.2025 | 1.11.9.7 | replace IMEM and DMEM RTL modules by a generic memory component | [#1344](https://github.com/stnolting/neorv32/pull/1344) |
3435
| 16.08.2025 | 1.11.9.6 | :warning: rework layout of `SYSINFO.MISC` information register | [#1342](https://github.com/stnolting/neorv32/pull/1342) |

rtl/core/neorv32_dma.vhd

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,25 @@ architecture neorv32_dma_rtl of neorv32_dma is
5757
constant ctrl_done_c : natural := 30; -- r/-: transfer has completed
5858
constant ctrl_busy_c : natural := 31; -- r/-: DMA transfer in progress
5959

60+
-- replicate byte 4 times --
61+
function rep4_f(b : std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
62+
begin
63+
return b & b & b & b;
64+
end function rep4_f;
65+
66+
-- one-hot encoding --
67+
function onehot_f(sel : std_ulogic_vector(1 downto 0)) return std_ulogic_vector is
68+
variable res_v : std_ulogic_vector(3 downto 0);
69+
begin
70+
case sel is
71+
when "00" => res_v := "0001";
72+
when "01" => res_v := "0010";
73+
when "10" => res_v := "0100";
74+
when others => res_v := "1000";
75+
end case;
76+
return res_v;
77+
end function onehot_f;
78+
6079
-- control and status register --
6180
type ctrl_t is record
6281
enable, start, err, done : std_ulogic;
@@ -92,10 +111,10 @@ architecture neorv32_dma_rtl of neorv32_dma is
92111
signal engine : engine_t;
93112

94113
-- address increment --
95-
signal src_add, dst_add : unsigned(31 downto 0);
114+
signal src_add, dst_add : unsigned(31 downto 0);
96115

97116
-- data buffer --
98-
signal rdata, data_buf : std_ulogic_vector(31 downto 0);
117+
signal data_buf : std_ulogic_vector(31 downto 0);
99118

100119
begin
101120

@@ -304,6 +323,29 @@ begin
304323
end process address_inc;
305324

306325

326+
-- Input Data Alignment -------------------------------------------------------------------
327+
-- -------------------------------------------------------------------------------------------
328+
src_align: process(rstn_i, clk_i)
329+
begin
330+
if (rstn_i = '0') then
331+
data_buf <= (others => '0');
332+
elsif rising_edge(clk_i) then
333+
if (engine.state = S_READ_RSP) then
334+
if (engine.src_type(0) = '0') then -- byte
335+
case engine.src_addr(1 downto 0) is
336+
when "00" => data_buf <= rep4_f(dma_rsp_i.data( 7 downto 0));
337+
when "01" => data_buf <= rep4_f(dma_rsp_i.data(15 downto 8));
338+
when "10" => data_buf <= rep4_f(dma_rsp_i.data(23 downto 16));
339+
when others => data_buf <= rep4_f(dma_rsp_i.data(31 downto 24));
340+
end case;
341+
else -- word
342+
data_buf <= dma_rsp_i.data;
343+
end if;
344+
end if;
345+
end if;
346+
end process src_align;
347+
348+
307349
-- Bus Output Control ---------------------------------------------------------------------
308350
-- -------------------------------------------------------------------------------------------
309351
bus_control: process(engine, data_buf)
@@ -320,24 +362,31 @@ begin
320362
dma_req_o.addr <= engine.src_addr(31 downto 2) & "00";
321363
dma_req_o.rw <= '0';
322364
if (engine.src_type(0) = '0') then -- byte
323-
dma_req_o.ben(to_integer(unsigned(engine.src_addr(1 downto 0)))) <= '1';
365+
dma_req_o.ben <= onehot_f(engine.src_addr(1 downto 0));
324366
else -- word
325367
dma_req_o.ben <= (others => '1');
326368
end if;
327369
else -- write access
328370
dma_req_o.addr <= engine.dst_addr(31 downto 2) & "00";
329371
dma_req_o.rw <= '1';
330372
if (engine.dst_type(0) = '0') then -- byte
331-
dma_req_o.ben(to_integer(unsigned(engine.dst_addr(1 downto 0)))) <= '1';
373+
if (engine.bswap = '0') then
374+
dma_req_o.ben <= onehot_f(engine.dst_addr(1 downto 0));
375+
else
376+
dma_req_o.ben <= onehot_f(not engine.dst_addr(1 downto 0));
377+
end if;
332378
else -- word
333379
dma_req_o.ben <= (others => '1');
334380
end if;
335381
end if;
336382
-- output data alignment --
337-
if (engine.dst_type(0) = '0') then -- byte
338-
dma_req_o.data <= data_buf(7 downto 0) & data_buf(7 downto 0) & data_buf(7 downto 0) & data_buf(7 downto 0);
339-
else -- word
383+
if (engine.bswap = '0') then
340384
dma_req_o.data <= data_buf;
385+
else -- swap Endianness
386+
dma_req_o.data( 7 downto 0) <= data_buf(31 downto 24);
387+
dma_req_o.data(15 downto 8) <= data_buf(23 downto 16);
388+
dma_req_o.data(23 downto 16) <= data_buf(15 downto 8);
389+
dma_req_o.data(31 downto 24) <= data_buf( 7 downto 0);
341390
end if;
342391
-- request strobe --
343392
if (engine.state = S_READ_REQ) or (engine.state = S_WRITE_REQ) then
@@ -346,34 +395,4 @@ begin
346395
end process bus_control;
347396

348397

349-
-- Input Data Alignment -------------------------------------------------------------------
350-
-- -------------------------------------------------------------------------------------------
351-
src_align: process(rstn_i, clk_i)
352-
begin
353-
if (rstn_i = '0') then
354-
data_buf <= (others => '0');
355-
elsif rising_edge(clk_i) then
356-
if (engine.state = S_READ_RSP) then
357-
if (engine.src_type(0) = '0') then -- byte
358-
case engine.src_addr(1 downto 0) is
359-
when "00" => data_buf <= x"000000" & rdata(7 downto 0);
360-
when "01" => data_buf <= x"000000" & rdata(15 downto 8);
361-
when "10" => data_buf <= x"000000" & rdata(23 downto 16);
362-
when others => data_buf <= x"000000" & rdata(31 downto 24);
363-
end case;
364-
else -- word
365-
data_buf <= rdata;
366-
end if;
367-
end if;
368-
end if;
369-
end process src_align;
370-
371-
-- swap byte order (Endianness conversion) --
372-
bswap_gen:
373-
for i in 0 to 3 generate
374-
rdata(i*8+7 downto i*8) <= dma_rsp_i.data(i*8+7 downto i*8) when (engine.bswap = '0') else
375-
dma_rsp_i.data((32-i*8)-1 downto 32-(i+1)*8);
376-
end generate;
377-
378-
379398
end neorv32_dma_rtl;

rtl/core/neorv32_package.vhd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ package neorv32_package is
2828

2929
-- Architecture Constants -----------------------------------------------------------------
3030
-- -------------------------------------------------------------------------------------------
31-
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01110908"; -- hardware version
31+
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01110909"; -- hardware version
3232
constant archid_c : natural := 19; -- official RISC-V architecture ID
3333
constant XLEN : natural := 32; -- native data path width
3434

0 commit comments

Comments
 (0)