32位ALU
实验要求是使用3位OP码,实现32位ALU的相关运算。需要输出运算结果和4个标志位:
- CF:进位(无符号溢出)
- OF:溢出标志(有符号溢出)
- ZF:零标志
- SF:符号位
ALU_32本体代码实现
module ALU_32(
input logic [2:0] op,
input logic [31:0] a,
input logic [31:0] b,
output logic [31:0] out,
output logic OF,
output logic CF,
output logic ZF,
output logic SF
);
always@(*)
begin
case(op)
//A AND B
3'b000:
begin
out=a&b;
ZF = (out==0)?1:0;
CF =0;
OF =0;
SF = out[31];
end
// A OR B
3'b001:
begin
out = a|b;
ZF = (out==0)?1:0;
CF=0;
OF=0;
SF=out[31];
end
//A+B signed
3'b010:
begin
{CF,out}=a+b;
ZF =(out==0)?1:0;
OF=((a[31]==b[31])&&(~out[31]==a[31]));//符号相同,但结果变号了
SF=out[31];
end
// A AND ~B
3'b100:
begin
out = a&(~b);
ZF = (out==0)?1:0;
CF =0;
OF =0;
SF = out[31];
end
//A OR ~B
3'b101:
begin
out = a |(~b);
ZF = (out==0)?1:0;
CF =0;
OF =0;
SF = out[31];
end
// A - B signed
3'b110:
begin
{CF,out}=a-b;
ZF=(out==0)?1:0;
SF=(out[31]);
OF=((a[31]^b[31])&&(out[31]==b[31]));//正数减负数得到一个负数,或者负数减正数得到一个正数显然溢出
end
//SLT 小于则置1
3'b111:
begin
out= a < b;
ZF=(out==0);
CF=0;
OF=0;
SF= out[31];
end
default:
begin OF=0;CF=0;ZF=1;SF=0;out=0; end
endcase
end
上板需要的七段数码管显示代码
x7seg
module X7Seg(
input logic clr,
input logic clk,
input logic [31:0] x,
output logic [6:0] a2g,
output logic [7:0] an
);
logic [2:0] s;//选择哪个数码管,共8个,3位
logic [3:0]digit;//依次显示的数据,0到9有10位数,故需要4位
logic [19:0]clkdiv;//分频
assign dp=1; //关闭小数点
assign s=clkdiv[19:17]; //选择一个合适的频率
always_comb
case(s)
0: begin an=8'b01111111;digit=x[31:28]; end
1: begin an=8'b10111111;digit=x[27:24]; end
2: begin an=8'b11011111;digit=x[23:20]; end
3: begin an=8'b11101111;digit=x[19:16]; end
4: begin an=8'b11110111;digit=x[15:12]; end
5: begin an=8'b11111011;digit=x[11:8 ]; end
6: begin an=8'b11111101;digit=x[ 7:4 ]; end
7: begin an=8'b11111110;digit=x[ 3:0 ]; end
default: digit='b1111;
endcase
always @(posedge clk,posedge clr)
if(clr==1) clkdiv <= 0;
else clkdiv <= clkdiv+1;
Hex7Seg s7(.x(digit),.a2g(a2g));
endmodule
Hex7Seg
module Hex7Seg(
input logic [3:0] x,
output logic [6:0] a2g
);
always_comb
case(x)
'h0:a2g=7'b0000001;
'h1:a2g=7'b1001111;
'h2:a2g=7'b0010010;
'h3:a2g=7'b0000110;
'h4:a2g=7'b1001100;
'h5:a2g=7'b0100100;
'h6:a2g=7'b0100000;
'h7:a2g=7'b0001111;
'h8:a2g=7'b0000000;
'h9:a2g=7'b0000100;
'ha:a2g=7'b0001000;
'hb:a2g=7'b1100000;
'hc:a2g=7'b0110001;
'hd:a2g=7'b1000010;
'he:a2g=7'b0110000;
'hf:a2g=7'b0111000;
default: a2g=7'b1111111;
endcase
endmodule
仿真验证
仿真代码
module ALU_test(
);
logic [2:0] op;
logic [31:0] a,b;
logic [31:0] out;
logic CF,OF,ZF,SF;
ALU_32 alu(op,a,b,out,OF,CF,ZF,SF);
initial
begin
//A + B signed
op=3'b010;
a=32'hf2340000;
b=32'h80000000;//最小的数+,负溢出,OF=1
#20 a=32'h7fffffff;
b=32'h70000001;//正溢出
#20 a=32'h7fffffff;
b=32'hf0000001;//最大的正数加一个负数
#20 a=32'hffffffff;
b=32'h00000001;//-1+1
//A-B signed
#20 op=3'b110;
a=32'h72340000;
b=32'h60000000;//随便一个数字
#20 a=32'h7fffffff;
b=32'hf0000001;//正溢出的
#20 a=32'hf00fffff;
b=32'h7ffffff1;//负溢出的
#20 a=32'hffffffff;
b=32'hffffffff;//为0的
#20 a=32'hf0000000;
b=32'h0fffffff;//边界测试
#20 a=32'h7fffffff;
b=32'h80000000;
//a and b
#20 op=3'b000;
a=32'h72340000;
b=32'h60000000;
#20 a=32'h7fffffff;
b=32'h00000000;
// a or b
#20 op=3'b001;
a=32'h00000000;
b=32'h00000000;
#20 a=32'h7fffffff;
b=32'hf0000001;
//A AND ~B
#20 op=3'b100;
a=32'ha0000000;
b=32'h50000000;
#20 a=32'h7fffffff;
b=32'hf0000001;
//A OR ~B
#20 op=3'b101;
a=32'h123451ff;
b=32'h60000000;
#20 a=32'h7fffffff;
b=32'hf0000001;
//SLT
#20 op=3'b111;
a = 32'hffffffff;
b = 32'hffffffff;
#20 a = 32'h12345678;
b = 32'h01234567;
#20 a = 32'h01234567;
b = 32'h12345678;
#20 a = 32'hf1234567;
b = 32'h7231423;
#20 b = 32'hf1234567;
a = 32'h7231423;
end
endmodule
仿真结果
遇到的问题
问题1:
[DRC BIVC-1] Bank IO Standard Vcc: Conficting Vcc voltages in bank xx. For example, the following two ports in this bank have conficting VCCOs: xxx0(LVCMOS18, requiring VCCO=1.800) and xxx1(LVCMOS33, requiring VCCO=3.300)
Solution: pin 电压约束错误,一个bank上只能约束同一种电压。如果你有一个pin约束在了bank xxx,约束的是LVCMOS18,那么你其他也约束在该bank xxx的pin的电压约束也只能是LVCOMS18。
解决方案:芯片型号选错了,重新选下