Interfaces: Packages as an Interface Construct

Current VHDL: The Basics

Signals declared in a package are accessible to any model that accesses the package. For each model that we need to communicate to, create a package. This can be something like the following. Note that it can include any type, in particular types like integer, real, and time which a common in testbench models.

package Model1Pkg is 
   signal CmdRdy              : std_logic ;
   signal CmdAck              : std_logic ; 
   signal UnsignedToModel     : unsigned(15 downto 0) ;
   signal UnsignedFromModel   : unsigned(15 downto 0) ;
   signal IntegerToModel       : integer;
   signal IntegerFromModel     : integer;
end Model1Pkg ;

To create a transaction based environment, we may wish to add procedures that can interact with the internal signals. This could be something like DoOp (do operation).

package Model1Pkg is
   ...
  procedure DoOp (
    constant UnsignedI       : in    unsigned ;
    constant IntegerI        : in    integer ; 
    signal   CmdRdy          : out   std_logic ; 
    signal   UnsignedToModel : out   unsigned ;
    signal   IntegerToModel  : out   integer  
  ) ; 
end Model1Pkg ;
package body Model1Pkg is 
  procedure DoOp (
    constant UnsignedI       : in    unsigned ;
    constant IntegerI        : in    integer ; 
    signal   CmdRdy          : out   std_logic ; 
    signal   UnsignedToModel : out   unsigned ;
    signal   IntegerToModel  : out   integer
  ) is
  begin
    UnsignedToModel <= UnsignedI ; 
    IntegerToModel  <= IntegerI ; 

    -- hand-off signaling if required
    RequestAction(Rdy => CmdRdy, Ack => CmdAck) ; 
  end procedure ; 
end Model1Pkg ;

One downside is that all signals driven by the procedure must be on the interface list. However, this is addressed in the proposed Implicity Parameter and Port Connections. With this the outs would need to be specified as part of the procedure, but would not need to be part of the call.

VHDL-2008: Multiple Instances of the same design

Another downside happens when we have the multiple instances of the same design. Now we need separate packages for each design. One way to do this is with VHDL-2008 package generics.

Change Model1Pkg to the following:

package ModelGenericPkg is 
  generic ( count : integer ) ; 

    constant ModelNum : integer := count ; 

    ...
end ModelGenericPkg ; 

Now for each instance of the model, we will create package instance as a design unit:

package Model1Pkg is new work.ModelGenericPkg
  generic map ( count  =>   1  ) ;  

Each model must be able to associate which package it is using. As a result, the model needs a formal generic for the package.

entity Model1 is 
  generic ( 
    package InterfacePkg is new work.ModelGenericPkg generic map (<>) 
  ) ; 
  port (
    Clk                 : In    std_ulogic ;
    nReset              : In    std_ulogic 
  ) ;
end Model1 ;
architecture BFM of Model1 is

  use InterfacePkg.all ; 

begin

And then in the design instance we need to map the package instance:

  U_Model1 : Model1 
  generic map ( InterfacePkg => Model1Pkg ) 
  port map(
    Clk                    => Clk,
    nReset                 => nReset
  ) ; 

VHDL-2008: Multiple Instances of the design that instances

Creating a package as a design unit is a normal way of working with packages. The problem with this methodology is that if we have multiple instances of designs that use the package. Now each of the lower level connections is using a package instance of the same name.

VHDL-2008 offers another feature that helps out here - local packages. That is a package that is not in a library scope, but instead is local to an architecture declarative region. As a result we have:

architecture struct of UpperTestbenchModel is

  package Model1Pkg is new work.ModelGenericPkg
    generic map ( count  =>   1  ) ; 

  use Mode1Pkg.all ;  
 

Proposed Extension: Limiting Access to objects and subprograms

One of the things we have lost with this approach is any sense of which model is allowed to drive which signal. Another thing we may wish to do is grant specific models to specific subprograms. SystemVerilog uses a modport construct to do this. We could adopt a VHDL version of this. These would have to be optional additional syntax since there is no way to prevent the usage shown previously.

package Model1Pkg is 
  ... 
  modport model of Model1Pkg is 
     CmdRdy              : in std_logic ;
     CmdAck              : out std_logic ; 
     UnsignedToModel     : in unsigned(15 downto 0) ;
     UnsignedFromModel   : out unsigned(15 downto 0) ;
     IntegerToModel       : in integer;
     IntegerFromModel     : out integer;
   end modport ;  

  modport TB of Model1Pkg is 
     CmdRdy              : out std_logic ;
     CmdAck              : in std_logic ; 
     UnsignedToModel     : out unsigned(15 downto 0) ;
     UnsignedFromModel   : in unsigned(15 downto 0) ;
     IntegerToModel       : out integer;
     IntegerFromModel     : in integer;
     procedure DoOp ;  -- signatures permitted by not required
   end modport ;  
    . . . 
end  Model1Pkg; 

The package gives read access to all of the internal signals, so perhaps, specifying something as in could be optional.

The design instance would now need to specify the modport:

  U_Model1 : Model1 
  generic map ( InterfacePkg => Model1Pkg.model ) 
  port map(
    Clk                    => Clk,
    nReset                 => nReset
  ) ; 

Limitations

What is missing: SystemVerilog interfaces allow a concurrent code region for assertions and interface behavior (such as a fifo or such).

How does an interface contain another interface as a subset?

For cases where there are multiple instances of the same design, it can be convenient to use "for generate". To do this with packages, we would need to be able to do an array of package instances. Is this somewhere we would want to go?

I started out thinking that I would like a protected type better as the container, however, a package can contain a shared variable declaration. Hence, it can do everything the shared variable can. With protected types perhaps it is more natural to use arrays than with packages.

Concerns

Comments

Most of this is VHDL-2008. This is a potential next step in testbench interfaces. The proposed extension allows static checking for correct usage of subprograms and driving signals - although SystemVerilog added this capability, I am not sure we require this feature for testbenches.

Topic revision: r3 - 2016-11-15 - 18:23:42 - BrentHahoe
 
Copyright © 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback