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

[VHDL] Jak zrobić multipleksację w czasie na matrycy diod?

22 Sty 2011 23:11 1538 5
  • Poziom 2  
    Witam,
    pytanie jak w temacie... Co do sytuacji: mamy dwukolorową matrycę diodową 8x8 (http://www.tme.eu/html/PL/matryce-led-dwukolorowe/ramka_3096_PL_pelny.html) i chcemy na niej zrealizować grę "w skoczka" - matryca to szachownica, na niej w każdym momencie 8 pionków czerwonych i 8 zielonych. Grę realizujemy na płytce uruchomieniowej Xilinxa SPARTAN3, programujemy w VHDL. Do matrycy jest zrobiony układ, który rozwiązuje problem zasilania diod (układy ULN2003 na wiersze, tranzystory BD140 na kolumny, do tego odpowiednie rezystory), tak że pozostaje tylko dobrze to wysterować. I tu jest właśnie problem, że nie wiemy, jak dobrze napisać kod do wyświetlania tej gry na matrycy... Staraliśmy się pisać według algorytmu:

    .
    .
    .
    1) ustaw "0" na kolumnach
    2) wczytaj wartości wszystkich wierszy na wyjścia
    3) ustaw KOLUMNA(i) <= '1', reszta kolumn = '0', a na wyjściach ustaw "i-ty" element każdego wiersza - rób to przez ok. 4 msek
    4) i = i + 1
    5) ustaw "0" na kolumnach
    6) wczytaj wartości wszystkich wierszy na wyjścia
    7) ustaw KOLUMNA(i) <= '1', reszta kolumn = '0', a na wyjściach ustaw "i-ty" element każdego wiersza - rób to przez ok. 4 msek
    4) i = i + 1
    .
    .
    .
    .

    No i wyświetlać - wyświetla, pierwsze ustawienie dobrze, ale już po pierwszym ruchu robią się błędy, przybywa ich coraz bardziej i ogólny chaos.

    Czy to jest dobry algorytm? Jakieś sugestie odnośnie czasów, samego algorytmu, sposobu realizacji?

    Aha, kod jest dość długi, więc nie wstawiam na razie, chyba że powiecie, że koniecznie chcecie zobaczyć to cudo ;P

    Z góry dziękuję za pomoc
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Poziom 8  
    w jaki sposób realizujesz multipleksowanie: rejestr przesuwny czy jakoś inaczej ? i przypisania do sygnałów wyjściowych... jakbyś wkleił kawałek kodu multipleksera ;)
  • Poziom 2  
    Code:
    entity multiplekser is
    
       
       port(
          
          --      inputs   
          CLK : in STD_LOGIC;
          RESET : in STD_LOGIC;     -- reset gry - ustawienie pozycji początkowych
          
          WIERSZ1_IN : in STD_LOGIC_VECTOR (0 to 7); -- (pierwszy wiersz szachownicy - dioda czerwona, drugi - zielona, itd)
             .
             .
          WIERSZ16_IN : in STD_LOGIC_VECTOR (0 to 7);
          
          --      outputs      -----------------------------------------------      
          
          KOLUMNA1: out STD_LOGIC;
          .
          .
          KOLUMNA8: out STD_LOGIC;
          
          CZERW_WIERSZ1: out STD_LOGIC;
          .
          .
          CZERW_WIERSZ8: out STD_LOGIC;
          
          ZIEL_WIERSZ1: out STD_LOGIC;
          .
          .
          ZIEL_WIERSZ8: out STD_LOGIC
          );
    end multiplekser;


    architecture multiplekser of multiplekser is
       

          -- sygnały - rejestry do zapisywania stanu poszczególnych wierszy
       signal CZERW_REG0 : std_logic_vector(0 to 7);
          .
          .
       signal CZERW_REG7 : std_logic_vector(0 to 7);
       
       signal ZIEL_REG0 : std_logic_vector(0 to 7);
          .
          .
       signal ZIEL_REG7 : std_logic_vector(0 to 7);

          -- rejestr przesuwny do multipleksowania (włączona tylko jedna kolumna)   
       signal KOLUMNY_SHIFT_REG : std_logic_vector(0 to 7);
       
       
          
          -- dla zegara 50 MHz licznik modulo 200000 generuje odstępy czasowe 4 msek
       constant divide_factor: integer := 200000;
       signal presc_mux: std_logic_vector(17 downto 0);   -- ten sygnał stanowi licznik modulo(divide_factor)
       
    begin
       process (CLK, RESET) is
          variable i : integer := 0;         -- iterator dla wierszy
          variable check : integer := 0;         -- '1', jeśli był reser
       begin
          if RESET = '1' then
             presc_mux <= (others=>'0');
             check := 1;
             KOLUMNY_SHIFT_REG <= "10000000";
          elsif CLK'event and CLK = '1' then
             if check = 0 then
                KOLUMNA1 <= '0';
                .
                .
                KOLUMNA8 <= '0';
             elsif check = 1 then
                if i<8 then
                   if presc_mux < (divide_factor-1) then
                      
                      if presc_mux < 10 then
                         
                         KOLUMNA1 <= '0';
                         .
                         .
                         KOLUMNA8 <= '0';
                         
                         CZERW_REG0 <= WIERSZ1_IN;
                         .
                         .
                         CZERW_REG7 <= WIERSZ15_IN;
                         
                         ZIEL_REG0 <= WIERSZ2_IN;
                         .
                         .
                         ZIEL_REG7 <= WIERSZ16_IN;
                         
                         presc_mux <= presc_mux + 1;
                         
                      elsif presc_mux >= 10 then
                         
                         CZERW_WIERSZ1 <= CZERW_REG0(i);
                         .
                         .
                         CZERW_WIERSZ8 <= CZERW_REG7(i);
                         
                         ZIEL_WIERSZ1 <= ZIEL_REG0(i);
                         .
                         .
                         ZIEL_WIERSZ8 <= ZIEL_REG7(i);
                         
                         KOLUMNA1 <= KOLUMNY_SHIFT_REG(0);
                         .
                         .
                         KOLUMNA8 <= KOLUMNY_SHIFT_REG(7);
                         
                         presc_mux <= presc_mux + 1;
                         
                      end if;
                      
                   else
                      
                      KOLUMNY_SHIFT_REG <= KOLUMNY_SHIFT_REG(7) & KOLUMNY_SHIFT_REG(0 to 6);
                      i := i+1;
                      presc_mux <= (others => '0');
                      
                   end if;
                else
                   i := 0;
                end if;
             end if;
          end if;
       
    end multiplekser;
  • Poziom 30  
    Nawet nie chce w to wnikać, CHAOS. I dlaczego piszesz w liczbie mnogiej?
    Teraz tak:
    1. Stosuj STD_LOGIC_VECTOR skróci opis, będzie czytelniejszy, w ucf Sobie porozdzielasz, w opisie dla czytelności stosować ALIASy.
    2. Dzielić zadania na małe procesy:
    -proces na dzielnik częstotliwości.
    -zegar z divider'a na proces odpowiadający za multipleksację.
    3. Za każdym tyknięciem zegara, skok na następną kolumnę za pomocą instrukcji wybory case ... is ... when. I używać rising_edge(clk), a nie CLK'event and CLK = '1', w szczególnie jak zegar jest typu std_logic (8 stanów tranzycji!), np. ominięcie przypadkowego stanu silnej jedynki H do 1.
    4. Da się to skrócić do bardzo małego i prostego opisu.
    5. Może lepiej nie pokazujcie reszty :D
  • Poziom 2  
    Hehe, dla dobra Twojego poczucia estetyki faktycznie lepiej nie oglądać reszty ;p Problem rozwiązałem parę godzin wcześniej (przy RESECIE brakowało zerowania iteratora "i" -> to załatwia sprawę), układ się syntezuje i symulacja daje poprawne wyniki.
    Dzięki za rady, postaram się zastosować te wskazówki, zwłaszcza jeśli chodzi o grupowanie kodu w procesy ;) i zastosowanie wektorów na wierszach (nie wiedziałem, że da się to rozdzielić w .ucf).