Cursus VHDL Aansturing van een stappenmotor Peter Slaets KHLim
VHDL:stappenmotor Peter Slaets KHLim Basisopgave Programmeer de aandrijving van een stappenmotor die in twee richtingen kan draaien –4 wikkelingen (A, B, C, D) moeten aangestuurd worden (actief hoog) Drie drukknoppen zijn voorzien als input: –voorwaarts (draaivolgorde: A, B, C, D, A,….) –achterwaarts (draaivolgorde: D, C, B, A, D, ….) –stop (prioritair ten opzichte van de andere drukknoppen) De sequentie van wikkelingen wordt aangedreven met de snelheid van de klok library ieee; use ieee.std_logic_1164.all; entity stappenmotor is port (voorwaarts, achterwaarts, stop: in std_logic; klok: in std_logic; A,B,C,D: out std_logic); end stappenmotor; library ieee; use ieee.std_logic_1164.all; entity stappenmotor is port (voorwaarts, achterwaarts, stop: in std_logic; klok: in std_logic; A,B,C,D: out std_logic); end stappenmotor;
VHDL:stappenmotor Peter Slaets KHLim Eerste stap: implementatie FSM Er zijn drie toestanden extern waarneembare aanwezig: –T_stop (ook de opstart toestand) –T_voorwaarts –T_achterwaarts T_StopT_VoorwaartsT_Achterwaarts opstart
VHDL:stappenmotor Peter Slaets KHLim Code voor state variabelen architecture motor_arch of stappenmotor is type Extern_T is (T_stop,T_voorwaarts,T_achterwaarts); signal T_oud,T_nieuw : Extern_T; begin -- nu verder in te vullen end motor_arch; architecture motor_arch of stappenmotor is type Extern_T is (T_stop,T_voorwaarts,T_achterwaarts); signal T_oud,T_nieuw : Extern_T; begin -- nu verder in te vullen end motor_arch; De mogelijke toestanden definiëren we steeds als een nieuw type voor de toestandsvariabelen. Het synthese tool kan dan de meest aangewezen state encodering kiezen.
VHDL:stappenmotor Peter Slaets KHLim Transitie diagram Onder welke voorwaarde van stop, voorwaarts en achterwaarts gaan we over? T_StopT_VoorwaartsT_Achterwaarts opstart stop, voorwaarts, achterwaarts 0X0 1XX ,1XX 011 1XX 00X
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor volgende toestand Enkel stop, voorwaarts, achterwaarts (kader op het transitie diagram) bepalen de evolutie, dus deze komen samen met de huidige toestand in de sensitivity list. comb_T : process(T_oud,stop,voorwaarts,achterwaarts) begin if (stop = '1')or ((achterwaarts='1') and (voorwaarts='1')) then T_nieuw <= T_stop; elsif voorwaarts='1' then T_nieuw <= T_voorwaarts; elsif achterwaarts='1' then T_nieuw <= T_achterwaarts; else T_nieuw <= T_oud; end if; end process comb_T; comb_T : process(T_oud,stop,voorwaarts,achterwaarts) begin if (stop = '1')or ((achterwaarts='1') and (voorwaarts='1')) then T_nieuw <= T_stop; elsif voorwaarts='1' then T_nieuw <= T_voorwaarts; elsif achterwaarts='1' then T_nieuw <= T_achterwaarts; else T_nieuw <= T_oud; end if; end process comb_T; 1xx,
VHDL:stappenmotor Peter Slaets KHLim geklokt process voor volgende toestand Seq_T: Process (klok) begin if (klok'event and (klok='1')) then T_oud <= T_nieuw; end if; end process Seq_T; Seq_T: Process (klok) begin if (klok'event and (klok='1')) then T_oud <= T_nieuw; end if; end process Seq_T; Bij een geklokt process staat enkel de klok in de sensitivity list (er zijn geen asynchrone resets)
VHDL:stappenmotor Peter Slaets KHLim Alternatieve implementatie Tussen voorwaarts en achterwaarts stoppen we eventjes T_StopT_VoorwaartsT_Achterwaarts opstart stop, voorwaarts, achterwaarts 0X0 1XX, 0X1 1XX, 01X X 000,1XX 011
VHDL:stappenmotor Peter Slaets KHLim Interne FSM Welke wikkeling (A,B,C,D) momenteel aangedreven wordt, bepaalt de interne FSM T_AT_DT_CT_B
VHDL:stappenmotor Peter Slaets KHLim Toevoegen state variabelen in de architectuur architecture motor_arch of stappenmotor is type Extern_T is (T_stop,T_voorwaarts,T_achterwaarts); type Intern_T is (T_A,T_B,T_C,T_D); signal T_oud,T_nieuw : Extern_T; signal Ti_oud,Ti_nieuw : Intern_T; begin -- nu verder in te vullen end motor_arch; architecture motor_arch of stappenmotor is type Extern_T is (T_stop,T_voorwaarts,T_achterwaarts); type Intern_T is (T_A,T_B,T_C,T_D); signal T_oud,T_nieuw : Extern_T; signal Ti_oud,Ti_nieuw : Intern_T; begin -- nu verder in te vullen end motor_arch;
VHDL:stappenmotor Peter Slaets KHLim Transitie diagram T_AT_DT_CT_B T_stop, T_voorwaarts, T_achterwaarts De combinaties die niet kunnen voorkomen moeten niet weergegeven worden 100
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor volgende toestand comb_Ti : process(Ti_oud,T_oud) begin if T_oud = T_voorwaarts then case Ti_oud is when T_A=>Ti_nieuw <= T_B; when T_B=>Ti_nieuw <= T_C; when T_C=>Ti_nieuw <= T_D; when others=>Ti_nieuw <= T_A; end case; elsif T_oud = T_achterwaarts then case Ti_oud is when T_A=>Ti_nieuw <= T_D; when T_B=>Ti_nieuw <= T_A; when T_C=>Ti_nieuw <= T_B; when others=>Ti_nieuw <= T_C; end case; else Ti_nieuw <=Ti_oud; end if; end process comb_Ti; comb_Ti : process(Ti_oud,T_oud) begin if T_oud = T_voorwaarts then case Ti_oud is when T_A=>Ti_nieuw <= T_B; when T_B=>Ti_nieuw <= T_C; when T_C=>Ti_nieuw <= T_D; when others=>Ti_nieuw <= T_A; end case; elsif T_oud = T_achterwaarts then case Ti_oud is when T_A=>Ti_nieuw <= T_D; when T_B=>Ti_nieuw <= T_A; when T_C=>Ti_nieuw <= T_B; when others=>Ti_nieuw <= T_C; end case; else Ti_nieuw <=Ti_oud; end if; end process comb_Ti; bij verandering externe toestand bij verandering interne toestand (klok)
VHDL:stappenmotor Peter Slaets KHLim Geklokt process voor volgende toestand Seq_Ti: Process (klok) begin if (klok'event and (klok='1')) then Ti_oud <= Ti_nieuw; end if; end process Seq_Ti; Seq_Ti: Process (klok) begin if (klok'event and (klok='1')) then Ti_oud <= Ti_nieuw; end if; end process Seq_Ti;
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch Output process Het output process wordt enkel bepaald door de state variable (Ti_oud) comb_out: Process (Ti_oud) begin case Ti_oud is when T_A=>A<='1';B<='0';C<='0';D<='0'; when T_B=>A<='0';B<='1';C<='0';D<='0'; when T_C=>A<='0';B<='0';C<='1';D<='0'; when T_D=>A<='0';B<='0';C<='0';D<='1'; end case; end process comb_out; comb_out: Process (Ti_oud) begin case Ti_oud is when T_A=>A<='1';B<='0';C<='0';D<='0'; when T_B=>A<='0';B<='1';C<='0';D<='0'; when T_C=>A<='0';B<='0';C<='1';D<='0'; when T_D=>A<='0';B<='0';C<='0';D<='1'; end case; end process comb_out;
VHDL:stappenmotor Peter Slaets KHLim Resultaat van simulatie 4 onderste signalen zijn input, de 4 bovenste signalen zijn de output. Het nummer van de pin staat erbij Voor de eerste klok is de toestand onduidelijk.
VHDL:stappenmotor Peter Slaets KHLim Report file: gebruikte state encodering State variable 't_nieuw' is represented by a Bit_vector (0 to 1). State encoding (sequential) for 't_nieuw' is: t_stop :=b"00"; t_voorwaarts :=b"01"; t_achterwaarts :=b"10"; State variable 't_oud' is represented by a Bit_vector (0 to 1). State encoding (sequential) for 't_oud' is: t_stop :=b"00"; t_voorwaarts :=b"01"; t_achterwaarts :=b"10"; State variable 'ti_nieuw' is represented by a Bit_vector (0 to 1). State encoding (sequential) for 'ti_nieuw' is: t_a :=b"00"; t_b :=b"01"; t_c :=b"10"; t_d :=b"11"; State variable 'ti_oud' is represented by a Bit_vector (0 to 1). State encoding (sequential) for 'ti_oud' is: t_a :=b"00"; t_b :=b"01"; t_c :=b"10"; t_d :=b"11";
VHDL:stappenmotor Peter Slaets KHLim Report file: design equations voor de output DESIGN EQUATIONS a = /ti_oudSBV_0.Q * /ti_oudSBV_1.Q b = /ti_oudSBV_0.Q * ti_oudSBV_1.Q c = ti_oudSBV_0.Q * /ti_oudSBV_1.Q d = ti_oudSBV_0.Q * ti_oudSBV_1.Q DESIGN EQUATIONS a = /ti_oudSBV_0.Q * /ti_oudSBV_1.Q b = /ti_oudSBV_0.Q * ti_oudSBV_1.Q c = ti_oudSBV_0.Q * /ti_oudSBV_1.Q d = ti_oudSBV_0.Q * ti_oudSBV_1.Q t_a :=b"00"; t_b :=b"01"; t_c :=b"10"; t_d :=b"11";
VHDL:stappenmotor Peter Slaets KHLim design equations voor de output t_oudSBV_0.D = t_nieuwSBV_0 t_oudSBV_0.C = klok t_oudSBV_1.D = t_nieuwSBV_1 t_oudSBV_1.C = klok t_oudSBV_0.D = t_nieuwSBV_0 t_oudSBV_0.C = klok t_oudSBV_1.D = t_nieuwSBV_1 t_oudSBV_1.C = klok Data ingang FF bit 0 klok ingang FF bit 0
VHDL:stappenmotor Peter Slaets KHLim Besluit synthese CPLD CY7C331-20PC Kleinste uit de reeks 20 % van de producttermen gebruikt 56 % van de macrocellen gebruikt c331 __________________________________________ achterwaarts =| 1| |28|= t_nieuwSBV_0 voorwaarts =| 2| |27|= a not used *| 3| |26|= t_nieuwSBV_1 not used *| 4| |25|= c not used *| 5| |24|= t_oudSBV_0 not used *| 6| |23|= stop not used *| 7| |22|* not used not used *| 8| |21|* not used not used *| 9| |20|= ti_oudSBV_0 not used *|10| |19|= klok not used *|11| |18|= d not used *|12| |17|= ti_nieuwSBV_0 not used *|13| |16|= b not used *|14| |15|= ti_nieuwSBV_1 __________________________________________ c331 __________________________________________ achterwaarts =| 1| |28|= t_nieuwSBV_0 voorwaarts =| 2| |27|= a not used *| 3| |26|= t_nieuwSBV_1 not used *| 4| |25|= c not used *| 5| |24|= t_oudSBV_0 not used *| 6| |23|= stop not used *| 7| |22|* not used not used *| 8| |21|* not used not used *| 9| |20|= ti_oudSBV_0 not used *|10| |19|= klok not used *|11| |18|= d not used *|12| |17|= ti_nieuwSBV_0 not used *|13| |16|= b not used *|14| |15|= ti_nieuwSBV_1 __________________________________________
VHDL:stappenmotor Peter Slaets KHLim Synthese naar de kleinste FPGA: overzicht Slechts een klein deel van de logica is gebruikt: –7.3 % van de cellen –20 % van de bonding padden –2 % van de verbindingslijnen –0.1 % van de via’s Grootste vertraging: –12.1 ns
VHDL:stappenmotor Peter Slaets KHLim Synthese naar de kleinste FPGA: eerste FSM
VHDL:stappenmotor Peter Slaets KHLim Synthese naar de kleinste FPGA: beide FSM
VHDL:stappenmotor Peter Slaets KHLim Synthese naar de kleinste FPGA: output
VHDL:stappenmotor Peter Slaets KHLim Delay histogram Vertragingstijd (ns) Aantal verbindingen
VHDL:stappenmotor Peter Slaets KHLim Vertraging per pad nummer Vertragingstijd (ns) Nummer van de verbinding
VHDL:stappenmotor Peter Slaets KHLim Extra aanpassing van de opgave (1) Een stappenmotor kan ook aan halve snelheid worden gebruikt. Hiertoe wordt de tussenpositie gebruikt. Dit wordt bekomen door beide klemmen gelijktijdig aan te sturen. De voorwaartse sequentie die dan wordt bekomen is A, AB, B, BC, C, CD, D, DA, … en een gelijkaardige sequentie voor achterwaarts Een schakelaar (geen drukknop) laat toe te selecteren tussen volle (‘1’) en halve (‘0’) snelheid. Zorg ervoor dat, als hij overgaat van volle snelheid voorwaarts naar volle snelheid achterwaarts, er langs halve snelheid voorwaarts, stop en halve snelheid achterwaarts gepasseerd wordt (maar gedurende 1 klokperiode). Equivalente overgangen passeren op een equivalente wijze langs de stop. entity stappenmotor is port (voorwaarts, achterwaarts, stop: in std_logic; klok: in std_logic; snelheid:in std_logic); A,B,C,D: out std_logic); end stappenmotor; entity stappenmotor is port (voorwaarts, achterwaarts, stop: in std_logic; klok: in std_logic; snelheid:in std_logic); A,B,C,D: out std_logic); end stappenmotor;
VHDL:stappenmotor Peter Slaets KHLim Implementatie van de stappenmotor
VHDL:stappenmotor Peter Slaets KHLim Positie van de stappenmotor Een stappenmotor kan veel stappen per omwenteling hebben –Tot 1000 stappen per omwenteling is niet ongewoon Het is vaak belangrijk de positie, of de hoek bij te houden –We veronderstellen in dit uitgewerkt voorbeeld dat we 200 posities moeten kunnen bijhouden (van 0 tot 199) –Dit is dus een FSM met 200 toestanden We gaan dit implementeren als een teller (dit is ook een FSM) –een stap vooruit is +1 –een stap achteruit is
VHDL:stappenmotor Peter Slaets KHLim Implementatie van de teller (voorbeeld 2) We moeten een bibliotheek (package) gebruiken waarin staat hoe een optelling moet geïmplementeerd worden –Een optelling in hardware kan gebeuren op veel verschillende manieren (ripple carry, carry select, …) –Wij moeten kiezen hoe –In elke bibliotheek (package) wordt een keuze gemaakt –Je kan overwegen een andere implementatie te gebruiken omwille van verschillende redenen: snelheid, hoeveelheid logica,... Vooraan in de VHDL code (voor de declaratie van de entity) komt dus: library ieee; use ieee.std_logic_1164.all; use work.std_arith.all; library ieee; use ieee.std_logic_1164.all; use work.std_arith.all;
VHDL:stappenmotor Peter Slaets KHLim Vergelijking van de teller met de interne FSM Wanneer we de teller vergelijken met de interne FSM zien we dat deze erg parallel lopen. Hoezo? Bovendien zien we dat de 2 laatste bits overeenkomen met de wikkeling die moet aangestuurd worden. We kunnen dus de interne FSM vervangen door de implementatie van de teller. Maar indien we een stappenmotor met 3 fasen genomen hadden (zie implementatievoorbeeld) konden we de beide FSM niet samennemen Maar indien we een stappenmotor met 3 fasen genomen hadden (zie implementatievoorbeeld) konden we de beide FSM niet samennemen Dan behouden we ze allebei
VHDL:stappenmotor Peter Slaets KHLim Signaal declaraties: voorbeeld 2 architecture motor_arch of stappenmotor is type Extern_T is (T_stop,T_voorwaarts,T_achterwaarts); signal T_oud,T_nieuw : Extern_T; signal teller, teller_nieuw:std_logic_vector(7 downto 0); begin... architecture motor_arch of stappenmotor is type Extern_T is (T_stop,T_voorwaarts,T_achterwaarts); signal T_oud,T_nieuw : Extern_T; signal teller, teller_nieuw:std_logic_vector(7 downto 0); begin... We declareren de teller als een vector van 8 bits
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor volgende toestand Het combinatorisch process voor de volgende toestand van de teller wordt: comb_Ti : process(T_oud,teller) begin if T_oud = T_voorwaarts then teller_nieuw<=teller+1; elsif T_oud = T_achterwaarts then teller_nieuw<=teller-1; else teller_nieuw <= teller; end if; end process comb_Ti; comb_Ti : process(T_oud,teller) begin if T_oud = T_voorwaarts then teller_nieuw<=teller+1; elsif T_oud = T_achterwaarts then teller_nieuw<=teller-1; else teller_nieuw <= teller; end if; end process comb_Ti; Dit is eenvoudiger dan de vorige implementatie
VHDL:stappenmotor Peter Slaets KHLim Geklokt process voor volgende toestand Het nieuwe geklokte process wordt: Seq_Ti: Process (klok) begin if (klok'event and (klok='1')) then teller <= teller_nieuw; end if; end process Seq_Ti; Seq_Ti: Process (klok) begin if (klok'event and (klok='1')) then teller <= teller_nieuw; end if; end process Seq_Ti;
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch Output process Het output process wordt enkel bepaald door de waarde van de teller comb_out: Process (teller) begin case teller(1 downto 0) is when "00"=>A<='1';B<='0';C<='0';D<='0'; when "01"=>A<='0';B<='1';C<='0';D<='0'; when "10"=>A<='0';B<='0';C<='1';D<='0'; when others =>A<='0';B<='0';C<='0';D<='1'; end case; end process comb_out; comb_out: Process (teller) begin case teller(1 downto 0) is when "00"=>A<='1';B<='0';C<='0';D<='0'; when "01"=>A<='0';B<='1';C<='0';D<='0'; when "10"=>A<='0';B<='0';C<='1';D<='0'; when others =>A<='0';B<='0';C<='0';D<='1'; end case; end process comb_out;
VHDL:stappenmotor Peter Slaets KHLim Bespreking van de synthese Na synthese blijkt alles normaal te werken In de report file vinden we echter: Detecting unused logic User names teller_nieuw_7 teller_nieuw_6 teller_nieuw_5 teller_nieuw_4 teller_nieuw_3 teller_nieuw_2 teller_7 teller_6 teller_5 teller_4 teller_3 teller_2 Deleted 12 User equations/components. Deleted 12 Synthesized equations/components Detecting unused logic User names teller_nieuw_7 teller_nieuw_6 teller_nieuw_5 teller_nieuw_4 teller_nieuw_3 teller_nieuw_2 teller_7 teller_6 teller_5 teller_4 teller_3 teller_2 Deleted 12 User equations/components. Deleted 12 Synthesized equations/components.
VHDL:stappenmotor Peter Slaets KHLim Bespreking van de synthese (2) Dit is logisch: –intern gebruiken we deze hogere orde bits niet –we exporteren deze bits ook niet (ze staan niet in de port van de entity) –Dus zal hij deze extra logica niet maken als hij ze toch niet gebruikt. Het nodige aantal –producttermen –macrocellen blijft dus ook exact hetzelfde dan bij de vorige synthese Waarom dan de teller bijvoegen?
VHDL:stappenmotor Peter Slaets KHLim Meerwaarde van de teller (1) De meerwaarde van het toevoegen van een teller is dat we er voor kunnen zorgen dat de motor steeds binnen zijn grenzen (0 tot 199) blijft. We moeten deze eis dan ook toevoegen aan het combinatorisch blok voor de volgende tellerwaarde. comb_Ti : process(T_oud,teller) begin if (T_oud = T_voorwaarts) and (teller/=" ") then teller_nieuw<=teller+1; elsif (T_oud = T_achterwaarts) and (teller/=” ") then teller_nieuw<=teller-1; else teller_nieuw <= teller; end if; end process comb_Ti; comb_Ti : process(T_oud,teller) begin if (T_oud = T_voorwaarts) and (teller/=" ") then teller_nieuw<=teller+1; elsif (T_oud = T_achterwaarts) and (teller/=” ") then teller_nieuw<=teller-1; else teller_nieuw <= teller; end if; end process comb_Ti;
VHDL:stappenmotor Peter Slaets KHLim Bespreking van de synthese Dit krijgen we niet meer in een CY7C331-20PC omdat dit ontwerp te complex geworden is, vooral door de vergelijking en de optelling. –Een CPLD expandeert deze volledig Een CY7C341B-15HC is bijvoorbeeld wel een goede CPLD om de synthese naar uit te voeren.
VHDL:stappenmotor Peter Slaets KHLim Invoering van de reset Om een systeem bij het opstarten of bij een probleem in de goede startsituatie te krijgen is het meestal goed een globale reset te voorzien. Elk geklokt process passen we aan als hiernaast aangegeven De reset moet ook aan de port toegevoegd worden Bij het begin van een simulatie brengen we de reset gedurende enkele ticks ‘1’ Seq_T: Process (reset,klok) begin if reset='1' then T_oud <=T_stop; elsif (klok'event and (klok='1')) then T_oud <= T_nieuw; end if; end process Seq_T; Seq_T: Process (reset,klok) begin if reset='1' then T_oud <=T_stop; elsif (klok'event and (klok='1')) then T_oud <= T_nieuw; end if; end process Seq_T; Seq_Ti: Process (reset,klok) begin if reset='1' then teller <=" "; elsif (klok'event and (klok='1')) then teller <= teller_nieuw; end if; end process Seq_Ti; Seq_Ti: Process (reset,klok) begin if reset='1' then teller <=" "; elsif (klok'event and (klok='1')) then teller <= teller_nieuw; end if; end process Seq_Ti;
VHDL:stappenmotor Peter Slaets KHLim Uitbreiding voor de liefhebbers (toon de positie) Toon de huidige positie van de stappenmotor op een 3-digit seven segment display (21 signalen), waarvan de cijfers gemultiplexed zijn Rechstreeks omrekenen van de digitale waarde van de positie (8 bits) naar een BCD (binary coded decimal) waarde vraagt veel te veel logica (13) to 0001 (1) 0011 (3) Houdt de positie ook decimaal bij, in parallel –Implementeer 3 FSM, elk als een BCD teller (decimale teller). –Implementeer een combinatorische BCD naar seven-segment decoder –Implementeer een multiplexer tussen deze BCD tellers en de decoder –Implementeer een FSM die afwisselend elk van de 3 cijfers naar de decoder stuurt.
VHDL:stappenmotor Peter Slaets KHLim Stappenmotor met externe positiesturing In de port voegen de 3 signalen toe: –de gewenste positie (8bit: in) –het “go” signaal (in) waarna de gewenste positie gestockeerd wordt en de motor naar deze positie gaat –het “ok” signaal (out) als deze positie bereikt is. Verwijder 2 signalen uit de port: –“voorwaarts” en “achterwaarts” Herbruik de stop ingang als een noodstop: –zet dan de gestockeerde gewenste positie gelijk aan de huidige positie
VHDL:stappenmotor Peter Slaets KHLim Aanpassing van de enitity en signaaldeclaratie entity stappenmotor is port (go,stop,klok,reset: in std_logic; positie: in std_logic_vector(7 downto 0); A,B,C,D,ok: out std_logic); end stappenmotor; architecture motor_arch of stappenmotor is signal T_positie,T_positie_nieuw : std_logic_vector(7 downto 0); signal teller,teller_nieuw :std_logic_vector(7 downto 0); begin entity stappenmotor is port (go,stop,klok,reset: in std_logic; positie: in std_logic_vector(7 downto 0); A,B,C,D,ok: out std_logic); end stappenmotor; architecture motor_arch of stappenmotor is signal T_positie,T_positie_nieuw : std_logic_vector(7 downto 0); signal teller,teller_nieuw :std_logic_vector(7 downto 0); begin teller T_positie teller_nieuw T_positie_nieuw A,B,C,D gewenste positie
VHDL:stappenmotor Peter Slaets KHLim Nieuwe combinatorisch process van de externe FSM Comb_T: Process (teller,T_positie,positie,stop,go) begin if stop ='1' then T_positie_nieuw <= teller; elsif go='1' then T_positie_nieuw <= positie; else T_positie_nieuw <= T_positie; end if; end process Comb_T; Comb_T: Process (teller,T_positie,positie,stop,go) begin if stop ='1' then T_positie_nieuw <= teller; elsif go='1' then T_positie_nieuw <= positie; else T_positie_nieuw <= T_positie; end if; end process Comb_T; teller T_positie T_positie_nieuw Stop go positie
VHDL:stappenmotor Peter Slaets KHLim Nieuwe geklokt process van de externe FSM T_positie T_positie_nieuw Seq_T: Process (reset,klok) begin if reset='1' then T_positie <=" "; elsif (klok'event and (klok='1')) then T_positie <= T_positie_nieuw; end if; end process Seq_T; Seq_T: Process (reset,klok) begin if reset='1' then T_positie <=" "; elsif (klok'event and (klok='1')) then T_positie <= T_positie_nieuw; end if; end process Seq_T;
VHDL:stappenmotor Peter Slaets KHLim Nieuwe combinatorisch blok van de interne FSM teller T_positie teller_nieuw comb_Ti : process(T_positie,teller) begin if (teller<T_positie) and (teller/=" ") then teller_nieuw<=teller+1; elsif (teller>T_positie) and (teller/=" ") then teller_nieuw<=teller-1; else teller_nieuw<=teller; end if; end process comb_Ti; comb_Ti : process(T_positie,teller) begin if (teller<T_positie) and (teller/=" ") then teller_nieuw<=teller+1; elsif (teller>T_positie) and (teller/=" ") then teller_nieuw<=teller-1; else teller_nieuw<=teller; end if; end process comb_Ti;
VHDL:stappenmotor Peter Slaets KHLim Extra output process Interne geklokt process en output functie blijven Bijkomende output functie voor OK teller T_positie teller_nieuw T_positie_nieuw A,B,C,D ok_P: Process (teller, T_positie) begin if teller=T_positie then ok <='1'; else ok <='0'; end if; end process ok_P; ok_P: Process (teller, T_positie) begin if teller=T_positie then ok <='1'; else ok <='0'; end if; end process ok_P; ok
VHDL:stappenmotor Peter Slaets KHLim Resultaat van de simulatie
VHDL:stappenmotor Peter Slaets KHLim Uitlezing van een lijn CCD array met 2/3 klokken Dit is een heel gelijkaardige opgave –Eerst moet er een opneem signaal komen –Vervolgens komen de klokken »De 2 klokken komen volgens de sequentie A,B,A, »3 klokken moeten volgens de sequentie A, AB,B, BC, C, … Kan echter aan veel hogere frequenties werken
VHDL:stappenmotor Peter Slaets KHLim Combinatie beide systemen: uitlezing flatbed scanner Een stappenmotor gaat langs de verticale as –snel als er geen informatie dient doorgestuurd te worden –stap voor stap als er een gescande lijn dient doorgestuurd te worden P.S. Dit was een examenopgave van het academiejaar
VHDL:stappenmotor Peter Slaets KHLim SCSI standaard voor flatbed scanners De SCSI standaard definieert ook voor scanners welk de volgorde is voor de door te geven bytes. Op basis hiervan kan een IC de scanner aansturen.
VHDL:stappenmotor Peter Slaets KHLim Gevraagd # stappen? Hoofd FSM Inlezen SCSI gegevens Motor naar startpositie Inlezen en doorsturen CCD Motor naar beginpositie Motor één stap verder neen ja Inleesteller=40 OK=1 CCDOK=1 aparte FSM1 aparte FSM2
VHDL:stappenmotor Peter Slaets KHLim Typedeclaratie voor de HoofdFSM architecture scan_arch of scanner is type hoofdFSM_T is (T_inleesSCSI,T_naarstart,T_doCCD,T_stapverder,T_naarbegin); signal T_hoofdFSM_oud,T_hoofdFSM_nieuw : hoofdFSM_T; -- nu verder in te vullen end scan_arch; architecture scan_arch of scanner is type hoofdFSM_T is (T_inleesSCSI,T_naarstart,T_doCCD,T_stapverder,T_naarbegin); signal T_hoofdFSM_oud,T_hoofdFSM_nieuw : hoofdFSM_T; -- nu verder in te vullen end scan_arch;
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor de volgende toestand comb_hoofdFSM : process(T_hoofdFSM_oud,inleesteller,OK,CCDOK, verticaalstappen, verticaalteller) begin case T_hoofdFSM_oud is when T_inleesSCSI=>if inleesteller="101000" then T_hoofdFSM_nieuw <=T_naarstart; else T_hoofdFSM_nieuw <=T_inleesSCSI; end if; when T_naarstart=> if OK='1' then T_hoofdFSM_nieuw <=T_doCCD; else T_hoofdFSM_nieuw <=T_naarstart; end if; comb_hoofdFSM : process(T_hoofdFSM_oud,inleesteller,OK,CCDOK, verticaalstappen, verticaalteller) begin case T_hoofdFSM_oud is when T_inleesSCSI=>if inleesteller="101000" then T_hoofdFSM_nieuw <=T_naarstart; else T_hoofdFSM_nieuw <=T_inleesSCSI; end if; when T_naarstart=> if OK='1' then T_hoofdFSM_nieuw <=T_doCCD; else T_hoofdFSM_nieuw <=T_naarstart; end if; teller=40 inwendige teller motor in start of begin lijn lezen gewenste pos. verticaal
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor de volgende toestand when T_doCCD=> if CCDOK='1' then if (verticaalstappen=verticaalteller) then T_hoofdFSM_nieuw <=T_naarbegin; else T_hoofdFSM_nieuw <=T_stapverder; end if; else T_hoofdFSM_nieuw <=T_doCCD; end if; when T_stapverder=>T_hoofdFSM_nieuw <=T_doCCD; when others=> if OK='1' then T_hoofdFSM_nieuw <=T_inleesSCSI; else T_hoofdFSM_nieuw <=T_naarbegin; end if; end case; end process comb_hoofdFSM; when T_doCCD=> if CCDOK='1' then if (verticaalstappen=verticaalteller) then T_hoofdFSM_nieuw <=T_naarbegin; else T_hoofdFSM_nieuw <=T_stapverder; end if; else T_hoofdFSM_nieuw <=T_doCCD; end if; when T_stapverder=>T_hoofdFSM_nieuw <=T_doCCD; when others=> if OK='1' then T_hoofdFSM_nieuw <=T_inleesSCSI; else T_hoofdFSM_nieuw <=T_naarbegin; end if; end case; end process comb_hoofdFSM; T_naarbegin
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor de output comb_hoofdFSM_out : process(T_hoofdFSM_oud,startpositie,teller) begin CCDgo<='0'; go<='0'; case T_hoofdFSM_oud is when T_inleesSCSI=>null; when T_naarstart=>positie<=startpositie;go<='1'; when T_doCCD=>CCDgo<='1'; when T_stapverder=>positie<=teller+1;go<='1'; when others=>positie '0');go<='1'; end case; end process comb_hoofdFSM_out; comb_hoofdFSM_out : process(T_hoofdFSM_oud,startpositie,teller) begin CCDgo<='0'; go<='0'; case T_hoofdFSM_oud is when T_inleesSCSI=>null; when T_naarstart=>positie<=startpositie;go<='1'; when T_doCCD=>CCDgo<='1'; when T_stapverder=>positie<=teller+1;go<='1'; when others=>positie '0');go<='1'; end case; end process comb_hoofdFSM_out; T_naarbegin
VHDL:stappenmotor Peter Slaets KHLim Inlezen (en tellen) van de SCSI-data Hiervoor gaan we de SCSI_data_ready als klok gebruiken Met deze klok verhogen we de inleesteller met 1 –vergeet niet deze teller terug op nul te zetten als we in een ander hoofdblok bezig zijn. Als we aan de juiste tellerwaarde gekomen zijn slagen we de nuttige gegeven op –startpositie (byte 12 en byte 13) –verticaalstappen (byte 20 en byte 21) –CCDstartpositie (byte 8 en byte 9) –CCDstappen (byte 17 en byte 18) We kiezen voor een A4 blad en 300 dpi –Dit geeft 2475 * 3510 punten –12 bit getallen zijn voldoende om posities voor te stellen (2^12=4096)
VHDL:stappenmotor Peter Slaets KHLim Tellen van de SCSI data bytes tellerreset<='1' when T_hoofdFSM_oud=T_naarbegin else '0'; SCSI_bytes_teller : process(scsi_data_ready,tellerreset) begin if (tellerreset='1') then inleesteller '0'); elsif (SCSI_data_ready'event and (SCSI_data_ready='1')) then inleesteller <= inleesteller+1; end if; end process SCSI_bytes_teller; tellerreset<='1' when T_hoofdFSM_oud=T_naarbegin else '0'; SCSI_bytes_teller : process(scsi_data_ready,tellerreset) begin if (tellerreset='1') then inleesteller '0'); elsif (SCSI_data_ready'event and (SCSI_data_ready='1')) then inleesteller <= inleesteller+1; end if; end process SCSI_bytes_teller; klokteller op nul zetten
VHDL:stappenmotor Peter Slaets KHLim Geklokt process voor de opslag van de ingelezen SCSI data opslag_SCSI_bytes : process(scsi_data_ready) begin if (SCSI_data_ready'event and (SCSI_data_ready='1')) then case inleesteller is when "001100" =>startpositie(11 downto 8)<=scsi_data(3 downto 0); when "001101" =>startpositie(7 downto 0)<=scsi_data(7 downto 0); when "010100" =>verticaalstappen(11 downto 8)<=scsi_data(3 downto 0); when "010101" =>verticaalstappen(7 downto 0)<=scsi_data(7 downto 0); when "001000" =>CCDstartpositie(11 downto 8)<=scsi_data(3 downto 0); when "001001" =>CCDstartpositie(7 downto 0)<=scsi_data(7 downto 0); when "010001" =>CCDstappen(11 downto 8)<=scsi_data(3 downto 0); when "010010" =>CCDstappen(7 downto 0)<=scsi_data(7 downto 0); when others =>null; end case; end if; end process opslag_SCSI_bytes; opslag_SCSI_bytes : process(scsi_data_ready) begin if (SCSI_data_ready'event and (SCSI_data_ready='1')) then case inleesteller is when "001100" =>startpositie(11 downto 8)<=scsi_data(3 downto 0); when "001101" =>startpositie(7 downto 0)<=scsi_data(7 downto 0); when "010100" =>verticaalstappen(11 downto 8)<=scsi_data(3 downto 0); when "010101" =>verticaalstappen(7 downto 0)<=scsi_data(7 downto 0); when "001000" =>CCDstartpositie(11 downto 8)<=scsi_data(3 downto 0); when "001001" =>CCDstartpositie(7 downto 0)<=scsi_data(7 downto 0); when "010001" =>CCDstappen(11 downto 8)<=scsi_data(3 downto 0); when "010010" =>CCDstappen(7 downto 0)<=scsi_data(7 downto 0); when others =>null; end case; end if; end process opslag_SCSI_bytes;
VHDL:stappenmotor Peter Slaets KHLim Uitlezen van de CCD array Hiervoor gaan we een aparte bouwblok (component) maken. Deze bouwblok kunnen we dan afzonderlijk testen Hierna gaan we deze component instantiëren in de architectuur van de scanner ARCHITECTURE scan_arch OF scanner IS -- COMPONENT CCD PORT (-- in te vullen ); END COMPONENT; BEGIN u1: CCD PORT MAP (-- in te vullen ); END scan_arch ; ARCHITECTURE scan_arch OF scanner IS -- COMPONENT CCD PORT (-- in te vullen ); END COMPONENT; BEGIN u1: CCD PORT MAP (-- in te vullen ); END scan_arch ;
VHDL:stappenmotor Peter Slaets KHLim Specificaties van de CCD aansturing Als het "CCDgo" signaal '1' wordt, wordt de gehele lijn ingeladen in de CCDs. (CCD_load wordt eventjes '1') Er zijn dan telkens 3 klokpulsen nodig om de hele lijn één pixel naar links te schuiven (het meest linkse punt wordt telkens uitgelezen) We tellen hoeveel pixels we verschuiven tot we aan de "CCDstartpositie" komen We herstarten de teller en verschuiven terug tot we "CCDstappen" aantal pixels naar buiten geschoven hebben. –Hierbij zullen we dan steeds de pixels doorgeven aan de SCSI bus. Hierna geven we een CCDOK signaal
VHDL:stappenmotor Peter Slaets KHLim Entity van de CCD aansturing library ieee; use ieee.std_logic_1164.all; use work.std_arith.all; entity CCD is port (CCDgo,CCD_klok: in std_logic; CCDstartpositie,CCDstappen: in std_logic_vector(11 downto 0); CCD_DATA:in std_logic_vector(7 downto 0); CCD_load: out std_logic; CCD_A,CCD_B,CCD_C: buffer std_logic; CCDOK,SCSI_DATA_Available: out std_logic; SCSI_DATA:inout std_logic_vector(7 downto 0)); end CCD; library ieee; use ieee.std_logic_1164.all; use work.std_arith.all; entity CCD is port (CCDgo,CCD_klok: in std_logic; CCDstartpositie,CCDstappen: in std_logic_vector(11 downto 0); CCD_DATA:in std_logic_vector(7 downto 0); CCD_load: out std_logic; CCD_A,CCD_B,CCD_C: buffer std_logic; CCDOK,SCSI_DATA_Available: out std_logic; SCSI_DATA:inout std_logic_vector(7 downto 0)); end CCD; lijn in CCD's laden
VHDL:stappenmotor Peter Slaets KHLim Externe FSM Wachten op stappenmotor schuiven naar startpositie Schuiven naar eindpositie CCDgo=1 CCDstartpositie=teller CCDstappen=teller Einddetectie1 Einddetectie2
VHDL:stappenmotor Peter Slaets KHLim Interne FSM De telrichting is hier steeds dezelfde, en elke klokpuls bewegen we verder tenzij we in toestand A zitten en schuiven='0' Toestand A is ook de reset-toestand. toestand B gebruiken we om de teller 1 te verhogen. 2 klokpulsen om lijn 1 bit door te schuiven T_AT_CT_B schuiven 0 1
VHDL:stappenmotor Peter Slaets KHLim Declaratie interne signalen/toekenning hulpsignalen architecture CCD_arch of CCD is type Extern_T is (T_wacht,T_naarstart,T_naareinde); type Intern_T is (T_A,T_B,T_C); signal T_oud,T_nieuw : Extern_T; signal Ti_oud,Ti_nieuw : Intern_T; signal teller,teller_nieuw:std_logic_vector(11 downto 0); signal schuiven, einddetectie1,einddetectie2:std_logic; begin einddetectie1<='1' when (teller==CCDstartpositie) else '0'; einddetectie2<='1' when (teller==CCDstappen) else '0'; architecture CCD_arch of CCD is type Extern_T is (T_wacht,T_naarstart,T_naareinde); type Intern_T is (T_A,T_B,T_C); signal T_oud,T_nieuw : Extern_T; signal Ti_oud,Ti_nieuw : Intern_T; signal teller,teller_nieuw:std_logic_vector(11 downto 0); signal schuiven, einddetectie1,einddetectie2:std_logic; begin einddetectie1<='1' when (teller==CCDstartpositie) else '0'; einddetectie2<='1' when (teller==CCDstappen) else '0'; Concurrent alternatief voor if then else in process
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process van de externe FSM comb_T : process(T_oud,CCDgo,einddetectie1,einddetectie2) begin case T_oud is when T_wacht=>if (CCDgo ='1') then T_nieuw <= T_naarstart; else T_nieuw <= T_wacht; end if; when T_naarstart=>if (einddetectie1 ='1') then T_nieuw <= T_naareinde; else T_nieuw <= T_naarstart; end if; when others=>if (einddetectie2 ='1') then T_nieuw <= T_wacht; else T_nieuw <= T_naareinde; end if; end case; end process comb_T; comb_T : process(T_oud,CCDgo,einddetectie1,einddetectie2) begin case T_oud is when T_wacht=>if (CCDgo ='1') then T_nieuw <= T_naarstart; else T_nieuw <= T_wacht; end if; when T_naarstart=>if (einddetectie1 ='1') then T_nieuw <= T_naareinde; else T_nieuw <= T_naarstart; end if; when others=>if (einddetectie2 ='1') then T_nieuw <= T_wacht; else T_nieuw <= T_naareinde; end if; end case; end process comb_T;
VHDL:stappenmotor Peter Slaets KHLim Output process (1,schuiven) van de externe FSM outp_T : process(T_oud,einddetectie1,einddetectie2) begin case T_oud is when T_wacht=>schuiven<='0'; when T_naarstart=>if (einddetectie1 ='1') then schuiven <= '0'; else schuiven <= '1'; end if; when others=>if (einddetectie2 ='1') then schuiven <= '0'; else schuiven <= '1'; end if; end case; end process outp_T; outp_T : process(T_oud,einddetectie1,einddetectie2) begin case T_oud is when T_wacht=>schuiven<='0'; when T_naarstart=>if (einddetectie1 ='1') then schuiven <= '0'; else schuiven <= '1'; end if; when others=>if (einddetectie2 ='1') then schuiven <= '0'; else schuiven <= '1'; end if; end case; end process outp_T;
VHDL:stappenmotor Peter Slaets KHLim Output process (2,CCD_load) van de externe FSM outp_T2 : process(T_oud,CCDgo) begin case T_oud is when T_wacht=>if (CCDgo ='1') then CCD_load <= '1'; else CCD_load <= '0'; end if; when others=>CCD_load <= '0'; end case; end process outp_T2; outp_T2 : process(T_oud,CCDgo) begin case T_oud is when T_wacht=>if (CCDgo ='1') then CCD_load <= '1'; else CCD_load <= '0'; end if; when others=>CCD_load <= '0'; end case; end process outp_T2;
VHDL:stappenmotor Peter Slaets KHLim Output process (3,CCDOK) van de externe FSM outp_T3 : process(T_oud,einddetectie2) begin case T_oud is when T_naareinde=>if (einddetectie2 ='1') then CCDOK <= '1'; else CCDOK <= '0'; end if; when others=>CCDOK <= '0'; end case; end process outp_T3; outp_T3 : process(T_oud,einddetectie2) begin case T_oud is when T_naareinde=>if (einddetectie2 ='1') then CCDOK <= '1'; else CCDOK <= '0'; end if; when others=>CCDOK <= '0'; end case; end process outp_T3;
VHDL:stappenmotor Peter Slaets KHLim Output process (4,SCSI_data) van de externe FSM outp_T4 : process(T_oud,CCD_C,CCD_data) begin case T_oud is when T_naareinde=>if ( CCD_C='1') then SCSI_data <= CCD_data; SCSI_DATA_Available<='1'; else SCSI_data 'Z'); SCSI_DATA_Available<='0'; end if; when others=>SCSI_data 'Z'); SCSI_DATA_Available<='0'; end case; end process outp_T4; outp_T4 : process(T_oud,CCD_C,CCD_data) begin case T_oud is when T_naareinde=>if ( CCD_C='1') then SCSI_data <= CCD_data; SCSI_DATA_Available<='1'; else SCSI_data 'Z'); SCSI_DATA_Available<='0'; end if; when others=>SCSI_data 'Z'); SCSI_DATA_Available<='0'; end case; end process outp_T4;
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor volgende Ti comb_Ti : process(Ti_oud,schuiven) begin case Ti_oud is when T_A=>if (schuiven ='1') then Ti_nieuw <= T_B; else Ti_nieuw <= T_A; end if; when T_B=>Ti_nieuw <= T_C; when others=>Ti_nieuw <= T_A; end case; end process comb_Ti; comb_Ti : process(Ti_oud,schuiven) begin case Ti_oud is when T_A=>if (schuiven ='1') then Ti_nieuw <= T_B; else Ti_nieuw <= T_A; end if; when T_B=>Ti_nieuw <= T_C; when others=>Ti_nieuw <= T_A; end case; end process comb_Ti;
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch process voor de volgende tellerwaarde comb_Tel : process(teller,CCD_B,schuiven) begin if schuiven = '0' then teller_nieuw '0'); elsif CCD_B = '1' then teller_nieuw<=teller+1; else teller_nieuw<=teller; end if; end process comb_Tel; comb_Tel : process(teller,CCD_B,schuiven) begin if schuiven = '0' then teller_nieuw '0'); elsif CCD_B = '1' then teller_nieuw<=teller+1; else teller_nieuw<=teller; end if; end process comb_Tel;
VHDL:stappenmotor Peter Slaets KHLim Geklokt process voor volgende toestand Seq: Process (CCD_klok) begin if (CCD_klok'event and (CCD_klok='1')) then Ti_oud <= Ti_nieuw; T_oud <= T_nieuw; teller <= teller_nieuw; end if; end process Seq; Seq: Process (CCD_klok) begin if (CCD_klok'event and (CCD_klok='1')) then Ti_oud <= Ti_nieuw; T_oud <= T_nieuw; teller <= teller_nieuw; end if; end process Seq; We plaatsen de teller, de externe en de interne toestand in eenzelfde geklokt process
VHDL:stappenmotor Peter Slaets KHLim Combinatorisch Output process Het output process wordt enkel bepaald door de state variable (Ti_oud) comb_out: Process (Ti_oud) begin case Ti_oud is when T_A=>CCD_A<='1';CCD_B<='0';CCD_C<='0'; when T_B=>CCD_A<='0';CCD_B<='1';CCD_C<='0'; when T_C=>CCD_A<='0';CCD_B<='0';CCD_C<='1'; end case; end process comb_out; comb_out: Process (Ti_oud) begin case Ti_oud is when T_A=>CCD_A<='1';CCD_B<='0';CCD_C<='0'; when T_B=>CCD_A<='0';CCD_B<='1';CCD_C<='0'; when T_C=>CCD_A<='0';CCD_B<='0';CCD_C<='1'; end case; end process comb_out;