我有一个模块,我最初是这样写的:
module design_name #(
parameter AWIDTH = 32,
parameter DWIDTH = 32,
...
) (
input wire clk,
input wire rst,
input wire [AWIDTH-1:0] write_addr,
...
);
// logic, etc.
endmodule
我现在当然想在测试台上测试这个块。我想使用一个界面,所以我创建了一个这样的界面:
interface design_name_if #(
parameter AWIDTH = 32,
...
) (
input clk
);
logic rst;
logic [AWIDTH-1:0] write_addr;
...
modport des (
input rst,
input write_addr,
...
);
endinterface
我想我的问题现在开始了;我如何在我的测试台上使用这个接口?我目前有:
module tb;
reg clk;
design_name_if intf (clk);
design_name dut (
.clk (intf.clk),
.rst (intf.des.rst),
.write_addr (intf.des.write_addr),
...
// I don't think the above is correct
initial begin
clk = 0; // or intf.clk = 0; ?
forever #1 clk = ~clk;
end
initial begin
rst = 0;
#10
rst = 1;
end
endmodule
我还尝试了一些其他简单的逻辑,比如只是尝试断言某些信号和其他东西,但我什至无法启动 clk,也无法在运行模拟时首先断言。如果重要,接口在同一文件中的 tb 上方声明。我正在测试的模块很可能在不同的文件中。通过在测试台内将所有信号声明为 reg 和 wire,我可以让测试台在没有接口的情况下正常工作,但我想使用带有任务、功能等的接口。感谢任何帮助,谢谢!
你们非常亲密。只需去掉引用中的 modport——
modport
不是作用域,它是端口连接或虚拟接口引用的一组访问权限。
design_name dut (
.clk (intf.clk),
.rst (intf.rst),
.write_addr (intf.write_addr),
...
有几个问题:
从结构上看,一个接口就是一堆电线。 wire intf.clk 不同于 wire clk。发布的代码使用永久循环驱动 clk,但测试台将 intf.clk 连接到未驱动的 dut,因此 dut 将看不到任何时钟(驱动 dut clk 输入引脚的电线没有驱动程序)。这种模式也首先出现在信号/电线/变量上。
在测试平台中声明
永远 #1 clk = ~clk;
初始块中间的语句。这将阻止执行同一初始块中的所有其他语句。例如,它永远不会执行 #10 或 rst = 1 语句。解决方案是使用不同的初始块或始终块来驱动时钟(无论您选择使用接口或本地声明的时钟)。
在初始刺激块结束时没有 $finish 来停止测试。该测试台将在无限循环中运行模拟器。初始块需要模板:
initial
begin
<statements>
$finish;
end
这样测试就不会让模拟器陷入循环。