VHDL Code for Elevator Operation Simulation
Advertisement
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;