序
接上篇的加减指令,本篇主要实现CLZ、CLO、SLT等指令。
CLZ:从最高位开始数0的个数直到遇到1。
例:0x0000,0001 CLZ指令结果:31 0x8000,ffff CLZ指令结果是0
CLZ:从高位开始数1的个数直到遇到0。
例:0xffff,0000 CLO指令结果:16 0x0000,ffff CLO指令结果是0
修改ID模块
主要修改部分:
end else if (op == `EXE_SPECIAL2) begin //由FUNC字段决定,操作码为011100的指令 reg1_rden <= 1'd1; reg2_rden <= 1'd1; reg_wb <= 1'd1; case (func) `EXE_CLZ: begin aluop <= `EXE_CLZ_FUNC; end `EXE_CLO: begin aluop <= `EXE_CLO_FUNC; end default: begin aluop <= 7'd0; end endcase整体代码:
`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 (op == `EXE_SPECIAL) begin reg1_rden <= 1'd1; reg2_rden <= 1'd1; reg_wb <= 1'd1; case (func) `EXE_AND: begin aluop <= `EXE_AND_FUNC; end `EXE_OR: begin aluop <= `EXE_OR_FUNC; end `EXE_XOR: begin aluop <= `EXE_XOR_FUNC; end `EXE_NOR: begin aluop <= `EXE_NOR_FUNC; end `EXE_SLLV: begin aluop <= `EXE_SLL_FUNC; end `EXE_SRLV: begin aluop <= `EXE_SRLV_FUNC; end `EXE_SRAV: begin aluop <= `EXE_SRAV_FUNC; end `EXE_SLL: begin reg1_rden <= 1'd0; imm[4:0] <= shmat; aluop <= `EXE_SLL_FUNC; end `EXE_SRL: begin reg1_rden <= 1'd0; imm[4:0] <= shmat; aluop <= `EXE_SRL_FUNC; end `EXE_SRA: begin reg1_rden <= 1'd0; imm[4:0] <= shmat; aluop <= `EXE_SRA_FUNC; end `EXE_MOVN: begin if (reg2 == 32'd0) begin reg_wb <= 1'b0; end else begin reg_wb <= 1'b1; aluop <= `EXE_MOVN_FUNC; end end `EXE_MOVZ: begin if (reg2 == 32'd0) begin reg_wb <= 1'b1; aluop <= `EXE_MOVZ_FUNC; end else begin reg_wb <= 1'b0; end end `EXE_MFHI: begin reg1_rden <= 1'b0; reg2_rden <= 1'b0; aluop <= `EXE_MFHI_FUNC; end `EXE_MFLO: begin reg1_rden <= 1'b0; reg2_rden <= 1'b0; aluop <= `EXE_MFLO_FUNC; end `EXE_MTHI: begin reg2_rden <= 1'b0; reg_wb <= 1'b0; aluop <= `EXE_MTHI_FUNC; end `EXE_MTLO: begin reg2_rden <= 1'b0; reg_wb <= 1'b0; aluop <= `EXE_MTLO_FUNC; end `EXE_ADD: begin aluop <= `EXE_ADD_FUNC; end `EXE_ADDU: begin aluop <= `EXE_ADDU_FUNC; end `EXE_SUB: begin aluop <= `EXE_SUB_FUNC; end `EXE_SUBU: begin aluop <= `EXE_SUBU_FUNC; end `EXE_SLT: begin aluop <= `EXE_SLT_FUNC; end `EXE_SLTU: begin aluop <= `EXE_SLTU_FUNC; end default: aluop <= 7'd0; endcase end else if (op == `EXE_SPECIAL2) begin //由FUNC字段决定,操作码为011100的指令 reg1_rden <= 1'd1; reg2_rden <= 1'd1; reg_wb <= 1'd1; case (func) `EXE_CLZ: begin aluop <= `EXE_CLZ_FUNC; end `EXE_CLO: begin aluop <= `EXE_CLO_FUNC; end default: begin aluop <= 7'd0; end endcase end else begin reg1_rden <= 1'd1; //需要读取操作数1 rs寄存器的值 reg2_rden
自己动手写CPU_step6.1_算数运算指令
最新推荐文章于 2025-07-16 12:08:59 发布

最低0.47元/天 解锁文章
252

被折叠的 条评论
为什么被折叠?



