The eml_hdl_design_patterns
библиотека представляет собой обширный набор примеров, демонстрирующих полезные приложения блока MATLAB Function при генерации HDL-кода.
Чтобы открыть библиотеку, введите следующую команду в MATLAB® приглашение:
eml_hdl_design_patterns
Можно использовать много блоков в библиотеке как примеры cookbook различных аппаратных элементов, следующим образом:
Скопируйте блок из библиотеки в вашу модель и используйте его как вычислительный модуль.
Скопируйте код из блока и используйте его как локальную функцию в существующем блоке MATLAB Function.
Когда вы создаете пользовательские блоки, можно управлять, входить ли в строку или создавать экземпляры HDL-кода, сгенерированного из MATLAB Function блоков. Установите флажок Inline MATLAB Function block code в разделе HDL Code Generation > Global Settings > Coding style диалогового окна Параметры конфигурации. Для получения дополнительной информации см. Inline MATLAB Function block code.
Примечание
Не используйте настройку Inline MATLAB Function block code с MATLAB Datapath
архитектура блока MATLAB Function. Вместо этого используйте FlattenHierarchy. Для получения дополнительной информации смотрите Оптимизация HDL через контур блока MATLAB function с использованием архитектуры MATLAB Datapath.
Блок MATLAB Function поддерживает арифметику с плавающей точкой, а также арифметику с фиксированной точкой при помощи Fixed-Point Designer™ fi
функция. Эта функция поддерживает режимы округления и насыщения, которые полезны для алгоритмов кодирования, которые манипулируют произвольными длинами слов и дробей. HDL Coder™ поддерживает все fi
режимы округления и переполнения. HDL-код, сгенерированный из блока MATLAB Function, имеет битовое значение true к семантике MATLAB. Сгенерированный код использует бит операторов манипуляции и битового доступа (для примера, Среза, Extend, Reduce, Concat и т.д.), которые являются собственными для VHDL® и Verilog®.
Следующее обсуждение показывает, как HDL-код, сгенерированный из блока MATLAB Function, следует семантике перед сложением и вычитанием, в которой операнды сложения и вычитания приводятся к типу результата перед выполнением сложения или вычитания.
Откройте eml_hdl_design_patterns
и выберите Combinatorics/eml_expr
блок. eml_expr
реализует простое выражение, содержащее операторы сложения, вычитания и умножения с различными типами данных с фиксированной точкой. Сгенерированный HDL-код показывает преобразование этого выражения с операндами с фиксированной точкой. Блок MATLAB Function использует следующий код:
% fixpt arithmetic expression expr = (a*b) - (a+b); % cast the result to (sfix7_En4) output type y = fi(expr, 1, 7, 4);
Значение по умолчанию fimath
спецификация для блока определяет поведение арифметических выражений с помощью операндов с фиксированной точкой внутри блока MATLAB Function:
fimath(... 'RoundMode', 'ceil',... 'OverflowMode', 'saturate',... 'ProductMode', 'FullPrecision', 'ProductWordLength', 32,... 'SumMode', 'FullPrecision', 'SumWordLength', 32,... 'CastBeforeSum', true)
Типы данных операндов и выхода следующие:
a
: (sfix5_En2)
b
: (sfix5_En3)
y
: (sfix7_En4)
Перед генерацией HDL-кода это выражение разбивается внутри на многие шаги.
expr = (a*b) - (a+b);
Шаги включают в себя:
tmul = a * b;
tadd = a + b;
tsub = tmul - tadd;
y = tsub;
На основе fimath
как описано в Design Guidelines для Блок MATLAB Function, это выражение далее разбивается внутри следующим образом:
На основе заданного ProductMode
, 'FullPrecision'
, тип выхода tmul
вычисляется следующим (sfix10_En5)
.
Начиная с CastBeforeSum
для свойства задано значение 'true'
Шаг 2 разбивается следующим образом:
t1 = (sfix7_En3) a; t2 = (sfix7_En3) b; tadd = t1 + t2;
sfix7_En3
- тип суммы результатов после выравнивания двоичных точек и учета дополнительного бита для расчета возможного переполнения.
На основе промежуточных типов tmul (sfix10_En5)
и tadd (sfix7_En3)
тип результата вычитания на шаге 3 вычисляется как sfix11_En5
. Соответственно, этап 3 разбивается на следующие части:
t3 = (sfix11_En5) tmul; t4 = (sfix11_En5) tadd; tsub = t3 - t4;
Наконец, результат приведен к меньшему типу (sfix7_En4
) приводя к следующим заключительным операторам:
tmul = a * b; t1 = (sfix7_En3) a; t2 = (sfix7_En3) b; tadd = t1 + t2; t3 = (sfix11_En5) tmul; t4 = (sfix11_En5) tadd; tsub = t3 - t4; y = (sfix7_En4) tsub;
В следующих списках показан сгенерированный код VHDL и Verilog из eml_expr
блок.
Это код VHDL:
BEGIN --MATLAB Function 'Subsystem/eml_expr': '<S2>:1' -- fixpt arithmetic expression --'<S2>:1:4' mul_temp <= signed(a) * signed(b); sub_cast <= resize(mul_temp, 11); add_cast <= resize(signed(a & '0'), 7); add_cast_0 <= resize(signed(b), 7); add_temp <= add_cast + add_cast_0; sub_cast_0 <= resize(add_temp & '0' & '0', 11); expr <= sub_cast - sub_cast_0; -- cast the result to correct output type --'<S2>:1:7' y <= "0111111" WHEN ((expr(10) = '0') AND (expr(9 DOWNTO 7) /= "000")) OR ((expr(10) = '0') AND (expr(7 DOWNTO 1) = "0111111")) ELSE "1000000" WHEN (expr(10) = '1') AND (expr(9 DOWNTO 7) /= "111") ELSE std_logic_vector(expr(7 DOWNTO 1) + ("0" & expr(0))); END fsm_SFHDL;
Это код Verilog:
//MATLAB Function 'Subsystem/eml_expr': '<S2>:1' // fixpt arithmetic expression //'<S2>:1:4' assign mul_temp = a * b; assign sub_cast = mul_temp; assign add_cast = {a[4], {a, 1'b0}}; assign add_cast_0 = b; assign add_temp = add_cast + add_cast_0; assign sub_cast_0 = {{2{add_temp[6]}}, {add_temp, 2'b00}}; assign expr = sub_cast - sub_cast_0; // cast the result to correct output type //'<S2>:1:7' assign y = (((expr[10] == 0) && (expr[9:7] != 0)) || ((expr[10] == 0) && (expr[7:1] == 63)) ? 7'sb0111111 : ((expr[10] == 1) && (expr[9:7] != 7) ? 7'sb1000000 : expr[7:1] + $signed({1'b0, expr[0]})));
Эти фрагменты кода показывают, что сгенерированный HDL-код из блока MATLAB Function представляет битовое поведение выражений арифметики с фиксированной точкой с использованием HDL- операторов высокого уровня. HDL-код генерируется с помощью правил HDL-кодирования, таких как high level bitselect
и partselect
операторы репликации и операторы явного расширения знаков и изменения размера.
В модели программирования MATLAB Function блоков элементы, удерживающие состояние, представлены как постоянные переменные. Переменная, которая объявлена persistent
сохраняет свое значение между вызовами функций в программном обеспечении и между временными шагами расчета во время симуляции.
Обратите внимание, что ваш код MATLAB должен считать постоянную переменную, прежде чем она будет написана, если вы хотите, чтобы HDL Coder вывел регистр в HDL-коде. Генератор кода выводит предупреждающее сообщение, если ваш код не следует этому правилу.
Следующий пример показывает unit delay
блок, который задерживает выборку входа, u
, на один временной шаг симуляции. u
является операндом типа с фиксированной точкой sfix6
. u_d
- постоянная переменная, которая содержит вход выборку.
function y = fcn(u) persistent u_d; if isempty(u_d) u_d = fi(-1, numerictype(u), fimath(u)); end % return delayed input from last sample time hit y = u_d; % store the current input to be used later u_d = u;
Потому что этот код предназначен для u_d
для вывода регистра во время генерации HDL-кода, u_d
считывается в операторе назначения, y = u_d
, прежде чем это будет записано в u_d = u
.
HDL Coder генерирует следующий HDL-код для unit delay
блок.
ENTITY Unit_Delay IS PORT ( clk : IN std_logic; clk_enable : IN std_logic; reset : IN std_logic; u : IN std_logic_vector(15 DOWNTO 0); y : OUT std_logic_vector(15 DOWNTO 0)); END Unit_Delay; ARCHITECTURE fsm_SFHDL OF Unit_Delay IS BEGIN initialize_Unit_Delay : PROCESS (clk, reset) BEGIN IF reset = '1' THEN y <= std_logic_vector(to_signed(0, 16)); ELSIF clk'EVENT AND clk = '1' THEN IF clk_enable = '1' THEN y <= u; END IF; END IF; END PROCESS initialize_Unit_Delay;
Инициализация стойких переменных перемещается в главную область сброса в процессе инициализации.
Обратитесь к Delays
подсистема в eml_hdl_design_patterns
библиотека, чтобы увидеть, как векторы стойких переменных могут использоваться, чтобы смоделировать целочисленную задержку, задержку касания и векторные блоки задержки касания. Эти шаблоны проекта полезны при реализации последовательных алгоритмов, которые несут состояние между выполнениями блока MATLAB Function в модели.
Блок MATLAB Function помогает вам создать интеллектуальное свойство и создать альтернативные реализации части алгоритма. При помощи MATLAB Function блоков таким образом можно руководствоваться подробной операцией генератора HDL-кода даже при записи алгоритмов высокого уровня.
Для примера, подсистема Comparators
в eml_hdl_design_patterns
библиотека включает несколько альтернативных алгоритмов для нахождения минимального значения вектора. The Comparators/eml_linear_min
блок последовательно находит минимум вектора в линейном режиме. The Comparators/eml_tree_min
блок сравнивает элементы в древовидной структуре. Реализация дерева может достичь более высокой тактовой частоты путем добавления регистров конвейера между log2(N)
этапы. (См. eml_hdl_design_patterns/Filters
для примера.)
Теперь рассмотрите замену простой операции сравнения в Comparators
блоки с арифметической операцией (для примера, сложения, вычитания или умножения), где промежуточные результаты должны быть квантованы. Использование fimath
настройки округления, можно точно настроить расчеты промежуточных значений перед подачей промежуточных значений на следующий этап. Можно использовать этот метод для настройки сгенерированного оборудования или настройки алгоритма.
Можно объявить нетронутый параметр для блока MATLAB Function, установив его Scope на Parameter
в графическом интерфейсе пользователя Ports and Data Manager и очистке опции Tunable.
Неотключаемый параметр не отображается как сигнальный порт на блоке. Аргументы параметра для блоков MATLAB Function берут их значения из параметров, определенных в родительском Simulink® маскированная подсистема или от переменных, определенных в базовом рабочем пространстве MATLAB, а не от сигналов в модели Simulink.
MATLAB Function блока управляющие конструкции, такие как switch/case
и if-elseif-else
, в сочетании с арифметическими операциями с фиксированной точкой, позволяют вам быстро моделировать логику управления.
The FSMs/mealy_fsm_blk
и FSMs/moore_fsm_blk
блоки в eml_hdl_design_patterns
библиотека предоставляет примеры реализации конечных машин состояний Мили и Мура в блоке MATLAB Function.
В следующем списке реализован конечный автомат Мура.
function Z = moore_fsm(A) persistent moore_state_reg; if isempty(moore_state_reg) moore_state_reg = fi(0, 0, 2, 0); end S1 = 0; S2 = 1; S3 = 2; S4 = 3; switch uint8(moore_state_reg) case S1, Z = true; if (~A) moore_state_reg(1) = S1; else moore_state_reg(1) = S2; end case S2, Z = false; if (~A) moore_state_reg(1) = S1; else moore_state_reg(1) = S2; end case S3, Z = false; if (~A) moore_state_reg(1) = S2; else moore_state_reg(1) = S3; end case S4, Z = true; if (~A) moore_state_reg(1) = S1; else moore_state_reg(1) = S3; end otherwise, Z = false; end
В этом примере постоянная переменная (moore_state_reg
) моделирует переменные состояния. Это выход зависит только от переменных состояния, таким образом моделируя машину Мура.
The FSMs/mealy_fsm_blk
блок в eml_hdl_design_patterns
библиотека реализует конечный автомат Мили. Конечный автомат Мили отличается от конечного автомата Мура тем, что выходы зависят от входов, а также от переменных состояния.
Блок MATLAB Function может быстро смоделировать простые машины состояний и другие основанные на управлении алгоритмы оборудования (такие как шаблоны matcher или контроллеры, связанные с синхронизацией), используя операторы управления и постоянные переменные.
Для моделирования более сложных и иерархических машин состояний с сложной временной логикой используйте Stateflow® график для моделирования конечного автомата.
Для реализации арифметических и управляющих логических алгоритмов в блоках MATLAB Function, предназначенных для генерации HDL-кода, существуют некоторые простые требования к HDL-кодированию:
Блок MATLAB Function верхнего уровня должен вызываться один раз в временной шаг.
Должна быть возможность полного разблокирования циклов программы.
Стойкие переменные с значениями сброса и логикой обновления должны использоваться, чтобы удерживать значения на всех временных шагах симуляции.
Квантованные переменные данных должны использоваться внутри циклов.
Следующий скрипт показывает, как смоделировать синхронный счетчик вверх/вниз с предустановленными значениями и входами управления. Пример предоставляет и главное управление сбросом переменных стойкого состояния, и локальное управление сбросом с помощью блока входов (например presetClear
). The isempty
условие входит в процесс инициализации под управлением синхронного сброса. The presetClear
раздел реализован в выход разделе сгенерированного HDL-кода.
Операторы вверх и вниз, реализующие цикл счетчика, требуют, чтобы значения счетчика квантовались после сложения или вычитания. По умолчанию блок MATLAB Function автоматически распространяет настройки с фиксированной точкой, заданные для блока. Однако в этом скрипте явно заданы настройки с фиксированной точкой для промежуточных величин и констант.
function [Q, QN] = up_down_ctr(upDown, presetClear, loadData, presetData) % up down result % 'result' syntheses into sequential element result_nt = numerictype(0,4,0); result_fm = fimath('OverflowMode', 'saturate', 'RoundMode', 'floor'); initVal = fi(0, result_nt, result_fm); persistent count; if isempty(count) count = initVal; end if presetClear count = initVal; elseif loadData count = presetData; elseif upDown inc = count + fi(1, result_nt, result_fm); -- quantization of output count = fi(inc, result_nt, result_fm); else dec = count - fi(1, result_nt, result_fm); -- quantization of output count = fi(dec, result_nt, result_fm); end Q = count; QN = bitcmp(count);
Следующий пример кода показывает, как смоделировать регистры сдвига в MATLAB Function блоке при помощи bitsliceget
и bitconcat
функций. Эта функция реализует последовательный вход и выход переключатели с 32-битным операндом с фиксированной точкой входа. Смотрите Shift Registers/shift_reg_1by32
блок в eml_hdl_design_patterns
для получения дополнительной информации.
function sr_out = fcn(shift, sr_in) %shift register 1 by 32 persistent sr; if isempty(sr) sr = fi(0, 0, 32, 0, 'fimath', fimath(sr_in)); end % return sr[31] sr_out = getmsb(sr); if (shift) % sr_new[32:1] = sr[31:1] & sr_in sr = bitconcat(bitsliceget(sr, 31, 1), sr_in); end
В следующем примере кода показан код процесса VHDL, сгенерированный для shift_reg_1by32
блок.
shift_reg_1by32 : PROCESS (shift, sr_in, sr) BEGIN sr_next <= sr; -- MATLAB Function Function 'Subsystem/shift_reg_1by32': '<S2>:1' --shift register 1 by 32 --'<S2>:1:1 -- return sr[31] --'<S2>:1:10' sr_out <= sr(31); IF shift /= '0' THEN --'<S2>:1:12' -- sr_new[32:1] = sr[31:1] & sr_in --'<S2>:1:14' sr_next <= sr(30 DOWNTO 0) & sr_in; END IF; END PROCESS shift_reg_1by32;
The Shift Registers/shift_reg_1by64
блок показывает 64-битный переключатель. В этом случае сдвигатель использует два слова с фиксированной точкой, чтобы представлять операнд, преодолевая 32-битное ограничение размера слова для целых чисел с фиксированной точкой.
Просмотр eml_hdl_design_patterns
модель для других полезных аппаратных элементов, которые можно легко реализовать с помощью блока MATLAB Function.
Можно выполнить преобразования из целого типа, чтобы сгенерировать выход вектора битов и наоборот. Для примера модели, которая показывает, как выполнить это преобразование, откройте модель hdlcoder_int2bits_bits2int
.
open_system('hdlcoder_int2bits_bits2int')
eml_hdl_design_patterns
библиотека под Word Twiddlers
библиотека.Проверьте настройки блока MATLAB Function