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

⚠️ Replace IO_GPIO_EN generic #491

Merged
merged 7 commits into from
Feb 12, 2023
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 @@ -31,6 +31,7 @@ mimpid = 0x01040312 => Version 01.04.03.12 => v1.4.3.12

| Date (*dd.mm.yyyy*) | Version | Comment |
|:-------------------:|:-------:|:--------|
| 11.02.2023 | 1.8.0.6 | :warning: replaced boolean `IO_GPIO_EN` generic by natural `IO_GPIO_NUM` generic to fine-tune GPIO pin number; [#491](https://github.com/stnolting/neorv32/pull/491) |
| 10.02.2023 | 1.8.0.5 | :test_tube: add CPU co-processor monitor (to auto-terminate operation if a co-processor operation takes too long); [#490](https://github.com/stnolting/neorv32/pull/490) |
| 10.02.2023 | 1.8.0.4 | replace CPU-internal control bus by a VHDL `record` (much cleaner code); minor control optimizations; add 6ht CPU co-processor slot (yet unused); [#489](https://github.com/stnolting/neorv32/pull/489) |
| 05.02.2023 | 1.8.0.3 | CPU control optimizations; [#487](https://github.com/stnolting/neorv32/pull/487) |
Expand Down
7 changes: 4 additions & 3 deletions docs/datasheet/soc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -803,13 +803,14 @@ implemented reducing access latency by one cycle but eventually increasing the c
==== Processor Peripheral/IO Modules

:sectnums!:
===== _IO_GPIO_EN_
===== _IO_GPIO_NUM_

[cols="4,4,2"]
[frame="all",grid="none"]
|======
| **IO_GPIO_EN** | _boolean_ | false
3+| Implement <<_general_purpose_input_and_output_port_gpio>> module when true.
| **IO_GPIO_NUM** | _natural_ | 0
3+| Number of general purpose input/output pairs of the <<_general_purpose_input_and_output_port_gpio>>. If set to zero,
GPIO controller is not implemented at all.
|======


Expand Down
17 changes: 7 additions & 10 deletions docs/datasheet/soc_gpio.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,23 @@
| | neorv32_gpio.h |
| Top entity port: | `gpio_o` | 64-bit parallel output port
| | `gpio_i` | 64-bit parallel input port
| Configuration generics: | _IO_GPIO_EN_ | implement GPIO port when _true_
| Configuration generics: | _IO_GPIO_NUM_ | number of input/output pairs (0..64)
| CPU interrupts: | none |
|=======================

The general purpose parallel IO port unit provides a simple 64-bit parallel input port and a 64-bit parallel
output port. These ports can be used chip-externally (for example to drive status LEDs, connect buttons, etc.)
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.
The general purpose parallel IO unit provides a simple parallel input and output port. These ports can be used chip-externally
(for example to drive status LEDs, connect buttons, etc.) or chip-internally to provide control signals for other IP modules.
The actual number of input/output pairs is defined by the _IO_GPIO_NUM_ generic. When set to zero, the GPIO module is excluded
from synthesis and the output port `gpio_o` is tied to all-zero. If _IO_GPIO_NUM_ is less than the maximum value of 64
only the LSB-aligned bits in `gpio_o` and `gpio_i` are actually connected while the remaining bits are unconnected or tied
to zero, respectively.

.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.


**Register Map**

Expand Down
62 changes: 35 additions & 27 deletions rtl/core/neorv32_gpio.vhd
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
-- #################################################################################################
-- # << NEORV32 - General Purpose Parallel Input/Output Port (GPIO) >> #
-- # ********************************************************************************************* #
-- # 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) 2022, Stephan Nolting. All rights reserved. #
-- # Copyright (c) 2023, 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 @@ -43,6 +40,9 @@ library neorv32;
use neorv32.neorv32_package.all;

entity neorv32_gpio is
generic (
GPIO_NUM : natural -- number of GPIO input/output pairs (0..64)
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
Expand All @@ -53,7 +53,6 @@ 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 @@ -73,11 +72,16 @@ architecture neorv32_gpio_rtl of neorv32_gpio is
signal rden : std_ulogic; -- read enable

-- accessible regs --
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
signal din, din_rd, dout, dout_rd : std_ulogic_vector(63 downto 0);

begin

-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert not ((GPIO_NUM < 0) or (GPIO_NUM > 64)) report
"NEORV32 PROCESSOR CONFIG ERROR! Invalid GPIO pin number configuration (0..64)." severity error;


-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = gpio_base_c(hi_abb_c downto lo_abb_c)) else '0';
Expand All @@ -91,53 +95,57 @@ begin
write_access: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
dout_lo <= (others => '0');
dout_hi <= (others => '0');
dout <= (others => '0');
elsif rising_edge(clk_i) then
if (wren = '1') then
if (addr = gpio_out_lo_addr_c) then
dout_lo <= data_i;
dout(31 downto 00) <= data_i;
end if;
if (addr = gpio_out_hi_addr_c) then
dout_hi <= data_i;
dout(63 downto 32) <= data_i;
end if;
end if;
end if;
end process write_access;

-- GPIO output --
gpio_o <= dout_hi & dout_lo;


-- Read Access ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
read_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- bus handshake --
ack_o <= (wren and addr(3)) or rden;
err_o <= wren and (not addr(3)); -- INPUT registers are read only!
ack_o <= wren or rden;
-- read data --
data_o <= (others => '0');
if (rden = '1') then
case addr(3 downto 2) is
when "00" => data_o <= din_lo;
when "01" => data_o <= din_hi;
when "10" => data_o <= dout_lo;
when others => data_o <= dout_hi;
when "00" => data_o <= din_rd(31 downto 00);
when "01" => data_o <= din_rd(63 downto 32);
when "10" => data_o <= dout_rd(31 downto 00);
when others => data_o <= dout_rd(63 downto 32);
end case;
end if;
end if;
end process read_access;

-- sample buffer to prevent metastability --
input_buffer: process (clk_i)

-- Physical Pin Mapping -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
pin_mapping: process(din, dout)
begin
if rising_edge(clk_i) then
din_lo <= gpio_i(31 downto 00);
din_hi <= gpio_i(63 downto 32);
end if;
end process input_buffer;
-- defaults --
din_rd <= (others => '0');
dout_rd <= (others => '0');
for i in 0 to GPIO_NUM-1 loop
din_rd(i) <= din(i);
dout_rd(i) <= dout(i);
end loop;
end process pin_mapping;

-- IO --
gpio_o <= dout_rd;
din <= gpio_i when rising_edge(clk_i); -- sample buffer to prevent metastability


end neorv32_gpio_rtl;
73 changes: 38 additions & 35 deletions rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ package neorv32_package is

-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080005"; -- NEORV32 version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080006"; -- NEORV32 version
constant archid_c : natural := 19; -- official RISC-V architecture ID

-- Check if we're inside the Matrix -------------------------------------------------------
Expand Down Expand Up @@ -764,50 +764,51 @@ package neorv32_package is
alu_opb_mux : std_ulogic; -- operand B select (0=rs2, 1=IMM)
alu_unsigned : std_ulogic; -- is unsigned ALU operation
alu_frm : std_ulogic_vector(02 downto 0); -- FPU rounding mode
alu_cp_trig : std_ulogic_vector(05 downto 0); -- trigger CP (one-hot)
alu_cp_trig : std_ulogic_vector(05 downto 0); -- co-processor trigger (one-hot)
-- bus interface --
bus_req : std_ulogic; -- trigger memory request
bus_mo_we : std_ulogic; -- memory address and data output register write enable
bus_fence : std_ulogic; -- fence operation
bus_fencei : std_ulogic; -- fence.i operation
bus_priv : std_ulogic; -- effective privilege level for load/store
-- instruction word bit fields --
ir_funct3 : std_ulogic_vector(02 downto 0); -- funct3 bit-field
ir_funct12 : std_ulogic_vector(11 downto 0); -- funct12 bit-field
ir_opcode : std_ulogic_vector(06 downto 0); -- opcode bit-field
-- instruction word --
ir_funct3 : std_ulogic_vector(02 downto 0); -- funct3 bit field
ir_funct12 : std_ulogic_vector(11 downto 0); -- funct12 bit field
ir_opcode : std_ulogic_vector(06 downto 0); -- opcode bit field
-- cpu status --
cpu_priv : std_ulogic; -- effective privilege mode
cpu_sleep : std_ulogic; -- set when CPU is in sleep mode
cpu_trap : std_ulogic; -- set when CPU is entering trap exec
cpu_debug : std_ulogic; -- set when CPU is in debug mode
end record;

-- control bus reset initializer --
constant ctrl_bus_zero_c : ctrl_bus_t := (
rf_wb_en => '0',
rf_rs1 => (others => '0'),
rf_rs2 => (others => '0'),
rf_rs3 => (others => '0'),
rf_rd => (others => '0'),
rf_mux => (others => '0'),
rf_zero_we => '0',
alu_op => (others => '0'),
alu_opa_mux => '0',
alu_opb_mux => '0',
alu_unsigned => '0',
alu_frm => (others => '0'),
alu_cp_trig => (others => '0'),
bus_req => '0',
bus_mo_we => '0',
bus_fence => '0',
bus_fencei => '0',
bus_priv => '0',
ir_funct3 => (others => '0'),
ir_funct12 => (others => '0'),
ir_opcode => (others => '0'),
cpu_priv => '0',
cpu_sleep => '0',
cpu_trap => '0',
cpu_debug => '0'
rf_wb_en => '0',
rf_rs1 => (others => '0'),
rf_rs2 => (others => '0'),
rf_rs3 => (others => '0'),
rf_rd => (others => '0'),
rf_mux => (others => '0'),
rf_zero_we => '0',
alu_op => (others => '0'),
alu_opa_mux => '0',
alu_opb_mux => '0',
alu_unsigned => '0',
alu_frm => (others => '0'),
alu_cp_trig => (others => '0'),
bus_req => '0',
bus_mo_we => '0',
bus_fence => '0',
bus_fencei => '0',
bus_priv => '0',
ir_funct3 => (others => '0'),
ir_funct12 => (others => '0'),
ir_opcode => (others => '0'),
cpu_priv => '0',
cpu_sleep => '0',
cpu_trap => '0',
cpu_debug => '0'
);

-- Comparator Bus -------------------------------------------------------------------------
Expand Down Expand Up @@ -1027,7 +1028,7 @@ package neorv32_package is
XIRQ_TRIGGER_TYPE : std_ulogic_vector(31 downto 0) := x"FFFFFFFF"; -- trigger type: 0=level, 1=edge
XIRQ_TRIGGER_POLARITY : std_ulogic_vector(31 downto 0) := x"FFFFFFFF"; -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge
-- Processor peripherals --
IO_GPIO_EN : boolean := false; -- implement general purpose input/output port unit (GPIO)?
IO_GPIO_NUM : natural := 0; -- number of GPIO input/output pairs (0..64)
IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean := false; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART0_RX_FIFO : natural := 1; -- RX fifo depth, has to be a power of two, min 1
Expand Down Expand Up @@ -1091,7 +1092,7 @@ package neorv32_package is
slink_rx_val_i : in std_ulogic_vector(7 downto 0) := (others => 'L'); -- valid input
slink_rx_rdy_o : out std_ulogic_vector(7 downto 0); -- ready to receive
slink_rx_lst_i : in std_ulogic_vector(7 downto 0) := (others => 'L'); -- last data of packet
-- GPIO (available if IO_GPIO_EN = true) --
-- GPIO (available if IO_GPIO_NUM > 0) --
gpio_o : out std_ulogic_vector(63 downto 0); -- parallel output
gpio_i : in std_ulogic_vector(63 downto 0) := (others => 'U'); -- parallel input
-- primary UART0 (available if IO_UART0_EN = true) --
Expand Down Expand Up @@ -1704,6 +1705,9 @@ package neorv32_package is
-- Component: General Purpose Input/Output Port (GPIO) ------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_gpio
generic (
GPIO_NUM : natural -- number of GPIO input/output pairs (0..64)
);
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
Expand All @@ -1714,7 +1718,6 @@ 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 Expand Up @@ -2154,7 +2157,7 @@ package neorv32_package is
-- On-Chip Debugger --
ON_CHIP_DEBUGGER_EN : boolean; -- implement OCD?
-- Processor peripherals --
IO_GPIO_EN : boolean; -- implement general purpose input/output port unit (GPIO)?
IO_GPIO_NUM : natural; -- number of GPIO input/output pairs (0..64)
IO_MTIME_EN : boolean; -- implement machine system timer (MTIME)?
IO_UART0_EN : boolean; -- implement primary universal asynchronous receiver/transmitter (UART0)?
IO_UART1_EN : boolean; -- implement secondary universal asynchronous receiver/transmitter (UART1)?
Expand Down
Loading