LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY Keyboard_Encoder IS PORT ( clock_50 : IN STD_ULOGIC; --50Mhz Systemtakt clockNC : IN STD_ULOGIC; --Wortgeschwindigkeit reset : IN STD_ULOGIC; --Reset-Signal done_pressing : IN STD_ULOGIC; --Signal ob eine Taste der Tastatur zuende übertragen hat data_keyboard : IN STD_ULOGIC_VECTOR (7 DOWNTO 0); --Tastaturdaten Audio_Out : OUT STD_ULOGIC; --Signal zum Anschalten des Tons bei einem codierten Morsesignal word : IN STD_ULOGIC; --Schalter zur Umstellung zwischen Buchstaben- und Wortmodus mem_addr_leds : OUT STD_ULOGIC_VECTOR (7 DOWNTO 0) --LEDs zur Anzeige der aktuellen Speicheradresse des RAMs ); END Keyboard_Encoder; ARCHITECTURE structure OF Keyboard_Encoder IS SIGNAL sound : STD_ULOGIC := '0'; SIGNAL cnt : NATURAL := 0; SIGNAL token : STD_ULOGIC_VECTOR (13 DOWNTO 0) := (OTHERS => '0'); SIGNAL token_word : STD_ULOGIC_VECTOR (15 DOWNTO 0) := (OTHERS => '0'); SIGNAL done_old : STD_ULOGIC := '0'; SIGNAL done_rise : STD_ULOGIC := '0'; SIGNAL done_old2 : STD_ULOGIC := '0'; SIGNAL done_rise2 : STD_ULOGIC := '0'; SIGNAL mem_addr : NATURAL RANGE 0 TO 279 := 0; SIGNAL RAM_ADDR : STD_ULOGIC_VECTOR (7 DOWNTO 0); SIGNAL RAM_OUT : STD_ULOGIC_VECTOR (21 DOWNTO 0); SIGNAL RAM_IN : STD_ULOGIC_VECTOR (21 DOWNTO 0); SIGNAL read_write : STD_ULOGIC := '0'; SIGNAL mem_reset_addr : NATURAL RANGE 0 TO 279 := 0; SIGNAL mem_reset_data : STD_ULOGIC_VECTOR (21 DOWNTO 0) := (OTHERS => '0'); SIGNAL soft_reset : STD_ULOGIC := '1'; SIGNAL mem_max : NATURAL RANGE 0 TO 279 := 0; component Word_Memory is port ( mem_clock_2_clk : in STD_ULOGIC := 'X'; -- clk mem_slave_2_address : in STD_ULOGIC_VECTOR(7 downto 0) := (others => 'X'); -- address mem_slave_2_clken : in STD_ULOGIC := 'X'; -- clken mem_slave_2_chipselect : in STD_ULOGIC := 'X'; -- chipselect mem_slave_2_write : in STD_ULOGIC := 'X'; -- write mem_slave_2_readdata : out STD_ULOGIC_VECTOR(21 downto 0); -- readdata mem_slave_2_writedata : in STD_ULOGIC_VECTOR(21 downto 0) := (others => 'X'); -- writedata mem_reset_2_reset : in STD_ULOGIC := 'X'; -- reset mem_reset_2_reset_req : in STD_ULOGIC := 'X' -- reset_req ); end component Word_Memory; BEGIN u0 : component Word_Memory port map ( mem_clock_2_clk => clock_50, -- mem_clock_2.clk mem_slave_2_address => RAM_ADDR, -- mem_slave_2.address mem_slave_2_clken => '1', -- .clken mem_slave_2_chipselect => '1', -- .chipselect mem_slave_2_write => read_write,-- .write mem_slave_2_readdata => RAM_OUT, -- .readdata mem_slave_2_writedata => RAM_IN, -- .writedata mem_reset_2_reset => '0' -- mem_reset_2.reset ); Audio_Out <= sound; --------------------------------------------------------------------------------------------------------------- --Zuweisung der entsprechenden Speicheradresse in Abhängigkeit davon ob ein reset ausgelöst wurde oder nicht,-- --sowie das Leeren des RAM durch Auffüllen des Speichers mit Nullen-------------------------------------------- --------------------------------------------------------------------------------------------------------------- assignment: PROCESS (clock_50, reset, soft_reset) BEGIN IF clock_50'EVENT AND clock_50 = '1' THEN IF reset = '0' OR soft_reset = '1' THEN --Leeren des Speichers RAM_ADDR <= STD_ULOGIC_VECTOR(TO_UNSIGNED(mem_reset_addr,8)); IF mem_reset_addr <= 279 THEN mem_reset_addr <= mem_reset_addr + 1; ELSE mem_reset_addr <= 0; END IF; ELSE --"normale" Zuweisung der Speicheradresse im "normalen" Betrieb RAM_ADDR <= STD_ULOGIC_VECTOR(TO_UNSIGNED(mem_addr,8)); mem_reset_addr <= 0; END IF; END IF; END PROCESS; -------------------------------------------------------------------- --Erzeugung eines gespiegelten Token-Signals zum späteren Auslesen-- -------------------------------------------------------------------- token_generation: PROCESS (reset, done_pressing, data_keyboard) BEGIN IF reset = '0' THEN token <= (OTHERS => '0'); ELSIF done_pressing'EVENT AND done_pressing = '1' THEN CASE data_keyboard IS --Buchstaben WHEN x"1C" => token <="00000000001101"; -- A WHEN x"32" => token <="00000001010111"; -- B WHEN x"21" => token <="00000001110111"; -- C WHEN x"23" => token <="00000000010111"; -- D WHEN x"24" => token <="00000000000001"; -- E WHEN x"2B" => token <="00000001110101"; -- F WHEN x"34" => token <="00000000011111"; -- G WHEN x"33" => token <="00000001010101"; -- H WHEN x"43" => token <="00000000000101"; -- I WHEN x"3B" => token <="00000011111101"; -- J WHEN x"42" => token <="00000000110111"; -- K WHEN x"4B" => token <="00000001011101"; -- L WHEN x"3A" => token <="00000000001111"; -- M WHEN x"31" => token <="00000000000111"; -- N WHEN x"44" => token <="00000000111111"; -- O WHEN x"4D" => token <="00000001111101"; -- P WHEN x"15" => token <="00000011011111"; -- Q WHEN x"2D" => token <="00000000011101"; -- R WHEN x"1B" => token <="00000000010101"; -- S WHEN x"2C" => token <="00000000000011"; -- T WHEN x"3C" => token <="00000000110101"; -- U WHEN x"2A" => token <="00000011010101"; -- V WHEN x"1D" => token <="00000000111101"; -- W WHEN x"22" => token <="00000011010111"; -- X WHEN x"1A" => token <="00000011110111"; -- Y WHEN x"35" => token <="00000001011111"; -- Z --Zahlen WHEN x"45" => token <="00001111111111"; -- 0 WHEN x"16" => token <="00001111111101"; -- 1 WHEN x"1E" => token <="00001111110101"; -- 2 WHEN x"26" => token <="00001111010101"; -- 3 WHEN x"25" => token <="00001101010101"; -- 4 WHEN x"2E" => token <="00000101010101"; -- 5 WHEN x"36" => token <="00000101010111"; -- 6 WHEN x"3D" => token <="00000101011111"; -- 7 WHEN x"3E" => token <="00000101111111"; -- 8 WHEN x"46" => token <="00000111111111"; -- 9 --Sonderzeichen -- WHEN x"" => token <="00000111110111"; -- Å WHEN x"52" => token <="00000011011101"; -- Ä -- WHEN x"" => token <="00000111010111"; -- È -- WHEN x"" => token <="00000101110101"; -- É WHEN x"4C" => token <="00000001111111"; -- Ö WHEN x"54" => token <="00000011110101"; -- Ü WHEN x"4E" => token <="01011111010101"; -- ß -- WHEN x"" => token <="00110111011101"; -- ; -- WHEN x"" => token <="00010111110101"; -- ? WHEN x"4A" => token <="00110101010111"; -- - -- WHEN x"" => token <="00010111110111"; -- _ -- WHEN x"" => token <="00001111011111"; -- Ñ WHEN x"49" => token <="00110111011101"; -- . WHEN x"41" => token <="00111101011111"; -- , -- WHEN x"" => token <="00111111010101"; -- : -- WHEN x"" => token <="00001101111101"; -- ( -- WHEN x"" => token <="00110111110111"; -- ) -- WHEN x"" => token <="00011111111101"; -- ' -- WHEN x"" => token <="00001101010111"; -- = WHEN x"5B" => token <="00000111011101"; -- + -- WHEN x"" => token <="00001101011101"; -- / -- WHEN x"" => token <="00011111011101"; -- @ WHEN x"29" => token <="10000000000000"; -- " " WHEN x"5A" => token <="11000000000000"; -- "ENTER" WHEN OTHERS => token <= (OTHERS => '0'); END CASE; 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 (reset, clockNC, token, word) VARIABLE double: NATURAL RANGE 0 TO 16 := 0; VARIABLE state: NATURAL RANGE 0 TO 3 := 0; VARIABLE word_state: NATURAL RANGE 0 TO 2 := 0; VARIABLE state2: NATURAL RANGE 0 TO 2 := 0; BEGIN IF reset = '0' THEN sound <= '0'; cnt <= 0; double := 0; word_state := 0; state2 := 0; state := 0; mem_max <= 0; mem_addr <= 0; read_write <= '1'; RAM_IN <= (OTHERS => '0'); soft_reset <= '0'; token_word <= (OTHERS => '0'); ELSIF clockNC'EVENT AND clockNC = '1' THEN soft_reset <= '0'; --BUCHSTABENMODUS --Codierung einzelner Buchstaben durch paarweises Überprüfen der Bits des Token-Signals IF word = '0' THEN done_rise <= '0'; done_old <= done_pressing; IF done_old = '0' AND done_pressing = '1' THEN done_rise <= '1'; END IF; IF double >= 0 AND double < 14 THEN --Codierung eines "Dits" als Signal mit doppelter Periodendauer der Wortgeschwindigkeit IF token(double + 1 DOWNTO double) = "01" THEN IF cnt >= 2 THEN cnt <= 0; sound <= '0'; double := double + 2; ELSE cnt <= cnt + 1; sound <= '1'; END IF; --Codierung eines "Dahs" als Signal mit sechsfacher Periodendauer der Wortgeschwindigkeit --(3-fache Dit-Länge) ELSIF token(double +1 DOWNTO double) = "11" THEN IF cnt >= 6 THEN cnt <= 0; sound <= '0'; double := double + 2; ELSE cnt <= cnt + 1; sound <= '1'; END IF; --Auslesen beenden, wenn nur noch Nullen im Token-Signal gelesen werden ELSE sound <= '0'; double := 14; END IF; END IF; --WORTMODUS --Codierung ganzer Worte / Sätze durch auslesen des Speichers und dann paarweises Überprüfen der Bits des gelesenen Datenworts ELSIF word = '1' THEN done_rise2 <= '0'; done_old2 <= done_pressing; IF done_old2 = '0' AND done_pressing = '1' THEN done_rise2 <= '1'; END IF; --Daten in den RAM schreiben, wenn eine Taste betätigt wurde und diese Taste KEIN "Enter" war IF (done_rise2 = '1' OR state > 0) AND token /= "11000000000000" AND word_state = 0 THEN CASE state IS --Datens in den RAM schreiben und Speicheradresse inkrementieren WHEN 0 => read_write <= '1'; RAM_IN <= "00000000" & token; state := 1; WHEN 1 => read_write <= '0'; mem_addr <= mem_addr + 1; mem_max <= mem_max + 1; state := 0; WHEN OTHERS => END CASE; --Token-Signal in Token_Word-Signal übertragen, wenn eine Taste gedrückt wurde und diese Taste ein "Enter" war ELSIF done_rise2 = '1' AND token = "11000000000000" THEN token_word(13 DOWNTO 0) <= token; --Datenworte aus dem RAM zurücklesen und anschließend nacheinander in Morsesignale codieren ELSIF (token_word(13 DOWNTO 0) = "11000000000000" OR mem_addr > 279) OR word_state > 0 THEN CASE word_state IS --Einmalig beim Eintritt in diesen Fall soll die Speicheradresse auf Null gesetzt werden --um von Anfang an die Werte aus dem Speicher auszulesen WHEN 0 => mem_addr <= 0; read_write <= '0'; token_word(13 DOWNTO 0) <= RAM_OUT(13 DOWNTO 0); word_state := 1; --Birpaarweises Auslesen der einzelnen Datenworte mit anschließender Inkrementierung der Speicher- / Leseadresse WHEN 1 => IF double >= 0 AND double < 14 THEN IF token_word(double + 1 DOWNTO double) = "01" THEN --Codierung eines "Dits" als Signal mit doppelter Periodendauer der Wortgeschwindigkeit IF cnt >= 2 THEN cnt <= 0; sound <= '0'; double := double + 2; ELSE cnt <= cnt + 1; sound <= '1'; END IF; ELSIF token_word(double +1 DOWNTO double) = "11" THEN --Codierung eines "Dahs" als Signal mit sechsfacher Periodendauer der Wortgeschwindigkeit --(3-fache Dit-Länge) IF cnt >= 6 THEN cnt <= 0; sound <= '0'; double := double + 2; ELSE cnt <= cnt + 1; sound <= '1'; END IF; ELSIF token_word(13 DOWNTO 0) = "10000000000000" THEN --Prüfen ob das Tokenwort ein Leerzeichen repräsentiert --In kombination mit dem cnt = 6 von "double >= 14" ergibt sich eine Länge von 7 "Dits"! => Pause zwischen Worten IF cnt >= 8 THEN cnt <= 0; sound <= '0'; double := 14; state2 := 0; ELSE cnt <= cnt + 1; END IF; --wird wieder ein "Enter" aus dem Speicher ausgelesen ist man am Ende der Übertragung angekommen ELSIF token_word(13 DOWNTO 0) = "11000000000000" THEN sound <= '0'; word_state := 2; --ist die aktuelle Leseadresse größer-gleich der maximalen Adresse in die beim Schreiben gespeichert wurde, --so ist die Übertragung ebenfalls beendet ELSIF mem_addr >= mem_max THEN sound <= '0'; word_state := 2; --wenn im Datenwort nur noch Nullen stehen muss die Leseadresse inkrementiert und anschließend das neue Datenwort ausgelesen werden ELSIF token_word(double +1 DOWNTO double) = "00" AND token_word(13 DOWNTO 0) /= "11000000000000" AND token_word(13 DOWNTO 0) /= "10000000000000" THEN sound <= '0'; cnt <= 0; double := 14; END IF; END IF; --Wenn das Datenwort zuende analysiert wurde, wird die Leseadresse inkrementiert und das nächste Datenwort ausgelesen IF double >= 14 THEN IF cnt >= 6 THEN cnt <= 0; sound <= '0'; double := 0; mem_addr <= mem_addr + 1; token_word(13 DOWNTO 0) <= RAM_OUT(13 DOWNTO 0); ELSE cnt <= cnt + 1; read_write <= '0'; END IF; END IF; --Wenn der SPeicher komplett ausgelesen wurde, dann wird der Speicher durch einen Software-Reset --wieder geleert (siehe Prozess: Assignment) WHEN OTHERS => soft_reset <= '1'; IF cnt >= 6 THEN cnt <= 0; sound <= '0'; double := 0; word_state := 0; mem_max <= 0; mem_addr <= 0; cnt <= 0; read_write <= '0'; sound <= '0'; double := 0; token_word <= (OTHERS => '0'); ELSE cnt <= cnt + 1; read_write <= '1'; RAM_IN <= (Others => '0'); END IF; END CASE; END IF; END IF; END IF; --Ist das Token-Signal komplett ausgelesen worden und eine neue Taste wurde gedrückt, --dann soll das bitpaarweise Auslesen erneut beginnen IF double >= 14 AND (done_rise = '1' AND word = '0') THEN double := 0; END IF; --Ausgabe der Speicheradresse auf einigen der LEDs mem_addr_leds <= STD_ULOGIC_VECTOR(TO_UNSIGNED(mem_addr,8)); END PROCESS; END structure;