HDL Video Filter
This example illustrates how to generate HDL code for an ITU-R BT.601 luma filter with 8-bit input data and 10-bit output data. This filter is a low-pass filter with a -3 dB point of 3.2 MHz with a 13.5 MHz sampling frequency and a specified range for both passband ripple and stopband attenuation shown in the ITU specification. The filter coefficients were designed using the DSP System Toolbox™. This example focuses on quantization effects and generating HDL code for the System object filter.
Set up the Coefficients
Assign the previously designed filter coefficients to variable b. This is a halfband filter and, therefore, every other coefficient is zero with the exception of the coefficient at the filter midpoint, which is exactly one-half.
Check that double-precision filter design meets the ITU-R BT.601 template for passband ripple and stopband attenuation using freqz and plot the passband. The red lines show the allowed variation in the specification.
b = [0.00303332064210658, 0,... -0.00807786494715095, 0,... 0.0157597395206364, 0,... -0.028508691397868, 0,... 0.0504985344927114, 0,... -0.0977926818362618, 0,... 0.315448742029959,... 0.5,... 0.315448742029959, 0,... -0.0977926818362618, 0,... 0.0504985344927114, 0,... -0.028508691397868, 0,... 0.0157597395206364, 0,... -0.00807786494715095, 0,... 0.00303332064210658]; f = 0:100:2.75e6; H = freqz(b,1,f,13.5e6); plot(f,20*log10(abs(H))); title('HDL Video Filter Double-Precision Passband'); axis([0 2.75e6 -.8 .8]); passbandrange = {[2.75e6; 1e6; 0; 1e6; 2.75e6],... [ -0.5; -0.5; 0; 0.5; 0.5]}; line(passbandrange{:}, 'Color', 'red');
Plot the Stopband
The red line shows a "not to exceed" limit on the stopband.
f = 4e6:100:6.75e6; H = freqz(b,1,f,13.5e6); plot(f,20*log10(abs(H))); title('HDL Video Filter Double-Precision Stopband'); axis([4e6 6.75e6 -70 -35]); stopbandrange = {[4e6; 6.25e6; 6.75e6],... [-40; -55; -55]}; line(stopbandrange{:}, 'Color', 'red');
Create the Quantized Filter
Create a FIR filter System object filter with previously defined coefficients. Experiment with the coefficient word length to get the desired response for 8-bit input data and 10-bit output data.
videoFilter = dsp.FIRFilter; videoFilter.Numerator = b; videoFilter.Structure = 'Direct form symmetric'; %Try 10-bit coefficients videoFilter.CoefficientsDataType = 'Custom'; videoFilter.CustomCoefficientsDataType = numerictype(1,10);
Plot the Quantized Filter Response
Now examine the passband and stopband response of the quantized filter relative to the specification. Plot and check the quantized passband first.
The quantized design meets the passband specifications except at DC, where it misses the specification by about 0.035 dB.
f = 0:100:2.75e6; H = freqz(videoFilter,f,13.5e6,'Arithmetic','fixed'); plot(f,20*log10(abs(H))); title('HDL Video Filter Quantized Passband'); axis([0 2.75e6 -.8 .8]); line(passbandrange{:}, 'Color', 'red');
Plot the Quantized Stopband
The red lines again show a "not to exceed" limit on the stopband.
The stopband limit is violated, which indicates a problem with the quantization settings.
f = 4e6:100:6.75e6; H = freqz(videoFilter,f,13.5e6,'Arithmetic','fixed'); plot(f,20*log10(abs(H))); title('HDL Video Filter Quantized Stopband'); axis([4e6 6.75e6 -70 -35]); line(stopbandrange{:}, 'Color', 'red');
Change the Coefficient Quantizer Settings
Adding more bits to the coefficient word length enables the filter to meet the specification. Increment the word length by one and replot the stopband.
This just misses the specification at the end of the stopband. This small deviation from the specification might be acceptable if you know that some other part of your system applies a lowpass filter to this signal.
videoFilter.CustomCoefficientsDataType = numerictype(1,11); f = 4e6:100:6.75e6; H = freqz(videoFilter,f,13.5e6,'Arithmetic','fixed'); plot(f,20*log10(abs(H))); title('HDL Video Filter Quantized Stopband'); axis([4e6 6.75e6 -70 -35]); line(stopbandrange{:}, 'Color', 'red');
Set the Final Coefficient Quantizer Word Length
Add one more bit to the coefficient quantizer word length and replot the stopband. This should meet the specification.
videoFilter.CustomCoefficientsDataType = numerictype(1,12); f = 4e6:100:6.75e6; H = freqz(videoFilter,f,13.5e6,'Arithmetic','fixed'); plot(f,20*log10(abs(H))); title('HDL Video Filter Final Quantized Stopband'); axis([4e6 6.75e6 -70 -35]); line(stopbandrange{:}, 'Color', 'red');
Perform a Final Check on the Passband Response
Recheck the passband to be sure the changes have improved the problems in the response near DC. The response now passes the specification.
f = 0:100:2.75e6; H = freqz(videoFilter,f,13.5e6,'Arithmetic','fixed'); plot(f,20*log10(abs(H))); title('HDL Video Filter Final Quantized Passband'); axis([0 2.75e6 -.8 .8]); line(passbandrange{:}, 'Color', 'red');
Generate HDL Code and Test Bench from the Quantized Filter
Starting from the quantized filter, generate VHDL or Verilog code.
Create a temporary work directory. After generating the HDL (selecting VHDL in this case), open the generated VHDL file in the editor.
Generate a VHDL test bench to make sure that it matches the response in MATLAB exactly. Select the default input stimulus, which for FIR is impulse, step, ramp, chirp, and noise inputs.
To generate Verilog code and Verilog test bench instead, change value for 'TargetLanguage' property from 'VHDL' to 'Verilog'.
The warnings indicate that by selecting the symmetric structure for the filter and generating HDL, may result in smaller area or a higher clock rate.
Assume an input of 8-bit word length with 7-bit fractional bits.
workingdir = tempname; generatehdl(videoFilter, 'Name', 'hdlvideofilt', ... 'InputDataType' ,numerictype(1,8,7), ... 'TargetLanguage', 'VHDL', ... 'TargetDirectory', workingdir, ... 'GenerateHDLTestbench', 'on');
### Starting VHDL code generation process for filter: hdlvideofilt ### Generating: /tmp/Bdoc24a_2528353_289974/tpec69817c_0bde_4bb2_879c_bc276682f9a8/hdlvideofilt.vhd ### Starting generation of hdlvideofilt VHDL entity ### Starting generation of hdlvideofilt VHDL architecture ### Successful completion of VHDL code generation process for filter: hdlvideofilt ### HDL latency is 2 samples ### Starting generation of VHDL Test Bench. ### Generating input stimulus ### Done generating input stimulus; length 3261 samples. ### Generating Test bench: /tmp/Bdoc24a_2528353_289974/tpec69817c_0bde_4bb2_879c_bc276682f9a8/hdlvideofilt_tb.vhd ### Creating stimulus vectors ... ### Done generating VHDL Test Bench.
edit(fullfile(workingdir, 'hdlvideofilt.vhd'));
Plot the Test Bench Stimulus
Plot the default test bench stimulus used by the above command, using the generatetbstimulus function.
tbstim = generatetbstimulus(videoFilter,'InputDataType', numerictype(1,8,7)); plot(tbstim); title('HDL Video Filter Test Bench Stimulus');
Conclusion
You designed a double precision filter to meet the ITU-R BT.601 luma filter specification and then created a FIR filter System object that also met the specification. You generated VHDL code and a VHDL test bench that functionally verified the filter.
You can use a VHDL simulator, such as ModelSim®, to verify these results. You can also experiment with Verilog. You can use many optimizations to get smaller and faster HDL results by removing the constraint that the generated HDL be exactly true to MATLAB. When you use these optimizations, the HDL test bench can check the filter response to be within a specified error margin of the MATLAB response.