Expand description
Source manifests, simulation entry points, synthesis scripts, and evidence rules.
§Building, Testing, And Verifying The SystemVerilog
This chapter explains how source files become a simulator executable, a Vivado out-of-context design, or a packaged Vitis kernel. It also defines what each kind of evidence proves. Read the overview first if the active and predecessor source sets are not yet familiar.
§Active Elaboration Manifest
The current fixed-64 cryptographic top is fast64_cached_sign_core. Its active
source closure is:
| Layer | Files elaborated |
|---|---|
| Field | radix51_field_mul_pipe.sv, radix17_field_addsub_pipe.sv |
| Fixed base | multicomb_lookup_rom.sv, multicomb_mul_stream.sv |
| SHA-512 | sha512_compress_3phase.sv, sha512_compress_pool4.sv |
| Point codec | point_compress_pair_stream.sv |
| Scalar | scalar_arithmetic_dsp_pipe.sv |
| Signing top | fast64_cached_sign_core.sv |
scalar_arithmetic_2phase.sv is also supplied by the packaging and synthesis
scripts for compatibility with older top-level configurations. No module in
the current cached signer instantiates it, so Vivado removes it during
elaboration. Source presence in a command is not proof that hardware exists;
the instantiated hierarchy and post-synthesis utilization report are the
authoritative answers.
The optional deployment shell adds
bench/rhdl/rtl/fast64_cached_sign_io_kernel.sv. The compute-only benchmark
instead adds fast64_cached_sign_benchmark_engine.sv and
fast64_benchmark_kernel.sv.
The active initialized memories are:
crates/rhdl_ed25519_fast_fixed_base/assets/multicomb_t8_n4_s8/
comb_scan_bank00.mem
comb_scan_bank01.mem
comb_scan_bank02.mem
comb_scan_bank03.memVivado must run with that asset directory available because the scan-bank
instances pass these names to $readmemh or Xilinx memory initialization.
Moving a build without the memory images can produce an elaboration failure or,
worse in a permissive flow, an uninitialized table.
§Rust Crates Versus Synthesized RTL
The fast Rust crates serve four purposes:
- They expose stable Rust descriptions and black-box boundaries.
- They generate deterministic test vectors and Dalek-derived expected values.
- They launch Icarus or Verilator testbenches with an explicit SV source list.
- They retain scheduler and arithmetic models useful for regression tests.
Rust code in these crates is not automatically translated into the optimized datapath. The files listed above are handwritten SystemVerilog and are passed directly to the HDL tool. The general compatibility backend is the portion implemented as RHDL synchronous devices and lowered through RHDL.
§Focused Simulation Tests
Run one Cargo job on memory-constrained systems. These tests cover the active blocks from leaves upward:
| Test source | What it checks |
|---|---|
crates/rhdl_ed25519_fast_field/tests/rtl_radix51_pipeline.rs | Radix-51 products, canonical reduction, latency, and consecutive valid inputs |
crates/rhdl_ed25519_fast_field/tests/rtl_addsub_pipeline.rs | Modular add/subtract results and pipeline ordering |
crates/rhdl_ed25519_fast_sha512/tests/rtl_compress.rs | SHA-512 compression states against a software oracle |
crates/rhdl_ed25519_fast_scalar/tests/rtl_scalar_dsp_pipeline.rs | Wide reduction and multiply-add against integer reference arithmetic |
crates/rhdl_ed25519_fast_fixed_base/tests/rtl_multicomb_lookup.rs | Table image contents, signed selection, and scan behavior |
crates/rhdl_ed25519_fast_fixed_base/tests/rtl_multicomb_mul.rs | Projective fixed-base products against Dalek points |
crates/rhdl_ed25519_fast_point_codec/tests/rtl_pair_throughput.rs | Paired inversion/compression correctness for an explicit six-lane experiment; it does not measure the active four-lane wrapper |
crates/rhdl_ed25519_fast_sign/tests/rtl_fast64_cached_sign.rs | Key expansion and complete signatures against Dalek |
crates/rhdl_ed25519_fast_sign/tests/rtl_fast64_cached_benchmark.rs | Saturated 512-message service interval and aggregate checksum |
bench/rhdl/tb/fast64_cached_sign_io_kernel_tb.sv | AXI control, exact memory beats, odd batches, and signature retirement |
For example:
cargo test -p rhdl_ed25519_fast_field --test rtl_radix51_pipeline -j 1
cargo test -p rhdl_ed25519_fast_scalar --test rtl_scalar_dsp_pipeline -j 1
cargo test -p rhdl_ed25519_fast_fixed_base --test rtl_multicomb_mul -j 1
cargo test -p rhdl_ed25519_fast_point_codec --test rtl_pair_throughput -j 1
cargo test -p rhdl_ed25519_fast_sign --test rtl_fast64_cached_sign -j 1
cargo test -p rhdl_ed25519_fast_sign \
--test rtl_fast64_cached_benchmark -j 1 -- --nocaptureThe Rust tests construct temporary testbenches and compiler outputs outside the tracked source tree. Inspect the test source when debugging because it is the exact compile manifest: SystemVerilog has no hidden Cargo linker that discovers modules automatically.
§Documentation Coverage Test
This documentation crate contains a structural guard:
cargo test -p ed25519_fast_sv_docs -j 1It recursively finds every .sv file in the six fast RTL directories and
every fast64_*.sv file in bench/rhdl/rtl. It then checks that:
- every source filename is named in this manual;
- every declared
moduleis named; - every module
parameteris named; and - every
function automatichelper is named.
The test cannot judge explanation quality, prove that grouped AXI port tables are complete, or infer which modules elaborate. A reviewer must still compare the active hierarchy, parameter overrides, ports, state machines, and memory assets with the source.
§Vivado Out-Of-Context Synthesis
tools/vivado/synth_fast64_cached_sign_ooc.tcl reads the active core source,
changes into the memory-asset directory, elaborates
fast64_cached_sign_core, creates the requested clock, and writes:
| Artifact | Meaning |
|---|---|
post_synth.dcp | Synthesized design checkpoint |
utilization.rpt | Flat resource totals |
utilization_hierarchical.rpt | Resource attribution by instance |
ram_utilization.rpt | Inferred and primitive memory details |
timing_summary.rpt | Constraint and setup/hold summary |
critical_paths.rpt | Twenty worst maximum-delay paths |
summary.txt | Part, target frequency/period, and worst setup slack |
The script sets general.maxThreads to two to reduce peak memory use. It runs
synth_design -mode out_of_context and opt_design; it does not place or
route the design. A positive OOC WNS says that the estimated synthesized path
meets the requested period at this stage. It is not a routed kernel timing
result and is not an FPGA throughput measurement.
tools/vivado/synth_fast64_io_kernel_ooc.tcl performs the corresponding check
with fast64_cached_sign_io_kernel as top. Use the shell report for a claim
about the deployable AXI kernel; a core-only clock does not include shell
control, data movers, or result buffering.
The current matching-source evidence is kept under:
reports/generated/
u280_fast64_cached_singlepoint_dspacc_norm2_ooc200_20260714/For xcu280-fsvh2892-2L-e at a 200 MHz, 5.000 ns request, the optimized OOC
report has WNS +0.520 ns. The worst path is 4.462 ns from
muladd/reducer/biased_reg[25] to
muladd/reducer/reduced1_reg[247], with 14 reported logic levels and only
10.959% estimated routing delay. Resource totals are 202,344 LUTs, 219,803
FFs, 356 RAMB36s, 6,745 DSP48E2s, and no URAM.
This run does not establish 250 MHz: 250 MHz allows 4.000 ns, shorter than the reported 4.462 ns data path. It also has no placement, no routing, and no matching-source AXI shell result. The maximum-delay report warns that 788 inputs and 786 outputs have no I/O delays and does not analyze hold timing. Timing claims must always include the top module, part, requested clock, implementation stage, report path, and source revision.
§Physical Implementation Evidence
Placement and routing have occurred, but only for the preceding
builder-pipeline source. FAST64_PACKAGE_SHA256SUMS fails against the current
working tree for seven active RTL files and the host source, so these reports
must retain the predecessor label.
The predecessor standalone core is fully routed. At 200 MHz it misses setup by
0.007 ns; rechecking the same checkpoint at 199 MHz gives WNS +0.018 ns, TNS
zero, and no setup failures. All 569,193 routable nets are routed with no route
errors. The routed core uses 248,852 LUTs, 237,472 FFs, 356 RAMB36s, 3,376 DSPs,
and no URAM. Its reports are:
reports/generated/u280_fast64_cached_quadmul_ctx16_codec4x4_addsub2_mul2z_builderpipe_route200_20260713/
reports/generated/u280_fast64_builderpipe_route199_timing_20260713/The predecessor was also linked inside the full U280 Vitis platform. Synthesis,
placement, and routing completed, but the 199 MHz kernel clock finished with
WNS -1.836 ns, TNS -91,954.969 ns, and 137,269 failing setup endpoints.
The worst 6.404 ns path runs from point context state to a field-multiplier DSP
input and is 89% routing delay. Hold timing passes with WHS +0.006 ns. Vitis
stops before bitstream and xclbin generation because setup timing fails:
reports/generated/u280_fast64_io_reference_link199_timing_failed_20260714/The full routed device uses 381,802 LUTs, 419,571 FFs, 558 RAMB36s, six RAMB18s, 3,380 DSPs, and no URAM, including the fixed U280 platform. Subtracting the report’s fixed column leaves 274,173 LUTs, 283,485 FFs, 365 RAMB36 plus one RAMB18, and 3,376 DSPs in the dynamic region; that difference includes AXI and interconnect and is not kernel-only utilization. The only valid conclusion is that this predecessor was physically routable but did not close full-platform timing. Current-source placement remains open.
§Vitis RTL Kernel Packaging
bench/rhdl/package_fast64_io_kernel.tcl packages the SV closure as an RTL
kernel named fast64_cached_sign_io_kernel. It:
- Creates a temporary Vivado project for
xcu280-fsvh2892-2L-e. - Adds the active RTL and four scan-bank memory images.
- marks the AXI-Lite control and four AXI memory buses as clocked by
ap_clk. - Creates the control-register metadata used by XRT.
- Declares the XPM libraries used for memories and FIFOs.
- Checks IP integrity and emits an
.xokernel object.
The lowercase m_axi_gmem* names in IP metadata correspond to the uppercase
SystemVerilog signal prefixes documented in
shells and benchmarks. The link configuration
then assigns those logical ports to U280 memory banks. Packaging proves that
the source is structurally acceptable as a Vitis RTL kernel; only linking,
routing, programming the board, and validating every returned signature prove
the deployed design.
§Reading Cycle Evidence Correctly
The current matching cached benchmark reports:
PASS cached_benchmark=512 cycles=119459 key_load=8517 first=18020 span=101438There are 511 completion intervals between 512 outputs, so the sustained interval is:
101,438 / 511 = 198.508806 cycles/signatureThe complete finite batch, including key load and fill/drain, averages:
119,459 / 512 = 233.318359 cycles/signatureCycles become signatures per second only after selecting a justified clock.
For example, the current core’s met 200 MHz OOC target projects
200,000,000 / 198.508806 = 1,007,512 sustained signatures/s. The finite batch
projects to 857,198 signatures/s. These remain core simulation plus OOC
projections until a matching shell is routed, an xclbin is generated, and the
U280 validates every result.
§Safe Change Workflow
When modifying an SV module:
- Identify whether it is active, predecessor, shell, benchmark, or resource probe code in the overview.
- Update every caller’s parameter and port connection explicitly.
- Preserve ready/valid semantics and opaque tags through added pipeline stages.
- For lookup changes, inspect addresses and enables as well as values; secret digits must not alter memory access patterns.
- Run the leaf arithmetic test, then its parent engine test, then cached-sign and saturated benchmark tests.
- Run the real-core AXI test if ports, backpressure, ordering, or completion behavior changed.
- Regenerate matching-source Vivado reports before updating timing or area numbers.
- Update this manual and run its coverage test before publishing rustdoc.
Do not infer correctness from synthesis success, timing from RTL simulation, throughput from latency alone, or current performance from a predecessor xclbin. Each claim needs the evidence type that directly measures it.