Sekvensiell logikk De fleste digitale systemer har også minneelementer (f.eks flipflopper) i tillegg til kombinatorisk logikk, og kalles da sekvensiell logikk Output i en sekvensiell krets er avhengig av både nåværende input og nåværende tilstand (state) til minneelementene.
Synkron logikk Sekvensiell logikk; to typer: Synkron sekvensiell logikk Asynkron sekvensiell logikk Synkron logikk benytter klokkepulser, s.a. minneelementene bare oppdateres til bestemte tider (stigende-/fallende klokkeflanke)
library ieee; use ieee.std_logic_1164.all; entity dff_logic is port ( d, clk : in std_logic; q : out std_logic); end dff_logic; D-flip-flop architecture example of dff_logic is process (clk) if (clk'event and clk = '1') then q <= d; end process; end example; if (clk'event and clk = '1') then if rising_edge(clk) = 1 then -- stigende flanke ingen else; dvs. indirekte minne (q beholder verdien) if (clk'event and clk = 0') then If falling_edge(clk) = 1 then -- fallende flanke
process (clk,d) if (clk = '1') then q <= d; end process; D-latch - nivåsensitiv if (clk'event and clk = '1') then q <= d; har samme mening som if (clk'event and clk = '1') then q <= d; else q <= q; Men følgende er ikke klart hvordan skal syntetiseres if (clk'event and clk = '1') then q <= d; else q <= a;
8-bits register library ieee; use ieee.std_logic_1164.all; entity reg_logic is port ( d : in std_logic_vector(0 to 7); clk : in std_logic; q : out std_logic_vector(0 to 7)); end reg_logic; architecture r_example of reg_logic is process (clk) if (clk'event and clk = '1') then q <= d; end process; end r_example; Laster ny verdi inn i registeret på stigende klokkeflanke
rising_edge og falling_edge Definert av pakken std_logic_1164 Signalet må være av typen std_logic for å benytte disse to funksjonene Detekterer stigende/fallende flanke på signaler library ieee; use ieee.std_logic_1164.all; entity dff_logic is port ( d, clk : in std_logic; q : out std_logic); end dff_logic; architecture example of dff_logic is process (clk) if rising_edge (clk) then q <= d; end process; end example library ieee; use ieee.std_logic_1164.all; entity dff_logic is port ( d, clk : in std_logic; q : out std_logic); end dff_logic; architecture example of dff_logic is process (clk) if falling_edge (clk) then q <= d; end process; end example
rising_edge og falling_edge Tips: Ikke forsøk å skrive en prosess som trigger på både stigende og fallende flanke, det går ikke! Skriv dette i stedet som to separate prosesser ikke_lov: process(clk) if rising_edge(clk) then < gjør noe> elsif falling_edge(clk) then < gjør noe annet> end process;
Reset i synkron logikk; asynkron reset library ieee; use ieee.std_logic_1164.all; entity dff_logic is port ( d, clk, reset: in std_logic; q : out std_logic); end dff_logic; architecture rexample of dff_logic is process (clk, reset) if reset = '1' then q <= '0'; elsif rising_edge(clk) then q <= d; end process; end rexample; reset og preset: plassere logikken i en kjent tilstand hvis man ønsker preset-funksjon: if preset = '1' then q <= 1'
Synkron reset architecture sync_rexample of dff_logic is process (clk) if rising_edge(clk) then if (reset = '1 ) then q <= '0'; Synkron logikk else q <= d; end process; end sync_rexample; reset plassert innenfor den delen av prosessen som beskriver logikk som er synkron med klokka
8-bits register med asynkron reset og synkron initialisering
Aritmetiske operatorer (+, -, *, / osv.) I syntese: + og mest brukt * og / krever veldig mye logikk! Aritmetriske operatorer er definert for integer og floating. Må bruke biblioteker (f.eks std_arith fra warp) hvis aritmetriske operatore skal brukes for andre typer, som f.eks std_logic
Asynkron reset og synkron load 8 bit teller
Kombinere reset og preset cnt <= (others => 0 ) cnt <= 00000000 ; for i in 0 to 7 loop cnt(i) <= 0 ; end loop;
Three-state buffers Gjør at output buffere kan settes i en høy-impedans ( Z ) tilstand, slik at ikke flere drivere driver en buss samtidig Tre mulige signalnivåer: 0, 1, Z De fleste programmerbare kretser har three-state buffere på utgangene (de signalene som er definert som port i entiteten) NB! Mange programmerbare kretser har ikke mulighet for three-state buffere internt i kretsen (på interne signaler)
library ieee; use ieee.std_logic_1164.all; use work.std_arith.all; entity cnt8 is port( txclk, grst: in std_logic; enable, load: in std_logic; oe: in std_logic; data: in std_logic_vector(7 downto 0); cnt_out: buffer std_logic_vector(7 downto 0)); end cnt8; 3-state buffere Eksempel: 8 bit teller architecture archcnt8 of cnt8 is signal cnt: std_logic_vector(7 downto 0); count: process (grst, txclk) if grst = '1' then cnt <= "00111010"; elsif rising_edge(txclk) then if load = '1' then cnt <= data; elsif enable = '1' then cnt <= cnt + 1; end process count; oes: process (oe, cnt) - if oe = '0' then cnt_out <= (others => 'Z'); else cnt_out <= cnt; end process oes; end archcnt8;
library ieee; use ieee.std_logic_1164.all; use work.std_arith.all; entity cnt8 is port(... collision: out std_logic;... end cnt8; -- 3-state output architecture archcnt8 of cnt8 is signal cnt: std_logic_vector(7 downto 0); count: process (grst, txclk).. end process count; -- three-state outputs described here: cnt_out <= (others => 'Z') when oe = '0' else cnt; collision <= (enable and load) when oe = '1' else 'Z'; dataflow end archcnt8;
Bidireksjonal signaler entity cnt8 is port(.. cnt_out: inout std_logic_vector(7 downto 0)); -- mode inout req'd end cnt8; architecture archcnt8 of cnt8 is signal cnt: std_logic_vector(7 downto 0); count: process (grst, txclk) if grst = '1' then cnt <= "00111010"; elsif (txclk'event and txclk='1') then if load = '1' then cnt <= cnt_out; elsif enable = '1' then cnt <= cnt + 1; end process count; Leser inn fra bussen oes: process (oe, cnt) if oe = '0' then cnt_out <= (others => 'Z'); else cnt_out <= cnt; end process oes; end archcnt8;
Konvertere interne 3-state til multipleksere Hvis den programmerbare kretsen ikke har interne tretilstands buffere, kan multiplekser-logikk brukes i stedet
Løkker for loop for i in 7 downto 0 loop fifo(i) <= (others => '0'); end loop; Løkke -variabelen i automatisk deklarert i en for loop while loop reg_array: process (rst, clk) variable i: integer :=0; if rst = '1' then while i < 7 loop fifo(i) <= (others => '0'); i := i + 1; end loop; Deklarasjon og initialisering av løkke-variabelen i inkremntering av løkkevariabelen i
Løkker II Hoppe over et element i en løkke ved å benytte next Hopper ut av løkken med exit
Bruk av integer Synteseverktøyet vil konvertere en integer til en binær verdi, slik at tellere som er beskrevet med integer vil starte på null igjen når den når sin maksimalverdi. En VHDL simulator derimot, vil ikke konvertere en integer til en binær verdi, og vil gi en feilmelding når man forsøker å øke verdien ut over maksimalverdien. Løsninger for å gjøre syntese og simulering kompatible: Null ut integeren etter at den har nådd sin maksimale verdi Bruk std_logic_vector i stedet for integer signal cnt: integer range 0 to 255; cnt <= cnt + 1; signal cnt: std_logic_vector( 7 downto 0); cnt <= cnt + 1;
Unintentional registers NB! Signaltilordninger etter if (clk event and clk = 1 ) representerer tilstander til flip-flopper! NB! Signaler oppdateres rett før prosessen termineres; ikke umiddelbart! Gjør at a og h ikke mellomlagres i registre!
OBS! OBS! x ikke tilordnet den nye verdi enda. Sammenlikner derfor med verdien x fikk forrige gang prosessen ble utført!
Variabel-tilordning skjer umiddelbart!
Bruk av variable Variable bare synlig innenfor prosessen de er deklarert i For å bruke variabelens verdi utenfor prosessen, må verdien tilordnes et signal innenfor prosessen. Syntese av variable ikke veldefinert! Derfor brukes variable primært bare til indeksering (f.eks i en while-løkke) i kode som skal syntetiseres Ikke skriv tellere slik som koden til venstre; bruk signaler i stedet! Et signal tilordnes verdien til variabelen