Part A

一、实验目的

  理解并掌握运算器的基本电路结构及其设计方法,学会使用Verilog HDL对电路进行行为建模、结构建模以及仿真测试。

二、实验内容

  利用Verilog HDL设计一个运算器模型,并进行仿真测试。要求该运算器的字长为32位,能够实现加法、减法、逻辑与、逻辑或四种运算,并产生N(结果为负)、Z(结果为零)、V(结果溢出)、C(进位)四个标志位。要求采用层次化的建模方法,即先搭建低层模块,然后再逐级搭建高层模块。

三、实验环境

  PC机1台、Modelsim仿真软件1套。

四、实验步骤

1、电路结构设计



2、建立Verilog模型

module fadd(a,b,s,ci,co);
input a,b,ci;
output s,co;
reg s,co;
always @ (a or b or ci)
begin 
s<=(a&~b&~ci)|(~a&b&~ci)|(~a&~b&ci)|(a&b&ci);
co<=(a&b)|(a&ci)|(b&ci);
end
endmodule

module add(a,b,sub,s,c,v,n);
input [31:0]a;
input [31:0]b;
input sub;
output [31:0]s;
output c,v,n;
wire [31:0]a;
wire [31:0]b;
wire c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15,c16,c17,c18,c19,c20,c21,c22,c23,c24,c25,c26,c27,c28,c29,c30,c31;
fadd f0(a[0],b[0]^sub,s[0],sub,c1);
fadd f1(a[1],b[1]^sub,s[1],c1,c2);
fadd f2(a[2],b[2]^sub,s[2],c2,c3);
fadd f3(a[3],b[3]^sub,s[3],c3,c4);
fadd f4(a[4],b[4]^sub,s[4],c4,c5);
fadd f5(a[5],b[5]^sub,s[5],c5,c6);
fadd f6(a[6],b[6]^sub,s[6],c6,c7);
fadd f7(a[7],b[7]^sub,s[7],c7,c8);
fadd f8(a[8],b[8]^sub,s[8],c8,c9);
fadd f9(a[9],b[9]^sub,s[9],c9,c10);
fadd f10(a[10],b[10]^sub,s[10],c10,c11);
fadd f11(a[11],b[11]^sub,s[11],c11,c12);
fadd f12(a[12],b[12]^sub,s[12],c12,c13);
fadd f13(a[13],b[13]^sub,s[13],c13,c14);
fadd f14(a[14],b[14]^sub,s[14],c14,c15);
fadd f15(a[15],b[15]^sub,s[15],c15,c16);
fadd f16(a[16],b[16]^sub,s[16],c16,c17);
fadd f17(a[17],b[17]^sub,s[17],c17,c18);
fadd f18(a[18],b[18]^sub,s[18],c18,c19);
fadd f19(a[19],b[19]^sub,s[19],c19,c20);
fadd f20(a[20],b[20]^sub,s[20],c20,c21);
fadd f21(a[21],b[21]^sub,s[21],c21,c22);
fadd f22(a[22],b[22]^sub,s[22],c22,c23);
fadd f23(a[23],b[23]^sub,s[23],c23,c24);
fadd f24(a[24],b[24]^sub,s[24],c24,c25);
fadd f25(a[25],b[25]^sub,s[25],c25,c26);
fadd f26(a[26],b[26]^sub,s[26],c26,c27);
fadd f27(a[27],b[27]^sub,s[27],c27,c28);
fadd f28(a[28],b[28]^sub,s[28],c28,c29);
fadd f29(a[29],b[29]^sub,s[29],c29,c30);
fadd f30(a[30],b[30]^sub,s[30],c30,c31);
fadd f31(a[31],b[31]^sub,s[31],c31,c);
assign n=s[31];
assign v=c^c31;
endmodule

module mux21_32(f,a,b,s);
output[31:0] f;
input[31:0] a,b;
input s;
reg [31:0] f;
always @(s or a or b)
case(s)
1'd0: f=a;
1'd1: f=b;
endcase
endmodule

module ALU(op,a,b,s,n,v,c,z);
input [1:0]op;
input [31:0]a,b;
output[31:0]s;
output n,v,c,z;
wire [31:0]d,e,f,s1;
assign d=a&b;
assign e=a|b;
mux21_32 u0(f,d,e,op[0]);
add u2(a,b,op[0],s1,c,v,n);
mux21_32 u1(s,f,s1,op[1]);
assign z=~(|s);
endmodule

3、设计测试文件

`timescale 1ns / 1ns
module ALUtest;
reg clk;
reg [1:0]op;
reg [31:0]a,b;
wire [31:0]s;
wire n,v,c,z;
//op=00 AND;
//op=01 OR;
//op=10 ADD;
//op=11 SUB;
ALU A(op,a,b,s,n,v,c,z);
//clock generation
initial clk = 1;
always #50 clk = ~clk;
initial
  begin
#20  a=32'b0100_0101_0100_0000_0010_0010_0101_0001;
     b=32'b1010_0101_0010_0000_0100_0010_0011_0010;
     op=2'b00;
#100 a=32'b0100_0101_0100_0000_0010_0010_0101_0001;
     b=32'b1010_0101_0010_0000_0100_0010_0011_0010;
     op=2'b01;
#100 a=32'b0100_0101_0100_0000_0010_0010_0101_0001;
     b=32'b1010_0101_0010_0000_0100_0010_0011_0010;
     op=2'b10;
#100 a=32'b0100_0101_0100_0000_0010_0010_0101_0001;
     b=32'b1010_0101_0010_0000_0100_0010_0011_0010;
     op=2'b11;
#100 a=32'b0111_1011_1101_1110_1111_1111_1111_1111;
     b=32'b0111_1011_1101_1110_1111_1111_1111_1111;
     op=2'b11;
#100 a=32'd15;
     b=32'd9;
     op=2'b11;
#100 a=32'd9;
     b=32'd15;
     op=2'b11;
#100 $stop;
  end
endmodule

注意:测试的完备性。

4、将设计文件和测试文件输入Modesim仿真工具,并进行编译和功能仿真。

5、观测仿真波形图,分析结果是否正确。若有错误,则修改设计文件或测试文件,重新编译和仿真。

Part B

一、实验目的

  理解并掌握寄存器堆的基本电路结构及其设计方法,学会使用Verilog HDL对电路进行行为建模、结构建模以及仿真测试。

二、实验内容

  利用Verilog HDL设计一个寄存器堆模型,并进行仿真测试。要求该寄存器堆具有32个32位的寄存器,并具有2个读端口和1个写端口。要求采用层次化的建模方法,即先搭建低层模块,然后再逐级搭建高层模块。

三、实验环境

  PC机1台、Modelsim仿真软件1套。

四、实验步骤

1、电路结构设计
寄存器堆外框图:

寄存器堆内部结构图:

module registerfile(Q1,Q2,DI,clk,reset,writeen,AD,A1,A2);
output[31:0] Q1,Q2;
input[31:0] DI;
input clk,reset,writeen;
input[4:0] AD,A1,A2;

wire[31:0] decoderout;
wire[31:0] regen;
wire[31:0] q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31;

decoder dec0(decoderout,AD);

assign  regen[0]=decoderout[0] & writeen;
assign  regen[1]=decoderout[1] & writeen;
assign  regen[2]=decoderout[2] & writeen;
assign  regen[3]=decoderout[3] & writeen;
assign  regen[4]=decoderout[4] & writeen;
assign  regen[5]=decoderout[5] & writeen;
assign  regen[6]=decoderout[6] & writeen;
assign  regen[7]=decoderout[7] & writeen;
assign  regen[8]=decoderout[8] & writeen;
assign  regen[9]=decoderout[9] & writeen;
assign  regen[10]=decoderout[10] & writeen;
assign  regen[11]=decoderout[11] & writeen;
assign  regen[12]=decoderout[12] & writeen;
assign  regen[13]=decoderout[13] & writeen;
assign  regen[14]=decoderout[14] & writeen;
assign  regen[15]=decoderout[15] & writeen;
assign  regen[16]=decoderout[16] & writeen;
assign  regen[17]=decoderout[17] & writeen;
assign  regen[18]=decoderout[18] & writeen;
assign  regen[19]=decoderout[19] & writeen;
assign  regen[20]=decoderout[20] & writeen;
assign  regen[21]=decoderout[21] & writeen;
assign  regen[22]=decoderout[22] & writeen;
assign  regen[23]=decoderout[23] & writeen;
assign  regen[24]=decoderout[24] & writeen;
assign  regen[25]=decoderout[25] & writeen;
assign  regen[26]=decoderout[26] & writeen;
assign  regen[27]=decoderout[27] & writeen;
assign  regen[28]=decoderout[28] & writeen;
assign  regen[29]=decoderout[29] & writeen;
assign  regen[30]=decoderout[30] & writeen;
assign  regen[31]=decoderout[31] & writeen;

register reg0(q0,DI,clk,reset,regen[0]);
register reg1(q1,DI,clk,reset,regen[1]);
register reg2(q2,DI,clk,reset,regen[2]);
register reg3(q3,DI,clk,reset,regen[3]);
register reg4(q4,DI,clk,reset,regen[4]);
register reg5(q5,DI,clk,reset,regen[5]);
register reg6(q6,DI,clk,reset,regen[6]);
register reg7(q7,DI,clk,reset,regen[7]);
register reg8(q8,DI,clk,reset,regen[8]);
register reg9(q9,DI,clk,reset,regen[9]);
register reg10(q10,DI,clk,reset,regen[10]);
register reg11(q11,DI,clk,reset,regen[11]);
register reg12(q12,DI,clk,reset,regen[12]);
register reg13(q13,DI,clk,reset,regen[13]);
register reg14(q14,DI,clk,reset,regen[14]);
register reg15(q15,DI,clk,reset,regen[15]);
register reg16(q16,DI,clk,reset,regen[16]);
register reg17(q17,DI,clk,reset,regen[17]);
register reg18(q18,DI,clk,reset,regen[18]);
register reg19(q19,DI,clk,reset,regen[19]);
register reg20(q20,DI,clk,reset,regen[20]);
register reg21(q21,DI,clk,reset,regen[21]);
register reg22(q22,DI,clk,reset,regen[22]);
register reg23(q23,DI,clk,reset,regen[23]);
register reg24(q24,DI,clk,reset,regen[24]);
register reg25(q25,DI,clk,reset,regen[25]);
register reg26(q26,DI,clk,reset,regen[26]);
register reg27(q27,DI,clk,reset,regen[27]);
register reg28(q28,DI,clk,reset,regen[28]);
register reg29(q29,DI,clk,reset,regen[29]);
register reg30(q30,DI,clk,reset,regen[30]);
register reg31(q31,DI,clk,reset,regen[31]);

mux_32 mux0(Q1,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31,A1);
mux_32 mux1(Q2,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31,A2);
endmodule

module decoder(decoderout,waddr);
output[31:0] decoderout;
input[4:0] waddr;

reg [31:0] decoderout;
always @ (waddr)
case(waddr)
5'd0: decoderout=32'b0000_0000_0000_0000_0000_0000_0000_0001;
5'd1: decoderout=32'b0000_0000_0000_0000_0000_0000_0000_0010;
5'd2: decoderout=32'b0000_0000_0000_0000_0000_0000_0000_0100;
5'd3: decoderout=32'b0000_0000_0000_0000_0000_0000_0000_1000;
5'd4: decoderout=32'b0000_0000_0000_0000_0000_0000_0001_0000;
5'd5: decoderout=32'b0000_0000_0000_0000_0000_0000_0010_0000;
5'd6: decoderout=32'b0000_0000_0000_0000_0000_0000_0100_0000;
5'd7: decoderout=32'b0000_0000_0000_0000_0000_0000_1000_0000;
5'd8: decoderout=32'b0000_0000_0000_0000_0000_0001_0000_0000;
5'd9: decoderout=32'b0000_0000_0000_0000_0000_0010_0000_0000;
5'd10: decoderout=32'b0000_0000_0000_0000_0000_0100_0000_0000;
5'd11: decoderout=32'b0000_0000_0000_0000_0000_1000_0000_0000;
5'd12: decoderout=32'b0000_0000_0000_0000_0001_0000_0000_0000;
5'd13: decoderout=32'b0000_0000_0000_0000_0010_0000_0000_0000;
5'd14: decoderout=32'b0000_0000_0000_0000_0100_0000_0000_0000;
5'd15: decoderout=32'b0000_0000_0000_0000_1000_0000_0000_0000;
5'd16: decoderout=32'b0000_0000_0000_0001_0000_0000_0000_0000;
5'd17: decoderout=32'b0000_0000_0000_0010_0000_0000_0000_0000;
5'd18: decoderout=32'b0000_0000_0000_0100_0000_0000_0000_0000;
5'd19: decoderout=32'b0000_0000_0000_1000_0000_0000_0000_0000;
5'd20: decoderout=32'b0000_0000_0001_0000_0000_0000_0000_0000;
5'd21: decoderout=32'b0000_0000_0010_0000_0000_0000_0000_0000;
5'd22: decoderout=32'b0000_0000_0100_0000_0000_0000_0000_0000;
5'd23: decoderout=32'b0000_0000_1000_0000_0000_0000_0000_0000;
5'd24: decoderout=32'b0000_0001_0000_0000_0000_0000_0000_0000;
5'd25: decoderout=32'b0000_0010_0000_0000_0000_0000_0000_0000;
5'd26: decoderout=32'b0000_0100_0000_0000_0000_0000_0000_0000;
5'd27: decoderout=32'b0000_1000_0000_0000_0000_0000_0000_0000;
5'd28: decoderout=32'b0001_0000_0000_0000_0000_0000_0000_0000;
5'd29: decoderout=32'b0010_0000_0000_0000_0000_0000_0000_0000;
5'd30: decoderout=32'b0100_0000_0000_0000_0000_0000_0000_0000;
5'd31: decoderout=32'b1000_0000_0000_0000_0000_0000_0000_0000;
endcase
endmodule

module register(q,data,clk,reset,en);
output[31:0] q;
input[31:0] data;
input clk,reset,en;

dff u0(q[0],data[0],clk,reset,en);
dff u1(q[1],data[1],clk,reset,en);
dff u2(q[2],data[2],clk,reset,en);
dff u3(q[3],data[3],clk,reset,en);
dff u4(q[4],data[4],clk,reset,en);
dff u5(q[5],data[5],clk,reset,en);
dff u6(q[6],data[6],clk,reset,en);
dff u7(q[7],data[7],clk,reset,en);
dff u8(q[8],data[8],clk,reset,en);
dff u9(q[9],data[9],clk,reset,en);
dff u10(q[10],data[10],clk,reset,en);
dff u11(q[11],data[11],clk,reset,en);
dff u12(q[12],data[12],clk,reset,en);
dff u13(q[13],data[13],clk,reset,en);
dff u14(q[14],data[14],clk,reset,en);
dff u15(q[15],data[15],clk,reset,en);
dff u16(q[16],data[16],clk,reset,en);
dff u17(q[17],data[17],clk,reset,en);
dff u18(q[18],data[18],clk,reset,en);
dff u19(q[19],data[19],clk,reset,en);
dff u20(q[20],data[20],clk,reset,en);
dff u21(q[21],data[21],clk,reset,en);
dff u22(q[22],data[22],clk,reset,en);
dff u23(q[23],data[23],clk,reset,en);
dff u24(q[24],data[24],clk,reset,en);
dff u25(q[25],data[25],clk,reset,en);
dff u26(q[26],data[26],clk,reset,en);
dff u27(q[27],data[27],clk,reset,en);
dff u28(q[28],data[28],clk,reset,en);
dff u29(q[29],data[29],clk,reset,en);
dff u30(q[30],data[30],clk,reset,en);
dff u31(q[31],data[31],clk,reset,en);
endmodule

module dff(q,data,clk,reset,en);
output q;
input data,clk,reset,en;

reg q;
always @ (posedge clk)
    begin
        if (reset)
            q=0;
        else if (en)
                    q=data;
                else 
                    q=q;
    end
endmodule

module mux_32(q,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31,raddr);
output[31:0] q;
input[31:0] q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31;
input[4:0] raddr;

reg [31:0] q;
always @(raddr or q0 or q1 or q2 or q3 or q4 or q5 or q6 or q7 or q8 or q9 or q10 or q11 or q12 or q13 or q14 or q15 or q16 or q17 or q18 or q19 or q20 or q21 or q22 or q23 or q24 or q25 or q26 or q27 or q28 or q29 or q30 or q31)
case(raddr)
5'd0: q=q0;
5'd1: q=q1;
5'd2: q=q2;
5'd3: q=q3;
5'd4: q=q4;
5'd5: q=q5;
5'd6: q=q6;
5'd7: q=q7;
5'd8: q=q8;
5'd9: q=q9;
5'd10: q=q10;
5'd11: q=q11;
5'd12: q=q12;
5'd13: q=q13;
5'd14: q=q14;
5'd15: q=q15;
5'd16: q=q16;
5'd17: q=q17;
5'd18: q=q18;
5'd19: q=q19;
5'd20: q=q20;
5'd21: q=q21;
5'd22: q=q22;
5'd23: q=q23;
5'd24: q=q24;
5'd25: q=q25;
5'd26: q=q26;
5'd27: q=q27;
5'd28: q=q28;
5'd29: q=q29;
5'd30: q=q30;
5'd31: q=q31;
endcase
endmodule

3、设计测试文件

`timescale 1ns / 1ns
module rftest;

wire [31:0]q11,q22;
reg [31:0]data;
reg [4:0]waddr;
reg [4:0]raddr1,raddr2;
reg clk,reset,we;

registerfile r(q11,q22,data,clk,reset,we,waddr,raddr1,raddr2);

always #50 clk=~clk;

initial
   begin 
     clk=0;
     reset=1;
     we=0;
#120 reset=0;
     data=32'd1;
     we=1;
     waddr=5'd0;
#100 data=32'd2;
     waddr=5'd1;
#100 data=32'd3;
     waddr=5'd2;
#100 data=32'd4;
     waddr=5'd3;
#100 data=32'd5;
     waddr=5'd4;
#100 data=32'd6;
     waddr=5'd5;
#100 data=32'd7;
     waddr=5'd6;
#100 data=32'd8;
     waddr=5'd7;
#100 data=32'd9;
     waddr=5'd8;
#100 data=32'd10;
     waddr=5'd9;
#100 data=32'd11;
     waddr=5'd10;
#100 data=32'd12;
     waddr=5'd11;
#100 data=32'd13;
     waddr=5'd12;
#100 data=32'd14;
     waddr=5'd13;
#100 data=32'd15;
     waddr=5'd14;
#100 data=32'd16;
     waddr=5'd15;
#100 data=32'd17;
     waddr=5'd16;
#100 data=32'd18;
     waddr=5'd17;
#100 data=32'd19;
     waddr=5'd18;
#100 data=32'd20;
     waddr=5'd19;
#100 data=32'd21;
     waddr=5'd20;
#100 data=32'd22;
     waddr=5'd21;
#100 data=32'd23;
     waddr=5'd22;
#100 data=32'd24;
     waddr=5'd23;
#100 data=32'd25;
     waddr=5'd24;
#100 data=32'd26;
     waddr=5'd25;
#100 data=32'd27;
    waddr=5'd26;
#100 data=32'd28;
     waddr=5'd27;
#100 data=32'd29;
     waddr=5'd28;
#100 data=32'd30;
     waddr=5'd29;
#100 data=32'd31;
     waddr=5'd30;
#100 data=32'd32;
     waddr=5'd31;

#100 we=0;
     raddr1=5'd0;
raddr2=5'd1;
#100 raddr1=5'd1;
     raddr2=5'd2;
#100 raddr1=5'd2;
     raddr2=5'd3;
#100 raddr1=5'd3;
     raddr2=5'd4;
#100 raddr1=5'd4;
     raddr2=5'd5;
#100 raddr1=5'd5;
     raddr2=5'd6;
#100 raddr1=5'd6;
     raddr2=5'd7;
#100 raddr1=5'd7;
     raddr2=5'd8;
#100 raddr1=5'd8;
     raddr2=5'd9;
#100 raddr1=5'd9;
     raddr2=5'd10;
#100 raddr1=5'd10;
     raddr2=5'd11;
#100 raddr1=5'd11;
     raddr2=5'd12;
#100 raddr1=5'd12;
     raddr2=5'd13;
#100 raddr1=5'd13;
     raddr2=5'd14;
#100 raddr1=5'd14;
     raddr2=5'd15;
#100 raddr1=5'd15;
     raddr2=5'd16;
#100 raddr1=5'd16;
     raddr2=5'd17;
#100 raddr1=5'd17;
     raddr2=5'd18;
#100 raddr1=5'd18;
     raddr2=5'd19;
#100 raddr1=5'd19;
     raddr2=5'd20;
#100 raddr1=5'd20;
     raddr2=5'd21;
#100 raddr1=5'd21;
     raddr2=5'd22;
#100 raddr1=5'd22;
     raddr2=5'd23;
#100 raddr1=5'd23;
     raddr2=5'd24;
#100 raddr1=5'd24;
     raddr2=5'd25;
#100 raddr1=5'd25;
     raddr2=5'd26;
#100 raddr1=5'd26;
     raddr2=5'd27;
#100 raddr1=5'd27;
     raddr2=5'd28;
#100 raddr1=5'd28;
     raddr2=5'd29;
#100 raddr1=5'd29;
     raddr2=5'd30;
#100 raddr1=5'd30;
     raddr2=5'd31;
#100 raddr1=5'd31;
     raddr2=5'd0;

#200 $stop;
    end
endmodule

注意:测试的完备性。

4、将设计文件和测试文件输入Modesim仿真工具,并进行编译和功能仿真。

5、观测仿真波形图,分析结果是否正确。若有错误,则修改设计文件或测试文件,重新编译和仿真。

Part C

一、实验目的

  理解并掌握CPU控制器的基本电路结构及其设计方法,学会使用Verilog HDL对电路进行行为建模、结构建模以及仿真测试。

二、实验内容

  利用Verilog HDL设计一个多周期处理机控制器,并进行仿真测试。要求该处理机能够实现下列指令系统:


要求把指令的执行分为以下5个步骤,每个步骤用一个时钟周期。
  1、取指令及PC+1周期
  2、指令译码、读寄存器及转移周期
  3、ALU执行或者存储器地址计算周期
  4、ALU指令结束周期或者存储器访问周期
  5、写回周期

该多周期处理机的数据路径如下:

该多周期处理机的数据路径所需要的控制信号定义如下:
  WRITEPC:PC写使能信号,为1时,CLK上升沿把PC输入端的数据写入PC;
  SELLDST:存储器地址输入选择,为1时,选ALU计算出的地址,为0选PC;
  WRITEMEM:写存储器使能信号,由store指令产生;
  WRITEIR:IR写使能信号,为1时,CLK上升沿把由PC访问到的指令写入IR;
  SELLOAD:寄存器堆数据输入选择,为1时选存储器输出,为0选ALU输出;
  SELST:执行store指令时,从寄存器堆Q2端口读出寄存器rd的内容;
  WRITEREG:写寄存器堆使能信号;
  SELALUA:ALU A输入端选择,0选寄存器RS1,1选PC;
  SELALUB:ALU B输入端选择,00选寄存器RS2,01选立即数IM,10选1,11选偏移量;
  ALUOP:ALU操作控制码;
  WRITEZERO:写标志寄存器ZERO的使能信号;

三、实验环境

  PC机1台、Modelsim仿真软件1套。

四、实验步骤

1、电路结构设计与逻辑设计

电路结构图:

状态转移图:

状态转移表:

其中:
  RR=and+or+add+sub(寄存器-寄存器操作);
  RI=andi+ori+addi+subi(寄存器-立即数操作);
  BR=branch+bne+beq(转移指令);X=任意。

根据上述状态转移表,可以得到下一状态产生电路的逻辑表达式:
  D0=S0+S1RI+S1store+S3+S5;
  D1=S1RR+S1RI+S2+S3+S8;
  D2=S1load+S1store+S2+S3;
  D3=S4+S5+S8;

控制信号取值表:

根据上述控制信号取值表,可以得到控制信号产生电路的逻辑表达式:

2、建立Verilog模型

module   control(clk,start,zero,opcode,writepc,selldst,writemem,writeir,
selload,selst,writereg,selalua,selalub,aluop,writezero);

input   clk,start,zero;
input  [5:0]  opcode;
output  writepc,selldst,writemem,writeir,selload,selst,
writereg,selalua,writezero;
output [1:0]  selalub,aluop;

reg  [3:0] q;
wire [3:0] d;
wire  zero;

always @(posedge clk)
    begin
        if(start)
            q<=4'd0;
        else
            q<=d;
    end

assign d[0]=(~q[3]&~q[2]&~q[1]&~q[0])|((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&opcode[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&opcode[0]))|(~q[3]&~q[2]&q[1]&q[0])|(~q[3]&q[2]&~q[1]&q[0]);
assign d[1]=((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&~opcode[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&opcode[0]))|(~q[3]&~q[2]&q[1]&~q[0])|(~q[3]&~q[2]&q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0]);
assign d[2]=((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&~opcode[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&opcode[0]))|(~q[3]&~q[2]&q[1]&~q[0])|(~q[3]&~q[2]&q[1]&q[0]);
assign d[3]=(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0]);

assign writepc=(~q[3]&~q[2]&~q[1]&~q[0])|((~q[3]&~q[2]&~q[1]&q[0])&((opcode[3]&opcode[2]&~opcode[1]&~opcode[0])|(opcode[3]&~opcode[2]&opcode[1]&~opcode[0]&~zero)|(opcode[3]&~opcode[2]&opcode[1]&opcode[0]&zero)));
assign selldst=(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign writemem=q[3]&~q[2]&~q[1]&q[0];
assign writeir=~q[3]&~q[2]&~q[1]&~q[0];
assign selload=(~q[3]&q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign selst=(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&q[0]);
assign writereg=(~q[3]&q[2]&q[1]&~q[0])|(~q[3]&q[2]&q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign selalua=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0]);
assign selalub[1]=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0]);
assign selalub[0]=(~q[3]&~q[2]&~q[1]&q[0])|(~q[3]&~q[2]&q[1]&q[0])|(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(~q[3]&q[2]&q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign writezero=(~q[3]&q[2]&q[1]&~q[0])|(~q[3]&q[2]&q[1]&q[0]);
assign aluop[1]=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0])|((~q[3]&~q[2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&~q[2]&q[1]&q[0])&(~opcode[3]&opcode[2]))|(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|((~q[3]&q[2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&q[2]&q[1]&q[0])&(~opcode[3]&opcode[2]))|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign aluop[0]=((~q[3]&~q[2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&~q[2]&q[1]&q[0])&(~opcode[3]&opcode[2]))|((~q[3]&q[2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&q[2]&q[1]&q[0])&(~opcode[3]&opcode[2]));

endmodule

3、设计测试文件

`timescale 1ns / 1ns
module controltest;

reg clk,rst,zero;
reg [5:0] opcode;
wire writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero;
wire [1:0] selalub,aluop;

control  con(clk,rst,zero,opcode,writepc,selldst,writemem,writeir,selload,
selst,writereg,selalua,selalub,aluop,writezero);

always #50 clk=~clk;

initial
  begin
    clk=1;
    rst=0;
#20 rst=1;
#100 rst=0;//IF
#100 opcode=6'd0;//ID-- and rd,rs1,rs2     
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd1;//ID-- andi rd,rs1,imme
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd2;//ID-- or rd,rs1,rs2
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd3;//ID-- ori rd,rs1,imme
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd4;//ID-- add rd,rs1,rs2
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd5;//ID-- addi rd,rs1,imme
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd6;//ID-- sub rd,rs1,rs2
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd7;//ID-- subi rd,rs1,imme
#100//EXE
#100//WB

#100//IF     
#100 opcode=6'd8;//ID-- load rd,rs1,imme
#100//EXE
#100//MEM
#100//WB

#100//IF     
#100 opcode=6'd9;//ID-- store rd,rs1,imme
#100//EXE
#100//MEM

#100//IF     
#100 opcode=6'd10;//ID-- bne disp
     zero=1;
     
#100//IF     
#100 opcode=6'd10;//ID-- bne disp
     zero=0;

#100//IF     
#100 opcode=6'd11;//ID-- beq disp
     zero=1;
     
#100//IF     
#100 opcode=6'd11;//ID-- beq disp
     zero=0;

#100//IF     
#100 opcode=6'd12;//ID-- branch disp
     

#100 $stop;
end

endmodule

注意:测试的完备性。

4、将设计文件和测试文件输入Modesim仿真工具,并进行编译和功能仿真。

5、观测仿真波形图,分析结果是否正确。若有错误,则修改设计文件或测试文件,重新编译和仿真。

Part D

一、实验目的

  理解并掌握CPU的基本电路结构及其设计方法,学会使用Verilog HDL对电路进行行为建模、结构建模以及仿真测试。

二、实验内容

  利用Verilog HDL设计一个简单的CPU模型,并进行仿真测试。
  要求该处理机能够实现下列指令系统:

要求把指令的执行分为以下5个步骤,每个步骤用一个时钟周期。
  1、取指令及PC+1周期
  2、指令译码、读寄存器及转移周期
  3、ALU执行或者存储器地址计算周期
  4、ALU指令结束周期或者存储器访问周期
  5、写回周期

三、实验环境

  PC机1台、Modelsim仿真软件1套。

四、实验步骤

1、电路结构设计与逻辑设计

2、建立Verilog模型

module TOP(clk,rst,start,memwe,memin,memaddr,zero,n,v,c,dataout);
input clk,rst,start,memwe;
input [31:0]memin;
input [4:0]memaddr;
output [31:0]dataout;
output n,v,c,zero;
wire clk,rst;
wire writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero;
wire [5:0]opcode;
wire [1:0]aluop,selalub;
wire zero;
datapath u0(writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,selalub,aluop,writezero,clk,rst,memin,memaddr,memwe,zero,n,v,c,opcode,dataout);
control u1(clk,start,zero,opcode,writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,selalub,aluop,writezero);
endmodule

module datapath(writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,selalub,aluop,writezero,clk,rst,memin,memaddr,memwe,zero,n,v,c,opcode,dataout);
input writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero,clk,rst,memwe;
input [1:0] selalub,aluop;
input [4:0]memaddr;
input [31:0]memin;
output zero,n,v,c;
output [5:0]opcode;
output [31:0]dataout;
wire [4:0]pcout,address,memaddr,mux3out;
wire [31:0]memin,mux4out,mux5out,imme,disp;
wire memwe,zero1;
wire [31:0]dataout,Q1,datain,irout,f,aluout;
pc pc1(pcout,aluout[4:0],writepc,clk,rst);
mux21_5 mux1(address,pcout,aluout[4:0],selldst);
memory mem(dataout,datain,address,writemem,memin,memaddr,memwe,clk,rst);
//memin,memaddr,memweÊÇΪÁËÔڼĴæÆ÷ÖÐÊäÈëÊý¾Ý¶øÓÃ
ir ir1(irout,dataout,clk,rst,writeir);
mux21_32 mux2(f,aluout,dataout,selload);
mux21_5  mux3(mux3out,irout[4:0],irout[25:21],selst);
registerfile registerfile(Q1,datain,f,clk,rst,writereg,irout[25:21],irout[20:16],mux3out);
mux21_32 mux4(mux4out,Q1,{27'b0,pcout},selalua);
assign imme={irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15],irout[15:0]};
assign disp={irout[25],irout[25],irout[25],irout[25],irout[25],irout[25],irout[25:0]};
mux41_32 mux5(mux5out,datain,imme,32'd1,disp,selalub);
ALU alu1(aluop,mux4out,mux5out,aluout,n,v,c,zero1);
dff  zeroflag(zero,zero1,clk,rst,writezero);
assign opcode=irout[31:26];
endmodule

module   control(clk,start,zero,opcode,writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,selalub,aluop,writezero);

input clk,start,zero;
input [5:0] opcode;
output writepc,selldst,writemem,writeir,selload,selst,writereg,selalua,writezero;
output [1:0] selalub,aluop;
reg  [3:0]q;
wire [3:0]d;
wire  zero;
always @(posedge clk)
    begin
        if(start)
            q<=4'd0;
        else
            q<=d;
    end 
assign d[0]=(~q[3]&~q[2]&~q[1]&~q[0])|((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&opcode[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&opcode[0]))|(~q[3]&~q[2]&q[1]&q[0])|(~q[3]&q[2]&~q[1]&q[0]);
assign d[1]=((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&~opcode[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(~opcode[3]&opcode[0]))|(~q[3]&~q[2]&q[1]&~q[0])|(~q[3]&~q[2]&q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0]);
assign d[2]=((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&~opcode[0]))|((~q[3]&~q[2]&~q[1]&q[0])&(opcode[3]&~opcode[2]&~opcode[1]&opcode[0]))|(~q[3]&~q[2]&q[1]&~q[0])|(~q[3]&~q[2]&q[1]&q[0]);
assign d[3]=(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0]);
assign writepc=(~q[3]&~q[2]&~q[1]&~q[0])|((~q[3]&~q[2]&~q[1]&q[0])&((opcode[3]&opcode[2]&~opcode[1]&~opcode[0])|(opcode[3]&~opcode[2]&opcode[1]&~opcode[0]&~zero)|(opcode[3]&~opcode[2]&opcode[1]&opcode[0]&zero)));
assign selldst=(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign writemem=q[3]&~q[2]&~q[1]&q[0];
assign writeir=~q[3]&~q[2]&~q[1]&~q[0];
assign selload=(~q[3]&q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign selst=(~q[3]&q[2]&~q[1]&q[0])|(q[3]&~q[2]&~q[1]&q[0]);
assign writereg=(~q[3]&q[2]&q[1]&~q[0])|(~q[3]&q[2]&q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign selalua=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0]);
assign selalub[1]=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0]);
assign selalub[0]=(~q[3]&~q[2]&~q[1]&q[0])|(~q[3]&~q[2]&q[1]&q[0])|(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|(~q[3]&q[2]&q[1]&q[0])|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign writezero=(~q[3]&q[2]&q[1]&~q[0])|(~q[3]&q[2]&q[1]&q[0]);
assign aluop[1]=(~q[3]&~q[2]&~q[1]&~q[0])|(~q[3]&~q[2]&~q[1]&q[0])|((~q[3]&~q[2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&~q[2]&q[1]&q[0])&(~opcode[3]&opcode[2]))|(~q[3]&q[2]&~q[1]&~q[0])|(~q[3]&q[2]&~q[1]&q[0])|((~q[3]&q[2]&q[1]&~q[0])&(~opcode[3]&opcode[2]))|((~q[3]&q[2]&q[1]&q[0])&(~opcode[3]&opcode[2]))|(q[3]&~q[2]&~q[1]&~q[0])|(q[3]&~q[2]&~q[1]&q[0])|(q[3]&~q[2]&q[1]&~q[0]);
assign aluop[0]=((~q[3]&~q[2]&q[1]&~q[0])&(~opcode[3]&opcode[1]))|((~q[3]&~q[2]&q[1]&q[0])&(~opcode[3]&opcode[1]))|((~q[3]&q[2]&q[1]&~q[0])&(~opcode[3]&opcode[1]))|((~q[3]&q[2]&q[1]&q[0])&(~opcode[3]&opcode[1]));
endmodule

module memory(dataout,datain,address,we,memin,memaddr,memwe,clk,reset);
output[31:0] dataout;
input[31:0] datain,memin;
input[4:0] address,memaddr;
input clk,reset,we,memwe;
wire we1;
wire[4:0] address1;
wire[31:0] decoderout;
wire[31:0] regen;
wire[31:0] datain1;
wire[31:0] q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31;
assign address1=memwe?memaddr:address;
assign datain1=memwe? memin:datain;
decoder dec0(decoderout,address1);
assign we1=we | memwe;
assign  regen[0]=decoderout[0] & we1;
assign  regen[1]=decoderout[1] & we1;
assign  regen[2]=decoderout[2] & we1;
assign  regen[3]=decoderout[3] & we1;
assign  regen[4]=decoderout[4] & we1;
assign  regen[5]=decoderout[5] & we1;
assign  regen[6]=decoderout[6] & we1;
assign  regen[7]=decoderout[7] & we1;
assign  regen[8]=decoderout[8] & we1;
assign  regen[9]=decoderout[9] & we1;
assign  regen[10]=decoderout[10] & we1;
assign  regen[11]=decoderout[11] & we1;
assign  regen[12]=decoderout[12] & we1;
assign  regen[13]=decoderout[13] & we1;
assign  regen[14]=decoderout[14] & we1;
assign  regen[15]=decoderout[15] & we1;
assign  regen[16]=decoderout[16] & we1;
assign  regen[17]=decoderout[17] & we1;
assign  regen[18]=decoderout[18] & we1;
assign  regen[19]=decoderout[19] & we1;
assign  regen[20]=decoderout[20] & we1;
assign  regen[21]=decoderout[21] & we1;
assign  regen[22]=decoderout[22] & we1;
assign  regen[23]=decoderout[23] & we1;
assign  regen[24]=decoderout[24] & we1;
assign  regen[25]=decoderout[25] & we1;
assign  regen[26]=decoderout[26] & we1;
assign  regen[27]=decoderout[27] & we1;
assign  regen[28]=decoderout[28] & we1;
assign  regen[29]=decoderout[29] & we1;
assign  regen[30]=decoderout[30] & we1;
assign  regen[31]=decoderout[31] & we1;
register reg0(q0,datain1,clk,reset,regen[0]);
register reg1(q1,datain1,clk,reset,regen[1]);
register reg2(q2,datain1,clk,reset,regen[2]);
register reg3(q3,datain1,clk,reset,regen[3]);
register reg4(q4,datain1,clk,reset,regen[4]);
register reg5(q5,datain1,clk,reset,regen[5]);
register reg6(q6,datain1,clk,reset,regen[6]);
register reg7(q7,datain1,clk,reset,regen[7]);
register reg8(q8,datain1,clk,reset,regen[8]);
register reg9(q9,datain1,clk,reset,regen[9]);
register reg10(q10,datain1,clk,reset,regen[10]);
register reg11(q11,datain1,clk,reset,regen[11]);
register reg12(q12,datain1,clk,reset,regen[12]);
register reg13(q13,datain1,clk,reset,regen[13]);
register reg14(q14,datain1,clk,reset,regen[14]);
register reg15(q15,datain1,clk,reset,regen[15]);
register reg16(q16,datain1,clk,reset,regen[16]);
register reg17(q17,datain1,clk,reset,regen[17]);
register reg18(q18,datain1,clk,reset,regen[18]);
register reg19(q19,datain1,clk,reset,regen[19]);
register reg20(q20,datain1,clk,reset,regen[20]);
register reg21(q21,datain1,clk,reset,regen[21]);
register reg22(q22,datain1,clk,reset,regen[22]);
register reg23(q23,datain1,clk,reset,regen[23]);
register reg24(q24,datain1,clk,reset,regen[24]);
register reg25(q25,datain1,clk,reset,regen[25]);
register reg26(q26,datain1,clk,reset,regen[26]);
register reg27(q27,datain1,clk,reset,regen[27]);
register reg28(q28,datain1,clk,reset,regen[28]);
register reg29(q29,datain1,clk,reset,regen[29]);
register reg30(q30,datain1,clk,reset,regen[30]);
register reg31(q31,datain1,clk,reset,regen[31]);
mux_32 mux0(dataout,q0,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28,q29,q30,q31,address);
endmodule

3、设计测试文件

`timescale 1ns / 1ns
module TOP_test;
reg clk,rst,start,memwe;
reg [31:0] memin;
reg [4:0] memaddr;
wire zero,n,v,c;
wire [31:0] dataout;
TOP u(clk,rst,start,memwe,memin,memaddr,zero,n,v,c,dataout);
always #50 clk=~clk;
initial
  begin
     clk=1;
     rst=0;
     start=0;
#20  rst=1;//test reset       
#100 rst=0; //load instruction and data to memory.
     memwe=1;
     memin=32'b001000_00000_11111_0000000000010000; //load r0,r31,16
     memaddr=5'd0;
#100 memwe=1;
     memin=32'b001001_00000_11111_0000000000010001; //store r0,r31,17
     memaddr=5'd1;
#100 memwe=1;
     memin=32'b001000_00001_11111_0000000000010001; //load r1,r31,17
     memaddr=5'd2;
#100 memwe=1;
     memin=32'b000001_00010_00000_0101010101010101;
//andi r2,r0,16'b0101010101010101
     memaddr=5'd3;
#100 memwe=1;
     memin=32'b000101_00011_00010_0000000000001011;
//addi r3,r2,16'b0000000000001011
     memaddr=5'd4;
#100 memwe=1;
     memin=32'b001100_11111111111111111111111011;
//branch -5
     memaddr=5'd5;     
#100 memwe=1;
     memin=32'hFFFF_FFFF;
//load data to memory 
     memaddr=5'd16;
//start to execuit instructions.
#100 memwe=0;
     start=1;
#100 start=0;
#10000 $stop;
end
endmodule

注意:测试的完备性。

4、将设计文件和测试文件输入Modesim仿真工具,并进行编译和功能仿真。

5、观测仿真波形图,分析结果是否正确。若有错误,则修改设计文件或测试文件,重新编译和仿真。

评论已关闭

Loading...
Fullscreen Image