1. Experimental code and notes (.v file)
`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
); // 将相与的值向左移动 m 位
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; // 绝对值都是正数,所以拓展成 8 位后,前面四位都要补上 0
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); // T5 = T1 + T2
add_sub_8 m3(T5,T3,0,0,T6,o4,c4); // T6 = T5 + T3
add_sub_8 m4(T6,T4,0,0,res,o5,c5); // res = T6 + T4
add_sub_8 m5(~res,1,0,0,T7,o6,c6); // T7 = ~res + 1 即是取 res 的补码
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; // 是否将临时变量的值存如 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; // 根据写入数(补码)最高位,判断并 4 位长拓展为 8 位,下同
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; // default
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;//id0~3对应左到右四个数码管
wire flag; //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
Copy the code
2. Experimental constraint file code (.xdc file)
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]Copy the code