HUB75 Refresh-Rate Math: BCM Color Depth Without Flicker

A HUB75 controller can be logically correct and still produce dim output, visible flicker, missing low bits, or camera banding. The cause is often an impossible timing budget. This tutorial turns panel geometry, scan ratio, bit depth, shift time, blanking, and BCM dwell into one refresh-rate calculation you can run before writing the RTL.

Define the costs

  • C: columns shifted for each row pair.
  • R: row addresses per complete frame, such as 16 for a 1:16-scan panel.
  • B: BCM bitplanes.
  • S: system clocks per shifted column.
  • O: blank, latch, and address-settling clocks per plane.
  • T: system clocks in one least-significant dwell unit.

The conservative frame equation

If shifting and display time do not overlap, one row address costs:

row clocks = B(CS + O) + T(2B − 1)

The full refresh rate is:

Frefresh = Fclk / [R × row clocks]

Worked 64×32 example

Assume a 100 MHz FPGA clock, 64 columns, 1:16 scan, 12 bitplanes, two clocks per shifted column, 8 clocks of overhead per plane, and a 10-clock base dwell. Shifting and overhead cost 12 × (128 + 8) = 1,632 clocks. Weighted display time costs 10 × 4,095 = 40,950 clocks. One row address therefore costs 42,582 clocks and a frame costs 681,312 clocks. The resulting full refresh is about 147 Hz.

That may look acceptable to an eye while still showing bands on a rolling-shutter camera. It also leaves little room for longer blanking, memory stalls, or a slower external shift clock.

Ways to recover timing margin

  • Reduce bit depth. Ten bits has 1,023 dwell units instead of 4,095.
  • Shift the next plane while the current plane is visible, if the panel latches allow it.
  • Use both clock edges only when the interface and timing constraints genuinely support it.
  • Split a wide display across parallel data paths.
  • Use temporal dithering to recover apparent depth across frames.
  • Keep blanking long enough for clean output; do not “optimize” by reintroducing ghosting.

Effective bits matter more than nominal bits

If the least-significant plane is shorter than driver propagation and settling time, it is not a real brightness bit. Measure the smallest repeatable pulse at the panel output and choose T from that result. A stable 10-bit system usually looks better than a nominal 12-bit system whose lower planes vanish or jitter.

Verify the scheduler

  • Count exactly C shift clocks before every latch.
  • Assert that OE is inactive during latch and row changes.
  • Measure each plane dwell and verify powers-of-two weighting.
  • Count row visits per frame and frames per second in simulation.
  • Compare simulated timing with a logic-analyzer capture on hardware.

Do the arithmetic first, then choose the architecture. It is much cheaper to change B, T, or the number of parallel lanes in a spreadsheet than after the serializer and framebuffer are complete.


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 SystemVerilog verification.

Comments

Leave a Reply

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