单周期CPU数据通路
数据通路中各模块代码
- PC(程序计数器)
module PC #(parameter WIDTH=32)(
input clk,reset,
input [WIDTH-1:0] d,
output reg[WIDTH-1:0] q
);
always @(posedge clk,posedge reset)
if(reset)q<=0;
else q<=d;
endmodule
- Add(1)(使PC自增的加法器)
module PC_adder(
adr,n_adr
);
input [31:0] adr;
output [31:0] n_adr;
assign n_adr = adr + 32'd4;
endmodule
- 指令存储器
module codeRAM(
address,data
);
parameter DataWidth=32;
parameter AddrWidth=32;
parameter DataDepth=32;
input [AddrWidth-1:0] address;
output [DataWidth-1:0] data;
reg [DataWidth-1:0] men [0:DataDepth-1];
assign data=men[address[6:2]];
initial
begin
men[0]=32'h20020005;
men[1]=32'h2003000c;
men[2]=32'h2067fff7;
men[3]=32'h00e22025;
men[4]=32'h00642824;
men[5]=32'h00a42820;
men[6]=32'h10a7000a;
men[7]=32'h0064202a;
men[8]=32'h10800001;
men[9]=32'h20050000;
men[10]=32'h00e2202a;
men[11]=32'h10800001;
men[12]=32'h20050000;
men[13]=32'h00e2202a;
men[14]=32'h00853820;
men[15]=32'h00e23822;
men[16]=32'hac670044;
men[17]=32'h8c020050;
men[18]=32'h08000011;
men[19]=32'h20020001;
men[20]=32'hac020054;
end
endmodule
- MCU(主控制器)
module mainDec(
input [5:0] op,
output mentoreg,menwrite,
output branch,alusrc,
output regdst,regwrite,
output jump,
output [1:0] aluop
);
reg [8:0] controls;
assign{regwrite,regdst,alusrc,branch,menwrite,mentoreg,jump,aluop}=controls;
always @(*)
case(op)
6'b000000:controls<=9'b110000010;
6'b100011:controls<=9'b101001000;
6'b101011:controls<=9'b001010000;
6'b000100:controls<=9'b000100001;
6'b001000:controls<=9'b101000000;
6'b000010:controls<=9'b000000100;
default:controls<=9'bxxxxxxxxx;
endcase
endmodule
- 多路选择器(6位)
module MUX6(
A,B,Src,S
);
input [4:0] A,B;
input Src;
output [4:0] S;
assign S = (Src==0) ? A:B;
endmodule
- RF(寄存器组)
module RegisterUnit(
clk,we,ra1,ra2,wa3,wd,rd1,rd2
);
parameter DataWidth=32;
parameter AddrWidth=5;
parameter DataDepth=1<<AddrWidth;
input clk;
input we;
input [AddrWidth-1:0] ra1,ra2,wa3;
input [DataWidth-1:0] wd;
output [DataWidth-1:0] rd1,rd2;
reg [DataWidth-1:0] rf [DataDepth-1:0];
assign rd1=rf[ra1];
assign rd2=rf[ra2];
always @ (posedge clk)
begin :MEM_WRITE
if(we)begin
rf[wa3]=wd;
end
end
initial
begin
rf[0]=32'h0;
rf[1]=32'h0;
rf[2]=32'h0;
rf[3]=32'h0;
rf[4]=32'h0;
rf[5]=32'h0;
rf[6]=32'h0;
rf[7]=32'h0;
rf[8]=32'h0;
rf[9]=32'h0;
rf[10]=32'h0;
rf[11]=32'h0;
rf[12]=32'h0;
rf[13]=32'h0;
rf[14]=32'h0;
rf[15]=32'h0;
rf[16]=32'h0;
end
endmodule
- SigExt16/32
module Extend16to32(
order,addr
);
input [15:0] order;
output reg [31:0] addr;
always @(order)
begin
if(order[15]==1) addr[31:16]=16'b1111111111111111;
else addr[31:16]=16'b0000000000000000;
addr[15:0]=order[15:0];
end
endmodule
- 多路选择器(32位)
module MUX32(
A,B,Src,S
);
input [31:0] A,B;
input Src;
output [31:0] S;
assign S = (Src==0) ? A:B;
endmodule
- ALUCU(ALU控制器)
module aluDec(
input [5:0]funct,
input [1:0]aluop,
output reg [3:0] alucontrol
);
always @(*)
case(aluop)
2'b00:alucontrol<=3'b0010;
2'b01:alucontrol<=3'b0011;
default:case(funct)
6'b100000:alucontrol<=4'b0010;
6'b100001:alucontrol<=4'b0000;
6'b100010:alucontrol<=4'b0011;
6'b100011:alucontrol<=4'b0001;
6'b100100:alucontrol<=4'b0100;
6'b100101:alucontrol<=4'b0101;
6'b100110:alucontrol<=4'b0110;
6'b100111:alucontrol<=4'b0111;
6'b101010:alucontrol<=4'b1011;
6'b101011:alucontrol<=4'b1010;
default:alucontrol<=4'bxxxx;
endcase
endcase
endmodule
- ALU
module alu(
input [31:0] a,
input [31:0] b,
input [3:0] aluc,
output [31:0] r,
output zero,
output carry,
output negative,
output overflow);
parameter Addu = 4'b0000;
parameter Add = 4'b0010;
parameter Subu = 4'b0001;
parameter Sub = 4'b0011;
parameter And = 4'b0100;
parameter Or = 4'b0101;
parameter Xor = 4'b0110;
parameter Nor = 4'b0111;
parameter Slt = 4'b1011;
parameter Sltu = 4'b1010;
parameter Sra = 4'b1100;
parameter Sll = 4'b1110;
- 数据存储器
module RAM(
clk,address,data_in,data,we
);
parameter DataWidth=32;
parameter AddrWidth=32;
parameter DataDepth=32;
input clk;
input [AddrWidth-1:0] address;
input we;
input [DataWidth-1:0] data_in;
output [DataWidth-1:0] data;
reg [DataWidth-1:0] data_out;
reg [DataWidth-1:0] men [0:DataDepth-1];
assign data=(!we) ? data_out:8'bz;
always @ (posedge clk)
begin :MEM_WRITE
if(we)begin
men[address[6:2]]=data_in;
end
end
always @ (posedge clk)
begin :MEM_READ
if(!we)begin
data_out=men[address[6:2]];
end
end
endmodule
- SHL2(图中右侧的那个)
module Left2(data,odata);
input [31:0] data;
output reg [31:0] odata;
always @(data)
begin
odata[31:2]<=data[29:0];
odata[1:0]<=2'b00;
end
endmodule
- Add(2)
module ALU_Add_32(addr1,addr2,out_addr);
input [31:0] addr1,addr2;
output [31:0] out_addr;
assign out_addr = addr1+addr2;
endmodule
- 与操作模块
module myand(
R,A,B
);
input A,B;
output R;
assign R=A&B;
endmodule
- SHL2(图中左侧的那个)
module Left2_26(data,data1,odata);
input [25:0] data;
input [3:0] data1;
output reg [31:0] odata;
always @(data,data1)
begin
odata[27:2]<=data[25:0];
odata[1:0]<=2'b00;
odata[31:28]<=data1[3:0];
end
endmodule
连接各模块
module CPU(
clk,rst,out_ALU,Read_Data1,Read_Data2,Address_in_PC,Address_out_PC,Address_Add_PC,Order,Read_Data_Mem,Order_Left,zero
);
input clk;
input rst;
output [31:0]out_ALU;
output [31:0] Read_Data1,Read_Data2,Address_in_PC,Address_out_PC,Address_Add_PC,Order,Read_Data_Mem,Order_Left;
output zero;
wire [31:0] Read_Data1;
wire [31:0] Read_Data2;
wire [31:0] Address_in_PC,Address_out_PC;
wire [31:0] Address_Add_PC;
wire [31:0] Order;
wire RegDst,Jump,Branch,MemtoReg,ALUSrc,RegWrite,MemWrite;
wire [1:0] ALUop;
wire [4:0] Write_register;
wire [31:0] Write_Data;
wire [31:0] sign,out_sign,ALU1,out_ALU;
wire [31:0] ALU_Add_32_out,Branch_or_normal;
wire [3:0] ALU_ctr;
wire [31:0] Read_Data_Mem;
wire [31:0] Order_Left;
wire zero,Mux32_EN;
wire carry,negative,overflow;
PC pc(.clk(clk),.reset(rst),.d(Address_in_PC),.q(Address_out_PC));
PC_adder pc_adder(.adr(Address_out_PC),.n_adr(Address_Add_PC));
codeRAM coderam(.address(Address_out_PC),.data(Order));
mainDec maindec(.op(Order[31:26]),.mentoreg(MemtoReg),.menwrite(MemWrite),.branch(Branch),.alusrc(ALUSrc),.regdst(RegDst),.regwrite(RegWrite),.jump(Jump),.aluop(ALUop));
MUX6 mux6(.A(Order[20:16]),.B(Order[15:11]),.Src(RegDst),.S(Write_register));
RegisterUnit ru(.clk(clk),.we(RegWrite),.ra1(Order[25:21]),.ra2(Order[20:16]),.wa3(Write_register),.wd(Write_Data),.rd1(Read_Data1),.rd2(Read_Data2));
Extend16to32 extend16to32(.order(Order[15:0]),.addr(sign));
MUX32 mux32_1(.A(Read_Data2),.B(sign),.Src(ALUSrc),.S(ALU1));
aluDec aludec(.funct(Order[5:0]),.aluop(ALUop),.alucontrol(ALU_ctr));
alu ALU(.a(Read_Data1),.b(ALU1),.aluc(ALU_ctr),.r(out_ALU),.zero(zero),.carry(carry),.negative(negative),.overflow(overflow));
RAM ram(.clk(clk),.address(out_ALU),.data_in(Read_Data2),.data(Read_Data_Mem),.we(MemWrite));
MUX32 MUX32_2(.A(out_ALU),.B(Read_Data_Mem),.Src(MemtoReg),.S(Write_Data));
Left2 left2(.data(sign),.odata(out_sign));
ALU_Add_32 aluadd32(.addr1(Address_Add_PC),.addr2(out_sign),.out_addr(ALU_Add_32_out));
myand myand_(.R(Mux32_EN),.A(Branch),.B(zero));
MUX32 mux32_3(.A(Address_Add_PC),.B(ALU_Add_32_out),.Src(Mux32_EN),.S(Branch_or_normal));
Left2_26 left2_26(.data(Order[25:0]),.data1(Address_Add_PC[31:28]),.odata(Order_Left));
MUX32 mux32_4(.A(Branch_or_normal),.B(Order_Left),.Src(Jump),.S(Address_in_PC));
endmodule
测试
-
测试使用指令(已写入到指令寄存器)
-
测试代码
module sim_cpu(
);
reg clk;
reg rst;
wire [31:0]out_ALU;
wire [31:0] Read_Data1,Read_Data2,Address_in_PC,Address_out_PC,Address_Add_PC,Order,Read_Data_Mem,Order_Left;
wire zero;
CPU cpu(
.clk(clk),
.rst(rst),
.out_ALU(out_ALU),
.Read_Data1(Read_Data1),
.Read_Data2(Read_Data2),
.Address_in_PC(Address_in_PC),
.Address_out_PC(Address_out_PC),
.Address_Add_PC(Address_Add_PC),
.Order(Order),
.Read_Data_Mem(Read_Data_Mem),
.Order_Left(Order_Left),
.zero(zero)
);
always begin
#10 clk=~clk;
end
initial begin
clk=0;
rst=0;
#10;
rst=1;
#10;
rst=0;
end
endmodule
- 测试结果
仿真波形图如下,其中,Address_in_PC[31:0]为运行的指令地址(红色方框内容),Read_Data1[31:0]和Read_Data2[31:0]为读取的寄存器组Rs和Rt的值(蓝色方框内容)。因一次截取图片模糊不清,选择截取为2张图片。
- 根据测试指令,PC的变化应该为:0->4->8->c->10->14->18->1c->20(跳转)->28->2c->30->34->38->3c(跳转)->44
根据红色方框内容,PC的变化与预测相同。
- 逐个考察蓝色方框内容,分析各个时钟周期内Rs和Rt所对应寄存器的值,与预期相同。
- 运行完上述指令后,寄存器组的值如下图,与预期结果相同。
- 运行完上述指令后,数据寄存器的值如下图,与预期结果相同。