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) { + } +}