Expand description
Projective Edwards point compression and paired batch inversion.
§Edwards Point Compression
Ed25519 compression converts a projective point (X:Y:Z) to affine
x=X/Z, y=Y/Z, then emits the 255-bit canonical y value with the parity of
x in bit 255. The active backend compresses two points with one inversion:
u = 1 / (Za * Zr)
1 / Za = u * Zr
1 / Zr = u * ZaThe inversion is a fixed addition chain for exponent p-2. No data-dependent
loop or early exit is used.
§point_compress_pair_stream
Source: crates/rhdl_ed25519_fast_point_codec/rtl/point_compress_pair_stream.sv.
One instance retains several point pairs and interleaves their multiplication
steps through one II=1 radix51_field_mul_pipe.
§Parameters
| Parameter | Default | Active per-way value | Meaning |
|---|---|---|---|
TAG_BITS | 16 | 14 for the current signer pair tag | Metadata width |
CONTEXTS | 12 | 4 | Number of pair-compression contexts retained by one instance |
CONTEXT_BITS | 4 | 2 | Context index width; active settings match log2(CONTEXTS) |
FIELD_LATENCY | 17 | 17 | Context/tag delay matching the field multiplier |
The three local states are ST_FREE for allocation, ST_READY for a context
eligible to issue its next multiplication, and ST_WAIT while that result is
in flight.
§Ports
| Port | Direction | Meaning |
|---|---|---|
clk, rst | input | Clock and synchronous reset |
valid_in | input | Qualifies both projective points and tag_in |
ready_in | output | At least one pair context is free |
a_x_in, a_y_in, a_z_in | input, 255 bits each | First projective point, conventionally public-key point A during legacy use |
r_x_in, r_y_in, r_z_in | input, 255 bits each | Second projective point, conventionally nonce point R |
tag_in | input, TAG_BITS | Opaque pair metadata |
valid_out | output | One-cycle pulse when both encodings are ready |
tag_out | output, TAG_BITS | Delayed pair tag |
a_compressed_out | output, 256 bits | {parity(Xa/Za), Ya/Za} |
r_compressed_out | output, 256 bits | {parity(Xr/Zr), Yr/Zr} |
§Scheduler and retained state
Allocation chooses the first ST_FREE context. The issue scheduler advances by
context pairs and toggles issue_pair_prefer_odd, giving both contexts in a
pair an opportunity before moving on. context_pipe and tag_valid_pipe track
the 17-position field result. Per context, step, squares_left, and
after_square control the fixed exponentiation sequence; temp0 through
temp2 hold named powers.
§Addition-chain steps
The first request multiplies Za*Zr and labels the completion as step 31. Steps
0 through 14 then compute its inverse with a standard Curve25519 fixed chain:
| Completion step | Next operation or retained value |
|---|---|
| 31 | Save Za*Zr as base; square it |
| 0 | Save square as temp0; square again |
| 1 | Square again |
| 2 | Multiply by base |
| 3 | Save in temp1; multiply by temp0 |
| 4 | Save in temp0; square |
| 5 | Multiply by temp1 |
| 6 | Save in temp1; schedule 5 squarings, then multiply by temp1 |
| 7 | Save in temp1; schedule 10 squarings, then multiply by temp1 |
| 8 | Save in temp2; schedule 20 squarings, then multiply by temp2 |
| 9 | Schedule 10 squarings, then multiply by temp1 |
| 10 | Save in temp2; schedule 50 squarings, then multiply by temp2 |
| 11 | Save in temp1; schedule 100 squarings, then multiply by temp1 |
| 12 | Schedule 50 squarings, then multiply by temp2 |
| 13 | Schedule 5 squarings, then multiply by temp0 |
| 14 | The result is 1/(Za*Zr); begin affine recovery |
Affine recovery uses steps 15 through 20:
| Step | Operation and use |
|---|---|
| 15 | Multiply inverse product by Zr to obtain 1/Za |
| 16 | Multiply inverse product by Za to obtain 1/Zr |
| 17 | Multiply Xa by 1/Za; retain bit 0 as affine_a_sign |
| 18 | Multiply Ya by 1/Za; retain affine ya in base |
| 19 | Multiply Xr by 1/Zr; retain bit 0 as affine_r_sign |
| 20/default completion | Multiply Yr by 1/Zr, assemble both encodings, pulse valid, and free the context |
The state schedule is fixed for every input point pair.
§point_compress_pair_parallel4
Source: crates/rhdl_ed25519_fast_point_codec/rtl/point_compress_pair_stream.sv.
The active signer instantiates this wrapper. It creates four physical
point_compress_pair_stream ways, each configured for four contexts and one
field multiplier. Thus 16 point pairs can be in flight without one global
16-way operand mux.
§Parameters
| Parameter | Default | Meaning |
|---|---|---|
TAG_BITS | 16 | Pair metadata width passed unchanged into every way |
FIELD_LATENCY | 17 | Field multiplier return delay passed to every way |
LANES | 4 | Number of independent pair-compression ways |
The local constant QUEUE_DEPTH=4 fixes each way’s result FIFO depth. The
active signer retains the four-lane default.
§Ports
The wrapper has the same clk, rst, valid_in, ready_in, two point input
triples, tag_in, valid_out, tag_out, and two compressed outputs as
point_compress_pair_stream. ready_in means at least one way is ready.
input_rr distributes accepted pairs round-robin among ready ways. Each way can
finish several resident inversion chains close together, so its outputs enter a
four-entry local queue. output_rr drains nonempty queues round-robin and emits
at most one pair per cycle. A simulation-only fatal check detects queue overflow;
there is no output backpressure port.
Current matching-source OOC synthesis attributes 84,295 LUTs, 67,702
registers, no block RAM, and 2,092 DSP48E2s to the four-way codec. The DSP total
is exactly four 523-DSP field multipliers. The integrated signer profile issues
and completes 257 pair requests while processing one key point and 512 nonce
points. A focused throughput test currently overrides LANES=6 and reports
223.659 cycles/pair for that six-lane experiment; it is not the service interval
of this active four-lane wrapper.
§Legacy point_compress_stream
Source: crates/rhdl_ed25519_fast_point_codec/rtl/point_compress_stream.sv.
This predecessor compresses one point per context rather than sharing one inversion across two points. It is not instantiated by the active core.
§Parameters
| Parameter | Default | Meaning |
|---|---|---|
TAG_BITS | 16 | Metadata width |
CONTEXTS | 16 | Number of interleaved inversion contexts |
CONTEXT_BITS | 4 | Context index width |
FIELD_LATENCY | 16 | Multiplier result/tag delay |
§Ports
Inputs are clk, rst, valid_in, projective x_in, y_in, z_in, and
tag_in. Outputs are ready_in, valid_out, tag_out, and 256-bit
compressed_out.
States ST_FREE, ST_CHAIN_READY, and ST_CHAIN_WAIT manage inversion;
ST_AFFINE_READY and ST_AFFINE_WAIT issue X/Z and Y/Z. It runs the same
steps 0 through 14 over z, then schedules two affine products. The first
result supplies the sign bit; the second supplies affine y and completes
compressed_out = {x_parity,y}.