Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Practice Problem 1: Suppose you are employed in a company and on a very first da

ID: 2248304 • Letter: P

Question

Practice Problem 1: Suppose you are employed in a company and on a very first day you
have been given a task to design an elevator using FPGA that covers three floors, Ground
floor, First floor and Second floor. The elevator is initially assumed to be at the ground floor
with its door open. If a destination is given from the ground floor, the destination indicator of
that floor is turned on and the door closes. When the elevator reaches the destination, the door
opens and the indicator turns off. If the elevator is called from another floor, the door closes
and the call indicator of the floor calling is turned on. The elevator takes 3secs to move from
one floor to the next.

NOTE:
Can you please write above design in Verilog HDL so that your boss can tell Software to
synthesize circuit?

Explanation / Answer

Library IEEE;

use IEEE.std_logic_1164.all;

use IEEE.STD_LOGIC_UNSIGNED.all;

USE WORK.LCD_GRAP.ALL;

entity elevator is

generic(bits : integer := 8 ); -- number of bits used for duty cycle.

-- Also determines pwm period.

port ( CLK: in STD_LOGIC; -- 4 MHz clock

RESET,EN: in STD_LOGIC; -- master reset pin

lcd_rw : out std_logic;

pwm : out std_logic_VECTOR(1 DOWNTO 0);

lcd_select : out std_logic;

lcd_enable : out std_logic;

ROW: in STD_LOGIC_VECTOR(0 to 3); -- this are the row lines

lcd_data: out STD_LOGIC_VECTOR (7 downto 0); -- gives registered data output

COL: inout STD_LOGIC_VECTOR(0 to 3));

end elevator;

architecture rtl of elevator is

signal counter : std_logic_vector(bits - 1 downto 0):="00000000";

type KEYPAD_STATE_TYPE is (WAIT_R_0, C3, C2, C1, C0, FOUND, SAMPLE,

WAIT_R_1);

-- state names

TYPE STATE_TYPE IS (initial,display,clear,location,putchar);

SIGNAL state,next_state: STATE_TYPE;

-- Clear screen.

constant CLR: std_logic_vector(7 downto 0) := "00000001";

-- Display ON, without cursor.

constant DON: std_logic_vector(7 downto 0) := "00001100";

-- Function set for 8-bit data transfer and 2-line display

constant SET: std_logic_vector(7 downto 0) := "00111000";

--frequency divider

constant big_delay: integer :=16;

constant small_delay: integer :=2;

constant reg_setup: integer :=1;

signal CS, NS: KEYPAD_STATE_TYPE; -- signals for current and next states

signal duty_cycle,duty_cycle1 : std_logic_vector(bits - 1 downto 0);

signal DIV_REG: STD_LOGIC_VECTOR (22 downto 0); -- clock divide register

signal DCLK,DDCLK: STD_LOGIC; -- this has the divided clock.

signal COL_REG_VALUE: STD_LOGIC_VECTOR (0 to 3);

signal R1,CLK_D,START,STOP: STD_LOGIC; -- row detection signal

signal KEY_VALUE1,FLOOR,KEY_VALUE: integer range 0 to 15;

signal DATA,data1,FLOOR_NUM: STD_LOGIC_VECTOR (7 downto 0);

signal TEMP1,TEMP2,TEMP3,TEMP4: STD_LOGIC_VECTOR (7 downto 0);

signal TEMP5,TEMP6,TEMP7,TEMP8: STD_LOGIC_VECTOR (7 downto 0);

begin

--CLK_OUT <= DCLK;

R1 <= ROW(3) or ROW(2) or ROW(1) or ROW(0);

---------------------------- BEGINING OF FSM1 (KEYPAD SCANNER) ---------------------

SYNC_PROC: process (DCLK, RESET, KEY_VALUE) -- This is the synchronous part

begin

if (RESET = '0') then -- you must have a reset for fsm to synthesize properly

CS <= WAIT_R_0;

elsif (DCLK'event and DCLK = '1') then

CS <= NS;

end if; end process;

COMB_PROC: process (CS, R1, COL_REG_VALUE) -- This is the combinational part

begin

case CS is

when WAIT_R_0 => -- waits till a button is pressed

COL <= "1111"; -- keep all columns activated

if R1 = '1' then -- a button was pressed. but which one?

NS <= C3; -- let's find out

else

NS <= WAIT_R_0;

end if;

---------------------------------------------------------------------------------------------------

when C3 => --

COL <= "0001"; -- activate column 3

if R1 = '0' then -- this means button was not in column 3

NS <= C2; -- so check if it was in column 2

Else NS <= FOUND; -- button was in column 3

end if;

---------------------------------------------------------------------------------------------------

when C2 => --

COL <= "0010"; -- activate column 2

if R1 = '0' then -- this means button was not in column 2

NS <= C1; -- so check if it was in column 1

else

NS <= FOUND; -- button was in column 2

end if;

---------------------------------------------------------------------------------------------------

when C1 => --

COL <= "0100"; -- activate column 1

if R1 = '0' then -- this means button was not in column 1

NS <= C0; -- so check if it was in column 0

else

NS <= FOUND; -- button was in column 1

end if;

---------------------------------------------------------------------------------------------------

when C0 => --

COL <= "1000"; -- activate column 0

if R1 = '0' then -- this means button was not in column 0 ??

NS <= WAIT_R_0; -- so the button must have been depressed fast

else

NS <= FOUND; -- button was in column 3

end if;

---------------------------------------------------------------------------------------------------

when FOUND => --

COL <= COL_REG_VALUE;

if R1 = '0' then -- this means button is depressed

NS <= WAIT_R_0; -- so go back to initial state

else

NS <= SAMPLE; -- otherwise write the key value to DATA register

end if;

---------------------------------------------------------------------------------------------------

when SAMPLE => -- this state will generate a signal with one clock period for sampling

COL <= COL_REG_VALUE;

NS <= WAIT_R_1; -- otherwise wait till button is pressed

---------------------------------------------------------------------------------------------------

when WAIT_R_1 => --

COL <= COL_REG_VALUE;

if R1 = '0' then -- this means button was depressed

NS <= WAIT_R_0; -- so go back to initial state

else

NS <= WAIT_R_1; -- otherwise wait till button is pressed

end if;

---------------------------------------------------------------------------------------------------

end case;

end process;

---------------------------------------------------------------------------------------------------

WRITE_DATA: process (DCLK, CS, KEY_VALUE) -- write valid data to register

begin

if DCLK'event and DCLK = '0' then -- on the falling edge

if CS = FOUND then

KEY_VALUE <= KEY_VALUE1;

end if;

end if;

end process; -- WRITE_DATA

---------------------------------------------------------------------------------------------------

COL_REG: process (DCLK, CS, COL) -- this is the column value register

begin

if (DCLK'event and DCLK = '0') then -- register the COL value on the falling edge

if (CS = C3 or CS = C2 or CS = C1 or CS = C0) then -- provided we're in states C3 thru

C0 only

COL_REG_VALUE <= COL; -- otherwise the column value is not valid

end if;

end if;

end process; -- COL_REG

---------------------------------------------------------------------------------------------------

DECODER: process(ROW, COL_REG_VALUE) -- decodes binary value of pressed key

from row and

column

variable CODE: STD_LOGIC_VECTOR (0 to 7);

begin

CODE := (ROW & COL_REG_VALUE);

case CODE is

-- COL

-- ROW 0 0123

when "00010001" => KEY_VALUE1 <= 0;

when "00010010" => KEY_VALUE1 <= 1;

when "00010100" => KEY_VALUE1 <= 2;

when "00011000" => KEY_VALUE1 <= 3;

-- ROW 1

when "00100001" => KEY_VALUE1 <= 4;

when "00100010" => KEY_VALUE1 <= 5;

when "00100100" => KEY_VALUE1 <= 6;

when "00101000" => KEY_VALUE1 <= 7;

-- ROW 2

when "01000001" => KEY_VALUE1 <= 8;

when "01000010" => KEY_VALUE1 <= 9;

when "01000100" => KEY_VALUE1 <= 10;

when "01001000" => KEY_VALUE1 <= 11;

-- ROW 3

when "10000001" => KEY_VALUE1 <= 12;

when "10000010" => KEY_VALUE1 <= 13;

when "10000100" => KEY_VALUE1 <= 14;

when "10001000" => KEY_VALUE1 <= 15;

when others => KEY_VALUE1 <= 0;

end case;

end process; -- DECODER

---------------------------- END OF FSM1 (KEYPAD SCANNER) -----------------------------

-- select the appropriate lines for setting frequency

CLK_DIV: process (CLK, DIV_REG) -- clock divider

begin

if (CLK'event and CLK='1') then

DIV_REG <= DIV_REG + 1;

end if;

end process;

DCLK <= div_reg(8);

DDCLK<=DIV_REG(10);

CLK_D<=DIV_REG(22);

---------------------------- END OF CLOCK DIVIDER -------------------------------------------

lcd_rw<='0';

process (DDclk,rEsEt)

variable count: integer range 0 to big_delay;

variable c1 : std_logic_vector(7 downto 0);

begin

IF rEsEt = '0' THEN

state<=initial;

count:=0;

lcd_enable<='0';

lcd_select<='0';

c1 := "01111111";

elsIF DDclk'EVENT AND DDclk = '1' THEN

case state is

WHEN initial => -- to set the function

if count=reg_setup then

lcd_enable<='1';

else lcd_enable<='0';

end if;

lcd_data<=SET;

lcd_select<='0';

if count=small_delay then

state<=display;

count:=0;

else count:=count+1;

end if;

WHEN display => -- to set display on

if count=reg_setup then

lcd_enable<='1';

else lcd_enable<='0';

end if;

lcd_data<=DON;

lcd_select<='0';

if count=small_delay then

state<=clear;

count:=0;

else count:=count+1;

end if;

WHEN clear => -- clear the screen

if count=reg_setup then

lcd_enable<='1';

else lcd_enable<='0';

end if;

lcd_data<=CLR;

lcd_select<='0';

if count=big_delay then

state<=location;

count:=0;

else count:=count+1;

end if;

WHEN location => -- clear the screen

if count=reg_setup then

lcd_enable<='1';

else lcd_enable<='0';

end if;

IF COUNT=0 THEN

if c1="10001111" then

c1:="11000000";

elsif c1="11001111" then

c1:="10000000";

else c1:=c1+'1';

end if;

END IF;

lcd_data <= c1;

lcd_select<='0';

if count=big_delay then

state<=putchar;

count:=0;

else count:=count+1;

end if;

when putchar=> -- display the character on the LCD

if count=reg_setup then

lcd_enable<='1';

else lcd_enable<='0';

end if;

case c1 is

when "10000000" => lcd_data<= F ;--SIGLE LINE

when "10000001" => lcd_data<= L ;--SIGLE LINE

when "10000010" => lcd_data<= O ;--SIGLE LINE

when "10000011" => lcd_data<= O ;--SIGLE LINE

when "10000100" => lcd_data<= R ;--SIGLE LINE

when "10000101" => lcd_data<= SPACE ;--SIGLE LINE

when "10000110" => lcd_data<= N ;--SIGLE LINE

when "10000111" => lcd_data<= U ;--SIGLE LINE

when "10001000" => lcd_data<= M ;

when "10001001" => lcd_data<= B ;

when "10001010" => lcd_data<= E ;

when "10001011" => lcd_data<= R ;

when "10001100" => lcd_data<= SPACE ;

when "10001101" => lcd_data<= EQUAL ;

when "10001110" => lcd_data<= FLOOR_NUM ;

when "10001111" => lcd_data<= SPACE;

when "11000000" => lcd_data<= S ;--SIGLE LINE

when "11000001" => lcd_data<= T ;--SIGLE LINE

when "11000010" => lcd_data<= A ;--SIGLE LINE

when "11000011" => lcd_data<= T ;--SIGLE LINE

when "11000100" => lcd_data<= U ;--SIGLE LINE

when "11000101" => lcd_data<= S ;--SIGLE LINE

when "11000110" => lcd_data<= SPACE ;--SIGLE LINE

when "11000111" => lcd_data<= TEMP1 ;--SIGLE LINE

when "11001000" => lcd_data<= TEMP2 ;

when "11001001" => lcd_data<= TEMP3 ;

when "11001010" => lcd_data<= TEMP4 ;

when "11001011" => lcd_data<= SPACE ;

when "11001100" => lcd_data<= TEMP5 ;

when "11001101" => lcd_data<= TEMP6 ;

when "11001110" => lcd_data<= TEMP7 ;

when "11001111" => lcd_data<= TEMP8 ;

when others => NULL;

end case ;

lcd_select<='1';

if count=small_delay then

state<=location;

count:=0;

else count:=count+1;

end if; end case; end if; end process;

PROCESS(CLK_D,RESET)

VARIABLE COU : STD_LOGIC_VECTOR(1 DOWNTO 0);

VARIABLE START,STOP: STD_LOGIC; -- row detection signal

BEGIN

IF RESET='0' THEN

COU:="00";

TEMP1 <= L ;

TEMP2 <= I ;

TEMP3 <= F ;

TEMP4 <= T ;

TEMP5 <= I ;

TEMP6 <= D ;

TEMP7 <= L ;

TEMP8 <= E ;

FLOOR_NUM <= ZERO ;

ELSIF RISING_EDGE(CLK_D) THEN

CASE KEY_VALUE IS

WHEN 0 => FLOOR_NUM <= ZERO ;

FLOOR <=0;

WHEN 1 => FLOOR_NUM <= ONE ;

FLOOR <=1;

WHEN 2 => FLOOR_NUM <= TWO ;

FLOOR <=2;

WHEN 3 => FLOOR_NUM <= THREE ;

FLOOR <=3;

WHEN 4 =>

TEMP1 <= D ;

TEMP2 <= O ;

TEMP3 <= O ;

TEMP4 <= R ;

TEMP5 <= O ;

TEMP6 <= P ;

TEMP7 <= E ;

TEMP8 <= N ;

WHEN 5 =>

TEMP1 <= D ;

TEMP2 <= O ;

TEMP3 <= O ;

TEMP4 <= R ;

TEMP5 <= C ;

TEMP6 <= L ;

TEMP7 <= O ;

TEMP8 <= S ;

WHEN 6 =>

START:='1';

STOP:='0';

WHEN 7 =>

STOP:='1';

START:='0';

WHEN OTHERS =>

TEMP1 <= I ;

TEMP2 <= D ;

TEMP3 <= L ;

TEMP4 <= E ;

TEMP5 <= K ;

TEMP6 <= E ;

TEMP7 <= Y ;

TEMP8 <= SPACE ;

END CASE;

IF START='1' THEN

IF COU=FLOOR THEN

START := '0';

COU:=COU;

TEMP7 <= "001100" & COU ;

ELSIF COU<=FLOOR THEN

COU:=COU + '1';

TEMP1 <= U ;

TEMP2 <= P ;

TEMP3 <= SPACE ;

TEMP4 <= SPACE ;

TEMP5 <= SPACE ;

TEMP6 <= "01111110" ;

TEMP7 <= "001100" & COU ;

TEMP8 <= SPACE ;

ELSIF COU>=FLOOR THEN

COU:=COU-'1';

TEMP1 <= D ;

TEMP2 <= O ;

TEMP3 <= W ;

TEMP4 <= N ;

TEMP5 <= SPACE ;

TEMP6 <= "01111111" ;

TEMP7 <= "001100" & COU ;

TEMP8 <= SPACE ;

END IF; END IF; END IF;

END PROCESS;

end rtl;

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote