Practice

Market Sign LED Chain

St Jude's covered market hung a two-lamp smart sign above its fish entrance. Each lamp held one chip, and data passed through both on one wire.

The colors looked right for one frame. Then each update slid them one lamp farther down the chain. The controller left too little low time between frames.

The chips never latched, so each new frame pushed the old bits farther along. Soon the red and green lamps traded places after every update.

Your task: build a sender with exact pulse widths and a real latch gap. Send both lamp colors in order, then hold the wire low long enough.

Interface

PortDirectionTypeDescription
clk_iin1 bit20 MHz clock, 50 ns per clock
rst_iin1 bitSynchronous reset (active high)
start_iin1 bitSend one frame
rgb0_iin24-bit vectorFirst lamp color, red in bits 23..16, green in 15..8, and blue in 7..0
rgb1_iin24-bit vectorSecond lamp color, red in bits 23..16, green in 15..8, and blue in 7..0
din_oout1 bitChain data wire, idle low, registered
busy_oout1 bitHigh while a frame runs, registered
done_oout1 bitOne-clock pulse on the frame's final gap clock, registered

Behavior

  • start_i is honored only while the sender sits idle, and the accepted frame begins on the following clock
  • Acceptance takes a snapshot of both color inputs
  • A running frame keeps that snapshot even if rgb0_i or rgb1_i change beneath it
  • A busy sender pays no attention to new start_i assertions
  • busy_o goes high at acceptance and remains high through the final latch-gap clock
  • Each lamp contributes 24 bits in green, red, then blue byte order
  • Within every byte, the most significant bit is sent first
  • The 24 bits from rgb0_i are sent first, followed by the 24 bits from rgb1_i
  • Every bit occupies exactly 25 clocks
  • A zero bit drives din_o high for exactly 8 clocks, then low for exactly 17 clocks
  • A one bit drives din_o high for exactly 16 clocks, then low for exactly 9 clocks
  • All 48 bits are sent back to back with no extra clocks between them
  • After the 48th bit, din_o remains low for exactly 1000 clocks, which is 50 us
  • done_o pulses exactly once, on the final clock of the 1000-clock latch gap
  • busy_o remains high during the done_o pulse
  • On the next clock, busy_o and done_o fall together, and the unit becomes idle
  • While idle, din_o, busy_o, and done_o are low
  • rst_i high at any rising edge drives all outputs low, returns the unit to idle, and cancels all frame progress
  • No cancelled frame resumes after reset

What the bench checks

  • A decoder plays the two chips: it measures every high run in clocks, classifies all 48 bits, and maps them back to each lamp's color
  • Pulse widths are exact: a high run of anything but 8 or 16 clocks fails, as does a low remainder of anything but 17 or 9
  • The latch gap is counted to the clock: a frame that ends before 1000 low clocks is called out as the colors sliding down the chain
  • Both color inputs switch to decoys one clock after acceptance, so a frame built from live inputs decodes wrong
  • Extra start_i pulses land mid-bit, deep in the gap, and on the final gap clock, and none may leave a mark
  • It asserts reset during a high pulse, a low remainder, and the latch gap
  • After every reset it expects the wire low on the very next clock and no cancelled frame resuming

Constraints

TIMING: everything is synchronous to the 20 MHz clk_i; inputs are sampled on rising edges, and all outputs are registered.

SCOPE: this models the data wire's digital pulse train at exact clock counts; the chips' analog thresholds, supply, and color mixing are out of scope.

Do not add ports.

Loading editor...

Click Run to execute your code. Output will appear here.