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?
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;