Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
    • Controller and Datapath
    • Moore vs Mealy
    • State Encoding
    • Multi-Cycle Sequencers
    • UART Transmitter
      • Framing and Timing
      • The UART TX FSM
      • Cycle-by-Cycle Walkthrough
      • Verification and Integration
      • Mini Project: an SPI Master
    • Memory Controller
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹UART Transmitter
  1. Topics
  2. RTL Design
  3. FSM & Control
  4. UART Transmitter
  5. Verification and Integration

Part 4 · FSM & Control · Intermediate

Verification and Integration

What the testbench checks, which bugs it catches, and how to connect the block.

On this page

    Why this matters

    A transmitter and a receiver written by the same person can share one wrong assumption, such as most-significant-bit first, and pass each other's tests. Real hardware then rejects the frames.

    After this lesson you can: list what a UART testbench must check, choose mutations that prove it can fail, and connect the transmitter to a producer, a pin and a CTS input.

    What the supplied testbench checks

    The table lists what the testbench checks on every run.

    Check

    How

    Every clock of every frame is right

    Acceptance is sampled before the rising edge; the monitor checks the post-update line against each expected frame sample, including start on the acceptance edge.

    Data is correct and in order

    The driver queues each accepted byte; the monitor pops one per frame.

    No lost or extra frames

    Completed frames + reset-cancelled frames = accepted bytes; unsolicited low line while idle fails.

    Valid/ready is honoured

    The driver records acceptance at the rising edge and changes the offer only at the falling edge after an accepted one. An offered byte keeps tx_valid and data unchanged until accepted, and the monitor reports a FAIL if they change first. Random pauses are inserted between offers.

    Back-to-back frames have no gap

    Every consecutive saturated acceptance is exactly 10*CPB rising edges apart; the full-frame monitor checks that each acceptance starts its frame immediately. Pair coverage is required, alongside the aggregate throughput bound.

    Parameter, reset and CTS boundaries

    CPB=1,2,3,434; directed 00/FF/A5/96; idle and mid-frame resets; CTS withdrawal during a stalled offer and at the last STOP slot. The pending byte stays stable and the accepted frame finishes.

    Mutation checks

    Each mutation below is applied to the listing, and the testbench must fail.

    Mutation

    Result

    Tick compare changed from CLKS_PER_BIT - 1 to CLKS_PER_BIT - 2

    Fails: every bit is one clock short; at CPB=4 the stop bit arrives early (sample 27) and burst spacing is 30 instead of 40 clocks; at CPB=1 the tick never fires and the offer times out

    STOP not accepting a byte at its last clock

    Fails: burst phase gap check

    Data sent MSB-first

    Fails on 0x96 (sample 4); 0x00, 0xFF and 0xA5 read the same in both orders and pass

    Using it in a design

    • Producer side: follow valid/ready. A FIFO in front of uart_tx lets the producer burst bytes while the line drains at baud rate (10 × CLKS_PER_BIT clocks per byte).

    • Pin side: drive the pin from the transmitter's registered tx in its own clock domain, with the appropriate I/O timing constraints. A single output flop clocked by an unrelated clock is not a safe CDC circuit and can distort or miss serial bits. If transmission must run in another domain, cross complete bytes (or complete configured data words) through an asynchronous FIFO or a CDC handshake, then run the UART FSM and baud generator in that destination domain.

    • Reset: asynchronous assert, synchronous release (see reset strategy). Reset drives tx high and cancels an active frame and any pending producer offer under a shared reset contract. A remote receiver may see a truncated frame: discard it and reestablish framing before relying on subsequent bytes. The bench checks local cancellation and a fresh complete frame; it does not simulate receiver recovery.

    • Flow control: synchronize remote CTS and normalize its polarity to cts_allow in the UART clock domain. The listing gates exported tx_ready internally and uses exactly that ready in accept. Keep producer valid/data stable under stall. CTS blocks acceptance at the sampled edge; after acceptance the whole frame finishes. A stateless CTS mask on valid can withdraw a stalled offer and violates that contract.

    Common extensions

    Extension

    Change

    Parity bit

    Add a PARITY state after DATA; the bit is ^data (even parity) or ~^data (odd). Latch the parity at accept.

    Two stop bits

    Make STOP last 2 × CLKS_PER_BIT clocks (count a second bit) before tx_ready.

    Configurable word size (5 to 9 bits)

    For a fixed WORD_BITS parameter, size tx_data and shreg as [WORD_BITS-1:0], bit_idx as [$clog2(WORD_BITS)-1:0], and compare bit_idx with WORD_BITS-1. Replace both fixed shreg[7:1] shift expressions with shreg >> 1. Nine bits require a 4-bit index and 9-bit data ports/storage. For runtime configuration, use 9-bit data ports/storage and a 4-bit index, and latch word_bits with each accepted word; enforce 5 through 9.

    Fractional baud

    Replace baud_cnt with a phase accumulator that produces tick at the average rate.

    The listing and testbench above remain fixed at 8N1. When implementing configurable width, extend the monitor and scoreboard too: a frame has word_bits + 2 bits including start and stop. Check 5-bit and 9-bit frames, especially 9'h100 and 9'h001, at every clock; require a bounded return to ready and back-to-back completion. For runtime configuration, change the live width input after acceptance to confirm the latched width controls the entire frame. Changing only the terminal comparison leaves the 3-bit index unable to reach 8, so a 9-bit frame never ends.

    Common mistakes

    Common pitfall

    Never test only with the receiver you wrote. A receiver and a transmitter that share the same misunderstanding (for example both use MSB-first) pass each other's tests and fail against real hardware. The monitor in this lesson is an independent description of the frame.

    Interview

    Be ready to list what you would test in a UART: frame format, every bit width, back-to-back bytes, reset in the middle of a frame, tx_valid held low for long periods, and a baud mismatch on the receiver side.

    Check yourself The transmitter runs at 50 MHz with CLKS_PER_BIT = 434 and the receiver uses a 16 MHz clock with an effective divisor of 139. How large is the nominal mismatch, and is it acceptable?

    TX = 115207.373 baud, RX = 115107.914 baud; TX/RX - 1 = +0.0864%. That fits the illustrative 2% allocation before oscillator corners, but acceptance requires the selected receiver's tolerance and sampling-mode specification. A hardware register divisor may include an oversampling factor; 139 here is the total effective divisor.

    Remember

    • Check every clock of every frame, data order, no lost or extra frames, valid/ready stability and back-to-back spacing.

    • Mutations prove the bench: a wrong tick compare and an MSB-first transmitter both make it fail.

    • Drive the pin from a flop in the UART's own clock domain, and cross whole bytes into that domain.

    Rule of thumb: never test only against a receiver you wrote.

    How this was checked

    The testbench was run with Icarus Verilog 13.0 (2026-10-16) and prints PASS. The checks cover the digital clock model, not receiver tolerance, pin timing or physical fault recovery.

    The tick and MSB-first mutation rows were rerun against this listing on 2026-10-16 (Icarus Verilog, CPB=4). The STOP row was recorded on the original listing and has not been rerun.

    Keep going

    • Practice: FSM verification strategy: coverage and assertions for corner cases

    • Code lab: UART TX byte

    • Interview: run a mock interview on this topic

    Related topics

    • Mini project: an SPI master

    • Memory controller FSM

    Previous

    110 / 350

    Next: Mini Project: an SPI Master

    Up next

    Up nextMini Project: an SPI Master

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Framing and Timing
    • The UART TX FSM