VHDL Code for Elevator Operation Simulation

vhdl
elevator
simulation
code
finite state machine

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;