You are on page 1of 13

MATLAB AND MODELSIM LINKING

DR.S.S.Limaye

Introduction: MATLAB is powerful software package for mathematical


simulation, especially when signals are represented in an abstract i.e.
mathematical form. When we want to test a hardware system in terms of the
abstract inputs and outputs, linking Modelsim VHDL or Verilog simulator with
MATLAB is very helpful. The most beneficial use could be to write a test
bench for the HDL model in MATLAB. The test cases can be generated in
MATLAB at a higher level of abstraction, making it suitable for regression
testing with random inputs. Given the ease of interfacing, this provides a
very attractive alternative to Verilog PLI or VHDL FLI programming. It can be
even considered as a serious alternative to e, vera, system C or system
verilog languages.
Configuring: For the link to work, Modelsim has to be invoked from the
command prompt of MATLAB. For this purpose, MATLAB needs to know the
location of MODELSIM. Install MATLAB and MODELSIM on your computer.
Open MATLAB and type following command.
>>configuremodelsim
The system responds with following:
Do you want configuremodelsim to locate installed ModelSim executables
[y]/n?
Press y
If it finds Modelsim properly installed, it responds with following:
[1] C:\Modeltech_6.2c\win32
ModelSim SE 6.2c
[0] None
Select ModelSim installation to be configured:
Press 1
System responds with following:
ModelSim successfully configured to be used with MATLAB and Simulink

Invoking socket server

MATLAB and Modelsim communicate with each other either through shared
memory server or through TCP/IP links using socket calls. If MATLAB and
Modelsim are running on different machines then TCP/IP link is mandatory.
For same machine, shared memory is preferable. For inter process
communication, MATLAB starts a server called HDLDaemon. For shared
memory mode, give command:
hdldaemon
The system should respond with
HDLDaemon shared memory server is running with 0 connections
In case of trouble, try following steps.
type following command to first check the status:
>>hdldaemon('status')
MATLAB should normally respond with:
HDLDaemon is NOT running

If a previous instance of HDLDaemon is running, it needs to be killed with


the command:
>>hdldaemon('kill')
MATLAB will respond with:
HDLDaemon server was shut down
For socket mode, start the HDLDaemon with the command:
>>hdldaemon('socket', 0)
0 tells the OS to allocate the next available port. MATLAB will respond with:
HDLDaemon socket server is running on Port portnum with 0 connections
Where portnum is a socket port number assigned by the OS. Remember this
number as it will be required for the Modelsim connection later.

Developing VHDL program


Let us start with a small VHDL program for implementing a full adder.
a
b
cin

FULL ADDER

sum
cout

The program listing is given below.


library IEEE;
use IEEE.std_logic_1164.all;
entity adder is
port (a
: in std_logic;
b
: in std_logic;
cin : in std_logic;
sum : out std_logic;
cout : out std_logic);
end adder;
architecture rtl of adder is
begin
sum <= (a xor b) xor cin;
cout <= (a and b) or (cin and a) or (cin and b);
end rtl;

Note that the entity name is adder. Remember this as it will be required
during invocation of the simulator.
Create a folder outside MATLAB. In our demo, we are creating it as
C:\MODELSIM_PROJ. Change MATLAB current directory to above. Invoke
Modelsim compiler from MATLAB command window with command:
>>vsim
In Modelsim command window, give dir command and make sure it is
pointing to C:\MODELSIM_PROJ. Invoke text editor by pressing File> New>
Source> VHDL. Enter the above program and save it as adderfile.vhd.
In Modelsim command window, give following commands:
ModelSim> vlib work
ModelSim> vmap work work

Either press compile menu or press compile tool button to invoke COMPILE
SOURCE dialog box. Double click on adderfile.vhd. The file gets compiled. If
there are errors, correct them and again compile till they are removed.

Developing MATLAB test bench


The test bench consists of a MATLAB callback function that gets invoked
either after a given delay or at rising edge (or falling edge) of any desired
port signal. In synchronous systems, usually it is the clock signal. If you wrap
the DUT in a VHDL test bench and generate clock as a part of the VHDL test
bench then the callback function will be periodically invoked with the clock.
However it is possible to avoid the test bench wrapper in VHDL and generate
the clock and all other port signals in MATLAB. Since the present example is
asynchronous, there is no clock in the device and hence we will generate all
the input signals in MATLAB. By default, the name of the MATLAB callback
function is same as the VHDL entity name but we can choose any other
name for it and inform it to the simulator with the -mfunc switch. The
prototype of the callback function is as follows.
function [iport,tnext] = ADD_TESTER (oport, tnow, portinfo)

Input parameters

Oport It is a structure having one member for each VHDL output port
signal. In our example, this structure will have following fields:
oport.sum, oport.cout
The values of these ports will be one of the 9 values of VHDL, namely
U,X,0,1,Z,W,L,H,-. If the port signals are of the type STD_LOGIC_VECTOR,
then the oport members will be arrays of matching length. Suppose the DUT
has a vector output signal named val. It will be represented as a character
string will typically look like 0110X. We can use following functions to
convert VHDL values to numeric values.
bin2dec(oport.val') is used to convert STD_LOGIC_VECTOR to unsigned
integer.
Note the quote mark after val which takes its transpose. If you dont use the
quote, then the function returns an array with same length as val.
If the port output signal (y) represents a signed integer, then we can convert
it like this:
op = bin2dec(oport.y');
b = 2^length(oport.y);
if oport.y(1) == '1' ; If sign bit is set, subtract MSB weight
op = op - 2^length(oport.y);
end

tnow Current simulation time in seconds.


portinfo: For the first call to the function (at the start of the simulation)
only, this parameter receives a structure whose fields describe the ports
defined for the associated VHDL entity or Verilog module. This parameter is

skipped in subsequent calls. For each port, the portinfo structure passes
information such as the port's type, direction, and size. Using this
information it is possible to validate the signals or to create a generic
MATLAB function that operates differently depending on the port information
supplied at startup. In our first example, we are ignoring this parameter. We
can check whether portinfo data has been passed with a call to the MATLAB
function nargin. For example: if(nargin == 3)
The information is supplied in four fields.
Field
Subfields
Sub sub fields
portinfo.in
portinfo.in.a
type, label, size
portinfo.in.b
type, label, size
portinfo.in.c
type, label, size
portinfo.out
portinfo.out.sum type, label, size
portinfo.out.cout type, label, size
portinfo.Inout
null
portinfo.tscale
In our example, type of all signals is std_logic, label is U,X,0,1,Z,W,L,H,-, and
size is 1.
The Simulator tick size in seconds can be accessed in MATLAB with the
statement portinfo.tscale. The size of a port, say cout can be accessed by
statement portinfo.out.cout.size.

Input parameters
The input parameters of the DUT are supplied to the simulator through the
output of the callback function.

iport

iport (DUT input ports) This is a structure similar to oport. We can apply
stimulus to the DUT inputs by setting the desired values on the iport
members. Single bit values can be assigned as:
iport.a = 1;
For vector inputs, unsigned integers in MATLAB can be converted to a VHDL
compatible string with dec2bin function. For example, if you have a 5 bit
input port named val, it can be assigned the value of an unsigned integer x
as:
inport.val = dec2bin(x,5);
For signed integers, use mvl2bin(x,5).

tnext

Time for next invocation of MATLAB test bench. It can be given directly in
seconds e.g.
tnext = tnow + 100e-9;
or in terms of simulator time steps (If configured this way):
tnext = 100;

If you dont want invocation after a fixed time, then you can leave the vector
null. The next invocation should then be based on transition of a specified
signal.

Testing of full adder

In the callback routine, it is useful to define a persistent (similar to static in


C) type variable (named ud here) to store variables that retain their values
from call to call. Here we are using ud.call_count to count the number of calls
to the callback routine.
This DUT has 3 inputs a,b,cin and 2 outputs sum and cout. We want to
give all possible combinations on a,b,cin. A convenient way to generate the
input sequence is to convert the call count into a bit string with dec2bin
function and apply its individual bits to the inputs a,b,cin. As long as the call
count is less than 8, we reinvoke the function after 100 ns.
The complete MATLAB program is given below.
function [iport,tnext] = ADD_TESTER (oport, tnow, portinfo)
persistent ud;
tnext = [];
iport = struct();

%Create a struct to store persistent user data


%initialize tnext to null
%initialize iport to null

if(nargin ==3)
%First call has 3 arguments
ud.call_count = 0; %Initialize call counter
tnext = tnow+100e-9;%Next invocation after 100 ns
iport.a = '0';
iport.b = '0';
iport.cin = '0';
else
ud.call_count = ud.call_count + 1;
if ud.call_count < 8
%run for 8 cycles
tnext = tnow+100e-9;
%Next invocation after 100 ns
bin = dec2bin(ud.call_count,3);%Convert counter to binary string
iport.a = bin(1);
%Assign bits of bin to 3 inputs
iport.b = bin(2);
iport.cin = bin(3);
else
disp('Over');
%If 8 cycles are over, dont invoke with tnext
end
end

Invoking Modelsim

Give following command on the Modelsim prompt to load the ADDER entity
for simulation.
ModelSim> vsimmatlab adder
Now link it to MATLAB test bench with the command at the VSIM prompt:
VSIM 3> matlabtb adder -mfunc ADD_TESTER
If you are using the socket mode, give command
VSIM 3> matlabtb adder -mfunc ADD_TESTER -socket portnum
Where portnum is the port number returned by the HDLDaemon

In the Modelsim window, using the GUI commands, add all signals in the
design to the waveform viewer. Press the run all tool button.
The waveforms of input and output should appear in MATLAB and VHDL.

If you want to debug the MATLAB function, you may insert suitable break
points.

Testing of FIR filter

The VHDL code of an 8 tap linear phase FIR is given below. It is a low pass
filter having cut off frequency of /4 radians, i.e. one eighth of sampling
frequency. For the details of design, refer to VHDL a design oriented
approach, by Dr S.S.Limaye, McGraw Hill India. It takes an 8 bit signed
integer x and produces 8 bit signed integer y. The filter coefficients can be
calculated with MATLAB command:
fir1(6,.25,'low',rectwin(7),'noscale')
--8 TAP LINEAR PHASE FIR FILTER
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_SIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
PACKAGE FILT IS
TYPE CONST_ARRAY IS ARRAY(POSITIVE RANGE <>)
OF SIGNED(7 DOWNTO 0);
END PACKAGE;
USE WORK.FILT.ALL; --USE DEFINITION OF CONST_ARRAY
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_SIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY FIRFILT8 IS
GENERIC(CON:CONST_ARRAY := ("00110110",

"00110001","00100011","00010000"));
-- 54,49,35,16 - SCALED FROM
-- .25,.2251,.1592,.075 CUT OFF AT PI/4
PORT(X:IN SIGNED(7 DOWNTO 0);
Y:OUT SIGNED(7 DOWNTO 0);
CLK,RST:STD_LOGIC);
END FIRFILT8;
ARCHITECTURE RTL OF FIRFILT8 IS
TYPE X_ARRAY IS ARRAY(1 TO 2*CON'HIGH - 2) OF
SIGNED(7 DOWNTO 0);
SIGNAL XA:X_ARRAY;--SIGNAL DELAY LINE
BEGIN
SHIFT_PROC:PROCESS(XA,X,CLK,RST)
BEGIN
IF RST = '1' THEN XA <= (OTHERS => "00000000");
ELSIF CLK'EVENT AND CLK = '1' THEN
XA(1) <= X;
FOR I IN 1 TO XA'HIGH-1 LOOP
XA(I+1) <= XA(I);
END LOOP;
END IF;
END PROCESS SHIFT_PROC;
SUM_PROC:PROCESS(XA,X)
VARIABLE SUM :SIGNED(18 DOWNTO 0);
VARIABLE SUM1:SIGNED( 8 DOWNTO 0);
VARIABLE SUM2:SIGNED( 8 DOWNTO 0);
BEGIN
--INPUT X IS NOT PART OF DELAY LINE XA
-- HANDLE IT SEPARATELY
SUM1 := (X(7) & X) + XA(XA'HIGH);--FORCE IT TO 9 BITS
SUM := (SUM1(8) & SUM1(8) & SUM1) * CON(CON'HIGH);
SUM := SUM + XA(CON'HIGH-1) * CON(1); -- UNPAIRED CENTER ELEMENT
FOR I IN 1 TO (CON'HIGH - 2) LOOP--OTHER ELEMENTS IN LINE
SUM2 := (XA(CON'HIGH-I-1)(7)
& XA(CON'HIGH-I-1)) + XA(CON'HIGH+I-1);
SUM := SUM + SUM2 * (CON(I+1));
END LOOP;
Y <= SUM(15 DOWNTO 8);
END PROCESS SUM_PROC;
END RTL;
The MATLAB test bench initializes the filter by activating RST for 100 ns,
setting X to 0 and then starts invoking itself after every 100 ns. In each
invocation, 100 sin(X) is computed and applied to X. The user data area ud
stores the call count and it is used as the index for arrays that store X and Y

values. At the end, the X and Y values are plotted in a graph. The MATLAB
code is given below.
MATLAB TEST BENCH
% FIR_TESTER
function [iport,tnext] = FIR_TESTER (oport, tnow, portinfo)
persistent ud;
%Create a struct to store persistent user data
tnext = [];
%initialize tnext to null
iport = struct(); %initialize iport to null
if(nargin ==3) %First call
ud.call_count = 0;ud.tb_clk = 0;
ud.X = zeros(1,10);
ud.Y = zeros(1,10);
tnext = tnow+100e-9;
iport.rst = '1';
iport.clk = '0';
iport.x = dec2bin(0,8);
else
iport.rst = '0';
if ud.call_count < 50
tnext = tnow+100e-9;
if ud.tb_clk == 0
iport.clk = '1';
ud.tb_clk = 1;
else
iport.clk = '0';
ud.tb_clk = 0;
ud.call_count = ud.call_count + 1;
x = 125 * sin(ud.call_count * 3* pi/8);
%x= 100;
iport.x = dec2mvl(x,8);
ud.X(ud.call_count)=x;
%op = bin2dec(oport.y')/256;
op = bin2dec(oport.y');
b = 2^length(oport.y);
if oport.y(1) == '1'
op = op - 2^length(oport.y);
end
ud.Y(ud.call_count)= op;
end
else
subplot(2,1,1);plot(ud.X);subplot(2,1,2);plot(ud.Y);
disp('Over');
end
end

SIMULINK and MODELSIM


ADDER example:
Creating simulink model:

In this example, we will embed the previously created adder block in a


simulink model. The model will be created in the adder folder. Invoke
simulink from the MATLAB command prompt by typing the command
simulink or by clicking the simulink icon. In the simulink library window,
select File>New>Model. Select Link for Modelsim library in the left pane
and HDL cosimulation block from the right pane. Drag it to the center of
the new model, leaving space for the stimulus generator on the left side and
scope on the right. Enter the simulation stop time as 40 s. Double click on
the block to invoke the Function Block Parameters dialog box as shown
below. This box has tabs for configuring Ports, Clocks, Timescales, connection
and Tcl. By default, the Ports tab is selected. It shows one input port named
sig1 and two input ports named sig1 and sig2. Delete all of them one by one
by selecting the line and pressing the Delete button to the right. Add a new
line by pressing the New button. In the edit box under title Hull HDL name,
enter /adder/a and choose I/O mode as Input. Press the Update button
situated in the bottom right corner. If the button is not visible, then enlarge
the window. In a similar manner, make entries for inputs b, cin and outputs
sum, cout. For the output ports, enter sample time as 1, indicating that the

output is updated in every cycle. The dialog box should now look like this.
Press OK

Since we are not using clock, dont use the clocks tab. Select Timescales tab.
Make 1 second in simulink correspond to 10 ticks in Modelsim. By default,
Modelsim tick is configured for 1 ns. Thus 1 step of simulink running (40s)
advances the Modelsim simulator by 400 ns. Press the connection tab and
observe that the connection method is shared memory. Dont use the Tcl tab.
Press OK. We need to add stimulus generator and scope blocks. We want to
show the input and output signal in MATLAB as well as Modelsim. The model
should look like this when completed.

Now
let
us
create a stimulus generator block. A convenient way to apply exhaustive
input combinations to the inputs a, b, cin is to create a 3-bit counter and
apply its individual bits to the three inputs. We will create the stimulus
generator as a subsystem. In the simulink library browser, in tab simulink,
select Ports & subsystems. In the right pane, select configurable
subsystem and drag it to the left of the HDL cosimulation block. Click on its
caption and change it to 3 bit counter. Double click on it to open its edit
window. When completed, it should look like this.

In the initial state, it has an input port connected to an output port. Delete
the input port and the connecting link. Add two more output ports from the
library simulink> Ports and subsystems> Out1.
In the simulink library browser, select simulink> sources> counter limited
and drag it to the 3-bit counter window. Double click on it to open its block
parameters window and set the upper limit to 7, i.e. it cycles through 0-7.
In the simulink library browser, select Communication blockset> Utility
blocks> Integer to bit converter and drag it to the right of the counter.
Double click it to open its parameters dialog and set the number of bits per
integer to 4. (One extra bit is required for proper operation of the index
vector blocks.) Also, set its output data type as Boolean. The output of the
Integer to bit converter block is a bit vector. To pick up its individual bits, we
use three index vector blocks. Select them from the library by clicking
simulink> signal routing> index vector. Place three constant blocks from the
simulink> commonly used blocks library to the left of the index vector blocks
and connect them to the select inputs. Double click on the constant blocks
and set their values as 1, 2, 3. Note that the index 1 corresponds to the MSB
and the index 3 corresponds to the LSB. Connect the output of the Integer to
bit converter block to all the index vector blocks. Connect the outputs of the
index vector blocks to the corresponding output ports. Save the design and
return to the main model. Add a scope from simulink> sinks library. Double
click on it to invoke its display window. In this window, click on the parameter
tool button (Second from left) and set the number of axes to 5. The scope
block in the model now shows 5 inputs. Connect them to a, b, cin, sum and
cout. Save the model as adder_simulink.
Invoking Modelsim
The adder entity has been already developed in the previous exercise. As in
previous exercise, on MATLAB prompt, type:
Hdldaemon
The system should respond with
HDLDaemon shared memory server is running with 0 connections
Now type
vsim
This invokes Modelsim. In the Modelsim command window, type
vsimulink adder
The adder entity gets loaded. Add all signals in the design to the waveform
viewer.
Running simulation
In MATLAB test bench, the VHDL simulator is the master and it calls the
MATLAB callback function when programmed. The simulation is started by
clicking the run all button in the Modelsim window. In Simulink method,
Simulink is the master and it calls VHDL simulator for the evaluation of the
VHDL block. The simulation starts by clicking the run button of the simulink

model window. The simulation will run for 40 simulated seconds in simulink
and 400 ns in Modelsim. We can observe waveforms in both windows.

FIR FILTER in Simulink

Change the MATLAB current directory to c:\Modelsim_proj\FIR. We have


already saved the VHDL code for FIR filter in this directory.
Start simulink library browser either by typing simulink on the command
prompt or by clicking on simulink tool button. In the simulink library browser
window, click the icon for new model file. The untitled model editor window
opens up. Drag the block Link for Modelsim> HDL cosimulation to the
model editor. Click the menu simulation> configuration parameters to invoke
the configuration parameters dialog box. Select the solver tab in the left
pane. In the right pane, make following settings. Set the type as fixed step.
Set the solver to discrete (no continious states). Set the tasking mode to
single tasking. Click OK.
Double click on the HDL cosimulation block to invoke the Function Block
Parameters dialog box. By selecting the ports tab, change the port values to
look like this:

Do not change any other tabs. Press OK.


From the simulink> sources library, drag the pulse generator block to the
model editor. Double click its icon. Set its pulse type to sample based,
amplitude to 1, period to 2 and pulse width to 1 and sample time to 1. Press
OK.
From the simulink> sources library, drag the convert block to the model
editor. Double click its icon. Set its output data type mode to Boolean.
Connect pulse generator to converter and converter to CLK input of
Modelsim.
From the simulink> sources library, drag the sine wave block to the model
editor. Double click its icon. Set its sine type to sample based, amplitude to
100, samples per period to 16 and sample time to 2. Sample time should be
2 because the clock period is 2. From the simulink> sources library, drag the
converter block to the model editor. Double click its icon. Set its output data
type mode to Int8. Connect the sine wave to converter and converter to x.
For reset pulse, there is no suitable readymade block. So we will use a signal
builder block. From the simulink> sources library, drag the signal builder
block to the model editor. Double click its icon. In the signal builder window,
drag the vertical lines so that we have a high pulse of 1 sample duration.
Since this is a continuous type block, convert it to a discrete type by using a
zero hold from simulink> discrete library. Connect the signal builder to the
zero order hold and the zero order hold to RST input of Modelsim.
Add a scope from simulink> sinks library. Double click on it to invoke its
display window. In this window, click on the parameter tool button (Second
from left) and set the number of axes to 3. The scope block in the model now
shows 3 inputs. Connect them to x,y and reset. Save the model as
fir_simulink.
Running the simulation
On MATLAB prompt, first type hdldaemon, and then vsim. In the Modelsim
window, type vsimulink firfilt8. In the fir_simulink model window, click the
run button. Following results should appear.

You might also like