Skip to content

Building a bitfile

Use build_bitfile.tcl. It sets the rate, forces the IP to regenerate, refuses to hand you a bitfile that failed timing, copies the result out under its scheme name, and writes a provenance stamp beside it.

vivado -mode batch -source hdl/build/build_bitfile.tcl -tclargs 12

The argument is the shift depth, not the rate. rate = 100 / Depth MHz:

Depth Rate Depth Rate
12 8.33 MHz 5 20 MHz
10 10 MHz 4 25 MHz
8 12.5 MHz 3 33.33 MHz
7 14.29 MHz 2 50 MHz
6 16.67 MHz

The rate applies to both channels.

Why not do it by hand

Changing Depth through Re-customize IP does not reliably regenerate c_shift_ram_0, so a build can be labelled one rate and synthesised at another. The script forces the regeneration — prefer it.

The provenance stamp

Every build writes a .txt next to the bitfile:

bitfile:      USBInterface-8_33mhz-J2_2+J2_4-3v3-IEEE.bit
built:        2026-09-21 10:51:50
vivado:       2023.2
git commit:   a0e5c13f4e249f92e451aef61e1e4d2fc66d7a6e
git dirty:    no  (sampled before the build wrote anything)
shift depth:  12  (=> 8.33 MHz on both channels)
WNS:          0.208229 ns
WHS:          0.024302 ns
clock:        dec_clk period 120.000 ns
clock:        dec2_clk period 120.000 ns

Commit the .txt with the .bit. git dirty: yes means the tree had uncommitted changes — treat that build as unreproducible.

Timing is not the limit

WNS is 0.208 ns for every rate from 8.33 to 50 MHz, because the critical path is the DDR3/USB interface, not the decoder. A bitfile closing timing tells you nothing about whether it can recover Manchester at that rate.

Naming

miniscope-io parses the filename, so the scheme is not decorative:

USBInterface-<rate>-<input pins>-<IO voltage>-<Manchester convention>.bit

e.g. USBInterface-8_33mhz-J2_2+J2_4-3v3-IEEE.bit. Each field is explained in Reading a bitfile name. No spaces, no extra periods; miniscope-io's test suite checks this.

Note

wireless_daq.runs/impl_1/USBInterface.bit is overwritten by every build. Always copy the result out under its scheme name — build_bitfile.tcl does this for you.

Debug pin variants

DEBUG_MODE in USBInterface.v selects which signals reach the three spare output pins. The hdl/build/ bitfiles use the default (1, both recovered clocks plus pipe2_ready); hdl/build/ch1_debug/ holds the same rates built with the channel-1-era signal set. See Pinout.

Changing the ring size

Each channel's buffer is a DDR3 ring sized by RING_ADDR_BITS in hdl/source/design/ddr3/ddr3_ui.v — 26, meaning 256 MiB per channel. Changing it is a one-line edit with no IP regeneration.

Both rings must fit in the device together: the channel bit sits immediately above RING_ADDR_BITS, so the two of them occupy 2^(RING_ADDR_BITS+1) words of app_addr. 26 puts that at 512 MiB on a 1 GiB board.

Check it in simulation first

tb_ddr3_ui overrides RING_ADDR_BITS to 5 so ring wrap and the full/empty conditions happen in microseconds. See the arbiter testbench.