В последнее время производители ПЛИС и сторонние компании активно разрабатывают методы разработки ПЛИС, отличающиеся от традиционных подходов с использованием инструментов разработки высокого уровня.
Как разработчик FPGA, моим основным инструментом является язык описания аппаратного обеспечения ( ЛПВП ) Verilog, но растущая популярность новых методов вызвала у меня большой интерес, поэтому в этой статье я решил сам разобраться, что к чему.
Данная статья не является руководством или инструкцией по использованию, это мой обзор и выводы о том, что могут дать различные инструменты разработки высокого уровня разработчику или программисту FPGA, желающему окунуться в мир FPGA. Чтобы сравнить наиболее интересные на мой взгляд инструменты разработки, я написал несколько тестов и проанализировал результаты.
Под катом — что из этого получилось.
Зачем нужны инструменты разработки FPGA высокого уровня
- Ускорить разработку проекта
- путем повторного использования кода, уже написанного на языках высокого уровня;
— за счет использования всех преимуществ языков высокого уровня при написании кода с нуля;
— за счет сокращения времени компиляции и проверки кода.
- Возможность создания универсального кода, который будет работать на любом семействе ПЛИС.
- Снизить барьер входа в разработку ПЛИС, например, отойдя от понятий «тактовая частота» и других низкоуровневых сущностей.
Возможность написания кода FPGA для разработчика, незнакомого с HDL.
Откуда берутся инструменты разработки высокого уровня?
В наше время многих привлекает идея развития высокого уровня.Занимаются этим как энтузиасты, как, например, Квокка И Генератор кода Python и такие корпорации, как Математические работы и производители FPGA Интел И Ксилинкс Каждый использует свои методы и инструменты для достижения своих целей.
Энтузиасты в борьбе за идеальный и чудесный мир используют свои любимые языки разработки, такие как Python или C#.
Корпорации, пытаясь угодить клиенту, предлагают свои или адаптируют существующие инструменты.
Mathworks предлагает свой инструмент кодирования HDL для генерации HDL-кода из m-скриптов и моделей Simulink, а Intel и Xilinx предлагают компиляторы для распространенных C/C++.
На данный момент большего успеха добились компании, обладающие значительными финансовыми и человеческими ресурсами, а энтузиасты несколько отстают. Эту статью я посвящу обзору продукта HDL-кодера от Mathworks и HLS Compiler от Intel. А что насчет Ксилинкса? В этой статье я не рассматриваю HLS от Xilinx из-за разных архитектур и САПР Intel и Xilinx, что не позволяет провести однозначное сравнение результатов.
Но хочу отметить, что Xilinx HLS, как и Intel HLS, предоставляет компилятор C/C++ и концептуально они схожи.
Начнем сравнивать HDL-кодер от Mathworks и HLS Compiler от Intel с решения нескольких задач с использованием разных подходов.
Сравнение инструментов разработки высокого уровня
Тест один.
«Два умножителя и сумматор» Решение этой задачи не имеет практической ценности, но вполне подходит в качестве первой проверки.
Функция принимает 4 параметра, умножает первый на второй, третий на четвертый и складывает результаты умножения.
Ничего сложного, но посмотрим, как с этим справятся наши испытуемые.
HDL-кодер от Mathworks
Для решения этой проблемы m-скрипт выглядит так:Давайте посмотрим, что нам предлагает Mathworks для преобразования кода в HDL. Я не буду подробно рассматривать работу с HDL-кодером, остановлюсь лишь на тех настройках, которые я буду менять в дальнейшем для получения разных результатов в ПЛИС, и об изменениях которых придется думать программисту MATLAB. которому нужно запустить свой код в FPGA. Итак, первое, что вам нужно сделать, это установить тип и диапазон входных значений.function [out] = TwoMultAdd(a,b,c,d) out = (a*b)+(c*d); end
В ПЛИС нет привычных char, int, float, double. Номер может иметь любую разрядность; логично выбирать его исходя из диапазона входных значений, который вы планируете использовать.
Изображение 1
MATLAB проверяет типы переменных, их значения и автоматически подбирает правильную разрядность шин и регистров — это действительно удобно.
Если проблем с разрядностью и набором текста нет, можно переходить к следующим шагам.
фигура 2
HDL Code Generation имеет несколько вкладок, на которых можно выбрать язык, на который будет происходить преобразование (Verilog или VHDL); стиль кода; названия сигналов.
Самая интересная вкладка, на мой взгляд, это «Оптимизация» — с ней я поэкспериментирую, но позже, а пока оставим все значения по умолчанию и посмотрим, какой HDL-кодер выйдет из коробки.
Нажмите кнопку «Выполнить» и получите следующий код: `timescale 1 ns / 1 ns
module TwoMultAdd_fixpt
(a,
b,
c,
d,
out);
input [7:0] a; // ufix8
input [7:0] b; // ufix8
input [7:0] c; // ufix8
input [7:0] d; // ufix8
output [16:0] out; // ufix17
wire [15:0] TwoMultAdd_fixpt_mul_temp; // ufix16
wire [16:0] TwoMultAdd_fixpt_2; // ufix17
wire [15:0] TwoMultAdd_fixpt_mul_temp_1; // ufix16
wire [16:0] TwoMultAdd_fixpt_3; // ufix17
//HDL code generation from MATLAB function: TwoMultAdd_fixpt
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %
// Generated by MATLAB 9.2 and Fixed-Point Designer 5.4 %
// %
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
assign TwoMultAdd_fixpt_mul_temp = a * b;
assign TwoMultAdd_fixpt_2 = {1'b0, TwoMultAdd_fixpt_mul_temp};
assign TwoMultAdd_fixpt_mul_temp_1 = c * d;
assign TwoMultAdd_fixpt_3 = {1'b0, TwoMultAdd_fixpt_mul_temp_1};
assign out = TwoMultAdd_fixpt_2 + TwoMultAdd_fixpt_3;
endmodule // TwoMultAdd_fixpt
Код выглядит хорошо.
MATLAB понимает, что писать все выражение в одной строке в Verilog — плохая практика.
Создает отдельные проволока К умножителю и сумматору придраться действительно не к чему.
Настораживает отсутствие описания регистров.
Это произошло потому, что мы не просили об этом HDL-кодер, а оставили все поля в настройках со значениями по умолчанию.
Вот что Quartus синтезирует из такого кода.
Рисунок 3
Никаких проблем, все было по плану.
В ПЛИС мы реализуем синхронные схемы, но нам всё равно хотелось бы видеть регистры.
HDL-кодер предлагает механизм размещения регистров, но где их разместить — решать разработчику.
Мы можем разместить регистры на входе умножителя, на выходе умножителя перед сумматором или на выходе сумматора.
Для синтеза примеров я выбрал семейство FPGA Cyclone V, где для реализации арифметических операций используются специальные блоки DSP со встроенными сумматорами и умножителями.
Блок DSP выглядит так:
Рисунок 4
Блок DSP имеет входные и выходные регистры.
Не нужно пытаться зафиксировать результаты умножения в регистре перед сложением, это только сломает архитектуру (в определенных случаях такой вариант возможен и даже необходим).
Что делать с входным и выходным регистром — решать разработчику, исходя из требований к задержке (латентности) и необходимой максимальной частоте.
Я решил использовать только выходной регистр.
Чтобы этот регистр описывался в коде, сгенерированном HDL-кодером, во вкладке Options в HDL-кодере необходимо поставить галочку в поле Register output и перезапустить преобразование.
В результате получается следующий код: `timescale 1 ns / 1 ns
module TwoMultAdd_fixpt
(clk,
reset,
clke_ena_i,
a,
b,
c,
d,
clke_ena_o,
out);
input clk;
input reset;
input clke_ena_i;
input [7:0] a; // ufix8
input [7:0] b; // ufix8
input [7:0] c; // ufix8
input [7:0] d; // ufix8
output clke_ena_o;
output [16:0] out; // ufix17
wire enb;
wire [16:0] out_1; // ufix17
wire [15:0] TwoMultAdd_fixpt_mul_temp; // ufix16
wire [16:0] TwoMultAdd_fixpt_2; // ufix17
wire [15:0] TwoMultAdd_fixpt_mul_temp_1; // ufix16
wire [16:0] TwoMultAdd_fixpt_3; // ufix17
reg [16:0] out_2; // ufix17
//HDL code generation from MATLAB function: TwoMultAdd_fixpt
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %
// Generated by MATLAB 9.2 and Fixed-Point Designer 5.4 %
// %
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
assign TwoMultAdd_fixpt_mul_temp = a * b;
assign TwoMultAdd_fixpt_2 = {1'b0, TwoMultAdd_fixpt_mul_temp};
assign TwoMultAdd_fixpt_mul_temp_1 = c * d;
assign TwoMultAdd_fixpt_3 = {1'b0, TwoMultAdd_fixpt_mul_temp_1};
assign out_1 = TwoMultAdd_fixpt_2 + TwoMultAdd_fixpt_3;
assign enb = clke_ena_i;
always @(posedge clk or posedge reset)
begin : out_reg_process
if (reset == 1'b1) begin
out_2 <= 17'b00000000000000000;
end
else begin
if (enb) begin
out_2 <= out_1;
end
end
end
assign clke_ena_o = clke_ena_i;
assign out = out_2;
endmodule // TwoMultAdd_fixpt
Как видите, в коде есть принципиальные отличия по сравнению с предыдущей версией.
Появился всегда-блок, представляющий собой описание регистра (именно то, что мы хотели).
Для работы всегда-блока также появились входы модуля clk (тактовая частота) и сброс (сброс).
Видно, что выход сумматора фиксируется в триггере, описанном всегда.
Еще есть пара сигналов включения ena, но они нам не очень интересны.
Давайте посмотрим на схему, которую сейчас синтезирует Quartus.
Рисунок 5
И снова результаты хорошие и ожидаемые.
На рисунке ниже представлена таблица используемых ресурсов — имейте это в виду.
Рисунок 6
Mathworks получает оценку за это первое задание.
Все не сложно, предсказуемо и с желаемым результатом.
Я достаточно подробно описал простой пример, привел схему блока DSP и описал возможности использования настроек использования регистров в HDL-кодере, отличных от настроек «по умолчанию».
Это было сделано не просто так.
При этом я хотел подчеркнуть, что даже в таком простом примере при использовании HDL-кодера необходимы знания архитектуры ПЛИС и основ цифровой схемотехники, а настройки нужно менять осознанно.
HLS-компилятор от Intel
Попробуем собрать аналогичный по функционалу код, написанный на C++, и посмотреть, что в итоге синтезируется на ПЛИС с помощью HLS-компилятора.Итак, код на C++.
component unsigned int TwoMultAdd(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
{
Теги: #Электроника для начинающих #Высокая производительность #C++ #hls #matlab #FPGA #verilog #HDL
-
12 Неписаных Правил В Дизайне
19 Oct, 24 -
Поиск Google Переехал На Новый Веб-Сервер.
19 Oct, 24 -
Беспроводное Электричество Показали На Ted
19 Oct, 24 -
Действительно Ли Социальная Среда — Чушь?
19 Oct, 24