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

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

jerzu8 22 Sty 2011 23:11 1850 5
REKLAMA
  • #1 9043687
    jerzu8
    Poziom 2  
    Posty: 4
    Ocena: 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
  • REKLAMA
  • #2 9043720
    gerlin
    Poziom 9  
    Posty: 32
    Ocena: 1
    w jaki sposób realizujesz multipleksowanie: rejestr przesuwny czy jakoś inaczej ? i przypisania do sygnałów wyjściowych... jakbyś wkleił kawałek kodu multipleksera ;)
  • REKLAMA
  • #3 9043773
    jerzu8
    Poziom 2  
    Posty: 4
    Ocena: 2
    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;
    
  • REKLAMA
  • #4 9048437
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    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
  • REKLAMA
  • #5 9048808
    jerzu8
    Poziom 2  
    Posty: 4
    Ocena: 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).
  • Pomocny post
    #6 9048819
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    jerzu8 napisał:
    ...(nie wiedziałem, że da się to rozdzielić w .ucf).

    Zwyczajnie:
    #Example
    NET "red_o(0)" 	LOC = "A1" ; 
    NET "red_o(1)" 	LOC = "A2" ; 
    NET "red_o(2)" 	LOC = "A3" ;
REKLAMA