Skip to main content

Module folded

Module folded 

Source
Expand description

A folded SHA-512 core: S round stages in a ring, S / 80 blocks per clock, for lines smaller than one full pipeline.

           ┌──────────────────── recirculate (round < 80) ───────────────┐
           ▼                                                             │
 ShaIn ─▶ [skid] ─▶ mux ─▶ round ─▶ round ─▶ … ─▶ round ──┬─────────────┘
                           stage 0  stage 1      stage S−1 └─▶ [final add] ─▶ ShaOut
                                                               (round = 80)

§Why this exists

Problem. The full Sha512Pipeline gives one block per clock for ~43k LUTs. The Ed25519 modules need far less: the default Ed25519 chip hashes about 25M blocks per second, an eighth of a block per clock. Before this core the line came only in whole and half blocks per clock (the half-rate “folded” core was a plan), so most of its LUTs bought nothing, and a line shrunk below ~23k could not be built.

Reasoning. All 80 rounds are the same step with a different constant. A block does not need 80 stages of its own: it can go round a ring of S stages 80 / S times. Every stage carries the block’s round counter, and the constant K_t is read from a 128-entry ROM by that counter (a 7-input function per bit, two LUT6 each), so a stage serves any round. The ring holds S blocks at once, each for 80 cycles: S / 80 blocks per clock, and the latency stays 82 cycles.

Decision. One core per stage count S that divides 80: Sha512Folded2, Sha512Folded4, Sha512Folded5, Sha512Folded8, Sha512Folded10, Sha512Folded16, Sha512Folded20 and Sha512Folded40 (FOLDS). S = 80 would be a full pipeline with a ROM per stage, so the line uses Sha512Pipeline there. The cores share one control kernel (fold_control) and differ only in their ring segment (FoldSeg10 and friends: at most ten children each, every stage wired as one expression, because RHDL lowers array-element writes to whole-array copies). The planner (crate::planner) builds the line from any mix of folded cores and full pipelines, the fastest that fits the line’s LUTs, so the line’s rate moves in steps of 1/40 block per clock instead of 1/2.

Status. Every size is bit-exact against sha2::compress512 in RHDL simulation at its full rate and under back-pressure, and lowers to Verilog that passes RHDL’s syntax check; the 2-, 5- and 10-stage Verilog matches the Rust model cycle by cycle in Icarus (tests/folded.rs). Every core routes out of context at 4.878 ns (205 MHz) with positive slack; the planner uses those routed LUTs (planner::ROUTED_LUT), and folded_lut remains the older Yosys estimate.

§Ports and flow control

The same ShaIn and ShaOut as the full pipeline, but with back-pressure: ShaCoreOut::ready is low while the ring is full. A client presents a block and holds it until ready is high in that cycle (a block presented while ready is low is ignored).

Inside, a one-entry skid buffer holds the accepted block until the slot arriving at stage 0 is free. A slot is busy while its block still has rounds to do; it frees the cycle its block finishes round 79, and the buffered block takes it. Blocks finish in the order they entered.

§Where to go next

You want to…Start here
see one stageFoldRound, fold_round_kernel
see the ring and the skid bufferfold_control
change what the planner thinks a fold costsfolded_lut, crate::planner

Structs§

FoldControl
What the ring control decides in one cycle.
FoldRound
One registered ring stage: performs round t of whatever block arrives.
FoldSeg2
Two ring stages.
FoldSeg4
Four ring stages.
FoldSeg5
Five ring stages.
FoldSeg8
Eight ring stages (two four-stage segments).
FoldSeg10
Ten ring stages (two five-stage segments).
FoldSeg16
Sixteen ring stages (two eight-stage segments).
FoldSeg20
Twenty ring stages (two ten-stage segments).
FoldSeg40
Forty ring stages (four ten-stage segments).
FoldStage
A block’s state between stages, with its round counter.
Sha512Folded2
2 stages: 1/40 block per clock.
Sha512Folded4
4 stages: 1/20 block per clock.
Sha512Folded5
5 stages: 1/16 block per clock.
Sha512Folded8
8 stages: 1/10 block per clock.
Sha512Folded10
10 stages: 1/8 block per clock.
Sha512Folded16
16 stages: 1/5 block per clock.
Sha512Folded20
20 stages: 1/4 block per clock.
Sha512Folded40
40 stages: 1/2 block per clock.

Constants§

FOLDED_LATENCY
Cycles from accepting a block (into the skid buffer) to presenting its result when the ring has room: the buffer, 80 rounds and the output register. The same as the full pipeline’s LATENCY.
FOLDS
Ring stage counts that have a core, smallest first.
K128
The round constants padded to 128 entries, so a 7-bit round counter can index them (entries 80–127 are zero and never used).

Functions§

fold_control
The ring control, the same for every stage count. leaving is the state leaving the last stage this cycle: it recirculates into stage 0 while it has rounds left, and is added to its chaining value when it has done round 79. A free slot takes the buffered block; the buffer takes the client’s block when it is empty or being placed (ready).
fold_round_kernel
Round t with K_{t+1} from the ROM for the next round’s look-ahead.
fold_seg2_kernel
Chain the stages of FoldSeg2 in series.
fold_seg4_kernel
Chain the stages of FoldSeg4 in series.
fold_seg5_kernel
Chain the stages of FoldSeg5 in series.
fold_seg8_kernel
Chain the stages of FoldSeg8 in series.
fold_seg10_kernel
Chain the stages of FoldSeg10 in series.
fold_seg16_kernel
Chain the stages of FoldSeg16 in series.
fold_seg20_kernel
Chain the stages of FoldSeg20 in series.
fold_seg40_kernel
Chain the stages of FoldSeg40 in series.
folded_lut
Estimated LUTs of a core with a ring of stages round stages: 1,020 per stage (round, schedule step, constant ROM, counter) plus 3,450 for the skid buffer, the stage-0 mux and the final addition. Fitted to Yosys synth_xilinx -family xcup of the 2-, 5- and 10-stage cores (5,491, 8,550 and 13,654 LUTs). An estimate: Yosys is not Vivado, and nothing here is placed or timed.
sha512_folded2_kernel
The ring control around Sha512Folded2’s segment.
sha512_folded4_kernel
The ring control around Sha512Folded4’s segment.
sha512_folded5_kernel
The ring control around Sha512Folded5’s segment.
sha512_folded8_kernel
The ring control around Sha512Folded8’s segment.
sha512_folded10_kernel
The ring control around Sha512Folded10’s segment.
sha512_folded16_kernel
The ring control around Sha512Folded16’s segment.
sha512_folded20_kernel
The ring control around Sha512Folded20’s segment.
sha512_folded40_kernel
The ring control around Sha512Folded40’s segment.