VHDL (Very High Speed Integrated Circuits)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 17:30, 8 июня 2016.
VHDL
Парадигма concurrent, reactive
Первый   появившийся 1980s
Печать дисциплины strong
Портал: IEEE VASG
Под влиянием
Ada, Pascal

VHDL (VHSIC, англ. Very High Speed Integrated Circuits – Hardware Description Language) разрабатывался как язык описания аппаратуры для высокоскоростных интегральных схем. Первоначальное назначение языка заключалось в обеспечении обмена проектами между различными соисполнителями работ по созданию сверхскоростных интегральных схем. Однако позже с учетом предложений и рекомендаций известных специалистов в области ВС язык был усовершенствован и стандартизован Институтом инженеров по электротехнике и радиоэлектронике (IEEE), в результате чего в 1987 году был утвержден стандарт IEEE Standard 1076 VHDL.

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

VHDL является формальной записью, предназначенной для описания функции и логической организации цифровой системы. Функция системы определяется как преобразование значений на входах в значения на выходах. Причем время в этом преобразовании задается явно. Организация системы задается перечнем связанных компонентов. Язык предназначен для моделирования преимущественно на вентильном уровне, уровне регистровых передач и корпусов микросхем, он успешно используется и при синтезе устройств. VHDL - не единственный язык проектирования радиоэлектронной аппаратуры (HDL - Hardware Design Language). Так, для проектирования интегральных схем широко применяется Verilog, находят применение языки Cupl, Palasm, Ample и др., но для сквозного проектирования на всех требуемых для СБИС уровнях (выше схемотехнического) предназначены только VHDL и Verilog. Преимущества VHDL по сравнению с Verilog следующие:

  • Промышленный стандарт IEEE
  • Не зависит от конкретной технологии или производителя
  • Код может использоваться многократно[1]

Лексические элементы

Текст описания на языке VHDL состоит из одного или более файлов проекта. Файл проекта представляет собой последовательность лексических элементов, каждый из которых составлен из строго определенного набора символов. Текст каждого модуля проекта является последовательностью отдельных лексических элементов. Каждый лексический элемент - это либо ограничитель, либо идентификатор (который может быть служебным словом), либо абстрактный литерал, либо символьный литерал, либо строковый литерал, либо битово-строковый литерал, либо комментарий.

VHDL поддерживает три различных стиля для описания аппаратных архитектур. Первый из них – структурное описание" (structural description), в котором архитектура представляется в виде иерархии связанных компонентов. Второй – "потоковое описание" (data-flow description), в котором архитектура представляется в виде множества параллельных регистровых операций, каждая из которых управляется вентильными сигналами. Третий – поведенческое описание" (behavioral description), в котором преобразование описывается последовательными программными предложениями, которые похожи на имеющиеся в любом современном языке программирования высокого уровня.

Рис. 1. Основные стили языка.

Основными понятиями в языке VHDL являются.

  • ОБЪЕКТ ПРОЕКТА (entity) представляет собой описание компоненты проекта, имеющей чётко заданные входы и выходы и выполняющей чётко определённую функцию. Объект проекта может представлять всю проектируемую систему, некоторую подсистему, устройство, узел, стойку, плату, кристалл, макроячейку, логический элемент и т. п. В описании объекта проекта можно использовать компоненты, которые, в свою очередь, могут быть описаны как самостоятельные объекты проекта более низкого уровня.
  • ОБЪЯВЛЕНИЕ ОБЪЕКТА ПРОЕКТА (entity declaration) описывает интерфейс и определяет только входы и выходы объекта проекта.
  • Для описания поведения объекта или его структуры служит АРХИТЕКТУРНОЕ ТЕЛО (architecture body). Чтобы задать, какие объекты проекта использованы для создания полного проекта, используется ОБЪЯВЛЕНИЕ КОНФИГУРАЦИИ (configuration declaration).
  • В языке VHDL предусмотрен механизм пакетов для часто используемых описаний, констант, типов, сигналов. Эти описания помещаются в ОБЪЯВЛЕНИИ ПАКЕТА (package declaration).
  • Если пользователь использует нестандартные операции или функции, их интерфейсы описываются в объявлении пакета, а тела содержатся в ТЕЛЕ ПАКЕТА (package body).

Таким образом, при описании цифровых схем на языке VHDL возможно использование пяти различных типов описаний: объявление объекта проекта, архитектурное тело, объявление конфигурации, объявление пакета и тело пакета. Каждое из описаний является самостоятельной конструкцией языка VHDL, может быть независимо проанализировано анализатором и поэтому получило название МОДУЛЬ ПРОЕКТА (design unit).

Рассмотрим пример программы, выполняющей шифрование данных алгоритмом RC5. Программный комплекс, реализующий соответственно шифрование, состоит из 2 частей – программной и аппаратной. Программная реализация выполнена на языке C#, аппаратная – на языке VHDL.

Основной функцией части программного комплекса «RC5 C#» является шифрование входных данных алгоритмом RC5 32/12/5 средствами ПЭВМ, отправка данных на шифрование на программируемую интегральную микросхему (ПЛИС) и прием результата ее работы.

Основной функцией части программного комплекса «RC5 VHDL» является шифрование входных данных алгоритмом RC5 32/12/5 средствами ПЛИС, прием входных данных со стороны ПЭВМ и отправка результата на ПЭВМ.

Текст программы “RC5 VHDL” реализован в виде символической записи на исходном языке. Исходным языком данной разработки является VHDL. Среда разработки – компилятор Quartus II (нелокализованная английская версия).

Описание изделия

Изделие представляет собой хрупкий прибор. Оно состоит из программируемой логической интегральной микросхемы Cyclone II EP2C20F484C7 (далее ПЛИС), кабеля USB-COM и программного обеспечения. Шифруемые данные и ключ шифрования передаются с ПЭВМ посредством кабеля Gembird, далее обрабатываются на ПЛИС и отправляются обратно на ПЭВМ аналогичным путем.

Подготовка к эксплуатации

Следует аккуратно, придерживая плату рукой, подключить кабель питания (USB-blaster, поставляется в комплекте) к слоту USB 2.0 ПЭВМ и к USB Blaster Port выходу платы (см. рис. 2). Далее необходимо нажать кнопку включения Power ON/OFFSwitch (см. рис. 2). Характерным признаком того, что плата включилась корректно, является мигание диодов и семисегментных индикаторов. В случае, если этого не произошло, следует попробовать перезагрузить плату и, в случае повторного возникновения неисправности, обратиться к техническим специалистам.

Чтобы сменить прошивку платы на необходимую со стороны ПЭВМ необходимо свободно распространяемое программное обеспечение Quartus II и программное обеспечение «RC5 VHDL», разработанное в рамках данного программно-аппаратного комплекса. Открыв «RC5 VHDL» в Quartus II штатными средствами ПЭВМ, следует произвести следующие действия:

  • Зайти в меню «Tools»;
  • Выбрать пункт меню «Programmer»;
  • В появившемся диалоговом окне нажать кнопку «Hardware Setup»;
  • В появившемся диалоговом окне выбрать пункт «USB Blaster»;
  • Нажать кнопку «Close»;
  • Нажать кнопку «Start».

Для использования изделия необходимо подключить USB-COM переходник к ПЭВМ и плате соответственно. На плате следует пользоваться слотом RS-232 Serial Port (см. рис. 2). На ПЭВМ – любым из доступных USB-портов. Взаимодействие платы с ЭВМ осуществляется при помощи последовательного порта. Программа осуществляет открытие и настройку COM-порта. Так же она обеспечивает пересылку и прием сообщений средствами COM-порта.

Рис. 2. ПЛИС Altera

Выполнение программы

Программа осуществляет шифрование блоков данных по 8 байт пятибайтовым ключом по 12-раундовой модификации алгоритма RC5. Шифрование осуществляется программным методом. Для шифрования данных программными средствами оператору необходимо нажать кнопку «Зашифровать (программа)» (см. рис. 3). Далее все действия будут выполнены автоматически. Предварительно необходимо заполнить поля ввода текста «Ключ» и «Открытый текст» соответствующими значениями в шестнадцатеричном коде (по 2 символа на байт). Правила заполнения этих полей занесены во всплывающие подсказки. Пример всплывающей подсказки см. на рис. 4. В случае ошибочно ввода на экран будет выведено сообщение о соответствующей ошибке.

Рис. 3. Общий вид окна
Рис. 4. Всплывающая подсказка

В ходе выполнения программы возможны некоторые ошибки:

  1. Введенный ключ имеет длину, отличную от пяти байт. Причиной ошибки является то, что программа не предусматривает шифрование ключом произвольной длины. Для ее устранения необходимо скорректировать введенные данные.
Рис. 5. Сообщение об ошибке-неверно введен ключ
  1. Формат введенных данных не совпадает с требуемым. Необходимо вводить данные в шестнадцатеричной системе счисления. Для устранения ошибки необходимо скорректировать формат ввода данных.
Рис. 6. Сообщение об ошибке – неверный формат данных
  1. Введены некорректные данные о COM-порте. Программа не может открыть порт с указанными параметрами. Для устранения ошибки необходимо уточнить имя COM-порта, посредством которого передаются данные, и корректно ввести его в соответствующее поле.
Рис. 7. Сообщение об ошибке – неверные данные о ком-порте
  1. Введен слишком длинный входной вектор. Программа не предусматривает шифрование более 255 блоков по 8 байт за один раз.
Рис. 8. Сообщение об ошибке – длина входного вектора превышает установленную длину

Описание алгоритма

В данном алгоритме использованы следующие операции:

  • сложение по модулю 2;
  • побитовое исключающее ИЛИ (XOR);
  • операции циклического сдвига на переменное число бит (<<, >>).

Шифрование по алгоритму RC5 состоит из двух этапов. Процедура расширения ключа и непосредственно шифрование. Перед непосредственно шифрованием данных выполняется процедура расширения ключа. Процедура генерации ключа состоит из четырех этапов:

  • Генерация констант;
  • Разбиение ключа на слова;
  • Построение таблицы расширенных ключей;
  • Перемешивание;

На этапе «Генерация констант» генерируются две псевдослучайные величины, используя две математические константы: (экспонента) и (Золотое сечение). Для данной реализации значения констант следующие:

  1. P32=B7E1516316;
  2. Q32=9E3779B916.

На этапе «Разбиение ключа на слова» происходит копирование ключа поблочно в массив байтов L.

На этапе «Построение таблицы расширенных ключей» происходит построение таблицы расширенных ключей, которая выполняется следующим образом:

  • S0= P32;
  • Si-1= S32 + Q32.

На этапе «Перемешивание» циклически выполняются следующие действия:

  • A = Li = (Li + A + B) << 3;
  • H = Lj = (Lj + A + B) << (A + B);
  • i = (i+1) mod 26;
  • j=(j+1) mod c, где с = b/8, b - длина ключа.

Далее происходит непосредственно шифрование. Перед первым раундом выполняются операции наложения расширенного ключа на шифруемые данные.

  • A = (A + S0);
  • B = (B + S1).

В каждом раунде выполняются следующие действия:

  • Ai+1 = ((Ai + Bi) << Bi + S2i;
  • Bi+1 = ((Ai + Bi) << Ai + S2i+1.

Далее приведены фрагменты кода на языке VHDL.

Главный файл

library ieee; --подключаемые библиотеки
use ieee.std_logic_1164.all; --использовать все объекты из пакета std_logic_1164 библиотеки ieee 
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library work;
use work.expansion_key.all;


entity RC5 is	--интерфейс объекта верхнего уровня
	port
	(
		clk: in std_logic;		--сигнал синхронизации
		InS: in std_logic;		--входные последовательные данные
		OutS: out std_logic		--выходные последовательные данные
	);
end entity;

architecture arc of RC5 is			--архитектура объекта верхнего уровня

signal S: ARR;					--таблица расширенных ключей
signal exp_ready: std_logic := '0';		--сигнал завершения расширения
signal key_read_ready: std_logic := '0';	--сигнал завершения чтения ключа
signal enc_ready: std_logic := '0';		--сигнал завершения шифровки очередного блока
signal read_ready: std_logic := '0';		--сигнал завершения чтения очередного блока данных
signal pt, ct: std_logic_vector (63 downto 0);	--открытый и шифрованный блоки соответственно
signal key: std_logic_vector (39 downto 0);	--ключ шифрования

Основные библиотеки языка VHDL, используемые в данной программе, следующие:

  • ieee - определяет многозначную систему логики (типы std_logic, std_logic_vector);
  • std - определяет стандартные типы данных и связанные с ними операции;
  • work - объекты, создаваемые пользователем (после синтеза).

Далее происходит описание компонентов:

component Receiver is port						--драйвер COM-порта (приемник)
	(
		Clk: in std_logic;	 				--сигнал синхронизации
		RxIn: in std_logic; 					--информация с COM-порта
		KeyOut: out std_logic_vector(39 downto 0);		--полученный ключ
		KeyReady: out std_logic;				--сигнал завершения чтения ключа
		PtOut: out std_logic_vector (63 downto 0);		--очередной блок данных
		ReadReady: out std_logic				--сигнал завершения чтения блока данных
	); 
end component;
	
component Sender is port						--драйвер COM-порта (передатчик)
	(
		clk: in std_logic;	  				--сигнал синхронизации
		OutS: out std_logic; 					--выходная информация для COM-порта
		RxIn: in std_logic_vector(63 downto 0);			--данные для отправки
		init_in: in std_logic					--разрешение на отсылку
	); 
end component;

component encryption is port						--непосредственно шифратор
	(
		clk: in std_logic;					--сигнал синхронизации
		in_A, in_B: in std_logic_vector(31 downto 0);		--исходные данные
		ct_data: out std_logic_vector(63 downto 0);		--зашифрованные данные
		S: in ARR; 						--таблица расширенных ключей
		ena: in std_logic;					--разрешающий сигнал
		enc_ready: out std_logic				--сигнал готовности шифровки
	);
end component;

Для улучшения понимания связей между компонентами можно рассмотреть следующий рисунок (рис. 9):

Рис. 9. Конечный автомат для блока Encryption

Таким образом, интерфейс описывается в объявлении объекта entity declaration и определяет входы и выходы объекта, его входные и выходные порты ports. Порты объекта характеризуются направлением потока информации. Они могут быть:

  • входными (in);
  • выходными (out);
  • двунаправленными (inout);
  • двунаправленными буферными (buffer).

В данном коде применяются только 2 типа портов – in и out.

Тело объекта специфицирует его структуру или поведение. Его описание по терминологии VHDL содержится в описании его архитектуры architecture.

Средства VHDL для отображения структур цифровых систем базируются на представлении о том, что описываемый объект entity представляет собой структуру из компонент component соединяемых друг с другом линиями связи (компонент часто называют «черным ящиком» - он является аналогом объявления интерфейса объекта, реализованного в библиотеке). Каждая компонента, в свою очередь, является объектом и может состоять из компонент низшего уровня (иерархия объектов). Взаимодействуют объекты путем передачи сигналов signal по линиям связи. Линии связи подключаются к входным и выходным портам компонент. В VHDL сигналы отождествляются с линиями связи. Описание структуры объекта строится как описание связей конкретных компонент, каждая из которых имеет имя, тип и карты портов. Карта портов port map определяет соответствие портов компонент поступающим на них сигналам, можно интерпретировать карту портов как разъем, на который приходят сигналы и в который вставляется объект-компонента. В данном примере карта портов строится следующим образом:

unit: expansion port map
	(
		clk => clk,
		key => key,
		S => S,
		ena => key_read_ready
	); 

unit1: encryption port map
	(
		clk => clk,
		in_A => pt(63 downto 32),
		in_B => pt(31 downto 0),
		S => S,
		ena => read_ready,
		ct_data => ct,
		enc_ready => enc_ready
	);

И так далее для каждого компонента.

Приведем пример использования signal. Из кода объекта Sender (передатчик по COM-порту) рассмотрим следующее описание:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity Sender is
port(
	(
		clk: in std_logic;  				--сигнал синхронизации
		OutS: out std_logic; 				--выходная информация для COM-порта
		RxIn: in std_logic_vector(63 downto 0);		--данные для отправки
		init_in: in std_logic				--разрешение на отсылку
	); 
end Sender; 


architecture RTL of Sender is
	--регистр, хранящий выходные данные
	signal RxReg: std_logic_vector(79 downto 0) := x"FFFFFFFFFFFFFFFFFFFF"; 
	signal ClkCount: Integer range 0 to 5208 := 0; 		--счетчик для генерации псевдосинхронизации
	
begin 
	

process (clk, init_in)
variable Init: std_logic := '0';				--переменные для поимки разрешающего сигнала фронта 
variable DelayInit: std_logic := '0';
begin
 
end process;
end architecture;

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

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

TYPE имя_типа IS
ARRAY (диапазон_индексов [ , диапазон_индексов] )
OF тип_элемента;

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

  • явным заданием границ диапазона:
m TO n
n DOWNTO m
где m, n – целочисленные константы, m <= n;
  • с использованием идентификатора ограниченного подтипа. В этом случае значения границ подтипа являются значениями границ индекса массива.

Непосредственно в программе было использовано следующее задание массива («массив для хранения расширенных ключей»):

library ieee;
use ieee.std_logic_1164.all;

package expansion_key is
type ARR is array (25 downto 0) of std_logic_vector(31 downto 0);
end package;

Еще одной важной частью было создание сигнала синхронизации clk с частотой 20МГц.

create_clock -name "clk" -period 20.000ns [get_ports {clk}]

Основные объекты были описаны с использованием поведенческого стиля, который описывает алгоритм формирования выходов в зависимости от входов. Операторы внутри блоков описываются последовательно, а, значит, порядок операторов имеет значение. Вот пример такой реализации:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library work;
use work.expansion_key.all;

entity expansion is 
	port
	(
		clk: in std_logic;							--сигнал синхронизации
		key: in std_logic_vector(39 downto 0);					--ключ
		S: out ARR;								--таблица расширенных ключей
		ena: in std_logic							--разрешающий сигнал
	);
end entity;



architecture arc of expansion is

component rotl is									--вращатель
	port
	(
		data		: in std_logic_vector (31 downto 0);
		distance	: in std_logic_vector (4 downto 0);
		result		: out std_logic_vector (31 downto 0)
	);
end component;


type ARR1 is array (1 downto 0) of std_logic_vector(31 downto 0);			--тип данных для массива L
type condition is (idle, init, sum_Q, rotl_A, rotl_B, temp1_update, temp2_update); 	--модель конечного автомата

signal step: condition := idle;						--конечный автомат
signal A,B: std_logic_vector (31 downto 0);				--сигналы для промежуточных вычислений
signal lS: ARR;								--таблица расширенных ключей
signal L: ARR1;								--массив блоков ключей
signal i: integer range 0 to 25;					--счетчик по mod 26
signal j: integer range 0 to 1;						--счетчик по mod 2
signal rotl1, rotl2: std_logic_vector (31 downto 0);			--результаты вращений
signal temp1, temp2: std_logic_vector (31 downto 0);			--входные сигналы для вращения
signal temp3: std_logic_vector (4 downto 0);				--на сколько вращать
signal count: integer range 0 to 3;					--счетчик по mod 4

begin
unit1: rotl								--вращатель на 3 бита
	port map
	(
		data => temp1,
		distance => "00011",
		result => rotl1
	);

process(ena, key, clk) 							--описание процесса
variable DelayEna: std_logic := 0; 					--вводится переменная – элемент задержки

begin			
if (rising_edge(clk)) then						--если пришел фронт сигнала синхронизации
	case step is     						--выбирается состояние 
	
		when idle => 						--состояние ожидания
			
			if (ena = '1' and DelayEna = 0) then 		--если фронт разрешающего сигнала
				step <= init;				--переход в следующее состояние
			else null;	
			end if;
			
			
		when init =>						--состояние инициализации
		
			A <= x"00000000";				--обнуление А и В

--Далее следует описание всех состояний
end case;
end if;
end process;
end architecture;

Временные диаграммы

На временной диаграмме (рис. 10) цифрой 1 обозначено время расширения ключа, цифрой 2 – время шифрования одного блока. Как видно из рисунка, расширение ключа занимает порядка 7 мс, а шифрование – порядка 1 мкс.

Рис. 10. Временные диаграммы

Примечания