序
上文我们实现了加减和比较的指令,本篇将实现乘法运算指令。
MUL指令格式:(rs × rt => rd,只保存低32位)
OP rs rt rd FUNC
011100 xxxxx xxxxx xxxxx 00000 000010
MULT指令格式:(rs × rt => {hi,lo},结果高32位保存至HI寄存器、低32位保存至LO寄存器)
OP rs rt FUNC
000000 xxxxx xxxxx 00000 00000 011000
MULTU指令格式:(rs × rt => {hi,lo},无符号乘法,上面两条都是有符号)
OP rs rt FUNC
000000 xxxxx xxxxx 00000 00000 011001
指令定义
`define EXE_MUL 6'b000010 // rs × rt -> rd(保存结果低32位) `define EXE_MULT 6'b011000 // rs × rt -> {HI,LO} `define EXE_MULTU 6'b011001 // rs × rt -> {HI,LO} 无符号 `define EXE_MULT_FUNC 8'b00_011000 `define EXE_MULTU_FUNC 8'b00_011001 `define EXE_MUL_FUNC 8'b01_000010
修改ID模块
`include "defines.v" //译码阶段 对if_id传入的指令进行译码,分离出操作数和操作码 module id( input rst, input [`InstAddrBus] pc, input [`InstDataBus] inst, //读通用寄存器 读取 input [`RegDataBus] reg1_data, input [`RegDataBus] reg2_data, output reg reg1_rden, output reg reg2_rden, output reg [`RegAddrBus] reg1_addr, //源操作数1的地址 output reg [`RegAddrBus] reg2_addr, //源操作数2的地址 //送到ex阶段的值 output reg [`RegDataBus] reg1, //源操作数1 32b output reg [`RegDataBus] reg2, //源操作数2 32b output reg reg_wb, //写回目的寄存器标志 output reg [`RegAddrBus] reg_wb_addr,//写回目的寄存器地址 output reg [`AluOpBus] aluop, //操作码 //相邻指令的冲突,由EX阶段给出数据旁路 input ex_wr_en, //处于执行阶段的指令是否要写目的寄存器 input [`RegDataBus] ex_wr_data, input [`RegAddrBus] ex_wr_addr, //相隔一条指令的冲突,由MEM阶段给出数据旁路 input mem_wr_en, //处于访存阶段指令是否要写目的寄存器 input [`RegDataBus] mem_wr_data, input [`RegAddrBus] mem_wr_addr ); wire [5:0] op = inst[31:26]; //从指令中获取操作码 高6位 wire [5:0] func = inst[5:0]; //从指令中获取功能号确定指令类型 低6位 wire [4:0] shmat = inst[10:6]; //部分移位位数不从寄存器取值,直接由shmat给出 reg [`RegDataBus] imm; //立即数 always @ (*) begin if (rst) begin reg1_rden <= 1'd0; reg2_rden <= 1'd0; reg1_addr <= 5'd0; reg2_addr <= 5'd0; imm <= 32'd0; reg_wb <= 1'd0; reg_wb_addr <= 5'd0; aluop <= 7'd0; end else begin reg1_rden <= 1'd0; reg2_rden <= 1'd0; reg1_addr <= inst[25:21]; //默认从指令中读取操作数1地址 reg2_addr <= inst[20:16]; //默认从指令中读取操作数2地址 imm <= 32'd0; reg_wb <= 1'd0; reg_wb_addr <= inst[15:11]; //默认结果地址寄存器rd aluop <= 7'd0; //操作类型 if
08-30
1356
