基于MIPS32的流水线CPU设计与实现(verilog)

1.实验内容

  1. 本实例所设计 CPU 的指令格式的拟定。
  2. 基本功能部件的设计与实现。
  3. CPU 各主要功能部件的设计与实现。
  4. CPU 的封装。
  5. 了解提高 CPU 性能的方法。
  6. 掌握流水线 MIPS 微处理器的工作原理。
  7. 理解数据冒险、控制冒险的概念以及流水线冲突的解决方法。
  8. 掌握流水线 MIPS 微处理器的测试方法。

2.实验要求

  1. 设计的流水线 CPU 能够执行 20 条整数指令,每条指令的编码长度均为 32 位。
  2. 采用 5 级流水线技术,具有数据前推机制。
  3. 具有解决控制冒险,数据冒险等问题的能力,能够插入气泡暂停等。
  4. 具有缩短分支的延迟方案。

3. 实验难点

本实验只选取了 20 条典型的 MIPS 指令来描述 CPU 逻辑电路的设计方法。表中出了本实验的所涉及到的 20 条 MIPS 指令。
在这里插入图片描述
在实验过程中,注意寄存器在时钟下降沿进行写使能端操作。为了缩短分支的冒险,应当在ID/EX和IF/ID寄存器中添加condep输入信号。为实现暂停操作,在PC寄存器和IF/ID寄存器添加stall输入信号。

4. 模块详细分析

4.1 取指令部分(IF)

4.1.1 PCAdd4

主要实现代码:

module PCadd4(PC_o,PCadd4);
 input [31:0] PC_o;//偏移量
 output [31:0] PCadd4;//新指令地址
 CLA_32 cla32(PC_o,4,0, PCadd4, Cout);
endmodule

4.1.2 PC 寄存器的设计与实现

主要代码为:

module PC(IF_Result,Clk,En,Clrn,IF_Addr,stall);
 input [31:0]IF_Result;
 input Clk,En,Clrn,stall;
 output [31:0]IF_Addr;
 wire [31:0]IF_Addr_n;
 wire En_S;
 assign En_S=En&~stall;
 D_FFEC32 pc(IF_Result,Clk,En_S,Clrn,IF_Addr,IF_Addr_n);
endmodule

4.1.3 指令存储器的设计与实现

主要代码:

module INSTMEM(Addr,Inst);//指令存储器
 input[31:0]Addr;
 //状态为'0',写指令寄存器,否则为读指令寄存器
 output[31:0]Inst;
 wire[31:0]Rom[31:0];
 assign Rom[5'h00]=32'h20010008;//addi $1,$0,8 $1=8 001000 00000 00001 0000000000001000
 assign Rom[5'h01]=32'h3402000C;//ori $2,$0,12 $2=12
 assign Rom[5'h02]=32'h00221820;//add $3,$1,$2 $3=20//数据冒险
 assign Rom[5'h03]=32'h00412022;//sub $4,$2,$1 $4=4//内部前推
 assign Rom[5'h04]=32'h00222824;//and $5,$1,$2
 assign Rom[5'h05]=32'h00223025;//or $6,$1,$2
 assign Rom[5'h06]=32'h14220006;//bne $1,$2,6//00010100001000010000000000000110 缩短分
支的延迟
 assign Rom[5'h07]=32'h00221820;//add $3,$1,$2 $3=20
 assign Rom[5'h08]=32'h00412022;//sub $4,$2,$1 $4=4
 assign Rom[5'h09]=32'h14220002;// bme $1,$2,2
 assign Rom[5'h0A]=32'h0800000D;// J 0D
 assign Rom[5'h0B]=32'h00221820;//add $3,$1,$2 $3=20
 assign Rom[5'h0C]=32'h00412022;//sub $4,$2,$1 $4=4
 assign Rom[5'h0D]=32'hAD02000A;//sw $2 10($8) memory[$8+10]=12
 assign Rom[5'h0E]=32'h8D04000A;//lw $4 10($8) $4=12
 assign Rom[5'h0F]=32'h10440002;//beq $2,$4,2//lw 数据冒险
 assign Rom[5'h10]=32'h20210004;//addi $1,$1,4 //00100000001000010000000000000100
 流水线 CPU 的设计与实验
 assign Rom[5'h11]=32'h00222824;//and $5,$1,$2
 assign Rom[5'h12]=32'h14220006;//bne $1,$2,6
 assign Rom[5'h13]=32'h30470009;//andi $7,$2,9
 assign Rom[5'h14]=32'h382300EF;//xori $3,$10xef
 assign Rom[5'h15]=32'h3C011234;//lui $1,0x1234
 assign Rom[5'h16]=32'h00021900;//sll $3,$2,4
 assign Rom[5'h17]=32'h00011102;//srl $1,$2,4
 assign Rom[5'h18]=32'h00020903;//sra $3,$1,4//数据冒险
 assign Rom[5'h19]=32'h0C00001D;//Jal 1D
 assign Rom[5'h1A]=32'h08000007;//J 07
 assign Rom[5'h1B]=32'h00021900;//sll $3,$2,4
 assign Rom[5'h1C]=32'h00021903;//sra $3,$2,4
 assign Rom[5'h1D]=32'h00021900;//sll $3,$2,4
 assign Rom[5'h1E]=32'h00021903;//sra $3,$2,4
 assign Rom[5'h1F]=32'h03E00008;//Jr 1A
 assign Inst=Rom[Addr[6:2]];
endmodule

4.1.4 32 位 4 选 1 选择器的设计与实现

主要代码:

module MUX4X32(A0, A1, A2, A3, S, Y);
 input [31:0] A0, A1, A2, A3;
 input [1:0] S;
 output [31:0] Y;
 function [31:0] select;
 input [31:0] A0, A1, A2, A3;
 input [1:0] S;
 case(S)
 2'b00: select = A0;
 2'b01: select = A1;
 2'b10: select = A2;
 2'b11: select = A3;
 endcase
 endfunction
 assign Y = select (A0, A1, A2, A3, S);
endmodule

4.1.5 REG_ifid 设计与实现

主要代码:

module REG_ifid(D0,D1,En,Clk,Clrn,Q0,Q1,stall,condep);
 input [31:0]D0,D1;
 input En,Clk,Clrn;
 input stall,condep;
 output [31:0]Q0,Q1;
 wire En_S,Clrn_C;
 wire [31:0]Q0n,Q1n;
 assign En_S=En&~stall;
 assign Clrn_C=Clrn&~condep;
 D_FFEC32 q0(D0,Clk,En_S,Clrn_C,Q0,Q0n);
 D_FFEC32 q1(D1,Clk,En_S,Clrn_C,Q1,Q1n);
endmodule

4.2 指令译码部分(ID)

4.2.1 控制器(CONUNIT)的设计与实现

实现CONUNIT的verilog代码如下:

module CONUNIT(E_Op,Op,E_Func,Func,Z,Regrt,Se,Wreg,Aluqb,Aluc,Wmem,Pcsrc,Reg2reg,shift,j,Rs,Rt,E_Rd,M_Rd,E_Wreg,M_Wreg,FwdA,FwdB,E_Reg2reg,stall,condep);
    input [5:0]Op,Func,E_Op,E_Func;
    input Z;
    input E_Wreg,M_Wreg,E_Reg2reg;
    input [4:0]E_Rd,M_Rd,Rs,Rt;
    output Regrt,Se,Wreg,Aluqb,Wmem,Reg2reg,stall,condep;
    output [1:0]Pcsrc;
    output [3:0]Aluc;
    output shift;
    output j;
    output reg [1:0]FwdA,FwdB;
    wire i_add = (Op == 6'b000000 & Func == 6'b100000)?1:0;
    wire i_sub = (Op == 6'b000000 & Func == 6'b100010)?1:0;
    wire i_and = (Op == 6'b000000 & Func == 6'b100100)?1:0;
    wire i_or  = (Op == 6'b000000 & Func == 6'b100101)?1:0;
    wire i_xor = (Op == 6'b000000 & Func == 6'b100110)?1:0;
    wire i_sll = (Op == 6'b000000 & Func == 6'b000000)?1:0;
    wire i_srl = (Op == 6'b000000 & Func == 6'b000010)?1:0;
    wire i_sra = (Op == 6'b000000 & Func == 6'b000011)?1:0;
    wire i_jr  = (Op == 6'b000000 & Func == 6'b001000)?1:0;
    wire E_jr  = (E_Op == 6'b000000 & E_Func == 6'b001000)?1:0;
    //R
    wire i_addi = (Op == 6'b001000)?1:0;
    wire i_andi = (Op == 6'b001100)?1:0; 
    wire i_ori  = (Op == 6'b001101)?1:0;
    wire i_xori = (Op == 6'b001110)?1:0;
    wire i_lw   = (Op == 6'b100011)?1:0;
    wire i_sw   = (Op == 6'b101011)?1:0;
    wire i_beq  = (Op == 6'b000100)?1:0;
    wire i_bne  = (Op == 6'b000101)?1:0;
    wire i_lui  = (Op == 6'b001111)?1:0;
    //I
    wire i_j    = (Op == 6'b000010)?1:0;
    wire i_jal  = (Op == 6'b000011)?1:0;
    wire E_j    = (E_Op == 6'b000010)?1:0;
    wire E_jal  = (E_Op == 6'b000011)?1:0;
    //J
    wire E_beq = (E_Op == 6'b000100)?1:0;
    wire E_bne = (E_Op == 6'b000101)?1:0;
    wire E_Inst = i_add|i_sub|i_and|i_or|i_sw|i_beq|i_bne;
    assign Wreg = i_add|i_sub|i_and|i_or|i_xor|i_sll|i_srl|i_sra|i_addi|i_andi|i_ori|i_or|i_xori|i_lw|i_lui|i_jal;
    assign Regrt = i_addi|i_andi|i_ori|i_xori|i_lw|i_sw|i_lui|i_beq|i_bne|i_j|i_jal;
    assign Reg2reg  = i_add|i_sub|i_and|i_or|i_xor|i_sll|i_srl|i_sra|i_addi|i_andi|i_ori|i_xori|i_sw|i_beq|i_bne|i_j|i_jal;
    assign Aluqb = i_add | i_sub | i_and | i_or | i_xor | i_sll | i_srl | i_sra | i_beq | i_bne |i_j;
    assign Se   = i_addi | i_lw | i_sw | i_beq | i_bne;
    assign Aluc[3] = i_sra;
    assign Aluc[2] = i_xor |i_lui | i_sll | i_srl | i_sra |i_xori;
    assign Aluc[1] = i_and | i_or | i_lui | i_srl | i_sra | i_andi | i_ori;
    assign Aluc[0] = i_sub | i_ori | i_or | i_sll | i_srl |i_sra| i_beq | i_bne;
    assign Wmem = i_sw;
    assign Pcsrc[0] = E_jal | E_j | (E_beq&Z) | (E_bne&~Z);
    assign Pcsrc[1] = E_j | E_jr | E_jal;
    assign shift = i_sll | i_srl | i_sra;
    assign j = i_jal | i_jr;
    always@(E_Rd,M_Rd,E_Wreg,M_Wreg,Rs,Rt,i_add,i_sub,i_and,i_or,i_sw,i_beq,i_bne)begin
        FwdA=2'b00;
        if((Rs==E_Rd)&(E_Rd!=0)&(E_Wreg==1))begin
            FwdA=2'b10;
        end else begin
            if((Rs==M_Rd)&(M_Rd!=0)&(M_Wreg==1))begin
                FwdA=2'b01;
            end
        end
    end
    always@(E_Rd,M_Rd,E_Wreg,M_Wreg,Rs,Rt,i_add,i_sub,i_and,i_or,i_sw,i_beq,i_bne)begin
        FwdB=2'b00;
        if((Rt==E_Rd)&((i_add==1)|(i_sub==1)|(i_and==1)|(i_or==1)|(i_sw==1)|(i_beq==1)|(i_bne==1))&(E_Rd!=0)&(E_Wreg==1))begin
            FwdB=2'b10;
        end else begin
            if((Rt==M_Rd)&((i_add==1)|(i_sub==1)|(i_and==1)|(i_or==1)|(i_sw==1)|(i_beq==1)|(i_bne==1))&(M_Rd!=0)&(M_Wreg==1))begin
                FwdB=2'b01;
            end
        end
    end
    assign stall=((Rs==E_Rd)|(Rt==E_Rd))&(E_Reg2reg==0)&(E_Rd!=0)&(E_Wreg==1);
    assign condep=(E_jal)|(E_jr)|(E_beq&Z)|(E_bne&~Z);
endmodule

4.2.2 5 位 2 选 1 选择器的设计与实现

实现代码如下:

module MUX2X5(A0,A1,S,Y);
 input [4:0]A0,A1;
 input S;
 output [4:0] Y;
 function [4:0] select;
 input [4:0] A0,A1;
 input S;
 case(S)
 1'b0:select=A0;
 1'b1:select=A1;
 endcase
 endfunction
 assign Y=select(A0,A1,S);
endmodule

4.2.3 16 位-32 位扩展器的设计与实现

实现代码如下:

module EXT16T32(X,Se,Y);
 input [15:0]X;
 input Se;
 output [31:0]Y;
 wire [31:0]E0,E1;
 wire [15:0]e={16{X[15]}};
 parameter z=16'b0;
 assign E0={z,X};
 assign E1={e,X};
 MUX2X32 i(E0,E1,Se,Y);
endmodule

4.2.4 26 位-32 位移位器的设计与实现

module SHIFTER_COMBINATION(X,PCADD4,Sh);
 input [25:0] X;
 input [31:0] PCADD4;
 output [31:0] Sh;
 parameter z=2'b00;
assign Sh={PCADD4[3:0],X[25:0],z};
endmodule

4.2.5 固定移位器(SHIFTER32_L2)的设计与实现

主要代码实现:

module SHIFTER32_L2(X,Sh);
 input [31:0] X;
 output [31:0] Sh;
 parameter z=2'b00;
 assign Sh={X[29:0],z};
endmodule

4.2.6 32 位 2 选 1 选择器的设计与实现

module MUX2X32(A0,A1,S,Y);
 input [31:0]A0,A1;
 input S;
 output [31:0]Y;
 function [31:0]select;
 input [31:0]A0,A1;
 input S;
 case(S)
 1'b0:select=A0;
 1'b1:select=A1;
 endcase
 endfunction
 assign Y = select(A0,A1,S);

4.2.7 32 位加/减法器的设计与实现

32 位加/减法器的功能是完成 32 位的加法/减法运算。由于:
A − B = A + (−B ) = A + B + 1
故可以用加法器实现减法操作。下面给出其模块 Verilog 实现代码:

module ADDSUB_32(X,Y,Sub,S);
 input [31:0]X,Y;
 wire Cout;
 input Sub;
 output [31:0]S;
 CLA_32 adder0(X,Y^{32{Sub}},Sub,S,Cout);
 endmodule

下面给出其模块 CLA_32 Verilog 实现代码:

module CLA_32(X,Y,Cin,S,Cout);
 input[31:0]X,Y;
 input Cin;
 output[31:0]S;
 output Cout;
 wire Cout0,Cout1,Cout2,Cout3,Cout4,Cout5,Cout6;
 CLA_4 add0(X[3:0],Y[3:0],Cin,S[3:0],Cout0);
 CLA_4 add1(X[7:4],Y[7:4],Cout0,S[7:4],Cout1);
 CLA_4 add2(X[11:8],Y[11:8],Cout1,S[11:8],Cout2);
 CLA_4 add3(X[15:12],Y[15:12],Cout2,S[15:12],Cout3);
 CLA_4 add4(X[19:16],Y[19:16],Cout3,S[19:16],Cout4);
 CLA_4 add5(X[23:20],Y[23:20],Cout4,S[23:20],Cout5);
 CLA_4 add6(X[27:24],Y[27:24],Cout5,S[27:24],Cout6);
 CLA_4 add7(X[31:28],Y[31:28],Cout6,S[31:28],Cout);
endmodule

下面给出其模块 CLA_4 Verilog 实现代码:

module CLA_4(X,Y,Cin,S,Cout);
 input [3:0]X,Y;
 output Cout;
 input Cin;
 output [3:0]S;
 and i0(Y_3,X[3],Y[3]);
 or i1(X_3,X[3],Y[3]);
 and i2(Y_2,X[2],Y[2]);
 or i3(X_2,X[2],Y[2]);
 and i4(Y_1,X[1],Y[1]);
 or i5(X_1,X[1],Y[1]);
 and i6(Y_0,X[0],Y[0]);
 or i7(X_0,X[0],Y[0]);
 not i01(Y_31,Y_3);
 nand i02(Y_32,X_3,Y_2);
 nand i03(Y_33,X_3,X_2,Y_1);
 nand i04(Y_34,X_3,X_2,X_1,Y_0);
 nand i05(Y_35,X_3,X_2,X_1,X_0,Cin);
 nand i00(Cout,Y_31,Y_32,Y_33,Y_34,Y_35);//Cout 的输出门级电路实现
 not i_2(Y__3,Y_3);
 and i21(Y_21,Y__3,X_3);
 not i22(Y_22,Y_2);
 nand i23(Y_23,X_2,Y_1);
 nand i24(Y_24,X_2,X_1,Y_0);
 nand i25(Y_25,X_2,X_1,X_0,Cin);
 nand i26(Y_26,Y_22,Y_23,Y_24,Y_25);
 xor i20(S[3],Y_21,Y_26);//S3 的输出门级电路实现
 not i_1(Y__2,Y_2);
 and i11(Y_11,Y__2,X_2);
 not i12(Y_12,Y_1);
 nand i13(Y_13,X_1,Y_0);
 nand i14(Y_14,X_1,X_0,Cin);
 nand i15(Y_15,Y_12,Y_13,Y_14);
 xor i10(S[2],Y_11,Y_15);//S2 的输出门级电路实现
 not i_0(Y__1,Y_1);
 and i51(Y_51,Y__1,X_1);
 not i52(Y_52,Y_0);
 nand i53(Y_53,X_0,Cin);
 nand i54(Y_54,Y_52,Y_53);
 xor i50(S[1],Y_51,Y_54);//S1 的输出门级电路
 not i41(Y__0,Y_0);
 and i42(Y_4,Y__0,X_0);
 xor i40(S[0],Y_4,Cin);//S0 的输出门级电路
endmodule

4.2.8 寄存器堆(REGFILE)的设计与实现

实现REGFILE的代码如下:

 module REGFILE(Ra,Rb,D,Wr,We,Clk,Clrn,Qa,Qb);
 input [4:0]Ra,Rb,Wr;
 input [31:0]D;
 input We,Clk,Clrn;
 output [31:0]Qa,Qb;
 wire [31:0]Y;
wire [31:0]Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0;
 DEC5T32E dec(Wr,We,Y);//5-32 译码器
REG32 reg32(D,Y,Clk,Clrn,Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0);
Ra[4:0]
Rb[4:0]
Wr[4:0]
D[31:0]
We
Clk
Qa[31:0]
Qb[31:0]
REGFILE
图 6-1 REGFILE 逻辑结构
Clrn
 流水线 CPU 的设计与实验
计算机科学与工程学院 22
//32 个寄存器
MUX32X32 select1(Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,
Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0,Ra,Qa);
//32 位 32 选 1 选择器
MUX32X32 select2(Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,
Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0,Rb,Qb);
//32 位 32 选 1 选择器
endmodule

5-32 译码器的代码实现为:

module DEC5T32E(I,En,Y);
 input [4:0] I;
 input En;
 output [31:0] Y;
 reg [31:0] Y;
 always@(En or I)
 begin
 if(En)
 begin
 case(I)
 5'b00000:Y=32'b00000000000000000000000000000001;
5'b00001:Y=32'b00000000000000000000000000000010;
5'b00010:Y=32'b00000000000000000000000000000100;
5'b00011:Y=32'b00000000000000000000000000001000;
5'b00100:Y=32'b00000000000000000000000000010000;
5'b00101:Y=32'b00000000000000000000000000100000;
5'b00110:Y=32'b00000000000000000000000001000000;
 5'b00111:Y=32'b00000000000000000000000010000000;
 5'b01000:Y=32'b00000000000000000000000100000000;
5'b01001:Y=32'b00000000000000000000001000000000;
5'b01010:Y=32'b00000000000000000000010000000000;
5'b01011:Y=32'b00000000000000000000100000000000;
5'b01100:Y=32'b00000000000000000001000000000000;
5'b01101:Y=32'b00000000000000000010000000000000;
5'b01110:Y=32'b00000000000000000100000000000000;
5'b01111:Y=32'b00000000000000001000000000000000;
5'b10000:Y=32'b00000000000000010000000000000000;
 5'b10001:Y=32'b00000000000000100000000000000000;
 5'b10010:Y=32'b00000000000001000000000000000000;
5'b10011:Y=32'b00000000000010000000000000000000;
5'b10100:Y=32'b00000000000100000000000000000000;
5'b10101:Y=32'b00000000001000000000000000000000;
5'b10110:Y=32'b00000000010000000000000000000000;
5'b10111:Y=32'b00000000100000000000000000000000;
5'b11000:Y=32'b00000001000000000000000000000000;
5'b11001:Y=32'b00000010000000000000000000000000;
5'b11010:Y=32'b00000100000000000000000000000000;
 5'b11011:Y=32'b00001000000000000000000000000000;
 5'b11100:Y=32'b00010000000000000000000000000000;
5'b11101:Y=32'b00100000000000000000000000000000;
5'b11110:Y=32'b01000000000000000000000000000000;
5'b11111:Y=32'b10000000000000000000000000000000;
 endcase
 end
 else
 Y=32'b00000000000000000000000000000000;
 end
endmodule

32 位 32 选 1 选择器代码实现为:

module MUX32X32(Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0,S,Y);
input [31:0]Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0;
 input [4:0]S;
 output [31:0]Y;
 function [31:0]select;
 input [31:0]Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0;
 input [4:0]S;
 case(S)
 5'b00000:select=Q0;
 5'b00001:select=Q1;
 5'b00010:select=Q2;
 5'b00011:select=Q3;
 5'b00100:select=Q4;
 5'b00101:select=Q5;
 5'b00110:select=Q6;
 5'b00111:select=Q7;
 5'b01000:select=Q8;
 5'b01001:select=Q9;
 5'b01010:select=Q10;
 5'b01011:select=Q11;
 5'b01100:select=Q12;
 5'b01101:select=Q13;
 5'b01110:select=Q14;
 5'b01111:select=Q15;
 5'b10000:select=Q16;
 5'b10001:select=Q17;
 5'b10010:select=Q18;
 5'b10011:select=Q19;
 5'b10100:select=Q20;
 5'b10101:select=Q21;
 5'b10110:select=Q22;
 5'b10111:select=Q23;
 5'b11000:select=Q24;
 5'b11001:select=Q25;
 5'b11010:select=Q26;
 5'b11011:select=Q27;
 5'b11100:select=Q28;
 5'b11101:select=Q29;
 5'b11110:select=Q30;
 5'b11111:select=Q31;
 endcase
 endfunction
assign Y = select(Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0,S);
endmodule

32 个寄存器代码实现为:

module REG32(D,En,Clk,Clrn,Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,
Q19,Q18,Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0);
 input[31:0]D,En;
 input Clk,Clrn;
 output [31:0]Q31,Q30,Q29,Q28,Q27,Q26,Q25,Q24,Q23,Q22,Q21,Q20,Q19,Q18,
Q17,Q16,Q15,Q14,Q13,Q12,Q11,Q10,Q9,Q8,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0;
wire [31:0]Qn31,Qn30,Qn29,Qn28,Qn27,Qn26,Qn25,Qn24,Qn23,Qn22,Qn21,Qn20,
Qn19,Qn18,Qn17,Qn16,Qn15,Qn14,Qn13,Qn12,Qn11,Qn10,Qn9,Qn8,Qn7,Qn6,Qn5,Qn4,
Qn3,Qn2,Qn1,Qn0;
 D_FFEC32 q31(D,Clk,En[31],Clrn,Q31,Qn31);
 D_FFEC32 q30(D,Clk,En[30],Clrn,Q30,Qn30);
 D_FFEC32 q29(D,Clk,En[29],Clrn,Q29,Qn29);
 D_FFEC32 q28(D,Clk,En[28],Clrn,Q28,Qn28);
 D_FFEC32 q27(D,Clk,En[27],Clrn,Q27,Qn27);
 D_FFEC32 q26(D,Clk,En[26],Clrn,Q26,Qn26);
 D_FFEC32 q25(D,Clk,En[25],Clrn,Q25,Qn25);
 D_FFEC32 q24(D,Clk,En[24],Clrn,Q24,Qn24);
 D_FFEC32 q23(D,Clk,En[23],Clrn,Q23,Qn23);
 D_FFEC32 q22(D,Clk,En[22],Clrn,Q22,Qn22);
 D_FFEC32 q21(D,Clk,En[21],Clrn,Q21,Qn21);
 D_FFEC32 q20(D,Clk,En[20],Clrn,Q20,Qn20);
 D_FFEC32 q19(D,Clk,En[19],Clrn,Q19,Qn19);
 D_FFEC32 q18(D,Clk,En[18],Clrn,Q18,Qn18);
 D_FFEC32 q17(D,Clk,En[17],Clrn,Q17,Qn17);
 D_FFEC32 q16(D,Clk,En[16],Clrn,Q16,Qn16);
 D_FFEC32 q15(D,Clk,En[15],Clrn,Q15,Qn15);
 D_FFEC32 q14(D,Clk,En[14],Clrn,Q14,Qn14);
 D_FFEC32 q13(D,Clk,En[13],Clrn,Q13,Qn13);
 D_FFEC32 q12(D,Clk,En[12],Clrn,Q12,Qn12);
 D_FFEC32 q11(D,Clk,En[11],Clrn,Q11,Qn11);
 D_FFEC32 q10(D,Clk,En[10],Clrn,Q10,Qn10);
 D_FFEC32 q9(D,Clk,En[9],Clrn,Q9,Qn9);
 D_FFEC32 q8(D,Clk,En[8],Clrn,Q8,Qn8);
 D_FFEC32 q7(D,Clk,En[7],Clrn,Q7,Qn7);
 D_FFEC32 q6(D,Clk,En[6],Clrn,Q6,Qn6);
 D_FFEC32 q5(D,Clk,En[5],Clrn,Q5,Qn5);
 D_FFEC32 q4(D,Clk,En[4],Clrn,Q4,Qn4);
 D_FFEC32 q3(D,Clk,En[3],Clrn,Q3,Qn3);
 D_FFEC32 q2(D,Clk,En[2],Clrn,Q2,Qn2);
 D_FFEC32 q1(D,Clk,En[1],Clrn,Q1,Qn1);
 assign Q0=0;
 assign Qn0=0;
endmodule

带有异步清零的 32 位 D 触发器的代码实现:

module D_FFEC32(D,Clk,En,Clrn,Q,Qn);
 input[31:0]D;
 input Clk,En,Clrn;
 output[31:0]Q,Qn;
 D_FFEC d0(D[0],Clk,En,Clrn,Q[0],Qn[0]);
 D_FFEC d1(D[1],Clk,En,Clrn,Q[1],Qn[1]);
 D_FFEC d2(D[2],Clk,En,Clrn,Q[2],Qn[2]);
 D_FFEC d3(D[3],Clk,En,Clrn,Q[3],Qn[3]);
 D_FFEC d4(D[4],Clk,En,Clrn,Q[4],Qn[4]);
 D_FFEC d5(D[5],Clk,En,Clrn,Q[5],Qn[5]);
 D_FFEC d6(D[6],Clk,En,Clrn,Q[6],Qn[6]);
 D_FFEC d7(D[7],Clk,En,Clrn,Q[7],Qn[7]);
 D_FFEC d8(D[8],Clk,En,Clrn,Q[8],Qn[8]);
 D_FFEC d9(D[9],Clk,En,Clrn,Q[9],Qn[9]);
 D_FFEC d10(D[10],Clk,En,Clrn,Q[10],Qn[10]);
 D_FFEC d11(D[11],Clk,En,Clrn,Q[11],Qn[11]);
 D_FFEC d12(D[12],Clk,En,Clrn,Q[12],Qn[12]);
 D_FFEC d13(D[13],Clk,En,Clrn,Q[13],Qn[13]);
 D_FFEC d14(D[14],Clk,En,Clrn,Q[14],Qn[14]);
 D_FFEC d15(D[15],Clk,En,Clrn,Q[15],Qn[15]);
 D_FFEC d16(D[16],Clk,En,Clrn,Q[16],Qn[16]);
 D_FFEC d17(D[17],Clk,En,Clrn,Q[17],Qn[17]);
 D_FFEC d18(D[18],Clk,En,Clrn,Q[18],Qn[18]);
 D_FFEC d19(D[19],Clk,En,Clrn,Q[19],Qn[19]);
 D_FFEC d20(D[20],Clk,En,Clrn,Q[20],Qn[20]);
 D_FFEC d21(D[21],Clk,En,Clrn,Q[21],Qn[21]);
 D_FFEC d22(D[22],Clk,En,Clrn,Q[22],Qn[22]);
 D_FFEC d23(D[23],Clk,En,Clrn,Q[23],Qn[23]);
 D_FFEC d24(D[24],Clk,En,Clrn,Q[24],Qn[24]);
 D_FFEC d25(D[25],Clk,En,Clrn,Q[25],Qn[25]);
 D_FFEC d26(D[26],Clk,En,Clrn,Q[26],Qn[26]);
 D_FFEC d27(D[27],Clk,En,Clrn,Q[27],Qn[27]);
 D_FFEC d28(D[28],Clk,En,Clrn,Q[28],Qn[28]);
 D_FFEC d29(D[29],Clk,En,Clrn,Q[29],Qn[29]);
 D_FFEC d30(D[30],Clk,En,Clrn,Q[30],Qn[30]);
 D_FFEC d31(D[31],Clk,En,Clrn,Q[31],Qn[31]);
endmodule

带有使能端 D 触发器的代码实现:

module D_FFEC(D,Clk,En,Clrn,Q,Qn);
 input D,Clk,En,Clrn;
 output Q,Qn;
 wire Y0,Y_C;
 MUX2X1 m0(Q,D,En,Y0);
 and i0(Y_C,Y0,Clrn);
 D_FF d0(Y_C,Clk,Q,Qn);
endmodule

2 选 1 选择器的代码实现:

module MUX2X1(A0,A1,S,Y);
 input A0,A1,S;
 output Y;
 not i0(S_n,S);
 nand i1(A0_S,A0,S_n);
 nand i2(A1_S,A1,S);
 nand i3(Y,A0_S,A1_S);
endmodule

D 锁存器的代码实现:

module D_FF(D,Clk,Q,Qn);
 input D,Clk;
 output Q,Qn;
 wire Clkn,Q0,Qn0;
 not i0(Clkn,Clk);
 D_Latch d0(D,Clkn,Q0,Qn0);
 D_Latch d1(Q0,Clk,Q,Qn);
endmodule

D 触发器的代码实现:

module D_Latch(D,En,Q,Qn);
 input D,En;
 output Q,Qn;
 wire Sn,Rn,Dn;
 not i0(Dn,D);
 nand i1(Sn,D,En);
 nand i2(Rn,En,Dn);
 nand i3(Q,Sn,Qn);
 nand i4(Qn,Q,Rn);
endmodule

4.2.9 REG_idex 设计与实现

module REG_idex(D17,D16,D15,D14,D13,D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,En,Clk,Clrn,Q0,Q1,Q2
,Q3,Q4,Q5,Q6,Q7,Q8,Q9,Q10,D11,D12,Q11,Q12,Q13,stall,Q14,Q15,Q16,Q17,condep);
 input [31:0] D15,D14,D6,D7,D8,D9,D13;
 input [5:0]D3,D17;
 input [4:0]D10;
 input [3:0]D4;
 input [1:0]D11,D12;
 input D0,D1,D2,D5,D16;
 input En,Clk,Clrn,condep,stall;

 output [31:0] Q15,Q14,Q6,Q7,Q8,Q9,Q13;
 output [5:0] Q3,Q17;
 output [4:0]Q10;
 output [3:0]Q4;
 output [1:0]Q11,Q12;
 output Q0,Q1,Q2,Q5,Q16;

 wire [31:0] Qn15,Qn6,Qn7,Qn8,Qn9,Qn13,Qn14;
 wire [5:0] Qn3,Qn17;
 wire [4:0]Qn10;
 wire [3:0]Qn4;
 wire [1:0]Qn11,Qn12;
 wire Qn0,Qn1,Qn2,Qn5,Qn16;
 wire Clrn_SC;
 assign Clrn_SC=Clrn&~stall&~condep;

 D_FFEC q0(D0,Clk,En,Clrn_SC,Q0,Qn0);
 D_FFEC q1(D1,Clk,En,Clrn_SC,Q1,Qn1);
 D_FFEC q2(D2,Clk,En,Clrn_SC,Q2,Qn2);
 D_FFEC6 q3(D3,Clk,En,Clrn_SC,Q3,Qn3);
 D_FFEC4 q4(D4,Clk,En,Clrn_SC,Q4,Qn4);
 D_FFEC q5(D5,Clk,En,Clrn_SC,Q5,Qn5);
 D_FFEC32 q6(D6,Clk,En,Clrn_SC,Q6,Qn6);
 D_FFEC32 q7(D7,Clk,En,Clrn_SC,Q7,Qn7);
 D_FFEC32 q8(D8,Clk,En,Clrn_SC,Q8,Qn8);
 D_FFEC32 q9(D9,Clk,En,Clrn_SC,Q9,Qn9);
 D_FFEC5 q10(D10,Clk,En,Clrn_SC,Q10,Qn10);
 D_FFEC2 q11(D11,Clk,En,Clrn_SC,Q11,Qn11);
 D_FFEC2 q12(D12,Clk,En,Clrn_SC,Q12,Qn12);
 D_FFEC32 q13(D13,Clk,En,Clrn_SC,Q13,Qn13);
 D_FFEC32 q14(D14,Clk,En,Clrn_SC,Q14,Qn14);
 D_FFEC32 q15(D15,Clk,En,Clrn_SC,Q15,Qn15);
 D_FFEC q16(D16,Clk,En,Clrn_SC,Q16,Qn16);
D_FFEC6 q17(D17,Clk,En,Clrn_SC,Q17,Qn17);
endmodule

4.3 执行部分(EX)

4.3.1 MUX4X32 设计与实现

代码实现如下:

module MUX4X32(A0, A1, A2, A3, S, Y);
 input [31:0] A0, A1, A2, A3;
 input [1:0] S;
 output [31:0] Y;
 function [31:0] select;
 input [31:0] A0, A1, A2, A3;
 input [1:0] S;
 case(S)
 2'b00: select = A0;
 2'b01: select = A1;
 2'b10: select = A2;
 2'b11: select = A3;
 endcase
 endfunction
 assign Y = select (A0, A1, A2, A3, S);
endmodule

4.3.2 32 位 2 选 1 选择器的设计与实现

输入模块代码:

module MUX2X32(A0,A1,S,Y);
 input [31:0]A0,A1;
 input S;
 output [31:0]Y;
 function [31:0]select;
 input [31:0]A0,A1;
 input S;
 case(S)
 1'b0:select=A0;
 1'b1:select=A1;
 endcase
 endfunction
 assign Y = select(A0,A1,S);

4.3.3 运算器(ALU)的设计与实现

ALU模块的代码实现如下:

module ALU(X,Y,Aluc,R,Z);
 input[31:0]X,Y;
 input[3:0]Aluc;
 output[31:0]R;
 output Z;
 wire[31:0]d_as,d_and,d_or,d_xor,d_lui,d_sh,d;
 ADDSUB_32 as32(X,Y,Aluc[0],d_as);
 assign d_and=X&Y;
 assign d_or=X|Y;
 assign d_xor=X^Y;
 assign d_lui={Y[15:0],16'h0};
 SHIFTER shift(Y,X[4:0],Aluc[3],Aluc[1],d_sh);
 MUX6X32 select(d_and,d_or,d_xor,d_lui,d_sh,d_as,Aluc[3:0],R);
 assign Z=~|R;
endmodule

32 位 6 选 1 的代码如下:

module MUX6X32(d_and,d_or,d_xor,d_lui,d_sh,d_as,Aluc,d);
 input [31:0]d_and,d_or,d_xor,d_lui,d_sh,d_as;
 input [3:0]Aluc;
 output [31:0]d;
 function [31:0]select;
 input [31:0]d_and,d_or,d_xor,d_lui,d_sh,d_as;
 input [3:0]Aluc;
 case(Aluc)
 4'b0000:select=d_as;
 4'b0001:select=d_as;
 4'b0010:select=d_and;
 4'b0011:select=d_or;
 4'b0100:select=d_xor;
 4'b0110:select=d_lui;
 4'b0101:select=d_sh;
 4'b0111:select=d_sh;
 4'b1111:select=d_sh;
 4'b1101:select=d_sh;
 endcase
 endfunction
 assign d=select(d_and,d_or,d_xor,d_lui,d_sh,d_as,Aluc);
endmodule

4.3.4 32 位移位器的设计与实现

主要代码实现如下:

module SHIFTER(X,Sa,Arith,Right,Sh);
 input [31:0]X;
 input [4:0]Sa;
 input Arith,Right;
 output [31:0]Sh;
 wire [31:0]T4,T3,T2,T1,T0,S4,S3,S2,S1;
 wire a=X[31]&Arith;
 wire [15:0]e={16{a}};
 parameter z=16'b0000000000000000;
 wire [31:0]L1u,L1d,L2u,L2d,L3u,L3d,L4u,L4d,L5u,L5d;
 assign L1u={X[15:0],z[15:0]};
 assign L1d={e,X[31:16]};
 MUX2X32 M1l(L1u,L1d,Right,T4);
 MUX2X32 M1r(X,T4,Sa[4],S4);
 //完成第 1 级多路器实现
 assign L2u={S4[23:0],z[7:0]};
 assign L2d={e[7:0],S4[31:8]};
 MUX2X32 M2l(L2u,L2d,Right,T3);
 MUX2X32 M2r(S4,T3,Sa[3],S3);
 //完成第 2 级多路器实现
 assign L3u={S3[27:0],z[3:0]};
 assign L3d={e[3:0],S3[31:4]};
 MUX2X32 M3l(L3u,L3d,Right,T2);
 MUX2X32 M3r(S3,T2,Sa[2],S2);
 //完成第 3 级多路器实现
 assign L4u={S2[29:0],z[1:0]};
 assign L4d={e[1:0],S2[31:2]};
 MUX2X32 M4l(L4u,L4d,Right,T1);
 MUX2X32 M4r(S2,T1,Sa[1],S1);
 //完成第 4 级多路器实现
 assign L5u={S1[30:0],z[0]};
 assign L5d={e[0],S1[31:1]};
 MUX2X32 M5l(L5u,L5d,Right,T0);
MUX2X32 M5r(S1,T0,Sa[0],Sh);
//完成第 5 级多路器实现
endmodule

4.3.5 REG_exmem 设计与实现

代码实现如下:

module REG_exmem(D4,D3,D0,D1,D2,D6,D7,D8,En,Clk,Clrn,Q0,Q1,Q2,Q6,Q7,Q8,Q3,
Q4);
 input [31:0]D3,D6,D7;
 input [4:0]D8;
 input D0,D1,D2,D4;

 input En,Clk,Clrn;
 output [31:0] Q3,Q6,Q7;
 output [4:0]Q8;
 output Q0,Q1,Q2,Q4;

 wire [31:0] Qn3,Qn6,Qn7;
 wire [4:0]Qn8;
 wire Qn0,Qn1,Qn2,Qn4;
 D_FFEC q0(D0,Clk,En,Clrn,Q0,Qn0);
 D_FFEC q1(D1,Clk,En,Clrn,Q1,Qn1);
 D_FFEC q2(D2,Clk,En,Clrn,Q2,Qn2);
 D_FFEC32 q3(D3,Clk,En,Clrn,Q3,Qn3);
 D_FFEC q4(D4,Clk,En,Clrn,Q4,Qn4);
 D_FFEC32 q6(D6,Clk,En,Clrn,Q6,Qn6);
 D_FFEC32 q7(D7,Clk,En,Clrn,Q7,Qn7);
 D_FFEC5 q8(D8,Clk,En,Clrn,Q8,Qn8);
endmodule

4.4 存储器访问部分(MEM)

4.4.1 数据存储器的设计与实现

实现 DATAMEM 的 verilog 程序代码如下:

module DATAMEM(Addr,Din,Clk,We,Dout);
 input [31:0]Addr,Din;
 input Clk,We;
 output [31:0]Dout;
reg [31:0]ram[0:31];
integer i;
initial begin
 for ( i = 0 ; i <= 31 ; i = i + 1)
 ram [i] = i;
 end
always @ (posedge Clk) begin
 if (We) ram[Addr[6:2]] = Din;
end
assign Dout = ram[Addr[6:2]];
endmodule

4.4.2 REG_memwb 设计与实现

主要代码如下:

module REG_memwb(D6,D5,D0,D1,D2,D3,D4,En,Clk,Clrn,Q0,Q1,Q2,Q3,Q4,Q5,Q6);
 input D0,D1,D6;
 input [31:0] D2,D3,D5;
 input [4:0] D4;
 input En,Clk,Clrn;
 output Q0,Q1;
 output [31:0] Q2,Q3,Q6;
 output [4:0] Q4,Q5;
 wire Qn0,Qn1;
 wire [31:0] Qn2,Qn3,Qn6;
 wire [4:0] Qn4,Qn5;
 D_FFEC q0(D0,Clk,En,Clrn,Q0,Qn0);
 D_FFEC q1(D1,Clk,En,Clrn,Q1,Qn1);
 D_FFEC32 q2(D2,Clk,En,Clrn,Q2,Qn2);
 D_FFEC32 q3(D3,Clk,En,Clrn,Q3,Qn3);
 D_FFEC5 q4(D4,Clk,En,Clrn,Q4,Qn4);
endmodule

4.5 寄存器堆写回部分(WB)

4.5.1 MUX2X32 设计与实现

主要代码实现:

module MUX2X32(A0,A1,S,Y);
 input [31:0]A0,A1;
 input S;
 output [31:0]Y;
 function [31:0]select;
 input [31:0]A0,A1;
 input S;
 case(S)
 1'b0:select=A0;
 1'b1:select=A1;
 endcase
 endfunction
 assign Y = select(A0,A1,S);
endmodule

4.6 顶层模块

实现CPU的封装,在封装模块进行寄存器Clk信号的求反操作。代码如下:

module CPU(Clk,En,Clrn,IF_ADDR,EX_X,EX_Y,EX_R);

 input Clk,En,Clrn;
 output[31:0] IF_ADDR,EX_R,EX_X,EX_Y;

wire [31:0] IF_Result,IF_Addr,IF_PCadd4,IF_Inst,D,D1,ID_Qa,ID_Qb,ID_PCadd4,ID_Inst,ID_InstL2,EX_InstL2;
wire [31:0] E_R1,E_R2,E_I,X,Y,E_R,EX_PC,EX_Inst,M_R,M_S,Dout,W_D,W_C,ID_EXTIMM,Alu_X,E_NUM,ID_EXTIMM_L2,ID_PC,EX_PCadd4,M_PCadd4,W_PCadd4;
 wire [5:0] E_Op,E_Func;
 wire [4:0] ID_Wr,ID_Wr1,W_Wr,E_Rd,M_Rd;
 wire [3:0]Aluc,E_Aluc;
 wire [1:0]Pcsrc,FwdA,FwdB,E_FwdA,E_FwdB;
 wire Regrt,Se,Wreg,Aluqb,Reg2reg,Wmem,Z,shift,j,Clkn,E_j,M_j,W_j;
wire E_Wreg,E_Reg2reg,E_Wmem,E_Aluqb,Cout,M_Wreg,M_Reg2reg,M_Wmem,W_Wreg,W_Reg2reg,stall,condep;

 //IF
 not i0(Clkn,Clk);
 MUX4X32 mux4x32(IF_PCadd4,EX_PC,E_R1,EX_InstL2,Pcsrc,IF_Result);
 PC pc(IF_Result,Clk,En,Clrn,IF_Addr,stall);
 PCadd4 pcadd4(IF_Addr,IF_PCadd4);
 INSTMEM instmem(IF_Addr,IF_Inst);

REG_ifid ifid(IF_PCadd4,IF_Inst,En,Clk,Clrn,ID_PCadd4,ID_Inst,stall,
condep);

 //ID
 CONUNIT conunit(E_Op,ID_Inst[31:26],E_Func,ID_Inst[5:0],Z,Regrt,Se,Wreg,Aluqb,Aluc,Wmem,Pcsrc,Reg2reg,shift,j,ID_Inst[25:21],ID_Inst[20:16],E_Rd,M_Rd,E_Wreg,M_Wreg,FwdA,FwdB,E_Reg2reg,stall,condep);
 MUX2X5 mux2x5_1(ID_Inst[15:11],ID_Inst[20:16],Regrt,ID_Wr1);
 MUX2X5 mux2x5_2(ID_Wr1,31,j,ID_Wr);
 EXT16T32 ext16t32(ID_Inst[15:0],Se,ID_EXTIMM);//ID_EXTIMM 对应 E_I
REGFILE regfile(ID_Inst[25:21],ID_Inst[20:16],D,W_Wr,W_Wreg,Clkn,Clrn,ID_Qa,ID_Qb);
 SHIFTER32_L2 shifter2(ID_EXTIMM,ID_EXTIMM_L2);//控制冒险
 SHIFTER_COMBINATION shifter1(ID_Inst[25:0],ID_PCadd4,ID_InstL2);
 CLA_32 cla_32(ID_PCadd4,ID_EXTIMM_L2,0,ID_PC,Cout);//ID_PCadd4 对应 E_PC
 MUX2X32 mux2x32_1(D1,W_PCadd4,W_j,D);
REG_idex idex(ID_Inst[5:0],j,ID_PCadd4,ID_InstL2,ID_PC,Wreg,Reg2reg,Wmem,ID_Inst[31:26],Aluc,Aluqb,ID_Inst,ID_Qa,ID_Qb,ID_EXTIMM,ID_Wr,En,Clk,Clrn,E_Wreg,E_Reg2reg,E_Wmem,E_Op,E_Aluc,E_Aluqb,EX_Inst,E_R1,E_R2,E_I,E_Rd,FwdA,FwdB,E_FwdA,E_FwdB,EX_PC,stall,EX_InstL2,EX_PCadd4,E_j,E_Func,condep);

 //EX
 MUX4X32 mux4x32_ex_1(E_R1,D1,M_R,0,E_FwdA,Alu_X);
 MUX4X32 mux4x32_ex_2(E_R2,D1,M_R,0,E_FwdB,E_NUM);
 MUX2X32 mux2x32_2(E_I,E_NUM,E_Aluqb,Y);
 MUX2X32 mux2x32_3(Alu_X,EX_Inst,shift,X);
 ALU alu(X,Y,E_Aluc,E_R,Z);

REG_exmem exmem(E_j,EX_PCadd4,E_Wreg,E_Reg2reg,E_Wmem,E_R,E_R2,E_Rd,En,Clk,Clrn,M_Wreg,M_Reg2reg,M_Wmem,M_R,M_S,M_Rd,M_PCadd4,M_j);

 //MEM
 DATAMEM datamem(M_R,M_S,Clk,M_Wmem,Dout);

REG_memwb memwb(M_j,M_PCadd4,M_Wreg,M_Reg2reg,M_R,Dout,M_Rd,En,Clk,Clrn,W_Wreg,W_Reg2reg,W_D,W_C,W_Wr,W_PCadd4,W_j);

 //WB
MUX2X32 mux2x32_4(W_C,W_D,W_Reg2reg,D1);
assign IF_ADDR=IF_Addr;
 assign EX_R=E_R;
 assign EX_X=X;
 assign EX_Y=Y;
endmodule

4.7 仿真模块

测试代码如下:

module CPU_test;
 reg Clk,En,Clrn;
 wire[31:0] IF_ADDR,EX_R,EX_X,EX_Y;
 CPU u(Clk,En,Clrn,IF_ADDR,EX_X,EX_Y,EX_R);
 initial begin 
 Clk=0;
 Clrn=0;
 En=1;
 #10
 Clrn<=1;
 end
 always #5 Clk=~Clk;
endmodule

如仿真图所示,能够实现流水线 CPU 的基本功能。这里依旧是上升沿写入,在 CPU封装中,利用非门将时钟信号上升沿修改为下降沿。

4.8 其它模块

其它组件如D_FFEC2、D_FFEC4、D_FFEC5、D_FFEC6等,原理与D_FFEC32相似,这里不再给出代码。

5.仿真模拟分析

5.1 指令代码分析

为方便分析指令,在测试代码中进行CPU的封装。挑选重要地方进行分析:
1.assign Rom[5’h02]=32’h00221820;//add $3,$1,$2
指令含义: add $3,$1,$2 ($1=8, $2=12),此指令存在数据冒险,需要将第 1,2条指令的 ALU 计算结果提前输入到 EX 部分。
结果: EX_R=20,ALU 的计算结果为 20,即 16 进制的 0h14
如下图说示,这里的 EX_R 为 0h14,十进制后为 20,解决数据冒险问题,继续观察E_FwdA 和 E_FwdB 的数值,分别为 1 和 2,ALU 的输入分别为 MEM 部分的结果和 WB 部分的结果。观察其他数值,结果与分析一致,能较好地解决数据冒险的问题。
在这里插入图片描述
3.assign Rom[5’h03]=32’h00412022;//sub $4,$2,$1
指令含义: sub $4,$2,$1 ($1=8,$2=12),存在数据冒险和内部前推
结果:EX_R=4
如下图所示,E_FwdB 和 E_Fwda 即 EX 部分寄存器锁存的数值分别为 0,1。ALU 的输入端分别来自寄存器堆的值和 MEM 部分的计算结果。这里存在内部前推,所以寄存器在时钟周期下降沿就写入数值,观察发现 ID_Qb 在下降沿数值变化为 8。能够实现内部前推的功能。
在这里插入图片描述
4.assign Rom[5’h06]=32’h14220006;//bne $1,$2,6
指令含义:bne $1,$2,2 ($1 和$2 不相等,则跳到 8+当前 PC 地址的值)
结果:PC 地址跳到 0x34
这里存在缩短分支的延迟,减少插入气泡的数目。需要暂停两个时钟周期,这里实现了缩短分支的延迟,暂停后不再进行操作,还需将 bne 下面的两条指令清零。
在这里插入图片描述
存在跳转指令后的两个气泡
如图所示,在下两个时钟周期,将已经进入的两个指令进行了清零操作。
在这里插入图片描述
5.assign Rom[5’h 18]=32’h00020903;//sra $3,$1,4
指令含义:sra $3,$1,4,存在数据冒险
结果:EX_R=0 ,E_FwdB 值为 2,选择 MEM 部分的值作为输入
在这里插入图片描述

5.2 阻塞分析

第一个红框是流水线 CPU 因为数据冒险而实现内部前推的两个时钟周期
第二个红框是流水线 CPU 因为 bne 控制冒险而实现缩短分支延迟的时钟周期,
第三个红框是流水线 CPU 因为 lw 数据冒险而暂停的一个时钟周期,
第四个红框是流水线 PCU 因为 bne 控制冒险而实现缩短分支延迟的时钟周期

在这里插入图片描述

6.结果与体会

经过不断地努力,最后较好的实现了流水线 CPU 的基本功能。能够支持单周期的所有 20 条指令,并且能够解决 Lw,sw 数据冒险,J 型指令,beq 等跳转类指令的控制冒险,实现寄存器堆的写操作提前半个周期和缩短延迟方案。能够完整的实现指令存储器所有指令和过程,且于理论分析有符。
参考:https://blog.csdn.net/Accelerato/article/details/92847394
源代码下载链接:https://download.csdn.net/download/qq_45288566/12254638

  • 16
    点赞
  • 198
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值