В этом примере показано, как можно использовать For Each Subsystem для реализации алгоритма потокового квадратного корня путем каскадирования идентичных итераций CORDIC. Затем можно сгенерировать код для алгоритма с помощью HDL- Coder™.
CORDIC является итеративным алгоритмом, который может использоваться для аппроксимации математики с фиксированной точкой, такой как тригонометрические функции, квадратный корень и деление. Итеративное ядро состоит из простых операций сдвига и добавления, что позволяет эффективно реализовывать алгоритм на оборудовании FPGA или ASIC. Для приложений с низкой скоростью передачи данных одно ядро может быть повторно использовано, чтобы выполнить все итерации и достичь очень малой площади. Для приложений, требующих обработки новой выборки данных в каждом такте, отдельное ядро может использоваться, чтобы вычислить каждую итерацию в каскадной цепи, как показано на следующей схеме.
Хотя несложно вручную каскадировать ядра в Simulink ®, возможность автоматически настроить количество ядер на основе значения параметров была бы весьма желательной. Это можно сделать с помощью For Each Subsystem.
В этой модели итерационное ядро помещается в повторяемую N подсистему For Each, где N - количество итераций, заданное в маске блока верхнего уровня. The N
выходы ядра формируют вектор на выходе For Each Subsystem, где они конвейеризуются, и затем возвращаются во входы For Each Subsystem. Выходы ядра (1:N-1)
соединяются с входами ядра (2:N)
, точно так же, как в каскадной модели вручную.
Допустимый путь сигнала включен для обработки прерывистых входных данных и протестирован путем вставки случайных погрешностей между допустимыми выборками данных.
open_system('hdlcoder_foreach_cordic') open_system('hdlcoder_foreach_cordic/For Each Cordic Sqrt','force')
Использование 14-битного входа со знаком в области значений [0.5,2)
, выходы модели Simulink совпадают с cordicsqrt
ссылочная функция точно. Входная область значений за пределами [0.5,2)
не ожидается, что это сработает, потому что в примере отсутствует ступень нормализатора.
В сложение, итоговая регулировка усиления в модели использует 18-битный параметр усиления для оптимального отображения DSP FPGA; в то время как cordicsqrt
функция совпадает с параметром размера слова усиления и параметром входа усиления. Это приводит к небольшим различиям между выходом модели Simulink и cordicsqrt
функция, когда используются другие типы входных данных.
slout = sim('hdlcoder_foreach_cordic'); data_out = slout.logsout.getElement('data out').Values.Data; valid_out = slout.logsout.getElement('valid out').Values.Data; data_out = data_out(valid_out); ref_cordic = double(cordicsqrt(v_fix, niter)); data_in = double(v_fix); data_out = double(data_out'); figure; subplot(211); plot(data_in, data_out, 'r.', data_in, ref_cordic, 'b-'); legend('ForEach', 'MATLAB CORDICSQRT', 'Location', 'SouthEast'); title('ForEach Model and MATLAB CORDICSQRT Reference Results'); subplot(212); absErr = abs(ref_cordic - data_out); plot(data_in, absErr); title('Absolute Differences (vs. MATLAB CORDICSQRT Reference)');
makehdl('hdlcoder_foreach_cordic/For Each Cordic Sqrt');
### Generating HDL for 'hdlcoder_foreach_cordic/For Each Cordic Sqrt'. ### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_foreach_cordic', { 'HDL Code Generation' } )">hdlcoder_foreach_cordic</a> for HDL code generation parameters. ### Running HDL checks on the model 'hdlcoder_foreach_cordic'. ### Begin compilation of the model 'hdlcoder_foreach_cordic'... ### Applying HDL optimizations on the model 'hdlcoder_foreach_cordic'... ### Begin model generation. ### Model generation complete. ### Begin VHDL Code Generation for 'hdlcoder_foreach_cordic'. ### Working on hdlcoder_foreach_cordic/For Each Cordic Sqrt/MATLAB Function2 as hdlsrc/hdlcoder_foreach_cordic/MATLAB_Function2.vhd. ### Working on hdlcoder_foreach_cordic/For Each Cordic Sqrt/For Each Subsystem/MATLAB Function1 as hdlsrc/hdlcoder_foreach_cordic/MATLAB_Function1.vhd. ### Working on hdlcoder_foreach_cordic/For Each Cordic Sqrt/For Each Subsystem as hdlsrc/hdlcoder_foreach_cordic/For_Each_Subsystem.vhd. ### Working on hdlcoder_foreach_cordic/For Each Cordic Sqrt as hdlsrc/hdlcoder_foreach_cordic/For_Each_Cordic_Sqrt.vhd. ### Generating package file hdlsrc/hdlcoder_foreach_cordic/For_Each_Cordic_Sqrt_pkg.vhd. ### Code Generation for 'hdlcoder_foreach_cordic' completed. ### Creating HDL Code Generation Check Report file:///tmp/BR2021ad_1584584_202060/publish_examples1/tp8fdc0684/hdlsrc/hdlcoder_foreach_cordic/For_Each_Cordic_Sqrt_report.html ### HDL check for 'hdlcoder_foreach_cordic' complete with 0 errors, 0 warnings, and 0 messages. ### HDL code generation complete.
Соблюдайте следующие рекомендации при каскадировании блоков в вашем алгоритме с использованием For Each Subsystem:
Поскольку For Each Subsystem является атомарной, связь между выходом блока X и входом блока X + 1 создает искусственный алгебраический цикл. Чтобы разорвать этот цикл, поместите регистры трубопровода между каскадными блоками вне Подсистемы For Each, как показано в этом примере.
Мультиплексорный блок используется для конкатенации внешнего входа и выходов блока (1:N-1)
для формирования входов для каждой подсистемы. Это требует, чтобы каскадные блоки использовали одинаковые типы входных и выходных данных.