Add an automated JTAG IDCODE test case
diff --git a/verilog/dv/caravel/microwatt/jtag/Makefile b/verilog/dv/caravel/microwatt/jtag/Makefile
new file mode 100644
index 0000000..54ddec5
--- /dev/null
+++ b/verilog/dv/caravel/microwatt/jtag/Makefile
@@ -0,0 +1,59 @@
+FIRMWARE_PATH = ../..
+VERILOG_PATH = ../../../..
+RTL_PATH = $(VERILOG_PATH)/rtl
+IP_PATH = ../../../../ip
+BEHAVIOURAL_MODELS = ../../
+
+PDK_PATH?=/ef/tech/SW/sky130A
+
+RISCV_CROSS_COMPILE?=riscv64-linux-gnu-
+RISCV_CFLAGS=-static -Os -g -Wall -march=rv32imc -mabi=ilp32 -ffreestanding -nostdlib
+
+POWERPC_CROSS_COMPILE?=powerpc64le-linux-gnu-
+POWERPC_CFLAGS=-static -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -ffreestanding -fdata-sections -ffunction-sections -nostdlib -I../include
+
+SIM?=RTL
+
+.SUFFIXES:
+
+PATTERN = jtag
+
+all: ${PATTERN:=.vcd}
+
+%.vvp: %_tb.v mgmt_engine.hex microwatt.hex
+ifeq ($(SIM),RTL)
+ iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \
+ -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \
+ $< -o $@
+else
+ iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \
+ -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \
+ $< -o $@
+endif
+
+%.vcd: %.vvp
+ vvp $<
+
+# Management engine code
+
+mgmt_engine.elf: mgmt_engine.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s
+ $(RISCV_CROSS_COMPILE)gcc $(RISCV_CFLAGS) -Wl,-T,$(FIRMWARE_PATH)/sections.lds -o $@ $(FIRMWARE_PATH)/start.s $<
+
+mgmt_engine.hex: mgmt_engine.elf
+ $(RISCV_CROSS_COMPILE)objcopy -O verilog $< $@
+ # to fix flash base address
+ sed -i 's/@1000/@0000/g' $@
+
+# Microwatt code
+microwatt.elf: microwatt.c ../lib/console.c ../lib/head.S ../microwatt.lds
+ $(POWERPC_CROSS_COMPILE)gcc $(POWERPC_CFLAGS) -Wl,-T,../microwatt.lds -o $@ microwatt.c ../lib/console.c ../lib/head.S
+
+microwatt.hex: microwatt.elf
+ $(POWERPC_CROSS_COMPILE)objcopy -O verilog $< $@
+ # to fix flash base address
+ sed -i 's/@F000/@0000/g' $@
+
+clean:
+ rm -f *.vvp *.vcd *.elf *.bin *.o *.vvp *.vcd *.log *.hex
+
+.PHONY: clean hex all
diff --git a/verilog/dv/caravel/microwatt/jtag/jtag_tb.v b/verilog/dv/caravel/microwatt/jtag/jtag_tb.v
new file mode 100644
index 0000000..6476190
--- /dev/null
+++ b/verilog/dv/caravel/microwatt/jtag/jtag_tb.v
@@ -0,0 +1,259 @@
+`default_nettype none
+/*
+ * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Tim Edwards <tim@efabless.com>
+ * Copyright (C) 2020 Anton Blanchard <anton@linux.ibm.com>
+ * Copyright (C) 2021 Michael Neuling <mikey@linux.ibm.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+`timescale 1 ns / 1 ps
+
+`include "caravel_netlists.v"
+`include "spiflash.v"
+
+module jtag_expect_idcode (
+ input tdo,
+ input tck,
+ input en
+);
+ reg [4:0] recv_state;
+ reg [31:0] pattern;
+
+ reg clk;
+
+ initial begin
+ recv_state <= 0;
+ pattern <= 0;
+ end
+
+ always @(posedge tck) begin
+ if (en == 1'b1) begin
+ pattern <= {tdo, pattern[31:1]};
+ recv_state <= recv_state + 1;
+ end
+ case (recv_state)
+ 31: begin
+ recv_state <= 0;
+ $display("Testing: Read %x from JTAG", pattern);
+ // Expecting 7 back
+ if (pattern == 32'h14d57048) begin
+ $display("PASSED");
+ $finish;
+ end else begin
+ $display("FAILED: should have been 14d57048");
+ $fatal;
+ end
+ end
+ endcase
+ end
+endmodule
+
+module jtag_tb;
+ reg clock;
+ reg RSTB;
+ reg CSB;
+ reg power1, power2;
+
+ wire gpio;
+ wire flash_csb;
+ wire flash_clk;
+ wire flash_io0;
+ wire flash_io1;
+ wire [37:0] mprj_io;
+ wire user_flash_csb;
+ wire user_flash_clk;
+ inout user_flash_io0;
+ inout user_flash_io1;
+
+ wire jtag_tdo;
+ reg jtag_tdo_en;
+ reg jtag_tms;
+ reg jtag_tck;
+ reg jtag_tdi;
+
+ assign user_flash_csb = mprj_io[8];
+ assign user_flash_clk = mprj_io[9];
+ assign user_flash_io0 = mprj_io[10];
+ assign mprj_io[11] = user_flash_io1;
+
+ assign jtag_tdo = mprj_io[14];
+ assign mprj_io[15] = jtag_tms;
+ assign mprj_io[16] = jtag_tck;
+ assign mprj_io[17] = jtag_tdi;
+
+ // 50 MHz clock
+ always #10 clock <= (clock === 1'b0);
+
+ initial begin
+ clock = 0;
+ end
+
+ initial begin
+ $dumpfile("jtag.vcd");
+ $dumpvars(0, jtag_tb);
+
+ $display("Microwatt JTAG IDCODE test");
+
+ repeat (150) begin
+ repeat (10000) @(posedge clock);
+ // Diagnostic. . . interrupts output pattern.
+ end
+ $finish;
+ end
+
+ initial begin
+ RSTB <= 1'b0;
+ CSB <= 1'b1; // Force CSB high
+ #1000;
+ RSTB <= 1'b1; // Release reset
+ #170000;
+ CSB = 1'b0; // CSB can be released
+ end
+
+ initial begin // Power-up sequence
+ power1 <= 1'b0;
+ power2 <= 1'b0;
+ #200;
+ power1 <= 1'b1;
+ #200;
+ power2 <= 1'b1;
+ end
+
+ initial begin
+ jtag_tms <= 1'b1;
+ jtag_tck <= 1'b1;
+ jtag_tdi <= 1'b1;
+ jtag_tdo_en <= 1'b0;
+
+ #200000;
+
+ jtag_tms <= 1'b1;
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ jtag_tms <= 1'b0; //rti
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ jtag_tms <= 1'b1; //drs
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ jtag_tms <= 1'b0; // cdr
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ jtag_tms <= 1'b0; // sdr
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ jtag_tms <= 1'b0; // sdr
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ jtag_tms <= 1'b0; // sdr
+ jtag_tdo_en <= 1'b1;
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+
+ repeat (32) begin
+ jtag_tck <= 1'b0;
+ #1000;
+ jtag_tck <= 1'b1;
+ #1000;
+ end
+
+ end
+
+ wire VDD3V3;
+ wire VDD1V8;
+ wire VSS;
+
+ assign VDD3V3 = power1;
+ assign VDD1V8 = power2;
+ assign VSS = 1'b0;
+
+ assign mprj_io[3] = (CSB == 1'b1) ? 1'b1 : 1'bz;
+
+ caravel uut (
+ .vddio (VDD3V3),
+ .vssio (VSS),
+ .vdda (VDD3V3),
+ .vssa (VSS),
+ .vccd (VDD1V8),
+ .vssd (VSS),
+ .vdda1 (VDD3V3),
+ .vdda2 (VDD3V3),
+ .vssa1 (VSS),
+ .vssa2 (VSS),
+ .vccd1 (VDD1V8),
+ .vccd2 (VDD1V8),
+ .vssd1 (VSS),
+ .vssd2 (VSS),
+ .clock (clock),
+ .gpio (gpio),
+ .mprj_io (mprj_io),
+ .flash_csb(flash_csb),
+ .flash_clk(flash_clk),
+ .flash_io0(flash_io0),
+ .flash_io1(flash_io1),
+ .resetb (RSTB)
+ );
+
+ spiflash #(
+ .FILENAME("mgmt_engine.hex")
+ ) spiflash (
+ .csb(flash_csb),
+ .clk(flash_clk),
+ .io0(flash_io0),
+ .io1(flash_io1),
+ .io2(), // not used
+ .io3() // not used
+ );
+
+ spiflash #(
+ .FILENAME("microwatt.hex")
+ ) spiflash_microwatt (
+ .csb(user_flash_csb),
+ .clk(user_flash_clk),
+ .io0(user_flash_io0),
+ .io1(user_flash_io1),
+ .io2(), // not used
+ .io3() // not used
+ );
+
+ jtag_expect_idcode tb_jtag (
+ .tdo(jtag_tdo),
+ .tck(jtag_tck),
+ .en(jtag_tdo_en)
+ );
+
+endmodule
+`default_nettype wire
diff --git a/verilog/dv/caravel/microwatt/jtag/mgmt_engine.c b/verilog/dv/caravel/microwatt/jtag/mgmt_engine.c
new file mode 100644
index 0000000..d42cbf8
--- /dev/null
+++ b/verilog/dv/caravel/microwatt/jtag/mgmt_engine.c
@@ -0,0 +1,22 @@
+#include "../../defs.h"
+#include "../../stub.c"
+
+#include "../include/microwatt_util.h"
+#include "../include/mgmt_engine_util.h"
+
+void main(void)
+{
+ mgmt_engine_io_setup(true, true);
+
+ // Take microwatt out of reset
+ reg_la2_data &= ~0x00000002;
+
+ while (reg_la0_data != LA_MICROWATT_START)
+ /* Do Nothing */ ;
+
+ // Signal to TB that microwatt is alive
+ reg_mprj_datal = GPIO1_MICROWATT_START;
+
+ while (1)
+ /* Do Nothing */;
+}
diff --git a/verilog/dv/caravel/microwatt/jtag/microwatt.c b/verilog/dv/caravel/microwatt/jtag/microwatt.c
new file mode 100644
index 0000000..1f2a497
--- /dev/null
+++ b/verilog/dv/caravel/microwatt/jtag/microwatt.c
@@ -0,0 +1,15 @@
+#include <stdint.h>
+
+#include "console.h"
+#include "microwatt_util.h"
+
+int main(void)
+{
+ console_init();
+
+ microwatt_alive();
+
+ /* Do nothing for JTAG test */
+ while (1) {
+ }
+}