This project implements a complete UART (Universal Asynchronous Receiver-Transmitter) communication system using VHDL for Xilinx Vivado. It includes transmitter (TX), receiver (RX), baud rate generator, top-level module with loopback testing, and a simulation testbench.
- Clock: 50 MHz (Spartan 3E FPGA)
- Baud Rate: 9600 (exact, divider = 325 for ~153.6 kHz tick → 16x oversampling)
- UART Format: 8 data bits, No parity, 1 stop bit (8N1)
- Oversampling: 16 clock ticks per UART bit for precise timing
- Loopback Mode: TX output connected internally to RX input for self-verification
- FPGA Pins: Switches for TX input data, LEDs for RX output data, button for reset
- Simulation: Full testbench for Vivado behavioral simulation
[50 MHz CLK] ───┐
│
▼
┌─────────────────┐ tick ───┐
clk ───►│ baudRateGenerator│────────────┼──► s_tick (16x baud)
└─────────────────┘ │
▼
[sw[7:0]] ───┐ │
▼ ▼
┌──────────────┐ ┌──────────────┐
btn┐│ tx_start │ │ rx │ ┌──────────┐
reset►logic ───► TX ───► tx ──────► RX ───► dataout ──► led[7:0]
│ │ │ │
└────── tx_done◄──────┘ rx_done │
└──────────┘
(Loopback: tx connects to rx internally)
- FSM-based: Both TX and RX use Moore FSMs with 4 states:
idle,start,data,stop. - Bit Timing: Each UART bit = 16 system ticks.
- TX: Outputs constant level during bit, shifts on 16th tick.
- RX: Samples at bit center (8 ticks for start validation, 16 ticks for data/stop).
- Shift Register: 8-bit data shifted LSB-first (TX) or loaded MSB-first (RX).
- Async Reset: Active-high for FPGA compatibility.
- Edge-triggered: All synchronous on
rising_edge(clk).
- Purpose: Divides 50 MHz clock to UART sampling tick (~153.6 kHz).
- Logic: 9-bit counter (0-325), pulses
tickon overflow. - Formula:
tick_freq = 50e6 / 326 ≈ 153.6 kHz→ baud = 9600 = tick_freq / 16. (MAX=325 updated for Spartan 3E). - Ports:
clk→tick
- Purpose: Serializes 8-bit parallel data to UART stream.
- FSM Transitions:
State Action Duration idle tx='1', wait tx_start - start tx='0' 16 ticks data tx = b_reg[0], shift left 8×16 ticks stop tx='1' 16 ticks → tx_done='1' - Ports:
clk, reset, tx_start, datain[7:0], s_tick→tx, tx_done
- Purpose: Deserializes UART stream to 8-bit data.
- FSM Transitions:
State Action Duration idle wait rx='0' (start bit) - start validate rx='0' @ tick=8 16 ticks data sample rx → shift-in MSB, 8 bits 8×16 ticks stop validate rx='1' @ tick=16 16 ticks → rx_done='1' - Ports:
clk, reset, rx, s_tick→rx_done, dataout[7:0]
- Purpose: Full system integration + loopback demo.
- Logic:
- Instantiates baud/TX/RX.
reset = btn.datain = sw[7:0].- Loopback:
rx_inst.rx <= tx_line. - Auto-trigger:
tx_startpulses after eachtx_done. - Outputs:
tx(external),led = dataout(echoes TX data).
- Ports:
clk, btn, sw[7:0]→tx, led[7:0]
- Purpose: Vivado simulation verification.
- Stimulus:
- 50 MHz test clk (20ns period).
- reset → release.
- Send
tx_startfordatain = 0xAA(twice). - Monitors
tx_done,rx_done, waveforms.
- Expected: RX reconstructs 0xAA, no errors in loopback.
1. Vivado → Create Project → RTL Project → No Board.
2. Add all *.vhd files.
3. Set Top Module: uart_testbench.
4. Run Simulation → Behavioral Simulation.
5. Zoom waveforms: verify TX stream (0xAA: start0 + 10101010 + stop1), RX data matches.
Note: Update .ucf/.xdc constraints for your Spartan 3E board pins (clk typically C9 or similar).
1. New Project → Board Files (select your board).
2. Add *.vhd, set Top: uart_top.
3. Constraints (.xdc):
set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
# btn, sw[7:0], led[7:0], tx pins...
4. Run Synthesis → Implementation → Generate Bitstream.
5. Program FPGA.
6. Test: Flip switches → LEDs show same pattern (loopback). Monitor tx pin with scope/another UART.
For other baud/clk: MAX_COUNT = (clk_freq / (baud * 16)) - 1;
Example 50MHz/9600: 325 (done).
For 115200 @50MHz: ~ (50e6/(115200*16))-1 ≈ 26.
- TX Line: Idle'1' → start'0'(16t) → d0(16t) → d1...d7 → stop'1'(16t) → repeat.
- dataout: Loads after stop bit.
- Baud: Approximate; calibrate divider.
- No Framing/Parity Error Check: Add in RX stop/data.
- No FIFO/Buffering: Single byte at a time.
- Extensions: Interrupt on done, multi-byte TX/RX, full-duplex external loopback.
Target: Spartan 3E @50MHz, 9600 baud. Verified in Vivado 2025.2 simulation.