Constant-current LED drivers move current regulation and grayscale timing closer to the LEDs. The FPGA sends brightness words, controls shift and latch signals, and supplies any required grayscale clock. This tutorial uses TI’s TLC5940 and TLC5955 as concrete examples while keeping the controller architecture reusable.
Know what the driver provides
VHDL-2008 reference implementation
This article uses synthesizable VHDL-2008. The complete tested VHDL bundle is linked below; adapt clock constraints, I/O standards, and timing parameters to the target board and panel.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity hub75_row_scanner is
generic (COLUMNS : positive := 64; ROW_GROUPS : positive := 16);
port (
clk : in std_logic;
rst : in std_logic;
dwell_done: in std_logic;
pixel_bits: in std_logic_vector(5 downto 0);
hub_clk : out std_logic;
lat : out std_logic;
oe_n : out std_logic;
row_addr : out natural range 0 to ROW_GROUPS - 1;
rgb : out std_logic_vector(5 downto 0)
);
end entity;
architecture rtl of hub75_row_scanner is
type state_t is (blank, shift_low, shift_high, latch, set_row, display);
signal state : state_t := blank;
signal col : natural range 0 to COLUMNS - 1 := 0;
signal row : natural range 0 to ROW_GROUPS - 1 := 0;
begin
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
state <= blank; col <= 0; row <= 0;
else
case state is
when blank => col <= 0; state <= shift_low;
when shift_low => state <= shift_high;
when shift_high => if col = COLUMNS - 1 then state <= latch; else col <= col + 1; state <= shift_low; end if;
when latch => state <= set_row;
when set_row => state <= display;
when display => if dwell_done = '1' then if row = ROW_GROUPS - 1 then row <= 0; else row <= row + 1; end if; state <= blank; end if;
end case;
end if;
end if;
end process;
hub_clk <= '1' when state = shift_high else '0';
lat <= '1' when state = latch else '0';
oe_n <= '0' when state = display else '1';
row_addr <= row;
rgb <= pixel_bits when state = shift_low else (others => '0');
end architecture;
Download the VHDL-2008 FPGA LED controller examples
| Device | Channels | Grayscale | Serial rate |
|---|---|---|---|
| TLC5940 | 16 | 12 bit | Up to 30 MHz |
| TLC5955 | 48 | 16 bit | Up to 25 MHz |
The TLC5940 uses an external grayscale clock and exposes BLANK, XLAT, error, and programming-mode behavior. The TLC5955 adds 16-bit grayscale, per-color brightness controls, dot correction, error detection, and display-repeat features. The exact bit packing and edge timing come from the selected datasheet—not from a generic SPI assumption.
A reusable shift-and-latch engine
Parameterize frame width and bit order, then wrap the engine with a device-specific formatter. Register all outputs and constrain the interface as real external timing paths.
Initialization sequence matters
- Hold outputs blank while clocks and configuration stabilize.
- Program current range, brightness control, and dot correction before grayscale data.
- Load a known all-zero frame and latch it.
- Start the grayscale clock or display-repeat function.
- Release blanking only after a complete valid frame is active.
Electrical and thermal checks
The current-setting resistor, LED supply, output compliance voltage, simultaneous-channel current, package power dissipation, and PCB copper determine safe operation. Do not choose LED current from RTL. Calculate it from the device equations and verify worst-case thermal conditions.
Official datasheets
FPGA LED controller tutorial series
This article is part of the FPGA LED Controller Tutorials learning path. Continue with PWM vs. BCM, the HUB75 timing calculator, or VHDL-2008 verification.
Leave a Reply