1、实验代码及注解(.v 文件)
`timescale 1ns / 1ps
// Create Date: 2021/10/15 17:10:25
module adder(
input ia,
input ib,
input cin,
output cout,
output cur
)
assign cur = ia ^ ib ^ cin
assign cout = ia & cin | ib & cin | ia & ib
endmodule
module add_8(
input [7:0] a,
input [7:0] b,
input cin,
output [7:0] s,
output o, // overflow,
output cout
)
wire c0,c1,c2,c3,c4,c5,c6,c7
adder d0(a[0],b[0],cin,c0,s[0])
adder d1(a[1],b[1],c0,c1,s[1])
adder d2(a[2],b[2],c1,c2,s[2])
adder d3(a[3],b[3], c2,c3,s[3])
adder d4(a[4],b[4],c3,c4,s[4])
adder d5(a[5],b[5],c4,c5,s[5])
adder d6(a[6],b[6],c5,c6,s[6])
adder d7(a[7],b[7],c6,c7,s[7])
assign cout = c7
assign o = (a[7] & b[7] & ~s[7]) | (~a[7] & ~b[7] & s[7])
endmodule
module add_sub_8(
input [7:0] a,
input [7:0] b,
input cin,
input op,
output [7:0] res,
output overflow,
output cout
)
add_8 d4(a,{op,op,op,op,op,op,op,op} ^ b,op ^ cin,res,overflow,cout)
endmodule
module slt(
input [7:0] a,
input [7:0] b,
output result
)
wire o, c
wire [7:0] r
add_sub_8 sub(a, b, 0, 1, r, o, c)
assign result = o ^ r[7]
endmodule
module shift(
input [7:0] a,
input b,
input [1:0]m,
output [7:0] out
)
assign out = b == 1'b0 ? 8'b0000_0000 : ((8'b1111_1111 & a) << m);
endmodule
module mult(
input [3:0] a,
input [3:0] b,
output [7:0] out
);
wire [7:0] abs_a; // a 的绝对值
wire [7:0] abs_b; // b 的绝对值
wire flag;
assign flag = a[3] ^ b[3]; // 通过对符号位的异或取得乘积的符号
wire [3:0] t1;
wire [3:0] t2;
wire o1,c1,o2,c2,o3,c3,o4,c4,o5,c5,o6,c6;
add_sub_8 m0(a,1,0,1,t1,o1,c1); // a - 1
add_sub_8 m1(b,1,0,1,t2,o2,c2); // b - 1
assign abs_a[7:4] = 4'b0000
assign abs_b[7:4] = 4'b0000
assign abs_a[3:0] = a[3] == 1'b1 ? ~t1 : a
assign abs_b[3:0] = b[3] == 1'b1 ? ~t2 : b
wire [7:0] T1
wire [7:0] T2
wire [7:0] T3
wire [7:0] T4
shift h1(abs_a,abs_b[0],2'b00,T1)
shift h2(abs_a,abs_b[1],2'b01,T2)
shift h3(abs_a,abs_b[2],2'b10,T3)
shift h4(abs_a,abs_b[3],2'b11,T4)
wire [7:0] T5
wire [7:0] T6
wire [7:0] res
wire [7:0] T7
add_sub_8 m2(T1,T2,0,0,T5,o3,c3)
add_sub_8 m3(T5,T3,0,0,T6,o4,c4)
add_sub_8 m4(T6,T4,0,0,res,o5,c5)
add_sub_8 m5(~res,1,0,0,T7,o6,c6)
assign out = flag == 1'b1 ? T7 : res; // 由乘积符号标志,确定输出的是原值还是它的补码
endmodule
module CPU(
input read_to_R2, // 是否把值存入 R2
input alu, // 控制是否开启 alu 部分计算
input clk, // 时钟
input [7:0] b, // 数据源
output reg [7:0] led_id,
output reg [6:0] out_led, // 数码管显示
output ZF, // 运算结果全零,则为 1
CF, // 进借位标志位
OF, // 溢出标志位
SF, // 符号标志位,与 F 的最高位相同
PF // 奇偶标志位,F 有奇数个 1,则 PF=1,否则为 0
);
reg [7:0] R0; // 对应地址码 00
reg [7:0] R1; // 对应地址码 01
reg [7:0] R2; // 对应地址码 10
reg [7:0] data_to_R2; // 在 alu 计算 和 存入 R2 的值的零时变量
wire [7:0] res1,res2,res3,res4,res5;
wire res9;
wire OF1,OF2,OF3,OF4;
wire CF1,CF2,CF3,CF4;
reg of,cf;
reg [7:0] A1;
reg [7:0] B1;
wire [7:0] A; // 第一个源数据
wire [7:0] B; // 第二个源数据
assign A = A1;
assign B = B1;
add_sub_8 fun1(A,B,0,0,res1,OF1,CF1); // res1 = A + B
add_sub_8 fun2(A,1,0,0,res2,OF2,CF2); // res2 = A - 1
add_sub_8 fun3(A,B,0,1,res3,OF3,CF3); // res3 = A - B
add_sub_8 fun4(A,1,0,1,res4,OF4,CF4); // res4 = A - 1;
mult fun5(A[3:0],B[3:0],res5); // res5 = A * B
slt fun9(A,B,res9); // 比较 A 和 B 的大小,A >= B, res9 = 0; A < B, res9 = 1;
always@(b) begin
if (read_to_R2 == 1'b1) R2 = data_to_R2
if (b[7:6] == 2'b10 && alu == 1'b0) begin // 写入数据进入寄存器
if (b[5:4] == 2'b00) begin // 根据地址码,存入值
if (b[3] == 1'b1) R0[7:4] = 4'b1111
else R0[7:4] = 4'b0000
R0[3:0] = b[3:0]
end
else if (b[5:4] == 2'b01) begin
if (b[3] == 1'b1) R1[7:4] = 4'b1111
else R1[7:4] = 4'b0000
R1[3:0] = b[3:0]
end
else if (b[5:4] == 2'b10) begin
if (b[3] == 1'b1) begin
R2[7:4] = 4'b1111
data_to_R2[7:4] = 4'b1111
end
else begin
R2[7:4] = 4'b0000
data_to_R2[7:4] = 4'b0000
end
R2[3:0] = b[3:0]
data_to_R2 = b[3:0]
end
end
else if (alu == 1'b1) begin
case(b[3:2])
2'b00: A1 = R0
2'b01: A1 = R1
2'b10: A1 = R2
endcase
case(b[1:0])
2'b00: B1 = R0
2'b01: B1 = R1
2'b10: B1 = R2
endcase
case(b[7:4]) // 以下模拟 alu 部分进行取出对应状态计算的结果和状态
4'b0000: begin
data_to_R2 = res1
of = OF1
cf = CF1
end
4'b0001: begin
data_to_R2 = res2
of = OF2
cf = CF2
end
4'b0010: begin
data_to_R2 = res3
of = OF3
cf = ~CF3
end
4'b0011: begin
data_to_R2 = res4
of = OF4
cf = ~CF4
end
4'b1100: data_to_R2 = res5
4'b0100: data_to_R2 = A & B
4'b0101: data_to_R2 = A | B
4'b0110: data_to_R2 = A ^ B
4'b0111: data_to_R2 = res9
endcase
end
end
// 数码管灯显示数据
wire [7:0] n
assign n = b[7:0] == 8'b1111_0010 ? R2 : // 读取 R2 的值
b[7:0] == 8'b1111_0000 ? R0 : // 读取 R0 的值
b[7:0] == 8'b1111_0001 ? R1 : // 读取 R1 的值
b[7:0] == 8'b1111_0011 ? data_to_R2 : // 读取储存 R2 值的中间变量
b[7:0] == 8'b1111_0100 ? A : // 读取第二个源数据
b[7:0] == 8'b1111_0101 ? B : // 读取第二个源数据
8'b0000_0000
assign OF = of
assign CF = cf
assign SF = n[7]
assign ZF = ~ (n[0] | n[1] | n[2] | n[3] | n[4] | n[5] | n[6] | n[7])
assign PF = ~(n[0] ^ n[1] ^ n[2] ^ n[3] ^ n[4] ^ n[5] ^ n[6] ^ n[7])
parameter CLK_COUNT = 249999
reg [31:0] count
reg [1:0] id
wire flag
assign flag=n[7]
//8位2进制,十进制至多3位
reg [7:0] n1
reg [7:0] n2
reg [7:0] n3
reg [7:0] abs
always @(*)
case(flag) //求正数的个十百位
1'b0:
begin
n1 = n / 100 % 10
n2 = n / 10 % 10
n3 = n % 10
end
1'b1:
begin
abs=(~n)+1
n1 = abs / 100 % 10
n2 = abs / 10 % 10
n3 = abs % 10
end
endcase
//时钟上升沿
always@(posedge clk) begin //根据时钟信号控制切换显示的数码管
if (count == CLK_COUNT)begin
count <= 0
id = (id + 1)
end
else
count <= count+1
end
//选择灯,显示数字
always@(id) begin
if (id == 0) begin
led_id <= 8'b1111_0111
if(n[7]==1)
out_led<=7'b1111110
else
out_led<=7'b1111111
end
//其余三个管显示逻辑相同
else if (id == 1) begin
led_id <= 8'b1111_1011
begin
case(n1)
4'b0000: out_led = 7'b0000001; //0
4'b0001: out_led = 7'b1001111; //1
4'b0010: out_led = 7'b0010010; //2
4'b0011: out_led = 7'b0000110; //3
4'b0100: out_led = 7'b1001100; //4
4'b0101: out_led = 7'b0100100; //5
4'b0110: out_led = 7'b0100000; //6
4'b0111: out_led = 7'b0001111; //7
4'b1000: out_led = 7'b0000000; //8
4'b1001: out_led = 7'b0000100; //9
endcase
end
end
else if (id == 2) begin
led_id <= 8'b1111_1101
begin
case(n2)
4'b0000: out_led = 7'b0000001; //0
4'b0001: out_led = 7'b1001111; //1
4'b0010: out_led = 7'b0010010; //2
4'b0011: out_led = 7'b0000110; //3
4'b0100: out_led = 7'b1001100; //4
4'b0101: out_led = 7'b0100100; //5
4'b0110: out_led = 7'b0100000; //6
4'b0111: out_led = 7'b0001111; //7
4'b1000: out_led = 7'b0000000; //8
4'b1001: out_led = 7'b0000100; //9
endcase
end
end
else if (id == 3) begin
led_id <= 8'b1111_1110
begin
case(n3)
4'b0000: out_led = 7'b0000001; //0
4'b0001: out_led = 7'b1001111; //1
4'b0010: out_led = 7'b0010010; //2
4'b0011: out_led = 7'b0000110; //3
4'b0100: out_led = 7'b1001100; //4
4'b0101: out_led = 7'b0100100; //5
4'b0110: out_led = 7'b0100000; //6
4'b0111: out_led = 7'b0001111; //7
4'b1000: out_led = 7'b0000000; //8
4'b1001: out_led = 7'b0000100; //9
endcase
end
end
end
endmodule
2、实验约束文件代码(.xdc 文件)
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_id[0]}]
set_property PACKAGE_PIN J17 [get_ports {led_id[0]}]
set_property PACKAGE_PIN J18 [get_ports {led_id[1]}]
set_property PACKAGE_PIN T9 [get_ports {led_id[2]}]
set_property PACKAGE_PIN J14 [get_ports {led_id[3]}]
set_property PACKAGE_PIN P14 [get_ports {led_id[4]}]
set_property PACKAGE_PIN T14 [get_ports {led_id[5]}]
set_property PACKAGE_PIN K2 [get_ports {led_id[6]}]
set_property PACKAGE_PIN U13 [get_ports {led_id[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {out_led[0]}]
set_property PACKAGE_PIN T10 [get_ports {out_led[6]}]
set_property PACKAGE_PIN R10 [get_ports {out_led[5]}]
set_property PACKAGE_PIN K16 [get_ports {out_led[4]}]
set_property PACKAGE_PIN K13 [get_ports {out_led[3]}]
set_property PACKAGE_PIN P15 [get_ports {out_led[2]}]
set_property PACKAGE_PIN T11 [get_ports {out_led[1]}]
set_property PACKAGE_PIN L18 [get_ports {out_led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {b[0]}]
set_property PACKAGE_PIN R13 [get_ports {b[7]}]
set_property PACKAGE_PIN U18 [get_ports {b[6]}]
set_property PACKAGE_PIN T18 [get_ports {b[5]}]
set_property PACKAGE_PIN R17 [get_ports {b[4]}]
set_property PACKAGE_PIN R15 [get_ports {b[3]}]
set_property PACKAGE_PIN M13 [get_ports {b[2]}]
set_property PACKAGE_PIN L16 [get_ports {b[1]}]
set_property PACKAGE_PIN J15 [get_ports {b[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN E3 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports alu]
set_property PACKAGE_PIN T8 [get_ports alu]
set_property IOSTANDARD LVCMOS33 [get_ports t]
set_property PACKAGE_PIN U8 [get_ports t]
set_property IOSTANDARD LVCMOS33 [get_ports ZF]
set_property IOSTANDARD LVCMOS33 [get_ports CF]
set_property IOSTANDARD LVCMOS33 [get_ports OF]
set_property IOSTANDARD LVCMOS33 [get_ports SF]
set_property IOSTANDARD LVCMOS33 [get_ports PF]
set_property PACKAGE_PIN R18 [get_ports ZF]
set_property PACKAGE_PIN N14 [get_ports CF]
set_property PACKAGE_PIN J13 [get_ports OF]
set_property PACKAGE_PIN K15 [get_ports SF]
set_property PACKAGE_PIN H17 [get_ports PF]