I'm trying to implement a testbench for the following fsm in created in vhdl. The problem is that currently, I'm not seeing any state transitions in the test bench. The simulation stays at state 0.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FPGA_Challenge is
Port ( led : out STD_LOGIC;
clk_in : in STD_LOGIC; -- 100 MHZ internal clock
reset : in STD_LOGIC; -- is reset necessary
button : in STD_LOGIC;
data_line : in STD_LOGIC);
end FPGA_Challenge;
architecture Behavioral of FPGA_Challenge is
type state_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20);
signal state: state_type;
signal x:std_logic;
signal y:std_logic;
signal count : integer:= 0;
--signal tmp: std_logic:= '1';
begin
process(clk_in, reset)
begin
if rising_edge(clk_in)then
if reset = '1'then -- Goes back to known state (state 0)
state <= s0;
count <= 0;
else
count <= count + 1;
case state is
-- Initial state- if button is pressed, then LED is lit and machine goes to state 2, if not it stays in state 1
when s0 =>
if (button <= '1') then
led <= '1';
state <= s1;
else
state <= s0;
led <= '0'; --is this necessary?
end if;
-- Beginning of preamble detection(states 1-17)
-- Count = ((freq in) / (freq out))/ 2 -1 = (100 MHz/ 2 MHz)/ 2 -1 = 50/2 - 1 (due to 50% duty cycle)
when s1=> -- do I need to put led = '1' in each state because it stays on ?
if (count = 25 -1) then
count <= 0;
if (data_line = '1')then
y <= '0';
-- led = '1';
state <= s2;
else
-- led = '1';
y <= '0';
state <= s1;
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s2 =>
if (count = 25-1) then
count <= 0;
if (data_line = '0')then
y <= '0';
-- led = '1';
state <= s3;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s3 =>
if (count = 25-1)then
count <= 0; ----reinitializes count
if (data_line <= '1')then
y <= '0';
-- led = '1';
state <= s4;
else
state <= s1;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s4 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s5;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s5 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s6;
else
state <= s4;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s6 =>
if (count= 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s7;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s7 =>
if (count = 25-1)then
count<= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s7;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s8 =>
if (count = 25-1)then
count <= 0;
if (data_line <='1')then
y <= '0';
-- led = '1';
state <= s9;
else
state <= s1;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s9 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s10;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s10=>
if (count = 25-1)then
count <= 0;
if (data_line <='1')then
y <= '0';
--led = '1';
state <= s11;
else
state <= s1;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s11 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s12;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s12 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s13;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s13 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s14;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s14 =>
if (count = 25-1)then
count <=0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s15;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s15 =>
if (count = 25-1)then
count <=0;
if (data_line <='0') then
y <= '0';
-- led = '1';
state <= s16;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s16 =>
if (count = 25-1) then
count <= 0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s17;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s17 =>
if (count = 25-1)then
count <= 0;
if (data_line ='1')then
y <= '1';
-- led = '1';
state <= s18;
else
state <= s1;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s18 => -- no real condition here except varying period of clock
if (count = 25)then
count <= 0; ----reinitializes count
state <= s19;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s19=> -- no real condition here except varying period of clock
if (count = 25)then
count <= 0; ----reinitializes count
state <= s0;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when others=>
null;
end case;
end if;
end if;
end process;
end architecture;
The following is the testbench I have so far. I have internal signals such as y(output for each state), and count(counter for how long I'm in a state) that I probably should be using as drivers in the testbench. Any input is appreciated
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FPGA_tb is
-- Port ( );
end FPGA_tb;
architecture Behavioral of FPGA_tb is
component FPGA_Challenge is
Port( led : out STD_LOGIC;
clk_in : in STD_LOGIC; -- 100 MHZ internal clock
reset : in STD_LOGIC; -- is reset necessary
button : in STD_LOGIC;
data_line : in STD_LOGIC);
end component;
signal led : STD_LOGIC;
signal clk_in : STD_LOGIC; -- 100 MHZ internal clock
signal reset : STD_LOGIC; -- is reset necessary
signal button : STD_LOGIC;
signal data_line : STD_LOGIC;
type state_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20);
signal state: state_type;
signal x,y: std_logic;
signal count : integer:= 0;
begin
UUT: FPGA_Challenge
PORT MAP(
led => led,
clk_in => clk_in,
reset => reset,
button => button,
data_line => data_line
);
Testing: Process
begin
--wait until rising_edge(clk_in);
--wait until rising_edge(clk_in);
clk_in <='0';
reset <= '1';
button <= '0';
data_line <= '0';
WAIT For 10ns;
clk_in <='1';
reset <= '0';
button <= '1';
data_line <= '0';
WAIT For 10ns;
clk_in <='1';
reset <= '1';
button <= '0';
data_line <= '1';
WAIT For 10ns;
clk_in <='0';
reset <= '1';
button <= '0';
data_line <= '0';
WAIT For 10ns;
clk_in <='1';
reset <= '1';
button <= '0';
data_line <= '0';
WAIT For 10ns;
end process;
end Behavioral;
Try this in the testbench to have a running clock and proper reset
signal clk_in : STD_LOGIC := '1'; -- 100 MHZ internal clock
signal reset : STD_LOGIC := '1'; -- is reset necessary
clk_in <=NOT clk_in after 10ns;
reset <= 0 after 30ns;
play with button after the reset. that is, from 40ns
Related
I'm working on project which should convert data from analog to digital with approximation and I have error when i try compile code in Quartus II 9.1sp2 Web Edition which is shown in title with Case Statement in the code below:
architecture behavior of adc is
type state is (reset, state1, state2, state3, state4, state5, state6, state7, state8, state9, state10);
signal nx_state : state;
begin
process (in_clk, rst_n, start)
begin
if(rst_n'event and rst_n='0') then
B_hold <= "1111";
D_out <= "0000";
data_out <= "0000";
hold <= '1';
sample <= '0';
eoc <= '0';
if start = '1' then
nx_state <= state1;
else
nx_state <= reset;
end if;
elsif(in_clk'event and in_clk='1') then
case nx_state is
when state1 => nx_state <= state2;
B_hold <= "0000";
hold <= '0';
sample <= '1';
when state2 => nx_state <= state3;
B_hold <= "1111";
D_out <= "0000";
when state3 => nx_state <= state4;
B_hold(3) <= '0';
D_out(3) <= '1';
data_out(3) <= '1';
when state4 => nx_state <= state5;
if comp_in = '1' then
B_hold(3) <= '0';
D_out(3) <= '1';
data_out(3) <= '1';
else
B_hold(3) <= '1';
D_out(3) <= '0';
data_out(3) <= '0';
end if;
when state5 => nx_state <= state6;
B_hold(2) <= '0';
D_out(2) <= '1';
data_out(2) <= '1';
when state6 => nx_state <= state7;
if comp_in = '1' then
B_hold(2) <= '0';
D_out(2) <= '1';
data_out(2) <= '1';
else
B_hold(2) <= '1';
D_out(2) <= '0';
data_out(2) <= '0';
end if;
when state7 => nx_state <= state8;
B_hold(1) <= '0';
D_out(1) <= '1';
data_out(1) <= '1';
when state8 => nx_state <= state9;
if comp_in = '1' then
B_hold(1) <= '0';
D_out(1) <= '1';
data_out(1) <= '1';
else
B_hold(1) <= '1';
D_out(1) <= '0';
data_out(1) <= '0';
end if;
when state9 => nx_state <= state10;
B_hold(0) <= '0';
D_out(0) <= '1';
data_out(0) <= '1';
when state10 => nx_state <= reset;
if comp_in = '1' then
B_hold(0) <= '0';
D_out(0) <= '1';
data_out(0) <= '1';
else
B_hold(0) <= '1';
D_out(0) <= '0';
data_out(0) <= '0';
end if;
eoc <= '1';
end case;
end if;
end process;
end behavior;
I'm new newbie at vhdl and I don't know what exactly is wrong with the conditions shown above.
Your type includes a state named reset. You need a when for that state.
case nx_state is
when reset =>
Reset is level sensitive. So change
if(rst_n'event and rst_n='0') then
to
if(rst_n='0') then
It is also unusual to have a condition within the reset condition
if start = '1' then
nx_state <= state1;
else
nx_state <= reset;
end if;
Hence, you probably just want:
nx_state <= reset;
I'm setting up adv7513 on altera GX starter kit. Data that I've read from registers after setup is different from what I've sent.
I've tried to divide writes in to the single registers instead of one long transaction, and change the order of writes and reads, but I always read 0x03 from 0x98 and 0x00 from the rest of the registers.
I've used this i2c controller: https://www.digikey.com/eewiki/pages/viewpage.action?pageId=10125324
and I've made state machine in vhdl to control it, and write data stored in rom
if rising_edge(clk) then
case state is
when idle =>
if (beg='1') then
state <= start;
else
state <= idle;
end if;
when start =>
rom_addr <= count;
state <= lut_addr_i2c;
when lut_addr_i2c =>
ena <= '1';
rw <= '0';
addr <= "0111001";
data_wr <= lut_data(15 downto 8);
state <= lut_data_i2c;
when lut_data_i2c =>
if (busy='1' and busy_prev='0') then
data_wr <= lut_data(7 downto 0);
state <= cleanup;
count <= count+1;
end if;
when cleanup =>
if (busy='1' and busy_prev='0') then
state <= next_lut;
end if;
when next_lut =>
if (count = 31) then
state <= rd;
ena <= '0';
else
state <= start;
end if;
when rd =>
ready <= '1';
count <= 0;
if (rd_delay = 10000) then
state <= start_rd;
else
rd_delay <= rd_delay+1;
state <= rd;
end if;
when start_rd =>
rom_addr <= count;
if (next_rd = 20000) then
state <= rd_lut_addr;
next_rd <= 0;
else
next_rd <= next_rd+1;
state <= start_rd;
end if;
when rd_lut_addr =>
ena <= '1';
rw <= '0';
addr <= "0111001";
data_wr <= lut_data(15 downto 8);
state <= rd_lut;
when rd_lut =>
if (busy='1' and busy_prev='0') then
rw <= '1';
count <= count+1;
state <= rd_cleanup;
end if;
when rd_cleanup =>
if (busy='1' and busy_prev='0') then
state <= rd_next_lut;
end if;
when rd_next_lut =>
if (count = 31) then
state <= fin;
ena <= '0';
else
state <= start_rd;
ena <= '0';
end if;
when fin =>
state <= fin;
end case;
end if;
signal tap, what I write
signal tap, what I read
I think your problem is that you simply overrun the i2c slave. You should wait for not busy in your cleanup state latest after you've provided your second data byte.
Your code does not appear to wait for not busy at all?
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.
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.
I am new in VHDL. I try to create train ticket machine using vhdl. It have 3 destination and all destination have fee. When user insert money with same of fee, ticket will out and no change but if user enter extra money than fee, ticket will out also with change.When i run the simulation all output does not appear correctly but only come out with uuu. Anybody can help me with my code below, please.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity trainticket_machine is
PORT( Clock,Reset,Cancel : IN STD_LOGIC;
RM1,RM2,RM5 : IN STD_LOGIC;
KL_station,Mid_station,Klang_station : IN STD_LOGIC;
Ticket : OUT STD_LOGIC;
Change,Retrn : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
Money_sum : INOUT STD_LOGIC_VECTOR (3 DOWNTO 0)
);
end trainticket_machine;
architecture Behavioral of trainticket_machine is
TYPE state IS (S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,Cancl,waiting1,waiting2,waiting3,KL_Ticket,Mid_Ticket,Shah_Ticket);
SIGNAL p_state,Train_state: STATE;
BEGIN
PROCESS(Reset,Clock)
BEGIN
IF (Reset = '1') THEN
p_state <= S0;
Ticket <= '0';
Retrn <= "0000";
Money_sum <= "ZZZZ";
ELSIF (Clock'EVENT AND Clock = '1') THEN
p_state <= Train_state;
END IF;
END PROCESS;
PROCESS (p_state,Cancel,RM1,RM2,RM5,KL_station,Mid_station,Klang_station)
BEGIN
CASE p_state IS
WHEN S0 =>
Money_sum <= "0000";
Change <= "0000";
IF (KL_station = '1') THEN Train_state <= waiting1;
ELSIF(Mid_station = '1') THEN Train_state <= waiting2;
ELSIF(Klang_station = '1') THEN Train_state <= waiting3;
ELSE Train_state <= S0;
END IF;
WHEN waiting1 =>
Ticket <= '0';
Change <= "0000";
IF (RM1 = '1') THEN Train_state <= S1;
ELSIF (RM2 = '1') THEN Train_state <= S2;
ELSIF (RM5 = '1') THEN Train_state <= S3;
ELSIF (Money_sum >= 2) THEN train_state <= KL_Ticket;
ELSIF (Cancel = '1') THEN Train_state <= Cancl;
ELSE Train_state <= waiting1;
END IF;
WHEN waiting2 =>
Ticket <= '0';
Change <= "0000";
IF (RM1 = '1') THEN Train_state <= S4;
ELSIF (RM2 = '1') THEN Train_state <= S5;
ELSIF (RM5 = '1') THEN Train_state <= S6;
ELSIF (Money_sum >= 4) THEN train_state <= Mid_Ticket;
ELSIF (Cancel = '1') THEN Train_state <= Cancl;
ELSE Train_state <= waiting2;
END IF;
WHEN waiting3 =>
Ticket <= '0';
Change <= "0000";
IF (RM1 = '1') THEN Train_state <= S7;
ELSIF (RM2 = '1') THEN Train_state <= S8;
ELSIF (RM5 = '1') THEN Train_state <= S9;
ELSIF (Money_sum >= 6) THEN train_state <= Shah_Ticket;
ELSIF (Cancel = '1') THEN Train_state <= Cancl;
END IF;
WHEN S1 =>
IF (RM1 <= '1' AND RM2 <= '0' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 1;
ELSE Train_state <= waiting1;
END IF;
WHEN S2 =>
IF (RM1 <= '1' AND RM2 <= '1' AND RM5 <= '0') THEN
Ticket <= '1';
Change <= "0000";
Money_sum <= Money_sum + 2;
ELSE Train_state <= waiting1;
END IF;
WHEN S3 =>
IF (RM1 <= '0' AND RM2 <= '0' AND RM5 <= '1') THEN
Ticket <= '1';
Change <= "0001";
Money_sum <= Money_sum + 5;
ELSE Train_state <= waiting1;
END IF;
WHEN S4 =>
IF (RM1 <= '1' AND RM2 <= '0' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 1;
ELSE Train_state <= waiting2;
END IF;
WHEN S5 =>
IF (RM1 <= '0' AND RM2 <= '1' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 2;
ELSE Train_state <= waiting2;
END IF;
WHEN S6 =>
IF (RM1 <= '0' AND RM2 <= '0' AND RM5 <= '1') THEN
Ticket <= '0';
Change <= "0001";
Money_sum <= Money_sum + 5;
ELSE Train_state <= waiting2;
END IF;
WHEN S7 =>
IF (RM1 <= '1' AND RM2 <= '0' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 1;
ELSE Train_state <= waiting3;
END IF;
WHEN S8 =>
IF (RM1 <= '0' AND RM2 <= '1' AND RM5 <= '0') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 2;
ELSE Train_state <= waiting3;
END IF;
WHEN S9 =>
IF (RM1 <= '0' AND RM2 <= '0' AND RM5 <= '1') THEN
Ticket <= '0';
Change <= "0000";
Money_sum <= Money_sum + 5;
ELSE Train_state <= waiting3;
END IF;
WHEN KL_Ticket =>
Ticket <= '1';
Change <= Money_sum - 2;
Train_state <= waiting1;
WHEN Mid_Ticket =>
Ticket <= '1';
Change <= Money_sum - 4;
Train_state <= waiting2;
WHEN Shah_Ticket =>
Ticket <= '1';
Change <= Money_sum - 6;
Train_state <= waiting3;
WHEN Cancl =>
IF (Cancel <= '1') THEN
Retrn <= Money_sum;
ELSE Train_state <= S0;
END IF;
END CASE;
END PROCESS;
end Behavioral;
------------------------------simulation----------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
ENTITY trainticket_machine_tb IS
END trainticket_machine_tb;
ARCHITECTURE behavior OF trainticket_machine_tb IS
Signal Clock,Reset,Cancel,RM1,RM2,RM5,KL_station,Mid_station,Klang_station : std_logic := '0';
Signal Ticket : std_logic ;
signal Change,Retrn,Money_sum : std_logic_vector(3 downto 0);
constant Clock_period : time := 10 ns;
BEGIN
uut: entity work.trainticket_machine PORT MAP (
Clock => Clock,
Reset => Reset,
Cancel => Cancel,
RM1 => RM1,
RM2 => RM2,
RM5 => RM5,
KL_station => KL_station,
Mid_station => Mid_station,
Klang_station => Klang_station,
Ticket => Ticket,
Change => Change,
Retrn => Retrn,
Money_sum => Money_sum
);
Clock_process :process
begin
Clock <= '0';
wait for Clock_period/2;
Clock <= '1';
wait for Clock_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for Clock_period*2;
Reset <= '1';
wait for Clock_period;
Reset <= '0';
wait for Clock_period;
Cancel <= '1';
wait for Clock_period;
Cancel <= '0';
wait for Clock_period;
KL_station <= '1';
wait for Clock_period;
KL_station <= '0';
wait for Clock_period;
Mid_station <= '1';
wait for Clock_period;
Mid_station <= '0';
wait for Clock_period;
Klang_station <= '1';
wait for Clock_period;
Klang_station <= '0';
wait for Clock_period;
RM1 <= '1';
wait for Clock_period;
RM1 <= '0';
wait for Clock_period;
RM2 <= '1';
wait for Clock_period;
RM2 <= '0';
wait for Clock_period;
RM5 <= '1';
wait for Clock_period;
RM5 <= '0';
wait for Clock_period;
wait;
end process;
END;
Starting with the first problem you describe: since you are seeing only 'U's, maybe your outputs were never assigned any value. Did you remember to force Reset to '1' in the beginning of the simulation?
Now let's take a look at the state machine logic itself, which has many problems. First thing: you should differentiate between combinational logic and registered state. By state I mean values that must be kept in registers of flip-flops, between the clock transitions.
This is important because for each process you will have to decide whether it is combinational or registered. If the process is registered, it must be sensitive to your clock. If the process is combinational, it cannot have any statements that woud imply keeping state information.
So the first suggestion is to go through your code, and decide the nature of each process you have. You may have to create a few more processes, it's ok. From your code, it looks like the signal money_sum is state information, and therefore it should be updated on the rising edge of clock.
The second suggestion is: if you have an output that depends only on the current state (maybe your signal ticket), you need to assign a value to this signal on every condition of your case statement. Try removing the line Ticket <= '0'; from your first process and see what happens.
Third, please use more descriptive names for your states and signals, it is really hard to understand what is going on from names like S0, S1, S2, RM1, RM2, and RM5.
Finally, it would be really helpful to have some assertions in your testbench code. For instance, after every wait for Clock_period;, you could check your outputs to make sure they match what you expected:
Reset <= '1';
wait for Clock_period;
assert ticket = '0' report "Wrong value for 'ticket' after reset";
assert change = "0000" report "Wrong value for 'change' after reset";
assert retrn = "0000" report "Wrong value for 'retrn' after reset";
assert money_sum = "0000" report "Wrong value for 'money_sum' after reset";