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.
Related
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
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.
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.
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";
I am attempting to write a Successive Approximation Register in VHDL for an ADC. I am making it a state machine. I am just a little unsure about my code in the final State block (current_state = S_LSB). Is this code valid? Is there a better way to reset DigitalOutTemp and OutTemp before going back to state one?
NOTE The value of Comparator depends on the DigitalOutTemp output after it goes through a Digital to Analog Converter.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY SARegister IS
PORT (
Comparator, Clock : IN std_logic;
DigitalOutFinal, DigitalOutTemp : OUT std_logic_vector (13 downto 0)
);
END;
ARCHITECTURE Behavioural OF SARegister IS
CONSTANT S_MSB : STD_LOGIC_VECTOR(3 downto 0) := "0000";
CONSTANT S_TWELVE : STD_LOGIC_VECTOR(3 downto 0) := "0001";
CONSTANT S_ELEVEN : STD_LOGIC_VECTOR(3 downto 0) := "0010";
CONSTANT S_TEN : STD_LOGIC_VECTOR(3 downto 0) := "0011";
CONSTANT S_NINE : STD_LOGIC_VECTOR(3 downto 0) := "0100";
CONSTANT S_EIGHT : STD_LOGIC_VECTOR(3 downto 0) := "0101";
CONSTANT S_SEVEN : STD_LOGIC_VECTOR(3 downto 0) := "0110";
CONSTANT S_SIX : STD_LOGIC_VECTOR(3 downto 0) := "0111";
CONSTANT S_FIVE : STD_LOGIC_VECTOR(3 downto 0) := "1000";
CONSTANT S_FOUR : STD_LOGIC_VECTOR(3 downto 0) := "1001";
CONSTANT S_THREE : STD_LOGIC_VECTOR(3 downto 0) := "1010";
CONSTANT S_TWO : STD_LOGIC_VECTOR(3 downto 0) := "1011";
CONSTANT S_ONE : STD_LOGIC_VECTOR(3 downto 0) := "1100";
CONSTANT S_LSB : STD_LOGIC_VECTOR(3 downto 0) := "1101";
SIGNAL Next_state : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL Current_state : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL OutTemp : STD_LOGIC_VECTOR(13 DOWNTO 0);
BEGIN
PROCESS (Clock)
BEGIN
IF (rising_edge (Clock)) THEN
Current_state <= Next_state;
END IF;
END PROCESS;
PROCESS (Current_state, Comparator)
BEGIN
Next_state <= Current_state;
DigitalOutTemp <= "10000000000000";
OutTemp <= "10000000000000";
DigitalOutFinal <= "00000000000000";
IF (Current_state = S_MSB) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(13) <= '0';
OutTemp(13) <= '0';
END IF;
DigitalOutTemp(12) <='1';
OutTemp(12) <= '1';
Next_state <= S_TWELVE;
ELSIF (Current_state = S_TWELVE) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(12) <= '0';
OutTemp(12) <= '0';
END IF;
DigitalOutTemp(11) <='1';
OutTemp(11) <= '1';
Next_state <= S_ELEVEN;
ELSIF (Current_state = S_ELEVEN) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(11) <= '0';
OutTemp(11) <= '0';
END IF;
DigitalOutTemp(10) <='1';
OutTemp(10) <= '1';
Next_state <= S_TEN;
ELSIF (Current_state = S_TEN) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(10) <= '0';
OutTemp(10) <= '0';
END IF;
DigitalOutTemp(9) <='1';
OutTemp(9) <= '1';
Next_state <= S_NINE;
ELSIF (Current_state = S_NINE) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(9) <= '0';
OutTemp(9) <= '0';
END IF;
DigitalOutTemp(8) <='1';
OutTemp(8) <= '1';
Next_state <= S_EIGHT;
ELSIF (Current_state = S_EIGHT) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(8) <= '0';
OutTemp(8) <= '0';
END IF;
DigitalOutTemp(7) <='1';
OutTemp(7) <= '1';
Next_state <= S_SEVEN;
ELSIF (Current_state = S_SEVEN) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(7) <= '0';
OutTemp(7) <= '0';
END IF;
DigitalOutTemp(6) <='1';
OutTemp(6) <= '1';
Next_state <= S_SIX;
ELSIF (Current_state = S_SIX) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(6) <= '0';
OutTemp(6) <= '0';
END IF;
DigitalOutTemp(5) <='1';
OutTemp(5) <= '1';
Next_state <= S_FIVE;
ELSIF (Current_state = S_FIVE) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(5) <= '0';
OutTemp(5) <= '0';
END IF;
DigitalOutTemp(4) <='1';
OutTemp(4) <= '1';
Next_state <= S_FOUR;
ELSIF (Current_state = S_FOUR) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(4) <= '0';
OutTemp(4) <= '0';
END IF;
DigitalOutTemp(3) <='1';
OutTemp(3) <= '1';
Next_state <= S_THREE;
ELSIF (Current_state = S_THREE) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(3) <= '0';
OutTemp(3) <= '0';
END IF;
DigitalOutTemp(2) <='1';
OutTemp(2) <= '1';
Next_state <= S_TWO;
ELSIF (Current_state = S_TWO) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(2) <= '0';
OutTemp(2) <= '0';
END IF;
DigitalOutTemp(1) <='1';
OutTemp(1) <= '1';
Next_state <= S_ONE;
ELSIF (Current_state = S_ONE) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(1) <= '0';
OutTemp(1) <= '0';
END IF;
DigitalOutTemp(0) <='1';
OutTemp(0) <= '1';
Next_state <= S_LSB;
ELSIF (Current_state = S_LSB) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(0) <= '0';
OutTemp(0) <= '0';
END IF;
DigitalOutFinal <= OutTemp;
DigitalOutTemp <= "10000000000000";
OutTemp <= "10000000000000";
Next_state <= S_MSB;
END IF;
END PROCESS;
END;
Its hard to tell what your code is trying to accomplish, so I thought I'd make some general observations that might help you along.
There is a lot of needless repetition in your code that you can fix by using a counter to index your bits rather than a hard coded index in each state, for example using a counter idx that counts from your MSB to LSB you can do:
...
elsif (current_state = COMPARE) then
OutTemp(idx) <= comparator;
if idx > 0 then
OutTemp(idx-1) <= '1';
idx <= idx - 1;
next_state <= current_state;
else
idx <= MSB;
next_state <= idle;
end if;
end if;
This assumes you want to set OutTemp(idx-1) in the previous state, which strikes me as a bit pointless, but maybe its required by your external hardware...
You have also duplicated your OutTemp by assigning to both a signal and a port, I would remove all your assignments to the port DigitalOutTemp and instead add the following to your clocked process:
process (clock)
begin
if rising_edge(clock) then
Current_state <= Next_state;
DigitalOutTemp <= OutTemp;
end if;
end process;
This will set DigitalOutTemp synchronously, if you dont want this you can set it outside of the clocked process instead, but I would advise you to set it synchronously to avoid glitches.
To answer your question, the final state:
ELSIF (Current_state = S_LSB) THEN
IF (Comparator = '0') THEN
DigitalOutTemp(0) <= '0';
OutTemp(0) <= '0';
END IF;
DigitalOutFinal <= OutTemp;
DigitalOutTemp <= "10000000000000";
OutTemp <= "10000000000000";
Next_state <= S_MSB;
END IF;
.. will just set DigitalOutTemp to "10000000000000" and DigitalOutFinal to whatever was in OutTemp in the previous state. It appears that you expect OutTemp to have been updated by the assignment to OutTemp(0) further up, but this wont be the case. The assignment to OutTemp(0) is scheduled for the end of the process; it isn't visible immediately.
The assignments to OutTemp(0) and DigitalOutTemp(0) in the IF statement will do nothing as their scheduled writes are cancelled by your assignments to them further down.
So to answer your question, it looks like valid code in that it will probably compile and synthesize, but it wont exhibit the behaviour you seem to expect.
Hope this helps.