caravel_test: Import from git@github.com:konradwilk/sha1.git
046ef581e5191a01ea3d8b2537ddfc44783dd941
Signed-off-by: Konrad Rzeszutek Wilk <konrad@kernel.org>
diff --git a/verilog/dv/caravel_test/Makefile b/verilog/dv/caravel_test/Makefile
new file mode 100644
index 0000000..072d695
--- /dev/null
+++ b/verilog/dv/caravel_test/Makefile
@@ -0,0 +1,94 @@
+# 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
+
+# include the modules that cocotb needs for test
+#export PYTHONPATH := $(UPRJ_RTL_PATH)/wrapped_wrapper/wrapper/test
+
+.SUFFIXES:
+
+PATTERN = wrapper
+
+all: coco_test
+
+hex: ${PATTERN:=.hex}
+
+coco_test: ${PATTERN}.hex
+ rm -rf sim_build/
+ mkdir sim_build/
+ iverilog -o sim_build/sim.vvp -s wrapper_tb wrapper_tb.v -DSIM -DFUNCTIONAL \
+ -I $(PDK_PATH) \
+ -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) \
+ -I $(UPRJ_BEHAVIOURAL_MODELS) -I $(UPRJ_RTL_PATH)
+ MODULE=test_caravel vvp -M $$(cocotb-config --prefix)/cocotb/libs -m libcocotbvpi_icarus sim_build/sim.vvp
+ ! grep failure results.xml
+
+%.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 $<
+
+test:
+ echo ${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 $<
+
+%.elf: %.c sections.lds start.S
+ ${GCC_PATH}/${GCC_PREFIX}-gcc -I $(CARAVEL_PATH) -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ 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/caravel_test/__init__.py b/verilog/dv/caravel_test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/verilog/dv/caravel_test/__init__.py
diff --git a/verilog/dv/caravel_test/custom_ops.S b/verilog/dv/caravel_test/custom_ops.S
new file mode 100644
index 0000000..e3d1e2d
--- /dev/null
+++ b/verilog/dv/caravel_test/custom_ops.S
@@ -0,0 +1,116 @@
+/*
+ * SPDX-FileCopyrightText: 2015 Clifford Wolf
+ * PicoRV32 -- A Small RISC-V (RV32I) Processor Core
+ *
+ * Copyright (C) 2015 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * SPDX-License-Identifier: ISC
+ */
+
+#define regnum_q0 0
+#define regnum_q1 1
+#define regnum_q2 2
+#define regnum_q3 3
+
+#define regnum_x0 0
+#define regnum_x1 1
+#define regnum_x2 2
+#define regnum_x3 3
+#define regnum_x4 4
+#define regnum_x5 5
+#define regnum_x6 6
+#define regnum_x7 7
+#define regnum_x8 8
+#define regnum_x9 9
+#define regnum_x10 10
+#define regnum_x11 11
+#define regnum_x12 12
+#define regnum_x13 13
+#define regnum_x14 14
+#define regnum_x15 15
+#define regnum_x16 16
+#define regnum_x17 17
+#define regnum_x18 18
+#define regnum_x19 19
+#define regnum_x20 20
+#define regnum_x21 21
+#define regnum_x22 22
+#define regnum_x23 23
+#define regnum_x24 24
+#define regnum_x25 25
+#define regnum_x26 26
+#define regnum_x27 27
+#define regnum_x28 28
+#define regnum_x29 29
+#define regnum_x30 30
+#define regnum_x31 31
+
+#define regnum_zero 0
+#define regnum_ra 1
+#define regnum_sp 2
+#define regnum_gp 3
+#define regnum_tp 4
+#define regnum_t0 5
+#define regnum_t1 6
+#define regnum_t2 7
+#define regnum_s0 8
+#define regnum_s1 9
+#define regnum_a0 10
+#define regnum_a1 11
+#define regnum_a2 12
+#define regnum_a3 13
+#define regnum_a4 14
+#define regnum_a5 15
+#define regnum_a6 16
+#define regnum_a7 17
+#define regnum_s2 18
+#define regnum_s3 19
+#define regnum_s4 20
+#define regnum_s5 21
+#define regnum_s6 22
+#define regnum_s7 23
+#define regnum_s8 24
+#define regnum_s9 25
+#define regnum_s10 26
+#define regnum_s11 27
+#define regnum_t3 28
+#define regnum_t4 29
+#define regnum_t5 30
+#define regnum_t6 31
+
+// x8 is s0 and also fp
+#define regnum_fp 8
+
+#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
+.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
+
+#define picorv32_getq_insn(_rd, _qs) \
+r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
+
+#define picorv32_setq_insn(_qd, _rs) \
+r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
+
+#define picorv32_retirq_insn() \
+r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
+
+#define picorv32_maskirq_insn(_rd, _rs) \
+r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
+
+#define picorv32_waitirq_insn(_rd) \
+r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
+
+#define picorv32_timer_insn(_rd, _rs) \
+r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
+
diff --git a/verilog/dv/caravel_test/sections.lds b/verilog/dv/caravel_test/sections.lds
new file mode 100644
index 0000000..c328222
--- /dev/null
+++ b/verilog/dv/caravel_test/sections.lds
@@ -0,0 +1,83 @@
+/*
+# 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
+*/
+
+/*
+ *-------------------------------------------------------------------------
+ * Note: This is like the default sections.lds file for Caravel, but moves
+ * the start of SRAM used by the compiler to address 0x80 to make room for
+ * memory used by the firmware routines defined in the local start.S file.
+ *-------------------------------------------------------------------------
+ */
+
+MEMORY {
+ FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x400000 /* 4MB */
+ RAM(xrw) : ORIGIN = 0x00000080, LENGTH = 0x0380 /* 256 words (1 KB) */
+}
+
+SECTIONS {
+ /* The program code and other data goes into FLASH */
+ .text :
+ {
+ . = ALIGN(4);
+ *(.text) /* .text sections (code) */
+ *(.text*) /* .text* sections (code) */
+ *(.rodata) /* .rodata sections (constants, strings, etc.) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+ *(.srodata) /* .srodata sections (constants, strings, etc.) */
+ *(.srodata*) /* .srodata*sections (constants, strings, etc.) */
+ . = ALIGN(4);
+ _etext = .; /* define a global symbol at end of code */
+ _sidata = _etext; /* This is used by the startup to initialize data */
+ } >FLASH
+
+ /* Initialized data section */
+ .data : AT ( _sidata )
+ {
+ . = ALIGN(4);
+ _sdata = .;
+ _ram_start = .;
+ . = ALIGN(4);
+ *(.data)
+ *(.data*)
+ *(.sdata)
+ *(.sdata*)
+ . = ALIGN(4);
+ _edata = .;
+ } >RAM
+
+ /* Uninitialized data section */
+ .bss :
+ {
+ . = ALIGN(4);
+ _sbss = .;
+ *(.bss)
+ *(.bss*)
+ *(.sbss)
+ *(.sbss*)
+ *(COMMON)
+
+ . = ALIGN(4);
+ _ebss = .;
+ } >RAM
+
+ /* Define the start of the heap */
+ .heap :
+ {
+ . = ALIGN(4);
+ _heap_start = .;
+ } >RAM
+}
diff --git a/verilog/dv/caravel_test/start.S b/verilog/dv/caravel_test/start.S
new file mode 100644
index 0000000..ed66ceb
--- /dev/null
+++ b/verilog/dv/caravel_test/start.S
@@ -0,0 +1,217 @@
+/*
+ * 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
+ */
+
+/*-----------------------------------------------*/
+/* Start code that enables and handles IRQs */
+/*-----------------------------------------------*/
+/* Code modified specifically for this testbench */
+/*-----------------------------------------------*/
+
+#undef ENABLE_FASTIRQ
+
+#include "custom_ops.S"
+
+.section .text
+.global irq
+
+reset_vec:
+ j start
+
+.balign 16
+# this interrupt handler adapted from Claire's here:
+# https://raw.githubusercontent.com/cliffordwolf/picorv32/master/firmware/start.S
+irq_vec:
+ /* save registers */
+
+ sw gp, 0*4+0x200(zero)
+ sw x1, 1*4+0x200(zero)
+ sw x2, 2*4+0x200(zero)
+ sw x3, 3*4+0x200(zero)
+ sw x4, 4*4+0x200(zero)
+ sw x5, 5*4+0x200(zero)
+ sw x6, 6*4+0x200(zero)
+ sw x7, 7*4+0x200(zero)
+ sw x8, 8*4+0x200(zero)
+ sw x9, 9*4+0x200(zero)
+ sw x10, 10*4+0x200(zero)
+ sw x11, 11*4+0x200(zero)
+ sw x12, 12*4+0x200(zero)
+ sw x13, 13*4+0x200(zero)
+ sw x14, 14*4+0x200(zero)
+ sw x15, 15*4+0x200(zero)
+ sw x16, 16*4+0x200(zero)
+ sw x17, 17*4+0x200(zero)
+ sw x18, 18*4+0x200(zero)
+ sw x19, 19*4+0x200(zero)
+ sw x20, 20*4+0x200(zero)
+ sw x21, 21*4+0x200(zero)
+ sw x22, 22*4+0x200(zero)
+ sw x23, 23*4+0x200(zero)
+ sw x24, 24*4+0x200(zero)
+ sw x25, 25*4+0x200(zero)
+ sw x26, 26*4+0x200(zero)
+ sw x27, 27*4+0x200(zero)
+ sw x28, 28*4+0x200(zero)
+ sw x29, 29*4+0x200(zero)
+ sw x30, 30*4+0x200(zero)
+ sw x31, 31*4+0x200(zero)
+
+ // call to C function
+ jal ra, irq
+
+ // retire interrupt
+ picorv32_retirq_insn()
+
+.balign 0x200
+irq_regs:
+ // registers are saved to this memory region during interrupt handling
+ // the program counter is saved as register 0
+ .fill 32,4
+
+
+start:
+
+# zero-initialize register file
+addi x1, zero, 0
+# x2 (sp) is initialized by reset
+addi x3, zero, 0
+addi x4, zero, 0
+addi x5, zero, 0
+addi x6, zero, 0
+addi x7, zero, 0
+addi x8, zero, 0
+addi x9, zero, 0
+addi x10, zero, 0
+addi x11, zero, 0
+addi x12, zero, 0
+addi x13, zero, 0
+addi x14, zero, 0
+addi x15, zero, 0
+addi x16, zero, 0
+addi x17, zero, 0
+addi x18, zero, 0
+addi x19, zero, 0
+addi x20, zero, 0
+addi x21, zero, 0
+addi x22, zero, 0
+addi x23, zero, 0
+addi x24, zero, 0
+addi x25, zero, 0
+addi x26, zero, 0
+addi x27, zero, 0
+addi x28, zero, 0
+addi x29, zero, 0
+addi x30, zero, 0
+addi x31, zero, 0
+
+# zero initialize scratchpad memory
+# setmemloop:
+# sw zero, 0(x1)
+# addi x1, x1, 4
+# blt x1, sp, setmemloop
+
+# This part copied from Tim's demo.
+# Write these instructions to memory location zero and following:
+# lui t4, 0x10000 = 10000eb7
+# addi t4, t4, 4 = 0e91
+# jalr t4, 0 = 000e80e7
+#
+# These three instructions jump to 0x10000004, which is the location
+# of the interrupt handler. For a fast interrupt handler, the whole
+# handler should be moved into SRAM.
+li t4, 0x10000eb7
+sw t4, 0(zero)
+li t4, 0x80e70e91
+sw t4, 4(zero)
+li t4, 0x000e
+sw t4, 8(zero)
+
+# Enable the user interrupts only on irq[14:12]
+# needs to be 0 to allow the interrupt
+# https://github.com/efabless/caravel-lite/blob/13f2590e4b3a74b910dac56a6b757f5a66fd5212/verilog/rtl/mgmt_soc.v#L360
+li t4, 0x8FFF
+picorv32_maskirq_insn(t4, t4)
+
+# call main
+call main
+loop:
+j loop
+
+.global flashio_worker_begin
+.global flashio_worker_end
+
+flashio_worker_begin:
+# a0 ... data pointer
+# a1 ... data length
+# a2 ... optional WREN cmd (0 = disable)
+
+# address of SPI ctrl reg
+li t0, 0x02000000
+
+# Set CS high, IO0 is output
+li t1, 0x120
+sh t1, 0(t0)
+
+# Enable Manual SPI Ctrl
+sb zero, 3(t0)
+
+# Send optional WREN cmd
+beqz a2, flashio_worker_L1
+li t5, 8
+andi t2, a2, 0xff
+flashio_worker_L4:
+srli t4, t2, 7
+sb t4, 0(t0)
+ori t4, t4, 0x10
+sb t4, 0(t0)
+slli t2, t2, 1
+andi t2, t2, 0xff
+addi t5, t5, -1
+bnez t5, flashio_worker_L4
+sb t1, 0(t0)
+
+# SPI transfer
+flashio_worker_L1:
+beqz a1, flashio_worker_L3
+li t5, 8
+lbu t2, 0(a0)
+flashio_worker_L2:
+srli t4, t2, 7
+sb t4, 0(t0)
+ori t4, t4, 0x10
+sb t4, 0(t0)
+lbu t4, 0(t0)
+andi t4, t4, 2
+srli t4, t4, 1
+slli t2, t2, 1
+or t2, t2, t4
+andi t2, t2, 0xff
+addi t5, t5, -1
+bnez t5, flashio_worker_L2
+sb t2, 0(a0)
+addi a0, a0, 1
+addi a1, a1, -1
+j flashio_worker_L1
+flashio_worker_L3:
+
+# Back to MEMIO mode
+li t1, 0x80
+sb t1, 3(t0)
+
+ret
+flashio_worker_end:
+
diff --git a/verilog/dv/caravel_test/test_caravel.py b/verilog/dv/caravel_test/test_caravel.py
new file mode 100644
index 0000000..6a3f870
--- /dev/null
+++ b/verilog/dv/caravel_test/test_caravel.py
@@ -0,0 +1,96 @@
+import cocotb
+from cocotb.clock import Clock
+from cocotb.binary import BinaryValue
+from cocotb.triggers import ClockCycles, RisingEdge, FallingEdge;
+from cocotb.result import TestSuccess;
+
+@cocotb.test()
+async def test_start(dut):
+ clock = Clock(dut.clock, 10, units="ns")
+ cocotb.fork(clock.start())
+
+ dut.RSTB <= 0
+ dut.power1 <= 0;
+ dut.power2 <= 0;
+ dut.power3 <= 0;
+ dut.power4 <= 0;
+ dut.uut.mprj.wrapper_sha1.wbs_dat_i.value <= 0;
+
+ dut._log.info("Cycling power");
+ await ClockCycles(dut.clock, 8)
+ dut.power1 <= 1;
+ await ClockCycles(dut.clock, 8)
+ dut.power2 <= 1;
+ await ClockCycles(dut.clock, 8)
+ dut.power3 <= 1;
+ await ClockCycles(dut.clock, 8)
+ dut.power4 <= 1;
+
+ await ClockCycles(dut.clock, 80)
+ dut.RSTB <= 1
+
+ dut._log.info("Waiting for active (This can take a while)");
+ # wait for the project to become active
+ # wrapper.v has .active (la_data_in[32+0])
+ # wrapper.c: reg_la1_ena = 0;
+ # reg_la1_data = 1; /* 0x2500,0004 */
+ await RisingEdge(dut.uut.mprj.wrapper_sha1.active)
+ dut._log.info("Active ON");
+
+async def test_wb(dut, i):
+
+ ack_str = "";
+ addr = int(dut.uut.mprj.wrapper_sha1.wbs_adr_i.value);
+ ack = int(dut.uut.mprj.wrapper_sha1.wbs_ack_o.value);
+ try:
+ data = int(dut.uut.mprj.wrapper_sha1.wbs_dat_o.value);
+ data_i = int(dut.uut.mprj.wrapper_sha1.wbs_dat_i.value);
+ except:
+ dut._log.info("%4d %s %s DATA_IN=RAW[%s] DATA_OUT=%s" % (i, hex(addr), ack_str,
+ dut.uut.mprj.wrapper_sha1.wbs_dat_i.value,
+ dut.uut.mprj.wrapper_sha1.wbs_dat_o.value));
+ pass
+
+ if (addr >= 0x30000024):
+ if (ack == 1):
+ ack_str = "ACK";
+
+ dut._log.info("%4d %s %s DATA_IN=%s DATA_OUT=%s" % (i, hex(addr), ack_str, hex(data_i), hex(data)));
+
+ if (ack == 0):
+ return;
+
+ if (addr == 0x30000024): # CTRL_GET_NR
+ assert(data == 4);
+
+ if (addr == 0x30000028): # CTRL_GET_ID
+ assert(data == 0x53484131);
+
+ if (addr == 0x30000038): # CTRL_PANIC
+ assert (data_i == 0x0badf00d); # It is a write..
+
+ raise TestSuccess
+
+@cocotb.test()
+async def test_values(dut):
+ clock = Clock(dut.clock, 10, units="ns")
+ cocotb.fork(clock.start())
+
+ # wait for the reset (
+ dut._log.info("Waiting for reset");
+
+ # /* .reset(la_data_in[0]) */
+ # reg_la0_ena = 0; /* 0x2500,0010 */
+ # reg_la0_data = 1; /* RST on 0x2500,0000*/
+
+ await RisingEdge(dut.uut.mprj.wrapper_sha1.reset)
+ await FallingEdge(dut.uut.mprj.wrapper_sha1.reset)
+
+ dut._log.info("Reset done");
+
+ await ClockCycles(dut.clock,1)
+
+ for i in range(300000):
+
+ await ClockCycles(dut.clock,1)
+ await test_wb(dut, i);
diff --git a/verilog/dv/caravel_test/wrapper.c b/verilog/dv/caravel_test/wrapper.c
new file mode 100644
index 0000000..edb30cd
--- /dev/null
+++ b/verilog/dv/caravel_test/wrapper.c
@@ -0,0 +1,205 @@
+/*
+ * 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
+ */
+
+#include "verilog/dv/caravel/defs.h"
+#include "verilog/dv/caravel/stub.c"
+
+#define BASE_ADDRESS 0x30000024
+#define CTRL_GET_NR (BASE_ADDRESS + 0x00)
+#define CTRL_GET_ID (BASE_ADDRESS + 0x04)
+#define CTRL_SHA1_OPS (BASE_ADDRESS + 0x08)
+#define CTRL_MSG_IN (BASE_ADDRESS + 0x0C)
+#define CTRL_SHA1_DIGEST (BASE_ADDRESS + 0x10)
+#define CTRL_PANIC (BASE_ADDRESS + 0x14)
+
+#define CTRL_ID 0x53484131
+#define CTRL_NR 4
+
+static uint32_t read(unsigned long addr)
+{
+ return *(volatile uint32_t *)addr;
+}
+
+static void write(unsigned long addr, uint32_t val)
+{
+ *(volatile uint32_t *)addr = val;
+}
+
+
+void configure_gpio(void)
+{
+ reg_mprj_io_37 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_36 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_35 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_34 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_33 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_32 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_31 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_30 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_29 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_28 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_27 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_26 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_25 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_24 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_23 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_22 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_21 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_20 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_19 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_18 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_17 = GPIO_MODE_USER_STD_OUTPUT;
+ reg_mprj_io_16 = GPIO_MODE_USER_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;
+
+ /* Enable user IRQs */
+ reg_mprj_irq = 1;
+}
+
+void activate(void)
+{
+ /* [31:0] is reg_la0_oenb, 0x2500,0010
+ * [63:32] is reg_la1_oenb, 0x2500,0014
+ * [95:64] is reg_la2_oenb 0x2500,0018
+ * [127:96] is reg_la3_oenb 0x2500,001C
+ *
+ * All data go on la_data_in[127:0] , which starts
+ * at 0x2500,0000
+ */
+ reg_la1_iena = 0 << 3; /* 0x25000024: Input enable off */
+ reg_la1_oenb = 0 << 3; /* 0x25000014: 32th, corresponds to active */
+ /* .active() HIGH */
+ reg_la1_data = 1 << 3; /* 0x25000004 */
+}
+
+void reset(void)
+{
+ /* .reset(la_data_in[0]) */
+ reg_la0_iena = 0;
+ reg_la0_oenb = 0; /* 0x2500,0010 */
+
+ reg_la0_data = 1; /* RST on 0x2500,0000*/
+ reg_la0_data = 0; /* RST off */
+}
+
+void panic(uint32_t line)
+{
+ /* TODO: Strobe LEDs or UART. 6/7*/
+ do {
+ write(CTRL_PANIC, line);
+ } while (1);
+
+}
+#define BUG_ON(x) { if ((x)) panic(__LINE__); }
+
+#define MAGIC_VAL 0xdeadbeef
+#define MAGIC_END 0x0badf00d
+
+volatile bool flag;
+
+// gets jumped to from the interrupt handler defined in start.S
+uint32_t *irq()
+{
+ flag = 0;
+
+ write(CTRL_SHA1_OPS, 0); /* Ack the IRQ */
+
+ write(CTRL_PANIC, MAGIC_END);
+}
+
+void wishbone_test(void)
+{
+ uint32_t val, i;
+
+ val = read(CTRL_GET_ID);
+ BUG_ON(val != CTRL_ID);
+
+ val = read(CTRL_GET_NR);
+ BUG_ON(val != CTRL_NR);
+
+ /* The sha1_done should _NOT_ be set */
+ val = read(CTRL_SHA1_OPS);
+ BUG_ON(val & 0x1 == 0x1)
+
+ write(CTRL_MSG_IN, 0x61626380); /* [0]= */
+ for (i = 1; i < 15; i++)
+ write(CTRL_MSG_IN, 0x0);
+
+ write(CTRL_MSG_IN, 0x18); /* [15]= */
+
+ /* The sha1_done should be set */
+ val = read(CTRL_SHA1_OPS);
+ BUG_ON(val & 0x1 != 0x1)
+
+ do {
+ val = read(CTRL_SHA1_OPS);
+ /* [3] will be set when it is done. */
+ if (val & 1 << 3)
+ break;
+ } while (val & 1); /* Spin as long as sha1_on is set */
+
+
+ val = read(CTRL_SHA1_DIGEST);
+ BUG_ON(val != 0xa9993e36);
+
+ val = read(CTRL_SHA1_DIGEST);
+ BUG_ON(val != 0x4706816a);
+
+ val = read(CTRL_SHA1_DIGEST);
+ BUG_ON(val != 0xba3e2571);
+
+ val = read(CTRL_SHA1_DIGEST);
+ BUG_ON(val != 0x7850c26c);
+
+ val = read(CTRL_SHA1_DIGEST);
+ BUG_ON(val != 0x9cd0d89d);
+
+ do {
+ // Spin until IRQ come in (it may already..)
+ } while (flag);
+
+ write(CTRL_PANIC, MAGIC_END);
+}
+
+void main()
+{
+ flag = 1;
+
+ // All GPIO pins are configured to be output
+ configure_gpio();
+
+ /* Apply configuration */
+ reg_mprj_xfer = 1;
+ while (reg_mprj_xfer == 1);
+
+ activate();
+
+ reset();
+
+ wishbone_test();
+ /* There it goes .. */
+
+}
+
diff --git a/verilog/dv/caravel_test/wrapper_tb.v b/verilog/dv/caravel_test/wrapper_tb.v
new file mode 100644
index 0000000..acf68ae
--- /dev/null
+++ b/verilog/dv/caravel_test/wrapper_tb.v
@@ -0,0 +1,87 @@
+// 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" // this file gets created automatically by multi_project_tools from the source section of info.yaml
+`include "caravel_netlists.v"
+`include "spiflash.v"
+
+module wrapper_tb;
+ initial begin
+ $dumpfile ("wrapper_tb.vcd");
+ $dumpvars (0, wrapper_tb);
+ #1;
+ end
+
+ reg clock;
+ reg RSTB;
+ reg power1, power2;
+ reg power3, power4;
+
+ wire gpio;
+ wire [37:0] mprj_io;
+
+ wire flash_csb;
+ wire flash_clk;
+ wire flash_io0;
+ wire flash_io1;
+
+ wire VDD3V3 = power1;
+ wire VDD1V8 = power2;
+ wire USER_VDD3V3 = power3;
+ wire USER_VDD1V8 = power4;
+ wire VSS = 1'b0;
+
+ caravel uut (
+ .vddio (VDD3V3),
+ .vssio (VSS),
+ .vdda (VDD3V3),
+ .vssa (VSS),
+ .vccd (VDD1V8),
+ .vssd (VSS),
+ .vdda1 (USER_VDD3V3),
+ .vdda2 (USER_VDD3V3),
+ .vssa1 (VSS),
+ .vssa2 (VSS),
+ .vccd1 (USER_VDD1V8),
+ .vccd2 (USER_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("wrapper.hex")
+ ) spiflash (
+ .csb(flash_csb),
+ .clk(flash_clk),
+ .io0(flash_io0),
+ .io1(flash_io1),
+ .io2(), // not used
+ .io3() // not used
+ );
+
+endmodule
+`default_nettype wire
diff --git a/verilog/rtl/sha1/src/sha1_wb.v b/verilog/rtl/sha1/src/sha1_wb.v
new file mode 100644
index 0000000..a52e033
--- /dev/null
+++ b/verilog/rtl/sha1/src/sha1_wb.v
@@ -0,0 +1,423 @@
+`default_nettype none
+`timescale 1ns/1ns
+`ifdef FORMAL
+`define MPRJ_IO_PADS 38
+`endif
+`ifdef VERILATOR
+`define MPRJ_IO_PADS 38
+`endif
+
+module sha1_wb #(
+ parameter [31:0] BASE_ADDRESS = 32'h30000024,
+ parameter IDX_WIDTH = 6,
+ parameter DATA_WIDTH = 32
+ ) (
+ input wire reset,
+ input wire [7:0] chicken_bits_in,
+ output wire [15:0] chicken_bits_out,
+ output wire done,
+ output wire irq,
+
+ /* WishBone logic */
+
+ input wire wb_clk_i,
+ input wire wb_rst_i,
+ input wire wbs_stb_i, /* strobe */
+ input wire wbs_cyc_i,
+ input wire wbs_we_i,
+ input wire [3:0] wbs_sel_i,
+ input wire [31:0] wbs_dat_i,
+ input wire [31:0] wbs_adr_i,
+ output wire wbs_ack_o,
+ output wire [31:0] wbs_dat_o
+
+);
+ wire wb_active = wbs_stb_i & wbs_cyc_i;
+
+ reg [31:0] buffer;
+ reg [31:0] buffer_o;
+
+ reg sha1_on;
+ reg sha1_reset;
+ reg sha1_panic;
+ reg sha1_done;
+ wire finish;
+ reg [2:0] sha1_digest_idx;
+ reg [6:0] sha1_msg_idx;
+ reg transmit;
+
+ wire [159:0] digest;
+ reg [DATA_WIDTH-1:0] message[79:0];
+ reg [IDX_WIDTH:0] index;
+
+ localparam STATE_INIT = 0;
+ localparam STATE_START = 1;
+ localparam LOOP_ONE = 2; /* Really 0 <= i <= 19 */
+ localparam LOOP_TWO = 3; /* 20 39 */
+ localparam LOOP_THREE = 4; /* 40 59 */
+ localparam LOOP_FOUR = 5; /* 60 79 */
+ localparam STATE_DONE = 6;
+ localparam STATE_FINAL = 7;
+ localparam STATE_PANIC = 8;
+ reg [3:0] state;
+
+ wire [DATA_WIDTH-1:0] w;
+ wire [DATA_WIDTH-1:0] a_left_5;
+ wire [DATA_WIDTH-1:0] w_left_1;
+ wire [DATA_WIDTH-1:0] b_old_left_30;
+
+ reg [DATA_WIDTH-1:0] a;
+ reg [DATA_WIDTH-1:0] a_old;
+ reg [DATA_WIDTH-1:0] b;
+ reg [DATA_WIDTH-1:0] b_old;
+ reg [DATA_WIDTH-1:0] c;
+ reg [DATA_WIDTH-1:0] c_old;
+ reg [DATA_WIDTH-1:0] d;
+ reg [DATA_WIDTH-1:0] d_old;
+ reg [DATA_WIDTH-1:0] e;
+ reg [DATA_WIDTH-1:0] e_old;
+
+ reg [DATA_WIDTH-1:0] k;
+ reg [DATA_WIDTH-1:0] f;
+ reg [DATA_WIDTH-1:0] temp;
+ reg [DATA_WIDTH-1:0] temp_old;
+
+ reg [DATA_WIDTH-1:0] h0;
+ reg [DATA_WIDTH-1:0] h1;
+ reg [DATA_WIDTH-1:0] h2;
+ reg [DATA_WIDTH-1:0] h3;
+ reg [DATA_WIDTH-1:0] h4;
+
+ reg panic;
+ reg inc_counter;
+ reg copy_values;
+ reg compute;
+
+ /* CTRL_GET parameters. */
+ localparam CTRL_GET_NR = BASE_ADDRESS;
+ localparam CTRL_NR = 4;
+
+ localparam CTRL_GET_ID = BASE_ADDRESS + 'h4;
+ localparam CTRL_ID = 32'h53484131; /* SHA1 */
+ localparam DEFAULT = 32'hf00df00d;
+ /*
+ * When writing: The [2:0] are operations.
+ * When reading: [10:4] in what loop we are [0->79]. [1:0] are operations.
+ */
+ localparam CTRL_SHA1_OPS = BASE_ADDRESS + 'h8;
+ localparam ON = 4'b0001;
+ localparam OFF = 4'b0000;
+ localparam RESET = 4'b0010;
+ localparam PANIC = 4'b0100; /* Can only be read. */
+ localparam DONE = 4'b1000; /* Can only be read. */
+
+ /* This requires 16 CTRL_MSG_IN and after that we start processing. */
+ localparam CTRL_MSG_IN = BASE_ADDRESS + 'hC;
+ localparam ACK = 32'h0000001;
+ localparam EINVAL = 32'hfffffea; /* -14 */
+
+ /* Five reads for the digest. */
+ localparam CTRL_SHA1_DIGEST = BASE_ADDRESS + 'h10;
+ localparam EBUSY = 32'hfffffff0; /* -10 */
+ localparam CTRL_PANIC = BASE_ADDRESS + 'h14;
+
+ always @(posedge wb_clk_i) begin
+ if (reset) begin
+ buffer_o <= DEFAULT;
+ buffer <= DEFAULT;
+ sha1_panic <= 1'b0;
+ transmit <= 1'b0;
+ sha1_msg_idx <= 0;
+ sha1_digest_idx <= 0;
+ sha1_done <= 0;
+ sha1_reset <= 1'b1; /* Reset the SHA1 compute engine */
+ sha1_on <= 1'b0;
+ end else begin
+ if (transmit)
+ transmit <= 1'b0;
+
+ if (sha1_reset) begin
+ sha1_digest_idx <= 0;
+ sha1_reset <= 1'b0;
+ end
+ if (finish)
+ sha1_done <= 1'b1;
+ if (chicken_bits_in) begin
+ case (chicken_bits_in[7:0])
+ 8'b0000_0001: sha1_on <= 1'b1;
+ 8'b0000_0010: sha1_on <= 1'b0;
+ 8'b0000_0100: sha1_reset <= 1'b1;
+ 8'b0000_1000: sha1_reset <= 1'b0;
+ 8'b0001_0000: sha1_panic <= 1'b1;
+ 8'b0010_0000: sha1_panic <= 1'b0;
+ 8'b0100_0000: sha1_done <= 1'b1;
+ 8'b1000_0000: sha1_done <= 1'b0;
+ default: ;
+ endcase
+ end
+ if (wb_active && !wbs_we_i) begin
+ case (wbs_adr_i)
+ CTRL_GET_NR:
+ begin
+ buffer_o <= CTRL_NR;
+ end
+ CTRL_GET_ID:
+ buffer_o <= CTRL_ID;
+ CTRL_MSG_IN:
+ buffer_o <= EINVAL;
+ CTRL_SHA1_OPS:
+ buffer_o <= {21'b0, index, sha1_done, sha1_panic, sha1_reset, sha1_on};
+ CTRL_SHA1_DIGEST:
+ begin
+ if (sha1_done) begin
+ case (sha1_digest_idx)
+ 'h4: buffer_o <= h4;
+ 'h3: buffer_o <= h3;
+ 'h2: buffer_o <= h2;
+ 'h1: buffer_o <= h1;
+ 'h0: buffer_o <= h0;
+ default: sha1_panic <= 1'b1;
+ endcase
+ if (!transmit) begin
+ if (sha1_digest_idx == 4)
+ sha1_digest_idx <= 0;
+ else
+ sha1_digest_idx <= sha1_digest_idx + 1'b1;
+ end
+ end else
+ buffer_o <= EBUSY;
+ end
+ CTRL_PANIC:
+ buffer_o <= {31'b0, sha1_panic};
+ endcase
+ if ((wbs_adr_i[31:0] >= BASE_ADDRESS) && (wbs_adr_i <= CTRL_PANIC))
+ transmit <= 1'b1;
+ end
+ /* Write case */
+ if (wb_active && wbs_we_i && &wbs_sel_i) begin
+ case (wbs_adr_i)
+ CTRL_SHA1_OPS:
+ begin
+ sha1_on <= wbs_dat_i[0];
+ sha1_reset <= wbs_dat_i[1];
+ if (wbs_dat_i[0]) begin
+ sha1_msg_idx <= 0;
+ sha1_done <= 0;
+ sha1_digest_idx <= 0;
+ end
+ buffer_o <= {21'b0, index, sha1_done, sha1_panic, wbs_dat_i[1], wbs_dat_i[0]};
+ end
+ CTRL_MSG_IN:
+ begin
+ if (sha1_on)
+ buffer_o <= EINVAL;
+ else begin
+ buffer_o <= ACK;
+ if (sha1_msg_idx > 15)
+ sha1_panic <= 1'b1;
+ else
+ message[sha1_msg_idx] <= wbs_dat_i;
+ if (!transmit) begin
+ if (sha1_msg_idx == 'hf) begin
+ sha1_on <= 1'b1;
+ sha1_msg_idx <= 0;
+ end else
+ sha1_msg_idx <= sha1_msg_idx + 1'b1;
+ end
+ end
+ end
+ CTRL_PANIC:
+ begin
+ sha1_panic <= 1'b1;
+ buffer <= wbs_dat_i;
+ buffer_o <= ACK;
+ end
+ endcase
+ if ((wbs_adr_i[31:0] >= BASE_ADDRESS) && (wbs_adr_i <= CTRL_PANIC))
+ transmit <= 1'b1;
+ end
+ end
+ end
+
+ always @(posedge wb_clk_i) begin
+ if (reset || sha1_reset) begin
+ state <= STATE_INIT;
+ temp <= DEFAULT;
+ index <= 0;
+ panic <= 0;
+ inc_counter <= 1'b0;
+ copy_values <= 1'b0;
+ compute <= 1'b0;
+ end else begin
+ /* We are running and someone turned it off. */
+ if ((index > 1) && !sha1_on)
+ state <= STATE_INIT;
+
+ /* Never should happen. TODO: Remove*/
+ if (index > 80) begin
+ panic <= 1'b1;
+ state <= STATE_PANIC;
+ end
+ /* Increment if allowed to increment counter. */
+ if (inc_counter) begin
+ index <= index + 1'b1;
+ inc_counter <= 1'b0;
+ end
+ /*
+ * Every LOOP_ call ends up with copying the data, so
+ * make it generic
+ */
+ if (compute) begin
+ a_old <= a;
+ b_old <= b;
+ c_old <= c;
+ d_old <= d;
+ end
+ if (copy_values) begin
+ e <= d_old;
+ d <= c_old;
+ c <= b_old_left_30;
+ b <= a_old;
+ a <= temp;
+ copy_values <= 1'b0;
+ compute <= 1'b1;
+ inc_counter <= 1'b1;
+ end
+ /*
+ * For t = 16 to 79
+ * w[i] = (w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]) leftrotate 1
+ *
+ * This means we need this ready before we get to index=16 hence
+ * the +1 adjustment for every offset.
+ */
+ if (index >= 15) begin
+ message[index+1] <= {(message[index-3+1][30:0] ^ message[index-8+1][30:0] ^
+ message[index-14+1][30:0] ^ message[index-16+1][30:0]),
+ (message[index-3+1][31] ^ message[index-8+1][31] ^
+ message[index-14+1][31] ^ message[index-16+1][31])};
+ end
+ case (state)
+ STATE_INIT: begin
+ if (sha1_on)
+ state <= STATE_START;
+ else
+ state <= STATE_INIT;
+ end
+ STATE_START: begin
+ a <= 32'h67452301;
+ h0 <= 32'h67452301;
+ b <= 32'hEFCDAB89;
+ h1 <= 32'hEFCDAB89;
+ c <= 32'h98BADCFE;
+ h2 <= 32'h98BADCFE;
+ d <= 32'h10325476;
+ h3 <= 32'h10325476;
+ e <= 32'hC3D2E1F0;
+ h4 <= 32'hC3D2E1F0;
+
+ state <= LOOP_ONE;
+ k <= 32'h5A827999;
+ index <= 0;
+ inc_counter <= 1'b1;
+ compute <= 1'b1;
+ copy_values <= 1'b0;
+ end
+
+ LOOP_ONE: begin
+ if ((index == 19) && (inc_counter)) begin
+ state <= LOOP_TWO;
+ k <= 32'h6ED9EBA1;
+ end
+
+ if (compute) begin
+ /* f = (b and c) or ((not b) and d) */
+ /* temp = (a leftrotate 5) + f + e + k + w[i] */
+ temp <= (a_left_5) + ((b & c) | (~b) & d) + e + k + w;
+ copy_values <= 1'b1;
+ compute <= 1'b0;
+ end
+ end
+ LOOP_TWO: begin
+ if ((index == 39) && (inc_counter)) begin
+ state <= LOOP_THREE;
+ k <= 32'h8F1BBCDC;
+ end
+ if (compute) begin
+ /* f = b xor c xor d */
+ /* temp = (a leftrotate 5) + f + e + k + w[i] */
+ temp <= (a_left_5) + (b ^ c ^ d) + e + k + w;
+ copy_values <= 1'b1;
+ compute <= 1'b0;
+ end
+ end
+ LOOP_THREE: begin
+ if ((index == 59) && (inc_counter)) begin
+ state <= LOOP_FOUR;
+ k <= 32'hCA62C1D6;
+ end
+ if (compute) begin
+ /* f = (b and c) or (b and d) or (c and d) */
+ /* temp = (a leftrotate 5) + f + e + k + w[i] */
+ temp <= (a_left_5) + ((b & c) | (b & d) | (c & d)) + e + k + w;
+ copy_values <= 1'b1;
+ compute <= 1'b0;
+ end
+ end
+ LOOP_FOUR: begin
+ if ((index == 79) && (inc_counter)) begin
+ state <= STATE_DONE;
+ k <= DEFAULT;
+ end
+ if (compute) begin
+ /* f = b xor c xor d
+ /* temp = (a leftrotate 5) + f + e + k + w[i] */
+ temp <= (a_left_5) + (b ^ c ^ d) + e + k + w;
+ copy_values <= 1'b1;
+ compute <= 1'b0;
+ end
+ end
+ STATE_DONE: begin
+ index <= 0;
+ inc_counter <= 1'b0;
+ if (compute) begin
+ h0 <= h0 + a;
+ h1 <= h1 + b;
+ h2 <= h2 + c;
+ h3 <= h3 + d;
+ h4 <= h4 + e;
+ state <= STATE_FINAL;
+ copy_values <= 1'b0;
+ compute <= 1'b0;
+ end
+ end
+ STATE_FINAL: begin
+ if (!sha1_on)
+ state <= STATE_INIT;
+ end
+ STATE_PANIC: begin
+ end
+ endcase
+ end
+ end
+
+ assign a_left_5 = {a[26:0], a[31:27]};
+ assign b_old_left_30 = {b_old[1:0], b_old[31:2]};
+
+ /* Provides the w[index] funcionality */
+ assign w = message[index];
+
+ assign digest = {h0, h1, h2, h3, h4};
+
+ assign finish = (state == STATE_FINAL) ? 1'b1 : 1'b0;
+
+ assign wbs_ack_o = reset ? 1'b0 : transmit;
+
+ assign wbs_dat_o = reset ? 32'b0 : buffer_o;
+
+ assign done = reset ? 1'b0 : sha1_done;
+
+ assign irq = reset ? 1'b0: sha1_done;
+
+ assign chicken_bits_out = {buffer_o[14:0], sha1_panic};
+endmodule
+`default_nettype wire
diff --git a/verilog/rtl/sha1/src/wrapper_sha1.v b/verilog/rtl/sha1/src/wrapper_sha1.v
new file mode 100644
index 0000000..4459881
--- /dev/null
+++ b/verilog/rtl/sha1/src/wrapper_sha1.v
@@ -0,0 +1,101 @@
+`default_nettype none
+`timescale 1ns/1ns
+`ifdef FORMAL
+`define MPRJ_IO_PADS 38
+`endif
+`ifdef VERILATOR
+`define MPRJ_IO_PADS 38
+`endif
+module wrapper_sha1 (
+`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
+ // interface as user_proj_example.v
+ input wire wb_clk_i,
+ input wire wb_rst_i,
+ input wire wbs_stb_i, /* strobe */
+ input wire wbs_cyc_i,
+ input wire wbs_we_i,
+ input wire [3:0] wbs_sel_i,
+ input wire [31:0] wbs_dat_i,
+ input wire [31:0] wbs_adr_i,
+ output wire wbs_ack_o,
+ output wire [31:0] wbs_dat_o,
+
+ // Logic Analyzer Signals
+ // only provide first 32 bits to reduce wiring congestion
+ input wire [31:0] la_data_in,
+ output wire [31:0] la_data_out,
+ input wire [31:0] la_oenb,
+
+ // IOs
+ input wire [`MPRJ_IO_PADS-1:0] io_in,
+ output wire [`MPRJ_IO_PADS-1:0] io_out,
+ output wire [`MPRJ_IO_PADS-1:0] io_oeb,
+
+ // IRQ
+ output wire [2:0] irq,
+
+ // active input, only connect tristated outputs if this is high
+ input wire active
+);
+
+ // all outputs must be tristated before being passed onto the project
+ wire buf_wbs_ack_o;
+ wire [31:0] buf_wbs_dat_o;
+ wire [31:0] buf_la_data_out;
+ wire [`MPRJ_IO_PADS-1:0] buf_io_out;
+ wire [`MPRJ_IO_PADS-1:0] buf_io_oeb;
+ wire [2:0] buf_irq;
+
+`ifdef FORMAL
+ // formal can't deal with z, so set all outputs to 0 if not active
+ assign wbs_ack_o = active ? buf_wbs_ack_o : 1'b0;
+ assign wbs_dat_o = active ? buf_wbs_dat_o : 32'b0;
+ assign la_data_out = active ? buf_la_data_out : 32'b0;
+ assign io_out = active ? buf_io_out : {`MPRJ_IO_PADS{1'b0}};
+ assign io_oeb = active ? buf_io_oeb : {`MPRJ_IO_PADS{1'b0}};
+ assign irq = active ? buf_irq : 3'b0;
+`include "properties.v"
+`else
+ // tristate buffers
+ assign wbs_ack_o = active ? buf_wbs_ack_o : 1'bz;
+ assign wbs_dat_o = active ? buf_wbs_dat_o : 32'bz;
+ assign la_data_out = active ? buf_la_data_out : 32'bz;
+ assign io_out = active ? buf_io_out : {`MPRJ_IO_PADS{1'bz}};
+ assign io_oeb = active ? buf_io_oeb : {`MPRJ_IO_PADS{1'bz}};
+ assign irq = active ? buf_irq : 3'bz;
+`endif
+
+ // permanently set oeb so that outputs are always enabled: 0 is output, 1 is high-impedance
+ assign buf_io_oeb = {`MPRJ_IO_PADS{1'b0}};
+
+ wire reset = la_data_in[0];
+
+
+ sha1_wb sha1_wishbone (
+ .reset(reset),
+ .chicken_bits_in(la_data_in[12:5]),
+ .chicken_bits_out(buf_la_data_out[20:5]),
+ .done(buf_io_out[8]),
+ .irq(buf_irq[0]),
+ .wb_clk_i(wb_clk_i),
+ .wb_rst_i(wb_rst_i),
+ .wbs_stb_i(wbs_stb_i),
+ .wbs_cyc_i(wbs_cyc_i),
+ .wbs_we_i(wbs_we_i),
+ .wbs_sel_i(wbs_sel_i),
+ .wbs_dat_i(wbs_dat_i),
+ .wbs_adr_i(wbs_adr_i),
+ .wbs_ack_o(buf_wbs_ack_o),
+ .wbs_dat_o(buf_wbs_dat_o));
+
+endmodule
+`default_nettype wire
diff --git a/verilog/rtl/uprj_netlists.v b/verilog/rtl/uprj_netlists.v
index 3537de8..a74edc1 100644
--- a/verilog/rtl/uprj_netlists.v
+++ b/verilog/rtl/uprj_netlists.v
@@ -1,4 +1,6 @@
-// SPDX-FileCopyrightText: 2020 Efabless Corporation
+// SPDX-FileCopyrightText:
+// 2020 Efabless Corporation
+// 2021 Konrad Rzeszutek Wilk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -21,8 +23,10 @@
// 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"
`else
`include "user_project_wrapper.v"
- `include "user_proj_example.v"
-`endif
\ No newline at end of file
+ // 3 ('SHA1',) : /home/konrad/sha1
+ `include "sha1/src/wrapper_sha1.v"
+ `include "sha1/src/sha1_wb.v"
+
+`endif
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v
index 2a3462b..12d1dec 100644
--- a/verilog/rtl/user_project_wrapper.v
+++ b/verilog/rtl/user_project_wrapper.v
@@ -78,52 +78,50 @@
output [2:0] user_irq
);
-/*--------------------------------------*/
-/* User project is instantiated here */
-/*--------------------------------------*/
+ // instantiate user project here
+ wrapper_sha1 wrapper_sha1(
+ `ifdef USE_POWER_PINS
+ .vdda1(vdda1), // User area 1 3.3V power
+ .vdda2(vdda2), // User area 2 3.3V power
+ .vssa1(vssa1), // User area 1 analog ground
+ .vssa2(vssa2), // User area 2 analog ground
+ .vccd1(vccd1), // User area 1 1.8V power
+ .vccd2(vccd2), // User area 2 1.8V power
+ .vssd1(vssd1), // User area 1 digital ground
+ .vssd2(vssd2), // User area 2 digital ground
+ `endif
-user_proj_example mprj (
- `ifdef USE_POWER_PINS
- .vdda1(vdda1), // User area 1 3.3V power
- .vdda2(vdda2), // User area 2 3.3V power
- .vssa1(vssa1), // User area 1 analog ground
- .vssa2(vssa2), // User area 2 analog ground
- .vccd1(vccd1), // User area 1 1.8V power
- .vccd2(vccd2), // User area 2 1.8V power
- .vssd1(vssd1), // User area 1 digital ground
- .vssd2(vssd2), // User area 2 digital ground
- `endif
+ // interface as user_proj_example.v
+ .wb_clk_i (wb_clk_i),
+ .wb_rst_i (wb_rst_i),
+ .wbs_stb_i (wbs_stb_i),
+ .wbs_cyc_i (wbs_cyc_i),
+ .wbs_we_i (wbs_we_i),
+ .wbs_sel_i (wbs_sel_i),
+ .wbs_dat_i (wbs_dat_i),
+ .wbs_adr_i (wbs_adr_i),
+ .wbs_ack_o (wbs_ack_o),
+ .wbs_dat_o (wbs_dat_o),
- .wb_clk_i(wb_clk_i),
- .wb_rst_i(wb_rst_i),
+ // only provide first 32 bits to reduce wiring congestion
+ .la_data_in (la_data_in [31:0]),
+ .la_data_out(la_data_out[31:0]),
+ .la_oenb (la_oenb[31:0]),
- // MGMT SoC Wishbone Slave
+ // IOs
+ .io_in (io_in),
+ .io_out (io_out),
+ .io_oeb (io_oeb),
- .wbs_cyc_i(wbs_cyc_i),
- .wbs_stb_i(wbs_stb_i),
- .wbs_we_i(wbs_we_i),
- .wbs_sel_i(wbs_sel_i),
- .wbs_adr_i(wbs_adr_i),
- .wbs_dat_i(wbs_dat_i),
- .wbs_ack_o(wbs_ack_o),
- .wbs_dat_o(wbs_dat_o),
+ // IRQs
+ .irq (user_irq),
- // Logic Analyzer
+ // active input, only connect tristated outputs if this is high
+ .active (la_data_in[32+3])
+ );
- .la_data_in(la_data_in),
- .la_data_out(la_data_out),
- .la_oenb (la_oenb),
- // IO Pads
-
- .io_in (io_in),
- .io_out(io_out),
- .io_oeb(io_oeb),
-
- // IRQ
- .irq(user_irq)
-);
+ // end of module instantiation
endmodule // user_project_wrapper
-
`default_nettype wire