Исторически так сложилось что ПЛИС я начал изучать только на новой работе.
Это были серии ПЛИС фирмы Altera.
Старшие коллеги на перебой рекомендовали как AHDL так и VHDL для программирования этих микросхем.
В итоге я остановился на языке VHDL, поскольку он является языком высокого уровня, в отличии от ADHL.
Хоть и листинг у последнего был куда приятнее.
И я приступил к изучению всех хитростей и ограничений языка VHDL.
В итоге сошелся на мысли что конструкции языка просто ужасны, а ограничения избыточны для проектирования аппаратуры.
Приведу пример листинга из статьи Делаем таймер или первый проект на ПЛИС
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity Div_27Mhz_to_1Hz is
port
(
clk : in std_logic;
clk_out : out std_logic
);
end Div_27Mhz_to_1Hz;
architecture div_behavior of Div_27Mhz_to_1Hz is
Begin
process(clk)
variable cnt: integer range 0 to 27000000;
begin
if (clk'event and clk = '1') then
if (cnt >= 13500000) then
clk_out <= '1';
else
clk_out <= '0';
end if;
if (cnt = 27000000) then
cnt := 0;
else
cnt := cnt + 1;
end if;
end if;
end process;
end div_behavior;
Подробно описывать как это работает я не буду — достаточно прочитать оригинальную статью. Я же постараюсь выразить свое впечатление от листинга в целом.
Для начала невозможный блок объявления библиотек. Причем библиотеки необходимы даже для часто применяемых типов данных (std_logic) или функция конвертации типов).
Заставьте новичка сделать преобразование внутренней переменной типа integer в тип std_logic_vector и установить это значение на внешний порт!
И что мы получим? Несколько часов мучительных поисков того как же это сделать.
В итоге оказывается, что нам надо:
1. подключить библиотеки:
use ieee.std_logic_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.ALL;
2. запись integer в порт std_logic_vector напрямую невозможна. Необходимо применять специальные функции преобразования типов! (Всегда возмущало понятие типа в проектах для ПЛИС)
std_logic_vector (to_unsgined(, ))
данная запись преобразует младших бит регистра в вектор std_logic_vector.
И того минимум 4 строки для записи числа в порт.
Так же для меня ужасом было явление записи вектора:
vector(M downto N)
или
vector(M upto N)
слова downto и upto просто выводили меня из равновесия своей избыточностью. По моему мнению они являются лишними.
Я уже молчу о том. что числа разных типов пишутся по разному:
integer пишется как нормально число — 1, 2, 3, 4, 5
а вот с std_logic_vector возникают проблемы.
Запись имеет вид '1' и '0' для единичного вектора, а вот вектора 2х и более разрядов по умолчанию НЕ МОГУТ принимать десятичные значения. Только HEX или BIN.
К счастью на этом мое знакомство с этим языком закончилось и я окунулся в религию языков Verilog и SystemVerilog.
Для меня это было откровение!
Никаких лишних записей. Листинг чистый и понятный. Каждый знак имеет оправданный смысл и место.
К сожалению современные компиляторы для ПЛИС не до конца поддерживают стандарт данных языков, от того не все их возможности можно использовать. (В моей личной практике Quartus II плохо понимал проект с использованием процедур и функций.
Так же он плохо понимал классы (или вообще не понимал? уже не помню).
Сравните сами листинг приведенный выше в записи на SystemVerilog:
module Div_27Mhz_to_1Hz
(
input CLK,
output logic CLK_OUT,
output logic[7:0] CNT_OUT
);
integer cnt = 0;
always@(posedge CLK) begin
if (cnt >= 13500000) begin
CLK_OUT <= 1;
end
else begin
CLK_OUT <= 0;
end
if (cnt == 27000000) begin
cnt <= 0;
end
else begin
cnt <= cnt + 1;
end
CNT_OUT <= cnt;
end
endmodule
Как видите количество строк заметно уменьшилось. Сам листинг более прост и однотипен (числа везде записываются как числа). Блок проверки фронта сигнала перекочевал к месту объявления триггера процесса.
Так же я специально расширил функционал модуля для демонстрации удобства и простоты преобразования типа данных.
Как вы можете заметить в описании портов модуля я ввел специальный восьмибитный выходной порт CNT_OUT. Тип данных порта logic.
Тут стоит сделать легкое отступление о типах в SystemVerilog.
В SV есть два основных типа данных:
цепи (wire)
регистры (reg)
все остальные типы данных не воспринимаются Quartus в полной мере и потому мной не использовались.
При этом разница между данными типами (по стандарту) в том, что тип цепь не может принимать значения.
тип данных logic указывает на то, что компилятор волен сам решать что это — цепь или регистр.
Стоит отметить что Quartus вообще игнорирует типы данных SV при компиляции. Его компилятор позволяет использовать wire как регистр и наоборот. Потому применение типа данных logic несколько условно. Мы имеем переменную счетчика типа integer (по умолчанию она 32 бита) и внешний порт вывода типа logic и разрядностью 8 бит.
Строка CNT_OUT <= cnt; делает следующее:
каждый такт в порт CNT_OUT записывается младшие 8 разрядов регистра cnt. (стоит отметить, что в данной записи не указан явно диапазон разрядов для записи в порт.
Потому берется 8 младших).
Таким образом видим, что для преобразования типов SV не требует специализированных библиотек и функций. Все эти задачи решаются компилятором.
Так же в SV есть удобство в виде автоматического выравнивания разрядности данных.
Т.е. если в проекте используется тип данных integer но по логике работы понятно что значение данного регистра не превышает 255 (в десятичной системе),
то после компиляции данный регистр будет 8 разрядным.
Таким образом налицо очередная вольность допускаемая стандартом SV — он не требует явного выравнивания длин регистров.
В общем и целом на мой взгляд листинг SystemVerilog выглядит более гармонично и удобочитаемо. Что достигается отсутствием длинных названий типов данных и строк объявления сигналов и регистров.
Так же проще и аккуратнее реализована запись векторов.
В целом эти языки можно сравнивать гораздо глубже и дольше. Но я уверен, что в бОльшем количестве всех сравнений SV покажет свою красоту, компактность текста и удобство применения.
В общем и целом SystemVerilog придется по вкусу программистам.
Если же вы закоренелый схемотехник то вам по нраву будет AHDL.
Я не привожу его в сравнении т.к. он совсем другая тема и сравнивать его с приведенными в статье языками, все равно что сравнивать ассемблер и С.
Автор: axi01