UMEÅ UNIVERSITET Tillämpad fysik och elektronik Digitalteknik Lars Wållberg Håkan Joëlson 2002-10-10 v 1.4 Elektronik DIGITALTEKNIK Grunderna i VHDL Innehåll Inledning...1 KOMBINATORISKA FUNKTIONER...1 Entity. Mode. Type...2 Backus-Naur form...2 Architecture...3 Concurrent Statement...4 Parallell/Sekventiell...4 Alternativa programlösningar...6 Process...7 Fler programalternativ...8 Vector-deklarationer...8 SEKVENSFUNKTIONER...10 Moore. Mealy...10 Tillståndsdiagram...11 Moore-exempel...12 Three_process_FSM...13 Mealy-exempel...14
INLEDNING Under första hälften av 1990-talet expanderade elektronikindustrin kraftigt. Höghastighets datakommunikation och tillverkning av persondatorer, mobiltelefoner är exempel på sådana expansiva produktområden. Marknaden hade en efterfrågan på produkter med flera och mer komplexa funktioner, billigare kretsar med lägre effektförbrukning och med allt mindre dimensioner. Dessutom ville man att tiden från ide till färdig produkt skulle kunna väsentligt förkortas. För att möta den efterfrågan som marknaden hade krävdes att både de programmerbara logiska kretsarna (PLD s) och de språk som behövdes för att beskriva de logiska funktionerna i dessa kretsar utvecklades. De beskrivningsspråk som för närvarande (år 1999) dominerar är Verilog och VHDL. Många konstruktionsverktyg ger användaren möjlighet att välja något av dessa två språk som båda är standardiserade enligt IEEE-normen. Olika varianter av beskrivningsspråk, HDL (Hardware Description Language) utvecklades. HDL är en samlingsförkortning som används för många språk. Mot slutet av1980-talet utvecklades en form som fick namnet VHDL. V:et kommer från VHSIC (Very High Speed Integrated Circuit). VHDL står alltså för Very high speed integrated circuit Hardware Description Language. 1987 standardiserades VHDL. Detta kompendium ska ge grundläggande information om VHDL. VHDL är ett ordrikt språk. Det är utvecklat för att passa både hårdvarukonstruktörer och programmerare. Innehållet i detta kompendium avser inte att beskriva VHDL på ett uttömmande sätt, men vill ge kunskaper i några språkkonstruktioner som är användbara för att beskriva enklare digitala funktioner. VHDL utvecklades för att beskriva och simulera digitala funktioner, inte för att konstruera (syntetisera) digital logik. Mer och mer användes det dock för syntes av logik. När man skriver VHDL-kod för syntes av logik är det viktigt att komma ihåg att det ursprungligen inte utvecklades för detta ändamål. Många språkkonstruktioner kan vara korrekt VHDL-syntax men omöjliga för syntesverktyg (konstruktionsprogramvara) att realisera (förverkliga med AND/ORlogik och vippor). De exempel som finns i detta häfte är alla skrivna med syfte att konstruktionerna ska realiseras i någon PLD. 1
KOMBINATORISKA FUNKTIONER ENTITY och ARCHITECTURE Två centrala begrepp i VHDL är Entity och Architecture. Entity är den kod som beskriver konstruktionens yttre anslutningar. I digitaltekniken kallar man dem portar. En port är en konstruktion som ger möjlighet till kommunikation med omvärlden. En figur beskriver enklast entityn s yttre anslutningar. Ingångar placeras vanligtvis till vänster och utgångar till höger. Pilar används också för att visa datariktning. In1 Entity ex1 Ut1 In2 In3 Ut2 Entity:ns portar är signaler. De kan vara av fyra sorter (modes). Mode beskriver datans riktning genom porten. MODE IN OUT INOUT BUFFER :Insignal :Utsignal (kan enbart tilldelas ett värde, inte läsas i architecturen) :Dubbelriktad signal :En slags signal som kan läsas i architecturen men ej användas som utsignal. TYPE Signalerna i entity:n måste ges en värdemängd. eller typ. Signaltyperna kan vara av många olika slag till exempel: TYPE VÄRDEMÄNGD bit 0 eller 1 bit_vector vektor där elementen kan anta värdena 0 eller 1. Ex 0100 boolean true/false integer heltal std_logic kan anta nio olika värden där 0 och 1 är två av dem std_logic_vector vektor där elementen kan anta nio olika värden där 0 och 1 är två av dem. Ex 0XH11ULW enumerated uppräkning av värden som kan antas t.ex. kalle, ulla o.s.v. time tid, minsta enhet Picosekunder. 2
SYNTAX För att beskriva VHDL-syntaxen generellt används Backus-Naur Form (BNF): Fetstil reserverade ord val av olika möjliga alternativ [ ] kan väljas. eller uteslutas. { } alternativa val som kan upprepas OBSERVERA att enl. VHDL-syntaxen ska varje statement eller declaration avslutas med semikolon!! Därför innehåller inte syntaxbeskrivningarna några semikolon!! Den generella beskrivningen av en entity med BNF är ENTITY entity entity_name is port ( identifier {,indentifier } :[mode] signaltype {;identifier {,identifier} [mode] signaltype} ); Så här kan entity:n i figuren ovan beskrivas med VHDL-kod. entity ex1 is port( In1 :in bit; In2,In3 :in bit; Ut1 :inout bit; ); Ut2 :out bit ARCHITECTURE Architecture är den VHDL-kod som beskriver sambandet mellan in och utsignaler. Här erbjuder VHDL ett flertal olika sätt att beskriva digitala funktioner. In1 Entity ex1 Ut1 In2 In3 ecture Som beskriver samband mellan in och utsignaler Ut2 Den generella beskrivningen av en architecture: architecture architecture_name of entity_name is type_declaration 3
signal_declaration constant_declaration component_declaration alias_declaration; attribute_specifikation subprogram_body {process_statement concurrent_signal_assignment_statement component_intstantiation_statement} I detta kompendium kommer följande moment att beskrivas: type_declaration, signal_declaration, component_declaration process_statement concurrent_signal_assignment_statement En architecture-beskrivning till entiteten ex1 kan se ut så här: architecture beh_ex1 of ex1 is ut2 <= ut1 or in3; ut1 <= in1 and in2; arcnitecture-namnet beh_ex1 är helt godtyckligt valt. ex1 är den entitet som architecturen beskriver. Signaltilldelning <= används för signaltilldelning (portar är signaler!!) CONCURRENT STATEMENTS Tilldelningsordningen mellan och end är helt godtycklig. Alla satser betraktas som samtidiga, så kallade concurrent_signal_assignment_statement. Satserna utförs så snart något till höger om tilldelningspilen ändrar värde, det vill säga tills utsignalerna får ett stabilt värde. Satser åtskiljs med semikolon. PARALLELL/SEKVENTIELL DATABEHANDLING All elektronik är till sin natur parallell. Man kan i praktiken se alla grindar och vippor som parallellt exekverande enheter. VHDL har språkkonstruktioner som kan hantera både parallell och sekventiell databehandling. Vissa kommandon är bara tillåtna i den parallella resp. sekventiella delen av koden. 4
Här följer en lista på vanligt förekommande VHDL-kommandon. Parallella konstruktioner Process When else With select Sekventiella konstruktioner If then else Case Variable declaration Variable assignment Loop statement Både parallella och sekventiella kommandon Signal assignment Boolean functions Declaration of types and constants Function and procedure calls Signal attributes VHDL-koden är parallell i hela architecturen utom inuti processer, funktioner och procedurer! Process är en central VHDL-konstruktion. Alla kod i processen exekveras sekventiellt och alltså är bara sekventiella instruktioner tillåtna. Vanliga sekventiella instruktioner är: If then else Case Motsvarande parallella kommandon är: When else With select Mer om processkonstruktionen senare i kompendiet. För att visa hur man med VHDL kan beskriva en digital funktion på olika sätt visas flera exempel med en MUX 2/1. d0 d1 entity mux2/1 architecture b_2/1 ut s En mux 2/1 väljer vilken av två datasignaler d0, d1 som ska överföras till utsignalen. Med s=0 => ut = d0 med s=1 => ut = d1 5
Konstruktionen kan göras med grindar enligt nedan s 1 d0 & ut d1 & Här följer koden för konstruktionens entity: entity mx2_1 is port( s,d0,d1 :in bit; ut :out bit ); Några förslag till architecture som realiserar en mux2_1 Boolean function architecture b_mx2_1 of mx2_1 is ut<= (not s and d0) or (s and d1); Exemplet beskriver konstruktionen med logiska funktioner. Observera att åtminstone den andra parentesen krävs för prioritetsordningen av funktionerna. architecture b_mx2_1 of mx2_1 is ut<= d0 when s='0' else d1; when... else Här används den parallella konstruktionen med when else. Syntax: {Signal_assignment when condition }else Signal_assignment; Architecturen kan även skrivas utan else architecture b_mx2_1 of mx2_1 is ut <= d0 when s='0'; ut <= d1 when s='1'; 6
Två varianter: with... select architecture b_mx2_1 of mx2_1 is with s select ut <= d0 when '0', d1 when '1'; architecture b_mx2_1 of mx2_1 is with s select ut <= d0 when '0', d1 when others; end Här används det reserverade kommandot others som representerar övriga alternativ. Others används ofta för att täcka in alla resterande möjliga fall. Syntax: with selection_expression select {identifier <= expression when identifier expression discrete_range others,} identifier <= expression when identifier expression discrete_range others; Alla exempel som hittills presenterats använder parallella kommandon mellan och end i architecturen. PROCESS STATEMENT PROCESS är en viktig VHDL-konstruktion. Om en architecture innehåller flera processer så betraktas dessa som parallella, det vill säga samtidiga, konstruktioner. Processen är ett subprogram där exekveringen är sekventiell. Syntax: [process_label:] process (sensitivity_list) {type_declaration constant_declaration variable_declaration alias_declaration} {wait_statement signal_assignment_statement variable_assignment_statement if_statement case_statement loop_statememt end process [process_lable]; 7
Observera att if, case och loop instruktioner bara är tillåtna i processer, funktioner och procedurer! OBS!! En process exekveras endast om någon av de signaler som finns i sensitivitetslistan ändrar värde!ingen sensitivitetslista medför att processen aldrig exekveras! Så här kan architecturen skrivas om man använder en process. architecture b_mx2_1 of mx2_1 is process (s,d0,d1) if s='0' then ut <= d0; else ut <= d1; end process; Inuti processen ovan används denna konstruktion. if... then... else Syntax: If condition then sequense_of_ assignment_statement {elsif condition then sequense_of_ assignment_statement} [else sequense_of_ assignment_statement] Om man i stället vill använda en case-sats kan architecturen skrivas: architecture b_mx2_1 of mx2_1 is process (s,d0,d1) case s is when '0' => ut <= d0; when '1' => ut <= d1; end process; Syntaxen för case-satsen är: case expression is {when identifier expression discrete_range others => sequence_of assignment_statements} VECTOR Ofta är det praktiskt att använda vectorer som signaler. I stället för att ge signaler namnen d0,d1,d2,d3 :in bit; så kan man namnge dem d :in bit_vector(3 downto 0); 8
Ett element i en vector kan man nå genom att skriva: d(2)= 0 eller d2<= 1 d(1 to 3)<= 101 Många fler aggregat (skrivsätt) finns att tillgå i VHDL-syntaxen. OBServera att vid typdeklarationen är den siffra som står till vänster i deklarationen den mest signifikanta! Därför används nästan uteslutande deklarationen d(7 downto 0). Elementet d(7) är då det mest signifikanta. Exempel 4 bitars Mux4_1 entity 4bit_mx_4/1 da 4 db dc architecture 4bit_mx_4/1 4 ut dd 2 s entity mx4_1 is port( s :in bit_vector(1 downto 0); da,db,dc,dd :in bit_vector (3 downto 0); ut :out bit_vector (3 downto 0) ); architecture bit4_mx4_1 of mx4_1 is with s select ut <= da when "00", db when "01", dc when "10", dd when "11"; Detta exempel visar hur enkelt man kan beskriva en ganska komplex kombinatorisk krets, med VHDL-kod. En beskrivning med logiska operatorer skulle bli mera omfattande. 9
SEKVENSFUNKTIONER (automater, maskiner ) MOORE OCH MEALY Det finns två huvudtyper av sekvensnät: Moore och Mealy Skillnaden och likhet framgår av nedanstående blockscheman. in Nxt State logic nxt Output logic ut pre clk State register Moore sekvensnät. Utsignalerna beror enbart av nuvarande tillstånd (pre). in Nxt State logic nxt Output logic ut pre clk State register Mealy sekvensnät. Utsignalen beror både av nuvarande tillstånd och aktuella insignaler. 10
TILLSTÅNDSDIAGRAM För att beskriva en funktionen hos sekvenskretsen behöver man beskriva såväl konstruktionens tillstånd som dess in- och utgångar. Ett sätt att göra en sådan beskrivning är med ett tillståndsdiagram. I VHDL används konstruktionens in och utgångar för att definiera portar i entiteten. Tillståndsdiagrammet är ett sätt att med en figur beskriva kretsens architecture. För att illustrera ett exempel visas följande figurer. gon=0 S1/u1 h=1 h=1 gon=0 v=1 S2/u2 S3/u3 h=1 gon=0 h v Sekvenskrets av Moore-typ ut gon Ibland bidrar en kompletterande text till att figurerna kan tolkas korrekt. Kretsen ska vara ett 3-bits-skiftregister som skiftar en etta åt höger (h) eller vänster (v). Om gon=0 stoppas skiftningen. På nästa sida ges ett förslag till VHDL-beskrivning av sekvenskretsen. Koden kommenteras senare. 11
Exempel på VHDL-kod för en Moore-maskin entity Moore_ex is port( gon,h,v :in bit; clk :in bit; u :out bit_vector(2 downto 0) ); architecture b_moore_ex of Moore_ex is type state is (s1,s2,s3); signal pre,nxt :state; --type declaration -- interna signaler p0: process(v,h,gon,pre) case pre is when s1 => if (v='0' and h='1' and gon='1') then nxt <= s2; elsif (h='0' and v='1' and gon='1') then nxt <= s3; else nxt <= s1; when s2 => if (v='0' and h='1' and gon='1') then nxt <= s3; elsif (h='0' and v='1' and gon='1') then nxt <= s1; else nxt <= s2; when s3 => if (v='0' and h='1' and gon='1') then nxt <= s1; elsif (h='0' and v='1' and gon='1') then nxt <= s2; else nxt <= s3; end process; p1: process(clk) if clk'event and clk='1' then pre <= nxt; end process; p2: process(pre) case pre is when s1 => u <= "100"; when s2 => u <= "010"; when s3 => u <= "001"; end process; 12
THREE-PROCESS-FSM VHDL-koden som redovisats på föregående sida är en så kallad, Three-Process-FSM (Finite State Machine). De tre processerna motsvarar var sitt block i blockschemat på sidan 10. Process P0 beskriver tillståndsdiagrammet med VHDL-kod och motsvarar det som i blockschemat benämnes Next State logic. Denna logik kommer ge upphov till ett kombinatoriskt nät av AND och OR-grindar som ska anslutas till vippornas preparatoriska ingångar. (D, RS eller JK - beroende på vilka vippor som är tänkta att användas). Denna logik avgör vilket som blir nästa tillstånd. Processen kallas för deklarationsdelen i koden. Process P1 avgör när ett tillståndsbyte ska ske. Processen aktiveras av tillståndsmaskinens klocka. I denna sekvenskrets kommer byte av tillstånd ske på positiv klockpulsflank. Processen benämnes synkroniseringsprocess, men kan även innehålla kod för asynkrona preset och reset-signaler. Processen motsvarar blocket State Register i blockschemat på sid. 10. Process P2 kallas i blockschemat för Output logic. Denna process ska ge upphov till ett kombinatoriskt nät av And och Or logik som genererar utsignaler beroende på i vilket tillstånd sekvensen befinner sig. Nyheter i koden är bland annat följande delar i architecturen: type state is (s1,s2,s3); signal pre,nxt :state; --type declaration -- interna signaler Vi behöver något i koden som representerar tillstånden. Därför deklarerar vi en ny typ, state, och anger vilken värdemängd den har. State är alltså en egenvald benämning liksom valet av tillståndsnamn. (s1, s2, s3) För att kunna kommunicera mellan blocken krävs två interna signaler. En från Nexte State logicblocket till registrens (vippornas) dataingångar, nxt, och en annan intern signal,pre, som anger vilket nuvarande tillstånd som kretsen befinner sig. I den synkrona processen anger koden: if clk'event and clk='1' then pre <= nxt; att byte av tillstånd ska ske på positiv klockpulsflank. 13
Exempel på VHDL-kod för en Mealy-maskin Här följer ett VHDL exempel som beskriver en Mealyautomat. Rita som övning ett tillståndsdiagram som illustrerar funktionen hos automaten. library ieee; use ieee.std_logic_1164.all; entity mealyex is port ( i :in std_logic_vector(2 downto 0); u :out std_logic_vector(2 downto 0); clk :in std_logic ); architecture b_mealyex of mealyex is type state is (s0,s1); signal cs,ns :state; p0:process (cs,i) case cs is when s0 => if i="000" then ns <= s1; else ns <= s0; when s1 => if i="001" then ns <= s0; else ns <= s1; end process; p1:process (clk) if rising_edge(clk) then cs <= ns; end process; p2:process (cs,i) case cs is when s0 => case i is when "001" => u <= "001"; when "101" => u <= "101"; when "100" => u <= "100"; when others => u <= "111"; when s1 => case i is when "000" => u <= "001"; when "101" => u <= "011"; when "100" => u <= "010"; when others => u <= "000"; end Process; 14