sv:interface

本文介绍了SystemVerilog的interface概念,包括如何定义端口方向、如何连接interface与DUT,以及interface带来的好处。此外,讲解了clocking block在testbench中的作用,对比了Verilog与SystemVerilog中接口的差异,并展示了interface的参数化、数组使用及modport的应用,强调了interface在简化设计连接、提高可维护性方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Interface 初识

接口是一种将信号封装到block中的方法。

语法

interface[name]([port_list]);
	[list_of_signals]
endinterface

接口还可以具有函数、任务、变量和参数,使其更像一个类模板。它还可以通过 modport 结构定义不同模块端口的方向信息策略,以及带有时钟块的 testbench 同步功能。它还可以有断言、覆盖率记录和其他协议检查元素。它还可以包含initial过程和always过程以及连续赋值(assign)语句。

模块不能在接口中实例化! 但是接口可以在模块中实例化。

interface apb_if (input pclk);
    logic[31:0]    paddr;
    logic[31:0]    pwdata;
    logic[31:0]    prdata;
    logic           penable;
    logic           pwrite;
    logic           psel;
endinterface

1.如何定义端口方向?

接口信号可用于各种验证组件以及 DUT,使用 modport 来定义信号方向。不同的 modport 定义可以传递给不同的组件,这样我们就可以为每个组件定义不同的输入输出方向。

interface myBus (input clk);
    logic[7:0]  data;
    logic      enable;
    // From TestBench perspective, 'data' is input and 'write' is output
    modport TB  (input data, clk,output enable);
    // From DUT perspective, 'data' is output and 'enable' is input
    modport DUT (output data,input enable, clk);
endinterface

2.如何连接interface与 DUT?

接口对象应该在实例化 DUT 的顶级 testbench 模块中创建,并传递给 DUT。确保为 DUT 分配正确的模型是非常重要的。
testbench模块中,接口对象在DUT前创建。

module dut (myBus busIf);
always @(posedge busIf.clk)
if(busIf.enable)
      busIf.data <= busIf.data+1;
else
      busIf.data <=0;
endmodule

// Filename : tb_top.sv
module tb_top;
    bit clk;
    // Create a clock
    always #10 clk =~clk;

    // Create an interface object  
    myBus busIf (clk);

    // Instantiate the DUT; pass modport DUT of busIf
    dut dut0 (busIf.DUT);
    
    // Testbench code : let's wiggle enable
    initialbegin
        busIf.enable  <=0;
        #10 busIf.enable <=1;
        #40 busIf.enable <=0;
        #20 busIf.enable <=1;
        #100 $finish;
    end
endmodule

2.有什么好处?

接口可以包含任务、函数、参数、变量、函数覆盖和断言(tasks, functions, parameters, variables, functional coverage, and assertions.)。这使我们能够通过该块中的接口监视和记录事务。由于信息封装在一个接口中,不管它有多少个端口,连接到设计也变得更加容易。

3.如何参数化接口?

接口定义可以使用与模块定义相同的方式利用参数和参数重定义。下面的示例演示如何在接口定义中使用参数

interface myBus #(parameter D_WIDTH=31)(input clk);
	logic [D_WIDTH-1:0] data;
	logic enable;
endinterface

interface simple_bus #(AWIDTH = 8, DWIDTH = 8) (input logic clk); // Define the interface
	logic req, gnt;
	logic [AWIDTH-1:0] addr;
	logic [DWIDTH-1:0] data;
	logic [1:0] mode;
	logic start, rdy;
endinterface : simple_bus

clocking block

时钟块内指定的信号将相对于该时钟进行采样/驱动。在一个接口中可以有多个时钟块。
注意,这是用于 testbench 相关信号。控制 TB 何时驱动信号,何时从 DUT 采样信号。 解决了竞争条件的一部分,但不是全部。倾斜值(skew values)可以参数化。

interface my_int (inputbit clk);
	// Rest of interface code
	
	clocking cb_clk @(posedge clk);
		default input #3ns output #2ns;
		input enable;
		output data;
	endclocking
endinterface

在上面的例子中,指定默认情况下,input应该在 clk 的posedge 之前3ns 采样,output应该在clk 的posedge 之后2ns 被驱动。

// To wait for posedge of clock
@busIf.cb_clk;
// To use clocking block signals
busIf.cb_clk.enable =1;

在enable 赋值1之前,您不必等待 clk 的posedge。 这样,您可以确保在下一个posedge clk 后2ns 驱动enable。

clocking

它是与特定时钟同步的信号集合,有助于指定时钟与信号之间的定时要求。
这将使测试编写人员能够更多地关注事务,而不用担心信号什么时候会与时钟交互。一个 testbench 可以有许多时钟块,但是每个时钟只有一个时钟块。

语法

[default] clocking [identifier_name] @ [event_or_identifier]
	default input #[delay_or_edge] output #[delay_or_edge] 
	[list of signals]
endclocking

delay_value表示一个信号被采样或驱动时离时钟事件有多少个时间单位的偏移。如果没有指定默认偏移,那么在指定的事件之后,所有的输入信号将采样 # 1步,输出信号驱动0ns。

2. interface intro

在 Verilog 和 SystemVerilog 中使用相同设计的接口。

Verilog 设计的interface

如何在测试平台中使用接口,并使用端口列表连接到标准的 Verilog 设计。下面显示的代码是 Verilog 编写的上下计数器的设计。这个模块接受一个参数来决定计数器的宽度。它还接受一个输入加载值 load,该加载值仅在 load_en 为1时加载到计数器中。

当输入向下为1时,计数器开始向下计数,否则向上计数。翻转输出指示计数器何时从最大值转换为0或从0转换为最大值。
在这里插入图片描述

module counter_ud  #(parameter WIDTH =4)(
    input 					clk,
    input 					rstn,
    inputwire[WIDTH-1:0]	load,
    input 					load_en,
    input 					down,
    output 					rollover,
    outputreg[WIDTH-1:0]	count
);    
    always @(posedge clk ornegedge rstn)begin
        if(!rstn)
            count <=0;
        elseif(load_en)
            count <= load;
        else begin
            if(down)
                count <= count -1;
            else
                count <= count +1;
        end
    end
    assign rollover =&count;
endmodule

下面声明了一个名为 cnt_if 的接口,并使用可参数化的值作为计数器信号的宽度。 这个任务还有一个task init() 来赋值。

interface cnt_if #(parameter WIDTH = 4) (input bit clk);
  logic 			rstn;
  logic 			load_en;
  logic [WIDTH-1:0] load;
  logic [WIDTH-1:0] count;
  logic 			down;
  logic 			rollover;
endinterface

module tb;
  reg clk;
  
  // TB Clock Generator used to provide the design
  // with a clock -> here half_period = 
### SystemVerilog Interface Definition and Usage In hardware design, especially within the context of IP and ASIC development requiring a minimum of 5 years' experience in areas such as RTL coding and verification[^1], interfaces play an essential role. Interfaces simplify communication between modules by encapsulating signals and methods that can be reused across different parts of a design. #### Defining an Interface An interface defines a set of signals (wires), modports to specify directions from the perspective of various users of the interface, clocking blocks for synchronization purposes, tasks, functions, and properties associated with these elements: ```systemverilog interface my_if #(parameter WIDTH=8)(input logic clk); // Define wires logic [WIDTH-1:0] data; logic valid; // Modport definitions modport master ( output data, output valid ); modport slave ( input data, input valid ); // Clocking block clocking cb @(posedge clk); default input #1step output #2ns; output data; output valid; endclocking : cb endinterface : my_if ``` This code snippet demonstrates how one might define an interface named `my_if` which includes parameters for configurability, signal declarations, modports specifying directionality relative to potential masters or slaves using this interface, along with a clocking block facilitating synchronous operations. #### Using an Interface To use an already defined interface inside another module like those involved when having hands-on experience in RTL coding and verification: ```systemverilog module top(); bit clk; always #5 clk = ~clk; // For simulation only // Instantiate the interface my_if #(.WIDTH(32)) dut_if(clk); // Connect it to DUT (Device Under Test) device_under_test dut( .data(dut_if.data), .valid(dut_if.valid) ); initial begin // Use the interface's clocking block uvm_default_seq.set_global_sequencer(null); // Assuming UVM environment setup is done elsewhere. run_test(); // Start testbench execution $finish; end endmodule : top ``` Here, `top` instantiates `dut_if`, connecting its components directly into the Device Under Test (`device_under_test`). The example also shows initializing sequences potentially used during testing phases where good communication skills interact with internal teams and customers are beneficial.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值