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

[UART] add FIFO configuration to DATA register #581

Merged
merged 4 commits into from
Apr 14, 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 |
|:-------------------:|:-------:|:--------|
| 14.04.2023 | 1.8.3.6 | [UARTs] software can now retrieve the configured RX/TX FIFO sizes from the `DATA` register; [#581](https://github.com/stnolting/neorv32/pull/581) |
| 13.04.2023 | 1.8.3.5 | :bug: fixed bug in FPU control logic (introduced in some earlier clean-up commit); minor code edits and optimizations; [#578](https://github.com/stnolting/neorv32/pull/578) |
| 07.04.2023 | 1.8.3.4 | rtl edits and cleanups; [#571](https://github.com/stnolting/neorv32/pull/571) |
| 05.04.2023 | 1.8.3.3 | update **external interrupt controller (XIRQ)**; [#570](https://github.com/stnolting/neorv32/pull/570) |
Expand Down
12 changes: 9 additions & 3 deletions docs/datasheet/soc_uart.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ Once an UART interrupt has fired it remains pending until the actual cause of th
example if just the `UART_CTRL_IRQ_RX_NEMPTY` bit is set, the RX interrupt will keep firing until the RX FIFO is empty again.
Furthermore, a pending UART interrupt has to be explicitly cleared again by writing zero to the according <<_mip>> CSR bit.

.RX/TX FIFO Size
[TIP]
Software can retrieve the configured sizes of the RX and TX FIFO via the according `UART_DATA_RX_FIFO_SIZE` and
`UART_DATA_TX_FIFO_SIZE` bits from the `DATA` register.

**RTS/CTS Hardware Flow Control**

Expand Down Expand Up @@ -137,9 +141,11 @@ Both file are created in the simulation's home folder.
<|`29:27` - ^| r/- <| _reserved_ read as zero
<|`30` `UART_CTRL_RX_OVER` ^| r/- <| RX FIFO overflow
<|`31` `UART_CTRL_TX_BUSY` ^| r/- <| TX busy or TX FIFO not empty
.3+<| `0xffffffa4` .3+<| `DATA` <|`7:0` ^| r/w <| receive/transmit data
<|`31:8` ^| r/- <| _reserved_, read as zero
<|`31:0` ^| -/w <| **simulation data output**
.5+<| `0xffffffa4` .3+<| `DATA` <|`7:0` `UART_DATA_RTX_MSB : UART_DATA_RTX_LSB` ^| r/w <| receive/transmit data
<|`11:8` `UART_DATA_RX_FIFO_SIZE_MSB : UART_DATA_RX_FIFO_SIZE_LSB` ^| r/- <| log2(RX FIFO size)
<|`15:12` `UART_DATA_TX_FIFO_SIZE_MSB : UART_DATA_TX_FIFO_SIZE_LSB` ^| r/- <| log2(RX FIFO size)
<|`31:16` ^| r/- <| _reserved_, read as zero
<|`31:0` ^| -/w <| **simulation data output**
|=======================


Expand Down
4 changes: 2 additions & 2 deletions rtl/core/neorv32_package.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ package neorv32_package is
-- log2 of co-processor timeout cycles --
constant cp_timeout_c : natural := 7; -- default = 7 (= 128 cycles)

-- Architecture Constants --------------------------------------------------------------
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080305"; -- hardware version
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01080306"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width, do not change!

Expand Down
14 changes: 12 additions & 2 deletions rtl/core/neorv32_uart.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ architecture neorv32_uart_rtl of neorv32_uart is
constant ctrl_rx_over_c : natural := 30; -- r/-: RX FIFO overflow
constant ctrl_tx_busy_c : natural := 31; -- r/-: UART transmitter is busy and TX FIFO not empty

-- data register bits --
constant data_rtx_lsb_c : natural := 0; -- r/w: RX/TX data LSB
constant data_rtx_msb_c : natural := 7; -- r/w: RX/TX data MSB
constant data_rx_fifo_size_lsb : natural := 8; -- r/-: log2(RX fifo size) LSB
constant data_rx_fifo_size_msb : natural := 11; -- r/-: log2(RX fifo size) MSB
constant data_tx_fifo_size_lsb : natural := 12; -- r/-: log2(TX fifo size) LSB
constant data_tx_fifo_size_msb : natural := 15; -- r/-: log2(TX fifo size) MSB

-- access control --
signal acc_en : std_ulogic; -- module access enable
signal addr : std_ulogic_vector(31 downto 0); -- access address
Expand Down Expand Up @@ -291,7 +299,9 @@ begin
data_o(ctrl_rx_over_c) <= rx_engine.over;
data_o(ctrl_tx_busy_c) <= tx_engine.busy or tx_fifo.avail;
else -- data register
data_o(7 downto 0) <= rx_fifo.rdata;
data_o(data_rtx_msb_c downto data_rtx_lsb_c) <= rx_fifo.rdata;
data_o(data_rx_fifo_size_msb downto data_rx_fifo_size_lsb) <= std_ulogic_vector(to_unsigned(index_size_f(UART_RX_FIFO), 4));
data_o(data_tx_fifo_size_msb downto data_tx_fifo_size_lsb) <= std_ulogic_vector(to_unsigned(index_size_f(UART_TX_FIFO), 4));
end if;
end if;
end if;
Expand Down Expand Up @@ -330,7 +340,7 @@ begin
);

tx_fifo.clear <= '1' when (ctrl.enable = '0') or (ctrl.sim_mode = '1') else '0';
tx_fifo.wdata <= data_i(7 downto 0);
tx_fifo.wdata <= data_i(data_rtx_msb_c downto data_rtx_lsb_c);
tx_fifo.we <= '1' when (wren = '1') and (addr = uart_id_rtx_addr_c) else '0';
tx_fifo.re <= '1' when (tx_engine.state = "100") else '0';

Expand Down
4 changes: 4 additions & 0 deletions sw/lib/include/legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
**************************************************************************/
/**@{*/
#define neorv32_uart0_available() neorv32_uart_available(NEORV32_UART0)
#define neorv32_uart0_get_rx_fifo_depth() neorv32_uart_get_rx_fifo_depth(NEORV32_UART0)
#define neorv32_uart0_get_tx_fifo_depth() neorv32_uart_get_tx_fifo_depth(NEORV32_UART0)
#define neorv32_uart0_setup(baudrate, irq_mask) neorv32_uart_setup(NEORV32_UART0, baudrate, irq_mask)
#define neorv32_uart0_disable() neorv32_uart_disable(NEORV32_UART0)
#define neorv32_uart0_enable() neorv32_uart_enable(NEORV32_UART0)
Expand All @@ -73,6 +75,8 @@
**************************************************************************/
/**@{*/
#define neorv32_uart1_available() neorv32_uart_available(NEORV32_UART1)
#define neorv32_uart1_get_rx_fifo_depth() neorv32_uart_get_rx_fifo_depth(NEORV32_UART1)
#define neorv32_uart1_get_tx_fifo_depth() neorv32_uart_get_tx_fifo_depth(NEORV32_UART1)
#define neorv32_uart1_setup(baudrate, irq_mask) neorv32_uart_setup(NEORV32_UART1, baudrate, irq_mask)
#define neorv32_uart1_disable() neorv32_uart_disable(NEORV32_UART1)
#define neorv32_uart1_enable() neorv32_uart_enable(NEORV32_UART1)
Expand Down
16 changes: 15 additions & 1 deletion sw/lib/include/neorv32_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
/** UART module prototype */
typedef volatile struct __attribute__((packed,aligned(4))) {
uint32_t CTRL; /**< offset 0: control register (#NEORV32_UART_CTRL_enum) */
uint32_t DATA; /**< offset 4: data register */
uint32_t DATA; /**< offset 4: data register (#NEORV32_UART_DATA_enum) */
} neorv32_uart_t;

/** UART0 module hardware access (#neorv32_uart_t) */
Expand Down Expand Up @@ -95,6 +95,18 @@ enum NEORV32_UART_CTRL_enum {
UART_CTRL_RX_OVER = 30, /**< UART control register(30) (r/-): RX FIFO overflow */
UART_CTRL_TX_BUSY = 31 /**< UART control register(31) (r/-): Transmitter busy or TX FIFO not empty */
};

/** UART data register bits */
enum NEORV32_UART_DATA_enum {
UART_DATA_RTX_LSB = 0, /**< UART data register(0) (r/w): UART receive/transmit data, LSB */
UART_DATA_RTX_MSB = 7, /**< UART data register(7) (r/w): UART receive/transmit data, MSB */

UART_DATA_RX_FIFO_SIZE_LSB = 8, /**< UART data register(8) (r/-): log2(RX FIFO size), LSB */
UART_DATA_RX_FIFO_SIZE_MSB = 11, /**< UART data register(11) (r/-): log2(RX FIFO size), MSB */

UART_DATA_TX_FIFO_SIZE_LSB = 12, /**< UART data register(12) (r/-): log2(RX FIFO size), LSB */
UART_DATA_TX_FIFO_SIZE_MSB = 15, /**< UART data register(15) (r/-): log2(RX FIFO size), MSB */
};
/**@}*/


Expand All @@ -103,6 +115,8 @@ enum NEORV32_UART_CTRL_enum {
**************************************************************************/
/**@{*/
int neorv32_uart_available(neorv32_uart_t *UARTx);
int neorv32_uart_get_rx_fifo_depth(neorv32_uart_t *UARTx);
int neorv32_uart_get_tx_fifo_depth(neorv32_uart_t *UARTx);
void neorv32_uart_setup(neorv32_uart_t *UARTx, uint32_t baudrate, uint32_t irq_mask);
void neorv32_uart_enable(neorv32_uart_t *UARTx);
void neorv32_uart_disable(neorv32_uart_t *UARTx);
Expand Down
34 changes: 31 additions & 3 deletions sw/lib/source/neorv32_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,34 @@ void neorv32_uart_setup(neorv32_uart_t *UARTx, uint32_t baudrate, uint32_t irq_m
}


/**********************************************************************//**
* Get UART RX FIFO depth.
*
* @param[in,out] UARTx Hardware handle to UART register struct, #neorv32_uart_t.
*
* @return FIFO depth (number of entries)
**************************************************************************/
int neorv32_uart_get_rx_fifo_depth(neorv32_uart_t *UARTx) {

uint32_t tmp = (UARTx->DATA >> UART_DATA_RX_FIFO_SIZE_LSB) & 0x0f;
return (int)(1 << tmp);
}


/**********************************************************************//**
* Get UART TX FIFO depth.
*
* @param[in,out] UARTx Hardware handle to UART register struct, #neorv32_uart_t.
*
* @return FIFO depth (number of entries)
**************************************************************************/
int neorv32_uart_get_tx_fifo_depth(neorv32_uart_t *UARTx) {

uint32_t tmp = (UARTx->DATA >> UART_DATA_TX_FIFO_SIZE_LSB) & 0x0f;
return (int)(1 << tmp);
}


/**********************************************************************//**
* Enable UART.
*
Expand Down Expand Up @@ -184,7 +212,7 @@ void neorv32_uart_putc(neorv32_uart_t *UARTx, char c) {

// wait for previous transfer to finish
while ((UARTx->CTRL & (1<<UART_CTRL_TX_FULL))); // wait for free space in TX FIFO
UARTx->DATA = (uint32_t)c;
UARTx->DATA = (uint32_t)c << UART_DATA_RTX_LSB;
}


Expand Down Expand Up @@ -217,7 +245,7 @@ char neorv32_uart_getc(neorv32_uart_t *UARTx) {

while (1) {
if (UARTx->CTRL & (1<<UART_CTRL_RX_NEMPTY)) { // data available?
return (char)UARTx->DATA;
return (char)(UARTx->DATA >> UART_DATA_RTX_LSB);
}
}
}
Expand Down Expand Up @@ -254,7 +282,7 @@ int neorv32_uart_char_received(neorv32_uart_t *UARTx) {
**************************************************************************/
char neorv32_uart_char_received_get(neorv32_uart_t *UARTx) {

return (char)(UARTx->DATA);
return (char)(UARTx->DATA >> UART_DATA_RTX_LSB);
}


Expand Down