tinyriscv测试通过iverilog和gtkwave实现,对其在指令集测试时如何判断test pass比较好奇,故分析一下这方面的代码。
一,外设模块与地址
tinyriscv挂了六个外设,rom从0x0000_0000开始,ram从0x1000_0000开始,而外设的地址在总线中定义,rib总线的主从模块接口如下:
module rib( input wire clk, input wire rst, ...... // master 0 interface input wire[`MemAddrBus] m0_addr_i, // 主设备0读、写地址 input wire[`MemBus] m0_data_i, // 主设备0写数据 output reg[`MemBus] m0_data_o, // 主设备0读取到的数据 input wire m0_req_i, // 主设备0访问请求标志 input wire m0_we_i, // 主设备0写标志 // slave 0 interface output reg[`MemAddrBus] s0_addr_o, // 从设备0读、写地址 output reg[`MemBus] s0_data_o, // 从设备0写数据 input wire[`MemBus] s0_data_i, // 从设备0读取到的数据 output reg s0_we_o, // 从设备0写标志 ...... endmodule
在soc_top.v中,例化各个模块时将输入输出接入总线:
//这段例化把内核模块接入总线的master模块,注意pc取指也当作一个主模块来访问总线以获得data, tinyriscv u_tinyriscv( .clk(clk), .rst(rst), .rib_ex_addr_o(m0_addr_i), .rib_ex_data_i(m0_data_o), .rib_ex_data_o(m0_data_i), .rib_ex_req_o(m0_req_i), .rib_ex_we_o(m0_we_i), .rib_pc_addr_o(m1_addr_i), .rib_pc_data_i(m1_data_o), .jtag_reg_addr_i(jtag_reg_addr_o), .jtag_reg_data_i(jtag_reg_data_o), .jtag_reg_we_i(jtag_reg_we_o), .jtag_reg_data_o(jtag_reg_data_i), .rib_hold_flag_i(rib_hold_flag_o), .jtag_halt_flag_i(jtag_halt_req_o), .jtag_reset_flag_i(jtag_reset_req_o), .int_i(int_flag) );
从设备接入总线:
// gpio模块例化 gpio gpio_0( .clk(clk), .rst(rst), .we_i(s4_we_o), .addr_i(s4_addr_o), .data_i(s4_data_o), .data_o(s4_data_i), .io_pin_i(io_in), .reg_ctrl(gpio_ctrl), .reg_data(gpio_data) );
而设备地址在rib.v中设置:
// 访问地址的最高4位决定要访问的是哪一个从设备 // 因此最多支持16个从设备 parameter [3:0]slave_0 = 4'b0000; parameter [3:0]slave_1 = 4'b0001; parameter [3:0]slave_2 = 4'b0010; parameter [3:0]slave_3 = 4'b0011; parameter [3:0]slave_4 = 4'b0100; parameter [3:0]slave_5 = 4'b0101;
即对应的这个设备图的情况:
