CodiodeCodiode
Home
Problem Solving
Skill Tracks
My Assignments
Contests
Leaderboard
Community
Settings
Codiode/Problems/Sequential Logic

Protocol Integration: UART to AXI Stream Bridge

HardVerilog / SystemVerilogBuild

Modern SoCs standardize internal communication on synchronous protocols like AXI-Stream, but still need to interface with legacy or external peripherals like UARTs. A bridge module is required to cross this protocol boundary, ensuring that the single-cycle valid pulses from a UART receiver are safely converted into the handshake-driven Valid/Ready protocol of AXI-Stream.

The module receives an 8-bit data payload and a single-cycle valid pulse from a UART receiver. When the valid pulse arrives, the module must assert the AXI-Stream valid signal and present the data on the AXI-Stream data bus. Because the downstream AXI-Stream consumer might not be ready, the bridge must hold both the valid signal and the data indefinitely until the downstream ready signal is asserted. The transfer completes on the clock cycle where both valid and ready are high. If a new UART byte arrives while a previous byte is still waiting to be accepted by the AXI-Stream consumer, the bridge must drop the new incoming byte and pulse the overrun error flag for exactly one clock cycle.

Timing and Reset Rules: • Positive-edge triggered clock clk. • Asynchronous active-low reset rst_n. • On reset, m_axis_tvalid, m_axis_tdata, and overrun must all be driven to 0. • m_axis_tvalid and m_axis_tdata are registered outputs. They update on the clock edge immediately following a change in inputs. • Priority: A transfer completes when m_axis_tvalid and m_axis_tready are both 1 on a rising clock edge. If uart_rx_valid is asserted on the exact same cycle that a pending transfer completes, the bridge must immediately register the new data, keeping m_axis_tvalid high for the next cycle without asserting overrun.

Worked Trace: Cycle 1: rst_n=0 → m_axis_tvalid=0, m_axis_tdata=00, overrun=0 Cycle 2: rst_n=1, uart_rx_valid=1, uart_rx_data=AA → outputs remain 0 (inputs clock in) Cycle 3: uart_rx_valid=0 → m_axis_tvalid=1, m_axis_tdata=AA (data held) Cycle 4: uart_rx_valid=1, uart_rx_data=BB, m_axis_tready=0 → m_axis_tvalid=1, m_axis_tdata=AA Cycle 5: uart_rx_valid=0 → overrun=1 (pulsed due to dropped BB), m_axis_tvalid=1, m_axis_tdata=AA Cycle 6: m_axis_tready=1 → overrun=0, m_axis_tvalid=1, m_axis_tdata=AA (transfer completes) Cycle 7: m_axis_tready=0 → m_axis_tvalid=0, m_axis_tdata=AA (data holds previous value)

{ "signal": [
  { "name": "clk",           "wave": "p........." },
  { "name": "rst_n",         "wave": "01........" },
  { "name": "uart_rx_valid", "wave": "0.1010..10" },
  { "name": "uart_rx_data",  "wave": "x.==x...=x", "data": ["AA", "BB", "CC"] },
  { "name": "m_axis_tready", "wave": "0....10.10" },
  {},
  { "name": "m_axis_tvalid", "wave": "0..1..0.10" },
  { "name": "m_axis_tdata",  "wave": "0..=....=.", "data": ["AA", "CC"] },
  { "name": "overrun",       "wave": "0....10..." }
], "head": { "text": "Basic transfer followed by an overrun condition." } }

| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered clock | | rst_n | input | 1 | Asynchronous active-low reset | | uart_rx_valid | input | 1 | High for one cycle when new UART data is available | | uart_rx_data | input | 8 | 8-bit payload from the UART receiver | | m_axis_tready | input | 1 | AXI-Stream ready signal from downstream consumer | | m_axis_tvalid | output | 1 | AXI-Stream valid signal; registered | | m_axis_tdata | output | 8 | AXI-Stream data payload; registered | | overrun | output | 1 | High for one cycle when incoming UART data is dropped |

Constraints

  • m_axis_tvalid and m_axis_tdata must be registered outputs.
  • If uart_rx_valid is asserted while m_axis_tvalid is high and m_axis_tready is low, the incoming UART data is dropped.
  • The overrun flag must pulse for exactly one clock cycle immediately following the cycle where the dropped data was presented.
  • If uart_rx_valid is asserted on the exact same cycle that an AXI transfer completes (m_axis_tvalid == 1 and m_axis_tready == 1), the bridge must immediately register the new data, keeping m_axis_tvalid high for the next cycle.
  • m_axis_tdata should hold its previous value when m_axis_tvalid goes low, resetting only on rst_n.

Topics

UARTInterfacesAXI-StreamProtocol Bridge

Solve this problem

Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.

This problem is part of Codiode Pro. The statement above is free to read.

Sign in to solveSee what Pro unlocks

The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.

Related problems

  • Basic D Flip FlopEasy
  • Debug: Missing Edge in Sensitivity ListMedium
  • Read After Write Hazard DetectionEasy
  • Parameterized Interface with ModportsHard
  • Struct Array PipelineHard
  • T Flip Flop from D Flip Flop TemplateEasy
  • Recursive Generate Reduction TreeHard
  • Four Stage Shift RegisterEasy

Browse all problems · Learning tracks