W większym projekcie nad którym właśnie pracuje natknąłem się na pewien problem - mianowicie z maszyny stanów chcę odwoływać się do procedur i czekać na ich wykonanie. Chciałem się upewnić, że takie podejście będzie syntezowalne więc wykonałem niewielki programik - prosty licznik który odlicza sekundy od 0 do 59 i tak w kółko. Liczba dziesiątek obsługiwana jest przez maszynę stanu która w każdym stanie (0 - 5) odwołuje się do procedury, która z kolei zlicza od 0 do 9 i podaje wynik na wyjście po czym następuje zmiana stanu. Zegar systemowy (50 MHz) jest dzielony aby otrzymać impuls co sekundę.Myślę, że poniższy kod wszystko wyjaśni:
Na początku kod nie działał poprawnie, nie mogłem znaleźć błędu. Okazało się że zamiana miejscami linii 1 i linii 2 (zaznaczone komentarzem w opisie procedury) wszystko naprawiła. Jestem jednak nieco zdziwiony - z tego co wiem nie powinno być żadnej zmiany jako że obie linie to przypisanie wartości do sygnału, które powinno nastąpić równocześnie na następnym zboczu zegara. Jako że jednak teoria często niewiele ma wspólnego z praktyką chciałem poprosić kogoś o wyjaśnienie zjawiska i odpowiedź na pytanie czy jest to poprawnie napisany kod, czy też jest to łut szczęścia że akurat ten a nie inny kompilator (pracuje w Xilinxie) tak to zinterpretował i kod nie będzie działał tak samo na innej platformie (np Altery).
entity Main is
port (reset,clk : in STD_LOGIC;
out1: inout STD_LOGIC_VECTOR(3 downto 0);
out10: out STD_LOGIC_VECTOR(3 downto 0));
type state_type is (s0,s1,s2,s3,s4,s5);
end Main;
architecture Behavioral of Main is
constant divide : integer := 49999999;
signal counter : integer range 49999999 downto 0;
signal clk_div : STD_LOGIC;
signal state_pres, state_nxt : state_type;
signal count9: STD_LOGIC_VECTOR (3 downto 0);
procedure COUNT (signal out1: out STD_LOGIC_VECTOR(3 downto 0);
signal count9: inout STD_LOGIC_VECTOR (3 downto 0)) is
begin
if reset = '1' then
count9 <= (others => '0');
elsif rising_edge(clk_div) then
if count9 = "1001" then
out1 <= count9;
count9 <=(others => '0');
else
out1 <= count9; --linia 1
count9 <= count9 + 1; --linia 2
end if;
end if;
end COUNT;
begin
CLK_DIVIDE:
process (reset, clk)
begin
if reset = '1' then
counter <= 0;
elsif rising_edge(clk) then
if counter = divide then
clk_div <= '1';
counter <= 0;
else
clk_div <= '0';
counter <= counter + 1;
end if;
end if;
end process CLK_DIVIDE;
STATE_CHANGE:
process (reset, clk_div)
begin
if reset = '1' then
state_pres <= s0;
elsif rising_edge(clk_div) then
state_pres <= state_nxt;
end if;
end process STATE_CHANGE;
NXT_STATE_LOGIC:
process (state_pres,clk_div, reset)
begin
case state_pres is
when s0 => out10 <= "0000";
COUNT(out1,count9);
if out1 /= "1001" then
state_nxt <= s0;
else
state_nxt <= s1;
end if;
when s1 => out10 <= "0001";
COUNT(out1,count9);
if out1 /= "1001" then
state_nxt <= s1;
else
state_nxt <= s2;
end if;
when s2 => out10 <= "0010";
COUNT(out1,count9);
if out1 /= "1001" then
state_nxt <= s2;
else
state_nxt <= s3;
end if;
when s3 => out10 <= "0011";
COUNT(out1,count9);
if out1 /= "1001" then
state_nxt <= s3;
else
state_nxt <= s4;
end if;
when s4 => out10 <= "0100";
COUNT(out1,count9);
if out1 /= "1001" then
state_nxt <= s4;
else
state_nxt <= s5;
end if;
when s5 => out10 <= "0101";
COUNT(out1,count9);
if out1 /= "1001" then
state_nxt <= s5;
else
state_nxt <= s0;
end if;
end case;
end process NXT_STATE_LOGIC;
end Behavioral;
Na początku kod nie działał poprawnie, nie mogłem znaleźć błędu. Okazało się że zamiana miejscami linii 1 i linii 2 (zaznaczone komentarzem w opisie procedury) wszystko naprawiła. Jestem jednak nieco zdziwiony - z tego co wiem nie powinno być żadnej zmiany jako że obie linie to przypisanie wartości do sygnału, które powinno nastąpić równocześnie na następnym zboczu zegara. Jako że jednak teoria często niewiele ma wspólnego z praktyką chciałem poprosić kogoś o wyjaśnienie zjawiska i odpowiedź na pytanie czy jest to poprawnie napisany kod, czy też jest to łut szczęścia że akurat ten a nie inny kompilator (pracuje w Xilinxie) tak to zinterpretował i kod nie będzie działał tak samo na innej platformie (np Altery).