# Enhancing VHDL Testbench Using Matlab® Interface

## Introduction

The MATLAB interface was introduced in its full version in Active-HDL 7.1. If you are using earlier versions, only Simulink interface is available. The key difference between those two interfaces is that in MATLAB interface Active-HDL controls the co-simulation process and starts MATLAB when necessary, while in Simulink interface the MathWorks? Simulink controls the co-simulation process and starts Active-HDL when necessary.

The MATLAB interface, available from VHDL code level, provides the following features:

Running of MATLAB commands (both native and user-created m-files)

Passing variables between Active-HDL and MATLAB

Creation and destruction of data structures required for arrays transfer between Active-HDL and MATLAB

Quick array data passing between Active-HDL and MATLAB

Typical tasks that can be accomplished thanks to the MATLAB interface include:

Computation of functions hard to describe in HDLs

Quick generation of complicated waveforms

Post-processing of simulation results

Advanced visualization of simulation results

To fully utilize the interface, you have to have MATLAB version 7 (R14) or later installed on your computer and registered as a COM server ( type MATLAB /regserver in the command prompt to perform the registration).

## Getting Access to the Interface

To use MATLAB interface, you must call special functions, tasks and procedures from your VHDL code (MATLAB windows will show up after the first command or data transfer request is executed). To make those VHDL routines visible in your code, you have to configure your environment. MATLAB windows will show up after the first command or data transfer request is executed.

All units in your VHDL code that want to access MATLAB interface must be preceded with the following library/use clauses:

library aldec; use aldec.MATLAB.all;

## Importing Data from Matlab

The simplest task frequently useful in testbenches is generation of a waveform in MATLAB and import of waveform data to the testbench. In the examples that follow we assume that appropriate libraries were already attached and made visible to your testbench code.

Our task is to generate modulate sine wave stimulus with the following parameters:

Carrier frequency CFRQ equal 40

Carrier amplitude AMPL equal 16383

Signal frequency SFRQ equal 4

Modulation depth DPTH equal 0.8

The mathematical formula describing the stimulus is:

AMPL*sin(2*pi*CFRQ*t) * (1-DPTH*cos(2*pi*SFRQ*t))

Assuming sampling period 1 ns, we want to create at least 1000 samples in Matlab, collect them in an array, transfer the array to the Active-HDL and use it to generate waveform fed to the 16 bit input DI of a test circuit (e.g. digital filter).

To generate samples in Matlab, we have to create a do_wave.m file in the SRC folder of your Active-HDL project and type two lines in that file:

t = 0:.001:1.024 ; sw = fix(AMPL*sin(2*pi*CFRQ*t).*(1-DPTH*cos(2*pi*SFRQ*t))) ;

Notes:

The first line creates time domain vector t, storing all values between 0 and 1.024 with 0.001 step

The second line creates our waveform

The Matlab function fix rounds its argument to the nearest integer towards zero

The Matlab operator .* multiplies elements of both sine waves (regular * operator would attempt matrix multiplication in this context)

Please refer to Matlab documentation for more detailed description of Matlab functions.

To distinguish between row and column structures, one dimensional arrays in Matlab are internally stored as two dimensional arrays: 1-by-n for row-vectors and n-by-1 for column-vectors. This distinction is reflected in the internal structure of both t and sw arrays: they are two-dimensional arrays, with the first dimension size equal 1, and the second dimension size equal 1025. This structure is maintained after import to the Active-HDL environment.

The following variable and type declarations should be added to the VHDL testbench:

shared variable inp_arr_id : integer; type arr2dim is array (1 to 1025) of std_logic_vector(15 downto 0); shared variable stim_arr : arr2dim;

Notes:

inp_arr_id will hold the id of array of samples imported from Matlab

arr2dim is a data type for storing groups of 16-bit samples

stim_arr is an array storing samples for waveform generation in VHDL

To pass values of stimulus generation parameters to MATLAB, you have to call put_variable procedure from the aldec.MATLAB package:

put_variable("AMPL", amplitude); put_variable("CFRQ", carrier_frq); put_variable("SFRQ", signal_frq); put_variable("DPTH", mod_depth);

The first argument of the task is the string representing Matlab variable name. The second argument is value that should be assigned to that variable (we are using VHDL constants as the second argument).

HINT: The first use of Matlab-related procedures during simulation starts Matlab application. On some installations of Microsoft Windows loading Matlab for the first time is quite long. To avoid this period of apparent inactivity during simulation, you may consider starting and immediately closing Matlab before you run simulation in Active-HDL. Subsequent runs of Matlab should be faster.

To execute the m-file presented earlier and import the sw array created in MATLAB, you have to call two subprograms from the aldec.MATLAB package:

eval_string("do_wave"); inp_arr_id := ml2hdl("sw");

Notes:

eval_string procedure executes MATLAB command or m-file passed as its string argument

ml2hdl function imports MATLAB array passed as its string argument and returns integer identifier for the imported array

As we have mentioned before, the sw array maintains its original 1-by-1025 size after import. That's why we have to use the following syntax of the get_item procedure to transfer the elements from the imported array to the regular, VHDL array variable stim_arr:

for i in stim_arr'range loop get_item( stim_arr(i), 0, inp_arr_id, (1,i) ); end loop

Notes:

stim_arr(i) is the vector where one element of the imported array will be stored

0 is the number of digits in the fractional part of the value being transferred

inp_arr_id is the identifier of the imported array (returned by ml2hdl)

(1,i) is an aggregate representing position of the transferred element in the imported array

To complete our task, we have to transfer samples stored in the stim_arr array to the input of the tested circuit:

for i in stim_arr'range loop DI <= stim_arr(i); wait for 1 ns; end loop; destroy_array(inp_arr_id);

Note:

destroy_array procedure cleans up the memory allocated for the imported array.

## Exporting Data to Matlab

Waveform viewer in your HDL simulator is powerful, but restricted to time-domain graphs (waveforms). If you want to display any other graphs (e.g. Fast Fourier Transform of the data produced by the tested circuit), Matlab is an excellent solution.

In this section of the note, our task is to:

collect 512 samples of the output DO of our tested circuit,

create temporary 1-by-512 array required for export procedures

transfer samples to the temporary array

export temporary array to Matlab

process and graph exported data

import some computation results back to the HDL simulator

To tell Matlab how to process exported data we have to create m-file named do_fft.m in our design and fill it with Matlab commands computing FFT and creating graph. Here's the list of Matlab commands:

Y=fft(smpl,512) ; My = sqrt(Y.* conj(Y)) ; f = 1000*(0:256)/512 ; [MM, MI] = max( My(1:50) ); MF = f(MI); plot(f,My(1:257)) title('Frequency content of filter output') xlabel('frequency (Hz)') grid on

Notes:

the first line requests computation of 512 point FFT and stores results in complex matrix Y

the second line computes modules of FFT coefficients stored in Y and sends them to My matrix

the third line computes frequency domain required for our final graph; since the results of FFT are symmetrical, we only have to use half of the points

the fourth and fifth line find maximal power frequency in the previously computed spectrum of the output signal

the remaining lines create graph, label it and its frequency axis, display grid

In the VHDL testbench, you will need an array to store samples of the output of the tested circuit. Here?s an example of type and variable declaration:

type s_arr is array(1 to 512) of STD_LOGIC_VECTOR(15 downto 0); variable samples : s_arr;

You should write appropriate sampling code, according to the nature of the tested circuit and your verification procedures. The only assumption we are making is the sampling period of 1 ns. Once the samples array is filled with data, we can proceed to the export to MATLAB:

out_arr_id := create_array( "smpl", 2, (1,samples'right) ); for i in samples'range loop put_item( samples(i), 0, out_arr_id, (1,i) ); end loop; hdl2ml( out_arr_id ); // send temp. array to Matlab

Notes:

out_arr_id is an integer identifier of the temporary array we are creating

create_array function creates temporary array with smpl MATLAB name, 2 dimensions and sizes of those two dimensions represented by the (1,samples'right) aggregate

put_item is a procedure that transfers value from samples(i), treated as a number with 0 fractional part size, into the element of temporary array represented by out_arr_id, with index values specified in the aggregate (1,i)

hdl2ml procedure exports temporary array represented by out_arr_id to MATLAB environment

Once the data was exported to Matlab, we are ready to execute m-file, read MF variable from Matlab and delete temporary array:

$eval_string( "do_fft" ); // request processing $get_variable( "MF", fmax ); // read variable from Matlab $destroy_array( out_arr_id ); // clean up!

Note:

get_variable is a procedure that imports MATLAB scalar variable specified by the first argument to the VHDL variable specified by the second argument

## Conclusion

Matlab interface, as described in this document, is the easy way of enhancing functionality of your Verilog or VHDL code using Matlab's extensive mathematical and graphing features.