0
votes

I'm implementing a system that uses an interface to connect two blocks that implements AXI4 lite functions.

Problem is the master and the slave blocks are inside other blocks.

The code above shows an example of what I'm trying to do:

interface bus 
  logic [ADDR_WIDTH-1:0] wr_addr;   // Write address
  logic [DATA_WIDTH-1:0] wr_data;   // Write data
  logic [ADDR_WIDTH-1:0] rd_addr;   // Read address
  logic [DATA_WIDTH-1:0] rd_data;   // Read data

  modport master (
    output wr_addr,
    output wr_data,
    input  rd_addr,
    input  rd_data
  );

  modport slave (
    input   wr_addr,
    input   wr_data,
    output  rd_addr,
    output  rd_data
  );

endinterface


// innermost master block
module m0(bus.master bus_inst_m0);

  // write/ read data from/to master modport
  bus_inst_m0.wr_addr <= ...
  if(bus_inst_m0.rd_addr == ...

endmodule


// instance of m0 block connected
// to interface
module m1(bus.master bus_inst_m1);

  m0 m0_inst(.bus_inst_m0 (bus_inst_m1))

endmodule



// innermost slave block
module s0(bus.slave bus_inst_s0);

  // write/ read data from/to slave modport
  bus_inst_s0.rd_addr <= ...
  if(bus_inst_s0.wd_addr == ...

endmodule


// instance of ms block connected
// to interface
module s1(bus.slave bus_inst_s1);

  s0 s0_inst(.bus_inst_s0 (bus_inst_s1))

endmodule


// top module
module top();

  bus local_bus;

  m1 m1_inst (.bus_inst_m1 (local_bus));
  s1 s1_inst (.bus_inst_s1 (local_bus));

endmodule

In Cadence Incisive simulator, the code compiles, but it not works. Looking in the schematic I see that the top interface is connected, but the inner interfaces are just open.

I made a small test connecting directly the master and slave blocks and it worked fine.

I have tried other combinations of interface/modport too, like using modport just in the innermost blocks, but it didn't work.

I read the LRM and did not found any clue about what I'm doing wrong.

Can anyone help?

Thanks Rods

1
Any warnings? Also try with local_bus.master and local_bus.slave instead of local_bus - Karan Shah

1 Answers

0
votes

First of all, you have a bunch of options to use. You can use generic interfaces as module parameters to avoid type errors. In this case, as long as the connected interface has all the signals that the module use, you will be okay. (And if the tool finds the proper interface...) Eg.:

module mod_gen_inf(interface gen_if);
endmodule
...
module top();
  m_bus_if m_bus;
  m_1 slave_actor(.gen_if(m_bus.master));
endmodule: top

Secondly, you can, but you are not required to specify the modport (type) at the module declaration. You can use the interface's name, and connect the specific modport at the module instantiation. Eg.:

module slave_actor(m_bus m_bus_if);
endmodule
...
module top();
  m_bus_if m_bus;
  m_1 slave_actor(.m_bus_if(m_bus.slave));
endmodule: top

Think of this as the modport is a compatible type of the given interface.

Thus a corrected/shortened version of your code:

interface m_bus;
  logic [1:0] a;
  modport master(input a);
  modport slave (output a);
endinterface

module m1(m_bus.master bus_inst_m1);
  m2 m2_inst(.bus_inst_m2(bus_inst_m1));
endmodule

module m2 (m_bus.master bus_inst_m2);
endmodule

module s1(m_bus.slave bus_inst_s1);
endmodule

module top();
  m_bus local_bus();

  m1 m1_inst (.bus_inst_m1 (local_bus.master));
  s1 s1_inst (.bus_inst_s1 (local_bus.slave));
endmodule

This worked me fine in QuestaSim 10.5c. If your code compiled but does not work, make sure that your innermost block sees the interface as well. (include the library that your IF is compiled into.)