updated readme, info and user_project_wrapper.v
diff --git a/README.md b/README.md
index 15727b1..5137b51 100644
--- a/README.md
+++ b/README.md
@@ -1,149 +1,87 @@
-<!---
-# SPDX-FileCopyrightText: 2020 Efabless Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# SPDX-License-Identifier: Apache-2.0
--->
-# CIIC Harness  
+# Multi Project Harness - mpw-one-b
 
-A template SoC for Google SKY130 free shuttles. It is still WIP. The current SoC architecture is given below.
+* This is a proposal for handling multiple projects in the user project area of the [Caravel harness](https://github.com/efabless/caravel)
+* This is a fork of caravel with https://github.com/mattvenn/multi-project-harness/tree/separate-macro added to /verilog/rtl/
+* user_project_wrapper is then adjusted to instantiate all the submodules.
 
-<p align="center">
-<img src="/doc/ciic_harness.png" width="75%" height="75%"> 
-</p>
+![multi project harness](doc/multi-project-harness.png)
 
+# Important!
 
-## Getting Started:
+* If you want to actually build the wrapper, you need to checkout the release branch.
+* This branch is just used to rebuild caravel.gds with 'make ship'
 
-* For information on tooling and versioning, please refer to [this][1].
+# Tests
 
-Start by cloning the repo and uncompressing the files.
-```bash
-git clone https://github.com/efabless/caravel.git
-cd caravel
-make uncompress
-```
+* Full system tests for each sub project: verilog/dv/caravel/user_proj_example
+* Separate projects: run make sim in root directory of multi_project_harness: https://github.com/mattvenn/multi-project-harness/blob/separate-macro/test_harness.py
 
-Then you need to install the open_pdks prerequisite:
- - [Magic VLSI Layout Tool](http://opencircuitdesign.com/magic/index.html) is needed to run open_pdks -- version >= 8.3.60*
+# OpenLane Configs
 
- > \* Note: You can avoid the need for the magic prerequisite by using the openlane docker to do the installation step in open_pdks. This could be done by cloning [openlane](https://github.com/efabless/openlane/tree/master) and following the instructions given there to use the Makefile.
+All the OpenLane configs for each project are here: https://github.com/mattvenn/multi-project-harness/tree/main/openlane/macroconfig
 
-Install the required version of the PDK by running the following commands:
+# Submodules
 
-```bash
-export PDK_ROOT=<The place where you want to install the pdk>
-make pdk
-```
+## seven-segment-seconds
 
-Then, you can learn more about the caravel chip by watching these video:
-- Caravel User Project Features -- https://youtu.be/zJhnmilXGPo
-- Aboard Caravel -- How to put your design on Caravel? -- https://youtu.be/9QV8SDelURk
-- Things to Clarify About Caravel -- What versions to use with Caravel? -- https://youtu.be/-LZ522mxXMw
-    - You could only use openlane:rc6
-    - Make sure you have the commit hashes provided here inside the [Makefile](./Makefile)
-## Aboard Caravel:
+description: shows seconds on a seven segment LED display.
 
-Your area is the full user_project_wrapper, so feel free to add your project there or create a differnt macro and harden it seperately then insert it into the user_project_wrapper. For example, if your design is analog or you're using a different tool other than OpenLANE.
+author: Matt Venn
 
-If you will use OpenLANE to harden your design, go through the instructions in this [README.md][0].
+url: https://github.com/mattvenn/seven-segment-seconds
 
-You must copy your synthesized gate-level-netlist for `user_project_wrapper` to `verilog/gl/` and overwrite `user_project_wrapper.v`. Otherwise, you can point to it in [info.yaml](info.yaml).
+## ws2812
 
-> Note: If you're using openlane to harden your design, this should happen automatically.
+description: ws2812 LED interface for 8 addressable LEDs
 
-Then, you will need to put your design aboard the Caravel chip. Make sure you have the following:
+author: Matt Venn
 
-- [Magic VLSI Layout Tool](http://opencircuitdesign.com/magic/index.html) installed on your machine. We may provide a Dockerized version later.\*
-- You have your user_project_wrapper.gds under `./gds/` in the Caravel directory.
+url: https://github.com/mattvenn/ws2812-core.git
 
- > \* **Note:** You can avoid the need for the magic prerequisite by using the openlane docker to run the make step. This [section](#running-make-using-openlane-magic) shows how.
+## vga-clock
 
-Run the following command:
+description: show the time on a VGA panel
 
-```bash
-export PDK_ROOT=<The place where the installed pdk resides. The same PDK_ROOT used in the pdk installation step>
-make
-```
+author: Matt Venn
 
-This should merge the GDSes using magic and you'll end up with your version of `./gds/caravel.gds`. You should expect ~90 magic DRC violations with the current "development" state of caravel.
+url: https://github.com/mattvenn/vga-clock.git
 
-## Running Make using OpenLANE Magic
+## spinet
 
-To use the magic installed inside Openlane to complete the final GDS streaming out step, export the following:
+description: multi node computer controller
 
-```bash
-export PDK_ROOT=<The location where the pdk is installed>
-export OPENLANE_ROOT=<the absolute path to the openlane directory cloned or to be cloned>
-export IMAGE_NAME=<the openlane image name installed on your machine. Preferably openlane:rc6>
-export CARAVEL_PATH=$(pwd)
-```
+author: Richard Miller
 
-Then, mount the docker:
+url: https://github.com/millerresearch/spinet
 
-```bash
-docker run -it -v $CARAVEL_PATH:$CARAVEL_PATH -v $OPENLANE_ROOT:/openLANE_flow -v $PDK_ROOT:$PDK_ROOT -e CARAVEL_PATH=$CARAVEL_PATH -e PDK_ROOT=$PDK_ROOT -u $(id -u $USER):$(id -g $USER) $IMAGE_NAME
-```
+## asicfreq
 
-Finally, once inside the docker run the following commands:
-```bash
-cd $CARAVEL_PATH
-make
-exit
-```
+description: Frequency counter
 
-This should merge the GDSes using magic and you'll end up with your version of `./gds/caravel.gds`. You should expect ~90 magic DRC violations with the current "development" state of caravel.
+author: Michael Betz & Vamsi Vytla
 
+url: https://git.sr.ht/~jersey99/asicfreq
 
-## IMPORTANT:
+## ASIC_watch
 
-Please make sure to run `make compress` before commiting anything to your repository. Avoid having 2 versions of the gds/user_project_wrapper.gds or gds/caravel.gds one compressed and the other not compressed.
+description: 4 digit 7 segment clock
 
-## Required Directory Structure
+author: Guillem Cabo
 
-- ./gds/ : includes all the gds files used or produced from the project.
-- ./def/ : includes all the def files used or produced from the project.
-- ./lef/ : includes all the lef files used or produced from the project.
-- ./mag/ : includes all the mag files used or produced from the project.
-- ./maglef/ : includes all the maglef files used or produced from the project.
-- ./spi/lvs/ : includes all the maglef files used or produced from the project.
-- ./verilog/dv/ : includes all the simulation test benches and how to run them. 
-- ./verilog/gl/ : includes all the synthesized/elaborated netlists. 
-- ./verilog/rtl/ : includes all the Verilog RTLs and source files.
-- ./openlane/`<macro>`/ : includes all configuration files used to run openlane on your project.
-- info.yaml: includes all the info required in [this example](info.yaml). Please make sure that you are pointing to an elaborated caravel netlist as well as a synthesized gate-level-netlist for the user_project_wrapper
+url: https://github.com/GuillemCabo/ASIC_watch.git
 
-## Managment SoC
-The managment SoC runs firmware that can be used to:
-- Configure User Project I/O pads
-- Observe and control User Project signals (through on-chip logic analyzer probes)
-- Control the User Project power supply
+## TPM2137
 
-The memory map of the management SoC can be found [here](verilog/rtl/README)
+description: Reverse Engineering challenge
 
-## User Project Area
-This is the user space. It has limited silicon area (TBD, about 3.1mm x 3.8mm) as well as a fixed number of I/O pads (37) and power pads (10).  See [the Caravel  premliminary datasheet](doc/caravel_datasheet.pdf) for details.
-The repository contains a [sample user project](/verilog/rtl/user_proj_example.v) that contains a binary 32-bit up counter.  </br>
+author: Q3K
 
-<p align="center">
-<img src="/doc/counter_32.png" width="50%" height="50%">
-</p>
+url: https://github.com/mattvenn/TPM2137
 
-The firmware running on the Management Area SoC, configures the I/O pads used by the counter and uses the logic probes to observe/control the counter. Three firmware examples are provided:
-1. Configure the User Project I/O pads as o/p. Observe the counter value in the testbench: [IO_Ports Test](verilog/dv/caravel/user_proj_example/io_ports).
-2. Configure the User Project I/O pads as o/p. Use the Chip LA to load the counter and observe the o/p till it reaches 500: [LA_Test1](verilog/dv/caravel/user_proj_example/la_test1).
-3. Configure the User Project I/O pads as o/p. Use the Chip LA to control the clock source and reset signals and observe the counter value for five clock cylcles:  [LA_Test2](verilog/dv/caravel/user_proj_example/la_test2).
+## mm2hdmi
 
-[0]: openlane/README.md
-[1]: mpw-one-b.md
+description: HDMI driver
+
+author: Aleksandar Pajkanovic
+
+url: https://github.com/nanoluka/mm2hdmi.git
diff --git a/doc/multi-project-harness.png b/doc/multi-project-harness.png
new file mode 100644
index 0000000..4e6967f
--- /dev/null
+++ b/doc/multi-project-harness.png
Binary files differ
diff --git a/info.yaml b/info.yaml
index 685ee5e..fa59949 100644
--- a/info.yaml
+++ b/info.yaml
@@ -1,13 +1,13 @@
 --- 
 project: 
-  description: "A template SoC for Google sponsored Open MPW shuttles for SKY130."
+  description: "multi project harness"
   foundry: "SkyWater"
-  git_url: "https://github.com/efabless/caravel.git"
-  organization: "Efabless"
-  organization_url: "http://efabless.com"
-  owner: "Tim Edwards"
+  git_url: "https://github.com/mattvenn/caravel-mph"
+  organization: "Matt Venn"
+  organization_url: ""
+  owner: "Matt Venn"
   process: "SKY130"
-  project_name: "Caravel"
+  project_name: "multi project harness"
   tags: 
     - "Open MPW"
     - "Test Harness"
@@ -15,4 +15,4 @@
   top_level_netlist: "verilog/gl/caravel.v"
   user_level_netlist: "verilog/gl/user_project_wrapper.v"
   version: "1.00"
-  cover_image: "doc/ciic_harness.png"
+  cover_image: "doc/multi-project-harness.png"
diff --git a/verilog/dv/caravel/user_proj_example/.gitignore b/verilog/dv/caravel/user_proj_example/.gitignore
new file mode 100644
index 0000000..2e7e861
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/.gitignore
@@ -0,0 +1,2 @@
+*vcd
+*hex
diff --git a/verilog/dv/caravel/user_proj_example/ASIC_watch/ASIC_watch.c b/verilog/dv/caravel/user_proj_example/ASIC_watch/ASIC_watch.c
new file mode 100644
index 0000000..323d860
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ASIC_watch/ASIC_watch.c
@@ -0,0 +1,66 @@
+#include "../../defs.h"
+
+#define PROJECT 5
+#define NB_OUTPUTS 28
+
+#define reg_mprj_oeb0 (*(volatile uint32_t*)0x30000004)
+#define reg_mprj_oeb1 (*(volatile uint32_t*)0x30000008)
+#define reg_mprj_ws2812 (*(volatile uint32_t*)0x30000500)
+/*
+	IO Test:
+		- Configures MPRJ pins
+*/
+
+void main()
+{
+	/*
+	IO Control Registers
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 3-bits | 1-bit | 1-bit | 1-bit  | 1-bit  | 1-bit | 1-bit   | 1-bit   | 1-bit | 1-bit | 1-bit   |
+	Output: 0000_0110_0000_1110  (0x1808) = GPIO_MODE_USER_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 0       |
+	Output: 0000_0110_0000_1111  (0x1809) = GPIO_MODE_MGNT_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 1       |
+
+
+	Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 001    | 0     | 0     | 0      | 0      | 0     | 0       | 0       | 0     | 1     | 0       |
+	*/
+
+    /*
+    Inputs
+    36 - Safe mode
+    37 - 2^15Hz crystal clock
+
+    Outputs
+    8  - 14 segment_hxxx
+    15 - 21 segment_xhxx
+    22 - 28 segment_xxmx
+    29 - 35 segment_xxxm
+    */
+    volatile uint32_t *io = &reg_mprj_io_0;
+    for (int i = 8 ; i < 8+NB_OUTPUTS ; i++) {
+        io[i] = GPIO_MODE_USER_STD_OUTPUT;
+    }
+
+    io[36] = GPIO_MODE_USER_STD_INPUT_NOPULL;
+    io[37] = GPIO_MODE_USER_STD_INPUT_NOPULL;
+    
+    /* Apply configuration */
+    reg_mprj_xfer = 1;
+    while (reg_mprj_xfer == 1);
+
+    // change to project
+    reg_mprj_slave = PROJECT;
+
+    reg_mprj_oeb1 = (1 << 4) + (1 << 5); //GPIO 36 and 37 as inputs
+
+    // use logic analyser bit 0 as reset
+    reg_la0_ena  = 0x00000000; // bits 31:0 outputs
+    reg_la0_data = 0x00000001; // reset high is on bit 0
+    reg_la0_data = 0x00000000; // low
+
+}
diff --git a/verilog/dv/caravel/user_proj_example/ASIC_watch/ASIC_watch_tb.v b/verilog/dv/caravel/user_proj_example/ASIC_watch/ASIC_watch_tb.v
new file mode 100644
index 0000000..9951781
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ASIC_watch/ASIC_watch_tb.v
@@ -0,0 +1,162 @@
+`default_nettype none
+
+`timescale 1 ns / 1 ps
+
+`include "caravel.v"
+`include "spiflash.v"
+
+module ASIC_watch_tb;
+    reg clock;
+    reg RSTB;
+    reg power1, power2;
+    reg power3, power4;
+
+    wire gpio;
+    wire [37:0] mprj_io;
+    // inputs
+    reg clk_32768;
+    reg safemode;
+
+    // outputs
+    wire [6:0] segment_hxxx;
+    wire [6:0] segment_xhxx;
+    wire [6:0] segment_xxhx;
+    wire [6:0] segment_xxxh;
+
+    assign segment_hxxx[0] = uut.gpio_control_in[8].pad_gpio_out;
+    assign segment_hxxx[1] = uut.gpio_control_in[9].pad_gpio_out;
+    assign segment_hxxx[2] = uut.gpio_control_in[10].pad_gpio_out;
+    assign segment_hxxx[3] = uut.gpio_control_in[11].pad_gpio_out;
+    assign segment_hxxx[4] = uut.gpio_control_in[12].pad_gpio_out;
+    assign segment_hxxx[5] = uut.gpio_control_in[13].pad_gpio_out;
+    assign segment_hxxx[6] = uut.gpio_control_in[14].pad_gpio_out;
+
+    assign segment_xhxx[0] = uut.gpio_control_in[15].pad_gpio_out;
+    assign segment_xhxx[1] = uut.gpio_control_in[16].pad_gpio_out;
+    assign segment_xhxx[2] = uut.gpio_control_in[17].pad_gpio_out;
+    assign segment_xhxx[3] = uut.gpio_control_in[18].pad_gpio_out;
+    assign segment_xhxx[4] = uut.gpio_control_in[19].pad_gpio_out;
+    assign segment_xhxx[5] = uut.gpio_control_in[20].pad_gpio_out;
+    assign segment_xhxx[6] = uut.gpio_control_in[21].pad_gpio_out;
+
+    assign segment_xxhx[0] = uut.gpio_control_in[22].pad_gpio_out;
+    assign segment_xxhx[1] = uut.gpio_control_in[23].pad_gpio_out;
+    assign segment_xxhx[2] = uut.gpio_control_in[24].pad_gpio_out;
+    assign segment_xxhx[3] = uut.gpio_control_in[25].pad_gpio_out;
+    assign segment_xxhx[4] = uut.gpio_control_in[26].pad_gpio_out;
+    assign segment_xxhx[5] = uut.gpio_control_in[27].pad_gpio_out;
+    assign segment_xxhx[6] = uut.gpio_control_in[28].pad_gpio_out;
+
+    assign segment_xxxh[0] = uut.gpio_control_in[29].pad_gpio_out;
+    assign segment_xxxh[1] = uut.gpio_control_in[30].pad_gpio_out;
+    assign segment_xxxh[2] = uut.gpio_control_in[31].pad_gpio_out;
+    assign segment_xxxh[3] = uut.gpio_control_in[32].pad_gpio_out;
+    assign segment_xxxh[4] = uut.gpio_control_in[33].pad_gpio_out;
+    assign segment_xxxh[5] = uut.gpio_control_in[34].pad_gpio_out;
+    assign segment_xxxh[6] = uut.gpio_control_in[35].pad_gpio_out;
+
+    assign mprj_io[36] = safemode ;
+    assign mprj_io[37] = clk_32768;
+
+    // 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 #12.5 clock <= (clock === 1'b0);
+    always #12.5 clk_32768 <= (clk_32768 === 1'b0);
+
+    initial begin
+        clock = 0;
+        clk_32768 = 0;
+        safemode = 0;
+    end
+
+
+    initial begin
+        $dumpfile("ASIC_watch.vcd");
+        $dumpvars(0, ASIC_watch_tb);
+
+        // Repeat cycles of 1000 clock edges as needed to complete testbench
+        repeat (15) begin
+            repeat (1000) @(posedge clock);
+            // $display("+1000 cycles");
+        end
+        $display("%c[1;31m",27);
+        $display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed");
+        $display("%c[0m",27);
+        $finish;
+    end
+
+    initial begin
+        RSTB <= 1'b0;
+        #2000;
+        RSTB <= 1'b1;       // Release reset
+    end
+
+    initial begin       // Power-up sequence
+        power1 <= 1'b0;
+        power2 <= 1'b0;
+        power3 <= 1'b0;
+        power4 <= 1'b0;
+        #200;
+        power1 <= 1'b1;
+        #200;
+        power2 <= 1'b1;
+        #200;
+        power3 <= 1'b1;
+        #200;
+        power4 <= 1'b1;
+    end
+
+    wire flash_csb;
+    wire flash_clk;
+    wire flash_io0;
+    wire flash_io1;
+
+    wire VDD1V8;
+    wire VDD3V3;
+    wire VSS;
+
+    assign VDD3V3 = power1;
+    assign VDD1V8 = power2;
+    wire USER_VDD3V3 = power3;
+    wire USER_VDD1V8 = power4;
+    assign VSS = 1'b0;
+
+    caravel uut (
+        .vddio    (VDD3V3),
+        .vssio    (VSS),
+        .vdda     (VDD3V3),
+        .vssa     (VSS),
+        .vccd     (VDD1V8),
+        .vssd     (VSS),
+        .vdda1    (USER_VDD3V3),
+        .vdda2    (USER_VDD3V3),
+        .vssa1    (VSS),
+        .vssa2    (VSS),
+        .vccd1    (USER_VDD1V8),
+        .vccd2    (USER_VDD1V8),
+        .vssd1    (VSS),
+        .vssd2    (VSS),
+        .clock    (clock),
+        .gpio     (gpio),
+        .mprj_io  (mprj_io),
+        .flash_csb(flash_csb),
+        .flash_clk(flash_clk),
+        .flash_io0(flash_io0),
+        .flash_io1(flash_io1),
+        .resetb   (RSTB)
+    );
+
+    spiflash #(
+        .FILENAME("ASIC_watch.hex")
+    ) spiflash (
+        .csb(flash_csb),
+        .clk(flash_clk),
+        .io0(flash_io0),
+        .io1(flash_io1),
+        .io2(),         // not used
+        .io3()          // not used
+    );
+
+endmodule
diff --git a/verilog/dv/caravel/user_proj_example/ASIC_watch/Makefile b/verilog/dv/caravel/user_proj_example/ASIC_watch/Makefile
new file mode 100644
index 0000000..2a55901
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ASIC_watch/Makefile
@@ -0,0 +1,42 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+#MP_PATH = ../../../../rtl/multi_project_harness
+BEHAVIOURAL_MODELS = ../../ 
+
+TOOLCHAIN_PREFIX?=/opt/riscv32ic/bin/riscv32-unknown-elf-
+PDK_PATH?=/home/bscuser/hacking/skywater-pdk
+
+.SUFFIXES:
+
+PATTERN = ASIC_watch
+
+all:  ${PATTERN:=.vcd}
+
+hex:  ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+	$(TOOLCHAIN_PREFIX)gcc -mabi=ilp32 -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
+
+%.hex: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O verilog $< $@
+	# to fix flash base address
+	sed -i 's/@10000000/@00000000/g' $@
+
+%.bin: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
+
+# ---- Clean ----
+
+clean:
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/Makefile b/verilog/dv/caravel/user_proj_example/Makefile
index 7e37e02..6b5248c 100644
--- a/verilog/dv/caravel/user_proj_example/Makefile
+++ b/verilog/dv/caravel/user_proj_example/Makefile
@@ -1,19 +1,3 @@
-# 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
-
 # ---- Test patterns for project striVe ----
 
 .SUFFIXES:
diff --git a/verilog/dv/caravel/user_proj_example/README.md b/verilog/dv/caravel/user_proj_example/README.md
index 503b8f4..244df05 100644
--- a/verilog/dv/caravel/user_proj_example/README.md
+++ b/verilog/dv/caravel/user_proj_example/README.md
@@ -1,20 +1,3 @@
-<!---
-# 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
--->
 # Mega-Project Counter Tests
 
 The directory includes three tests for the counter mega-project example: 
diff --git a/verilog/dv/caravel/user_proj_example/asicfreq/Makefile b/verilog/dv/caravel/user_proj_example/asicfreq/Makefile
new file mode 100644
index 0000000..7b5d620
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/asicfreq/Makefile
@@ -0,0 +1,44 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+BEHAVIOURAL_MODELS = ../../
+
+TOOLCHAIN_PREFIX?=riscv32-unknown-elf-
+PDK_PATH?=$(PDK_ROOT)/sky130A
+
+.SUFFIXES:
+
+PATTERN = asicfreq
+
+all:  ${PATTERN:=.vcd}
+
+hex:  ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(RTL_PATH) \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+	$(TOOLCHAIN_PREFIX)gcc -mabi=ilp32 -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
+
+%.lst: %.elf
+	$(TOOLCHAIN_PREFIX)objdump -d $< > $@
+
+%.hex: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O verilog $< $@
+	# to fix flash base address
+	sed -i 's/@10000000/@00000000/g' $@
+
+%.bin: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
+
+# ---- Clean ----
+
+clean:
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq.c b/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq.c
new file mode 100644
index 0000000..85d8e25
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq.c
@@ -0,0 +1,70 @@
+#include "../../defs.h"
+
+// Test asicfreq frequency counter and 7-segment display interface
+
+#define reg_mprj_address_oeb0    (*(volatile uint32_t*)0x30000004)
+#define reg_mprj_address_oeb1    (*(volatile uint32_t*)0x30000008)
+
+#define reg_mprj_asicfreq_uart_div    (*(volatile uint32_t*)0x30000400)
+//   write UART clock divider (min. value = 4),
+
+#define reg_mprj_asicfreq_meas_period (*(volatile uint32_t*)0x30000404)
+//   write frequency counter update period [sys_clks]
+
+#define reg_mprj_asicfreq_7seg_mode   (*(volatile uint32_t*)0x30000408)
+//   set 7-segment display mode,
+//   0: show meas. freq., 1: show wishbone value
+
+#define reg_mprj_asicfreq_7seg_digit0 (*(volatile uint32_t*)0x3000040C)
+//   set 7-segment display value:
+//   digit7 ... digit0  (4 bit each)
+
+#define reg_mprj_asicfreq_7seg_digit1 (*(volatile uint32_t*)0x30000410)
+//   set 7-segment display value:
+//   digit8
+
+#define reg_mprj_asicfreq_7seg_decs   (*(volatile uint32_t*)0x30000414)
+//   set 7-segment decimal points:
+//   dec_point8 ... dec_point0  (1 bit each)
+
+#define reg_mprj_asicfreq_cnt         (*(volatile uint32_t*)0x30000418)
+//   read number of SUT edges over `meas_period`
+
+#define reg_mprj_asicfreq_cnt_cont    (*(volatile uint32_t*)0x3000041C)
+//   read number of SUT edges since reset
+
+int main()
+{
+    // Setup GPIOs
+    reg_mprj_io_6 = GPIO_MODE_USER_STD_OUTPUT;
+    volatile uint32_t *io = &reg_mprj_io_8;
+    for (unsigned i=0; i<17; i++)
+        io[i] = GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_25 = GPIO_MODE_USER_STD_INPUT_NOPULL;
+
+    // Apply configuration
+    reg_mprj_xfer = 1;
+    while (reg_mprj_xfer == 1);
+
+    // enable MPH outputs (all expect mprj_io[25], which is the SUT)
+    reg_mprj_address_oeb0 = (1 << 25);
+
+    // change to project 4
+    reg_mprj_slave = 4;
+
+    // use logic analyser to reset the design
+    reg_la0_ena  = 0x00000000; // bits 31:0 outputs
+    reg_la0_data = 0x00000001; // reset high is on bit 0
+    reg_la0_data = 0x00000000; // low
+
+    // write to 7 segment
+    reg_mprj_asicfreq_7seg_mode = 1;
+    reg_mprj_asicfreq_7seg_digit0 = 0xDEADBEEF;
+
+    // nonsense statement, to demonstrate wb reading works
+    // checked by testbench
+    reg_mprj_asicfreq_meas_period = reg_mprj_asicfreq_cnt_cont;
+
+    return 0;
+}
+
diff --git a/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq.gtkw b/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq.gtkw
new file mode 100644
index 0000000..9ffbc64
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq.gtkw
@@ -0,0 +1,86 @@
+[dumpfile] "asicfreq.vcd"
+[timestart] 520440000
+[size] 2044 1108
+[pos] -1 -1
+*-22.000000 548687500 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] asicfreq_tb.
+[treeopen] asicfreq_tb.uut.
+[treeopen] asicfreq_tb.uut.mprj.
+[treeopen] asicfreq_tb.uut.mprj.mprj.
+[treeopen] asicfreq_tb.uut.mprj.mprj.proj_4.
+[treeopen] asicfreq_tb.uut.soc.
+[treeopen] asicfreq_tb.uut.soc.soc.
+[treeopen] asicfreq_tb.uut.soc.soc.cpu.
+[treeopen] asicfreq_tb.uut.soc.soc.cpu.picorv32_core.
+[sst_width] 285
+[signals_width] 363
+[sst_expanded] 1
+[sst_vpaned_height] 432
+@800200
+-CPU
+@22
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_insn_addr[31:0]
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_addr[31:0]
+@28
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_instr
+@22
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_rdata[31:0]
+@28
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_ready
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_valid
+@22
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_wdata[31:0]
+asicfreq_tb.uut.soc.soc.cpu.picorv32_core.dbg_mem_wstrb[3:0]
+@1000200
+-CPU
+@22
+asicfreq_tb.uut.mprj.mprj.active_project[7:0]
+@800200
+-proj_4
+@28
+asicfreq_tb.uut.mprj.mprj.proj_4.rst
+@200
+-
+@29
+asicfreq_tb.uut.mprj.mprj.proj_4.strobe
+@22
+asicfreq_tb.uut.mprj.mprj.proj_4.addr[3:0]
+asicfreq_tb.uut.mprj.mprj.proj_4.value[31:0]
+@200
+-
+@22
+asicfreq_tb.uut.mprj.mprj.proj_4.oc[31:0]
+asicfreq_tb.uut.mprj.mprj.proj_4.o[31:0]
+asicfreq_tb.uut.mprj.mprj.proj_4.f_meter_period[31:0]
+asicfreq_tb.uut.mprj.mprj.proj_4.f_meter.period_counter[31:0]
+@200
+-
+@22
+asicfreq_tb.uut.mprj.mprj.proj_4.col_drvs[8:0]
+@28
+asicfreq_tb.uut.mprj.mprj.proj_4.seg_man_mode
+@22
+asicfreq_tb.uut.mprj.mprj.proj_4.seg_man_value[35:0]
+@c00022
+asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+@28
+(0)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(1)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(2)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(3)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(4)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(5)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(6)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+(7)asicfreq_tb.uut.mprj.mprj.proj_4.seven_seg_seg_drvs[7:0]
+@1401200
+-group_end
+@200
+-
+@820
+asicfreq_tb.uut.mprj.mprj.proj_4.serial.uart.tx_data[7:0]
+@28
+asicfreq_tb.uut.mprj.mprj.proj_4.serial_tx_out
+@1000200
+-proj_4
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq_tb.v b/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq_tb.v
new file mode 100644
index 0000000..932500a
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/asicfreq/asicfreq_tb.v
@@ -0,0 +1,130 @@
+`default_nettype none
+
+`timescale 1 ns / 1 ps
+
+`include "caravel.v"
+`include "spiflash.v"
+
+module asicfreq_tb;
+    reg clock;
+    reg RSTB;
+    reg power1, power2;
+    reg power3, power4;
+
+    wire gpio;
+    wire [37:0] mprj_io;
+
+    // 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 #12.5 clock <= (clock === 1'b0);
+
+    initial begin
+        clock = 0;
+    end
+
+    initial begin
+        $dumpfile("asicfreq.vcd");
+        $dumpvars(0, asicfreq_tb);
+
+        // Repeat cycles of 1000 clock edges as needed to complete testbench
+        repeat (44) begin
+            repeat (1000) @(posedge clock);
+            // $display("+1000 cycles");
+        end
+        $display("%c[1;31m",27);
+        $display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed");
+        $display("%c[0m",27);
+        $stop;
+    end
+
+    // apply a clock to the signal under test (SUT) pin
+    assign mprj_io[25] = clock;
+
+    // Check the last statement in the C program
+    always @(posedge clock) begin
+        if (
+            uut.mprj.mprj.proj_4.strobe &&
+            uut.mprj.mprj.proj_4.addr == 32'h1 &&
+            uut.mprj.mprj.proj_4.value >= 32'h300
+            // uut.mprj.mprj.proj_4.value == (uut.mprj.mprj.proj_4.oc - 32'h8)
+        ) begin
+            $display("PASS");
+            $finish;
+        end
+    end
+
+    initial begin
+        RSTB <= 1'b0;
+        #2000;
+        RSTB <= 1'b1;       // Release reset
+    end
+
+    initial begin       // Power-up sequence
+        power1 <= 1'b0;
+        power2 <= 1'b0;
+        power3 <= 1'b0;
+        power4 <= 1'b0;
+        #200;
+        power1 <= 1'b1;
+        #200;
+        power2 <= 1'b1;
+        #200;
+        power3 <= 1'b1;
+        #200;
+        power4 <= 1'b1;
+    end
+
+    wire flash_csb;
+    wire flash_clk;
+    wire flash_io0;
+    wire flash_io1;
+
+    wire VDD1V8;
+    wire VDD3V3;
+    wire VSS;
+
+    assign VDD3V3 = power1;
+    assign VDD1V8 = power2;
+    wire USER_VDD3V3 = power3;
+    wire USER_VDD1V8 = power4;
+    assign VSS = 1'b0;
+
+    caravel uut (
+        .vddio    (VDD3V3),
+        .vssio    (VSS),
+        .vdda     (VDD3V3),
+        .vssa     (VSS),
+        .vccd     (VDD1V8),
+        .vssd     (VSS),
+        .vdda1    (USER_VDD3V3),
+        .vdda2    (USER_VDD3V3),
+        .vssa1    (VSS),
+        .vssa2    (VSS),
+        .vccd1    (USER_VDD1V8),
+        .vccd2    (USER_VDD1V8),
+        .vssd1    (VSS),
+        .vssd2    (VSS),
+        .clock    (clock),
+        .gpio     (gpio),
+            .mprj_io  (mprj_io),
+        .flash_csb(flash_csb),
+        .flash_clk(flash_clk),
+        .flash_io0(flash_io0),
+        .flash_io1(flash_io1),
+        .resetb   (RSTB)
+    );
+
+    spiflash #(
+        .FILENAME("asicfreq.hex")
+    ) spiflash (
+        .csb(flash_csb),
+        .clk(flash_clk),
+        .io0(flash_io0),
+        .io1(flash_io1),
+        .io2(),         // not used
+        .io3()          // not used
+    );
+
+endmodule
diff --git a/verilog/dv/caravel/user_proj_example/io_ports/io_ports.c b/verilog/dv/caravel/user_proj_example/io_ports/io_ports.c
index a159f0a..f6a829d 100644
--- a/verilog/dv/caravel/user_proj_example/io_ports/io_ports.c
+++ b/verilog/dv/caravel/user_proj_example/io_ports/io_ports.c
@@ -1,20 +1,3 @@
-/*
- * 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"
 
 /*
diff --git a/verilog/dv/caravel/user_proj_example/io_ports/io_ports_tb.v b/verilog/dv/caravel/user_proj_example/io_ports/io_ports_tb.v
index c680a0b..63b7c93 100644
--- a/verilog/dv/caravel/user_proj_example/io_ports/io_ports_tb.v
+++ b/verilog/dv/caravel/user_proj_example/io_ports/io_ports_tb.v
@@ -1,18 +1,3 @@
-// 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
diff --git a/verilog/dv/caravel/user_proj_example/la_test1/Makefile b/verilog/dv/caravel/user_proj_example/la_test1/Makefile
index 968a74b..19fd4a1 100644
--- a/verilog/dv/caravel/user_proj_example/la_test1/Makefile
+++ b/verilog/dv/caravel/user_proj_example/la_test1/Makefile
@@ -1,19 +1,3 @@
-# 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
-
 FIRMWARE_PATH = ../..
 RTL_PATH = ../../../../rtl
 IP_PATH = ../../../../ip
@@ -23,8 +7,6 @@
 GCC_PREFIX?=riscv32-unknown-elf
 PDK_PATH?=/ef/tech/SW/sky130A
 
-SIM?=RTL
-
 .SUFFIXES:
 
 PATTERN = la_test1
@@ -34,15 +16,9 @@
 hex:  ${PATTERN:=.hex}
 
 %.vvp: %_tb.v %.hex
-ifeq ($(SIM),RTL)
-	iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \
+	iverilog -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
 	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
-	$< -o $@
-else
-	iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \
-	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
-	$< -o $@
-endif
+	-o $@ $<
 
 %.vcd: %.vvp
 	vvp $<
diff --git a/verilog/dv/caravel/user_proj_example/la_test1/la_test1.c b/verilog/dv/caravel/user_proj_example/la_test1/la_test1.c
index 9759ed7..a564a9f 100644
--- a/verilog/dv/caravel/user_proj_example/la_test1/la_test1.c
+++ b/verilog/dv/caravel/user_proj_example/la_test1/la_test1.c
@@ -1,20 +1,3 @@
-/*
- * 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"
 
diff --git a/verilog/dv/caravel/user_proj_example/la_test1/la_test1_tb.v b/verilog/dv/caravel/user_proj_example/la_test1/la_test1_tb.v
index 210098f..ed13c40 100644
--- a/verilog/dv/caravel/user_proj_example/la_test1/la_test1_tb.v
+++ b/verilog/dv/caravel/user_proj_example/la_test1/la_test1_tb.v
@@ -1,18 +1,3 @@
-// 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
diff --git a/verilog/dv/caravel/user_proj_example/la_test2/Makefile b/verilog/dv/caravel/user_proj_example/la_test2/Makefile
index 4980a08..d9d9a0d 100644
--- a/verilog/dv/caravel/user_proj_example/la_test2/Makefile
+++ b/verilog/dv/caravel/user_proj_example/la_test2/Makefile
@@ -1,19 +1,3 @@
-# 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
-
 FIRMWARE_PATH = ../..
 RTL_PATH = ../../../../rtl
 IP_PATH = ../../../../ip
@@ -23,8 +7,6 @@
 GCC_PREFIX?=riscv32-unknown-elf
 PDK_PATH?=/ef/tech/SW/sky130A
 
-SIM?=RTL
-
 .SUFFIXES:
 
 PATTERN = la_test2
@@ -34,15 +16,9 @@
 hex:  ${PATTERN:=.hex}
 
 %.vvp: %_tb.v %.hex
-ifeq ($(SIM),RTL)
-	iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \
+	iverilog -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
 	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
-	$< -o $@
-else
-	iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \
-	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
-	$< -o $@
-endif
+	-o $@ $<
 
 %.vcd: %.vvp
 	vvp $<
diff --git a/verilog/dv/caravel/user_proj_example/la_test2/la_test2.c b/verilog/dv/caravel/user_proj_example/la_test2/la_test2.c
index 0267d25..18e185b 100644
--- a/verilog/dv/caravel/user_proj_example/la_test2/la_test2.c
+++ b/verilog/dv/caravel/user_proj_example/la_test2/la_test2.c
@@ -1,20 +1,3 @@
-/*
- * 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"
 
diff --git a/verilog/dv/caravel/user_proj_example/la_test2/la_test2_tb.v b/verilog/dv/caravel/user_proj_example/la_test2/la_test2_tb.v
index b9e5c80..9c549de 100644
--- a/verilog/dv/caravel/user_proj_example/la_test2/la_test2_tb.v
+++ b/verilog/dv/caravel/user_proj_example/la_test2/la_test2_tb.v
@@ -1,18 +1,3 @@
-// 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
diff --git a/verilog/dv/caravel/user_proj_example/seven-segment-counter/Makefile b/verilog/dv/caravel/user_proj_example/seven-segment-counter/Makefile
new file mode 100644
index 0000000..d93f72d
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/seven-segment-counter/Makefile
@@ -0,0 +1,42 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+#MP_PATH = ../../../../rtl/multi_project_harness
+BEHAVIOURAL_MODELS = ../../ 
+
+TOOLCHAIN_PREFIX?=/opt/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-
+PDK_PATH?=~/work/asic-workshop/pdks/sky130A
+
+.SUFFIXES:
+
+PATTERN = seven_segment
+
+all:  ${PATTERN:=.vcd}
+
+hex:  ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+	$(TOOLCHAIN_PREFIX)gcc -mabi=ilp32 -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
+
+%.hex: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O verilog $< $@
+	# to fix flash base address
+	sed -i 's/@10000000/@00000000/g' $@
+
+%.bin: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
+
+# ---- Clean ----
+
+clean:
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.c b/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.c
new file mode 100644
index 0000000..4ae44af
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.c
@@ -0,0 +1,67 @@
+#include "../../defs.h"
+
+/*
+	IO Test:
+		- Configures MPRJ pins
+		- Observes counter value through the LED digits
+*/
+
+#define reg_mprj_7seg (*(volatile uint32_t*)0x30000200)
+
+void main()
+{
+	/* 
+	IO Control Registers
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 3-bits | 1-bit | 1-bit | 1-bit  | 1-bit  | 1-bit | 1-bit   | 1-bit   | 1-bit | 1-bit | 1-bit   |
+
+	Output: 0000_0110_0000_1110  (0x1808) = GPIO_MODE_USER_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 0       |
+
+	Output: 0000_0110_0000_1111  (0x1809) = GPIO_MODE_MGNT_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 1       |
+	
+	 
+	Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 001    | 0     | 0     | 0      | 0      | 0     | 0       | 0       | 0     | 1     | 0       |
+
+	*/
+
+    /* 
+    Inputs
+
+    system clock
+    system reset
+
+    Outputs
+
+    14:8 seven segment LEDs
+    */
+
+	reg_mprj_io_8  =  GPIO_MODE_USER_STD_OUTPUT;
+	reg_mprj_io_9  =  GPIO_MODE_USER_STD_OUTPUT;
+	reg_mprj_io_10 =  GPIO_MODE_USER_STD_OUTPUT;
+	reg_mprj_io_11 =  GPIO_MODE_USER_STD_OUTPUT;
+	reg_mprj_io_12 =  GPIO_MODE_USER_STD_OUTPUT;
+	reg_mprj_io_13 =  GPIO_MODE_USER_STD_OUTPUT;
+	reg_mprj_io_14 =  GPIO_MODE_USER_STD_OUTPUT;
+
+    /* Apply configuration */
+    reg_mprj_xfer = 1;
+    while (reg_mprj_xfer == 1);
+
+    // change to project 0
+    reg_mprj_slave = 0;
+
+    // use logic analyser to reset the counter
+    reg_la0_ena  = 0x00000000; // bits 31:0 outputs
+    reg_la0_data = 0x00000001; // reset high is on bit 0
+    reg_la0_data = 0x00000000; // low
+
+    // update 7seg compare reg to 10
+    reg_mprj_7seg = 10;
+}
+
diff --git a/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.gtkw b/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.gtkw
new file mode 100644
index 0000000..d081a58
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.gtkw
@@ -0,0 +1,314 @@
+[*]
+[*] GTKWave Analyzer v3.3.108 (w)1999-2020 BSI
+[*] Thu Nov 26 15:54:45 2020
+[*]
+[dumpfile] "/home/matt/work/asic-workshop/caravel/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.vcd"
+[dumpfile_mtime] "Thu Nov 26 15:53:35 2020"
+[dumpfile_size] 101461023
+[savefile] "/home/matt/work/asic-workshop/caravel/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment.gtkw"
+[timestart] 0
+[size] 2488 1529
+[pos] -1 -1
+*-26.000000 192362500 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] seven_segment_tb.
+[treeopen] seven_segment_tb.uut.
+[treeopen] seven_segment_tb.uut.gpio_control_bidir[0].
+[treeopen] seven_segment_tb.uut.gpio_control_bidir[0].gpio_in_buf.
+[treeopen] seven_segment_tb.uut.gpio_control_bidir[0].gpio_logic_high.
+[treeopen] seven_segment_tb.uut.gpio_control_in[2].
+[treeopen] seven_segment_tb.uut.gpio_control_in[3].
+[treeopen] seven_segment_tb.uut.gpio_control_in[4].
+[treeopen] seven_segment_tb.uut.gpio_control_in[4].gpio_in_buf.
+[treeopen] seven_segment_tb.uut.gpio_control_in[4].gpio_logic_high.
+[treeopen] seven_segment_tb.uut.gpio_control_in[8].
+[treeopen] seven_segment_tb.uut.gpio_control_in[9].
+[treeopen] seven_segment_tb.uut.mprj.
+[treeopen] seven_segment_tb.uut.mprj.mprj.
+[treeopen] seven_segment_tb.uut.mprj.mprj.proj_0.
+[treeopen] seven_segment_tb.uut.soc.
+[treeopen] seven_segment_tb.uut.soc.housekeeping.
+[treeopen] seven_segment_tb.uut.soc.soc.
+[treeopen] seven_segment_tb.uut.soc.soc.cpu.
+[treeopen] seven_segment_tb.uut.soc.soc.cpu.picorv32_core.
+[treeopen] seven_segment_tb.uut.soc.soc.gpio_wb.
+[treeopen] seven_segment_tb.uut.soc.soc.mprj_ctrl.
+[sst_width] 719
+[signals_width] 1098
+[sst_expanded] 1
+[sst_vpaned_height] 710
+@28
+seven_segment_tb.clock
+seven_segment_tb.RSTB
+@200
+-
+@800200
+-wbs
+@28
+seven_segment_tb.uut.mprj.mprj.wb_rst_i
+seven_segment_tb.uut.mprj.mprj.wb_clk_i
+seven_segment_tb.uut.mprj.mprj.wbs_ack_o
+@22
+seven_segment_tb.uut.mprj.mprj.wbs_adr_i[31:0]
+@28
+seven_segment_tb.uut.mprj.mprj.wbs_cyc_i
+@24
+seven_segment_tb.uut.mprj.mprj.wbs_dat_i[31:0]
+@22
+seven_segment_tb.uut.mprj.mprj.wbs_dat_o[31:0]
+seven_segment_tb.uut.mprj.mprj.wbs_sel_i[3:0]
+@28
+seven_segment_tb.uut.mprj.mprj.wbs_stb_i
+seven_segment_tb.uut.mprj.mprj.wbs_we_i
+@1000200
+-wbs
+@800200
+-multi proj control
+@28
+seven_segment_tb.uut.soc.soc.mprj_ctrl.mprj_ctrl.xfer_ctrl
+@1000200
+-multi proj control
+@800200
+-la
+@22
+seven_segment_tb.uut.mprj.mprj.la_data_in[127:0]
+seven_segment_tb.uut.mprj.mprj.la_data_out[127:0]
+seven_segment_tb.uut.mprj.mprj.la_oen[127:0]
+@1000200
+-la
+@22
+seven_segment_tb.uut.soc.soc.cpu.picorv32_core.next_insn_opcode[31:0]
+@200
+-
+@800200
+-multi project
+@22
+seven_segment_tb.uut.mprj.mprj.active_project[7:0]
+@28
+seven_segment_tb.uut.mprj.mprj.wb_rst_i
+@c00022
+seven_segment_tb.uut.mprj.io_in[37:0]
+@28
+(0)seven_segment_tb.uut.mprj.io_in[37:0]
+(1)seven_segment_tb.uut.mprj.io_in[37:0]
+(2)seven_segment_tb.uut.mprj.io_in[37:0]
+(3)seven_segment_tb.uut.mprj.io_in[37:0]
+(4)seven_segment_tb.uut.mprj.io_in[37:0]
+(5)seven_segment_tb.uut.mprj.io_in[37:0]
+(6)seven_segment_tb.uut.mprj.io_in[37:0]
+(7)seven_segment_tb.uut.mprj.io_in[37:0]
+(8)seven_segment_tb.uut.mprj.io_in[37:0]
+(9)seven_segment_tb.uut.mprj.io_in[37:0]
+(10)seven_segment_tb.uut.mprj.io_in[37:0]
+(11)seven_segment_tb.uut.mprj.io_in[37:0]
+(12)seven_segment_tb.uut.mprj.io_in[37:0]
+(13)seven_segment_tb.uut.mprj.io_in[37:0]
+(14)seven_segment_tb.uut.mprj.io_in[37:0]
+(15)seven_segment_tb.uut.mprj.io_in[37:0]
+(16)seven_segment_tb.uut.mprj.io_in[37:0]
+(17)seven_segment_tb.uut.mprj.io_in[37:0]
+(18)seven_segment_tb.uut.mprj.io_in[37:0]
+(19)seven_segment_tb.uut.mprj.io_in[37:0]
+(20)seven_segment_tb.uut.mprj.io_in[37:0]
+(21)seven_segment_tb.uut.mprj.io_in[37:0]
+(22)seven_segment_tb.uut.mprj.io_in[37:0]
+(23)seven_segment_tb.uut.mprj.io_in[37:0]
+(24)seven_segment_tb.uut.mprj.io_in[37:0]
+(25)seven_segment_tb.uut.mprj.io_in[37:0]
+(26)seven_segment_tb.uut.mprj.io_in[37:0]
+(27)seven_segment_tb.uut.mprj.io_in[37:0]
+(28)seven_segment_tb.uut.mprj.io_in[37:0]
+(29)seven_segment_tb.uut.mprj.io_in[37:0]
+(30)seven_segment_tb.uut.mprj.io_in[37:0]
+(31)seven_segment_tb.uut.mprj.io_in[37:0]
+(32)seven_segment_tb.uut.mprj.io_in[37:0]
+(33)seven_segment_tb.uut.mprj.io_in[37:0]
+(34)seven_segment_tb.uut.mprj.io_in[37:0]
+(35)seven_segment_tb.uut.mprj.io_in[37:0]
+(36)seven_segment_tb.uut.mprj.io_in[37:0]
+(37)seven_segment_tb.uut.mprj.io_in[37:0]
+@1401200
+-group_end
+@800022
+seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+@28
+(0)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(1)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(2)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(3)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(4)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(5)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(6)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(7)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(8)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(9)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(10)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(11)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(12)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(13)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(14)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(15)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(16)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(17)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(18)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(19)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(20)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(21)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(22)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(23)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(24)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(25)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(26)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(27)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(28)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(29)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(30)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(31)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(32)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(33)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(34)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(35)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(36)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(37)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+@1001200
+-group_end
+@22
+seven_segment_tb.uut.mprj.mprj.io_oeb[37:0]
+@1000200
+-multi project
+@c00022
+seven_segment_tb.mprj_io[37:0]
+@28
+(0)seven_segment_tb.mprj_io[37:0]
+(1)seven_segment_tb.mprj_io[37:0]
+(2)seven_segment_tb.mprj_io[37:0]
+(3)seven_segment_tb.mprj_io[37:0]
+(4)seven_segment_tb.mprj_io[37:0]
+(5)seven_segment_tb.mprj_io[37:0]
+(6)seven_segment_tb.mprj_io[37:0]
+(7)seven_segment_tb.mprj_io[37:0]
+(8)seven_segment_tb.mprj_io[37:0]
+(9)seven_segment_tb.mprj_io[37:0]
+(10)seven_segment_tb.mprj_io[37:0]
+(11)seven_segment_tb.mprj_io[37:0]
+(12)seven_segment_tb.mprj_io[37:0]
+(13)seven_segment_tb.mprj_io[37:0]
+(14)seven_segment_tb.mprj_io[37:0]
+(15)seven_segment_tb.mprj_io[37:0]
+(16)seven_segment_tb.mprj_io[37:0]
+(17)seven_segment_tb.mprj_io[37:0]
+(18)seven_segment_tb.mprj_io[37:0]
+(19)seven_segment_tb.mprj_io[37:0]
+(20)seven_segment_tb.mprj_io[37:0]
+(21)seven_segment_tb.mprj_io[37:0]
+(22)seven_segment_tb.mprj_io[37:0]
+(23)seven_segment_tb.mprj_io[37:0]
+(24)seven_segment_tb.mprj_io[37:0]
+(25)seven_segment_tb.mprj_io[37:0]
+(26)seven_segment_tb.mprj_io[37:0]
+(27)seven_segment_tb.mprj_io[37:0]
+(28)seven_segment_tb.mprj_io[37:0]
+(29)seven_segment_tb.mprj_io[37:0]
+(30)seven_segment_tb.mprj_io[37:0]
+(31)seven_segment_tb.mprj_io[37:0]
+(32)seven_segment_tb.mprj_io[37:0]
+(33)seven_segment_tb.mprj_io[37:0]
+(34)seven_segment_tb.mprj_io[37:0]
+(35)seven_segment_tb.mprj_io[37:0]
+(36)seven_segment_tb.mprj_io[37:0]
+(37)seven_segment_tb.mprj_io[37:0]
+@c00022
+seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+@28
+(0)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(1)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(2)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(3)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(4)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(5)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(6)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(7)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(8)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(9)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(10)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(11)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(12)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(13)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(14)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(15)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(16)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(17)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(18)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(19)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(20)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(21)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(22)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(23)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(24)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(25)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(26)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(27)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(28)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(29)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(30)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(31)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(32)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(33)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(34)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(35)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(36)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+(37)seven_segment_tb.uut.mprj.mprj.io_out[37:0]
+@1401200
+-group_end
+@22
+seven_segment_tb.uut.mprj.mprj.io_oeb[37:0]
+seven_segment_tb.uut.mprj.mprj.io_in[37:0]
+@1401200
+-group_end
+@800200
+-seven seg
+@28
+seven_segment_tb.uut.mprj.mprj.proj_0.clk
+@22
+seven_segment_tb.uut.mprj.mprj.proj_0.second_counter[23:0]
+@24
+seven_segment_tb.uut.mprj.mprj.proj_0.compare[23:0]
+@28
+seven_segment_tb.uut.mprj.mprj.proj_0.reset
+@800022
+seven_segment_tb.uut.mprj.mprj.proj_0.digit[3:0]
+@28
+(0)seven_segment_tb.uut.mprj.mprj.proj_0.digit[3:0]
+(1)seven_segment_tb.uut.mprj.mprj.proj_0.digit[3:0]
+(2)seven_segment_tb.uut.mprj.mprj.proj_0.digit[3:0]
+(3)seven_segment_tb.uut.mprj.mprj.proj_0.digit[3:0]
+@200
+-
+@800022
+seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+@28
+(0)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+(1)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+(2)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+(3)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+(4)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+(5)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+(6)seven_segment_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+@1001200
+-group_end
+-group_end
+@1000200
+-seven seg
+@800022
+seven_segment_tb.segments[6:0]
+@28
+(0)seven_segment_tb.segments[6:0]
+(1)seven_segment_tb.segments[6:0]
+(2)seven_segment_tb.segments[6:0]
+(3)seven_segment_tb.segments[6:0]
+(4)seven_segment_tb.segments[6:0]
+(5)seven_segment_tb.segments[6:0]
+(6)seven_segment_tb.segments[6:0]
+@1001200
+-group_end
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment_tb.v b/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment_tb.v
new file mode 100644
index 0000000..57b8b3c
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/seven-segment-counter/seven_segment_tb.v
@@ -0,0 +1,143 @@
+`default_nettype none
+
+`timescale 1 ns / 1 ps
+
+`include "caravel.v"
+`include "spiflash.v"
+
+module seven_segment_tb;
+    reg clock;
+    reg RSTB;
+    reg power1, power2;
+    reg power3, power4;
+
+    wire gpio;
+    wire [37:0] mprj_io;
+    wire [6:0] segments;
+
+    
+    assign segments = mprj_io[14:8];
+
+    // 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 #12.5 clock <= (clock === 1'b0);
+
+    initial begin
+        clock = 0;
+    end
+
+    initial begin
+        $dumpfile("seven_segment.vcd");
+        $dumpvars(0, seven_segment_tb);
+
+        // Repeat cycles of 1000 clock edges as needed to complete testbench
+        repeat (15) begin
+            repeat (1000) @(posedge clock);
+            // $display("+1000 cycles");
+        end
+        $display("%c[1;31m",27);
+        $display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed");
+        $display("%c[0m",27);
+        $finish;
+    end
+
+    initial begin
+        // Observe segments counting from 0 to 9
+
+        wait(segments == 7'b0111111); 
+        wait(segments == 7'b0000110);
+        wait(segments == 7'b1011011);
+        wait(segments == 7'b1001111);
+        wait(segments == 7'b1100110);
+        wait(segments == 7'b1101101);
+        wait(segments == 7'b1111100);
+        wait(segments == 7'b0000111);
+        wait(segments == 7'b1111111);
+        wait(segments == 7'b1111111);
+        wait(segments == 7'b1100111);
+
+        $display("Monitor: Test 1 Mega-Project IO (RTL) Passed");
+        $finish;
+    end
+
+    initial begin
+        RSTB <= 1'b0;
+        #2000;
+        RSTB <= 1'b1;       // Release reset
+    end
+
+    initial begin       // Power-up sequence
+        power1 <= 1'b0;
+        power2 <= 1'b0;
+        power3 <= 1'b0;
+        power4 <= 1'b0;
+        #200;
+        power1 <= 1'b1;
+        #200;
+        power2 <= 1'b1;
+        #200;
+        power3 <= 1'b1;
+        #200;
+        power4 <= 1'b1;
+    end
+
+    /*
+    always @(mprj_io) begin
+        #1 $display("MPRJ-IO state = %b ", mprj_io[7:0]);
+    end
+    */
+
+    wire flash_csb;
+    wire flash_clk;
+    wire flash_io0;
+    wire flash_io1;
+
+    wire VDD1V8;
+    wire VDD3V3;
+    wire VSS;
+    
+    assign VDD3V3 = power1;
+    assign VDD1V8 = power2;
+    wire USER_VDD3V3 = power3;
+    wire USER_VDD1V8 = power4;
+    assign VSS = 1'b0;
+
+    caravel uut (
+        .vddio    (VDD3V3),
+        .vssio    (VSS),
+        .vdda     (VDD3V3),
+        .vssa     (VSS),
+        .vccd     (VDD1V8),
+        .vssd     (VSS),
+        .vdda1    (USER_VDD3V3),
+        .vdda2    (USER_VDD3V3),
+        .vssa1    (VSS),
+        .vssa2    (VSS),
+        .vccd1    (USER_VDD1V8),
+        .vccd2    (USER_VDD1V8),
+        .vssd1    (VSS),
+        .vssd2    (VSS),
+        .clock    (clock),
+        .gpio     (gpio),
+        .mprj_io  (mprj_io),
+        .flash_csb(flash_csb),
+        .flash_clk(flash_clk),
+        .flash_io0(flash_io0),
+        .flash_io1(flash_io1),
+        .resetb   (RSTB)
+    );
+
+    spiflash #(
+        .FILENAME("seven_segment.hex")
+    ) spiflash (
+        .csb(flash_csb),
+        .clk(flash_clk),
+        .io0(flash_io0),
+        .io1(flash_io1),
+        .io2(),         // not used
+        .io3()          // not used
+    );
+
+endmodule
diff --git a/verilog/dv/caravel/user_proj_example/spinet/Makefile b/verilog/dv/caravel/user_proj_example/spinet/Makefile
new file mode 100644
index 0000000..890d235
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/spinet/Makefile
@@ -0,0 +1,42 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+#MP_PATH = ../../../../rtl/multi_project_harness
+BEHAVIOURAL_MODELS = ../../ 
+
+TOOLCHAIN_PREFIX?=/opt/gcc-riscv/bin/riscv32-unknown-elf-
+PDK_PATH?=/mnt/extra/vlsi/sky130A
+
+.SUFFIXES:
+
+PATTERN = spinet
+
+all:  ${PATTERN:=.vcd}
+
+hex:  ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+	$(TOOLCHAIN_PREFIX)gcc -O2 -mabi=ilp32 -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
+
+%.hex: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O verilog $< $@
+	# to fix flash base address
+	sed -i 's/@10000000/@00000000/g' $@
+
+%.bin: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
+
+# ---- Clean ----
+
+clean:
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/spinet/spinet.c b/verilog/dv/caravel/user_proj_example/spinet/spinet.c
new file mode 100644
index 0000000..29997e6
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/spinet/spinet.c
@@ -0,0 +1,66 @@
+#include "../../defs.h"
+
+/*
+	IO Test:
+		- Configures MPRJ pins
+		- Nothing else to do: spinet is autonomous
+*/
+
+#define PROJECT 3
+#define NUMNODES 6
+
+void main()
+{
+	/* 
+	IO Control Registers
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 3-bits | 1-bit | 1-bit | 1-bit  | 1-bit  | 1-bit | 1-bit   | 1-bit   | 1-bit | 1-bit | 1-bit   |
+
+	Output: 0000_0110_0000_1110  (0x1808) = GPIO_MODE_USER_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 0       |
+
+	Output: 0000_0110_0000_1111  (0x1809) = GPIO_MODE_MGNT_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 1       |
+	
+	 
+	Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 001    | 0     | 0     | 0      | 0      | 0     | 0       | 0       | 0     | 1     | 0       |
+
+	*/
+
+    /*
+          Inputs       | Outputs
+	Node  MOSI SCK  SS   MISO TXRDY RXRDY
+	0     0    6    12   18   24    30
+	1     1    7    13   19   25    31
+	2     2    8    14   20   26    32
+	3     3    9    15   21   27    33
+	4     4   10    16   22   28    34
+	5     5   11    17   23   29    35
+
+    */
+
+	volatile uint32_t *io = &reg_mprj_io_0;
+	for (int i = 0; i < NUMNODES; i++) {
+		for (int j = 0; j <= 12; j += 6)
+			io[i + j] = GPIO_MODE_USER_STD_INPUT_NOPULL;
+		for (int j = 18; j <= 30; j += 6)
+			io[i + j] = GPIO_MODE_USER_STD_OUTPUT;
+	}
+			
+    /* Apply configuration */
+    reg_mprj_xfer = 1;
+    while (reg_mprj_xfer == 1);
+
+    // change to project
+    reg_mprj_slave = PROJECT;
+
+    // use logic analyser bit 0 as reset
+    reg_la0_ena  = 0x00000000; // bits 31:0 outputs
+    reg_la0_data = 0x00000001; // reset high is on bit 0
+    reg_la0_data = 0x00000000; // low
+
+}
diff --git a/verilog/dv/caravel/user_proj_example/spinet/spinet_tb.v b/verilog/dv/caravel/user_proj_example/spinet/spinet_tb.v
new file mode 100644
index 0000000..35f98a0
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/spinet/spinet_tb.v
@@ -0,0 +1,240 @@
+`default_nettype none
+
+`timescale 1 ns / 1 ps
+
+`include "caravel.v"
+`include "spiflash.v"
+
+module spinet_tb;
+	reg clock;
+	reg ext_clock;
+    	reg RSTB;
+	reg power1, power2;
+	reg power3, power4;
+
+    	wire gpio;
+    	wire [37:0] mprj_io;
+
+	localparam N = 6;
+
+	// SPI signals for each node
+	reg mosi0, sck0, ss0;
+	wire [N-1:0] mosi, sck, ss;
+	wire [N-1:0] miso, txrdy, rxrdy;
+	assign mprj_io[5:0]   = {mosi[5:1],mosi0};
+	assign mprj_io[11:6]  = {sck[5:1],sck0};
+	assign mprj_io[17:12] = {ss[5:1],ss0};
+	assign miso  = mprj_io[23:18];
+	assign txrdy = mprj_io[29:24];
+	assign rxrdy = mprj_io[35:30];
+
+	initial begin
+		sck0 = 0;
+		ss0 = ~0;
+		mosi0 = 0;
+	end
+
+	// 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 #12.5 clock <= (clock === 1'b0);
+	always #6.25 ext_clock <= (ext_clock === 1'b0);
+
+	initial begin
+		clock = 0;
+	        ext_clock = 0;
+	end
+
+	initial begin
+		$dumpfile("spinet.vcd");
+		$dumpvars(0, spinet_tb);
+
+		// Repeat cycles of 1000 clock edges as needed to complete testbench
+		repeat (50) begin
+			repeat (1000) @(posedge clock);
+		end
+		$display("%c[1;31m",27);
+		$display ("Monitor: Timeout, Test Failed");
+		$display("%c[0m",27);
+		$finish;
+	end
+
+	reg [15:0] snd, rcv, sent;
+	reg [N-1:0] echoed = 1;
+	initial begin
+		// Wait for initial reset
+		wait (uut.la_data_in_mprj[0] === 1'b1);
+		wait (uut.la_data_in_mprj[0] === 1'b0);
+		// Node 0 sends one packet to each other node
+		for (integer i = 1; i < N; i = i + 1) begin
+			snd <= {2'b10,3'h0,3'h0,8'h40};
+			snd[13:11] <= i;
+			snd[2:0] <= i;
+			#100 ss0 <= 0;
+			sent <= snd;
+			#50;
+			repeat (16) begin
+				#50 mosi0 <= snd[15];
+				sck0 <= 1;
+				#50 rcv <= {rcv[14:0],miso[0]};
+				sck0 <= 0;
+				snd <= snd << 1;
+			end
+			#100 ss0 <= 1;
+			$display("sent %h received: %h", sent, rcv);
+			if (rcv[15])
+				echoed[rcv[10:8]] = 1;
+			
+		end
+		#100 ss0 <= 1;
+		// Read packets echoed back by other nodes
+		snd <= 0;
+		while (&echoed == 0) begin
+			wait (rxrdy[0] === 1'b1);
+			ss0 <= 0;
+			#50;
+			repeat (16) begin
+				#50 mosi0 <= snd[15];
+				sck0 <= 1;
+				#50 rcv <= {rcv[14:0],miso[0]};
+				sck0 <= 0;
+				snd <= snd << 1;
+			end
+			sent <= snd;
+			#100 ss0 <= 1;
+			$display("sent %h received: %h", sent, rcv);
+			if (rcv[15])
+				echoed[rcv[10:8]] = 1;
+		end
+		$display("Monitor: Test Passed");
+	    $finish;
+	end
+
+	genvar node;
+	generate for (node = 1; node < N; node = node + 1)
+		echo ECHO (mosi[node], sck[node], ss[node], miso[node], txrdy[node], rxrdy[node]);
+	endgenerate
+
+	initial begin
+		RSTB <= 1'b0;
+		#2000;
+		RSTB <= 1'b1;	    // Release reset
+	end
+
+	initial begin		// Power-up sequence
+		power1 <= 1'b0;
+		power2 <= 1'b0;
+		power3 <= 1'b0;
+		power4 <= 1'b0;
+		#200;
+		power1 <= 1'b1;
+		#200;
+		power2 <= 1'b1;
+		#200;
+		power3 <= 1'b1;
+		#200;
+		power4 <= 1'b1;
+	end
+
+    /*
+	always @(mprj_io) begin
+		#1 $display("MPRJ-IO state = %b ", mprj_io[7:0]);
+	end
+    */
+
+    	wire flash_csb;
+	wire flash_clk;
+	wire flash_io0;
+	wire flash_io1;
+
+	wire VDD1V8;
+    	wire VDD3V3;
+	wire VSS;
+    
+	assign VDD3V3 = power1;
+	assign VDD1V8 = power2;
+	assign USER_VDD3V3 = power3;
+	assign USER_VDD1V8 = power4;
+	assign VSS = 1'b0;
+
+	caravel uut (
+		.vddio	  (VDD3V3),
+		.vssio	  (VSS),
+		.vdda	  (VDD3V3),
+		.vssa	  (VSS),
+		.vccd	  (VDD1V8),
+		.vssd	  (VSS),
+		.vdda1    (USER_VDD3V3),
+		.vdda2    (USER_VDD3V3),
+		.vssa1	  (VSS),
+		.vssa2	  (VSS),
+		.vccd1	  (USER_VDD1V8),
+		.vccd2	  (USER_VDD1V8),
+		.vssd1	  (VSS),
+		.vssd2	  (VSS),
+		.clock	  (clock),
+		.gpio     (gpio),
+        	.mprj_io  (mprj_io),
+		.flash_csb(flash_csb),
+		.flash_clk(flash_clk),
+		.flash_io0(flash_io0),
+		.flash_io1(flash_io1),
+		.resetb	  (RSTB)
+	);
+
+	spiflash #(
+		.FILENAME("spinet.hex")
+	) spiflash (
+		.csb(flash_csb),
+		.clk(flash_clk),
+		.io0(flash_io0),
+		.io1(flash_io1),
+		.io2(),			// not used
+		.io3()			// not used
+	);
+
+endmodule
+
+// SPI host emulation to read and echo packets
+module echo (
+	output reg mosi,
+	output reg sck,
+	output reg ss,
+	input miso,
+	input txrdy,
+	input rxrdy);
+
+	reg [15:0] pkt = 0;
+	initial begin
+		ss = 1;
+		sck = 0;
+		mosi = 0;
+	end
+	always @(posedge rxrdy) begin
+		// receive a packet
+		ss <= 0;
+		sck <= 0;
+		mosi <= 0;
+		#50;
+		repeat (16) begin
+			#50 sck <= 1;
+			#50 pkt <= {pkt[14:0],miso};
+			sck <= 0;
+		end
+		#100 ss <= 1;
+		// swap sender and receiver address
+		pkt[13:8] <= {pkt[10:8],pkt[13:11]};
+		// send the packet back
+		#50 ss <= 0;
+		#50;
+		repeat (16) begin
+			#50 mosi <= pkt[15];
+			sck <= 1;
+			#50 sck <= 0;
+			pkt <= pkt << 1;
+		end
+		#100 ss <= 1;
+	end
+
+endmodule
diff --git a/verilog/dv/caravel/user_proj_example/vga-clock/Makefile b/verilog/dv/caravel/user_proj_example/vga-clock/Makefile
new file mode 100644
index 0000000..0bb601f
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/vga-clock/Makefile
@@ -0,0 +1,42 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+#MP_PATH = ../../../../rtl/multi_project_harness
+BEHAVIOURAL_MODELS = ../../ 
+
+TOOLCHAIN_PREFIX?=/opt/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-
+PDK_PATH?=~/work/asic-workshop/pdks/sky130A
+
+.SUFFIXES:
+
+PATTERN = vga_clock
+
+all:  ${PATTERN:=.vcd}
+
+hex:  ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+	$(TOOLCHAIN_PREFIX)gcc -mabi=ilp32 -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
+
+%.hex: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O verilog $< $@
+	# to fix flash base address
+	sed -i 's/@10000000/@00000000/g' $@
+
+%.bin: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
+
+# ---- Clean ----
+
+clean:
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.c b/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.c
new file mode 100644
index 0000000..a6fe3fc
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.c
@@ -0,0 +1,77 @@
+#include "../../defs.h"
+
+#define reg_mprj_oeb0 (*(volatile uint32_t*)0x30000004)
+#define reg_mprj_oeb1 (*(volatile uint32_t*)0x30000008)
+/*
+	IO Test:
+		- Configures MPRJ pins
+		- Observes counter value through the LED digits
+*/
+
+void main()
+{
+	/* 
+	IO Control Registers
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 3-bits | 1-bit | 1-bit | 1-bit  | 1-bit  | 1-bit | 1-bit   | 1-bit   | 1-bit | 1-bit | 1-bit   |
+
+	Output: 0000_0110_0000_1110  (0x1808) = GPIO_MODE_USER_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 0       |
+
+	Output: 0000_0110_0000_1111  (0x1809) = GPIO_MODE_MGNT_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 1       |
+	
+	 
+	Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 001    | 0     | 0     | 0      | 0      | 0     | 0       | 0       | 0     | 1     | 0       |
+
+	*/
+
+    /* 
+    Inputs
+
+    system clock
+    system reset
+    8   adj hours
+    9   adj min
+    10   adj sec
+
+    Outputs
+
+    11   hsync
+    12   vsync
+    13-18 rrggbb
+    */
+
+    reg_mprj_io_8  =  GPIO_MODE_USER_STD_INPUT_NOPULL;
+    reg_mprj_io_9  =  GPIO_MODE_USER_STD_INPUT_NOPULL;
+    reg_mprj_io_10 =  GPIO_MODE_USER_STD_INPUT_NOPULL;
+
+    reg_mprj_io_11 =  GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_12 =  GPIO_MODE_USER_STD_OUTPUT;
+
+    reg_mprj_io_13 =  GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_14 =  GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_15 =  GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_16 =  GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_17 =  GPIO_MODE_USER_STD_OUTPUT;
+    reg_mprj_io_18 =  GPIO_MODE_USER_STD_OUTPUT;
+
+    /* Apply configuration */
+    reg_mprj_xfer = 1;
+    while (reg_mprj_xfer == 1);
+
+    // change to project 2
+    reg_mprj_slave = 2;
+
+    // setup oeb, low for output, high for input
+    reg_mprj_oeb0 = (1 << 8) + (1 << 9) + (1 << 10);
+
+    // use logic analyser to reset the design
+    reg_la0_ena  = 0x00000000; // bits 31:0 outputs
+    reg_la0_data = 0x00000001; // reset high is on bit 0
+    reg_la0_data = 0x00000000; // low
+}
diff --git a/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.gtkw b/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.gtkw
new file mode 100644
index 0000000..78a082e
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.gtkw
@@ -0,0 +1,197 @@
+[*]
+[*] GTKWave Analyzer v3.3.108 (w)1999-2020 BSI
+[*] Thu Nov 26 13:29:36 2020
+[*]
+[dumpfile] "/home/matt/work/asic-workshop/caravel/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.vcd"
+[dumpfile_mtime] "Thu Nov 26 13:28:55 2020"
+[dumpfile_size] 194298414
+[savefile] "/home/matt/work/asic-workshop/caravel/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock.gtkw"
+[timestart] 0
+[size] 1700 1529
+[pos] -1 -1
+*-28.000000 253000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] vga_clock_tb.
+[treeopen] vga_clock_tb.uut.
+[treeopen] vga_clock_tb.uut.gpio_control_bidir[0].gpio_in_buf.
+[treeopen] vga_clock_tb.uut.gpio_control_in[4].gpio_in_buf.
+[treeopen] vga_clock_tb.uut.gpio_control_in[4].gpio_logic_high.
+[treeopen] vga_clock_tb.uut.gpio_control_in[8].
+[treeopen] vga_clock_tb.uut.gpio_control_in[8].gpio_in_buf.
+[treeopen] vga_clock_tb.uut.mprj.
+[treeopen] vga_clock_tb.uut.mprj.mprj.
+[treeopen] vga_clock_tb.uut.mprj.mprj.proj_0.
+[treeopen] vga_clock_tb.uut.mprj.mprj.proj_2.
+[treeopen] vga_clock_tb.uut.soc.
+[treeopen] vga_clock_tb.uut.soc.housekeeping.
+[treeopen] vga_clock_tb.uut.soc.soc.
+[treeopen] vga_clock_tb.uut.soc.soc.cpu.
+[treeopen] vga_clock_tb.uut.soc.soc.cpu.picorv32_core.
+[treeopen] vga_clock_tb.uut.soc.soc.gpio_wb.
+[treeopen] vga_clock_tb.uut.soc.soc.mprj_ctrl.
+[sst_width] 506
+[signals_width] 741
+[sst_expanded] 1
+[sst_vpaned_height] 862
+@28
+vga_clock_tb.clock
+vga_clock_tb.RSTB
+@200
+-
+@800200
+-wbs
+@28
+vga_clock_tb.uut.mprj.mprj.wb_rst_i
+vga_clock_tb.uut.mprj.mprj.wb_clk_i
+vga_clock_tb.uut.mprj.mprj.wbs_ack_o
+@22
+vga_clock_tb.uut.mprj.mprj.wbs_adr_i[31:0]
+@28
+vga_clock_tb.uut.mprj.mprj.wbs_cyc_i
+@24
+vga_clock_tb.uut.mprj.mprj.wbs_dat_i[31:0]
+@22
+vga_clock_tb.uut.mprj.mprj.wbs_dat_o[31:0]
+vga_clock_tb.uut.mprj.mprj.wbs_sel_i[3:0]
+@28
+vga_clock_tb.uut.mprj.mprj.wbs_stb_i
+vga_clock_tb.uut.mprj.mprj.wbs_we_i
+@1000200
+-wbs
+@800200
+-multi proj control
+@28
+vga_clock_tb.uut.soc.soc.mprj_ctrl.mprj_ctrl.xfer_ctrl
+@1000200
+-multi proj control
+@800200
+-la
+@22
+vga_clock_tb.uut.mprj.mprj.la_data_in[127:0]
+vga_clock_tb.uut.mprj.mprj.la_data_out[127:0]
+vga_clock_tb.uut.mprj.mprj.la_oen[127:0]
+@1000200
+-la
+@22
+vga_clock_tb.uut.soc.soc.cpu.picorv32_core.next_insn_opcode[31:0]
+@200
+-
+@800200
+-multi project
+@22
+vga_clock_tb.uut.mprj.mprj.active_project[7:0]
+@23
+vga_clock_tb.uut.mprj.mprj.reg_oeb[37:0]
+@28
+vga_clock_tb.uut.mprj.mprj.wb_rst_i
+@c00022
+vga_clock_tb.uut.mprj.io_in[37:0]
+@28
+(0)vga_clock_tb.uut.mprj.io_in[37:0]
+(1)vga_clock_tb.uut.mprj.io_in[37:0]
+(2)vga_clock_tb.uut.mprj.io_in[37:0]
+(3)vga_clock_tb.uut.mprj.io_in[37:0]
+(4)vga_clock_tb.uut.mprj.io_in[37:0]
+(5)vga_clock_tb.uut.mprj.io_in[37:0]
+(6)vga_clock_tb.uut.mprj.io_in[37:0]
+(7)vga_clock_tb.uut.mprj.io_in[37:0]
+(8)vga_clock_tb.uut.mprj.io_in[37:0]
+(9)vga_clock_tb.uut.mprj.io_in[37:0]
+(10)vga_clock_tb.uut.mprj.io_in[37:0]
+(11)vga_clock_tb.uut.mprj.io_in[37:0]
+(12)vga_clock_tb.uut.mprj.io_in[37:0]
+(13)vga_clock_tb.uut.mprj.io_in[37:0]
+(14)vga_clock_tb.uut.mprj.io_in[37:0]
+(15)vga_clock_tb.uut.mprj.io_in[37:0]
+(16)vga_clock_tb.uut.mprj.io_in[37:0]
+(17)vga_clock_tb.uut.mprj.io_in[37:0]
+(18)vga_clock_tb.uut.mprj.io_in[37:0]
+(19)vga_clock_tb.uut.mprj.io_in[37:0]
+(20)vga_clock_tb.uut.mprj.io_in[37:0]
+(21)vga_clock_tb.uut.mprj.io_in[37:0]
+(22)vga_clock_tb.uut.mprj.io_in[37:0]
+(23)vga_clock_tb.uut.mprj.io_in[37:0]
+(24)vga_clock_tb.uut.mprj.io_in[37:0]
+(25)vga_clock_tb.uut.mprj.io_in[37:0]
+(26)vga_clock_tb.uut.mprj.io_in[37:0]
+(27)vga_clock_tb.uut.mprj.io_in[37:0]
+(28)vga_clock_tb.uut.mprj.io_in[37:0]
+(29)vga_clock_tb.uut.mprj.io_in[37:0]
+(30)vga_clock_tb.uut.mprj.io_in[37:0]
+(31)vga_clock_tb.uut.mprj.io_in[37:0]
+(32)vga_clock_tb.uut.mprj.io_in[37:0]
+(33)vga_clock_tb.uut.mprj.io_in[37:0]
+(34)vga_clock_tb.uut.mprj.io_in[37:0]
+(35)vga_clock_tb.uut.mprj.io_in[37:0]
+(36)vga_clock_tb.uut.mprj.io_in[37:0]
+(37)vga_clock_tb.uut.mprj.io_in[37:0]
+@1401200
+-group_end
+@c00022
+vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+@28
+(0)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(1)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(2)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(3)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(4)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(5)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(6)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(7)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(8)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(9)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(10)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(11)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(12)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(13)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(14)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(15)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(16)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(17)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(18)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(19)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(20)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(21)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(22)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(23)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(24)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(25)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(26)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(27)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(28)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(29)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(30)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(31)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(32)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(33)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(34)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(35)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(36)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+(37)vga_clock_tb.uut.mprj.mprj.io_out[37:0]
+@1401200
+-group_end
+@1000200
+-multi project
+@28
+vga_clock_tb.uut.mprj.mprj.proj_2.reset
+@22
+vga_clock_tb.uut.mprj.mprj.proj_2.hrs_u[3:0]
+@28
+vga_clock_tb.uut.mprj.mprj.proj_2.hrs_d[1:0]
+vga_clock_tb.adj_hrs
+vga_clock_tb.uut.gpio_control_in[8].pad_gpio_in
+vga_clock_tb.uut.gpio_control_in[8].pad_gpio_in
+vga_clock_tb.uut.gpio_control_in[8].pad_gpio_inenb
+vga_clock_tb.uut.gpio_control_in[8].pad_gpio_outenb
+vga_clock_tb.uut.mprj.mprj.proj_2.adj_hrs
+vga_clock_tb.uut.mprj.mprj.proj_2.px_clk
+@24
+vga_clock_tb.uut.mprj.mprj.proj_2.y_px[9:0]
+vga_clock_tb.uut.mprj.mprj.proj_2.x_px[9:0]
+@28
+vga_clock_tb.uut.mprj.mprj.proj_2.activevideo
+vga_clock_tb.uut.mprj.mprj.proj_2.vsync
+vga_clock_tb.hsync
+@22
+vga_clock_tb.rrggbb[5:0]
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock_tb.v b/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock_tb.v
new file mode 100644
index 0000000..730469b
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/vga-clock/vga_clock_tb.v
@@ -0,0 +1,147 @@
+`default_nettype none
+
+`timescale 1 ns / 1 ps
+
+`include "caravel.v"
+`include "spiflash.v"
+
+module vga_clock_tb;
+    reg clock;
+    reg RSTB;
+    reg power1, power2;
+    reg power3, power4;
+
+    wire gpio;
+    wire [37:0] mprj_io;
+    wire [5:0] rrggbb;
+    wire hsync, vsync;
+
+    assign hsync = mprj_io[11];
+    assign vsync = mprj_io[12];
+    assign rrggbb = mprj_io[18:13];
+
+    reg adj_hrs = 0;
+    reg adj_min = 0;
+    reg adj_sec = 0;
+    assign mprj_io[8] = adj_hrs;
+    assign mprj_io[9] = adj_min;
+    assign mprj_io[10] = adj_sec;
+
+    // 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 #12.5 clock <= (clock === 1'b0);
+
+    initial begin
+        clock = 0;
+    end
+
+    initial begin
+        $dumpfile("vga_clock.vcd");
+        $dumpvars(0, vga_clock_tb);
+
+        // Repeat cycles of 1000 clock edges as needed to complete testbench
+        repeat (15) begin
+            repeat (1000) @(posedge clock);
+            // $display("+1000 cycles");
+        end
+        $display("%c[1;31m",27);
+        $display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed");
+        $display("%c[0m",27);
+        $finish;
+    end
+
+    initial begin
+        // wait for reset, we have 2 before the project is ready
+        wait(uut.mprj.mprj.proj_2.reset == 1);
+        wait(uut.mprj.mprj.proj_2.reset == 0);
+        wait(uut.mprj.mprj.proj_2.reset == 1);
+        wait(uut.mprj.mprj.proj_2.reset == 0);
+
+        // press all the buttons! button clk_en deboucing is slow so don't want to wait around
+        adj_hrs = 1;
+        adj_min = 1;
+        adj_sec = 1;
+        wait(uut.mprj.mprj.proj_2.hrs_u == 1);
+        $display ("adjusted hours ok");
+        wait(uut.mprj.mprj.proj_2.min_u == 1);
+        $display ("adjusted min ok");
+        wait(uut.mprj.mprj.proj_2.sec_u == 1);
+        $display ("adjusted sec ok");
+        
+    end
+
+    initial begin
+        RSTB <= 1'b0;
+        #2000;
+        RSTB <= 1'b1;       // Release reset
+    end
+
+    initial begin       // Power-up sequence
+        power1 <= 1'b0;
+        power2 <= 1'b0;
+        power3 <= 1'b0;
+        power4 <= 1'b0;
+        #200;
+        power1 <= 1'b1;
+        #200;
+        power2 <= 1'b1;
+        #200;
+        power3 <= 1'b1;
+        #200;
+        power4 <= 1'b1;
+    end
+
+    wire flash_csb;
+    wire flash_clk;
+    wire flash_io0;
+    wire flash_io1;
+
+    wire VDD1V8;
+        wire VDD3V3;
+    wire VSS;
+    
+    assign VDD3V3 = power1;
+    assign VDD1V8 = power2;
+    wire USER_VDD3V3 = power3;
+    wire USER_VDD1V8 = power4;
+    assign VSS = 1'b0;
+
+    caravel uut (
+        .vddio    (VDD3V3),
+        .vssio    (VSS),
+        .vdda     (VDD3V3),
+        .vssa     (VSS),
+        .vccd     (VDD1V8),
+        .vssd     (VSS),
+        .vdda1    (USER_VDD3V3),
+        .vdda2    (USER_VDD3V3),
+        .vssa1    (VSS),
+        .vssa2    (VSS),
+        .vccd1    (USER_VDD1V8),
+        .vccd2    (USER_VDD1V8),
+        .vssd1    (VSS),
+        .vssd2    (VSS),
+        .clock    (clock),
+        .gpio     (gpio),
+        .mprj_io  (mprj_io),
+        .flash_csb(flash_csb),
+        .flash_clk(flash_clk),
+        .flash_io0(flash_io0),
+        .flash_io1(flash_io1),
+        .resetb   (RSTB)
+    );
+
+    spiflash #(
+        .FILENAME("vga_clock.hex")
+    ) spiflash (
+        .csb(flash_csb),
+        .clk(flash_clk),
+        .io0(flash_io0),
+        .io1(flash_io1),
+        .io2(),         // not used
+        .io3()          // not used
+    );
+
+endmodule
diff --git a/verilog/dv/caravel/user_proj_example/ws2812/Makefile b/verilog/dv/caravel/user_proj_example/ws2812/Makefile
new file mode 100644
index 0000000..bd8cd22
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ws2812/Makefile
@@ -0,0 +1,42 @@
+FIRMWARE_PATH = ../..
+RTL_PATH = ../../../../rtl
+IP_PATH = ../../../../ip
+#MP_PATH = ../../../../rtl/multi_project_harness
+BEHAVIOURAL_MODELS = ../../
+
+TOOLCHAIN_PREFIX?=riscv32-unknown-elf-
+PDK_PATH?=$(PDK_ROOT)/sky130A/
+
+.SUFFIXES:
+
+PATTERN = ws2812
+
+all:  ${PATTERN:=.vcd}
+
+hex:  ${PATTERN:=.hex}
+
+%.vvp: %_tb.v %.hex
+	iverilog -DSIM -DFUNCTIONAL -I $(BEHAVIOURAL_MODELS) \
+	-I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+	$(TOOLCHAIN_PREFIX)gcc -mabi=ilp32 -march=rv32imc -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
+
+%.hex: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O verilog $< $@
+	# to fix flash base address
+	sed -i 's/@10000000/@00000000/g' $@
+
+%.bin: %.elf
+	$(TOOLCHAIN_PREFIX)objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
+
+# ---- Clean ----
+
+clean:
+	rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/user_proj_example/ws2812/ws2812.c b/verilog/dv/caravel/user_proj_example/ws2812/ws2812.c
new file mode 100644
index 0000000..b04ef42
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ws2812/ws2812.c
@@ -0,0 +1,68 @@
+#include "../../defs.h"
+
+/*
+	IO Test:
+		- Configures MPRJ pins
+		- Observes counter value through the LED digits
+*/
+#define reg_mprj_oeb0 (*(volatile uint32_t*)0x30000004)
+#define reg_mprj_oeb1 (*(volatile uint32_t*)0x30000008)
+
+#define reg_mprj_ws2812 (*(volatile uint32_t*)0x30000100)
+
+void main()
+{
+	/* 
+	IO Control Registers
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 3-bits | 1-bit | 1-bit | 1-bit  | 1-bit  | 1-bit | 1-bit   | 1-bit   | 1-bit | 1-bit | 1-bit   |
+
+	Output: 0000_0110_0000_1110  (0x1808) = GPIO_MODE_USER_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 0       |
+
+	Output: 0000_0110_0000_1111  (0x1809) = GPIO_MODE_MGNT_STD_OUTPUT
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 110    | 0     | 0     | 0      | 0      | 0     | 0       | 1       | 0     | 0     | 1       |
+	
+	 
+	Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
+	| DM     | VTRIP | SLOW  | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
+	| 001    | 0     | 0     | 0      | 0      | 0     | 0       | 0       | 0     | 1     | 0       |
+
+	*/
+
+    /* 
+    Inputs
+
+    system clock
+    system reset
+
+    Outputs
+
+    8 data for ws2812
+    */
+
+    reg_mprj_io_8 =  GPIO_MODE_USER_STD_OUTPUT;
+
+    /* Apply configuration */
+    reg_mprj_xfer = 1;
+    while (reg_mprj_xfer == 1);
+
+    // change to project 1
+    reg_mprj_slave = 1;
+    // all outputs enabled
+    reg_mprj_oeb0 = 0;
+
+    // use logic analyser to reset the design
+    reg_la0_ena  = 0x00000000; // bits 31:0 outputs
+    reg_la0_data = 0x00000001; // reset high is on bit 0
+    reg_la0_data = 0x00000000; // low
+
+    // update led 7
+    uint8_t led_num = 7;
+    uint8_t r = 255;
+    uint8_t g = 10;
+    uint8_t b = 100;
+    reg_mprj_ws2812 = (led_num << 24) + (r << 16) + (g << 8) + b;
+}
diff --git a/verilog/dv/caravel/user_proj_example/ws2812/ws2812.gtkw b/verilog/dv/caravel/user_proj_example/ws2812/ws2812.gtkw
new file mode 100644
index 0000000..65cbad9
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ws2812/ws2812.gtkw
@@ -0,0 +1,250 @@
+[*]
+[*] GTKWave Analyzer v3.3.108 (w)1999-2020 BSI
+[*] Fri Nov 20 10:34:36 2020
+[*]
+[dumpfile] "/home/matt/work/asic-workshop/caravel/verilog/dv/caravel/user_proj_example/ws2812/ws2812.vcd"
+[dumpfile_mtime] "Fri Nov 20 10:32:17 2020"
+[dumpfile_size] 192131563
+[savefile] "/home/matt/work/asic-workshop/caravel/verilog/dv/caravel/user_proj_example/ws2812/ws2812.gtkw"
+[timestart] 0
+[size] 2488 1529
+[pos] -1 -1
+*-26.000000 138637500 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] ws2812_tb.
+[treeopen] ws2812_tb.uut.
+[treeopen] ws2812_tb.uut.gpio_control_bidir[0].gpio_in_buf.
+[treeopen] ws2812_tb.uut.gpio_control_in[4].gpio_in_buf.
+[treeopen] ws2812_tb.uut.gpio_control_in[4].gpio_logic_high.
+[treeopen] ws2812_tb.uut.mprj.
+[treeopen] ws2812_tb.uut.mprj.mprj.
+[treeopen] ws2812_tb.uut.mprj.mprj.proj_0.
+[treeopen] ws2812_tb.uut.mprj.mprj.proj_2.
+[treeopen] ws2812_tb.uut.soc.
+[treeopen] ws2812_tb.uut.soc.housekeeping.
+[treeopen] ws2812_tb.uut.soc.soc.
+[treeopen] ws2812_tb.uut.soc.soc.cpu.
+[treeopen] ws2812_tb.uut.soc.soc.cpu.picorv32_core.
+[treeopen] ws2812_tb.uut.soc.soc.gpio_wb.
+[treeopen] ws2812_tb.uut.soc.soc.mprj_ctrl.
+[sst_width] 719
+[signals_width] 682
+[sst_expanded] 1
+[sst_vpaned_height] 862
+@28
+ws2812_tb.clock
+ws2812_tb.RSTB
+@200
+-
+@800200
+-wbs
+@28
+ws2812_tb.uut.mprj.mprj.wb_rst_i
+ws2812_tb.uut.mprj.mprj.wb_clk_i
+ws2812_tb.uut.mprj.mprj.wbs_ack_o
+@22
+ws2812_tb.uut.mprj.mprj.wbs_adr_i[31:0]
+@28
+ws2812_tb.uut.mprj.mprj.wbs_cyc_i
+@24
+ws2812_tb.uut.mprj.mprj.wbs_dat_i[31:0]
+@22
+ws2812_tb.uut.mprj.mprj.wbs_dat_o[31:0]
+ws2812_tb.uut.mprj.mprj.wbs_sel_i[3:0]
+@28
+ws2812_tb.uut.mprj.mprj.wbs_stb_i
+ws2812_tb.uut.mprj.mprj.wbs_we_i
+ws2812_tb.uut.mprj.mprj.valid
+@24
+ws2812_tb.uut.mprj.mprj.wstrb[3:0]
+@1000200
+-wbs
+@800200
+-multi proj control
+@28
+ws2812_tb.uut.soc.soc.mprj_ctrl.mprj_ctrl.xfer_ctrl
+@1000200
+-multi proj control
+@800200
+-la
+@22
+ws2812_tb.uut.mprj.mprj.la_data_in[127:0]
+ws2812_tb.uut.mprj.mprj.la_data_out[127:0]
+ws2812_tb.uut.mprj.mprj.la_oen[127:0]
+@1000200
+-la
+@22
+ws2812_tb.uut.soc.soc.cpu.picorv32_core.next_insn_opcode[31:0]
+@200
+-
+@800200
+-multi project
+@22
+ws2812_tb.uut.mprj.mprj.active_project[7:0]
+@28
+ws2812_tb.uut.mprj.mprj.wb_rst_i
+@c00022
+ws2812_tb.uut.mprj.io_in[37:0]
+@28
+(0)ws2812_tb.uut.mprj.io_in[37:0]
+(1)ws2812_tb.uut.mprj.io_in[37:0]
+(2)ws2812_tb.uut.mprj.io_in[37:0]
+(3)ws2812_tb.uut.mprj.io_in[37:0]
+(4)ws2812_tb.uut.mprj.io_in[37:0]
+(5)ws2812_tb.uut.mprj.io_in[37:0]
+(6)ws2812_tb.uut.mprj.io_in[37:0]
+(7)ws2812_tb.uut.mprj.io_in[37:0]
+(8)ws2812_tb.uut.mprj.io_in[37:0]
+(9)ws2812_tb.uut.mprj.io_in[37:0]
+(10)ws2812_tb.uut.mprj.io_in[37:0]
+(11)ws2812_tb.uut.mprj.io_in[37:0]
+(12)ws2812_tb.uut.mprj.io_in[37:0]
+(13)ws2812_tb.uut.mprj.io_in[37:0]
+(14)ws2812_tb.uut.mprj.io_in[37:0]
+(15)ws2812_tb.uut.mprj.io_in[37:0]
+(16)ws2812_tb.uut.mprj.io_in[37:0]
+(17)ws2812_tb.uut.mprj.io_in[37:0]
+(18)ws2812_tb.uut.mprj.io_in[37:0]
+(19)ws2812_tb.uut.mprj.io_in[37:0]
+(20)ws2812_tb.uut.mprj.io_in[37:0]
+(21)ws2812_tb.uut.mprj.io_in[37:0]
+(22)ws2812_tb.uut.mprj.io_in[37:0]
+(23)ws2812_tb.uut.mprj.io_in[37:0]
+(24)ws2812_tb.uut.mprj.io_in[37:0]
+(25)ws2812_tb.uut.mprj.io_in[37:0]
+(26)ws2812_tb.uut.mprj.io_in[37:0]
+(27)ws2812_tb.uut.mprj.io_in[37:0]
+(28)ws2812_tb.uut.mprj.io_in[37:0]
+(29)ws2812_tb.uut.mprj.io_in[37:0]
+(30)ws2812_tb.uut.mprj.io_in[37:0]
+(31)ws2812_tb.uut.mprj.io_in[37:0]
+(32)ws2812_tb.uut.mprj.io_in[37:0]
+(33)ws2812_tb.uut.mprj.io_in[37:0]
+(34)ws2812_tb.uut.mprj.io_in[37:0]
+(35)ws2812_tb.uut.mprj.io_in[37:0]
+(36)ws2812_tb.uut.mprj.io_in[37:0]
+(37)ws2812_tb.uut.mprj.io_in[37:0]
+@1401200
+-group_end
+@c00022
+ws2812_tb.uut.mprj.mprj.io_out[37:0]
+@28
+(0)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(1)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(2)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(3)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(4)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(5)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(6)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(7)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(8)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(9)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(10)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(11)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(12)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(13)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(14)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(15)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(16)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(17)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(18)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(19)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(20)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(21)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(22)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(23)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(24)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(25)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(26)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(27)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(28)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(29)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(30)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(31)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(32)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(33)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(34)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(35)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(36)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+(37)ws2812_tb.uut.mprj.mprj.io_out[37:0]
+@1401200
+-group_end
+@1000200
+-multi project
+@800022
+ws2812_tb.mprj_io[37:0]
+@28
+(0)ws2812_tb.mprj_io[37:0]
+(1)ws2812_tb.mprj_io[37:0]
+(2)ws2812_tb.mprj_io[37:0]
+(3)ws2812_tb.mprj_io[37:0]
+(4)ws2812_tb.mprj_io[37:0]
+(5)ws2812_tb.mprj_io[37:0]
+(6)ws2812_tb.mprj_io[37:0]
+(7)ws2812_tb.mprj_io[37:0]
+(8)ws2812_tb.mprj_io[37:0]
+(9)ws2812_tb.mprj_io[37:0]
+(10)ws2812_tb.mprj_io[37:0]
+(11)ws2812_tb.mprj_io[37:0]
+(12)ws2812_tb.mprj_io[37:0]
+(13)ws2812_tb.mprj_io[37:0]
+(14)ws2812_tb.mprj_io[37:0]
+(15)ws2812_tb.mprj_io[37:0]
+(16)ws2812_tb.mprj_io[37:0]
+(17)ws2812_tb.mprj_io[37:0]
+(18)ws2812_tb.mprj_io[37:0]
+(19)ws2812_tb.mprj_io[37:0]
+(20)ws2812_tb.mprj_io[37:0]
+(21)ws2812_tb.mprj_io[37:0]
+(22)ws2812_tb.mprj_io[37:0]
+(23)ws2812_tb.mprj_io[37:0]
+(24)ws2812_tb.mprj_io[37:0]
+(25)ws2812_tb.mprj_io[37:0]
+(26)ws2812_tb.mprj_io[37:0]
+(27)ws2812_tb.mprj_io[37:0]
+(28)ws2812_tb.mprj_io[37:0]
+(29)ws2812_tb.mprj_io[37:0]
+(30)ws2812_tb.mprj_io[37:0]
+(31)ws2812_tb.mprj_io[37:0]
+(32)ws2812_tb.mprj_io[37:0]
+(33)ws2812_tb.mprj_io[37:0]
+(34)ws2812_tb.mprj_io[37:0]
+(35)ws2812_tb.mprj_io[37:0]
+(36)ws2812_tb.mprj_io[37:0]
+(37)ws2812_tb.mprj_io[37:0]
+@1001200
+-group_end
+@c00200
+-seven seg
+@28
+ws2812_tb.uut.mprj.mprj.proj_0.clk
+@22
+ws2812_tb.uut.mprj.mprj.proj_0.second_counter[23:0]
+@24
+ws2812_tb.uut.mprj.mprj.proj_0.compare[23:0]
+@28
+ws2812_tb.uut.mprj.mprj.proj_0.reset
+@800022
+ws2812_tb.uut.mprj.mprj.proj_0.digit[3:0]
+@28
+(0)ws2812_tb.uut.mprj.mprj.proj_0.digit[3:0]
+(1)ws2812_tb.uut.mprj.mprj.proj_0.digit[3:0]
+(2)ws2812_tb.uut.mprj.mprj.proj_0.digit[3:0]
+(3)ws2812_tb.uut.mprj.mprj.proj_0.digit[3:0]
+@22
+ws2812_tb.uut.mprj.mprj.proj_0.led_out[6:0]
+@1001200
+-group_end
+@1401200
+-seven seg
+@29
+ws2812_tb.uut.mprj.mprj.proj_1.reset
+@800200
+-ws2812
+@24
+ws2812_tb.uut.mprj.mprj.proj_1.bit_counter[11:0]
+ws2812_tb.uut.mprj.mprj.proj_1.rgb_counter[4:0]
+ws2812_tb.uut.mprj.mprj.proj_1.led_counter[2:0]
+@1000200
+-ws2812
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/verilog/dv/caravel/user_proj_example/ws2812/ws2812_tb.v b/verilog/dv/caravel/user_proj_example/ws2812/ws2812_tb.v
new file mode 100644
index 0000000..2f12b51
--- /dev/null
+++ b/verilog/dv/caravel/user_proj_example/ws2812/ws2812_tb.v
@@ -0,0 +1,115 @@
+`default_nettype none
+
+`timescale 1 ns / 1 ps
+
+`include "caravel.v"
+`include "spiflash.v"
+
+module ws2812_tb;
+    reg clock;
+    reg RSTB;
+    reg power1, power2;
+    reg power3, power4;
+
+    wire gpio;
+    wire [37:0] mprj_io;
+
+    // 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 #12.5 clock <= (clock === 1'b0);
+
+    initial begin
+        clock = 0;
+    end
+
+
+    initial begin
+        $dumpfile("ws2812.vcd");
+        $dumpvars(0, ws2812_tb);
+
+        // Repeat cycles of 1000 clock edges as needed to complete testbench
+        repeat (15) begin
+            repeat (1000) @(posedge clock);
+            // $display("+1000 cycles");
+        end
+        $display("%c[1;31m",27);
+        $display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed");
+        $display("%c[0m",27);
+        $finish;
+    end
+
+    initial begin
+        RSTB <= 1'b0;
+        #2000;
+        RSTB <= 1'b1;       // Release reset
+    end
+
+    initial begin       // Power-up sequence
+        power1 <= 1'b0;
+        power2 <= 1'b0;
+        power3 <= 1'b0;
+        power4 <= 1'b0;
+        #200;
+        power1 <= 1'b1;
+        #200;
+        power2 <= 1'b1;
+        #200;
+        power3 <= 1'b1;
+        #200;
+        power4 <= 1'b1;
+    end
+
+    wire flash_csb;
+    wire flash_clk;
+    wire flash_io0;
+    wire flash_io1;
+
+    wire VDD1V8;
+    wire VDD3V3;
+    wire VSS;
+    
+    assign VDD3V3 = power1;
+    assign VDD1V8 = power2;
+    wire USER_VDD3V3 = power3;
+    wire USER_VDD1V8 = power4;
+    assign VSS = 1'b0;
+
+    caravel uut (
+        .vddio    (VDD3V3),
+        .vssio    (VSS),
+        .vdda     (VDD3V3),
+        .vssa     (VSS),
+        .vccd     (VDD1V8),
+        .vssd     (VSS),
+        .vdda1    (USER_VDD3V3),
+        .vdda2    (USER_VDD3V3),
+        .vssa1    (VSS),
+        .vssa2    (VSS),
+        .vccd1    (USER_VDD1V8),
+        .vccd2    (USER_VDD1V8),
+        .vssd1    (VSS),
+        .vssd2    (VSS),
+        .clock    (clock),
+        .gpio     (gpio),
+            .mprj_io  (mprj_io),
+        .flash_csb(flash_csb),
+        .flash_clk(flash_clk),
+        .flash_io0(flash_io0),
+        .flash_io1(flash_io1),
+        .resetb   (RSTB)
+    );
+
+    spiflash #(
+        .FILENAME("ws2812.hex")
+    ) spiflash (
+        .csb(flash_csb),
+        .clk(flash_clk),
+        .io0(flash_io0),
+        .io1(flash_io1),
+        .io2(),         // not used
+        .io3()          // not used
+    );
+
+endmodule
diff --git a/verilog/rtl/user_project_wrapper.v b/verilog/rtl/user_project_wrapper.v
index 47d92f4..c5f1aaf 100644
--- a/verilog/rtl/user_project_wrapper.v
+++ b/verilog/rtl/user_project_wrapper.v
@@ -1,19 +1,8 @@
-// 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
+`include "multi_project_harness/includes.v"
+`ifdef COCOTB_SIM
+    `define MPRJ_IO_PADS 38
+`endif
 /*
  *-------------------------------------------------------------
  *
@@ -78,8 +67,8 @@
     /*--------------------------------------*/
     /* User project is instantiated  here   */
     /*--------------------------------------*/
-
-    user_proj_example mprj (
+    parameter num_projects = 8;
+    multi_project_harness #(.num_projects(num_projects)) mprj (
     `ifdef USE_POWER_PINS
 	.vdda1(vdda1),	// User area 1 3.3V power
 	.vdda2(vdda2),	// User area 2 3.3V power
@@ -116,9 +105,200 @@
 	// IO Pads
 
 	.io_in (io_in),
-    	.io_out(io_out),
-    	.io_oeb(io_oeb)
+    .io_out(io_out),
+    .io_oeb(io_oeb),
+
+    .proj0_wb_update    (proj0_wb_update),
+    .proj0_clk          (proj0_clk),
+    .proj0_reset        (proj0_reset),
+    .proj0_io_in        (proj0_io_in),
+    .proj0_io_out       (proj0_io_out),
+
+    .proj1_wb_update    (proj1_wb_update),
+    .proj1_clk          (proj1_clk),
+    .proj1_reset        (proj1_reset),
+    .proj1_io_in        (proj1_io_in),
+    .proj1_io_out       (proj1_io_out),
+
+    .proj2_clk          (proj2_clk),
+    .proj2_reset        (proj2_reset),
+    .proj2_io_in        (proj2_io_in),
+    .proj2_io_out       (proj2_io_out),
+
+    .proj3_clk          (proj3_clk),
+    .proj3_reset        (proj3_reset),
+    .proj3_io_in        (proj3_io_in),
+    .proj3_io_out       (proj3_io_out),
+
+    .proj4_clk          (proj4_clk),
+    .proj4_reset        (proj4_reset),
+    .proj4_io_in        (proj4_io_in),
+    .proj4_io_out       (proj4_io_out),
+    .proj4_cnt          (proj4_cnt),
+    .proj4_cnt_cont     (proj4_cnt_cont),
+    .proj4_wb_update    (proj4_wb_update),
+
+    .proj5_wb_update    (proj5_wb_update),
+    .proj5_clk          (proj5_clk),
+    .proj5_reset        (proj5_reset),
+    .proj5_io_in        (proj5_io_in),
+    .proj5_io_out       (proj5_io_out),
+
+    .proj6_clk          (proj6_clk),
+    .proj6_io_in        (proj6_io_in),
+    .proj6_io_out       (proj6_io_out),
+
+    .proj7_reset        (proj7_reset),
+    .proj7_io_in        (proj7_io_in),
+    .proj7_io_out       (proj7_io_out)
+
     );
 
+    `ifdef COCOTB_SIM
+        initial begin
+            $dumpfile ("user_project_wrapper.vcd");
+            $dumpvars (0, user_project_wrapper);
+            #1;
+        end
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj0_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj0_io_out;
+    wire proj0_wb_update;
+    wire proj0_clk;
+    wire proj0_reset;
+
+    `ifndef NO_PROJ0
+    seven_segment_seconds proj_0 (.clk(proj0_clk), .reset(proj0_reset), .led_out(proj0_io_out[14:8]), .compare_in(wbs_dat_i[23:0]), .update_compare(proj0_wb_update));
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj1_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj1_io_out;
+    wire proj1_wb_update;
+    wire proj1_clk;
+    wire proj1_reset;
+
+    `ifndef NO_PROJ1
+    ws2812                proj_1 (.clk(proj1_clk), .reset(proj1_reset), .led_num(wbs_dat_i[31:24]), .rgb_data(wbs_dat_i[23:0]), .write(proj1_wb_update), .data(proj1_io_out[8]));
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj2_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj2_io_out;
+    wire proj2_clk;
+    wire proj2_reset;
+
+    `ifndef NO_PROJ2
+    vga_clock             proj_2 (.clk(proj2_clk), .reset_n(proj2_reset), .adj_hrs(proj2_io_in[8]), .adj_min(proj2_io_in[9]), .adj_sec(proj2_io_in[10]), .hsync(proj2_io_out[11]), .vsync(proj2_io_out[12]), .rrggbb(proj2_io_out[18:13]));
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj3_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj3_io_out;
+    wire proj3_clk;
+    wire proj3_reset;
+
+    `ifndef NO_PROJ3
+	spinet5 proj_3 ( .clk(proj3_clk), .rst(proj3_reset), .io_in(proj3_io_in), .io_out(proj3_io_out));
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj4_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj4_io_out;
+    wire proj4_clk;
+    wire proj4_reset;
+    wire [31:0] proj4_cnt;
+    wire [31:0] proj4_cnt_cont;
+    wire proj4_wb_update;
+
+    `ifndef NO_PROJ4
+    asic_freq proj_4(
+        .clk(proj4_clk),
+        .rst(proj4_reset),
+
+        // register write interface (ignores < 32 bit writes):
+        // 30000400:
+        //   write UART clock divider (min. value = 4),
+        // 30000404:
+        //   write frequency counter update period [sys_clks]
+        // 30000408
+        //   set 7-segment display mode,
+        //   0: show meas. freq., 1: show wishbone value
+        // 3000040C
+        //   set 7-segment display value:
+        //   digit7 ... digit0  (4 bit each)
+        // 30000410
+        //   set 7-segment display value:
+        //   digit8
+        // 30000414
+        //   set 7-segment decimal points:
+        //   dec_point8 ... dec_point0  (1 bit each)
+        // 30000418
+        //   read periodically reset freq. counter value
+        // 3000041C
+        //   read continuous freq. counter value
+        .addr(wbs_adr_i[5:2]),
+        .value(wbs_dat_i),
+        .strobe(proj4_wb_update),
+
+        // signal under test input
+        .samplee(proj4_io_in[25]),
+
+        // periodic counter output to wishbone
+        .o(proj4_cnt),
+
+        // continuous counter output to wishbone
+        .oc(proj4_cnt_cont),
+
+        // UART output to FTDI input
+        .tx(proj4_io_out[6]),
+
+        // 7 segment display outputs
+        .col_drvs(proj4_io_out[16:8]),  // 9 x column drivers
+        .seg_drvs(proj4_io_out[24:17])  // 8 x segment drivers
+    );
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj5_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj5_io_out;
+    wire proj5_clk;
+    wire proj5_reset;
+    wire proj5_wb_update;
+
+    `ifndef NO_PROJ5
+    watch_hhmm proj_5 (
+        .sysclk_i     (proj5_clk),
+        .smode_i      (proj5_io_in[36]),
+        .sclk_i       (proj5_io_in[37]),
+        .dvalid_i     (proj5_wb_update),
+        .cfg_i        (wbs_dat_i[11:0]),
+        .rstn_i       (proj5_reset),
+        .segment_hxxx (proj5_io_out[14:8]),
+        .segment_xhxx (proj5_io_out[21:15]),
+        .segment_xxmx (proj5_io_out[28:22]),
+        .segment_xxxm (proj5_io_out[35:29])
+    );
+    `endif
+
+    wire [`MPRJ_IO_PADS-1:0] proj6_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj6_io_out;
+    wire proj6_clk;
+    `ifndef NO_PROJ6
+    challenge proj_6 (.uart(proj6_io_in[8]), .clk_10(proj6_clk), .led_green(proj6_io_out[9]), .led_red(proj6_io_out[10]));
+    `endif
+
+
+    wire [`MPRJ_IO_PADS-1:0] proj7_io_in;
+    wire [`MPRJ_IO_PADS-1:0] proj7_io_out;
+    wire proj7_reset;
+
+    `ifndef NO_PROJ7
+    MM2hdmi proj_7 (
+    .clock(proj7_io_in[35]),
+    .reset(proj7_reset),
+    .io_data(proj7_io_in[23:8]),
+    .io_newData(proj7_io_in[24]),
+    .io_red(proj7_io_out[32:25]),
+    .io_hSync(proj7_io_out[33]),
+    .io_vSync(proj7_io_out[34])
+    );
+    `endif
 endmodule	// user_project_wrapper
 `default_nettype wire