LMS 滤波器的 HDL 代码生成
此示例说明如何从实现 LMS 滤波器的 MATLAB® 设计生成 HDL 代码。该示例还说明如何设计使用此滤波器消除含噪信号的测试平台。
LMS 滤波器 MATLAB 设计
示例中使用的 MATLAB 设计是 LMS(最小均方)滤波器的实现。LMS 滤波器是一类自适应滤波器,用于识别嵌入在噪声中的 FIR 滤波器信号。MATLAB 中的 LMS 滤波器设计实现包含一个顶层函数 mlhdlc_lms_fcn,该函数计算最优滤波器系数,以减少输出信号与期望信号之间的差异。
design_name = 'mlhdlc_lms_fcn'; testbench_name = 'mlhdlc_lms_noise_canceler_tb';
查看 MATLAB 设计:
open(design_name);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MATLAB Design: Adaptive Noise Canceler algorithm using Least Mean Square % (LMS) filter implemented in MATLAB % % Key Design pattern covered in this example: % (1) Use of function calls % (2) Function inlining vs instantiation knobs available in the code % generator % (3) Use of system objects in the testbench to stream test vectors into the design %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %#codegen function [filtered_signal, y, fc] = mlhdlc_lms_fcn(input, ... desired, step_size, reset_weights) % 'input' : The signal from Exterior Mic which records the ambient noise. % 'desired': The signal from Pilot's Mic which includes % original music signal and the noise signal % 'err_sig': The difference between the 'desired' and the filtered 'input' % It represents the estimated music signal (output of this block) % % The LMS filter is trying to retrieve the original music signal('err_sig') % from Pilot's Mic by filtering the Exterior Mic's signal and using it to % cancel the noise in Pilot's Mic. The coefficients/weights of the filter % are updated(adapted) in real-time based on 'input' and 'err_sig'. % register filter coefficients persistent filter_coeff; if isempty(filter_coeff) filter_coeff = zeros(1, 40); end % Variable Filter: Call 'mtapped_delay_fcn' function on path to create % 40-step tapped delay delayed_signal = mtapped_delay_fcn(input); % Apply filter coefficients weight_applied = delayed_signal .* filter_coeff; % Call treesum function on matlab path to sum up the results filtered_signal = mtreesum_fcn(weight_applied); % Output estimated Original Signal td = desired; tf = filtered_signal; esig = td - tf; y = esig; % Update Weights: Call 'update_weight_fcn' function on MATLAB path to % calculate the new weights updated_weight = update_weight_fcn(step_size, esig, delayed_signal, ... filter_coeff, reset_weights); % update filter coefficients register filter_coeff = updated_weight; fc = filter_coeff; function y = mtreesum_fcn(u) %Implement the 'sum' function without a for-loop % y = sum(u); % The loop based implementation of 'sum' function is not ideal for % HDL generation and results in a longer critical path. % A tree is more efficient as it results in % delay of log2(N) instead of a delay of N delay % This implementation shows how to explicitly implement the vector sum in % a tree shape to enable hardware optimizations. % The ideal way to code this generically for any length of 'u' is to use % recursion but it is not currently supported by MATLAB Coder % NOTE: To instruct MATLAB Coder to compile an external function, % add the following compilation directive or pragma to the function code %#codegen % This implementation is hardwired for a 40tap filter. level1 = vsum(u); level2 = vsum(level1); level3 = vsum(level2); level4 = vsum(level3); level5 = vsum(level4); level6 = vsum(level5); y = level6; function output = vsum(input) coder.inline('always'); vt = input(1:2:end); for i = int32(1:numel(input)/2) k = int32(i*2); vt(i) = vt(i) + input(k); end output = vt; function tap_delay = mtapped_delay_fcn(input) % The Tapped Delay function delays its input by the specified number % of sample periods, and outputs all the delayed versions in a vector % form. The output includes current input % NOTE: To instruct MATLAB Coder to compile an external function, % add the following compilation directive or pragma to the function code %#codegen persistent u_d; if isempty(u_d) u_d = zeros(1,40); end u_d = [u_d(2:40), input]; tap_delay = u_d; function weights = update_weight_fcn(step_size, err_sig, ... delayed_signal, filter_coeff, reset_weights) % This function updates the adaptive filter weights based on LMS algorithm % Copyright 2007-2022 The MathWorks, Inc. % NOTE: To instruct MATLAB Coder to compile an external function, % add the following compilation directive or pragma to the function code %#codegen step_sig = step_size .* err_sig; correction_factor = delayed_signal .* step_sig; updated_weight = correction_factor + filter_coeff; if reset_weights weights = zeros(1,40); else weights = updated_weight; end
MATLAB 函数是模块化的,并使用以下函数:
mtapped_delay_fcn,用于以向量形式计算输入信号的延迟版本。mtreesum_fcn,用于以树状结构计算所应用权重之和。使用vsum函数计算各个和。update_weight_fcn,用于基于最小均方算法计算更新的滤波器权重。
LMS 滤波器 MATLAB 测试平台
查看 MATLAB 测试平台:
open(testbench_name)
% Returns an adaptive FIR filter System object, % HLMS, that computes the filtered output, filter error and the filter % weights for a given input and desired signal using the Least Mean % Squares (LMS) algorithm. % Copyright 2011-2022 The MathWorks, Inc. clear('mlhdlc_lms_fcn'); hfilt2 = dsp.FIRFilter(... 'Numerator', fir1(10, [.5, .75])); rng('default'); % always default to known state x = randn(1000,1); % Noise d = step(hfilt2, x) + sin(0:.05:49.95)'; % Noise + Signal stepSize = 0.01; reset_weights =false; hSrc = dsp.SignalSource(x); hDesiredSrc = dsp.SignalSource(d); hOut = dsp.SignalSink; hErr = dsp.SignalSink; %%%%%%%%%%%%%%%%%%%%%%%%%%%% %Call to the design %%%%%%%%%%%%%%%%%%%%%%%%%%%% while (~isDone(hSrc)) [y, e] = mlhdlc_lms_fcn(step(hSrc), step(hDesiredSrc), ... stepSize, reset_weights); step(hOut, y); step(hErr, e); end figure('Name', [mfilename, '_signal_plot']); subplot(2,1,1), plot(hOut.Buffer), title('Noise + Signal'); subplot(2,1,2),plot(hErr.Buffer), title('Signal');
测试 MATLAB 算法
为避免运行时错误,请使用测试平台对设计进行仿真。
mlhdlc_lms_noise_canceler_tb

创建 HDL Coder 工程
要从 MATLAB 设计生成 HDL 代码,请执行以下操作:
1.创建一个 HDL Coder 工程:
coder -hdlcoder -new mlhdlc_lms_nc
2.将文件 mlhdlc_lms_fcn.m 作为 MATLAB 函数添加到工程中,并将 mlhdlc_lms_noise_canceler_tb.m 作为 MATLAB 测试平台添加。
3.点击 Autodefine types 以使用为 MATLAB 函数 mlhdlc_lms_fcn 的输入和输出推荐的类型。
有关创建和填充 MATLAB HDL Coder 工程的更完整教程,请参阅 Generate HDL Code from MATLAB Algorithms。

运行定点转换和 HDL 代码生成
点击工作流顾问按钮以启动工作流顾问。
右键点击 HDL 代码生成任务,然后选择运行到选定任务。
为 MATLAB 设计生成单个 HDL 文件 mlhdlc_lms_fcn_FixPt.vhd。要检查滤波器设计的生成 HDL 代码,请点击“代码生成日志”窗口中的超链接。
如果您要为 MATLAB 设计中的每个函数生成一个 HDL 文件,请在 HDL 代码生成任务的高级选项卡中,选中为函数生成可实例化的代码复选框。另请参阅Generate Instantiable Code for Functions。