ОСНОВЫ ЯЗЫКА VHDL 1
Описание типовых дискретных устройств 2 Комбинационные логические схемы Представление функции в форме бинарного дерева решений основано на последовательном переходе от представления функции большого числа переменных через суперпозицию функций меньшего числа переменных. Теоретической основой метода является разложение Шеннона: Тогда вычисление первого терма разложения записывается как одна возможная альтернатива условного оператора или условного присваивания, а вычисление другого - как противоположная: IF x1='0' THEN z ; ELSE z ; ЕND IF; Подформулы разложения могут быть, в свою очередь, далее разложены:
Пустой экран 3
Описание типовых дискретных устройств 4 Комбинационные логические схемы Оператор процесса, содержащий описание комбинационной схемы, представленной на рисунке с использованием условного оператора, приведен в примере 12. Здесь вспомогательные переменные pr1 и рг 2 введены для возможности представления несимметричных переходных процессов. Если это несущественно, то можно ограничиться присвоением значений сигналам out1 и out2 непосредственно в условном операторе. Пример 12 PROCESS (a,b,c,d) VARIABLE pr1,pr2:std_logic; BEGIN IF b=1' THEN pr1:= a; pr2:=a OR ( not a AND not c AND d ); ELSIF a='0' THEN pr1:=d; pr2:= not c AND d ; ELSE pr1:=c AND d; pr2= not d ; END IF; out1
Описание триггеров 5 Асинхронное управление характеризуется тем, что события на информационных входах непосредственно вызывают изменение состояния триггера. Единственный нетривиальный триггер с асинхронным управлением это RS-триггер, функциональная модель которого может быть представлена следующим образом: PROCESS (R, S) BEGIN IF R='1' AND S='l' THEN ASSERT FALSE REPORT " Illegal nput combination" SEVERITY error; ELSIF S=1' THEN Q
Описание триггеров 6 Если требуется выполнить моделирование с учетом возможных переходных состояний входов и выходов, то следует ввести ряд уточнений, например таких, как в программе, представленной ниже. ENTITY R_S IS GENERIC (delay: time:=2 ns;); PORT (R,S: IN std_logic; Q,NQ: OUT std_logic) END R_S; ARCHITECTURE R_S_timing OF R_S IS BEGIN PROCESS (R, S) BEGIN IF R='0' AND S=1' THEN Q
Описание триггеров 7 В триггерах со статическим управлением при пассивном уровне сигнала на управляющем входе изменение состояния невозможно, а при активном изменения информационных сигналов приводят к изменению состояния. Рассмотрим процесс d ievei, описывающий D-триггер с потенциальным управлением, иногда называемый защелкой (Latch), для которого положительный сигнал является разрешающим. d_level: PROCESS (clock, data) BEGIN IF clock='l' THEN Q
Описание триггеров 8 При динамическом управлении изменение состояния триггера происходит только непосредственно после фронта или спада сигнала на тактирующем входе. Новое состояние определяется сигналами на информационных входах в момент изменения управляющего сигнала, а само по себе изменение состояний информационных входов не вызывает изменения состояния триггера. Оператор процесса d_edge в нижеприведенном листинге интерпретирует это правило и отличается от оператора d_level списком чувствительности. Указанный процесс вызывается только при изменении сигнала clock, причем состояние может измениться, если произошел переход clock в состояние логической единицы. Следующее состояние определяется состоянием информационного входа. Но если сигнал data стабилен перед фронтом clock в течение интервала времени, меньшего, чем необходимое для данного триггера время предустановки delay_d_clk, следующее состояние не определено. d_edge: PROCESS (clock) BEGIN IF clock='1' THEN IF data'last_event
Описание триггеров 9 При представлении комбинированных триггерных устройств в число чувствительности процесса, в котором описывается такое устройство, включают и асинхронные входы, и тактирующий сигнал. При составлении программы необходимо учитывать относительные приоритеты управляющих сигналов и их совместимость. Рассмотрим упрощенное описание комбинированного JKRS- триггера. Входы асинхронной установки и сброса S и R, как обычно, являются более приоритетными по сравнению с входом синхронизации clock (в данном случае представлена синхронизация положительным фронтом). Только при нулевых сигналах на входах R и S выполняется оператор выбора CASE, интерпретирующий функционирование J-K-триггера. PROCESS (clock,R,S) VARIABLE Qinternal:= bit; VARIABLE variant: bit_vector (2 DOWNTO 0); BEGIN variant := j&k; IF R= 4' AND S=1' THEN ASSERT FALSE REPORT "Illegal input combination" SEVERITY ERROR; ELSIF S='1' THEN Q Qinternal:='0'; WHEN "00"=> Qinternal:=Qinternal; WHEN "11"=> Qinternal:= NOT Qinternal; END CASE; END IF; Q
Описание регистров 10 Регистры в программах удобно представлять процессами, список чувствительности которых включает управляющие сигналы, а в теле процесса находятся операторы присваивания, определяющие состояние триггеров регистра после изменений управляющих сигналов. Логика анализа условий выполнения операторов в теле этого процесса такая же, как для одиночных триггеров. Ниже представлена программа, описывающая преобразователь параллельного кода в последовательный с асинхронной загрузкой кода и синхронным сдвигом. LIBRARY ieee; USE ieee.std_logic_1164. ALL ENTITY Parallel_to_sequential IS GENERIC (n:integer:=8); PORT (clk,load: IN std_logic; din: IN std_logic_vector (n-1 DOWNTO 0); dout: OUT std_logic); END Parallel_to_sequential; ARCHITECTURE test OF Parallel_to_sequential IS SIGNAL reg: std_logic_vector (n-1 DOWNTO 0); BEGIN dout
Описание триггеров 11 В ряде случаев удобно представлять содержимое регистра в форме ограниченных целых и перечислимых типов данных. Такое представление может обеспечить большую наглядность и улучшить проницаемость программ. Формально такие типы данных определены как скалярные, а по существу могут в сжатой форме отражать групповой объект код состояния регистра. Ниже представлен операционный блок, предназначенный для выполнения различного набора операций с содержимым регистра data_register. PACKAGE oper_unit_decl IS TYPE instruction IS (clear, nop, load, shift, inc, dec); TYPE data IS RANGE 0 TO 255; END oper_unit_decl; USE work.oper_unit_decl.ALL; ENTITY oper_unit IS PORT (load_command, execute: IN bit; command: IN instruction; data_in: IN data; data_OUT:OUT data); END oper_unit; ARCHITECTURE test OF oper_unit IS SIGNAL data_register: data; SIGNAL instruction_register:instruction; BEGIN PROCESS (load_cammand) BEGIN instruction_register data_registernull; WHEN clear=> data_register data_register data_register data_register
Описание триггеров и регистров 12 Для представления узла без памяти (комбинационной схемы) описание его функционирования можно представить оператором параллельного присваивания, а в случае сложной логики и наличия общих условий в нескольких функциях удобно разместить в теле оператора PROCESS. В последнем случае в список чувствительности или в условия прекращения ожидания включаются все информационные сигналы. Для устройств с памятью логические выражения, определяющие очередное состояние регистровой схемы, следует разместить в теле оператора PROCESS, но в этом случае список чувствительности включает только управляющие сигналы (тактирующий и, при необходимости, сигналы принудительной установки и сброса). В комбинационной схеме недопустимо использовать выходной сигнал в качестве одного из входов этой же схемы. В регистровых схемах это допустимо, однако в таком случае при представлении в программе следует предусмотреть конструкции, которые соответствуют представлению динамически управляемых триггерных устройств.
Простые арифметические узлы 13 Перечисленные выше правила в полной мере применимы к арифметическим узлам, которые могут, в зависимости от требований проекта, реализоваться и как комбинационные схемы, и как элементы с памятью. Развитием устройств с памятью, являются конвейерные реализации, предполагающие наличие нескольких регистров, сохраняющих промежуточные результаты. Например, процессы, помеченные метками comb и registered в нижеприведенном листинге, несмотря на подобие выполняемых операций (в обоих процессах выполняются инкремент и сдвиг), представляют совершенно различные алгоритмы функционирования и технические реализации. Процесс comb задает комбинационные схемы арифметических преобразований входных кодов, в то время как процесс registered определяет счетчик и регистр сдвига. Исходными данными могут быть как целые, так и битовые векторы. comb: PROCESS ( data_a, data_b) BEGIN shift
Простые арифметические узлы 14 Логика формирования выходной величины арифметического узла может представляться в программе как с помощью логических выражений, так и в арифметической форме. Нижеприведенный листинг представляет первичный проектный модуль ENTITY add_subb сумматор- вычитатель чисел в беззнаковом двоичном представлении, при этом разрядность width является параметром настройки. Этому ENTITY сопоставлено архитектурное тело arithmetic_presentation, в котором применяется арифметическая форма представления преобразований. LIBRARY IEEE; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_unsigned."+";' ENTITY add_subb IS GENERIC (width:INTEGER); PORT (data_a, data_b: IN std_logic_vector (width-1 DOWNTO 0);-- входы direction, -- '0'-сложение, '1'-вычитание carry_in: IN std_logic; -- входной перенос sum:OUT std_logic_vector (width-1 DOWNTO 0);-- результат overflow: OUT std_logic); -- переполнение END add_subb; ARCHITECTURE arithmetic_presentation OF add_subb IS SIGNAL a,b,s:std_logic_vector(width DOWNTO 0); BEGIN a
Простые арифметические узлы. Конвейерная реализация 15 Описание конвейерных реализаций рассмотрим на примере программы конвейерного умножителя. Реализуется стандартная вычислительная схема для умножения целых чисел, представленных в двоичной форме: где а множимое, b(i) i-й разряд множителя, п разрядность операндов и product результат. Особенность реализации состоит в том, что исходные аргументы data_a и data_b продвигаются в каждом такте, инициируемом фронтом тактового сигнала, между ступенями конвейера. В каждой i -й ступени конвейера к накопленной на предыдущей ступени сумме прибавляется произведение множимого, сдвинутого на i разрядов, и i-го бита множителя.
Простые арифметические узлы. Конвейерная реализация 16 LIBRARY IEEE; USE ieee.std_logic_1164.all; USE work.std_logic_arith.all; ENTITY pipe_mul IS GENERIC (width:integer:=8); PORT (data_a, data_b: IN integer RANGE 0 TO 2**width-1; clock: IN std_logic; product :OUT integer RANGE 0 TO 2**(2*width)-1 ); END pipe_mul; ARCHITECTURE behave OF pipe_mul IS TYPE shift_array IS ARRAY (width-1 DOWNTO 0) OF integer RANGE 0 TO 2*width-1; TYPE partial_mult_array IS ARRAY (width DOWNTO 0) OF integer RANGE 0 TO 2**(2*width)-1; SIGNAL a_shift, b_shift:shift_array; SIGNAL p_mul:partial_mult_array; BEGIN PROCESS( clock) VARIABLE i: integer range width-1 DOWNTO 0; VARIABLE b,b0: std_logic_vector( width-1 DOWNTO 0); BEGIN IF (clock='1') AND NOT clock'stable THEN b0:= conv_std_logic_vector(data_b,width); IF ( b0(0) =1') THEN p_mult(0)
СПАСИБО ЗА ВНИМАНИЕ