www.gusucode.com > hdlfilter 案例代码 matlab源码程序 > hdlfilter/hdlfirda.m
%% HDL Distributed Arithmetic for FIR Filters % This example illustrates how to generate HDL code for a lowpass FIR filter % with Distributed Arithmetic (DA) architecture. % Copyright 2006-2016 The MathWorks, Inc. %% Distributed Arithmetic % Distributed Arithmetic is a popular architecture for implementing % FIR filters without the use of multipliers. DA realizes the sum of % products computation required for FIR filters efficiently using LUTs, % shifters and adders. Since these operations map efficiently onto an % FPGA, DA is a favored architecture on these devices. %% Design the Filter % Use a sampling rate of 48 kHz, passband edge frequency of % 9.6 kHz and stop frequency of 12k. Set the allowable peak-to-peak % passband ripple to 1 dB and the stopband attenuation to -90 dB. % Then, design the filter using fdesign.lowpass, and create the % System object filter as a direct form FIR filter. Fs = 48e3; % Sampling Frequency in Hz Fpass = 9.6e3; % Passband Frequency in Hz Fstop = 12e3; % Stopband Frequency in Hz Apass = 1; % Passband Ripple in dB Astop = 90; % Stopband Attenuation in dB lpSpec = fdesign.lowpass( 'Fp,Fst,Ap,Ast',... Fpass, Fstop, Apass, Astop, Fs); lpFilter = design(lpSpec, 'equiripple', 'filterstructure', 'dffir',... 'SystemObject', true); %% Quantize the Filter % Since DA implements the FIR filter by serializing the input data bits, it % requires a quantized filter. Assume that 12 bit input and output word lengths % with 11 fractional bits are required (due to of fixed data path % requirements or input ADC/output DAC widths). Apply these fixed point % settings. inputDataType = numerictype(1,12,11); outputDataType = inputDataType; coeffsDataType = numerictype(1,16,16); lpFilter.FullPrecisionOverride = false; lpFilter.CoefficientsDataType = 'Custom'; lpFilter.CustomCoefficientsDataType = coeffsDataType; lpFilter.OutputDataType = 'Custom'; lpFilter.CustomOutputDataType = outputDataType; % Now check the filter response with fvtool. fvtool(lpFilter,'Fs',Fs,'Arithmetic','fixed'); %% Generate HDL Code with DA Architecture % To generate HDL Code with DA architecture, invoke the generatehdl command, % passing in a valid value to the 'DALUTPartition' property. % The 'DALUTPartition' property directs the code generator to use DA architecture, % and divides the LUT into a specified number of partitions. % The 'DALUTPartition' property specifies the number of LUT partitions, % and the number of the taps associated with each partition. % For a filter with many taps it is best to % divide the taps into a number of LUTs, with each LUT storing the sum of % coefficients for only the taps associated with it. The sum of the LUT % outputs is computed in a tree structure of adders. % % Check the filter length by getting the number of coefficients. FL = length(lpFilter.Numerator); %% % Assume that you have 8 input LUTs; calculate the value of the % DALUTPartition property such that you use as many of these LUTs as possible % per partition. dalut = [ones(1, floor(FL/8))*8, mod(FL, 8)]; %% % Generate HDL with DA architecture. By default, VHDL code is generated. % To generate Verilog code, pass in the 'TargetLanguage' property with the value % 'Verilog'. workingdir = tempname; generatehdl(lpFilter, 'DALUTPartition', dalut, ... 'TargetDirectory', workingdir, ... 'InputDataType', inputDataType); %% Convert the Filter Structure to 'Direct form symmetric' and Generate HDL % A symmetrical filter structure offers advantages in hardware, as it % halves the number of coefficients to work with. This reduces the hardware % complexity substantially. Create a new FIR filter System object 'lpSymFilter' % with a 'Direct form symmetric' structure and the same fixed point % settings. lpSymFilter = design(lpSpec, 'equiripple', 'filterstructure', 'dfsymfir',... 'SystemObject', true); lpSymFilter.FullPrecisionOverride = false; lpSymFilter.CoefficientsDataType = 'Custom'; lpSymFilter.CustomCoefficientsDataType = coeffsDataType; lpSymFilter.OutputDataType = 'Custom'; lpSymFilter.CustomOutputDataType = outputDataType; % Calculate filter length FL for lpSymFilter for the purpose of calculating 'DALUTPartition' FL = ceil(length(lpSymFilter.Numerator)/2); % Generate the value for 'DALUTPartition' as done previously for lpFilter. dalut_sym = [ones(1, floor(FL/8))*8, mod(FL, 8)]; % Generate HDL code for default radix of 2 generatehdl(lpSymFilter, 'DALUTPartition', dalut_sym, ... 'TargetDirectory', workingdir, ... 'InputDataType', inputDataType); %% % Notice that a symmetrical filter takes one additional clock cycle before % the output is obtained. This is because of the carry bit that is added to % the input word length as the input data from the symmetrical taps are summed % together. The clock rate for 'lpSymFilter' is 13 times the input sample rate, % whereas for 'lpFilter' the clock rate was 12 times the input sample rate. %% DARadix % The default architecture is a Radix 2 implementation, which operates on one bit of % input data on each clock cycle. The number of clock cycles elapsed % before an output is obtained is equal to the number of bits in the input data. % Thus DA can potentially limit the throughput. To improve the throughput of DA, % you can configure DA to process multiple bits in parallel. % The 'DARadix' property is provided for this purpose. % For example, you can set 'DARadix' to 2^3 to operate on 3 bits in parallel. % For a 12 bit input word length, you can specify processing of % 1, 2, 3, 4, 6 or 12 bits at a time by specifying corresponding % 'DARadix' values of 2^1, 2^2, 2^3, 2^4, 2^6, or 2^12 respectively. %% % In selecting different 'DARadix' values, you trade off speed vs. area % within the DA architecture. The number of bits operated in parallel % determines the factor by which the clock rate needs to be increased. This % is known as folding factor. For example, the default 'DARadix of 2^1, % implying 1 bit at a time, results in a clock rate 12 times the input % sample rate or a folding factor of 12. A 'DARadix' of 2^3 results in a % clock rate only 4 times the input sample rate, but requires 3 identical % sets of LUTs, one for each bit being processed in parallel. %% Information Regarding DA Architecture % As explained in previous section, DA architecture presents a lot of % options both in terms of LUT sizes and the folding factor. You can use % hdlfilterdainfo function to get information regarding various filter % lengths based on the value of coefficients. This function also displays % two other tables, one for all possible values of DARadix property with % corresponding folding factors. The second table displays details of % LUT sets with the corresponding values of DALUTPartition property. hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType); %% % You can use optional properties for LUT and folding factors to % display specific information. You can choose one of the two LUT % properties, 'LUTInputs' or 'DALUTPartition' to display all the folding % factor options available for the specific LUT inputs. hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'LUTInputs', 4); %% % You can also choose one of the two folding factor related properties, % 'FoldingFactor' or 'DARadix' to display all the LUT options for the % specific folding factor. hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'Foldingfactor', 6); %% % Notice that LUT details indicate a factor by which the LUT sets need to be % replicated to achieve the corresponding folding factor. Also, total LUT % size is calculated with above factor. %% % You can use output arguments to return the values of DALUTPartition and % DARadix for a specific configuration and use it with generatehdl command. % Let us assume that you can intend to raise the clock rate by 4 times the % sample rate and want to use 6 input LUTs. You can verify that the LUT % details meet your area requirements. hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'FoldingFactor', 4, ... 'LUTInputs', 6); %% % Now generate HDL with the above constraints by first storing the required % values of DALUTPartition and DARadix in variables by using the output % arguments to the hdlfilterdainfo function. You can then invoke % generatehdl command using these variables. [dalut, dr] = hdlfilterdainfo(lpFilter, 'InputDataType', inputDataType, ... 'FoldingFactor', 4, ... 'LUTInputs', 6); generatehdl(lpFilter, 'InputDataType', inputDataType, ... 'DALUTPartition', dalut, ... 'DAradix', dr, ... 'TargetDirectory', workingdir); %% Conclusion % You designed a lowpass direct form FIR filter to meet the % given specification. You then quantized and checked your design. You % generated VHDL code for DA with various radices and explored speed vs. area % trade-offs within DA by replicating LUTs and operating on multiple bits in % parallel. % % You can generate a test bench with a standard stimulus and/or your own defined % stimulus, and use an HDL Simulator to verify the generated HDL code for % DA architectures. You can use a synthesis tool to compare % the area and speed of these architectures.