Lab9_8 V6.8
版本控制
版本 | 描述 |
---|---|
V0 | Lab3 |
V1.0 | Lab3 相对V0变化: 修改了文件名,各阶段以_stage结尾(因为if是关键词,所以module名不能叫if,遂改为if_stage,为了统一命名,将所有module后缀加上_stage) 删除了imm_sign信号(默认对立即数进行有符号数扩展) 由于对sw指令进行了重新理解:无论如何都是需要将rt_data传递给EXE阶段,故将部分译码逻辑进行后移至EXE阶段,避免id_to_exe_data总线过于庞大 将ins_shmat剔除出id_to_exe_data,因为imm包括ins_shamt 对信号进行重命名(例如在ID阶段有个信号叫rf_we,最终要传递给WB阶段,那么在EXE阶段,该信号叫作exe_rf_we,同理mem_rf_we,wb_rf_we),不然都叫rf_we,Debug的时候太痛苦了。 |
V2.0 | Lab4 相对V1.0的变化 引入`ifdef-`else-`endif来实现相对V1.0的代码增量 增加了旁路控制,减少流水线阻塞(因为增加了旁路,所以修改了ID、EXE、MEM的接口) 修改了ready_go命令,用于控制流水线的阻塞 |
V3.0 | Lab6(加载的是func_lab6的.coe文件,而不是func_lab5的,因为没有func_lab5这个东西) 相对V2.0的变化:电路细节变化详见:“CPU设计实战电路图”,图中Lab6的变化均以红色背景的方框框起来,并以黄色背景的“Lab6复用/新增信号”标注。本lab6.docx中,新增及修改的信号以红色标注。 删掉了ALU.v的接口,将alu_shamt合并至data_1,方便对新加指令sllv、srlv、srav的数据通路的复用 增加了ID.v中的alu_add的“或门”的输入 扩充了id_to_exe_data总线数据, 因为alu_op扩充了新的指令 添加了imm_zero_ext信号 修改了ins_R、ins_J、ins_I,因为增加了新的指令 乘法器和除法器调用vivado的IP,其周期参数化可配置设计 乘法和除法结果存放的寄存器HI/LO放在WB.v中 增加了sfr.v,用于特殊寄存器的存储 增加了mul_div.v,用于处理乘法和除法。增加了mul.v用于处理乘法,增加了divu.v用于处理无符号除法,增加了divs.v用于处理有符号除法 修改了id_to_exe_data,添加了新信号:imm_zero_ext_en 修改了id_to_exe_data,扩充了alu_op的位宽,并将alu_op调整至id_to_exe_data的最高位,方便未来扩充指令 |
V4.0 | Lab7 修改了alu_op的位宽 新增了两个bus:lw_bus、sw_bus,同时将mem_rd整合至lw_bus,将mem_we整合至sw_bus 扩大了id_to_exe_data lw_bus传递至MEM阶段结束,sw_bus传递至EXE阶段结束 修改了旁路,之前都是lw的旁路,这里将其扩充了lb、lbu、lh、lhu、lwl、lwr |
V5.0 | Lab8 (对应第7章任务一):添加syscall例外支持 增加MTC0、MFC0、ERET指令 增加CP0寄存器Status、Cause、EPC 增加SYSCALL指令 新建SSR.v(即system registers),是ID.v的子模块 为ID、EXE、MEM、WB级增加了flush信号,用于将数据清零 |
V6.0 | 添加break指令断点例外 添加地址错、整数溢出、保留指令例外 增加CP0寄存器Count、Compare、BadVAddr 增加时钟中断 增加6个硬中断 增加2个软件中断 |
V6.8 | 此版本感觉叫5.8更好,但是本人就顺着叫6.8了,此版本实际上是V5.0的重写,重新设计了数据通路: 将SSR.v放在WB阶段(依据原书P173) MFC0/MTC0也放在WB阶段,并且不引入旁路,而是直接插入NOP(依据原书P180) |
Top顶层
接口信号
MYCPU_TOP.v(TOP)
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
取指端访存接口 | |||
inst_sram_en | 1 | O | 指令RAM使能信号,高电平有效 |
inst_sram_wen | 4 | O | 指令RAM字节写使能信号,高电平有效 |
inst_sram_addr | 32 | O | 指令RMA读写地址,字节寻址 |
inst_sram_wdata | 32 | O | 指令RAM写数据 |
inst_sram_rdata | 32 | I | 指令RAM读数据 |
数据端访存接口 | |||
data_sram_en | 1 | O | 数据RAM使能信号,高电平有效 |
data_sram_wen | 4 | O | 数据RAM字节写使能信号,高电平有效 |
data_sram_addr | 32 | O | 数据RAM读写地址,字节寻址 |
data_sram_wdata | 32 | O | 数据RAM写数据 |
data_sram_rdata | 32 | I | 数据RAM读数据 |
debug信号,供验证平台使用 | |||
debug_wb_pc | 32 | O | 写回级(多周期最后一级)的PC,需要myCPU里将PC一路传递到写回级 |
debug_wb_rf_wen | 4 | O | 写回级写寄存器堆(regfiles)的写使能,为字节使能,如果myCPU写regfiles为单字节写使能,则将写使能扩展成4位即可 |
debug_wb_rf_wnum | 5 | O | 写回级写regfiles的目的寄存器号 |
debug_wb_rf_wdata | 32 | O | 写回级写regfiles的写数据 |
接口时序
略(MIPS经典五级流水线)
代码结构
MYCPU_TOP.v
|____IF.v
|____ID.v
|____RF.v(2个读端口,1个写端口)
|____SFR.v(1个读端口,2个写端口)
|____EXE.v
|____ALU.v
|____MUL_DIV.v(专门处理乘法和除法)
|____MUL.v
|____DIVU.v
|____DIVS.v
|____MEM.v
|____WB.v
|____SSR.v
|____MYCPU.h
DATA_RAM.v
IF.v(修改为IF_STAGE,因为会与关键词if冲突)
接口信号
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与TOP | |||
inst_sram_en | 1 | O | RAM使能信号,高电平有效 |
inst_sram_wen | 4 | O | RAM字节写使能信号,高电平有效 |
inst_sram_addr | 32 | O | RMA读写地址,字节寻址 |
inst_sram_wdata | 32 | O | RAM写数据 |
inst_sram_rdata | 32 | I | RAM读数据 |
与ID | |||
id_to_if_allowin | 1 | I | pipe allowin |
if_to_id_vld | 1 | O | pipe valid |
if_to_id_data | 64 | O | pipe data(instruction 32-bits, pc 32-bits) |
jump_bus | 33 | I | branch instructions(enable 1bit,address 32-bits) |
与WB | |||
wb_jump_en | 1 | I | 检测到EXC,然后决定是否jump |
wb_jump_pc | 32 | I | 检测到EXC,jump的PC值 |
接口时序
ID.v
接口信号
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与TOP | |||
inst_sram_en | 1 | O | RAM使能信号,高电平有效 |
inst_sram_wen | 4 | O | RAM字节写使能信号,高电平有效 |
inst_sram_addr | 32 | O | RMA读写地址,字节寻址 |
inst_sram_wdata | 32 | O | RAM写数据 |
inst_sram_rdata | 32 | I | RAM读数据 |
与IF | |||
id_to_if_allowin | 1 | I | pipe allowin |
if_to_id_vld | 1 | O | pipe valid |
if_to_id_data | 64 | O | pipe data(instruction 32-bits, pc 32-bits) |
jump_bus | 33 | I | branch instructions(enable 1bit,address 32-bits) |
与EXE | |||
exe_to_id_allowin | 1 | I | pipe allowin |
id_to_exe_vld | 1 | O | pipe valid |
id_to_exe_data | 179 | O | {alu_op:21, shamt_is_shamt:1, imm_zero_ext_en:1, ins_R:1, ins_I:1, imm:16, mem_rd:1, mem_we:1, rf_we:1, rf_dst_addr:5, rt_data:32, rs_sfr_data_2:32, pc:32} {id_exc_bus:16, alu_op:21, shamt_is_shamt:1, imm_zero_ext_en:1, ins_R:1, ins_I:1, imm:16, lwx_bus_less2:10, swx_bus:8, rf_we:4, rf_dst_addr:5, rt_data:32, rs_sfr_data_2:32, pc:32} |
exe_bypass_bus | 38 | I | {exe_rf_we:1, exe_rf_dst_addr:5, exe_rf_data:32} |
exe_to_id_sfr_bus | 76 | I | [75] exe_sfr_we1 [74:70] exe_sfr_w_addr1 [69:38] exe_sfr_data1 [37] exe_sfr_we2 [36:32] exe_sfr_w_addr2 [31:0] exe_sfr_data2 |
lwx_bus_less2 将其合并至id_to_exe_data中 | 10 | O | lwx类总线: ins_lb: 1, ins_lbu: 1, ins_lh: 1, ins_lhu: 1, ins_lwl: 1, ins_lwr: 1, ins_lw: 1, rs_low2: 2 mem_rd: 1 |
swx_bus 将其合并至id_to_exe_data中 | 8 | O | swx类总线: ins_sb: 1, ins_sh: 1, ins_swl: 1, ins_swr: 1, mem_we[3:0]: 4 |
mul_div_busy | 1 | I | 正在进行乘法或除法运算 |
exe_ins_mfc0 | 1 | I | 指令mfc0传递至EXE阶段 |
exe_ins_lwx | 1 | I | lwx类指令传递至EXE阶段 |
与MEM | |||
mem_bypass_bus | 38 | I | {mem_rf_we:1, mem_rf_dst_addr:5, mem_rf_data:32} |
mem_ins_mfc0 | 1 | I | 指令mfc0传递至MEM阶段 |
与WB | |||
wb_to_rf_bus | 41 | I | {rf_we:4, rf_addr:5, rf_data:32} |
wb_exc_flush | 1 | I | WB阶段检测到EXC,对流水线清空 |
wb_c0_has_int | 1 | I | WB阶段的SSR检测到中断 |
wb_ins_mfc0 | 1 | I | 指令mfc0传递至WB阶段 |
接口信号(RF.v)
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
与ID内部信号 | |||
rf_r_addr1 | 5 | I | RF读地址1 |
rf_r_data1 | 32 | O | RF读数据1 |
rf_r_addr2 | 5 | I | RF读地址2 |
rf_r_data2 | 32 | O | RF读数据2 |
rf_wen1 | 4 | I | RF写使能1 |
rf_w_addr1 | 5 | I | RF写地址1 |
rf_w_data1 | 32 | O | RF写数据1 |
接口信号(SFR)
当写入同一地址时,以sfr_we_1优先
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ID内部信号 | |||
sfr_r_addr1 | 5 | I | SFR读地址1 |
sfr_r_data1 | 32 | O | SFR读数据1 |
sfr_we_1 | 1 | I | SFR写使能1 |
sfr_w_addr1 | 5 | I | SFR写地址1 |
sfr_w_data1 | 32 | I | SFR写数据1 |
sfr_we_2 | 1 | I | SFR写使能2 |
sfr_w_addr2 | 5 | I | SFR写地址2 |
sfr_w_data2 | 32 | I | SFR写数据2 |
接口时序
电路设计
图3-4-1 译码电路分组(注:黄线少画了两条)
根据附录——MIPS指令。由于跳转指令不传递给EXE阶段,直接传递给IF阶段,且为纯组合逻辑输出,有可能成为关键路径,故对跳转指令单独处理。除了跳转指令外,涉及加法(减法归为加法)的指令如图3-4-1所示,即ins_addu、ins_addiu、ins_subu、ins_lw、ins_sw。
对于图3-4-1的拼接运算,可以当作移位运算执行。
EXE.v
接口信号
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与TOP(外接的DATA_RAM) | |||
data_sram_en | 1 | O | 数据RAM使能信号,高电平有效 |
data_sram_wen | 4 | O | 数据RAM字节写使能信号,高电平有效(4个比特,应该代表32 = 4 bytes) |
data_sram_addr | 32 | O | 数据RAM读写地址,字节寻址 |
data_sram_wdata | 32 | O | 数据RAM写数据 |
与ID | |||
exe_to_id_allowin | 1 | O | pipe allowin |
id_to_exe_vld | 1 | I | pipe valid |
id_to_exe_data | 179 | I | {alu_op:21, shamt_is_shamt:1, imm_zero_ext_en:1, ins_R:1, ins_I:1, imm:16, mem_rd:1, mem_we:1, rf_we:1, rf_dst_addr:5, rt_data:32, rs_sfr_data_2:32, pc:32} {id_exc_bus:16, alu_op:21, shamt_is_shamt:1, imm_zero_ext_en:1, ins_R:1, ins_I:1, imm:16, lwx_bus_less2:10, swx_bus:8, rf_we:4, rf_dst_addr:5, rt_data:32, rs_sfr_data_2:32, pc:32} |
exe_bypass_bus | 41 | O | {exe_rf_we:4, exe_rf_dst_addr:5, exe_rf_data:32} |
exe_ins_mfc0 | 1 | O | 指令mfc0传递至EXE阶段 |
exe_ins_lwx | 1 | O | lwx类指令传递至EXE阶段 |
exe_to_id_sfr_bus | 76 | O | [75] exe_sfr_we1 [74:70] exe_sfr_w_addr1 [69:38] exe_sfr_data1 [37] exe_sfr_we2 [36:32] exe_sfr_w_addr2 [31:0] exe_sfr_data2 |
mul_div_busy | 1 | O | 正在进行乘法或除法运算 |
lwx_bus 将其合并至id_to_exe_data中 | 10 | I | lwx类总线: ins_lb: 1, ins_lbu: 1, ins_lh: 1, ins_lhu: 1, ins_lwl: 1, ins_lwr: 1, ins_lw: 1, rs_low2: 2 mem_rd: 1 |
swx_bus 将其合并至id_to_exe_data中 | 8 | I | swx类总线: ins_sb: 1, ins_sh: 1, ins_swl: 1, ins_swr: 1, mem_we[3:0]: 4 |
与MEM | |||
mem_to_id_allowin | 1 | I | pipe allowin |
exe_to_mem_vld | 1 | O | pipe valid |
exe_to_mem_data | 138 | O | {mem_rd:1, rf_we:1, rf_dst_addr:5, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc), exe_result:32 {exe_to_mem_exc_bus:56, lwx_bus:10, rf_we:4, rf_dst_addr:5, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc), exe_result:32 |
lwx_bus 将其合并至id_to_exe_data中 | 10 | O | lwx类总线: ins_lb: 1, ins_lbu: 1, ins_lh: 1, ins_lhu: 1, ins_lwl: 1, ins_lwr: 1, ins_lw: 1, rs_low2: 2 mem_rd: 1 |
与WB | |||
wb_exc_flush | 1 | I | WB阶段检测到EXC,对流水线清空 |
接口信号(ALU.v)
暂时不需要时钟和复位,纯组合逻辑
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ID内部信号 | |||
alu_shamt | 6 | I | ALU移位(R-指令的shamt部分) |
alu_op | 19 | I | ALU操作(加、减、乘除、位运算) |
alu_add_ov | 1 | O | 加法/减法溢出 |
alu_din1 | 32 | I | ALU输入1 |
alu_din2 | 32 | I | ALU输入2 |
alu_out | 32 | O | ALU输出 |
mul_div_busy | 1 | O | 正在进行乘法或除法运算 |
接口信号(MUL_DIV.v)
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ALU内部信号 | |||
alu_mult | 1 | I | 有符号乘 |
alu_multu | 1 | I | 无符号乘 |
alu_div | 1 | I | 有符号除 |
alu_divu | 1 | I | 无符号除 |
alu_mthi | 1 | I | 将寄存器 rs 的值写入到 HI 寄存器中 |
alu_mtlo | 1 | I | 将寄存器 rs 的值写入到LO寄存器中 |
alu_din1 | 32 | I | ALU输入1 |
alu_din2 | 32 | I | ALU输入2 |
exe_to_id_sfr_bus | 76 | O | [75] exe_sfr_we1 [74:70] exe_sfr_w_addr1 [69:38] exe_sfr_data1 [37] exe_sfr_we2 [36:32] exe_sfr_w_addr2 [31:0] exe_sfr_data2 |
mul_div_busy | 1 | O | 正在进行乘法或除法运算 |
接口信号MUL.v
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ALU内部信号 | |||
mul_din_vld | 1 | I | 数据有效信号 |
mul_din1 | 33 | I | 乘数1 |
mul_din2 | 33 | I | 乘数2 |
mul_result_hi | 32 | O | 乘法高32位 |
mul_result_lo | 32 | O | 乘法低32位 |
接口信号DIVU.v
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ALU内部信号 | |||
divu_din_vld | 1 | I | 数据有效信号 |
divu_din1 | 33 | I | 被除数 |
divu_din2 | 33 | I | 除数 |
divu_hi | 32 | O | 结果高32位 |
divu_lo | 32 | O | 结果低32位 |
接口信号DIVS.v
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ALU内部信号 | |||
divs_din_vld | 1 | I | 数据有效信号 |
divs_din1 | 33 | I | 被除数 |
divs_din2 | 33 | I | 除数 |
divs_hi | 32 | O | 结果高32位 |
divs_lo | 32 | O | 结果低32位 |
接口时序
MEM.v
接口信号
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与TOP(外接的DATA_RAM) | |||
data_sram_rdata | 32 | I | 数据RAM读数据 |
与ID | |||
mem_bypass_bus | 38 | O | {mem_rf_we:4, mem_rf_dst_addr:5, mem_rf_data:32} |
mem_ins_mfc0 | 1 | O | 指令mfc0传递至MEM阶段 |
与EXE | |||
mem_to_exe_allowin | 1 | O | pipe allowin |
exe_to_mem_vld | 1 | I | pipe valid |
exe_to_mem_data | 138 | I | {mem_rd:1, rf_we:1, rf_dst_addr:5, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc), exe_result:32 {exe_to_mem_exc_bus:56, lwx_bus:10, rf_we:4, rf_dst_addr:5, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc), exe_result:32 |
lwx_bus 将其合并至id_to_exe_data中 | 10 | I | lwx类总线: ins_lb: 1, ins_lbu: 1, ins_lh: 1, ins_lhu: 1, ins_lwl: 1, ins_lwr: 1, ins_lw: 1, rs_low2: 2 mem_rd: 1 |
与WB | |||
wb_to_mem_allowin | 1 | I | pipe allowin |
mem_to_wb_vld | 1 | O | pipe valid |
mem_to_wb_data | 128 | O | { mem_to_wb_exc_bus:56, rf_we:4, rf_dst_addr:5, mem_result:32, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc)} |
wb_exc_flush | 1 | I | WB阶段检测至EXC,对流水线清空 |
WB.v
接口信号
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与TOP | |||
debug_wb_pc | 32 | O | 写回级(多周期最后一级)的PC,需要myCPU里将PC一路传递到写回级(与原书保持一致) |
debug_wb_rf_wen | 4 | O | 写回级写寄存器堆(regfiles)的写使能,为字节使能,如果myCPU写regfiles为单字节写使能,则将写使能扩展成4位即可(与原书保持一致) |
debug_wb_rf_wnum | 5 | O | 写回级写regfiles的目的寄存器号(与原书保持一致) |
debug_wb_rf_wdata | 32 | O | 写回级写regfiles的写数据(与原书保持一致) |
与IF | |||
wb_jump_en | 1 | O | 检测到EXC,然后决定是否jump |
wb_jump_pc | 32 | O | 检测到EXC,jump的PC值 |
与MEM | |||
wb_to_mem_allowin | 1 | O | pipe allowin |
mem_to_wb_vld | 1 | I | pipe valid |
mem_to_wb_data | 128 | I | { mem_to_wb_exc_bus:56, rf_we:4, rf_dst_addr:5, mem_result:32, pc:32(其实可以删掉pc,这里是debug显示用的,可以叫debug_pc)} |
与ID | |||
wb_to_rf_bus | 41 | O | {rf_we:4, rf_addr:5, rf_data:32} |
wb_exc_flush | 1 | O | WB阶段检测到EXC,对流水线清空 |
wb_c0_has_int | 1 | O | WB阶段的SSR检测到中断 |
wb_ins_mfc0 | 1 | O | 指令mfc0传递至WB阶段 |
接口信号(SSR)
名称 | 宽度 | 方向 | 描述 |
---|---|---|---|
时钟与复位 | |||
clk | 1 | I | 时钟信号,来自clk_pll的输出时钟 |
resetn | 1 | I | 复位信号,低电平同步复位 |
与ID内部信号 | |||
c0_op | 4 | I | 3:保留着,先置为0 2:wb_bd:branch delay slot(本Lab8版本可以恒置为0) 1:wb_exc:由WB传回来的例外 0:syscall |
c0_eret | 1 | I | eret |
c0_int | 6 | I | 中断 |
c0_excode | 5 | I | 由WB传回来的excode |
c0_wb_pc | 32 | I | 由WB传回来的PC值 |
c0_we | 1 | I | SSR写使能(1:写,0:读) |
c0_addr | 8 | I | SSR写/读地址 [7:5]:c0_sel [5:0]:c0_id |
c0_wdata | 32 | I | SSR写数据 |
c0_rdata | 32 | O | SSR读数据 |
c0_has_int | 1 | O | 发生中断 |
c0_badvaddr_i | 32 | I | badvaddr的数据输入 |
Lab9_8 完结
好艰难啊,一周时间:对例外理解得不够深入导致重新Lab8和Lab9。
Lab9_8——Debug
badvaddr报错
经排查,是SSR.v设计有问题,缺少badvaddr输入(因为需要同时向EPC和c0_badvaddr两个寄存器写数据)。故作以下修改:
使用((c0_excode == `EX_ADEL) || (c0_excode == `EX_ADES))控制使能:
SSR.v的接口添加c0_badvaddr_i:
EXE阶段创建exe_exc_data_mux信号:
(因为mtc0是向c0寄存器组中写rt_data,故之前的设计中向SSR.v引了一条rt_data的数据通路,因为mtc0和badvaddr不会同时发生,所以这里复用了先前设计的rt_data的数据通路):
mfc0报错
经排查是之前的sw有问题,该sw地址报错,但是还是将错误数据写进去了,故报错,已修改为:
即通过exe_exc控制EXE阶段的SRAM的写使能
adel报错
从报告的地址及波形中是判断不出是adel报错的,我是在看了“test.s”和波形,判断按我的逻辑跳转地址是没有任何问题的,会为什么reference会报例外呢(跳到0xbfc00380显然是报例外了),过了一会儿(约5分钟),在我观察波形的时候,发现pc的值不是4的整数倍,恍然就意识到了PC的adel问题。
eret的清零问题
简单解释一下该bug:遇到eret指令时,也应将流水线给清零,但是我没有清零。
-
不可将eret与wb_exc合并,因为eret不需要写EPC寄存器,故不可与之合并
-
需要单独清空,故有:
通过wb_exc_flush来清空各级(这里指ID/EXE/MEM/WB)流水线
-
rf_we的使能问题
从上图中可以看出div_u_result_hi的结果是0x00000039,而结果的前一个周期就是0x800d0000,所以最开始我以为是rf_we的问题(脑子抽风了hi、lo寄存器和rf_we根本没有关系),后来发现不是,具体经历如下:
-
经查看波形,怀疑是rf_we的问题(后来发现不是,因为读取的指令都是全0(NOP指令),即使rf_we使能也无所谓)于是修改如下:
后来才发现都是NOP指令,所以都给注释掉了
-
发现不是id_rf_we的问题后,脑子终于回来了,意识到HI/LO寄存器是sfr_we控制的,然后查看sfr_we的控制信号:
发现我将exe_to_id_sfr_bus通过exe_flush给清零的(不应该清零的),故已将该代码改为:assign exe_to_id_sfr_bus = exe_sfr_bus;
-
后来到jump型指令的时候又报错了:
因为刚开始我认为jump型指令(如jal)是无论如何都要跳的,因此没必要加上将bd置1,需要置1应该只有条件转移指令(如bne),然而经测试还是需要加上jump型指令:(本人不理解何故这样处理,存疑)已添加jump型指令:
-
-
c0_bd问题
从报错内容看wb_rf_wdata只差了4,经波形确定是bd问题,因为设计之初不知如何安排这个bd,遂干脆置0,又阅读了原书P178关于EPC寄存器的描述,得知:“报例外指令如果是转移延迟槽指令,那么EPC记录的不是报例外指令的PC,而是该延迟槽对应的转移指令的PC”
于是在ID.v中添加如下代码: