De-bounced button press resulting in successive state transitions - vhdl

I am programming an FPGA that uses push buttons as input signals. It has a finite state machine with 11 states that transition from state to state using specific button presses.
For example, in my design, state s0 goes to state s1 using a button press. This is the same transition case from state s1 to s2 and from state s2 to s3. This state transition system is implemented in my VHDL code using case statements.
LEDs light up in each state to keep track of which state the board is currently in.
My issue is that when my_btnL = '1' is true while in state s0, the board shows that it has moved to state s3.
What I think is happening is that it is indeed going to state s1 and s2 but the same button press in state s0 is also being read in state s1 and s2. This happens so fast that the boards doesn't have enough time to show the LED indications for state s1 and s2. It stops at state s3 because state s3 moves to state s4 using a different button.
So my question is how do I make the button press signal have a rising edge and a falling edge such that a single button press is read only in one state and not the ones that follow it?
The press button signals are de-bounced but this only makes the signal a uniform square wave.
In the following code btnC, btnL, btnR,... are the push buttons:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity digital_lock is
Port (
my_btnC, clk, my_btnU, my_btnR, my_btnL, my_btnD: in std_logic;
my_sw: in std_logic_vector(3 downto 0);
hex0, hex1, hex2, hex3: out std_logic_vector (3 downto 0);
my_led: out std_logic_vector(15 downto 0)
);
end digital_lock;
architecture Behavioral of digital_lock is
type state IS (s0, s1, s2, s3, s4 ,s5 ,s6, s7, s8, s9, s10,s11);
signal my_state: state;
signal my_status: unsigned(1 downto 0);
signal num1, num2, num3, key1, key2, key3: std_logic_vector(3 downto 0);
signal number, final_key: std_logic_vector(11 downto 0);
begin
FSM: process(clk, my_btnC)
begin
if(my_btnC ='1') then
my_state <= s0;
elsif rising_edge(clk) then
case my_state is
when s0 =>
my_status <= "00";
my_led <= "1100000000000000";
hex3 <= "0000";
hex2 <= "0000";
hex1 <= "0000";
hex0 <= "0000";
if(my_btnL ='1') then
my_state <= s1;
else
my_state <= s0;
end if;
when s1 =>
key1 <= my_sw;
hex0 <= key1;
my_led <= "0000000000000001";
if(my_btnL='1') then
my_state <= s2;
else
my_state <= s1;
end if;
when s2 =>
key2 <= my_sw;
hex0 <= key2;
my_led <= "0000000000000010";
if(my_btnL ='1') then
my_state <= s3;
else
my_state <= s2;
end if;
when s3 =>
key3 <= my_sw;
hex0 <= key3;
my_led <= "0000000000000011";
if(my_btnR= '1') then
my_state <= s4;
else
my_state <= s3;
end if;
when s4 =>
final_key(11 downto 8) <= key1;
final_key(7 downto 4) <= key2;
final_key(3 downto 0) <= key3;
my_led <= "0000000000000100";
if(my_btnU ='1') then
my_state <= s5;
else
my_state <= s4;
end if;
when s5 =>
num1 <= my_sw;
hex0 <= num1;
my_led <= "0000000000000101";
if(my_btnD ='1') then
my_state <= s0;
elsif (my_btnL ='1') then
my_state <= s6;
else
my_state <= s5;
end if;
when s6 =>
num2 <= my_sw;
hex0 <= num2;
my_led <= "0000000000000110";
if(my_btnD ='1') then
my_state <= s0;
elsif(my_btnL ='1') then
my_state <= s7;
else
my_state <= s6;
end if;
when s7 =>
num3 <= my_sw;
hex0 <= num3;
my_led <= "0000000000000111";
if(my_btnD ='1') then
my_state <= s0;
elsif(my_btnR = '1') then
my_state <= s8;
else
my_state <= s7;
end if;
when s8 =>
number(11 downto 8) <= num1;
number(7 downto 4) <= num2;
number(3 downto 0) <= num3;
my_led <= "0000000000001000";
if(number = final_key) then
my_state <= s9;
else
my_state <= s10;
end if;
when s9 =>
my_led <= "1111111111111111";
if(my_btnD = '1') then
my_state <= s0;
else
my_state <= s9;
end if;
when s10 =>
my_status <= my_status + 1;
if(my_status >= 3) then
my_state <= s11;
elsif(my_status < 3) then
my_state <= s5;
end if;
when s11 =>
my_led <= "0000000000000000";
hex0 <= "1111";
hex1 <= "1111";
hex2 <= "1111";
hex3 <= "1111";
my_state <= s11;
end case;
end if;
end process;
end Behavioral;

An edge detector for a de-bounced signal in the same clock domain as the state machine can be done with a flip flop with the signal input and a gate to detect the preferred state on the input (following the input edge) while the flip flop is in the other state.
signal my_btnL_event: std_logic;
signal my_btnLd: std_logic; -- architecture declarative items
process (clk)
begin
if rising_edge(clk) then
my_btnLd <= my_btnL;
end if;
my_btnL_event <= my_btnL and not my_btnLd;
Where you'd use my_btnL_event in place of my_btnL for transitioning between states.
Note this would require my_btnL to go invaid before going valid again assuming adequate de-bounce.
The my_btnL_event assignment could be expressed in multiple ways, such as an by an if statement or a conditional signal assignment.

Related

Can't find the issues and latches are generated

My code generates two latches, could please someone help me finding why?
According to Xilinx ISE latches are generated because of "try_counter" which is a counter for how many times you get a numeric sequence wrong. (which is the main point of my code).
I don't know what else to do.
entity moore is
Port ( badgeSx : in STD_LOGIC;
badgeDx : in STD_LOGIC;
col : in std_logic_vector (1 to 3);
row : in std_logic_vector (1 to 4);
clk : in std_logic;
rst : in std_logic;
unlock : out STD_LOGIC
);
end moore;
architecture Behavioral of moore is
type stato is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9);
signal current_state,next_state : stato;
signal badge : std_logic_vector(1 downto 0);
signal count, new_count: integer range 0 to 28;
signal temp_unlock : std_logic :='0';
signal timeover : std_logic :='0';
begin
badge <= badgeDx & badgeSx; --concatenazione dei badge
--processo sequenziale
current_state_register: process(clk)
begin
if rising_edge(clk) then
if (rst = '1') then
current_state <= s0;
count <= 0;
else
current_state <= next_state;
count <= new_count;
end if;
end if;
end process;
process (current_state,badge,col,row,timeover)
variable try_counter: integer range 0 to 3;
begin
case current_state is
when s0 =>
try_counter := 0;
temp_unlock <= '0';
unlock <='0';
if(badge ="01" and row = "0000" and col = "000" ) then
next_state <= s1;
else
next_state <= s0;
end if;
when s1 =>
temp_unlock <= '1';
unlock <= '0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s2;
elsif (timeover ='1' or badge = "10" or try_counter = 3) then
next_state <= s0;
else
next_state <= s1;
try_counter := try_counter +1;
end if;
when s2 =>
temp_unlock <= '0';
unlock <='0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s2;
else
next_state <= s3;
end if;
when s3 =>
temp_unlock <= '1';
unlock <= '0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s4;
elsif (timeover ='1' or badge = "10" or try_counter = 3) then
next_state <= s0;
else
next_state <= s1;
try_counter := try_counter +1;
end if;
when s4 =>
temp_unlock <= '0';
unlock <='0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s4;
else
next_state <= s5;
end if;
when s5 =>
temp_unlock <= '1';
unlock <= '0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s6;
elsif (timeover ='1' or badge = "10" or try_counter = 3) then
next_state <= s0;
else
next_state <= s1;
try_counter := try_counter +1;
end if;
when s6 =>
temp_unlock <= '0';
unlock <='0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s6;
else
next_state <= s7;
end if;
when s7 =>
temp_unlock <= '1';
unlock <= '0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s8;
elsif (timeover ='1' or badge = "10" or try_counter = 3) then
next_state <= s0;
else
next_state <= s1;
try_counter := try_counter +1;
end if;
when s8 =>
temp_unlock <= '0';
unlock <='0';
if (badge = "00" and col ="001" and row = "0001" and timeover = '0') then
next_state <= s8;
else
next_state <= s9;
end if;
when s9 =>
temp_unlock <= '0';
unlock <= '1';
if (badge = "10") then
next_state <= s0;
else
next_state <= s5;
end if;
when others =>
next_state <= s0;
end case;
end process;
Contatore_TIMER : process(temp_unlock,count)
begin
if temp_unlock = '1' then
if count = 28 then
new_count<=0;
timeover<='1';
else
new_count<=count+1;
timeover<='0';
end if;
else
new_count<=0;
timeover <= '0';
end if;
end process;
end Behavioral;
The code nearly works as expected (I mean it compiles and I don't get any error) but the RTL schematic isn't what it is supposed to be since it synthesises latches in the process.
In the apparently combinatorial process with process (current_state,badge,col,row,timeover), the variable try_counter is used to store information (sequential behaviour), which is only updated when process evaluation is triggered. This will very likely to generate the 2 latches, which matches the value range from 0 to 3 for try_counter.
To fix this, you can define try_counter as a signal, and include it in the sensitivity list for the process.
Having try_counter as a signal will also ease debugging, since the current state can easily be inspected in waveforms.

VHDL Test Bench working but incorrect results when run on FPGA

I am trying to write a program to detect if a given input is a prime number or not. When I run the test bench I get correct results however when I run it on the FPGA it only recognizes numbers that are divisible 3 or even as not prime. Any number such as 25 which is divisible by 5 will result in isPrime being 1. What could be causing this inconsistent result?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.std_logic_unsigned.all;
USE IEEE.numeric_std.all;
entity PrimeNumber is
Port ( clk: in std_logic;
rst : in std_logic;
input: in std_logic_vector(15 downto 0);
isPrime: out std_logic:= '0';
testOut: out std_logic_vector(31 downto 0)
);
end PrimeNumber;
architecture Behavioral of PrimeNumber is
SIGNAL current_state: std_logic_vector(2 downto 0);
signal next_state: std_logic_vector(2 downto 0):= "000";
signal max: integer;
signal temp: integer;
signal x: integer;
signal nextX:integer;
signal localPrime : std_logic:= '0';
signal current : integer;
signal update: std_logic := '0';
begin
nextX <= x +2;
process(current_state,input)
begin
case (current_state) is
when "000" => --Initial State
update <= '0';
localPrime <= '0';
if(input < x"0004")then
next_state <= "111";
else
max <= to_integer(unsigned(input(15 downto 1)));
current <=to_integer(unsigned(input));
if(input(0) = '0')then
next_state <= "110";
else
next_state <= "001";
end if;
end if;
when "001" => -- Computation State
localPrime <= '0';
temp <= current mod x;
if(x > max) then
next_state <= "111";
else
next_state <= "010";
end if;
update <= '1';
when "010" => -- Checking State
update <= '0';
localPrime <= '0';
if(temp = 0) then
next_state <= "110";
else
next_state <= "001";
end if;
when "110" =>
localPrime <= '0'; -- Not Prime State
next_state <= "110";
when "111" =>
update <= '0';
localPrime <= '1'; --Prime State
next_state <= "111";
when others =>
temp <= 0;
localPrime <= '0';
next_state <= "000";
end case;
end process;
Update_Registers: process(clk)
begin
if(clk'event and clk = '1') then
if ( rst = '1') then
current_state <= "000";
isPrime <= '0';
x<=3;
else
if(update = '1') then
x <= nextX;
end if;
current_state <= next_state;
isPrime <= localPrime;
end if;
end if;
end process;
end Behavioral;
To quickly check sim/syn mismatch, with the visibility you need outside of HW: output the mod result to a port, sim, should still "work"... syn, compile your (hopefully, verilog) netlist for TB, point to compiled netlist, sim, check the mod result against RTL/expected results.

Traffic VHDL simulation issues

I have updated the program, it does finish but now I am trying simulate the project. I am able to get the clock clear and lights on the pins, but I am not able to get the lights to work and count and states are not even showing. I believe I have this all set correctly but I could be wrong. Thank you once again Morten Zilmer for the help with the Error code.
http://tinypic.com/r/24yog0z/8
This is the simulation of the file,
entity traffic is
port (clk: in std_logic;
clr: in std_logic;
lights: out std_logic_vector (5 downto 0));
end traffic;
architecture traffic of traffic is
type state_type is (s0, s1, s2, s3, s4, s5);
signal state: state_type;
signal count : std_logic_vector (3 downto 0);
constant sec5: std_logic_vector (3 downto 0) := "1111";
constant sec1: std_logic_vector (3 downto 0) := "0011";
begin
process(clk, clr)
begin
if clr = '1' then
state<= s0;
count <= x"0";
elsif (clk'event and clk = '1') then
case state is
when s0 =>
if count <= sec5 then
state <= s0;
count <= count +1;
else
state <= s1;
count <= x"0";
end if;
when s1 =>
if count <= sec1 then
state <= s1;
count <= count +1;
else
state <= s2;
count <= x"0";
end if;
when s2 =>
if count <= sec1 then
state <= s2;
count <= count +1;
else
state <= s3;
count <= x"0";
end if;
when s3 =>
if count <= sec5 then
state <= s3;
count <= count +1;
else
state <= s4;
count <= x"0";
end if;
when s4 =>
if count <= sec1 then
state <= s4;
count <= count +1;
else
state <= s5;
count <= x"0";
end if;
when s5 =>
if count <= sec1 then
state <= s5;
count <= count +1;
else
state <= s0;
count <= x"0";
end if;
when others =>
state <= s0;
end case;
end if;
end process;
c2 : process (state)
begin
case state is
when s0 => lights <= "100001";
when s1 => lights <= "100010";
when s2 => lights <= "100100";
when s3 => lights <= "001100";
when s4 => lights <= "010100";
when s5 => lights <= "100100";
when others => lights <= "100001";
end case;
end process;
end traffic;
Change elseif to elsif, for valid VHDL syntax.

VHDL keypad code issues

I have a 4x3 keypad, i wrote this FSM for interfacing it with my Nexys2 board, trouble I am having here is
When I run the code, the LEDs glow without any key pressed, it shows random combinations automatically
When I press a key it shows that particular combination then goes on to the next condition of ROW without any key pressed. And sometimes it does not even respond if i press a key.
What is happening? What is wrong with this code? I am clueless. Can someone point out the mistakes and suggest some solution? Here is my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity keypad_3x4 is
Port ( CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
ROW : in STD_LOGIC_VECTOR (3 downto 0);
COL : out STD_LOGIC_VECTOR (2 downto 0);
LED : out STD_LOGIC_VECTOR (3 downto 0)
);
end keypad_3x4;
architecture Behavioral of keypad_3x4 is
architecture Behavioral of keypad_3x4 is
TYPE STATE_TYPE is
( RESET_ST,
S1,
S2,
S3,
S4,
S5,
S6
);
signal state: STATE_TYPE;
begin
process (CLK, RESET)
begin
if (RESET = '1') then
state <= RESET_ST;
elsif (CLK'event and CLK = '1') then
case (state) is
WHEN RESET_ST =>
LED <= (others => '0');
COL <= (others => '0');
state <= S1;
WHEN S1 =>
COL <= "001"; --C1 selected
LED <= (others => '0');
state <= S2;
WHEN S2 =>
if ROW <= "0001" then
led <= "0001"; --1
elsif ROW <= "0010" then
led <= "0100"; --4
elsif ROW <= "0100" then
led <= "0111"; --7
elsif ROW <= "1000" then
led <= "1111"; --*
else
LED <= (others => '0');
state <= S3;
end if;
WHEN S3 =>
COL <= "010"; --C2 selected
LED <= (others => '0');
state <= S4;
WHEN S4 =>
if ROW <= "0001" then
led <= "0010"; --2
elsif ROW <= "0010" then
led <= "0101"; --5
elsif ROW <= "0100" then
led <= "1000"; --8
elsif ROW <= "1000" then
led <= "0000"; --0
else
LED <= (others => '0');
state <= S5;
end if;
WHEN S5 =>
COL <= "100"; --C3 selected
LED <= (others => '0');
state <= S6;
WHEN S6 =>
if ROW <= "0001" then
led <= "0011"; --3
elsif ROW <= "0010" then
led <= "0110"; --6
elsif ROW <= "0100" then
led <= "1001"; --9
elsif ROW <= "1000" then
led <= "1111"; --#
else
LED <= (others => '0');
state <= RESET_ST;
end if;
WHEN others =>
state <= RESET_ST;
END case;
END if;
END process;
end Behavioral;

why the elevator stuckes in a state?

this is vhdl code for an elevator for 7 floors
the coding is encapsulated into 3 states s0=no move ,s1=move up , s2 =move down
if it is in s0 it should wait for 2 cycles after that move up/down according to the desired floor or called floor on the next positive edge .
The problem is that the elevator is stuck in s1 state
could anyone help me please ?
-- Cad Project
-- Project Name : Elevator
-- Date : 18\12\2013
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--Entity Decleration
entity Elevator is
port (call, clk, press : in std_logic;
-- Call To Call The Elevator ,press if a key is pressrd from the pannel inside the elevator .
Desire_floor, Call_Floor : in std_logic_vector (2 downto 0);
-- Desired_floor is the floor number choosed from inside the elevator .
-- called_floor is the floor number that the "Call" Key has been pressed from .
weight : in std_logic;
Door_open_close, Move_up, move_down, OverWeight : out std_logic;
-- Door_open_close is 1 when opened ,0 when closed .
-- OverWeight is 1 when the weight is over 500 KG.
Current_Floor : buffer std_logic_vector (2 downto 0) := "000";
temp1_state, temp2_state : buffer std_logic_vector (1 downto 0);
o1, o2, o3, o4, o5, o6, o7 : out std_logic_vector (2 downto 0));
end;
--architecture Decleration
architecture Elevator of Elevator is
type state is (s0, s1, s2);
--s0 state represents no move ,s1 state represents move up ,s2 state represents move down .
signal current_state : state := s0;
signal next_state : state;
signal Desired_floor, Called_Floor : std_logic_vector (2 downto 0);
signal X : std_logic := '0'; -- X is a signal used to restart the timer or to resume it's count.
signal counter : std_logic_vector (2 downto 0); -- Timer befor closing/opening the doors "timer".
signal counter2 : std_logic_vector (2 downto 0) := "000"; -- Timer for the elevator to move up or down.
signal temp1, temp2, temp3, temp4, temp5 : std_logic_vector (2 downto 0);
begin
P1 : process (clk , weight, x)
variable s11 : std_logic_vector (2 downto 0) := "000";
-- Variable insted of the counter signal -->to have the direct assigment
begin
if (weight = '1') then
OverWeight <= '1';
current_state <= s0;
elsif (clk'event and clk = '1') then
if (x = '1') then -- if X equals to 1 that means restart the timer.
s11 := "000";
elsif (x = '0') then -- if X equals 0 then count up "keep counting ".
s11 := s11+1;
end if;
current_state <= next_state;
counter <= s11;
OverWeight <= '0';
end if;
counter <= s11;
o5 <= counter;
end process P1;
P2 : process (clk) -- this process if for the 2nd timer.
variable s4 : std_logic_vector (2 downto 0) := "000";
-- Variable insted of the counter2 signal -->to have the direct assigment
begin
if (rising_edge(clk)) then
if (press = '1') then
Desired_floor <= Desire_floor;
if (Current_Floor < Desired_floor) then
s4 := s4 +1;
elsif (Current_Floor > Desired_floor) then
s4 := s4 -1;
end if;
counter2 <= s4;
elsif (call = '1') then
Called_Floor <= Call_Floor;
if (Current_Floor < Called_Floor) then
s4 := s4 +1;
elsif (Current_Floor > Called_Floor) then
s4 := s4 -1;
end if;
end if;
end if;
counter2 <= s4;
o1 <= counter2;
o2 <= Desired_floor;
o3 <= Called_Floor;
counter2 <= s4;
--Desired_floor<=Desire_floor;
end process P2;
P3 : process (counter, current_state)
begin
case current_state is
when s0 =>
if(counter < "001") then
x <= '0';
Current_Floor <= Current_Floor;
next_state <= s0;
temp1_state <= "00";
else
if (press = '1') then
if(Desired_floor > Current_Floor) then
next_state <= s1;
temp2_state <= "01";
elsif (Desired_floor < Current_Floor) then
next_state <= s2;
temp2_state <= "10";
end if;
else
if (call = '1') then
if (Called_Floor > Current_Floor) then
next_state <= s1;
temp2_state <= "01";
elsif (Called_Floor < Current_Floor) then
next_state <= s2;
temp2_state <= "10";
end if;
end if;
end if;
x <= '1';
end if;
Door_open_close <= '1';
Move_up <= '0';
move_down <= '0';
Current_Floor <= counter2;
temp1_state <= "00";
when s1 =>
temp1 <= (Desired_floor - Current_Floor);
temp2 <= (Called_Floor-Current_Floor);
o4 <= temp1;
if ((temp1 /= "000") or (temp2 /= "000")) then
next_state <= s1;
temp2_state <= "01";
Current_Floor <= counter2;
elsif (((Desired_floor-Current_Floor) = "000")or ((Called_Floor-Current_Floor) = "000")) then
next_state <= s0;
temp2_state <= "00";
end if;
Door_open_close <= '0';
Move_up <= '1';
move_down <= '0';
Current_Floor <= counter2;
x <= '1';
temp1_state <= "01";
when s2 =>
temp3 <= (Current_Floor-Desired_floor);
temp4 <= (Current_Floor-Called_Floor);
if ((temp3 /= "000") or (temp4 /= "000")) then
next_state <= s2;
temp2_state <= "10";
Current_Floor <= counter2;
elsif (((Current_Floor-Desired_floor) = "000") or ((Called_Floor-Current_Floor) = "000")) then
next_state <= s0;
temp2_state <= "00";
end if;
Door_open_close <= '0';
Move_up <= '0';
move_down <= '1';
Current_Floor <= counter2;
x <= '1';
temp1_state <= "10";
end case;
end process P3;
end;
**********************************
I mad a lot of changes on the code and still have a problem .How can i save the value of an input at a certain state and ignore it's value until the next entering of the same state
-- Cad Project .
-- Project Name : Elevator .
-- Date : 18\12\2013.
-- Group Number : 13.
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--Entity Decleration
entity Elevator is
port (clk, press : in std_logic;
-- Call To Call The Elevator ,press if a key is pressrd from the pannel inside the elevator .
Desire_floor : in std_logic_vector (2 downto 0);
-- Desired_floor is the floor number choosed from inside the elevator .
-- called_floor is the floor number that the "Call" Key has been pressed from .
weight : in std_logic;
Door_open_close, Move_up, move_down, OverWeight : out std_logic;
-- Door_open_close is 1 when opened ,0 when closed .
-- OverWeight is 1 when the weight is over 500 KG.
Current_Floor : buffer std_logic_vector (2 downto 0) := "000";
temp1_state, temp2_state : buffer std_logic_vector (1 downto 0);
o1, o2, o3, o4, o5, o6, o7 : out std_logic_vector (2 downto 0));
end;
--architecture Decleration
architecture Elevator of Elevator is
type state is (s0, s1, s2);
--s0 state represents no move ,s1 state represents move up ,s2 state represents move down .
signal current_state : state := s0;
signal next_state : state;
signal Desired_floor : std_logic_vector (2 downto 0);
signal X : std_logic := '0'; -- X is a signal used to restart the timer or to resume it's count.
signal counter : std_logic_vector (2 downto 0); -- Timer befor closing/opening the doors "timer".
signal counter2 : std_logic_vector (2 downto 0) := "000"; -- Timer for the elevator to move up or down.
signal temp1, temp2, temp3, temp4, temp5 : std_logic_vector (2 downto 0);
signal temp6 : std_logic;
begin
P1 : process (clk , weight, x)
variable s11 : std_logic_vector (2 downto 0) := "000";
-- Variable insted of the counter signal -->to have the direct assigment
begin
if (weight = '1') then
OverWeight <= '1';
current_state <= s0;
elsif (clk'event and clk = '1') then
if (x = '1') then -- if X equals to 1 that means restart the timer.
s11 := "000";
elsif (x = '0') then -- if X equals 0 then count up "keep counting ".
s11 := s11+1;
end if;
current_state <= next_state;
counter <= s11;
OverWeight <= '0';
end if;
counter <= s11;
o5 <= counter;
end process P1;
P2 : process (clk) -- this process if for the 2nd timer.
variable s4 : std_logic_vector (2 downto 0) := "000";
-- Variable insted of the counter2 signal -->to have the direct assigment
begin
if (rising_edge(clk)) then
if (press = '1') then
if (Current_Floor < Desired_floor) then
s4 := s4 +1;
elsif (Current_Floor > Desired_floor) then
s4 := s4 -1;
end if;
counter2 <= s4;
end if;
end if;
counter2 <= s4;
o1 <= counter2;
o2 <= Desired_floor;
counter2 <= s4;
end process P2;
P3 : process (counter, current_state)
begin
case current_state is
when s0 =>
if(counter < "010") then
x <= '0';
Current_Floor <= Current_Floor;
next_state <= s0;
temp1_state <= "00";
else
if (press = '1') then
if(Desired_floor > Current_Floor) then
next_state <= s1;
temp2_state <= "01";
elsif (Desired_floor < Current_Floor) then
next_state <= s2;
temp2_state <= "10";
end if;
end if;
x <= '1';
end if;
Door_open_close <= '1';
Move_up <= '0';
move_down <= '0';
Current_Floor <= counter2;
temp1_state <= "00";
temp6 <= '1';
when s1 =>
temp1 <= (Desired_floor - Current_Floor);
o4 <= temp1;
if ((temp1 /= "000")) then
next_state <= s1;
temp2_state <= "01";
Current_Floor <= counter2;
elsif ((Desired_floor-Current_Floor) = "000") then
next_state <= s0;
temp2_state <= "00";
end if;
Door_open_close <= '0';
Move_up <= '1';
move_down <= '0';
Current_Floor <= counter2;
x <= '1';
temp1_state <= "01";
temp6 <= '0';
when s2 =>
temp3 <= (Current_Floor-Desired_floor);
if ((temp3 /= "000")) then
next_state <= s2;
temp2_state <= "10";
Current_Floor <= counter2;
elsif ((Current_Floor-Desired_floor) = "000") then
next_state <= s0;
temp2_state <= "00";
end if;
Door_open_close <= '0';
Move_up <= '0';
move_down <= '1';
Current_Floor <= counter2;
x <= '1';
temp1_state <= "10";
temp6 <= '0';
end case;
end process P3;
P4 : process (temp6, clk)
begin
if (clk 'event and clk = '1') then
if (temp6'event and temp6 = '1')then
--if ( current_state =s0 ) then
Desired_floor <= Desire_floor;
else
Desired_floor <= Desired_floor;
end if;
Desired_floor <= Desired_floor;
end if;
end process P4;
end;
It looks like the floor counter is only being incremented when the user presses 'press'.
Explanation
If we're not on the desired floor yet, then Current_Floor is driven by counter2
temp1 <= (Desired_floor - Current_Floor);
o4 <= temp1;
if ((temp1 /= "000")) then
next_state <= s1;
temp2_state <= "01";
Current_Floor <= counter2;
counter2 is driven by s4:
if (rising_edge(clk)) then
if (press = '1') then
if (Current_Floor < Desired_floor) then
s4 := s4 +1;
elsif (Current_Floor > Desired_floor) then
s4 := s4 -1;
end if;
counter2 <= s4; <-
end if;
end if;
counter2 <= s4; <-
o1 <= counter2;
o2 <= Desired_floor;
counter2 <= s4; <-
(Aside, why do you assign s4 to counter2 three times?)
s4 is only changed when press is asserted. So your lift is only going to be moving up or down a floor when someone pushes the button.
General comments
Your process sensitivity lists are all over the place! Your sensitivity lists should either be clock or clock,reset. Asynchronous processes (those without a clock in the sensitivity list) do have their place, but I generally avoid them unless absolutely necessary. I find it a lot easier to visualise the timing behaviour in my head when everything is strictly synchronous.
P1 : process (clk , weight, x) <- BAD
P2 : process (clk) <- GOOD
P3 : process (counter, current_state) <- OKAY
P4 : process (temp6, clk) <- BAD
Indenting has a huge impact on how you read the code. Learn to indent properly. I use the emacs VHDL mode, it has a great beautify function which really helps. I ran your code through it when I edited the comment and wrote this answer.
Your signal names need work. things like temp are a bad idea. you are doing pretty well with commenting though, so that's a plus. keep that up!
I'm going to briefly mention the code redundancy, example:
if (temp6'event and temp6 = '1')then
--if ( current_state =s0 ) then
Desired_floor <= Desire_floor;
else
Desired_floor <= Desired_floor;
end if;
Desired_floor <= Desired_floor;
If it was different before, totally understandable, but clean that stuff up, unnecessary reading for whoever is on the receiving end of your code.

Resources