RF Wireless World

Browse articles, tutorials, tools, and vendors.

VHDL Code for Elevator Operation Simulation

By RF Wireless Expert Team

This document provides VHDL code for simulating the operation of an elevator.

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
    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
                col <= "0001";
                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
                col <= "0010";
                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
                col <= "0100";
                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
                col <= "1000";
                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;
                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;
                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;

Explore VHDL Hardware Interfaces & Controllers

Continue Learning VHDL

Keep Reading