A One-Bit-Stream Binary32 Divider Sustains 6.75 Million Divisions Per Second

Open FPGA IP · IEEE-754 binary32 · continuous serial arithmetic

One complete floating-point division leaves this FPGA every 32 clocks.

Brian Greenforest built a source-exact binary32 divider whose arithmetic ports are one bit wide. It accepts a fresh raw numerator and denominator every 32 clocks, sustains 6,750,000 divisions per second at 216 MHz, and passed 65,536 physical USB/FPGA cases with every result correct.

The design turns the continuous serial multiplier into a complete reciprocal, refinement, correction, rounding, exponent, sign, and binary32 packing graph. The RTL, host oracle, constraints, build scripts, reports, verified bitstream, physical result, and complete ZIP are open for study and reuse.

Download the complete divider IP Open the build README Inspect the 65,536-case result
Flow diagram showing binary32 inputs unpacked into separate one-bit significand, exponent, and sign paths; a reciprocal seed and three serial multipliers form and round the quotient before one final binary32 pack
IEEE-754 is a boundary format here. Significand, exponent, and sign travel as separate fixed-cadence streams and meet only in the final registered pack.

The Result Is A Divider, Not A Serialized Parallel Divider

A conventional floating-point divider often begins with wide fields, wide operators, transaction controls, and a variable amount of work hidden behind ready/valid handshaking. This architecture begins from a different premise: the surrounding compute graph already speaks in time.

Each input word arrives least-significant bit first. The divider consumes one numerator bit and one denominator bit on every arithmetic clock. Thirty-two clocks form a record. After the fixed pipeline fills, every record boundary carries another completed quotient with no load pulse, drain cycle, clock enable, retry, or stall.

The boundary latency is exactly 32 records: 1,024 clocks, or 4.740741 microseconds at 216 MHz. Latency determines when the first answer appears. The 32-clock initiation interval determines the sustained rate.

The Interface Contract Fits A High-Rate Finite-Normal Compute Graph

Inputs
Two raw IEEE-754 binary32 streams, LSB-first
Output
One raw IEEE-754 binary32 stream, LSB-first
Operating domain
Finite, nonzero, normal operands with a finite normal quotient
Cadence
One new operand pair and one steady-state result per 32 clocks
Rounding
IEEE round-to-nearest, ties-to-even
Arithmetic control
Reset plus fixed local phases; no transaction backpressure

That operating contract lets the silicon serve continuous finite-normal numerical work directly. The graph spends its logic on quotient quality and cadence rather than exception dispatch, subnormal shifting, or a transaction controller. The resulting core contains zero RAM blocks and zero DSP blocks.

Binary32 Is Unpacked Once And Packed Once

The raw 32-bit inputs are not repeatedly converted between a floating-point word and internal arithmetic. Each boundary unpack separates three facts exactly once:

Those paths remain separate through the graph. The significand path performs reciprocal generation, products, residual correction, and rounding. In parallel, the exponent path evaluates Ea - Eb + 127 - normalization_adjust. The sign path is one XOR followed by fixed delays. They reunite only at the registered output pack.

This separation is more than neat organization. It preserves the real shape of floating-point division: sign does not belong in reciprocal arithmetic, and exponent arithmetic does not need to widen the significand graph. Each fact moves through the smallest machinery that can transform it.

One Comparison Normalizes The Ratio Without A Leading-One Detector

Normal binary32 operands already supply an implicit leading one. A serial comparison decides whether the numerator significand is smaller than the denominator significand. The graph then selects the numerator directly or left-shifted by one bit so the normalized ratio enters the interval required by the reciprocal path.

The same decision becomes the exponent normalization adjustment. No later result scan is needed, so the entire divider uses zero leading-one detectors. A fact established at the entrance controls both the significand and exponent paths at their appropriate fixed phases.

Fourteen Non-Restoring Digits Start The Reciprocal

The denominator enters an exact fourteen-digit non-restoring recurrence. It emits a quotient prefix Q, a remainder P, and the delayed denominator while retaining the invariant:

2^37 = Q * B + P

The recurrence is built from 29 scalar add/subtract cells. It does not ask a wide divider operator for an approximate reciprocal. It grows the reciprocal information one decision and one bit-stream recurrence at a time, already aligned to the 32-clock record cadence of the surrounding graph.

This seed is good enough to make one refinement step decisive. It also keeps the denominator, quotient prefix, and remainder causally aligned for the products that follow.

Three Continuous Serial Multipliers Build The Quotient

The first product multiplies Q by P and emits the shift-23 window needed by the refinement. A serial addition forms:

X1 = (Q << 14) + floor((Q * P) / 2^23)

The second product multiplies the normalized numerator A' by X1. Its shift-28 window becomes the initial integer quotient estimate:

q0 = floor((A' * X1) / 2^28)

The third product computes the low 32 bits of q0 * B. That is precisely the product window needed to form the residual under the graph's proven bound. The residual chooses the fixed quotient correction, and two exact remainder comparisons supply the round decision. The final selection implements round-to-nearest, ties-to-even, including the carry case.

All three products inherit the multiplier's essential property: an operand bit enters on every clock, product work continues across record boundaries, and pipeline depth never creates a bubble in the record stream.

The Complete Graph Has A Fixed U0-To-U31 Schedule

U0-U1
Unpack; compare significands; conditionally shift the numerator
U1-U16
Generate the exact fourteen-digit non-restoring seed
U17-U21
Compute Q*P and form the refined reciprocal X1
U22-U26
Compute A'*X1 and extract the initial quotient q0
U26-U28
Compute low-32 q0*B, the exact residual, and fixed correction
U27-U30
Compare the remainder and round to nearest, ties to even
U0-U30
Carry exponent and sign through their independent serial paths
U31
Pack one registered raw binary32 result stream

Local one-hot phase rings and registered relays control the arithmetic sites. Registered fanout trees distribute high-dependency data and tag bits. When a route would become long, the architecture spends a fixed pipeline stage and preserves the global 216 MHz cadence.

The Machinery Is Countable Down To Scalar Recurrences

At graph level, the divider contains three serial multipliers, eight additional serial add/subtract engines, three serial comparators, and zero leading-one detectors.

At physical recurrence level, 192 add/subtract cells perform the work:

The structure is visible in the downloadable RTL. Its build audit rejects behavioral wide multiplication, division, shifts, comparisons, DSP inference, carry macros, gated arithmetic flops, and transaction-control names inside the divider hierarchy.

A Physical Probe Found Product Bits Reentering The Next Record

The low-product engine only needs positions 0 through 31 of q0 * B. During physical bring-up, a 1.0 / 1.0 internal probe returned 0xff803fff instead of the required 0xff800000. The pattern identified the problem: true product positions 32 through 45 were circulating into phases 0 through 13 of the following record.

The correction masks every partial-product term whose indices satisfy i + j >= 32 before it can enter the adder tree. The registered carry-clear phases remain unchanged because the issue was truncation aliasing, not carry timing. The corrected probe produced 0xff800000, and the full 65,536-vector division run then passed.

This is exactly why the package includes both a mathematical oracle and a physical USB path. The probe turned a phase-shaped failure into a local structural fix that is now explicit in the published multiplier RTL.

The Core Uses Logic And State, Not DSP Or RAM

Arithmetic core
1,247 LUT4; 6,805 DFF; 6,807 / 7,680 logic cells; 0 RAM; 0 DSP
Complete USB image
1,389 LUT4; 7,150 DFF; 7,192 / 7,680 logic cells; 14 I/O; 7 global buffers; 1 PLL; 0 RAM
Arithmetic clock route in the complete USB image
240.096039 MHz achieved for the 216 MHz build
Sustained rate
216,000,000 / 32 = 6,750,000 divisions/s
Fixed latency
1,024 clocks = 4.740741 microseconds at 216 MHz

The arithmetic core's 6,805 flip-flops are the spatial memory of the schedule: phase rings, bounded fanout trees, delayed streams, local carries, and causal histories. That state turns wide space into narrow time without surrendering throughput.

The readable utilization report, raw nextpnr timing/utilization JSON, and timing gate are published beside the source.

65,536 Physical Divisions Returned 65,536 Correct Results

The final 135,100-byte SRAM image ran on the iCE40 HX8K at exactly 216 MHz. An FT2232H channel-B MPSSE link clocked at 30 MHz sent numerator bits followed by denominator bits for binary32 positions 0 through 31. The FPGA returned every quotient bit twice so the host could check both arithmetic and output-slot coherence.

The expected quotient came from exact integer ratio arithmetic with binary32 round-to-nearest, ties-to-even. Host floating-point arithmetic was not used as the oracle, and no HDL emulator stood in for the FPGA result. The N16 RF output remained unconditionally high impedance throughout the run.

The programmed bitstream SHA-256 is 804af96defb0cfb9a941d24439ad2b77cff81463a722ea38c05d95ea9fb89152. The same image is included in the download package.

Everything Needed To Inspect, Build, And Verify It Is Open

The source package is MIT-licensed and organized as a working engineering handoff, not a code excerpt. It contains the four reusable divider RTL files, the physical USB wrapper, HX8K constraints, the 216 MHz timing constraint, the audited build script, exact-integer host oracle, MPSSE and SRAM-programming helpers, selected raw reports, verified bitstream, physical evidence, utilization guide, and a package-local SHA-256 manifest.

Complete package
Download one ZIP with source, tools, reports, evidence, and bitstream
Divider graph
gf_binary32_divider_stream.sv
Serial support
unpack, pack, add/subtract, compare, delay, and phase modules
Reciprocal seed
fourteen-digit non-restoring seed RTL
Product engines
three II=32 serial multiplier forms
Physical wrapper
HX8K, PLL, CDC, MPSSE, and high-impedance N16 top
Verification
exact-integer RNE oracle and physical verifier
Integrity
SHA-256 for every other payload file in the ZIP

Start with the README. The verifier can run its oracle, rounding, codec, and controlled-vector tests without opening an FTDI device. Hardware access occurs only with the explicit execute option. The build script recreates the audited Yosys, nextpnr, and IceStorm path from the published RTL.

Use The Divider As A Beginning

This IP makes a concrete design space available: floating-point arithmetic whose terminal interface is familiar while its internal movement is temporal, scalar, local, and composable. It can be retargeted, widened, wrapped in another transport, embedded in a serial compute graph, used in a class, or studied as a worked example of transforming an algorithm into fixed-phase spatial machinery.

Download it, synthesize it, trace the U stages, change the seed, instrument a recurrence, or build another operation from the same stream discipline. If you want Brian to adapt this architecture to a product, FPGA, research program, or custom numerical system, start the conversation.