You're reading the documentation for a development version.
For the latest stable release version, please have a look at master.

Interfacing with System Verilog

Description

The Interface type specifically targets System Verilog designs. This type extends from Bundle. When generating Verilog or VHDL, the behavior of this type is exactly the same as that of Bundle. However, when generating System Verilog and enabling the svInterface option in SpinalConfig, this type will be generated as an Interface.

This type is still an experimental feature.

Declaration

The syntax to declare a Interface is as follows:

case class myBundle extends Interface {
  val bundleItem0 = AnyType
  val bundleItem1 = AnyType
  val bundleItemN = AnyType
}

For example, a Interface holding a color could be defined as:

case class Color(channelWidth: Int) extends Interface {
  val r, g, b = UInt(channelWidth bits)
}

modport

modport can be implemented through add annotations above functions, with the function name serving as the modport name.

case class Color(channelWidth: Int) extends Interface {
  val r, g, b = UInt(channelWidth bits)

  @modport
  def mst = {
     out(r, g, b)
  }

  @modport
  def slv = {
     in(r, g, b)
  }
}

with IMasterSlave

case class Color(channelWidth: Int) extends Interface with IMasterSlave {
  val r, g, b = UInt(channelWidth bits)

  override def asMaster = {
     out(r, g, b)
  }

  @modport
  def mst = asMaster

  @modport
  def slv = asSlave
}

Parameter

case class Color(channelWidth: Int) extends Interface {
  val width = addGeneric("WIDTH", channelWidth) // or addParameter
  val r, g, b = UInt(channelWidth bits)
  tieGeneric(r, width) // or tieParameter
  tieGeneric(g, width)
  tieGeneric(b, width)

  @modport
  def mst = out(r, g, b)

  @modport
  def slv = in(r, g, b)
}
case class ColorHandShake(Width: Int) extends Interface with IMasterSlave {
  val w = addGeneric("W", Width, default = "8")
  val valid = Bool()
  val payload = Color(Width)
  val ready = Bool()
  tieIFParameter(payload, "WIDTH", "W") // for generate "  .WIDTH (W)"

  override def asMaster = {
    out(valid, payload)
    in(ready)
  }

  @modport
  def mst = asMaster

  @modport
  def slv = asSlave
}

This will generate system verilog code as below:

interface ColorHandShake #(
   parameter W = 8
) () ;

   logic           valid ;
   Color #(
      .WIDTH (W)
   ) payload();
   logic           ready ;

   modport mst (
      output          valid,
      Color.slv       payload,
      input           ready
   );

   modport slv (
      input           valid,
      Color.mst       payload,
      output          ready
   );

endinterface

interface Color #(
   parameter WIDTH
) () ;

   logic  [WIDTH-1:0] r ;
   logic  [WIDTH-1:0] g ;
   logic  [WIDTH-1:0] b ;

   modport mst (
      input           r,
      input           g,
      input           b
   );

   modport slv (
      output          r,
      output          g,
      output          b
   );

endinterface

Definition Name

You can use setDefinitionName to set the definition name. But remember to use it before any clone of this interface.

Not Interface

If you have used a certain interface in multiple places, and at one of those locations mySignal, you wish to flatten it instead of generating an interface, you can achieve this by calling mySignal.notSVIF() to fully flatten the signal. If the signal has nested interfaces and you only want to expand the outermost layer, you can use mySignal.notSVIFthisLevel().