Skip to content

[ot] hw/opentitan: ot_uart: model watermark/empty as status interrupts#328

Open
moidx wants to merge 1 commit into
lowRISC:ot-10.2.0from
moidx:qemu-updates
Open

[ot] hw/opentitan: ot_uart: model watermark/empty as status interrupts#328
moidx wants to merge 1 commit into
lowRISC:ot-10.2.0from
moidx:qemu-updates

Conversation

@moidx
Copy link
Copy Markdown

@moidx moidx commented May 31, 2026

tx_watermark, rx_watermark and tx_empty are declared as status-type interrupts in the UART HWIP (uart.hjson / prim_intr_hw IntrT="Status"): their INTR_STATE bits track the live FIFO condition every cycle rather than latching, and a RW1C write has no lasting effect while the condition holds. The model treated them as event-type, latching the bit on a receive batch and clearing it only via RW1C. As a result, once software drained the RX FIFO the latched rx_watermark bit stayed asserted, so the next received byte produced no fresh interrupt edge and interrupt-driven RX (e.g. a software-loopback test on ot-earlgrey) would hang.

Compute the status-type bits live from the FIFO levels and OR them with the latched event-type bits when reading INTR_STATE and when driving the IRQ lines, so they assert and de-assert with the hardware condition:

  • rx_watermark: rx_fifo_depth >= threshold
  • tx_watermark: tx_fifo_depth < threshold
  • tx_empty: tx_fifo_depth == 0

Re-evaluate the lines after an RDATA pop and on FIFO_CTRL writes, and drop the now-unused tx_watermark edge-tracking state.

Also align the FIFO depths (TxFifoDepth=32, RxFifoDepth=64) and the watermark threshold mappings (TX saturates at TxFifoDepth/2; RX saturates at RxFifoDepth-2, with rxilvl=7 disabling the interrupt) with uart_core.sv, and only push as many received bytes as the RX FIFO can hold.

@moidx moidx requested review from cfrantz and luismarques May 31, 2026 00:13
tx_watermark, rx_watermark and tx_empty are declared as status-type
interrupts in the UART HWIP (uart.hjson / prim_intr_hw IntrT="Status"):
their INTR_STATE bits track the live FIFO condition every cycle rather
than latching, and a RW1C write has no lasting effect while the condition
holds. The model treated them as event-type, latching the bit on a
receive batch and clearing it only via RW1C. As a result, once software
drained the RX FIFO the latched rx_watermark bit stayed asserted, so the
next received byte produced no fresh interrupt edge and interrupt-driven
RX (e.g. a software-loopback test on ot-earlgrey) would hang.

Compute the status-type bits live from the FIFO levels and OR them with
the latched event-type bits when reading INTR_STATE and when driving the
IRQ lines, so they assert and de-assert with the hardware condition:

  - rx_watermark: rx_fifo_depth >= threshold
  - tx_watermark: tx_fifo_depth <  threshold
  - tx_empty:     tx_fifo_depth == 0

Re-evaluate the lines after an RDATA pop and on FIFO_CTRL writes, and drop
the now-unused tx_watermark edge-tracking state.

Also align the FIFO depths (TxFifoDepth=32, RxFifoDepth=64) and the
watermark threshold mappings (TX saturates at TxFifoDepth/2; RX saturates
at RxFifoDepth-2, with rxilvl=7 disabling the interrupt) with
uart_core.sv, and only push as many received bytes as the RX FIFO can
hold.

Signed-off-by: Miguel Osorio <miguelosorio@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants