Expand description
Field addition, subtraction, and multiplication datapaths.
§Field Arithmetic Modules
All field interfaces carry canonical packed integers modulo
p = 2^255 - 19. Bits 254:0 contain the ordinary little-endian binary value.
The active multiplier interprets that vector internally as five 51-bit limbs;
the predecessor interprets it as fifteen 17-bit limbs. No conversion is needed
at the module boundary.
§radix51_field_mul_pipe
Source: crates/rhdl_ed25519_fast_field/rtl/radix51_field_mul_pipe.sv.
This is the active field multiplier. It accepts one multiplication every cycle,
has a 17-position valid/data pipeline, and computes a*b mod p. The active signer
instantiates four copies in multicomb_mul_stream and four more in the four
point-compression ways.
This module has no overridable parameters. Its internal local parameters are:
| Local parameter | Meaning |
|---|---|
LIMBS = 5 | Number of radix-2^51 limbs |
LIMB_MASK | Low-51-bit mask used during carry propagation |
FIELD_P | Canonical modulus 2^255 - 19 |
LATENCY = 17 | Number of valid pipeline positions |
CURRENT_LIMB | Generate-loop constant naming the carry limb normalized by that stage |
§Ports
| Port | Direction | Meaning |
|---|---|---|
clk | input | Rising-edge clock |
rst | input | Synchronously clears valid_pipe; data registers are ignored while invalid |
valid_in | input | Qualifies a and b; a new operation may arrive every cycle |
a | input, 255 bits | First canonical field operand |
b | input, 255 bits | Second canonical field operand |
valid_out | output | Delayed validity corresponding to result |
result | output, 255 bits | Canonical product modulo p |
§weighted
weighted(value, wrap) is the module’s only helper function. value is a
105-bit 51x51 limb product. If wrap is false, it zero-extends the value. If
wrap is true, it returns 19*value as (value << 4) + (value << 1) + value.
The factor 19 implements the reduction identity 2^255 = 19 mod p for
convolution terms whose limb index wrapped past four.
§Pipeline
The 17 accepted-operation stages are:
| Stage | Register written | Function |
|---|---|---|
| 1 | a_part, b_part | Split all five 51-bit limbs into three private 17-bit chunks before the high-fanout product array |
| 2 | partial | Launch the 225 registered 17x17 products, one for every (field limb pair, chunk pair) |
| 3 | diagonal0..4 | Sum chunk products that share the same power of 2^17 inside each 51x51 product |
| 4 | product_low, product_middle, product_high | Shift the five diagonals into three bounded 105-bit groups |
| 5 | product_low_middle, product_high_q | Add the low and middle groups and delay the high group |
| 6 | limb_product | Add the high group to reconstruct each of the 25 full 51x51 limb products |
| 7 | coefficient_pair0, coefficient_pair1, coefficient_single | Gather the five convolution terms for each output limb and apply weighted to terms wrapping past bit 254 |
| 8 | coefficient_four, coefficient_single_q | Add the two pairs and delay the fifth term |
| 9 | coefficient_pipe | Add the fifth term, producing five unreduced radix-51 coefficients |
| 10 | carry_first[0] | Normalize limbs 0 and 1 and propagate their carries into limb 2 |
| 11 | carry_first[1] | Normalize limb 2 and propagate into limb 3 |
| 12 | carry_first[2] | Normalize limb 3 and propagate into limb 4 |
| 13 | carry_first[3] | Normalize limb 4 and fold its carry into limb 0 by multiplying it by 19 |
| 14 | carry_second[0] | Begin a second pass, normalizing limbs 0 and 1 after the wraparound fold |
| 15 | carry_second[1] | Normalize limb 2 |
| 16 | carry_second[2] | Normalize limb 3 |
| 17 | carry_second[3] | Normalize limb 4 and perform the final bounded wrap; packed output then conditionally subtracts FIELD_P combinationally |
valid_pipe[n] identifies the operation occupying stage n+1; reset clears
only validity because invalid data registers are ignored. The source marks the
product, reconstruction, coefficient, and carry additions with use_dsp.
Current matching-source U280 OOC synthesis attributes 523 DSP48E2s to each
instance. Eight active instances therefore consume 4,184 DSPs. The number 523
is an implementation result, not simply the 225 explicit multiplications.
§radix17_field_addsub_pipe
Source: crates/rhdl_ed25519_fast_field/rtl/radix17_field_addsub_pipe.sv.
Despite its retained name, this active module does not expose radix-17 limbs.
It performs canonical packed modular addition or subtraction and accepts one
operation each cycle. multicomb_mul_stream instantiates two copies for point
formula construction.
It has no overridable parameters. FIELD_P is the only local parameter.
§Ports
| Port | Direction | Meaning |
|---|---|---|
clk | input | Rising-edge clock |
rst | input | Synchronously clears all valid stages and the output register |
valid_in | input | Qualifies subtract, a, and b |
subtract | input | 0 selects a+b; 1 selects a-b modulo p |
a | input, 255 bits | First canonical operand |
b | input, 255 bits | Second canonical operand |
valid_out | output | Qualifies result after the registered pipeline |
result | output, 255 bits | Canonical modular sum or difference |
The five registered positions are:
| Stage | Function |
|---|---|
| 1 | Capture subtract, a, and b |
| 2 | Compute the low 128-bit add/subtract, retain its signed carry, and capture high operands |
| 3 | Compute the high 128-bit half with the low-half carry and concatenate the 256-bit raw result |
| 4 | Fold raw bit 255 back as 19 using 2^255 = 19 mod p |
| 5 | Conditionally subtract p and register the canonical 255-bit result |
Subtraction adds one copy of p before subtracting b, keeping the intermediate
nonnegative. Current matching-source OOC synthesis maps 12 DSP48E2s to each
active add/subtract lane. The point engine has two lanes, so they use 24 DSPs.
§radix17_field_mul_pipe
Source: crates/rhdl_ed25519_fast_field/rtl/radix17_field_mul_pipe.sv.
This is the predecessor field multiplier and is not instantiated by the current cached core. It remains useful as a historical implementation and differential reference. It accepts one operation per cycle but uses a much deeper systolic pipeline than the active radix-51 module.
It has no overridable parameters. Internal parameters are LIMBS = 15, the
17-bit LIMB_MASK, and FIELD_P.
Its ports clk, rst, valid_in, a, b, valid_out, and result have the
same meanings as the radix-51 multiplier. Internally it creates fifteen cyclic
dot-product rows of fifteen DSP-sized MAC cells, then performs two fifteen-limb
carry passes. Terms wrapping past bit 254 are multiplied by 19. The final packed
value is conditionally reduced by p.
The active source list should contain radix51_field_mul_pipe.sv, not this file.