parent
5c87fc09ef
commit
8214134b89
|
@ -1,2 +1,2 @@
|
|||
本分支(bram)是在master分支的基础上,将指令和数据存储器由LUTRAM(DRAM)改为BRAM,以便可以运行更大的(C语言)程序。
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
+incdir+../rtl/core
|
||||
|
||||
../rtl/core/clint.sv
|
||||
../rtl/core/csr_reg.sv
|
||||
../rtl/core/defines.sv
|
||||
../rtl/core/divider.sv
|
||||
../rtl/core/exu.sv
|
||||
../rtl/core/exu_alu_datapath.sv
|
||||
../rtl/core/exu_commit.sv
|
||||
../rtl/core/exu_dispatch.sv
|
||||
../rtl/core/exu_mem.sv
|
||||
../rtl/core/exu_muldiv.sv
|
||||
../rtl/core/gpr_reg.sv
|
||||
../rtl/core/idu.sv
|
||||
../rtl/core/idu_exu.sv
|
||||
../rtl/core/ifu.sv
|
||||
../rtl/core/ifu_idu.sv
|
||||
../rtl/core/pipe_ctrl.sv
|
||||
../rtl/core/rst_ctrl.sv
|
||||
../rtl/core/tinyriscv_core.sv
|
||||
|
||||
../rtl/debug/jtag_dm.sv
|
||||
../rtl/debug/jtag_driver.sv
|
||||
../rtl/debug/jtag_top.sv
|
||||
|
||||
../rtl/perips/gpio.sv
|
||||
../rtl/perips/ram.sv
|
||||
../rtl/perips/rom.sv
|
||||
../rtl/perips/timer.sv
|
||||
../rtl/perips/uart.sv
|
||||
|
||||
../rtl/sys_bus/rib.sv
|
||||
|
||||
../rtl/top/tinyriscv_soc_top.sv
|
||||
|
||||
../rtl/utils/full_handshake_rx.sv
|
||||
../rtl/utils/full_handshake_tx.sv
|
||||
../rtl/utils/gen_buf.sv
|
||||
../rtl/utils/gen_dff.sv
|
||||
../rtl/utils/gen_ram.sv
|
||||
../rtl/utils/vld_rdy.sv
|
||||
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// core local interruptor module
|
||||
// 核心中断管理、仲裁模块
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// CSR寄存器模块
|
||||
module csr_reg(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 除法模块
|
||||
// 试商法实现32位整数除法
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 执行模块
|
||||
// 纯组合逻辑电路
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
|
||||
`define DATAPATH_MUX_WIDTH (32+32+16)
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
|
||||
module exu_commit(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
|
||||
module exu_dispatch(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
|
||||
module exu_mem(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
|
||||
module exu_muldiv(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 通用寄存器模块
|
||||
module gpr_reg(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 译码模块
|
||||
// 纯组合逻辑电路
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 将译码结果向执行模块传递
|
||||
module idu_exu(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 取指模块
|
||||
module ifu(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 将指令向译码模块传递
|
||||
module ifu_idu(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 流水线控制模块
|
||||
// 发出暂停、冲刷流水线信号
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// 复位控制模块
|
||||
module rst_ctrl(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "defines.v"
|
||||
`include "defines.sv"
|
||||
|
||||
// tinyriscv处理器核顶层模块
|
||||
module tinyriscv_core(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
// JTAG顶层模块
|
||||
module jtag_top #(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
|
||||
module ram #(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
|
||||
module rom #(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
// 32位向上计数定时器模块
|
||||
module timer(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
// 串口收发模块(默认: 115200, 8,N,1)
|
||||
module uart(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
// tinyriscv soc顶层模块
|
||||
module tinyriscv_soc_top(
|
|
@ -14,7 +14,7 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "../core/defines.v"
|
||||
`include "../core/defines.sv"
|
||||
|
||||
|
||||
module gen_ram #(
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
RISCV_TOOLS_PATH := $(TOOLCHAIN_DIR)/tools/gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64/bin
|
||||
RISCV_TOOLS_PREFIX := riscv-none-embed-
|
||||
RISCV_TOOLS_PATH := /opt/riscv/bin
|
||||
RISCV_TOOLS_PREFIX := riscv32-unknown-elf-
|
||||
|
||||
RISCV_GCC := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)gcc)
|
||||
RISCV_AS := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)as)
|
||||
|
@ -11,6 +10,8 @@ RISCV_AR := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)ar)
|
|||
RISCV_OBJCOPY := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)objcopy)
|
||||
RISCV_READELF := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)readelf)
|
||||
|
||||
BIN_TO_MEM := $(COMMON_DIR)/../../tools/BinToMem.py
|
||||
|
||||
.PHONY: all
|
||||
all: $(TARGET)
|
||||
|
||||
|
@ -34,7 +35,7 @@ C_OBJS := $(C_SRCS:.c=.o)
|
|||
LINK_OBJS += $(ASM_OBJS) $(C_OBJS)
|
||||
LINK_DEPS += $(LINKER_SCRIPT)
|
||||
|
||||
CLEAN_OBJS += $(TARGET) $(LINK_OBJS) $(TARGET).dump $(TARGET).bin
|
||||
CLEAN_OBJS += $(TARGET) $(LINK_OBJS) $(TARGET).dump $(TARGET).bin $(TARGET).hex $(TARGET).mem
|
||||
|
||||
CFLAGS += -march=$(RISCV_ARCH)
|
||||
CFLAGS += -mabi=$(RISCV_ABI)
|
||||
|
@ -44,6 +45,7 @@ $(TARGET): $(LINK_OBJS) $(LINK_DEPS) Makefile
|
|||
$(RISCV_GCC) $(CFLAGS) $(INCLUDES) $(LINK_OBJS) -o $@ $(LDFLAGS)
|
||||
$(RISCV_OBJCOPY) -O binary $@ $@.bin
|
||||
$(RISCV_OBJDUMP) --disassemble-all $@ > $@.dump
|
||||
$(BIN_TO_MEM) $@.bin $@.mem
|
||||
|
||||
$(ASM_OBJS): %.o: %.S
|
||||
$(RISCV_GCC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
testbench_verilator
|
||||
*.log
|
||||
*.vcd
|
||||
*.bin
|
||||
*.dump
|
||||
inst.data
|
||||
out.vvp
|
||||
tinyriscv_soc_tb.vcd
|
||||
jtag_tb.vcd
|
||||
cobj_dir/
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
PROG := ../sdk/examples/simple/simple.mem
|
||||
PROG_DIR := $(shell dirname $(PROG))
|
||||
|
||||
MAKE := make
|
||||
VERILATOR := verilator
|
||||
|
||||
VERI_FLAGS += +vcd
|
||||
VERI_CFLAGS +=
|
||||
|
||||
VERI_VFLAGS += -DRVFI
|
||||
|
||||
TRACE_ENABLE := 1
|
||||
|
||||
RTL_FILES = ../rtl.flist
|
||||
|
||||
VERI_OBJ_DIR := cobj_dir
|
||||
|
||||
ifeq ($(findstring +vcd,$(VERI_FLAGS)),+vcd)
|
||||
VERI_TRACE = "--trace"
|
||||
VERI_CFLAGS += "-DVCD_TRACE"
|
||||
else
|
||||
VERI_TRACE =
|
||||
endif
|
||||
|
||||
SIM_SRC := sim_jtag.sv
|
||||
|
||||
SIM_SRC += tb_top_verilator.sv \
|
||||
tb_top_verilator.cpp
|
||||
|
||||
SIM_TOP_MODULE := tb_top_verilator
|
||||
|
||||
.DEFAULT_GOAL := sim
|
||||
all: sim
|
||||
|
||||
.PHONY: recompile
|
||||
recompile:
|
||||
rm -rf $(VERI_OBJ_DIR) testbench_verilator
|
||||
$(MAKE) -C ./remote_bitbang clean
|
||||
$(MAKE) -C $(PROG_DIR) clean
|
||||
$(MAKE) compile
|
||||
|
||||
.PHONY: compile
|
||||
compile: remote_bitbang/librbs.so $(PROG) testbench_verilator
|
||||
|
||||
testbench_verilator:
|
||||
$(VERILATOR) --cc --sv --exe \
|
||||
$(VERI_TRACE) \
|
||||
--Wno-lint --Wno-UNOPTFLAT \
|
||||
--Wno-MODDUP --top-module \
|
||||
$(SIM_TOP_MODULE) \
|
||||
-f $(RTL_FILES) \
|
||||
$(SIM_SRC) \
|
||||
--Mdir $(VERI_OBJ_DIR) \
|
||||
$(VERI_VFLAGS) \
|
||||
-LDFLAGS "-L../remote_bitbang \
|
||||
-Wl,--enable-new-dtags -Wl,-rpath,remote_bitbang -lrbs" \
|
||||
-CFLAGS "-std=gnu++11 $(VERI_CFLAGS)"
|
||||
$(MAKE) -C $(VERI_OBJ_DIR) -f V$(SIM_TOP_MODULE).mk
|
||||
cp $(VERI_OBJ_DIR)/V$(SIM_TOP_MODULE) testbench_verilator
|
||||
|
||||
remote_bitbang/librbs.so:
|
||||
$(MAKE) -C ./remote_bitbang all
|
||||
|
||||
$(PROG):
|
||||
$(MAKE) -C $(PROG_DIR)
|
||||
|
||||
.PHONY: run
|
||||
run:
|
||||
./testbench_verilator "+firmware=$(PROG)"
|
||||
|
||||
.PHONY: sim
|
||||
sim: recompile run
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(VERI_OBJ_DIR) testbench_verilator *.log *.vcd
|
||||
$(MAKE) -C ./remote_bitbang clean
|
||||
$(MAKE) -C $(PROG_DIR) clean
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'rebuild all:'
|
||||
@echo 'make PROG=/path/file.mem recompile'
|
||||
@echo 'run directly:'
|
||||
@echo 'make PROG=/path/file.mem run'
|
||||
@echo 'rebuild & run:'
|
||||
@echo 'make PROG=/path/file.mem sim'
|
||||
@echo 'clean obj files:'
|
||||
@echo 'make PROG=/path/file.mem clean'
|
|
@ -1,50 +1,3 @@
|
|||
# compile_rtl.py
|
||||
|
||||
编译rtl代码。
|
||||
|
||||
使用方法:
|
||||
|
||||
`python compile_rtl.py [rtl目录相对路径]`
|
||||
|
||||
比如:
|
||||
|
||||
`python compile_rtl.py ..`
|
||||
|
||||
# sim_new_nowave.py
|
||||
|
||||
对指定的bin文件(重新生成inst.data文件)进行测试。
|
||||
|
||||
使用方法:
|
||||
|
||||
windows系统下:
|
||||
|
||||
`python sim_new_nowave.py ..\tests\isa\generated\rv32ui-p-add.bin inst.data`
|
||||
|
||||
Linux系统下:
|
||||
|
||||
`python sim_new_nowave.py ../tests/isa/generated/rv32ui-p-add.bin inst.data`
|
||||
|
||||
# sim_default_nowave.py
|
||||
|
||||
对已经存在的inst.data文件进行测试。
|
||||
|
||||
使用方法:
|
||||
|
||||
`python sim_default_nowave.py`
|
||||
|
||||
# test_all_isa.py
|
||||
|
||||
一次性测试../tests/isa/generated目录下的所有指令。
|
||||
|
||||
使用方法:
|
||||
|
||||
`python test_all_isa.py`
|
||||
|
||||
# test_jtag.py
|
||||
|
||||
测试JTAG的内存读、写功能。
|
||||
|
||||
使用方法:
|
||||
|
||||
`python test_jtag.py`
|
||||
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
import sys
|
||||
import filecmp
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
rtl_dir = sys.argv[1]
|
||||
|
||||
if rtl_dir != r'..':
|
||||
tb_file = r'/tb/compliance_test/tinyriscv_soc_tb.v'
|
||||
else:
|
||||
tb_file = r'/tb/tinyriscv_soc_tb.v'
|
||||
|
||||
# iverilog程序
|
||||
iverilog_cmd = ['iverilog']
|
||||
# 顶层模块
|
||||
#iverilog_cmd += ['-s', r'tinyriscv_soc_tb']
|
||||
# 编译生成文件
|
||||
iverilog_cmd += ['-o', r'out.vvp']
|
||||
# 头文件(defines.v)路径
|
||||
iverilog_cmd += ['-I', rtl_dir + r'/rtl/core']
|
||||
# 宏定义,仿真输出文件
|
||||
iverilog_cmd += ['-D', r'OUTPUT="signature.output"']
|
||||
# testbench文件
|
||||
iverilog_cmd.append(rtl_dir + tb_file)
|
||||
# ../rtl/core
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/clint.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/csr_reg.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/defines.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/divider.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_alu_datapath.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_commit.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_dispatch.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_mem.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_muldiv.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/gpr_reg.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu_exu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu_idu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/pipe_ctrl.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/tinyriscv_core.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/rst_ctrl.v')
|
||||
# ../rtl/perips
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/ram.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/rom.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/timer.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/uart.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/gpio.v')
|
||||
# ../rtl/debug
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_dm.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_driver.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_top.v')
|
||||
# ../rtl/sys_bus
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/sys_bus/rib.v')
|
||||
# ../rtl/utils
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_rx.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_tx.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_buf.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_dff.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_ram.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/vld_rdy.v')
|
||||
# ../rtl/top
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/top/tinyriscv_soc_top.v')
|
||||
|
||||
# 编译
|
||||
process = subprocess.Popen(iverilog_cmd)
|
||||
process.wait(timeout=5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -1,11 +0,0 @@
|
|||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.bin
|
||||
*.dump
|
||||
inst.data
|
||||
out.vvp
|
||||
tinyriscv_soc_tb.vcd
|
||||
run.log
|
||||
signature.output
|
|
@ -1,11 +0,0 @@
|
|||
对新的指令测试项进行测试。
|
||||
|
||||
使用方法:
|
||||
|
||||
Windows系统下:
|
||||
|
||||
`python compliance_test.py ..\..\tests\riscv-compliance\build_generated\rv32i\I-ADD-01.elf.bin inst.data`
|
||||
|
||||
Linux系统下:
|
||||
|
||||
`python compliance_test.py ../../tests/riscv-compliance/build_generated/rv32i/I-ADD-01.elf.bin inst.data`
|
|
@ -1,96 +0,0 @@
|
|||
import sys
|
||||
import filecmp
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
# 找出path目录下的所有reference_output文件
|
||||
def list_ref_files(path):
|
||||
files = []
|
||||
list_dir = os.walk(path)
|
||||
for maindir, subdir, all_file in list_dir:
|
||||
for filename in all_file:
|
||||
apath = os.path.join(maindir, filename)
|
||||
if apath.endswith('.reference_output'):
|
||||
files.append(apath)
|
||||
|
||||
return files
|
||||
|
||||
# 根据bin文件找到对应的reference_output文件
|
||||
def get_reference_file(bin_file):
|
||||
file_path, file_name = os.path.split(bin_file)
|
||||
tmp = file_name.split('.')
|
||||
# 得到bin文件的前缀部分
|
||||
prefix = tmp[0]
|
||||
#print('bin prefix: %s' % prefix)
|
||||
|
||||
files = []
|
||||
if (bin_file.find('rv32im') != -1):
|
||||
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32im/references')
|
||||
elif (bin_file.find('rv32i') != -1):
|
||||
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32i/references')
|
||||
elif (bin_file.find('rv32Zicsr') != -1):
|
||||
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32Zicsr/references')
|
||||
elif (bin_file.find('rv32Zifencei') != -1):
|
||||
files = list_ref_files(r'../../tests/riscv-compliance/riscv-test-suite/rv32Zifencei/references')
|
||||
else:
|
||||
return None
|
||||
|
||||
# 根据bin文件前缀找到对应的reference_output文件
|
||||
for file in files:
|
||||
if (file.find(prefix) != -1):
|
||||
return file
|
||||
|
||||
return None
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
#print(sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2])
|
||||
|
||||
# 1.将bin文件转成mem文件
|
||||
cmd = r'python ../../tools/BinToMem_CLI.py' + ' ' + sys.argv[1] + ' ' + sys.argv[2]
|
||||
f = os.popen(cmd)
|
||||
f.close()
|
||||
|
||||
# 2.编译rtl文件
|
||||
cmd = r'python ../compile_rtl.py' + r' ../..'
|
||||
f = os.popen(cmd)
|
||||
f.close()
|
||||
|
||||
# 3.运行
|
||||
logfile = open('run.log', 'w')
|
||||
vvp_cmd = [r'vvp']
|
||||
vvp_cmd.append(r'out.vvp')
|
||||
process = subprocess.Popen(vvp_cmd, stdout=logfile, stderr=logfile)
|
||||
process.wait(timeout=5)
|
||||
logfile.close()
|
||||
|
||||
# 4.比较结果
|
||||
ref_file = get_reference_file(sys.argv[1])
|
||||
if (ref_file != None):
|
||||
# 如果文件大小不一致,直接报fail
|
||||
if (os.path.getsize('signature.output') != os.path.getsize(ref_file)):
|
||||
print('!!! FAIL, size != !!!')
|
||||
return
|
||||
f1 = open('signature.output')
|
||||
f2 = open(ref_file)
|
||||
f1_lines = f1.readlines()
|
||||
i = 0
|
||||
# 逐行比较
|
||||
for line in f2.readlines():
|
||||
# 只要有一行内容不一样就报fail
|
||||
if (f1_lines[i] != line):
|
||||
print('!!! FAIL, content != !!!')
|
||||
f1.close()
|
||||
f2.close()
|
||||
return
|
||||
i = i + 1
|
||||
f1.close()
|
||||
f2.close()
|
||||
print('### PASS ###')
|
||||
else:
|
||||
print('No ref file found, please check result by yourself.')
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.d
|
||||
*.so
|
|
@ -0,0 +1,124 @@
|
|||
# Copyright (C) 2020 ETH Zurich and University of Bologna
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
# Author: Robert Balas (balasr@iis.ee.ethz.ch)
|
||||
|
||||
CFLAGS = -Wall -Wextra -Wno-missing-field-initializers \
|
||||
-Wno-unused-function -Wno-missing-braces \
|
||||
-O2 -g -march=native \
|
||||
-DENABLE_LOGGING -DNDEBUG
|
||||
CFLAGS_DBG =
|
||||
# we need gnu11 and no-strict-aliasing
|
||||
ALL_CFLAGS = -std=gnu11 -fno-strict-aliasing $(CFLAGS)
|
||||
ALL_CFLAGS_DBG = -std=gnu11 -Wall -Wextra -Wno-missing-field-initializers \
|
||||
-Wno-unused-function -Wno-missing-braces \
|
||||
-O0 -g -fno-strict-aliasing \
|
||||
-fsanitize=address -fno-omit-frame-pointer \
|
||||
-DENABLE_LOGGING -DENABLE_DEBUG $(CFLAGS_DBG)\
|
||||
# -fsanitize=undefined \
|
||||
# -fsanitize=leak \
|
||||
|
||||
|
||||
# TODO: better path?
|
||||
LIB_DIRS =
|
||||
LIBS =
|
||||
INCLUDE_DIRS = ./
|
||||
|
||||
|
||||
LDFLAGS = $(addprefix -L, $(LIB_DIRS))
|
||||
LDLIBS = $(addprefix -l, $(LIBS))
|
||||
|
||||
SRCS = remote_bitbang.c sim_jtag.c
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
INCLUDES = $(addprefix -I, $(INCLUDE_DIRS))
|
||||
|
||||
HEADERS = $(wildcard *.h)
|
||||
|
||||
# libs
|
||||
SV_LIB = librbs.so
|
||||
|
||||
# header file dependency generation
|
||||
DEPDIR := .d
|
||||
DEPDIRS := $(addsuffix /$(DEPDIR),.)
|
||||
# goal: make gcc put a dependency file called obj.Td (derived from subdir/obj.o)
|
||||
# in subdir/.d/
|
||||
DEPFLAGS = -MT $@ -MMD -MP -MF $(@D)/$(DEPDIR)/$(patsubst %.o,%.Td,$(@F))
|
||||
# move gcc generated header dependencies to DEPDIR
|
||||
# this rename step is here to make the header dependency generation "atomic"
|
||||
POSTCOMPILE = @mv -f $(@D)/$(DEPDIR)/$(patsubst %.o,%.Td,$(@F)) \
|
||||
$(@D)/$(DEPDIR)/$(patsubst %.o,%.d,$(@F)) && touch $@
|
||||
|
||||
# GNU recommendations for install targets
|
||||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_PROGRAM = $(INSTALL)
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
|
||||
CTAGS = ctags
|
||||
|
||||
# compilation targets
|
||||
all: sv-lib
|
||||
|
||||
debug: ALL_CFLAGS = $(ALL_CFLAGS_DBG)
|
||||
debug: all
|
||||
|
||||
sv-lib: ALL_CFLAGS += -fPIC
|
||||
sv-lib: $(SV_LIB)
|
||||
|
||||
#compilation boilerplate
|
||||
$(SV_LIB): $(OBJS)
|
||||
$(LD) -shared -E --exclude-libs ALL -o $(SV_LIB) $(LDFLAGS) \
|
||||
$(OBJS) $(LDLIBS)
|
||||
|
||||
# $@ = name of target
|
||||
# $< = first dependency
|
||||
%.o: %.c
|
||||
%.o: %.c $(DEPDIR)/%.d $(DEPDIRS)
|
||||
$(CC) $(DEPFLAGS) $(ALL_CFLAGS) $(INCLUDES) $(LDFLAGS) \
|
||||
-c $(CPPFLAGS) $< -o $@ $(LDLIBS)
|
||||
$(POSTCOMPILE)
|
||||
|
||||
# check if we need to create the dependencies folders (gcc doesn't)
|
||||
$(DEPDIRS):
|
||||
$(shell mkdir -p $(DEPDIRS) > /dev/null)
|
||||
# make won't fail if the dependency file doesn't exist
|
||||
$(addsuffix /$(DEPDIR)/%.d,. main benchmark test dpi): ;
|
||||
|
||||
# prevent automatic deletion as intermediate file
|
||||
.PRECIOUS: $(addsuffix /$(DEPDIR)/%.d,. main benchmark test dpi)
|
||||
|
||||
# emacs tag generation
|
||||
.PHONY: TAGS
|
||||
TAGS:
|
||||
$(CTAGS) -R -e -h=".c.h" --tag-relative=always \
|
||||
. $(LIB_DIRS) $(INCLUDE_DIRS) $(BINUTILS_PATH)/bfd
|
||||
|
||||
# TODO: missing install targets
|
||||
# cleanup
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(SV_LIB) $(OBJS) $(DEPDIRS)
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
rm -f TAGS
|
||||
|
||||
# include auto generated header dependency information
|
||||
include $(wildcard $(addsuffix /*.d,$(DEPDIRS)))
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (C) 2020 ETH Zurich and University of Bologna
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* Author: Robert Balas (balasr@iis.ee.ethz.ch)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned char jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn;
|
||||
unsigned char jtag_TDO = 0;
|
||||
|
||||
printf("calling rbs_init\n");
|
||||
int v = rbs_init(0);
|
||||
|
||||
printf("tick 1\n");
|
||||
rbs_tick(&jtag_TCK, &jtag_TMS, &jtag_TDI, &jtag_TRSTn, jtag_TDO);
|
||||
printf("jtag exit is %d\n", rbs_done());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
int rbs_init(uint16_t port)
|
||||
{
|
||||
socket_fd = 0;
|
||||
client_fd = 0;
|
||||
recv_start = 0;
|
||||
recv_end = 0;
|
||||
rbs_err = 0;
|
||||
|
||||
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (socket_fd == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed to make socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
fcntl(socket_fd, F_SETFL, O_NONBLOCK);
|
||||
int reuseaddr = 1;
|
||||
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
|
||||
sizeof(int)) == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed setsockopt: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if (bind(socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed to bind socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (listen(socket_fd, 1) == -1) {
|
||||
fprintf(stderr, "remote_bitbang failed to listen on socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
if (getsockname(socket_fd, (struct sockaddr *)&addr, &addrlen) == -1) {
|
||||
fprintf(stderr, "remote_bitbang getsockname failed: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
tck = 1;
|
||||
tms = 1;
|
||||
tdi = 1;
|
||||
trstn = 1;
|
||||
quit = 0;
|
||||
|
||||
fprintf(stderr, "JTAG remote bitbang server is ready\n");
|
||||
fprintf(stderr, "Listening on port %d\n", ntohs(addr.sin_port));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rbs_accept()
|
||||
{
|
||||
fprintf(stderr, "Attempting to accept client socket\n");
|
||||
int again = 1;
|
||||
while (again != 0) {
|
||||
client_fd = accept(socket_fd, NULL, NULL);
|
||||
if (client_fd == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
// No client waiting to connect right now.
|
||||
} else {
|
||||
fprintf(stderr, "failed to accept on socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
again = 0;
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
fcntl(client_fd, F_SETFL, O_NONBLOCK);
|
||||
fprintf(stderr, "Accepted successfully.");
|
||||
again = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms,
|
||||
unsigned char *jtag_tdi, unsigned char *jtag_trstn,
|
||||
unsigned char jtag_tdo)
|
||||
{
|
||||
if (client_fd > 0) {
|
||||
tdo = jtag_tdo;
|
||||
rbs_execute_command();
|
||||
} else {
|
||||
rbs_accept();
|
||||
}
|
||||
|
||||
*jtag_tck = tck;
|
||||
*jtag_tms = tms;
|
||||
*jtag_tdi = tdi;
|
||||
*jtag_trstn = trstn;
|
||||
}
|
||||
|
||||
void rbs_reset()
|
||||
{
|
||||
// trstn = 0;
|
||||
}
|
||||
|
||||
void rbs_set_pins(char _tck, char _tms, char _tdi)
|
||||
{
|
||||
tck = _tck;
|
||||
tms = _tms;
|
||||
tdi = _tdi;
|
||||
}
|
||||
|
||||
void rbs_execute_command()
|
||||
{
|
||||
char command;
|
||||
int again = 1;
|
||||
while (again) {
|
||||
ssize_t num_read = read(client_fd, &command, sizeof(command));
|
||||
if (num_read == -1) {
|
||||
if (errno == EAGAIN) {
|
||||
// We'll try again the next call.
|
||||
if (VERBOSE)
|
||||
fprintf(
|
||||
stderr,
|
||||
"Received no command. Will try again on the next call\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"remote_bitbang failed to read on socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
again = 0;
|
||||
abort();
|
||||
}
|
||||
} else if (num_read == 0) {
|
||||
fprintf(stderr, "No command received. Stopping further reads.\n");
|
||||
// again = 1;
|
||||
return;
|
||||
} else {
|
||||
again = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int dosend = 0;
|
||||
|
||||
char tosend = '?';
|
||||
|
||||
switch (command) {
|
||||
case 'B':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "*BLINK*\n");
|
||||
break;
|
||||
case 'b':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "blink off\n");
|
||||
break;
|
||||
case 'r':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "r-reset\n");
|
||||
rbs_reset();
|
||||
break; // This is wrong. 'r' has other bits that indicated TRST and
|
||||
// SRST.
|
||||
case 's':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "s-reset\n");
|
||||
rbs_reset();
|
||||
break; // This is wrong.
|
||||
case 't':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "t-reset\n");
|
||||
rbs_reset();
|
||||
break; // This is wrong.
|
||||
case 'u':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "u-reset\n");
|
||||
rbs_reset();
|
||||
break; // This is wrong.
|
||||
case '0':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 0 0 0\n");
|
||||
rbs_set_pins(0, 0, 0);
|
||||
break;
|
||||
case '1':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 0 0 1\n");
|
||||
rbs_set_pins(0, 0, 1);
|
||||
break;
|
||||
case '2':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 0 1 0\n");
|
||||
rbs_set_pins(0, 1, 0);
|
||||
break;
|
||||
case '3':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 0 1 1\n");
|
||||
rbs_set_pins(0, 1, 1);
|
||||
break;
|
||||
case '4':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 1 0 0\n");
|
||||
rbs_set_pins(1, 0, 0);
|
||||
break;
|
||||
case '5':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 1 0 1\n");
|
||||
rbs_set_pins(1, 0, 1);
|
||||
break;
|
||||
case '6':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 1 1 0\n");
|
||||
rbs_set_pins(1, 1, 0);
|
||||
break;
|
||||
case '7':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Write 1 1 1\n");
|
||||
rbs_set_pins(1, 1, 1);
|
||||
break;
|
||||
case 'R':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Read req\n");
|
||||
dosend = 1;
|
||||
tosend = tdo ? '1' : '0';
|
||||
break;
|
||||
case 'Q':
|
||||
if (VERBOSE)
|
||||
fprintf(stderr, "Quit req\n");
|
||||
quit = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
|
||||
command);
|
||||
}
|
||||
if (dosend) {
|
||||
while (1) {
|
||||
ssize_t bytes = write(client_fd, &tosend, sizeof(tosend));
|
||||
if (bytes == -1) {
|
||||
fprintf(stderr, "failed to write to socket: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
abort();
|
||||
}
|
||||
if (bytes > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quit) {
|
||||
fprintf(stderr, "Remote end disconnected\n");
|
||||
close(client_fd);
|
||||
client_fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char rbs_done()
|
||||
{
|
||||
return quit;
|
||||
}
|
||||
|
||||
int rbs_exit_code()
|
||||
{
|
||||
return rbs_err;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
#ifndef REMOTE_BITBANG_H
|
||||
#define REMOTE_BITBANG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
int rbs_err;
|
||||
|
||||
unsigned char tck;
|
||||
unsigned char tms;
|
||||
unsigned char tdi;
|
||||
unsigned char trstn;
|
||||
unsigned char tdo;
|
||||
unsigned char quit;
|
||||
|
||||
int socket_fd;
|
||||
int client_fd;
|
||||
|
||||
static const ssize_t buf_size = 64 * 1024;
|
||||
char recv_buf[64 * 1024];
|
||||
ssize_t recv_start, recv_end;
|
||||
|
||||
// Create a new server, listening for connections from localhost on the given
|
||||
// port.
|
||||
int rbs_init(uint16_t port);
|
||||
|
||||
// Do a bit of work.
|
||||
void rbs_tick(unsigned char *jtag_tck, unsigned char *jtag_tms,
|
||||
unsigned char *jtag_tdi, unsigned char *jtag_trstn,
|
||||
unsigned char jtag_tdo);
|
||||
|
||||
unsigned char rbs_done();
|
||||
|
||||
int rbs_exit_code();
|
||||
|
||||
// Check for a client connecting, and accept if there is one.
|
||||
void rbs_accept();
|
||||
// Execute any commands the client has for us.
|
||||
// But we only execute 1 because we need time for the
|
||||
// simulation to run.
|
||||
void rbs_execute_command();
|
||||
|
||||
// Reset. Currently does nothing.
|
||||
void rbs_reset();
|
||||
|
||||
void rbs_set_pins(char _tck, char _tms, char _tdi);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "remote_bitbang.h"
|
||||
|
||||
int init = 0;
|
||||
|
||||
int jtag_tick(int port, unsigned char *jtag_TCK, unsigned char *jtag_TMS,
|
||||
unsigned char *jtag_TDI, unsigned char *jtag_TRSTn,
|
||||
unsigned char jtag_TDO)
|
||||
|
||||
{
|
||||
if (!init) {
|
||||
if (port < 0 || port > UINT16_MAX)
|
||||
fprintf(stderr, "Port number of out range: %d\n", port);
|
||||
init = rbs_init(port);
|
||||
}
|
||||
|
||||
rbs_tick(jtag_TCK, jtag_TMS, jtag_TDI, jtag_TRSTn, jtag_TDO);
|
||||
if (VERBOSE)
|
||||
fprintf(
|
||||
stderr,
|
||||
"Tick with: TCK=%hhd TMS=%hhd TDI=%hhd TRSTn=%hhd --> TDO=%hhd\n",
|
||||
*jtag_TCK, *jtag_TMS, *jtag_TDI, *jtag_TRSTn, jtag_TDO);
|
||||
|
||||
return rbs_done() ? (rbs_exit_code() << 1 | 1) : 0;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
import sys
|
||||
import filecmp
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
#print(sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2])
|
||||
|
||||
# 1.编译rtl文件
|
||||
cmd = r'python compile_rtl.py' + r' ..'
|
||||
f = os.popen(cmd)
|
||||
f.close()
|
||||
|
||||
# 2.运行
|
||||
vvp_cmd = [r'vvp']
|
||||
vvp_cmd.append(r'out.vvp')
|
||||
process = subprocess.Popen(vvp_cmd)
|
||||
try:
|
||||
process.wait(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
print('!!!Fail, vvp exec timeout!!!')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -0,0 +1,85 @@
|
|||
// See LICENSE.SiFive for license details.
|
||||
//VCS coverage exclude_file
|
||||
import "DPI-C" function int jtag_tick
|
||||
(
|
||||
input int port,
|
||||
output bit jtag_TCK,
|
||||
output bit jtag_TMS,
|
||||
output bit jtag_TDI,
|
||||
output bit jtag_TRSTn,
|
||||
|
||||
input bit jtag_TDO
|
||||
);
|
||||
|
||||
module sim_jtag #(
|
||||
parameter TICK_DELAY = 50,
|
||||
parameter PORT = 0
|
||||
)(
|
||||
|
||||
input clock,
|
||||
input reset,
|
||||
|
||||
input enable,
|
||||
input init_done,
|
||||
|
||||
output jtag_TCK,
|
||||
output jtag_TMS,
|
||||
output jtag_TDI,
|
||||
output jtag_TRSTn,
|
||||
|
||||
input jtag_TDO_data,
|
||||
input jtag_TDO_driven,
|
||||
|
||||
output [31:0] exit
|
||||
);
|
||||
|
||||
reg [31:0] tickCounterReg;
|
||||
wire [31:0] tickCounterNxt;
|
||||
|
||||
assign tickCounterNxt = (tickCounterReg == 0) ? TICK_DELAY : (tickCounterReg - 1);
|
||||
|
||||
bit r_reset;
|
||||
|
||||
wire [31:0] random_bits = $random;
|
||||
|
||||
wire #0.1 __jtag_TDO = jtag_TDO_driven ?
|
||||
jtag_TDO_data : random_bits[0];
|
||||
|
||||
bit __jtag_TCK;
|
||||
bit __jtag_TMS;
|
||||
bit __jtag_TDI;
|
||||
bit __jtag_TRSTn;
|
||||
int __exit;
|
||||
|
||||
reg init_done_sticky;
|
||||
|
||||
assign #0.1 jtag_TCK = __jtag_TCK;
|
||||
assign #0.1 jtag_TMS = __jtag_TMS;
|
||||
assign #0.1 jtag_TDI = __jtag_TDI;
|
||||
assign #0.1 jtag_TRSTn = __jtag_TRSTn;
|
||||
|
||||
assign #0.1 exit = __exit;
|
||||
|
||||
always @(posedge clock) begin
|
||||
r_reset <= reset;
|
||||
if (reset || r_reset) begin
|
||||
__exit = 0;
|
||||
tickCounterReg <= TICK_DELAY;
|
||||
init_done_sticky <= 1'b0;
|
||||
end else begin
|
||||
init_done_sticky <= init_done | init_done_sticky;
|
||||
if (enable && init_done_sticky) begin
|
||||
tickCounterReg <= tickCounterNxt;
|
||||
if (tickCounterReg == 0) begin
|
||||
__exit = jtag_tick(PORT,
|
||||
__jtag_TCK,
|
||||
__jtag_TMS,
|
||||
__jtag_TDI,
|
||||
__jtag_TRSTn,
|
||||
__jtag_TDO);
|
||||
end
|
||||
end // if (enable && init_done_sticky)
|
||||
end // else: !if(reset || r_reset)
|
||||
end // always @ (posedge clock)
|
||||
|
||||
endmodule
|
|
@ -1,33 +0,0 @@
|
|||
import sys
|
||||
import filecmp
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
#print(sys.argv[0] + ' ' + sys.argv[1] + ' ' + sys.argv[2])
|
||||
|
||||
# 1.将bin文件转成mem文件
|
||||
cmd = r'python ../tools/BinToMem_CLI.py' + ' ' + sys.argv[1] + ' ' + sys.argv[2]
|
||||
f = os.popen(cmd)
|
||||
f.close()
|
||||
|
||||
# 2.编译rtl文件
|
||||
cmd = r'python compile_rtl.py' + r' ..'
|
||||
f = os.popen(cmd)
|
||||
f.close()
|
||||
|
||||
# 3.运行
|
||||
vvp_cmd = [r'vvp']
|
||||
vvp_cmd.append(r'out.vvp')
|
||||
process = subprocess.Popen(vvp_cmd)
|
||||
try:
|
||||
process.wait(timeout=20)
|
||||
except subprocess.TimeoutExpired:
|
||||
print('!!!Fail, vvp exec timeout!!!')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
// Top level wrapper for a verilator RI5CY testbench
|
||||
// Contributor: Robert Balas <balasr@student.ethz.ch>
|
||||
|
||||
#include "svdpi.h"
|
||||
#include "Vtb_top_verilator__Dpi.h"
|
||||
#include "Vtb_top_verilator.h"
|
||||
#include "verilated_vcd_c.h"
|
||||
#include "verilated.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <exception>
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cerrno>
|
||||
|
||||
//void dump_memory();
|
||||
double sc_time_stamp();
|
||||
|
||||
static vluint64_t t = 0;
|
||||
Vtb_top_verilator *top;
|
||||
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Verilated::traceEverOn(true);
|
||||
top = new Vtb_top_verilator();
|
||||
|
||||
//svSetScope(svGetScopeFromName(
|
||||
// "TOP.tb_top_verilator.u_ram.ram"));
|
||||
//Verilated::scopesDump();
|
||||
|
||||
#ifdef VCD_TRACE
|
||||
VerilatedVcdC *tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99);
|
||||
tfp->open("verilator_tb.vcd");
|
||||
#endif
|
||||
top->fetch_enable_i = 1;
|
||||
top->clk_i = 0;
|
||||
top->rst_ni = 0;
|
||||
|
||||
top->eval();
|
||||
//dump_memory();
|
||||
|
||||
while (!Verilated::gotFinish()) {
|
||||
if (t > 40)
|
||||
top->rst_ni = 1;
|
||||
top->clk_i = !top->clk_i;
|
||||
top->eval();
|
||||
#ifdef VCD_TRACE
|
||||
tfp->dump(t);
|
||||
#endif
|
||||
t += 5;
|
||||
if (t > 1000)
|
||||
break;
|
||||
}
|
||||
#ifdef VCD_TRACE
|
||||
tfp->close();
|
||||
#endif
|
||||
delete top;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
double sc_time_stamp()
|
||||
{
|
||||
return t;
|
||||
}
|
||||
/*
|
||||
void dump_memory()
|
||||
{
|
||||
errno = 0;
|
||||
std::ofstream mem_file;
|
||||
svLogicVecVal addr = {0};
|
||||
|
||||
mem_file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
|
||||
try {
|
||||
mem_file.open("memory_dump.bin");
|
||||
for (size_t i = 0; i < 1048576; i++) {
|
||||
addr.aval = i;
|
||||
uint32_t val = read_byte(&addr);
|
||||
mem_file << std::setfill('0') << std::setw(2) << std::hex << val
|
||||
<< std::endl;
|
||||
}
|
||||
mem_file.close();
|
||||
|
||||
std::cout << "finished dumping memory" << std::endl;
|
||||
|
||||
} catch (std::ofstream::failure e) {
|
||||
std::cerr << "exception opening/reading/closing file memory_dump.bin\n";
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this 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.
|
||||
|
||||
// Top level wrapper for a verilator RI5CY testbench
|
||||
// Contributor: Robert Balas <balasr@student.ethz.ch>
|
||||
|
||||
|
||||
module tb_top_verilator #(
|
||||
|
||||
) (
|
||||
input clk_i,
|
||||
input rst_ni,
|
||||
input fetch_enable_i
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
initial begin: load_prog
|
||||
automatic logic [1023:0] firmware;
|
||||
|
||||
if($value$plusargs("firmware=%s", firmware)) begin
|
||||
//if($test$plusargs("verbose"))
|
||||
$display("[TESTBENCH] %t: loading firmware %0s ...",
|
||||
$time, firmware);
|
||||
$readmemh (firmware, u_tinyriscv_soc_top.u_rom.u_gen_ram.ram);
|
||||
//$display("mem[0x80]=0x%x", u_ram.ram.mem[32]);
|
||||
//$display("mem[0x84]=0x%x", u_ram.ram.mem[33]);
|
||||
end else begin
|
||||
$display("No firmware specified");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
tinyriscv_soc_top u_tinyriscv_soc_top(
|
||||
.clk(clk_i),
|
||||
.rst_ext_i(rst_ni)
|
||||
);
|
||||
|
||||
endmodule // tb_top_verilator
|
|
@ -1,43 +0,0 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
# 找出path目录下的所有bin文件
|
||||
def list_binfiles(path):
|
||||
files = []
|
||||
list_dir = os.walk(path)
|
||||
for maindir, subdir, all_file in list_dir:
|
||||
for filename in all_file:
|
||||
apath = os.path.join(maindir, filename)
|
||||
if apath.endswith('.bin'):
|
||||
files.append(apath)
|
||||
|
||||
return files
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
bin_files = list_binfiles(r'../tests/isa/generated')
|
||||
|
||||
anyfail = False
|
||||
|
||||
# 对每一个bin文件进行测试
|
||||
for file in bin_files:
|
||||
#print(file)
|
||||
cmd = r'python sim_new_nowave.py' + ' ' + file + ' ' + 'inst.data'
|
||||
f = os.popen(cmd)
|
||||
r = f.read()
|
||||
f.close()
|
||||
if (r.find('TEST_PASS') != -1):
|
||||
print(file + ' PASS')
|
||||
else:
|
||||
print(file + ' !!!FAIL!!!')
|
||||
anyfail = True
|
||||
break
|
||||
|
||||
if (anyfail == False):
|
||||
print('Congratulation, All PASS...')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -1,72 +0,0 @@
|
|||
import sys
|
||||
import filecmp
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
# 主函数
|
||||
def main():
|
||||
rtl_dir = '..'
|
||||
|
||||
tb_file = r'/tb/jtag_tb.v'
|
||||
|
||||
# iverilog程序
|
||||
iverilog_cmd = ['iverilog']
|
||||
# 顶层模块
|
||||
#iverilog_cmd += ['-s', r'tinyriscv_soc_tb']
|
||||
# 编译生成文件
|
||||
iverilog_cmd += ['-o', r'out.vvp']
|
||||
# 头文件(defines.v)路径
|
||||
iverilog_cmd += ['-I', rtl_dir + r'/rtl/core']
|
||||
# 宏定义,仿真输出文件
|
||||
iverilog_cmd += ['-D', r'OUTPUT="signature.output"']
|
||||
# testbench文件
|
||||
iverilog_cmd.append(rtl_dir + tb_file)
|
||||
# ../rtl/core
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/clint.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/csr_reg.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/defines.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/divider.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_alu_datapath.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_commit.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_dispatch.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_mem.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/exu_muldiv.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/gpr_reg.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/idu_exu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/ifu_idu.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/pipe_ctrl.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/tinyriscv_core.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/core/rst_ctrl.v')
|
||||
# ../rtl/perips
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/ram.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/rom.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/timer.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/uart.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/perips/gpio.v')
|
||||
# ../rtl/debug
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_dm.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_driver.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/debug/jtag_top.v')
|
||||
# ../rtl/sys_bus
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/sys_bus/rib.v')
|
||||
# ../rtl/utils
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_rx.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/full_handshake_tx.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_buf.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_dff.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/gen_ram.v')
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/utils/vld_rdy.v')
|
||||
# ../rtl/top
|
||||
iverilog_cmd.append(rtl_dir + r'/rtl/top/tinyriscv_soc_top.v')
|
||||
|
||||
# 编译
|
||||
process = subprocess.Popen(iverilog_cmd)
|
||||
process.wait(timeout=5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -1,3 +0,0 @@
|
|||
tinyriscv_soc_tb.v是适用于旧的指令测试testbench文件。
|
||||
|
||||
compliance_test/tinyriscv_soc_tb.v是适用于新的指令测试testbench文件。
|
|
@ -1,535 +0,0 @@
|
|||
`timescale 1 ns / 1 ps
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
// select one option only
|
||||
`define TEST_PROG 1
|
||||
//`define TEST_JTAG 1
|
||||
|
||||
|
||||
// testbench module
|
||||
module tinyriscv_soc_tb;
|
||||
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
|
||||
|
||||
always #10 clk = ~clk; // 50MHz
|
||||
|
||||
wire[31:0] x3 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[3];
|
||||
wire[31:0] x26 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[26];
|
||||
wire[31:0] x27 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[27];
|
||||
|
||||
wire[31:0] ex_end_flag = tinyriscv_soc_top_0.u_ram.u_gen_ram.ram[4];
|
||||
wire[31:0] begin_signature = tinyriscv_soc_top_0.u_ram.u_gen_ram.ram[2];
|
||||
wire[31:0] end_signature = tinyriscv_soc_top_0.u_ram.u_gen_ram.ram[3];
|
||||
|
||||
integer r;
|
||||
integer fd;
|
||||
|
||||
`ifdef TEST_JTAG
|
||||
reg TCK;
|
||||
reg TMS;
|
||||
reg TDI;
|
||||
wire TDO;
|
||||
|
||||
integer i;
|
||||
reg[39:0] shift_reg;
|
||||
reg in;
|
||||
wire[39:0] req_data = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_data;
|
||||
wire[4:0] ir_reg = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.ir_reg;
|
||||
wire dtm_req_valid = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_valid;
|
||||
wire[31:0] dmstatus = tinyriscv_soc_top_0.u_jtag_top.u_jtag_dm.dmstatus;
|
||||
`endif
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
rst_n = 1'b1;
|
||||
`ifdef TEST_JTAG
|
||||
TCK = 1;
|
||||
TMS = 1;
|
||||
TDI = 1;
|
||||
`endif
|
||||
$display("test running...");
|
||||
#100
|
||||
rst_n = 1'b0;
|
||||
#100
|
||||
rst_n = 1'b1;
|
||||
#200
|
||||
/*
|
||||
`ifdef TEST_PROG
|
||||
wait(x26 == 32'b1) // wait sim end, when x26 == 1
|
||||
#100
|
||||
if (x27 == 32'b1) begin
|
||||
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
|
||||
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
end else begin
|
||||
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("fail testnum = %2d", x3);
|
||||
for (r = 0; r < 32; r = r + 1)
|
||||
$display("x%2d = 0x%x", r, tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[r]);
|
||||
end
|
||||
`endif
|
||||
*/
|
||||
|
||||
wait(ex_end_flag == 32'h1); // wait sim end
|
||||
|
||||
fd = $fopen(`OUTPUT); // OUTPUT的值在命令行里定义
|
||||
for (r = begin_signature; r < end_signature; r = r + 4) begin
|
||||
$fdisplay(fd, "%x", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram[r[31:2]]);
|
||||
end
|
||||
$fclose(fd);
|
||||
|
||||
`ifdef TEST_JTAG
|
||||
// reset
|
||||
for (i = 0; i < 8; i++) begin
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
end
|
||||
|
||||
// IR
|
||||
shift_reg = 40'b10001;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-IR & EXIT1-IR
|
||||
for (i = 5; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
|
||||
end
|
||||
|
||||
// PAUSE-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// dmi write
|
||||
shift_reg = {6'h10, {(32){1'b0}}, 2'b10};
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
$display("ir_reg = 0x%x", ir_reg);
|
||||
$display("dtm_req_valid = %d", dtm_req_valid);
|
||||
$display("req_data = 0x%x", req_data);
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
$display("dmstatus = 0x%x", dmstatus);
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// dmi read
|
||||
shift_reg = {6'h11, {(32){1'b0}}, 2'b01};
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// dmi read
|
||||
shift_reg = {6'h11, {(32){1'b0}}, 2'b00};
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
#100
|
||||
|
||||
$display("shift_reg = 0x%x", shift_reg[33:2]);
|
||||
|
||||
if (dmstatus == shift_reg[33:2]) begin
|
||||
$display("######################");
|
||||
$display("### jtag test pass ###");
|
||||
$display("######################");
|
||||
end else begin
|
||||
$display("######################");
|
||||
$display("!!! jtag test fail !!!");
|
||||
$display("######################");
|
||||
end
|
||||
`endif
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
// sim timeout
|
||||
initial begin
|
||||
#500000
|
||||
$display("Time Out.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
// read mem data
|
||||
initial begin
|
||||
$readmemh ("inst.data", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram);
|
||||
end
|
||||
|
||||
// generate wave file, used by gtkwave
|
||||
initial begin
|
||||
$dumpfile("tinyriscv_soc_tb.vcd");
|
||||
$dumpvars(0, tinyriscv_soc_tb);
|
||||
end
|
||||
|
||||
tinyriscv_soc_top tinyriscv_soc_top_0(
|
||||
.clk(clk),
|
||||
.rst_ext_i(rst_n)
|
||||
`ifdef TEST_JTAG
|
||||
,
|
||||
.jtag_TCK(TCK),
|
||||
.jtag_TMS(TMS),
|
||||
.jtag_TDI(TDI),
|
||||
.jtag_TDO(TDO)
|
||||
`endif
|
||||
);
|
||||
|
||||
endmodule
|
733
tb/jtag_tb.v
733
tb/jtag_tb.v
|
@ -1,733 +0,0 @@
|
|||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
|
||||
`define JTAG_CLK 500 // 1MHz. This value do not less than 100
|
||||
|
||||
|
||||
module jtag_tb;
|
||||
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
|
||||
reg TCK;
|
||||
reg TMS;
|
||||
reg TDI;
|
||||
wire TDO;
|
||||
|
||||
reg[39:0] shift_reg;
|
||||
reg in;
|
||||
reg[39:0] resp_data;
|
||||
|
||||
|
||||
always #10 clk = ~clk; // core clock = 50MHz
|
||||
|
||||
|
||||
integer i;
|
||||
integer j;
|
||||
|
||||
|
||||
task tap_reset;
|
||||
begin
|
||||
for (i = 0; i < 8; i = i + 1) begin
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task select_ir;
|
||||
input[39:0] ir;
|
||||
|
||||
begin
|
||||
// IR
|
||||
shift_reg = ir;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-IR & EXIT1-IR
|
||||
for (i = 5; i > 0; i = i - 1) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
|
||||
end
|
||||
|
||||
// PAUSE-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task dmi_write;
|
||||
input[5:0] addr;
|
||||
input[31:0] data;
|
||||
output[39:0] out;
|
||||
|
||||
begin
|
||||
// op write
|
||||
shift_reg = {addr, data, 2'b10};
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i = i - 1) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// op nop
|
||||
shift_reg = {addr, {(32){1'b0}}, 2'b00};
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i = i - 1) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
out = shift_reg;
|
||||
end
|
||||
endtask
|
||||
|
||||
task dmi_read;
|
||||
input[5:0] addr;
|
||||
output[39:0] out;
|
||||
|
||||
begin
|
||||
// op read
|
||||
shift_reg = {addr, {(32){1'b0}}, 2'b01};
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i = i - 1) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// op nop
|
||||
shift_reg = {addr, {(32){1'b0}}, 2'b00};
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i = i - 1) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#`JTAG_CLK
|
||||
TCK = 1;
|
||||
#`JTAG_CLK
|
||||
TCK = 0;
|
||||
|
||||
out = shift_reg;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
rst_n = 1'b1;
|
||||
|
||||
TCK = 1;
|
||||
TMS = 1;
|
||||
TDI = 1;
|
||||
shift_reg = 40'h0;
|
||||
resp_data = 40'h0;
|
||||
in = 1'b0;
|
||||
|
||||
$display("test running...");
|
||||
#100
|
||||
rst_n = 1'b0;
|
||||
#100
|
||||
rst_n = 1'b1;
|
||||
#200
|
||||
|
||||
/*************************** start test ***************************/
|
||||
// reset TAP state machine
|
||||
tap_reset();
|
||||
// select dm regs
|
||||
select_ir(40'b10001);
|
||||
// reset dm module
|
||||
dmi_write(6'h10, 32'h0, resp_data);
|
||||
|
||||
// read dmstatus reg
|
||||
dmi_read(6'h11, resp_data);
|
||||
$display("dmstatus = 0x%x", resp_data[33:2]);
|
||||
|
||||
// write data to memory
|
||||
dmi_write(6'h38, 32'h20050404, resp_data); // write sbcs
|
||||
dmi_write(6'h39, 32'h0, resp_data); // write sbaddress0
|
||||
for (j = 0; j < 5; j = j + 1) begin
|
||||
$display("write: addr = 0x%x, data = 0x%x", j * 4, 32'h0 + j);
|
||||
dmi_write(6'h3c, 32'h0 + j, resp_data); // write sbdata0
|
||||
end
|
||||
|
||||
// read data from memory
|
||||
dmi_write(6'h38, 32'h20158404, resp_data); // write sbcs
|
||||
dmi_write(6'h39, 32'h0, resp_data); // write sbaddress0
|
||||
for (j = 0; j < 5; j = j + 1) begin
|
||||
dmi_read(6'h3c, resp_data); // read sbdata0
|
||||
$display("read: addr = 0x%x, data = 0x%x", j * 4, resp_data[33:2]);
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Check whether the data read is equal to the data written.
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
// sim timeout
|
||||
initial begin
|
||||
#10000000
|
||||
$display("Time Out.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
// generate wave file, used by gtkwave
|
||||
initial begin
|
||||
$dumpfile("jtag_tb.vcd");
|
||||
$dumpvars(0, jtag_tb);
|
||||
end
|
||||
|
||||
tinyriscv_soc_top tinyriscv_soc_top_0(
|
||||
.clk(clk),
|
||||
.rst_ext_i(rst_n),
|
||||
.jtag_TCK(TCK),
|
||||
.jtag_TMS(TMS),
|
||||
.jtag_TDI(TDI),
|
||||
.jtag_TDO(TDO)
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,521 +0,0 @@
|
|||
`timescale 1 ns / 1 ps
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
// select one option only
|
||||
`define TEST_PROG 1
|
||||
//`define TEST_JTAG 1
|
||||
|
||||
|
||||
// testbench module
|
||||
module tinyriscv_soc_tb;
|
||||
|
||||
reg clk;
|
||||
reg rst_n;
|
||||
|
||||
|
||||
always #10 clk = ~clk; // 50MHz
|
||||
|
||||
wire[31:0] x3 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[3];
|
||||
wire[31:0] x26 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[26];
|
||||
wire[31:0] x27 = tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[27];
|
||||
|
||||
integer r;
|
||||
|
||||
`ifdef TEST_JTAG
|
||||
reg TCK;
|
||||
reg TMS;
|
||||
reg TDI;
|
||||
wire TDO;
|
||||
|
||||
integer i;
|
||||
reg[39:0] shift_reg;
|
||||
reg in;
|
||||
wire[39:0] req_data = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_data;
|
||||
wire[4:0] ir_reg = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.ir_reg;
|
||||
wire dtm_req_valid = tinyriscv_soc_top_0.u_jtag_top.u_jtag_driver.dtm_req_valid;
|
||||
wire[31:0] dmstatus = tinyriscv_soc_top_0.u_jtag_top.u_jtag_dm.dmstatus;
|
||||
`endif
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
rst_n = 1'b1;
|
||||
`ifdef TEST_JTAG
|
||||
TCK = 1;
|
||||
TMS = 1;
|
||||
TDI = 1;
|
||||
`endif
|
||||
$display("test running...");
|
||||
#100
|
||||
rst_n = 1'b0;
|
||||
#100
|
||||
rst_n = 1'b1;
|
||||
#200
|
||||
|
||||
`ifdef TEST_PROG
|
||||
wait(x26 == 32'b1) // wait sim end, when x26 == 1
|
||||
#100
|
||||
if (x27 == 32'b1) begin
|
||||
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
|
||||
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
|
||||
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
end else begin
|
||||
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
$display("fail testnum = %2d", x3);
|
||||
for (r = 0; r < 32; r = r + 1)
|
||||
$display("x%2d = 0x%x", r, tinyriscv_soc_top_0.u_tinyriscv_core.u_gpr_reg.regs[r]);
|
||||
end
|
||||
`endif
|
||||
|
||||
`ifdef TEST_JTAG
|
||||
// reset
|
||||
for (i = 0; i < 8; i++) begin
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
end
|
||||
|
||||
// IR
|
||||
shift_reg = 40'b10001;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-IR & EXIT1-IR
|
||||
for (i = 5; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
|
||||
end
|
||||
|
||||
// PAUSE-IR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-IR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// dmi write
|
||||
shift_reg = {6'h10, {(32){1'b0}}, 2'b10};
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
$display("ir_reg = 0x%x", ir_reg);
|
||||
$display("dtm_req_valid = %d", dtm_req_valid);
|
||||
$display("req_data = 0x%x", req_data);
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
$display("dmstatus = 0x%x", dmstatus);
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// dmi read
|
||||
shift_reg = {6'h11, {(32){1'b0}}, 2'b01};
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
// PAUSE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// EXIT2-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// UPDATE-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// IDLE
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SELECT-DR
|
||||
TMS = 1;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// dmi read
|
||||
shift_reg = {6'h11, {(32){1'b0}}, 2'b00};
|
||||
|
||||
// CAPTURE-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR
|
||||
TMS = 0;
|
||||
TCK = 0;
|
||||
#100
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
// SHIFT-DR & EXIT1-DR
|
||||
for (i = 40; i > 0; i--) begin
|
||||
if (shift_reg[0] == 1'b1)
|
||||
TDI = 1'b1;
|
||||
else
|
||||
TDI = 1'b0;
|
||||
|
||||
if (i == 1)
|
||||
TMS = 1;
|
||||
|
||||
TCK = 0;
|
||||
#100
|
||||
in = TDO;
|
||||
TCK = 1;
|
||||
#100
|
||||
TCK = 0;
|
||||
|
||||
shift_reg = {in, shift_reg[39:1]};
|
||||
end
|
||||
|
||||
#100
|
||||
|
||||
$display("shift_reg = 0x%x", shift_reg[33:2]);
|
||||
|
||||
if (dmstatus == shift_reg[33:2]) begin
|
||||
$display("######################");
|
||||
$display("### jtag test pass ###");
|
||||
$display("######################");
|
||||
end else begin
|
||||
$display("######################");
|
||||
$display("!!! jtag test fail !!!");
|
||||
$display("######################");
|
||||
end
|
||||
`endif
|
||||
|
||||
$finish;
|
||||
end
|
||||
|
||||
// sim timeout
|
||||
initial begin
|
||||
#1000000
|
||||
$display("Time Out.");
|
||||
$finish;
|
||||
end
|
||||
|
||||
// read mem data
|
||||
initial begin
|
||||
$readmemh ("inst.data", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram);
|
||||
end
|
||||
|
||||
// generate wave file, used by gtkwave
|
||||
initial begin
|
||||
$dumpfile("tinyriscv_soc_tb.vcd");
|
||||
$dumpvars(0, tinyriscv_soc_tb);
|
||||
end
|
||||
|
||||
tinyriscv_soc_top tinyriscv_soc_top_0(
|
||||
.clk(clk),
|
||||
.rst_ext_i(rst_n)
|
||||
`ifdef TEST_JTAG
|
||||
,
|
||||
.jtag_TCK(TCK),
|
||||
.jtag_TMS(TMS),
|
||||
.jtag_TDI(TDI),
|
||||
.jtag_TDO(TDO)
|
||||
`endif
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -4,6 +4,3 @@
|
|||
*.obj
|
||||
*.bin
|
||||
*.dump
|
||||
|
||||
__pycache__
|
||||
gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue