В очередной раз, начав изучать что-то новое для себя, я столкнулся с типичной для меня проблемой: нет нигде быстро гуглящегося how-to и step-by-step руководства по быстрому созданию какой-либо простой конструкции на Verilog и описания способа эту конструкцию быстро симулировать без необходимости запуска кода в железе для проверки конечного результата. Я надеялся очень быстро найти готовый материал о том, как под Altera Quartus 20.1 и ModelSim 2020.1 под Linux всё по-быстрому сделать и идти дальше. В итоге не найдя ничего системно и последовательно описанного в одном месте я традиционно разобрался самостоятельно и решил это исправить своей очередной статьей на Хабре. 

Возможно, этот материал поможет таким же как я новичкам на самом старте и позволит не растерять энтузиазм во время танцев по граблям. Всем, кто заинтересовался — добро пожаловать под кат. 

image


Дисклеймер. Перед началом повествования, хотелось бы заранее оговориться, что основная цель, которую я преследую при написании этой статьи — рассказать о своем опыте. Я не являюсь профессиональным разработчиком под ПЛИС на языке SystemVerilog и могу допускать какие-либо ошибки в использовании терминологии, использовать не самые оптимальные пути решения задач, etc. Но отмечу, что любая конструктивная и аргументированная критика только приветствуется. Что ж, поехали…

Постановка задачи


Итак. Представим, что вы абсолютный новичок в области ПЛИС aka FPGA и вот однажды вы услышали, интересные рассказы о том, что с помощью одного из языков описания аппаратуры (HDL) можно решать разнообразные задачи с очень высокой скоростью и при этом параллельно, т.е. одновременно. Первым вопросом, которым задался я как новичок когда услышал про ПЛИС — а с чего начать? На тот момент мне казалось, что все начинается с отладок с нужным чипом и примеров. Я без особого понимания критериев отбора, чем отличаются Altera от Xilinx — быстренько заказал себе отладку на Cyclone IV и после того как получил — научился создавать и запускать простейшие проекты. Каждая правка исходного проекта и проверка сопровождалась ожиданием синтеза, роутинга, заливкой прошивки в ПЛИС для проверки и отладки с помощью светодиодов и кнопок и SignalTap. И чем сложнее были примеры — тем больше времени я тратил на ожидание синтеза, рассовывания пробников отладчика по сигналам и тут я начал задумываться о том, что возможно что-то тут я делаю не так. А если вспомнить, что SignalTap занимает в ПЛИС тоже некоторое количество логических блоков и в сложных проектах он уже не умещался в ПЛИС — ситуация точно требовала изменения подхода.

И тут я начал вникать в то, как организуют процесс разработки в среде профессионалов — я понял, что я упустил тут один очень важный шаг — симуляцию и тестирование с помощью т.н. testbench-ей. 

Вникнув и разобравшись — я захотел поделиться своим опытом в этом материале и при написании этой статьи я поставил для себя несколько задач: разобрать вопрос создания простого проекта в Altera Quartus под Linux и как запустить его симуляцию в ModelSim, с попутным объяснением как решить возникающие проблемы, коих по ходу дела возникает немало (вполне возможно, что только у меня).

Задачи для меня и моего уровня вполне достижимые, давайте расскажу и покажу как я их решал.

Общий flow разработки под ПЛИС


Вообще, отдельно стоит рассказать о том, как работают с ПЛИС профессионалы и что следует взять себе за ориентир. Ниже, я попытался обобщить в виде схемы свое представление о алгоритме разработки под ПЛИС. Коротко опишу каждый из этих этапов. Оговорюсь сразу, что в рамках этой статьи я рассмотрю только первые три интересующих нас этапа. 

image

Идея и техническое задание. Пункт с вполне понятным смысловым наполнением. На этом этапе формируется идея будущего устройства, что он должен уметь делать, чего делать не должен. На основании идеи формируется уже техническое задание которое отражает в форме измеримых величин требования для конечного устройства.

Реализация HDL-кода. На этом этапе происходит основная часть работы — в HDL-коде реализуется конечный автомат или группа из таковых, вместе со всеми багами, корявостями и синтаксическими ошибками ????.

Функциональное и поведенческое моделирование (например, в ModelSim). А вот на этом этапе происходит, на мой взгляд самое интересное. Здесь как раз и происходит первая проверка полученного результата, а не напрямую в ПЛИС, как я делал до этого. 

В ходе реализации проекта, на каждом этапе когда находятся те или иные ошибки — происходят доработки и исправления — и все начинается по новому циклу. В целом все достаточно просто. Вот реализацию этого флоу я хочу отразить на конкретном примере с картинками и разбором всех граблей. 

Создаем проект в Quartus


Итак, казалось бы, что может быть проще: создаем проект и запускаем ModelSim, пишем тестбенч и проверяем, что всё работает как нужно. Я так думал, когда первый раз хотел, что-нибудь прогнать через симуляцию. Но не тут-то было. Но обо всё по порядку. 

Открываем Quartus и создадим новый проект:

image

Жмем New Project Wizard, откроется мастер и можно идти по шагам.

image  

Жмём Next и указываем каталог, в котором будет жить наш проект, заполняем его имя.

image

Тыкаем кнопку Next и указываем, что мы создаем пустой проект, выбрав пункт Empty project

image

Файлы никакие добавлять не будем, поэтому жмякаем Next. 

image

В следующем меню выбираем модель чипа с которым вы работаете, в моем случае это EP4CE6F17C8.

image

А вот в последнем меню в пункте Simulation нужно выбрать ModelSim-Altera и SystemVerilog HDL (если конечно именно он используется, а не VHDL или Verilog HDL например). 

image

Просматриваем Summary, проверяем нет ли ошибок и жмем Finish

image

Откроется окно пустого проекта и можно приступать к его наполнению и настройке.

Наполняем проект смыслом


Реализуем первый этап из флоу — т.е. составим техническое задание: необходимо реализовать на языке SystemVerilog модуль, который на входе будет иметь два логических сигнала A и B, и один на выходе Y, который будет результатом логической операции & (AND) от A и B. Идея достаточно простая и эту, казалось бы простую задачу, можно реализовать аж тремя путями. 

Рассмотрим каждый из вариантов:

  • Gate Level, то есть через представление в виде логических элементов:

module AND_GATE(output Y, input A, B);
  and(Y, A, B);
endmodule

  • Data flow, то есть через обозначение направления потока данных:

module AND_DATA_FLOW(output Y, input A, B);
  assign Y = A & B; 
endmodule

  • Behavioral, то есть поведенческий подход, в котором происходит работа с изменениями состояний сигналов:

module AND_BEHAVIORAL(output reg Y, input A, B);
always @ (A or B) begin
   if (A == 1'b1 & B == 1'b1) begin
       Y = 1'b1;
   end
   else 
       Y = 1'b0; 
end
endmodule

Какой из вариантов вам больше нравится — такой и выбирайте. Мне нравится больше подход Data Flow.

Создаем новый файл в меню File — New — System Verilog HDL File. Откроется редактор, и запишем интересующий вариант модуля:

image

Далее сохраняем файл и даем ему соответствующее его роли название:

image

Теперь нужно добавить файл Top-Level entity, в котором будет находиться модуль, который мы будем пропускать через симуляцию. Для этого в Project Navigator с включенным видом Files кликаем правой кнопкой и выбираем пункт Set as Top-Level Entity:

image

В меню сообщений будет следующая строка: Info (125061): Changed top-level design entity name to «Top». 

Теперь можно запустить анализ и синтез:

image

Но Quartus выдаст нам ошибку, что якобы Error (12007): Top-level design entity «Top» is undefined.

image
 
Что ж, придется снова указать, кто в проекте Top-level Entity. Выбираем в Project Navigator вид отображения Hierarchy, кликаем правой по Top и Settings:

image

Выбираем первый пункт в меню настроек General, далее кликаем по многоточию и выбираем AND_DATA_FLOW и нажимаем ОК и еще раз ОК чтобы закрыть это меню и перезапускаем анализ и синтез:

image

Дожидаемся окончания операции и видим что все окончилось успешно и без ошибок, только предупреждения: 

image

Смотрим в отчет и видим, что израсходован один логический элемент и задействовано три пина. Эта информация может в будущем оказаться весьма полезной: 

image

Идём дальше. Теперь, раз всё компилируется, стоит произвести моделирование полученного дизайна и убедиться что все будет работать как нужно. 

Интеграция Quartus с ModelSim и запуск симуляции


Итак, общий флоу по интеграции ModelSim в процесс разработки под ПЛИС из нескольких этапов:

  • Конфигурирование NativeLink, благодаря которому происходит обмен информацией между Quartus и внешними инструментами, например ModelSim;
  • Компиляция необходимых библиотек Quartus, которыми будет оперировать ModelSim;
  • Написание Testbench (тестового скрипта) и интеграция его в проект;
  • Запуск симуляции, анализ результатов и внесение изменений в проект (при необходимости).

Если не осуществить эту настройку — можно собрать много разнообразных ошибок и ничего не получится. Например, если попробовать просто запустить RTL Simulation

image

То само собой получим ошибку, что EDA Simulation Software настроен:

image

Что ж, перейдем к настройке Native Link. Для этого необходимо перейти в общие настройки Quartus и указать каталог, в котором находится ModelSim. Это делается путем перехода в главном меню Tools — Options

image

Откроется меню настроек и нужно перейти в пункт меню EDA Tools Options и в поле ModelSim и\или ModelSim-Altera указать путь до каталога modelsim_ase/linux так, как это сделано у меня:

image

Далее в настройках проекта тоже необходимо какой тип симулятора используется. Для этого возвращаемся в настройки проекта в Project Navigator (в котором мы устанавливали Top-Level Entity) и переходим в пункт меню EDA Tools Settings и в пункте Simulation выбираем ModelSim-Altera / SystemVerilog HDL:

image

После переходим в пункт Simulation и видим что в пункте настроек NativeLink ничего не настроено и всё нужно сделать своими ручками:

image

На этом этапе необходимо указать файл testbench, которые у нас еще отсутствуют. Перейдем к созданию этих файлов. 

В многих источниках рекомендуют воспользоваться пунктом меню Processing — Start — Start Test Bench Template Writer:

image

Но на этом этапе я столкнулся с ошибкой, что якобы данная опция для SystemVerilog не поддерживается:

image

Окей, попробуем создать файл Testbench самостоятельно в проект и прикрепить его в настройках симуляции руками самостоятельно. Для этого берем создаем новый файл через File — New — SystemVerilog HDL File. 

После создания файла откроется редактор и в него запишем заготовку: 

module and_gate_test_bench;

endmodule

После сохраним файл c именем and_gate_test_bench.sv и возвращаемся в меню NativeLink settings. Выбираем пункт меню Compile test bench и кликаем по кнопке Test Benches

В открывшемся меню Test Benches нажимаем кнопку New… и заполняем настройки следующим образом:

image

Главное указать Top level module in test bench в четком соответствии как это было заполнено в файле в предыдущих шагах. Везде нажимаем OK и выходим. 

Теперь запускаем компиляцию:

image

И видим в сообщениях, что все завершено удачно: 

image

Теперь запуск RTL Simulation из главного меню должен открыть ModelSim, но этого не достаточно т.к. при запуске симуляции будет выданы ошибки о том, что нет необходимых библиотек для симуляции. Поэтому сделаем компиляцию необходимых библиотек.

Для это необходимо перейти в главное меню и нажать Tools — Launch Simulation Library Compiler

image

Откроется меню, в котором нужно указать ModelSim, проверить что в поле Selected families указан Cyclone IV E и что указана директория для сохранения результатов компиляции:

image

Жмём кнопку Start Compilation и ожидаем результатов компиляции. Ожидаем, что компиляция пройдет успешно: 

image

После закрываем окно и попробуем совершить акт симуляции. =)

Пишем Testbench для проекта


Теперь можно перейти ко второму этапу — моделирование и проверка правильности работы полученного кода через Testbench. Как вы уже поняли — Testbench является по сути отдельным модулем написанный на языке HDL, который объявляется в отдельном файле. Поэтому перейдем в наш файл and_gate_test_bench.sv, который мы создали в предыдущих шагах. 

Напомню, что в этой статье я не ставил себе целью подробный разбор как писать testbench-файлы и не планировал рассматривать синтаксис, поэтому приведу код testbench-файла как есть, лишь сопроводив его некоторым количеством комментариев:

module and_gate_test_bench;
	reg A, B;
	wire Y;

	AND_DATA_FLOW DUT(Y, A, B);

	initial begin
		A = 0; B = 0;
	 	#1 A = 0; B = 1;
	 	#1 A = 1; B = 0;
	 	#1 A = 1; B = 1;
	end

	initial begin
		 $monitor ("%t | A = %d| B = %d| Y = %d", $time, A, B, Y);
	end

endmodule

В начале мы объявляем два регистра A и B, чтобы они сохраняли свое значение до тех пор пока не будут назначено новое. Они будут означать входные сигналы. И зададим сигнальный проводник Y, который будет выводить результат. 

После инициализируем экземпляр модуля, созданного в главном файле проекта, с именем DUT, указав сигналы в порядке объявления. 

В модуле initial указываются действия которые исполняются после старта модуля в симуляторе. Соответственно при старте задаются значения сигналов A и B равными нулю и через каждый условную единицу времени изменяем сигналы на новые значения (в соответствии с таблицей истинности модуля).

Плюсом к этому добавляем отладочный вывод в лог симулятора, чтобы помимо временной диаграммы видеть текущие значения входных сигналов и того, что имеем на выходе. Сохраняем полученный testbench-файл и нажимаем Compilation

Запускаем Testbench


Дождавшись результатов компиляции — можно запустить ModelSim и увидеть результаты моделирования. Для этого нужно перейти в главное меню и нажать Tools — RTL Simulation:

image

Если в предыдущих шагах все сделали правильно — то будет запущен ModelSim и выведен лог: 

image

И если увеличить масштаб в Waveform-меню — можно увидеть результат на временной шкале: 

image

Соответственно, зная наперёд как работает логический элемент AND — мы можем сказать что всё сработало верно, результаты соответствуют ожидаемым, как в логе, так и во временной диаграмме. Ну и покуда всё работает верно — нет необходимости переходить к пути коррекции ошибок и можем считать, что задача решена.

Заключение


Вот путём таких не хитрых манипуляций можно достаточно быстро, без реальной железки, проверить свой HDL-дизайн и получить быстрый ответ на вопрос “работает\не работает”. Если вы застряли, на каком-либо из этапов — не стесняйтесь обращаться за помощью в комментариях, возможно я или более опытные коллеги смогут вам помочь. 

Как пользоваться средой моделирования и как раскрыть весь потенциал ModelSim — тема на большое количество статей или даже книгу, тут мы с вами скорее попробовали просто настроить проект перед тем как приступать к более сложным вещам. Но думаю, что много из того, что я буду рассматривать в своих следующих статьях, в той или иной степени, позволит расширить представление о ModelSim и его возможностях.

Если статья вам понравилась — ставьте “подписывайтесь и ставьте стрелочку вверх”. Этим самым вы поддерживаете меня как автора и стимулируете на написание новых материалов для вас. До встречи в следующих статьях! 



Возможно, захочется почитать и это:


Комментарии (1)


  1. anonymous
    00.00.0000 00:00

    НЛО прилетело и опубликовало эту надпись здесь