计算机组成原理实验项目1 基本功能部件 —— 寄存器堆和算术逻辑单元

本文深入探讨了ALU(算术逻辑单元)和Reg_File(寄存器文件)的实现原理。在Reg_File部分,重点介绍了如何在上升沿读写操作,并在读取0号位置时返回0。而在ALU部分,详细解析了加法、减法、求补等操作,特别提到了补码运算在减法中导致的Carryout取反问题,以及如何优化实现以提高效率。同时,文章还给出了Overflow和Zero的判断方法,并展示了相应的Verilog代码实现。
摘要由CSDN通过智能技术生成

Reg_File:
在这里插入图片描述
Reg_File 原件示意图:
在这里插入图片描述

Reg_File实验总的来讲比较简单,其要求实现的操作是在每一次上升沿读取一个地址和一个要求写入的数,如果该地址不为0,且wen信号处于高电平,那么就将该数写入目标地址。实现操作非常的简单,才每个上升沿时判断是否符合写入标准,如果符合,那么写入。在读出的时候,注意特判0位置即可。
波形示意:

在这里插入图片描述

上升沿来临,向01写入值,读出是组合逻辑,因此在赋值后直接读出了01写入的值。
在这里插入图片描述

访问0号位置,输出为0。

ALU实验详细电路示意图:
在这里插入图片描述

ALU实验总体来讲要复杂一些,它包含了几个主要的部分:
最简单的两个部分是求与和或,直接使用|,&运算符即可:
在这里插入图片描述

随后的Add、Sub和Slt本质上可以使用一套加法器电路。对于Add,直接使用A+B便可以得到预期的结果。对于减法,则可以考虑使用补码运算,但是值得注意的是进行补码运算所得到的Carryout结果和实际预想到的结果是不一致的:
对于计算A-B:
在补码计算时实际上是:2^{33}+A-B,对于carryout,它此时实际上就是第33位的值,如果其为1,则这代表这A-B\geq0。反之,如果其为0,则这代表A-B<0,这恰好和期望的溢出结果相反,所以在Sub运算和Slt运算中,要对实际运算结果取反。
在这里插入图片描述

波形说明:

读入SUB的信号:
A = 0 X 664 D 9757 = 1716361047 , B = 0 X 6 C 2 A 01 B C = 1814692284 A=0X664D9757=1716361047,B=0X6C2A01BC=1814692284 A=0X664D9757=1716361047B=0X6C2A01BC=1814692284
A-B自然是小于0的,但是此时   B = 0 X 93 D 5 F E 43 = 2480275011 ~B=0X93D5FE43=2480275011  B=0X93D5FE43=2480275011
A +   B + 1 = 4196636059 = 0 X F A 23959 B A+~B+1=4196636059=0XFA23959B A+ B+1=4196636059=0XFA23959B
该结果并没有溢出,这正是源于先前说明的A-B<0,因此 2 33 + A − B 2^{33}+A-B 233+AB的第33位值为0。因此减法求得的Carryout需要取反。
其次一个比较重要的问题是要调整取得相反数补码的运算流程。如果使用一般的三目运算符尝试直接取得B的补码是不正确的,因为这经历了一个先求得补码再取数的过程,那么实际电路中是使用了两个加法器,这明显影响了ALU的效率,因此需要先选出B是否取反,得到反码然后在加法器中利用进位输入功能加上1,则这仅需要一个加法器电路。
电路示意图:
在这里插入图片描述

可以看出在这种写法下仅需要一个32位全加器就能得到加法结果。
Overflow判定:
在最开始时,我选择了一种非常朴素的判定方法:
在这里插入图片描述
这个判定的基本思路是,在进行加法时当且仅当AB同号,并且计算结果与之异号才会出现Overflow,在减法时只有A-(-B)时符号位为负和(-A)-B时符号位为正时才会出现Overflow。
在这里插入图片描述

实际代码如上,基本含义为当ALUop[2]=0,即加法时,即分别判断A,B=1,Result_Add=0和A,B=0,Result_Add=1.减法时判断A、B异号和A是否与Result异号。
电路图示意:
在这里插入图片描述

在得到最终的Result时,直接使用与或判断选数即可,对于利用overflow获得Result_slt。
在经过思考后我发现可以直接利用overflow和result直接得到结果:

在这里插入图片描述

这个代码正确的原因是如果overflow为0,那么结果没有问题,直接用result符号位判断就好了,如果overflow为1,那么结果溢出,符号位和实际的值相反,因此只需要用符号位和overflow异或就好了。

在书写zero判断时,我学习了一种新的verilog语法,也就是|Result它是指将所有位按位或,因此为快速判零提供了一种更加便捷的办法

`timescale 10 ns / 1 ns

`define DATA_WIDTH 32

module alu(
	input  [`DATA_WIDTH - 1:0]  A,
	input  [`DATA_WIDTH - 1:0]  B,
	input  [              2:0]  ALUop,
	output                      Overflow,
	output                      CarryOut,
	output                      Zero,
	output [`DATA_WIDTH - 1:0]  Result
);
	wire op_and = ALUop == 3'b000;
	wire op_or  = ALUop == 3'b001;
	wire op_add = ALUop == 3'b010;
	wire op_sltu= ALUop == 3'b011;
	wire op_xor = ALUop == 3'b100;
	wire op_nor = ALUop == 3'b101;
	wire op_sub = ALUop == 3'b110;
	wire op_slt = ALUop == 3'b111;
	/*pretreatment for getting the operation that the ALUop referred*/

	wire   [`DATA_WIDTH - 1:0] Result_or =   A | B;
	wire   [`DATA_WIDTH - 1:0] Result_and =  A & B;
	wire   [`DATA_WIDTH - 1:0] Result_xor =  A ^ B;
	wire   [`DATA_WIDTH - 1:0] Result_nor =~(A | B);
	wire   [`DATA_WIDTH - 1:0] Result_add;
	/*Result add contains the result of add and sub, and we can also using this wire to get slt*/

	wire   [`DATA_WIDTH - 1:0] B1;

	wire   C1,Cin;
	
	assign B1={`DATA_WIDTH{op_slt|op_sub|op_sltu}}&~B|{`DATA_WIDTH{~(op_slt|op_sub|op_sltu)}}&B;
	assign Cin=op_slt|op_sub|op_sltu;
	assign {C1,Result_add}=A+B1+Cin;
	
	/*by using this method, Cin will be recognized as a carry signal, so only one full adder is required*/
	
	assign CarryOut=(op_sub|op_sltu)&(C1^1)|~(op_sub|op_sltu)&C1;
	
	/*in the substraction case the calculation result is 2^{33}+A-B, 
	so the only cases for C1 to be 1 is that A-B is a natural number.
	In this case, the carryout should be 0. When A-B<0, C1 will be 1,
	so in the case of substraction, the appropriate solution is to reverse C1 to get carryout.
	*/

	assign Overflow=A[`DATA_WIDTH - 1 ]&(ALUop[2]^B[`DATA_WIDTH - 1 ])&~Result_add[`DATA_WIDTH - 1 ]|~A[`DATA_WIDTH - 1 ]&(ALUop[2]^~B[`DATA_WIDTH - 1 ])&Result_add[`DATA_WIDTH - 1 ];//simplification by Karnaugh map
	
	/*this overflow is fully simplied, and the original one is:
	
	assign Overflow=(ALUop==3'b010)?(((A[`DATA_WIDTH - 1 ]==B[`DATA_WIDTH - 1 ])&&(~R1[`DATA_WIDTH - 1 ]==A[`DATA_WIDTH - 1 ]))?1:0):
					((ALUop==3'b110)?(((A[`DATA_WIDTH - 1 ]==0&&B[`DATA_WIDTH - 1 ]==1&&R1[`DATA_WIDTH - 1 ]==1)||(A[`DATA_WIDTH - 1 ]==1&&B[`DATA_WIDTH - 1 ]==0&&R1[`DATA_WIDTH - 1 ]==0))?1:0):0);
			
			in the case of addition, overflow only occurs when A and B are both positive or negative, and the symbol of result differed to A.
			in the case of substraction, overflow occurs when A - (-B) or (-A)-B
	*/

	assign Result={`DATA_WIDTH{op_slt}}&(Overflow^Result_add[`DATA_WIDTH - 1 ])|{`DATA_WIDTH{op_add|op_sub}}&Result_add|{`DATA_WIDTH{op_and}}&Result_and|{`DATA_WIDTH{op_or}}&Result_or|{`DATA_WIDTH{op_xor}}&Result_xor|{`DATA_WIDTH{op_nor}}&Result_nor|{`DATA_WIDTH{op_sltu}}&CarryOut;
	
	/*we can use the result of substraction to get the slt:
	  when overflow does not occur, the symbol of Result is answer.
	  when overflow occurs, the symbol of Result differs, so using the overflower to xor can get the answer. 
	*/

	assign Zero=~|Result;
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值