Documentation

HDL Sample Rate Conversion Using Farrow Filters

This example shows how you can design and implement hardware efficient Sample Rate Converters for an arbitrary factor using polynomial-based (Farrow) structures. Sample Rate Conversion (SRC) between arbitrary factors is useful for many applications including symbol synchronizations in Digital receivers, speech coding, audio sampling, etc. For the purpose of this example, we will show how you can convert the sampling rate of an audio signal from 8kHz to 44.1 kHz.

Overview

In order to resample the incoming signal from 8 kHz to 44.1 kHz, we will have to essentially interpolate by 441 and decimate by 80. This SRC can be implemented using polyphase structures. However using the polyphase structures for any arbitrary factor usually results in large number of coefficients leading to a lot of memory requirement and area. In this example, we will show you how SRC can be efficiently implemented by a mix of polyphase and farrow filter structures.

Design of Interpolating Stages

First, we interpolate the original 8 kHz signal by a factor of 4 using a cascade of FIR halfband filters. This will result in an intermediate signal of 32 kHz. Polyphase filters are particularly well adapted for interpolation or decimation by an integer factor and for fractional rate conversions when the interpolation and the decimation factors are low. For the specifications as below, let us design the interpolating stages.

TW  = .125; % Transition Width
Astop = 50; % Minimum stopband attenuation
cascadeSpec  = fdesign.interpolator(4, 'Nyquist', 4, 'TW,Ast', TW, Astop);
FIRCascade   = design(cascadeSpec, 'multistage', ...
    'HalfbandDesignMethod', 'equiripple', 'SystemObject', true);

Design of Farrow Filter

The signal output from the above interpolating stages need to be further interpolated from 32 kHz to 44.1 kHz. This will be done by a Farrow Rate Converter filter designed with a cubic Lagrange polynomial.

FsInp = 32e3;   % Input sample rate
FsOut = 44.1e3; % Output sample rate
TOL   = 0;      % Output rate tolerance
NP    = 3;      % Polynomial order

farrowFilter = dsp.FarrowRateConverter(FsInp, FsOut, TOL, NP);

To prevent the datapath from growing to very large word lengths, quantize the filter stages such that the inputs to each stage are 12 bits and the outputs are 12 bits.

cascadeOutNT = numerictype([],12,11);
FIRCascade.Stage1.FullPrecisionOverride = false;
FIRCascade.Stage1.OutputDataType        = 'Custom';
FIRCascade.Stage1.CustomOutputDataType  = cascadeOutNT;
FIRCascade.Stage2.FullPrecisionOverride = false;
FIRCascade.Stage2.OutputDataType        = 'Custom';
FIRCascade.Stage2.CustomOutputDataType  = cascadeOutNT;

farrowOutNT = numerictype(1,12,11);
farrowFilter.OutputDataType = farrowOutNT;

Cascade of Complete SRC and Magnitude Response

The overall filter is simply obtained by creating a cascade of the interpolating stages and the farrow filter.

sampleRateConverter = cascade(FIRCascade.Stage1, FIRCascade.Stage2, farrowFilter);

The magnitude response of the cascaded SRC filter shows that it meets the 50 dB minimum stopband attenuation specification.

Fs = 32e3*441;                % The highest clock rate is 14.112 MHz
W = linspace(0,44.1e3,2048);  % Define the frequency range analysis

fvt = fvtool(sampleRateConverter,'FrequencyRange','Specify freq. vector', ...
    'FrequencyVector',W,'Fs',Fs, ...
    'NormalizeMagnitudeto1','on', 'Color', 'white');

legend(fvt,'Cascade of FIR and Farrow Rate Converter Response',...
    'Location','NorthEast')

Generate HDL & Testbench

You can now generate VHDL code for the cascaded SRC using the generatehdl command. You can also generate the VHDL testbench by passing the 'TestBenchUserStimulus' and 'GenerateHDLTestbench' properties into the generatehdl command. The VHDL code can be simulated in any HDL simulator to verify the results.

workingdir = tempname;
inpFrameSz = 640;
tVector    = linspace(0.005, 7.5, inpFrameSz);
srcTBStim  = (chirp(tVector, 0, 1, 150))';

generatehdl(sampleRateConverter, ...
    'TargetDirectory',       workingdir, ...
    'InputDataType',         numerictype(1,12,11), ...
    'OptimizeForHDL',        'on', ...
    'GenerateHDLTestbench',  'on', ...
    'TestBenchUserStimulus', srcTBStim, ...
    'ErrorMargin',           2);
### Starting VHDL code generation process for filter: casfilt
### Cascade stage # 1
### Starting VHDL code generation process for filter: casfilt_stage1
### Generating: <a href="matlab:edit('/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_stage1.vhd')">/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_stage1.vhd</a>
### Starting generation of casfilt_stage1 VHDL entity
### Starting generation of casfilt_stage1 VHDL architecture
### Successful completion of VHDL code generation process for filter: casfilt_stage1
### Cascade stage # 2
### Starting VHDL code generation process for filter: casfilt_stage2
### Generating: <a href="matlab:edit('/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_stage2.vhd')">/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_stage2.vhd</a>
### Starting generation of casfilt_stage2 VHDL entity
### Starting generation of casfilt_stage2 VHDL architecture
### Successful completion of VHDL code generation process for filter: casfilt_stage2
### Cascade stage # 3
### Starting VHDL code generation process for filter: casfilt_stage3
### Generating: <a href="matlab:edit('/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_stage3.vhd')">/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_stage3.vhd</a>
### Starting generation of casfilt_stage3 VHDL entity
### Starting generation of casfilt_stage3 VHDL architecture
### Successful completion of VHDL code generation process for filter: casfilt_stage3
### Generating: <a href="matlab:edit('/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt.vhd')">/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt.vhd</a>
### Starting generation of casfilt VHDL entity
### Starting generation of casfilt VHDL architecture
### Successful completion of VHDL code generation process for filter: casfilt
### HDL latency is 1325 samples
### Starting generation of VHDL Test Bench.
### Generating input stimulus
### Done generating input stimulus; length 640 samples.
Warning: HDL optimization may cause small numeric differences that will be
flagged as errors when running this testbench. 
Warning: The input stimulus length 640 is less than 27342, length of the
impulse response of the filter. Consider adding more input samples. 
### Generating Test bench: <a href="matlab:edit('/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_tb.vhd')">/tmp/Bdoc17b_716109_27120/publish_examples2/tpbb7d36c2_f396_478a_9c66_20ad52bf2ba5/casfilt_tb.vhd</a>
### Creating stimulus vectors ...
### Done generating VHDL Test Bench.

ModelSim® Simulation Results

The following display shows the ModelSim® HDL simulator results after running the VHDL testbench.

Conclusion

In this example, we showed how you can design a sample rate converter using a farrow structure. We also showed you how you can analyze the response, quantize it, and generate bit-accurate VHDL code and testbench.

Was this topic helpful?