Показаны сообщения с ярлыком verilog. Показать все сообщения
Показаны сообщения с ярлыком verilog. Показать все сообщения

понедельник, 4 сентября 2017 г.

Как начать работать с HDL и ПЛИС (FPGA)

Предисловие

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

Современные тенденции

К сожалению, а может быть и к счастью (в зависимости как на это посмотреть) разработка современной электроники, особенно цифровой, но не только сводится к описанию цифровых функций и автоматов сводится к описанию их на основе одного из HDL (Hardware Description Language) -языков описания аппаратуры. На данный момент, существуют следующие языки описания аппаратуры: AHDL, VHDL, Verilog и System Verilog. Сами ПЛИС (CPLD, FPGA) представляют собой квадратные матрицы ячеек (состоящих из сотен - тысяч, в зависимости  от ресурсов ПЛИС, логических элементов), к этим ячейкам подходят магистрали источников синхросигналов (клоков) и линий питания (+5 или +3,3 В) и земли.  К слову говоря, современные ПЛИС (7 серия от Xilinx, 5 поколение Cyclone и т.п.) - это SoC в которых кроме, самой ПЛИС присутствует процессорное ядро и аппаратная поддержка различных интерфейсов таких, как : USB, Ethernet, CAN, SPI, I2C, RS232 и др.

Три кита разработки цифровых устройств с использованием ПЛИС (FPGA)

 1. Основа всего это алгебра логики (булева алгебра) и способы построения простых цифровых схем и автоматов с использованием алгебры логики.

2. Схемотехника входных и выходных каскадов логических элементов (для понимания, что такое высокоимпедансное Z-состояние, нагрузочные характеристики элементов, схемы с открытым коллектором).

3. И, конечно, 3 этап это способы построения простых цифровых схем с использованием языков описания аппаратуры.

Алгебра логики

Основными в алгебре логики являются следующие вещи:

1) Принцип двойственности
2) Теорема Де-Моргана 
 
 Эти два принципа можно посмотреть, например, здесь: https://studme.org/2002061028280/tovarovedenie/algebra_logiki . Позже сам напишу про алгебру логики.

Так же следует упомянуть про способы представления (алгебраическое, табличное и в виде карт/диаграм Карно и Вена) и минимизации логических функций через карты Карно или другие методы, например, метод Мак-Класки (https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%9A%D1%83%D0%B0%D0%B9%D0%BD%D0%B0_%E2%80%94_%D0%9C%D0%B0%D0%BA-%D0%9A%D0%BB%D0%B0%D1%81%D0%BA%D0%B8).

Одна неплохая презентация про алгебру логики: https://drive.google.com/file/d/0B9GLCHSwsJn8cURyT3BOUEVxdVE/view?usp=sharing

После понимания математических основ цифровой электроники нужно двигаться к способам реализации простых цифровых схем клмбинационной логики (логики не зависящей от состояния схемы):

- мультиплексоры
- дешифраторы
- преобразователи кода
- и другие схемы.

Вот, например, https://drive.google.com/open?id=0B9GLCHSwsJn8NmxtTVNUOVZZbWs

 Следующий шаг - изучение последовательностных схем (схемы зависящие от состояния и сигналов на входе схемы).  Такими схемами являются:

-триггеры
-счетчики
-регистры
-генераторы
и др.

Например, https://distant.msu.ru/pluginfile.php/38192/mod_resource/content/1/%D0%9B%D0%B5%D0%BA%D1%86%D0%B8%D1%8F%204.pdf

или

https://drive.google.com/open?id=0B9GLCHSwsJn8YkJZeGtVZzZ4LTQ

а также ознакомиться с описанием цифровых автоматов (которых, 2 основных вида: Мили и Мура (https://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D1%8B_%D0%9C%D1%83%D1%80%D0%B0_%D0%B8_%D0%9C%D0%B8%D0%BB%D0%B8)

Схемотехника логических элементов

Данный раздел в большей степени относится к разаботке цифровых устройств с использованием дискретных микросхем, однако, в ряде моментов при проектировании с использованием ПЛИС эти знания также оказываются необходимыми

Прежде всего схемотехника зависит от типа логики: ТТЛ (ТТЛШ), КМОП и ЭСЛ: http://www.inp.nsk.su/students/radio/lectures/Pulse/07.pdf

Параметры логических элементов:
 http://myrepititor.ru/electronics/82-Osnovnye_xarakteristiki_i_parametry_logicheskix_eleme.html

http://audioakustika.ru/node/1555

Языки HDL, способы проектирования
У меня довольно большаыя подборка книг по ПЛИС: https://drive.google.com/open?id=0B9GLCHSwsJn8Z0Y3U24ybmxjVjA

Если использовать Verilog, то стоить начать с Verilog и VerilogTutorial, если VHDL - то "Языки Verilog и VHDL", кроме того среди этого архива есть документ с "Золотыми ссылками по HDL".


Что будет в продолжении?

В будущем планирую пройтись по каждому из этих пунктов и написать цикл статей с примерами дизайна цифровых схем (на github).

воскресенье, 18 июня 2017 г.

Gated clock в HDL

Что такое Gated clock (and/or signal ripple) и его последствия

Недавно занимался одним из своих старых проектов (Quartus 9.1) и, перечитывая, в очередной раз, предупреждения компиляции проекта, обнаружил, что появился такой интересный ворнинг : "Found 1 node(s) in clock paths which may be acting as ripple and or gated clocks -- node(s) analyzed as buffer(s) resulting in clock skew".  Данное предупреждение оказалось связано с моим модулем, управляющим работой двухканальным счетчиком (каждый из счетчиков работает попеременно), сам модуль формирует сигнал адреса и сигналы разрешения и сброса счетчиков.

Прежде всего попытаемся понять, что же означает данное предупреждение. А означает оно то, что на линии тактового сигнала (клока) присутствует логический вентиль (gate). Поскольку мы имеем дело с конкретной микросхемой, а не с математической функцией, то прохождение сигнала через логические элементы всякий раз будет добавлять задержку на время переключения вентиля из 0 в 1 или из 1 в 0. Другая часть предупреждения говорит о том, что наличие вентиля будет приводить к пульсациям. На самом деле, в этом случае могут быть проблемы с переключением на линии клока, например, время переключения вентиля 10 нс, на линии клока пришло переключение из 0 в 1 (posedge), за эти 10 нс, предположим клок переключился из 1 в 0 и, потом, снова из  0 в 1 непрерывно с малыми интервалами, так вот gated clock отфильтрует часть переключений и, как следствие, часть важной информации может быть потеряна.

Как же удалось этого добиться?

Сам удивляюсь как я смог спроектировать такую ерунду, но вот часть кода, описывающая мой модуль.

assign counter0_enable = ~counter_address;
 assign counter1_enable = counter_address;

d_trigger counter0_force_clear_trigger (.clk(counter0_enable), .data(vcc), .reset(counter0_reset), .enable(enable), .out(counter0_force_clear));
- d_trigger counter1_force_clear_trigger (.clk(counter1_enable), .data(vcc), .reset(counter1_reset), .enable(enable), .out(counter1_force_clear));

counter_address генерируется периодически по другому сигналу с помощью Т-триггера. Самое интересное, что к этому эффекту приводит генерация сигналов в counterХ_enable через триггер. И как же быть в такой ситуации? Почитав, что пишут в интернетах и немного подумав, я использовал для клока триггеров исходный сигнал, а операцию выбора работы триггера по адресу перенес в enable (т.е. force_clear сигналы генерируются только в моменты когда enable на триггерах равен 1):

d_trigger counter0_force_clear_trigger (.clk(~channel), .data(vcc), .reset(counter0_reset), .enable(enable & counter1_enable), .out(counter0_force_clear));
+ d_trigger counter1_force_clear_trigger (.clk(channel), .data(vcc), .reset(counter1_reset), .enable(enable & counter0_enable), .out(counter1_force_clear));
На RTL View данная ситуация (gated clock) проявляется следующим образом:










Согласно этому изображению, проблема в шунтировании двух D-триггеров гэйтами.

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



суббота, 3 июня 2017 г.

Странности в Verilog-2001


Немного истории или появление ПЛИС и HDL
Ха-ха, здравствуйте-здравствуйте, дорогие читатели. Недавно я писал про странности, связанные с софтом, а именно - Vivado, но дело дошло до самого языка.Вообще для программирования FPGA/PLD/ПЛИС используют языки программирования, позволяющие описать прохождение цифровых электрических сигналов и реакцию цифровых схем на эти сигналы. В данной статье я не буду затрагивать вопросы, связанные с цифровой схемотехникой, булевой алгеброй (алгеброй логики и т.п.). Прообразом ПЛИС стали Программируемые логические матрицы (ПЛМ/PLM), построенные на основе N-в-1 логических элементах (ИЛИ/И), к которым подведены от 1 до N сигналов. Программирование осуществляется с помощью плавления перемычек между входами логических элементов:
Любая логическая функция и любые последовательностные схемы могут быть реализованы на базисных элементах. 

После ПЛМ появились ПЛИС представляющие собой несколько десятков слоев ПЛМ (например, семейство MAX7000). Далее ПЛИС стали сохранять конфигурацию во внутреннюю оперативную память, а конфигурация при старте загружалась с Flash-памяти.

Для описания связей между  логическими элементами (задания какие перемычки нужно включить, а какие убрать) были придуманы языки для описания аппаратуры (HDL): AHDL, VHDL и Verilog.  Наиболее востребованными являются 2 последних, лично я предпочитаю Verilog, т.к. он отдаленно напоминает классику - язык С, а VHDL - Pascal.

Этот странный Verilog

В этом разделе я опишу, пожалуй лишь несколько из странностей Verilog.

1. Доступ к параметрам модуля из функции

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

module my_module #
(
      parameter PARAM_1 = 1
)
(
    // ports defenitions
);

localparam _PARAM_1_LOC = PARAM_1;

function[1:0] some_func();
// local variables defined here ...
      // <!!!!! в этой функции мне недоступен PARAM_1, но доступен PARAM_1_LOC
endfunction;

endmodule

Несмотря на то, что функция some_func принадлежит модулю my_module у нее нет доступа к параметрам модуля, но есть доступ к локальным параметрам.

2. Инверсия порядка бит в байте

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

reg[7:0] byte_vector;

reg[7:0] inversed_byte_vector;
 // где-то внутри always
inversed_byte_vector = byte_vector[0:7]; // ОШИБКА КОМПИЛЯЦИИ

 К сожалению, это не работает, приходится использовать конкатенацию или цикл:

inversed_byte_vector = {byte_vector[0], byte_vector[1], ....byte_vector[7]}


3. Доступ к вектору по индексам

 Известно, что чтобы получить доступ к произвольной части вектора достаточно обратиться к нему указав индексы, по которым необходимо сделать срез:

reg [31:0] my_vector;
reg [7:0] vector_part;

// где-то внутри always блока
vector_part = my_vector[29:22];

Но доступ по индексам возможен только тогда, когда передаются константы, поэтому приходится городить такие конструкции.

// присвоение внутри функции
reg[7:0] shift;
begin
shift = `MAX_DATA_WIDTH - NUMBER_OF_BYTES * 8;
// потом я не могу вырезать данные так:
result = data[MAX_DATA_WIDTH : shift]; // ошибка

для того, чтобы получить то, что я хочу, я должен сделать так:
result = data[`MAX_DATA_WIDTH - 1 : `MAX_DATA_WIDTH - NUMBER_OF_BYTES * 8];

 4. Чудесный мир литералов

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

my_reg  = 8'b10001111; // Разрядность в битах, одинарная кавычка, латинская "бэ" и бит за битом (старшие биты идут вперед).

Но, что делать если нужно записать значение в 16-ричной системе счисления, т.к. 64 бита писать нереально утомительно, даже если пользоваться конкатом, для этих целей существует представление hex-литералов:

my_reg = 64'hAABBCCDDEEFF0011;
Хоть синтаксис и С подобный, но никаких тебе 0x и т.п.

Это не баги, это фичи
Verilog, конечно же, неплох, для описания HDL, но хочется, чтобы таких неудобств в нем было как можно меньше, учитывая, что последний раз стандарт выходил в 2001 г., а сам язык является наиболее популярным для программирования ПЛИС. Поэтому ждем перемен (с).

среда, 17 мая 2017 г.

Как справиться с багами в Vivado (Xilinx)

Предыстория 

До недавнего времени моя работа с ПЛИС (FPGA, PLD) касалась лишь работы с микросхемами серии MAX7000 Altera (Intel), на тот момент времени мне казалось, что хуже Altera ничего нет из-за изобилия недостатков их ПО (Quartus), например:

  • - компилятор Altera не синтезировал ряд синтаксических конструкций: циклы, не позволял иметь более 2х always-блоков внутри одного модуля.
  • - сам Quartus обожал абсолютные пути, которые впоследствии удалось заменить на относительные через "." и "..", разбивал настройки проектов на несколько файлов (из-за чего я не сразу мог их найти) поэтому для настройки проектов на разных машинах приходилась вбивать руками пути и т.п.
Мое мнение об превосходной отвратительности ПО Altera прожило ровно до того момента, пока я не погрузился в чудесный мир от Xilinx с Vivado. Начал я с последней, на тот момент времени (осень 2016),  версией - 2016.2 Сам перенос проекта на другую версию Vivado сопряжен с рядом проблем, о которых я напишу позднее, поэтому до полной реализации устройства я не решился переносить проект и продолжил работу с 2016.2.

Сказать ужасно значит вовсе не описать качества продуктов Xilinx.

1. Документация по софтовым продуктам, чипам, проектированию и т.п. доступна в разных документах с именами UGXXX, где XXX - номер документа. Документация временами и правда UG, многие вещи необходимо искать в многостраничным pdf, в которых на зерно информации тонна воды, документы не всегда актуальны (созданы для более ранних версий Vivado).

2. Сам принцип дизайна, у 12-13 версий Quartus проектирование строилось относительно создания топового модуля с использованием HDL, у Xilinx нужно нарисовать блок дизайн, затем на основе него создать топовый модуль,  причем обязательно нужно создавать процессорное IP - ядро и IP-ядро сброса, подцеплять к минимальной системе источники тактового сигнала (клок), подцеплять DDR оперативку и т.п. Хотя это SoC, поэтому тут все сложнее, чем для более простых семейств ПЛИС, но тем не менее Xilinx  не предусмотрела ситуации когда мне нужно только логические ячейки без всех наворотов (без AXI и т.п.).

3. Работа Vivado: сотни предупреждений на собственные IP-ядра (ядра от Xilinx) при синтезе.

4. Дизайн: ориентирован на IP-ядра, а не на модули. Я не думаю, что на легковесные модули типа таблицы преобразований или инвертора нужно создавать IP-ядро, однако Vivado сильно параноит при использовании модулей.

5. Ресурсы. Очень долго выполняется синтез и имплементация проекта занимающего процентов 10-20% всех ресурсов от Zynq-7020. Например на 4-ядерном E2-6110 (слабенький 1,5 ГГц и TDP всего 15 Вт) полный цикл - 1 час. На топовых процессорах летает (на моем i7 - 1-2 минуты). По ощущениям Quartus на слабых машинах работал в разы быстрее. На аппаратной виртуальной машине, созданной на KVM с 4 ядрами и 5 Гб оперативки может упасть с Out Of Memory Exception (даже жирный своп не помогает от этой болезни).

6. Кривые и забагованные Vivado и Xilinx SDK, которые могут вылететь и закончить работу по абсолютно любым причинам с потерей всех результатов работы (на практике я не решился использовать частичный результат работы синтеза или имплементации при вылете на одном из шагов для продолжения с этого шага).

7. Отсутствие средств для инверсии логических сигналов на блок-дизайне (да мне пришлось создать модуль инвертора с телом в 3 строчки verilog кода)

8. Куча других более мелких причин...

Использование СКВ (системы контроля версий) для работы с проектом 

Наиважнейший момент при разработке на ПЛИС. Отдельную функциональность/фичу я реализую в отдельной ветке и потом уже объединяю с основной ветвью (как правило, это master). На мой взгляд, идеальный выбор это git, для ряда своих проектов я использую github. У меня была ситуация когда по непонятным причинам код в двух ветках оказался полностью нерабочим, я не мог ничего сделать несмотря на массу попыток и относительно простых изменений в дизайне, поэтому пришлось откатиться на ветку, от которой я создал ранее обе эти ветви. Если бы у меня не было СКВ или СКВ с неудобной работой с ветками (CVS, Subversion) я бы попал в неприятное положение (получил бы нерабочий дизайн в trunk) и, возможно, мне пришлось бы создать весь дизайн заново.

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

./src - директория с моими HDL - исходниками, если использовать %ProjectName%.srcs/sources_1/..., то, во-первых, это выглядит ужасно, а, во-вторых, мы получим кашу из генерируемых Vivado файлов и собственных HDL-исходников, сама же Vivado любит на каждый чих делать толпу изменений в файлах. Если вы что-то поменяли в одном из модулей и желаете сделать коммит изменений одного конкретного модуля, то такой подходя позволяет быстрее находить измененные модули в списке измененных файлов .
/tests - файлы тестбенчей на HDL-модули
/constraints - директория для сохранения файлов ограничений (как временных, так и физических), здесь ситуация аналогичная с src
/app - рабочее пространство (воркспэйс) С/С++ Xilinx SDK-проектов (софтина, созданная на базе Eclipse, но с бОльшим числом проблем, чем у Eclipse.
/config - файлы аппаратной конфигурация SoC.
/ip - каталог моих IP-ядер.

Чтобы в коммите не было по 1000+ изменений файлов (я не шучу их реально несколько сотен минимум), нужно правильно настроить .gitignore (список не отслеживаемых файлов/директорий с возможностью задания имен по шаблону). Например, в качестве образца можно использовать такой шаблон: https://github.com/OpticalMeasurementsSystems/2DImageProcessing/blob/master/.gitignore

А вот и сами проблемы

Описания самих проблем будет значительно меньше по объему, чем всей предыстории. Если мне удастся записать видео в момент наступления проблемы и ее решения, то позднее я добавлю ссылку и на видео. Список при обнаружении проблем и решения будет обновляться.

1. Синтез/имплементация падают с генерацией исключения и демонстрацией мессадж бокса - проблема в кэше, для лучшего эффекта стоит удалить директории %ProjectName%.hw, %ProjectName%.cache, %ProjectName%.runs.

2. Синтез/имплементация зависли на длительное время - некоторые проблемы, когда Vivado падает не отображаются в виде мессадж боксом, но они видны в окне Log. Решение сбросить синтез имплементацию (нажать на кнопку Cancel в правом верхнем углу), прибить директорию %ProjectName%.runs.


3. На блок дизайне не обновляется размер некоторых портов, например, Concat IP-ядро. Для этого можно попробовать сначала сбросить Output Products (Reset Output Products при клике правой кнопкой мыши по экземпляру HDL Wrapper'а в иерархии исходных файлов модулей), а затем сгенерировать их заново (Generate Output Products).

4. При запуске Xilinx SDK появляется Splash Screen, потом пропадает, сам SDK не запускается. Нашел 2 причины с проблемами запуска SDK:
       1) Оказалось, что у меня на компьютере было установлено 2 версии Java Development Kit (x32 и x64 параллельно), удалил x32 и SDK стал запускаться без проблем.
       2) Хардкорное решение: удаление папки .metadata, тогда из воркспэйса пропадают все проекты кроме hardware platform, восстановить проекты легко File->Import->General->Existing Project Into Workspace, выбрать галочками необходимые для импорта проекты, нажать ОК.
Видео рения этой проблемы здесь: https://www.youtube.com/watch?v=R_dwpoqsmX4

      3) [Дополнение]: Заметил, что если удалить файл lock в metadata и директорию  eclipse.cdt.ui из плагинов там же в metadata, то можно избежать повторного муторного добавления проектов в воркспэйс (не знаю, работает ли это во всех случаях или нет).

5. Неожиданно перестал собираться BSP, вероятно, в воркспеэйсе появился доп. хардварный проект, а BSP связан с другим железом, для решения этой проблемы удаляем все лишние hardware проекты и обновляем железный проект через правый клик по проекту -> Change Hardware Description File (выбираем экспортированный hdf) и вуаля, после этого можно собрать BSP и приложение.


6. Не открывается репозиторий одним из гит клиентов (GitKraken и т.п.) - это связано с запущенным SDK, который блокирует доступ к скрытой директории .git, решение - закрыть SDK.

Почему все так ужасно?

Можно сказать, что это болезнь всего ПО, заточенного под Embed-проектирование, оно все, как правило, ужасно и изобилует большим количеством багов, а современные тенденции к генерации HDL-кода из ПО для моделирования типа Matlab + SimuLink приводят к разрастанию самого кода ввиду неоптимальных подходов, плохой поддержке этого кода, к созданию "одноразового (write only)" кода и т.п., уменьшают порог вхождения и увеличивают степень энтропии создаваемого продукта людьми далекими от какого-либо понимания принципов работы цифровой электроники и программирования.


Распространение Windows-приложений (Chocolatey)

Менеджеры пакетов для ОС Windows В большинстве дистрибутивов Linux есть свои менеджеры пакетов: в Ubuntu/Mint это apt и deb, в OpenSuse э...