Add source files
diff --git a/.gitignore b/.gitignore index f4e486c..b2a927b 100644 --- a/.gitignore +++ b/.gitignore
@@ -1 +1,2 @@ -precheck_results \ No newline at end of file +precheck_results +*~
diff --git a/openlane/user_project/config.tcl b/openlane/user_project/config.tcl index 7ac305c..82334ea 100755 --- a/openlane/user_project/config.tcl +++ b/openlane/user_project/config.tcl
@@ -19,21 +19,27 @@ set ::env(VERILOG_FILES) "\ $::env(CARAVEL_ROOT)/verilog/rtl/defines.v \ + $script_dir/../../verilog/rtl/defines.v \ + $script_dir/../../verilog/rtl/logic_cell.v \ + $script_dir/../../verilog/rtl/logic_grid.v \ $script_dir/../../verilog/rtl/user_project.v" set ::env(DESIGN_IS_CORE) 0 -set ::env(CLOCK_PORT) "wb_clk_i" -set ::env(CLOCK_NET) "counter.clk" +set ::env(SYNTH_NO_FLAT) 1 + +set ::env(CLOCK_PORT) "" +set ::env(CLOCK_NET) "wb_clk_i" set ::env(CLOCK_PERIOD) "10" +#set ::env(BASE_SDC_FILE) "$::env(DESIGN_DIR)/base.sdc" set ::env(FP_SIZING) absolute -set ::env(DIE_AREA) "0 0 900 600" +set ::env(DIE_AREA) "0 0 1200 1200" set ::env(FP_PIN_ORDER_CFG) $script_dir/pin_order.cfg set ::env(PL_BASIC_PLACEMENT) 1 -set ::env(PL_TARGET_DENSITY) 0.05 +set ::env(PL_TARGET_DENSITY) 0.02 # Maximum layer used for routing is metal 4. # This is because this macro will be inserted in a top level (user_project_wrapper)
diff --git a/openlane/user_project_wrapper/config.tcl b/openlane/user_project_wrapper/config.tcl index 36c664e..39f574b 100755 --- a/openlane/user_project_wrapper/config.tcl +++ b/openlane/user_project_wrapper/config.tcl
@@ -51,6 +51,9 @@ ### Black-box verilog and views set ::env(VERILOG_FILES_BLACKBOX) "\ $::env(CARAVEL_ROOT)/verilog/rtl/defines.v \ + $script_dir/../../verilog/rtl/defines.v \ + $script_dir/../../verilog/rtl/logic_cell.v \ + $script_dir/../../verilog/rtl/logic_grid.v \ $script_dir/../../verilog/rtl/user_project.v" set ::env(EXTRA_LEFS) "\
diff --git a/verilog/rtl/defines.v b/verilog/rtl/defines.v new file mode 100644 index 0000000..699b764 --- /dev/null +++ b/verilog/rtl/defines.v
@@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2021 Tamas Hubai + +`default_nettype none + +// width of cell grid +`define WIDTH 8 + +// height of cell grid +`define HEIGHT 8 + +// size of width/height field, i.e. clog2(max(WIDTH, HEIGHT)) +`define ADDRSIZE 3 + +// number of input pins = number of output pins +`define IOPAIRS 8 + +// x coordinate of input pins +`define X_IN 0 + +// x coordinate of output pins +`define X_OUT (`WIDTH-1) + +// y coordinate of first input/output pin pair +`define Y_FIRST 0 + +// y coordinate difference of successive input/output pin pairs +`define Y_STEP 1 + +`default_nettype wire +
diff --git a/verilog/rtl/logic_cell.v b/verilog/rtl/logic_cell.v new file mode 100644 index 0000000..1370f2c --- /dev/null +++ b/verilog/rtl/logic_cell.v
@@ -0,0 +1,104 @@ +// 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 +
diff --git a/verilog/rtl/logic_grid.v b/verilog/rtl/logic_grid.v new file mode 100644 index 0000000..3d160c3 --- /dev/null +++ b/verilog/rtl/logic_grid.v
@@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2021 Tamas Hubai + +`default_nettype none + +module logic_grid ( + input clk, + input rst_n, + input trig_en, + input [`ADDRSIZE-1:0] trig_x, + input [`ADDRSIZE-1:0] trig_y, + input [`IOPAIRS-1:0] in_pins, + output [`IOPAIRS-1:0] out_pins +); + +wire ic_u[`HEIGHT-1:0][`WIDTH-1:0]; // interconnect for data going upwards +wire ic_d[`HEIGHT-1:0][`WIDTH-1:0]; // ~ downwards +wire ic_r[`HEIGHT-1:0][`WIDTH-1:0]; // ~ to the right +wire ic_l[`HEIGHT-1:0][`WIDTH-1:0]; // ~ to the left +wire trig_h[`HEIGHT-1:0]; // horizontal trigger lines +wire trig_v[`WIDTH-1:0]; // vertical trigger lines + +generate genvar x, y; +for (y=0; y<`HEIGHT; y=y+1) begin:g_y + for (x=0; x<`WIDTH; x=x+1) begin:g_x + wire trig = trig_h[y] & trig_v[x]; + wire in_i; + wire en_i; + wire out_o; + + if (y >= `Y_FIRST && y <= `Y_FIRST+`Y_STEP*(`IOPAIRS-1) && (y-`Y_FIRST)%`Y_STEP == 0) begin + if (x == `X_IN) begin + assign en_i = 1; + assign in_i = in_pins[(y-`Y_FIRST)/`Y_STEP]; + end else begin + assign en_i = 0; + assign in_i = 0; + end + if (x == `X_OUT) begin + assign out_pins[(y-`Y_FIRST)/`Y_STEP] = out_o; + end + end else begin + assign en_i = 0; + assign in_i = 0; + end + + logic_cell lc ( + .clk(clk), + .rst_n(rst_n), + .trig(trig), + .in_t(ic_d[y][x]), + .in_r(ic_l[y][(x+1)%`WIDTH]), + .in_b(ic_u[(y+1)%`HEIGHT][x]), + .in_l(ic_r[y][x]), + .in_i(in_i), + .en_i(en_i), + .out_t(ic_u[y][x]), + .out_r(ic_r[y][(x+1)%`WIDTH]), + .out_b(ic_d[(y+1)%`HEIGHT][x]), + .out_l(ic_l[y][x]), + .out_o(out_o) + ); + end +end + +for (x=0; x<`WIDTH; x=x+1) begin:g_vt + assign trig_v[x] = trig_en & (trig_x == x); +end + +for (y=0; y<`HEIGHT; y=y+1) begin:g_ht + assign trig_h[y] = trig_en & (trig_y == y); +end +endgenerate + +endmodule + +`default_nettype wire +
diff --git a/verilog/rtl/user_project.v b/verilog/rtl/user_project.v index 8174ffd..db163fe 100644 --- a/verilog/rtl/user_project.v +++ b/verilog/rtl/user_project.v
@@ -1,43 +1,9 @@ -// SPDX-FileCopyrightText: 2020 Efabless Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2021 Tamas Hubai `default_nettype none -/* - *------------------------------------------------------------- - * - * user_project - * - * This is an example of a (trivially simple) user project, - * showing how the user project can connect to the logic - * analyzer, the wishbone bus, and the I/O pads. - * - * This project generates an integer count, which is output - * on the user area GPIO pads (digital output only). The - * wishbone connection allows the project to be controlled - * (start and stop) from the management SoC program. - * - * See the testbenches in directory "mprj_counter" for the - * example programs that drive this user project. The three - * testbenches are "io_ports", "la_test1", and "la_test2". - * - *------------------------------------------------------------- - */ -module user_project #( - parameter BITS = 32 -)( +module user_project ( `ifdef USE_POWER_PINS inout vccd1, // User area 1 1.8V supply inout vssd1, // User area 1 digital ground @@ -68,98 +34,56 @@ // IRQ output [2:0] irq ); - wire clk; - wire rst; - wire [`MPRJ_IO_PADS-1:0] io_in; - wire [`MPRJ_IO_PADS-1:0] io_out; - wire [`MPRJ_IO_PADS-1:0] io_oeb; +// clock & reset +wire clk = wb_clk_i; +wire rst_n = ~wb_rst_i; - wire [31:0] rdata; - wire [31:0] wdata; - wire [BITS-1:0] count; +// single cycle input only wishbone logic +wire valid = wbs_stb_i && wbs_cyc_i; +assign wbs_ack_o = valid; +wire trig_en = valid && wbs_we_i; +wire [15:0] trig_x = trig_en ? wbs_adr_i[15:0] : 0; +wire [15:0] trig_y = trig_en ? wbs_adr_i[31:16] : 0; +assign wbs_dat_o = 32'b0; - wire valid; - wire [3:0] wstrb; - wire [31:0] la_write; - - // WB MI A - assign valid = wbs_cyc_i && wbs_stb_i; - assign wstrb = wbs_sel_i & {4{wbs_we_i}}; - assign wbs_dat_o = rdata; - assign wdata = wbs_dat_i; - - // IO - assign io_out = count; - assign io_oeb = {(`MPRJ_IO_PADS-1){rst}}; - - // IRQ - assign irq = 3'b000; // Unused - - // LA - assign la_data_out = {{(127-BITS){1'b0}}, count}; - // Assuming LA probes [63:32] are for controlling the count register - assign la_write = ~la_oenb[63:32] & ~{BITS{valid}}; - // Assuming LA probes [65:64] are for controlling the count clk & reset - assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i; - assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i; - - counter #( - .BITS(BITS) - ) counter( - .clk(clk), - .reset(rst), - .ready(wbs_ack_o), - .valid(valid), - .rdata(rdata), - .wdata(wbs_dat_i), - .wstrb(wstrb), - .la_write(la_write), - .la_input(la_data_in[63:32]), - .count(count) - ); - -endmodule - -module counter #( - parameter BITS = 32 -)( - input clk, - input reset, - input valid, - input [3:0] wstrb, - input [BITS-1:0] wdata, - input [BITS-1:0] la_write, - input [BITS-1:0] la_input, - output ready, - output [BITS-1:0] rdata, - output [BITS-1:0] count -); - reg ready; - reg [BITS-1:0] count; - reg [BITS-1:0] rdata; - - always @(posedge clk) begin - if (reset) begin - count <= 0; - ready <= 0; - end else begin - ready <= 1'b0; - if (~|la_write) begin - count <= count + 1; - end - if (valid && !ready) begin - ready <= 1'b1; - rdata <= count; - if (wstrb[0]) count[7:0] <= wdata[7:0]; - if (wstrb[1]) count[15:8] <= wdata[15:8]; - if (wstrb[2]) count[23:16] <= wdata[23:16]; - if (wstrb[3]) count[31:24] <= wdata[31:24]; - end else if (|la_write) begin - count <= la_write & la_input; - end - end +// trigger debugging +reg parity; +always @ (posedge clk) begin + if (!rst_n) begin + parity <= 0; + end else begin + parity <= parity ^ trig_en; end +end + +// pin assignment +wire [11:0] in_pins = io_in[23:12]; +wire [11:0] out_pins; +assign io_out[23:0] = 24'b0; +assign io_out[35:24] = out_pins; +assign io_out[36] = clk; +assign io_out[37] = parity; +assign io_oeb[23:0] = 24'b1; // input +assign io_oeb[37:24] = 14'b0; // output + +// logic analyzer is unused +assign la_data_out = 128'b0; + +// irq is unused +assign irq = 3'b0; + +logic_grid lg ( + .clk(clk), + .rst_n(rst), + .trig_en(trig_en), + .trig_x(trig_x), + .trig_y(trig_y), + .in_pins(in_pins), + .out_pins(out_pins) +); endmodule + `default_nettype wire +
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v index b47c807..5057915 100644 --- a/verilog/rtl/user_project_wrapper.v +++ b/verilog/rtl/user_project_wrapper.v
@@ -29,9 +29,7 @@ *------------------------------------------------------------- */ -module user_project_wrapper #( - parameter BITS = 32 -) ( +module user_project_wrapper ( `ifdef USE_POWER_PINS inout vdda1, // User area 1 3.3V supply inout vdda2, // User area 2 3.3V supply @@ -121,3 +119,4 @@ endmodule // user_project_wrapper `default_nettype wire +