
Posits are an alternative to IEEE 754 floating point, proposed by John Gustafson. They use a variable-length regime field that gives them tapered precision — more accuracy near 1.0 where you usually need it, less out at the extremes. An 8-bit posit with 2 exponent bits covers a surprisingly usable dynamic range while being dead simple to decode in hardware.
The really interesting bit is the quire — a fixed-point accumulator wide enough to hold exact products without rounding. This means you can do long dot products and the intermediate sum never loses a bit. You only round once at the very end when you convert back to a posit. For 8-bit posits this is practical to build in silicon, which is exactly what this project does.
If you want to read more: https://posithub.org/docs/Posits4.pdf
This is a posit multiply-accumulate (MAC) unit with a 32-bit quire register. It takes two 8-bit posit inputs (es=2), multiplies them, and accumulates the exact product into the quire. You can then read the quire back out as a posit8, or clear it for the next dot product.
The 32-bit quire uses Q16.16 fixed-point format, covering values from 2^-16 to 2^15. This is a compromise — a full-precision quire for posit(8,2) would need 128 bits, but 32 bits fits on a 1x1 tile while still covering the most practical range of posit8 values.
The multiply path reuses building blocks from PACoGen: https://github.com/manish-kj/PACoGen Which was part of this paper: https://ieeexplore.ieee.org/document/8731915
Simple ready/valid interfaces hooked up to the main FSM control data flow between the user and the unit. Input and output data registers are read/written via the uio_in and uio_out bidirectional ports. These ports are controlled via the ready/valid signals on ui_in and uo_out.
When the quire overflows, it clamps to its max representable value (preserving sign), the overflow flag (uo_out[4]) latches high, and posit output returns maxpos or -maxpos. The overflow flag stays latched until a CLEAR is issued.
Running make -B in the test directory will run the testbench.
The testbench checks basic MAC, READ, and CLEAR operations using known perfectly representable values (like 1.5 and 0.3125), verifies accumulation across multiple MACs, tests negative values and zero handling, and validates the ready/valid FSM states.
It also runs a dot product fuzz test — random-length sequences of MACs with random posit8 values — and compares the result against a float reference using the softposit python library.
Rounding errors at the edges of the quire's Q16.16 range are expected.
None
| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | INPUT_1_VALID | VALID_OUTPUT | IO_BIT0 |
| 1 | INPUT_2_VALID | ZERO_FLAG | IO_BIT1 |
| 2 | INSTRUCTION_VALID | INF_FLAG | IO_BIT2 |
| 3 | OPCODE_BIT0 | READY_OUT | IO_BIT3 |
| 4 | OPCODE_BIT1 | OVERFLOW_FLAG | IO_BIT4 |
| 5 | READY_IN | IO_BIT5 | |
| 6 | IO_BIT6 | ||
| 7 | IO_BIT7 |