Main Content

Verify Digital Up-Converter Using FPGA-in-the-Loop

This example shows you how to verify a digital up-converter design generated with Filter Design HDL Coder™ using FPGA-in-the-Loop simulation.

Requirements

Tools required for this example:

  • FPGA design software

  • One of the supported FPGA development boards and accessories (the ML403 board is not supported for this example). For more information about supported hardware, see Supported FPGA Devices for FPGA Verification.

  • For connection using Ethernet: Gigabit Ethernet Adapter installed on host computer, Gigabit Ethernet crossover cable

  • For connection using JTAG: JTAG cable with USB Blaster I or II, USB Blaster driver

  • For connection using PCI Express®: FPGA board installed into PCI Express slot of host computer.

Create Cascade Filter for DUC

A digital up-converter (DUC) is a digital circuit that converts a digital baseband signal to a passband signal. A DUC is composed of three filtering stages; each stage filters the input signal with a lowpass interpolating filter, followed by a sample rate change. In this example, the DUC is a cascade of two FIR interpolation filters and a CIC interpolation filter, as described in the example HDL Digital Up-Converter (DUC).

1. Create the two FIR and CIC filters.

pfir = [0.0007    0.0021   -0.0002   -0.0025   -0.0027    0.0013    0.0049    0.0032 ...
     -0.0034   -0.0074   -0.0031    0.0060    0.0099    0.0029   -0.0089   -0.0129 ...
     -0.0032    0.0124    0.0177    0.0040   -0.0182   -0.0255   -0.0047    0.0287 ...
      0.0390    0.0049   -0.0509   -0.0699   -0.0046    0.1349    0.2776    0.3378 ...
      0.2776    0.1349   -0.0046   -0.0699   -0.0509    0.0049    0.0390    0.0287 ...
     -0.0047   -0.0255   -0.0182    0.0040    0.0177    0.0124   -0.0032   -0.0129 ...
     -0.0089    0.0029    0.0099    0.0060   -0.0031   -0.0074   -0.0034    0.0032 ...
      0.0049    0.0013   -0.0027   -0.0025   -0.0002    0.0021    0.0007 ];
hpfir = dsp.FIRInterpolator(2, pfir);
hpfir.FullPrecisionOverride = false;
hpfir.CoefficientsDataType = 'Custom';
hpfir.CustomCoefficientsDataType = numerictype([],16);
hpfir.ProductDataType = 'Custom';
hpfir.CustomProductDataType = numerictype([],31,31);
hpfir.AccumulatorDataType = 'Custom';
hpfir.CustomAccumulatorDataType = numerictype([],16,15);
hpfir.OutputDataType = 'Custom';
hpfir.CustomOutputDataType = numerictype([],16,15);
hpfir.RoundingMethod = 'Nearest';
cfir = [-0.0007   -0.0009    0.0039    0.0120    0.0063   -0.0267   -0.0592   -0.0237 ...
       0.1147    0.2895    0.3701    0.2895    0.1147   -0.0237   -0.0592   -0.0267 ...
       0.0063    0.0120    0.0039   -0.0009   -0.0007];
hcfir = dsp.FIRInterpolator(2, cfir);
hcfir.FullPrecisionOverride = false;
hcfir.CoefficientsDataType = 'Custom';
hcfir.CustomCoefficientsDataType = numerictype([],16);
hcfir.ProductDataType = 'Custom';
hcfir.CustomProductDataType = numerictype([],31,31);
hcfir.AccumulatorDataType = 'Custom';
hcfir.CustomAccumulatorDataType = numerictype([],16,15);
hcfir.OutputDataType = 'Custom';
hcfir.CustomOutputDataType = numerictype([],16,15);
hcfir.RoundingMethod = 'Nearest';
hcic = dsp.CICInterpolator(32, 1, 5);
hcic.FixedPointDataType = 'Minimum section word lengths';
hcic.OutputWordLength = 20;

2. Create a cascade filter using these filters.

hduc = dsp.FilterCascade(hpfir, hcfir, hcic);

The frequency response of the cascade filter is shown in the following figure.

filterAnalyzer(hduc,'Arithmetic','fixed');

Generate HDL Code

When the cascade filter is ready, generate HDL code for the DUC using the Filter Design HDL Coder function generatehdl, with the property 'AddPipelineRegisters' set to 'on'.

generatehdl(hduc, 'Name', 'hdlduc', 'AddPipelineRegisters', 'on', 'InputDataType', numerictype(1,16,15));

This option inserts pipeline registers between filter stages, and allows the generated filter to be synthesized at a higher clock frequency.

If you do not have Filter Design HDL Coder, you can use the pre-generated HDL files in the current directory.

Set Up FPGA Design Software

Before using FPGA-in-the-Loop, make sure your system environment is set up properly for accessing FPGA design software. You can use the function hdlsetuptoolpath to add FPGA design software to the system path for the current MATLAB session.

Configure and Build FPGA-in-the-Loop

The FIL Wizard guides you in configuring settings necessary for building FPGA-in-the-Loop. Launch the wizard with the following command:

filWizard

1. In Hardware Options, select the FPGA development board connected to your host computer. If necessary, you can also customize the Board IP and MAC Address under Advanced Options. Click *Next" to continue.

2. In Source Files, add the following generated HDL files for the DUC to the source file table using Browse.

hdlduc.vhd
hdlduc_stage1.vhd
hdlduc_stage2.vhd
hdlduc_stage3.vhd

Select the top-level checkbox next to hdlduc.vhd. Click *Next" to continue.

3. In DUT I/O Ports, the input and output port information, such as port name, direction, width and port type are automatically generated from the HDL file. Port types, such as Clock and Data, are generated based on port names; you may change the selection as necessary. For this example, the generated port types are correct, and you can click Next.

4. In Build Options, specify the folder for FIL output files. You can use the default value for this example. Click Build. Clicking Build causes the FIL Wizard to generate all the necessary files for FPGA-in-the-Loop simulation and perform the following actions:

  • Generates a FIL block in a new Simulink® model

  • Opens a command-line window to compile the FPGA project and generate the FPGA programming file

The FPGA project compilation process takes several minutes. When the process is finished, you are prompted to close the command-line window. Close this window now.

Configure FIL Block

To prepare for FPGA-in-the-Loop simulation, follow the steps below to configure the FIL block.

1. Open the Open Model button to open the testbench model and copy the generated FIL block into the model.

2. Double-click the FIL block to open the block mask. Click Load to program the FPGA with the generated programming file.

3. Under Runtime Options, change Overclocking factor to 128. This specifies that an input value is sampled 128 times by the FPGA clock before the input changes value.

4. On the FIL block mask, click on the Signal Attributes tab. Change the data type for filter_out to fixdt(1,20,-1) to match the data type of the behavioral filter block.

5. Click OK to close the block mask.

Verify Generated Filter

In this example, the generated filter running on FPGA is compared to a behavioral filter block. Delays are added to the output of the behavioral filter to match the HDL latency of the generated filter.

Run simulation. Observe the output waveforms from the behavioral filter block, the FIL block, and the error margin. Because the behavioral filter block does not have pipeline registers, there are small differences between the behavioral filter block output and the FIL block output. These errors are within the error margin.

This concludes the example.