diff --git a/CHANGELOG.md b/CHANGELOG.md index e118460be..6baa2b4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12 | Date | Version | Comment | Link | |:----:|:-------:|:--------|:----:| +| 10.01.2024 | 1.9.2.10 | re-add MTIME system time output to processor top (`mtime_time_o`) | [#762](https://github.com/stnolting/neorv32/pull/762) | | 08.01.2024 | 1.9.2.9 | minor rtl code cleanups | [#760](https://github.com/stnolting/neorv32/pull/760) | | 06.01.2024 | 1.9.2.8 | :sparkles: add timer-capture mode to General Purpose Timer (GPTMR); :warning: remove "single-shot" mode, change control register layout | [#759](https://github.com/stnolting/neorv32/pull/759) | | 19.12.2023 | 1.9.2.7 | minor rtl code cleanups, edits and optimization; :lock: reset `mtvec`, `mepc` and `dpc` CSRs to CPU boot address (`CPU_BOOT_ADDR` CPU generic) | [#755](https://github.com/stnolting/neorv32/pull/755) | diff --git a/docs/datasheet/soc.adoc b/docs/datasheet/soc.adoc index 9861558fb..22c2f4c81 100644 --- a/docs/datasheet/soc.adoc +++ b/docs/datasheet/soc.adoc @@ -150,6 +150,8 @@ Some interfaces (like the TWI and the 1-Wire bus) require tri-state drivers in t | `cfs_out_o` | 32 | out | custom CFS output signal conduit 4+^| **<<_smart_led_interface_neoled>>** | `neoled_o` | 1 | out | asynchronous serial data output +4+^| **<<_machine_system_timer_mtime>>** +| `mtime_time_o` | 64 | out | MTIME system time output 4+^| **<<_general_purpose_timer_gptmr>>** | `gptmr_trig_i` | 1 | in | timer capture input 4+^| **<<_external_interrupt_controller_xirq>>** diff --git a/docs/datasheet/soc_mtime.adoc b/docs/datasheet/soc_mtime.adoc index c511aaf73..2c48a5b69 100644 --- a/docs/datasheet/soc_mtime.adoc +++ b/docs/datasheet/soc_mtime.adoc @@ -5,31 +5,32 @@ [cols="<3,<3,<4"] [frame="topbot",grid="none"] |======================= -| Hardware source file(s): | neorv32_mtime.vhd | +| Hardware source file(s): | neorv32_mtime.vhd | | Software driver file(s): | neorv32_mtime.c | | | neorv32_mtime.h | -| Top entity port: | `mtime_irq_i` | RISC-V machine timer IRQ if internal one is **not** implemented +| Top entity port: | `mtime_irq_i` | RISC-V machine timer IRQ if internal one is **not** implemented +| | `mtime_time_o` | Current system time (`TIME` register) | Configuration generics: | `IO_MTIME_EN` | implement machine timer when `true` | CPU interrupts: | `MTI` | machine timer interrupt (see <<_processor_interrupts>>) |======================= -The MTIME module implements a memory-mapped MTIME machine system timer that is compatible to the RISC-V -privileged specifications. The 64-bit system time is accessed via the memory-mapped `TIME_LO` and -`TIME_HI` registers. A 64-bit time compare register, which is accessible via the memory-mapped `TIMECMP_LO` -and `TIMECMP_HI` registers, can be used to configure the CPU's `MTI` (machine timer interrupt). The interrupt +The MTIME module implements a memory-mapped machine system timer that is compatible to the RISC-V +privileged specifications. The 64-bit system time is accessed via individual `TIME_LO` and +`TIME_HI` registers. A 64-bit time compare register, which is accessible via individual `TIMECMP_LO` +and `TIMECMP_HI` registers, can be used to configure the CPU's machine timer interrupt (`MTI`)). The interrupt is triggered whenever `TIME` (high & low part) is greater than or equal to `TIMECMP` (high & low part). -The interrupt remains active (=pending) until `TIME` becomes less `TIMECMP` again (either by modifying -`TIME` or `TIMECMP`). +The interrupt remains active (=pending) until `TIME` becomes less than `TIMECMP` again (either by modifying +`TIME` or `TIMECMP`). The current system time is available for other SoC modules via the top's `mtime_time_o` signal. -.Reset +.Hardware Reset [NOTE] After a hardware reset the `TIME` and `TIMECMP` register are reset to all-zero. .External MTIME Interrupt -[IMPORTANT] -If the internal MTIME module is disabled (`IO_MTIME_EN` = `false`) the machine timer interrupt becomes available as external signal. -The `mtime_irq_i` signal is level-triggered and high-active. Once set the signal has to stay high until -the interrupt request is explicitly acknowledged (e.g. writing to a memory-mapped register). +[NOTE] +If the internal MTIME module is disabled (`IO_MTIME_EN` = `false`) the machine timer interrupt becomes available +as external signal. The `mtime_irq_i` signal is level-triggered and high-active. Once set the signal has to stay +high until the interrupt request is explicitly acknowledged (e.g. writing to a user-defined memory-mapped register). **Register Map** @@ -39,8 +40,8 @@ the interrupt request is explicitly acknowledged (e.g. writing to a memory-mappe [options="header",grid="all"] |======================= | Address | Name [C] | Bits | R/W | Function -| `0xfffff400` | `TIME_LO` | 31:0 | r/w | machine system time, low word -| `0xfffff404` | `TIME_HI` | 31:0 | r/w | machine system time, high word +| `0xfffff400` | `TIME_LO` | 31:0 | r/w | system time, low word +| `0xfffff404` | `TIME_HI` | 31:0 | r/w | system time, high word | `0xfffff408` | `TIMECMP_LO` | 31:0 | r/w | time compare, low word | `0xfffff40c` | `TIMECMP_HI` | 31:0 | r/w | time compare, high word |======================= diff --git a/rtl/core/neorv32_mtime.vhd b/rtl/core/neorv32_mtime.vhd index b3601b471..ef1134fc4 100644 --- a/rtl/core/neorv32_mtime.vhd +++ b/rtl/core/neorv32_mtime.vhd @@ -6,7 +6,7 @@ -- # ********************************************************************************************* # -- # BSD 3-Clause License # -- # # --- # Copyright (c) 2023, Stephan Nolting. All rights reserved. # +-- # Copyright (c) 2024, Stephan Nolting. All rights reserved. # -- # # -- # Redistribution and use in source and binary forms, with or without modification, are # -- # permitted provided that the following conditions are met: # @@ -48,6 +48,7 @@ entity neorv32_mtime is rstn_i : in std_ulogic; -- global reset line, low-active, async bus_req_i : in bus_req_t; -- bus request bus_rsp_o : out bus_rsp_t; -- bus response + time_o : out std_ulogic_vector(63 downto 0); -- current system time irq_o : out std_ulogic -- interrupt request ); end neorv32_mtime; @@ -134,6 +135,9 @@ begin -- mtime.time_LO increment -- mtime_lo_nxt <= std_ulogic_vector(unsigned('0' & mtime_lo) + 1); + -- system time output -- + time_o <= mtime_hi & mtime_lo; -- NOTE: low and high words are not synchronized here! + -- Comparator ----------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index a52424a22..dba939026 100644 --- a/rtl/core/neorv32_package.vhd +++ b/rtl/core/neorv32_package.vhd @@ -56,7 +56,7 @@ package neorv32_package is -- Architecture Constants ----------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- - constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090209"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090210"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width @@ -908,6 +908,8 @@ package neorv32_package is cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- neoled_o : out std_ulogic; + -- Machine timer system time (available if IO_MTIME_EN = true) -- + mtime_time_o : out std_ulogic_vector(63 downto 0); -- GPTMR timer capture (available if IO_GPTMR_EN = true) -- gptmr_trig_i : in std_ulogic := 'L'; -- External platform interrupts (available if XIRQ_NUM_CH > 0) -- diff --git a/rtl/core/neorv32_top.vhd b/rtl/core/neorv32_top.vhd index c5f26c187..2f580b18f 100644 --- a/rtl/core/neorv32_top.vhd +++ b/rtl/core/neorv32_top.vhd @@ -241,6 +241,9 @@ entity neorv32_top is -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- neoled_o : out std_ulogic; -- async serial data line + -- Machine timer system time (available if IO_MTIME_EN = true) -- + mtime_time_o : out std_ulogic_vector(63 downto 0); -- current system time + -- GPTMR timer capture (available if IO_GPTMR_EN = true) -- gptmr_trig_i : in std_ulogic := 'L'; -- capture trigger @@ -336,6 +339,9 @@ architecture neorv32_top_rtl of neorv32_top is signal firq : irq_t; signal mtime_irq : std_ulogic; + -- misc -- + signal mtime_time : std_ulogic_vector(63 downto 0); + begin -- ************************************************************************************************************************** @@ -1109,14 +1115,30 @@ begin rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_MTIME), bus_rsp_o => iodev_rsp(IODEV_MTIME), + time_o => mtime_time, irq_o => mtime_irq ); + + -- synchronize system time output LO -- + mtime_sync: process(rstn_sys, clk_i) + begin + if (rstn_sys = '0') then + mtime_time_o(31 downto 0) <= (others => '0'); + elsif rising_edge(clk_i) then + mtime_time_o(31 downto 0) <= mtime_time(31 downto 0); + end if; + end process mtime_sync; + + -- system time output HI -- + mtime_time_o(63 downto 32) <= mtime_time(63 downto 32); + end generate; neorv32_mtime_inst_false: if (IO_MTIME_EN = false) generate iodev_rsp(IODEV_MTIME) <= rsp_terminate_c; mtime_irq <= mtime_irq_i; + mtime_time_o <= (others => '0'); end generate; diff --git a/sim/neorv32_tb.vhd b/sim/neorv32_tb.vhd index 7d66650e2..b9b7338c1 100644 --- a/sim/neorv32_tb.vhd +++ b/sim/neorv32_tb.vhd @@ -377,6 +377,8 @@ begin cfs_out_o => open, -- custom CFS outputs -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- neoled_o => open, -- async serial data line + -- Machine timer system time (available if IO_MTIME_EN = true) -- + mtime_time_o => open, -- GPTMR timer capture (available if IO_GPTMR_EN = true) -- gptmr_trig_i => gpio(63), -- capture trigger -- External platform interrupts (available if XIRQ_NUM_CH > 0) -- diff --git a/sim/simple/neorv32_tb.simple.vhd b/sim/simple/neorv32_tb.simple.vhd index d8513278c..024bcd297 100644 --- a/sim/simple/neorv32_tb.simple.vhd +++ b/sim/simple/neorv32_tb.simple.vhd @@ -325,6 +325,8 @@ begin cfs_out_o => open, -- custom CFS outputs -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- neoled_o => open, -- async serial data line + -- Machine timer system time (available if IO_MTIME_EN = true) -- + mtime_time_o => open, -- GPTMR timer capture (available if IO_GPTMR_EN = true) -- gptmr_trig_i => gpio(63), -- capture trigger -- External platform interrupts (available if XIRQ_NUM_CH > 0) --