Monday 4 April 2011

VHDL Test Bench Package: An Internal BFM, Like a CPU


This post will present how the VHDL Test Bench Package can be used as the “internal” test bench or BFM. By internal I mean that the test bench bhv architecture file be substituted in the place of an internal architecture block of the DUT. i.e. Replacing some of the RTL with behavioural test bench code, namely the script parser. This enables the test script to emulate internal blocks with simple custom commands. This can be very useful in several situations.

The first and most popular is to replace the CPU Core with the scripting portion of the bhv file. As an internal block, the CPU does not source a clock, so the clock_driver process can be removed from the bhv file. A code snip of this implementation is provided in section 3 of the Code Snips download file. Presented in the code snip is the structure modifications that would have to be made to the DUT RTL. The code is also included here to facilitate better descriptions.

The addition of a generic to the entity who's architecture instantiates the component of interest. Below is a sample of the additional code. The addition of the generic and additional structure will have no effect on synthesis.

-- this is the top enity or at the level where you can assign the
-- en_bfm generic and it makes sense
entity my_top_dut is
generic (
g_en_bfm : integer := 0
);
port (
-- top port definitions
);
end enity my_top_dut;

A copy of the RTL block is made, renamed and a generic is added to it that points to the stimulus file. Some methods have the declaration of components in a package, in the case of the example, the components are declared in the architecture of the example entity (my_top_dut). The architecture start could look like the code below:

architecture struct of my_top_dut is
-- this is the component of an internal block of my_top_dut
component rtl_block
port (
reset_n : in std_logic;
clk_in : in std_logic;
-- ...
);
end component;
-- bhv_block has the same pin out as rtl_block, except for the generic
component bhv_block
generic (
stimulus_file: in string
);
port (
reset_n : in std_logic;
clk_in : in std_logic;
-- ...
);
end component;
--....
begin

When it comes to port mapping an instance, a VHDL generate statement round the RTL and around the bhv port mappings enables one or the other to be included in the load. Hence an optional internal BFM. This is shown in the example code below:

begin
-- if generic is default value, include rtl
if(g_en_bfm = 0) generate
begin
rtl_b1: rtl_block
port map(
reset_n => reset_n,
clk_in => clk,
-- ...
);
end generate;
-- if generic is set for bhv, include it
if(g_en_bfm = 1) generate
begin
bfm: bhv_block
generic map(
stimulus_file => "stm/stimulus_file.stm"
)
port map(
reset_n => reset_n,
clk_in => clk,
-- ...
);
end generate;
-- ...
end struct;

Be it a simulator or a synthesis tool, the user has control over which version to load through the top enable generic (g_en_bfm). By default the above implementation will load RTL, and to get the BFM in place you have to modify code or pass in a different generic value when loading the simulation. This facility is provided by all major tool vendors.

Now with the test bench bhv file substituted for the CPU, the CPU emulation commands can be pasted into the else if chain. That and the other modifications detailed in Section 2 of the code snips file, and have a nice start to the implementation. The one thing that will have to be created is the interface logic for the block being emulated. In the case of a CPU, READ and WRITE commands will have to be created that use the bus signalling. There may be many types of bus cycles that need to be emulated. Using procedures within the read_file process will enable a reduction in file size and stability of interface commands. This topic will be detailed in a future post.

Another place that is a good candidate for internal BFM substitution is the debug link block. Many processors have a debug facility with some implementations being controllable over a system bus through a simple RS-232 serial link, for example. The RS-232 debug link in RTL is a bus master that can control some debug slave on the bus system. The idea is to replace that RTL debug link with an internal BFM. This makes the scripting system a bus master, and now can control the system as if it was a host computer over the RS-232 link. This removes the slow RS-232 system from having to be simulated/modelled. The real CPU RTL can now be controlled as it would in the implementation, through it's debug interface. If the CPU had been modelled before as a bus master (as I would assume it was), you can most likely reuse some of that code.

As stated in the test bench package documentation, having multiple script parsers in one environment will increase complexity significantly. If an internal BFM uses the read_file process, all effort should be made to make it the central place for control. If the verification system needs to have scripting control from the top level, another way to gain control of an internal block is to use the signal connection facility found in most simulation tools. In the Modelsim world this is know as signal spy. It enables the connection of one signal to another while ignoring VHDL structure boundaries. The user can drive/read these signals and control the end points. This enables one script parser to control what ever is required by the effort.

Using facilities like signal_spy is good if it helps you get the job done. The implementation can use the same generate structure presented above, but use an empty architecture for the bhv instead of the test bench bhv file. Once the signal_spy is connected you can operate on the internal block as if the scripting system was there. Commands in the bhv file can act on the signal_spy signals like any other signal or pin it has access to.

That concludes the presentation of how the VHDL Test Bench Package can be used as an internal BFM. I have personally implemented all of the above methods. I hope that helps some to implement some good verification environments.

Sckoarn

No comments:

Post a Comment