logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak zaimplementować licznik taktów w maszynie stanów VHDL dla napisu PKO?

No Comprende 27 Cze 2006 19:28 3207 7
REKLAMA
  • #1 2769118
    No Comprende
    Poziom 12  
    Posty: 93
    Pomógł: 4
    Ocena: 2
    Witam, chcialem zrobic prosta maszyne stanow. Dzialanie : z kazdym taktem zegara zaswieca sie kolejna litera neonu "PKO" (1 na odpowiednim bicie wyjscia), przy literze O, sprawdzic stan wejscia R i dla stanu wysokiego zaswiecic caly napis przez 3 takty zegara. Dla 0 przez 1 takt.

    Problem mam z licznikiem taktow w stanie wyswietlania calego napisu. Oto kod:

    
    library IEEE;
    use IEEE.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    use IEEE.STD_LOGIC_ARITH.All;  
    
    entity System_PKO is
    	port (
    			R   : in std_logic;
    			clock : in std_logic;
    			reset : in std_logic;
    			wy  : out std_logic_vector( 2 downto 0)
    		);
    end System_PKO;
    
    architecture sys_arch of System_PKO is
    
    -- definicje typow
    type fsm_state_type is (P, K, O, PKO_3, PKO_1);
    
    -- definicje sygnalow
    signal fsm_state : fsm_state_type;
    signal nxt_state : fsm_state_type;
    signal licznik   : integer := 0;
    signal licz_en   : std_logic;
    signal licz_rst  : std_logic;
    
    begin
    	
    
    fsm_synch_proc:
    process (clock, reset)
    begin
    	if reset = '1' then fsm_state <= P;
    	elsif rising_edge(clock) then
    		fsm_state <= nxt_state;
    	end if;						  
    end process;
    
    fsm_komb_proc:
    process (fsm_state,R)
    
    begin  
    	nxt_state <= P;
    		
     	case fsm_state is
    		 when P => nxt_state <= K;
    		 			wy <= "100";
    		 when K => nxt_state <= O;
    		 			wy <= "010";
    		 when O => if R = '1' then nxt_state <= PKO_3;
    		 		   elsif R = '0' then nxt_state <= PKO_1;
    			 	   end if;
    				   wy <= "001";
    	****when PKO_3 => if licznik = 2 then 
    						nxt_state <= P;
    						licznik <= 0;
    					  else	nxt_state <= PKO_3;
    							licznik <= licznik + 1;
    					  end if;
    					 wy <= "111";	****			 
    		when PKO_1 => nxt_state <= P;
    						wy <= "111";
    		when others => wy <= "000";
    	end case;	
    end process;
    
    
    end sys_arch;
    


    Problematyczny fragment zaznaczylem gwiazdkami. Gdy napisalem to bez
    przeladowywania stanow, tzn byly tylko polecenia zerowania/inkrementowania licznika to dzialalo ok. Jak dodalem zmiane stanu to w stanie PKO_3 licznik sie zacina i zostaje na 1. Jest ciagly stan PKO_3.
    Jaka moze byc przyczyna takiego zachowania?
  • REKLAMA
  • #2 2769631
    yego666
    Poziom 33  
    Posty: 2175
    Pomógł: 239
    Ocena: 564
    W twoim programie tworzony jest latch dla licznika i dlatego nie zmienia wartosci :(.

    Wydaje mi sie , ze to ponizej dziala poprawnie. Sprawdz i ew popraw sobie stany wyjsc bo nie bardzo na to zwracalem uwage.

    -- Module Name:    nocompfsm - nocompfsm_arch 
    ----------------------------------------------------------------------------------
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    
    entity nocompfsm is
       port ( 
             R   : in std_logic; 
             clock : in std_logic; 
             reset : in std_logic; 
             wy  : out std_logic_vector( 2 downto 0)); 
    end nocompfsm;
    
    architecture nocompfsm_arch of nocompfsm is
    -- definicje typow 
    type fsm_state_type is (P, K, O, PKO_30,PKO_31,PKO_32, PKO_1); 
    -- definicje sygnalow 
    signal fsm_state : fsm_state_type; 
    signal nxt_state : fsm_state_type; 
    signal licz_en   : std_logic; 
    signal licz_rst  : std_logic; 
    
    begin
    fsm_synch_proc: 
    process (clock, reset) 
    begin 
       if reset = '1' then 
         fsm_state <= P;
       elsif rising_edge(clock) then 
          fsm_state <= nxt_state;
       end if;                    
    end process; 
    
    fsm_komb_proc: 
    process (fsm_state,R) 
    
    begin  
        nxt_state <= P;    
        case fsm_state is 
           when P => nxt_state <= K; 
                    wy <= "100"; 
           when K => nxt_state <= O; 
                    wy <= "010"; 
           when O => if R = '1' then 
                       nxt_state <= PKO_30; 
                     else
                       nxt_state <= PKO_1; 
                     end if; 
                   wy <= "001"; 
    ---------------- **** ------------------------
           when PKO_30 => nxt_state <= PKO_31; 
                    wy <= "111";
           when PKO_31 => nxt_state <= PKO_32; 
                    wy <= "111";
           when PKO_32 => nxt_state <= P; 
                    wy <= "111";
    ----------------- **** ------------------------                
          when PKO_1 => nxt_state <= P; 
                      wy <= "111"; 
          when others => wy <= "000"; 
       end case;    
    end process; 
    end nocompfsm_arch;
  • REKLAMA
  • #3 2769665
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #4 2771315
    No Comprende
    Poziom 12  
    Posty: 93
    Pomógł: 4
    Ocena: 2
    yego666:
    Faktycznie jesli jest tak mala ilosc taktow do zliczenia to oplaca sie zrobic stany posrednie, o tym nie pomyslalem.

    kierowniku kuli ziemskiej:
    Zasymulowalem twoj kod w active-hdl i licznik dzialal poprawnie, natomiast automat zatrzymywal sie w stanie PKO_3, ale to chyba z tego powodu ktory opisales, takze juz wiem jak to rozwiazac.

    Ogolnie to myslalem ze przypisanie wartosci do sygnalu (nawet takiej samej jak aktualna), powoduje wystapienie zdarzenia i wtedy odpalany jest proces, dzieki za uswiadomienie ;p
  • #5 2771585
    Konto nie istnieje
    Poziom 1  
  • #6 2851681
    apacz
    Poziom 12  
    Posty: 39
    W liście czułości zawsze piszemy wszystkie sygnały "odczytywane" w procesie. Dla programów do implementacji niekompletna lista czułości nie jest problemem, pojawi się ewentualnie jakiś "warning", że coś nam brakuje, ale sam proces zostanie poprawnie zsyntezowany. Co innego dla programów do symulacji. Tutaj przy niekompletnej liście sygnałów w czasie symulacji mogą dziać się "cuda" ;)

    Pozdrawiam,
    Apacz
  • REKLAMA
  • #7 2919585
    griva
    Poziom 17  
    Posty: 203
    Pomógł: 12
    Ocena: 1
    apacz napisał:
    W liście czułości zawsze piszemy wszystkie sygnały "odczytywane" w procesie.


    jesli w procesie masz miec logike kombinacyjna lub latche to tak, ale dla logiki synchronicznej nie masz racji, masz miec w liscie czulosci zegar i ew reset i nic wiecej. To ze syntezer cos tam sie domaga nalezy olac.

    jesli chodzi o maszyne stanu, to moja sugestia jest wrzucic wszystko do jednego procesu i nie bawic sie w 2 procesy czy nawet 3.

    p_fsm : process ( clk, reset)
    begin
    if rising_edge(clk) then
    if reset = '1' then
    ... cos tam
    else
    case present_state is
    when asd =>
    when adf =>
    when others => present_state <= asd;
    end if;
    end if
    end process;

    taki proces zawsze zsyntezuje sie bez latchy.
  • #8 2954481
    tony_tg
    Poziom 16  
    Posty: 140
    Pomógł: 13
    Ocena: 3
    Czesc,

    Reset na liscie czulosci powinien byc ale tylko jak masz asynchroniczny reset. Jesli jest synchroniczny to nie powinien tam byc bo proces bedzie schedulowany na zmiane na oba sygnaly wiec bedzie sie wzbudzal w symulatorze za kazdym razem jak cos sie bedzie dzialo z resetem. Jak masz synchroniczny reset to zegar jest wystarczajacy. Zrobi sie co ma sie zrobic i proces zostanie zaschedulowany na nastepna zmiane zegara i dopiero wtedy odpalony. Inaczej symulator bez sensu bedzie odpalal ten proces non stop tylko po to zeby zobaczyc pierwszy "if" i stwierdzic ze zegar sie nie zmienil.

    Lista czulosci jest tez wazna dla symulatora bo to jedyna rzecz ktora mowi mu kiedy proces ma sie odpalic. Inaczej symulator czeka na jakakolwiek zmiane czegokolwiek na liscie czulosci. Jak sie zapomni o jakims sygnale i on sie zmieni to process sie nie odpali bo czeka na inne sygnaly. Jak cos jest poza procesem jak w przypadku "with - select" to domyslnie wszystkie sygnaly sa na liscie czulosci i jak ktorykolwiek sie zmieni to lewa strona zostanie zaktualizowana.

    Griva ma racje, dla tak prostej maszyny wszystko moze byc w jednym synchronicznym procesie. Zero latchy i wszystko mozesz zresetowac w jednym miejscu. A jak juz sie chce miec dwa procesy to nalezy sie upewnic, ze w tym kombinacyjnym ma sie wszystkie sygnaly ktore sie czyta na liscie czulosci i ja jeszcze tuz przed otwarciem "case" przypisuje wszystkim wyjsciom z tego procesu ich wartosci domyslne. Nie dlatego, ze to cos znaczy dla syntezatora ale dla mnie bo mam w jednym miejscu informacje co sygnal bedzie mial jak go nie przypisze w case'ie i nie musze szukac tego w kodzie.

    Pozdrawiam,
    Rafal

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy implementacji licznika taktów w maszynie stanów VHDL, która steruje wyświetlaniem kolejnych liter napisu "PKO" na wyjściu. Problemem było prawidłowe zliczanie taktów w stanie, gdy cały napis ma być wyświetlany przez określoną liczbę cykli zegara, zależną od stanu wejścia R. Wskazano, że błędem było tworzenie latcha dla licznika, co powodowało nieprawidłowe działanie. Zaproponowano rozwiązanie z rozbudowaną maszyną stanów, zawierającą stany pośrednie dla zliczania taktów. Podkreślono znaczenie poprawnego zarządzania listą czułości procesów w VHDL, zwłaszcza dla symulacji, gdzie brak sygnałów na liście może powodować błędy. Omówiono różnice w obsłudze listy czułości między syntezą a symulacją oraz zalecenia dotyczące umieszczania logiki synchronicznej w jednym procesie z zegarem i ewentualnym resetem. Wskazano, że asynchroniczny reset wymaga umieszczenia go na liście czułości, natomiast synchroniczny reset nie. Dyskusja zawierała przykładowe fragmenty kodu VHDL ilustrujące poprawne podejście do implementacji licznika i maszyny stanów.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA