Professional Documents
Culture Documents
DR.S.S.Limaye
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
FULL ADDER
sum
cout
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.
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
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.
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.
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
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.