How to bind an interface with system verilog module?

时间:2016-07-11 20:53:56

标签: interface system-verilog uvm

I have an system verilog interface

interface add_sub_if(
input bit clk,
input [7:0] a,
input [7:0] b,
input       doAdd,
input [8:0] result
);

  clocking dut_cb @(posedge clk);
    output    a;
    output    b;
    output    doAdd;
    input     result;
  endclocking // cb

  modport dut(clocking dut_cb);

endinterface: add_sub_if

And i have a SV module which uses this interface

module dummy(add_sub_if.dut _if);
  ....
endmodule: dummy

What is the ideal way to hook up this in my TB?

If i instantiate the interface, i need to create wires.

If i use bind then also i need to do a port mapping of the individual signals, that beats the convenience of having an interface.

Another add on question is, how to assign one such interface to another interface?

Thanks in advance,

Rajdeep

3 个答案:

答案 0 :(得分:3)

You can find a simple example of an interface definition and usage in the IEEE Std 1800-2012 Section 3.5 (Interfaces). It shows how to define the interface and hook it up to the design (the way you have already done it). It also shows how the interface can be instantiated (and connected) inside a top level module/wrapper (I copied the code below directly from the spec for your convenience):

interface simple_bus(input logic clk); // Define the interface
  logic req, gnt;
  logic [7:0] addr, data;
  logic [1:0] mode;
  logic start, rdy;
endinterface: simple_bus

module memMod(simple_bus a); // simple_bus interface port
  logic avail;
  // When memMod is instantiated in module top, a.req is the req
  // signal in the sb_intf instance of the 'simple_bus' interface
  always @(posedge clk) a.gnt <= a.req & avail;
endmodule

module cpuMod(simple_bus b); // simple_bus interface port
  ...
endmodule

module top;
  logic clk = 0;

  simple_bus sb_intf(.clk(clk)); // Instantiate the interface

  memMod mem(.a(sb_intf)); // Connect interface to module instance
  cpuMod cpu(.b(sb_intf)); // Connect interface to module instance

endmodule

Once you have the interface hooked up, then you can have drive/sample all the signals from a testcase program (just remember that you have to pass the interface to it). In this case, it would be be something like:

program testcase(simple_bus tb_if);

  initial begin
    tb_if.mode <= 0;
    repeat(3) #20 tb_if.req <= 1'b1;
    [...]
    $finish;
  end

endprogram

For a real-world example, you can check the source code of a UVM testbench that is available on my GitHub page. The interface hook-up is done in the xge_test_top.sv file.

答案 1 :(得分:2)

这是fsm dut with testbench。

此fsm dut按顺序执行状态转换1 - 0 - 1 - 0。

测试台验证dut是否正常工作。

verilog模块代码(dut):

module melay_fsm(o,clk,rst,i);
output o;
input i,clk,rst;
reg o;
reg [1:0]state;
// [1:0]state;
always@(posedge clk,posedge rst)
begin
if(rst)
begin
state <=2'b00;
end
else
begin
case(state)
2'b00:
begin
if(i)
state<=2'b01;
else
state<=2'b00;
end

2'b01:
begin
if(!i)
state<=2'b10;
else
state<=2'b01;
end

2'b10:
begin
if(i)
state<=2'b11;
else
state<=2'b00;
end

2'b11:
begin
if(!i)
state<=2'b00;
else
state<=2'b01;
end
endcase
end
end

always@(posedge clk,negedge rst)
begin
if(rst)
o<=1'b0;
else if(state==2'b11 && i==0)
o<=1'b1;
else
o<=1'b0;
end
endmodule

系统verilog模块代码(testbench):

interface melay_intf(input bit clk);

  logic o,rst,i;
  wire clk;

  clocking c1@(posedge clk);
    input o;
    output i,rst;
  endclocking

  modport tes(clocking c1);

endinterface

    module top;
      bit clk;

      always
        #1 clk = ~clk;

      melay_intf i1(clk);

      melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));

      melay_tes(i1);

    endmodule

    program melay_tes(melay_intf i1);

      initial
        #100 $finish;

      initial
        begin
          i1.rst <= 0;
          #4 i1.rst <= 1;
          #4 i1.rst <= 0;

          i1.i = 1;
              #2 i1.i = 0;
              #2 i1.i = 1;
              #2 i1.i = 0;
              #2 i1.i = 1;
              #2 i1.i = 0;


          repeat(10)
            begin
              i1.i = 1;
              #2 i1.i = $urandom_range(0,1); 
            end
        end

      initial
        $monitor("output = %d   clk = %d    rst = %d    i = %d",i1.o,i1.clk,i1.rst,i1.i);
      initial
        begin
          $dumpfile("mem.vcd");
          $dumpvars();

        end
    endprogram

这里要注意的重要事项是顶部模块中的信号连接。

melay_fsm a1(.o(i1.o),. clk(i1.clk),。rst(i1.rst),. i(i1.i));

请正确观察我如何将界面与testbench和dut绑定。 请注意以下事项。

我定义了所有dut信号的接口。

我在顶层模块中使用了接口(melay_intf)的实例(i1)。

我在顶层模块中使用了dut(melay_fsm)的实例(a1)。

现在观察 melay_fsm a1(.o(i1.o),. clk(i1.clk),。rst(i1.rst),。i(i1.i))

所有dut的信号都与接口相连。

我在testbench中传递了接口(i1)的实例。的 melay_tes(I1)

因此,testbench可以访问接口信号,接口信号连接到dut的信号。

现在,您可以借助界面访问测试平台中的dut信号。

我认为现在你可以理解正确的流程了。

如果您有任何疑问,请提出问题。

答案 2 :(得分:1)

您可以在系统verilog模块中绑定接口。

在这里,我提供了示例代码,您可以了解如何在系统verilog模块和dut中绑定接口。

这里我提供了verilog模块和系统verilog模块。代码的主要部分是连接verilog和系统verilog模块的接口。

verilog模块代码(dut):

module dff(qn,d,clk,reset);

output qn;
input d,clk,reset;
reg qn;

always@(posedge clk,negedge reset)

begin

if (!reset)

begin
qn=1'bx;
end

else if (d==0)
begin
qn=0;
end
else if (d==1)
begin 
qn=1;
end

end

endmodule

系统verilog模块代码(testbench):

interface melay_intf(input bit clk);

  logic o,clk,rst,i;

  clocking c1@(posedge clk);
    input o;
    output i,rst;
  endclocking

endinterface

module top;
  bit clk;

  always
    #1 clk = ~clk;

  melay_intf i1(clk);

  dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));

  melay_tes(i1.tes);

endmodule

program melay_tes(melay_intf i1);

  initial
    #100 $finish;

  initial
    begin
      i1.rst <= 0;
      #4 i1.rst <= 1;
      #4 i1.rst <= 0;

      i1.i = 1;
          #2 i1.i = 0;
          #2 i1.i = 1;
          #2 i1.i = 0;
          #2 i1.i = 1;
          #2 i1.i = 0;


      repeat(10)
        begin
          i1.i = 1;
          #2 i1.i = $urandom_range(0,1); 
        end
    end

  initial
    $monitor("output = %d   clk = %d    rst = %d    i = %d",i1.o,i1.clk,i1.rst,i1.i);
  initial
    begin
      $dumpfile("mem.vcd");
      $dumpvars();

    end
endprogram

这里重要的部分是接口,在其中我使用时钟块进行同步。在这里计时c1 @(posedge clk);所以在时钟模块中提到的所有信号都是i,o,rst。所有这个信号在clk信号的每个位置都会改变它的值。

这里 dff d1(.o(i1.o),. clk(i1.clk),。rst(i1.rst),. i(i1.i));在顶层模块中找到的重要事项我在verilog信号和系统verilog信号之间建立了连接。

你可以找到verilog模块名称是“dff”。我拿了dff verilog模块的实例并建立了连接。这里i1.o,i1.clk,i1.rst,i1.i是系统verilog信号,它连接到具有点约定的verilog模块的o,clk,rst,i信号。