Увод у VHDL
Увод Строго типизиран. Није case sensitive. Основни елементи: библиотека: LIBRARY naziv_biblioteke; USE naziv_biblioteke.naziv_paketa.deo_paketa; ентитет: ENTITY naziv_entiteta IS port( lista_portova); END [ENTITY][naziv_entiteta] архитектура: ARCHITECTURE naziv_arhitekture OF naziv_ent IS deklarativna_sekcija BEGIN konkurentni_iskazi END [ARCHITECTURE][naziv_arhitekture];
Лексички елементи Коментари Идентификатори Кључне речи Специјални симболи Бројеви Карактери Стрингови Бит стрингови
Коментари Коментар до краја реда почиње са -- -- Ovo je komentar Стандард VHDL-2008 уводи и коментар у више редова /* Ovo je komentar u vise redova*/
Идентификатори Идентификатори: Проширени идентификатори могу садржати мала и велика слова, бројеве и доњу црту "_"; морају почети словом, не смeју се завршити доњом цртом, не смeју садржати доњу црту два пута узастопно. Проширени идентификатори Од стандарда VHDL-93 Пишу се између карактера \ Могу да садрже све карактере
Примери Исправни: Неисправни: а а0 а_b а_b_c \a____v$324\ -- проширени идентификатор Неисправни: a? --недозвољен знак 0a --не почиње словом ab_ --завршава се са доњом цртом a__b --садржи двe узастопне доње црте
Кључне речи
Специјални симболи Један карактер " # & ' ( ) * + - , . / : ; < = > ? @ [ ] ` | Више карактера => ** := /= >= <= <> ?? ?= ?/= ?> ?< ?>= ?<= << >> Значење: ** exponentiation, numeric ** integer, result numeric /= test for inequality, result is boolean
Целобројни литерали Декадне константе: 0 10 22 0 10 22 -32 је комбинација оператора '-' и константе 32 Декадне константе са експонентом: 10е2 12Е14 експонент је ненегативан цeо број Константе у основи из опсега 2..16: бинарна: 2#1000000000000# = 2#1#е12 октална: 8#12000# = 8#12#Е3 хексадесимална: 16#F1A# =16#f1a#е0 Раздвајање цифара помоћу доње црте 2_150_252 2#1100_0101_1010#
Реални литерали Декадне реалне константе: 0.1 1.0 2.2 0.1 1.0 2.2 Декадне реалне константе константе са експонентом: 1.0е2 1.2Е-14 експонент је цeо број Реалне константе у основи из опсега 2..16: бинарна: 2#1000000000000.0# = 2#1.0#е12 октална: 8#1200.0# = 8#1.2#Е3 хексадецимална: 16#F1.A# = 16#f1.a#е0
Знаковни литерали и литерали стрингова Знакови: 'а', 'А', '1', ... Стрингови: "Pera", "Mika", "Tekst ""pod"" dvostrukim navodnicima" Оператор & служи за надовезивање стрингова
Бит стрингови Стрингови који описују бинарне вредности садрже само цифре у одговарајућој основи. Бројни системи: бинарни: B"1001010", B"0010_0110" октални: О"1532" хексадецимални: Х“a3b5" декадни: D"123" -- подржано тек у стандарду VHDL-2008
Типови VHDL је строго типизиран језик. Тип дефинише: Скаларни типови скуп вредности могуће операције Скаларни типови цели бројеви реални бројеви физичке величине типови којима се описује један бит знакови набројиви логички Сложени типови фајлови низови записи
Целобројни типови Основни: INTEGER (по стандарду минимално 32 бита) Дефинисање: RANGE izraz ( TO I DOWNTO ) izraz subtype small_int is integer range 0 to 10 ; to: растуће уређени бројеви downto: опадајуће уређени бројеви Операције: + сабирање – одузимање, или негација * множење / дељење mod модуо rem остатак abs апсолутна вредност ** експонент Различит тип од бит вектора Почетна вредност је најмања вредност у скупу
Дефинисање новог типа type_declaration ⇐ type identifikator_tipa is definicija_tipa ; Примери: type apples is range 0 to 100; type oranges is range 0 to 100; Типови су различити иако су дефиниције идентичне. Није дозвољено вредност једног типа доделити променљивој другог типа.
Дефинисање подтипа subtype_declaration ⇐ subtype identifikator is subtype_indication ; subtype_indication ⇐ type_mark [ range simple_expression ( to I downto ) simple_expression ] Пример: subtype small_int is integer range -128 to 127; variable pomeraj : small_int; variable pozicija : integer; Исправно је и: pozicija := pozicija + pomeraj; Резултат се може сместити и у објекат подтипа ако резултат изађе из опсега, пријављује се грешка.
Набројиви типови Дефинисање набројивог типа type naziv_tipa is (prva_vrednost {,...} ); Пример: type stanje is (spreman, radi, zavrsio); Погодан за описивање машина стања Могуће мењати кодирање стања Напомена: константе истог назива из различитих типова су различите константе.
Физичке величине 1 hour = 3.6x1018 femtoseconds Користи се за опис реалних физичких величина За нас од интереса само време: type time is range implementation defined units fs; ps = 1000 fs; ns = 1000 ps; us = 1000 ns; ms = 1000 us; sec = 1000 ms; min = 60 sec; hr = 60 min; end units; 1 hour = 3.6x1018 femtoseconds
Битови Предефинисани набројиви тип са могућим вредностима: '0' '1' Дефинисане су стандардне логичке операције: and or not xor ...
std_logic Скуп могућих вредности: 'U' – неиницијализовано 'X' – строго непознато '0' – строго 0 '1' – строго 1 'Z' – стање високе импедансе 'W' – слабо непознато 'L' – слабо 0 'H' – слабо 1 '-' – није битно Ретко се користе све вредности Велики скуп различитих вредности боље моделује понашање реалног система олакшава детектовање и уклањање грешака За проверу поклапања нивоа испред релационих оператора додати упитник. Тачно је: '0' /= 'L' , али и '0' ?= 'L' На почетку сваког фајла неопходно укључити IEEE библиотеку: library ieee; use ieee.std_logic_1164.all;
Низови Дефинисање: TYPE naziv_tipa IS ARRAY(granica [TO|DOWNTO] granica {,...}) OF tip_pojedinačnog_elementa; Групишу више елемената истог типа заједно Погодни за опис магистрала: TYPE address_buss IS ARRAY (63 DOWNTO 0) OF std_logic; type matrix is array (integer range <>, integer range <>) of real; Постоје предефинисани типови: std_logic_vector bit_vector
std_logic_vector Не постоји нумеричка интерпретација std_logic_vector типа Аритметичке операције не постоје Сигнали std_logic_vector типа не могу да се користе као идекси низова Решење: Користити пакете из библиотека ieee.numeric_std и ieee.numeric_bit Користити пакете из библиотека ieee. std_logic_arith и ieee. std_logic_unsigned и ieee. std_logic_signed Препоручује се прва варијанта Не препотставља ништа о представи броја (све мора експлицитно) Друга је наметнута од стране једне компаније
numeric_std type UNSIGNED is array ( NATURAL range <> ) of STD_LOGIC; type SIGNED is array ( NATURAL range <> ) of STD_LOGIC; ... -- Id: A.3 function "+" (L,R: UNSIGNED ) return UNSIGNED; -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). -- Result: Adds two UNSIGNED vectors that may be of different lengths.
numeric_std -- Id: D.1 function TO_INTEGER ( ARG: UNSIGNED) return NATURAL; -- Result subtype: NATURAL. Value cannot be negative since parameter is an -- UNSIGNED vector. -- Result: Converts the UNSIGNED vector to an INTEGER.
numeric_std signal reg : std_logic_vector(7 downto 0); signal reg_unsigned:unsigned(7 downto 0); Конверзија UNSIGNED STD_LOGIC_VECTOR reg_unsigned <= unsigned(reg); reg <= std_logic_vector(reg_unsigned);
numeric_std - конверзија
Типови
Подаци у VHDL Постоје 3 класе објеката за чување података: константе променљиве сигнали
Константе Дефинисање: CONSTANT identifier { , … } : subtype_indication [ := expression ] ; За сада, израз за почетну вредност сматрамо обавезним. Примери дефинисања: constant number_of_bytes : integer := 4; constant number_of_bits : integer := 8 * number_of_bytes; constant e : real := 2.718281828; constant prop_delay : time := 3 ns; constant size_limit, count_limit : integer := 255;
Променљиве Декларисање: VARIABLE identifier { , … } : subtype_indication [ := expression ] ; Користе се у процесима, потпрограмима и функцијама свака променљива сме бити видљива и коришћена у само једном процесу (осим дељених). Пример: variable index : integer := 0; variable sum, average, largest : real; variable start, finish : time := 0 ns; Последња линија је еквивалентна са: variable start : time := 0 ns; variable finish : time := 0 ns;
Додела вредности променљивој promenljiva := izraz; Увек секвенцијални исказ Израз мора бити истог типа као и променљива Променљиве тренутно добијају нову вредност променљива може и у истом симулационом циклусу да промени вредност више пута, све промене су видљиве и у текућем симулационом циклусу.
Сигнали Концепт који је осмишљен да би се описале везе које постоје у реалним системима. Битно се разликују од променљивих. Дефинисање сигнала: SIGNAL identifikator {,...}: tip [register|bus] [:=izraz]; Израз за почетну вредност битан само при симулацији; при синтези се одбацује signal a_bit : bit := '0'; a_bit <= b_bit xor '1'; -- concurrent assignment
Додела вредности сигналу Битно се разликује од доделе вредности променљивој: Додела вредности није тренутна – у току симулационог циклуса вредност сигнала се не мења. Дифинише се трансакција: вредност и тренутак када сигнал треба да добије задату вредност. Више сигнала може у истом тренутку променити вредност. Свака нова трансакција брише све трансакције заказане за исти или наредни тренутак за дати сигнал Врсте исказа за доделу вредности сигналу: секвенцијална, конкурентна.
Сигнали vs. Променљиве Сигнал Променљива Оператор доделе <= := Шта моделује Физичку везу Локалну информацију Опсег важења Може бити глобалан Локалан Понашање Додела није тренутна у секвенцијалном коду Додела је тренутна Употреба У пактерима, ентитетима и/или архитектурама У секвенцијалним изразима
Ентитет entity identifier is [ generic ( generic_list ) ; ] [ port ( port_interface_list ) ; ] { entity_declarative_item } end [ entity ] [ identifier ] ; interface_list ⇐ ( identifier { , … } : [ mode ] subtype_indication [ := expression ] ) { ; … } mode ⇐ in I out I buffer I inout Декларативни део ентитета је заједнички за све имплементације (архитектуре). buffer – као out који може и да се чита унутар архитектуре.
Архитектура architecture identifier of entity_name is { block_declarative_item } begin { concurrent_statement } end [ architecture ] [ identifier ] ; concurrent_statement <= concurrent_signal_assignment_statement | process_statement | block_statement | concurrent_procedure_call_statement | concurrent_assertion_statement | component_instantiation_statement | generate_statement
Конкурентна додела вредности сигналу Постоје 3 врсте: Додела једног фиксног израза Додела једног од више израза: Селекциона додела вредности Условна додела вредности
Конкурентна додела фиксног израза Додела вредности сигналу као исказ у телу архитектуре. Синтакса: [label:] (name|aggregate) <= [delay_mechanism] waveform delay_mechanism <= transport | [reject time_expression] inertial waveform <= (value_expression [after time_expression] | null [after time_expression]) {,...} | unaffected Извршава се увек када дође до догађаја на неком од сигнала који учествују у изразу за израчунавање нове вриједности. Генерише се комбинациона логика.
Пример entity mux is port(d0, d1, d2, d3, sel0, sel1:in bit; z:out bit); end entity; architecture dataflow of mux is begin zmux: z <= (d0 and not sel1 and not sel0) or (d1 and not sel1 and sel0) or (d2 and sel1 and not sel0) or (d3 and sel1 and sel0); end architecture;
Синтетизовани модел
Селекциона додела вредности with expression select[?] name <= [delay_mechanism] {waveform when choices, } waveform when choices; Погодно када нова вредност зависи од вредности неког конкретног израза. Опциони упитник има исту улогу као испред релационих оператора. Пример alu: with alu_function select result <= a + b after Tpd when alu_add | alu_add_unsigned, a - b after Tpd when alu_sub | alu_sub_unsigned, a and b after Tpd when alu_and, a or b after Tpd when alu_or, a after Tpd when alu_pass_a;
Пример entity mux is port(d0, d1, d2, d3:in bit; sel:in bit_vector(1 downto 0); z:out bit); end entity; architecture dataflow of mux is begin with sel select z <= d0 when "00", d1 when "01", d2 when "10", d3 when "11"; end architecture;
Синтетизован модел
Условна додела вредности name <= [delay_mechanism] {waveform when boolean_expression else } waveform [when boolean_expression]; Погодно када се услов не може за сваки случај добити поређењем вредности једног израза са неком вредношћу. Приоритетно испитивање услова; додељује се прва вредност код које је услов тачан и прекида се даље испитивање преосталих услова. Примјер zmux: z <= d0 when sel1 = '0' and sel0 = '0' else d1 when sel1 = '0' and sel0 = '1' else d2 when sel1 = '1' and sel0 = '0' else d3 when sel1 = '1' and sel0 = '1';
Синтетизован модел
Упоредни приказ претходна 3 синтетизована модела
Конкурентна додела вредности и секвенцијална логичка кола? Претходни примери: Условна и селекциона додела вредности се синтетизују као комбинациона логичка кола У свим условима генерисана нова вриједност за сигнал Z. Уколико се догоди да при се промени неког улазног сигнала не дефинише нова вриједност сигнала Z, алати ће претпоставити да вриједност треба да остане неизмењена; Пошто се може догодити да то није била жеља дизајнера, алат ће дизајнера информисати о томе Вероватно ће бити генерисано упозорење да меморијски елементи можда неће радити како треба, зашто? Ако се секвенцијална логика формира на начин описан на датом слајду, у израчунавању нове вриједности ће учествовати сигнал који учествује и у израчунавању такта меморијског елемента те то може за резултат дати непредвидиву вредност. Пример дат на наредном слајду.
Пример – секвенцијално коло entity mux is port(d0, d1, d3:in bit; sel0, sel1:in bit; z:out bit); end entity; architecture dataflow of mux is begin z <= d0 when sel1 = '0' and sel0 = '0' else d1 when sel1 = '0' and sel0 = '1' else --d2 when sel1 = '1' and sel0 = '0' else d3 when sel1 = '1' and sel0 = '1'; end architecture;
Синтетизовани модел – RTL поглед
Синтетизовани модел – технолошки поглед
Секвенцијално процесирање Појављује се унутар процеса и потпрограма. Наредбе се извршавају у редоследу појављивања унутар процеса (потпрограма); редослед наредби из различитих процеса није дефинисан. Променљивим се вредност мења у тренутку извршавања исказа доделе вредности тој променљивој. Могу се користити и математички оператори. У току извршавања, време се не мења! За сваки процес мора се дефинисати под којим условима ће се активирати (шта је потребно да се догоди да се процес активира наредни пут).
Листа сигнала на које је процес осетљив – листа осетљивости процеса Процес Листа сигнала на које је процес осетљив – листа осетљивости процеса Конкурентни исказ. Садржи секвенцијалне исказе. Синтакса: [labela_procesa:] process [(naziv_signala {,...})] is {deklarativna_sekcija} begin {sekvencijalni_iskaz} end process [labela_procesa]; Процес не мора да има листу сигнала на које је осетљив активира се на почетку симулације активира се сваки пут када се "пробуди" са неког wait исказа кад дође до краја, враћа се на почетак Уколико процес има и листу сигнала на које је осетљив: активира се и суспендује исто као да нема листу осетљивости суспендује се увек када дође до краја процеса Догађај на сигналу из листе осетљивости => процес се активира ако је суспендован због доласка до краја.
Секвенцијални искази sequential_statement <= wait_statement | report_statement | variable_assignment_statement | if_statement | loop_statement | exit_statement | null_statement | assertion_statement | signal_assignment_statement | procedure_call_statement | case_statement | next_statement | return_statement
Секвенцијална додела вредности сигналу Додела вредности сигналу унутар процеса Сваки процес добија по један драјвер за сваки сигнал којем додељује вредност Уколико се у неком случају сигналу не додели вредност, памти се претходна (секвенцијална кола). У једном симулационом циклусу може се изгенерисати више трансакција за исти сигнал Конкурентна додела вредности сигналу еквивалентна је процесу: који садржи исту такву секвенцијалну доделу и који у листи сигнала на које је осетљив има све сигнала који се користе при израчунавању нове вредности сигнала Од ВХДЛ 2008 уведени су секвенцијални искази за селекциону и условну доделу вредности сигналу.
Пример entity mux is port(d0, d1, d2, d3, sel0, sel1:in bit; z:out bit); end entity; architecture dataflow of mux is begin process (d0, d1, d2, d3, sel0, sel1) is begin zmux: z <= (d0 and not sel1 and not sel0) or (d1 and not sel1 and sel0) or (d2 and sel1 and not sel0) or (d3 and sel1 and sel0); end process; end architecture;
Механизми кашњења Два могућа: delay_mechanism <= transport | транспортни инертни (подразумевани) delay_mechanism <= transport | [reject time_expression] inertial Користе се само за потребе симулације: симулира се кашњење логичких кола симулира се кашњење веза између логичких кола При синтези ова кашњења се занемаре => на овај начин није могуће мерити време за потребе имплементације неког алгоритма
Транспортно кашњење Транспортни механизам кашњења (transport) Мора се експлицитно навести Све трансакције се генеришу са наведеним кашњењем Опонаша кашњење које настаје дуж линија за пренос сигнала (идеалне линије која пропушта све фреквенције) Није погодно за опис логичких кола
Примери Пример који генерише две трансакције у току једног симулационог циклуса на једном сигналу: entity е1 is end e1; architecture а1 of е1 is signal a:bit:='1'; begin process a <= transport '0' after 1ns; a <= transport '1' after 2ns; wait; end process; end а1; Пример у којем остаје само једна трансакција (дат само измењени део) каснија трансакција је за ранији тренутак од претходне и због тога се претходно генерисана трансакција брише. 0ns 1ns 2ns 0ns 1ns 2ns
Транспортно кашњење - пример transmission_line: process(a) is begin z <= transport a after 500 ps; end process transmission line; a z 700 ps 1 1000 ps
Транспортно кашњење - пример transmission_line: process(a) is begin if a=‘1’ z <= transport a after 800 ps; else z <= transport a after 500 ps; end process transmission line; a z 1000 ps 1 900 ps postoji transakcija, ali ne i događaj
Инертно кашњење Подразумеван ако се не наведе ниједан Инертни механизам кашњења (inertial) Подразумеван ако се не наведе ниједан Побудни сигнал мора да постоји дуже од времена одбацивања Економичан за ресурсе симулатора Гличеви се не пропагирају кроз дизајн Брише и све трансакције заказане у претходном интервалу одбацивања, почев од прве која се разликује од нове вредности гледано са краја интервала Упрошћено: одбацује све импулсе који нису дужи од времена одбацивања
Инертно кашњење - пример inv: process(a) is begin z <= inertial not a after 3 ns; end process inv; a z
Инертно кашњење - пример inv: process(a) is begin z <= reject 1 ns inertial not a after 3 ns; end process inv; a z reject 0 ps inertial a transport a
Инертно кашњење - пример inv: process(a,b) is begin z <= reject 3 ns inertial a or b after 5 ns; end process inv;
Пример entity primer is end primer; architecture ponasanje of primer is signal a:bit:='1'; signal b:bit:='0'; begin process variable c:bit:='0'; begin if (a='1')or(b='0') then a <= inertial not c after 1ns; else a<=inertial not c after 1.5ns; end if; b <= inertial (b)nand(a or c) after 1ns; c := a and b; wait on a, b; end process; end ponasanje;
Агрегација сигнала aggregate ⇐ ( ( [ choices => ] expression ) { , … } ) choices ⇐ ( simple_expression I discrete_range I others ) { | … } Примјери: type byte is array (7 downto 0) of bit; signal d_reg : byte; signal a, b : bit; d_reg <= (a, "1001", b, "00"); d_reg <= (7 => a, 6 downto 3 => "1001", 2 => b, 1 downto 0 => "00");
Агрегација сигнала signal status_reg : bit_vector(7 downto 0); signal int_priority, cpu_priority : bit_vector(2 downto 0); signal int_enable, cpu_mode : bit; (2 downto 0 => int_priority, 6 downto 4 => cpu_priority, 3 => int_en, 7 => cpu_mode) <= status_reg;
Комбинационе мреже – примери Ефикасно HDL моделовање Дељење оператора Дељење функционалности Оптимизација распоређивања Опште мреже
Ефикасно HDL моделовање Језик за МОДЕЛОВАЊЕ HARDWARE-a Погрешан приступ Замислити C програм и превести га у HDL Добар приступ Истраживање области да се пронађе ефикасан модел Преточити модел у HDL код
Дељење Сложеност физичких модела варира Аритметички оператори Гломазни Оптимизација од стране алата минимална Оптимизација постигне дељењем на RT нивоу Оператори Функционалност
CMOS имплементација стандардних ћелија
Дељење оператора Израчунавање израза је међусобно искључено Само један резултат се прослеђује на излаз Пример - условна додела вредности сигналу sig <= value_1 when boolean_1 else value_2 when boolean_2 else value_3 when boolean_3 else . . . value_n;
Дељење оператора – пример (1) Код: r <= a+b when boolean_exp else a+c; Модификован код: src0 <= b when boolean_exp else c; r <= a + src0;
Дељење оператора – пример (2) Простор: 2 add, 1 mux Кашњење: max(Tadd, Tbool) + Tmux Простор: 1 add, 1 mux Кашњење: Tadd + Tbool + Tmux
Дељење оператора Дељење се ради додавањем мреже за рутирање Добробити од дељења зависи од сложености имплементације оператора и мреже за рутирање Идеално – алат обавља овај посао
Дељење функционалности Велика мрежа може имати пуно функционалности Неколико функција могу бити сличне Неколико функција могу да деле исти hardware Ради се ad hoc Алат не може лако да одради дељење, јер не разуме функционалности
Компаратор – пример (1) Компаратор са два мода 8 бита Неозначени бројеви Означени бројеви 8 бита Размислити о проширењу
Компаратор – пример (2) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity cmp2m is port( a,b: in std_logic_vector(7 downto 0); mode : in std_logic; f_out : out std_logic ); end cmp2m;
Компаратор – пример (3) architecture direct_arch of cmp2m is signal f_out_signed, f_out_unsigned : std_logic; begin f_out_signed <= '1' when signed(a) > signed(b) else '0'; f_out_unsigned <= '1' when unsigned(a) > unsigned(b) else f_out <= f_out_unsigned when mode = '0' else f_out_signed; end direct_arch;
Компаратор – пример (4)
Компаратор – пример (5) architecture shared_arch of cmp2m is signal a1_b0, f_out_cmp : std_logic; begin a1_b0 <= '1' when a(7) = '1' and b(7) = '0' else '0'; f_out_cmp <= '1' when a(6 downto 0) > b(6 downto 0) else f_out <= f_out_cmp when (a(7) = b(7)) else a1_b0 when mode = '0' else not a1_b0; end shared_arch;
Компаратор – пример (6)
Оптимизација распоређивања “Place and route” после синтезе VHDL не може да специфицира тачан распоред VHDL може да специфицира приближан облик Чип је дводимензионалан Дводомензионални облик бољи од једнодимензионог Условна додела генерише хоризонталан ланац Селекциона додела генерише вертикалан ланац Ни један ни други није идеалан
Вишебитно XOR коло (1)
Вишебитно XOR коло (2) Проблем? library ieee; use ieee.std_logic_1164.all; entity r_xor is port(a: in std_logic_vector(7 downto 0); f : out std_logic); end r_xor; architecture cascade_arch_1 of r_xor is begin f <= a(0) xor a(1) xor a(2) xor a(3) xor a(4) xor a(5) xor a(6) xor a(7); end cascade_arch_1;
loop iskaz Бесконачна петља; могуће искочити из средине. [ loop_label : ] loop { sequential_statement } end loop [ loop_label ] ; Пример: incrementer : process is variable count_value : natural := 0; begin count <= count_value; loop wait until clk; count_value := (count_value + 1) mod 16; count <= count_value; end loop; end process incrementer;
exit Исказ којим се излази из петље. exit [ loop_label ] [ when condition ] ; У зависности да ли је лабела наведена или не зависи која петља се заврши: наведена лабела => излази се из петље означене са том лабелом, без лабеле => излази се из окружујуће петље.
Пример outer : loop ... inner : loop ... exit outer when condition_1; -- target B ... exit when condition_2; -- target A ... end loop inner; ... -- target A exit outer when condition_3; -- target B ... end loop outer; ... -- target B
next Прескаче остатак текуће итерације петље. [ label : ] next [ loop_label ] [ when condition ] ; Уколико се специфицира нека окружујућа петља, угнежђене петље се завршавају и прескаче се остатак текуће итерације наведене петље.
while loop Петља са условом на почетку. [ loop_label : ] while condition loop { sequential_statement } end loop [ loop_label ] ;
for loop [ loop_label : ] for identifier in discrete_range loop { sequential_statement } end loop [ loop_label ] ; discrete_range => simple_expression ( to I downto ) simple_expression Бројачку променљиву (идентификатор непосредно после for): није потребно експлицитно дефинисати, може се користити само у телу петље, није дозвољен упис у бројачку променљиву, прикрива друге променљиве истог назива.
Пример лоше употребе erroneous : process is variable i, j : integer; begin i := loop_param; -- error! for loop_param in 1 to 10 loop loop_param := 5; -- error! end loop; j := loop_param; -- error! end process erroneous;
Вишебитно XOR коло (3) architecture cascade_arch_2 of r_xor is constant WIDTH:integer :=8; begin process (a) variable tmp : std_logic; tmp:= a(0); for i in 1 to WIDTH - 1 loop tmp:= tmp xor a(i); end loop; f <= tmp; end process; end cascade_arch_2;
Вишебитно XOR коло (4) architecture cascade_arch_3 of r_xor is constant WIDTH:integer :=8; signal p: std_logic_vector(WIDTH -1 downto 0); begin p <= (p(WIDTH - 2 downto 0) & '0') xor a; f <= p(WIDTH - 1); end cascade_arch_3;
Вишебитно XOR коло (5) architecture tree_arch of r_xor is begin f <= (((a(0) xor a(1)) xor (a(2) xor a(3))) xor ((a(4) xor a(5)) xor (a(6) xor a(7)))); end tree_arch;
Вишебитно XOR коло (6)
Вишебитно XOR коло (7) Упоређивање Ланац Простор: (n – 1) xor кола Кашњење: (n – 1) Кодирање: Лако се скалира Дрво Кашњење: log2n Кодирање:не скалира се лако У зависности од алата и технологије имплементације конверзија може да буде аутоматска
Опште мреже Пример – Грејев бројач
Грејев бројач (1) library ieee; use ieee.std_logic_1164.all; entity gray_inc is port( g: in std_logic_vector(3 downto 0); g1 : out std_logic_vector(3 downto 0) ); end gray_inc;
Грејев бројач (2) architecture direct_arch of gray_inc is begin with g select g1 <= "0001" when "0000", "0011" when "0001", "0010" when "0011", "1001" when "1011", ... "1000" when "1001", "0000" when others; -- "1000" end direct_arch;
Грејев бројач (3) Нескалабилно Алгоритам за опште инкрементирање Грејевог кода не постоји Други приступ Конвертовати у бинарни број Инкрементирати Вратити у Грејев код
Грејев бројач (4) architecture compact_arch of gray_inc is constant WIDTH: integer := 4; signal b, b1: std_logic_vector(WIDTH-1 downto 0); begin -- Gray to binary b <= g xor ('0' & b(WIDTH-1 downto 1)); -- binary increment b1 <= std_logic_vector((unsigned(b)) + 1); -- binary to Gray g1<= b1 xor ('0' & g1(WIDTH-1 downto 1)); end compact_arch ;
Атрибути сигнала S’delayed(T) – Сигнал S закашњен за T S’stable(T) – Враћа тачно ако сигнал S у претходном интервалу T није мењао вредност S’quiet(T) – Враћа тачно ако на сигналу S у претходном интервалу T није било трансакција S’transaction – Сигнал који мења вредност из '0' у '1' и обрнуто сваки пут када се догоди трансакција сигнала S http://www.velocityreviews.com/forums/t375590-transaction-vs-event.html >Does anyone know what the difference between <signal>'event and ><signal>'transaction is? Anyone has a precise definition of these <sig>'event is a boolean value that is TRUE in a delta cycle when <sig> has just changed, and FALSE at other times. You can test 'event in an IF statement. Take, for example, the not-very-pretty traditional form of clocked process: process(clk, rst) begin if rst='1' then -- do reset actions elsif clk='1' and clk'event then -- clk has just changed to '1', and -- that change triggered the process -- so do clocked actions <sig>'transaction allows you to check whether some assignment was made to the signal, even if that assignment didn't change the signal's value. <sig>'transaction is a completely new signal, of type BIT, that toggles from '0' to '1' or back again in each delta cycle when one or more assignment is made to <sig>. This is occasionally useful if you have a data structure representing a transaction, and you would like to detect when someone puts a new value on that data structure - even if it's the same as the existing value. Because it's a new signal in its own right, you can use it in a sensitivity list... wait on thing'transaction; -- someone has written to "thing" -- so we need to process the new value
Атрибути сигнала S’event – Враћа тачно ако је у текућем симулационом циклусу дошло до догађаја на сигналу S S’active – Враћа тачно ако је у текућем симулационом циклусу дошло до трансакције на сигналу S S’last_event – Време од последњег догађаја S’last_active – Време од последње трансакције S’last_value – Вредност сигнала S пре последњег догађаја
Пример употребе атрибута Провера да ли је задовољено setup време: if clk'event and (clk = '1' or clk = 'H') and (clk'last_value = '0' or clk'last_value = 'L') then assert d'last_event >= Tsu report "Timing error: d changed within setup time of clk"; end if; Провера да ли је улазни сигнал такта довољно мале фреквенције: assert (not clk'event) or clk'delayed'last_event >= Tpw_clk report "Clock frequency too high"; http://noasic.com/blog/how-to-check-setup-and-hold-times-in-vhdl/ Tsu je setup time, znaci ako je doslo do promene za manje od toga, onda je greska
Наредба wait Обезбеђује могућност суспендовања догађаја до испуњења неког од услова: догађај на неком сигналу испуњења задатог логичког услова истека задатог временског интервала. Могућа и комбинација услова када се наредба тумачи на следећи начин: чекање је временски ограничено временом наведеним у for делу сваки пут када дође до догађаја на неком од сигнала у on делу проверава се услов; ако је испуњен наставља се даље. wait_statement <= [label:] wait [on signal_name{,...}] [until boolean_expression] [for time_expression] Услов се проверава: ако нема on клаузула: на сваки догађај било ког сигнала наведеног у услову, ако има on клаузула: сваки пут када дође до догађаја на неком од сигнала у on клаузули. wait on a, b; - aktivira proces na promenu a ili b wait until clk=‘1’ - aktivira proces kada clk postane ‘1’ wait on clk until reset=‘0’ - kada se promeni clk testira reset wait until trigger=‘1’ for 1ms - proces je suspendovan dok trigger ne postane 1 ilii dok ne prođe 1 ms
if-then-else Секвенцијални исказ. Обезбеђује условно извршавање других секвенцијалних исказа. Условно извршавање је приоритирано; када се наиђе на први тачан услов, прекида се провера осталих. Могуће угнездити више if-then-else исказа. [ if_label : ] if uslov then { sekvencijalni_iskaz } { elsif uslov then {sekvencijalni_iskaz } } [ else {sekvencijalni_iskaz } ] end if [ if_label ] ;
Пример 1 if sel0 = '0' and sel1 = '0' then z<= d0; elsif sel0 = '1' and sel1 = '0' then z<= d1; elsif sel0 = '0' and sel1 = '1' then z<= d2; elsif sel0 = '1' and sel1 = '1' then z<= d3; end if;
Синтетизован модел примера 1 Пример 1 Конкурентна условна додела сигнала
Синтетизован модел примера 1 технолошки поглед
Пример 2 if sel0 = '0' and sel1 = '0' then z<= d0; elsif sel0 = '1' and sel1 = '0' then z<= d1; elsif sel0 = '0' and sel1 = '1' then z<= d2; else z<= d3; end if; Због постојања else никада не остаје стара вредност. Зато синтетизовани модел нема леч коло. Погодно за синтезу, али при тестирању може да прeкрије потенцијални проблем. http://en.wikipedia.org/wiki/Latch_(electronics)
Синтетизован пример 2 RTL поглед
Пример 3 if sel0 = '0' and sel1 = '0' then z<= d0; elsif sel0 = '1' and sel1 = '0' then z<= d1; elsif sel0 = '1' and sel1 = '1' then z<= d3; end if;
Синтетизован пример 3 Пример 3 Примјер формирања секвенцијалног кола са конкурентном условном доделом вредности
Пример 4 if sel0 = '0' and sel1 = '0' then z<= d0; elsif sel0 = '1' and sel1 = '0' then z<= d1; elsе z<= d3; end if;
Синтетизован пример 4 Пример 4 Пример формирања секвенцијалног кола са конкурентном условном доделом вредности
Пример 5 if sel1 = '0' then if sel0 = '0' then z<= d0; else z<= d1; end if; else if sel0 = '0' then z<= d2; else z<= d3; end if; end if;
Синтетизован пример 5
Пример 6 Унутар било којег блока може да буде и више секвенцијалних наредби. if opcode = halt_opcode then PC := effective_address; executing := false; halt_indicator <= true; end if;
Условна додела променљивој name := expression when condition { else expression when condition } [ else expression ] ; Појављује се тек у VHDL 2008 Пример: result := a - b when mode = subtract else a + b; Еквивалентно са: if mode = subtract then result := a - b; else result := a + b; end if;
CASE Секвенцијални исказ. Омогућава извршавање одговарајућег низа исказа у зависности од вредности исказа. Извршава се само једна опција. Нема приоритета. Свака могућа вредност се у опцијама мора појавити тачно једном (погледати забeлешке уз слајд). [ case_label : ] case[?] izraz is ( when opcija => { sekvencijalni_iskaz } ) { … } end case [ case_label ] ; opcija ⇐ ( konstantan_izraz I diskretan_opseg I others ) { | … } Израз за селекцију (између case и is) се може конвертовати у одговарајући подтип ако се жели скратити скуп опција. naziv_podtipa'(izraz)
Пример 1 case func is when pass1 => result := operand1; when pass2 => result := operand2; when add => result := operand1 + operand2; when subtract => result := operand1 - operand2; end case;
Пример 2 case opcode is when load | add | subtract => operand := memory_operand; when store | jump | jumpsub | branch => operand := address_operand; when others => operand := 0; end case;
Пример 3 entity mux is port(d0, d1, d2, d3:in std_logic; sel:in std_logic_vector(1 downto 0); z:out std_logic); end entity; architecture dataflow of mux is begin process(d0, d1, d2, d3, sel)is begin case sel is when "00" => z <= d0; when "01" => z <= d1; when "10" => z <= d2; when "11" => z <= d3; end case; end process; end architecture;
Пример 4 type opcodes is (nop, add, subtract, load, store, jump, jumpsub, branch, halt); case opcode is when add to load => operand := memory_operand; when branch downto store => operand := address_operand; when others => operand := 0; end case;
Пример 5 type opcodes is (nop, add, subtract, load, store, jump, jumpsub, branch, halt); subtype control_transfer_opcodes is opcodes range jump to branch; when control_transfer_opcodes | store => operand := address_operand;
Пример нерегуларног case исказа variable N : integer := 1; case expression is when N | N+1 => ... when N+2 to N+5 => ... when others => ... end case; Да је N константа, горњи исказ би био коректан.
Селекциона додела променљивој with expression select[?] name := { expression when choices , } expression when choices ; Тек од VHDL 2008. Примјер: with func select result := operand1 when pass1, operand2 when pass2, operand1 + operand2 when add, operand1 - operand2 when subtract;
null исказ Начин да се специфицира да се у неком случају не дешава ништа case opcode is when add => Acc := Acc + operand; when subtract => Acc := Acc - operand; when nop => null; end case; control_section : process ( sensitivity_list ) is begin null; end process control_section;
assert i report Исказ намењен за помоћ при провери исправности модела. [ label : ] assert condition [ report expression ] [ severity expression ] ; Уколико се при симулацији деси да услов буде нетачан, генерише се обавештење; report клаузула омогућава да се прецизније опише место где је настала грешка, нпр.: assert current_character >= '0' and current_character <= '9' report "Input number " & input_string & " contains a non-digit"; Алат за синтезу може сматрати да ће услов бити тачан. severity: note – обавештење, warning – може се наставити али резултати могу бити неочекивани, error – грешка, потребно предузети акције за опоравак - подразумевано, failure – ситуација која се није смела догодити. report – исто као значење assert false... , али се пише без assert. подразумевано note.
Процедуре subprogram body <= procedure identifier [(parameter_interface_list)] is {subprogram_declarative_part} begin {sequential_statement} end [procedure] [identifier ]; Могу се декларисати у декларативном делу: пакета => видљива где год се користи тај пакет, архитектуре => видљива свим процесима, процеса => видљива само том процесу, други подпрограми=> видљива само у том подпрограму.
Пример procedure average_samples is variable total: real := 0.0; begin assert samples’length /= 0 severity failure; for index in samples’range loop total:= total + samples(index); end loop; average:= total/real(samples’length); end procedure average_samples;
Пример (1/3) architecture RTL of control_processor is type func_code is (add, subtract); signal op1, op2, dest: integer; signal Z_flag: boolean; signal func: func_code; ... begin ...
Пример (2/3) alu: process is procedure do_arith_op is variable result: integer; begin case func is when add => result:= op1 + op2; when sub => result:= op1 - op2; end case; dest <= result after Tpd; Z_flag <= result = 0 after Tpd; end procedure do_arith_op; http://stackoverflow.com/questions/9084975/vhdl-driving-signal-from-different-processes
Пример (3/3) begin ... do_arith_op; ... end process alu; ... end architecture RTL;
Параметри потпрограма interface_list <= ([constant | variable | signal] identifier {,...}: [mode] subtype_indication [:= static_expression]){,...} mode <= in | out | inout ; подразумевани мод: in. Подразумевано: in => constant out => variable inout => variable Од ВХДЛ 2008 дозвољено читање out параметара, али се добија последња уписана вриједност у процедури или ако још није додељена вредност, добија се почетна вредност.
Сигнали као параметри in: Процедура добија референцу на сигнал Ако у процедури постоји wait iсказ, вредност сигнала се може променити. out: Процедури се прослеђује референца на драјвер сигнала Приликом доделе вредности сигналу унутар процедуре, дефинишу се трансакције за прослеђени сигнал. inout: прослеђују се и референца на сигнал и референца на драјвер
Позивање процедуре procedure_call_statement <= [label:] procedure_name [(parameter_association_list)]; parameter_association_list <= ([parameter_name =>] expression | signal_name | variable_name | open) {,...} Примјери: procedure p(f1: in t1; f2: in t2; out t3; f4: in t4:=v4) is begin ... end procedure p; poziv: p(val1, val2, val3, val4); poziv: p(f1 => val1, f2=> val2, f4=> val4, f3=> val3); poziv: p(val1, val2, f4 => open, f3 => val3); Ако се везивање врши по називу, аргументи се могу навести произвољним редом.
Конкурентни позив процедуре concurrent_procedure_call_statement <= [label:] procedure_name [(parameter_association_list)]; Еквивалентно процесу који позива ту процедуру. Примјер: call_proc: p(s1, s2, 10) --s1, s2 сигнали call_proc: process is begin p (s1, s2, 10); wait on s1, s2; end process call_proc;
Функције subprogram body <= [pure | impure] function identifier [(parameter_interface_list)] return type_mark is {subprogram_declarative_part} begin {sequential_statement} end [function] [identifier ]; pure => резултат зависи само од параметара за исте аргументе увијек враћа исту вредност. Подразумијевано pure.
Параметри функција Исто као код процедура, осим: сви параметри морају бити типа in класа параметра не може бити променљива. in – подразумевани смер constant – подразумевана класа параметра.
Пример function limit(value,min,max:integer) return integer is begin if value > max then return max; elsif value <min then return min; else return value; end if; end function limit;
Функција now now враћа тренутно време. Примјер употребе: hold_time_checker : process ( clk, d ) is variable last_clk_edge_time : time := 0 fs; begin if rising_edge(clk) then last_clk_edge_time := now; end if; if d'event then assert now - last_clk_edge_time >= Thold_d_clk report "hold time violation"; end process hold_time_checker; http://vhdlguru.blogspot.com/2010/04/difference-between-risingedgeclk-and.html
Преклапање потпрограма Више потпрограма истог назива различитог броја и/или типа параметара. procedure increment (a:inout integer, n:in integer:=1) is ... procedure increment (a:inout bit_vector, n:in bit_vector :=1) is ... procedure increment (a:inout bit_vector, n: in integer:=1) is ...
Преклапање оператора function “+” (left, right: in bit_vector) return bit_vector is begin ... end function “+”; addr_reg:= addr_reg + X”0000_0004”;
Видљивост декларација Свака декларативна секција има одговарајућу секцију за исказе. Свака декларација се види од мјеста декларисања до краја одговарајуће секције за исказе.
Пакети Обједињују заједничке типове, константе, сигнале и потпрограме. package_declaration <= package identifier is {package_declarative_item} end [package] [identifier]; package_body <= package body identifier is {package_body_declarative_item} end [package body] [identifier];
Пример декларације пакета package cpu_types is constant word_size: positive:= 16; constant address_size: positive:= 24; subtype word is bit_vector(word_size-1 downto 0); subtype address is bit_vector(address_size-1 downto 0); type status_value is (halted, idle, fetch, mem_read, mem_write, io_read, io_write, int_ack); end package cpu_types;
Пример коришћења пакета Пакет се одвојено анализира и након тога смешта у радну библиотеку. (зависи од алата) Пример коришћења: entity address_decoder is port (addr: in work.cpu_types.address; status: in work.cpu_types.status_value; mem_sel, int_sel, io_sel: out bit); end entity address_decoder;
use use_clause <= use selected_name {,...}; selected_name <=naziv_biblioteke.naziv_paketa. (identifier | character_literal | operator_symbol | all) Примјер: use work.cpu_types.word, work.cpu_types.address; ... variable data_word: word; variable next_address: address; Примјер: use work.cpu_types.all; Sva imena iz paketa postaju vidljiva
Видљивост увезених идентификатора Стандардно: виде се у декларативној секцији у којој су увезени и одговарајућој секцији за исказе. Увезени на почетку фајла => виде се до краја фајла. Увезени испред ентитета (или пакета) => виде се и у одговарајућој архитектури (односно телу пакета). Конфликт са локалним идентификатором => директно видљив само локални глобалном се приступа преко пуног назива. Конфлит два увезена: имплицитни и експлицитни оператор => види се експлицитни у супротном ништа није директно видљив. Функције које могу да се преклопе => нема конфликта.
alias alias_declaration <= alias identifier is name; Примјери: alias alu_data_width is work.alu_types.data_width; Могуће је дефинисати и алијасе и за типове: alias binary_string is bit_vector; и за потпрограме: procedure increment (bv: inout bit_vector, by: in integer:= 1) alias bv_increment is work.ops.increment[bit_vector, integer]
Примери type register_array is array (0 to 15) of bit_vector(31 downto 0); type register_set is record general_purpose_registers: register_array; program_counter: bit_vector(31 downto 0); program_status: bit_vector(31 downto 0); end record; variable CPU_registers: register_set; alias PSW is CPU_registers.program_status; alias PC is CPU_registers.program_counter; alias GPR is CPU_registers.general_purpose_registers;
Разрешени сигнали Користе се када за један сигнал има више драјвера који генеришу његову вредност. Служи искључиво за потребе симулације за моделовње ситуација које није могуће моделовати са две вредности. Пример: моделовање стања високе импедансе type tri_state_logic is (‘0’, ‘1’, ‘Z’); type tri_state_logic_array is array (integer range<>) of tri_state; signal s: resolve_tri_state_logic tri_state_logic; Испред сигнала се наводи функција за разрешавање Приликом доделе нове вредности сигналу, позива се функција којој се као параметар прослеђује низ драјвера. Резултат позване функције се додељује сигналу.
Пример функције за разрешавање function resolve_tri_state_logic (values: in tri_state_array) return tri_state_logic is variable result: tri_state_logic:= ‘Z’; begin for index in values’range loop if values(index) /= ‘Z’ then result:= values(index); end if; end loop; return result; end function resolve_tri_state_logic; Која претпоставка мора важити да би функција дала очекивани резултат?
Пример разрешеног подтипа (1/2) type MLV4_ulogic is (‘X’, ‘0’, ‘1’, ‘Z’); type MLV4_ulogic_vector is array (natural range <>) of MVL4_ulogic; function resolve_MVL4 (contribution: MVL4_ulogic_vector) return MVL4_ulogic sybtype MVL4_logic is resolve_MVL4 MVL4_ulogic; type table is array (MVL4_ulogic, MVL4_ulogic) of MVL4_ulogic; constant resolution_table: table:= -- ‘X’ ‘0’ ‘1’ ‘Z’ ----------------------------- (( ‘X’, ‘X’, ‘X’, ‘X’), -- ‘X’ ( ‘X’, ‘0’, ‘X’, ‘0’), -- ‘0’ ( ‘X’, ‘X’, ‘1’, ‘1’), -- ‘1’ ( ‘X’, ‘0’, ‘1’, ‘Z’)) -- ‘Z’
Пример разрешеног подтипа (2/2) function resolve_MVL4 (contribution: MVL4_ulogic_vector) return MVL4_ulogic is variable result: MVL4_ulogic := 'Z' begin for index in contribution’range loop result:= resolution_table(result, contribution(index)); end loop; return result; end function resolve_MVL4;
Разрешавање вектора sybtype MVL4_logic_vector is (resolve_MVL4) MVL4_ulogic_vector; Заграде око функције за разрешавање говоре да се она примјењује на елементе вектора, а не на читав вектор. Могуће је имати и већи број заграда нпр. ако се разрешавају елементи матрице, користе се две заграде.
Разрешавање std_ulogic
Комбинационе vs. Секвенцијалне мреже
D latch временски параметри
DFF временски параметри
Синхроне vs. Асинхроне мреже Глобално синхроне мреже Сви меморијски елементи активни на ивицу једног сигнала клока Глабално асинхроне локално синхроне мреже Глобално асихнроне мреже Сви меморијски елементи имај свој клок Нема клока
Синхроне мреже Синтеза се своди на синтезу комбинационих мрежа Временска ограничења Један од најтежих проблема Временска анализа захтева само анализу комбинационих мрежа и једне повратне петље Симулација помоћу циклуса Тестирање помоћу “scan” алгоритама
Асинхроне мреже Комбинационе мреже са повратним везама Другачији дизајн у односу на комбинационе мреже Осетљиве на кашњење
Асинхроне мреже - пример library ieee; use ieee.std_logic_1164.all; entity dlatch is port( c: in std_logic; d: in std_logic; q: out std_logic ); end dlatch;
Асинхроне мреже - пример architecture demo_arch of dlatch is signal q_latch: std_logic; begin process (c, d, q_latch) if (c = '1') then q_latch <= d; else q_latch <= q_latch; end if; end process; q <= q_latch; end demo_arch;
Асинхроне мреже - пример
D FF library ieee; use ieee.std_logic_1164.all; entity dff is port( clk: in std_logic; d: in std_logic; q: out std_logic ); end dff;
D FF architecture demo_arch of dff is begin process (clk) if (clk’event and clk = '1') then q <= d; end if; end process; end demo_arch;
Register entity register8 is port(clk,reset:in std_logic; d:in std_logic_vector(7 downto 0); q:out std_logic_vector(7 downto 0) ); end entity register8;
Register architecture reg of register8 is begin process (clk, reset) is if (reset = '1') then q <= (others => '0'); elsif (clk'event and clk = '1') then q <= d; end if; end process write; end;
Проста секвенцијална кола
DFF са Enable сигналом
DFF са Enable сигналом library ieee; use ieee.std_logic_1164.all; entity dff is port( clk, reset, en: in std_logic; d: in std_logic; q: out std_logic ); end dff;
DFF са Enable сигналом architecture demo_arch of dff is signal q_reg, q_next : std_logic; begin process (clk, reset) if (reset = '1') then q_reg <= '0'; elsif (clk’event and clk = '1') then q_reg <= q_next; end if; end process;
DFF са Enable сигналом -- next-state logic q_next <= d when en = '1' else q_reg; -- output-state logic q <= q_reg; end demo_arch;
Shift register
Shift register
Shift register
Shift register Операције Учитавање Померање улево Померање удесно Задржавање старе вредности
Shift register library ieee; use ieee.std_logic_1164.all; entity shift_register is port(clk,reset:in std_logic; ctrl:in std_logic_vector(1 downto 0); d:in std_logic_vector(3 downto 0); q:out std_logic_vector(3 downto 0) ); end entity shift_register;
Shift register architecture usr of shift_register is signal r_reg: std_logic_vector(3 downto 0); signal r_next: std_logic_vector(3 downto 0); begin process (clk, reset) is if (reset = '1') then r_reg <= (others => '0'); elsif (clk'event and clk = '1') then r_reg <= r_next; end if; end process;
Shift register with ctrl select r_next <= r_reg when "00", r_reg(2 downto 0) & d(0) when "01", d(3) & r_reg(3 downto 1) when "10", d when others; q <= r_reg; end usr;
Алтернатива Мешање кода за меморијске елементе и комбинациону логику у једном или више процеса За проста кола код може да буде елегантнији Обично се стварају неочекиване грешке Избегавати!!!
Променљиве Могу да се користе за моделирање меморијских елемената Локална за процес Додела вредности променљивој пре употребе Не захтева прављење меморијског елемнта Коришћење променљиве пре доделе Захтева прављење меморијског елемента Лако је направити грешку Најчешћа употреба Смештање међурезултата без прављења меморијских елемената
Променљиве - пример library ieee; use ieee.std_logic_1164.all; entity variable_demo is port(clk:in std_logic; a,b:in std_logic; q1, q2, q3:out std_logic ); end entity variable_demo;
Променљиве - пример architecture arch of variable_demo is signal tmp_sig1: std_logic; begin -- atempt 1 process (clk) if (clk'event and clk = '1') then tmp_sig1 <= a and b; q1 <= tmp_sig1; end if; end process;
Променљиве - пример -- atempt 2 process (clk) variable tmp_var2:std_logic; begin if (clk'event and clk = '1') then tmp_var2 := a and b; q2 <= tmp_var2; end if; end process; end arch;
Променљиве - пример -- atempt 3 process (clk) variable tmp_var3:std_logic; begin if (clk'event and clk = '1') then q3 <= tmp_var3; tmp_var3 := a and b; end if; end process; end arch;
Променљиве - пример
Register transfer (RT) моделовање Како реализовати алгоритам у хардверу? Две одлике алгоритама: Коришћење променљивих Секвенцијално извршавање
Register transfer (RT) моделовање Пример алгоритма: Сабирање 4 броја Дељење резултата са 8 Заокруживање резултата
Dataflow Имплементација у VHDL-у Конвертован алгоритам у комбинациону мрежу Нема меморијских елемената Секвенца је одређена током података
Dataflow
Dataflow
Dataflow Проблеми: Лако за тривијалне алгоритме Није флексибилно Број улазних елемената треба да се повећа Број улазних елемената треба да буде произвољан
RT моделовање Користити регистре за имитирање променљивих из алгоритма Користити ток података за реализацију свих регистарских операција Користити КА-те за одређивање редоследа регистарских операција
RT операције Основна форма Интерпретација: После узлазне ивице сигнала такта, излази изворишних регистара су спремни Излази се прослеђују комбинационој мрежи која врши произвољну функцију На следећу ивицу сигнала такта, резултат се смешта у дестинациони регистар
RT операције Пример: r ← 1 r ← r r0 ← r1 n ← n - 1 y ← a xor b xor c xor d s ← a2 + b2
RT пример имплементације r1 ← r1 + r2
KA као контролна јединица КА је добар као контролна јединица за RT операције Стања се мењају на сваки сигнал такта КА може да омогући секвенцијално извршавање КА дозвољава опције (гранање) Дијаграм тока добар за репрезентовање контролне јединице
RT систем
GCD коло - пример GCD – Највећи заједнички делилац GCD без дељења gcd(a, b) = a if a = b gcd(a – b, b) if a = b gcd(a, b - a) if a = b
GCD коло - пример Псеудо алгоритам a = a_in; b = b_in; while (a /= b) { if (b > a) then a = a – b; else b = b – a; end if } r = a;
GCD коло - пример Модификован псеудо алгоритам a = a_in; b = b_in; swap: if (a = b) then goto stop; else if (b > a) then a = b; --swap a and b b = a; end if; a = a – b; goto swap; stop: r = a;
Дијаграм тока
Инстанцирање ентитета component_instantiation_statement <= instantiation_label: entity entity_name [(architecture_identifier)] [generic map (generic_association_list)] [port map (port_association_list)]; port_association_list <= ([port_name =>] (signal_name|expression|open)) {, ...} open – означава да порту није придружен сигнал. Уколико се наведу називи портова, редослед није битан. Пре ВХДЛ 2008 израз је морао бити статички => израчунати одговарајући израз као конкурентни исказ доделе вредности сигналу и тај сигнал мапирати на порт.
Пример entity DRAM_controller is port (rd, wr, mem: in bit; ras, cas, we, ready: out bit); end entity DRAM_controller; mem_controller: entity work.DRAM_controler (fpld) port map (cpu_rd, cpu_wr, cpu_mem, mem_ras, mem_cas, mem_we, cpu_rdy) mem_controller: entity work.DRAM_controler (fpld) port map (rd => cpu_rd, wr =>cpu_wr, mem => cpu_mem, ras => mem_ras, cas => mem_cas, we => mem_we, ready => cpu_rdy)
Компоненте Декларација vs дефиниција. Могуће их је декларисати и у пакетима. тада се у декларативном делу архитектуре увози назив компоненте (USE naziv_paketa.naziv_komponente). component_declaration <= component identifier [is] [generic (generic_interface_list);] [port (port_interface_list);] end component [identifier]; Primer: component flipflop is generic (Tprop, Tsetup, Thold: delay_lenght); port (clk: in bit; clr: in bit; q: out bit); end component flipflop;
Инстанцирање компонената component_instantiation_statement <= instantiation_label: [component] component_name [generic map (generic_association_list)] [port map (port_association_list)]
Пример (1/2) entity reg4 is port (clk, clr: in bit, d: in bit_vector(0 to 3), q: out bit_vector (0 to 3)); end entity reg4; architecture struct of reg4 is component flipflop is generic (Tprop, Tsetup, Thold: delay_lenght); port (clk: in bit; clr: in bit; q: out bit); end component flipflop; ...
Пример (2/2) ... begin bit0: component flipflop generic map (Tprop=>2ns, Tsetup=>2ns, Thold=>1ns) port map (clk=>clk, clr=>clr, d=>d(0), q=>q(0)); bit1: component flipflop generic map (Tprop=>2ns, Tsetup=>2ns, Thold=>1ns) port map (clk=>clk, clr=>clr, d=>d(1), q=>q(1)); ... end;
Конфигурисање компонената Свака компонента може имати више реализација => Конфигурацијом се компоненте везују за жељене ентитете. configuration_declaration <= configuration identifier of entity_name is for architecture_name {for component_specification binding_indication; end for;} end for; end [configuration] [identifier]; component_specification ⇐ ( instantiation_label { , … } I others I all ) : component_name binding_indication ⇐ use entity entity_name[(architecture_identifier ) ] Називи портова компоненте и ентитета за који се везује се морају поклапати.
Пример configuration reg4_gate_level of reg4 is for struct -- architecture of reg4 for bit0: flipflop use entity edge_triggered_Dff(hi_fanout); end for; for others: flipflop use entity edge_trigerd_Dff(basic); end for; end for; -- end of architecture struct end configuration reg4_gate_level;
Конфигурисање компонената Ако се компонента везује са ентитетом за који је такође потребна конфигурација, тада се при везивању уместо: use entity naziv_entiteta koristi: use configuration naziv_konfiguracije Могуће је и угнездити конфигурације, није прегледан => не препоручује се. Могуће директно инстанцирати конфигурације: instantiation_label : configuration configuration_name [ generic map ( generic_association_list ) ] [ port map ( port_association_list ) ] ;
Пример configuration counter_down_to_gate_level of counter is for registered for all : digit_register use configuration work.reg4_gate_level; end for; ... -- bindings for other component instances end for; -- end of architecture registered end configuration counter_down_to_gate_level;
Конфигурисање Омогућава ремапирање портова и генеричких константи, као и прилагођавање ентитета компонентама binding_indication ⇐ use (entity entity_name [(architecture_identifier )] I configuration configuration_name ) [ generic map ( generic_association_list ) ] [ port map ( port_association_list ) ]
Пример (1/3) architecture structure of computer_system is component decoder_2_to_4 is generic ( prop_delay : delay_length ); port ( in0, in1 : in bit; out0, out1, out2, out3 : out bit ); end component decoder_2_to_4; ... begin interface_decoder : component decoder_2_to_4 generic map ( prop_delay => 4 ns ) port map ( in0 => addr(4), in1 => addr(5), out0 => interface_a_select, out1 => interface_b_select, out2 => interface_c_select, out3 => interface_d_select ); end architecture structure;
Пример (2/3) Уместо декодера 2 на 4 имамо 3 на 8: entity decoder_3_to_8 is generic ( Tpd_01, Tpd_10 : delay_length ); port ( s0, s1, s2 : in bit; enable : in bit; y0, y1, y2, y3, y4, y5, y6, y7 : out bit ); end entity decoder_3_to_8;
Пример (3/3) configuration computer_structure of computer_system is for structure for interface_decoder : decoder_2_to_4 use entity work.decoder_3_to_8(basic) generic map ( Tpd_01 => prop_delay, Tpd_10 => prop_delay ) port map ( s0 => in0, s1 => in1, s2 => '0', enable => '1', y0 => out0, y1 => out1, y2 => out2, y3 => out3, y4 => open, y5 => open, y6 => open, y7 => open ); end for; ... end configuration computer_structure;
Одложено везивање Користи се у сложеном дизајну када је потребно тестирати један део система који је тренутно завршен. binding_indication ⇐ use open
Генерисање структура Користе се у случају репликације компонената. for_generate_statement ⇐ generate_label : for identifier in discrete_range generate generate_statement_body end generate [ generate_label ] ; generate_statement_body ⇐ [ { block_declarative_item } begin ] { concurrent_statement } [ end ; ]
Пример (1/3) Описати регистар генеричке ширине. entity register_tristate is generic (width: positive); port (clock: in std_logic; out_enable: in std_logic; data_in: in std_logic_vector(0 to width-1); data_out: out std_logic_vector(0 to width-1); end entity register_tristate;
Пример (2/3) architecture cell_level of register_tristate is component D_flipflop is port (clk, d: in std_logic; q: out std_logic); end component D_flipflop; component tristate_buffer is port (a, en: in std_logic; y: out std_logic); end component tristate_buffer;
Пример (3/3) begin cell_array: for bit_index in 0 to width-1 generate signal data_unbuffered: std_logic; begin cell_storage: component D_flipflop port map (clk=> clock, d=>data_in(bit_index), q=>data_unbaffered); cell_storage: component tristate_buffer port map (a=> data_unbaffered, en=>out_enable, y=>data_out(bit_index)); end generate cell_array; end architecture cell_level;
Условно генерисање структура if_generate_statement ⇐ generate_label : if [alternative_label :] condition generate generate_statement_body { elsif [alternative_label :] condition generate generate_statement_body } [ else [alternative_label :] generate generate_statement_body ] end generate [ generate_label ] ; elsif i else су присутни тек у VHDL-2008.
Конфигурисање генерисаних компоненти block_configuration ⇐ for ( architecture_name I block_statement_label I generate_statement_label [ ( ( static_discrete_range I static_expression I alternative_label ) ) ] ) { block_configuration I for component_specification [ binding_indication ; ] [ block_configuration ] end for ; } end for ;
Пример configuration widget_cfg of arith_unit is for ripple_adder for adder for adder_cell(most_significant) for add_bit: full_adder use entity widget_lib.full_adder(asic_cell); end for; for adder_cell(middle) for adder_cell(least_significant) for add_bit: half_adder use entity widget_lib.half_adder(asic_cell); end for; -- adder end for; -- ripple_adder end configuration widget_cfg; adder: for i in width-1 downto 0 generate signal carry_chain : unsigned(width-1 downto 1); begin adder_cell: if most_significant: i = width-1 generate add_bit: component full_adder port map (...); elsif least_significant: i = 0 generate add_bit: component half_adder else middle: generate end generate adder_cell; end generate adder;
Ентитет и конкурентни искази entity identifier is [ generic (generic_interface_list);] [ port (port_interface_list);] {entity_declarative_item} [begin { concurrent_assertion_statement | passive_concurrent_procedure_call_statement | passive_process_statement } ] end [entity] [identifier];
Пример Опис SR леч кола: entity S_R_flipflop is port (s, r: in; q, q_n: out bit); begin check: assert not (s=‘1’ and r=‘1’) report “Incorrect use: s and r both ‘1’”; end entity and2;
register i bus signal_declaration ⇐ signal identifier { , … } : subtype_indication [ register I bus ] [ := expression ] ; Морају бити разрешени сигнали. register – дисконектовани сви драјвери => памти се последња вредност bus – дисконектовани сви драјвери => позива се функција за разрешавање са празним низом драјвера
Фајлови и улаз/излаз Дефинисање типа фајла: Пример: Дефинисање фајла: file_type_definition ⇐ file of type_mark Пример: type integer_file is file of integer; Дефинисање фајла: file identifier { , … } : subtype_indication [ [ open file_open_kind_expression] is "naziv_fajla"]; type file_open_kind is (read_mode, write_mode, append_mode); подразумевано za фајлове на диску: read_mode.
Отварање фајла Ако је при дефиницији наведено open: Ако се фајл дефинише у пакету, архитектури или процесу => отвара се имплицитно на почетку симулације, затвара се имплицитно на крају симулације. Ако се фајл дефинише у потпрограму => отвара се приликом позива потпрограма, затвара се приликом повратка из потпрограма. У супротном, отвара се и затвара експлицитно: Отварање procedure file_open ( file f : file_type; external_name : in string; open_kind : in file_open_kind := read_mode ); Затварање procedure file_close ( file f : file_type );
Читање из фајла Имплицитно дефинисане функције: procedure read ( file f:file_type; value:out element_type ); function endfile ( file f : file_type ) return boolean; Читање почиње од почетка. Након читања, текућа позиција се помера.
Пример (1/3) library ieee; use ieee.std_logic_1164.all; entity ROM is generic ( load_file_name : string ); port ( sel : in std_ulogic; address : in std_ulogic_vector; data : inout std_ulogic_vector ); end entity ROM; Иницијализовање ром меморије.
Пример (2/3) architecture behavioral of ROM is begin behavior : process is subtype word is std_ulogic_vector(0 to data'length - 1); type storage_array is array (natural range 0 to 2**address'length - 1) of word; variable storage : storage_array; variable index : natural; ... -- other declarations type load_file_type is file of word; file load_file : load_file_type open read_mode is load_file_name;
Пример (3/3) begin -- load ROM contents from load_file index := 0; while not endfile(load_file) loop read(load_file, storage(index)); index := index + 1; end loop; -- respond to ROM accesses loop ... end process behavior; end architecture behavioral;
Упис у фајл Користи се да се резултати симулације сачувају у фајл. Нпр.: мерење фреквенције појединих инструкција, утицај параметара дизајна на перформансе, ... По отварању фајла за упис, креира се нови фајл; ако је већ постојао истоимени фајл, биће обрисан. Процедура за упис: procedure write ( file f : file_type; value : in element_type ); Ако је фајл отворен у моду append, дописује се на крај фајла. Ако фајл не постоји, биће креиран нови. Омогућава акумулацију резултата низа симулација.
Преносивост Претходно описани фајлови су бинарни фајлови. За бинарне фајлове, начин кодирања података у фајлу зависи од алата и система. Решење => користити текстуалне фајлове.
Пакет textio Користи се показивач на стринг: type line is access string; Дефинисан је тип текстуалног фајла: type text is file of string; Тип за дефинисање поравнања: type side is (right, left); Тип за ширину поља приликом исписа: subtype width is natural; Предефинисани су фајлови за стандардни улаз и излаз: file input : text open read_mode is "STD_INPUT"; file output : text open write_mode is "STD_OUTPUT"; access – показивач
Читање из текстуалног фајла Алоцира стринг, учита једну линију у тај стринг и кроз L враћа показивач на учитану линију: procedure readline(file F: text; L: inout line); Потом се користи нека од функција за конверзију. Важи за све: ако је читање успешно, из стринга се брише прочитано, варијанте са 2 и 3 параметра, разликују се у случају неуспеха, верзија са два параметра пријављује грешку ако читање није успело; сви подаци остају неизмењени, трећи параметар се поставља на нетачно у случају неуспелог читања; коришћени подаци остају неизмењени. Функције за читање знакова: procedure read ( L : inout line; value: out character; good : out boolean ); procedure read ( L : inout line; value: out character );
Читање стрингова procedure read ( L : inout line; value: out string ); чита тачно онолико знакова колики је одредишни стринг; ако нема довољно знакова, читање је неуспешно. procedure sread ( L: inout line; value : out string; strlen: out natural); прескаче бланко знакове на почетку; чита највише онолико континуалних небланко знакова колико стаје у стринг; у strlen враћа број учитаних знакова. Пример за стринг већичине 4 знака: ако је садржај линије " st ring ", биће учитано st
Конверзија у бите Конверзија у бит: procedure read ( L : inout line; value: out bit ); Конверзија у бит вектор: ако стринг садржи бинарно записане векторе: procedure read ( L : inout line; value: out bit_vector ); alias bread is read [line, bit_vector]; ако стринг садржи хексадецимално записане векторе: procedure hread ( L: inout line; value: out bit_vector ); У оба случаја у фајлу је константа без ознаке основе. За std_logic постоје одговарајуће функције у пакету ieee.std_logic_textio. При читању хексадецимално записаног вектора, највиши бити се одбацују и морају бити 0. Као део вектора може да се нађе и доња црта.
Читање времена и бројева Читање времена: procedure read ( L : inout line; value: out time ); Време мора бити записано са размаком између броја и јединице времена Читање целих бројева: procedure read ( L : inout line; value: out integer );
Универзални тест Процес који улазне тест векторе чита из фајла. Могуће је извршити низ различитих симулација са истим testbench-ом мењајући само улазни фајл => нема потребе за рекомпилацијом. Пример улазног фајла: 0 ms on 0 2 ms fail 0 15 ms temp 56 100 ms set 70 1.5 sec on 1
Пример – "универзални тест" stimulus_interpreter : process is use std.textio.all; file control : text open read_mode is "control"; variable command : line; variable read_ok : boolean; variable next_time : time; variable whitespace : character; variable signal_id : string(1 to 4); variable temp_value, set_value : integer; variable on_value, fail_value : bit;
Пример – "универзални тест" command_loop : while not endfile(control) loop --čitanje jedne linije iz fajla readline ( control, command ); --čitanje trenutka kada treba da se izvrši promena read ( command, next_time, read_ok ); if not read_ok then report "error reading time from line: " & command.all severity warning; next command_loop; end if; wait for next_time - now;
Пример – "универзални тест" --preskakanje blanko znakova while command'length > 0 and ( command(command'left) = ' ' or command(command'left) = ' ' --non breaking space or command(command'left) = HT ) loop read ( command, whitespace ); end loop; -- čitanje naziva signala read ( command, signal_id, read_ok ); if not read_ok then report "error reading signal id from line: " & command.all severity warning; next command_loop; end if;
Пример – "универзални тест" -- dispatch based on signal id case signal_id is when "temp" => read ( command, temp_value, read_ok ); if not read_ok then report "error reading temperature value from line: " & command.all severity warning; next command_loop; end if; temperature <= temp_value; when "set " => ... – slično prethodnom
Пример – "универзални тест" when "on " => read ( command, on_value, read_ok ); if not read_ok then report "error reading on value from line: " & command.all severity warning; next command_loop; end if; enable <= on_value; when "fail" => ... – slično prethodnom when others => report "invalid signal id in line: " & signal_id severity warning; end case; end loop command_loop; wait; end process stimulus_interpreter;
Упис у текстуални фајл Прво се изврши конверзија из задатог типа у линију, па се потом линија упише у фајл. Упис само у задати фајл: procedure writeline ( file F : text; L : inout line ); Упис у задати фајл и на стандардни излаз: procedure tee ( file F: text; L: inout line ); Ако је L = null, на излаз се исписује празна линија.
Упис у текстуални фајл function justify ( value: string; justified: side := right; field: width := 0 ) return string; стринг value се у новом стрингу ширине width поравнава уз задату ивицу; остатак резултујућег стринга се попуњава бланко знацима аналогно важи и за остале процедуре, с тим што се резултујући стринг надовезује на крај линије. procedure write ( L : inout line; value : in bit; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in bit_vector; justified: in side := right; field: in width := 0 ); procedure hwrite ( L: inout line; value: in bit_vector; justified: in side := right; field: in width := 0 ); procedure write ( L : inout line; value : in time; justified: in side := right; field: in width := 0; unit: in time := ns );
Упис у текстуални фајл procedure write ( L : inout line; value : in string; justified: in side := right; field: in width := 0 ); alias swrite is write [line, string, side, width]; alias bwrite is write [line, bit_vector, side, width]; procedure write ( L : inout line; value : in integer; justified: in side := right; field: in width := 0 ); Приликом уписа константи типа string или bit_vector неопходно је навести тип константе. Примјер: write ( L, string'( "fred" ) ); write ( L, ' ' ); write ( L, bit_vector'( X"3A" ) ); Садржај резултујуће линије ако је на почетку линија била празна: fred 00111010