В этом примере показано, как сгенерировать модульный HDL-код из кода MATLAB®, содержащего функции.
HDL Coder™ по умолчанию встраивает тело всех функций MATLAB, названных в проекте верхнего уровня, и генерирует HDL-код в одном файле. Однако включение усовершенствованной опции кодирования 'Генерирует instantiable код для функций', помогает вам сгенерировать код модуля в нескольких файлах.
Проект MATLAB, используемый в примере, является реализацией фильтра LMS. Фильтр LMS используется, чтобы идентифицировать КИХ-сигнал фильтра, встроенный в шум.
design_name = 'mlhdlc_lms_fcn'; testbench_name = 'mlhdlc_lms_fir_id_tb';
Давайте смотреть на проект MATLAB,
dbtype(design_name);
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 % MATLAB Design: Adaptive Noise Canceler algorithm using Least Mean Square
3 % (LMS) filter implemented in MATLAB
4 %
5 % Key Design pattern covered in this example:
6 % (1) Use of function calls
7 % (2) Function inlining vs instantiation knobs available in the coder
8 % (3) Use of system objects in the testbench to stream test vectors into the design
9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10
11 %#codegen
12
13 function [filtered_signal, y, fc] = mlhdlc_lms_fcn(input, desired, step_size, reset_weights)
14 %
15 % 'input' : The signal from Exterior Mic which records the ambient noise.
16 % 'desired': The signal from Pilot's Mic which includes
17 % original music signal and the noise signal
18 % 'err_sig': The difference between the 'desired' and the filtered 'input'
19 % It represents the estimated music signal (output of this block)
20 %
21 % The LMS filter is trying to retrieve the original music signal ('err_sig')
22 % from Pilot's Mic by filtering the Exterior Mic's signal and using it to
23 % cancel the noise in Pilot's Mic. The coefficients/weights of the filter
24 % are updated(adapted) in real-time based on 'input' and 'err_sig'.
25
26 % register filter coefficients
27 persistent filter_coeff;
28 if isempty(filter_coeff)
29 filter_coeff = zeros(1, 40);
30 end
31
32 % Variable Filter
33 % call 'tapped_delay_fcn' function on path to create 40-step tapped delay
34 delayed_signal = mtapped_delay_fcn(input);
35
36 % apply filter coefficients
37 weight_applied = delayed_signal .* filter_coeff;
38
39 % call 'treesum' function on matlab path to sum up the results
40 filtered_signal = mtreesum_fcn(weight_applied);
41
42 % Output estimated Original Signal
43 td = desired;
44 tf = filtered_signal;
45
46 esig = td - tf;
47 y = esig;
48
49 % Update Weights
50 % call 'update_weight_fcn' function on matlab path to
51 % calculate the new weights
52 updated_weight = update_weight_fcn(step_size, esig, delayed_signal, ...
53 filter_coeff, reset_weights);
54
55 % update filter coefficients register
56 filter_coeff = updated_weight;
57
58 fc = filter_coeff;
59
60
61 function y = mtreesum_fcn(u)
62 %Implement the 'sum' function without a for-loop
63 % y = sum(u);
64
65 % The loop based implementation of 'sum' function is not ideal for
66 % HDL generation and results in a longer critical path.
67 % A tree is more efficient as it results in
68 % delay of log2(N) instead of a delay of N delay
69
70 % This implementation shows how to explicitly implement the vector sum in
71 % a tree shape to enable hardware optimizations.
72
73 % The ideal way to code this generically for any length of 'u' is to use
74 % recursion but it is not currently supported by MATLAB Coder
75
76
77 % NOTE: To instruct MATLAB Coder to compile an external function,
78 % add the following compilation directive or pragma to the function code
79 %#codegen
80
81 % This implementation is hardwired for a 40tap filter.
82
83 level1 = vsum(u);
84 level2 = vsum(level1);
85 level3 = vsum(level2);
86 level4 = vsum(level3);
87 level5 = vsum(level4);
88 level6 = vsum(level5);
89 y = level6;
90
91
92
93 function output = vsum(input)
94
95 coder.inline('always');
96
97 vt = input(1:2:end);
98
99 for i = int32(1:numel(input)/2)
100 k = int32(i*2);
101 vt(i) = vt(i) + input(k);
102 end
103
104 output = vt;
105
106 function tap_delay = mtapped_delay_fcn(input)
107 % The Tapped Delay function delays its input by the specified number
108 % of sample periods, and outputs all the delayed versions in a vector
109 % form. The output includes current input
110
111 % NOTE: To instruct MATLAB Coder to compile an external function,
112 % add the following compilation directive or pragma to the function code
113 %#codegen
114
115 persistent u_d;
116 if isempty(u_d)
117 u_d = zeros(1,40);
118 end
119
120
121 u_d = [u_d(2:40), input];
122
123 tap_delay = u_d;
124
125
126 function weights = update_weight_fcn(step_size, err_sig, delayed_signal, filter_coeff, reset_weights)
127 % This function updates the adaptive filter weights based on LMS algorithm
128
129 % Copyright 2007-2015 The MathWorks, Inc.
130
131 % NOTE: To instruct MATLAB Coder to compile an external function,
132 % add the following compilation directive or pragma to the function code
133 %#codegen
134
135 step_sig = step_size .* err_sig;
136 correction_factor = delayed_signal .* step_sig;
137 updated_weight = correction_factor + filter_coeff;
138
139 if reset_weights
140 weights = zeros(1,40);
141 else
142 weights = updated_weight;
143 end
Давайте смотреть на испытательный стенд MATLAB,
dbtype(testbench_name);
1
2 %
3
4 % Copyright 2011-2015 The MathWorks, Inc.
5
6 clear ('mlhdlc_lms_fcn');
7 % returns an adaptive FIR filter System object,
8 % HLMS, that computes the filtered output, filter error and the filter
9 % weights for a given input and desired signal using the Least Mean
10 % Squares (LMS) algorithm.
11
12 stepSize = 0.01;
13 reset_weights =false;
14
15 hfilt = dsp.FIRFilter; % System to be identified
16 hfilt.Numerator = fir1(10, .25);
17
18 rng('default'); % always default to known state
19 x = randn(1000,1); % input signal
20 d = step(hfilt, x) + 0.01*randn(1000,1); % desired signal
21
22 hSrc = dsp.SignalSource(x);
23 hDesiredSrc = dsp.SignalSource(d);
24
25 hOut = dsp.SignalSink;
26 hErr = dsp.SignalSink;
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 %Call to the design
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%
30 while (~isDone(hSrc))
31 [y, e, w] = mlhdlc_lms_fcn(step(hSrc), step(hDesiredSrc), stepSize, reset_weights);
32 step(hOut, y);
33 step(hErr, e);
34 end
35
36 figure('Name', [mfilename, '_plot']);
37 subplot(2,1,1), plot(1:1000, [d,hOut.Buffer,hErr.Buffer]);
38 title('System Identification of an FIR filter');
39 legend('Desired', 'Output', 'Error');
40 xlabel('time index'); ylabel('signal value');
41 subplot(2,1,2); stem([hfilt.Numerator.', w(end-10:end).']);
42 legend('Actual','Estimated');
43 xlabel('coefficient #'); ylabel('coefficient value');
Выполните следующие строки кода, чтобы скопировать необходимые файлы в качестве примера во временную папку.
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos'); mlhdlc_temp_dir = [tempdir 'mlhdlc_fcn_partition']; % create a temporary folder and copy the MATLAB files. cd(tempdir); [~, ~, ~] = rmdir(mlhdlc_temp_dir, 's'); mkdir(mlhdlc_temp_dir); cd(mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, [design_name,'.m*']), mlhdlc_temp_dir); copyfile(fullfile(mlhdlc_demo_dir, [testbench_name,'.m*']), mlhdlc_temp_dir); % At the end of this step you should see the design files being copied to % a temporary folder.
Это всегда - хорошая практика, чтобы симулировать проект с испытательным стендом до генерации кода, чтобы убедиться, что нет никаких ошибок периода выполнения.
mlhdlc_lms_fir_id_tb

coder -hdlcoder -new mlhdlc_fcn_partition
Затем добавьте файл 'mlhdlc_lms_fcn.m' в проект как функция MATLAB и 'mlhdlc_lms_fir_id_tb.m' как Испытательный стенд MATLAB.
Можно обратиться к Началу работы с MATLAB к примеру по Рабочему процессу HDL для более полного примера при создании и заполнении проектов HDL Coder MATLAB.

Запустите Советника по вопросам Рабочего процесса от вкладки Build, и щелчок правой кнопкой по 'Генерации кода' продвигаются и выбирают опцию, 'Запущенную к выбранной задаче', чтобы запустить все шаги с начала через генерацию HDL-кода.
Исследуйте сгенерированный HDL-код путем нажатия на гиперссылки в окне Code Generation Log. Заметьте, что HDL-код для всех функций в проекте встраивается в один файл 'mlhdlc_lms_fcn_FixPt.vhd'

Чтобы сгенерировать модульный код для всех функций в отдельных файлах, включите, это совершенствовалось, опция кодирования 'Генерируют instantiable код для функций'

Теперь сбросьте задачу генерации кода и повторно выполните шаг генерации HDL-кода, чтобы видеть, как код сгенерирован в нескольких файлах для функций

Иногда желательно к встроенному коду для помощников и утилит и инстанцируйте их. Чтобы локально управлять встраиванием таких функций используют 'coder.inline' прагму в коде MATLAB.
coder.inline('always') coder.inline('never') coder.inline('default')
Введите следующую команду, чтобы видеть, как использовать coder.inline прагму
help coder.inline
Нижеследующие ограничения существуют при инстанцировании HDL-кода от функций.
Вызовы функции в условных выражениях и циклах for встраиваются, и не становитесь инстанцированными.
Функции с состояниями встраиваются.
Можно запустить следующие команды, чтобы очистить временную папку проекта.
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos'); mlhdlc_temp_dir = [tempdir 'mlhdlc_fcn_partition']; clear mex; cd (mlhdlc_demo_dir); rmdir(mlhdlc_temp_dir, 's');