hexforge / examples
Examples
Eight designs live in examples/. They double as the board acceptance suite: a board earns full support when all eight build and run on it, which is why the set stays small and deliberately boring.
Follow an example for its build transcript and per-part figures, or read the set as examples.json.
The set
| Example | LUT4 | FF | BRAM | Clock | Teaches |
|---|---|---|---|---|---|
blink | 25 | 24 | - | 12 MHz | The smallest useful design: parameter, counter, one output. |
pwm_fan | 90 | 64 | - | 12 MHz | Comparator against a duty register, and what a wide comparator costs. |
seven_seg | 140 | 72 | - | 12 MHz | A case decoder plus time-multiplexed digit scanning. |
spi_master | 180 | 96 | 24 MHz | 24 MHz | A shift register and a small state machine with a clean enable. |
bram_rom | 60 | 40 | 2 | 12 MHz | The exact array shape that gets inferred as block RAM, and nothing else. |
uart_loopback | 310 | 180 | - | 12 / 48 MHz | Two clocks, a divider, and the warning you get for an unconstrained crossing. |
vga_bars | 980 | 412 | - | 25.175 MHz | A PLL instantiated by hand, 640×480 timing, and a design that actually needs its clock met. |
fifo_cdc | 2 140 | 1 180 | 4 | 12 / 48 MHz | The largest example, and the one with a caveat - see below. |
Building one
Each directory has a small makefile wrapping the four tools, so the normal invocation is one line:
$ make -C examples/uart_loopback BOARD=pebble-25
hxc uart_loopback.v -> uart_loopback.hxn
hxsyn --device T4-25K -> uart_loopback.hxr 310 LUT4, 180 FF
hxta --device T4-25K --corner slow 2 clocks, 0 violations
hxpack --board pebble-25 -> uart_loopback.bit 141 312 bytes
built in 4.1 s
Change BOARD and the device follows from the board file. The makefiles are deliberately thin - four commands and a dependency list - so that reading one tells you the whole flow without learning a build system.
Notes on individual examples
vga_bars
The only example that depends on a hard block: a HX_PLL instance turning the board's 12 MHz oscillator into 25.175 MHz. The divider values are written out in a comment with the arithmetic, because nothing in the toolchain will compute them and the next person deserves to see where they came from. On T4-12K it fits at 71% occupancy, which is close enough to the packer's comfortable range to be a fair stress test.
uart_loopback
Two clock domains with a two-stage synchroniser on the receive path. Timing passes, and the analyser still prints W204 for the crossing, because it cannot verify a synchroniser and does not pretend to. This example exists mostly so that warning gets seen early by everyone, and the timing page uses its report in full.
bram_rom
A 512×8 lookup table initialised from an initial block. It is written in the one array shape the inference rules accept; change the depth to 600 and it becomes 4 800 flip-flops, which is the fastest way to see why the shape matters. The limitations page lists the rule.
fifo_cdc
Builds and runs, not verified. This is a dual-clock FIFO with gray-coded pointers. It has been exercised on Pebble-25 for hours without losing a word, which is evidence and not proof: the toolchain cannot analyse the crossing, and nobody has formally checked the design. Treat it as a worked example of a pattern, not as a block to drop into something that matters.
spi_master
Runs its output clock at 24 MHz by dividing the oscillator rather than through a PLL, which keeps it buildable on Crofter Lite where no PLL exists. Of the eight, this is the one most often copied into other projects, so its state machine is written for reading rather than for the smallest possible resource count.
Seeds and reproducibility
Every example builds with seed 1 by default and the resulting bitstream hash is recorded in examples/HASHES. Each release is checked by rebuilding all eight on two machines and comparing against that file; a mismatch means determinism broke, which has happened once, in 0.6.0, and was found this way.
Three examples need a seed other than 1 to clear a 10% timing margin on the smaller part: vga_bars on T4-12K prefers seed 3, and fifo_cdc and uart_loopback both do better at seed 2 when clocked at 48 MHz. The makefiles do not do this for you, since quietly sweeping seeds would hide how marginal a design is.
Adding one
New examples are welcome if they teach something the eight do not, fit in 2 500 LUT4, and come with a line of output or a photograph proving the thing ran. An example that only compiles is a test case, and test cases belong in tests/ instead, where there are already 221 of them.