Added testbenches for irq, mem, mprj_ctrl, and pass_thru (note that "mem"

does not pass yet and still needs to be debugged).
This commit is contained in:
Tim Edwards 2021-10-18 20:32:50 -04:00
parent 2e57b5da08
commit 0fa2e3bb89
17 changed files with 2038 additions and 8 deletions

View File

@ -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 = irq
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 check-env
vvp $<
%.elf: %.c sections.lds start.S check-env
${GCC_PATH}/${GCC_PREFIX}-gcc -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 > $@
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

View File

@ -0,0 +1,32 @@
<!---
# 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
irq testbench
------------------------------------------------
This testbench demonstrates how to use the interrupts on the
picoRV32. It uses the internal picoRV32 counter to set up an
interval timer. At each timer expiration, an interrupt is
generated, and the assembler code in start.S runs and captures
data from a routine emulating a Digilent PMOD MIC-3 microphone
module. Data are accumulated in a ring buffer reserved in the
top of memory. The main loop of the program queries the
current ring buffer position, reads the data there, and
displays the value on the GPIO (upper 16 of the lower 32 GPIO
channels).

View File

@ -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)

View File

@ -0,0 +1,67 @@
/*
* 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"
// -------------------------------------------------------------------------
// Test IRQ callback
// -------------------------------------------------------------------------
uint16_t flag;
void irq_callback()
{
/* If this routine is called, then the test passes the 1st stage */
reg_mprj_datah = 0xa; // Signal end of test 1st stage
reg_mprj_datal = 0x20000;
flag = 1;
return;
}
void main()
{
uint16_t data;
int i;
// Configure GPIO upper bits to assert the test code
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_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;
/* Apply the GPIO configuration */
reg_mprj_xfer = 1;
while (reg_mprj_xfer == 1);
reg_mprj_datah = 0x5; // Signal start of test
reg_mprj_datal = 0;
flag = 0;
// Loop, waiting for the interrupt to change reg_mprj_datah
while (flag == 0) {
reg_mprj_datal = 0x10000;
}
reg_mprj_datal = 0x40000;
reg_mprj_datah = 0xc; // Signal end of test
}

View File

@ -0,0 +1,172 @@
`default_nettype none
/*
* SPDX-FileCopyrightText: 2017 Clifford Wolf, 2018 Tim Edwards
*
* Caravel - A full example SoC using PicoRV32 in SkyWater sky130
*
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
* Copyright (C) 2021 Tim Edwards <tim@efabless.com>
*
* 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 irq_tb;
reg clock;
reg power1;
reg power2;
always #10 clock <= (clock === 1'b0);
initial begin
clock <= 0;
end
initial begin
$dumpfile("irq.vcd");
$dumpvars(0, irq_tb);
// Repeat cycles of 1000 clock edges as needed to complete testbench
repeat (12) begin
repeat (1000) @(posedge clock);
$display("+1000 cycles");
end
$display("%c[1;31m",27);
`ifdef GL
$display ("Monitor: Timeout, Test IRQ (GL) Failed");
`else
$display ("Monitor: Timeout, Test IRQ (RTL) Failed");
`endif
$display("%c[0m",27);
$finish;
end
wire [37:0] mprj_io; // Most of these are no-connects
wire [3:0] status;
wire [3:0] checkbits;
assign checkbits = mprj_io[19:16];
assign status = mprj_io[35:32];
assign mprj_io[3] = 1'b1; // Force CSB high.
wire flash_csb;
wire flash_clk;
wire flash_io0;
wire flash_io1;
wire gpio;
reg RSTB;
// Monitor
initial begin
wait(status == 4'h5);
`ifdef GL
$display("Monitor: Test IRQ (GL) Started");
`else
$display("Monitor: Test IRQ (RTL) Started");
`endif
wait(status == 4'ha);
wait(status == 4'hc);
`ifdef GL
$display("Monitor: Test IRQ (GL) Passed");
`else
$display("Monitor: Test IRQ (RTL) Passed");
`endif
$finish;
end
initial begin
RSTB <= 1'b0;
#1000;
RSTB <= 1'b1; // Release reset
#2000;
end
initial begin // Power-up
power1 <= 1'b0;
power2 <= 1'b0;
#200;
power1 <= 1'b1;
#200;
power2 <= 1'b1;
end
always @(checkbits, status) begin
#1 $display("GPIO state = %b (%b)", checkbits, status);
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("irq.hex")
) spiflash (
.csb(flash_csb),
.clk(flash_clk),
.io0(flash_io0),
.io1(flash_io1),
.io2(), // not used
.io3() // not used
);
endmodule

View File

@ -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
}

View File

@ -0,0 +1,195 @@
/*
* 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 an IRQ */
/*-----------------------------------------------*/
#undef ENABLE_FASTIRQ
#include "custom_ops.S"
.section .text
.global irq
reset_vec:
j start
/* Interrupt handler @ 0x10000004 */
/* Requires defining a routine called irq_callback in the C code */
.balign 4
irq_vec:
sw gp, 0*4+0x10(zero)
sw t0, 1*4+0x10(zero)
sw t1, 2*4+0x10(zero)
sw t2, 3*4+0x10(zero)
sw t4, 4*4+0x10(zero)
sw t5, 5*4+0x10(zero)
call irq_callback
lw gp, 0*4+0x10(zero)
lw t0, 1*4+0x10(zero)
lw t1, 2*4+0x10(zero)
lw t2, 3*4+0x10(zero)
lw t4, 4*4+0x10(zero)
lw t5, 5*4+0x10(zero)
picorv32_retirq_insn()
irq_regs:
.fill 32,8
/* Main program */
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
# 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 timer IRQ only
li t4, 0xfff0
picorv32_maskirq_insn(t4, t4)
# Set the picorv32 32-bit counter/timer to trigger one interrupt.
li t4, 0x1200
picorv32_timer_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:

View File

@ -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 = mem
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

View File

@ -0,0 +1,92 @@
/*
* 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"
// --------------------------------------------------------
/*
Memory Test
It uses GPIO to flag the success or failure of the test
*/
unsigned int ints[10];
unsigned short shorts[10];
unsigned char bytes[10];
void main()
{
int i;
/* Upper 16 user area pins are configured to be GPIO 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;
// Apply configuration
reg_mprj_xfer = 1;
while (reg_mprj_xfer == 1);
// start test
reg_mprj_datal = 0xA0400000;
// Test Word R/W
for (i=0; i<10; i++)
ints[i] = i*5000 + 10000;
for (i=0; i<10; i++)
if ((i*5000+10000) != ints[i])
reg_mprj_datal = 0xAB400000;
reg_mprj_datal = 0xAB410000;
// Test Half Word R/W
reg_mprj_datal = 0xA0200000;
for (i=0; i<10; i++)
shorts[i] = i*500 + 100;
for(i=0; i<10; i++)
if((i*500+100) != shorts[i])
reg_mprj_datal = 0xAB200000;
reg_mprj_datal = 0xAB210000;
// Test byte R/W
reg_mprj_datal = 0xA0100000;
for(i=0; i<10; i++)
bytes[i] = i*5 + 10;
for(i=0; i<10; i++)
if((i*5+10) != bytes[i])
reg_mprj_datal = 0xAB100000;
reg_mprj_datal = 0xAB110000;
}

View File

@ -0,0 +1,203 @@
`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 <clifford@clifford.at>
* Copyright (C) 2018 Tim Edwards <tim@efabless.com>
*
* 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 mem_tb;
reg clock;
reg RSTB;
reg power1, power2;
wire gpio;
wire [15:0] checkbits;
wire [37:0] mprj_io;
wire flash_csb;
wire flash_clk;
wire flash_io0;
wire flash_io1;
assign checkbits = mprj_io[31:16];
// External clock is used by default. Make this artificially fast for the
// simulation. Normally this would be a slow clock and the digital PLL
// would be the fast clock.
always #10 clock <= (clock === 1'b0);
initial begin
clock = 0;
end
initial begin
$dumpfile("mem.vcd");
$dumpvars(0, mem_tb);
// Repeat cycles of 1000 clock edges as needed to complete testbench
repeat (100) begin
repeat (1000) @(posedge clock);
//$display("+1000 cycles");
end
$display("%c[1;31m",27);
`ifdef GL
$display ("Monitor: Timeout, Test MEM (GL) Failed");
`else
$display ("Monitor: Timeout, Test MEM (RTL) Failed");
`endif
$display("%c[0m",27);
$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'hA040) begin
$display("Mem Test (word rw) started");
end
else if(checkbits == 16'hAB40) begin
$display("%c[1;31m",27);
`ifdef GL
$display("Monitor: Test MEM (GL) [word rw] failed");
`else
$display("Monitor: Test MEM (RTL) [word rw] failed");
`endif
$display("%c[0m",27);
$finish;
end
else if(checkbits == 16'hAB41) begin
`ifdef GL
$display("Monitor: Test MEM (GL) [word rw] passed");
`else
$display("Monitor: Test MEM (RTL) [word rw] passed");
`endif
end
else if(checkbits == 16'hA020) begin
$display("Mem Test (short rw) started");
end
else if(checkbits == 16'hAB20) begin
$display("%c[1;31m",27);
`ifdef GL
$display("Monitor: Test MEM (GL) [short rw] failed");
`else
$display("Monitor: Test MEM (RTL) [short rw] failed");
`endif
$display("%c[0m",27);
$finish;
end
else if(checkbits == 16'hAB21) begin
`ifdef GL
$display("Monitor: Test MEM (GL) [short rw] passed");
`else
$display("Monitor: Test MEM (RTL) [short rw] passed");
`endif
end
else if(checkbits == 16'hA010) begin
$display("Mem Test (byte rw) started");
end
else if(checkbits == 16'hAB10) begin
$display("%c[1;31m",27);
`ifdef GL
$display("Monitor: Test MEM (GL) [byte rw] failed");
`else
$display("Monitor: Test MEM (RTL) [byte rw] failed");
`endif
$display("%c[0m",27);
$finish;
end
else if(checkbits == 16'hAB11) begin
`ifdef GL
$display("Monitor: Test MEM (GL) [byte rw] passed");
`else
$display("Monitor: Test MEM (RTL) [byte rw] passed");
`endif
$finish;
end
end
wire VDD3V3;
wire VDD1V8;
wire VSS;
assign VSS = 1'b0;
assign VDD3V3 = power1;
assign VDD1V8 = power2;
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("mem.hex")
) spiflash (
.csb(flash_csb),
.clk(flash_clk),
.io0(flash_io0),
.io1(flash_io1),
.io2(), // not used
.io3() // not used
);
endmodule
`default_nettype wire

View File

@ -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 = mprj_ctrl
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

View File

@ -0,0 +1,108 @@
/*
* 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"
// --------------------------------------------------------
/*
* User Project IO Control Test
*/
void main()
{
/* All GPIO pins are configured to be output */
/* The lower 28 bits are connected to the user */
/* project to output the counter result, and the */
/* upper 4 bits are connected to the management */
/* SoC to apply values that can be flagged by the */
/* testbench for specific benchmark tests. */
/* GPIOs 31 to 16 are connected to the management SoC */
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;
/* GPIOs 27 to 0 are connected to the user area */
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;
reg_mprj_io_7 = GPIO_MODE_USER_STD_OUTPUT;
reg_mprj_io_6 = GPIO_MODE_USER_STD_OUTPUT;
reg_mprj_io_5 = GPIO_MODE_USER_STD_OUTPUT;
reg_mprj_io_4 = GPIO_MODE_USER_STD_OUTPUT;
// reg_mprj_io_3 = GPIO_MODE_USER_STD_OUTPUT;
reg_mprj_io_2 = GPIO_MODE_USER_STD_OUTPUT;
reg_mprj_io_1 = GPIO_MODE_USER_STD_OUTPUT;
reg_mprj_io_0 = GPIO_MODE_USER_STD_OUTPUT;
// Apply configuration
reg_mprj_xfer = 1;
while (reg_mprj_xfer == 1);
reg_mprj_datal = 0;
// start test
reg_mprj_datal = 0x50000000;
// Write to IO Control
reg_mprj_io_0 = 0x004F;
if (reg_mprj_io_0 != 0x004F)
reg_mprj_datal = 0x60000000;
else
reg_mprj_datal = 0x70000000;
// Write to IO Control
reg_mprj_io_1 = 0x005F;
if (reg_mprj_io_1 != 0x005F)
reg_mprj_datal = 0x80000000;
else
reg_mprj_datal = 0x90000000;
// Write to IO Control
reg_mprj_io_2 = 0x006F;
if (reg_mprj_io_2 != 0x006F)
reg_mprj_datal = 0xA0000000;
else
reg_mprj_datal = 0xb0000000;
// Write to IO Control (NOTE: Only 13 bits are valid)
reg_mprj_io_3 = 0xF0F5;
if (reg_mprj_io_3 != 0x10F5)
reg_mprj_datal = 0xc0000000;
else
reg_mprj_datal = 0xd0000000;
}

View File

@ -0,0 +1,176 @@
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
`timescale 1 ns / 1 ps
`include "__uprj_netlists.v"
`include "caravel_netlists.v"
`include "spiflash.v"
module mprj_ctrl_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] user_io;
wire SDO;
wire [3:0] checkbits;
assign checkbits = user_io[31:28];
// External clock is used by default. Make this artificially fast for the
// simulation. Normally this would be a slow clock and the digital PLL
// would be the fast clock.
always #10 clock <= (clock === 1'b0);
initial begin
clock = 0;
end
initial begin
$dumpfile("mprj_ctrl.vcd");
$dumpvars(0, mprj_ctrl_tb);
repeat (25) begin
repeat (1000) @(posedge clock);
$display("+1000 cycles");
end
$display("%c[1;31m",27);
`ifdef GL
$display ("Monitor: Timeout, Test User Project (GL) Failed");
`else
$display ("Monitor: Timeout, Test User Project (RTL) Failed");
`endif
$display("%c[0m",27);
$finish;
end
always @(checkbits) begin
if(checkbits == 4'h5) begin
$display("User Project control Test started");
end else if(checkbits == 4'h6) begin
$display("%c[1;31m",27);
$display("Monitor: IO control R/W failed (check 6)");
$display("%c[0m",27);
$finish;
end else if(checkbits == 4'h7) begin
$display("Monitor: IO control R/W passed (check 7)");
end else if(checkbits == 4'h8) begin
$display("%c[1;31m",27);
$display("Monitor: power control R/W failed (check 8)");
$display("%c[0m",27);
$finish;
end else if(checkbits == 4'h9) begin
$display("Monitor: power control R/W passed (check 9)");
end else if(checkbits == 4'ha) begin
$display("%c[1;31m",27);
$display("Monitor: power control R/W failed (check 10)");
$display("%c[0m",27);
$finish;
end else if(checkbits == 4'hb) begin
$display("Monitor: power control R/W passed (check 11)");
end else if(checkbits == 4'hc) begin
$display("%c[1;31m",27);
$display("Monitor: power control R/W failed (check 12)");
$display("%c[0m",27);
$finish;
end else if(checkbits == 4'hd) begin
$display("Monitor: power control R/W passed (check 13)");
`ifdef GL
$display("Monitor: User Project control (GL) test passed.");
`else
$display("Monitor: User Project control (RTL) test passed.");
`endif
$finish;
end
end
initial begin
RSTB <= 1'b0;
#1000;
RSTB <= 1'b1; // Release reset
#2000;
end
initial begin
power1 <= 1'b0;
power2 <= 1'b0;
#200;
power1 <= 1'b1;
#200;
power2 <= 1'b1;
end
always @(gpio) begin
#1 $display("GPIO state = %b ", gpio);
end
wire VDD3V3;
wire VDD1V8;
wire VSS;
assign VDD3V3 = power1;
assign VDD1V8 = power2;
assign VSS = 1'b0;
assign user_io[3] = 1'b1;
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 (user_io),
.flash_csb (flash_csb),
.flash_clk (flash_clk),
.flash_io0 (flash_io0),
.flash_io1 (flash_io1),
.resetb (RSTB)
);
spiflash #(
.FILENAME("mprj_ctrl.hex")
) spiflash (
.csb(flash_csb),
.clk(flash_clk),
.io0(flash_io0),
.io1(flash_io1),
.io2(), // not used
.io3() // not used
);
endmodule
`default_nettype wire

View File

@ -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 = 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

View File

@ -0,0 +1,91 @@
/*
* 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;
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;
}

View File

@ -0,0 +1,351 @@
// 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 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 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("pass_thru.vcd");
$dumpvars(0, 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
// Now write a command directly to the SPI flash.
start_csb();
write_byte(8'hc4); // Pass-thru mode
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();
// 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];
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("pass_thru.hex")
) spiflash (
.csb(flash_csb),
.clk(flash_clk),
.io0(flash_io0),
.io1(flash_io1),
.io2(), // not used
.io3() // not used
);
tbuart tbuart (
.ser_rx(uart_tx)
);
endmodule
`default_nettype wire

View File

@ -263,17 +263,17 @@ module housekeeping #(
// Pass-through mode. Housekeeping SPI signals get inserted
// between the management SoC and the flash SPI I/O.
assign pad_flash_csb = (pass_thru_mgmt) ? mgmt_gpio_in[3] : spimemio_flash_csb;
assign pad_flash_csb_oeb = (pass_thru_mgmt) ? 1'b0 : (~porb ? 1'b1 : 1'b0);
assign pad_flash_csb = (pass_thru_mgmt_delay) ? mgmt_gpio_in[3] : spimemio_flash_csb;
assign pad_flash_csb_oeb = (pass_thru_mgmt_delay) ? 1'b0 : (~porb ? 1'b1 : 1'b0);
assign pad_flash_clk = (pass_thru_mgmt) ? mgmt_gpio_in[4] : spimemio_flash_clk;
assign pad_flash_clk_oeb = (pass_thru_mgmt) ? 1'b0 : (~porb ? 1'b1 : 1'b0);
assign pad_flash_io0_oeb = (pass_thru_mgmt) ? 1'b0 : spimemio_flash_io0_oeb;
assign pad_flash_io0_oeb = (pass_thru_mgmt_delay) ? 1'b0 : spimemio_flash_io0_oeb;
assign pad_flash_io1_oeb = (pass_thru_mgmt) ? 1'b1 : spimemio_flash_io1_oeb;
assign pad_flash_io0_ieb = (pass_thru_mgmt) ? 1'b1 : ~spimemio_flash_io0_oeb;
assign pad_flash_io1_ieb = (pass_thru_mgmt) ? 1'b1 : ~spimemio_flash_io1_oeb;
assign pad_flash_io0_do = (pass_thru_mgmt) ? mgmt_gpio_in[2] : spimemio_flash_io0_do;
assign pad_flash_io0_ieb = (pass_thru_mgmt_delay) ? 1'b1 : ~spimemio_flash_io0_oeb;
assign pad_flash_io1_ieb = (pass_thru_mgmt) ? 1'b0 : ~spimemio_flash_io1_oeb;
assign pad_flash_io0_do = (pass_thru_mgmt_delay) ? mgmt_gpio_in[2] : spimemio_flash_io0_do;
assign pad_flash_io1_do = spimemio_flash_io1_do;
assign spimemio_flash_io0_di = (pass_thru_mgmt) ? 1'b0 : pad_flash_io0_di;
assign spimemio_flash_io0_di = (pass_thru_mgmt_delay) ? 1'b0 : pad_flash_io0_di;
assign spimemio_flash_io1_di = (pass_thru_mgmt) ? 1'b0 : pad_flash_io1_di;
// Wishbone bus "back door" to SPI registers. This section of code
@ -715,7 +715,7 @@ module housekeeping #(
: mgmt_gpio_data[10];
assign mgmt_gpio_out_pre[9] = (pass_thru_user) ? mgmt_gpio_in[4]
: mgmt_gpio_data[9];
assign mgmt_gpio_out_pre[8] = (pass_thru_user) ? mgmt_gpio_in[3]
assign mgmt_gpio_out_pre[8] = (pass_thru_user_delay) ? mgmt_gpio_in[3]
: mgmt_gpio_data[8];
assign mgmt_gpio_out_pre[7] = mgmt_gpio_data[7];