本实验要求设计一个具有16种运算功能的32位ALU,并能够产生运算结果的标志:结果为零标志ZF(Zero Hag)和溢出标志OF(Overflow Flag)。ALU通过4根控制线ALU_OP[3:0]来选择其16种运算功能。仿真测试,要求测试用例能完整测试各种功能及标志位的不同结果。
ALU_OP[3:0] | ALU功能 | 操作说明 |
---|---|---|
0000 | and | 逻辑与运算 |
0001 | or | 逻辑或运算 |
0010 | xor | 逻辑异或运算 |
0011 | nor | 逻辑或非运算 |
0100 | add | 算术加运算 |
0101 | sub | 算术减运算 |
0110 | slt | 若A |
0111 | sll | B逻辑左移A所指定的位数 |
1000 | F=A+1 | 自加1 |
1000~1001 | 保留 |
module ALU(ALU_OP,A,B,F,ZF,OF); // 模块名为ALU
input [3:0] ALU_OP; // ALU_OP为控制16种运算功能的控制线
input [32:1] A; //A,B为32位的运算数
input [32:1] B;
output [32:1] F; // F为输出结果
output ZF; // ZF为零标志
output OF; // OF为溢出标志
module ALU(ALU_OP,A,B,F,ZF,OF,CF,SF,PF);//加了CF,SF,PF版
input [3:0] ALU_OP;
input [32:1] A;
input [32:1] B;
output [32:1] F;
output ZF,OF,CF,CF,SF,PF;
reg [32:1] F;
reg C,ZF,OF,CF,SF,PF;
always@(*)
begin
C=0;
OF=0;
case(ALU_OP)
4'b0000:begin F=A&B; end
4'b0001:begin F=A|B; end
4'b0010:begin F=A^B; end
4'b0011:begin F=~(A|B); end
4'b0100:begin {
C,F}=A+B;OF = A[32]^B[32]^F[32]^C;CF = C;end
4'b0101:begin {
C,F}=A-B;OF = A[32]^B[32]^F[32]^C;CF = ~C; end
4'b0110:begin F=A<B; end
4'b0111:begin F=B<<A; end
4'b1000:begin {
C,F}=A+1;OF = C;;CF = C; end
endcase
ZF = F==0;
SF = F[32];
PF = ~^F;
end
endmodule
module ALU(ALU_OP,A,B,F,ZF,OF); //未加CF,SF,PF版
input [3:0] ALU_OP;
input [32:1] A;
input [32:1] B;
output [32:1] F;
output ZF;
output OF;
reg [32:1] F;
reg C,ZF,OF;
always@(*)
begin
C=0;
OF=0;
case(ALU_OP)
4'b0000:begin F=A&B; end
4'b0001:begin F=A|B; end
4'b0010:begin F=A^B; end
4'b0011:begin F=~(A|B); end
4'b0100:begin {
C,F}=A+B;OF = A[32]^B[32]^F[32]^C; end
4'b0101:begin {
C,F}=A-B;OF = A[32]^B[32]^F[32]^C; end
4'b0110:begin F=A<B; end
4'b0111:begin F=B<<A; end
4'b1000:begin {
C,F}=A+1;OF = C!=0; end
endcase
ZF = F==0;
end
endmodule
initial begin
A=32'h55555555; B=32'h99999999;
ALU_OP = 4'b0000; #100;//按位与
ALU_OP = 4'b0001; #100;//按位或
ALU_OP = 4'b0010; #100;//按位异或
ALU_OP = 4'b0011; #100;//按位或非
ALU_OP = 4'b0100; #100;//相加
ALU_OP = 4'b0101; #100;//相减
ALU_OP = 4'b0110; #100;//判断A
ALU_OP = 4'b0111; #100;//B逻辑左移A
ALU_OP = 4'b1000; #100;//自加1
A=32'h00FF00FF; B=32'h5F5F5F5F;
ALU_OP = 4'b0000; #100;//按位与
ALU_OP = 4'b0001; #100;//按位或
ALU_OP = 4'b0010; #100;//按位异或
ALU_OP = 4'b0011; #100;//按位或非
ALU_OP = 4'b0100; #100;//相加
ALU_OP = 4'b0101; #100;//相减
ALU_OP = 4'b0110; #100;//判断A
ALU_OP = 4'b0111; #100;//B逻辑左移A
ALU_OP = 4'b1000; #100;//自加1
A=32'hF0F0F0F0; B=32'h00000004;
ALU_OP = 4'b0000; #100;//按位与
ALU_OP = 4'b0001; #100;//按位或
ALU_OP = 4'b0010; #100;//按位异或
ALU_OP = 4'b0011; #100;//按位或非
ALU_OP = 4'b0100; #100;//相加
ALU_OP = 4'b0101; #100;//相减
ALU_OP = 4'b0110; #100;//判断A
ALU_OP = 4'b0111; #100;//B逻辑左移A
ALU_OP = 4'b1000; #100;//自加1
A=32'h00000004; B=32'hEFEFEFEF;
ALU_OP = 4'b0000; #100;//按位与
ALU_OP = 4'b0001; #100;//按位或
ALU_OP = 4'b0010; #100;//按位异或
ALU_OP = 4'b0011; #100;//按位或非
ALU_OP = 4'b0100; #100;//相加
ALU_OP = 4'b0101; #100;//相减
ALU_OP = 4'b0110; #100;//判断A
ALU_OP = 4'b0111; #100;//B逻辑左移A
ALU_OP = 4'b1000; #100;//自加1
end
endmodule
①操作数:A=32’h55555555; B=32’h99999999;
②操作数:A=32’h00FF00FF; B=32’h5F5F5F5F;
对于加法运算,当输入测试数据A=OFFFFH, B=1H时,该组数据相加产生什么结果?请同学考虑,当A、B被看作无符号数,A. B被看成有符号数,这两种情况下运算器硬件操作上有区别吗?无符号数和有符号数是怎样识别的呢?
答:该组数据相加产生10000H。当A、B被看作无符号数,A. B被看成有符号数,这两种情况下运算器硬件操作上没有区别,系统对有符号数和无符号数的加减法都采用一样的策略。CPU只会根据输入信号进行逻辑运算,在硬件级别没有有符号无符号的概念。识别无符号数和有符号数,可以根据指令进行判断,如MIPS加法指令,add是带符号数加,addu是无符号数加。
仔细研究MIPS的核心指令集,结合本实验所实现的ALU,分析该ALU能否实现MIPS核心指令集的所有指令?如果不能,请分析它还需要哪些运算功能?
答:经过分析,该ALU不能实现MIPS核心指令集的所有指令。它还需要:带进位的加法运算、带进位的减法运算、位清除指令、负数比较、位测试指令、比较指令、相等测试指令等。
从你的实验结果中能否对以下问题得出结论:slt操作中“A
答:带入数据进行实验研究
A=32’b0; B=32’hFFFFFFFF; F=1
A=32’hFFFFFFFFF; B=32’b0; F=0
A=32’h8FFFFFFF; B=32’hFFFFFFFF; F=1
A=32’hFFFFFFFF; B=32’h8FFFFFFF; F=0
A=32’h0FFFFFFF; B=32’h7FFFFFFF; F=1
A=32’h8FFFFFFF; B=32’h7FFFFFFF; F=0
表明slt操作中的“A
实验中的ALU实现了逻辑左移操作sll,考虑逻辑右移和算术右移操作如何实现?
考虑为何MIPS指令系统中没有算术左移指令?
答:逻辑右移可以通过B>>A实现。算术右移还需判断原操作数的符号位(最高位),若原操作数符号位为0,则操作与逻辑右移相同。若原操作数符号为1,需要在逻辑右移的基础上,将B操作数的最高A位置1。MIPS指令系统中没有算术左移指令是因为算数左移和逻辑左移的方法是一样的。
80X86CPU除了ZF和OF,还有其他标志位,试理解80X86的3个标志位SF、CF和PF的作用和逻辑,将这3个标志位实现到MIPS的多功能ALU中,并完成板级调试。
答:详见实验源代码。