1 ------------------------------------------------------------------------------- 3 --! @author Hipolito Guzman-Miranda 4 --! @brief Emulates a Digilent PMOD keypad 5 ------------------------------------------------------------------------------- 7 --! Use IEEE standard definitions library 9 --! Use std_logic* signal types 10 use ieee.std_logic_1164.
all;
11 --! Use the slv2string function 14 --! @brief Emulates PMOD keypad 16 --! @details Propagates inputs from \c keypad_columns into \c keypad_rows, 17 --! according to the bits of \c pressed_keys, which is a vector that has 1 bit 18 --! for each key in the keypad. Please read the detailed description of the 19 --! architecture to understand which bit of the vector maps to each key. 22 VERBOSE : := false --! If true, log changes in the \c pressed_keys vector, apart from the changes in the individual keys. Also log which row is connected to which column when a key is pressed. 25 keypad_rows : out (3 downto 0);
--! This is the signal that must be read from the keypad 26 keypad_columns : in (3 downto 0);
--! Connect here the signal that drives the keypad 27 pressed_keys : in (15 downto 0) --! One bit for each key. Set to '1' to emulate key press, set to '0' to emulate key release 31 --! @brief Architecture is based on multiple concurrent assignments to the same 32 --! signal, but some of the drivers are weak (pullups), just like the real 36 --! Each pressed key connects a row to a column, so we have a second driver 37 --! for rows here. If multiple keys are pressed, we may have 38 --! multiple strong drivers with different values for the same column, 39 --! depending on what values the user puts in the rows, which 40 --! could result in an 'X' in simulation. In the hardware, the internal 41 --! resistances avoid a short-circuit, but the resulting value is not 44 --! The keys in the physical keyboard are: 46 --! | | Col0 | Col1 | Col2 | Col3 | 47 --! |------|------|------|------|------| 48 --! | Row0 | 1 | 2 | 3 | A | 49 --! | Row1 | 4 | 5 | 6 | B | 50 --! | Row2 | 7 | 8 | 9 | C | 51 --! | Row3 | 0 | F | E | D | 53 --! (Please note that Digilent's schematics are slightly outdated and do not 54 --! reflect the actual key layout. The correct key layout is in the table 57 --! The correspondence, for this simulation model, between the keys and the 58 --! bits in the \c pressed_keys input is: 60 --! pressed_keys(i) to Row/Col/Key 62 --! | i | Row | Col | Key | 63 --! |-----|-------|-------|-------| 74 --! | 10 | 2 | 2 | 9 | 75 --! | 11 | 2 | 3 | C | 76 --! | 12 | 3 | 0 | 0 | 77 --! | 13 | 3 | 1 | F | 78 --! | 14 | 3 | 2 | E | 79 --! | 15 | 3 | 3 | D | 84 signal last_pressed_keys : (15 downto 0);
86 -- This array allows converting a key position to the char representation 87 -- of the pressed button. This way, the simulation logs can show which 88 -- button is pressed or released. 89 type char_vector is array (0 to 15) of ;
90 constant keypad_table : char_vector := ('1', '2', '3', 'A', 97 -- The keypad connects all rows to a pullup, so emulate this 100 -- To implement that each key press connects a specific column to a specific 101 -- row, we just have to take into account that, according the to previous 102 -- table, Row is i/4 and Col is i mod 4 105 -- Store last values so we know if a key press is new or not 107 -- Avoid 'U' in outputs 112 report "pressed_keys: " & slv2string(pressed_keys) & " last_pressed_keys: " & slv2string(last_pressed_keys);
116 -- Implement key presses 117 for i in 0 to 15 loop 121 report "Key in position " & 'image(i) & " (" & keypad_table(i) & ")" & " pressed, connecting column " & 'image(i mod 4) & " to row " & 'image(i/4);
126 -- Report key presses in the simulation log 129 report "Key in position " & 'image(i) & " (" & keypad_table(i) & ")" & " pressed. Current value: " & 'image(pressed_keys(i)) & ", last value: " & 'image(last_pressed_keys(i));
131 report "Key in position " & 'image(i) & " (" & keypad_table(i) & ")" & " released. Current value: " & 'image(pressed_keys(i)) & ", last value: " & 'image(last_pressed_keys(i));
133 report "Key in position " & 'image(i) & " (" & keypad_table(i) & ")" & " set to a value different than '0' or '1', check testbench. Current value: " & 'image(pressed_keys(i)) & ", last value: " & 'image(last_pressed_keys(i));
VERBOSEboolean := false
If true, log changes in the pressed_keys vector, apart from the changes in the individual keys...
Common datatypes and component declarations.
in keypad_columnsstd_logic_vector( 3 downto 0)
Connect here the signal that drives the keypad.
_library_ ieeeieee
Use IEEE standard definitions library.
keypad_emu
Connect here the TX signal from your design.
in pressed_keysstd_logic_vector( 15 downto 0)
One bit for each key. Set to '1' to emulate key press, set to '0' to emulate key release.
out keypad_rowsstd_logic_vector( 3 downto 0)
This is the signal that must be read from the keypad.