blob: 1370f2c5bf4056c67bcf18aa92a0b1dac2531395 [file] [log] [blame]
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2021 Tamas Hubai
`default_nettype none
/*
Rotatable primitive logic cell
In upright position it implements:
- a buffer from left input to right & bottom outputs
- a NAND gate from right & bottom inputs to top output
- a D flip-flop from top input to left output
Any logic circuit can be built from this cell and its rotations arranged in a grid.
The cell can be rotated counterclockwise using the programming trigger at a clock edge,
affecting both input and output orientation.
A V
+-----|-----|-----+
| /==:=====/ |
| | | |
>====:==:=====+=======>
| | | | |
| D ~& | |
<====/ |\====:=======<
| | | |
| | | |
+-----|-----|-----+
A V
A few logic cells are designated as IO cells, these have their flip-flop
connected to an input and/or output pin.
*/
module logic_cell(
input clk, // clock
input rst_n, // reset, active low
input trig, // programming trigger
input in_t, // top input
input in_r, // right input
input in_b, // bottom input
input in_l, // left input
input in_i, // io cell input pin
input en_i, // is the input pin enabled
output out_t, // top output
output out_r, // right output
output out_b, // bottom output
output out_l, // left output
output out_o // io cell output pin
);
reg [1:0] rot; // current rotation
reg ff; // flip-flop status
wire inx_t, inx_r, inx_b, inx_l; // inputs after rotation
wire outx_t, outx_r, outx_b, outx_l; // outputs before rotation
wire inr_t, inr_r, inr_b, inr_l; // temporary values used during rotation
wire outr_t, outr_r, outr_b, outr_l;
// rotations
assign inr_t = rot[1] ? in_b : in_t;
assign inr_r = rot[1] ? in_l : in_r;
assign inr_b = rot[1] ? in_t : in_b;
assign inr_l = rot[1] ? in_r : in_l;
assign inx_t = rot[0] ? inr_l : inr_t;
assign inx_r = rot[0] ? inr_t : inr_r;
assign inx_b = rot[0] ? inr_r : inr_b;
assign inx_l = rot[0] ? inr_b : inr_l;
assign outr_t = rot[1] ? outx_b : outx_t;
assign outr_r = rot[1] ? outx_l : outx_r;
assign outr_b = rot[1] ? outx_t : outx_b;
assign outr_l = rot[1] ? outx_r : outx_l;
assign out_t = rot[0] ? outr_r : outr_t;
assign out_r = rot[0] ? outr_b : outr_r;
assign out_b = rot[0] ? outr_l : outr_b;
assign out_l = rot[0] ? outr_t : outr_l;
// outputs of the unrotated tile
assign outx_t = ~(inx_r & inx_b);
assign outx_r = inx_l;
assign outx_b = inx_l;
assign outx_l = ff;
assign out_o = ff;
always @ (posedge clk) begin
if (!rst_n) begin
rot <= 0;
ff <= 0;
end else begin
if (trig) rot <= rot + 1;
ff <= en_i ? in_i : inx_t;
end
end
endmodule
`default_nettype wire