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.
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.
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);
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;
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')
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: /tmp/BR2020bd_1459859_105924/mlx_to_docbook1/tp3ceb7abd_7567_4f10_b086_26c7cc45bc3d/casfilt_stage1.vhd ### 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: /tmp/BR2020bd_1459859_105924/mlx_to_docbook1/tp3ceb7abd_7567_4f10_b086_26c7cc45bc3d/casfilt_stage2.vhd ### 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: /tmp/BR2020bd_1459859_105924/mlx_to_docbook1/tp3ceb7abd_7567_4f10_b086_26c7cc45bc3d/casfilt_stage3.vhd ### 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: /tmp/BR2020bd_1459859_105924/mlx_to_docbook1/tp3ceb7abd_7567_4f10_b086_26c7cc45bc3d/casfilt.vhd ### 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.
### Generating Test bench: /tmp/BR2020bd_1459859_105924/mlx_to_docbook1/tp3ceb7abd_7567_4f10_b086_26c7cc45bc3d/casfilt_tb.vhd ### Creating stimulus vectors ... ### Done generating VHDL Test Bench.
The following display shows the ModelSim® HDL simulator results after running the VHDL testbench.
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.