Создание reusable-code на Verilog

codereuse

Написание многократно используемого кода при проектировании цифровых устройств на Verilog

Введение в reusable-code

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

Прежде всего, важно писать так называемый reusable (многократно используемый) код. Вместо того, что бы каждый раз изобретать велосипед, намного лучше взять уже готовы    й код, который протестирован должным образом и нет сомнений в его работоспособности. При чем для компании-производителя в 90% случаев оказывается экономически более выгодным использовать как можно больше готовых наработок.

Именно поэтому сейчас производство цифровой микросхемы, в основном, сводится к сбору различных модулей, соединение их вместе(для этого существуют стандартные шины, наиболее популярными являются AMBA и Wishbone) дополнение своими специфическими наработками, и комплексное тестирование получившейся системы.

Исходя из вышесказанного очевидно, что написанный код должен быть максимально понятен стороннему разработчику. В идеальном случае сторонний разработчик может вообще не знать о внутреннем устройстве модуля, при этом ему важен лишь интерфейс и принцип работы. Например, если есть некоторый цифровой DSP-фильтр, предназначенный для фильтрации голоса и подавления сторонних шумов, то использующему модуль разработчику может быть совершенно не важна внутренняя реализация такого модуля: ее понимание может потребовать множество часов рабочего времени, и если так поступать постоянно, то конечный продукт может оказаться просто нерентабельным. Вместо этого разработчик смотрит спецификацию модуля DSP-фильтра, и используя простой интерфейс к нему(например, задав пару параметров, отвечающих за чувствительность) уже может включить этот модуль в свой проект. В программировании такой подход называют инкапсуляцией.

 

Условия, необходимые для написания reusable-кода

Verilog HDL предоставляет все возможности для написания многократно используемого кода.

  • Прежде всего код должен быть хорошо документирован и снабжен комментариями. Ведь вполне возможно, что в дальнейшем кто-то захочет внести в код изменения.
  • Каждый модуль должен быть максимально параметризирован. Для этого в Verilog HDL есть ключевые слова parameter (с ’95) и localparam (с ‘2001). В основном localparam используется для упрощения восприятия кода, что бы избавиться от «магических чисел», либо чтобы защитить важные значения от ошибочного нечаянного изменения разработчиком. В свою очередь parameter и является основным инструментом для параметризации модулей. Таким образом, лучше написать один параметрический счетчик и задать нужные разрядности в момент создания экземпляра, чем писать несколько отдельных, почти идентичных счетчиков.
  • Следует пользоваться возможностями условной компиляции. Существует множество применений «словно компилируемых» ключевых слов Verilog HDL(таких как ‘define ‘ifdef ‘ifndef и т.д.). Так например, вместо того, что бы сначала писать код для ПЛИС Xilinx, а затем портировать его на ПЛИС Altera, намного лучше сразу предусмотреть такую ситуацию и описать критичные к железу участки кода в отдельных блоках. При этом то, какой именно блок используется будет зависеть от заданного `defineом параметра. А вместе с использованием возможностей скриптовых языков, таких как Python для задания необходимых условий компиляции можно сделать сборку проекта действительно гибкой.
  • Если разработка ведется на уровне вентилей(gate-level), то параметризации модулей можно достичь используя конструкцию generate Verilog HDL. Однако gate-level modeling является довольно сложным подходом, особенно если необходимо сделать модуль параметрическим. Написание кода на низкоуровневом verilog’e в ненужных местах может оказаться пустой тратой времени.
  • Многократно используемую комбинационную логику можно выносить в функции, таким образом одну функцию можно описать в отдельном файле и подключить сразу в несколько модулей. Конечно перед применением такого подхода следует задуматься о действиях выполняемых функцией, иногда использование экземпляров модулей является более прозрачным и понятным. Например, в функцию стоит вынести комбинационную схему, вычисляющую СRC-контрольную сумму от вектора строго заданной длины, поскольку сама CRC по определению является хеш-функцией.
  • Важно помнить о несинтезируемых конструкциях, они очень полезны при построении testbench’ей. Например, используя task можно сделать свой testbench логичным и удобным.
  • Каждому модулю нужен свой testbench. Конечно, верификация является отдельной темой в мире цифровых устройств, верификацией проектов часто занимаются совсем другие люди, нежели цифровые дизайнеры написавшие код проекта. Верификация сложных проектов это весьма непростая задача, требующая построения всеобъемлющих testbench’ей, затрагивающих все возможные ситуации в работе цифрового устройства. Крупные компании-производители микросхем часто привлекают для верификации обычных программистов, имеющих весьма отдаленное представление о цифровой схемотехнике. Тем не менее, важно тестировать код на каждом этапе. Если этого не делать, сложность тестирования возрастает в геометрической прогрессии и тестирование сложного устройства становится просто невозможным. Тем более, если отсутствует testbench конкретного модуля, то будет не с чем сравнивать результаты работы готового устройства, используещего этот модуль. Testbench должен предоставлять тестировщику максимально простой интерфейс к модулю, но при этом дать возможность отлавливать все граничные и ошибочные ситуации.
  • Не стоит смешивать синтезируемые и несинтезируемые конструкции. В противном случае код может моделироваться, но не синтезироваться, что очевидно повлечет дополнительные затраты времени на «разбор полетов»

Примеры проектов с использованием подхода с многократно-используемым кодом:

Автор: Ходнев Т.А., ДК-11.