[rtl] minor GPTMR code reworks (#529)

This commit is contained in:
Stephan 2023-03-03 07:36:33 +01:00 committed by GitHub
commit 747fcd5577
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 49 deletions

View file

@ -31,7 +31,8 @@ mimpid = 0x01040312 => Version 01.04.03.12 => v1.4.3.12
| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 02.03.2023 | 1.8.1.4 | :bug: fix timeout bug in **FPU** (conversion and add/sub instructions); #528 |
| 02.03.2023 | 1.8.1.5 | minor general purpose timer (GPTMR) code edits; [#529](https://github.com/stnolting/neorv32/pull/529) |
| 02.03.2023 | 1.8.1.4 | :bug: fix timeout bug in **FPU** (conversion and add/sub instructions); [#528](https://github.com/stnolting/neorv32/pull/528) |
| 25.02.2023 | 1.8.1.3 | :sparkles: add new processor module: **Serial Data Interface (SDI)** - a SPI _device-class_ interface; [#505](https://github.com/stnolting/neorv32/pull/505) |
| 24.02.2023 | 1.8.1.2 | :warning: rename top interface signals of **XIP** and **SIP** modules; [#504](https://github.com/stnolting/neorv32/pull/504) |
| 23.02.2023 | 1.8.1.1 | CFS: add another 32 interface register (now having 64 memory-mapped registers for custom usage); [#503](https://github.com/stnolting/neorv32/pull/503) |

View file

@ -46,8 +46,8 @@ writing zero to it.
**Timer Interrupt**
The timer interrupt is triggered when the timer is enabled and `COUNT` matches `THRES`. The interrupt
remains pending until explicitly cleared by writing zero to the according <<_mip>> CSR bit.
The GPTMR interrupt is triggered when the timer is enabled and `COUNT` matches `THRES`. The interrupt
remains pending inside the CPU until it explicitly cleared by writing zero to the according <<_mip>> CSR bit.
**Register Map**

View file

@ -84,34 +84,22 @@ architecture neorv32_gptmr_rtl of neorv32_gptmr is
signal wren : std_ulogic; -- word write enable
signal rden : std_ulogic; -- read enable
-- clock generator --
signal gptmr_clk_en : std_ulogic;
-- timer core --
type timer_t is record
count : std_ulogic_vector(31 downto 0); -- counter register
thres : std_ulogic_vector(31 downto 0); -- threshold value
tick : std_ulogic; -- clock generator tick
match : std_ulogic; -- count == thres
cnt_we : std_ulogic; -- write access to count
end record;
signal timer : timer_t;
-- interrupt detector --
signal irq_detect : std_ulogic_vector(1 downto 0);
begin
-- Access Control -------------------------------------------------------------------------
-- Host Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = gptmr_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= gptmr_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Write Access ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
write_access: process(rstn_i, clk_i)
-- write access --
process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
timer.cnt_we <= '0';
@ -135,18 +123,10 @@ begin
end if;
end if;
end if;
end process write_access;
end process;
-- clock generator enable --
clkgen_en_o <= ctrl(ctrl_en_c);
-- clock select --
gptmr_clk_en <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c))));
-- Read Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
read_access: process(clk_i)
-- read access --
process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden or wren; -- bus access acknowledge
@ -166,19 +146,25 @@ begin
end case;
end if;
end if;
end process read_access;
end process;
-- access control --
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = gptmr_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= gptmr_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
-- Timer Core -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
timer_core: process(rstn_i, clk_i)
process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
timer.count <= (others => '0');
elsif rising_edge(clk_i) then
if (timer.cnt_we = '1') then -- write access
timer.count <= data_i; -- data_i will stay unchanged for min. 1 cycle after WREN has returned to low again
elsif (ctrl(ctrl_en_c) = '1') and (gptmr_clk_en = '1') then -- enabled and clock tick
elsif (ctrl(ctrl_en_c) = '1') and (timer.tick = '1') then -- enabled and clock tick
if (timer.match = '1') then
if (ctrl(ctrl_mode_c) = '1') then -- reset counter if continuous mode
timer.count <= (others => '0');
@ -188,27 +174,29 @@ begin
end if;
end if;
end if;
end process timer_core;
end process;
-- counter = threshold? --
timer.match <= '1' when (timer.count = timer.thres) else '0';
-- clock generator enable --
clkgen_en_o <= ctrl(ctrl_en_c);
-- Interrupt Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
irq_generator: process(clk_i)
-- clock select --
process(clk_i)
begin
if rising_edge(clk_i) then
if (ctrl(ctrl_en_c) = '0') then
irq_detect <= "00";
else
irq_detect <= irq_detect(0) & timer.match;
end if;
timer.tick <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c))));
end if;
end process irq_generator;
end process;
-- IRQ request to CPU --
irq_o <= '1' when (irq_detect = "01") else '0';
-- interrupt --
process(clk_i)
begin
if rising_edge(clk_i) then
irq_o <= ctrl(ctrl_en_c) and timer.match;
end if;
end process;
end neorv32_gptmr_rtl;

View file

@ -65,7 +65,7 @@ package neorv32_package is
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080104"; -- NEORV32 version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080105"; -- NEORV32 version
constant archid_c : natural := 19; -- official RISC-V architecture ID
-- Check if we're inside the Matrix -------------------------------------------------------

View file

@ -64,10 +64,10 @@ void gptmr_firq_handler(void);
**************************************************************************/
int main() {
// capture all exceptions and give debug info via UART
// setup NEORV32 runtime environment (for trap handling)
neorv32_rte_setup();
// init UART at default baud rate, no parity bits, no HW flow control
// setup UART at default baud rate, no parity bits, no HW flow control
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
@ -93,7 +93,8 @@ int main() {
neorv32_gptmr_setup(CLK_PRSC_8, 1, NEORV32_SYSINFO->CLK / (8 * 2));
// enable interrupt
neorv32_cpu_csr_set(CSR_MIE, 1 << GPTMR_FIRQ_ENABLE); // enable GPTMR FIRQ channel
neorv32_cpu_csr_clr(CSR_MIP, 1 << GPTMR_FIRQ_PENDING); // make sure there is no GPTMR IRQ pending already
neorv32_cpu_csr_set(CSR_MIE, 1 << GPTMR_FIRQ_ENABLE); // enable GPTMR FIRQ channel
neorv32_cpu_csr_set(CSR_MSTATUS, 1 << CSR_MSTATUS_MIE); // enable machine-mode interrupts