Skip to content

Yale-Young/FPGA-project

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FPGA-project

项目结构FPGA-project
            ├─mcdf
            ├─RISC_CPU
            │  ├─design
            │  └─verification
            ├─RISC_V_CPU
            │  ├─design
            │  │  ├─core
            │  │  ├─debug
            │  │  ├─perips
            │  │  ├─soc
            │  │  └─utils
            │  └─verification
            └─SIFT_Sobel
                ├─design
                └─result

Project_init: risc_cpu by 夏宇闻

设计部分

设计需求:操作符:

              HLT(暂停+2)                     nop
              SKZ(为零转移+2/+4)    
              ADD(直接寻址数+累加器+2)        (<operand>)+ Acc => Acc
              AND(直接寻指数&累加器+2)        (<operand>)And Acc => Acc
              XOR(直接寻指数^累加器+2)        (<operand>)Xor Acc => Acc
              LDA(读:直接寻址数->累加器+2)   (<operand>)=> Acc
              STO(写:累加器->直接寻址数+2)    Acc =>(<operand>)
              JMP(无条件跳转)                  <operand> => PC

modules: cpu.v

//head
module cpu(    input clk,reset,         output halt,rd,wr,  output [12:0] addr,       inout [7:0] data);
      wire [2:0] opcode;
      wire [12:0] ir_addr,pc_addr;
      wire [7:0] alu_out,accum;
      wire zero,inc_pc,load_acc,load_pc,load_ir,data_ena,contr_ena;
//时钟生成:输出三个周期:clk1:clk的反相;fetch:clk的八分频;alu_clk: 8周期内只有一次;指令周期为八个机器周期
clk_gen m_clk_gen(.clk(clk),.clk1(clk1),.fetch(fetch),.alu_clk(alu_clk),.reset(reset));

//指令寄存器ir:取指 读两次data  输出 3'opcdoe 12'ir_addr
register m_register(.data(data),.ena(load_ir),.rst(reset),.clk1(clk1),.opc_iraddr({opcode,ir_addr}));

//累加器:存放结果data存至 reg[7:0]accum
accum m_accum(.data(alu_out),.ena(load_acc),.clk1(clk1),.rst(reset),.accum(accum));

//算数运算逻辑单元:alu_clk控制:根据操作数进行运算; zero为标志位:accum如果是全0则1;LDA 输出data,其他仍为accum
alu m_alu(.data(data),.accum(accum),.alu_clk(alu_clk),.opcode(opcode),.alu_out(alu_out),.zero(zero));

//数据控制器:控制累加器输出状态:高阻/输出
datactl m_datactl(.in(alu_out),.data_ena(data_ena),.data(data));

//地址多路器:选择地址:指令周期:前四周期从rom中读(输出pc地址);后四周期对ram写(输出指令中的地址)
adr m_adr(.fetch(fetch),.ir_addr(ir_addr),.pc_addr(pc_addr),.addr(addr));

//程序计数器:pc从13'b0开始读或load到ir_addr 上升沿有效
counter m_counter(.ir_addr(ir_addr),.load(load_pc),.clock(inc_pc),.rst(reset),.pc_addr(pc_addr));

//在fetch上升沿时刻,如果rst是高,那就enable为低,否则就正常工作
machinectl m_machinectl(.ena(contr_ena),.fetch(fetch),.rst(reset));

//输入opcode和标志位zero 输出各种  指令周期:
/**
*  1. rd=1,load_ir=1:从rom读指令到指令寄存器ir 3'opcdoe 5'ir_addr
*  2. inc_pc=1, rd=1,load_ir=1,pc+1,继续读rom的八位指令数据(低八位)'8ir_addr  获得一条完整指令
*  3. nop 00
*  4. HLT: 暂停,halt=1,inc_pc=1, pc+1; other: inc_pc=1, pc+1
*  5. JMP: load_pc=1 ;                      ADD||AND||XOR||LDA: rd=1;               STO: datactl=1;                                                 other: 00;
*  6. JMP: load_pc=1,inc_pc=1,pc->ir_addr;  ADD||AND||XOR||LDA: load_acc=1,rd=1;    STO:wr=1 datactl=1,->ram;   SKZ&&zero=1: inc_pc=1,pc+1;        other: 00;
*  7.                                       ADD||AND||XOR||LDA: rd=1;               STO: datactl=1; 
*  8.                                                                                                            SKZ&&zero=1: inc_pc=1,pc+1;
*/
machine m_machine(.inc_pc(inc_pc),.load_acc(load_acc),.load_pc(load_pc),.rd(rd),.wr(wr),.load_ir(load_ir),.clk1(clk1),.datactl_ena(data_ena),.halt(halt),.zero(zero),.ena(contr_ena),.opcode(opcode));


原理图(详看大图)

外设:addr_decode : 根据地址选通ram or rom; ram可读可写 rom仅读

验证部分

Project_rv: tiny_risc_v_cpu by liangkangnan

设计部分

设计需求:三级流水线,即取指,译码,执行,支持RV32IM指令集等 rv内容参见 rv中文手册

          32bits RV32I基础整数指令集(47条) 扩展硬件乘法器:(R) : mul mulh mulhsu mulhu div divu rem remu
          R: func-7      rs2-5 rs1-5 func-3  rd-5         opcode-7  寄存器-寄存器操作   add sub sll slt sltu xor srl sra or and 
          I: imm-12            rs1-5 func-3  rd-5         opcode-7  短立即数计算和访存load  lb lh lw lbu lhu addi slti sltiu xori ori andi fence fence.i ecall ebreak csrrw csrrs csrrc csrrwi cssrrsi csrrci
          S: imm-7       rs2-5 rs1-5 func-3  imm-5        opcode-7  访存store           sb sh sw 
          B: imm-1 imm-6 rs2-5 rs1-5 func-3  imm-4 imm-1  opcode-7  条件跳转            beq bne blt bge bltu bgeu
          U: imm-20                          rd-5         opcode-7  长立即数            lui auipc
          J: imm-1 imm-10 imm-1 imm-8        rd-5         opcode-7  无条件跳转          jal jalr

tinyriscv.v 结构分析

// tinyriscv处理器核顶层模块
module tinyriscv(
    input wire clk,
    input wire rst,
    output wire[`MemAddrBus] rib_ex_addr_o,    // 读、写外设的地址
    input wire[`MemBus] rib_ex_data_i,         // 从外设读取的数据
    output wire[`MemBus] rib_ex_data_o,        // 写入外设的数据
    output wire rib_ex_req_o,                  // 访问外设请求
    output wire rib_ex_we_o,                   // 写外设标志
    output wire[`MemAddrBus] rib_pc_addr_o,    // 取指地址
    input wire[`MemBus] rib_pc_data_i,         // 取到的指令内容
    input wire[`RegAddrBus] jtag_reg_addr_i,   // jtag模块读、写寄存器的地址
    input wire[`RegBus] jtag_reg_data_i,       // jtag模块写寄存器数据
    input wire jtag_reg_we_i,                  // jtag模块写寄存器标志
    output wire[`RegBus] jtag_reg_data_o,      // jtag模块读取到的寄存器数据
    input wire rib_hold_flag_i,                // 总线暂停标志
    input wire jtag_halt_flag_i,               // jtag暂停标志
    input wire jtag_reset_flag_i,              // jtag复位PC标志
    input wire[`INT_BUS] int_i                 // 中断信号
    );


    // pc寄存器: 重置->`CpuResetAddr | jump: pc-> jump_addr_i | hold: pc->pc | else : pc + 4
    pc_reg u_pc_reg(.clk(clk),.rst(rst),.jtag_reset_flag_i(jtag_reset_flag_i),.pc_o(pc_pc_o),.hold_flag_i(ctrl_hold_flag_o),.jump_flag_i(ctrl_jump_flag_o),.jump_addr_i(ctrl_jump_addr_o));

    // 控制模块: 发出跳转、暂停流水线信号 优先级:jump | exhold | clinthold 暂停流水线 -> ribhold暂停pc -> jtag 暂停流水线
    ctrl u_ctrl(.rst(rst),.jump_flag_i(ex_jump_flag_o),.jump_addr_i(ex_jump_addr_o),.hold_flag_ex_i(ex_hold_flag_o),.hold_flag_rib_i(rib_hold_flag_i),.hold_flag_o(ctrl_hold_flag_o),.hold_flag_clint_i(clint_hold_flag_o),.jump_flag_o(ctrl_jump_flag_o),.jump_addr_o(ctrl_jump_addr_o),.jtag_halt_flag_i(jtag_halt_flag_i));

    // 通用r1r2寄存器读写操作: 原子写r1,r2  并行读r1,r2 优先级 ex -> jtag
    regs u_regs(.clk(clk),.rst(rst),.we_i(ex_reg_we_o),.waddr_i(ex_reg_waddr_o),.wdata_i(ex_reg_wdata_o),.raddr1_i(id_reg1_raddr_o),.rdata1_o(regs_rdata1_o),.raddr2_i(id_reg2_raddr_o),.rdata2_o(regs_rdata2_o),.jtag_we_i(jtag_reg_we_i),.jtag_addr_i(jtag_reg_addr_i),.jtag_data_i(jtag_reg_data_i),.jtag_data_o(jtag_reg_data_o)
);

    // 状态控制寄存器:读写 优先级 ex -> clint 
    csr_reg u_csr_reg(.clk(clk),.rst(rst),.we_i(ex_csr_we_o),.raddr_i(id_csr_raddr_o),.waddr_i(ex_csr_waddr_o),.data_i(ex_csr_wdata_o),.data_o(csr_data_o),.global_int_en_o(csr_global_int_en_o),.clint_we_i(clint_we_o),.clint_raddr_i(clint_raddr_o),.clint_waddr_i(clint_waddr_o),.clint_data_i(clint_data_o),.clint_data_o(csr_clint_data_o),.clint_csr_mtvec(csr_clint_csr_mtvec),.clint_csr_mepc(csr_clint_csr_mepc),.clint_csr_mstatus(csr_clint_csr_mstatus));

    // 传递指令给译码器:包括指令地址和指令内容
    if_id u_if_id(.clk(clk),.rst(rst),.inst_i(rib_pc_data_i),.inst_addr_i(pc_pc_o),.int_flag_i(int_i),.int_flag_o(if_int_flag_o),.hold_flag_i(ctrl_hold_flag_o),.inst_o(if_inst_o),.inst_addr_o(if_inst_addr_o)
);

    // 指令解码器:传入指令地址32和内容32 寄存器1&2&csr的数据 根据后七位判断指令类型 输出寄存器操作 除以下特殊指令,均 读写地址置零 写标志置零
    INST_TYPE_I   : 0010011  func3 :[立即数&rs1加、比较、异或、与、移位]addi slti sltiu xori ori andi slli sri 获取操作数(符号位扩展) 设置读rs1和写rd: o
    INST_TYPE_R_M : 0110011  func7 :R/M func3 : [rs1&rs2加、比较、异或、与、移位]add_sub sll slt sltu xor sr or and 获取操作数 设置读rs1&2和写rd: o / func3 : [rs1&2乘、高位乘、有无符号乘]mul mulhu mulh mulhsu 获取操作数 设置读rs1&2和写rd:[rs1&2除法、无符号除法、求余、无符号余]div divu rem remu 获取操作数 设置读rs1&2和写rd: o
    INST_TYPE_L   : 0000011  func3 : [字节、半字、字加载offset & rs1]lb lh lw lbu lhu 获取操作数(符号位扩展) 设置读rs1和写rd:o
    INST_TYPE_S   : 0100011  func3 : [存rs2字节、字、半字至内存地址rs1+offset]sb sw sh 获取操作数off rs1 设置读rs1&2:o
    INST_TYPE_B   : 1100011  func3 : [r1r2相等、不等、小于、大于时pc分支offset]beq bne blt bge bltu bgeu 获取操作数rs1&2 跳转操作数pcaddr-off 设置读rs1&2:o 
    INST_JAL      : 1101111  跳转并链接 rd off ;x[rd] = pc+4; pc += sext(offset) 暂存下条指令,并跳转offset  获取操作数pc 4 跳转操作数pc off 写rd 
    INST_JALR     : 1100111  跳转并寄存器链接 t =pc+4; pc=(x[rs1]+sext(offset))&~1; x[rd]=t 暂存下条指令,并跳转offset 获取操作数pc 4 跳转rs1 off 写rd
    INST_LUI      : 0110111  高位立即数加载 x[rd] = sext(immediate[31:12] << 12) 操作数 {inst_i[31:12], 12'b0} 写入rd
    INST_AUIPC    : 0010111  PC加立即数 x[rd] = pc + sext(immediate[31:12] << 12)  操作数 pc {inst_i[31:12], 12'b0} 写入rd
    INST_NOP_OP   : 0000001  空 同默认
    INST_FENCE    : 0001111  同步内存和 I/O  跳转操作数pc 4
    INST_CSR      : 1110011  func3 : [读后写、读后置位(CSRs[csr] | x[rs1])、读后清除控制状态寄存器]csrrw csrrs crsrc 设置读rs1 写rd csr可写: csrrwi csrrsi csrrci 写rd csr可写:o
    id u_id(.rst(rst),.inst_i(if_inst_o),.inst_addr_i(if_inst_addr_o),.reg1_rdata_i(regs_rdata1_o),.reg2_rdata_i(regs_rdata2_o),.ex_jump_flag_i(ex_jump_flag_o),.reg1_raddr_o(id_reg1_raddr_o),.reg2_raddr_o(id_reg2_raddr_o),.inst_o(id_inst_o),.inst_addr_o(id_inst_addr_o),.reg1_rdata_o(id_reg1_rdata_o),.reg2_rdata_o(id_reg2_rdata_o),.reg_we_o(id_reg_we_o),.reg_waddr_o(id_reg_waddr_o),.op1_o(id_op1_o),.op2_o(id_op2_o),.op1_jump_o(id_op1_jump_o),.op2_jump_o(id_op2_jump_o),.csr_rdata_i(csr_data_o),.csr_raddr_o(id_csr_raddr_o),.csr_we_o(id_csr_we_o),.csr_rdata_o(id_csr_rdata_o),.csr_waddr_o(id_csr_waddr_o));

    // 从译码器传参给执行器:pc和内容 通用、csr寄存器写标志、读写地址 四个操作数:计算和跳转 
    id_ex u_id_ex(.clk(clk),.rst(rst),.inst_i(id_inst_o),.inst_addr_i(id_inst_addr_o),.reg_we_i(id_reg_we_o),.reg_waddr_i(id_reg_waddr_o),.reg1_rdata_i(id_reg1_rdata_o),.reg2_rdata_i(id_reg2_rdata_o),.hold_flag_i(ctrl_hold_flag_o),.inst_o(ie_inst_o),.inst_addr_o(ie_inst_addr_o),.reg_we_o(ie_reg_we_o),.reg_waddr_o(ie_reg_waddr_o),.reg1_rdata_o(ie_reg1_rdata_o),.reg2_rdata_o(ie_reg2_rdata_o),.op1_i(id_op1_o),.op2_i(id_op2_o),.op1_jump_i(id_op1_jump_o),.op2_jump_i(id_op2_jump_o),.op1_o(ie_op1_o),.op2_o(ie_op2_o),.op1_jump_o(ie_op1_jump_o),.op2_jump_o(ie_op2_jump_o),.csr_we_i(id_csr_we_o),.csr_waddr_i(id_csr_waddr_o),.csr_rdata_i(id_csr_rdata_o),.csr_we_o(ie_csr_we_o),.csr_waddr_o(ie_csr_waddr_o),.csr_rdata_o(ie_csr_rdata_o));

    // 执行!根据指令 与内存 除法器 通用寄存器 csr寄存器 控制器交互
    ex u_ex(.rst(rst),.inst_i(ie_inst_o),.inst_addr_i(ie_inst_addr_o),.reg_we_i(ie_reg_we_o),.reg_waddr_i(ie_reg_waddr_o),.reg1_rdata_i(ie_reg1_rdata_o),.reg2_rdata_i(ie_reg2_rdata_o),.op1_i(ie_op1_o),.op2_i(ie_op2_o),.op1_jump_i(ie_op1_jump_o),.op2_jump_i(ie_op2_jump_o),.mem_rdata_i(rib_ex_data_i),.mem_wdata_o(ex_mem_wdata_o),.mem_raddr_o(ex_mem_raddr_o),.mem_waddr_o(ex_mem_waddr_o),.mem_we_o(ex_mem_we_o).mem_req_o(ex_mem_req_o),.reg_wdata_o(ex_reg_wdata_o),.reg_we_o(ex_reg_we_o),.reg_waddr_o(ex_reg_waddr_o),.hold_flag_o(ex_hold_flag_o),.jump_flag_o(ex_jump_flag_o),.jump_addr_o(ex_jump_addr_o),.int_assert_i(clint_int_assert_o),.int_addr_i(clint_int_addr_o),.div_ready_i(div_ready_o),.div_result_i(div_result_o),.div_busy_i(div_busy_o),.div_reg_waddr_i(div_reg_waddr_o),.div_start_o(ex_div_start_o),.div_dividend_o(ex_div_dividend_o),.div_divisor_o(ex_div_divisor_o),.div_op_o(ex_div_op_o),.div_reg_waddr_o(ex_div_reg_waddr_o),.csr_we_i(ie_csr_we_o),.csr_waddr_i(ie_csr_waddr_o),.csr_rdata_i(ie_csr_rdata_o),.csr_wdata_o(ex_csr_wdata_o),.csr_we_o(ex_csr_we_o),.csr_waddr_o(ex_csr_waddr_o));

    // 除法器
    div u_div(.clk(clk),.rst(rst),.dividend_i(ex_div_dividend_o),.divisor_i(ex_div_divisor_o),.start_i(ex_div_start_o),.op_i(ex_div_op_o),.reg_waddr_i(ex_div_reg_waddr_o),.result_o(div_result_o),.ready_o(div_ready_o),.busy_o(div_busy_o),.reg_waddr_o(div_reg_waddr_o));

    // clint模块例化
    clint u_clint(.clk(clk),.rst(rst),.int_flag_i(if_int_flag_o),.inst_i(id_inst_o),.inst_addr_i(id_inst_addr_o),.jump_flag_i(ex_jump_flag_o),.jump_addr_i(ex_jump_addr_o),.hold_flag_i(ctrl_hold_flag_o),.div_started_i(ex_div_start_o),.data_i(csr_clint_data_o),.csr_mtvec(csr_clint_csr_mtvec),.csr_mepc(csr_clint_csr_mepc),.csr_mstatus(csr_clint_csr_mstatus),.we_o(clint_we_o),.waddr_o(clint_waddr_o),.raddr_o(clint_raddr_o),.data_o(clint_data_o),.hold_flag_o(clint_hold_flag_o),.global_int_en_i(csr_global_int_en_o),.int_addr_o(clint_int_addr_o),.int_assert_o(clint_int_assert_o));


tinyriscv_soc_top.v 结构分析

// tinyriscv soc顶层模块 - 内核连接外设
    // tinyriscv处理器核模块例化
    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));

    // rom模块例化
    rom u_rom(.clk(clk),.rst(rst),.we_i(s0_we_o),.addr_i(s0_addr_o),.data_i(s0_data_o),.data_o(s0_data_i));
    // ram模块例化
    ram u_ram(.clk(clk),.rst(rst),.we_i(s1_we_o),.addr_i(s1_addr_o),.data_i(s1_data_o),.data_o(s1_data_i));
    // timer模块例化
    timer timer_0(.clk(clk),.rst(rst),.data_i(s2_data_o),.addr_i(s2_addr_o),.we_i(s2_we_o),.data_o(s2_data_i),.int_sig_o(timer0_int));
    // uart模块例化
    uart uart_0(.clk(clk),.rst(rst),.we_i(s3_we_o),.addr_i(s3_addr_o),.data_i(s3_data_o),.data_o(s3_data_i),.tx_pin(uart_tx_pin),.rx_pin(uart_rx_pin));
    // io0
    assign gpio[0] = (gpio_ctrl[1:0] == 2'b01)? gpio_data[0]: 1'bz;
    assign io_in[0] = gpio[0];
    // io1
    assign gpio[1] = (gpio_ctrl[3:2] == 2'b01)? gpio_data[1]: 1'bz;
    assign io_in[1] = gpio[1];
    // 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)
    );
    // spi模块例化
    spi spi_0(.clk(clk),.rst(rst),.data_i(s5_data_o),.addr_i(s5_addr_o),.we_i(s5_we_o),.data_o(s5_data_i),.spi_mosi(spi_mosi),.spi_miso(spi_miso),.spi_ss(spi_ss),.spi_clk(spi_clk));

    // RISC-V Internal Bus
    rib u_rib(.clk(clk),.rst(rst),

        // master 0 interface
        .m0_addr_i(m0_addr_i),.m0_data_i(m0_data_i),.m0_data_o(m0_data_o),.m0_req_i(m0_req_i),.m0_we_i(m0_we_i),
        // master 1 interface
        .m1_addr_i(m1_addr_i),.m1_data_i(`ZeroWord),.m1_data_o(m1_data_o),.m1_req_i(`RIB_REQ),.m1_we_i(`WriteDisable),
        // master 2 interface
        .m2_addr_i(m2_addr_i),.m2_data_i(m2_data_i),.m2_data_o(m2_data_o),.m2_req_i(m2_req_i),.m2_we_i(m2_we_i),
        // master 3 interface
        .m3_addr_i(m3_addr_i),.m3_data_i(m3_data_i),.m3_data_o(m3_data_o),.m3_req_i(m3_req_i),.m3_we_i(m3_we_i),
        // slave 0 interface
        .s0_addr_o(s0_addr_o),.s0_data_o(s0_data_o),.s0_data_i(s0_data_i),.s0_we_o(s0_we_o),
        // slave 1 interface
        .s1_addr_o(s1_addr_o),.s1_data_o(s1_data_o),.s1_data_i(s1_data_i),.s1_we_o(s1_we_o),
        // slave 2 interface
        .s2_addr_o(s2_addr_o),.s2_data_o(s2_data_o),.s2_data_i(s2_data_i),.s2_we_o(s2_we_o),
        // slave 3 interface
        .s3_addr_o(s3_addr_o),.s3_data_o(s3_data_o),.s3_data_i(s3_data_i),.s3_we_o(s3_we_o),
        // slave 4 interface
        .s4_addr_o(s4_addr_o),.s4_data_o(s4_data_o),.s4_data_i(s4_data_i),.s4_we_o(s4_we_o),
        // slave 5 interface
        .s5_addr_o(s5_addr_o),.s5_data_o(s5_data_o),.s5_data_i(s5_data_i),.s5_we_o(s5_we_o),
        .hold_flag_o(rib_hold_flag_o));
    // 串口下载模块例化
    uart_debug u_uart_debug(.clk(clk),.rst(rst),.debug_en_i(uart_debug_pin),.req_o(m3_req_i),.mem_we_o(m3_we_i),.mem_addr_o(m3_addr_i),.mem_wdata_o(m3_data_i),.mem_rdata_i(m3_data_o));

    // jtag模块例化
    jtag_top #(.DMI_ADDR_BITS(6),.DMI_DATA_BITS(32),.DMI_OP_BITS(2)) u_jtag_top(.clk(clk),.jtag_rst_n(rst),.jtag_pin_TCK(jtag_TCK),.jtag_pin_TMS(jtag_TMS),.jtag_pin_TDI(jtag_TDI),.jtag_pin_TDO(jtag_TDO),.reg_we_o(jtag_reg_we_o),.reg_addr_o(jtag_reg_addr_o),.reg_wdata_o(jtag_reg_data_o),.reg_rdata_i(jtag_reg_data_i),.mem_we_o(m2_we_i),.mem_addr_o(m2_addr_i),.mem_wdata_o(m2_data_i),.mem_rdata_i(m2_data_o),.op_req_o(m2_req_i),.halt_req_o(jtag_halt_req_o),.reset_req_o(jtag_reset_req_o));







验证部分

core部分

pc寄存器

测试1500条指令,验证了暂停,跳转,和pc+4的功能
编译指令:make comp 仿真: ./simv -gui 查看覆盖率:make cov
代码覆盖率:image 条件覆盖率为2/3是一条|语句未完全判断
功能覆盖率:image rst,jump,hold,inst addr 均为100%;

regs 通用寄存器

测试了优先级判断,寄存器读写(含零寄存器5'b0),jtag的寄存器读写操作
结果比较方法:result = (get_actual.jdata===tmp_tran.jdata)&&(get_actual.data===tmp_tran.data);//包含不定态,要用===
测试结果: Compare SUCCESSFULLY @`J7BRQXJ5 PO)A_P%@LR3R 代码覆盖率:image 功能覆盖率:image

tiny_cpu

只测试指令执行和pc跳转功能 有两种思路:

1.在transaction中直接生成随机指令
会生成大量非法指令,很难达到覆盖率要求,例如使用15000条随机指令,代码覆盖率仅有60%,状态机覆盖率更是只有35%,所以有必要开发一个随机指令合法生成平台
image

2.搭建随机指令生成平台 使用instr_gen平台生成可配置的指令流,包括RV32im全部55条指令,可配置各种指令的占比。
使用指令生成平台控制指令,仅产生1500条指令便可达到很高的覆盖率(各指令权重均为1),图中clint覆盖率较低是因为未考虑各种中断,而非指令不全:
image image 仅测试add指令:

image

bus部分

rib总线
ram
rom
spi
gpio
timer
uart

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published