====== LAB 5: A Decoder ====== ===== Synopsis ===== The camera has a different button for each exposure time, i.e. the data signals from the keypad are transferred via a 10-bit data bus. If a button is pressed, the corresponding wire is set to 1. The exposure times are calculated according to the following formula: time(button) = 2^(-button), for button=0..9 (time in seconds). The result (1/1 s, 1/2 s, 1/4 s, ..., 1/512 s) shall be shown on the 7-segment display. Thus, another decoder is needed. We will not introduce any new VHDL concepts in this exercise but suggest to try out different implementations and to observe their impact on the synthesis result. The block diagram of the new module is rather simple. {{:vhdl_workshop:workshop_decoder.svg?nolink&350|The keypad decoder}} ==== Behaviour ==== As already mentioned, the functionality of this module is fairly simple. The denominator of the following calculation shall be coded in a suitable form for the 7-segment display. 2^(-button) = 1 / (2^(button) ) = 1/1, 1/2, 1/4, 1/8, ..., 1/512 (button = 0..9) It is up to you to decide about the behaviour when more than one button is pressed. There are basically two options: Either the buttons have a certain priority, or the user input is ignored. ==== Data types ==== The input data is generated by an external keypad and consists of 10 wires, one per button. Thus a **std_ulogic_vector** is used for the KEYPAD signal. The decoded values shall be processed by the display logic, i.e. **T_DIGITS** is the most suitable data type. ==== To do ==== * Create new files for the decoder entity and its architectures if you want to try out different implementations. Remember that synthesis tools ignore the VHDL configuration and use the most recent architecture. * Generate a testbench for the new design and add stimuli that cover "illegal" user input (more than one button pressed simultaneously). * Compile the VHDL code (package->entity->architectures->configurations). * Simulate the configurations and look out for differences in the behaviour. * Synthesize the architectures and find out about their area and maximum delay from input to output. ===== Implementation ===== architecture RTL_CASE of DECODER is begin process(KEYPAD) begin case KEYPAD is when "1000000000" => KEY <= …; when "0100000000" => KEY <= … ; when "0010000000" => KEY <= … ; when "0001000000" => KEY <= … ; when "0000110000" => KEY <= … ; … when "0000000001" => KEY <= … ; end case; end process; end RTL_CASE; architecture RTL_IF of DECODER is begin architecture process(KEYPAD) begin process if KEYPAD(0) = '1' then KEY <= … ; elsif KEYPAD(1) = '1' then KEY <= … ; elsif KEYPAD(2) = '1' then KEY <= … ; elsif KEYPAD(3) = '1' then KEY <= … ; elsif KEYPAD(4) = '1' then KEY <= … ; … elsif KEYPAD(9) = '1' then KEY <= … ; else KEY <= … ; end if; end process; end RTL_IF; use work.P_DISPLAY.all; entity DECODER is port (KEYPAD : in std_ulogic_vector(9 downto 0); KEY : out T_DIGITS); end DECODER; ===== Testbench ===== library ieee; use ieee.std_logic_1164.all; use work.P_DISPLAY.all; entity TB_DECODER is end TB_DECODER; architecture TEST of TB_DECODER is component DECODER port (KEYPAD : in std_ulogic_vector (9 downto 0); KEY : out T_DIGITS); end component; signal W_KEYPAD : std_ulogic_vector (9 downto 0); signal W_KEY : T_DIGITS; begin DUT : DECODER port map (KEYPAD => W_KEYPAD, KEY => W_KEY); STIMULI : process begin W_KEYPAD <= "1000000000"; -- KEY = (5,1,2) (this works in both architectures!!) wait for 20 ns; W_KEYPAD <= "1111100000"; -- KEY = (0,3,2) (if) -- (0,0,0) (case) wait for 20 ns; W_KEYPAD <= "0000100000"; -- KEY = (0,3,2) (both architectures) wait for 20 ns; for I in 9 downto 0 loop W_KEYPAD <= (others => '0'); W_KEYPAD(I) <= '1'; -- KEY = (5,1,2),(2,5,6),(1,2,8),(0,6,4),(0,3,2), -- (0,1,6),(0,0,8),(0,0,4),(0,0,2),(0,0,1) -- (both architectures) wait for 20 ns; end loop; wait; end process STIMULI; end TEST; configuration CFG_TB_DECODER of TB_DECODER is for TEST end for; end CFG_TB_DECODER; ===== Package ===== {{page>.:package}}