Skip to content

Commit

Permalink
⚠️ rename UART RTS/CTS signals (#1180)
Browse files Browse the repository at this point in the history
  • Loading branch information
stnolting authored Feb 7, 2025
2 parents 41a9afe + 91d44ff commit e7eee30
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12

| Date | Version | Comment | Ticket |
|:----:|:-------:|:--------|:------:|
| 07.02.2025 | 1.11.0.10 | :warning: rename UART RTS/CTS signals | [#1180](https://github.com/stnolting/neorv32/pull/1180) |
| 07.02.2025 | 1.11.0.9 | minor rtl edits and cleanups | [#1179](https://github.com/stnolting/neorv32/pull/1179) |
| 03.02.2025 | 1.11.0.8 | :sparkles: add explicit memory ordering/coherence support; :warning: remove WDT "halt-on-debug" and "halt-on-sleep" options; :bug: rework cache module fixing several (minor?) design flaws | [#1176](https://github.com/stnolting/neorv32/pull/1176) |
| 03.02.2025 | 1.11.0.7 | :bug: add missing CFS clock gen enable signal | [#1177](https://github.com/stnolting/neorv32/pull/1177) |
Expand Down
8 changes: 4 additions & 4 deletions docs/datasheet/soc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ to all inputs and output so the synthesis tool can insert an explicit IO (bounda
5+^| **<<_primary_universal_asynchronous_receiver_and_transmitter_uart0>>**
| `uart0_txd_o` | 1 | out | - | serial transmitter
| `uart0_rxd_i` | 1 | in | `'L'` | serial receiver
| `uart0_rts_o` | 1 | out | - | RX ready to receive new char
| `uart0_cts_i` | 1 | in | `'L'` | TX allowed to start sending, low-active
| `uart0_rtsn_o` | 1 | out | - | RX ready to receive new char
| `uart0_ctsn_i` | 1 | in | `'L'` | TX allowed to start sending, low-active
5+^| **<<_secondary_universal_asynchronous_receiver_and_transmitter_uart1>>**
| `uart1_txd_o` | 1 | out | - | serial transmitter
| `uart1_rxd_i` | 1 | in | `'L'` | serial receiver
| `uart1_rts_o` | 1 | out | - | RX ready to receive new char
| `uart1_cts_i` | 1 | in | `'L'` | TX allowed to start sending, low-active
| `uart1_rtsn_o` | 1 | out | - | RX ready to receive new char
| `uart1_ctsn_i` | 1 | in | `'L'` | TX allowed to start sending, low-active
5+^| **<<_serial_peripheral_interface_controller_spi>>**
| `spi_clk_o` | 1 | out | - | controller clock line
| `spi_dat_o` | 1 | out | - | serial data output
Expand Down
28 changes: 14 additions & 14 deletions docs/datasheet/soc_uart.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
| Hardware source files: | neorv32_uart.vhd |
| Software driver files: | neorv32_uart.c | link:https://stnolting.github.io/neorv32/sw/neorv32__uart_8c.html[Online software reference (Doxygen)]
| | neorv32_uart.h | link:https://stnolting.github.io/neorv32/sw/neorv32__uart_8h.html[Online software reference (Doxygen)]
| Top entity ports: | `uart0_txd_o` | serial transmitter output
| | `uart0_rxd_i` | serial receiver input
| | `uart0_rts_o` | flow control: RX ready to receive, low-active
| | `uart0_cts_i` | flow control: RX ready to receive, low-active
| Top entity ports: | `uart0_txd_o` | serial transmitter output
| | `uart0_rxd_i` | serial receiver input
| | `uart0_rtsn_o` | flow control: RX ready to receive, low-active
| | `uart0_ctsn_i` | flow control: RX ready to receive, low-active
| Configuration generics: | `IO_UART0_EN` | implement UART0 when `true`
| | `UART0_RX_FIFO` | RX FIFO depth (power of 2, min 1)
| | `UART0_TX_FIFO` | TX FIFO depth (power of 2, min 1)
Expand Down Expand Up @@ -92,17 +92,17 @@ Software can retrieve the configured sizes of the RX and TX FIFO via the accordi

**RTS/CTS Hardware Flow Control**

The NEORV32 UART supports optional hardware flow control using the standard CTS `uart0_cts_i` ("clear to send") and RTS
`uart0_rts_o` ("ready to send" / "ready to receive (RTR)") signals. Both signals are low-active.
The NEORV32 UART supports optional hardware flow control using the standard CTS `uart0_ctsn_i` ("clear to send") and RTS
`uart0_rtsn_o` ("ready to send" / "ready to receive (RTR)") signals. Both signals are low-active.
Hardware flow control is enabled by setting the `UART_CTRL_HWFC_EN` bit in the modules control register `CTRL`.

When hardware flow control is enabled:

. The UART's transmitter will not start a new transmission until the `uart0_cts_i` signal goes low.
. The UART's transmitter will not start a new transmission until the `uart0_ctsn_i` signal goes low.
During this time, the UART busy flag `UART_CTRL_TX_BUSY` remains set.
. The UART will set `uart0_rts_o` signal low if the RX FIFO is **less than half full** (to have a wide safety margin).
As long as this signal is low, the connected device can send new data. `uart0_rts_o` is always low if the hardware flow-control
is disabled. Disabling the UART (setting `UART_CTRL_EN` low) while having hardware flow-control enabled, will set `uart0_rts_o`
. The UART will set `uart0_rtsn_o` signal low if the RX FIFO is **less than half full** (to have a wide safety margin).
As long as this signal is low, the connected device can send new data. `uart0_rtsn_o` is always low if the hardware flow-control
is disabled. Disabling the UART (setting `UART_CTRL_EN` low) while having hardware flow-control enabled, will set `uart0_rtsn_o`
high to signal that the UARt is not capable of receiving new data.

[NOTE]
Expand Down Expand Up @@ -167,10 +167,10 @@ Both file are created in the simulation's home folder.
| Hardware source files: | neorv32_uart.vhd |
| Software driver files: | neorv32_uart.c |
| | neorv32_uart.h |
| Top entity ports: | `uart1_txd_o` | serial transmitter output
| | `uart1_rxd_i` | serial receiver input
| | `uart1_rts_o` | flow control: RX ready to receive, low-active
| | `uart1_cts_i` | flow control: RX ready to receive, low-active
| Top entity ports: | `uart1_txd_o` | serial transmitter output
| | `uart1_rxd_i` | serial receiver input
| | `uart1_rtsn_o` | flow control: RX ready to receive, low-active
| | `uart1_ctsn_i` | flow control: RX ready to receive, low-active
| Configuration generics: | `IO_UART1_EN` | implement UART1 when `true`
| | `UART1_RX_FIFO` | RX FIFO depth (power of 2, min 1)
| | `UART1_TX_FIFO` | TX FIFO depth (power of 2, min 1)
Expand Down
10 changes: 5 additions & 5 deletions rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ package neorv32_package is

-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01110009"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01110010"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width

Expand Down Expand Up @@ -868,13 +868,13 @@ package neorv32_package is
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_ulogic;
uart0_rxd_i : in std_ulogic := 'L';
uart0_rts_o : out std_ulogic;
uart0_cts_i : in std_ulogic := 'L';
uart0_rtsn_o : out std_ulogic;
uart0_ctsn_i : in std_ulogic := 'L';
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_ulogic;
uart1_rxd_i : in std_ulogic := 'L'; -- UART1 receive data
uart1_rts_o : out std_ulogic;
uart1_cts_i : in std_ulogic := 'L';
uart1_rtsn_o : out std_ulogic;
uart1_ctsn_i : in std_ulogic := 'L';
-- SPI (available if IO_SPI_EN = true) --
spi_clk_o : out std_ulogic;
spi_dat_o : out std_ulogic;
Expand Down
20 changes: 10 additions & 10 deletions rtl/core/neorv32_top.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,14 @@ entity neorv32_top is
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_ulogic; -- UART0 send data
uart0_rxd_i : in std_ulogic := 'L'; -- UART0 receive data
uart0_rts_o : out std_ulogic; -- HW flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_cts_i : in std_ulogic := 'L'; -- HW flow control: UART0.TX allowed to transmit, low-active, optional
uart0_rtsn_o : out std_ulogic; -- HW flow control: UART0.RX ready to receive ("RTR"), low-active, optional
uart0_ctsn_i : in std_ulogic := 'L'; -- HW flow control: UART0.TX allowed to transmit, low-active, optional

-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_ulogic; -- UART1 send data
uart1_rxd_i : in std_ulogic := 'L'; -- UART1 receive data
uart1_rts_o : out std_ulogic; -- HW flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_cts_i : in std_ulogic := 'L'; -- HW flow control: UART1.TX allowed to transmit, low-active, optional
uart1_rtsn_o : out std_ulogic; -- HW flow control: UART1.RX ready to receive ("RTR"), low-active, optional
uart1_ctsn_i : in std_ulogic := 'L'; -- HW flow control: UART1.TX allowed to transmit, low-active, optional

-- SPI (available if IO_SPI_EN = true) --
spi_clk_o : out std_ulogic; -- SPI serial clock
Expand Down Expand Up @@ -1186,8 +1186,8 @@ begin
clkgen_i => clk_gen,
uart_txd_o => uart0_txd_o,
uart_rxd_i => uart0_rxd_i,
uart_rts_o => uart0_rts_o,
uart_cts_i => uart0_cts_i,
uart_rtsn_o => uart0_rtsn_o,
uart_ctsn_i => uart0_ctsn_i,
irq_rx_o => firq(FIRQ_UART0_RX),
irq_tx_o => firq(FIRQ_UART0_TX)
);
Expand All @@ -1197,7 +1197,7 @@ begin
if not IO_UART0_EN generate
iodev_rsp(IODEV_UART0) <= rsp_terminate_c;
uart0_txd_o <= '0';
uart0_rts_o <= '1';
uart0_rtsn_o <= '1';
clk_gen_en(CG_UART0) <= '0';
firq(FIRQ_UART0_RX) <= '0';
firq(FIRQ_UART0_TX) <= '0';
Expand All @@ -1224,8 +1224,8 @@ begin
clkgen_i => clk_gen,
uart_txd_o => uart1_txd_o,
uart_rxd_i => uart1_rxd_i,
uart_rts_o => uart1_rts_o,
uart_cts_i => uart1_cts_i,
uart_rtsn_o => uart1_rtsn_o,
uart_ctsn_i => uart1_ctsn_i,
irq_rx_o => firq(FIRQ_UART1_RX),
irq_tx_o => firq(FIRQ_UART1_TX)
);
Expand All @@ -1235,7 +1235,7 @@ begin
if not IO_UART1_EN generate
iodev_rsp(IODEV_UART1) <= rsp_terminate_c;
uart1_txd_o <= '0';
uart1_rts_o <= '1';
uart1_rtsn_o <= '1';
clk_gen_en(CG_UART1) <= '0';
firq(FIRQ_UART1_RX) <= '0';
firq(FIRQ_UART1_TX) <= '0';
Expand Down
46 changes: 23 additions & 23 deletions rtl/core/neorv32_uart.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ entity neorv32_uart is
clkgen_i : in std_ulogic_vector(7 downto 0);
uart_txd_o : out std_ulogic; -- serial TX line
uart_rxd_i : in std_ulogic; -- serial RX line
uart_rts_o : out std_ulogic; -- UART.RX ready to receive ("RTR"), low-active, optional
uart_cts_i : in std_ulogic; -- UART.TX allowed to transmit, low-active, optional
uart_rtsn_o : out std_ulogic; -- ready to receive ("RTR"), low-active, optional
uart_ctsn_i : in std_ulogic; -- allowed to transmit, low-active, optional
irq_rx_o : out std_ulogic; -- RX interrupt
irq_tx_o : out std_ulogic -- TX interrupt
);
Expand Down Expand Up @@ -105,14 +105,14 @@ architecture neorv32_uart_rtl of neorv32_uart is

-- UART transmitter --
type tx_engine_t is record
state : std_ulogic_vector(2 downto 0);
sreg : std_ulogic_vector(8 downto 0);
bitcnt : std_ulogic_vector(3 downto 0);
baudcnt : std_ulogic_vector(9 downto 0);
done : std_ulogic;
busy : std_ulogic;
cts_sync : std_ulogic_vector(1 downto 0);
txd : std_ulogic;
state : std_ulogic_vector(2 downto 0);
sreg : std_ulogic_vector(8 downto 0);
bitcnt : std_ulogic_vector(3 downto 0);
baudcnt : std_ulogic_vector(9 downto 0);
done : std_ulogic;
busy : std_ulogic;
cts : std_ulogic_vector(1 downto 0);
txd : std_ulogic;
end record;
signal tx_engine : tx_engine_t;

Expand Down Expand Up @@ -321,16 +321,16 @@ begin
transmitter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
tx_engine.cts_sync <= (others => '0');
tx_engine.done <= '0';
tx_engine.state <= (others => '0');
tx_engine.baudcnt <= (others => '0');
tx_engine.bitcnt <= (others => '0');
tx_engine.sreg <= (others => '0');
tx_engine.txd <= '1';
tx_engine.cts <= (others => '0');
tx_engine.done <= '0';
tx_engine.state <= (others => '0');
tx_engine.baudcnt <= (others => '0');
tx_engine.bitcnt <= (others => '0');
tx_engine.sreg <= (others => '0');
tx_engine.txd <= '1';
elsif rising_edge(clk_i) then
-- synchronize clear-to-send --
tx_engine.cts_sync <= tx_engine.cts_sync(0) & uart_cts_i;
tx_engine.cts <= tx_engine.cts(0) & uart_ctsn_i;

-- defaults --
tx_engine.done <= '0';
Expand All @@ -352,7 +352,7 @@ begin
when "101" => -- WAIT: check if we can start sending
-- ------------------------------------------------------------
if (uart_clk = '1') and -- start with next clock tick
((tx_engine.cts_sync(1) = '0') or (ctrl.hwfc_en = '0')) then -- allowed to send OR flow-control disabled
((tx_engine.cts(1) = '0') or (ctrl.hwfc_en = '0')) then -- allowed to send OR flow-control disabled
tx_engine.state(1 downto 0) <= "11";
end if;

Expand Down Expand Up @@ -463,17 +463,17 @@ begin
rtr_control: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
uart_rts_o <= '0';
uart_rtsn_o <= '0';
elsif rising_edge(clk_i) then
if (ctrl.hwfc_en = '1') then
if (ctrl.enable = '0') or -- UART disabled
(rx_fifo.half = '1') then -- RX FIFO at least half-full: no "safe space" left in RX FIFO
uart_rts_o <= '1'; -- NOT allowed to send
uart_rtsn_o <= '1'; -- NOT allowed to send
else
uart_rts_o <= '0'; -- ready to receive
uart_rtsn_o <= '0'; -- ready to receive
end if;
else
uart_rts_o <= '0'; -- always ready to receive when HW flow-control is disabled
uart_rtsn_o <= '0'; -- always ready to receive when HW flow-control is disabled
end if;
end if;
end process rtr_control;
Expand Down
18 changes: 17 additions & 1 deletion rtl/system_integration/neorv32_vivado_ip.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ proc setup_ip_gui {} {
set_property enablement_dependency {$IO_SLINK_EN} [ipx::get_bus_interfaces s0_axis -of_objects [ipx::current_core]]
set_property enablement_dependency {$IO_SLINK_EN} [ipx::get_bus_interfaces s1_axis -of_objects [ipx::current_core]]
set_property enablement_dependency {$XBUS_EN} [ipx::get_bus_interfaces m_axi -of_objects [ipx::current_core]]
set_property enablement_dependency {$OCD_EN} [ipx::get_ports jtag_* -of_objects [ipx::current_core]]
set_property enablement_dependency {$IO_GPIO_EN} [ipx::get_ports gpio_* -of_objects [ipx::current_core]]
set_property enablement_dependency {$IO_UART0_EN} [ipx::get_ports uart0_* -of_objects [ipx::current_core]]
set_property enablement_dependency {$IO_UART1_EN} [ipx::get_ports uart1_* -of_objects [ipx::current_core]]
Expand All @@ -139,6 +138,23 @@ proc setup_ip_gui {} {
set_property enablement_dependency {!$IO_CLINT_EN} [ipx::get_ports mtime_irq_i -of_objects [ipx::current_core]]
set_property enablement_dependency {!$IO_CLINT_EN} [ipx::get_ports msw_irq_i -of_objects [ipx::current_core]]

# **************************************************************
# Interfaces: Add JTAG as standard interface
# **************************************************************
ipx::add_bus_interface JTAG [ipx::current_core]
set_property abstraction_type_vlnv xilinx.com:interface:jtag_rtl:2.0 [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property bus_type_vlnv xilinx.com:interface:jtag:2.0 [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property display_name JTAG [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property description {JTAG tap of the on-chip debugger} [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property enablement_dependency {$OCD_EN} [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
ipx::add_port_map TDI [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property physical_name jtag_tdi_i [ipx::get_port_maps TDI -of_objects [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]]
ipx::add_port_map TMS [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property physical_name jtag_tms_i [ipx::get_port_maps TMS -of_objects [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]]
ipx::add_port_map TCK [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property physical_name jtag_tck_i [ipx::get_port_maps TCK -of_objects [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]]
ipx::add_port_map TDO [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]
set_property physical_name jtag_tdo_o [ipx::get_port_maps TDO -of_objects [ipx::get_bus_interfaces JTAG -of_objects [ipx::current_core]]]

# **************************************************************
# Configuration pages
Expand Down
22 changes: 11 additions & 11 deletions rtl/system_integration/neorv32_vivado_ip.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,13 @@ entity neorv32_vivado_ip is
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_logic;
uart0_rxd_i : in std_logic := '0';
uart0_rts_o : out std_logic;
uart0_cts_i : in std_logic := '0';
uart0_rtsn_o : out std_logic;
uart0_ctsn_i : in std_logic := '0';
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_logic;
uart1_rxd_i : in std_logic := '0';
uart1_rts_o : out std_logic;
uart1_cts_i : in std_logic := '0';
uart1_rtsn_o : out std_logic;
uart1_ctsn_i : in std_logic := '0';
-- SPI (available if IO_SPI_EN = true) --
spi_clk_o : out std_logic;
spi_dat_o : out std_logic;
Expand Down Expand Up @@ -301,7 +301,7 @@ architecture neorv32_vivado_ip_rtl of neorv32_vivado_ip is
signal s0_axis_tdata_aux : std_ulogic_vector(31 downto 0);
signal s0_axis_tdest_aux : std_ulogic_vector(3 downto 0);
signal s1_axis_tready_aux, s0_axis_tvalid_aux, s0_axis_tlast_aux : std_ulogic;
signal uart0_txd_aux, uart0_rts_aux, uart1_txd_aux, uart1_rts_aux : std_ulogic;
signal uart0_txd_aux, uart0_rtsn_aux, uart1_txd_aux, uart1_rtsn_aux : std_ulogic;
signal spi_clk_aux, spi_do_aux : std_ulogic;
signal spi_csn_aux : std_ulogic_vector(7 downto 0);
signal sdi_do_aux : std_ulogic;
Expand Down Expand Up @@ -477,13 +477,13 @@ begin
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o => uart0_txd_aux,
uart0_rxd_i => std_ulogic(uart0_rxd_i),
uart0_rts_o => uart0_rts_aux,
uart0_cts_i => std_ulogic(uart0_cts_i),
uart0_rtsn_o => uart0_rtsn_aux,
uart0_ctsn_i => std_ulogic(uart0_ctsn_i),
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o => uart1_txd_aux,
uart1_rxd_i => std_ulogic(uart1_rxd_i),
uart1_rts_o => uart1_rts_aux,
uart1_cts_i => std_ulogic(uart1_cts_i),
uart1_rtsn_o => uart1_rtsn_aux,
uart1_ctsn_i => std_ulogic(uart1_ctsn_i),
-- SPI (available if IO_SPI_EN = true) --
spi_clk_o => spi_clk_aux,
spi_dat_o => spi_do_aux,
Expand Down Expand Up @@ -537,9 +537,9 @@ begin
s0_axis_tlast <= std_logic(s0_axis_tlast_aux);

uart0_txd_o <= std_logic(uart0_txd_aux);
uart0_rts_o <= std_logic(uart0_rts_aux);
uart0_rtsn_o <= std_logic(uart0_rtsn_aux);
uart1_txd_o <= std_logic(uart1_txd_aux);
uart1_rts_o <= std_logic(uart1_rts_aux);
uart1_rtsn_o <= std_logic(uart1_rtsn_aux);

spi_clk_o <= std_logic(spi_clk_aux);
spi_dat_o <= std_logic(spi_do_aux);
Expand Down
Loading

0 comments on commit e7eee30

Please sign in to comment.