Этот пример демонстрирует, как выполнить деление реальных чисел с помощью аппаратно-эффективного кода MATLAB ®, встроенного в модели Simulink ®. Модель, используемая в этом примере, подходит для генерации HDL-кода для входов с фиксированной точкой. Алгоритм использует полностью конвейерную архитектуру, которая подходит для устройств FPGA или ASIC, где пропускная способность вызывает беспокойство. Эта реализация также использует доступные ресурсы на микросхеме разумно, что делает ее также подходящей для ресурсосознательных проектов.
Операция деления для двух вещественных чисел и , где , определяется как , таким что .
CORDIC является акронимом COordinate Rotation DIgital Computer, и может использоваться для эффективного вычисления многих тригонометрических, гиперболических и арифметических функций. Для подробного объяснения алгоритма CORDIC и его применения в вычислении тригонометрической функции, смотрите Вычисление Синуса и Косина Использование CORDIC Rotation Kernel.
Блок Real Divide HDL Optimized поддерживает генерацию HDL-кода для данных с фиксированной точкой с двоичным масштабированием точек. Он разработан с учетом этого приложения и использует аппаратную семантику и оптимизацию. Одной из этих оптимизаций является конвейеризация всей своей внутренней схемы для поддержания очень высокой производительности.
При развертывании сложных алгоритмов на устройствах FPGA или ASIC часто существует компромисс между использованием ресурсов и общей пропускной способностью для заданных расчетов. Совместное использование ресурсов часто сокращает ресурсы, потребляемые в проекте, но также снижает пропускную способность в процессе. Простые арифметические и тригономические расчеты, которые обычно образуют части больших расчетов, требуют высокой пропускной способности, чтобы возбуждать схемы дальше в проекте. Таким образом, полностью конвейерные реализации потребляют больше ресурсов на микросхеме, но выгодны в больших проектах.
Все ключевые вычислительные модули в блоке Real Divide HDL Optimized полностью конвейеризованы внутри системы. Это включает не только схему CORDIC, используемую для выполнения вращений Гивенса, но и сумматоры и переключатели, используемые в другом месте проекта, что обеспечивает максимальную пропускную способность.
Из-за своей полностью конвейерной природы, блок Real Divide HDL Optimized способен принимать входные данные по любому циклу, включая последовательные циклы. Чтобы отправить входные данные в блок, validIn
сигнал должен быть true
. Когда блок закончит расчет и будет готов отправить выход, он изменится validOut
на true
для одного такта. Для входов, переданных на последовательных циклах, validOut
будет также установлено значение true
на последовательных циклах. Числитель и знаменатель должны быть отправлены вместе в одном цикле.
Чтобы открыть модель примера, в командной строке введите:
mdl = 'fxpdemo_realDivide';
open_system(mdl)
Модель содержит блок Real Divide HDL Optimized, соединенный с источником данных, который принимает массивы входов (числители и знаменатели) и передает входное значение из каждого массива в блок на последовательных циклах. Вычисленная для каждого значения выход сохранён в переменной рабочей области. Симуляция заканчивается, когда все входы были обработаны.
Задайте массивы входов realDivideNumerators
и realDivideDenominators
. В данном примере входы удваиваются. Обратите внимание, что и числитель, и знаменатель должны иметь одинаковый тип данных.
rng('default');
realDivideNumerators = 9*rand(1000,1) + 1;
realDivideDenominators = 9*rand(1000,1) + 1;
Задайте выход тип данных, который будет использоваться в модели. В данном примере выходы также удваиваются. Обратите внимание, что выходы с фиксированной точкой могут использоваться только с входами с фиксированной точкой.
OutputType = 'double';
Симулируйте модель.
sim(mdl);
Когда симуляция завершена, новая переменная рабочей области, realDivideOutputs
, создается, чтобы сохранить вычисленное значение для каждой пары входов.
Чтобы изучить ошибку вычисления, сравните вывод блока Real Divide HDL Optimized с выходом встроенной функции MATLAB ® divide.
expectedOutput = realDivideNumerators./realDivideDenominators; actualOutput = realDivideOutputs; maxError = max(abs(expectedOutput - actualOutput))
maxError = 0