Implementing the Filter Component of an Oscillator in MATLAB®

This examples shows how MATLAB® can be used to implement a filter component used in an HDL model. The example compiles a VHDL/Verilog oscillator, defines a filter component that is modeled using MATLAB, and runs the HDL simulation. This example requires a temporary directory to generate a working ModelSim VHDL or Incisive Verilog project. After creating the HDL project, this example starts the HDL simulator (this requires access to ModelSim/Incisive from the command line). This example uses shared memory to complete the link and therefore requires the HDL simulator to be on the same computer as MATLAB. Once the project is compiled, the simulation can be run from within ModelSim/Incisive.

In this example, a VHDL oscillator in ModelSim and a Verilog oscillator in Incisive have been designed and our job is to find a cleanup filter for the oscillator that meets our needs.

The first FIR filter is a 31st order (32-tap) filter with no oversampling. The second filter is a 127th order (128-tap) filter with 4X oversampling. The third filter is a 255th order (256-tap) filter with 8X oversampling. All three filters share the same delay line and the oversampling is implemented using the polyphase technique.

The file simple_osc.vhd / simple_osc.v contains the simple oscillator designed in VHDL/Verilog.

The file osc_filter.vhd / osc_filter.v contains the MATLAB component that we are modeling. It contains an entity with an empty architecture. The matlabcp command drives the VHDL/Verilog outputs and checks the VHDL/Verilog inputs of the instance created from this entity.

The file osc_top.vhd / osc_top.v contains the top-level wiring between the oscillator and the MATLAB component.

The file oscfilter.m / oscfilter_incisive.m contains the actual component behavioral model.

For ModelSim:

You can also define variables "UsrTclCmds" and "RunMode" before calling the MATLAB program with tcl commands and ModelSim's runmode. Examples:

UsrTclCmds = {'run 100000'}; RunMode = 'Batch' or 'CLI' or 'GUI';

srcfile1 = fullfile(matlabroot,'toolbox','edalink','extensions','modelsim','modelsimdemos','vhdl','osc','simple_osc.vhd');
srcfile2 = fullfile(matlabroot,'toolbox','edalink','extensions','modelsim','modelsimdemos','vhdl','osc','osc_filter.vhd');
srcfile3 = fullfile(matlabroot,'toolbox','edalink','extensions','modelsim','modelsimdemos','vhdl','osc','osc_top.vhd');

ModelSim uses UNIX® style directory format which uses forward slashes ("/") instead of backslashes ("\").

unixsrcfile1 = ['"' strrep(srcfile1,'\','/') '"'];
unixsrcfile2 = ['"' strrep(srcfile2,'\','/') '"'];
unixsrcfile3 = ['"' strrep(srcfile3,'\','/') '"'];

For Incisive:

srcfile1 = fullfile(matlabroot,'toolbox','edalink','extensions','incisive','incisivedemos','Oscillator','simple_osc.v');
srcfile2 = fullfile(matlabroot,'toolbox','edalink','extensions','incisive','incisivedemos','Oscillator','osc_filter.v');
srcfile3 = fullfile(matlabroot,'toolbox','edalink','extensions','incisive','incisivedemos','Oscillator','osc_top.v');

Create Project Directory

We create a temporary working directory in which the project will be generated.

For ModelSim:

if strcmp(computer,'PCWIN'),
    projdir = tempdir;  % Change to writable directory of your choosing
else
    projdir = tempname;
    if ~exist(projdir,'dir')
        mkdir(tempdir,strrep(projdir,tempdir,''));
    end
end
unixprojdir = strrep(projdir,'\','/');

For Incisive:

projdir = tempname;
warnstatus = warning('off','MATLAB:MKDIR:DirectoryExists');
mkdir(projdir);
warning(warnstatus);

Start the MATLAB Server

We first start the MATLAB server, hdldaemon, such that it uses shared memory communication. We first check if the server is already running using shared memory. If hdldaemon is not running, it is started. Or, if it is running using TCP/IP socket communication, it is shut down and restarted using shared memory communication.

dstatus = hdldaemon('status');
% Use shared memory
if isempty(dstatus)
    % not running - start it
    dstatus = hdldaemon;    % tell user what's happening
elseif strcmp(dstatus.comm,'shared memory')
    % already running
    % user knows what's happening from previous hdldaemon('status')
elseif strcmp(dstatus.comm,'sockets')
    % running with different comm - stop and restart it
    disp('Shutting down HDLDaemon to restart it with shared memory');
    hdldaemon('kill');
    dstatus = hdldaemon;
else
    error(message('HDLLink:modsimosc:UnexpectedDaemonStatus'));
end

Specify Tcl Commands

Next we specify the Tcl commands to execute in the HDL simulator before the simulation is run.

ModelSim:

tclcmd = {  ['cd ',unixprojdir],...
            'vlib work',... %create library (if necessary)
           ['vcom -performdefaultbinding ' unixsrcfile1],...
           ['vcom -performdefaultbinding ' unixsrcfile2],...
           ['vcom -performdefaultbinding ' unixsrcfile3],...
            'vsimmatlab  work.osc_top ',...
            'matlabcp u_osc_filter -mfunc oscfilter',...
            'add wave sim:/osc_top/clk',...
            'add wave sim:/osc_top/clk_enable',...
            'add wave sim:/osc_top/reset',...
           ['add wave -height 100 -radix decimal -format analog-step -scale 0.001 -offset 50000 ',...
            'sim:/osc_top/osc_out'],...
           ['add wave -height 100 -radix decimal -format analog-step -scale 0.00003125 -offset 50000 ',...
            'sim:/osc_top/filter1x_out'],...
           ['add wave -height 100 -radix decimal -format analog-step -scale 0.00003125 -offset 50000 ',...
            'sim:/osc_top/filter4x_out'],...
           ['add wave -height 100 -radix decimal -format analog-step -scale 0.00003125 -offset 50000 ',...
            'sim:/osc_top/filter8x_out'],...
            'force sim:/osc_top/clk_enable 1 0',...
            'force sim:/osc_top/reset 1 0, 0 120 ns',...
            'force sim:/osc_top/clk 1 0 ns, 0 40 ns -r 80ns',...
            };
% Add "if any" User tcl commands at the end
if exist('UsrTclCmds','var')
    tclcmd(end+1) = UsrTclCmds;
end

Incisive:

tclcmd = {  ['cd ',projdir],...
           ['exec ncvlog -64bit ' srcfile1],...
           ['exec ncvlog -64bit ' srcfile2],...
           ['exec ncvlog -64bit ' srcfile3],...
           'exec ncelab -64bit -access +wc osc_top',...
            ['hdlsimmatlab -gui  osc_top ', ...
           ' -input "{@matlabcp osc_top.u_osc_filter -mfunc oscfilter_incisive}"',...
           ' -input "{@force osc_top.clk_enable 1 -after 0ns}"',...
           ' -input "{@force osc_top.reset 0 -after 0ns 1 -after 40ns 0 -after 120ns}"',...
           ' -input "{@force osc_top.clk 1 -after 0ns 0 -after 40ns -repeat 80ns}"',...
           ' -input "{@simvision  {set w \[waveform new\]}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals osc_top.clk_enable}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals osc_top.clk}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals osc_top.reset}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals signed(osc_top.osc_out)}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals signed(osc_top.filter1x_out)}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals signed(osc_top.filter4x_out)}}"',...
           ' -input "{@simvision {waveform add -using \$w -signals signed(osc_top.filter8x_out)}}"',...
           ' -input "{@simvision {waveform format -using \$w signed(osc_top.osc_out) -trace analogSampleAndHold}}"',...
           ' -input "{@simvision {waveform format -using \$w signed(osc_top.filter1x_out) -trace analogSampleAndHold}}"',...
           ' -input "{@simvision {waveform format -using \$w signed(osc_top.filter4x_out) -trace analogSampleAndHold}}"',...
           ' -input "{@simvision {waveform format -using \$w signed(osc_top.filter8x_out) -trace analogSampleAndHold}}"',...
           ' -input "{@simvision {waveform axis range -min -50000 -max 50000 -using \$w signed(osc_top.osc_out)}}"',...
           ' -input "{@simvision {waveform axis range -min -1.5e6 -max 1.5e6 -using \$w signed(osc_top.filter1x_out)}}"',...
           ' -input "{@simvision {waveform axis range -min -1.5e6 -max 1.5e6 -using \$w signed(osc_top.filter4x_out)}}"',...
           ' -input "{@simvision {waveform axis range -min -1.5e6 -max 1.5e6 -using \$w signed(osc_top.filter8x_out)}}"'
           ]};

Start the HDL Simulator

Now we start the HDL simulator via vsim (in case of ModelSim) or nclaunch (in case of Incisive) command. The 'tclstart' property causes the specified Tcl commands to be run at startup. After launching the simulator, to run the simulation, use the run command, specifying the appropriate simulation time. For example type run 10000 ns in ModelSim or 'run 10000' in Incisive console. we can also specify RunMode='Batch' or 'CLI' or 'GUI' before running this example. If unspecified the default run mode is 'GUI'.

ModelSim:

if exist('RunMode','var')
    vsim('tclstart',tclcmd,'runmode',RunMode);
else
    vsim('tclstart',tclcmd);
end

Incisive:

nclaunch('tclstart',tclcmd);

Now check results in the ModelSim/Incisive plot window. You will see the non-oversampled filter does little good, but the 4X and 8X oversampled filters look much better.

This concludes this example.

Be sure to quit the HDL simulator once you are done with this example as each time the example is run, a new HDL simulator is started.