Skip to content

Commit

Permalink
⚠️ rework ONEWIRE and GPTMR interrupts (#859)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting committed Mar 23, 2024
2 parents 9c922c0 + 2322027 commit fe384b7
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 66 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12

| Date | Version | Comment | Link |
|:----:|:-------:|:--------|:----:|
| 23.03.2024 | 1.9.7.3 | :warning: **interrupt system rework**: rework ONEWIRE and GPTMR interrupts | [#859](https://github.com/stnolting/neorv32/pull/859) |
| 23.03.2024 | 1.9.7.2 | :warning: **interrupt system rework**: removed WDT and TRNG interrupts; :bug: fix core complex clocking during sleep mode | [#858](https://github.com/stnolting/neorv32/pull/858) |
| 23.03.2024 | 1.9.7.1 | CPU hardware optimization (reduced hardware footprint, shortened critical path) | [#857](https://github.com/stnolting/neorv32/pull/857) |
| 22.03.2024 | [**:rocket:1.9.7**](https://github.com/stnolting/neorv32/releases/tag/v1.9.7) | **New release** | |
Expand Down
7 changes: 3 additions & 4 deletions docs/datasheet/soc_onewire.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,9 @@ time **T~base~** (and by eventually changing the hardwired timing configuration

**Interrupt**

A single interrupt is provided by the ONEWIRE module to signal "operation done" condition to the CPU. Whenever the
controller completes a "generate reset pulse", a "transfer single-bit" or a "transfer full-byte" operation the
interrupt is triggered. Once triggered, the interrupt has to be _explicitly_ cleared again by writing zero to the
according <<_mip>> CSR FIRQ bit.
A single interrupt is provided by the ONEWIRE module to signal "idle" condition to the CPU. Whenever the
controller is idle (again) the interrupt becomes active. Once triggered, the interrupt has to be _explicitly_
cleared again by writing zero to the according <<_mip>> CSR FIRQ bit.


**Register Map**
Expand Down
4 changes: 1 addition & 3 deletions rtl/core/neorv32_cfs.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ begin
-- Interrupt ------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The CFS features a single interrupt signal, which is connected to the CPU's "fast interrupt" channel 1 (FIRQ1).
-- The interrupt is triggered by a one-cycle high-level. After triggering, the interrupt appears as "pending" in the CPU's
-- mip CSR ready to trigger execution of the according interrupt handler. It is the task of the application to programmer
-- to enable/clear the CFS interrupt using the CPU's mie and mip registers when required.
-- The according CPU interrupt becomes pending as long as <irq_o> is high.

irq_o <= '0'; -- not used for this minimal example

Expand Down
52 changes: 18 additions & 34 deletions rtl/core/neorv32_gptmr.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ end neorv32_gptmr;
architecture neorv32_gptmr_rtl of neorv32_gptmr is

-- control register --
constant ctrl_en_c : natural := 0; -- r/w: GPTMR enable
constant ctrl_en_c : natural := 0; -- r/w: global enable
constant ctrl_prsc0_c : natural := 1; -- r/w: clock prescaler select bit 0
constant ctrl_prsc1_c : natural := 2; -- r/w: clock prescaler select bit 1
constant ctrl_prsc2_c : natural := 3; -- r/w: clock prescaler select bit 2
Expand Down Expand Up @@ -122,25 +122,23 @@ begin
bus_rsp_o.data <= (others => '0');
timer.cnt_we <= '0';

-- trigger flags --
trig_match <= ctrl(ctrl_en_c) and (trig_match or timer.trigger);
trig_capture <= ctrl(ctrl_en_c) and (trig_capture or capture.trigger);
-- IRQ trigger --
trig_match <= ctrl(ctrl_en_c) and ctrl(ctrl_irqm_c) and (trig_match or timer.trigger);
trig_capture <= ctrl(ctrl_en_c) and ctrl(ctrl_irqc_c) and (trig_capture or capture.trigger);

-- actual bus access --
if (bus_req_i.stb = '1') then

-- write access --
if (bus_req_i.rw = '1') then
if (bus_req_i.rw = '1') then -- write access
if (bus_req_i.addr(3 downto 2) = "00") then -- control register
ctrl(ctrl_en_c) <= bus_req_i.data(ctrl_en_c);
ctrl(ctrl_prsc0_c) <= bus_req_i.data(ctrl_prsc0_c);
ctrl(ctrl_prsc1_c) <= bus_req_i.data(ctrl_prsc1_c);
ctrl(ctrl_prsc2_c) <= bus_req_i.data(ctrl_prsc2_c);
ctrl(ctrl_irqm_c) <= bus_req_i.data(ctrl_irqm_c);
ctrl(ctrl_irqc_c) <= bus_req_i.data(ctrl_irqc_c);
ctrl(ctrl_rise_c) <= bus_req_i.data(ctrl_rise_c);
ctrl(ctrl_fall_c) <= bus_req_i.data(ctrl_fall_c);
ctrl(ctrl_filter_c) <= bus_req_i.data(ctrl_filter_c);
ctrl(ctrl_en_c) <= bus_req_i.data(ctrl_en_c);
ctrl(ctrl_prsc0_c) <= bus_req_i.data(ctrl_prsc0_c);
ctrl(ctrl_prsc1_c) <= bus_req_i.data(ctrl_prsc1_c);
ctrl(ctrl_prsc2_c) <= bus_req_i.data(ctrl_prsc2_c);
ctrl(ctrl_irqm_c) <= bus_req_i.data(ctrl_irqm_c);
ctrl(ctrl_irqc_c) <= bus_req_i.data(ctrl_irqc_c);
ctrl(ctrl_rise_c) <= bus_req_i.data(ctrl_rise_c);
ctrl(ctrl_fall_c) <= bus_req_i.data(ctrl_fall_c);
ctrl(ctrl_filter_c) <= bus_req_i.data(ctrl_filter_c);
if (bus_req_i.data(ctrl_trigm_c) = '0') then -- clear by writing zero
trig_match <= '0';
end if;
Expand All @@ -154,9 +152,7 @@ begin
if (bus_req_i.addr(3 downto 2) = "10") then -- counter register
timer.cnt_we <= '1';
end if;

-- read access --
else
else -- read access
case bus_req_i.addr(3 downto 2) is
when "00" => -- control register
bus_rsp_o.data(ctrl_en_c) <= ctrl(ctrl_en_c);
Expand All @@ -179,11 +175,13 @@ begin
bus_rsp_o.data <= capture.count;
end case;
end if;

end if;
end if;
end process bus_access;

-- interrupt request --
irq_o <= trig_match or trig_capture;


-- Timer Core -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -274,18 +272,4 @@ begin
(ctrl(ctrl_fall_c) and capture.falling); -- falling-edge trigger


-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_generator: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
irq_o <= '0';
elsif rising_edge(clk_i) then
irq_o <= ctrl(ctrl_en_c) and
((ctrl(ctrl_irqm_c) and timer.trigger) or -- timer-match interrupt
(ctrl(ctrl_irqc_c) and capture.trigger)); -- capture interrupt
end if;
end process irq_generator;


end neorv32_gptmr_rtl;
24 changes: 16 additions & 8 deletions rtl/core/neorv32_onewire.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
-- # * generate reset pulse and check for device presence #
-- # * transfer single bit (read-while-write) #
-- # * transfer full byte (read-while-write) #
-- # After completing any of the operations the interrupt signal is triggered. #
-- # The module's interrupt fires whenever the module is idle (again). #
-- # The base time for bus interactions is configured using a 2-bit clock prescaler and a 8-bit #
-- # clock divider. All bus operations are timed using (hardwired) multiples of this base time. #
-- # ********************************************************************************************* #
Expand Down Expand Up @@ -121,7 +121,6 @@ architecture neorv32_onewire_rtl of neorv32_onewire is
tick : std_ulogic;
tick_ff : std_ulogic;
sreg : std_ulogic_vector(7 downto 0);
done : std_ulogic;
wire_in : std_ulogic_vector(1 downto 0);
wire_lo : std_ulogic;
wire_hi : std_ulogic;
Expand Down Expand Up @@ -238,7 +237,6 @@ begin
begin
if (rstn_i = '0') then
serial.wire_in <= (others => '0');
serial.done <= '0';
serial.wire_lo <= '0';
serial.wire_hi <= '0';
serial.state <= (others => '0');
Expand All @@ -259,7 +257,6 @@ begin
end if;

-- defaults --
serial.done <= '0';
serial.wire_lo <= '0';
serial.wire_hi <= '0';

Expand Down Expand Up @@ -309,7 +306,6 @@ begin
serial.sreg <= serial.sample & serial.sreg(7 downto 1); -- new bit; LSB first
serial.bit_cnt <= serial.bit_cnt - 1;
if (serial.bit_cnt = "000") then -- all done
serial.done <= '1'; -- operation done
serial.state(1 downto 0) <= "00"; -- go back to IDLE
else -- next bit
serial.wire_lo <= '1'; -- force bus to low again
Expand All @@ -333,7 +329,6 @@ begin
end if;
-- end of presence phase --
if (serial.tick_cnt = t_presence_end_c) then
serial.done <= '1'; -- operation done
serial.state(1 downto 0) <= "00"; -- go back to IDLE
end if;

Expand All @@ -350,8 +345,21 @@ begin
-- serial engine busy? --
serial.busy <= '0' when (serial.state(1 downto 0) = "00") else '1';

-- operation done interrupt --
irq_o <= serial.done;

-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_generator: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
irq_o <= '0';
elsif rising_edge(clk_i) then
if (serial.state = "100") then -- enabled and in idle state
irq_o <= '1';
else
irq_o <= '0';
end if;
end if;
end process irq_generator;


end neorv32_onewire_rtl;
2 changes: 1 addition & 1 deletion rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ package neorv32_package is

-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090702"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090703"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width

Expand Down
32 changes: 16 additions & 16 deletions rtl/core/neorv32_sdi.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ begin
-- read access (SDI) --
tx_fifo.re <= serial.start;


-- RX --
rx_fifo_inst: entity neorv32.neorv32_fifo
generic map (
Expand Down Expand Up @@ -262,6 +263,21 @@ begin
rx_fifo.re <= '1' when (bus_req_i.stb = '1') and (bus_req_i.rw = '0') and (bus_req_i.addr(2) = '1') else '0';


-- Interrupt Generator --
irq_generator: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
irq_o <= '0';
elsif rising_edge(clk_i) then
irq_o <= ctrl.enable and (
(ctrl.irq_rx_avail and rx_fifo.avail) or -- RX FIFO not empty
(ctrl.irq_rx_half and rx_fifo.half) or -- RX FIFO at least half full
(ctrl.irq_rx_full and (not rx_fifo.free)) or -- RX FIFO full
(ctrl.irq_tx_empty and (not tx_fifo.avail))); -- TX FIFO empty
end if;
end process irq_generator;


-- Input Synchronizer ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
synchronizer: process(rstn_i, clk_i)
Expand Down Expand Up @@ -351,20 +367,4 @@ begin
sdi_dat_o <= serial.sreg(serial.sreg'left);


-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_generator: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
irq_o <= '0';
elsif rising_edge(clk_i) then
irq_o <= ctrl.enable and (
(ctrl.irq_rx_avail and rx_fifo.avail) or -- RX FIFO not empty
(ctrl.irq_rx_half and rx_fifo.half) or -- RX FIFO at least half full
(ctrl.irq_rx_full and (not rx_fifo.free)) or -- RX FIFO full
(ctrl.irq_tx_empty and (not tx_fifo.avail))); -- TX FIFO empty
end if;
end process irq_generator;


end neorv32_sdi_rtl;

0 comments on commit fe384b7

Please sign in to comment.