这是 64 位复数乘法器的 SystemVerilog 代码
//
// SystemVerilog Project for EL Component of DSDV
// Author: Anudeep N Rao
// USN: 1RV22LVS01
//
module cmultx64
(
cmul_if if1
);
reg signed [63:0] ai_fifo1, ai_fifo2, ai_fifo3, ai_fifo4 ;
reg signed [63:0] ar_fifo1, ar_fifo2, ar_fifo3, ar_fifo4 ;
reg signed [63:0] bi_fifo1, bi_fifo2, bi_fifo3, br_fifo1, br_fifo2, br_fifo3 ;
reg signed [63:0] addcommon ;
reg signed [63:0] addr, addi ;
reg signed [128:0] mult0, multr, multi, pr_int, pi_int ;
reg signed [128:0] common, commonr1, commonr2 ;
always @(posedge if1.clk)
begin
ar_fifo1 <= if1.ar;
ar_fifo2 <= ar_fifo1;
ai_fifo1 <= if1.ai;
ai_fifo2 <= ai_fifo1;
br_fifo1 <= if1.br;
br_fifo2 <= br_fifo1;
br_fifo3 <= br_fifo2;
bi_fifo1 <= if1.bi;
bi_fifo2 <= bi_fifo1;
bi_fifo3 <= bi_fifo2;
end
// Common factor (ar ai) x bi, shared for the calculations of the real and imaginary final products
always @(posedge if1.clk)
begin
addcommon <= ar_fifo1 - ai_fifo1;
mult0 <= 128'($signed(addcommon * bi_fifo2));
common <= mult0;
end
// Real product
//
always @(posedge if1.clk)
begin
ar_fifo3 <= ar_fifo2;
ar_fifo4 <= ar_fifo3;
addr <= 64'($signed(br_fifo3 - bi_fifo3));
multr <= {128'($signed(addr * ar_fifo4))};
commonr1 <= common;
pr_int <= {128'($signed(multr + commonr1))};
end
// Imaginary product
//
always @(posedge if1.clk)
begin
ai_fifo3 <= ai_fifo2;
ai_fifo4 <= ai_fifo3;
addi <= 64'($signed(br_fifo3 + bi_fifo3));
multi <= {128'($signed(addi * ai_fifo4))};
commonr2 <= common;
pi_int <= {128'($signed(multi + commonr2))};
end
assign if1.pr = pr_int;
assign if1.pi = pi_int;
// Assertion to check if the real product calculation is correct
assert property (@(posedge if1.clk) multr + commonr1 == pr_int)
else $error("Real product calculation is incorrect");
// Assertion to check if the imaginary product calculation is correct
assert property (@(posedge if1.clk) multi + commonr2 == pi_int)
else $error("Imaginary product calculation is incorrect");
// Assertion to check if the common factor calculation is correct
assert property (@(posedge if1.clk) addcommon * bi_fifo2 == common)
else $error("Common factor calculation is incorrect");
endmodule // cmultx64
这是我一直在使用的测试平台:
//
// SystemVerilog Project for EL Component of DSDV
// Author: Anudeep N Rao
// USN: 1RV22LVS01
//
class Packet;
var rand signed [63:0] ar;
var rand signed [63:0] br;
var rand signed [63:0] ai;
var rand signed [63:0] bi;
bit signed [128:0] pr;
bit signed [128:0] pi;
constraint nse {
ar inside {[0:2**63-1]};
ai inside {[0:2**63-1]};
br inside {[0:2**63-1]};
bi inside {[0:2**63-1]};
}
// Print contents of the data packet
function void print(string tag="");
$display ("T=%0t %s ar=0x%0h ai=0x%0h br=0x%0h bi=0x%0h pr=0x%0h pi=0x%0h", $time, tag, ar,ai,br,bi,pr,pi);
$display ("T=%0t %s ar=0x%0d ai=0x%0d br=0x%0d bi=0x%0d pr=0x%0d pi=0x%0d", $time, tag, ar,ai,br,bi,pr,pi);
endfunction
// This is a utility function to allow copying contents in
// one Packet variable to another.
function void copy(Packet tmp);
this.ar = tmp.ar;
this.ai = tmp.ai;
this.br = tmp.br;
this.bi = tmp.bi;
this.pr = tmp.pr;
this.pi = tmp.pi;
endfunction
endclass
class driver;
virtual cmul_if m_cmul_vif;
event drv_done;
mailbox drv_mbx;
task run();
$display ("T=%0t [Driver] starting ...", $time);
// Try to get a new transaction every time and then assign
// packet contents to the interface. But do this only if the
// design is ready to accept new transactions
forever begin
Packet item;
$display ("T=%0t [Driver] waiting for item ...", $time);
drv_mbx.get(item);
@ (posedge m_cmul_vif.clk);
item.print("Driver");
m_cmul_vif.ar <= item.ar;
m_cmul_vif.ai <= item.ai;
m_cmul_vif.br <= item.br;
m_cmul_vif.bi <= item.bi;
->drv_done;
end
endtask
endclass
class monitor;
virtual cmul_if m_cmul_vif;
mailbox scb_mbx; // Mailbox connected to scoreboard
task run();
$display ("T=%0t [Monitor] starting ...", $time);
// Check forever at every clock edge to see if there is a
// valid transaction and if yes, capture info into a class
// object and send it to the scoreboard when the transaction
// is over.
forever begin
Packet m_pkt = new();
@(posedge m_cmul_vif.clk);
#1;
m_pkt.ar = m_cmul_vif.ar;
m_pkt.ai = m_cmul_vif.ai;
m_pkt.br = m_cmul_vif.br;
m_pkt.bi = m_cmul_vif.bi;
// m_pkt.reset = m_cmul_vif.reset;
m_pkt.pr = m_cmul_vif.pr;
m_pkt.pi = m_cmul_vif.pi;
m_pkt.print("Monitor");
scb_mbx.put(m_pkt);
end
endtask
endclass
class scoreboard;
mailbox scb_mbx;
bit [63:0]ar_fifo[7];
bit [63:0]ai_fifo[7];
bit [63:0]br_fifo[7];
bit [63:0]bi_fifo[7];
task run();
forever begin
Packet item, ref_item;
scb_mbx.get(item);
item.print("Scoreboard");
// Copy contents from received packet into a new packet so
// just to get a and b.
ref_item = new();
ref_item.copy(item);
for(int i=6;i>=0;i--)
begin
if(i) begin
ar_fifo[i]<=ar_fifo[i-1];
ai_fifo[i]<=ai_fifo[i-1];
br_fifo[i]<=br_fifo[i-1];
bi_fifo[i]<=bi_fifo[i-1];
end
if(i==0)begin
ar_fifo[i]<=ref_item.ar;
ai_fifo[i]<=ref_item.ai;
br_fifo[i]<=ref_item.br;
bi_fifo[i]<=ref_item.bi;
end
end
// Let us calculate the expected values in pi and pr
ref_item.pr = {ar_fifo[5]*br_fifo[5]} - {ai_fifo[5]*bi_fifo[5]};
ref_item.pi = {ai_fifo[5]*br_fifo[5]} + {ar_fifo[5]*bi_fifo[5]};
// Now, pi and pr outputs in the reference variable can be compared
// with those in the received packet
if (ref_item.pi != item.pi) begin
$display("[%0t] Scoreboard Error! pi mismatch ref_item=0x%0h item=0x%0h", $time, ref_item.pi, item.pi);
end else begin
$display("[%0t] Scoreboard Pass! pi match ref_item=0x%0h item =0x%0h", $time, ref_item.pi, item.pi);
end
if (ref_item.pr != item.pr) begin
$display("[%0t] Scoreboard Error! pr mismatch ref_item=0x%0h item=0x%0h", $time, ref_item.pr, item.pr);
end else begin
$display("[%0t] Scoreboard Pass! pr match ref_item=0x%0h item=0x%0h", $time, ref_item.pr, item.pr);
end
end
endtask
endclass
class generator;
int loop = 10;
event drv_done;
mailbox drv_mbx;
task run();
for (int i = 0; i < loop; i++) begin
Packet item = new;
item.randomize();
$display ("T=%0t [Generator] Loop:%0d/%0d create next item", $time, i+1, loop);
drv_mbx.put(item);
$display ("T=%0t [Generator] Wait for driver to be done", $time);
@(drv_done);
end
endtask
endclass
class env;
generator g0; // Generate transactions
driver d0; // Driver to design
monitor m0; // Monitor from design
scoreboard s0; // Scoreboard connected to monitor
mailbox scb_mbx; // Top level mailbox for SCB <-> MON
virtual cmul_if m_cmul_vif; // Virtual interface handle
event drv_done;
mailbox drv_mbx;
function new();
d0 = new;
m0 = new;
s0 = new;
scb_mbx = new();
g0 = new;
drv_mbx = new;
endfunction
virtual task run();
// Connect virtual interface handles
d0.m_cmul_vif = m_cmul_vif;
m0.m_cmul_vif = m_cmul_vif;
// Connect mailboxes between each component
d0.drv_mbx = drv_mbx;
g0.drv_mbx = drv_mbx;
m0.scb_mbx = scb_mbx;
s0.scb_mbx = scb_mbx;
// Connect event handles
d0.drv_done = drv_done;
g0.drv_done = drv_done;
// Start all components - a fork join_any is used because
// the stimulus is generated by the generator and we want the
// simulation to exit only when the generator has finished
// creating all transactions. Until then all other components
// have to run in the background.
fork
s0.run();
d0.run();
m0.run();
g0.run();
join_any
endtask
endclass
interface cmul_if();
logic clk;
logic [63:0] ar;
logic [63:0] ai;
logic [63:0] br;
logic [63:0] bi;
logic [128:0] pr;
logic [128:0] pi;
initial clk <= 0;
always #10 clk = ~clk;
endinterface
class test;
env e0;
mailbox drv_mbx;
function new();
drv_mbx = new();
e0 = new();
endfunction
virtual task run();
e0.d0.drv_mbx = drv_mbx;
e0.run();
endtask
endclass
module tb;
bit tb_clk;
cmul_if m_cmul_if();
cmultx64 m0 (m_cmul_if);
initial begin
test t0;
t0 = new;
t0.e0.m_cmul_vif = m_cmul_if;
$dumpfile("dump.vcd");
$dumpvars;
t0.run();
#50 $finish;
end
// Define a covergroup
covergroup cmultx64_cg @(posedge m_cmul_if.clk);
// Coverpoints
coverpoint m_cmul_if.ar { bins low = {0}; bins high = {64'h7FFF_FFFF_FFFF_FFFF}; }
coverpoint m_cmul_if.ai { bins low = {0}; bins high = {64'h7FFF_FFFF_FFFF_FFFF}; }
coverpoint m_cmul_if.br { bins low = {0}; bins high = {64'h7FFF_FFFF_FFFF_FFFF}; }
coverpoint m_cmul_if.bi { bins low = {0}; bins high = {64'h7FFF_FFFF_FFFF_FFFF}; }
// Cross coverage: This will give us a matrix of all possible combinations of ar, ai, br, bi
cross m_cmul_if.ar, m_cmul_if.ai, m_cmul_if.br, m_cmul_if.bi;
endgroup
// Instantiate the covergroup
cmultx64_cg cg1;
initial begin
// Initialize the covergroup
cg1 = new();
end
always @(posedge m_cmul_if.clk) begin
// Sample the covergroup
cg1.sample();
end
endmodule
输出是:
T=131 Monitor ar=0x3663928677917193535 ai=0x7890384334432080575 br=0x518813531089504302 bi=0x7052919361153373150 pr=0x135810663822377906 pi=0x10266323930858106324
# T=131 Scoreboard ar=0x32d8e3b8619ef53f ai=0x6d8046bf432192bf br=0x73332286141882e bi=0x61e100ca7f0593de pr=0x1e27f1445d7c3b2 pi=0x8e794f38c7e3add4
# T=131 Scoreboard ar=0x3663928677917193535 ai=0x7890384334432080575 br=0x518813531089504302 bi=0x7052919361153373150 pr=0x135810663822377906 pi=0x10266323930858106324
# [131] Scoreboard Pass! pi match ref_item=0x8e794f38c7e3add4 item =0x8e794f38c7e3add4
# [131] Scoreboard Pass! pr match ref_item=0x1e27f1445d7c3b2 item=0x1e27f1445d7c3b2
# T=150 Driver ar=0x737b139455d25390 ai=0x744cef14d0239552 br=0xe61f0f2107efd2e bi=0x124db73361155bbb pr=0x0 pi=0x0
# T=150 Driver ar=0x8321266264313058192 ai=0x8380335879300027730 br=0x1036374311721434414 bi=0x1318911697189428155 pr=0x0 pi=0x0
# T=150 [Driver] waiting for item ...
# T=150 [Generator] Loop:9/10 create next item
# T=150 [Generator] Wait for driver to be done
# ** Error: Common factor calculation is incorrect
# Time: 150 ns Started: 150 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 127
# ** Error: Imaginary product calculation is incorrect
# Time: 150 ns Started: 150 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 123
# ** Error: Real product calculation is incorrect
# Time: 150 ns Started: 150 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 119
# T=151 Monitor ar=0x737b139455d25390 ai=0x744cef14d0239552 br=0xe61f0f2107efd2e bi=0x124db73361155bbb pr=0x7608a64d5f26d1ec pi=0xfffffffffffffffff9c59515add5b864
# T=151 Monitor ar=0x8321266264313058192 ai=0x8380335879300027730 br=0x1036374311721434414 bi=0x1318911697189428155 pr=0x8505230747528253932 pi=0x340282366920938463462925818764258031716
# T=151 Scoreboard ar=0x737b139455d25390 ai=0x744cef14d0239552 br=0xe61f0f2107efd2e bi=0x124db73361155bbb pr=0x7608a64d5f26d1ec pi=0xfffffffffffffffff9c59515add5b864
# T=151 Scoreboard ar=0x8321266264313058192 ai=0x8380335879300027730 br=0x1036374311721434414 bi=0x1318911697189428155 pr=0x8505230747528253932 pi=0x340282366920938463462925818764258031716
# [151] Scoreboard Error! pi mismatch ref_item=0xf9c59515add5b864 item=0xfffffffffffffffff9c59515add5b864
# [151] Scoreboard Pass! pr match ref_item=0x7608a64d5f26d1ec item=0x7608a64d5f26d1ec
# T=170 Driver ar=0xd27934d8c819661 ai=0x2aff7bc8688b9785 br=0x2fa6f58da3a7dbb3 bi=0xbe7f758685c0d87 pr=0x0 pi=0x0
# T=170 Driver ar=0x947888207863846497 ai=0x3098331169331844997 br=0x3433701754601462707 bi=0x857926213117414791 pr=0x0 pi=0x0
# T=170 [Driver] waiting for item ...
# T=170 [Generator] Loop:10/10 create next item
# T=170 [Generator] Wait for driver to be done
# ** Error: Common factor calculation is incorrect
# Time: 170 ns Started: 170 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 127
# ** Error: Imaginary product calculation is incorrect
# Time: 170 ns Started: 170 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 123
# ** Error: Real product calculation is incorrect
# Time: 170 ns Started: 170 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 119
# T=171 Monitor ar=0xd27934d8c819661 ai=0x2aff7bc8688b9785 br=0x2fa6f58da3a7dbb3 bi=0xbe7f758685c0d87 pr=0xb87927d662a297b pi=0x28c010765c8cf339
# T=171 Monitor ar=0x947888207863846497 ai=0x3098331169331844997 br=0x3433701754601462707 bi=0x857926213117414791 pr=0x830793723555752315 pi=0x2936365057590489913
# T=171 Scoreboard ar=0xd27934d8c819661 ai=0x2aff7bc8688b9785 br=0x2fa6f58da3a7dbb3 bi=0xbe7f758685c0d87 pr=0xb87927d662a297b pi=0x28c010765c8cf339
# T=171 Scoreboard ar=0x947888207863846497 ai=0x3098331169331844997 br=0x3433701754601462707 bi=0x857926213117414791 pr=0x830793723555752315 pi=0x2936365057590489913
# [171] Scoreboard Error! pi mismatch ref_item=0x128c010765c8cf339 item=0x28c010765c8cf339
# [171] Scoreboard Pass! pr match ref_item=0xb87927d662a297b item=0xb87927d662a297b
# T=190 Driver ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0x0 pi=0x0
# T=190 Driver ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x0 pi=0x0
# T=190 [Driver] waiting for item ...
# ** Error: Common factor calculation is incorrect
# Time: 190 ns Started: 190 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 127
# ** Error: Imaginary product calculation is incorrect
# Time: 190 ns Started: 190 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 123
# ** Error: Real product calculation is incorrect
# Time: 190 ns Started: 190 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 119
# T=191 Monitor ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0x2e7bedf58d282440 pi=0xb0e57e7cabfe6610
# T=191 Monitor ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x3349532386771084352 pi=0x12746733394268677648
# T=191 Scoreboard ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0x2e7bedf58d282440 pi=0xb0e57e7cabfe6610
# T=191 Scoreboard ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x3349532386771084352 pi=0x12746733394268677648
# [191] Scoreboard Pass! pi match ref_item=0xb0e57e7cabfe6610 item =0xb0e57e7cabfe6610
# [191] Scoreboard Error! pr mismatch ref_item=0x1ffffffffffffffff2e7bedf58d282440 item=0x2e7bedf58d282440
# ** Error: Common factor calculation is incorrect
# Time: 210 ns Started: 210 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 127
# ** Error: Imaginary product calculation is incorrect
# Time: 210 ns Started: 210 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 123
# ** Error: Real product calculation is incorrect
# Time: 210 ns Started: 210 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 119
# T=211 Monitor ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0xffffffffffffffffdd8ae577b584733b pi=0xffffffffffffffff5381f455a77ce0dd
# T=211 Monitor ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x340282366920938463460891687489536029499 pi=0x340282366920938463450945222583921729757
# T=211 Scoreboard ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0xffffffffffffffffdd8ae577b584733b pi=0xffffffffffffffff5381f455a77ce0dd
# T=211 Scoreboard ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x340282366920938463460891687489536029499 pi=0x340282366920938463450945222583921729757
# [211] Scoreboard Error! pi mismatch ref_item=0x15381f455a77ce0dd item=0xffffffffffffffff5381f455a77ce0dd
# [211] Scoreboard Error! pr mismatch ref_item=0xdd8ae577b584733b item=0xffffffffffffffffdd8ae577b584733b
# ** Error: Common factor calculation is incorrect
# Time: 230 ns Started: 230 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 127
# ** Error: Imaginary product calculation is incorrect
# Time: 230 ns Started: 230 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 123
# ** Error: Real product calculation is incorrect
# Time: 230 ns Started: 230 ns Scope: tb.m0 File: C:/Users/Anudeep/Desktop/doc_temp/SV_EL/cmultx64.sv Line: 119
# T=231 Monitor ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0xffffffffffffffffcf4181621a71ecc1 pi=0x2e2aaa4d10ff1f50
# T=231 Monitor ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x340282366920938463459862223455746387137 pi=0x3326658522740891472
# T=231 Scoreboard ar=0xb1a0f6fdf759c97 ai=0x393a0e9c7d5cc062 br=0x68dfde48de03535a bi=0x1b3f115e4c0807cc pr=0xffffffffffffffffcf4181621a71ecc1 pi=0x2e2aaa4d10ff1f50
# T=231 Scoreboard ar=0x799968856976497815 ai=0x4123624474092028002 br=0x7557003104294753114 bi=0x1963307059257018316 pr=0x340282366920938463459862223455746387137 pi=0x3326658522740891472
# [231] Scoreboard Error! pi mismatch ref_item=0x12e2aaa4d10ff1f50 item=0x2e2aaa4d10ff1f50
# [231] Scoreboard Error! pr mismatch ref_item=0x1ffffffffffffffffcf4181621a71ecc1 item=0xffffffffffffffffcf4181621a71ecc1
# ** Note: $finish : C:/Users/Anudeep/Desktop/doc_temp/SV_EL/top.sv(276)
# Time: 240 ns Iteration: 0 Instance: /tb
# 1
可能是什么问题。覆盖群体的覆盖率非常低(6%)。该代码是大学课程体验式学习的一部分。该 EL 项目展示了使用 System Verilog 设计和验证 64 位复数乘法单元 (CMU)。 CMU 旨在以笛卡尔形式处理两个复数,输出其乘积的实部和虚部。该单元利用流水线架构来实现高吞吐量和低延迟。 CMU 功能的验证是使用 System Verilog 测试环境执行的,该环境生成随机输入并根据参考模型验证输出。这项工作展示了一种有效的高速复数乘法方法,在数字信号处理和控制系统中具有潜在的应用。
一个问题是用于加(减)的位数错误。例如这一行
addcommon <= ar_fifo1 - ai_fifo1;
这里是fpga算术中位增长的参考bit-growth。
代码很难理解。原因之一是您没有提供正在使用的算法。如果您提供配方并具有与算法匹配的简单变量名称,那么会更容易理解。这是我在问题“我正在尝试实现这个方程”中发布的内容的示例
该图片取自此处:示例。
我并不是说您需要使用该方程,而是说您没有说明您要使用的方程,然后在代码中用简单的变量名称来表达它,如示例中所做的那样( A B C D)。这将使代码更容易调试和验证中间量。