FIR Decimation for FPGA

This example shows how to decimate streaming samples using a hardware-friendly polyphase FIR filter. It also shows the differences between the dsp.FIRDecimator object and the hardware-friendly streaming interface of the FIR Decimation HDL Optimized block.

Generate an input sine wave in MATLAB®. The example model imports this signal from the MATLAB workspace. Choose a decimation factor and the input vector size for the HDL-optimized block.

T = 512;
waveGen = dsp.SineWave(0.9,100,0,'SamplesPerFrame',T);
dataIn = fi(waveGen()+0.05,1,16,14);

inputVecSize=4;
decimFactor=8;

The example model imports the input signal from the MATLAB workspace and applies it as vectors to the FIR Decimation HDL Optimized block. The model returns the output from the block to the MATLAB workspace for comparison.

The FIR Decimation HDL Optimized block applies samples to the filter in a different phase than the dsp.FIRDecimator object. To match the numerical behavior, apply decimFactor - 1 zeros to the FIR Decimation HDL Optimized block before the start of the data samples.

dataInHDL = [zeros(decimFactor-1,1);dataIn];

modelName = 'FIRDecimHDL';
open_system(modelName);
set_param(modelName,'SimulationCommand','Update');

The FIR Decimation HDL Optimized block accepts a vector of inputVecSize-by-1 samples and returns scalar output. The block performs single-rate processing and indicates valid samples in the output signal by setting the output valid signal to 1. The Simulink sample time is inputVecSize for the whole model. The block sets the output valid signal to 1 every decimFactor/inputVecSize samples.

out = sim('FIRDecimHDL');

Create a dsp.FIRDecimator System object™ and generate reference data to compare against the HDL model output. This example uses the default filter coefficients, which are the same for the block and the object. The object can accept any input vector size that is a multiple of the decimation factor, so you can calculate the output with one call to the object. If you change the decimation factor to a value that is not a factor of T, you must also adjust the value of T (size of dataIn).

The block and the object are both configured to use full-precision internal data types. The object computes a different output data type in this mode. This difference means that the output might not match if the internal values saturate the data types.

decimRef = dsp.FIRDecimator(decimFactor);
refDataOut = decimRef(dataIn);

For the output of the FIR Decimation HDL Optimized block, select data samples where the output valid signal was 1, and compare them with the samples returned from the dsp.FIRDecimator object.

hdlVec = out.dataOut(out.validOut);
refVec = refDataOut(1:size(hdlVec,1));
errVec = hdlVec - refVec;
maxErr = max(abs(errVec));
fprintf('\nFIR decimator versus reference: Maximum error out of %d values is %d\n',length(hdlVec),maxErr);
FIR decimator versus reference: Maximum error out of 54 values is 0

See Also

Blocks