From e2f6a0268862f096262a69369db413e8be49225e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 18 Oct 2021 21:53:09 -0400 Subject: [PATCH] Added and verified testbenches timer, timer2, uart, and user_pass_thru. --- verilog/dv/caravel/mgmt_soc/timer/Makefile | 86 ++++ verilog/dv/caravel/mgmt_soc/timer/timer.c | 141 +++++++ verilog/dv/caravel/mgmt_soc/timer/timer_tb.v | 201 +++++++++ verilog/dv/caravel/mgmt_soc/timer2/Makefile | 86 ++++ verilog/dv/caravel/mgmt_soc/timer2/timer2.c | 214 ++++++++++ .../dv/caravel/mgmt_soc/timer2/timer2_tb.v | 229 ++++++++++ verilog/dv/caravel/mgmt_soc/uart/Makefile | 86 ++++ verilog/dv/caravel/mgmt_soc/uart/uart.c | 76 ++++ verilog/dv/caravel/mgmt_soc/uart/uart_tb.v | 150 +++++++ .../caravel/mgmt_soc/user_pass_thru/Makefile | 86 ++++ .../dv/caravel/mgmt_soc/user_pass_thru/README | 14 + .../mgmt_soc/user_pass_thru/user_pass_thru.c | 96 +++++ .../user_pass_thru/user_pass_thru_tb.v | 399 ++++++++++++++++++ verilog/dv/caravel/stub.c | 29 ++ 14 files changed, 1893 insertions(+) create mode 100644 verilog/dv/caravel/mgmt_soc/timer/Makefile create mode 100644 verilog/dv/caravel/mgmt_soc/timer/timer.c create mode 100644 verilog/dv/caravel/mgmt_soc/timer/timer_tb.v create mode 100644 verilog/dv/caravel/mgmt_soc/timer2/Makefile create mode 100644 verilog/dv/caravel/mgmt_soc/timer2/timer2.c create mode 100644 verilog/dv/caravel/mgmt_soc/timer2/timer2_tb.v create mode 100644 verilog/dv/caravel/mgmt_soc/uart/Makefile create mode 100644 verilog/dv/caravel/mgmt_soc/uart/uart.c create mode 100644 verilog/dv/caravel/mgmt_soc/uart/uart_tb.v create mode 100644 verilog/dv/caravel/mgmt_soc/user_pass_thru/Makefile create mode 100644 verilog/dv/caravel/mgmt_soc/user_pass_thru/README create mode 100644 verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru.c create mode 100644 verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru_tb.v create mode 100644 verilog/dv/caravel/stub.c diff --git a/verilog/dv/caravel/mgmt_soc/timer/Makefile b/verilog/dv/caravel/mgmt_soc/timer/Makefile new file mode 100644 index 00000000..e1054c5e --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/timer/Makefile @@ -0,0 +1,86 @@ +# 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 + +PDK_PATH = $(PDK_ROOT)/sky130A +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +BEHAVIOURAL_MODELS = ../../ + +# Temporary: Path to management SoC wrapper repository +MGMT_WRAPPER_PATH = ~/gits/caravel_pico/verilog/rtl + +FIRMWARE_PATH = ../.. +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf + +SIM_DEFINES = -DFUNCTIONAL -DSIM + +SIM?=RTL + +.SUFFIXES: + +PATTERN = timer + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -Ttyp $(SIM_DEFINES) -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(RTL_PATH) -I $(MGMT_WRAPPER_PATH) \ + $< -o $@ +else + iverilog -Ttyp $(SIM_DEFINES) -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s check-env + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -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 > $@ + +check-env: +ifndef PDK_ROOT + $(error PDK_ROOT is undefined, please export it before running make) +endif +ifeq (,$(wildcard $(PDK_ROOT)/sky130A)) + $(error $(PDK_ROOT)/sky130A not found, please install pdk before running make) +endif +ifeq (,$(wildcard $(GCC_PATH)/$(GCC_PREFIX)-gcc )) + $(error $(GCC_PATH)/$(GCC_PREFIX)-gcc is not found, please export GCC_PATH and GCC_PREFIX before running make) +endif +# check for efabless style installation +ifeq (,$(wildcard $(PDK_ROOT)/sky130A/libs.ref/*/verilog)) +SIM_DEFINES := ${SIM_DEFINES} -DEF_STYLE +endif +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all + diff --git a/verilog/dv/caravel/mgmt_soc/timer/timer.c b/verilog/dv/caravel/mgmt_soc/timer/timer.c new file mode 100644 index 00000000..e01ed7f4 --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/timer/timer.c @@ -0,0 +1,141 @@ +/* + * 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 "../../defs.h" + +// -------------------------------------------------------- + +/* + * Timer Test + */ + +void main() +{ + int i; + uint32_t value; + + /* Initialize output data vector to zero */ + reg_mprj_datah = 0x00000000; + reg_mprj_datal = 0x00000000; + + /* Apply all 38 bits to management standard output. */ + + /* The lower 32 will be used to output the count value */ + /* from the timer. The top 5 bits will be used to mark */ + /* specific checkpoints for the testbench simulation. */ + + reg_mprj_io_37 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_36 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_35 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_34 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT; + 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_MGMT_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_MGMT_STD_OUTPUT; + // reg_mprj_io_3 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + /* Present start marker (see testbench verilog) */ + reg_mprj_datah = 0x0a; + + /* Configure timer for a single-shot countdown */ + reg_timer0_value = 0xdcba9876; + + /* Timer configuration bits: */ + /* 0 = timer enable (1 = enabled, 0 = disabled) */ + /* 1 = one-shot mode (1 = oneshot, 0 = continuous) */ + /* 2 = up/down (1 = count up, 0 = count down) */ + /* 3 = chain (1 = enabled, 0 = disabled) */ + /* 4 = IRQ enable (1 = enabled, 0 = disabled) */ + + reg_timer0_config = 3; /* Enabled, one-shot, down count */ + + for (i = 0; i < 8; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_timer0_config = 0; /* Disabled */ + + reg_mprj_datah = 0x01; /* Check value in testbench */ + + reg_timer0_value = 0x00000011; + reg_timer0_config = 7; /* Enabled, one-shot, count up */ + + for (i = 0; i < 3; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x02; /* Check value in testbench */ + + reg_timer0_data = 0x00000101; // Set value (will be reset) + reg_timer0_config = 2; /* Disabled, one-shot, count up */ + reg_timer0_config = 5; /* Enabled, continuous, count down */ + + for (i = 0; i < 5; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x03; /* Check value in testbench */ + + reg_timer0_data = 0x00000145; // Force new value + + reg_mprj_datah = 0x04; /* Check value in testbench */ + + for (i = 0; i < 5; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + /* Present end marker (see testbench verilog) */ + reg_mprj_datah = 0x05; +} + diff --git a/verilog/dv/caravel/mgmt_soc/timer/timer_tb.v b/verilog/dv/caravel/mgmt_soc/timer/timer_tb.v new file mode 100644 index 00000000..a5d21c1b --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/timer/timer_tb.v @@ -0,0 +1,201 @@ +`default_nettype none +/* + * SPDX-FileCopyrightText: 2017 Clifford Wolf, 2018 Tim Edwards + * + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf + * Copyright (C) 2018 Tim Edwards + * + * 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 + */ + +`timescale 1 ns / 1 ps + +`include "__uprj_netlists.v" +`include "caravel_netlists.v" +`include "spiflash.v" + +module timer_tb; + + reg RSTB; + reg clock; + reg power1, power2; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock <= 0; + end + + initial begin + $dumpfile("timer.vcd"); + $dumpvars(0, timer_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (50) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test GPIO (GL) Failed"); + `else + $display ("Monitor: Timeout, Test GPIO (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + wire [37:0] mprj_io; // Most of these are no-connects + wire [5:0] checkbits; + wire [31:0] countbits; + + assign checkbits = mprj_io[37:32]; + assign countbits = mprj_io[31:0]; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire gpio; + + // Monitor + initial begin + wait(checkbits == 6'h0a); + `ifdef GL + $display("Monitor: Test Timer (GL) Started"); + `else + $display("Monitor: Test Timer (RTL) Started"); + `endif + /* Add checks here */ + wait(checkbits == 6'h01); + $display(" countbits = 0x%x (should be 0xdcba7cf9)", countbits); + if(countbits !== 32'hdcba7cf9) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h02); + $display(" countbits = 0x%x (should be 0x19)", countbits); + if(countbits !== 32'h19) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h03); + $display(" countbits = %x (should be 0x0d)", countbits); + if(countbits !== ((32'h0d) | (3'b100))) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h04); + $display(" countbits = %x (should be 0x0d)", countbits); + if(countbits !== ((32'h0d) | (3'b100))) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h05); + $display(" countbits = %x (should be 0x12bc)", countbits); + if(countbits !== 32'h12bc) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + + `ifdef GL + $display("Monitor: Test Timer (GL) Passed"); + `else + $display("Monitor: Test Timer (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + #1 $display("Timer state = %b (%d)", countbits, countbits); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + // These are the mappings of mprj_io GPIO pads that are set to + // specific functions on startup: + // + // JTAG = mgmt_gpio_io[0] (inout) + // SDO = mgmt_gpio_io[1] (output) + // SDI = mgmt_gpio_io[2] (input) + // CSB = mgmt_gpio_io[3] (input) + // SCK = mgmt_gpio_io[4] (input) + // ser_rx = mgmt_gpio_io[5] (input) + // ser_tx = mgmt_gpio_io[6] (output) + // irq = mgmt_gpio_io[7] (input) + + 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("timer.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/dv/caravel/mgmt_soc/timer2/Makefile b/verilog/dv/caravel/mgmt_soc/timer2/Makefile new file mode 100644 index 00000000..c989403a --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/timer2/Makefile @@ -0,0 +1,86 @@ +# 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 + +PDK_PATH = $(PDK_ROOT)/sky130A +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +BEHAVIOURAL_MODELS = ../../ + +# Temporary: Path to management SoC wrapper repository +MGMT_WRAPPER_PATH = ~/gits/caravel_pico/verilog/rtl + +FIRMWARE_PATH = ../.. +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf + +SIM_DEFINES = -DFUNCTIONAL -DSIM + +SIM?=RTL + +.SUFFIXES: + +PATTERN = timer2 + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -Ttyp $(SIM_DEFINES) -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(RTL_PATH) -I $(MGMT_WRAPPER_PATH) \ + $< -o $@ +else + iverilog -Ttyp $(SIM_DEFINES) -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s check-env + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -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 > $@ + +check-env: +ifndef PDK_ROOT + $(error PDK_ROOT is undefined, please export it before running make) +endif +ifeq (,$(wildcard $(PDK_ROOT)/sky130A)) + $(error $(PDK_ROOT)/sky130A not found, please install pdk before running make) +endif +ifeq (,$(wildcard $(GCC_PATH)/$(GCC_PREFIX)-gcc )) + $(error $(GCC_PATH)/$(GCC_PREFIX)-gcc is not found, please export GCC_PATH and GCC_PREFIX before running make) +endif +# check for efabless style installation +ifeq (,$(wildcard $(PDK_ROOT)/sky130A/libs.ref/*/verilog)) +SIM_DEFINES := ${SIM_DEFINES} -DEF_STYLE +endif +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all + diff --git a/verilog/dv/caravel/mgmt_soc/timer2/timer2.c b/verilog/dv/caravel/mgmt_soc/timer2/timer2.c new file mode 100644 index 00000000..6d598ace --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/timer2/timer2.c @@ -0,0 +1,214 @@ +/* + * 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 "../../defs.h" + +// -------------------------------------------------------- + +/* + * Timer2 Test --- This runs the same testbench as the + * other timer, on the 2nd counter/timer module instance. + */ + +void main() +{ + int i; + uint32_t value; + + /* Initialize output data vector to zero */ + reg_mprj_datah = 0x00000000; + reg_mprj_datal = 0x00000000; + + /* Apply all 38 bits to management standard output. */ + + /* The lower 32 will be used to output the count value */ + /* from the timer. The top 5 bits will be used to mark */ + /* specific checkpoints for the testbench simulation. */ + + reg_mprj_io_37 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_36 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_35 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_34 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT; + 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_MGMT_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_MGMT_STD_OUTPUT; + // reg_mprj_io_3 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + /* Present start marker (see testbench verilog) */ + reg_mprj_datah = 0x0a; + + /* Configure timer for a single-shot countdown */ + reg_timer1_value = 0xdcba9876; + + /* Timer configuration bits: */ + /* 0 = timer enable (1 = enabled, 0 = disabled) */ + /* 1 = one-shot mode (1 = oneshot, 0 = continuous) */ + /* 2 = up/down (1 = count up, 0 = count down) */ + /* 3 = IRQ enable (1 = enabled, 0 = disabled) */ + + reg_timer1_config = 3; /* Enabled, one-shot, down count */ + + for (i = 0; i < 8; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_timer1_config = 0; /* Disabled */ + + reg_mprj_datah = 0x01; /* Check value in testbench */ + + reg_timer1_value = 0x00000011; + reg_timer1_config = 7; /* Enabled, one-shot, count up */ + + for (i = 0; i < 3; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x02; /* Check value in testbench */ + + reg_timer1_data = 0x00000101; // Set value (will be reset) + reg_timer1_config = 2; /* Disabled, one-shot, count up */ + reg_timer1_config = 5; /* Enabled, continuous, count down */ + + for (i = 0; i < 5; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x03; /* Check value in testbench */ + + reg_timer1_data = 0x00000145; // Force new value + + reg_mprj_datah = 0x04; /* Check value in testbench */ + + for (i = 0; i < 5; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x05; /* Check value in testbench */ + + /* Now, set up chained 64 bit timer. Check count-up */ + /* value and count-down value crossing the 32-bit */ + /* boundary. */ + + /* First disable both counters, and set the "chained" */ + /* property so that enable/disable will be synchronized */ + + reg_timer1_config = 8; /* Disabled, chained */ + reg_timer0_config = 8; /* Disabled, chained */ + + /* Configure timer for a chained single-shot countdown. */ + /* Count start = 0x0000000100001000, end = 0x0 */ + + reg_timer1_value = 0x00000055; + reg_timer0_value = 0x00001000; + + /* Timer configuration bits: */ + /* 0 = timer enable (1 = enabled, 0 = disabled) */ + /* 1 = one-shot mode (1 = oneshot, 0 = continuous) */ + /* 2 = up/down (1 = count up, 0 = count down) */ + /* 3 = chain (1 = enabled, 0 = disabled) */ + /* 4 = IRQ enable (1 = enabled, 0 = disabled) */ + + reg_timer1_config = 11; /* Enabled, one-shot, down count, chained */ + reg_timer0_config = 11; /* Enabled, one-shot, down count, chained */ + + for (i = 0; i < 1; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x06; /* Check value in testbench */ + + // Skip to the end. . . + reg_timer1_data = 0x00000000; + reg_timer0_data = 0x00000200; + + for (i = 0; i < 4; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x07; /* Check value in testbench */ + + reg_timer1_config = 14; /* Disabled, one-shot, up count, chained */ + reg_timer0_config = 14; /* Disabled, one-shot, up count, chained */ + + reg_timer1_value = 0x00000002; + reg_timer0_value = 0x00000000; + + reg_timer1_config = 15; /* Enabled, one-shot, up count, chained */ + reg_timer0_config = 15; /* Enabled, one-shot, up count, chained */ + + for (i = 0; i < 1; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x08; /* Check value in testbench */ + + // Skip to the end. . . + /* Count 0x00000001ffffff00 to 0x0000000200000000 and stop */ + + reg_timer1_data = 0x00000001; // Set value (will be reset) + reg_timer0_data = 0xffffff00; // Set value (will be reset) + + for (i = 0; i < 4; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put timer1 count value on GPIO + } + + /* Present end marker (see testbench verilog) */ + reg_mprj_datah = 0x10; +} + diff --git a/verilog/dv/caravel/mgmt_soc/timer2/timer2_tb.v b/verilog/dv/caravel/mgmt_soc/timer2/timer2_tb.v new file mode 100644 index 00000000..09917738 --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/timer2/timer2_tb.v @@ -0,0 +1,229 @@ +`default_nettype none +/* + * SPDX-FileCopyrightText: 2017 Clifford Wolf, 2018 Tim Edwards + * + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf + * Copyright (C) 2018 Tim Edwards + * + * 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 + */ + +`timescale 1 ns / 1 ps + +`include "__uprj_netlists.v" +`include "caravel_netlists.v" +`include "spiflash.v" + +module timer2_tb; + + reg clock; + reg RSTB; + reg power1, power2; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock <= 0; + end + + initial begin + $dumpfile("timer2.vcd"); + $dumpvars(0, timer2_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (60) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test Timer2 (GL) Failed"); + `else + $display ("Monitor: Timeout, Test Timer2 (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + wire [37:0] mprj_io; // Most of these are no-connects + wire [5:0] checkbits; + wire [31:0] countbits; + + assign checkbits = mprj_io[37:32]; + assign countbits = mprj_io[31:0]; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire gpio; + + // Monitor + initial begin + wait(checkbits == 6'h0a); + `ifdef GL + $display("Monitor: Test Timer2 (GL) Started"); + `else + $display("Monitor: Test Timer2 (RTL) Started"); + `endif + /* Add checks here */ + wait(checkbits == 6'h01); + $display(" countbits = 0x%x (should be 0xdcba7cf9)", countbits); + if(countbits !== 32'hdcba7cf9) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h02); + $display(" countbits = 0x%x (should be 0x19)", countbits); + if(countbits !== 32'h19) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h03); + $display(" countbits = %x (should be 0x0d)", countbits); + if(countbits !== 32'h0d) begin + $display("Monitor: Test Timer (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h04); + $display(" countbits = %x (should be 0x0d)", countbits); + if(countbits !== 32'h0d) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h05); + $display(" countbits = %x (should be 0x12bc)", countbits); + if(countbits !== 32'h12bc) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h06); + $display(" countbits = %x (should be 0x005d)", countbits); + if(countbits !== 32'h005d) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h07); + $display(" countbits = %x (should be 0x0008)", countbits); + if(countbits !== 32'h0008) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h08); + $display(" countbits = %x (should be 0x0259)", countbits); + if(countbits !== 32'h0259) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h10); + $display(" countbits = %x (should be 0x0008)", countbits); + if(countbits !== 32'h0008) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + `ifdef GL + $display("Monitor: Test Timer2 (GL) Passed"); + `else + $display("Monitor: Test Timer2 (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + #1 $display("Timer state = %b (%d)", countbits, countbits); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + // These are the mappings of mprj_io GPIO pads that are set to + // specific functions on startup: + // + // JTAG = mgmt_gpio_io[0] (inout) + // SDO = mgmt_gpio_io[1] (output) + // SDI = mgmt_gpio_io[2] (input) + // CSB = mgmt_gpio_io[3] (input) + // SCK = mgmt_gpio_io[4] (input) + // ser_rx = mgmt_gpio_io[5] (input) + // ser_tx = mgmt_gpio_io[6] (output) + // irq = mgmt_gpio_io[7] (input) + + 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("timer2.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/dv/caravel/mgmt_soc/uart/Makefile b/verilog/dv/caravel/mgmt_soc/uart/Makefile new file mode 100644 index 00000000..eb047159 --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/uart/Makefile @@ -0,0 +1,86 @@ +# 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 + +PDK_PATH = $(PDK_ROOT)/sky130A +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +BEHAVIOURAL_MODELS = ../../ + +# Temporary: Path to management SoC wrapper repository +MGMT_WRAPPER_PATH = ~/gits/caravel_pico/verilog/rtl + +FIRMWARE_PATH = ../.. +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf + +SIM_DEFINES = -DFUNCTIONAL -DSIM + +SIM?=RTL + +.SUFFIXES: + +PATTERN = uart + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -Ttyp $(SIM_DEFINES) -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(RTL_PATH) -I $(MGMT_WRAPPER_PATH) \ + $< -o $@ +else + iverilog -Ttyp $(SIM_DEFINES) -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s check-env + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -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 > $@ + +check-env: +ifndef PDK_ROOT + $(error PDK_ROOT is undefined, please export it before running make) +endif +ifeq (,$(wildcard $(PDK_ROOT)/sky130A)) + $(error $(PDK_ROOT)/sky130A not found, please install pdk before running make) +endif +ifeq (,$(wildcard $(GCC_PATH)/$(GCC_PREFIX)-gcc )) + $(error $(GCC_PATH)/$(GCC_PREFIX)-gcc is not found, please export GCC_PATH and GCC_PREFIX before running make) +endif +# check for efabless style installation +ifeq (,$(wildcard $(PDK_ROOT)/sky130A/libs.ref/*/verilog)) +SIM_DEFINES := ${SIM_DEFINES} -DEF_STYLE +endif +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all + diff --git a/verilog/dv/caravel/mgmt_soc/uart/uart.c b/verilog/dv/caravel/mgmt_soc/uart/uart.c new file mode 100644 index 00000000..13cee0f9 --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/uart/uart.c @@ -0,0 +1,76 @@ +/* + * 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 "../../defs.h" +#include "../../stub.c" + +// -------------------------------------------------------- + +void main() +{ + int j; + + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output + + 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_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Set clock to 64 kbaud and enable the UART. It is important to do this + // before applying the configuration, or else the Tx line initializes as + // zero, which indicates the start of a byte to the receiver. + + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Now, apply the configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xa0000000; + + // This should appear at the output, received by the testbench UART. + // (Makes simulation time long.) + print("Monitor: Test UART (RTL) passed\n"); + + // Allow transmission to complete before signalling that the program + // has ended. + for (j = 0; j < 20; j++); + reg_mprj_datal = 0xab000000; +} diff --git a/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v b/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v new file mode 100644 index 00000000..d8bbd35e --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/uart/uart_tb.v @@ -0,0 +1,150 @@ +`default_nettype none +/* + * SPDX-FileCopyrightText: 2017 Clifford Wolf, 2018 Tim Edwards + * + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf + * Copyright (C) 2018 Tim Edwards + * + * 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 + */ + +`timescale 1 ns / 1 ps + +`include "__uprj_netlists.v" +`include "caravel_netlists.v" +`include "spiflash.v" +`include "tbuart.v" + +module uart_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire [37:0] mprj_io; + wire [15:0] checkbits; + wire uart_tx; + wire SDO; + + 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("uart.vcd"); + $dumpvars(0, uart_tb); + + $display("Wait for UART o/p"); + repeat (150) begin + repeat (10000) @(posedge clock); + // Diagnostic. . . interrupts output pattern. + end + $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 + + always @(checkbits) begin + if(checkbits == 16'hA000) begin + $display("UART Test started"); + end + else if(checkbits == 16'hAB00) begin + `ifdef GL + $display("UART Test (GL) passed"); + `else + $display("UART Test (RTL) passed"); + `endif + $finish; + end + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + 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("uart.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/dv/caravel/mgmt_soc/user_pass_thru/Makefile b/verilog/dv/caravel/mgmt_soc/user_pass_thru/Makefile new file mode 100644 index 00000000..5804c11b --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/user_pass_thru/Makefile @@ -0,0 +1,86 @@ +# 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 + +PDK_PATH = $(PDK_ROOT)/sky130A +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +BEHAVIOURAL_MODELS = ../../ + +# Temporary: Path to management SoC wrapper repository +MGMT_WRAPPER_PATH = ~/gits/caravel_pico/verilog/rtl + +FIRMWARE_PATH = ../.. +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf + +SIM_DEFINES = -DFUNCTIONAL -DSIM + +SIM?=RTL + +.SUFFIXES: + +PATTERN = user_pass_thru + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -Ttyp $(SIM_DEFINES) -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(RTL_PATH) -I $(MGMT_WRAPPER_PATH) \ + $< -o $@ +else + iverilog -Ttyp $(SIM_DEFINES) -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s check-env + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -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 > $@ + +check-env: +ifndef PDK_ROOT + $(error PDK_ROOT is undefined, please export it before running make) +endif +ifeq (,$(wildcard $(PDK_ROOT)/sky130A)) + $(error $(PDK_ROOT)/sky130A not found, please install pdk before running make) +endif +ifeq (,$(wildcard $(GCC_PATH)/$(GCC_PREFIX)-gcc )) + $(error $(GCC_PATH)/$(GCC_PREFIX)-gcc is not found, please export GCC_PATH and GCC_PREFIX before running make) +endif +# check for efabless style installation +ifeq (,$(wildcard $(PDK_ROOT)/sky130A/libs.ref/*/verilog)) +SIM_DEFINES := ${SIM_DEFINES} -DEF_STYLE +endif +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all + diff --git a/verilog/dv/caravel/mgmt_soc/user_pass_thru/README b/verilog/dv/caravel/mgmt_soc/user_pass_thru/README new file mode 100644 index 00000000..e4072d66 --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/user_pass_thru/README @@ -0,0 +1,14 @@ +------------------------------------ +user_pass_thru test bench +------------------------------------ + +This test bench exercises the pass-thru mode to the GPIO pins +that are reserved for use by a user project for connecting to +an SPI flash. The pass-thru mode allows the SPI flash to be +programmed using the housekeeping SPI. + +The testbench is essentially the same as the pass_thru test +bench, but using the pins specified for the secondary SPI +flash. Note that the testbench does not define a controller +on the user side to access the SPI flash (which would be a +useful thing to add to the testbench). diff --git a/verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru.c b/verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru.c new file mode 100644 index 00000000..011102c0 --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru.c @@ -0,0 +1,96 @@ +/* + * 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 "../../defs.h" + +// -------------------------------------------------------- + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} + +// -------------------------------------------------------- + +void main() +{ + // This program is just to keep the processor busy while the + // housekeeping SPI is being accessed. to show that the + // processor is halted while the SPI is accessing the + // flash SPI in pass-through mode. + + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output + + 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; + + // Management needs to apply output on these pads to access the user area SPI flash + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xa0000000; + + // Set clock to 64 kbaud and enable the UART + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Test in progress + reg_mprj_datal = 0xa5000000; + + // Test message + print("Test message\n"); + + // End test + reg_mprj_datal = 0xab000000; +} + diff --git a/verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru_tb.v b/verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru_tb.v new file mode 100644 index 00000000..b7532b8a --- /dev/null +++ b/verilog/dv/caravel/mgmt_soc/user_pass_thru/user_pass_thru_tb.v @@ -0,0 +1,399 @@ +// 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 +/* + * StriVe housekeeping pass-thru mode SPI testbench. + */ + +`timescale 1 ns / 1 ps + +`include "__uprj_netlists.v" +`include "caravel_netlists.v" +`include "spiflash.v" +`include "tbuart.v" + +module user_pass_thru_tb; + reg clock; + reg SDI, CSB, SCK, RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [37:0] mprj_io; + wire uart_tx; + wire uart_rx; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + + wire user_csb; + wire user_clk; + wire user_io0; + wire user_io1; + + wire SDO; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + // The main testbench is here. Put the housekeeping SPI into + // pass-thru mode and read several bytes from the flash SPI. + + // First define tasks for SPI functions + + task start_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b0; + #50; + end + endtask + + task end_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b1; + #50; + end + endtask + + task write_byte; + input [7:0] odata; + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_byte; + output [7:0] idata; + begin + SCK <= 1'b0; + SDI <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_write_byte + (input [7:0] odata, + output [7:0] idata); + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + integer i; + + // Now drive the digital signals on the housekeeping SPI + reg [7:0] tbdata; + + initial begin + $dumpfile("user_pass_thru.vcd"); + $dumpvars(0, user_pass_thru_tb); + + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + #2000; + + RSTB <= 1'b1; + + // Wait on start of program execution + wait(checkbits == 16'hA000); + + // First do a normal read from the housekeeping SPI to + // make sure the housekeeping SPI works. + + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) + read_byte(tbdata); + end_csb(); + #10; + + $display("Read data = 0x%02x (should be 0x11)", tbdata); + if(tbdata !== 8'h11) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + + // The SPI flash may need to be reset. + start_csb(); + write_byte(8'hc2); // Apply user pass-thru command to housekeeping SPI + write_byte(8'hff); // SPI flash command ff + end_csb(); + + start_csb(); + write_byte(8'hc2); // Apply user pass-thru command to housekeeping SPI + write_byte(8'hab); // SPI flash command ab + end_csb(); + + start_csb(); + write_byte(8'hc2); // Apply user pass-thru command to housekeeping SPI + write_byte(8'h03); // Command 03 (read values w/3-byte address) + write_byte(8'h00); // Address is next three bytes (0x000000) + write_byte(8'h00); + write_byte(8'h00); + + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x93)", tbdata); + if(tbdata !== 8'h93) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x93)", tbdata); + if(tbdata !== 8'h93) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x01)", tbdata); + if(tbdata !== 8'h01) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + + end_csb(); + + // Reset processor + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h0b); // Address (register 11 = reset) + write_byte(8'h01); // Data (value 1 = apply reset) + end_csb(); + + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h0b); // Address (register 11 = reset) + write_byte(8'h00); // Data (value 1 = apply reset) + end_csb(); + + // Wait for processor to restart + wait(checkbits == 16'hA000); + + // Read product ID register again + + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) + read_byte(tbdata); + end_csb(); + #10; + $display("Read data = 0x%02x (should be 0x11)", tbdata); + if(tbdata !== 8'h11) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Passed"); + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Passed"); + `endif + + #10000; + $finish; + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + wire hk_sck; + wire hk_csb; + wire hk_sdi; + + assign hk_sck = SCK; + assign hk_csb = CSB; + assign hk_sdi = SDI; + + assign checkbits = mprj_io[31:16]; + assign uart_tx = mprj_io[6]; + assign mprj_io[5] = uart_rx; + assign mprj_io[4] = hk_sck; + assign mprj_io[3] = hk_csb; + assign mprj_io[2] = hk_sdi; + assign SDO = mprj_io[1]; + + assign user_csb = mprj_io[8]; + assign user_clk = mprj_io[9]; + assign user_io0 = mprj_io[10]; + assign mprj_io[11] = user_io1; + + 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("user_pass_thru.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + + // Use the same flash; this is just to put known data in memory that can be + // checked by reading it back through a pass-through command. + spiflash #( + .FILENAME("user_pass_thru.hex") + ) secondary ( + .csb(user_csb), + .clk(user_clk), + .io0(user_io0), + .io1(user_io1), + .io2(), // not used + .io3() // not used + ); + + + tbuart tbuart ( + .ser_rx(uart_tx) + ); + +endmodule +`default_nettype wire diff --git a/verilog/dv/caravel/stub.c b/verilog/dv/caravel/stub.c new file mode 100644 index 00000000..575cfc38 --- /dev/null +++ b/verilog/dv/caravel/stub.c @@ -0,0 +1,29 @@ +/* + * 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 + */ + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} \ No newline at end of file