Pipeline the GF16 matmul (9.97 → 36.36 MHz, bit-exact) and make requests start themselves - #633
Merged
Conversation
Withdrawing the old frequency claim left the core with an honest number and a
problem: 9.97 MHz post-route with a single register stage. Every comparable
vendor core reaches 100 MHz or more, and does it by pipelining, so a core at
10 MHz cannot be sold or compared.
The module's own structure hands over the stage boundaries — four multiplies,
then two adds, then the final add — so gf16_dot4_p cuts there. Latency three
cycles, one result per cycle, and the arithmetic is untouched: the same gf16_mul
and gf16_add instances with registers between them.
Measured post-route on an XC7A200T with nextpnr-xilinx, hard multipliers off:
gf16_dot4 combinational 18.83 MHz
gf16_dot4_p 3 stages 58.49 MHz 3.1x
gf16_matmul4x4_reg 1 register stage 9.97 MHz
gf16_matmul4x4_p 3 stages 36.36 MHz 3.6x
Equivalence is proven rather than assumed, which is the whole point of the method
this repository sells: tb_equiv.v compares the pipelined dot product against the
original delayed by three cycles across 59,993 cycles of random and special-case
operands — zero mismatches, including the format's zero, infinity-like, NaN-like
and unity encodings.
Where the floor now is, measured rather than guessed: the critical path runs from
the second-stage register through the final gf16_add, so one float add is about
17 ns. The clean cut inside it is between the mantissa alignment and the add.
Left undone deliberately — that is a rewrite of a 192-line float adder, and a
subtly wrong adder is worse than a slow one. The equivalence harness is ready
for whoever does it.
The timing harnesses put the LFSR and the XOR reduction outside the measured
path. That matters for a specific reason: constants on the inputs let synthesis
fold the whole matmul away, which is exactly how the phantom 323 MHz arose.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"Email me" is the step most people never take, and it puts the owner in the loop before there is anything to be in the loop about. A request now runs on its own. An issue form asks the three things that actually matter — where the RTL is, the top module, and what "correct" means for it. The third field is the important one and the form says why: the reference model is written from that description rather than from the code, because a model derived from the RTL agrees with the RTL, including where it is wrong. A workflow then acknowledges, clones the design, and runs the checks that need no human: elaboration, a latch check, generic synthesis with cell counts, and a count of clocked blocks — the last so a combinational design is told plainly that no frequency can belong to it. Results are posted into the issue with every command visible, so the requester can re-run all of it. What it does not do is claim to do the whole job. The comment it posts says outright that the reference model, the per-stage vectors and the board replay are still to come and cannot be automated. Overstating that would be the fastest way to lose the only thing being sold. Two things kept deliberately narrow: only a plain https://github.com/owner/repo URL is cloned — anything else is left for a human rather than guessed at — and the URL reaches the shell through the environment rather than being interpolated into it, so an issue body cannot inject a command. The service page now leads with this instead of a mailto, with the four steps and their timings named, and the same page keeps the address for anyone who would rather write. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
github-actions Bot
added a commit
that referenced
this pull request
Aug 8, 2026
Pipeline the GF16 matmul (9.97 → 36.36 MHz, bit-exact) and make requests start themselves (#633) * Pipeline the GF16 matmul: 9.97 MHz becomes 36.36 MHz, bit-exact Withdrawing the old frequency claim left the core with an honest number and a problem: 9.97 MHz post-route with a single register stage. Every comparable vendor core reaches 100 MHz or more, and does it by pipelining, so a core at 10 MHz cannot be sold or compared. The module's own structure hands over the stage boundaries — four multiplies, then two adds, then the final add — so gf16_dot4_p cuts there. Latency three cycles, one result per cycle, and the arithmetic is untouched: the same gf16_mul and gf16_add instances with registers between them. Measured post-route on an XC7A200T with nextpnr-xilinx, hard multipliers off: gf16_dot4 combinational 18.83 MHz gf16_dot4_p 3 stages 58.49 MHz 3.1x gf16_matmul4x4_reg 1 register stage 9.97 MHz gf16_matmul4x4_p 3 stages 36.36 MHz 3.6x Equivalence is proven rather than assumed, which is the whole point of the method this repository sells: tb_equiv.v compares the pipelined dot product against the original delayed by three cycles across 59,993 cycles of random and special-case operands — zero mismatches, including the format's zero, infinity-like, NaN-like and unity encodings. Where the floor now is, measured rather than guessed: the critical path runs from the second-stage register through the final gf16_add, so one float add is about 17 ns. The clean cut inside it is between the mantissa alignment and the add. Left undone deliberately — that is a rewrite of a 192-line float adder, and a subtly wrong adder is worse than a slow one. The equivalence harness is ready for whoever does it. The timing harnesses put the LFSR and the XOR reduction outside the measured path. That matters for a specific reason: constants on the inputs let synthesis fold the whole matmul away, which is exactly how the phantom 323 MHz arose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * A request that starts itself, with no correspondence "Email me" is the step most people never take, and it puts the owner in the loop before there is anything to be in the loop about. A request now runs on its own. An issue form asks the three things that actually matter — where the RTL is, the top module, and what "correct" means for it. The third field is the important one and the form says why: the reference model is written from that description rather than from the code, because a model derived from the RTL agrees with the RTL, including where it is wrong. A workflow then acknowledges, clones the design, and runs the checks that need no human: elaboration, a latch check, generic synthesis with cell counts, and a count of clocked blocks — the last so a combinational design is told plainly that no frequency can belong to it. Results are posted into the issue with every command visible, so the requester can re-run all of it. What it does not do is claim to do the whole job. The comment it posts says outright that the reference model, the per-stage vectors and the board replay are still to come and cannot be automated. Overstating that would be the fastest way to lose the only thing being sold. Two things kept deliberately narrow: only a plain https://github.com/owner/repo URL is cloned — anything else is left for a human rather than guessed at — and the URL reaches the shell through the environment rather than being interpolated into it, so an issue body cannot inject a command. The service page now leads with this instead of a mailto, with the four steps and their timings named, and the same page keeps the address for anyone who would rather write. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Dmitrii Vasilev <admin@t27.ai> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The core has a publishable number again
Withdrawing the old claim left an honest figure and a problem: 9.97 MHz post-route with a single register stage. Comparable vendor cores reach 100 MHz+, and do it by pipelining — a core at 10 MHz cannot be sold or compared.
The module's own structure hands over the boundaries (four multiplies → two adds → final add), so
gf16_dot4_pcuts there. Latency 3 cycles, one result per cycle, arithmetic untouched.Measured post-route on an XC7A200T,
nextpnr-xilinx, hard multipliers off:gf16_dot4combinationalgf16_dot4_p3 stagesgf16_matmul4x4_reg1 stagegf16_matmul4x4_p3 stagesEquivalence proven, not assumed — the whole point of the method this repo sells.
tb_equiv.vcompares the pipelined dot product against the original delayed by three cycles: 59,993 cycles, zero mismatches, including the format's zero, infinity-like, NaN-like and unity encodings.Where the floor is, measured: the critical path runs from the second-stage register through the final
gf16_add— one float add ≈ 17 ns. The clean cut inside it is between mantissa alignment and the add. Left undone deliberately: that is a rewrite of a 192-line float adder, and a subtly wrong adder is worse than a slow one. The equivalence harness is ready for whoever does it.The harnesses keep the LFSR and XOR reduction outside the measured path — constants on the inputs let synthesis fold the matmul away, which is exactly how the phantom 323 MHz arose.
Requests start themselves
"Email me" is the step most people never take. An issue form asks the three things that matter, then a workflow acknowledges, clones, and runs what needs no human: elaboration, latch check, synthesis with cell counts, and a count of clocked blocks — so a combinational design is told plainly that no frequency can belong to it. Every command is visible in the comment.
It does not claim to do the whole job: the posted comment says outright that the reference model, per-stage vectors and board replay are still to come and cannot be automated.
Kept narrow on purpose: only a plain
https://github.com/owner/repoURL is cloned, and it reaches the shell through the environment rather than interpolated into it, so an issue body cannot inject a command.🤖 Generated with Claude Code