Projects

KR260 FPGA ALU

An 8-bit ALU in SystemVerilog, integrated with a Kria KR260 and controlled from Python on Linux through AXI GPIO.

  • Hardware
  • Software

An 8-bit ALU implemented in SystemVerilog runs on my Kria KR260. The ALU sits behind AXI GPIO, and a Python script on the board's Linux side drives it and checks every result.

When
September 2026
Where
Independent project
Role
RTL design, board setup, and testing
Operations
ADD, SUB, AND, OR, XOR, with carry and zero flags
On the board
All 524,288 operand and op-code combinations passed
Timing
Met the 100 MHz interface clock in Vivado
Tools
SystemVerilog, Vivado, Kria KR260, AXI GPIO, Python, Linux

Try the ALU

Set two 8-bit operands and an op code. Addition and subtraction share one ripple-carry adder. To subtract, the ALU inverts B and feeds a 1 into the carry input, so A − B is computed as A + (inverted B) + 1. The carry row shows how each column's carry moves left.

Operand A
0xC8, signed -56
Operand B
0x64, signed 100
Operation
Carry in10000000A11001000B+01100100Result100101100
Result
44 0x2C, signed 44
Carry flag
1
Zero flag
0

200 + 100 = 300, which needs nine bits. The ALU keeps the low eight bits (44) and sets carry.

What Python sees through AXI GPIO

Written
0x064C8 op in bits 18 to 16, B in 15 to 8, A in 7 to 0
Read back
0x12C zero in bit 9, carry in bit 8, result in 7 to 0, plus a fixed signature word
Browser model of the ALU's logic, written for this site from the design's behaviour. It does not run on the FPGA. Op codes 101 to 111 are unused and return 0. Binary in this view: A is 11001000, B is 01100100.

The datapath

The ALU is built up in layers, each a small SystemVerilog module:

  1. A one-bit full adder.
  2. An 8-bit ripple-carry adder made of eight full adders, with each carry feeding the next bit.
  3. An add/subtract unit. For subtraction it inverts B and sets the carry-in to 1, so A − B becomes A + (inverted B) + 1 and the same adder does both jobs.
  4. The ALU, which picks the result from a 3-bit op code.
Op code Operation Carry flag
000 ADD Set when the sum needs a ninth bit
001 SUB Set when no borrow was needed
010 AND Always clear
011 OR Always clear
100 XOR Always clear
101 to 111 Unused, result is 0 Always clear

The zero flag is set whenever the result is 0. The ALU is purely combinational, with no clock or internal state.

From Linux to the fabric

The KR260 pairs ARM cores running Linux with FPGA fabric. A small adapter connects the ALU to an AXI GPIO block:

  • Software writes one word: A in bits 7 to 0, B in bits 15 to 8, and the op code in bits 18 to 16.
  • Software reads one word back: the result in bits 7 to 0, carry in bit 8, zero in bit 9, and a fixed signature in the upper bits so the test script can reject a design with a different register layout.

A Python script on the board’s Linux side reaches those registers through Linux UIO. The board’s DFX Manager loads the ALU design and can restore the previous one afterward.

Verification

The simulation testbench and the on-board script both check every combination of the two 8-bit operands across all eight op-code values against a reference model. That is 256 × 256 × 8 = 524,288 cases, including the three unused codes, which must return 0. All 524,288 cases passed on the physical KR260.

The routed Vivado design met timing on the 100 MHz clock that drives the AXI interface, with positive setup and hold slack. Because the ALU is combinational between the GPIO registers, that is a statement about the interface, not a clock rate for the ALU itself.