-- Dateiname: Tastatur Top -- Design Software : Quartus II 13.0sp1 (64-bit) -- -- Erstellt: -- von - Kai-Frederik Nessitt -- 2008 -- www.mikroelektronik.w-hs.de -- -- Verändert: -- Von Moujahid Bouhouch -- -- Am 10.06.2021 -- -------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; ENTITY audio_ausg_ram ISPORT ( ram_clk : IN std_logic; -- clock des Systems clockNC_en : IN std_logic; -- Clock des Wortgeschwindigkeit reset : IN STD_ULOGIC; -- Reset token : IN std_logic_vector(15 DOWNTO 0); -- Daten zum Codieren ausgabe_modus : IN std_logic; -- Modus des Codieren/ einzelne Buchtabe oder Sequenz von Buchstaben breakCode : IN std_logic; -- gibt an ob die Taste losgelassen wurde soft_reset : IN std_logic; sound : OUT std_logic; -- Sound Signal zum weiter schicken an die Audio Codec adresse : OUT std_logic_vector(11 DOWNTO 0); -- Adresse des RAMs ram_data_out : OUT std_logic_vector(15 DOWNTO 0) -- Daten die schon im RAM gespeichert wurde ); END audio_ausg_ram; ARCHITECTURE structure OF audio_ausg_ram IS SIGNAL mem_max : NATURAL RANGE 0 TO 279 := 0; signal breakCodevar : std_logic; signal read_write : std_logic; signal ram_addr_old : std_logic_vector(17 downto 0) := (others => '0'); signal ram_addr_new : std_logic_vector(17 downto 0) := (others => '0'); type ram_array is array (0 to 256 ) of std_logic_vector (15 downto 0); -- initial values in the ram signal ram: ram_array := (others=>(others=>'0')); signal breakCode_delayed : std_logic := '0'; signal breakCode_rising_edge : std_logic; signal Enter_taste : std_logic := '0'; SIGNAL count : NATURAL := 0; signal count_addr : NATURAL range 0 to 256 := 0; signal soft_reset_var : std_logic := soft_reset; signal token_word : std_logic_vector(15 DOWNTO 0) := (others => '0'); --signal ram_data_out_var : std_logic_vector(15 downto 0); BEGIN -- konviertierung des ram adresse adresse <= STD_LOGIC_VECTOR(TO_UNSIGNED(count_addr, 12)); -- Das Speichern von Daten im RAM sollte einmal erfolgen, wenn die Taste losgelassen wird -- es ist erforderlich, dass das Signal einmal während eines Taktzyklus auftritt -- es wird mit jedem Taktzyklus den Wert von den Wert von BreakCode vergleichen -- wenn sie sich unterscheiden, breakCode_rising_edge wird mit '1' zugewiesen get_delayed_breakCode : PROCESS (clockNC_en) BEGIN IF reset = '0' THEN breakCode_delayed <= '0'; ELSE IF rising_edge(clockNC_en) THEN breakCode_delayed <= breakCode; breakCode_rising_edge <= NOT breakCode_delayed AND breakCode; END IF; END IF;END PROCESS; -- Auslesen des Token-Signals und Erzeugung des "sound" Signals zur Ausgabe des codierten Morsesignals -- sowie Auslesen des rams bei der Aktivierung des "Wortmodus" durch Schalterstellung zur Übertragung -- ganzer Worte / Sätze audio : PROCESS (clockNC_en, reset, token, ausgabe_modus)VARIABLE two_bits_count : NATURAL RANGE 0 TO 16 := 0; VARIABLE ausgabe_modus_state : NATURAL RANGE 0 TO 2 := 0;BEGIN IF reset = '0' THEN sound <= '0'; count <= 0; two_bits_count := 0; ausgabe_modus_state := 0; count_addr <= 0; soft_reset_var <= '0'; token_word <= (OTHERS => '0');ELSIF clockNC_en'EVENT AND clockNC_en = '1' THENsoft_reset_var <= '0'; -- Codierung von einzelnen Buchstaben IF ausgabe_modus = '0' THENIF two_bits_count >= 0 AND two_bits_count < 16 THEN -- Codierung eines "Dits" als Signal mit doppelter Periodendauer der Wortgeschwindigkeit -- man prüft jede zwei bits und enscheidet ob dies ein dit oder dash ist IF token(two_bits_count + 1 DOWNTO two_bits_count) = "01" THEN IF count >= 2 THEN count <= 0; sound <= '0'; two_bits_count := two_bits_count + 2; ELSE count <= count + 1; sound <= '1'; END IF; --Codierung eines "Dahs" als Signal mit sechsfacher Periodendauer der Wortgeschwindigkeit ELSIF token(two_bits_count + 1 DOWNTO two_bits_count) = "11" THEN IF count >= 6 THEN count <= 0; sound <= '0'; two_bits_count := two_bits_count + 2; ELSE count <= count + 1; sound <= '1'; END IF; --Auslesen beenden, wenn nur noch Nullen im Token-Signal gelesen werden ELSE sound <= '0'; two_bits_count := 16; END IF; END IF;-- zweite Modus -- Codierung von Sequenz von Buchstaben -- wenn eine Taste der Tastatur losgelassen ist, wird das entsprechende Tokensignal -- im RAM gespeichert -- Das Lesen vom Ram erfolg, wenn die Enter Taste gedruckt und losgelassen wurde -- Enter Taste entspricht eine hexadecimalzahl von C0 ELSIF ausgabe_modus = '1' THEN -- Daten in den ram schreiben, wenn eine Taste betätigt wurde und diese Taste kein "Enter" war IF breakCode_rising_edge = '1' AND token /= x"C000" THEN RAM(count_addr) <= token; count_addr <= count_addr + 1; -- Token-Signal in token_word-Signal übertragen, wenn eine Taste gedrückt wurde und diese Taste ein "Enter" war ELSIF breakCode_rising_edge = '1' AND token = x"C000" THEN token_word(15 DOWNTO 0) <= token; -- Daten aus dem RAM zurücklesen ELSIF (token_word(15 DOWNTO 0) = x"C000" OR count_addr > 256) OR ausgabe_modus_state > 0 THEN CASE ausgabe_modus_state IS -- Das Lesen wird angefangen mit RAM Adresse 0. Zeile 0 WHEN 0 => count_addr <= 0; token_word(15 DOWNTO 0) <= RAM(count_addr); ram_data_out(15 DOWNTO 0) <= RAM(count_addr); ausgabe_modus_state := 1; -- Die Codieren wird genauso wie beim ersten Modus implementiert WHEN 1 => IF two_bits_count >= 0 AND two_bits_count < 16 THEN IF token_word(two_bits_count + 1 DOWNTO two_bits_count) = "01" THEN IF count >= 2 THEN count <= 0; sound <= '0'; two_bits_count := two_bits_count + 2;ELSE count <= count + 1; sound <= '1';END IF; ELSIF token_word(two_bits_count + 1 DOWNTO two_bits_count) = "11" THEN IF count >= 6 THEN count <= 0; sound <= '0'; two_bits_count := two_bits_count + 2;ELSE count <= count + 1; sound <= '1';END IF; ELSIF token_word(15 DOWNTO 0) = "1000000000000000" THEN --Prüfen ob das Tokenwort ein Leerzeichen repräsentiert --In kombination mit dem count = 6 von "two_bits_count >= 16" ergibt sich eine Länge von 7 "Dits"! => Pause zwischen Worten IF count >= 8 THEN count <= 0; sound <= '0'; two_bits_count := 16; ELSE count <= count + 1; END IF; ELSIF token_word(15 DOWNTO 0) = x"C000" THEN sound <= '0'; ausgabe_modus_state := 2; -- Beendung der Übertragung, wenn man die Zeile des RAMs nur aus nullen besteht ELSIF RAM(count_addr) = x"0000" THEN sound <= '0'; ausgabe_modus_state := 2; -- Beendung der Übertragung, wenn man die letzte RAM zeile erreicht ELSIF count_addr >= 256 THEN sound <= '0'; ausgabe_modus_state := 2; -- wenn im Datenwort nur noch Nullen stehen muss die Leseadresse inkrementiert und anschließend das neue Datenwort ausgelesen werden ELSIF token_word(two_bits_count + 1 DOWNTO two_bits_count) = "00" AND token_word(15 DOWNTO 0) /= "1100000000000000" AND token_word(15 DOWNTO 0) /= "1000000000000000" THEN sound <= '0'; count <= 0; two_bits_count := 16;END IF; END IF; -- Wenn das Datenwort zuende analysiert wurde, wird die Leseadresse inkrementiert und das nächste Datenwort ausgelesen IF two_bits_count >= 16 THEN IF count >= 6 THEN count <= 0; sound <= '0'; two_bits_count := 0; count_addr <= count_addr + 1; token_word(15 DOWNTO 0) <= RAM(count_addr); ram_data_out(15 DOWNTO 0) <= RAM(count_addr); ELSE count <= count + 1; END IF;END IF; -- Wenn der SPeicher komplett ausgelesen wurde, dann wird der Speicher durch einen Software-ResetWHEN OTHERS =>soft_reset_var <= '1'; IF count >= 6 THEN count <= 0; sound <= '0'; two_bits_count := 0; ausgabe_modus_state := 0; count_addr <= 0; count <= 0; sound <= '0'; two_bits_count := 0; token_word <= (OTHERS => '0'); ELSE count <= count + 1;END IF; END CASE; END IF;END IF; END IF; -- Ist das Token-Signal komplett ausgelesen ausgabe_modusen und eine neue Taste wurde gedrückt, -- dann soll das bitpaarweise Auslesen erneut beginnen IF two_bits_count >= 16 AND (breakCode_rising_edge = '1' AND ausgabe_modus = '0') THEN two_bits_count := 0; END IF;END PROCESS; END structure;