BP decoder

StaticTannerDatapath.scala contains the shared fixed-graph min-sum network. BpDecoder.scala adds an autonomous early-terminating controller.

Static Tanner network

TannerGraph.fromRows(variableCount, rowOnes) is the canonical graph input. TannerNodeGraphs.from derives local CNU and VNU ports from its stable, row-major edge identifiers.

StaticTannerCore instantiates:

  • one StaticCheckStage for each parity check;

  • one StaticVariableStage for each variable;

  • one fixed connection for every graph edge; and

  • one combinational ConvergenceChecker for \(H\hat e + s\) over \(\mathrm{GF}(2)\).

An accepted load stores the syndrome and unsigned prior magnitudes. Every variable-to-check message starts as the positive prior of that variable.

An accepted step starts one iteration. All check stages update on the first clock and all variable stages commit on the second. The immediate commit view is used by autonomous controllers; StaticTannerDatapath.result exposes the registered view. There is no row-by-row runtime schedule.

Node arithmetic

CheckNode computes syndrome-adjusted exclusive signs and a duplicate-preserving first/second minimum pair. An edge uses the second minimum when its input magnitude equals the first. Available scaling policies are:

  • NoScale: preserve the magnitude;

  • VallsScale(a, b): (x >> a) + (x >> b), clipped to the magnitude width;

  • RampScale(maxShift): x - (x >> t) for controls through maxShift, then x.

VariableNode converts incoming sign-magnitude messages to signed values, adds them to its bias, and computes one extrinsic value per edge. The hard decision is one only when the unsaturated total is negative. Stored marginals are signed and saturated; outgoing magnitudes are saturated separately.

Autonomous vanilla BP

VanillaBpConfig fixes the graph, maximum iterations, quantization, and check scaling. Its defaults use four magnitude bits, seven signed accumulator bits, and the ramp policy.

VanillaBpDecoder accepts StaticDecoderInput through io.in. It runs until the residual is zero or the frame limit is reached, then holds a BpDecoderResult on io.out until accepted. The result contains:

  • success and correction bits;

  • final signed marginals and residual;

  • completed iterations; and

  • legsExecuted = 1 and solutionsFound equal to the success flag.

When runtimeIterationLimit is elaborated, the optional limit port may select any positive prefix of the configured capacity. Each completed iteration costs exactly two decoder clocks. Output backpressure extends interface latency but does not alter the reported iteration count.

Inspect and test

./scripts/emit.sh static-steane
./scripts/emit.sh vanilla-steane
./mill chipsLDPC.test.testOnly chipsldpc.StaticTannerDatapathSpec
./mill chipsLDPC.test.testOnly chipsldpc.BpDecodersSpec

The maintained large experiment is in examples/BivariateBicycle144BpOnly/. Relay control is described in Relay BP.