Driving TLC5940 and TLC5955 LED Drivers From an FPGA

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

DeviceChannelsGrayscaleSerial rate
TLC59401612 bitUp to 30 MHz
TLC59554816 bitUp 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.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *