Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GPIO] raise bus exception if writing to INPUT registers #255

Merged
merged 4 commits into from
Jan 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defined by the `hw_version_c` constant in the main VHDL package file [`rtl/core/

| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 14.01.2022 | 1.6.5.9 | **GPIO** module: write accesses to the GPIO module's "input" registers will now raise a bus exception; [PR #255](https://github.com/stnolting/neorv32/pull/255) |
| 11.01.2022 | 1.6.5.8 | minor rtl code clean-ups and edits in `rtl/core`; any write access to the SYSINFO module will now show up as a BUSKEEPER's "DEVICE_ERR" |
| 08.01.2022 | 1.6.5.7 | :bug: fixed bug in BUSKEEPER's error type logic (introduced in version `1.6.5.4`); removed "unexpected ERR/ACK" error codes; [PR #253](https://github.com/stnolting/neorv32/pull/253) |
| 07.01.2022 | 1.6.5.6 | :sparkles: **XIP & SPI: added high-speed SPI mode** (SPI clocking at half of the processor clock), see [PR #251](https://github.com/stnolting/neorv32/pull/251) |
Expand Down
13 changes: 9 additions & 4 deletions docs/datasheet/soc_gpio.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,25 @@ output port. These ports can be used chip-externally (for example to drive statu
or chip-internally to provide control signals for other IP modules. The component is disabled for
implementation when the _IO_GPIO_EN_ generic is set _false_. In this case the GPIO output port `gpio_o` is tied to all-zero.

.Access atomicity
.Access Atomicity
[NOTE]
The GPIO modules uses two memory-mapped registers (each 32-bit) each for accessing the input and
output signals. Since the CPU can only process 32-bit "at once" updating the entire output cannot
be performed within a single clock cycle.

.INPUT is read-only
[NOTE]
Write accesses to the `NEORV32_GPIO.INPUT_LO` and `NEORV32_GPIO.INPUT_HI` registers will raise a store bus
error exception. The BUSKEEPER will indicate a "DEVICE_ERR" in this case.


.GPIO unit register map (`struct NEORV32_GPIO`)
[cols="<2,<2,^1,^1,<6"]
[options="header",grid="rows"]
|=======================
| Address | Name [C] | Bit(s) | R/W | Function
| `0xffffffc0` | `NEORV32_GPIO.INPUT_LO` | 31:0 | r/- | parallel input port pins 31:0 (write accesses are ignored)
| `0xffffffc4` | `NEORV32_GPIO.INPUT_HI` | 31:0 | r/- | parallel input port pins 63:32 (write accesses are ignored)
| Address | Name [C] | Bit(s) | R/W | Function
| `0xffffffc0` | `NEORV32_GPIO.INPUT_LO` | 31:0 | r/- | parallel input port pins 31:0
| `0xffffffc4` | `NEORV32_GPIO.INPUT_HI` | 31:0 | r/- | parallel input port pins 63:32
| `0xffffffc8` | `NEORV32_GPIO.OUTPUT_LO` | 31:0 | r/w | parallel output port pins 31:0
| `0xffffffcc` | `NEORV32_GPIO.OUTPUT_HI` | 31:0 | r/w | parallel output port pins 63:32
|=======================
15 changes: 9 additions & 6 deletions rtl/core/neorv32_gpio.vhd
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
-- #################################################################################################
-- # << NEORV32 - General Purpose Parallel Input/Output Port (GPIO) >> #
-- # ********************************************************************************************* #
-- # 64-bit general purpose parallel input & output port unit. #
-- # 64-bit general purpose parallel input & output port unit. Input/outputs are split into two #
-- # 32-bit memory-mapped registers each. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2022, 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: #
Expand Down Expand Up @@ -51,6 +52,7 @@ entity neorv32_gpio is
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
-- parallel io --
gpio_o : out std_ulogic_vector(63 downto 0);
gpio_i : in std_ulogic_vector(63 downto 0)
Expand All @@ -70,8 +72,8 @@ architecture neorv32_gpio_rtl of neorv32_gpio is
signal rden : std_ulogic; -- read enable

-- accessible regs --
signal din_lo, din_hi : std_ulogic_vector(31 downto 0); -- r/-
signal dout_lo, dout_hi : std_ulogic_vector(31 downto 0); -- r/w
signal din_hi, din_lo : std_ulogic_vector(31 downto 0); -- r/-: parallel input hi/lo
signal dout_hi, dout_lo : std_ulogic_vector(31 downto 0); -- r/w: parallel output hi/lo

begin

Expand All @@ -89,7 +91,8 @@ begin
begin
if rising_edge(clk_i) then
-- bus handshake --
ack_o <= wren or rden;
ack_o <= (wren and addr(3)) or rden;
err_o <= wren and (not addr(3)); -- INPUT registers are read only!

-- write access --
if (wren = '1') then
Expand All @@ -101,7 +104,7 @@ begin
end if;
end if;

-- input buffer --
-- input buffer (prevent metastability) --
din_lo <= gpio_i(31 downto 00);
din_hi <= gpio_i(63 downto 32);

Expand Down
3 changes: 2 additions & 1 deletion rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ package neorv32_package is
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060508"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01060509"; -- no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!

-- Check if we're inside the Matrix -------------------------------------------------------
Expand Down Expand Up @@ -1638,6 +1638,7 @@ package neorv32_package is
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
err_o : out std_ulogic; -- transfer error
-- parallel io --
gpio_o : out std_ulogic_vector(63 downto 0);
gpio_i : in std_ulogic_vector(63 downto 0)
Expand Down
2 changes: 1 addition & 1 deletion rtl/core/neorv32_top.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -1000,11 +1000,11 @@ begin
data_i => p_bus.wdata, -- data in
data_o => resp_bus(RESP_GPIO).rdata, -- data out
ack_o => resp_bus(RESP_GPIO).ack, -- transfer acknowledge
err_o => resp_bus(RESP_GPIO).err, -- transfer error
-- parallel io --
gpio_o => gpio_o,
gpio_i => gpio_i
);
resp_bus(RESP_GPIO).err <= '0'; -- no access error possible
end generate;

neorv32_gpio_inst_false:
Expand Down
6 changes: 3 additions & 3 deletions sw/lib/include/neorv32.h
Original file line number Diff line number Diff line change
Expand Up @@ -1165,8 +1165,8 @@ enum NEORV32_WDT_CTRL_enum {
/**@{*/
/** GPIO module prototype */
typedef struct __attribute__((packed,aligned(4))) {
const uint32_t INPUT_LO; /**< offset 0: parallel input port lower 32-bit */
const uint32_t INPUT_HI; /**< offset 4: parallel input port upper 32-bit */
const uint32_t INPUT_LO; /**< offset 0: parallel input port lower 32-bit, read-only */
const uint32_t INPUT_HI; /**< offset 4: parallel input port upper 32-bit, read-only */
uint32_t OUTPUT_LO; /**< offset 8: parallel output port lower 32-bit */
uint32_t OUTPUT_HI; /**< offset 12: parallel output port upper 32-bit */
} neorv32_gpio_t;
Expand Down Expand Up @@ -1234,7 +1234,7 @@ enum NEORV32_NEOLED_CTRL_enum {
* @name IO Device: System Configuration Information Memory (SYSINFO)
**************************************************************************/
/**@{*/
/** SYSINFO module prototype */
/** SYSINFO module prototype - whole module is read-only */
typedef struct __attribute__((packed,aligned(4))) {
const uint32_t CLK; /**< offset 0: clock speed in Hz */
const uint32_t CPU; /**< offset 4: CPU core features (#NEORV32_SYSINFO_CPU_enum) */
Expand Down