Tilstandsmaskiner (FSM) Kapittel 5
1) Sette opp tilstandsdiagram Tradisjonell konstruksjonsmetode
2) Sette opp tilstandstabell ut fra tilstandsdiagrammet Nåværende tilstand (PS) og input Neste tilstand (NS) og output
Sette opp de boolske likningene ut i fra tilstandstabellen. Bruke Karnaugh diagram til å forenkle de boolske likningene.
Tilstandsmaskiner i VHDL Tilstandsdiagram kan enkelt oversettes til VHDL beskrivelse! Eksempel: Tilstandsdiagrammet oversatt til 2- prosess FSM entity example is port ( read_write, ready, clk : in bit; oe, we : out bit); end example; architecture state_machine of example is type StateType is (idle, decision, read, write); signal present_state, next_state : StateType; begin Definert enumerert type
state_comb:process(present_state, read_write, ready) begin case present_state is when idle => oe <= '0'; we <= '0'; if ready = '1' then next_state <= decision; else next_state <= idle; when decision => oe <= '0'; we <= '0'; if (read_write = '1') then next_state <= read; else --read_write='0 next_state <= write; when read => oe <= '1'; we <= '0'; if (ready = '1') then next_state <= idle; else next_state <= read; when write => oe <= '0'; we <= '1'; if (ready = '1') then next_state <= idle; else next_state <= write; end case; end process state_comb; Fordi neste tilstand er bestemt av nåværende tilstand og input Beskriver tilstandsovergangene og output
state_clocked:process(clk) begin if (clk'event and clk='1') then present_state <= next_state; end process state_clocked; Synkron logikk end architecture state_machine; --"architecture" is optional; for clarity
2-prosess FSM clk
Simulering av tilstandsmaskinen
Koding av tilstander (utdrag av rapportfila fra synteseverktøyet) Sekvensiell enkoding
Eksempel: memorycontroller
Tilstandsdiagram Output i de ulike tilstandene
case present_state is when idle => oe <= '0'; we <= '0'; addr <= "00"; if (bus_id = "11110011") then next_state <= decision; else next_state <= idle; when decision=> oe <= '0'; we <= '0'; addr <= "00"; if (read_write = '1') then next_state <= read1; else next_state <= write; --read_write='0 when read1 => oe <= '1'; we <= '0'; addr <= "00"; if (ready = '0') then next_state <= read1; elsif (burst = '0') then next_state <= idle; else next_state <= read2; when read2 => oe <= '1'; we <= '0'; addr <= "01"; if (ready = '1') then next_state <= read3; else next_state <= read2; when read3 => oe <= '1'; we <= '0'; addr <= "10"; if (ready = '1') then next_state <= read4; else next_state <= read3; when read4 => oe <= '1'; we <= '0'; addr <= "11"; if (ready = '1') then next_state <= idle; else next_state <= read4; when write => oe <= '0'; we <= '1'; addr <= "00"; if (ready = '1') then next_state <= idle; else next_state <= write; end case;
library ieee; use ieee.std_logic_1164.all; entity memory_controller is port ( reset, read_write, ready, burst, clk : in std_logic; bus_id : in std_logic_vector(7 downto 0); oe, we : out std_logic; addr : out std_logic_vector(1 downto 0)); end memory_controller; architecture state_machine of memory_controller is type StateType is (idle, decision, read1, read2, read3, read4, write); signal present_state, next_state : StateType; begin state_comb:process(reset, bus_id, present_state, burst, read_write, ready) begin if (reset = '1') then oe <= '-'; we <= '-'; addr <= "--"; next_state <= idle; else case present_state is -- beskrevet på forrige foil end case; end process state_comb; Kombinatorisk logikk state_clocked:process(clk) begin if rising_edge(clk) then present_state <= next_state; end process state_clocked; end; Synkron logikk
Asynkron reset i to-prosess tilstandsmaskin
Alternativ koding: 1-prosess FSM Funksjonelt identisk, og samme logikk lages som for forrige beskrivelse med 2-prosess
To måter å definere output: Med concurrent statements (som her) Definert for hver tilstand innenfor case-when strukturen Alle output definert for hver tilstand Definert default verdier i begynneslen av prosessen som endres hvis nødvendig innenfor de enkelte tilstandene
Areal, hastighet og resursutnyttelse Ulike beskrivelser av logikken kan gi ulik hastighet Syntesedirektiver kan benyttes for å influere på hvordan logikken optimaliseres Ønskene om lite areal og høy hastighet motarbeider ofte hverandre For å få optimal hardware implementasjon må man vite hvordan spesifikke VHDL implementasjoner syntetiseres til logikk i kretsen Å få til den optimale implementasjon ikke alltid nødvendig Fire måter å generere output i en tilstandsmaskin:
Output decoded from state bits combinatorially Slik vi har gjort det i eksemplene til nå clk current_state
Outputs decoded in parallel output registers For å få tilstandsmaskin-output raskere til outputpinnene, kan output dekodes fra tilstandsbitene før de lagres i registerene (fra next-state) with next_state select addr_d <= "01" when read2, "10" when read3, "11" when read4, "00" when others; addr_d addr clk clk For å lagre verdiene
Outputs encoded within state bits Bruker tilstandsbitene selv som output (slik en teller gjør). Må lage en unik enkoding for hver tilstand Gjør designet vanskeligere å forstå og vedlikeholde, så anbefales bare hvor det er nødvendig for å oppnå bedre ytelse enn synteseverktøyet klarer. Bruker generelt færre registere enn forrige metode, men i FPGA er det ikke sikket denne metoden er bedre enn den forrige metoden med parallelle output-registere.
Ser på memory controller eks. Ønsker disse output. Men, kan ikke brukes direkte, fordi hver tilstand (state) må dekodes unikt! Siden vi har syv tilstander, trengs minst tre tilstandsbit. Trenger ofte flere for å enkode output rett.
Komplett state enkoding Trenger to ekstra bit, siden output 00 forekommer fire ganger State Addr(1) Addr(0) St1 St0 Idle 0 0 0 0 Decision 0 0 0 1 Read1 0 0 1 0 Read2 0 1 0 0 Read3 1 0 0 0 Read4 1 1 0 0 Write 0 0 1 1
Enkoding av alle fire output State Addr(1) Addr(0) oe we St0 Idle 0 0 0 0 0 Decision 0 0 0 0 1 Read1 0 0 1 0 0 Read2 0 1 1 0 0 Read3 1 0 1 0 0 Read4 1 1 1 0 0 Write 0 0 1 1 0 Må skille mellom disse Trenger ett ekstra tilstandsbit
VHDL implementasjon av tilstandsmaskinen library ieee; use ieee.std_logic_1164.all; entity memory_controller is port ( reset, read_write, ready, burst, clk : in std_logic; bus_id : in std_logic_vector(7 downto 0); oe, we : out std_logic; addr : out std_logic_vector(1 downto 0)); end memory_controller; architecture state_machine of memory_controller is -- state signal is a std_logic_vector rather than an enumeration type signal state : std_logic_vector(4 downto 0); constant idle : std_logic_vector(4 downto 0) := "00000"; constant decision : std_logic_vector(4 downto 0) := "00001"; constant read1 : std_logic_vector(4 downto 0) := "00100"; constant read2 : std_logic_vector(4 downto 0) := "01100"; constant read3 : std_logic_vector(4 downto 0) := "10100"; constant read4 : std_logic_vector(4 downto 0) := "11100"; constant write : std_logic_vector(4 downto 0) := "00010"; begin Fra tabellen forrige side Må definere konstantene for hver tilstand eksplisitt
state_tr:process(reset, clk) begin if reset = '1' then state <= idle; elsif rising_edge(clk) then case state is -- outputs not defined here when idle => if (bus_id = "11110011") then state <= decision; -- no else; implicit memory when decision=> if (read_write = '1') then state <= read1; else --read_write='0' state <= write; when read1 => if (ready = '0') then state <= read1; elsif (burst = '0') then state <= idle; else state <= read2; when read2 => if (ready = '1') then state <= read3; -- no else; implicit memory
end case; end process state_tr; when read2 => if (ready = '1') then state <= read3; -- no else; implicit memory when read3 => if (ready = '1') then state <= read4; -- no else; implicit memory when read4 => if (ready = '1') then state <= idle; -- no else; implicit memory when write => if (ready = '1') then state <= idle; -- no else; implicit memory when others => state <= "-----"; -- don't care if undefined state -- outputs associated with register values we <= state(1); oe <= state(2); addr <= state(4 downto 3); end state_machine; Output direkte fra tilstandene, uten likninger Fordi 2^5 mulige binære verdier ( og 9^5 mulige verdier for std_logic ved simulering)