A reconfigurable logic circuit built from identical copies of the tile above containing a NAND gate, a D flip-flop and a buffer, with each tile individually rotated or reflected as described by the FPGA configuration. Port of the original ROTFPGA from Caravel to TinyTapeout.
Porting the design required a 50-fold decrease in chip area which was achieved using a combination of cutting corners, heavy optimization and a few design changes. In particular:
Each tile can be configured in 8 possible orientations. Bits 0, 1 and 2 correspond to a diagonal, horizontal and vertical flip respectively. Any rotation or reflection can be described as a combination:
(The bottom row looks somewhat different, but we just rearranged the wires so that the inputs and outputs line up with the unmirrored tiles.)
Tiles are arranged in an 8×8 grid:
This is a 4×4 model of the tile grid, showing regular i/o as black and the scan chain as grey:
When the scan enable input is 0, the FPGA operates normally and each tile sets its flip-flop to the input it receives from one of the neighboring tiles according to its current rotation/reflection. When scan enable is 1, it sets the flip-flop to the value received through the scan chain instead. This allows us to set the initial state of each flip-flop and also to query their state later for debugging. With some extra machinery it also allows us to change the rotations/reflections.
When the 2-bit configuration input is is 01, each cell updates its vertical flip bit to the current value of its flip-flop. Similarly, for 10 it sets the horizontal flip and for 11 it sets the diagonal flip. When configuration is 00, all three flip bits are latched and the orientation doesn't change.
One can thus configure the FPGA by sending the sequence of all diagonal flip bits through the scan chain, then setting configuration to 11 and back to 00, then sending all horizontal flip bits, setting configuration to 10 and back to 00, and finally sending the vertical flip bits and setting configuration to 01 and back to 00.
Note that in order to save space the flip bits are stored in latches, not registers. Changing the configuration input from 00 to 11 or vice versa can cause a race condition where it is temporarily 01 or 10, overwriting the horizontal or vertical flip bits. Therefore one should configure the diagonal flips first.
The user design may intentionally or inadvertantly contain combinational loops such as ring oscillators. To help debug such designs, the chip has a loop breaker mechanism using a loop breaker enable input as well as a 2-bit loop breaker class input.
Tiles are assigned to loop breaker classes:
The loop breaker latches a tile output if and only if the following conditions are all met:
The loop breaker has the following properties:
Setting the active-low reset input to 0 has the following effect:
Input pins:
clk
provides a clock signal for the flip-flopsrst_n
is the active-low reset described aboveui_in[7:0]
are passed to the leftmost column of tiles as inputs from the leftOutput pins:
uo_out[7:0]
come from the rightwards output of the rightmost column of tilesBidirectional pins:
uio_in[0]
is the scan enable inputuio_in[1]
is the scan chain inputuio_in[3:2]
are the configuration input bitsuio_in[4]
is the loop breaker enable inputuio_in[6:5]
are the loop breaker class input bitsuio_out[7]
is the scan chain outputFollow the test suite the test
directory. It sets up the FPGA with the following two
configurations and runs a battery of tests on each.
Test configuration 1 used for upload, download, single-step and propagation tests:
Test configuration 2 used for testing the loop breaker with manual and automatic cycles:
None
# | Input | Output | Bidirectional |
---|---|---|---|
0 | tile(0,0) left in | tile(7,0) right out | _scan enable_ input |
1 | tile(0,1) left in | tile(7,1) right out | _scan chain_ input |
2 | tile(0,2) left in | tile(7,2) right out | _configuration_ input bit 0 |
3 | tile(0,3) left in | tile(7,3) right out | _configuration_ input bit 1 |
4 | tile(0,4) left in | tile(7,4) right out | _loop breaker enable_ input |
5 | tile(0,5) left in | tile(7,5) right out | _loop breaker class_ input bit 0 |
6 | tile(0,6) left in | tile(7,6) right out | _loop breaker class_ input bit 1 |
7 | tile(0,7) left in | tile(7,7) right out | _scan chain_ output |