Step-by-Step Guide: Designing a Low-Power UART Interface on a Xilinx CPLD
When your battery‑powered sensor node starts to die after a few weeks, you know it’s time to look at the tiny bits that waste power. The UART (Universal Asynchronous Receiver/Transmitter) is often the silent culprit—always listening, always driving. In this post I walk you through a practical, low‑power UART design on a Xilinx CPLD, using the same hands‑on style you’ll find on CPLD Insights.
Why Low Power Matters
Embedded designers wear many hats, but the one that never goes away is the “energy police” hat. Whether you are building a wearable, an IoT gateway, or a remote data logger, every microwatt counts. A UART that idles at full speed can drain a coin cell faster than you can say “sleep mode”. By trimming the UART’s power budget you extend battery life, reduce heat, and make your design more robust.
Picking the Right Xilinx CPLD
Xilinx offers several families of CPLDs: XC9500, XC9500XL, and the newer XC9500E. For low‑power work I prefer the XC9500E series because it supports fine‑grained clock gating and has a built‑in “Power‑Down” pin. The device also offers enough logic cells to implement a simple UART without resorting to an external transceiver.
Tip from the lab: I once tried to squeeze a full‑duplex UART into a tiny XC9500XL and ended up with a hot chip that smoked my breadboard. The lesson? Choose a device that gives you headroom for power‑saving tricks.
UART Basics in Plain Language
A UART is just a pair of shift registers that move bits in and out at a set baud rate. The transmitter takes parallel data, adds a start bit, optional parity, and stop bits, then shifts them out one by one. The receiver does the reverse, looking for the start bit, sampling the data, and checking parity if you use it.
Key parameters that affect power:
- Baud rate – Higher speeds mean more switching activity.
- Clock enable – Keeping the UART clock running when idle wastes power.
- Logic depth – More gates toggling = more current.
Step 1: Define Your Requirements
Before you open Vivado or any other tool, write down the specs:
| Parameter | Value |
|---|---|
| Baud rate | 115200 (max) |
| Data bits | 8 |
| Parity | None |
| Stop bits | 1 |
| Power budget | < 2 mW average |
| Supply voltage | 3.3 V |
Having these numbers on paper helps you decide where you can cut corners. For example, if your application never needs 115 kbaud, you can lower the clock frequency and save a lot of power.
Step 2: Create a Clock Gating Scheme
The biggest power win comes from stopping the UART clock when the line is idle. Xilinx CPLDs let you gate the internal clock with a simple enable signal.
- Add a “UART Enable” register that is set when you have data to send or when a start bit is detected on the RX line.
- Feed this register into the clock enable pin of the UART’s internal shift registers.
- When the register is cleared, the clock stops toggling, and the shift registers hold their state without consuming dynamic power.
In VHDL the code looks like this (plain ASCII, no fancy characters):
process (clk)
begin
if rising_edge(clk) then
if uart_enable = '1' then
uart_clk <= not uart_clk;
else
uart_clk <= '0';
end if;
end if;
end process;
The uart_enable flag is driven by two simple conditions: a transmit request or a detected start bit on the RX line.
Step 3: Implement a Low‑Power State Machine
A UART can be modeled as a small finite‑state machine (FSM). Keep the FSM tiny—four states are enough:
- IDLE – Clock gated, waiting for activity.
- START – Detect start bit, enable clock.
- DATA – Shift in/out data bits.
- STOP – Verify stop bit, then return to IDLE.
Because the FSM only changes state when needed, the switching activity stays low. Use synchronous reset to avoid glitches.
Step 4: Use a Low‑Power Baud Rate Generator
The baud rate generator is a simple counter that divides the system clock. To keep it low power:
- Use a binary counter with the smallest width that still reaches your max baud rate.
- Enable the counter only when
uart_enableis high. - Reset the counter to zero in the IDLE state.
Here’s a concise VHDL snippet:
process (clk)
begin
if rising_edge(clk) then
if uart_enable = '1' then
if baud_cnt = BAUD_MAX then
baud_tick <= '1';
baud_cnt <= (others => '0');
else
baud_tick <= '0';
baud_cnt <= baud_cnt + 1;
end if;
else
baud_tick <= '0';
baud_cnt <= (others => '0');
end if;
end if;
end process;
The baud_tick pulse drives the shift registers only when needed, further reducing unnecessary toggling.
Step 5: Add a Pull‑Down on the RX Line
When the UART is idle, the RX pin can float and cause the CPLD to toggle its input buffer. Adding a weak pull‑down resistor (10 kΩ is fine) keeps the line at a known low level, preventing spurious start‑bit detection and saving power.
Step 6: Simulate Power Consumption
Before you solder the board, run a power simulation. Xilinx’s Power Analyzer can estimate dynamic power based on toggle rates. Feed it a realistic traffic pattern: a burst of 10 bytes, then 5 seconds of silence. Adjust the clock gating logic until the average power falls below your 2 mW target.
Step 7: Verify on Hardware
Load the bitstream onto a development board (the Xilinx XC9500E Evaluation Kit works well). Use a logic analyzer to watch the UART clock line. You should see the clock stop completely during idle periods. Measure the current with a low‑ohm shunt resistor; you’ll be surprised how low the number drops.
A quick anecdote: The first time I tried this on a real board, the UART kept waking up because I forgot to debounce the start‑bit detection. A simple two‑flip‑flop synchronizer solved it, and the power curve flattened nicely. Always remember that noisy edges can defeat even the best clock‑gating plan.
Step 8: Document and Reuse
Once you have a working low‑power UART, wrap it in a reusable VHDL package. Include parameters for baud rate, data width, and enable polarity. This way, future projects can drop the UART in without re‑engineering the power tricks.
Designing a low‑power UART on a Xilinx CPLD is not magic; it’s a series of small, thoughtful choices—clock gating, minimal logic, and careful reset handling. By following the steps above you’ll get a UART that sleeps soundly when not needed, extending the life of your battery‑powered designs.
- → Designing a Low-Power RF Front-End for Wearable Devices: A Practical Step-by-Step Guide @circuittalk
- → Designing a Low‑Power Capacitive Proximity Sensor for IoT Edge Devices @proximitypulse
- → Designing a Low Power Capacitive Proximity Sensor for IoT Edge Devices @proximitypulse
- → Designing a Low‑Power RF Front‑End for Wearable Devices: A Practical Step‑by‑Step Guide @circuittalk
- → Troubleshooting Common UART Communication Errors on Raspberry Pi: A DIY Checklist @serialcablechronicles