You are browsing as a guest. Sign up (or log in) to start making projects!

JameswillWinsock

@JameswillWinsock

Joined June 6th, 2026

  • 3Devlogs
  • 1Projects
  • 0Ships
  • 0Votes
Open comments for this post

5h 19m 13s logged

YOU WANT A DEVLOG, YOU WANT ONE, HUH????? HERES A DEVLOG FOR YOU:

net_name: “spi_sck”
dont_route: true

FUCK YOU RENESAS FUCK YOU FUCKING PIECE OF SHIT FUCK YOU!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! YOUR PLACE AND ROUTE TOOL IS UTTER GARBAGE!!!!!!!!!!!!!!!!!!!!!!!!! WHY ARE YOU IGNORING USER NETS!!!!!!!!!!!!!!!!!!!!!!! STOP. OPTIMISING. THE. USER. CODE.

Edit: I figured what’s up
Aparently Renesas bought dialog semiconductor which bought silego, which made their greenpak line of fpgas, which was essentially scratch/Lego mindstorms for fpgas, and not meant to handle actual verilog, which when renesas made their forgefpga line they just reused greenpak

hence the mind boggling bugs

its like trying to run c in scratch

fuck my chud life

0
0
2
Open comments for this post

11h 38m 1s logged

Devlog #2: Building the NTT Core

Last time I ended on “okay, I’ll build a tiny NTT accelerator for Kyber on the Shrike Lite.” So that’s what I’ve been doing. No LEDs blinking yet since this whole devlog is me in a simulator, fighting my own garbage code.
But it’s progress, and it’s the kind of progress where I learned something every single time it broke.

Quick recap of the target: Kyber’s math runs mod q = 3329, and the whole NTT is 7 layers of 128 butterflies each (256 coefficients, standard Cooley-Tukey). On a chip with 1120 LUT5s and 32kb of BRAM, getting this to fit is a real damn sisyphean task. This sh*t is like tech from the 2000’s.

Started at the bottom: a 16-bit Han-Carlson adder, because I refuse to put ripple-carry anywhere near a critical path (We’re civilized men, writing civilized code, not animals).
Could I have done just a simple carry-look ahead? Yes, yes I could have. No, I don’t think I will. Fan out is getting crazy already, may as well use a PPA atp.
Built it as a proper parallel-prefix tree using 2D wire arrays in Verilog instead of copy-pasting carry logic by hand.

Found one non-bug worth noting for later: the top half of the adder (bits 8–15) isn’t a true prefix tree, it just ripples off the bit-7 carry. Works fine functionally, just means the top half is roughly double the gate depth of the bottom half. But, really, who cares. Not me. CBA.

The Montgomery reducer (a.k.a. the finite state machine from hell):

This is where it got ugly. Montgomery reduction is how you do modular multiplication without a hardware divider:

  1. multiply,
  2. then reduce using a precomputed constant instead of dividing by q every time.

I wrote it, simulated it, ran it cycle by cycle in EDA Playground because Icarus was being uncooperative (yeah, when does Icarus help anyways??? may as well switch to Quartus at this point), and found: add_a/add_b were registers, so they only update after the clock edge, but result <= add_sum was reading the sum from the previous cycle’s stale operands.
Every state that tried to compute-and-latch in one cycle was quietly latching garbage. Bit 0 of t_low was getting dropped somewhere in there too. Phenomenal. Simply beautiful.

Fixed it by making the adder operands purely combinational (mux on state), so add_sum always reflects the current state’s actual intent.
I thought that fixed it.

No, why would it fully fix it? Of course it would not. There was still a state-transition bug lurking. Very fun to debug.

The butterfly

This is the unit that actually does the NTT math: read two coefficients + a twiddle factor, multiply, reduce, add/subtract, write back. Spent a good chunk of time chasing what looked like a hang here, that turned out to be nothing but a testbench race condition - sampling signals in the same cycle they change, not an actual DUT problem. Frick me.

Bonus: figured out how BRAM actually gets wired
Dug through some existing Renesas example projects (shoutout to whoever wrote the FIFO-on-BRAM one, you saved my life)

Where it stands
Working (in simulation, against reference vectors):
Han-Carlson adder
Montgomery reducer
Modular ALU
Serial multiplier (shoutout to whoever made the Kyber spec sheet; you saved my ass because most of the time all I have to do is bit shift to “multiply”)
NTT butterfly
Address generator
Full 256-point forward NTT, top to bottom

Still to build:

  1. the inverse NTT (GS-DIF, reusing everything above),
  2. the pointwise multiplication step for after both polynomials are transformed,
  3. and the actual RP2040-FPGA SPI link tying it all to real hardware instead of a testbench.

atleast man the sim works, thats pretty damn good. im happy this works. next is getting it on the hardware and doing some actual cryptography with it.

0
0
3
Open comments for this post

1h 27m 50s logged

I was 15 minutes into a CTF crypto challenge, watching my CPU crawl through a polynomial multiplication, when it hit me: This is embarrassingly parallel. Why isn’t there hardware for this?

That night I fell down the FPGA rabbit hole. The idea was pretty great, a chip you can rewire into literally anything, like a custom RISC-V CPU, a cryptography accelerator. Where does that second idea take me? A method to execute a side-channel attack on cryptographic protocols using the FPGA, and all on a chip smaller than a credit card.

So I bought an FPGA on impulse, without researching properly. You can’t blame me, I was very excited.
I bought a Sipeed Tang Primer 20K core board. What I didn’t know: it’s just the RAM stick. The actual brains need a baseboard with power switches, reset buttons, and USB. Aaaaaaand I had none of that.
ba dum tss
What I did have: a Vicharak Shrike Lite (the green board in the photo). 1120 LUTs. An RP2040.
The Tang Primer has a JST debug connector. The Shrike Lite has JTAG pins. In theory, this was simple: connect the wires, run openFPGALoader, and go.

In practice:
The pinout I found online was confusing
The BL702 debug chip locks up after programming unless you power cycle the JST connector.
My multimeter showed 0V on TX, and no amount of head scratching made it work.

A week of “should just work” turned into a desk covered in jumper wires, a growing collection of frustrated terminal logs, and the Shrike Lite blinking an LED like it was mocking me.

I couldn’t get the Tang Primer running. But the Shrike Lite was working perfectly.
So I asked myself: what’s the smallest possible cryptography accelerator I could build on 1120 LUTs?

The answer: an NTT (Number Theoretic Transform) core for ML-KEM (Kyber). Why? Why not. Post-quantum cryptography is a hot topic of research. I figured I’d take a crack at it, see what makes it so hot.

Surely, after all of this, I have some lessons to take home, right? Those are:
FPGAs are not plug-and-play. The ecosystem assumes you bought the right baseboard.
1120 LUTs is tiny but not useless. You can’t fit full Kyber, but an NTT core fits comfortably. (I hope)
Documentation is scattered.
A working demo on cheap hardware beats a simulation on the PC. Much more satisfying to see a simple LED light up than stare at another waveform in GTKWave.

So what do I do next?
A working NTT accelerator on the Shrike Lite that processes Kyber polynomials with the RP2040 to FPGA and back bridge sending coefficients and getting transformed results.

The Bottom Line

I bought the wrong board. I didn’t have the right programmer. Nothing worked for weeks.
But I learned more from breaking things than I ever would from following a tutorial.

0
0
3

Followers

Loading…