测试平台与DUT之间的通信
验证一个设计需要经过几个步骤:生成输入激励、捕获输出响应、决定对错衡量进度。在理想的开发过程中需要将测试平台和设计分开,此时需要在测试平台和待测设计(DUT,Design Under Test)之间实现通信,下面展示了利用Verilog端口声明的风格。
使用端口仲裁器模型:
module arb_port(output_logic[1:0] grant,
input_logic[1:0] request,
input logic rst,
input logic clk);
...
always @(posedge clk or posedge rst) begin
if(rst)
grant<=2'b00;
else
...
end
endmodule
使用端口的测试平台:
module test(input logic[1:0] grant,
output logic[1:0] request,
output logic rst,
input logic clk);
initial begin
@(posedge clk) request<=2'b01;
$display("@%0t : Drove req=01",$time);
repeat (2) @(posedge clk);
if(grant!=2'b01)
$display("@%0t: al: grant!=2'b01",$time);
...
$finish;
end
endmodule
没有接口的顶层网单:
module top;
logic[1:0] grant,request;
bit clk,rst;
always # 5 clk=~clk;
arb_port a1(grant,request,rst,clk);//端口仲裁器
test t1(grant,request,rst,clk);//测试平台
endmodule
从上述端口通信可以看出利用verilog端口声明的方式不利于端口信号的扩展以及修改,更容易出现错误。SV可以很好的解决这一问题。
接口
- 接口可以用作设计,也可以用作验证;
- 在验证环境中,接口可以使连接变简介且不易出错;
- interface和module使用性质很像,它可以定义端口和双向信号,可以使用initial和always,也可以定义function和task;
- interface可以在硬件环境和软件环境中传递,例如作为module中的端口列表和软件方法中的形参;
- 可以把interface看作一个插排,而DUT与TB之间的数据驱动关系都可以使用interface这个“插排”来完成。
接口优势:
- 将有关信号封装在同个接口中,对于设计和验证环境都便于维护和使用。添加新信号只需要在接口中定义该信号,在使用该接口的模块或验证环境中做相应的修改;
- interface是SV中唯一的硬件和软件环境的媒介交互;
- 接口由于可以例化,使得对于多组相同的总线,在例化和使用时变得更加灵活。
接口的定义和使用:
- interface的端口列表中只需要定义时钟、复位等公共信号,或不定义任何端口信号,转而在变量列表中定义各个需要跟DUT和TB连接的logic变量;
- interface也可以依靠函数参数化方式提供复用性;
- interface在例化时,同module例化方式一样;
- 模块里面可以例化模块和interface,interface里面可以例化interface但不能例化module。
SV中使用接口为块之间的通信建模,接口可以看成一捆智能的“连线”,其中包括:连接、同步、甚至两个或者更多块之间的通信功能,连接了设计块和测试平台。
仲裁器简单接口:
interface arb_if(input bit clk);
logic[1:0] grant,request;
logic rst;
endinterface
使用了简单接口的仲裁器:
module arb(arb_if arbif);
...
always@(posedge arbif.clk or posedge arbif.rst)
begin
if(arbif.rst)
arbif.grant<=2'b00;
else
arbif.grant<=next_grant;
...
end
endmodule
使用简单仲裁器接口的测试平台:
module test(arb_if arbif);
...
initial begin
@(posedge arbif.clk);
arbif.request<=2'b01;
$display("@%0t: Drove req = 01",$time);
repeat(2)@(posedge arbif.clk);
if(arbif.grant!=2'b01)
$display("@%0t: al: grant!=2'b01",$time);
$finish;
end
endmodule:test
使用简单仲裁器接口的top模块:
module top;
bit clk;
always # 5 clk=~clk;
arb_if arbif(clk);
arb a1(arbif);
arb t1(arbif);
endmodule: top
鉴于接口的简洁不易出错特性,可以将Verilog中的端口改为接口,将接口的信号直接连接到每个端口上。
module top;
bit clk;
always #5 clk=~clk;
arb_if arbif(clk); //接口信号
arb_port a1(.grant(arbif.grant), //将接口信号直接连接到每个端口上
.request(arbif.request),
.rst(arbif.rst),
.clk(arbif.clk));
test t1(arbif);
endmodule : top