Added new files for the Chaos Automaton to the Caravel User Project.
diff --git a/README.md b/README.md index 3706438..59a1e24 100644 --- a/README.md +++ b/README.md
@@ -1,4 +1,4 @@ -# Caravel User Project +# Chaos Automaton (Caravel User Project) [](https://opensource.org/licenses/Apache-2.0) [](https://github.com/efabless/caravel_project_example/actions/workflows/user_project_ci.yml) [](https://github.com/efabless/caravel_project_example/actions/workflows/caravel_build.yml) @@ -9,3 +9,28 @@ Refer to [README](docs/source/index.rst) for this sample project documentation. + +The Chaos automaton +---------------------------------------------------- +Digital design for Caravel (user_project_wrapper) + +This chip is a pure asynchronous cellular automaton. Each cell has +four inputs from N, S, E, W and generates four outputs to N, S, E, W. +Each cell can be configured for any boolean function of the four +inputs. + +Outputs on the periphery (or some selection thereof) are passed to the +chip GPIO. Inputs may also come from the chip periphery; choice of +input or output is programmable like the cell boolean function. + +All inputs and outputs may be channeled through the logic analyzer to +set or grab the entire state of the system. + +The logic analyzer may also be used to program the cell functions. + +This can be used in a loop with an evolutionary algorithm to tune the +chip functions to achieve a specific behavior. + +Most of the core circuitry is straightforward. The total number of +cells is parameterized, so that the largest number of cells that will +fit in the caravel user project space can be determined.
diff --git a/mag/user_project_wrapper.mag b/mag/user_project_wrapper.mag deleted file mode 100644 index f917ca4..0000000 --- a/mag/user_project_wrapper.mag +++ /dev/null Binary files differ
diff --git a/mag/user_project_wrapper.mag.gz b/mag/user_project_wrapper.mag.gz new file mode 100644 index 0000000..221f614 --- /dev/null +++ b/mag/user_project_wrapper.mag.gz Binary files differ
diff --git a/verilog/dv/chaos_test1/Makefile b/verilog/dv/chaos_test1/Makefile new file mode 100644 index 0000000..517c6fb --- /dev/null +++ b/verilog/dv/chaos_test1/Makefile
@@ -0,0 +1,78 @@ +# 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 + +## Caravel Pointers +CARAVEL_ROOT ?= ../../../caravel +CARAVEL_PATH ?= $(CARAVEL_ROOT) +CARAVEL_FIRMWARE_PATH = $(CARAVEL_PATH)/verilog/dv/caravel +CARAVEL_VERILOG_PATH = $(CARAVEL_PATH)/verilog +CARAVEL_RTL_PATH = $(CARAVEL_VERILOG_PATH)/rtl +CARAVEL_BEHAVIOURAL_MODELS = $(CARAVEL_VERILOG_PATH)/dv/caravel + +## User Project Pointers +UPRJ_VERILOG_PATH ?= ../../../verilog +UPRJ_RTL_PATH = $(UPRJ_VERILOG_PATH)/rtl +UPRJ_BEHAVIOURAL_MODELS = ../ + +## RISCV GCC +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +## Simulation mode: RTL/GL +SIM?=RTL + +.SUFFIXES: + +PATTERN = chaos_test1 + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I $(UPRJ_RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) -I $(CARAVEL_VERILOG_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I$(UPRJ_RTL_PATH) -I $(UPRJ_VERILOG_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(CARAVEL_FIRMWARE_PATH)/sections.lds $(CARAVEL_FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -I $(CARAVEL_PATH) -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(CARAVEL_FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(CARAVEL_FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all
diff --git a/verilog/dv/chaos_test1/chaos_test1.c b/verilog/dv/chaos_test1/chaos_test1.c new file mode 100644 index 0000000..220bdfe --- /dev/null +++ b/verilog/dv/chaos_test1/chaos_test1.c
@@ -0,0 +1,124 @@ +/* + * 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 + */ + +// This include is relative to $CARAVEL_PATH (see Makefile) +#include "verilog/dv/caravel/defs.h" +#include "verilog/dv/caravel/stub.c" + +// -------------------------------------------------------- + +/* + MPRJ Logic Analyzer Test: + - Observes counter value through LA probes [31:0] + - Sets counter initial value through LA probes [63:32] + - Flags when counter value exceeds 500 through the management SoC gpio + - Outputs message to the UART when the test concludes successfuly +*/ + +void main() +{ + + /* Set up the housekeeping SPI to be connected internally so */ + /* that external pin changes don't affect it. */ + + reg_spimaster_config = 0xa002; // Enable, prescaler = 2, + // connect to housekeeping SPI + + // Connect the housekeeping SPI to the SPI master + // so that the CSB line is not left floating. This allows + // all of the GPIO pins to be used for user functions. + + // The upper GPIO pins are configured to be output + // and accessble to the management SoC. + // Used to flad the start/end of a test + // The lower GPIO pins are configured to be output + // and accessible to the user project. They show + // the project count value, although this test is + // designed to read the project count through the + // logic analyzer probes. + // I/O 6 is configured for the UART Tx line + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_15 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_3 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_USER_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Set UART clock to 64 kbaud (enable before I/O configuration) + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Configure LA probes [31:0], [127:64] as inputs to the cpu + // Configure LA probes [63:32] as outputs from the cpu + reg_la0_oenb = reg_la0_iena = 0xFFFFFFFF; // [31:0] + reg_la1_oenb = reg_la1_iena = 0x00000000; // [63:32] + reg_la2_oenb = reg_la2_iena = 0xFFFFFFFF; // [95:64] + reg_la3_oenb = reg_la3_iena = 0xFFFFFFFF; // [127:96] + + // Flag start of the test + reg_mprj_datal = 0xAB400000; + + // Set Counter value to zero through LA probes [63:32] + reg_la1_data = 0x00000000; + + // Configure LA probes from [63:32] as inputs to disable counter write + reg_la1_oenb = reg_la1_iena = 0xFFFFFFFF; + + while (1) { + if (reg_la0_data > 0x1F4) { + reg_mprj_datal = 0xAB410000; + break; + } + } + print("\n"); + print("Monitor: Test 2 Passed\n\n"); // Makes simulation very long! + reg_mprj_datal = 0xAB510000; +} +
diff --git a/verilog/dv/chaos_test1/chaos_test1.hex b/verilog/dv/chaos_test1/chaos_test1.hex new file mode 100755 index 0000000..a30d154 --- /dev/null +++ b/verilog/dv/chaos_test1/chaos_test1.hex
@@ -0,0 +1,78 @@ +@00000000 +93 00 00 00 93 01 00 00 13 02 00 00 93 02 00 00 +13 03 00 00 93 03 00 00 13 04 00 00 93 04 00 00 +13 05 00 00 93 05 00 00 13 06 00 00 93 06 00 00 +13 07 00 00 93 07 00 00 13 08 00 00 93 08 00 00 +13 09 00 00 93 09 00 00 13 0A 00 00 93 0A 00 00 +13 0B 00 00 93 0B 00 00 13 0C 00 00 93 0C 00 00 +13 0D 00 00 93 0D 00 00 13 0E 00 00 93 0E 00 00 +13 0F 00 00 93 0F 00 00 17 05 00 00 13 05 85 45 +93 05 00 00 13 06 00 00 63 D8 C5 00 14 41 94 C1 +11 05 91 05 E3 CC C5 FE 13 05 00 00 93 05 00 00 +63 57 B5 00 23 20 05 00 11 05 E3 4D B5 FE 11 22 +01 A0 01 00 B7 02 00 28 13 03 00 12 23 90 62 00 +A3 81 02 00 05 C6 21 4F 93 73 F6 0F 93 DE 73 00 +23 80 D2 01 93 EE 0E 01 23 80 D2 01 86 03 93 F3 +F3 0F 7D 1F E3 14 0F FE 23 80 62 00 A1 C9 13 0F +00 02 83 23 05 00 A1 4F 93 DE F3 01 23 80 D2 01 +93 EE 0E 01 23 80 D2 01 83 CE 02 00 93 FE 2E 00 +93 DE 1E 00 86 03 B3 E3 D3 01 7D 1F 63 17 0F 00 +23 20 75 00 11 05 83 23 05 00 FD 1F E3 96 0F FC +FD 15 F1 F1 63 04 0F 00 23 20 75 00 13 03 00 08 +A3 81 62 00 82 80 01 00 00 00 01 11 06 CE 22 CC +00 10 AA 87 A3 07 F4 FE 03 47 F4 FE A9 47 63 14 +F7 00 35 45 DD 37 B7 07 00 20 91 07 03 47 F4 FE +98 C3 01 00 F2 40 62 44 05 61 82 80 01 11 06 CE +22 CC 00 10 23 26 A4 FE 19 A8 83 27 C4 FE 13 87 +17 00 23 26 E4 FE 83 C7 07 00 3E 85 7D 37 83 27 +C4 FE 83 C7 07 00 F5 F3 01 00 F2 40 62 44 05 61 +82 80 41 11 06 C6 22 C4 00 08 B7 07 00 24 29 67 +09 07 98 C3 B7 07 00 26 93 87 07 0A 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 C7 09 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 87 09 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 47 09 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 07 09 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 C7 08 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 87 08 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 47 08 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 07 08 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 C7 07 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 87 07 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 47 07 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 07 07 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 C7 06 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 87 06 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 47 06 09 67 13 07 +97 80 98 C3 B7 07 00 26 93 87 07 06 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 C7 05 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 87 05 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 47 05 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 07 05 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 C7 04 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 87 04 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 47 04 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 07 04 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 87 03 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 47 03 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 07 03 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 C7 02 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 87 02 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 47 02 09 67 13 07 +87 80 98 C3 B7 07 00 26 93 87 C7 03 09 67 13 07 +97 80 98 C3 B7 07 00 20 13 07 10 27 98 C3 B7 07 +00 20 A1 07 05 47 98 C3 B7 07 00 26 05 47 98 C3 +01 00 B7 07 00 26 98 43 85 47 E3 0C F7 FE B7 07 +00 25 13 87 07 02 FD 57 1C C3 37 07 00 25 41 07 +1C C3 B7 07 00 25 13 87 47 02 81 47 1C C3 37 07 +00 25 51 07 1C C3 B7 07 00 25 13 87 87 02 FD 57 +1C C3 37 07 00 25 61 07 1C C3 B7 07 00 25 13 87 +C7 02 FD 57 1C C3 37 07 00 25 71 07 1C C3 B7 07 +00 26 B1 07 37 07 40 AB 98 C3 B7 07 00 25 91 07 +23 A0 07 00 B7 07 00 25 13 87 47 02 FD 57 1C C3 +37 07 00 25 51 07 1C C3 B7 07 00 25 98 43 93 07 +40 1F E3 FB E7 FE B7 07 00 26 B1 07 37 07 41 AB +98 C3 01 00 B7 07 00 10 13 85 07 4B C5 39 B7 07 +00 10 13 85 47 4B DD 31 B7 07 00 26 B1 07 37 07 +51 AB 98 C3 01 00 B2 40 22 44 41 01 82 80 00 00 +0A 00 00 00 4D 6F 6E 69 74 6F 72 3A 20 54 65 73 +74 20 32 20 50 61 73 73 65 64 0A 0A 00 00 00 00
diff --git a/verilog/dv/chaos_test1/chaos_test1_tb.v b/verilog/dv/chaos_test1/chaos_test1_tb.v new file mode 100644 index 0000000..a54c154 --- /dev/null +++ b/verilog/dv/chaos_test1/chaos_test1_tb.v
@@ -0,0 +1,156 @@ +// 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 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "uprj_netlists.v" +`include "caravel_netlists.v" +`include "spiflash.v" +`include "tbuart.v" + +/* + * This testbench is the original testbench for the logic analyzer with + * the example user project. It is not meant to do anything useful; + * it is just a valid wrapper around the project to check that the + * project compiles and simulates without error. + */ + +module chaos_test1_tb; + reg clock; + reg RSTB; + reg CSB; + + reg power1, power2; + + wire gpio; + wire uart_tx; + wire [37:0] mprj_io; + wire [15:0] checkbits; + + assign checkbits = mprj_io[31:16]; + assign uart_tx = mprj_io[6]; + + always #12.5 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + assign mprj_io[3] = (CSB == 1'b1) ? 1'b1 : 1'bz; + + initial begin + // $dumpfile("chaos_test1.vcd"); + // $dumpvars(0, chaos_test1_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (200) begin + repeat (1000) @(posedge clock); + // $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test (GL) Failed"); + `else + $display ("Monitor: Timeout, Test (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + initial begin + wait(checkbits == 16'hAB40); + $display("LA Test 1 started"); + wait(checkbits == 16'hAB41); + wait(checkbits == 16'hAB51); + #10000; + $finish; + end + + initial begin + RSTB <= 1'b0; + CSB <= 1'b1; // Force CSB high + #2000; + RSTB <= 1'b1; // Release reset + #170000; + CSB = 1'b0; // CSB can be released + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + wire VDD1V8; + wire VDD3V3; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("chaos_test1.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + + // Testbench UART + tbuart tbuart ( + .ser_rx(uart_tx) + ); + +endmodule +`default_nettype wire
diff --git a/verilog/rtl/chaos_automaton.v b/verilog/rtl/chaos_automaton.v new file mode 100644 index 0000000..ec65d5f --- /dev/null +++ b/verilog/rtl/chaos_automaton.v
@@ -0,0 +1,587 @@ +// 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 + +`default_nettype none +/* + *------------------------------------------------------------- + * + * chaos_automaton + * + * This chip is a pure asynchronous cellular automaton. Each cell has + * four inputs from N, S, E, W and generates four outputs to N, S, E, W. + * Each output can be configured for any boolean function of the four + * inputs (16 bits each). + * + * Outputs on the periphery (or some selection thereof) are passed to the + * chip GPIO. Inputs may also come from the chip periphery; choice of + * input or output is programmable like the cell boolean function. + * + * All periphery inputs and outputs may be channeled through the logic + * analyzer to apply input to or monitor output from the array. + * + * The wishbone bus may be used to program the cell functions. + * + * This can be used in a loop with an evolutionary algorithm to tune the + * chip functions to achieve a specific behavior. + * + * Most of the core circuitry is straightforward. The total number of + * cells is parameterized, so that the largest number of cells that will + * fit in the caravel user project space can be determined. + * + * Version v1: To avoid massive amounts of wiring (e.g., 16 or 32 + * data wires + 10 address wires to every single cell), all of the + * LUT configuration memory is stored in a (very long) serial chain + * in a full loop. The scan chain is 64 bits longer than the number + * of cells and allows 64 bits to be transferred to and from the + * wishbone bus independently of the cells. Every cell has 64 latches + * in addition to the 64 flops so that the scan chain can be cycled + * without affecting ongoing operation of the automaton. + * + * Memory mapped address space: + * + * BASE_ADR + 7 to BASE_ADR + 0: Data to read or write + * BASE_ADR + 15 to BASE_ADR + 8: Core cell address for read/write + * BASE_ADR + 16: Triggers + * + * Trigger bits: + * bit 0: Shift by (address) cells (64 bits). + * bit 1: Finish cycle. Return shift register to run state, toggle "hold" + * + * Both trigger bits are self-resetting. The trigger bit (as read) remains + * high until the transfer has completed. The trigger bit can be polled to + * determine when the cycle has completed. + * + * The shift cycle bit can be used to load the configuration of the array + * cell by cell. The typical case is to set address = 1 and apply or read + * each cell's configuration in turn. However, it can also be used piecemeal, + * for example, to read out a block of configurations, without having + * to loop a full cycle for each one. The counter tracks what the + * current offset is, and can return to the run-state position on + * application of bit 1, "Finish cycle". At the end of "Finish cycle" + * the hold bit is toggled to latch and apply any new configuration + * data. + * + * Reading and writing a single cell's configuration can be accomplished + * by a sequence of shift cycles and reads/writes. To change the + * configuration of a single cell: (1) Write the cell address, (2) Apply + * the shift cycle, (3) Write the configuration data, (4) Apply the + * finish cycle. To read the configuration of a single cell: (1) Write + * the cell address, (2) Apply the shift cycle, (3) Read the configuration + * data, (4) Apply the finish cycle. + * + *------------------------------------------------------------- + */ + +/* + *----------------------------------------------------------------- + * User project top level + *----------------------------------------------------------------- + */ + +module chaos_automaton #( + parameter XSIZE = 20, // Number of cells left to right + parameter YSIZE = 20, // Number of cells top to bottom + parameter ASIZE = 8, // Enough bits to count XSIZE * YSIZE + parameter BASE_ADR = 32'h 3000_0000 // Wishbone base address +)( +`ifdef USE_POWER_PINS + inout vdda1, // User area 1 3.3V supply + inout vdda2, // User area 2 3.3V supply + inout vssa1, // User area 1 analog ground + inout vssa2, // User area 2 analog ground + inout vccd1, // User area 1 1.8V supply + inout vccd2, // User area 2 1.8v supply + inout vssd1, // User area 1 digital ground + inout vssd2, // User area 2 digital ground +`endif + + // Wishbone Slave ports (WB MI A) + input wb_clk_i, + input wb_rst_i, + input wbs_stb_i, + input wbs_cyc_i, + input wbs_we_i, + input [3:0] wbs_sel_i, + input [31:0] wbs_dat_i, + input [31:0] wbs_adr_i, + output wbs_ack_o, + output [31:0] wbs_dat_o, + + // Logic Analyzer Signals + input [127:0] la_data_in, + output [127:0] la_data_out, + input [127:0] la_oenb, + + // IOs + input [`MPRJ_IO_PADS-1:0] io_in, + output [`MPRJ_IO_PADS-1:0] io_out, + output [`MPRJ_IO_PADS-1:0] io_oeb, + + // IRQ + output [2:0] irq +); + +`define IDLE 3'b000 +`define START 3'b001 +`define FINISH 3'b010 +`define XDATAS 3'b011 +`define XDATAF 3'b100 +`define LOAD 3'b101 + +`define CONFIGL 8'h00 /* Address offset of configuration data low word */ +`define CONFIGH 8'h04 /* Address offset of configuration data high word */ +`define ADDRESS 8'h08 /* Address offset of cell address value */ +`define XFER 8'h0c /* Address offset of transfer bits */ + +`define MAXADDR (XSIZE * YSIZE - 1) /* Highest cell address */ + + reg clk; /* serial clock to transfer data */ + reg hold; /* trigger to hold transferred data */ + reg [1:0] xfer_state; /* state of the data transfer */ + reg [1:0] xfer_ctrl; /* Transfer trigger bits */ + reg [63:0] config_data; /* 64 bits to read or write */ + + reg [ASIZE - 1:0] cell_addr; /* Core cell to address */ + reg [ASIZE - 1:0] cell_offset; /* Current offset of shift register */ + reg [ASIZE + 5:0] bit_count; /* Full count (cell address + bits) */ + + wire [`MPRJ_IO_PADS-1:0] io_in; + wire [`MPRJ_IO_PADS-1:0] io_out; + wire [`MPRJ_IO_PADS-1:0] io_oeb; + + wire [1:0] config_sel; + wire address_sel; + wire xfer_sel; + + wire valid; + reg ready; + wire [3:0] iomem_we; + wire selected; + wire [1:0] busy; + reg [31:0] rdata_pre; + wire [63:0] rdata; + reg [31:0] wbs_dat_o; + reg [63:0] wdata; + reg write; + reg prewrite; + + wire [2*XSIZE + 2*YSIZE - 1: 0] data_in; + + // Wishbone address select indicators + assign config_sel[0] = (wbs_adr_i[7:0] == `CONFIGL); + assign config_sel[1] = (wbs_adr_i[7:0] == `CONFIGH); + assign address_sel = (wbs_adr_i[7:0] == `ADDRESS); + assign xfer_sel = (wbs_adr_i[7:0] == `XFER); + + assign selected = config_sel[1] || config_sel[0] || address_sel || xfer_sel; + + assign valid = wbs_cyc_i && wbs_stb_i; + assign wbs_ack_o = ready; + assign iomem_we = wbs_sel_i & {4{wbs_we_i}}; + + // Chip pin output (Connects to a subset of la_data_in; + // 9 signals each N and S, 10 signals each W and E) + assign io_out = {la_data_out[2*YSIZE + XSIZE + 8: 2*YSIZE + XSIZE], // north + la_data_out[2*YSIZE + 8: 2*YSIZE], // south + la_data_out[YSIZE + 9: YSIZE], // east + la_data_out[9:0]}; // west + + // Chip pin direction is assigned to la_data sub-array + assign io_oeb = la_data_in[127:127-38] & ~la_oenb[127:127-38]; + + // IRQ + assign irq = 3'b000; // Unused + + // Instantiate the chaos cell array + + chaos_array #( + .XSIZE(XSIZE), + .YSIZE(YSIZE), + .BASE_ADR(BASE_ADR) + ) chaos_array_inst ( + `ifdef USE_POWER_PINS + .vccd1(vccd1), + .vssd1(vssd1), + `endif + .clk(clk), + .reset(wb_rst_i), + .hold(hold), + .rdata(rdata), + .wdata(wdata), + .write(write), + .data_in(data_in), + .data_out(la_data_out[2*XSIZE + 2*YSIZE - 1: 0]) + ); + + /* Hook up io_in (multiplexed with la_data_int based on value of la_oenb, + * using the same subsets as used for io_out). The expressions are more + * complicated because the signals that are connected to the GPIO pins + * have to be multiplexed with the logic analyzer inputs. + */ + + genvar i; + + generate + for (i = 2*YSIZE + XSIZE + 9; i < 2*YSIZE + 2*XSIZE; i=i+1) begin + assign data_in[i] = la_data_in[i]; + end + for (i = 2 * YSIZE + XSIZE; i < 2*YSIZE + XSIZE + 9; i=i+1) begin + assign data_in[i] = la_oenb[i] ? la_data_in[i] : io_in[i - 2*YSIZE + XSIZE + 29]; + end + for (i = 2 * YSIZE + 9; i < 2 * YSIZE + XSIZE; i=i+1) begin + assign data_in[i] = la_data_in[i]; + end + for (i = 2 * YSIZE; i < 2 * YSIZE + 9; i=i+1) begin + assign data_in[i] = la_oenb[i] ? la_data_in[i] : io_in[i - 2*YSIZE + 20]; + end + for (i = YSIZE + 10; i < 2 * YSIZE; i=i+1) begin + assign data_in[i] = la_data_in[i]; + end + for (i = YSIZE; i < YSIZE + 10; i=i+1) begin + assign data_in[i] = la_oenb[i] ? la_data_in[i] : io_in[i - YSIZE + 10]; + end + for (i = 10; i < YSIZE; i=i+1) begin + assign data_in[i] = la_data_in[i]; + end + for (i = 0; i < 10; i=i+1) begin + assign data_in[i] = la_oenb[i] ? la_data_in[i] : io_in[i]; + end + endgenerate + + /* Read data (only rdata is something that was not written by the processor) */ + + always @* begin + rdata_pre = 'b0; + if (xfer_sel) begin + rdata_pre = {30'b0, busy}; + end else if (config_sel[0]) begin + rdata_pre = rdata[31:0]; + end else if (config_sel[1]) begin + rdata_pre = rdata[63:32]; + end else if (address_sel) begin + /* When ADDRESS is selected, pass back the existing cell */ + /* count rather than what was written into cell_addr. */ + rdata_pre = bit_count[ASIZE + 5: 6]; + end + end + + /* Read data */ + + always @(posedge wb_clk_i or posedge wb_rst_i) begin + if (wb_rst_i) begin + wbs_dat_o <= 0; + ready <= 0; + end else begin + ready <= 0; + if (valid && !ready && wbs_adr_i[31:8] == BASE_ADR[31:8]) begin + ready <= 1'b1; + if (selected) begin + wbs_dat_o <= rdata_pre; + end + end + end + end + + /* Write data */ + + always @(posedge wb_clk_i or posedge wb_rst_i) begin + if (wb_rst_i) begin + xfer_ctrl <= 0; + wdata <= 0; + prewrite <= 1'b0; + write <= 1'b0; + end else begin + prewrite <= 1'b0; + write <= 1'b0; + if (valid && !ready && wbs_adr_i[31:8] == BASE_ADR[31:8]) begin + if (xfer_sel) begin + if (iomem_we[0]) xfer_ctrl <= wbs_dat_i[1:0]; + end else if (config_sel[0]) begin + if (iomem_we[0]) wdata[7:0] <= wbs_dat_i[7:0]; + if (iomem_we[1]) wdata[15:8] <= wbs_dat_i[15:8]; + if (iomem_we[2]) wdata[23:16] <= wbs_dat_i[23:16]; + if (iomem_we[3]) wdata[31:24] <= wbs_dat_i[31:24]; + prewrite <= 1'b1; + end else if (config_sel[1]) begin + if (iomem_we[0]) wdata[39:32] <= wbs_dat_i[7:0]; + if (iomem_we[1]) wdata[47:40] <= wbs_dat_i[15:8]; + if (iomem_we[2]) wdata[55:48] <= wbs_dat_i[23:16]; + if (iomem_we[3]) wdata[63:56] <= wbs_dat_i[31:24]; + prewrite <= 1'b1; + end else if (address_sel) begin + /* NOTE: If XSIZE * YSIZE > 256, this must be adjusted */ + if (iomem_we[0]) cell_addr <= wbs_dat_i[7:0]; + end + end else begin + xfer_ctrl <= 0; // Immediately self-resetting + end + + /* write data pulse follows prewrite by one cycle */ + if (prewrite == 1'b1) begin + write <= 1'b1; + end + end + end + + /* Transfer status */ + + assign busy[0] = (xfer_state == `START || xfer_state == `XDATAS); + assign busy[1] = (xfer_state == `FINISH || xfer_state == `XDATAF || + xfer_state == `LOAD); + + /* Transfer cycles */ + + always @(posedge wb_clk_i or posedge wb_rst_i) begin + if (wb_rst_i == 1'b1) begin + xfer_state <= `IDLE; + bit_count <= 'd0; + cell_offset <= 'd0; + write <= 1'b0; + end else begin + clk <= 1'b0; + hold <= 1'b1; + write <= 1'b0; + if (xfer_state == `IDLE) begin + if (xfer_ctrl[0] == 1'b1) begin + xfer_state <= `START; + end else if (xfer_ctrl[1] == 1'b1) begin + xfer_state <= `FINISH; + end + end else if (xfer_state == `START) begin + bit_count[ASIZE + 5:6] <= cell_addr; + bit_count[5:0] <= 6'd0; + xfer_state <= `XDATAS; + end else if (xfer_state == `FINISH) begin + bit_count[ASIZE + 5:6] <= `MAXADDR - cell_offset; + bit_count[5:0] <= 6'd0; + xfer_state <= `XDATAF; + end else if (xfer_state == `XDATAS) begin + clk <= ~clk; + bit_count <= bit_count - 1; + if (bit_count[5:0] == 0) begin + cell_offset <= cell_offset + 1; + end + if (clk == 1'b0) begin + if (bit_count == 0) begin + xfer_state <= `IDLE; + end + end + end else if (xfer_state == `XDATAF) begin + clk <= ~clk; + bit_count <= bit_count - 1; + if (bit_count[5:0] == 0) begin + cell_offset <= cell_offset + 1; + end + if (clk == 1'b0) begin + if (bit_count == 0) begin + xfer_state <= `LOAD; + end + end + end else if (xfer_state == `LOAD) begin + hold <= 1'b0; + xfer_state <= `IDLE; + end + end + end +endmodule + +/* + * Chaos automaton base cell definitions: Map directions to + * array indexes. + */ + +`define NORTH 0 +`define SOUTH 1 +`define EAST 2 +`define WEST 3 + +/* + *----------------------------------------------------------------- + * Chaos base cell (four 4-input LUTs + data load circuitry) + *----------------------------------------------------------------- + */ + +module chaos_cell ( +`ifdef USE_POWER_PINS + inout vccd1, // User area 1 1.8V supply + inout vssd1, // User area 1 digital ground +`endif + + input inorth, isouth, ieast, iwest, + output onorth, osouth, oeast, owest, + input clk, /* Serial load clock */ + input reset, /* System reset */ + input hold, /* Data latch signal */ + input idata, /* Shift register input */ + output odata /* Shift register output */ +); + + reg [15:0] lutfunc [3:0]; /* LUT configuration data */ + reg [15:0] lutdata [3:0]; /* Latched LUT configuration data */ + wire [3:0] insew; + wire [3:0] onsew; + + /* Gather inputs and outputs into arrays */ + + assign insew = {inorth, isouth, ieast, iwest}; + assign onsew = {onorth, osouth, oeast, owest}; + + /* Core functions */ + /* The four LUTs define each output as a function of the four inputs */ + + assign onorth = lutdata[`NORTH][insew]; + assign osouth = lutdata[`SOUTH][insew]; + assign oeast = lutdata[`EAST][insew]; + assign owest = lutdata[`WEST][insew]; + + /* Inferred latches from shift register */ + + always @* begin + if (!hold) begin + lutdata[0] = lutfunc[0]; + lutdata[1] = lutfunc[1]; + lutdata[2] = lutfunc[2]; + lutdata[3] = lutfunc[3]; + end + end + + /* Implement the shift register operation */ + + always @(posedge clk or posedge reset) begin + if (reset == 1'b1) begin + lutfunc[`NORTH] <= 16'd0; + lutfunc[`SOUTH] <= 16'd0; + lutfunc[`EAST] <= 16'd0; + lutfunc[`WEST] <= 16'd0; + end else begin + lutfunc[`NORTH][15:1] <= lutfunc[`NORTH][14:0]; + lutfunc[`SOUTH][15:1] <= lutfunc[`SOUTH][14:0]; + lutfunc[`EAST][15:1] <= lutfunc[`EAST][14:0]; + lutfunc[`WEST][15:1] <= lutfunc[`WEST][14:0]; + + lutfunc[`NORTH][0] <= idata; + lutfunc[`SOUTH][0] <= lutfunc[`NORTH][15]; + lutfunc[`EAST][0] <= lutfunc[`SOUTH][15]; + lutfunc[`WEST][0] <= lutfunc[`EAST][15]; + end + end + + assign odata = lutfunc[`WEST][15]; + +endmodule + +/* + *----------------------------------------------------------------- + * Chaos array (XSIZE * YSIZE) + *----------------------------------------------------------------- + */ + +module chaos_array #( + parameter XSIZE = 20, + parameter YSIZE = 20, + parameter BASE_ADR = 32'h3000_0000 +)( +`ifdef USE_POWER_PINS + inout vccd1, // User area 1 1.8V supply + inout vssd1, // User area 1 digital ground +`endif + + input clk, + input reset, + input hold, + input write, + input [63:0] wdata, + output [63:0] rdata, + input [2*XSIZE + 2*YSIZE - 1:0] data_in, + output [2*XSIZE + 2*YSIZE - 1:0] data_out +); + wire [XSIZE - 1: 0] uconn [YSIZE: 0]; + wire [XSIZE - 1: 0] dconn [YSIZE: 0]; + wire [YSIZE - 1: 0] rconn [XSIZE: 0]; + wire [YSIZE - 1: 0] lconn [XSIZE: 0]; + + wire [YSIZE - 1: 0] shiftreg [XSIZE: 0]; + + wire io_data_sel; // wishbone select data + wire xfer_sel; // wishbone select transfer + + /* The perimeter inputs and outputs connect to the logic analyzer */ + /* (To do: multiplex inputs between the chip I/O and logic analyzer */ + + assign data_out = {uconn[YSIZE][XSIZE - 1:0], dconn[0][XSIZE - 1:0], + rconn[XSIZE][YSIZE - 1:0], lconn[0][YSIZE - 1:0]}; + + assign dconn[YSIZE][XSIZE - 1:0] = data_in[2*XSIZE+2*YSIZE - 1: 2*YSIZE + XSIZE]; + assign uconn[0][XSIZE - 1:0] = data_in[2*YSIZE + XSIZE - 1:2*YSIZE]; + assign rconn[0][YSIZE - 1:0] = data_in[2*YSIZE-1:YSIZE]; + assign lconn[XSIZE][YSIZE - 1:0] = data_in[YSIZE-1:0]; + + genvar i, j; + + /* Connected array of cells */ + generate + for (j = 0; j < YSIZE; j=j+1) begin + for (i = 0; i < XSIZE; i=i+1) begin + chaos_cell chaos_cell_inst ( + .inorth(dconn[j+1][i]), + .isouth(uconn[j][i]), + .ieast(rconn[i+1][j]), + .iwest(lconn[i][j]), + .onorth(uconn[j+1][i]), + .osouth(dconn[j][i]), + .oeast(lconn[i+1][j]), + .owest(rconn[i][j]), + .clk(clk), + .reset(reset), + .hold(hold), + .idata(shiftreg[i][j]), + .odata(shiftreg[i+1][j]) + ); + end + end + + /* NOTE: This would work better topologically if each */ + /* row switched the direction of the shift register. */ + + for (j = 0; j < YSIZE - 1; j=j+1) begin + assign shiftreg[0][j+1] = shiftreg[XSIZE][j]; + end + endgenerate + + /* Storage for data transfers to and from the processor. This is */ + /* 64 bits, so can hold the configuration data for one core cell. */ + + reg [63:0] lutdata; + + /* Wire up the lutdata registers as a shift register and connect the */ + /* ends to the array's shift register to form a loop. */ + + always @(posedge clk or posedge write) begin + if (write) begin + /* Copy data from wdata to lutdata on write */ + lutdata <= wdata; + end else begin + /* Shift data on clock when "write" is not raised */ + lutdata[63:1] <= lutdata[62:0]; + lutdata[0] <= shiftreg[XSIZE][YSIZE-1]; + end + end + + assign shiftreg[0][0] = lutdata[63]; + + assign rdata = lutdata; /* Data to read back */ + +endmodule +`default_nettype wire
diff --git a/verilog/rtl/uprj_netlists.v b/verilog/rtl/uprj_netlists.v index 3537de8..947e2f7 100644 --- a/verilog/rtl/uprj_netlists.v +++ b/verilog/rtl/uprj_netlists.v
@@ -21,8 +21,8 @@ // Assume default net type to be wire because GL netlists don't have the wire definitions `default_nettype wire `include "gl/user_project_wrapper.v" - `include "gl/user_proj_example.v" + `include "gl/chaos_automaton.v" `else `include "user_project_wrapper.v" - `include "user_proj_example.v" -`endif \ No newline at end of file + `include "chaos_automaton.v" +`endif
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v index 2a3462b..a0c89a3 100644 --- a/verilog/rtl/user_project_wrapper.v +++ b/verilog/rtl/user_project_wrapper.v
@@ -82,7 +82,7 @@ /* User project is instantiated here */ /*--------------------------------------*/ -user_proj_example mprj ( +chaos_automaton mprj ( `ifdef USE_POWER_PINS .vdda1(vdda1), // User area 1 3.3V power .vdda2(vdda2), // User area 2 3.3V power