AUTO3030 Digitaalitekniikan jatkokurssi, harjoitus 2, ratkaisuja s2009 1. D-kiikku Toteuta DE2:lla synkroninen laskukone, jossa lasketaan kaksi nelibittistä lukua yhteen. Tulos esitetään ledeillä vasta, kun käyttäjä painaa KEY0-näppäintä. entity H2T1 is port(x,y : in std_logic_vector(3 downto 0); flush : in std_logic; -- KEY0 z: out std_logic_vector(4 downto 0)); end H2T1; -- Yhteenlasku architecture arch of H2T1 is signal temp1, temp2 : std_logic_vector(4 downto 0); process(flush, x, y) temp1 <= '0' & x; temp2 <= '0' & y; if falling_edge(flush) then -- Nappi invertoitu -> falling_edge z <= temp1 + temp2; 2. Tilakone Toteuta DE2:lla seuraava tilakone: Painettaessa KEY0 tilakone palaa alkutilaansa. KEY1 seuraava tila. Alkutilassa yksikään ledi ei pala. Kun SW0 = 1 ( 0 ), seuraavassa tilassa palaa yksi punainen ledi enemmän (vähemmän). Ledejä sytytetään järjestyksessä LEDR0, LEDR1,, kunnes kaikki punaiset ledit palavat. Vastaavasti ledejä sammutetaan käänteisessä järjestyksessä. Kokeile tilamuuttujana/signaalina sekä Natural että std_logic_vector -tyyppejä. Vertaa resurssien käyttöä sekä piiritoteutusta. Toteutetaan tilakone kahdella prosessilla, jotka kommunikoivat signaalin avulla. Ensimmäinen prosessi huolehtii tilasiirtymistä, toinen ulostuloista. Tila talletetaan joko Natural- tai std_logic_vector-muuttujaan. std_logic_vector-muuttujaan voidaan jälleen hyödyntää IEEE.std_logic_unsigned-kokoelman yhteenlaskua. entity H2T2 is port(direction: in std_logic; -- SW0 reset, nextstate: in std_logic; -- KEY0, KEY1 ledit: out std_logic_vector(17 downto 0)); jako@uwasa.fi 1
end H2T2; architecture arch of H2T2 is signal state : std_logic_vector(4 downto 0); --signal state : Natural; process(reset, nextstate, direction) state <= (others => '0');--0; elsif falling_edge(nextstate) then if state<18 and direction = '1' then state <= state+1; elsif state>0 and direction = '0' then state <= state-1; state <= state; state <= state; -- Ulostulojen ohjaus process(state) ledit <= (others => '0'); for i in 0 to 17 loop if i<=state-1 then ledit(i) <= '1'; end loop; Ulostulojen ohjaus on tehty mahdollisimman geneerisesti. Tarkoituksena on siis sytyttää kaikki ledit nollasta i 1:een. Huomaa, että for-silmukan rajat pitää olla vakioita. Ei voida kirjoittaa: for i in 0 to i-1 loop ledit(i) <= '1'; end loop; koska piiritoteutus ei voi muuttua syötteen perusteella. Tämä rajoite voidaan kuitenkin kiertää iflauseella, jonka piiritoteutus voidaan tehdä jokaiselle indeksille (ks. RTL Viewer). Havaitaan, että Natural-tyypin käyttäminen johtaa resurssien tuhlaukseen. 3. Kello/Taajuudenjakaja Käytä DE2:n 50 MHz kelloa. Tee taajuudenjakaja, jolla vilkutat lediä esim. 1 s välein. Toteuta esim. parilla switchillä ohjaus, joilla voit säätää kellotaajuutta. Kokeile taajuudenjakajassa sekä Natural että std_logic_vector -tyyppejä. Tehdään ensin yksi 10-bittinen taajuudenjakaja. jako@uwasa.fi 2
-- Taajuudenjakaja entity H2T3 is reset, SW0, SW1: in std_logic; -- reset = KEY0 led: out std_logic); end H2T3; architecture arch of H2T3 is signal clock_24414, clock_12, clock_out, clock_1 : std_logic; -- 10-bittinen taajuudenjakaja 50 MHz/(2*1024) -> 24414 Hz process(reset, clock_50) variable count : std_logic_vector(9 downto 0); clock_24414 <= '0'; elsif rising_edge(clock_50) then if count < 1023 then clock_24414 <= not clock_24414; led <= clock_50; Havaitaan, että piiri muodostuu vakiolla lisäämisestä, muistipiiristä, vakioon vertaamisesta, multiplekseristä, jolla muistiin kirjoitetaan joko yhteenlaskupiirin tulos tai vakio (0), sekä ulostuloa ohjaavasta kiikusta. Toteutus ei muutu, vaikka käytettäisiin Natural-tyyppiä. Tehdään lopullinen taajuudenjakaja kolmella sarjankytketyllä piirillä, joista viimeisessä laskurin maksimiarvoa voidaan muuttaa. Huomaa, että tässä toteutuksessa temp-muuttuja, voi muuttua kesken kellojaksonkin. jako@uwasa.fi 3
-- Taajuudenjakaja entity H2T3 is reset, SW0, SW1: in std_logic; -- reset = KEY0 led: out std_logic); end H2T3; architecture arch of H2T3 is signal clock_24414, clock_12, clock_out, clock_1 : std_logic; -- 10-bittinen taajuudenjakaja 50 MHz/(2*1024) -> 24414 Hz process(reset, clock_50) variable count : std_logic_vector(9 downto 0); clock_24414 <= '0'; elsif rising_edge(clock_50) then if count < 1023 then clock_24414 <= not clock_24414; -- 10-bittinen taajuudenjakaja 24414 Hz/(2*1024) -> 11,9 Hz process(reset, clock_24414) variable count : std_logic_vector(9 downto 0); clock_12 <= '0'; elsif rising_edge(clock_24414) then if count < 1023 then clock_12 <= not clock_12; -- 4-bittinen säädettävä taajuudenjakaja process(reset, clock_12, SW0, SW1) variable count : std_logic_vector(3 downto 0); jako@uwasa.fi 4
variable temp : std_logic_vector(1 downto 0); temp := SW1 & SW0; clock_out <= '0'; elsif rising_edge(clock_12) then case temp is -- f = 11,9 Hz/(2*10) when "00" => if count < 10 then count := count + 1; -- f = 11,9 Hz/(2*8) when "01" => if count < 8 then count := count + 1; -- f = 11,9 Hz/(2*6) when "10" => if count < 6 then count := count + 1; -- f = 11,9 Hz/(2*4) when "11" => if count < 4 then when others => clock_out <= clock_out; end case; led <= clock_out; 4. Peli Muunna tehtävän 2 tilakone peliksi tehtävän 3 avulla. Pelissä on tarkoituksena pitää ledipylvästä mahdollisimman keskellä eli että 9 10 lediä palaisi. Voit keksiä peliin myös esim. pistelaskurin. jako@uwasa.fi 5
Toteutuksessa voidaan käyttää suoraan edellisten tehtävien piirejä. Käytetään rakenteellista piirin esitystapaa: -- Ledipeli: tarvitsee tilakone.vhd ja taajuudenjakaja.vhd entity ledipeli is reset, SW0, SW1, SW17: in std_logic; -- reset = KEY0 -- SW0 ja SW1 ohjaavat taajuutta. SW17 ohjaa tilakoneen suuntaa. ledit: out std_logic_vector(17 downto 0)); end ledipeli; architecture arch of ledipeli is component taajuudenjakaja is reset, SW0, SW1: in std_logic; -- reset = KEY0 led: out std_logic); end component; component tilakone is port(direction: in std_logic; -- SW0 reset, nextstate: in std_logic; -- KEY0, KEY1 ledit: out std_logic_vector(17 downto 0)); end component; -- Sisäinen kello: taajuudenjakajasta tilakoneelle signal clock_1 : std_logic; u1: taajuudenjakaja port map(clock_50, reset, SW0, SW1, clock_1); u2: tilakone port map(sw17, reset, clock_1, ledit); Peli-iloa! jako@uwasa.fi 6