From ba4c0037ac3c54d80f3522dc02ed4524ff01c9ce Mon Sep 17 00:00:00 2001 From: stnolting Date: Sun, 1 Dec 2024 20:34:02 +0100 Subject: [PATCH 1/6] [package] update version ID --- rtl/core/neorv32_package.vhd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtl/core/neorv32_package.vhd b/rtl/core/neorv32_package.vhd index ff68c2a73..b18d5438f 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"01100607"; -- hardware version + constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100608"; -- hardware version constant archid_c : natural := 19; -- official RISC-V architecture ID constant XLEN : natural := 32; -- native data path width From 8056b357d4e591d3f00d80ae96654e884c931158 Mon Sep 17 00:00:00 2001 From: stnolting Date: Sun, 1 Dec 2024 20:37:08 +0100 Subject: [PATCH 2/6] [twi] add bus sensing logic and flags --- rtl/core/neorv32_twi.vhd | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rtl/core/neorv32_twi.vhd b/rtl/core/neorv32_twi.vhd index 23b410e03..8aa4f0c6a 100644 --- a/rtl/core/neorv32_twi.vhd +++ b/rtl/core/neorv32_twi.vhd @@ -47,6 +47,8 @@ architecture neorv32_twi_rtl of neorv32_twi is constant ctrl_fifo_size0_c : natural := 15; -- r/-: log2(fifo size), bit 0 (lsb) constant ctrl_fifo_size3_c : natural := 18; -- r/-: log2(fifo size), bit 3 (msb) -- + constant ctrl_sense_scl_c : natural := 27; -- r/-: current state of the SCL bus line + constant ctrl_sense_sda_c : natural := 28; -- r/-: current state of the SDA bus line constant ctrl_tx_full_c : natural := 29; -- r/-: TX FIFO full constant ctrl_rx_avail_c : natural := 30; -- r/-: RX FIFO data available constant ctrl_busy_c : natural := 31; -- r/-: Set if TWI unit is busy @@ -142,9 +144,11 @@ begin -- bus_rsp_o.data(ctrl_fifo_size3_c downto ctrl_fifo_size0_c) <= std_ulogic_vector(to_unsigned(index_size_f(IO_TWI_FIFO), 4)); -- - bus_rsp_o.data(ctrl_tx_full_c) <= not fifo.tx_free; - bus_rsp_o.data(ctrl_rx_avail_c) <= fifo.rx_avail; - bus_rsp_o.data(ctrl_busy_c) <= engine.busy or fifo.tx_avail; -- bus engine busy or TX FIFO not empty + bus_rsp_o.data(ctrl_sense_scl_c) <= io_con.scl_in_ff(1); + bus_rsp_o.data(ctrl_sense_sda_c) <= io_con.sda_in_ff(1); + bus_rsp_o.data(ctrl_tx_full_c) <= not fifo.tx_free; + bus_rsp_o.data(ctrl_rx_avail_c) <= fifo.rx_avail; + bus_rsp_o.data(ctrl_busy_c) <= engine.busy or fifo.tx_avail; -- bus engine busy or TX FIFO not empty else -- RX FIFO bus_rsp_o.data(8 downto 0) <= fifo.rx_rdata; -- ACK + data end if; @@ -378,7 +382,7 @@ begin engine.state(1 downto 0) <= "00"; -- go back to IDLE end if; - when others => -- "0---" OFFLINE: TWI deactivated, bus unclaimed + when others => -- "0--" OFFLINE: TWI deactivated, bus unclaimed -- ------------------------------------------------------------ io_con.scl_out <= '1'; -- SCL driven by pull-up resistor io_con.sda_out <= '1'; -- SDA driven by pull-up resistor From 12c235860b3df51785e01d46aec509a4fc2f6c8b Mon Sep 17 00:00:00 2001 From: stnolting Date: Sun, 1 Dec 2024 20:37:36 +0100 Subject: [PATCH 3/6] [docs] update TWI section --- docs/datasheet/soc_twi.adoc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/datasheet/soc_twi.adoc b/docs/datasheet/soc_twi.adoc index 673e1636c..579825b77 100644 --- a/docs/datasheet/soc_twi.adoc +++ b/docs/datasheet/soc_twi.adoc @@ -24,9 +24,6 @@ The NEORV32 TWI implements an I2C-compatible host controller to communicate with arbitrary I2C-devices. Note that peripheral-mode (controller acts as a device) and multi-controller mode are not supported yet. -The TWI controller provides two memory-mapped registers that are used for configuring the module and -for triggering operation: `CTRL` is the control and status register, `DCMD` is the command and data register. - Key features: @@ -37,10 +34,13 @@ Key features: * Generating a host-ACK (ACK send by the TWI controller) * Configurable data/command FIFO to "program" large TWI sequences without further involvement of the CPU +The TWI controller provides two memory-mapped registers that are used for configuring the module and +for triggering operations: the control and status register `CTRL` and the command and data register `DCMD`. + **Tristate Drivers** -The TWI module requires two tristate drivers (actually: open-drain drivers; signals can only be actively driven low) for +The TWI module requires two tristate drivers (actually: open-drain drivers - signals can only be actively driven low) for the SDA and SCL lines, which have to be implemented by the user in the setup's top module / IO ring. A generic VHDL example is shown below (here, `sda_io` and `scl_io` are the actual TWI bus lines, which are of type `std_logic`). @@ -56,8 +56,8 @@ twi_scl_i <= std_ulogic(scl_io); -- sense **TWI Clock Speed** -The TWI clock frequency is programmed by two bit-fields in the device's control register `CTRL`: a 3-bit `TWI_CTRL_PRSCx` -clock prescaler is sued for a coarse clock configuration and a 4-bit clock divider `TWI_CTRL_CDIVx` is used for a fine +The TWI clock frequency is programmed by two bit-fields in the device's control register `CTRL`: a 3-bit clock prescaler +(`TWI_CTRL_PRSCx`) is used for a coarse clock configuration and a 4-bit clock divider (`TWI_CTRL_CDIVx`) is used for a fine clock configuration. .TWI prescaler configuration @@ -74,7 +74,7 @@ from the processor's main clock f~main~ according to the following equation: _**f~SCL~**_ = _f~main~[Hz]_ / (4 * `clock_prescaler` * (1 + TWI_CTRL_CDIV)) Hence, the maximum TWI clock is f~main~ / 8 and the lowest TWI clock is f~main~ / 262144. The generated TWI clock is -always symmetric having a duty cycle of exactly 50%. +always symmetric having a duty cycle of exactly 50% (if the clock is not haled by a device during clock stretching). .Clock Stretching [NOTE] @@ -110,6 +110,9 @@ that have not been executed yet) or of the TWI bus engine is still processing an [TIP] An active transmission can be terminated at any time by disabling the TWI module. This will also clear the data/command FIFO. +[TIP] +The current state of the TWI bus lines (SCL and SDA) can be checked by software via the `TWI_CTRL_SENSE_*` control register bits. + [NOTE] When reading data from a device, an all-one byte (`0xFF`) has to be written to TWI data register `NEORV32_TWI.DATA` so the accessed device can actively pull-down SDA when required. @@ -128,13 +131,15 @@ TWI module is enabled (`TWI_CTRL_EN` = `1`) and the TX FIFO is empty and the TWI [options="header",grid="all"] |======================= | Address | Name [C] | Bit(s), Name [C] | R/W | Function -.10+<| `0xfffff900` .10+<| `CTRL` <|`0` `TWI_CTRL_EN` ^| r/w <| TWI enable, reset if cleared +.12+<| `0xfffff900` .12+<| `CTRL` <|`0` `TWI_CTRL_EN` ^| r/w <| TWI enable, reset if cleared <|`3:1` `TWI_CTRL_PRSC2 : TWI_CTRL_PRSC0` ^| r/w <| 3-bit clock prescaler select <|`7:4` `TWI_CTRL_CDIV3 : TWI_CTRL_CDIV0` ^| r/w <| 4-bit clock divider <|`8` `TWI_CTRL_CLKSTR` ^| r/w <| Enable (allow) clock stretching <|`14:9` - ^| r/- <| _reserved_, read as zero <|`18:15` `TWI_CTRL_FIFO_MSB : TWI_CTRL_FIFO_LSB` ^| r/- <| FIFO depth; log2(`IO_TWI_FIFO`) - <|`28:12` - ^| r/- <| _reserved_, read as zero + <|`26:12` - ^| r/- <| _reserved_, read as zero + <|`27` `TWI_CTRL_SENSE_SCL` ^| r/- <| current state of the SCL bus line + <|`28` `TWI_CTRL_SENSE_SDA` ^| r/- <| current state of the SDA bus line <|`29` `TWI_CTRL_TX_FULL` ^| r/- <| set if the TWI bus is claimed by any controller <|`30` `TWI_CTRL_RX_AVAIL` ^| r/- <| RX FIFO data available <|`31` `TWI_CTRL_BUSY` ^| r/- <| TWI bus engine busy or TX FIFO not empty From 0390a6ef6d964e9f021d2dd9a00ea60a22c35a3c Mon Sep 17 00:00:00 2001 From: stnolting Date: Sun, 1 Dec 2024 20:38:24 +0100 Subject: [PATCH 4/6] [lib] update TWI HAL --- sw/lib/include/neorv32_twi.h | 38 +++++++++++++++++++++--------------- sw/lib/source/neorv32_twi.c | 34 +++++++++++++++++++++++++++++++- sw/svd/neorv32.svd | 12 ++++++++++++ 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/sw/lib/include/neorv32_twi.h b/sw/lib/include/neorv32_twi.h index 5ec40aad6..f0cc26293 100644 --- a/sw/lib/include/neorv32_twi.h +++ b/sw/lib/include/neorv32_twi.h @@ -36,22 +36,24 @@ typedef volatile struct __attribute__((packed,aligned(4))) { /** TWI control register bits */ enum NEORV32_TWI_CTRL_enum { - TWI_CTRL_EN = 0, /**< TWI control register(0) (r/w): TWI enable */ - TWI_CTRL_PRSC0 = 1, /**< TWI control register(1) (r/w): Clock prescaler select bit 0 */ - TWI_CTRL_PRSC1 = 2, /**< TWI control register(2) (r/w): Clock prescaler select bit 1 */ - TWI_CTRL_PRSC2 = 3, /**< TWI control register(3) (r/w): Clock prescaler select bit 2 */ - TWI_CTRL_CDIV0 = 4, /**< TWI control register(4) (r/w): Clock divider bit 0 */ - TWI_CTRL_CDIV1 = 5, /**< TWI control register(5) (r/w): Clock divider bit 1 */ - TWI_CTRL_CDIV2 = 6, /**< TWI control register(6) (r/w): Clock divider bit 2 */ - TWI_CTRL_CDIV3 = 7, /**< TWI control register(7) (r/w): Clock divider bit 3 */ - TWI_CTRL_CLKSTR = 8, /**< TWI control register(8) (r/w): Enable/allow clock stretching */ - - TWI_CTRL_FIFO_LSB = 15, /**< SPI control register(15) (r/-): log2(FIFO size), lsb */ - TWI_CTRL_FIFO_MSB = 18, /**< SPI control register(18) (r/-): log2(FIFO size), msb */ - - TWI_CTRL_TX_FULL = 29, /**< TWI control register(29) (r/-): TX FIFO full */ - TWI_CTRL_RX_AVAIL = 30, /**< TWI control register(30) (r/-): RX FIFO data available */ - TWI_CTRL_BUSY = 31 /**< TWI control register(31) (r/-): Bus engine busy or TX FIFO not empty */ + TWI_CTRL_EN = 0, /**< TWI control register(0) (r/w): TWI enable */ + TWI_CTRL_PRSC0 = 1, /**< TWI control register(1) (r/w): Clock prescaler select bit 0 */ + TWI_CTRL_PRSC1 = 2, /**< TWI control register(2) (r/w): Clock prescaler select bit 1 */ + TWI_CTRL_PRSC2 = 3, /**< TWI control register(3) (r/w): Clock prescaler select bit 2 */ + TWI_CTRL_CDIV0 = 4, /**< TWI control register(4) (r/w): Clock divider bit 0 */ + TWI_CTRL_CDIV1 = 5, /**< TWI control register(5) (r/w): Clock divider bit 1 */ + TWI_CTRL_CDIV2 = 6, /**< TWI control register(6) (r/w): Clock divider bit 2 */ + TWI_CTRL_CDIV3 = 7, /**< TWI control register(7) (r/w): Clock divider bit 3 */ + TWI_CTRL_CLKSTR = 8, /**< TWI control register(8) (r/w): Enable/allow clock stretching */ + + TWI_CTRL_FIFO_LSB = 15, /**< SPI control register(15) (r/-): log2(FIFO size), lsb */ + TWI_CTRL_FIFO_MSB = 18, /**< SPI control register(18) (r/-): log2(FIFO size), msb */ + + TWI_CTRL_SENSE_SCL = 27, /**< TWI control register(27) (r/-): current state of the SCL bus line */ + TWI_CTRL_SENSE_SDA = 28, /**< TWI control register(28) (r/-): current state of the SDA bus line */ + TWI_CTRL_TX_FULL = 29, /**< TWI control register(29) (r/-): TX FIFO full */ + TWI_CTRL_RX_AVAIL = 30, /**< TWI control register(30) (r/-): RX FIFO data available */ + TWI_CTRL_BUSY = 31 /**< TWI control register(31) (r/-): Bus engine busy or TX FIFO not empty */ }; /** TWI command/data register bits */ @@ -64,6 +66,7 @@ enum NEORV32_TWI_DCMD_enum { }; /**@}*/ + /**********************************************************************//** * @name TWI commands **************************************************************************/ @@ -85,6 +88,9 @@ int neorv32_twi_get_fifo_depth(void); void neorv32_twi_disable(void); void neorv32_twi_enable(void); +int neorv32_twi_sense_scl(void); +int neorv32_twi_sense_sda(void); + int neorv32_twi_busy(void); int neorv32_twi_get(uint8_t *data); diff --git a/sw/lib/source/neorv32_twi.c b/sw/lib/source/neorv32_twi.c index ac9fc25d8..922b20fb1 100644 --- a/sw/lib/source/neorv32_twi.c +++ b/sw/lib/source/neorv32_twi.c @@ -85,7 +85,39 @@ void neorv32_twi_enable(void) { /**********************************************************************//** - * Check if TWI is busy (TWI bus engine busy or TX FIFO not empty). + * Get current state of SCL bus line. + * + * @return 1 if SCL is high, 0 if SCL is low. + **************************************************************************/ +int neorv32_twi_sense_scl(void) { + + if (NEORV32_TWI->CTRL & (1 << TWI_CTRL_SENSE_SCL)) { + return 1; + } + else { + return 0; + } +} + + +/**********************************************************************//** + * Get current state of SDA bus line. + * + * @return 1 if SDA is high, 0 if SDA is low. + **************************************************************************/ +int neorv32_twi_sense_sda(void) { + + if (NEORV32_TWI->CTRL & (1 << TWI_CTRL_SENSE_SDA)) { + return 1; + } + else { + return 0; + } +} + + +/**********************************************************************//** + * Check if TWI controller is busy (TWI bus engine busy or TX FIFO not empty). * * @return 0 if idle, 1 if busy **************************************************************************/ diff --git a/sw/svd/neorv32.svd b/sw/svd/neorv32.svd index bab0b9b22..90a3c8989 100644 --- a/sw/svd/neorv32.svd +++ b/sw/svd/neorv32.svd @@ -1251,6 +1251,18 @@ read-only TX FIFO full + + TWI_CTRL_SENSE_SCL + [27:27] + read-only + current state of the SCL bus line + + + TWI_CTRL_SENSE_SDA + [28:28] + read-only + current state of the SDA bus line + TWI_CTRL_RX_AVAIL [30:30] From 3be222eb791f1835bc0700ced66b8ba82700d681 Mon Sep 17 00:00:00 2001 From: stnolting Date: Sun, 1 Dec 2024 20:44:49 +0100 Subject: [PATCH 5/6] [changelog] add v1.10.6.8 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47ce4ddd6..f5b59938a 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 | Ticket | |:----:|:-------:|:--------|:------:| +| 01.12.2024 | 1.10.6.8 | add TWI bus sensing logic | [#1111](https://github.com/stnolting/neorv32/pull/1111) | | 26.11.2024 | 1.10.6.7 | :bug: fix some HDL issues that caused problems when auto-converting to Verilog | [#1103](https://github.com/stnolting/neorv32/pull/1103) | | 23.11.2024 | 1.10.6.6 | CPU control: large code edits and cleanups | [#1099](https://github.com/stnolting/neorv32/pull/1099) | | 10.11.2024 | 1.10.6.5 | :warning: switch to [xPack](https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack) as default prebuilt RISC-V GCC toolchain (now using `riscv-none-elf-` as default gcc prefix) | [#1091](https://github.com/stnolting/neorv32/pull/1091) | From 2955086dd0ceef6e60bb4845dff4309126da1e4f Mon Sep 17 00:00:00 2001 From: stnolting Date: Sun, 1 Dec 2024 20:46:39 +0100 Subject: [PATCH 6/6] [sw/example] update TWI example program --- sw/example/demo_twi/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sw/example/demo_twi/main.c b/sw/example/demo_twi/main.c index 73be81dfc..0960318fd 100644 --- a/sw/example/demo_twi/main.c +++ b/sw/example/demo_twi/main.c @@ -89,6 +89,7 @@ int main() { " start - generate (repeated) START condition\n" " stop - generate STOP condition\n" " send - write/read single byte to/from bus\n" + " sense - show current SCL and SDA bus levels\n" "Start a new transmission by generating a START condition. Next, transfer the 7-bit device address\n" "and the R/W flag. After that, transfer your data to be written or send a 0xFF if you want to read\n" "data from the bus. Finish the transmission by generating a STOP condition.\n"); @@ -110,6 +111,10 @@ int main() { else if (!strcmp(buffer, "send")) { send_twi(); } + else if (!strcmp(buffer, "sense")) { + neorv32_uart0_printf(" SCL: %u\n", neorv32_twi_sense_scl()); + neorv32_uart0_printf(" SDA: %u\n", neorv32_twi_sense_sda()); + } else { neorv32_uart0_printf("Invalid command. Type 'help' to see all commands.\n"); } @@ -168,6 +173,14 @@ void set_clock(void) { // print new clock frequency uint32_t clock = neorv32_sysinfo_get_clk() / (4 * PRSC_LUT[prsc] * (1 + cdiv)); neorv32_uart0_printf("\nNew I2C clock: %u Hz\n", clock); + + // check if bus lines are OK + if (neorv32_twi_sense_scl() != 1) { + neorv32_uart0_printf("WARNING! SCL bus line is not idle-high! Pull-up missing?\n"); + } + if (neorv32_twi_sense_sda() != 1) { + neorv32_uart0_printf("WARNING! SDA bus line is not idle-high! Pull-up missing?\n"); + } }