0

I have a design to verify. The design is similar to a network router. It has a number of FIFO input interfaces and a number of FIFO output interfaces. So the same group of interfaces will repeat over and over. DUT example:

module router(
    input logic [0:NUM_IN] sop_i,
    input logic [0:NUM_IN] eop_i,
    input logic [0:NUM_IN][128:0] data_i,

    output logic [0:NUM_OUT] sop_o,
    output logic [0:NUM_OUT] eop_o,
    output logic [0:NUM_OUT][128:0] data_o,
)
......
endmodule

So I think in my testbench the number of drivers should also be configurable, since I want to drive each FIFO interface separately.

interface fifo_intf;
    logic sop;
    logic eop;
    logic [128:0] data
endinterface

So the first issue is how to connect this interface to DUT. I am looking at something like

module tb_top;
...
top_intf top_if();

router dut (.sop_i(top_if.connect_if.sop)
            .eop_i(top_if.connect_if.eop),
            .data_i(top_if.connect_if.data))
endmodule

interface connect_intf #(NUM);
    logic [0:NUM-1] sop;
    logic [0:NUM-1] eop;
    logic [0:NUM-1][128:0] data;
endinterface

I also think it might be easier to pass a top interface wrapper to the env since, the number of FIFO interfaces are parameterized. So,

interface top_intf:
    fifo_intf fifo_if_input[`NUM_IN]();
    fifo_intf fifo_if_output[`NUM_OUT]();
    connect_intf #(`NUM_IN)connect_if();
endinterface

Then I need to do some routing from connect interface to fifo interface

   genvar i;
    generate
        for (i = 0; i < NUM_IN; i++) begin
            assign connect_if.sop[i]   = fifo_if_i[i].sop;
    endgenerate

But there are some issues when I pass the top_intf into testbench environment.

class env;
// local interfaces to avoid hierarchical reference??
virtual fifo_intf fifo_if_i[`NUM_IN];
virtual fifo_intf fifo_if_o[`NUM_OUT];

function env::new(virtual top_intf top_vif);
    this.top_vif = top_vif;
    fifo_if_i[0:`NUM_IN-1] = top_vif.fifo_if_input[0:`NUM_IN-1];
    fifo_if_o[0:`NUM_OUT-1] = top_vif.fifo_if_output[0:`NUM_OUT-1];
endfunction: new
endclass;

This works fine with NUM_In andNUM_OUT greater than 1. But having some issues when the NUM is 1. the error is

  Incompatible complex type assignment
  Type of source expression is incompatible with type of target expression. 
  Mismatching types cannot be used in assignments, initializations and 
  instantiations. The type of the target is 'virtual interface 
  fifo_intf$[0:0]', while the type of the source is 'interface fifo_intf'.
  Source Expression: this.top_vif.fifo_if_input[0]

What I am doing now is setting some defines to indicate what the NUM_IN value is, for example

`ifdef PROJ_A
    `define NUM_IN_IS_1
`elsif PROJ_B
    `define NUM_IN_IS_2
`endif

then

in another include file

`ifdef NUM_IN_IS_1
    fifo_if_i[0] = top_vif.fifo_if_input[0];
`elsif NUM_IN_IS_2
    fifo_if_i[0] = top_vif.fifo_if_input[0];
    fifo_if_i[1] = top_vif.fifo_if_input[1];  
`endif 

I think we can use some script to generate the testbench code, but I am trying to look for a way without scripting. I am open to suggestions. How do you deal with this design situation in you testbench?

Thanks a lot!

Shuo
  • 1
  • 1

1 Answers1

0

To avoid the array to array assignments, roll them up inside for loops:

function env::new(virtual top_intf top_vif);
    this.top_vif = top_vif;

    foreach (fifo_if_i[i])
      fifo_if_i[i] = top_vif.fifo_if_input[i];

    foreach (fifo_if_o[i])
      fifo_if_o[i] = top_vif.fifo_if_output[i];
endfunction: new
Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
  • Thanks for your answer, but I don't think this will work. I've tried it before. It reported "cannot find member fifo_if_input in interface top_intf. I don't think you can index an interface array. – Shuo Dec 30 '16 at 18:18
  • @Shuo This is legal syntax. You should open a case with your tool vendor. – Tudor Timi Dec 30 '16 at 19:04
  • I think the answer from @dave_59 explained why you cannot use a variable to index interface array: http://stackoverflow.com/questions/40839419/dynamic-array-of-interfaces-in-sv – Shuo Dec 30 '16 at 19:14
  • I think if this usage had been common, VCS should have already been supporting it. – Shuo Dec 30 '16 at 19:16
  • @Shao But the answer doesn't say it's not allowed. It says why the code shown by the OP is allowed. – Tudor Timi Dec 30 '16 at 19:18
  • @Shuo Oh, I get what the issue here might be. It's not the array declaration your tool has problems with, it's the references. Whether you use `0`, `1` or `i` in that context shouldn't make a difference, since you're in class code. The discussions about generate loops and such don't apply there. The tool is probably mixing contexts. – Tudor Timi Dec 30 '16 at 19:22
  • @Shuo Regardless, I don't think this usage is common. – Tudor Timi Dec 30 '16 at 19:24
  • Please correct me if I understand this wrong. From the answer, "which is why you are not allowed to use a variable to procedurally select a specific instance." The interfaces in top_intf are instances, so I think this says why, right? – Shuo Dec 30 '16 at 19:26
  • @Shuo I would assume that is meant for when you're inside a module/interface. I would also rather see your case as being different. You have a variable on the right hand side with variables of its own. I would conceptually see this case as having a struct with an array of virtual interfaces (a thing you could try instead, BTW). I'm not sure if the BNF descriptions quoted there apply in this case. I could also see this as being a really silly language limitation, because it's pretty clear what should happen and that there are no issues with instances and such. – Tudor Timi Dec 30 '16 at 19:55