library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; entity par_calculator is port( CK : in std_logic; RES : in std_logic; nSTROBE : in std_logic; DATA : in signed(7 downto 0); BUSY : out std_logic; RESULT : out signed(15 downto 0) ); end par_calculator; architecture arc of par_calculator is -- per il contatore signal Conta : std_logic := '0'; signal contBusy, nextContBusy : unsigned(2 downto 0); -- per il generatore di strobe signal newstrobe,nstrobe_CLK : std_logic; -- per l'accumulatore signal accumulatore, accumulatoreTemp : signed(15 downto 0); signal en_Acc, reset_Acc : std_logic; -- per l'aggiornamento dell'uscita signal en_Res_reg : std_logic; -- per la macchina a stati type stato is (wake, sleep, aggiornaRESULT, dato1, dato2, dato3, dato4); signal cs, ns : stato; -- per la memoria del comando signal en_comando_reg : std_logic; signal comando : signed(7 downto 0); begin -- mi serve un oggetto che trasformi l'nstrobe attivo 4 cicli -- in un segnale + amichevole newstrobe attivo alto per un solo CK process(CK,RES) begin if RES = '1' then nstrobe_CLK <= '0'; elsif (CK'event and CK = '1') then nstrobe_CLK <= nSTROBE; end if; end process; newstrobe <= not (nSTROBE) and nstrobe_CLK; -- mi serve un oggetto che piloti per 6 cicli CK il BUSY e si attivi -- ogni volta che il newstrobe va alto. process(CK,RES,newstrobe) begin if RES = '1' or newstrobe = '1' then contBusy <= (others => '0'); elsif CK'event and CK = '1' then if conta = '1'then contBusy <= nextContBusy; end if; end if; end process; nextContBusy <= contBusy + conv_unsigned(1, 3); conta <= '1' when contBusy < conv_unsigned(6, 3) else '0'; BUSY <= conta; -- registro per memorzzare la parola di comando utile a pilotare la logica di -- uscita per la gsetione del RESULT process(CK,RES) begin if RES = '1' then comando <= (others => '0'); elsif(CK'event and CK = '1') then if en_Comando_reg = '1' then comando <= DATA; end if; end if; end process; -- mi serve un'accumulatore che contenga di volta in volta mi memorizzi -- un nuovo dato sommandolo con i precedenti già campionati. Attenzione -- che tra due successivi comandi l'accumulatore va resettato. process (CK,RES,reset_Acc) begin if RES = '1' or reset_Acc = '1' then accumulatore <= (others => '0'); elsif CK'event and CK = '1' then if en_Acc = '1' then accumulatore <= accumulatoreTemp; end if; end if; end process; accumulatoreTemp <= accumulatore + DATA; -- macchina a stati per gestire le operazioni process (CK,RES) begin if RES = '1' then cs <= wake; elsif CK'event and CK = '1' then cs <= ns; end if; end process; process (cs, newstrobe, DATA, comando) begin en_Res_reg <= '0'; en_Comando_reg <= '0'; reset_Acc <= '0'; en_Acc <= '0'; case cs is when wake => if(newstrobe = '1') then en_comando_reg <= '1'; reset_Acc <= '1'; if (conv_std_logic_vector(DATA, 8) = "10000000") then -- sleep ns <= sleep; elsif(conv_std_logic_vector(DATA, 8) = "00000001" or -- somma o media o compl2 conv_std_logic_vector(DATA, 8) = "00000100" or conv_std_logic_vector(DATA, 8) = "00000010") then ns <= dato1; else ns <= cs; end if; else ns <= cs; end if; when sleep => if(newstrobe = '1') then if (conv_std_logic_vector(DATA, 8) = "10000001") then -- wake ns <= wake; else ns <= cs; end if; else ns <= cs; end if; when dato1 => if(newstrobe = '1') then en_Acc <= '1'; -- se compl2 al prox ciclo aggiorno il risultato if (conv_std_logic_vector(comando, 8) = "00000010") then ns <= aggiornaRESULT; else -- comando di somma o media ns <= dato2; end if; else ns <= cs; end if; when dato2 => if(newstrobe = '1') then en_Acc <= '1'; -- se somma al prox ciclo aggiorno il risultato if (conv_std_logic_vector(comando, 8) = "00000001") then ns <= aggiornaRESULT; else -- comando di media ns <= dato3; end if; else ns <= cs; end if; when dato3 => if(newstrobe = '1') then ns <= dato4; en_Acc <= '1'; else ns <= cs; end if; when dato4 => if(newstrobe = '1') then ns <= aggiornaRESULT; en_Acc <= '1'; else ns <= cs; end if; when aggiornaRESULT => en_Res_reg <= '1'; ns <= wake; when others => null; end case; end process; -- questo registro viene utilizzato per salvare il risulato da portare nell' -- uscita RESULT e mantenerlo valido sinchè non ho campionato un nuovo -- comando ed i relativi dati necessari ad espletare il calcolo rischiesto process (CK,RES) begin if RES = '1' then RESULT <= (others => '0'); elsif CK'event and CK = '1' then if en_Res_reg = '1' then if (conv_std_logic_vector(comando, 8) = "00000001") then -- somma RESULT <= accumulatore; elsif (conv_std_logic_vector(comando, 8) = "00000100") then -- media RESULT <= "00" & accumulatore(15 downto 2); elsif (conv_std_logic_vector(comando, 8) = "00000010") then -- complemento2 RESULT <= -accumulatore; end if; end if; end if; end process; end arc;