【学习笔记】SystemVerilog 常见组合逻辑电路
2 常见组合逻辑电路
2.1 32 位补码加法器
2.1.1一位全加器
一位全加器设计如下:
// 一位全加器
module FullAdder(
input logic a,
input logic b,
input logic cin,
output logic s,
output logic cout
);
assign s = ((~a) & (~b) & cin) | ((~a) & b & (~cin)) | (a & (~b) & (~cin)) | (a & b & cin);
assign cout = (b & cin) | (a & b) | (a & cin);
endmodule
2.1.2 32位补码加法器
利用一位全加器设计32位补码加法器:
// 32 位补码全加器
module Adder_32bit(
input logic [31:0] A,
input logic [31:0] B,
input logic m,
output logic [31:0] sum, // 各位输出
output logic v, // 溢出判断
output logic cout // 最后一位进位
);
// 初始化
logic [32:0] c;
logic s32;
logic [31:0] a;
logic [31:0] b;
assign a = A;
assign b = (m) ? (~B) : B; // m = 1 时对B求反
// 加法
FullAdder ADD0(a[0], b[0], m, sum[0], c[0]);
for( genvar i = 1; i < 32; i++)begin
FullAdder ADD(a[i], b[i], c[i-1], sum[i], c[i]);
end
FullAdder AD32(a[31], b[31], c[31], s32, c[32]);
// 进位与溢出判断赋值
assign cout = c[32];
assign v = sum[31] ^ s32;
endmodule
电路图如下(有点可怕):

2.1.3 测试与验证
编写 testbench 激励文件.
这里用AI生成了一些测试用例用作32位全加器的测试.
Test Case 1: A = 00000000, B = 00000000, m = 0
Test Case 2: A = 00000001, B = 00000002, m = 0
Test Case 3: A = FFFFFFFF, B = 00000001, m = 0
Test Case 4: A = 7FFFFFFF, B = 00000001, m = 0
Test Case 5: A = 80000000, B = 00000001, m = 0
Test Case 6: A = FFFFFFFF, B = FFFFFFFF, m = 0
Test Case 7: A = 00000001, B = 00000001, m = 1
Test Case 8: A = FFFFFFFF, B = FFFFFFFF, m = 1
将测试样例输入testbench文件.
`timescale 1ns / 1ps
module tb_Adder_32bit();
logic [31:0] A;
logic [31:0] B;
logic m;
logic [31:0] sum;
logic v;
logic cout;
Adder_32bit tb_Adder_32bit(.A(A),.B(B),.m(m),.sum(sum),.v(v),.cout(cout));
initial begin
// 初始化输入信号
A = 32'h00000000;
B = 32'h00000000;
m = 1'b0;
// 测试用例1: A = 00000000, B = 00000000, m = 0
#10;
$display("Test Case 1: A = 0, B = 0, m = 0");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例2: A = 00000001, B = 00000002, m = 0
A = 32'h00000001;
B = 32'h00000002;
#10;
$display("Test Case 2: A = 1, B = 2, m = 0");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例3: A = FFFFFFFF, B = 00000001, m = 0
A = 32'hFFFFFFFF;
B = 32'h00000001;
#10;
$display("Test Case 3: A = FFFFFFFF, B = 1, m = 0");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例4: A = 7FFFFFFF, B = 00000001, m = 0
A = 32'h7FFFFFFF;
B = 32'h00000001;
#10;
$display("Test Case 4: A = 7FFFFFFF, B = 1, m = 0");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例5: A = 80000000, B = 00000001, m = 0
A = 32'h80000000;
B = 32'h00000001;
#10;
$display("Test Case 5: A = 80000000, B = 1, m = 0");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例6: A = FFFFFFFF, B = FFFFFFFF, m = 0
A = 32'hFFFFFFFF;
B = 32'hFFFFFFFF;
#10;
$display("Test Case 6: A = FFFFFFFF, B = FFFFFFFF, m = 0");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例7: A = 00000001, B = 00000001, m = 1
A = 32'h00000001;
B = 32'h00000001;
m = 1'b1;
#10;
$display("Test Case 7: A = 1, B = 1, m = 1");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 测试用例8: A = FFFFFFFF, B = FFFFFFFF, m = 1
A = 32'hFFFFFFFF;
B = 32'hFFFFFFFF;
m = 1'b1;
#10;
$display("Test Case 8: A = FFFFFFFF, B = FFFFFFFF, m = 1");
$display("sum = %h, v = %b, cout = %b", sum, v, cout);
// 结束仿真
$finish;
end
endmodule
测试结果:


可以验证结果是正确的.
Test Case 1: A = 0, B = 0, m = 0
输入:A = 0, B = 0
输出:sum = 00000000, v = 0, cout = 0
说明:0 + 0 = 0,无溢出和进位。
Test Case 2: A = 1, B = 2, m = 0
输入:A = 1, B = 2
输出:sum = 00000003, v = 0, cout = 0
说明:1 + 2 = 3,无溢出和进位。
Test Case 3: A = FFFFFFFF, B = 1, m = 0
输入:A = -1 (补码表示为32'hFFFFFFFF), B = 1
输出:sum = 00000000, v = 0, cout = 1
说明:-1 + 1 = 0,进位标志为1,无溢出。
Test Case 4: A = 7FFFFFFF, B = 1, m = 0
输入:A = 2147483647 (最大正数), B = 1
输出:sum = 80000000, v = 1, cout = 0
说明:2147483647 + 1 = -2147483648(溢出),溢出标志为1。
Test Case 5: A = 80000000, B = 1, m = 0
输入:A = -2147483648 (最小负数), B = 1
输出:sum = 80000001, v = 0, cout = 0
说明:-2147483648 + 1 = -2147483647,无溢出。
Test Case 6: A = FFFFFFFF, B = FFFFFFFF, m = 0
输入:A = -1, B = -1
输出:sum = FFFFFFFE, v = 0, cout = 1
说明:-1 + (-1) = -2,进位标志为1,无溢出。
Test Case 7: A = 1, B = 1, m = 1
输入:A = 1, B = 1
输出:sum = 00000000, v = 0, cout = 1
说明:1 - 1 = 0,进位标志为1,无溢出。
Test Case 8: A = FFFFFFFF, B = FFFFFFFF, m = 1
输入:A = -1, B = -1
输出:sum = 00000000, v = 0, cout = 1
说明:-1 - (-1) = 0,进位标志为1,无溢出。
2.2 32 位补码乘法器
2.2.1 32位补码乘法器
利用32位补码加法器设计32位补码乘法器,其中全加器同上:点击跳转
`timescale 1ns / 1ps
module FullAdder(
input logic a,
input logic b,
input logic cin,
output logic s,
output logic cout
);
assign s = ((~a) & (~b) & cin) | ((~a) & b & (~cin)) | (a & (~b) & (~cin)) | (a & b & cin);
assign cout = (b & cin) | (a & b) | (a & cin);
endmodule
module Multiplier_32bit(
input logic [31:0] A,
input logic [31:0] B,
output logic [63:0] product
);
logic [31:0][30:0] sum, c;
logic [63:0] p;
logic [31:0] a, b;
assign a = A;
assign b = B;
assign p[0] = a[0] & b[0];
for(genvar i = 0; i < 31; i++) begin
FullAdder ADD(a[i+1] & b[0], a[i] & b[1] , 0, sum[0][i], c[0][i]);
end
for(genvar j = 1; j < 31; j++)begin
assign p[j] = sum[j-1][0];
for(genvar i = 0; i < 30; i++)begin
FullAdder ADD(sum[j-1][i+1], a[i] & b[j+1], c[j-1][i], sum[j][i], c[j][i]);
end
FullAdder ADD(a[31] & b[j], a[30] & b[j+1], c[j-1][30], sum[j][30], c[j][30]);
end
assign p[31] = sum[30][0];
FullAdder ADD31_0(sum[30][1], c[30][0], 0, sum[31][0], c[31][0]);
assign p[32] = sum[31][0];
for(genvar i = 1; i < 30; i++)begin
FullAdder ADD(sum[30][i+1], c[30][i], c[31][i-1], sum[31][i], c[31][i]);
assign p[32+i] = sum[31][i];
end
FullAdder ADD31_30(a[31] & b[31], c[30][30], c[31][29], sum[31][30], c[31][30]);
assign product = p;
endmodule
电路图如下(有点可怕\(\times 2\)):

2.2.2 测试与验证
编写 testbench 激励文件.
同样用AI生成一些测试用例用作32位补码乘法器的测试.
Test Case 1: A = 0, B = 0
Test Case 2: A = 1, B = 2
Test Case 3: A = -1, B = 1
Test Case 4: A = 2, B = -3
Test Case 5: A = -2, B = -3
Test Case 6: A = 0, B = 5
Test Case 7: A = 5, B = 0
Test Case 8: A = 0xFFFFFFFF, B = 0xFFFFFFFF
将测试样例输入testbench文件.
`timescale 1ns / 1ps
module tb_Multiplier_32bit();
logic [31:0] A;
logic [31:0] B;
logic [63:0] product;
logic [31:0] abs_a, abs_b, c;
always_comb begin
if(A[31] == 1'b1)begin
abs_a[30:0] = (~A[30:0]) + 1'b1;
abs_a[31] = 1'b0;
end
else begin
abs_a = A;
end
end
always_comb begin
if(B[31] == 1'b1)begin
abs_b[30:0] = (~B[30:0]) + 1'b1;
abs_b[31] = 1'b0;
end
else begin
abs_b = B;
end
end
assign c[31] = A[31] ^ B[31];
Multiplier_32bit tb_Multiplier_32bit(
.A(abs_a),
.B(abs_b),
.product(product)
);
always_comb begin
if(c[31] == 1'b1)begin
c[30:0] = (~product[30:0]) + 1'b1;
end
else begin
c[30:0] = product[30:0];
end
end
initial begin
// 初始化输入信号
A = 32'h00000000;
B = 32'h00000000;
// 测试用例1: A = 0, B = 0
#10;
$display("Test Case 1: A = 0, B = 0");
$display("c = %h", c);
// 测试用例2: A = 1, B = 2
A = 32'h00000001;
B = 32'h00000002;
#10;
$display("Test Case 2: A = 1, B = 2");
$display("c = %h", c);
// 测试用例3: A = -1, B = 1
A = 32'hFFFFFFFF;
B = 32'h00000001;
#10;
$display("Test Case 3: A = -1, B = 1");
$display("c = %h", c);
// 测试用例4: A = 2, B = -3
A = 32'h00000002;
B = 32'hFFFFFFFD;
#10;
$display("Test Case 4: A = 2, B = -3");
$display("c = %h", c);
// 测试用例5: A = -2, B = -3
A = 32'hFFFFFFFE;
B = 32'hFFFFFFFD;
#10;
$display("Test Case 5: A = -2, B = -3");
$display("c = %h", c);
// 测试用例6: A = 0, B = 5
A = 32'h00000000;
B = 32'h00000005;
#10;
$display("Test Case 6: A = 0, B = 5");
$display("c = %h", c);
// 测试用例7: A = 5, B = 0
A = 32'h00000005;
B = 32'h00000000;
#10;
$display("Test Case 7: A = 5, B = 0");
$display("c = %h", c);
// 测试用例8: A = 0xFFFFFFFF, B = 0xFFFFFFFF
A = 32'hFFFFFFFF;
B = 32'hFFFFFFFF;
#10;
$display("Test Case 8: A = 0xFFFFFFFF, B = 0xFFFFFFFF");
$display("c = %h", c);
// 结束仿真
$finish;
end
endmodule
测试结果:


可以验证结果是正确的.
Test Case 1: A = 0, B = 0
输入:A = 0, B = 0
输出:product = 0
说明:0乘以0等于0,无溢出。
Test Case 2: A = 1, B = 2
输入:A = 1, B = 2
输出:product = 2
说明:1乘以2等于2,无溢出。
Test Case 3: A = -1, B = 1
输入:A = -1, B = 1
输出:product = -1
说明:-1乘以1等于-1,无溢出。
Test Case 4: A = 2, B = -3
输入:A = 2, B = -3
输出:product = -6
说明:2乘以-3等于-6,无溢出。
Test Case 5: A = -2, B = -3
输入:A = -2, B = -3
输出:product = 6
说明:-2乘以-3等于6,无溢出。
Test Case 6: A = 0, B = 5
输入:A = 0, B = 5
输出:product = 0
说明:0乘以5等于0,无溢出。
Test Case 7: A = 5, B = 0
输入:A = 5, B = 0
输出:product = 0
说明:5乘以0等于0,无溢出。
Test Case 8: A = 0xFFFFFFFF, B = 0xFFFFFFFF
输入:A = 0xFFFFFFFF, B = 0xFFFFFFFF
输出:product = 0x0000000100000001
说明:-1乘以-1等于1,无溢出。

浙公网安备 33010602011771号