Elektroda.pl
Elektroda.pl
X
Metal Work Pneumatic
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Dzielnik czestot. + licznik w XC3s500E - problem

Wojtasss84 05 Lip 2007 20:12 1497 4
  • #1 05 Lip 2007 20:12
    Wojtasss84
    Poziom 10  

    Witam! Stworzyłem w VHDL'u prosty licznik i dzielnik częstotliwości. Po zaimplementowaniu w układzie, układ szaleje, tzn. diodki zapalają się w losowej kolejności, niektóre świecą jaśniej bądź ciemniej... Używam płytki Spartan 3E starter kit.

    Licznik:

    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity UPCTR is
        Port ( CLOCK : in  STD_LOGIC;
               enable : in  STD_LOGIC;
               reset : in  STD_LOGIC;
               PV : in  STD_LOGIC_VECTOR (15 downto 0);
               --wyjscie
               CV: out STD_LOGIC_VECTOR (15 downto 0);
               Q : out  STD_LOGIC);
    end UPCTR;

    architecture Behavioral of UPCTR is
    signal sCV : STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
    signal flaga: STD_LOGIC;

    begin process(reset,enable,clock)
    begin
    if reset='1' then
          sCV <= "0000000000000000";
    end if;

    if CLOCK='1' then
       if enable='1' then
             sCV<=sCV + 1;
       end if;
    end if;
    end process;
    CV<=sCV;
    end Behavioral;


    Dzielnik:
    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.all;

    entity T2 is
        port(
           CLOCK : in STD_LOGIC;
           T_10MS : out STD_LOGIC;
           T_100MS : out STD_LOGIC;
           T_MIN : out STD_LOGIC;
           T_SEC : out STD_LOGIC;
           enable : in STD_LOGIC
            );
    end T2;

    architecture T2 of T2 is                      
    constant minuta: integer := 59;
    constant step:integer := 0;   -- step:= (wartosc - 1)
    constant dzielnik:integer := 10000000;--dzielnik zegara taktujacego. Nalezy ustawic taka wartosc, aby
    signal CNT: integer :=0;
    signal s10MS: integer:=0;
    signal s100MS: integer:=0;
    signal sSEC: integer:=0;
    signal sMIN: integer:=0;
    signal f10MS: STD_LOGIC:='0';
    signal f100MS: STD_LOGIC:='0';
    signal fSEC: STD_LOGIC:='0';
    signal fMIN: STD_LOGIC:='0';




    begin
       process (CLOCK,enable)
       begin
          if enable='1' then                  
             if CLOCK'event and CLOCK='1' then   
                CNT<= CNT + 1;               
                if CNT = dzielnik then   
                   f10MS   <= not f10MS;
                   T_10MS   <= f10MS;
                   CNT      <=0;
                   s100MS<=s100MS + 1;
                end if;
    --------------------------------------------------------            
                if s100MS = 5 then
                   f100MS<= not f100MS;
                   T_100MS<=f100MS;
                   sSEC<=sSEC + 1;
                   s100MS<=0;
                end if;         
    ---------------------------------------------------------
                if sSEC = 10 then
                   fSEC<= not fSEC;
                   T_SEC<=fSEC;
                   sSEC<=0;
                   sMIN<=sMIN + 1;
                end if;         
    ----------------------------------------------------------
                if sMIN = 60 then
                   fMIN<= not fMIN;
                   T_MIN<=fMIN;
                   sMIN<=0;
                end if;         
    ----------------------------------------------------------
             end if;
          else T_10MS <='0';                  --gdy uklad nie jest aktywny
              T_100MS<='0';
              T_MIN  <='0';
              T_SEC   <='0';
          end if;
       end process   ;
       process (f10MS)
       begin            
       end process;
    end T2;                        

    Cały moduł:
    Code:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity upctr_t is
        Port ( CLOCK : in  STD_LOGIC;
               ENABLE : in STD_LOGIC;
               WART : out  STD_LOGIC_VECTOR (15 downto 0));
    end upctr_t;

    architecture Behavioral of upctr_t is
    signal en: STD_LOGIC:='1';
    signal sCV: STD_LOGIC_VECTOR (7 downto 0);

    component T2
      port (
           CLOCK : in STD_LOGIC;
           enable : in STD_LOGIC;
           T_100MS : out STD_LOGIC;
           T_10MS : out STD_LOGIC;
           T_MIN : out STD_LOGIC;
           T_SEC : out STD_LOGIC
      );
    end component;
    component UPCTR
      port (
           CLOCK : in STD_LOGIC;
           PV : in STD_LOGIC_VECTOR(15 downto 0);
           enable : in STD_LOGIC;
           reset : in STD_LOGIC;
           CV : out STD_LOGIC_VECTOR(15 downto 0);
           Q : out STD_LOGIC
      );
    end component;


    begin
    U1 : T2
      port map(
           CLOCK => CLOCK,
           enable => ENABLE,
          T_100MS => en
      );

    U2 : UPCTR
      port map(
           CLOCK => CLOCK,
           CV => WART,
           PV =>"0000000000000001",
           enable => en,
           reset =>'0'
          
      );


    end Behavioral;

    0 4
  • Metal Work Pneumatic
  • #2 06 Lip 2007 07:13
    Mirko51
    Poziom 15  

    Wojtasss84 napisał:
    Witam! Stworzyłem w VHDL'u prosty licznik i dzielnik częstotliwości.

    Licznik:
    Code:

    [...]

    begin process(reset,enable,clock)
    begin
    if reset='1' then
          sCV <= "0000000000000000";
    end if;

    if CLOCK='1' then
       if enable='1' then
             sCV<=sCV + 1;
       end if;
    end if;
    end process;



    dziwny jest ten twój licznik! to nie ma prawa działać poprawnie!!! a gdzie masz warunek czułości na zbocze zegarowe, bo jak widzę ty masz licznik asynchroniczny, który pędzi z max. szybkością, jaką może dać logika.
    reszty kodu nie sprawdzam.

    0
  • Metal Work Pneumatic
  • #3 06 Lip 2007 07:20
    __Grzegorz__
    Poziom 27  

    czyli powinno być:

    Code:

    [...]
    process(reset,enable,clock)
    begin
    if reset='1' then
          sCV <= "0000000000000000";
    elsif rising_edge(CLOCK) then
       if enable='1' then
             sCV<=sCV + 1;
       end if;
    end if;
    end process;


    jeżeli licznik ma zliczać zbocza narastające zegara...

    0
  • #4 06 Lip 2007 08:01
    Mirko51
    Poziom 15  

    Wojtasss84 napisał:

    Licznik:
    Code:

    begin process(reset,enable,clock)
    begin
    if reset='1' then
          sCV <= "0000000000000000";
    end if;
    if CLOCK='1' then
       if enable='1' then
             sCV<=sCV + 1;
       end if;
    end if;
    end process;



    reset powinien byc w tym samym "if" co reszta licznika. Kod będzie bardziej przejrzysty. Raczej stosuj reset synchroniczny, oczywiście zależy czy twój FPGA posiada asynchroniczne zerowanie przerzutników DFF, ale ja unikam większości asynchronizmów w układzie. Z tym często pojawiają się jakieś problemy, jeśli sygnał nie jest synchronizowany.

    W ogóle jak wprowadzasz jakieś zewnętrzne sygnały sterujące do układu, staraj się je synchronizować - kaskada 2 x DFF z zegarem systemowym. Jak np. piszesz komponent UART RX lub SPI Slave a sygnały wchodzą z zewnątrz asynchronicznie, a w FPGA modelujesz logikę synchr. to wszystkie zewnętrzne wejścia (o ile to konieczne) muszą być synchronizowane. Nie mówi się o tym na zajęciach i wykładach, ale to trzeba wiedzieć, jeśli chce się robić działające rzeczywiste projekty, a nie tylko kończyć na symulacji.

    ja bym to zrobił tak:
    lista czulości: tylko clk, bo wszystko chodzi synchronicznie w takt
    Code:

    process(clock)
    begin
    if rising_edge(CLOCK) then
       if reset='1' then
          sCV <= (others => '0');
       elsif enable='1' then
          sCV<=sCV + 1;
       end if;
    end if;
    end process;


    jak masz inicjować wektory, to nie pisz sCV <= "0000000000000000";
    to się ciężko wklepuje, można się pomylić w ilości. Stosuj słowo OTHERS

    Wojtasss84 napisał:

    Dzielnik:
    Code:

    begin
       process (CLOCK,enable)
       begin
          if enable='1' then                  
             if CLOCK'event and CLOCK='1' then   
                CNT<= CNT + 1;               
                if CNT = dzielnik then   
                   f10MS   <= not f10MS;
                   T_10MS   <= f10MS;
                   CNT      <=0;
                   s100MS<=s100MS + 1;
                end if;
    ----------------------------------------------------------
             end if;
          else T_10MS <='0';                  --gdy uklad nie jest aktywny
              T_100MS<='0';
              T_MIN  <='0';
              T_SEC   <='0';
          end if;
       end process   ;


    to enable też bym wrzucił pod zegar (jeśli jest on odpowiednio szybki, pewnie tak jest). Powód: sygnały t_10ms, t_min i podobne im zerujesz asynchronicznie a sterujesz nimi synchronicznie.
    Sterowanie wyjściami T_10ms, T_100ms itd odbywa się w procesie, rejestrowo z warunkiem logicznym. A nie wystarczyłoby poza procesem przypisać T_10ms <= f10ms, itd.? Skoro f10ms jest sygnałem rejestrowym, synchronicznym, to można go bezpośrednio wystawić na wyjścia. Oczywiście mogę się mylić, może jest jakieś uzasadnienie dla takiego kodowania.

    0
  • #5 06 Lip 2007 08:56
    Wojtasss84
    Poziom 10  

    Zmieniłem kod licznika na taki:

    Code:

    architecture Behavioral of UPCTR is
    signal sCV : STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
    signal flaga: STD_LOGIC;
    begin
    process(reset,clock)
    begin
    if reset='1' then
          sCV <= "0000000000000000";
    elsif rising_edge(CLOCK) then
             sCV<=sCV + 1;
     
    end if;
    end process;
    CV<=sCV;
    end Behavioral;

    i teraz wszystko działa :) Dziękuję wszystkim za pomoc! Teraz widzę, że symulacja a działanie w rzeczywistym układzie to dwie różne bajki...

    0
  Szukaj w 5mln produktów