基于Verilog的单周期和多周期CPU设计

基于Verilog的单周期和多周期CPU设计,数据通路采用分散互联,控制器采用硬布线方式实现
原理方面如各条指令的流程和控制信号的内容可参考相关教材,在此不进行介绍,仅介绍核心组件的实现方法
模拟采用的是modelsim,指令集参考的是MIPS32的标准指令集,实现的十条指令格式皆取自其中
10条指令内容:
在这里插入图片描述

单周期

总体结构

  • 数据通路

在这里插入图片描述

分散互联,CU采用组合逻辑+硬布线实现

组件实现

ALU

根据ALUctl信号对输入的A和B进行计算,若结果为零则Zero输出高电平

module ALU (ALUctl,A,B,ALUout,Zero);

input [2:0] ALUctl;
input [31:0] A,B;
output reg [31:0] ALUout;
output Zero;

assign Zero=(ALUout==0);

always @(ALUctl,A,B)
begin
	case(ALUctl)
		3'b000:ALUout<=A+B;	//add
		3'b001:ALUout<=A-B;	//sub
		3'b010:ALUout<=A+B;	//addu
		3'b011:ALUout<=A&B;	//and
		3'b100:ALUout<=A|B;	//or
		3'b101:ALUout<=~(A|B);	//nor
		default:ALUout<=0;
	endcase
end

endmodule

ALU_CU

根据ALUOp信号输出ALUctl

  • 00->addu
  • 01->sub
  • 10->由FuncCode决定,根据MIPS32指令输出对应信号
module ALU_CU(ALUop,FuncCode,Out);

input [1:0] ALUop;
input [5:0] FuncCode;
output reg [2:0] Out;
/*
add	000
sub	001
addu	010
and	011
or	100
nor	101
*/
always @*
case(ALUop)
	2'b00:Out=3'b010;	//addu
	2'b01:Out=3'b001;	//sub
	2'b10:
	begin
		case(FuncCode)
			6'b100000:Out=3'b000;	//add
			6'b100010:Out=3'b001;	//sub
			6'b100001:Out=3'b010;	//addu
			6'b100100:Out=3'b011;	//and
			6'b100101:Out=3'b100;	//or
			6'b100111:Out=3'b101;	//nor	
			default:Out=3'b111;
		endcase
	end
	default:Out=3'b111;
endcase

endmodule

RF

具体输入输出如下,其中RegWr为写使能,当其有效时,在clock上升沿将数据写入寄存器

为保证测试,第一个寄存器为基址寄存器,并初始化了基址为0

module reg_file(Read1,Read2,WriteReg,WriteData,RegWr,Data1,Data2,clock);

input [4:0] Read1,Read2,WriteReg;	//reg number
input [31:0] WriteData;	//data to write
input RegWr;	//write control
input clock;	//clock for write
output [31:0] Data1,Data2;	//data to read

reg [31:0] RF [31:0];	//32 reg(32bit)

//测试用,保存基址
initial
begin
	RF[0]=0;
end

assign Data1=RF[Read1];
assign Data2=RF[Read2];

always
begin
	@(posedge clock) if(RegWr) RF[WriteReg]<=WriteData;
end

endmodule

指令存储器

使用寄存器堆模拟,为了测试根据MIPS32指令集初始化了一些指令,并且为了保证PC+4的地址正确,对输入地址进行了转换以对应寄存器序号,具体测试代码见测试部分

module mem_ins(addr,ins);

input [31:0] addr;
output [31:0] ins;

reg [31:0] mem [1023:0];

//测试用
initial
begin
mem[0]=32'b100011_00000_00100_00000000_00000011; //lw
mem[1]=32'b100011_00000_00001_00000000_00000001; //lw
mem[2]=32'b100011_00000_00010_00000000_00000010; //lw
mem[3]=32'b100011_00000_00011_00000000_00000100; //lw
mem[4]=32'b000100_00010_00011_00000000_00000010; //beq
mem[5]=32'b000000_00010_00001_00010_00000_100000; //add
mem[6]=32'b000010_00_0001_0000_0000_0000_0000_0100; //j
mem[7]=32'b101011_00000_00010_00000000_00000011; //sw
mem[8]=32'b000010_00_0001_0000_0000_0000_0000_0000; //j
end

    assign ins=mem[((addr-32'h00400000)>>2)];	//转换输入地址为寄存器序号

endmodule

数据存储器

使用寄存器模拟,由于未实现立即数指令,为保证测试,初始化了一些数据,内容为对应的寄存器编号

由于只实现了按字读写,因此输入的地址无需翻译,直接对应了寄存器编号

clock信号用于保证写入正确,存储器只在clock信号的下降沿写,若不加clock信号会出现写入不稳定的输入的问题

module mem_data(ena_W,ena_R,addr,data_W,data_R,clock);

input ena_W,ena_R,clock;
input [31:0] addr;
input [31:0] data_W;
output reg [31:0] data_R;

reg [31:0] mem [1023:0];

//测试用
integer i;
initial
begin
	for(i=0;i<1024;i=i+1)
		mem[i]=i;
end
//只在下降沿写,保证写入内容的稳定
always@(negedge clock)
begin
	if(ena_W) 
	begin
		if((addr)<1024)
		begin 
			mem[(addr)]<=data_W;
		end
	end
end

always@(addr,ena_R,data_R)
begin
	if(ena_R)
	begin
		if((addr)<1024) data_R<=mem[(addr)];
	end
end 

endmodule

MCU

组合逻辑实现,输出输入指令编号对应操作所需要的信号(5种类型)

module MCU(
input [5:0] In,
output reg RegDst,reg Jump,reg RegWr,reg Branch,reg MemtoReg,reg [1:0] ALUOp,reg MemWr,reg MemRd,reg ALUSrc);


always@ (In)
begin
	case(In)
		6'b000000:{MemRd,MemWr,ALUOp,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg}={10'b0010011000};	//R
		6'b100011:{MemRd,MemWr,ALUOp,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg}={10'b1000101001};	//lw
		6'b101011:{MemRd,MemWr,ALUOp,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg}={10'b010010000x};	//sw
		6'b000100:{MemRd,MemWr,ALUOp,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg}={10'b000100010x};	//beq
		6'b000010:{MemRd,MemWr,ALUOp,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg}={10'b0011xx0x1x};	//j
		default:  {MemRd,MemWr,ALUOp,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg}={10'b0000000000};
	endcase
end

endmodule

PC

rst信号用于重置PC为第一条指令对应的地址;clock上升沿写入,由于是单周期,无需写使能

module reg_PC(clock,rst,In,Out);

input clock;
input rst;
//input ena;	单周期无需写使能
input [31:0] In;
output [31:0] Out;

reg [31:0] PC;

always @(posedge rst) PC<=32'h00400000;
    
always @(posedge clock) 
begin
    if(1/*ena*/) PC<=In;        //enable input (单周期无需写使能)
end

assign Out=PC;

endmodule

其他组件

其他模块实现较为简单

加法器

module ADD (A,B,Out);

input [31:0] A,B;
output reg [31:0] Out;

always @(A,B)
begin
	if(A===B) Out<=A+4;	//PC+4
	else Out<=A+B;
end

endmodule

与门

module ANDgate(in1,in2,Out);

input in1,in2;
output Out;

assign Out=in1&in2;

endmodule

MUX

module MUX_2_32(in0,in1,Sel,Out);

input [31:0] in0,in1;
input Sel;
output reg[31:0] Out;

always@(in0,in1,Sel)
case (Sel)
	0: Out<=in0;
	default: Out<=in1;
endcase

endmodule

module MUX_2_5(in0,in1,Sel,Out);

input [4:0] in0,in1;
input Sel;
output reg[4:0] Out;

always@(in0,in1,Sel)
case (Sel)
	0: Out<=in0;
	default: Out<=in1;
endcase

endmodule

SHL2

module SHL2_32(In,Out);

input [31:0] In;
output [31:0] Out;

assign Out={In[29:0],2'b00};

endmodule

module SHL2_26(In,Out);

input [25:0] In;
output [27:0] Out;

assign Out={In[25:0],2'b00};

endmodule

SigExt16_32

module SigExt16_32(In,Out);

input [15:0] In;
output [31:0] Out;

assign Out={
   
   {16{In[15]}},In[15:0]};

endmodule

CPU

根据数据通路进行连线,时钟信号和rst信号由外部输入

`include "MUX_2_32.v"
`include "ALU_CU.v"
`include "SHL2.v"
`include "ALU.v"
`include "reg_file.v"
`include "SigExt16_32.v"
`include "mem_ins.v"
`include "reg_PC.v"
`include "ANDgate.v"
`include "MCU.v"
`include "ADD_32.v"

module CPU(clock,rst);

input clock,rst;

wire [31:0] PC_out, PC_in, Inst, Add1_out, ALU_A, ALU_B, ALU_out, ADD2_B, ADD2_out, SigExt_out, data_W, data_R, WriteData_RF;
wire [31:0] MUX_2_32_1_out;
wire MemRd,MemWr,ALUSrc,RegDst,RegWr,Branch,Jump,MemtoReg,Zero,ANDgate_out;
wire [1:0] ALUOp;
wire [2:0] ALUctl;
wire [4:0] W_Reg;
wire [27:0] SHL2_out28;

reg_PC reg_PC(.clock(clock),.rst(rst),.In(PC_in),.Out(PC_out));

ADD ADD1(.A(PC_out),.B(PC_out),.Out(Add1_out));

MCU MCU(.MemRd(MemRd),.MemWr(MemWr),.ALUOp(ALUOp),.ALUSrc(ALUSrc),.RegDst(RegDst),.RegWr(RegWr),.Branch(Branch),.Jump(Jump),.MemtoReg(MemtoReg),
	.In(Inst[31:26]));

SHL2_26 SHL2_26(.In(Inst[25:0]),.Out(SHL2_out28));

ALU_CU ALU_CU(.ALUop(ALUOp),.FuncCode(Inst[5:0]),.Out(ALUctl));

ALU ALU(.ALUctl(ALUctl),.A(ALU_A),.B(ALU_B),.ALUout(ALU_out),.Zero(Zero));

ADD ADD2(.A(Add1_out),.B(ADD2_B),.Out(ADD2_out));

SigExt16_32 SigExt16_32(.In(Inst[15:0]),.Out(SigExt_out));

SHL2_32 SHL2_32(.In(SigExt_out),.Out(ADD2_B));

mem_ins mem_ins(.addr(PC_out),.ins(Inst));

mem_data mem_data(.ena_W(MemWr),.ena_R(MemRd),.addr(ALU_out),.data_W(data_W),.data_R(data_R),.clock(clock));

reg_file reg_file(.Read1(Inst[25:21]),.Read2(Inst[20:16]),.WriteReg(W_Reg),
		.WriteData(WriteData_RF),.RegWr(RegWr),.Data1(ALU_A),.Data2(data_W),.clock(clock));

ANDgate ANDgate(.in1(Branch),.in2(Zero),.Out(ANDgate_out));

MUX_2_5 MUX_2_5(.in0(Inst[20:16]),.in1(Inst[15:11]),.Sel(RegDst),.Out(W_Reg));

MUX_2_32 MUX_2_32_1(.in0(Add1_out),.in1(ADD2_out),.Sel(ANDgate_out),.Out(MUX_2_32_1_out));

MUX_2_32 MUX_2_32_2(.in0(MUX_2_32_1_out),.in1({Add1_out[31:28],SHL2_out28[27:0]}),.Sel(Jump),.Out(PC_in));

MUX_2_32 MUX_2_32_3(.in0(data_W),.in1(SigExt_out),.Sel(ALUSrc),.Out(ALU_B));

MUX_2_32 MUX_2_32_4(.in0(ALU_out),.in1(data_R),.Sel(MemtoReg),.Out(WriteData_RF));

endmodule

测试

测试模块

时钟信号和rst信号由测试模块给出

`include "CPU.v"

module CPU_TEST();

reg rst;
reg clock;
initial
begin
	rst=0;
	clock=0;
	#1 rst=1;
	#5 rst=0;
end
always #50 clock=~clock;

CPU CPU(.clock(clock),.rst(rst));

endmodule

测试代码

根据MIPS32指令集,设计了如下测试代码

编号 PC 内容 指令
0 0x00400000 R4<=mem[3] lw_R0_R4_3
1 0x00400004 R1<=mem[1] lw_R0_R1_1
2 0x00400008 R2<=mem[2] lw_R0_R2_2
3 0x0040000c R3<=mem[4] lw_R0_R3_4
4 0x00400010 beq R3==R2 ->7 beq_R2_R3_2
5 0x00400014 R2=R2+R1 0_R2_R1_R2_0_add
6 0x00400018 jmp->4 j_0x100004
7 0x0040001c mem[3]<=R2 sw_R0_R2_3
8 0x00400020 jmp->0 j_0x100000

首先寄存器R4,R1,R2,R3分别写入数据3,1,2,4,然后累加(每次加1(R1))R2直到R2(初值2)=R3(4),然后将R2的值写入内存mem[3]中,再跳转到程序开头,此时R4的写入的应该是R2的值(4)

测试结果

在这里插入图片描述

可以看到R2的值不断累加,直到等于R3,最后R4写入了R2的值,结果符合程序逻辑

多周期

总体结构

  • 数据通路

在这里插入图片描述

CU采用组合逻辑+有限状态机实现

  • CU

在这里插入图片描述

  • 有限状态机

在这里插入图片描述

主要组件

ALU和ALU_CU等组件与单周期相同

寄存器

不同于单周期,多周期数据通路多了很多寄存器用于存储中间数据,这些寄存器有不同特点:

  • 与单周期相同,只需clock信号控制写入(MDR、ALUOut、A、B)

    module reg_32(clock,In,Out);
    
    input clock;
    input [31:0] In;
    output [31:0] Out;
    
    reg [31:0] reg32;
        
    always @(posedge clock) 
    begin
    	reg32<=In;       
    end
    
    assign Out=reg32;
    
    endmodule
    
  • 需要写使能和clock信号同时对写入进行控制(PC、IR)

    module reg_IR(clock,ena_W,In,Out);
    
    input clock;
    input ena_W;	
    input [31:0] In;
    output [31:0] Out;
    
    reg [31:0] IR;
       
    always @(posedge clock) 
    begin
    	if(ena_W) IR<=In;        //enable input 
    end
    
    assign Out=IR;
    
    endmodule
    
  • 需要clock信号进行写入控制和rst信号进行重置(PC、SR)

    module reg_SR(clock,rst,In,Out);
    
    input clock;
    input rst;
    input [3:0] In;
    output [3:0] Out;
    
    reg [3:0] SR;
    
    always @(posedge rst) SR<=0;
        
    always @(posedge clock) 
    begin
    	SR<=In;        
    end
    
    assign Out=SR;
    
    endmodule
    
    module reg_PC(clock,rst,ena_W,In,Out);
    
    input clock;
    input rst;
    input ena_W;	
    input [31:0] In;
    output [31:0] Out;
    
    reg [31:0] PC;
    
    always @(posedge rst) PC<=32'h00400000;
        
    always @(posedge clock) 
    begin
    	if(ena_W) PC<=In;        //enable input 
    end
    
    assign Out=PC;
    
    endmodule
    

CU

用有限状态机实现,根据前一个状态和输入判断下一步状态并输出对应信号

module CU(
input [3:0] S, [5:0] OP,
output reg PCWr,reg PCWrCond,reg IorD,reg MemRd,reg MemWr,reg IRWr,reg MemtoReg,
output reg [1:0] PCSrc,reg [1:0] ALUOp,reg [1:0] ALUSrcB,reg ALUSrcA,reg RegWr,reg RegDst,
output reg [3:0] NS
);

always@(S)
begin
  case(S)
  0:NS<=1;
  1:
  begin
  	case(OP)
  	6'b100011:NS<=2;
  	6'b101011:NS<=2;
  	6'b000000:NS<=6;
  	6'b000100:NS<=8;
  	6'b000010:NS<=9;
  	default:NS<=4'b1xx1;
  	endcase
  end
  2:
  begin
  	case(OP)
  	6'b100011:NS<=3;
  	6'b101011:NS<=5;
  	default:NS<=0;
  	endcase
  end
  3:NS<=4;
  4:NS<=0;
  5:NS<=0;
  6:NS<=7;
  7:NS<=0;
  8:NS<=0;
  9:NS<=0;
  default:NS<=0;
  endcase
end

always@(S)
case(S)
0:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b1001010_00_00_01_000};
1:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0000000_00_00_11_000};
2:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0000000_00_00_10_100};
3:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0011000_00_00_00_000};
4:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0000001_00_00_00_010};
5:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0010100_00_00_00_000};
6:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0000000_00_10_00_100};
7:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0000000_00_00_00_011};
8:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0100000_01_01_00_100};
9:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b1000000_10_00_00_000};
default:{PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg, PCSrc , ALUOp , ALUSrcB ,ALUSrcA,RegWr,RegDst}={16'b0000000_00_00_00_000};
endcase

endmodule

内存

合并了数据存储器和指令存储器,同样用寄存器堆模拟,并初始化相应数据,指令同单周期

需要注意的是读指令和读数据的地址转换方式不同

module mem(ena_W,ena_R,addr,data_W,data_R,clock);

input ena_W,ena_R,clock;
input [31:0] addr;
input [31:0] data_W;
output reg [31:0] data_R;

reg [31:0] mem [1023:0];

//测试用
integer i;
initial
begin
	for(i=0;i<512;i=i+1)
		mem[i]=i;
end
//测试用
initial
begin
mem[512+0]=32'b100011_00000_00100_00000000_00000011;	//lw
mem[512+1]=32'b100011_00000_00001_00000000_00000001;	//lw
mem[512+2]=32'b100011_00000_00010_00000000_00000010;	//lw
mem[512+3]=32'b100011_00000_00011_00000000_00000100;	//lw
mem[512+4]=32'b000100_00010_00011_00000000_00000010;	//beq
mem[512+5]=32'b000000_00010_00001_00010_00000_100000;	//add
mem[512+6]=32'b000010_00_0001_0000_0000_0000_0000_0100;	//j
mem[512+7]=32'b101011_00000_00010_00000000_00000011;	//sw
mem[512+8]=32'b000010_00_0001_0000_0000_0000_0000_0000;	//j
end

always@(negedge clock)
begin
	if(ena_W) 
	begin
		if((addr)<512)
		begin 
			mem[(addr)]<=data_W;
		end
	end
end

always@(addr,ena_R,data_R)
begin
	if(ena_R)
	begin
        if((addr)<512) data_R<=mem[(addr)];	//读数据 
        else data_R<=mem[((addr-32'h00400000)>>2)+512];	//读指令
	end
end 

endmodule

其他组件

其他大部分组件与单周期相同

MUX_4

module MUX_3_32(in0,in1,in2,Sel,Out);

input [31:0] in0,in1,in2;
input [1:0] Sel;
output reg[31:0] Out;

always@(in0,in1,in2,Sel)
case (Sel)
	0: Out<=in0;
	1: Out<=in1;
	2: Out<=in2;
	default: Out<=in0;
endcase

endmodule

module MUX_4_32_1x(in0,in2,in3,Sel,Out);

input [31:0] in0,in2,in3;
input [1:0] Sel;
output reg[31:0] Out;

always@(in0,in2,in3,Sel)
case (Sel)
	0: Out<=in0;
	1: Out<=4;
	2: Out<=in2;
	default: Out<=in3;
endcase

endmodule

或门

module ORgate(in1,in2,Out);

input in1,in2;
output Out;

assign Out=in1|in2;

endmodule

CPU

根据数据通路进行连线,时钟信号和rst信号由外部输入

`include "MUX_2_32.v"
`include "ALU_CU.v"
`include "MUX_4_32.v"
`include "SHL2.v"
`include "ALU.v"
`include "reg_file.v"
`include "SigExt16_32.v"
`include "reg_PC.v"
`include "reg_32.v"
`include "ANDgate.v"
`include "ORgate.v"
`include "mem.v"
`include "CU.v"

module CPU(clock,rst);

input clock,rst;

wire [31:0] Inst,PC_in,PC_out,mem_addr,mem_data_R,A_in,B_in,A_out,B_out,ALU_A,ALU_B,ALU_out,ALUOut_out,MDR_out;
wire [31:0] SigExt_out,SHL2_32_out,WriteData_RF;
wire [27:0] SHL2_26_out;
wire PCWr,PCWrCond,IorD,MemRd,MemWr,IRWr,MemtoReg,ALUSrcA,RegWr,RegDst,ena_W_PC,Zero,ANDgate_out;
wire [1:0] PCSrc,ALUOp,ALUSrcB;
wire [3:0] SR_out,SR_in;
wire [2:0] ALUctl;
wire [4:0] WriteReg;

CU CU(.S(SR_out),.OP(Inst[31:26]),
.PCWr(PCWr),.PCWrCond(PCWrCond),.IorD(IorD),.MemRd(MemRd),.MemWr(MemWr),.IRWr(IRWr),.MemtoReg(MemtoReg),
.PCSrc(PCSrc),.ALUOp(ALUOp),.ALUSrcB(ALUSrcB),.ALUSrcA(ALUSrcA),.RegWr(RegWr),.RegDst(RegDst),
.NS(SR_in));

reg_SR SR(.clock(clock),.rst(rst),.In(SR_in),.Out(SR_out));

reg_PC PC(.clock(clock),.rst(rst),.ena_W(ena_W_PC),.In(PC_in),.Out(PC_out));

mem mem(.ena_W(MemWr),.ena_R(MemRd),.addr(mem_addr),.data_W(B_out),.data_R(mem_data_R),.clock(clock));

reg_IR IR(.clock(clock),.ena_W(IRWr),.In(mem_data_R),.Out(Inst));

reg_32 A(.clock(clock),.In(A_in),.Out(A_out));

reg_32 B(.clock(clock),.In(B_in),.Out(B_out));

ALU ALU(.ALUctl(ALUctl),.A(ALU_A),.B(ALU_B),.ALUout(ALU_out),.Zero(Zero));

ALU_CU ALU_CU(.ALUop(ALUOp),.FuncCode(Inst[5:0]),.Out(ALUctl));

reg_32 ALUOut(.clock(clock),.In(ALU_out),.Out(ALUOut_out));

reg_32 MDR(.clock(clock),.In(mem_data_R),.Out(MDR_out));

SigExt16_32 SigExt16_32(.In(Inst[15:0]),.Out(SigExt_out));

SHL2_32 SHL2_32(.In(SigExt_out),.Out(SHL2_32_out));

SHL2_26 SHL2_26(.In(Inst[25:0]),.Out(SHL2_26_out));

reg_file RF(.Read1(Inst[25:21]),.Read2(Inst[20:16]),.WriteReg(WriteReg),.WriteData(WriteData_RF),.RegWr(RegWr),.Data1(A_in),.Data2(B_in),.clock(clock));

ANDgate ANDgate(.in1(PCWrCond),.in2(Zero),.Out(ANDgate_out));

ORgate ORgate(.in1(PCWr),.in2(ANDgate_out),.Out(ena_W_PC));

MUX_2_32 MUX_2_32_1(.in0(PC_out),.in1(ALUOut_out),.Sel(IorD),.Out(mem_addr));

MUX_2_32 MUX_2_32_2(.in0(ALUOut_out),.in1(MDR_out),.Sel(MemtoReg),.Out(WriteData_RF));

MUX_2_32 MUX_2_32_3(.in0(PC_out),.in1(A_out),.Sel(ALUSrcA),.Out(ALU_A));

MUX_2_5 MUX_2_5(.in0(Inst[20:16]),.in1(Inst[15:11]),.Sel(RegDst),.Out(WriteReg));

MUX_4_32_1x MUX_4_32_1x(.in0(B_out),.in2(SigExt_out),.in3(SHL2_32_out),.Sel(ALUSrcB),.Out(ALU_B));

MUX_3_32 MUX_3_32(.in0(ALU_out),.in1(ALUOut_out),.in2({PC_out[31:28],SHL2_26_out[27:0]}),.Sel(PCSrc),.Out(PC_in));

endmodule

测试

测试模块和测试代码同单周期

测试结果

在这里插入图片描述

可以看到状态正常转换,并且R2累加
在这里插入图片描述

最后R4写入了R2的值,结果符合程序逻辑

猜你喜欢

转载自blog.csdn.net/Zireael2019/article/details/123450361
今日推荐