justrajdeep
justrajdeep

Reputation: 913

How to bind an interface with system verilog module?

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

Upvotes: 0

Views: 14810

Answers (3)

AndresM
AndresM

Reputation: 1373

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.

Upvotes: 6

Ashutosh Rawal
Ashutosh Rawal

Reputation: 301

Here is fsm dut with testbench.

This fsm dut performs state transition 1 - 0 - 1 - 0 in sequence.

Test bench verifies dut is properly working or not.

verilog module code(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

System verilog module code(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

Important thing to note down here is connection of signals in top module.

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

Please, observe properly how I bind interface with testbench and dut. Please, observe following things.

I defines interface with all the dut's signals.

I took instance(i1) of interface(melay_intf) in top module.

I took instance (a1) of dut (melay_fsm) in top module.

Now observes melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i))

All the dut's signals are connected with interface.

I passed instance of interface(i1) in testbench. melay_tes(i1)

So, testbench can access interface signals and interface signals are connected to dut's signals.

Now, you can access dut's signals in your test bench with help of interface.

I think now you can understand proper flow.

Please ask the question if you have any doubt.

Upvotes: 2

Ashutosh Rawal
Ashutosh Rawal

Reputation: 301

You can bind interface in system verilog module.

Here, I provides sample code with help of that you can understood how to bind interface in system verilog module and with dut.

Here I provides verilog module and system verilog module. Main part of code is interface from which verilog and system verilog module are connected.

verilog module code(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

System verilog module code(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

Here important part is interface and in it I used clocking block for synchronization purpose. Here clocking c1@(posedge clk); so all signals which are mention inside the clocking block which are i,o,rst.All this signal change its value at every posedge of clk signal.

Here dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i)); Important thing that you find in top module I made connection between verilog signals and system verilog signals.

You can find verilog module name is "dff". I took the instance of dff verilog module and made the connection. Here i1.o,i1.clk,i1.rst,i1.i is system verilog signals which are connected to o,clk,rst,i signals of verilog module of with dot convention.

Upvotes: 1

Related Questions