-- Per svolgere la prima parte dell'esercizio era necessario -- 1) istanziare un contatore in grado di contare 1000 cicli, -- con la sola funzione di scandire l'inizio del procedimento -- di lettura -- 2) uno shift register pilotato opportunamente allo scopo -- di acquisire la sequenza di ingresso -- 3) Tre registri ove memorizzare il valore corrente di A, -- il suo valore massimo ed il varo minimo. -- 4) La generazione del clock SCK e della sequenza SDO -- potevano essere implementate in maniera piuttosto banale -- attraverso una FSM un po rindondante (ovviamente -- il numero di stati puo essere ridotto in molteplici modi -- ma la soluzione proposta e' indubbiamente la piu' veloce) --contatore a 10 bit per contare i 1000 cicli di clock library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity contatore1000 is port(CLOCK,RESET:in std_logic; VALORE:out unsigned(9 downto 0)); end contatore1000; architecture A of contatore1000 is signal cont,next_cont:unsigned(9 downto 0); begin process(CLOCK) begin if CLOCK'event and CLOCK='1' then if RESET='1' then cont<=conv_unsigned(0,10); else cont<=next_cont; end if; end if; end process; next_cont<=cont+conv_unsigned(1,10); VALORE<=cont; end A; ------------------------------------------------------------------ -- contatore a 8 bit con enable per contare i secondi e valutare il -- periodo dell'ampiezza library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity contatore8enable is port(CLOCK,RESET, enable:in std_logic; VALORE:out unsigned(7 downto 0)); end contatore8enable; architecture A of contatore8enable is signal cont,next_cont:unsigned(7 downto 0); begin process(CLOCK) begin if CLOCK'event and CLOCK='1' then if RESET='1' then cont<=conv_unsigned(0,8); elsif enable = '1' then cont<=next_cont; end if; end if; end process; next_cont<=cont+conv_unsigned(1,8); VALORE<=cont; end A; --------------------------------------------------- --- ---------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity ACCELEROMETRO2 is port(CK:in std_logic; RES:in std_logic; SDI:in std_logic; SDO:out std_logic; SCK:out std_logic; A:out unsigned(7 downto 0); AMAX:out unsigned(7 downto 0); AMIN:out unsigned(7 downto 0); PERIODO: out unsigned(7 downto 0)); end ACCELEROMETRO2; architecture RTL of ACCELEROMETRO2 is component contatore1000 port(CLOCK,RESET:in std_logic; VALORE:out unsigned(9 downto 0)); end component; component contatore8enable port(CLOCK,RESET,enable:in std_logic; VALORE:out unsigned(7 downto 0)); end component; signal enableseriale,enableparallelo,enablemassimo,enableminimo,reset:std_logic; signal q:unsigned(8 downto 0); signal cicli:unsigned(9 downto 0); signal A_int, max,min:unsigned(7 downto 0); signal fine1000, fine26:std_logic; type stato is(idle,C0A, C0B, C1A, C1B, C2A,C2B, C3A,C3B, C4A,C4B, C5A, C5B, C6A, C6B, C7A, C7B, fineC, CC0A, CC0B, CC1A, CC1B, CC2A, CC2B, CC3A, CC3B, CC4A, CC4B, CC5A, CC5B, CC6A, CC6B, CC7A, CC7B, campiona, attesa); signal cs_C,ns_C:stato; ----- lista segnali per svolgere la seconda parte signal enableinit, uguali, dato0, resetc: std_logic; signal contasec, periodo_int, periodo0: unsigned(7 downto 0); signal A_init: unsigned(7 downto 0); type statoP is(parti,init,primodato,attesa1,valuta1,attesa2,valuta2, fine); signal cs_p,ns_p:statop; ------- begin ------- prima parte dell'esercizio contatore:contatore1000 port map(CLOCK=>CK,RESET=>reset,VALORE=>cicli); fine1000<='1' when cicli=conv_unsigned(46,10) else '0'; fine26 <='1' when cicli=conv_unsigned(26,10) else '0'; ---- dovrebbe essere conv_unisgned(1000,10) reset<=(RES or fine1000); ---- parte combinatoria della macchina a stati finiti che genera ---- i segnali di enable dello shift register che campiona SDI e del ---- registro che campiona A e che genera i segnal di uscita SCK e SDO process(cs_C,fine26, fine1000) begin enableseriale <= '0'; enableparallelo <= '0'; sck <= '0'; sdo <='0'; case cs_C is when idle=> ns_C<=c0A; when c0A=> SDO<='0'; SCK <= '1'; ns_C<=C0B; when c0B=> SDO<='0'; SCK <= '0'; ns_C<=c1A; when c1A => SDO<='0'; SCK <= '1'; ns_C<=C1B; when c1B=> SDO<='0'; SCK <= '0'; ns_C<=c2A; when c2A=> SDO<='1'; SCK <= '1'; ns_C<=C2B; when c2B=> SDO<='1'; SCK <= '0'; ns_C<=c3A; when c3A=> SDO<='0'; SCK <= '1'; ns_C<=C3B; when c3B=> SDO<='0'; SCK <= '0'; ns_C<=c4A; when c4A=> SDO<='1'; SCK <= '1'; ns_C<=C4B; when c4B=> SDO<='1'; SCK <= '0'; ns_C<=c5A; when c5A=> SDO<='1'; SCK <= '1'; ns_C<=C5B; when c5B=> SDO<='1'; SCK <= '0'; ns_C<=c6A; when c6A=> SDO<='0'; SCK <= '1'; ns_C<=C6B; when c6B=> SDO<='0'; SCK <= '0'; ns_C<=c7A; when c7A=> SDO<='0'; SCK <= '1'; ns_C<=C7B; when c7B=> SDO<='0'; SCK <= '0'; ns_C<=fineC; when fineC => if fine26 = '1' then ns_C <= cc0A ; else ns_C <= fineC; end if; when cc0A=> SCK <= '1'; ns_C<=cc0B; when cc0B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc1A; when cc1A=> SCK <= '1'; ns_C<=cc1B; when cc1B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc2A; when cc2A=> SCK <= '1'; ns_C<=cc2B; when cc2B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc3A; when cc3A=> SCK <= '1'; ns_C<=cc3B; when cc3B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc4A; when cc4A=> SCK <= '1'; ns_C<=cc4B; when cc4B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc5A; when cc5A=> SCK <= '1'; ns_C<=cc5B; when cc5B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc6A; when cc6A=> SCK <= '1'; ns_C<=cc6B; when cc6B=> enableseriale <= '1'; SCK <= '0'; ns_C<=cc7A; when cc7A=> SCK <= '1'; ns_C<=Cc7B; when cc7B=> enableseriale <= '1'; SCK <= '0'; ns_C<= campiona; when campiona => enableparallelo<='1'; ns_c <= attesa; when attesa => if fine1000 = '1' then ns_C <= idle ; else ns_C <= attesa; end if; when others=> ns_C<=idle; end case; end process; ---- parte sequenziale della macchina a stati finiti process(ck) begin if ck'event and ck='0' then if RES='1' then cs_C <=idle ; else cs_C <= ns_c; end if; end if; end process; --- shift register shift_reg: for i in 0 to 7 generate ff_i: process(ck) begin if ck'event and ck='0' then if RES='1' then q(i+1) <= '0' ; elsif enableseriale = '1' then q(i+1) <= q(i); end if; end if; end process; end generate; q(0) <= SDI; ---- registro per campionare i dati dallo shift register process(ck) begin if ck'event and ck='0' then if RES='1' then A_int <= (others => '0') ; elsif enableparallelo = '1' then A_int <= q(8 downto 1); end if; end if; end process; A <= A_int; ---- registro che memnorizza il valore minimo dell'ampiezza ---- process(ck) begin if ck'event and ck='0' then if RES='1' then min <= (others => '1') ; elsif enableminimo = '1' and enableparallelo = '1' then min <= q(8 downto 1); end if; end if; end process; Amin <= min; enableminimo <= '1' when q(8 downto 1) < min else '0'; ---- registro che memnorizza il valore massimo dell'ampiezza ---- process(ck) begin if ck'event and ck='0' then if RES='1' then max <= (others => '0') ; elsif enablemassimo = '1' and enableparallelo = '1' then max <= q(8 downto 1); end if; end if; end process; Amax <= max; enablemassimo <= '1' when q(8 downto 1) > max else '0'; --------------- ---- seconda parte dell'esercizio: calcolo del periodo contaperiodo: contatore8enable port map(CLOCK=>CK,RESET=>resetc, enable => fine1000, VALORE=>contasec); resetc <= RES ; ---- registro per campionare il valore iniziale process(ck) begin if ck'event and ck='0' then if RES='1' then A_init <= (others => '0') ; elsif enableinit = '1' then A_init <= A_int; end if; end if; end process; ---- riconosco se il valore campionato è uno 0 dato0 <= '1' when A_init = conv_unsigned(0,8) or A_init = conv_unsigned(255,8) else '0'; process(ck) begin if ck'event and ck='0' then if RES='1' then periodo_int <= (others => '0') ; elsif uguali = '1' then periodo_int <= contasec; end if; end if; end process; ------ valuto il periodo come l'intervallo in secondi fra la lettura non successiva di due ---- dati uguali --- (so infatti che il segnale è una sinusoide i cui valori sono tutti maggiori o uguali --- a 0; se il primo valore campionato è 0 o 255 bisogna dividere ---- il valore per due, infatti la sinusoide assume questi valori solo una volta per periodo) periodo0(7) <= '0'; periodo0(6 downto 0) <= periodo_int(7 downto 1); periodo <= periodo_int when dato0 = '0' else periodo0; --- parte combinatoria della macchina a stati finiti process(cs_p,enableparallelo,fine1000, A_init,A_int) begin uguali <='0'; case cs_p is when parti=> enableinit <= '0'; if enableparallelo = '1'then ns_p<=init; else ns_p <= cs_p; end if; when init => --- memorizzi il primo valore campionato enableinit <= '1'; ns_p <=primodato; when primodato => ---- non si fa il confronto con il primo dato perchè ---- è il valore campionato enableinit <= '0'; if fine1000 ='1' then ns_p <= attesa1 ; else ns_p <= cs_p; end if; when attesa1 => --- si fa il confronto solo ogni secondo enableinit <= '0'; if fine1000 ='1' then ns_p <= valuta1 ; else ns_p <= cs_p; end if; when valuta1=> ---- se il dato letto è uguale al primo si passa al nuovo ciclo di ---- attesa sul secondo dato uguale enableinit<= '0'; if A_init = A_int then ns_p <= attesa2; else uguali <= '0'; ns_p <= attesa1; end if; when attesa2 => --- si fa il confronto solo ogni secondo enableinit <= '0'; if fine1000 ='1' then ns_p <= valuta2 ; else ns_p <= cs_p; end if; when valuta2 => ---- se il dato letto è uguale al primo allora si aggiorna periodo enableinit<= '0'; if A_init = A_int then uguali <= '1'; ns_p <= fine; else uguali <= '0'; ns_p <= attesa2; end if; when fine => enableinit <= '0'; ns_p <= cs_p; when others => ns_p <= parti; end case; end process; ---- parte sequenziale della macchina a stati finiti process(ck) begin if ck'event and ck='0' then if RES='1' then cs_p <=parti ; else cs_p <= ns_p; end if; end if; end process; end RTL;