Generate HDL Code for High Throughput Channelizer
Generate HDL code for high throughput (Gigasamples per second, GSPS) Channelizer using Polyphase Filter Bank technique.
High speed signal processing is a requirement for applications such as radar, broadband wireless and backhaul.
Modern ADCs are capable of sampling signals at sample rates up to several Gigasamples per second. But the clock speeds for the fastest FPGA fall short of this sample rate. FPGAs typically run at hundreds of MHz. An approach to perform GSPS processing on an FPGA is to move from scalar processing to vector processing and process multiple samples at the same time at a much lower clock rate. Many modern FPGAs support the JESD204B standard interface that accepts scalar input at GHz clock rate and produces a vector of samples at a lower clock rate.
In this example we show how to design a signal processing application for GSPS throughput in Simulink. Input data is vectorized through a JESD204B interface and available at a lower clock rate in the FPGA. The model is a Polyphase Filter Bank which consists of a filter and an FFT that processes 16 samples at a time. The Polyphase Filter Bank technique is used to minimize the FFT's inaccuracy due to leakage and scalloping loss. See High resolution spectral analysis for more information about the Polyphase Filter Bank. In the first part of the example, a Polyphase Filter Bank with 4 tap filter is implemented. In the second part of the example, Channelizer HDL Optimized is used with 12-tap filter. Channelizer HDL Optimized uses the Polyphase Filter Bank technique.
Contents
Prerequisites
An HDL Coder™ license is required to generate HDL for this example.
Polyphase Filter Bank
Enter the following commands to open the example model:
modelname = 'PolyphaseFilterBankHDLExample_4tap';
open_system(modelname);
Set up the Model
The InitFcn callback(Model Properties > Callbacks > InitFcn) sets up the model. In this example, a 512-point FFT with a four tap filter for each band is used. Use the dsp.Channelizer object to generate the coefficients:
FFTLength = 512; h = dsp.Channelizer; h.NumTapsPerBand = 4; h.NumFrequencyBands = FFTLength; h.StopbandAttenuation = 60;
The polyphase method of the Channelizer object generates a 512-by-4 matrix. Each row represents the coefficients for each band. The coefficients are cast into fixed-point with the same word length as the input signal.
coef =fi(polyphase(h), 1, 15, 14, 'RoundingMethod', 'Convergent');
The algorithm requires 512 filters (one filter for each band). For a vector input of 16 samples we can reuse 16 filters, 32 times.
InVect = 16; ReuseFactor = FFTLength/InVect;
To synthesize the filter to a higher clock rate, we pipeline the multiplier and the coefficient bank. These values are explained in "Optimized Hardware Considerations".
Multiplication_PipeLine = 2; CoefBank_PipeLine = 1;
Data Source
The input data consists of two sine waves, 200 KHz and 250 KHz.
Simulation Results
To visualize the spectrum result run the following commands:
open_system('PolyphaseFilterBankHDLExample_4tap/FFT Spectrum Viewer/Power Spectrum viewer (FFT)'); open_system('PolyphaseFilterBankHDLExample_4tap/PFB Spectrum Viewer/Power Spectrum viewer (PFB)'); % Enter the following command to run the example model: sim(modelname);
The Polyphase Filter Bank (PFB) Power Spectrum Viewer shows the improvement in the power spectrum and minimization of frequency leakage and scalloping. By comparing the two spectrums, and zooming in between 100 KHz and 300 KHz, observe that the Polyphase Filter Bank has fewer peaks over -40 dB than the classic FFT.
Optimized Hardware Considerations
- Data type : The data word length affects both the accuracy of the result and the resources used in the hardware. For this example we design the filter at full precision. With an input data type of fixdt(1,15,13), the output is fixdt(1,18,17). Note that the absolute values of the filter coefficients are all smaller than 1 so the data doesn't grow after each multiplication, and we need to add one bit for each addition. To keep the accuracy in the FFT, we need to grow one bit for each stage. This makes the twiddle factor multiplication bigger at each stage. For many FPGAs it is desirable to keep multiplication size smaller than 18x18. Since a 512 point FFT has 9 stages, the input of the FFT cannot be more than 11 bits. By exploring the filter coefficients, we observe that the first 8 binary digits of the maximum coefficient are zero, and therefore we can cast the coefficients to fixdt(1,7,14) instead of fixdt(1,15,14). Also we observe that the maximum value of the Datatype block output inside the Polyphase Filter Bank has 7 leading zeros after the binary point, and therefore we cast the filter output to fixdt(1,11,17) instead. This keeps the multiplier size inside the FFT smaller than 18X18 and saves hardware resources.
- Design for speed:
- State control block: The State Control block is used in Synchronous mode to generate hardware friendly code for the delay block with enable port.
- Minimize clock enable : The model is set to generate HDL code with the Minimize Clock Enable option turned on (In Configuration Parameters choose > HDL Code Generation > Global settings > Ports > Minimize clock enables). This option is supported when the model is single rate. Clock enable is a global signal which is not recommended for high speed designs.
- Usage of the DSP block in FPGA: In order to map multipliers into a DSP block in the FPGA, the multipliers should be pipelined. In this example we pipeline the multipliers (2 delays before and 2 delays after) by setting Multiplication_PipeLine = 2; These pipeline registers should not have a reset. Set the reset type to none for each pipeline (right-click the Delay block and select HDL Code > HDL Block Properties > Reset Type = None).
- Usage of ROM in FPGA: The Coefficient block inside the Coefficient Bank is a combinatorial block. In order to map this block into a ROM, add a register after the block. The delay length is set by CoefBank_PipeLine. Set the reset type for these delays to none (right-click the Delay block and select HDL Code > HDL Block Properties > Reset Type = None).
Generate HDL Code and Test Bench
Use a temporary directory for the generated files:
systemname = 'PolyphaseFilterBankHDLExample_4tap/PolyPhaseFilterBank'; workingdir = tempname;
You can run the following command to check the PolyphaseFilterBank subsystem for HDL code generation compatibility:
checkhdl(systemname,'TargetDirectory',workingdir);
Run the following command to generate HDL code:
makehdl(systemname,'TargetDirectory',workingdir);
Run the following command to generate the test bench:
makehdltb(systemname,'TargetDirectory',workingdir);
Synthesis Result
The design was synthesized for Xilinx Virtex 7 (xc7vx550t-ffg1158, speed grade 3) using ISE. The design achieves a clock frequency of 499.525 MHz (before place and route). At 16 samples per clock, this translates to 8 GSPS throughput. Note that this subsystem has a high number of I/O ports and it is not suitable as a standalone design targeted to the FPGA.
HDL Optimized Channelizer
To improve the frequency response, use a filter with more taps. The following model uses the Channelizer HDL Optimized block, configured with 12-tap filter improve the spectrum. Using a built-in Channelizer HDL Optimized block makes it easier to change design parameters. Enter the following commands to open the example model:
modelname = 'PolyphaseFilterBankHDLExample_HDLChannelizer';
open_system(modelname);
Set up the Model
In this example, a 512-point FFT and a 12-tap filter for each band is being used.
InVect = 16; FFTLength = 512; h = dsp.Channelizer; h.NumTapsPerBand = 12; h.NumFrequencyBands = FFTLength; h.StopbandAttenuation = 60;
The number of coefficients for the channelizer is 512 frequency bands times 12 tap per frequency band. The tf(h) method generates all the coefficients.
coef12Tap = tf(h);
Data Source
The input data consists of two sine waves, 200 KHz and 206.5 KHz. The frequencies are closer to each other than the first example to illustrate the difference between a Channelizer and a 4-tap filter in spectrum resolution.
Simulation Results
To visualize the spectrum result run the following commands:
open_system('PolyphaseFilterBankHDLExample_HDLChannelizer/PFB_4tap Spectrum Viewer/Power Spectrum viewer (PFB_4tap)'); open_system('PolyphaseFilterBankHDLExample_HDLChannelizer/Channelizer Spectrum Viewer/Power Spectrum viewer (Channelizer_12tap)'); % Enter the following command to run the example model: sim(modelname);
The Power Spectrum Viewer for Channelizer (Channelizer_12tap) shows the improvement in the power spectrum of the Polyphase Filter Bank with 12-tap filter compared to the 4-tap filter in the previous example. Compare the spectrum results for the channelizer and 4-tap Polyphase Filter Banks. Zoom in between 100 KHz and 300 KHz to observe that the Channelizer detects only two peaks while the 4-tap Polyphase Filter Bank detects more than 2 peaks. Note that the expected result is two peaks since the input signal has only two frequency components.