Программирование Xilinx FAQ Sat, November 17 2018  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


FAQ Печать
Добавил(а) microsin   

В этой статье приведены решения различных проблем, возникающих при создании программируемой логики на микросхемах Xilinx (CPLD, FPGA).

Стандартный способ ответвления от шины - подключение к шине отводов с помощью кнопки "Add Bus Tap":

ISE WebPack ECS Add Bus Tap button

После этого от отвода рисуется проводник цепи, и присваивается ему подходящее по смыслу имя (потому что по умолчанию цепям автоматически назначаются бессмысленные имена на основе автоматической нумерации цепей, наподобие XLXI_137, и т. п.). Присвоение нужного имени осуществляется кнопкой Add Net Name:

ISE WebPack ECS Add Net Name button

Имя назначается для подключенной к отводу цепи таким образом, чтобы обозначить нужный проводник в шине. К примеру, у нас есть шина Q(7:0), это шина из 8 сигнальных проводников. Цепь каждого проводника шины Q в отдельности именуется как Q(7), Q(6), .., Q(0). Поэтому если нужно подключить отвод от шины к определенной цепи шины, то нужно проводнику этого отвода дать соответствующее имя. Например, если нужно подключиться к проводнику Q(5) шины, то на выходе из отвода нужно дать имя цепи Q(5).

ISE WebPack ECS Add Net Name example

Следует помнить, если Вы делаете подключение к части шины входов (не ко всем её проводникам), то на не подключенные входные разряды шины будет автоматически подан сигнал лог. 0.

[Соединение друг с другом двух шин]

Если шины имеют одинаковую разрядность, то никакой проблемы нет - просто надо нарисовать линию связи от начала шины до её конца.

ISE WebPack ECS connect busses

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

ISE WebPack ECS connect partial busses wrong

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

ISE WebPack ECS connect partial busses OK

При самых обычных действиях - при попытке добавления в проект файла *.ucf, при компиляции проекта среда _pn.exe завершается по ошибке "_pn.exe has stopped working". У меня так происходило в 64-битной Windows 8.1 для одного языка.

Причина в глючности 64-битной версии. Решение состоит в том, чтобы запускать 32-битную версию. Для этого исправьте свойства ярлычков, которые запускают Project Navigator. 64-битная версия запускается со следующей командной строкой:

X:\ISE\14.4\ISE_DS\settings64.bat X:\ISE\14.4\ISE_DS\ISE\bin\nt64\ise.exe

Исправьте путь запуска на 32-битную версию так:

X:\ISE\14.4\ISE_DS\settings32.bat X:\ISE\14.4\ISE_DS\ISE\bin\nt\ise.exe

run 32bit ISE WebPack

При синтезе дизайна VHDL в WebPACK происходит ошибка:

ERROR: (VHP__0808). имямодуля.vhd строка. + can not have such operands in this context
EXEWRAP detected a return code of '1' from program 'xst'
EXEWRAP complete - 0 errors, 0 warnings.
Done: failed with exit code: 0001.

Решение: если в коде VHDL используются любые арифметические операнды, то подключите для этого соответствующие пакеты IEEE, unsigned или signed (зависимости от типа используемых операндов).

use ieee.std_logic_unsigned.all;

или

use ieee.std_logic_signed.all;

ERROR:Simulator:904 - Unable to remove previous simulation file
 isim/имяфайла_isim_beh.exe.sim/имяфайла_isim_beh.exe. Please
 check if you have another instance of this simulation running
 on your system, terminate it and then recompile your design.
 System Error Message: boost::filesystem::remove: 
 "isim\имяфайла_isim_beh.exe.sim\имяфайла_isim_beh.exe"
 
ERROR:Simulator:861 - Failed to link the design

Причина в том, что симулятор iSIM уже запущен, и система по какой-то причине не может удалить файл предыдущей симуляции. Чтобы исправить ошибку, нужно закрыть iSIM, после этого заново запустить симуляцию. Если это не помогает, то выполните Project -> Cleanup Project Files..., и опять запустите симуляцию.

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

ISim show output XXXX

Здесь символы 'X' справа от выходной шины COUNT показывают неизвестное значение (Forcing Unknown). Причина в том, что симулятор не знает начального значения регистра счетчика, который попадает на выходы COUNT. Вот код счетчика (Verilog), который не работал в симуляторе (красным шрифтом показана строка, где нужно выполнить инициализацию регистра):

module top(
    input XTALIN,
    output [3:0] COUNT
    );
 
reg [3:0] counter;
 
always @(posedge XTALIN)begin
   counter = counter + 1;
end
 
assign COUNT = counter;
 
endmodule

Исправление ошибки:

reg [3:0] counter = 0;

Теперь симулятор правильно показывает изменения выхода COUNT:

ISim show output OK

Пример кода VHDL (генератор буквы "Ж" кода Морзе):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
 
entity top is
    Port ( XTALOUT1 : out  STD_LOGIC;
           XTALOUT2 : out  STD_LOGIC;
           XTALIN   : in  STD_LOGIC;
           MORSE    : out  STD_LOGIC);
end top;
 
architecture Behavioral of top is
constant v : unsigned ( 15 downto 0 ) := "1010101110000000";
signal clk : STD_LOGIC;
signal COUNT : unsigned (3 downto 0) := "0000";
 
begin
   -- Кварцевый генератор:
   clk <= not XTALIN;
   XTALOUT1 <= clk;
   XTALOUT2 <= not clk;
 
   -- Счетчик, по которому должны выбираться биты из константы v:
   process (clk) begin
   if clk'event and clk='1' then
      COUNT <= COUNT - 1;
   end if;
   end process;
 
   MORSE <= v(COUNT);
 
end Behavioral;

Строка, выделенная красным цветом, выдаст ошибку "ERROR:HDLParsers:821 - "имямодуля.vhd" строка. Wrong index type for v.". Здесь была сделана попытка применить вектор COUNT в качестве индекса.

Исправление ошибки:

   MORSE <= v(to_integer(COUNT));

1ns означает шкалу времени для симулятора, а 1ps означает точность учета времени для него. Единицы времени, указанные здесь, применяются при создании тестовых сигналов, подаваемых на вход тестируемой в симуляторе схемы. Например:

#1;       // Эта строка означает задержку в 1 нс
#0.001;   // Задержка 0.001 нс - минимальная, которая может быть
          // с настройкой шкалы "`timescale 1ns/1ps"
#0.0001;  // С этой шкалой времени задержка получится 0 нс!

Переключите дизайн в режим симуляции:

ISE WebPack change iSim simulation time1

В разделе Processes разверните пункт ISim Simulator, щелкните правой кнопкой мыши на пункт Simulate Behavioral Model и выберите в контекстном меню Process Properties...

ISE WebPack change iSim simulation time2

Измените настройку Simulation Run Time (по умолчанию там стоит время симуляции 1000 нс), кликните OK.

ISE WebPack change iSim simulation time3

Чем больше время симуляции, тем дольше будет вычисляться симуляция. Не устанавливайте здесь время больше 1 секунды (1000000000ns).

Простейшую вроде бы схему Fitter не может разместить на кристалле, и выдает ошибку наподобие:

ERROR:Cpld:887 - Cannot fit the design into this device.
ERROR:Cpld:868 - Cannot fit the design into any of the specified devices with
   the selected implementation options.

Причина скорее всего в том, что в Вашем файле ограничений дизайна (*.ucf) определены не все входы и выходы проекта. Для таких выходов система синтеза присваивает этим выходам свойства по умолчанию, которые настроены в проекте. В таком случае, если тип выхода выводов, которые назначены в файле UCF, не совпадают с типом выводов по умолчанию, и у фиттера не получится растасовать выводы разного типа по разным банкам I/O, то произойдет именно такая ошибка.

Как решить проблему? Есть как минимум 3 варианта, выберите любой по вкусу:

1. Можно в файле UCF корректно определить ВСЕ входы и выходы.
2. Можно вообще удалить файл UCF, тогда система сама назначит свойства выводов в соответствии с настройками по умолчанию проекта.
3. Поменять настройки по умолчанию проекта так, чтобы они соответствовали назначенным в файле UCF атрибутам выводов кристалла.

По умолчанию при создании для проекта шаблона модуля тестовых сигналов (File -> New Source... -> Verilog Test Fixture) в нем содержатся только определения для отображения только внешних портов схемы. При попытке добавить в блок Unit Under Test (UUT) внутреннего сигнала ISim при запуске выдаст ошибку:

ISim launch error show internal signal

При этом в файл лога isim.log будет записано примерно следующее:

ERROR: "имямодуля.vhd" строка n.  On entity block stimulus/uut/: attempted to connect to
 Port имявнутреннегосигнала which does not exist.ERROR: Time resolution is 1 fs
# onerror resume
# wave add /
No active Database
# run 1000000000 ns
Unable to execute live simulation command.

Как все-таки добиться просмотра в симуляторе любого внутреннего сигнала проекта? Можно конечно создать для этого сигнала порт out, и назначить его свободному выводу микросхемы.

Однако есть и более простой способ вручную отобразить вывод сигнала в симуляторе ISim. Для этого сделайте следующее:

1. Перейдите в ISim на закладку Instances and Processes. Если она почему-то не показывается, то это можно включить через меню View -> Panels. 

ISim show internal signal1

2. Кликните на треугольничек возле имени файла Velilog, в котором подготовлены сигналы для симуляции (в примере на скриншоте это stimulus.v). В развернутом дереве Вы увидите объект uut, кликните на него, чтобы выделить.

ISim show internal signal2 ISim show internal signal3

3. Перейдите на закладку Objects. Здесь Вы увидите все внутренние сигналы проекта.

ISim show internal signal4

4. Найдите в списке интересующий Вас сигнал. Например, нас интересует сигнал lfclk. Выберите его в списке, и нажмите комбинацию клавиш Ctrl+W (или кликните на нем правой кнопкой мыши и выберите в контекстном меню Add To Wave Window).

ISim show internal signal5

5. Запустите пересчет симуляции через меню Simulation -> Restart (или Ctrl+Shift+F5), и затем Simulation -> Run All (F5). Теперь на диаграмме будет показан новый внутренний сигнал lfclk, который мы выбрали.

ISim show internal signal6

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

[VHDL]

· Со строгим контролем типов
· Более подробный
· Высокая однозначность описания логики (детерминистический)
· Синтаксис и стиль мышления сильно отличается от языка C

[Verilog]

· Со слабым контролем типов
· Более краткий
· Детерминистический только в том случае, если Вы тщательно следуете некоторым правилам
· Больше похож на язык C

Ошибки Вы можете найти позже при симуляции проекта потому что от них никто не застрахован ни при использовании VHDL, ни при использовании Verilog (как и любого другого языка).

Также Verilog предпочитают использовать для конечной проверки логики проекта (в частности, на Verilog по умолчанию создаются шаблоны тестовых сигналов для симулятора ISim Xilinx), и в настоящее время все больше и больше разработчики переходят на язык SystemVerilog (фактически это очень значительное расширение Verilog).

Начиная с версии ISE 11.1, Xilinx больше не поддерживает Test Bench Waveform Editor. Когда проект, в котором есть test bench waveform (TBW), обновляется до версии 11.1, то TBW будет автоматически преобразован в HDL test bench, и добавлен в проект. Xilinx рекомендует для новых проектов использовать тесты (HDL test benches), написанные на основе HDL. Для дополнительной информации о создании HDL test bench см.:

• ISE Language Templates for starter examples site:xilinx.com
• Application Note XAPP199, Writing Efficient Test Benches site:xilinx.com
• Synthesis and Simulation Design Guide site:xilinx.com

Хорошее, простое руководство на Youtube:

• Creating a Simple VHDL Testbench site:youtube.com

Симулятор ISim предоставляет Test Bench Waveform Editor, в котором Вы можете графически определять тесты (test benches или (test fixtures). В Test Bench Waveform (TBW) Вы можете определить сигнал (stimulus) и длину теста (test bench length), чтобы проверить свой дизайн без необходимости знания HDL или скриптового языка. Определяемый Вами TBW можно добавить в проект ISE. Затем Вы можете использовать этот TBW для управления симуляцией своего дизайна точно так же, как используется для этой цели HDL test bench.

В любой момент времени Вы можете просмотреть HDL эквивалент своей формы сигнала (waveform), используя в среде ISE функцию View Generated Test Bench as HDL process.

При просмотре и определении TBW в редакторе Test Bench Waveform Editor редактирование осуществляется в исходном коде HDL source code. Это редактирование включает переименование портов, добавление и удаление сигналов, что будет отражаться на графическом отображении сигнала (graphic test bench waveform).  COREGen For more information, see Modifying Ports.

Оператора #1 на Verilog не существует. Есть оператор #, который имеет много разных смыслов, в зависимости от контекста использования. Обычно # используется для представления задержки для выражения, значение которой указывается после #. И опять-таки, нужно знать контекст, чтобы определить единицы задержки, так как 1 может означать 1 наносекунду, 1 микросекунду или что-то еще.

У Verilog есть несколько абстракций, разработанных для быстрой симуляции. Одна из них это простая модель сигналов 0/1/X/Z (+strength), другая это разрешающая способность тактов, которая указывается в начале файлов, например:

`timescale 1ns/1ps   // 1ns представляет опорное время, и 1ps это значение точности

В этом контексте "#1" это шаг во времени опорной тактовой частоты - использование малых целочисленных значений упрощает планирование событий (event scheduling), и потребляет меньше памяти. Тогда #1 станет соответствовать 1000 "тикам", если 1ps это самая большая точность, видимая в дизайне - что может быть сохранено в 16 битах (число short).

"#0" может использоваться для проталкивания текущего потока обратно к текущему слоту времени, что также известно как задержка "delta".

Примечание: VHDL для задержек использует высокоточное время в формате с плавающей точкой (double размером 64 бита).

#1 показывает задержки в Verilog для модели. #1 обычно используется для моделирования комбинационных задержек и задержек триггера.

Например, если я хочу моделировать задержку выхода D-триггера, то должен написать следующий код Verilog:

`timescale 1ns/100ps
 
reg q;   // выход триггера
wire d;  // вход триггера
 
// Моделирование D-триггера на Verilog
always @(posedge clk)  begin
   q <= #2 d;     // модель задержки clk->q 2ns на базе шкалы времени
end

Еще пример:

input ld;
reg ld_r;
always @(posedge clk) ld_r <= #1 ld;

Выражение always @(posedge clk) соответствует триггеру, но что тут делает #1? Ответ: ничего. Эти задержки будут игнорироваться системой синтеза, так что если Вы используете этот код в рабочем проекте, то есть некий риск, что он будет в нем работать не так, как в симуляторе.

Первое, что нужно понимать - язык C это язык программирования, а Verilog и VHDL это языки описания аппаратуры (Hardware Description Language, HDL). Это фундаментальные отличия между этими двумя типами языков.

Языки программирования используют для написания последовательности кода, который может быть выполнен на какой-то аппаратуре, чтобы получить нужные результаты, например математические операции, редактирование текста и т. п. С другой стороны, HDL-языки используются для создания полного функционального описания какой-либо аппаратуры, например блока арифметических операций (arithmetic logic unit, ALU), микроконтроллера (MCU) или даже микропроцессора (CPU)! Имеются специальные инструменты автоматизации разработки электроники, используемые для трансляции HDL-описания в реальный аппаратный компонент, реализованный в кремнии. На этом аппаратном компоненте Вы могли бы даже выполнить программу, написанную на C. Удивительно, не правда ли?

Вернемся к вопросу по алгоритмам DSP. На самом деле мы используем для них как C, так и Verilog/VHDL, однако их использование очень специфично для конкретного приложения.

Некоторые операции / алгоритмы часто используются в DSP, это такие операции, как конволюция, преобразование Фурье и т. п. Для их разработки мы используем специальные аппаратные блоки, и в результате получаем такие примитивы, как кольцевые буферы, ALU, модули быстрого преобразования Фурье БПФ (Fast Fourier Transform, FFT), массивы регистров и т. д. Эти блоки присутствуют внутри специализированных коммерческих процессоров DSP, имеющихся на рынке.

Предположим, что необходимо извлечь низкочастотный разговор их записанных выборок аудиосигнала. Звучит просто. Вам просто нужно разработать ФНЧ. Как Вы это кодируете? Конечно же на языке C. Вы также можете использовать любой другой язык программирования, однако C всегда самый популярный выбор. Затем Вы можете использовать компилятор, чтобы преобразовать программу на C в машинный код, который потом можно запустить на выбранном процессоре DSP. По сути Вам не нужно беспокоиться о том, что происходит внутри процессора. В процессоре уже имеются встроенный узлы ALU и FFT, которые заботятся о низкоуровневых операциях, и компилятор имеет для них встроенную поддержку. Реализации в программном обеспечении дает Вам дополнительную гибкость. Можно в любой момент поменять код C и запустить его на том же самом оборудовании. С другой стороны, если была выбрана реализация того же самого алгоритма с помощью HDL и логики, то нужно выпустить на заводе другой чип кроме случая, когда система реализована в FPGA.

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

Мы используем Verilog или VHDL для описания и разработки аппаратуры, которая будет размещена либо в специальной микросхеме (Application Specific Integrated Circuit, ASIC), или запрограммирована в кристалл FPGA, чтобы сконфигурировать его для требуемой аппаратуры.

Если нужно запустить DSP-алгоритм на определенном DSP-процессоре, то мы пишем для него специальную программу, реализующую нужный алгоритм, после чего запускаем эту программу на DSP-процессоре.

Если нам нужно создать новую схему, которая должна поддерживать какой-то отдельный алгоритм DSP, то используем для разработки FPGA или ASIC.

Итак, на практике ЛЮБОЙ алгоритм может быть как написан на C, так и реализован в виде схемы на уровне RTL с помощью HDL-языков описания аппаратуры. Перед разработчиком стоит задача выбора реализации - что реализовать в программе, а что в аппаратуре. C и HDL это просто инструменты в форме языков, и их соответствующие компиляторы преобразуют код этих языков соответственно в последовательно выполняемый код и работающую аппаратуру. Выбор между аппаратной и программной реализацией диктуется многими факторами и метриками, такими как требуемая скорость обработки (аппаратно реализуемая схема на FPGA вероятно будет иметь меньшую задержку и большую пропускную способность по сравнению с процессором DSP), отношение производительность / потребление энергии, форм-фактор устройства (память для набора инструкций процессора, такого как DSP или микроконтроллер, обычно меньше, чем память для хранения соответствующей конфигурации логики в большинстве FPGA), цена (FPGA обычно дороже), требования к обработке в реальном времени, требования по энергопотреблению, необходимое время вывода продукта на рынок (разработка на FPGA занимает больше времени), стоимость разработки (FPGA сложнее программировать), стоимость поддержки, исправления багов, удобство обновления прошивки и т. д. Также имеют значение опыт и предпочтения разработчика. О каждом из этих факторов стоит подумать, прежде чем принять решение о конкретной реализации - будет ли она реализована программно, аппаратно, или же это будет гибридный проект (FPGA + DSP).

Обычно говорят, что если Вы изучили один язык программирования, то скорее всего довольно легко изучите другой язык программирования. Причина тут в том, что все языки программирования используют единую концепцию (принцип работы), различия между ними только в синтаксисе.

У разработчика аппаратуры предметная область знаний коренным образом отличается. Если Вы не прекратите думать как программист C, то жизнь в качестве программиста VHDL сведет Вас с ума. Причина тут не только в разнице синтаксиса, но еще и в том, что концепция этих языков совершенно различна. Оба отличаются друг от друга по базовому принципу работы, а общие их черты поначалу будут вводить большую путаницу.

Ниже представлены базовые отличия между программированием на C и программированием на VHDL (то же самое можно сказать о Verilog и любом другом HDL-языке).

1. Язык C это язык "среднего" уровня, т. е. он занимает некое промежуточное положение между языком ассемблера и языком высокого уровня. На языке C можно добиться довольно точного (но не с абсолютной точностью) заданного поведения программы, если не в реальном времени, то в контексте выполнения какого-либо алгоритма.

2. VHDL это язык описания аппаратуры (hardware description language, HDL). Он используется для реализации аппаратной схемы.

3. C может обрабатывать инструкции только последовательно, каждая выполняется во времени строго перед завершением предыдущей. В действительности язык C не имеет никаких встроенных средств по управлению/анализу реального времени.

4. VHDL позволяет реализовать как последовательное выполнение каких-то действий, так и параллельное, конкурентное. HDL-язык позволяет очень точно управлять ресурсами логики в контексте реального времени.

5. Программа C может быть успешно написана только в контексте чисто логических или алгоритмических действий. Обычно не требуется глубоких знаний аппаратуры, на которой выполняется программа (из этого есть исключения, зависящие от приложения, в целом только подтверждающие правило).

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

7. При программировании на C обычно не задумываются о ресурсах (имеется в виду процессорное время и память). Причина в том, что обычно программа на C (после обработки компилятором) запускается на мощном процессоре под управлением операционной системы. Имеется достаточный запас по как по вычислительным ресурсам, так и по ресурсам памяти (конечно, из этого тоже есть исключения, когда проектируется система реального времени с помощью микроконтроллера или процессора DSP).

8. Когда разработка осуществляется на VHDL, Вы сталкиваетесь с большими ограничениями по ресурсам. Память и количество других логических элементов ограничена плотностью (емкостью) FPGA (это чип, для которого пишется прошивка на VHDL), причем ресурсы FPGA довольно дороги. По этой причине очень трудно, к примеру, реализовать обработку изображения на VHDL, чем сделать то же самое на C.

9. Разработка на VHDL требует выполнения дополнительных шагов по проверке реализации работы кода - сначала в виде симуляции, а потом и на реальной аппаратуре. Это требует специальных итераций в разработке, что занимает больше времени, поэтому разработка на VHDL обходится дороже.

[Ссылки]

1. В чем разница между VHDL, Verilog и SystemVerilog?

 
Top of Page