Pull to refresh

Схемотехника и язык программирования Verilog

Reading time5 min
Views14K
Хочу рассказать про свои впечатления о языке программирования Verilog. Он используется для описания аппаратуры. Еще проще сказать для описания архитектуры микросхем. Я начал использовать его в своих проектах недавно. Тем не менее, мне кажется, я «почувствовал его вкус».

Небольшое отступление от темы…
Для начала, из любопытства, давайте посмотрим немного хабровской статистики на момент написания этой статьи. Делаю поиск по ключевым словам java, c++, python, verilog, vhdl:

java: 1581 топик;
си ++: 598 топиков;
python: 995 топиков;

и

Verilog: 6 топиков
VHDL: 5 топиков (и кстати, это те же статьи, где упоминается Verilog).

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

Особенно поразила меня сегодняшняя статья на Хабре «Самостоятельное изучение схемотехники. Основные понятия. Часть 1» (вот здесь habrahabr.ru/blogs/arbeit/91922). Честно сказать не могу себе представить, чтобы люди изучали схемотехнику и при этом не упомянули про современные языки описания схем…

Отчего же так? Можно сделать два предположения. Либо разработчики аппаратуры в нашей необъятной стране в основном не читают хабр (в чем я сомневаюсь), либо микроэлектроника в у нас, к сожалению, умерла безвозвратно.

Можно конечно и по-охать: «умерла, так умерла»… А можно и пытаться кое что сделать.
В самом деле, в настоящее время разработка микросхем может вестись практически «на коленках» с использованием микросхем CPLD и FPGA. Если проект «пойдет», то можно будет позже перейти на eAsic или даже (при наличии инвесторов) на настоящий ASIC…
И даже совсем не обязательно иметь фабрику — все знают пример fabless компании ARM. Удачный дизайн процессора запатентован, и тиражируется уже сторонними компаниями в своих изделиях.

Все, что нужно для начала — это выбрать плату разработчика (Developer Kit) по потребностям и по карману. К счастью, приобрести плату разработчика в нашей стране не проблема. Например, компания ЭФО на сайте www.altera.ru предлагает приобрести платы для экспериментов от нескольких производителей: Altera, Terasic, LDM-Systems. Там конечно в списке есть и монстры по 7000$, но есть и недорогие платы по 150$. Если и это дорого, для начала, можно посоветовать совсем простые платы типа Марсоход (http://www.marsohod.org — кстати российская open-source разработка) — это около 1000 рублей.
Программная среда разработки для начальных изысканий так и вовсе бесплатна: например, Altera QuartusII Web Edition.

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

Язык Verilog весьма элегантен, не требует лишней писанины, и чем-то похож на Си.
Я хочу показать небольшие примеры и, самое главное, — ассоциации кода и результирующей схемы netlist. Мне кажется очень это важным. Современные программисты весьма «развращены» виртуальной памятью и мощью процессоров. При программировании для микросхем важно понимать, как оно получится на самом деле «внутри чипа». Каждый дополнительный код в программе оборачивается дополнительными триггерами и логическими элементами в проекте. В конечном счете все это сказывается на быстродействии, размере кристалла и потреблении электроэнергии.

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

Комбинаторная логика — это просто логические функции от входных данных, сигналов. Стоит одному из входных сигналов измениться, и сразу меняется (пересчитывается) вся функция. В реальных условиях отклик, конечно, немного запаздывает по времени.

Ну вот, например, функция расчета сигнала четности для 32 битной шины PCI. Нужно вычислить XOR от всех 32-х входных линий адресов/данных AD[31:0] и еще четырех сигналов CBE[3:0]. Если Вы рисуете схемы, то всего нужно нарисовать 35 двух-входовых логических элементов XOR и соединить их проводами.

На языке Verilog можно написать небольшой модуль для вычисления бита четности.
Выглядеть он будет так:

module pci_parity(
input wire [31:0]ad,
input wire [3:0]cbe,
output reg parity
);

always @*
begin
parity = ad[ 0] ^ ad[ 1] ^ ad[ 2] ^ ad[ 3] ^
ad[ 4] ^ ad[ 5] ^ ad[ 6] ^ ad[ 7] ^
ad[ 8] ^ ad[ 9] ^ ad[10] ^ ad[11] ^
ad[12] ^ ad[13] ^ ad[14] ^ ad[15] ^
ad[16] ^ ad[17] ^ ad[18] ^ ad[19] ^
ad[20] ^ ad[21] ^ ad[22] ^ ad[23] ^
ad[24] ^ ad[25] ^ ad[26] ^ ad[27] ^
ad[28] ^ ad[29] ^ ad[30] ^ ad[31] ^
cbe[0] ^ cbe[1] ^ cbe[2] ^ cbe[3];
end

endmodule


В этом коде особо следует обратить внимание на сочетание always @* — это как раз и обозначает то, что выходной сигнал всегда «пересчитывается» при изменении любого входного сигнала.

Еще лаконичней то же самое можно написать так:

module pci_parity(
input wire [31:0]ad,
input wire [3:0]cbe,
output wire parity
);

assign parity = (^ad) ^ (^cbe);

endmodule


Здесь унарный оператор "^" используется как reduction — то есть как раз XOR между всеми битами вектора ad[31:0].

Как посмотреть, что у нас получилось после компиляции в чипе? Я использую Altera QuartusII. После компиляции можно запустить программу RTLViewer (это часть среды QuartusII) и увидеть получившуюся «схему» после оптимизации компилятором.
Для обоих примеров кода pci_parity результат один и тот же:

image

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

Напишем на языке Verilog простой счетчик:
module my_counter
(
input wire clk,
output reg [3:0]counter
);

always @(posedge clk)
begin
counter <= counter + 1;
end

endmodule


Обратите внимание на строку always @(posedge clk) — эта строка как раз говорит о том, что процесс синхронный, связанный с фронтом сигнала clk. Опять откомпилируем с помощью QuartusII и посмотрим в RTLViewer, что у нас получилось:

image

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

Немного изменим наш модуль вот так:
module my_counter
(
input wire reset,
input wire clk,
output reg [3:0]counter
);

always @(posedge clk or posedge reset)
begin
if(reset)
counter <= 0;
else
counter <= counter + 1;
end

endmodule


Я добавил в модуль входной сигнал асинхронного сброса и изменил правило «always @».
Опять компилируем и смотрим получившийся RTL:

image

Как я и обещал, входной сигнал reset является для триггеров асинхронным сбросом.

Продолжаем наши эксперименты. Сделаем, например десятичный счетчик:
module my_counter
(
input wire reset,
input wire clk,
output reg [3:0]counter
);

always @(posedge clk or posedge reset)
begin
if(reset)
counter <= 0;
else
begin
if(counter==9)
counter <= 0;
else
counter <= counter + 1;
end
end

endmodule


Второй if в нашей программе модуле будет управлять мультиплексором для загрузки в регистры либо нуля, либо очередного значение счетчика.
Смотрим, что мы имеем после компиляции:

image

Действительно if «превратился» в мультиплексор.

Ну вот как-то примерно так.
На Verilog просто писать, просто моделировать. Современные средства проектирования делают изучение схемотехники действительно доступным. Наличие широкого набора плат разработчика позволяет довольно легко пробовать проект в железе.
Tags:
Hubs:
+18
Comments29

Articles

Change theme settings