欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

程序员文章站 2022-07-06 08:21:01
...

实验原理

  32×32位的寄存器堆模块示意图如图所示,含有32个寄存器,每个寄存器32位。该寄存器堆具有A和B两个读端口,分别由 5 位的寄存器编号 R_Addr_A 和 R_Addr_B 来寻址 2 个寄存器,读出的数据则由 R_Data_A(32 位)和R_Data_B(32 位)输出。读访问时,没有使能或者时钟信号控制,只要给出寄存器地址,就可读出寄存器中的数据。
  该寄存器堆只有一个写端口,端口地址为5位的W_Addr,写操作的控制信号是 Write_Reg,写入的数据为32位的W_Data。
  寄存器堆功能表如表所示。W_Addr、W_Data和 Write_Reg必须在时钟clk上升沿来临时,已经有效。此外,该寄存器堆具有清零功能,清零信号为 CPU 的 Reset 信号。

杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

寄存器堆模块示意图

杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

寄存器堆功能表

实验内容

  1. 设计一个寄存器堆模块,并仿真验证;
  2. 修改ALU模块中的ALU_OP为3位,完成前8种功能;
    调用ALU模块和寄存器堆模块设计一个图2所示的ALU_REG模块,完成 Ri θ Rj → Rk 的操作,即2 个寄存器数据做某种运算,结果送回第3 个寄存器中;其中运算功能θ则由ALU 模块中的ALU_OP 信号指定。设计仿真测试用例,仿真验证。
    杭电计算机组成原理课程设计-实验七-寄存器堆设计实验
ALU-REG模块示意图
ALU功能表
ALU_OP[2:0] ALU功能 操作说明
000 and 逻辑与运算
001 or 逻辑或运算
010 xor 逻辑异或运算
011 nor 逻辑或非运算
100 add 算术加运算
101 sub 算术减运算
110 slt 若A<B,则输出1;否则输出0
111 sll B逻辑左移A所指定的位数

模块功能说明

本实验共3个模块
 模块调用关系说明:ALU-REG模块中调用了ALU模块和REG模块

module REGS_ALU(
        clk,rst,Write_Reg,//控制信号
        R_Addr_A,R_Addr_B,W_Addr,//读写地址
        R_Data_A,R_Data_B,//数据数据
        OP,ZF,OF,ALU_F//ALU运算
        );//ALU-REG模块
    input clk, rst;//写入时钟信号, 清零信号
    input [4:0]R_Addr_A;//A读端口寄存器地址
    input [4:0]R_Addr_B;//B读端口寄存器地址
    input [4:0]W_Addr;//写寄存器地址
	input Write_Reg; //写控制信号
    output [31:0]R_Data_A;//A端口读出数据
    output [31:0]R_Data_B;//B端口读出数据
    input [2:0] OP;//运算符编码
    output ZF;//零标志
    output OF;//溢出标志(只对有符号数运算有意义)   
    output [31:0]ALU_F;//ALU运算结果

module REGS(R_Data_A,R_Data_B,W_Data,R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk);
//寄存器堆模块
	input clk;//写入时钟信号
    input rst;//清零信号
    input Write_Reg;//写控制信号
    input [4:0]R_Addr_A;//A端口读寄存器地址
    input [4:0]R_Addr_B;//B端口读寄存器地址
    input [4:0]W_Addr;//写寄存器地址
    input [31:0]W_Data;//写入数据
	output [31:0]R_Data_A;//A端口读出数据
    output [31:0]R_Data_B;//B端口读出数据

module ALU(ALU_OP,A,B,F,ZF,OF);//ALU模块
	  input  [2:0] ALU_OP; //运算功能的控制线
	  input  [31:0] A;    //运算数
	  input  [31:0]B;    //运算数
	  output [31:0] F;	//运算结果
	  output  ZF;	   //零标志位
	  output  OF;	  //溢出标志位

模块逻辑引脚图

杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

寄存器堆模块代码

module REGS_ALU(
        clk,rst,Write_Reg,//控制信号
        R_Addr_A,R_Addr_B,W_Addr,//读写地址
        R_Data_A,R_Data_B,//数据IO
        OP,ZF,OF,ALU_F//ALU运算
        );
   
    input clk, rst;//写入时钟信号, 清零信号
    input [4:0]R_Addr_A;//A读端口寄存器地址
    input [4:0]R_Addr_B;//B读端口寄存器地址
    input [4:0]W_Addr;//写寄存器地址
	input Write_Reg;//读写控制信号
    output [31:0]R_Data_A;//A端口读出数据
    output [31:0]R_Data_B;//B端口读出数据
    input [2:0] OP;//运算符编码
    output ZF;//零标志
    output OF;//溢出标志(只对有符号数运算有意义)   
    output [31:0]ALU_F;//运算结果F
	 
	 REGS REGS_1(R_Data_A,R_Data_B,ALU_F,R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk);
	 ALU ALU_1(OP,R_Data_A,R_Data_B,ALU_F,ZF,OF);
	 //assign W_Data = ALU_F;
endmodule

module REGS(R_Data_A,R_Data_B,W_Data,R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk);
	input clk;//写入时钟信号
    input rst;//清零信号
    input Write_Reg;//写控制信号
    input [4:0]R_Addr_A;//A端口读寄存器地址
    input [4:0]R_Addr_B;//B端口读寄存器地址
    input [4:0]W_Addr;//写寄存器地址
    input [31:0]W_Data;//写入数据
	output [31:0]R_Data_A;//A端口读出数据
    output [31:0]R_Data_B;//B端口读出数据
	 
	integer i;
	reg [31:0] REG_Files[0:31];  
	initial REG_Files[0]<=32'hF0F0F0F0;
	initial REG_Files[1]<=32'h00000004;
    initial
        for(i=2;i<32;i=i+1) REG_Files[i]<=0;
    aaa@qq.com(posedge clk or posedge rst)
   	 begin
        if(rst)
                for(i=0;i<32;i=i+1) REG_Files[i]<=0;
        else
                if(Write_Reg) REG_Files[W_Addr]<=W_Data;
  	  end
    assign R_Data_A=REG_Files[R_Addr_A];
    assign R_Data_B=REG_Files[R_Addr_B];

endmodule

module ALU(ALU_OP,A,B,F,ZF,OF);
	  input  [2:0] ALU_OP;
	  input  [31:0] A;
	  input  [31:0]B;
	  output [31:0] F;
	  output  ZF;
	  output  OF;
	  reg [31:0] F;
	  reg    C,ZF,OF;
	 aaa@qq.com(*)
	  begin
		C=0;
		OF=0;
		case(ALU_OP)
			3'b000:begin F=A&B; end
			3'b001:begin F=A|B; end
			3'b010:begin F=A^B; end
			3'b011:begin F=~(A|B); end 
			3'b100:begin {C,F}=A+B;OF = A[31]^B[31]^F[31]^C; end 
			3'b101:begin {C,F}=A-B;OF = A[31]^B[31]^F[31]^C; end 
			3'b110:begin F=A<B; end
			3'b111:begin F=B<<A; end
		endcase
		ZF = F==0;
		end
endmodule

REG模块测试用例

initial begin
		// Initialize Inputs
		W_Data = 0;
		R_Addr_A = 10101;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		rst = 0;
		clk = 0;
		#100
		
		W_Data = 32'hAAAAAAAA;
		R_Addr_A = 0;
		R_Addr_B = 0;
		W_Addr = 10101;
		Write_Reg = 1;
		#100
		
		W_Data = 0;
		R_Addr_A = 10101;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		rst = 0;
		clk = 0;
		#100
		
		W_Data = 32'hFFFFFFFF;
		R_Addr_A = 0;
		R_Addr_B = 0;
		W_Addr = 10101;
		Write_Reg = 1;
		clk = 1;
		#100
		
		W_Data = 0;
		R_Addr_A = 10101;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		clk = 0;
		#100
		
		rst = 1;
		W_Data = 0;
		R_Addr_A = 10101;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		#100
		
		rst = 0;
		W_Data = 0;
		R_Addr_A = 01010;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		#100
		
		W_Data = 32'hAABBCCDD;
		R_Addr_A = 0;
		R_Addr_B = 0;
		W_Addr = 01010;
		Write_Reg = 1;
		clk = 1;
		#100
		
		W_Data = 0;
		R_Addr_A = 01010;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		#100;
		
		W_Data = 0;
		R_Addr_A = 0;
		R_Addr_B = 0;
		W_Addr = 0;
		Write_Reg = 0;
		#100;
        
	end
endmodule

REG-ALU测试用例

always #33 clk=~clk;
	initial begin
		clk = 0;
		rst = 0;
		Write_Reg = 0;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd10;
		OP = 3'b000;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd10;
		OP = 3'b000;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd11;
		OP = 3'b001;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd12;
		OP = 3'b010;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd13;
		OP = 3'b011;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd14;
		OP = 3'b100;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd15;
		OP = 3'b101;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd0;
		R_Addr_B = 32'd1;
		W_Addr = 32'd16;
		OP = 3'b110;
		#100
		
		Write_Reg = 1;
		R_Addr_A = 32'd1;
		R_Addr_B = 32'd2;
		W_Addr = 32'd17;
		OP = 3'b111;
		#100
		
		rst=1;
		#100;
	end
endmodule

实验结果记录

 寄存器堆实验结果及分析

 1.实验结果记录表
杭电计算机组成原理课程设计-实验七-寄存器堆设计实验
 2.仿真波形图
杭电计算机组成原理课程设计-实验七-寄存器堆设计实验
杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

 ALU_REG运算器模块实验结果及分析

 1.实验结果记录表
杭电计算机组成原理课程设计-实验七-寄存器堆设计实验
 2.仿真波形图
杭电计算机组成原理课程设计-实验七-寄存器堆设计实验
杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

探索与思考

  与本实验设计的寄存器堆相比,MIPS 计算机的通用寄存器堆结构类似:有 32×32位的寄存器组,具有 2 个读端口和 1 个写端口,读操作不需要时钟信号,写操作在时钟边沿触发;不同之处在于,MIPS 的寄存器堆中,0R00 地址的寄存器(即 R0,汇编符号zero)中始终存储常数 0,对 R0 的读操作,直接返回常数 0;且不允许对 R0执行写操作。修改本实验所实现的基本寄存器堆模块,实现 MIPS 计算机的通用寄存器堆,以供后续 MIPS CPU 的设计使用。

module REGS(R_Data_A,R_Data_B,W_Data,R_Addr_A,R_Addr_B,W_Addr,Write_Reg,rst,clk);
	input clk;//写入时钟信号
    input rst;//清零信号
    input Write_Reg;//写控制信号
    input [4:0]R_Addr_A;//A端口读寄存器地址
    input [4:0]R_Addr_B;//B端口读寄存器地址
    input [4:0]W_Addr;//写寄存器地址
    input [31:0]W_Data;//写入数据
	output [31:0]R_Data_A;//A端口读出数据
    output [31:0]R_Data_B;//B端口读出数据
	 
	integer i;
	reg [31:0] REG_Files[0:31];  
    initial
        for(i=0;i<32;i=i+1) REG_Files[i]<=0;
    aaa@qq.com(posedge clk or posedge rst)
   	 begin
        if(rst)
                for(i=0;i<32;i=i+1) REG_Files[i]<=0;
        else
                if(Write_Reg&&W_Addr!=32'd0) REG_Files[W_Addr]<=W_Data;
   	 end
    assign R_Data_A=REG_Files[R_Addr_A];
    assign R_Data_B=REG_Files[R_Addr_B];

endmodule