Add miner testbench
diff --git a/build b/build
new file mode 100755
index 0000000..d3b2ee9
--- /dev/null
+++ b/build
@@ -0,0 +1,6 @@
+#!/bin/bash
+cd openlane
+make user_proj_example | tee ../user_proj_example.log
+make user_project_wrapper | tee ../user_project_wrapper.log
+cd ..
+make ship | tee ../ship.log
diff --git a/verilog/dv/caravel/user_proj_example/miner_test/Makefile b/verilog/dv/caravel/user_proj_example/miner_test/Makefile
new file mode 100644
index 0000000..f6bf3f8
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/miner_test/Makefile
@@ -0,0 +1,54 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+BEHAVIOURAL_MODELS = ../../
+
+GCC_PATH?=/opt/riscv32imc/bin
+GCC_PREFIX?=riscv32-unknown-elf
+PDK_PATH?=~/openlane/pdks/sky130A
+GCC_OPTS=-fverbose-asm -Wa,-adhlns="$@.lst" -Wl,-Map=$@.map
+GCC_OPTS+=-march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug
+GCC_OPTS+=-ffreestanding -nostdlib
+GCC_OPTS+=-O3
+
+SIM?=RTL
+
+.SUFFIXES:
+
+PATTERN = miner_test
+
+all: ${PATTERN:=.vcd}
+
+hex: ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+ifeq ($(SIM),RTL)
+ iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \
+ -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+ $< -o $@
+else
+ iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \
+ -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+ $< -o $@
+endif
+
+%.vcd: %.vvp
+ vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+ ${GCC_PATH}/${GCC_PREFIX}-gcc ${GCC_OPTS} -o $@ $(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 *.lst *.map
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/miner_test/miner_test.c b/verilog/dv/caravel/user_proj_example/miner_test/miner_test.c
new file mode 100644
index 0000000..b1b8a5c
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/miner_test/miner_test.c
@@ -0,0 +1,86 @@
+#include "../../defs.h"
+#include "../../stub.c"
+
+static volatile unsigned *regs = (unsigned*)0x30000000U;
+
+static const unsigned soln_b = 0;
+static const unsigned stat_b = 2;
+static const unsigned hdr_b = 4;
+static const unsigned diff_b = 12;
+static const unsigned start_b = 20;
+static const unsigned ctl_b = 22;
+
+// header: 644a7f32 cc155134 2997512a df12ab67 b94e7a63 2a26a07e d4615959 dd8d5b09
+// nonce: 1883832e 85da0f7a
+// hash: a4b44b86 80040878 f767b763 c46bbca6 19c1e1af 1c5c37da 42e11e05 8cb09ca0
+
+static inline void write_reg(unsigned r, unsigned v) {
+ regs[r] = v;
+}
+
+static inline unsigned read_reg(unsigned r) {
+ return regs[r];
+}
+
+
+void main()
+{
+ unsigned long long start, s, solution;
+ unsigned status;
+
+ // 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);
+
+ for (int i = 0; i < 32; i++) {
+ write_reg(ctl_b, 0);
+ // header
+ write_reg(hdr_b + 0, (0x644a7f32));
+ write_reg(hdr_b + 1, (0xcc155134));
+ write_reg(hdr_b + 2, (0x2997512a));
+ write_reg(hdr_b + 3, (0xdf12ab67));
+ write_reg(hdr_b + 4, (0xb94e7a63));
+ write_reg(hdr_b + 5, (0x2a26a07e));
+ write_reg(hdr_b + 6, (0xd4615959));
+ write_reg(hdr_b + 7, (0xdd8d5b09));
+ // start nonce
+ start = 0x1883832e85da0f7aULL;
+ s = start - i;
+ write_reg(start_b + 1, (unsigned)s);
+ write_reg(start_b + 0, s >> 32);
+ // diff
+ write_reg(diff_b + 0, (0xa4b44b86));
+ write_reg(diff_b + 1, (0x80040878));
+ write_reg(diff_b + 2, (0xf767b763));
+ write_reg(diff_b + 3, (0xc46bbca6));
+ write_reg(diff_b + 4, (0x19c1e1af));
+ write_reg(diff_b + 5, (0x1c5c37da));
+ write_reg(diff_b + 6, (0x42e11e05));
+ write_reg(diff_b + 7, (0x8cb09ca0));
+
+ // control
+ write_reg(ctl_b, 0x01800003);
+
+ for (int j = 0; j < 5000000; j = j + 1) {
+ status = read_reg(stat_b);
+ if ((status & 7) == 7)
+ break;
+ }
+ status = read_reg(ctl_b);
+ solution = read_reg(soln_b + 0) +
+ ((unsigned long long)read_reg(soln_b + 1) << 32);
+ write_reg(ctl_b, 0);
+ if ((solution != start) || ((status & 7) != 7)) {
+ print("\nFailed\n"); // Makes simulation very long!
+ reg_mprj_datal = 0xAB510000;
+ return;
+ }
+ }
+ print("\nPassed\n"); // Makes simulation very long!
+ reg_mprj_datal = 0xAB510000;
+}
+
diff --git a/verilog/dv/caravel/user_proj_example/miner_test/miner_test_tb.v b/verilog/dv/caravel/user_proj_example/miner_test/miner_test_tb.v
new file mode 100644
index 0000000..31f6d34
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/miner_test/miner_test_tb.v
@@ -0,0 +1,138 @@
+// 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 "caravel.v"
+`include "spiflash.v"
+`include "tbuart.v"
+
+module miner_test_tb;
+ reg clock;
+ reg RSTB;
+ 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
+
+ initial begin
+ $dumpfile("miner_test.vcd");
+ $dumpvars(0, miner_test_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);
+ $display ("Monitor: Timeout, Test Mega-Project IO (RTL) Failed");
+ $display("%c[0m",27);
+ $finish;
+ end
+
+ initial begin
+ wait(checkbits == 16'hAB40);
+ $display("Miner test started");
+ wait(checkbits == 16'hAB41);
+ wait(checkbits == 16'hAB51);
+ #10000;
+ $finish;
+ end
+
+ initial begin
+ RSTB <= 1'b0;
+ #1000;
+ RSTB <= 1'b1; // Release reset
+ #2000;
+ 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("miner_test.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