Коротенькое сравнение VHDL и Verilog в помощь начинающим знакомство с ПЛИС

от автора

Исторически так сложилось что ПЛИС я начал изучать только на новой работе.
Это были серии ПЛИС фирмы 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.
Я не привожу его в сравнении т.к. он совсем другая тема и сравнивать его с приведенными в статье языками, все равно что сравнивать ассемблер и С.

ссылка на оригинал статьи http://habrahabr.ru/post/191606/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *