自己动手写CPU_step6.1_算数运算指令

接上篇的加减指令,本篇主要实现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   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值