VHDL-verification
Package to ease directed testing of HDL entities
keypad_emu.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 --! @file
3 --! @author Hipolito Guzman-Miranda
4 --! @brief Emulates a Digilent PMOD keypad
5 -------------------------------------------------------------------------------
6 
7 --! Use IEEE standard definitions library
8 library ieee;
9 --! Use std_logic* signal types
10 use ieee.std_logic_1164.all;
11 --! Use the slv2string function
12 use work.vhdl_verification.all;
13 
14 --! @brief Emulates PMOD keypad
15 --!
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.
20 entity keypad_emu is
21  generic (
22  VERBOSE : boolean := 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.
23  );
24  port (
25  keypad_rows : out std_logic_vector(3 downto 0); --! This is the signal that must be read from the keypad
26  keypad_columns : in std_logic_vector(3 downto 0); --! Connect here the signal that drives the keypad
27  pressed_keys : in std_logic_vector(15 downto 0) --! One bit for each key. Set to '1' to emulate key press, set to '0' to emulate key release
28  );
29 end keypad_emu;
30 
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
33 --! hardware
34 --!
35 --! @detailed
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
42 --! defined.
43 --!
44 --! The keys in the physical keyboard are:
45 --!
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 |
52 --!
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
55 --! above)
56 --!
57 --! The correspondence, for this simulation model, between the keys and the
58 --! bits in the \c pressed_keys input is:
59 --!
60 --! pressed_keys(i) to Row/Col/Key
61 --!
62 --! | i | Row | Col | Key |
63 --! |-----|-------|-------|-------|
64 --! | 0 | 0 | 0 | 1 |
65 --! | 1 | 0 | 1 | 2 |
66 --! | 2 | 0 | 2 | 3 |
67 --! | 3 | 0 | 3 | A |
68 --! | 4 | 1 | 0 | 4 |
69 --! | 5 | 1 | 1 | 5 |
70 --! | 6 | 1 | 2 | 6 |
71 --! | 7 | 1 | 3 | B |
72 --! | 8 | 2 | 0 | 7 |
73 --! | 9 | 2 | 1 | 8 |
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 |
80 --!
81 
82 architecture keypad_emu_arch of keypad_emu is
83 
84  signal last_pressed_keys : std_logic_vector(15 downto 0);
85 
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 character;
90  constant keypad_table : char_vector := ('1', '2', '3', 'A',
91  '4', '5', '6', 'B',
92  '7', '8', '9', 'C',
93  '0', 'F', 'E', 'D');
94 
95 begin
96 
97  -- The keypad connects all rows to a pullup, so emulate this
98  keypad_rows <= (others => 'H');
99 
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
103  process(pressed_keys, keypad_columns)
104  begin
105  -- Store last values so we know if a key press is new or not
106  last_pressed_keys <= pressed_keys;
107  -- Avoid 'U' in outputs
108  keypad_rows <= (others => 'H');
109 
110  if VERBOSE then
111  if pressed_keys'event then
112  report "pressed_keys: " & slv2string(pressed_keys) & " last_pressed_keys: " & slv2string(last_pressed_keys);
113  end if;
114  end if;
115 
116  -- Implement key presses
117  for i in 0 to 15 loop
118  if pressed_keys(i) = '1' then
119  if VERBOSE then
120  if pressed_keys'event then
121  report "Key in position " & integer'image(i) & " (" & keypad_table(i) & ")" & " pressed, connecting column " & integer'image(i mod 4) & " to row " & integer'image(i/4);
122  end if;
123  end if;
124  keypad_rows(i/4) <= keypad_columns(i mod 4);
125  end if;
126  -- Report key presses in the simulation log
127  if pressed_keys(i) /= last_pressed_keys(i) then
128  if pressed_keys(i) = '1' then
129  report "Key in position " & integer'image(i) & " (" & keypad_table(i) & ")" & " pressed. Current value: " & std_logic'image(pressed_keys(i)) & ", last value: " & std_logic'image(last_pressed_keys(i));
130  elsif pressed_keys(i) = '0' then
131  report "Key in position " & integer'image(i) & " (" & keypad_table(i) & ")" & " released. Current value: " & std_logic'image(pressed_keys(i)) & ", last value: " & std_logic'image(last_pressed_keys(i));
132  else
133  report "Key in position " & integer'image(i) & " (" & keypad_table(i) & ")" & " set to a value different than '0' or '1', check testbench. Current value: " & std_logic'image(pressed_keys(i)) & ", last value: " & std_logic'image(last_pressed_keys(i));
134  end if;
135  end if;
136  end loop;
137  end process;
138 
139 end keypad_emu_arch;
Emulates PMOD keypad.
Definition: keypad_emu.vhd:20
VERBOSEboolean := false
If true, log changes in the pressed_keys vector, apart from the changes in the individual keys...
Definition: keypad_emu.vhd:23
Common datatypes and component declarations.
in keypad_columnsstd_logic_vector( 3 downto 0)
Connect here the signal that drives the keypad.
Definition: keypad_emu.vhd:26
_library_ ieeeieee
Use IEEE standard definitions library.
Definition: datawrite.vhd:8
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 &#39;1&#39; to emulate key press, set to &#39;0&#39; to emulate key release.
Definition: keypad_emu.vhd:28
out keypad_rowsstd_logic_vector( 3 downto 0)
This is the signal that must be read from the keypad.
Definition: keypad_emu.vhd:25