• 自己手写RISCV架构CPU-4其它指令


    自己手写RISCV架构CPU-4其它指令

    实现了RVI指令中除ori指令的其它指令。

    4.1、逻辑、移位操作与空指令

    4.1.1、基本整数指令RV32I

    RISCV指令集架构定义的基本整数指令RV32I有9条:

    ADDI、SLTI、SLTIU、ANDI、ORI、XORI、SLLI、SRLI、SRAI

    其格式如下

    addi rd, rs1, imm[11:0]
    
    • 1

    指令详解:

    addi指令将操作数rs1中的整数与12为立即数(进行符号位扩展)进行家吗操作,结果写回寄存器rd中。

    4.1.2、修改defines.v

    在I指令定义的后面添加其它I类型指令

    `define INST_ADDI   3'b000
    `define INST_SLTI   3'b010
    `define INST_SLTIU  3'b011
    `define INST_XORI   3'b100
    `define INST_ORI    3'b110
    `define INST_ANDI   3'b111
    `define INST_SLLI   3'b001
    `define INST_SRI    3'b101
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    4.1.3 修改译码阶段id模块
    case (opcode)
        `INST_TYPE_I: begin
            case (funct3)
                `INST_ADDI, `INST_SLTI, `INST_SLTIU, `INST_XORI, `INST_ORI, `INST_ANDI, `INST_SLLI, `INST_SRI: begin
                    reg_we_o = `WriteEnable;
                    reg_waddr_o = rd;
                    reg1_raddr_o = rs1;
                    reg2_raddr_o = `ZeroReg;
                    op1_o = reg1_rdata_i;
                    op2_o = {{20{inst_i[31]}}, inst_i[31:20]};
                end
                default: begin
                    reg_we_o = `WriteDisable;
                    reg_waddr_o = `ZeroReg;
                    reg1_raddr_o = `ZeroReg;
                    reg2_raddr_o = `ZeroReg;
                end
            endcase
        end
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    4.1.4 修改执行阶段ex模块
    case (opcode)
                `INST_TYPE_I: begin
                    case (funct3)
                        `INST_ADDI: begin
                            reg_wdata = op1_add_op2_res;
                        end
                        `INST_SLTI: begin
                            reg_wdata = {32{(~op1_ge_op2_signed)}} & 32'h1;
                        end
                        `INST_SLTIU: begin
                            reg_wdata = {32{(~op1_ge_op2_unsigned)}} & 32'h1;
                        end
                        `INST_XORI: begin
                            reg_wdata = op1_i ^ op2_i;
                        end
                        `INST_ORI: begin
                            reg_wdata = op1_i | op2_i;
                        end
                        `INST_ANDI: begin
                            reg_wdata = op1_i & op2_i;
                        end
                        `INST_SLLI: begin
                            reg_wdata = reg1_rdata_i << inst_i[24:20];
                        end
                        `INST_SRI: begin
                            if (inst_i[30] == 1'b1) begin
                                reg_wdata = (sri_shift & sri_shift_mask) | ({32{reg1_rdata_i[31]}} & (~sri_shift_mask));
                            end else begin
                                reg_wdata = reg1_rdata_i >> inst_i[24:20];
                            end
                        end
                        default: begin
                            reg_wdata = `ZeroWord;
                        end
                    endcase
                end
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    对于addi指令,添加

    wire[31:0] op1_add_op2_res;
    assign op1_add_op2_res = op1_i + op2_i;
    
    • 1
    • 2

    对于stli指令,添加

    wire op1_ge_op2_signed;
    assign op1_ge_op2_signed = $signed(op1_i) >= $signed(op2_i);
    
    • 1
    • 2

    对于stliu指令,添加

    wire op1_ge_op2_unsigned;
    assign op1_ge_op2_unsigned = op1_i >= op2_i;
    
    • 1
    • 2

    对于rsi指令,添加

    wire[31:0] sri_shift;
    wire[31:0] sri_shift_mask;
    assign sri_shift = reg1_rdata_i >> inst_i[24:20];
    assign sri_shift_mask = 32'hffffffff >> inst_i[24:20];
    
    • 1
    • 2
    • 3
    • 4

    4.2、R类型指令

    R类型指令有ADD、SUB、SLT、SLTU、AND、OR、XOR、SLL、SRL、SRA指令

    4.2.1、defines.v添加
    // R and M type inst
    `define INST_TYPE_R 7'b0110011
    // R type inst
    `define INST_ADD_SUB 3'b000
    `define INST_SLL    3'b001
    `define INST_SLT    3'b010
    `define INST_SLTU   3'b011
    `define INST_XOR    3'b100
    `define INST_SR     3'b101
    `define INST_OR     3'b110
    `define INST_AND    3'b111
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    4.2.2、id模块修改
    `INST_TYPE_R: begin
        if ((funct7 == 7'b0000000) || (funct7 == 7'b0100000)) begin
            case (funct3)
                `INST_ADD_SUB, `INST_SLL, `INST_SLT, `INST_SLTU, `INST_XOR, `INST_SR, `INST_OR, `INST_AND: begin
                    reg_we_o = `WriteEnable;
                    reg_waddr_o = rd;
                    reg1_raddr_o = rs1;
                    reg2_raddr_o = rs2;
                    op1_o = reg1_rdata_i;
                    op2_o = reg2_rdata_i;
                end
                default: begin
                    reg_we_o = `WriteDisable;
                    reg_waddr_o = `ZeroReg;
                    reg1_raddr_o = `ZeroReg;
                    reg2_raddr_o = `ZeroReg;
                end
            endcase
        end else begin
            reg_we_o = `WriteDisable;
            reg_waddr_o = `ZeroReg;
            reg1_raddr_o = `ZeroReg;
            reg2_raddr_o = `ZeroReg;
        end
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    4.2.3、ex模块修改
    `INST_TYPE_R: begin
        if ((funct7 == 7'b0000000) || (funct7 == 7'b0100000)) begin
            case (funct3)
                `INST_ADD_SUB: begin
                    if (inst_i[30] == 1'b0) begin
                        reg_wdata = op1_add_op2_res;
                    end else begin
                        reg_wdata = op1_i - op2_i;
                    end
                end
                `INST_SLL: begin
                    reg_wdata = op1_i << op2_i[4:0];
                end
                `INST_SLT: begin
                    reg_wdata = {32{(~op1_ge_op2_signed)}} & 32'h1;
                end
                `INST_SLTU: begin
                    reg_wdata = {32{(~op1_ge_op2_unsigned)}} & 32'h1;
                end
                `INST_XOR: begin
                    reg_wdata = op1_i ^ op2_i;
                end
                `INST_SR: begin
                    if (inst_i[30] == 1'b1) begin
                        reg_wdata = (sr_shift & sr_shift_mask) | ({32{reg1_rdata_i[31]}} & (~sr_shift_mask));
                    end else begin
                        reg_wdata = reg1_rdata_i >> reg2_rdata_i[4:0];
                    end
                end
                `INST_OR: begin
                    reg_wdata = op1_i | op2_i;
                end
                `INST_AND: begin
                    reg_wdata = op1_i & op2_i;
                end
                default: begin
                    reg_wdata = `ZeroWord;
                end
            endcase
        end else begin
            reg_wdata = `ZeroWord;
        end
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    4.3、整数Load/Store指令

    LW、LH、LHU、LB、LBU、SW、SH、SB指令

    lw rd, offset[11:0] (rs1)

    4.3.1、defines.v
    // L type inst
    `define INST_TYPE_L 7'b0000011
    `define INST_LB     3'b000
    `define INST_LH     3'b001
    `define INST_LW     3'b010
    `define INST_LBU    3'b100
    `define INST_LHU    3'b101
    
    // S type inst
    `define INST_TYPE_S 7'b0100011
    `define INST_SB     3'b000
    `define INST_SH     3'b001
    `define INST_SW     3'b010
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    4.3.2、id.v
    `INST_TYPE_L: begin
        case (funct3)
            `INST_LB, `INST_LH, `INST_LW, `INST_LBU, `INST_LHU: begin
                reg1_raddr_o = rs1;
                reg2_raddr_o = `ZeroReg;
                reg_we_o = `WriteEnable;
                reg_waddr_o = rd;
                op1_o = reg1_rdata_i;
                op2_o = {{20{inst_i[31]}}, inst_i[31:20]};
            end
            default: begin
                reg1_raddr_o = `ZeroReg;
                reg2_raddr_o = `ZeroReg;
                reg_we_o = `WriteDisable;
                reg_waddr_o = `ZeroReg;
            end
        endcase
    end
    `INST_TYPE_S: begin
        case (funct3)
            `INST_SB, `INST_SW, `INST_SH: begin
                reg1_raddr_o = rs1;
                reg2_raddr_o = rs2;
                reg_we_o = `WriteDisable;
                reg_waddr_o = `ZeroReg;
                op1_o = reg1_rdata_i;
                op2_o = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
            end
            default: begin
                reg1_raddr_o = `ZeroReg;
                reg2_raddr_o = `ZeroReg;
                reg_we_o = `WriteDisable;
                reg_waddr_o = `ZeroReg;
            end
        endcase
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    4.3.3、ex.v
    assign mem_raddr_index = (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 2'b11;
    assign mem_waddr_index = (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}) & 2'b11; 
    
    `INST_TYPE_L: begin
        case (funct3)
            mem_wdata_o = `ZeroWord;
            mem_waddr_o = `ZeroWord;
            mem_we = `WriteDisable;
            mem_req = `RIB_REQ;
            `INST_LB: begin
                mem_raddr_o = op1_add_op2_res;
                case (mem_raddr_index)
                    2'b00: begin
                        reg_wdata = {{24{mem_rdata_i[7]}}, mem_rdata_i[7:0]};
                    end
                    2'b01: begin
                        reg_wdata = {{24{mem_rdata_i[15]}}, mem_rdata_i[15:8]};
                    end
                    2'b10: begin
                        reg_wdata = {{24{mem_rdata_i[23]}}, mem_rdata_i[23:16]};
                    end
                    default: begin
                        reg_wdata = {{24{mem_rdata_i[31]}}, mem_rdata_i[31:24]};
                    end
                endcase
            end
            `INST_LH: begin
                mem_raddr_o = op1_add_op2_res;
                if (mem_raddr_index == 2'b0) begin
                    reg_wdata = {{16{mem_rdata_i[15]}}, mem_rdata_i[15:0]};
                end else begin
                    reg_wdata = {{16{mem_rdata_i[31]}}, mem_rdata_i[31:16]};
                end
            end
            `INST_LW: begin
                mem_raddr_o = op1_add_op2_res;
                reg_wdata = mem_rdata_i;
            end
            `INST_LBU: begin
                mem_raddr_o = op1_add_op2_res;
                case (mem_raddr_index)
                    2'b00: begin
                        reg_wdata = {24'h0, mem_rdata_i[7:0]};
                    end
                    2'b01: begin
                        reg_wdata = {24'h0, mem_rdata_i[15:8]};
                    end
                    2'b10: begin
                        reg_wdata = {24'h0, mem_rdata_i[23:16]};
                    end
                    default: begin
                        reg_wdata = {24'h0, mem_rdata_i[31:24]};
                    end
                endcase
            end
            `INST_LHU: begin
                mem_raddr_o = op1_add_op2_res;
                if (mem_raddr_index == 2'b0) begin
                    reg_wdata = {16'h0, mem_rdata_i[15:0]};
                end else begin
                    reg_wdata = {16'h0, mem_rdata_i[31:16]};
                end
            end
            default: begin
                reg_wdata = `ZeroWord;
            end
        endcase
    end
    `INST_TYPE_S: begin
        case (funct3)
            `INST_SB: begin
                reg_wdata = `ZeroWord;
                mem_we = `WriteEnable;
                mem_req = `RIB_REQ;
                mem_waddr_o = op1_add_op2_res;
                mem_raddr_o = op1_add_op2_res;
                case (mem_waddr_index)
                    2'b00: begin
                        mem_wdata_o = {mem_rdata_i[31:8], reg2_rdata_i[7:0]};
                    end
                    2'b01: begin
                        mem_wdata_o = {mem_rdata_i[31:16], reg2_rdata_i[7:0], mem_rdata_i[7:0]};
                    end
                    2'b10: begin
                        mem_wdata_o = {mem_rdata_i[31:24], reg2_rdata_i[7:0], mem_rdata_i[15:0]};
                    end
                    default: begin
                        mem_wdata_o = {reg2_rdata_i[7:0], mem_rdata_i[23:0]};
                    end
                endcase
            end
            `INST_SH: begin
                reg_wdata = `ZeroWord;
                mem_we = `WriteEnable;
                mem_req = `RIB_REQ;
                mem_waddr_o = op1_add_op2_res;
                mem_raddr_o = op1_add_op2_res;
                if (mem_waddr_index == 2'b00) begin
                    mem_wdata_o = {mem_rdata_i[31:16], reg2_rdata_i[15:0]};
                end else begin
                    mem_wdata_o = {reg2_rdata_i[15:0], mem_rdata_i[15:0]};
                end
            end
            `INST_SW: begin
                reg_wdata = `ZeroWord;
                mem_we = `WriteEnable;
                mem_req = `RIB_REQ;
                mem_waddr_o = op1_add_op2_res;
                mem_raddr_o = op1_add_op2_res;
                mem_wdata_o = reg2_rdata_i;
            end
            default: begin
                mem_wdata_o = `ZeroWord;
                mem_raddr_o = `ZeroWord;
                mem_waddr_o = `ZeroWord;
                mem_we = `WriteDisable;
                reg_wdata = `ZeroWord;
            end
        endcase
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
  • 相关阅读:
    我喜欢这种平平淡淡的生活!
    Spark与SQL之间NB的转换_withClumn,split及SubString
    Linux之IFS间隔符、C编程、Makefile工程文件、gdb调试、宏定义、预处理、assert和调试用特殊的宏
    ClickHouse 数据插入、更新与删除操作 SQL
    【数据结构笔记06】数据结构之队列的顺序表示和实现(普通队列、循环队列)
    任意文件上传
    基于bp神经网络汽车自动变速器最佳挡位判断(Matlab代码实现)
    【学术综述】-如何写出一篇好综述-写好综述要注意的问题
    前端js读取本地md或txt文件内容
    《微信小程序实战(1)· 开篇示例 》
  • 原文地址:https://blog.csdn.net/qq_42248523/article/details/128052764