├── D_to_E.v ├── E_to_M.v ├── F_to_D.v ├── M_to_W.v ├── README.md ├── alu.v ├── alu_decode.v ├── branch_check.v ├── branch_predict.v ├── cp0.v ├── datapath.v ├── defines.vh ├── div.v ├── exception.v ├── hazard.v ├── hilo.v ├── inst_ascii_decoder.v ├── jump_control.v ├── main_decode.v ├── mem_control.v ├── mux4.v ├── mycpu_top.v ├── pc_reg.v ├── regfile.v └── 硬件综合设计报告.pdf /D_to_E.v: -------------------------------------------------------------------------------- 1 | module D_to_E ( 2 | input wire clk, rst, 3 | input wire stallE, 4 | input wire flushE, 5 | input wire [31:0] pcD, 6 | input wire [31:0] rd1D, rd2D, 7 | input wire [4:0] rsD, rtD, rdD, 8 | input wire [31:0] immD, 9 | input wire [31:0] pc_plus4D, 10 | input wire [31:0] instrD, 11 | input wire [31:0] pc_branchD, 12 | input wire pred_takeD, 13 | input wire branchD, 14 | input wire jump_conflictD, 15 | input wire [4:0] saD, 16 | input wire is_in_delayslot_iD, 17 | input wire [4:0] alu_controlD, 18 | input wire jumpD, 19 | input wire [4:0] branch_judge_controlD, 20 | 21 | 22 | output reg [31:0] pcE, 23 | output reg [31:0] rd1E, rd2E, 24 | output reg [4:0] rsE, rtE, rdE, 25 | output reg [31:0] immE, 26 | output reg [31:0] pc_plus4E, 27 | output reg [31:0] instrE, 28 | output reg [31:0] pc_branchE, 29 | output reg pred_takeE, 30 | output reg branchE, 31 | output reg jump_conflictE, 32 | output reg [4:0] saE, 33 | output reg is_in_delayslot_iE, 34 | output reg [4:0] alu_controlE, 35 | output reg jumpE, 36 | output reg [4:0] branch_judge_controlE 37 | ); 38 | always @(posedge clk) begin 39 | if(rst | flushE) begin 40 | pcE <= 0 ; 41 | rd1E <= 0 ; 42 | rd2E <= 0 ; 43 | rsE <= 0 ; 44 | rtE <= 0 ; 45 | rdE <= 0 ; 46 | immE <= 0 ; 47 | pc_plus4E <= 0 ; 48 | instrE <= 0 ; 49 | pc_branchE <= 0 ; 50 | pred_takeE <= 0 ; 51 | branchE <= 0 ; 52 | jump_conflictE <= 0 ; 53 | saE <= 0 ; 54 | is_in_delayslot_iE <= 0 ; 55 | alu_controlE <= 0 ; 56 | jumpE <= 0 ; 57 | branch_judge_controlE <= 0 ; 58 | end 59 | else if(~stallE) begin 60 | pcE <= pcD ; 61 | rd1E <= rd1D ; 62 | rd2E <= rd2D ; 63 | rsE <= rsD ; 64 | rtE <= rtD ; 65 | rdE <= rdD ; 66 | immE <= immD ; 67 | pc_plus4E <= pc_plus4D ; 68 | instrE <= instrD ; 69 | pc_branchE <= pc_branchD ; 70 | pred_takeE <= pred_takeD ; 71 | branchE <= branchD ; 72 | jump_conflictE <= jump_conflictD ; 73 | saE <= saD ; 74 | is_in_delayslot_iE <= is_in_delayslot_iD ; 75 | alu_controlE <= alu_controlD ; 76 | jumpE <= jumpD ; 77 | branch_judge_controlE <= branch_judge_controlD; 78 | end 79 | end 80 | endmodule 81 | -------------------------------------------------------------------------------- /E_to_M.v: -------------------------------------------------------------------------------- 1 | module E_to_M ( 2 | input wire clk, rst,flushM, 3 | input wire stallM, 4 | input wire [31:0] pcE, 5 | input wire [63:0] alu_outE, 6 | input wire [31:0] rt_valueE, 7 | input wire [4:0] reg_writeE, 8 | input wire [31:0] instrE, 9 | input wire branchE, 10 | input wire pred_takeE, 11 | input wire [31:0] pc_branchE, 12 | input wire overflowE, 13 | input wire is_in_delayslot_iE, 14 | input wire [4:0] rdE, 15 | input wire actual_takeE, 16 | 17 | 18 | output reg [31:0] pcM, 19 | output reg [31:0] alu_outM, 20 | output reg [31:0] rt_valueM, 21 | output reg [4:0] reg_writeM, 22 | output reg [31:0] instrM, 23 | output reg branchM, 24 | output reg pred_takeM, 25 | output reg [31:0] pc_branchM, 26 | output reg overflowM, 27 | output reg is_in_delayslot_iM, 28 | output reg [4:0] rdM, 29 | output reg actual_takeM 30 | ); 31 | always @(posedge clk) begin 32 | if(rst | flushM) begin 33 | pcM <= 0; 34 | alu_outM <= 0; 35 | rt_valueM <= 0; 36 | reg_writeM <= 0; 37 | instrM <= 0; 38 | branchM <= 0; 39 | pred_takeM <= 0; 40 | pc_branchM <= 0; 41 | overflowM <= 0; 42 | is_in_delayslot_iM <= 0; 43 | rdM <= 0; 44 | actual_takeM <= 0; 45 | end 46 | else if(~stallM) begin 47 | pcM <= pcE ; 48 | alu_outM <= alu_outE[31:0] ; 49 | rt_valueM <= rt_valueE ; 50 | reg_writeM <= reg_writeE ; 51 | instrM <= instrE ; 52 | branchM <= branchE ; 53 | pred_takeM <= pred_takeE ; 54 | pc_branchM <= pc_branchE ; 55 | overflowM <= overflowE ; 56 | is_in_delayslot_iM <= is_in_delayslot_iE ; 57 | rdM <= rdE ; 58 | actual_takeM <= actual_takeE ; 59 | end 60 | end 61 | endmodule -------------------------------------------------------------------------------- /F_to_D.v: -------------------------------------------------------------------------------- 1 | 2 | module F_to_D( 3 | input wire clk, rst, 4 | input wire flushD, 5 | input wire stallD, 6 | input wire [31:0] pcF, 7 | input wire [31:0] pc_plus4F, 8 | 9 | input wire [31:0] instrF, 10 | input wire [31:0] F_change, 11 | 12 | 13 | output reg [31:0] pcD, 14 | output reg [31:0] pc_plus4D, 15 | output reg [31:0] instrD, 16 | output reg [31:0] is_in_delayslot_iD 17 | ); 18 | 19 | always @(posedge clk) begin 20 | if(rst | flushD) begin 21 | pcD <= 0 ; 22 | pc_plus4D <= 0 ; 23 | instrD <= 0 ; 24 | is_in_delayslot_iD <= 0 ; 25 | end 26 | else if(~stallD) begin 27 | pcD <= pcF ; 28 | pc_plus4D <= pc_plus4F ; 29 | instrD <= instrF ; 30 | is_in_delayslot_iD <= F_change ; 31 | end 32 | end 33 | endmodule 34 | -------------------------------------------------------------------------------- /M_to_W.v: -------------------------------------------------------------------------------- 1 | module M_to_W ( 2 | input wire clk, rst, 3 | input wire stallW, 4 | input wire [31:0] pcM, 5 | input wire [31:0] alu_outM, 6 | input wire [4:0] reg_writeM, 7 | input wire reg_write_enM, 8 | input wire [31:0] mem_rdataM, 9 | input wire [31:0] resultM, 10 | 11 | 12 | output reg [31:0] pcW, 13 | output reg [31:0] alu_outW, 14 | output reg [4:0] reg_writeW, 15 | output reg reg_write_enW, 16 | output reg [31:0] mem_rdataW, 17 | output reg [31:0] resultW 18 | ); 19 | always @(posedge clk) begin 20 | if(rst) begin 21 | pcW <= 0; 22 | alu_outW <= 0; 23 | reg_writeW <= 0; 24 | reg_write_enW <= 0; 25 | mem_rdataW <= 0; 26 | resultW <= 0; 27 | end 28 | else if(~stallW) begin 29 | pcW <= pcM; 30 | alu_outW <= alu_outM; 31 | reg_writeW <= reg_writeM; 32 | reg_write_enW <= reg_write_enM; 33 | mem_rdataW <= mem_rdataM; 34 | resultW <= resultM; 35 | end 36 | end 37 | endmodule -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpu20220108 2 | MIPS 57条指令五级流水线cpu (verilog实现+详细注释) 3 | 4 | 2022年cqu硬件综合设计代码\ 5 | 实现了局部分支预测\ 6 | 实现了52条普通指令+2条自陷指令+3条特权指令\ 7 | pc初值 0xbfc0_0000\ 8 | 例外入口 0xbfc0_0380\ 9 | -------------------------------------------------------------------------------- /alu.v: -------------------------------------------------------------------------------- 1 | `include "defines.vh" 2 | module ALU ( 3 | input wire clk, rst, 4 | input wire flushE, 5 | input wire [31:0] src_aE, src_bE, //操作数 6 | input wire [4:0] alu_controlE, //alu 控制信号 7 | input wire [4:0] sa, //sa值 8 | input wire [63:0] hilo, //hilo值 9 | 10 | output wire div_stallE, 11 | output wire [63:0] alu_outE, //alu输出 12 | output wire overflowE//算数溢出 13 | ); 14 | wire [63:0] alu_out_div; //乘除法结果 15 | reg [63:0] alu_out_mul; 16 | wire mul_sign; //乘法符号 17 | wire mul_valid; // 为乘法 18 | wire div_sign; //除法符号 19 | wire div_vaild; //为除法 20 | wire ready; 21 | reg [31:0] alu_out_simple; // 普通运算结果 22 | reg carry_bit; //进位 判断溢出 23 | //写硬综好累:( 24 | 25 | //乘法信号 26 | assign mul_sign = (alu_controlE == `ALU_SIGNED_MULT); 27 | assign mul_valid = (alu_controlE == `ALU_SIGNED_MULT) | (alu_controlE == `ALU_UNSIGNED_MULT); 28 | 29 | //aluout 30 | assign alu_outE = ({64{div_vaild}} & alu_out_div) 31 | | ({64{mul_valid}} & alu_out_mul) 32 | | ({64{~mul_valid & ~div_vaild}} & {32'b0, alu_out_simple}) 33 | | ({64{(alu_controlE == `ALU_MTHI)}} & {src_aE, hilo[31:0]}) // 若为mthi/mtlo 直接取Hilo的低32位和高32位 34 | | ({64{(alu_controlE == `ALU_MTLO)}} & {hilo[63:32], src_aE}); 35 | // 为加减 且溢出位与最高位不等时 算数溢出 36 | assign overflowE = (alu_controlE==`ALU_ADD || alu_controlE==`ALU_SUB) & (carry_bit ^ alu_out_simple[31]); 37 | 38 | // 算数操作及对应运算 39 | always @(*) begin 40 | carry_bit = 0; //溢出位取0 41 | case(alu_controlE) 42 | `ALU_AND: alu_out_simple = src_aE & src_bE; 43 | `ALU_OR: alu_out_simple = src_aE | src_bE; 44 | `ALU_NOR: alu_out_simple =~(src_aE | src_bE); 45 | `ALU_XOR: alu_out_simple = src_aE ^ src_bE; 46 | 47 | `ALU_ADD: {carry_bit, alu_out_simple} = {src_aE[31], src_aE} + {src_bE[31], src_bE}; 48 | `ALU_ADDU: alu_out_simple = src_aE + src_bE; 49 | `ALU_SUB: {carry_bit, alu_out_simple} = {src_aE[31], src_aE} - {src_bE[31], src_bE}; 50 | `ALU_SUBU: alu_out_simple = src_aE - src_bE; 51 | 52 | `ALU_SIGNED_MULT:alu_out_mul = $signed(src_aE) * $signed(src_bE); //乘法 53 | `ALU_UNSIGNED_MULT:alu_out_mul = src_aE * src_bE; 54 | 55 | `ALU_SLT: alu_out_simple = $signed(src_aE) < $signed(src_bE); //有符号比较 56 | `ALU_SLTU: alu_out_simple = src_aE < src_bE; //无符号比较 57 | 58 | `ALU_SLL: alu_out_simple = src_bE << src_aE[4:0]; //移位src a 59 | `ALU_SRL: alu_out_simple = src_bE >> src_aE[4:0]; 60 | `ALU_SRA: alu_out_simple = $signed(src_bE) >>> src_aE[4:0]; 61 | 62 | `ALU_SLL_SA: alu_out_simple = src_bE << sa; //移位sa 63 | `ALU_SRL_SA: alu_out_simple = src_bE >> sa; 64 | `ALU_SRA_SA: alu_out_simple = $signed(src_bE) >>> sa; 65 | 66 | `ALU_LUI: alu_out_simple = {src_bE[15:0], 16'b0}; //取高16位 67 | `ALU_DONOTHING: alu_out_simple = src_aE; // do nothing 68 | 69 | default: alu_out_simple = 32'b0; 70 | endcase 71 | end 72 | 73 | // 除法 74 | assign div_sign = (alu_controlE == `ALU_SIGNED_DIV); 75 | assign div_vaild = (alu_controlE == `ALU_SIGNED_DIV || alu_controlE == `ALU_UNSIGNED_DIV); 76 | 77 | div div( 78 | .clk(~clk), 79 | .rst(rst), 80 | .flush(flushE), 81 | .a(src_aE), //divident 82 | .b(src_bE), //divisor 83 | .valid(div_vaild), 84 | .sign(div_sign), //1 signed 85 | 86 | // .ready(ready), 87 | .div_stall(div_stallE), 88 | .result(alu_out_div) 89 | ); 90 | 91 | 92 | 93 | 94 | endmodule -------------------------------------------------------------------------------- /alu_decode.v: -------------------------------------------------------------------------------- 1 | `include "defines.vh" 2 | 3 | module alu_decode( 4 | input wire [31:0] instrD, 5 | 6 | output reg [4:0] alu_controlD, 7 | output reg [4:0] branch_judge_controlD 8 | ); 9 | 10 | wire [5:0] opcode; 11 | wire [4:0] rs, rt; 12 | wire [5:0] funct; 13 | 14 | assign opcode = instrD[31:26]; 15 | assign rs = instrD[25:21]; 16 | assign rt = instrD[20:16]; 17 | assign funct = instrD[5:0]; 18 | 19 | always @* begin 20 | case(opcode) 21 | // R型指令 22 | `EXE_R_TYPE: 23 | case(funct) 24 | //算数和逻辑运算 25 | `EXE_AND: alu_controlD <= `ALU_AND; //1 26 | `EXE_OR: alu_controlD <= `ALU_OR; 27 | `EXE_XOR: alu_controlD <= `ALU_XOR; 28 | `EXE_NOR: alu_controlD <= `ALU_NOR; 29 | 30 | `EXE_ADD: alu_controlD <= `ALU_ADD; //4 31 | `EXE_SUB: alu_controlD <= `ALU_SUB; 32 | `EXE_ADDU: alu_controlD <= `ALU_ADDU; 33 | `EXE_SUBU: alu_controlD <= `ALU_SUBU; 34 | `EXE_SLT: alu_controlD <= `ALU_SLT; 35 | `EXE_SLTU: alu_controlD <= `ALU_SLTU; 36 | 37 | //div and mul 38 | `EXE_DIV: alu_controlD <= `ALU_SIGNED_DIV; 39 | `EXE_DIVU: alu_controlD <= `ALU_UNSIGNED_DIV; 40 | `EXE_MULT: alu_controlD <= `ALU_SIGNED_MULT; 41 | `EXE_MULTU: alu_controlD <= `ALU_UNSIGNED_MULT; 42 | 43 | //移位指令 44 | `EXE_SLL: alu_controlD <= `ALU_SLL_SA; //2 45 | `EXE_SRL: alu_controlD <= `ALU_SRL_SA; 46 | `EXE_SRA: alu_controlD <= `ALU_SRA_SA; 47 | `EXE_SLLV: alu_controlD <= `ALU_SLL; 48 | `EXE_SRLV: alu_controlD <= `ALU_SRL; 49 | `EXE_SRAV: alu_controlD <= `ALU_SRA; 50 | 51 | //hilo 52 | `EXE_MTHI: alu_controlD <= `ALU_MTHI; 53 | `EXE_MTLO: alu_controlD <= `ALU_MTLO; 54 | default: alu_controlD <= `ALU_DONOTHING; 55 | endcase 56 | //I type 57 | `EXE_ADDI: alu_controlD <= `ALU_ADD; 58 | `EXE_ADDIU: alu_controlD <= `ALU_ADDU; 59 | `EXE_SLTI: alu_controlD <= `ALU_SLT; 60 | `EXE_SLTIU: alu_controlD <= `ALU_SLTU; 61 | `EXE_ANDI: alu_controlD <= `ALU_AND; 62 | `EXE_XORI: alu_controlD <= `ALU_XOR; 63 | `EXE_LUI: alu_controlD <= `ALU_LUI; 64 | `EXE_ORI: alu_controlD <= `ALU_OR; 65 | //memory 66 | `EXE_LW, `EXE_LB, `EXE_LBU, `EXE_LH, `EXE_LHU, `EXE_SW, `EXE_SB, `EXE_SH: 67 | alu_controlD <= `ALU_ADDU; 68 | default: 69 | alu_controlD <= `ALU_DONOTHING; 70 | endcase 71 | end 72 | 73 | // branch_judge控制信号 74 | // 各种branch指令相关的alu操作 75 | always @(*) begin 76 | case(opcode) 77 | `EXE_BEQ: 78 | branch_judge_controlD <= `ALU_EQ; 79 | `EXE_BGTZ: 80 | branch_judge_controlD <= `ALU_GTZ; 81 | `EXE_BLEZ: 82 | branch_judge_controlD <= `ALU_LEZ; 83 | `EXE_BNE: 84 | branch_judge_controlD <= `ALU_NEQ; 85 | `EXE_BRANCHS: //bltz, bltzal, bgez, bgezal 86 | case(rt) 87 | `EXE_BLTZ, `EXE_BLTZAL: 88 | branch_judge_controlD <= `ALU_LTZ; 89 | `EXE_BGEZ, `EXE_BGEZAL: 90 | branch_judge_controlD <= `ALU_GEZ; 91 | default: 92 | branch_judge_controlD <= `ALU_DONOTHING; 93 | endcase 94 | default: 95 | branch_judge_controlD <= `ALU_DONOTHING; 96 | endcase 97 | end 98 | endmodule 99 | 100 | -------------------------------------------------------------------------------- /branch_check.v: -------------------------------------------------------------------------------- 1 | 2 | module branch_check ( 3 | input wire [4:0] branch_judge_controlE, 4 | input wire [31:0] src_aE, src_bE, 5 | 6 | output reg actual_takeE 7 | ); 8 | always @(*) begin 9 | // 根据对应操作计算 10 | case(branch_judge_controlE) 11 | `ALU_EQ: actual_takeE = ~(|(src_aE ^ src_bE)); 12 | `ALU_NEQ: actual_takeE = |(src_aE ^ src_bE); 13 | `ALU_GTZ: actual_takeE = ~src_aE[31] & (|src_aE); 14 | `ALU_GEZ: actual_takeE = ~src_aE[31]; 15 | `ALU_LTZ: actual_takeE = src_aE[31]; 16 | `ALU_LEZ: actual_takeE = src_aE[31] | ~(|src_aE); 17 | default: 18 | actual_takeE = 1'b0; 19 | endcase 20 | end 21 | endmodule -------------------------------------------------------------------------------- /branch_predict.v: -------------------------------------------------------------------------------- 1 | `include "defines.vh" 2 | module branch_predict ( 3 | input wire clk, rst, 4 | 5 | input wire flushD, 6 | input wire stallD, 7 | 8 | input wire [31:0] instrD, 9 | input wire [31:0] immD, 10 | 11 | input wire [31:0] pcF, 12 | input wire [31:0] pcM, 13 | input wire branchM, 14 | input wire actual_takeM, 15 | 16 | output wire branchD, 17 | output wire branchL_D, 18 | output wire pred_takeD 19 | ); 20 | wire pred_takeF; 21 | reg pred_takeF_r; 22 | wire [5:0] op_code, funct; 23 | wire [4:0] rs, rt; 24 | assign op_code = instrD[31:26]; 25 | assign rs = instrD[25:21]; 26 | assign rt = instrD[20:16]; 27 | assign funct = instrD[5:0]; 28 | assign branchD = ( !(op_code ^ 6'b000001) & (!(instrD[19:17] ^ 3'b000) | !(instrD[19:17] ^ 3'b001)) ) //6'b000001 = EXE_REGIMM 29 | | !(op_code[5:2] ^ 4'b0001); //4'b0001 -> beq, bgtz, blez, bne 30 | // 3'b000 -> BLTZ BLTZAL BGEZAL BGEZ 31 | // 3'b001 -> BGEZALL BGEZL BLTZALL BLTZL 32 | assign branchL_D = ( !(op_code ^ 6'b000001) & !(instrD[19:17] ^ 3'b001) ) | 33 | !(op_code[5:2] ^ 4'b0101); //beql, bgtzl, blezl, bnel 34 | 35 | parameter Strongly_not_taken = 2'b00, Weakly_not_taken = 2'b01, Weakly_taken = 2'b11, Strongly_taken = 2'b10; 36 | parameter PHT_DEPTH = 6; 37 | parameter BHT_DEPTH = 10; 38 | 39 | reg [5:0] BHT [(1< rd, 01-> rt, 10-> 写$ra 60 | wire [4 :0] alu_controlE; //alu控制信号 61 | 62 | wire [31:0] src_aE, src_bE; //alu输入(操作数 63 | wire [63:0] alu_outE; //alu输出 64 | wire alu_imm_selE; //alu srcb选择 0->rd2E, 1->immE 65 | wire [4 :0] reg_writeE; //写寄存器号 66 | wire branchE; //分支信号 67 | wire [31:0] pc_branchE; //分支跳转pc 68 | 69 | wire [31:0] instrE; 70 | wire [31:0] pc_jumpE; //jump pc 71 | wire jump_conflictE; //jump冲突 72 | wire reg_write_enE; //写寄存器信号 73 | wire alu_stallE; //aluzant 74 | wire [31:0] rs_valueE, rt_valueE; //rs rt寄存器的值 75 | 76 | wire flush_jump_confilctE; //jump冲突 77 | wire jumpE; //jump信号 78 | wire actual_takeE; //分支预测 实际结果 79 | wire [4 :0] branch_judge_controlE; //分支判断控制 80 | 81 | // 异常处理信号 82 | wire is_in_delayslot_iE; //是否处于延迟槽 83 | wire overflowE; //溢出 84 | 85 | // MEM阶段 86 | wire [31:0] pcM; // pc 87 | wire [31:0] alu_outM; //alu输出 88 | wire [4:0] reg_writeM; //写寄存器号 89 | wire [31:0] instrM; //指令 90 | wire mem_read_enM; //读内存 91 | wire mem_write_enM; //写内存 92 | wire reg_write_enM; //寄存器写 93 | wire mem_to_regM; //写回寄存器选择信号 94 | wire [31:0] resultM; // mem out 95 | wire actual_takeM; //分支预测 真实结果 96 | wire pre_right; // 预测正确 97 | wire pred_takeM; // 预测 98 | wire branchM; // 分支信号 99 | wire [31:0] pc_branchM; //分支跳转地址 100 | 101 | wire [31:0] mem_ctrl_rdataM; 102 | 103 | wire hilo_wenE; //hilo写使能 104 | wire [63:0] hilo_oM; //hilo输出 105 | wire hilo_to_regM; 106 | 107 | wire [4:0] rdM; 108 | wire [31:0] rt_valueM; 109 | 110 | wire is_mfcM; 111 | 112 | //异常处理信号 exception 113 | wire riM; //指令不存在 114 | wire breakM; //break指令 115 | wire syscallM; //syscall指令 116 | wire eretM; //eretM指令 117 | wire overflowM; //算数溢出 118 | wire addrErrorLwM, addrErrorSwM; //访存指令异常 119 | wire pcErrorM; //pc异常 120 | 121 | // cp0 122 | wire [31:0] except_typeM; // 异常类型 123 | wire [31:0] cp0_statusM; //status值 124 | wire [31:0] cp0_causeM; //cause值 125 | wire [31:0] cp0_epcM; //epc值 126 | wire flush_exceptionM; // 发生异常时需要刷新流水线 127 | wire [31:0] pc_exceptionM; //异常处理的地址0xbfc0_0380,若为eret指令 则为返回地址 128 | wire pc_trapM; // 发生异常时pc特殊处理 129 | wire [31:0] badvaddrM; 130 | wire is_in_delayslot_iM; 131 | wire cp0_to_regM; 132 | wire cp0_wenM; 133 | 134 | //Write back 135 | wire [31:0] pcW; //pc 136 | wire reg_write_enW; //写寄存器 137 | wire [31:0] alu_outW; //alu输出 138 | wire [4 :0] reg_writeW; //写寄存器号 139 | wire [31:0] resultW; // 写入寄存器的result 140 | 141 | wire [31:0] cp0_statusW, cp0_causeW, cp0_epcW, cp0_data_oW; 142 | 143 | // stall 144 | wire stallF, stallD, stallE, stallM, stallW; //流水线暂停 145 | wire flushF, flushD, flushE, flushM, flushW; //流水线刷新 146 | wire [1:0] forward_aE, forward_bE; //数据前推片选信号 147 | 148 | //debug signal 149 | assign debug_wb_pc = pcM; 150 | assign debug_wb_rf_wen = {4{reg_write_enM & ~d_cache_stall & ~flush_exceptionM }};// 151 | assign debug_wb_rf_wnum = reg_writeM; 152 | assign debug_wb_rf_wdata = resultM; 153 | 154 | assign inst_addrF = pcF; //F阶段地址 155 | assign inst_enF = ~stallF & ~pc_errorF & ~flush_pred_failedM; // 指令读使能:一切正常 156 | assign pc_errorF = pcF[1:0] == 2'b0 ? 1'b0 : 1'b1; //pc最后两位不是0 则pc错误 157 | 158 | 159 | // main decode 160 | main_decode main_decode0( 161 | .clk(clk), .rst(rst), 162 | .instrD(instrD), 163 | 164 | .stallE(stallE), .stallM(stallM), .stallW(stallW), 165 | .flushE(flushE), .flushM(flushM), .flushW(flushW), 166 | //ID 167 | .sign_extD(sign_extD), 168 | //EX 169 | .reg_dstE(reg_dstE), 170 | .alu_imm_selE(alu_imm_selE), 171 | .reg_write_enE(reg_write_enE), 172 | .hilo_wenE(hilo_wenE), 173 | //MEM 174 | .mem_read_enM(mem_read_enM), 175 | .mem_write_enM(mem_write_enM), 176 | .reg_write_enM(reg_write_enM), 177 | .mem_to_regM(mem_to_regM), 178 | .hilo_to_regM(hilo_to_regM), 179 | .riM(riM), 180 | .breakM(breakM), 181 | .syscallM(syscallM), 182 | .eretM(eretM), 183 | .cp0_wenM(cp0_wenM), 184 | .cp0_to_regM(cp0_to_regM), 185 | .is_mfcM(is_mfcM) 186 | ); 187 | 188 | 189 | // alu decode 190 | alu_decode alu_decode0( 191 | .instrD(instrD), 192 | 193 | .alu_controlD(alu_controlD), 194 | .branch_judge_controlD(branch_judge_controlD) 195 | ); 196 | 197 | // hazard 冒险控制 198 | hazard hazard0( 199 | .d_cache_stall(d_cache_stall), 200 | .alu_stallE(alu_stallE), 201 | 202 | .flush_jump_confilctE (flush_jump_confilctE), 203 | .flush_pred_failedM (flush_pred_failedM), 204 | .flush_exceptionM (flush_exceptionM), 205 | 206 | .rsE(rsE), 207 | .rtE(rtE), 208 | .reg_write_enM(reg_write_enM), 209 | .reg_write_enW(reg_write_enW), 210 | .reg_writeM(reg_writeM), 211 | .reg_writeW(reg_writeW), 212 | .mem_read_enM(mem_read_enM), 213 | 214 | .stallF(stallF), .stallD(stallD), .stallE(stallE), .stallM(stallM), .stallW(stallW), 215 | .flushF(flushF), .flushD(flushD), .flushE(flushE), .flushM(flushM), .flushW(flushW), 216 | .forward_aE(forward_aE), .forward_bE(forward_bE) 217 | ); 218 | 219 | 220 | // Instruction Fetch 221 | // pc+4 222 | assign pc_plus4F = pcF + 4; 223 | 224 | // pc reg 225 | pc_reg pc_reg0( 226 | .clk(clk), 227 | .rst(rst), 228 | .stallF(stallF), 229 | .branchD(branchD), 230 | .branchM(branchM), 231 | .pre_right(pre_right), 232 | .actual_takeM(actual_takeM), 233 | .pred_takeD(pred_takeD), 234 | .pc_trapM(pc_trapM), 235 | .jumpD(jumpD), 236 | .jump_conflictD(jump_conflictD), 237 | .jump_conflictE(jump_conflictE), 238 | 239 | .pc_exceptionM(pc_exceptionM), 240 | .pc_plus4E(pc_plus4E), 241 | .pc_branchM(pc_branchM), 242 | .pc_jumpE(pc_jumpE), 243 | .pc_jumpD(pc_jumpD), 244 | .pc_branchD(pc_branchD), 245 | .pc_plus4F(pc_plus4F), 246 | 247 | .pc(pcF) 248 | ); 249 | 250 | 251 | assign instrF_4 = ({32{~(|(pcF[1:0] ^ 2'b00))}} & instrF); //低2位一定为00 不为0则inst清0 252 | assign F_change = branchD | jumpD; //F阶段得到此时d阶段是否为跳转指令 253 | 254 | // Decode 255 | assign rsD = instrD[25:21]; 256 | assign rtD = instrD[20:16]; 257 | assign rdD = instrD[15:11]; 258 | assign saD = instrD[10:6]; //sra srl 指令用到sa立即数 259 | 260 | //F->D pipeline 261 | F_to_D F_to_D( 262 | .clk(clk), .rst(rst), 263 | .stallD(stallD), 264 | .flushD(flushD), 265 | 266 | .pcF(pcF), 267 | .pc_plus4F(pc_plus4F), 268 | .instrF(instrF_4), 269 | .F_change(F_change), //上一条指令是跳转 270 | 271 | .pcD(pcD), 272 | .pc_plus4D(pc_plus4D), 273 | .instrD(instrD), 274 | .is_in_delayslot_iD(is_in_delayslot_iD) //处于延迟槽 275 | ); 276 | 277 | //use for debug 278 | // 指令转化为ascii码 279 | wire [44:0] ascii; 280 | inst_ascii_decoder inst_ascii_decoder0( 281 | .instr(instrD), 282 | .ascii(ascii) 283 | ); 284 | // 立即数扩展 1-有符号扩展 0-无符号扩展 285 | assign immD = sign_extD ? {{16{instrD[15]}}, instrD[15:0]}: 286 | {16'b0, instrD[15:0]}; 287 | 288 | 289 | // 分支跳转 立即数左移2 + pc+4 290 | assign pc_branchD = {immD[29:0], 2'b00} + pc_plus4D; 291 | 292 | //寄存器堆 293 | regfile regfile( 294 | .clk(clk), 295 | .stallW(stallW), 296 | .we3(reg_write_enM & ~flush_exceptionM),// 297 | .ra1(rsD), .ra2(rtD), .wa3(reg_writeM), 298 | .wd3(resultM), 299 | 300 | .rd1(rd1D), .rd2(rd2D) 301 | ); 302 | 303 | //分支预测器 304 | branch_predict branch_predict0( 305 | .clk(clk), .rst(rst), 306 | 307 | .flushD(flushD), 308 | .stallD(stallD), 309 | 310 | .instrD(instrD), 311 | .immD(immD), 312 | .pcF(pcF), 313 | .pcM(pcM), 314 | .branchM(branchM), 315 | .actual_takeM(actual_takeM), 316 | 317 | .branchD(branchD), 318 | .branchL_D(), 319 | .pred_takeD(pred_takeD) 320 | ); 321 | 322 | // jump指令控制 323 | jump_control jump_control( 324 | .instrD(instrD), 325 | .pc_plus4D(pc_plus4D), 326 | .rd1D(rd1D), 327 | .reg_write_enE(reg_write_enE), .reg_write_enM(reg_write_enM), 328 | .reg_writeE(reg_writeE), .reg_writeM(reg_writeM), 329 | 330 | .jumpD(jumpD), //是jump类指令(j, jr) 331 | .jump_conflictD(jump_conflictD), //jr rs寄存器发生冲突 332 | .pc_jumpD(pc_jumpD) //D阶段最终跳转地址 333 | ); 334 | 335 | // D->E pipeline 336 | D_to_E D_to_E( 337 | .clk(clk), 338 | .rst(rst), 339 | .stallE(stallE), 340 | .flushE(flushE), 341 | 342 | .pcD(pcD), 343 | .rsD(rsD), .rd1D(rd1D), .rd2D(rd2D), 344 | .rtD(rtD), .rdD(rdD), 345 | .immD(immD), 346 | .pc_plus4D(pc_plus4D), 347 | .instrD(instrD), 348 | .branchD(branchD), 349 | .pred_takeD(pred_takeD), 350 | .pc_branchD(pc_branchD), 351 | .jump_conflictD(jump_conflictD), 352 | .is_in_delayslot_iD(is_in_delayslot_iD), 353 | .saD(saD), 354 | .alu_controlD(alu_controlD), 355 | .jumpD(jumpD), 356 | .branch_judge_controlD(branch_judge_controlD), 357 | 358 | .pcE(pcE), 359 | .rsE(rsE), .rd1E(rd1E), .rd2E(rd2E), 360 | .rtE(rtE), .rdE(rdE), 361 | .immE(immE), 362 | .pc_plus4E(pc_plus4E), 363 | .instrE(instrE), 364 | .branchE(branchE), 365 | .pred_takeE(pred_takeE), 366 | .pc_branchE(pc_branchE), 367 | .jump_conflictE(jump_conflictE), 368 | .is_in_delayslot_iE(is_in_delayslot_iE), 369 | .saE(saE), 370 | .alu_controlE(alu_controlE), 371 | .jumpE(jumpE), 372 | .branch_judge_controlE(branch_judge_controlE) 373 | ); 374 | 375 | 376 | //ALU 377 | ALU alu0( 378 | .clk(clk), 379 | .rst(rst), 380 | .flushE(flushE), 381 | .src_aE(src_aE), .src_bE(src_bE), 382 | .alu_controlE(alu_controlE), 383 | .sa(saE), 384 | .hilo(hilo_oM), 385 | 386 | .div_stallE(alu_stallE), 387 | .alu_outE(alu_outE), 388 | .overflowE(overflowE) 389 | ); 390 | 391 | mux4 #(5) mux4_regdst( 392 | rdE, // 393 | rtE, // 394 | 5'd31, // 395 | 5'b0, // 396 | reg_dstE, // 397 | reg_writeE //选择writeback寄存器 398 | ); 399 | 400 | mux4 #(32) mux4_forward_aE( 401 | rd1E, // 402 | resultM, // 403 | resultW, // 404 | pc_plus4D, // 执行jalr,jal指令;写入到$ra寄存器的数据(跳转指令对应延迟槽指令的下一条指令的地址即PC+8) //可以保证延迟槽指令不会被flush,故plush_4D存在 405 | {2{jumpE | branchE}} | forward_aE, // 当ex阶段是jal或者jalr指令,或者bxxzal时,jumpE | branchE== 1;选择pc_plus4D;其他时候为数据前推 406 | 407 | src_aE 408 | ); 409 | mux4 #(32) mux4_forward_bE( 410 | rd2E, // 411 | resultM, // 412 | resultW, // 413 | immE, //立即数 414 | {2{alu_imm_selE}} | forward_bE, //main_decoder产生alu_imm_selE信号,表示alu第二个操作数为立即数 415 | 416 | src_bE 417 | ); 418 | 419 | mux4 #(32) mux4_rs_valueE(rd1E, resultM, resultW, 32'b0, forward_aE, rs_valueE); //数据前推后的rs寄存器的值 420 | mux4 #(32) mux4_rt_valueE(rd2E, resultM, resultW, 32'b0, forward_bE, rt_valueE); //数据前推后的rt寄存器的值 421 | 422 | //计算branch结果 得到真实是否跳转 423 | branch_check branch_check( 424 | .branch_judge_controlE(branch_judge_controlE), 425 | .src_aE(rs_valueE), 426 | .src_bE(rt_valueE), 427 | .actual_takeE(actual_takeE) 428 | ); 429 | 430 | assign pc_jumpE = rs_valueE; //jr指令 跳转到rs的值 431 | assign flush_jump_confilctE = jump_conflictE; 432 | 433 | // E->M pipeline 434 | E_to_M E_to_M( 435 | .clk(clk), 436 | .rst(rst), 437 | .stallM(stallM), 438 | .flushM(flushM), 439 | 440 | .pcE(pcE), 441 | .alu_outE(alu_outE), 442 | .rt_valueE(rt_valueE), 443 | .reg_writeE(reg_writeE), 444 | .instrE(instrE), 445 | .branchE(branchE), 446 | .pred_takeE(pred_takeE), 447 | .pc_branchE(pc_branchE), 448 | .overflowE(overflowE), 449 | .is_in_delayslot_iE(is_in_delayslot_iE), 450 | .rdE(rdE), 451 | .actual_takeE(actual_takeE), 452 | 453 | .pcM(pcM), 454 | .alu_outM(alu_outM), 455 | .rt_valueM(rt_valueM), 456 | .reg_writeM(reg_writeM), 457 | .instrM(instrM), 458 | .branchM(branchM), 459 | .pred_takeM(pred_takeM), 460 | .pc_branchM(pc_branchM), 461 | .overflowM(overflowM), 462 | .is_in_delayslot_iM(is_in_delayslot_iM), 463 | .rdM(rdM), 464 | .actual_takeM(actual_takeM) 465 | ); 466 | 467 | assign mem_addrM = alu_outM; 468 | assign mem_enM = (mem_read_enM | mem_write_enM) ; //读或者写 469 | 470 | // mem读写控制 471 | mem_control mem_control( 472 | .instrM(instrM), 473 | .addr(alu_outM), 474 | 475 | .data_wdataM(rt_valueM), //原始的wdata 476 | .mem_wdataM(mem_wdataM), //新的wdata 477 | .mem_wenM(mem_wenM), 478 | 479 | .mem_rdataM(mem_rdataM), 480 | .data_rdataM(mem_ctrl_rdataM), 481 | 482 | .addr_error_sw(addrErrorSwM), 483 | .addr_error_lw(addrErrorLwM) 484 | ); 485 | 486 | // hilo寄存器 487 | hilo hilo( 488 | .clk(clk), 489 | .rst(rst), 490 | .instrM(instrM), // 用于识别mfhi,mflo,决定输出; 491 | .we(hilo_wenE & ~flush_exceptionM), // both write lo and hi 492 | .hilo_in(alu_outE), 493 | 494 | .hilo_out(hilo_oM) 495 | ); 496 | 497 | assign pcErrorM = |(pcM[1:0] ^ 2'b00); //后两位不是00 498 | 499 | //异常处理 500 | exception exception( 501 | .rst(rst), 502 | .ext_int(ext_int), 503 | .ri(riM), .break(breakM), .syscall(syscallM), .overflow(overflowM), .addrErrorSw(addrErrorSwM), .addrErrorLw(addrErrorLwM), .pcError(pcErrorM), .eretM(eretM), 504 | .cp0_status(cp0_statusW), .cp0_cause(cp0_causeW), .cp0_epc(cp0_epcW), 505 | .pcM(pcM), 506 | .alu_outM(alu_outM), 507 | 508 | .except_type(except_typeM), 509 | .flush_exception(flush_exceptionM), 510 | .pc_exception(pc_exceptionM), 511 | .pc_trap(pc_trapM), 512 | .badvaddrM(badvaddrM) 513 | ); 514 | 515 | // cp0寄存器 516 | cp0 cp0( 517 | .clk(clk), 518 | .rst(rst), 519 | 520 | .en(flush_exceptionM), 521 | .we_i(cp0_wenM), 522 | 523 | .waddr_i(rdM), 524 | .raddr_i(rdM), 525 | .data_i(rt_valueM), 526 | .data_o(cp0_data_oW), 527 | 528 | .except_type_i(except_typeM), 529 | .current_inst_addr_i(pcM), 530 | .is_in_delayslot_i(is_in_delayslot_iM), 531 | .badvaddr_i(badvaddrM), 532 | 533 | .status_o(cp0_statusW), 534 | .cause_o(cp0_causeW), 535 | .epc_o(cp0_epcW) 536 | ); 537 | 538 | mux4 #(32) mux4_mem_to_reg(alu_outM, mem_ctrl_rdataM, hilo_oM, cp0_data_oW, {hilo_to_regM, mem_to_regM} | {2{is_mfcM}}, resultM); 539 | 540 | //分支预测结果 541 | assign pre_right = ~(pred_takeM ^ actual_takeM); 542 | assign flush_pred_failedM = ~pre_right; 543 | 544 | // M->W pipeline 545 | M_to_W M_to_W( 546 | .clk(clk), 547 | .rst(rst), 548 | .stallW(stallW), 549 | 550 | .pcM(pcM), 551 | .alu_outM(alu_outM), 552 | .reg_writeM(reg_writeM), 553 | .reg_write_enM(reg_write_enM), 554 | .resultM(resultM), 555 | 556 | 557 | .pcW(pcW), 558 | .alu_outW(alu_outW), 559 | .reg_writeW(reg_writeW), 560 | .reg_write_enW(reg_write_enW), 561 | .resultW(resultW) 562 | ); 563 | 564 | endmodule 565 | -------------------------------------------------------------------------------- /defines.vh: -------------------------------------------------------------------------------- 1 | 2 | `define EXE_R_TYPE 6'b000000 3 | //logic inst 4 | `define EXE_NOP 6'b000000 5 | `define EXE_AND 6'b100100 6 | `define EXE_OR 6'b100101 7 | `define EXE_XOR 6'b100110 8 | `define EXE_NOR 6'b100111 9 | `define EXE_ANDI 6'b001100 10 | `define EXE_ORI 6'b001101 11 | `define EXE_XORI 6'b001110 12 | `define EXE_LUI 6'b001111 13 | //shift inst 14 | `define EXE_SLL 6'b000000 15 | `define EXE_SLLV 6'b000100 16 | `define EXE_SRL 6'b000010 17 | `define EXE_SRLV 6'b000110 18 | `define EXE_SRA 6'b000011 19 | `define EXE_SRAV 6'b000111 20 | //move inst 21 | `define EXE_MFHI 6'b010000 22 | `define EXE_MTHI 6'b010001 23 | `define EXE_MFLO 6'b010010 24 | `define EXE_MTLO 6'b010011 25 | //算术运算 26 | `define EXE_SLT 6'b101010 27 | `define EXE_SLTU 6'b101011 28 | `define EXE_SLTI 6'b001010 29 | `define EXE_SLTIU 6'b001011 30 | `define EXE_ADD 6'b100000 31 | `define EXE_ADDU 6'b100001 32 | `define EXE_SUB 6'b100010 33 | `define EXE_SUBU 6'b100011 34 | `define EXE_ADDI 6'b001000 35 | `define EXE_ADDIU 6'b001001 36 | 37 | `define EXE_MULT 6'b011000 38 | `define EXE_MULTU 6'b011001 39 | 40 | `define EXE_DIV 6'b011010 41 | `define EXE_DIVU 6'b011011 42 | 43 | `define EXE_EQUAL 6'b111111 44 | //jump 45 | `define EXE_J 6'b000010 46 | `define EXE_JAL 6'b000011 47 | `define EXE_JALR 6'b001001 48 | `define EXE_JR 6'b001000 49 | //branch 50 | `define EXE_BEQ 6'b000100 51 | `define EXE_BGTZ 6'b000111 52 | `define EXE_BNE 6'b000101 53 | `define EXE_BLEZ 6'b000110 54 | `define EXE_BRANCHS 6'b000001 // 55 | `define EXE_BLTZ 5'b00000 56 | `define EXE_BLTZAL 5'b10000 57 | `define EXE_BGEZAL 5'b10001 58 | `define EXE_BGEZ 5'b00001 59 | //load/store 60 | `define EXE_LB 6'b100000 61 | `define EXE_LBU 6'b100100 62 | `define EXE_LH 6'b100001 63 | `define EXE_LHU 6'b100101 64 | `define EXE_LL 6'b110000 65 | `define EXE_LW 6'b100011 66 | `define EXE_LWL 6'b100010 67 | `define EXE_LWR 6'b100110 68 | `define EXE_SB 6'b101000 69 | `define EXE_SC 6'b111000 70 | `define EXE_SH 6'b101001 71 | `define EXE_SW 6'b101011 72 | `define EXE_SWL 6'b101010 73 | `define EXE_SWR 6'b101110 74 | //trap 75 | `define EXE_SYSCALL 6'b001100 76 | `define EXE_BREAK 6'b001101 77 | 78 | `define EXE_TEQ 6'b110100 79 | `define EXE_TEQI 5'b01100 80 | `define EXE_TGE 6'b110000 81 | `define EXE_TGEI 5'b01000 82 | `define EXE_TGEIU 5'b01001 83 | `define EXE_TGEU 6'b110001 84 | `define EXE_TLT 6'b110010 85 | `define EXE_TLTI 5'b01010 86 | `define EXE_TLTIU 5'b01011 87 | `define EXE_TLTU 6'b110011 88 | `define EXE_TNE 6'b110110 89 | `define EXE_TNEI 5'b01110 90 | 91 | // `define EXE_ERET 32'b01000010000000000000000000011000 92 | `define EXE_ERET 26'b10000000000000000000011000 93 | `define EXE_ERET_MFTC 6'b010000 94 | 95 | `define EXE_SYNC 6'b001111 96 | `define EXE_PREF 6'b110011 97 | 98 | `define EXE_MTC0 5'b00100 99 | `define EXE_MFC0 5'b00000 100 | 101 | //Exception code 102 | `define EXC_CODE_INT 5'h00 103 | `define EXC_CODE_ADEL 5'h04 104 | `define EXC_CODE_ADES 5'h05 105 | `define EXC_CODE_SYS 5'h08 106 | `define EXC_CODE_BP 5'h09 107 | `define EXC_CODE_RI 5'h0a 108 | `define EXC_CODE_OV 5'h0c 109 | 110 | //Exception type 111 | `define EXC_TYPE_INT 32'h0000_0001 112 | `define EXC_TYPE_ADEL 32'h0000_0004 113 | `define EXC_TYPE_ADES 32'h0000_0005 114 | `define EXC_TYPE_SYS 32'h0000_0008 115 | `define EXC_TYPE_BP 32'h0000_0009 116 | `define EXC_TYPE_RI 32'h0000_000a 117 | `define EXC_TYPE_OV 32'h0000_000c 118 | `define EXC_TYPE_ERET 32'h0000_000e 119 | `define EXC_TYPE_NOEXC 32'h0000_0000 120 | 121 | //CP0 122 | `define CP0_REG_BADVADDR 5'b01000 123 | `define CP0_REG_COUNT 5'b01001 124 | `define CP0_REG_COMPARE 5'b01011 125 | `define CP0_REG_STATUS 5'b01100 126 | `define CP0_REG_CAUSE 5'b01101 127 | `define CP0_REG_EPC 5'b01110 128 | `define CP0_REG_PRID 5'b01111 129 | `define CP0_REG_CONFIG 5'b10000 130 | 131 | `define InterruptAssert 1'b1 132 | `define InterruptNotAssert 1'b0 133 | `define InDelaySlot 1'b1 134 | `define NotInDelaySlot 1'b0 135 | 136 | `define ZeroWord 32'd0 137 | 138 | 139 | //alu defines 140 | `define ALU_AND 5'b0_0000 141 | `define ALU_OR 5'b0_0001 142 | `define ALU_ADD 5'b0_0010 143 | `define ALU_SUB 5'b0_0011 144 | `define ALU_SLT 5'b0_0100 145 | `define ALU_SLL 5'b0_0101 146 | `define ALU_SRL 5'b0_0110 147 | `define ALU_SRA 5'b0_0111 148 | `define ALU_SLTU 5'b0_1000 149 | `define ALU_UNSIGNED_MULT 5'b0_1001 150 | `define ALU_XOR 5'b0_1010 151 | `define ALU_NOR 5'b0_1011 152 | `define ALU_UNSIGNED_DIV 5'b0_1100 153 | `define ALU_SIGNED_MULT 5'b0_1101 154 | `define ALU_SIGNED_DIV 5'b0_1110 155 | `define ALU_LUI 5'b0_1111 156 | `define ALU_ADDU 5'b1_0000 157 | `define ALU_SUBU 5'b1_0001 158 | `define ALU_LEZ 5'b1_0010 159 | `define ALU_GTZ 5'b1_0011 160 | `define ALU_GEZ 5'b1_0100 161 | `define ALU_LTZ 5'b1_0101 162 | `define ALU_SLL_SA 5'b1_0110 163 | `define ALU_SRL_SA 5'b1_0111 164 | `define ALU_SRA_SA 5'b1_1000 165 | `define ALU_EQ 5'b1_1001 166 | `define ALU_NEQ 5'b1_1010 167 | `define ALU_MTHI 5'b1_1011 168 | `define ALU_MTLO 5'b1_1100 169 | `define ALU_EQUAL 5'b1_1101 170 | // 5'b1_1110 171 | `define ALU_DONOTHING 5'b1_1111 -------------------------------------------------------------------------------- /div.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module div( 4 | input clk, 5 | input rst, 6 | input flush, 7 | input [31:0] a, //divident 8 | input [31:0] b, //divisor 9 | input valid, 10 | input sign, //1:signed 11 | // output reg ready, 12 | output wire div_stall, 13 | output [63:0] result 14 | ); 15 | /* 16 | 1. 先取绝对值,计算出余数和商。再根据被除数、除数符号对结果调整 17 | 2. 计算过程中,由于保证了remainer为正,因此最高位为0,可以用32位存储。而除数需用33位 18 | */ 19 | reg [31:0] a_save, b_save; 20 | reg [63:0] SR; //shift register 21 | reg [32 :0] NEG_DIVISOR; //divisor 2's complement 22 | wire [31:0] REMAINER, QUOTIENT; 23 | assign REMAINER = SR[63:32]; 24 | assign QUOTIENT = SR[31: 0]; 25 | 26 | wire [31:0] divident_abs; 27 | wire [32:0] divisor_abs; 28 | wire [31:0] remainer, quotient; 29 | 30 | assign divident_abs = (sign & a[31]) ? ~a + 1'b1 : a; 31 | //余数符号与被除数相同 32 | assign remainer = (sign & a_save[31]) ? ~REMAINER + 1'b1 : REMAINER; 33 | assign quotient = sign & (a_save[31] ^ b_save[31]) ? ~QUOTIENT + 1'b1 : QUOTIENT; 34 | assign result = {remainer,quotient}; 35 | 36 | wire CO; 37 | wire [32:0] sub_result; 38 | wire [32:0] mux_result; 39 | //sub 40 | assign {CO,sub_result} = {1'b0,REMAINER} + NEG_DIVISOR; 41 | //mux 42 | assign mux_result = CO ? sub_result : {1'b0,REMAINER}; 43 | 44 | //state machine 45 | reg [5:0] cnt; 46 | reg start_cnt; 47 | always @(posedge clk) begin 48 | if(rst | flush) begin 49 | cnt <= 0; 50 | start_cnt <= 0; 51 | end 52 | else if(!start_cnt & valid) begin 53 | cnt <= 1; 54 | start_cnt <= 1; 55 | //save a,b 56 | a_save <= a; 57 | b_save <= b; 58 | 59 | //Register init 60 | SR[63:0] <= {31'b0,divident_abs,1'b0}; //left shift one bit initially 61 | NEG_DIVISOR <= (sign & b[31]) ? {1'b1,b} : ~{1'b0,b} + 1'b1; //divisor_abs的补码 62 | end 63 | else if(start_cnt) begin 64 | if(cnt==32) begin 65 | cnt <= 0; 66 | start_cnt <= 0; 67 | 68 | //Output result 69 | SR[63:32] <= mux_result[31:0]; 70 | SR[0] <= CO; 71 | end 72 | else begin 73 | cnt <= cnt + 1; 74 | 75 | SR[63:0] <= {mux_result[30:0],SR[31:1],CO,1'b0}; //wsl: write and shift left 76 | end 77 | end 78 | end 79 | 80 | assign div_stall = |cnt; //只有当cnt=0时不暂停 81 | endmodule -------------------------------------------------------------------------------- /exception.v: -------------------------------------------------------------------------------- 1 | `include "defines.vh" 2 | 3 | module exception( 4 | input rst, 5 | input [5:0] ext_int, 6 | input ri, break, syscall, overflow, addrErrorSw, addrErrorLw, pcError, eretM, 7 | input [31:0] cp0_status, cp0_cause, cp0_epc, 8 | input [31:0] pcM, 9 | input [31:0] alu_outM, 10 | 11 | output [31:0] except_type, 12 | output flush_exception, //是否有异常 13 | output [31:0] pc_exception, //pc异常处理地址 14 | output pc_trap, //是否trap 15 | output [31:0] badvaddrM //pc修正 16 | ); 17 | 18 | //INTERUPT 19 | wire int; 20 | // //IE //EXL 21 | assign int = cp0_status[0] && ~cp0_status[1] && ( 22 | //IM //IP 23 | ( |(cp0_status[9:8] & cp0_cause[9:8]) ) || //软件中断 24 | ( |(cp0_status[15:10] & ext_int) ) || //硬件中断 25 | (|(cp0_status[30] & cp0_cause[30])) //计时器中断 26 | ); 27 | // 全局中断开启,且没有例外在处理,识别软件中断或者硬件中断 28 | 29 | assign except_type = (int) ? `EXC_TYPE_INT : //中断 30 | (addrErrorLw | pcError) ? `EXC_TYPE_ADEL : //地址错误例外(lw地址 pc错误 31 | (ri) ? `EXC_TYPE_RI : //保留指令例外(指令不存在 32 | (syscall) ? `EXC_TYPE_SYS : //系统调用例外(syscall指令 33 | (break) ? `EXC_TYPE_BP : //断点例外(break指令 34 | (addrErrorSw) ? `EXC_TYPE_ADES : //地址错误例外(sw地址异常 35 | (overflow) ? `EXC_TYPE_OV : //算数溢出例外 36 | (eretM) ? `EXC_TYPE_ERET : //eret指令 37 | `EXC_TYPE_NOEXC; //无异常 38 | //interupt pc address 39 | assign pc_exception = (except_type == `EXC_TYPE_NOEXC) ? `ZeroWord: 40 | (except_type == `EXC_TYPE_ERET)? cp0_epc : 41 | 32'hbfc0_0380; //异常处理地址 42 | assign pc_trap = (except_type == `EXC_TYPE_NOEXC) ? 1'b0: 43 | 1'b1; //表示发生异常 处理pc 44 | assign flush_exception = (except_type == `EXC_TYPE_NOEXC) ? 1'b0: 45 | 1'b1; //异常时的清空信号 46 | assign badvaddrM = (pcError) ? pcM : alu_outM; //出错时的pc 47 | 48 | 49 | endmodule 50 | -------------------------------------------------------------------------------- /hazard.v: -------------------------------------------------------------------------------- 1 | module hazard ( 2 | input wire d_cache_stall, 3 | input wire alu_stallE, 4 | 5 | input wire flush_jump_confilctE, flush_pred_failedM, flush_exceptionM, 6 | 7 | input wire [4:0] rsE, 8 | input wire [4:0] rtE, //寄存器序号 9 | input wire reg_write_enM, 10 | input wire reg_write_enW, //写寄存器信号 11 | input wire [4:0] reg_writeM, 12 | input wire [4:0] reg_writeW, //写寄存器序号 13 | 14 | input wire mem_read_enM, //读mem信号 15 | 16 | output wire stallF, stallD, stallE, stallM, stallW, 17 | output wire flushF, flushD, flushE, flushM, flushW, //流水线控制 18 | 19 | output wire [1:0] forward_aE, forward_bE //00-> NONE, 01-> MEM, 10-> WB (LW instr) 20 | ); 21 | // 数据冒险,前推片选信号 22 | assign forward_aE = rsE != 0 && reg_write_enM && (rsE == reg_writeM) ? 2'b01 : 23 | rsE != 0 && reg_write_enW && (rsE == reg_writeW) ? 2'b10 : 24 | 2'b00; 25 | assign forward_bE = reg_write_enM && (rtE == reg_writeM) ? 2'b01 : 26 | reg_write_enW && (rtE == reg_writeW) ? 2'b10 : 27 | 2'b00; 28 | 29 | assign stallF = ~flush_exceptionM & (d_cache_stall | alu_stallE);// 30 | assign stallD = d_cache_stall | alu_stallE; 31 | assign stallE = d_cache_stall | alu_stallE; 32 | assign stallM = d_cache_stall; 33 | assign stallW = d_cache_stall; // 不暂停,会减少jr等指令冲突; 34 | 35 | assign flushF = 1'b0; 36 | assign flushD = flush_exceptionM | flush_pred_failedM | (flush_jump_confilctE & ~d_cache_stall); // //EX: jr(冲突), MEM: lw这种情况时,flush_jump_confilctE会导致暂停在D阶段jr的延迟槽指令消失 37 | assign flushE = flush_exceptionM | (flush_pred_failedM & ~alu_stallE);// //EX: div, MEM: beq, beq预测失败,要flush D和E,但由于div暂停在E,因此只需要flushD就可以了 38 | assign flushM = flush_exceptionM | alu_stallE;// 39 | assign flushW = 1'b0; 40 | endmodule 41 | -------------------------------------------------------------------------------- /hilo.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "defines.vh" 3 | 4 | module hilo( 5 | input wire clk,rst,we, //both write lo and hi 6 | input wire [31:0] instrM, 7 | input wire [63:0] hilo_in, //存入hilo的值 8 | 9 | output wire [31:0] hilo_out 10 | ); 11 | // hilo寄存器 12 | reg [63:0] hilo; 13 | 14 | // 更新 15 | always @(posedge clk) begin 16 | if(rst) 17 | hilo <= 0; 18 | else if(we) 19 | hilo <= hilo_in; 20 | else 21 | hilo <= hilo; 22 | end 23 | 24 | 25 | // 若为mfhi指令 读hilo高32位 若为mflo指令读hilo低32位 26 | wire mfhi; 27 | wire mflo; 28 | assign mfhi = ~(|(instrM[31:26] ^ `EXE_R_TYPE)) & ~(|(instrM[5:0] ^ `EXE_MFHI)); 29 | assign mflo = ~(|(instrM[31:26] ^ `EXE_R_TYPE)) & ~(|(instrM[5:0] ^ `EXE_MFLO)); 30 | 31 | assign hilo_out = ({32{mfhi}} & hilo[63:32]) | ({32{mflo}} & hilo[31:0]); 32 | endmodule 33 | -------------------------------------------------------------------------------- /inst_ascii_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "defines.vh" 3 | 4 | 5 | module inst_ascii_decoder( 6 | input wire [31:0] instr, 7 | output reg [44:0] ascii 8 | ); 9 | 10 | always @(*) 11 | begin 12 | ascii<="N-R"; 13 | case(instr[31:26]) 14 | `EXE_NOP: // R-type 15 | begin 16 | case(instr[5:0]) 17 | /* logic instraction */ 18 | `EXE_AND: ascii<= "AND"; 19 | `EXE_OR: ascii<= "OR"; 20 | `EXE_XOR: ascii<= "XOR"; 21 | `EXE_NOR: ascii<= "NOR"; 22 | /* shift instraction */ 23 | `EXE_SLL: ascii<= "SLL"; 24 | `EXE_SRL: ascii<= "SRL"; 25 | `EXE_SRA: ascii<= "SRA"; 26 | `EXE_SLLV: ascii<= "SLLV"; 27 | `EXE_SRLV: ascii<= "SRLV"; 28 | `EXE_SRAV: ascii<= "SRAV"; 29 | /* move instraction */ 30 | `EXE_MFHI: ascii<= "MFHI"; 31 | `EXE_MTHI: ascii<= "MTHI"; 32 | `EXE_MFLO: ascii<= "MFLO"; 33 | `EXE_MTLO: ascii<= "MTLO"; 34 | /* arithemtic instraction */ 35 | `EXE_ADD: ascii<= "ADD"; 36 | `EXE_ADDU: ascii<= "ADDU"; 37 | `EXE_SUB: ascii<= "SUB"; 38 | `EXE_SUBU: ascii<= "SUBU"; 39 | `EXE_SLT: ascii<= "SLT"; 40 | `EXE_SLTU: ascii<= "SLTU"; 41 | 42 | `EXE_MULT: ascii<= "MULT"; 43 | `EXE_MULTU: ascii<= "MULTU"; 44 | `EXE_DIV: ascii<= "DIV"; 45 | `EXE_DIVU: ascii<= "DIVU"; 46 | /* jump instraction */ 47 | `EXE_JR: ascii<= "JR"; 48 | `EXE_JALR: ascii<= "JALR"; 49 | 50 | `EXE_SYSCALL: ascii<= "SYSC"; 51 | `EXE_BREAK: ascii<= "BRE"; 52 | default: ascii<="N-R"; 53 | endcase 54 | end 55 | `EXE_ANDI: ascii<= "ANDI"; 56 | `EXE_XORI: ascii<= "XORI"; 57 | `EXE_LUI: ascii<= "LUI"; 58 | `EXE_ORI: ascii<= "ORI"; 59 | 60 | `EXE_ADDI: ascii<= "ADDI"; 61 | `EXE_ADDIU: ascii<= "ADDIU"; 62 | `EXE_SLTI: ascii<= "SLTI"; 63 | `EXE_SLTIU: ascii<= "SLTIU"; 64 | 65 | `EXE_J: ascii<= "J"; 66 | `EXE_JAL: ascii<= "JAL"; 67 | 68 | `EXE_BEQ: ascii<= "BEQ"; 69 | `EXE_BGTZ: ascii<= "BGTZ"; 70 | `EXE_BLEZ: ascii<= "BLEZ"; 71 | `EXE_BNE: ascii<= "BNE"; 72 | 73 | `EXE_LB: ascii<= "LB"; 74 | `EXE_LBU: ascii<= "LBU"; 75 | `EXE_LH: ascii<= "LH"; 76 | `EXE_LHU: ascii<= "LHU"; 77 | `EXE_LW: ascii<= "LW"; 78 | `EXE_SB: ascii<= "SB"; 79 | `EXE_SH: ascii<= "SH"; 80 | `EXE_SW: ascii<= "SW"; 81 | 6'b000001: begin 82 | case (instr[20:16]) 83 | `EXE_BGEZ: ascii<= "BGEZ"; 84 | `EXE_BGEZAL: ascii<= "BGEZAL"; 85 | `EXE_BLTZ: ascii<= "BLTZ"; 86 | `EXE_BLTZAL: ascii<= "BLTZAL"; 87 | default : ascii<= " "; 88 | endcase 89 | end 90 | 6'b010000: begin 91 | if(instr==`EXE_ERET) begin 92 | ascii<="ERET"; 93 | end else begin 94 | case (instr[25:21]) 95 | 5'b00100: ascii<="MTOC0"; 96 | 5'b00000: ascii<="MFC0"; 97 | endcase 98 | end 99 | end 100 | default: ascii<= "N-R"; 101 | endcase 102 | if(instr==`EXE_ERET) 103 | ascii<= "ERET"; 104 | if(!instr) 105 | ascii<= "NOP"; 106 | end 107 | 108 | endmodule 109 | -------------------------------------------------------------------------------- /jump_control.v: -------------------------------------------------------------------------------- 1 | module jump_control ( 2 | input wire [31:0] instrD, 3 | input wire [31:0] pc_plus4D, 4 | input wire [31:0] rd1D, 5 | input wire reg_write_enE, reg_write_enM, 6 | input wire [4:0] reg_writeE, reg_writeM, 7 | 8 | output wire jumpD, 9 | output wire jump_conflictD, 10 | output wire [31:0] pc_jumpD 11 | ); 12 | wire jr, j; 13 | wire [4:0] rsD; 14 | assign rsD = instrD[25:21]; 15 | assign jr = ~(|instrD[31:26]) & ~(|(instrD[5:1] ^ 5'b00100)); //判断jr, jalr 16 | assign j = ~(|(instrD[31:27] ^ 5'b00001)); //判断j, jal 17 | assign jumpD = jr | j; //需要jump 18 | 19 | // jump冲突 在E阶段或M阶段需要写回rsD(jr指令跳转目标为rs中的值 20 | assign jump_conflictD = jr && 21 | ((reg_write_enE && rsD == reg_writeE) || 22 | (reg_write_enM && rsD == reg_writeM)); 23 | 24 | wire [31:0] pc_jump_immD; 25 | assign pc_jump_immD = {pc_plus4D[31:28], instrD[25:0], 2'b00}; //instr_index左移2位 与pc+4高四位拼接 26 | 27 | assign pc_jumpD = j ? pc_jump_immD : rd1D; //j 和 jr的跳转目标 立即数:寄存器的值 28 | endmodule -------------------------------------------------------------------------------- /main_decode.v: -------------------------------------------------------------------------------- 1 | `include "defines.vh" 2 | 3 | 4 | module main_decode( 5 | 6 | input clk, rst, 7 | input wire [31:0] instrD, 8 | 9 | input wire stallE, stallM, stallW, 10 | input wire flushE, flushM, flushW, 11 | 12 | //ID 13 | // output wire is_multD, 14 | output wire sign_extD, //立即数是否为符号扩展 15 | //EX 16 | output reg [1 :0] reg_dstE, //写寄存器选择 00-> rd, 01-> rt, 10-> 写$ra 17 | output reg alu_imm_selE, //alu srcb选择 0->rd2E, 1->immE 18 | output reg reg_write_enE, //寄存器写使能 19 | output reg hilo_wenE, 20 | //MEM 21 | output reg mem_read_enM, mem_write_enM, //mem读写使能 22 | output reg reg_write_enM, //写寄存器堆使能 23 | output reg mem_to_regM, //result选择 0->alu_out, 1->read_data 24 | output reg hilo_to_regM, // 00--alu_outM; 01--hilo_o; 10 11--rdataM; 25 | output reg riM, 26 | output reg breakM, syscallM, eretM, 27 | output reg cp0_wenM, //写cp0 28 | output reg cp0_to_regM, //读cp0 29 | output wire is_mfcM //为mfc0 30 | ); 31 | reg [6:0] sigs; //控制信号 7bits 32 | wire [1:0] reg_dstD; 33 | wire reg_write_enD,alu_imm_selD,mem_to_regD, mem_read_enD, mem_write_enD; 34 | reg mem_to_regE, mem_read_enE, mem_write_enE; 35 | 36 | wire hilo_wenD; 37 | wire hilo_to_regD; 38 | reg hilo_to_regE; 39 | 40 | wire breakD, syscallD; 41 | reg breakE, syscallE; 42 | wire eretD; 43 | reg eretE; 44 | reg riD, riE; 45 | 46 | wire cp0_wenD; 47 | reg cp0_wenE; 48 | wire cp0_to_regD; 49 | reg cp0_to_regE; 50 | 51 | reg is_mfcD; 52 | wire is_mfcE; 53 | 54 | 55 | 56 | 57 | wire [4:0] rs,rt; 58 | wire [5:0] opcode; 59 | wire [5:0] funct; 60 | 61 | assign {reg_write_enD, reg_dstD, alu_imm_selD,mem_to_regD, mem_read_enD, mem_write_enD} = sigs; 62 | 63 | assign opcode = instrD[31:26]; //操作码 64 | assign rs = instrD[25:21]; //rs 65 | assign rt = instrD[20:16]; //rt 66 | assign funct = instrD[5:0]; //funct 67 | 68 | 69 | // assign is_multD = (~(|opcode) & ~(|(funct[5:1] ^ 5'b01100))); 70 | // 容易判断的信号 71 | assign sign_extD = |(opcode[5:2] ^ 4'b0011); //andi, xori, lui, ori(op[5:2]=0011)为无符号拓展--0,其它为有符号拓展--1 72 | 73 | assign hilo_wenD = ~(|( opcode ^ `EXE_R_TYPE )) & ( ~(|(funct[5:2] ^ 4'b0110)) // div divu mult multu 74 | | ( ~(|(funct[5:2] ^ 4'b0100)) & funct[0])); //mthi mtlo 75 | 76 | assign hilo_to_regD = ~(|(opcode ^ `EXE_R_TYPE)) & (~(|(funct[5:2] ^ 4'b0100)) & ~funct[0]); 77 | // 00--alu_outM; 01--hilo_o; 10 11--rdataM; 78 | 79 | 80 | // cp0写使能:为MTC0指令 81 | assign cp0_wenD = ~(|(opcode ^ `EXE_ERET_MFTC)) & ~(|(rs ^ `EXE_MTC0)); 82 | // 读cp0:为MFC0指令 83 | assign cp0_to_regD = ~(|(opcode ^ `EXE_ERET_MFTC)) & ~(|(rs ^ `EXE_MFC0)); 84 | 85 | // 判断是否为break syscall eret 86 | assign breakD = ~(|(opcode ^ `EXE_R_TYPE)) & ~(|(funct ^ `EXE_BREAK)); 87 | assign syscallD = ~(|(opcode ^ `EXE_R_TYPE)) & ~(|(funct ^ `EXE_SYSCALL)); 88 | // eret的32位固定 89 | assign eretD = ~(|(instrD ^ {`EXE_ERET_MFTC, `EXE_ERET})); 90 | 91 | always @(*) begin 92 | riD = 1'b0; 93 | is_mfcD = 1'b0; 94 | case(opcode) 95 | // R type 96 | 97 | `EXE_R_TYPE: 98 | // R型指令继续看funct 99 | case(funct) 100 | `EXE_JR, `EXE_MULT, `EXE_MULTU, `EXE_DIV, `EXE_DIVU, `EXE_MTHI, `EXE_MTLO, 101 | // 自陷指令 2条 op为000000 102 | `EXE_SYSCALL, `EXE_BREAK 103 | : begin 104 | sigs = 7'b0_00_0_000; //跳转指令 信号为0 105 | end 106 | // 算数运算指令 10条 107 | `EXE_ADD,`EXE_ADDU,`EXE_SUB,`EXE_SUBU,`EXE_SLTU,`EXE_SLT , 108 | `EXE_AND,`EXE_NOR, `EXE_OR, `EXE_XOR, 109 | // 移位指令 6条 110 | `EXE_SLLV, `EXE_SLL, `EXE_SRAV, `EXE_SRA, `EXE_SRLV, `EXE_SRL, 111 | `EXE_MFHI, `EXE_MFLO //写入HILO寄存器 112 | : begin 113 | sigs = 7'b1_00_0_000; //算数运算指令 114 | end 115 | `EXE_JALR 116 | : begin 117 | sigs = 7'b1_10_0_000; //jalr指令需要将分支之后的pc存入rd中 118 | end 119 | //不属于任何指令 120 | default: begin 121 | riD = 1'b1; 122 | sigs = 7'b1_00_0_000; 123 | end 124 | endcase 125 | 126 | // I type 127 | 128 | // 算数运算指令 129 | // 逻辑运算 8条 130 | `EXE_ADDI, `EXE_SLTI, `EXE_SLTIU, `EXE_ADDIU, `EXE_ANDI, `EXE_LUI, `EXE_XORI, `EXE_ORI 131 | : begin 132 | sigs = 7'b1_01_1_000; //I型信号:写回rs 操作立即数 不访存 133 | end 134 | 135 | // B族指令 8条 136 | `EXE_BEQ, `EXE_BNE, `EXE_BLEZ, `EXE_BGTZ 137 | : begin 138 | sigs = 7'b0_00_0_000; 139 | end 140 | // 分支指令:BGEZ BLTZ BGEZAL BLTZAL 141 | `EXE_BRANCHS: begin 142 | case(rt[4:1]) 143 | // BGEZAL BLTZAL rt:10001 10000 144 | // 无论转移与否 需要将延迟槽后pc保存至31号寄存器 145 | 4'b1000: begin 146 | sigs = 7'b1_10_0_000; 147 | end 148 | // BLTZ rt:00000 149 | 4'b0000: begin 150 | sigs = 7'b0_00_0_000; 151 | end 152 | // 不属于任何指令 153 | default:begin 154 | riD = 1'b1; 155 | sigs = 7'b0_00_0_000; 156 | end 157 | endcase 158 | end 159 | 160 | // 访存指令 8条 161 | `EXE_LW, `EXE_LB, `EXE_LBU, `EXE_LH, `EXE_LHU: begin 162 | sigs = 7'b1_01_1_1_1_0; //读mem 163 | end 164 | `EXE_SW, `EXE_SB, `EXE_SH: begin 165 | sigs = 7'b0_00_1_0_0_1; //写mem 166 | end 167 | 168 | // J type 2条 169 | 170 | `EXE_J: begin 171 | sigs = 7'b0_00_0_000; 172 | end 173 | // 需将延迟槽后pc保存至31号寄存器 174 | `EXE_JAL: begin 175 | sigs = 7'b1_10_0_000; 176 | end 177 | 178 | // 3条特权指令 179 | `EXE_ERET_MFTC:begin 180 | case(instrD[25:21]) 181 | `EXE_MTC0: begin 182 | sigs = 7'b0; 183 | end 184 | `EXE_MFC0: begin 185 | sigs = 7'b1_01_0_000; 186 | is_mfcD = 1'b1; 187 | end 188 | default: begin 189 | riD = |(instrD[25:0] ^ `EXE_ERET); //为eret指令:0 不为eret指令:1 190 | sigs = 7'b0; 191 | end 192 | endcase 193 | end 194 | 195 | // 不属于任何指令 196 | default: begin 197 | riD = 1; 198 | sigs = 7'b0; 199 | end 200 | endcase 201 | end 202 | 203 | // pipeline 204 | // ID-EX flow 205 | always@(posedge clk) begin 206 | if(rst | flushE) begin 207 | reg_dstE <= 0; 208 | alu_imm_selE <= 0; 209 | mem_read_enE <= 0; 210 | mem_write_enE <= 0; 211 | reg_write_enE <= 0; 212 | mem_to_regE <= 0; 213 | hilo_wenE <= 0; 214 | hilo_to_regE <= 0; 215 | riE <= 0; 216 | breakE <= 0; 217 | syscallE <= 0; 218 | eretE <= 0; 219 | cp0_wenE <= 0; 220 | cp0_to_regE <= 0; 221 | is_mfcE <= 0; 222 | end 223 | else if(~stallE)begin 224 | reg_dstE <= reg_dstD ; 225 | alu_imm_selE <= alu_imm_selD ; 226 | mem_read_enE <= mem_read_enD ; 227 | mem_write_enE <= mem_write_enD ; 228 | reg_write_enE <= reg_write_enD ; 229 | mem_to_regE <= mem_to_regD ; 230 | hilo_wenE <= hilo_wenD ; 231 | hilo_to_regE <= hilo_to_regD ; 232 | riE <= riD ; 233 | breakE <= breakD ; 234 | syscallE <= syscallD ; 235 | eretE <= eretD ; 236 | cp0_wenE <= cp0_wenD ; 237 | cp0_to_regE <= cp0_to_regD ; 238 | is_mfcE <= is_mfcD ; 239 | end 240 | end 241 | 242 | // EX-MEM flow 243 | always@(posedge clk) begin 244 | if(rst | flushM) begin 245 | mem_read_enM <= 0; 246 | mem_write_enM <= 0; 247 | reg_write_enM <= 0; 248 | mem_to_regM <= 0; 249 | hilo_to_regM <= 0; 250 | riM <= 0; 251 | breakM <= 0; 252 | syscallM <= 0; 253 | eretM <= 0; 254 | cp0_wenM <= 0; 255 | cp0_to_regM <= 0; 256 | is_mfcM <= 0; 257 | end 258 | else if(~stallM) begin 259 | mem_read_enM <= mem_read_enE ; 260 | mem_write_enM <= mem_write_enE ; 261 | reg_write_enM <= reg_write_enE ; 262 | mem_to_regM <= mem_to_regE ; 263 | hilo_to_regM <= hilo_to_regE ; 264 | riM <= riE ; 265 | breakM <= breakE ; 266 | syscallM <= syscallE ; 267 | eretM <= eretE ; 268 | cp0_wenM <= cp0_wenE ; 269 | cp0_to_regM <= cp0_to_regE ; 270 | is_mfcM <= is_mfcE ; 271 | end 272 | end 273 | endmodule 274 | 275 | -------------------------------------------------------------------------------- /mem_control.v: -------------------------------------------------------------------------------- 1 | `include "defines.vh" 2 | 3 | module mem_control( 4 | input wire [31:0] instrM, 5 | input wire [31:0] addr, //访存地址 6 | 7 | input wire [31:0] data_wdataM, //要写的数据 8 | output wire [31:0] mem_wdataM, //真正写数据 9 | output wire [3:0] mem_wenM, //写使能 10 | 11 | input wire [31:0] mem_rdataM, //内存读出 12 | output wire [31:0] data_rdataM, // 实际读出 13 | 14 | output wire addr_error_sw, addr_error_lw 15 | ); 16 | wire [3:0] mem_byte_wen; 17 | wire [5:0] op_code; 18 | 19 | wire instr_lw, instr_lh, instr_lb, instr_sw, instr_sh, instr_sb, instr_lhu, instr_lbu; 20 | wire addr_W0, addr_B2, addr_B1, addr_B3; 21 | 22 | 23 | assign op_code = instrM[31:26]; 24 | 25 | // 根据addr后两位选取读的位置 26 | assign addr_W0 = ~(|(addr[1:0] ^ 2'b00)); 27 | assign addr_B2 = ~(|(addr[1:0] ^ 2'b10)); 28 | assign addr_B1 = ~(|(addr[1:0] ^ 2'b01)); 29 | assign addr_B3 = ~(|(addr[1:0] ^ 2'b11)); 30 | 31 | // 判断是否为各种访存指令 32 | assign instr_lw = ~(|(op_code ^ `EXE_LW)); 33 | assign instr_lb = ~(|(op_code ^ `EXE_LB)); 34 | assign instr_lh = ~(|(op_code ^ `EXE_LH)); 35 | assign instr_lbu = ~(|(op_code ^ `EXE_LBU)); 36 | assign instr_lhu = ~(|(op_code ^ `EXE_LHU)); 37 | assign instr_sw = ~(|(op_code ^ `EXE_SW)); 38 | assign instr_sh = ~(|(op_code ^ `EXE_SH)); 39 | assign instr_sb = ~(|(op_code ^ `EXE_SB)); 40 | 41 | // 地址异常 42 | assign addr_error_sw = (instr_sw & ~addr_W0) 43 | | ( instr_sh & ~(addr_W0 | addr_B2)); 44 | assign addr_error_lw = (instr_lw & ~addr_W0) 45 | | (( instr_lh | instr_lhu ) & ~(addr_W0 | addr_B2)); 46 | 47 | // wdata and byte_wen 48 | assign mem_wenM = ( {4{( instr_sw & addr_W0 )}} & 4'b1111) //写字 49 | | ( {4{( instr_sh & addr_W0 )}} & 4'b0011) //写半字 低位 50 | | ( {4{( instr_sh & addr_B2 )}} & 4'b1100) //写半字 高位 51 | | ( {4{( instr_sb & addr_W0 )}} & 4'b0001) //写字节 四个字节 52 | | ( {4{( instr_sb & addr_B1 )}} & 4'b0010) 53 | | ( {4{( instr_sb & addr_B2 )}} & 4'b0100) 54 | | ( {4{( instr_sb & addr_B3 )}} & 4'b1000); 55 | 56 | 57 | // data ram 按字寻址 58 | assign mem_wdataM = ({ 32{instr_sw}} & data_wdataM) // 59 | | ( {32{instr_sh}} & {2{data_wdataM[15:0]} }) // 低位高位均为数据 具体根据操作 60 | | ( {32{instr_sb}} & {4{data_wdataM[7:0]} }); // 61 | // rdata 62 | assign data_rdataM = ( {32{instr_lw}} & mem_rdataM) //lw 直接读取字 63 | | ( {32{ instr_lh & addr_W0}} & { {16{mem_rdataM[15]}}, mem_rdataM[15:0] }) //lh 分别从00 10开始读半字 读取后进行符号扩展 64 | | ( {32{ instr_lh & addr_B2}} & { {16{mem_rdataM[31]}}, mem_rdataM[31:16] }) 65 | | ( {32{ instr_lhu & addr_W0}} & { 16'b0, mem_rdataM[15:0] }) //lhb 分别从00 10开始读半字 读取后进行0扩展 66 | | ( {32{ instr_lhu & addr_B2}} & { 16'b0, mem_rdataM[31:16] }) 67 | | ( {32{ instr_lb & addr_W0}} & { {24{mem_rdataM[7]}}, mem_rdataM[7:0] }) //lb 分别从00 01 10 11开始取bytes 读取后进行符号扩展 68 | | ( {32{ instr_lb & addr_B1}} & { {24{mem_rdataM[15]}}, mem_rdataM[15:8] }) 69 | | ( {32{ instr_lb & addr_B2}} & { {24{mem_rdataM[23]}}, mem_rdataM[23:16] }) 70 | | ( {32{ instr_lb & addr_B3}} & { {24{mem_rdataM[31]}}, mem_rdataM[31:24] }) 71 | | ( {32{ instr_lbu & addr_W0}} & { 24'b0 , mem_rdataM[7:0] }) //lbu 分别从00 01 10 11开始取bytes 读取后进行0扩展 72 | | ( {32{ instr_lbu & addr_B1}} & { 24'b0 , mem_rdataM[15:8] }) 73 | | ( {32{ instr_lbu & addr_B2}} & { 24'b0 , mem_rdataM[23:16] }) 74 | | ( {32{ instr_lbu & addr_B3}} & { 24'b0 , mem_rdataM[31:24] }); 75 | endmodule 76 | -------------------------------------------------------------------------------- /mux4.v: -------------------------------------------------------------------------------- 1 | 2 | module mux4 #(parameter WIDTH=32) ( 3 | input wire [WIDTH-1:0] d0, d1, d2, d3, 4 | input wire [1:0] s, 5 | 6 | output wire [WIDTH-1:0] out 7 | ); 8 | assign out = s[1] ? (s[0] ? d3: d2): 9 | (s[0] ? d1: d0); 10 | 11 | endmodule -------------------------------------------------------------------------------- /mycpu_top.v: -------------------------------------------------------------------------------- 1 | module mycpu_top( 2 | input wire clk,rst,resetn, 3 | input wire [5 :0] ext_int, 4 | 5 | // inst_mem 6 | output wire inst_sram_en, //读使能 7 | output wire [3 :0] inst_sram_wen, //写使能 8 | output wire [31:0] inst_sram_addr,inst_sram_wdata, //字寻址 写数据 9 | input wire [31:0] inst_sram_rdata, //读数据 10 | 11 | // data_mem 12 | output wire data_sram_en, 13 | output wire [3 :0] data_sram_wen, 14 | output wire [31:0] data_sram_addr,data_sram_wdata, 15 | input wire [31:0] data_sram_rdata, 16 | 17 | 18 | output wire [31:0] debug_wb_pc,debug_wb_rf_wdata, 19 | output wire [3 :0] debug_wb_rf_wen, 20 | output wire [4 :0] debug_wb_rf_wnum 21 | ); 22 | 23 | wire [31:0] data_addr_temp; 24 | datapath datapath( 25 | .clk (~clk), 26 | .rst (~resetn), 27 | .ext_int (ext_int), 28 | 29 | .inst_addrF (inst_sram_addr), 30 | .inst_enF (inst_sram_en), 31 | .instrF (inst_sram_rdata), 32 | 33 | 34 | .mem_enM (data_sram_en), 35 | .mem_addrM (data_addr_temp), 36 | .mem_rdataM (data_sram_rdata), 37 | .mem_wenM (data_sram_wen), 38 | .mem_wdataM (data_sram_wdata), 39 | .d_cache_stall(1'b0), 40 | 41 | .debug_wb_pc(debug_wb_pc), 42 | .debug_wb_rf_wen(debug_wb_rf_wen), 43 | .debug_wb_rf_wnum(debug_wb_rf_wnum), 44 | .debug_wb_rf_wdata(debug_wb_rf_wdata) 45 | ); 46 | assign inst_sram_wen = 4'b0; 47 | assign inst_sram_wdata = 32'b0; 48 | assign data_sram_addr = data_addr_temp[31:16]==16'hbfaf ? {3'b0,data_addr_temp[28:0]} : data_addr_temp; 49 | endmodule -------------------------------------------------------------------------------- /pc_reg.v: -------------------------------------------------------------------------------- 1 | module pc_reg( 2 | input clk,rst,stallF, 3 | input wire branchD, 4 | input wire branchM, 5 | input wire pre_right, 6 | input wire actual_takeM, 7 | input wire pred_takeD, 8 | 9 | input wire pc_trapM, //是否发生异常 10 | input wire jumpD, 11 | input wire jump_conflictD, 12 | input wire jump_conflictE, 13 | input wire [31:0] pc_exceptionM, //异常的跳转地址 14 | input wire [31:0] pc_plus4E, //预测跳,实际不跳 将pc_next指向branch指令的PC+8(注:pc_plus4E等价于branch指令的PC+8) //可以保证延迟槽指令不会被flush,故plush_4E存在 15 | input wire [31:0] pc_branchM, //预测不跳,实际跳转 将pc_next指向pc_branchD传到M阶段的值 16 | input wire [31:0] pc_jumpE, //jump冲突,在E阶段 (E阶段rs的值) 17 | input wire [31:0] pc_jumpD, //D阶段jump不冲突跳转的地址(rs寄存器或立即数) 18 | input wire [31:0] pc_branchD, //D阶段 预测跳转的跳转地址(PC+offset) 19 | input wire [31:0] pc_plus4F, //下一条指令的地址 20 | output reg [31:0] pc 21 | ); 22 | wire [31:0] next_pc; 23 | reg [2:0] pick; 24 | always @(*) begin 25 | if(pc_trapM) //发生异常 26 | pick = 3'b000; 27 | else 28 | if(branchM & ~pre_right & ~actual_takeM) //预测跳 实际不挑 pc+8 pick=001 29 | pick = 3'b001; 30 | else if(branchM & ~pre_right & actual_takeM) //预测不跳 实际跳 pc_branchM pick=010 31 | pick = 3'b010; 32 | else if(jump_conflictE) //jump冲突 pc_jumpE pick=011 33 | pick = 3'b011; 34 | //next_pc = pc_jumpE; 35 | else if(jumpD & ~jump_conflictD) //jump不冲突 pc_jumpD pick=100 36 | pick = 3'b100; 37 | else if(branchD & ~branchM & pred_takeD || branchD & branchM & pre_right & pred_takeD) 38 | // M阶段不是分支 该条是分支 D预测跳转 || 两跳均是分支 M预测正确 D预测跳转 ,pc=D阶段 预测跳转的跳转地址(PC+offset) 39 | pick = 3'b101; 40 | else 41 | pick = 3'b110; 42 | end 43 | 44 | assign next_pc = pick[2] ? (pick[1] ? (pick[0] ? 32'b0 : pc_plus4F): //111:110 45 | (pick[0]? pc_branchD : pc_jumpD)): //101:100 46 | (pick[1] ? (pick[0] ? pc_jumpE : pc_branchM): //011:010 47 | (pick[0] ? pc_plus4E : pc_exceptionM));//001:000 //发生异常时pc跳转至异常处理地址 48 | 49 | always @(posedge clk) begin 50 | if(rst) begin 51 | pc<=32'hbfc0_0000; //起始地址 52 | end 53 | else if(~stallF) begin 54 | pc<=next_pc; 55 | end 56 | end 57 | endmodule -------------------------------------------------------------------------------- /regfile.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module regfile( 4 | input wire clk, 5 | input wire stallW, 6 | input wire we3, 7 | input wire[4:0] ra1,ra2,wa3, 8 | input wire[31:0] wd3, 9 | output wire[31:0] rd1,rd2 10 | ); 11 | 12 | reg [31:0] rf[31:0]; 13 | 14 | always @(posedge clk) begin 15 | if(we3 & ~stallW) begin 16 | rf[wa3] <= wd3; 17 | end 18 | end 19 | 20 | assign rd1 = (ra1 != 0) ? rf[ra1] : 0; 21 | assign rd2 = (ra2 != 0) ? rf[ra2] : 0; 22 | endmodule -------------------------------------------------------------------------------- /硬件综合设计报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cquwei-cx/cpu20220108/4a9adfc634bd0050d97465dd3c6abc57639bd70e/硬件综合设计报告.pdf --------------------------------------------------------------------------------