Search code examples
packagevhdlprocedurereusabilitytest-bench

Package procedure calls for testbench stimulus


I have various designs that use an FPGA on a parallel bus with a Microcontroller. For each design I have a testbench were I simulate several Read/write operations on the bus, using procedures that emulates the MCU timing.

I'd like to know a good way to put these procedures in a package for easier reuse. Right now, the procedures are defined and acts on signals within the scope of the testbench entity. I'd rather have something like this.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.mcu_sim.all; -- contains MCU component and procedures for bus R/W operations

entity tb is
end tb;

architecture a of tb is
    -- DUT
    component fpga is 
        port (
        clk, rst: in std_logic;
        Data: inout std_logic_vector(7 downto 0);
        Addr: in std_logic_vector(15 downto 0);
        wr: in std_logic;
        rd: in std_logic);
    end component;

signal      clk, rst: std_logic;
-- Bus signals 
signal      Data: std_logic_vector(7 downto 0);
signal      Addr: std_logic_vector(15 downto 0);
signal      rd: std_logic;
signal      wr: std_logic;

begin

    dut: fpga
    port map (

        clk => clk,
        rst => rst,
        Data => Data,
        Addr => Addr,
        wr => wr,
        rd => rd
    );

    mcu1: mcu
    port map (

        clk => clk,
        rst => rst,
        Data => Data,
        Addr => Addr,
        wr => wr,
        rd => rd
    );


    process
    begin
        clk <= '0';
        wait for 0.5 us;
        clk <= '1';
        wait for 0.5 us;
    end process;

    stimulus: process
    begin
        rst <= '1', '0' after 1 us; 

        -- A list of nice, easy-to-read procedure calls to control the MCU
        -- Defined in package mcu_sim: procedure buswrite(data: in std_logic_vector(7 downto 0); addr: in std_logic_vector(15 downto 0));

        buswrite(X"01", X"0000"); -- Command for mcu to take control of bus and do a write operation to the fpga
        buswrite(X"02", X"0001"); -- Command for mcu to take control of bus and do a write operation to the fpga

        wait;
    end process;

end a;

The package mcu_sim would contain everything needed for emulating the MCU bus operations, and I can easily taylor my stimulus program using the procedure calls. I realize that it would require the procedures to control whats happening inside mcu1. Is it possible to do this?

If not, how would you make reusable procedures for test stimuli?


Solution

  • You can put procedures in a package. However, to do so, you need to do two things:

    i) You must split the procedure into two parts. The procedure declaration, including the name, parameters and return type, goes in the package declaration. The procedure body, which repeats the subprogram declaration and adds the implementation of the subprogram, goes in the package body.

    ii) Your procedure must have a complete parameter list: the parameter list must include all signals and variables read by the procedure and all signals and variables assigned to by it.

    package mcu_sim is
    
      procedure buswrite(
        data_in       : in  std_logic_vector(7 downto 0); 
        addr_in       : in  std_logic_vector(15 downto 0);
        -- you will need to add all the MCU I/O here to give you a complete parameter list, eg
        signal Data   : out std_logic_vector(7 downto 0);
        signal Addr   : out std_logic_vector(15 downto 0);
        signal rd     : out std_logic;
        signal wr     : out std_logic    
        );
    
    end package mcu_sim;
    
    package body mcu_sim is
    
      procedure buswrite(
        data_in       : in  std_logic_vector(7 downto 0); 
        addr_in       : in  std_logic_vector(15 downto 0);
        -- you will need to add all the MCU I/O here to give you a complete parameter list, eg
        signal Data   : out std_logic_vector(7 downto 0);
        signal Addr   : out std_logic_vector(15 downto 0);
        signal rd     : out std_logic;
        signal wr     : out std_logic    
        ) is
      begin
        -- the code
      end procedure buswrite;
    
    end package body mcu_sim;
    

    So, your stimulus process would become something like:

    stimulus: process
    begin
        rst <= '1', '0' after 1 us; 
    
        buswrite(X"01", X"0000", Data, Addr, rd, wr); 
        buswrite(X"02", X"0001", Data, Addr, rd, wr); 
    
        wait;
    end process;