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.
Related
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.
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.
I have 18 output and 9 push switches to work with and one led as output which changing its states each time the push button is pressed to automate the chance of two players. my code is not working, pls help
my code is...expected behavour is that when momentarily in1 switch is high then play_to_play should toggle on each event of the inputs and according to play_to_play status and in1 high either ou11 or ou21 should go high i.e one player has played his chance and automatically at the next event it takes that it is player 2 chance
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TicTac is
Port ( in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
in3 : in STD_LOGIC;
in4 : in STD_LOGIC;
in5 : in STD_LOGIC;
in6 : in STD_LOGIC;
in7 : in STD_LOGIC;
in8 : in STD_LOGIC;
in9 : in STD_LOGIC;
reset : in STD_LOGIC;
p_to_play : out STD_Logic;
p1_win : out STD_LOGIC;
p2_win : out STD_LOGIC;
ou11 : out STD_LOGIC;
ou12 : out STD_LOGIC;
ou13 : out STD_LOGIC;
ou14 : out STD_LOGIC;
ou15 : out STD_LOGIC;
ou16 : out STD_LOGIC;
ou17 : out STD_LOGIC;
ou18 : out STD_LOGIC;
ou19 : out STD_LOGIC;
ou21 : out STD_LOGIC;
ou22 : out STD_LOGIC;
ou23 : out STD_LOGIC;
ou24 : out STD_LOGIC;
ou25 : out STD_LOGIC;
ou26 : out STD_LOGIC;
ou27 : out STD_LOGIC;
ou28 : out STD_LOGIC;
ou29 : out STD_LOGIC);
end TicTac;
architecture Behavioral of TicTac is
Signal temp1, temp2, temp3, temp4, temp5, temp6,temp7, temp8, temp9,p1_play :std_logic :='0';
signal o11,o12,o13,o14,o15,o16,o17,o18,o19,o21,o22,o23,o24,o25,o26,o27,o28,o29 :std_logic :='0';
signal p1win,p2win :std_logic :='0';
begin
process(in1,in2,in3,in4,in5,in6,in7,in8,in9,reset)
begin
if ((in1'event or in2'event or in3'event or in4'event or in5'event or in6'event or in7'event or in8'event or in9'event) and
(in1='1' or in2 ='1' or in3='1' or in4='1' or in5='1' or in6='1' or in7='1' or in8='1' or in9='1')) then
p1_play <= not(p1_play);
if(reset'event and reset= '1') then
temp1 <='0';
temp2 <='0';
temp3 <='0';
temp4 <='0';
temp5 <='0';
temp6 <='0';
temp7 <='0';
temp8 <='0';
temp9 <='0';
p1_play <= '0';
p1win <='0';
p2win <='0';
o11 <='0';
o12 <='0';
o13 <='0';
o14 <='0';
o15 <='0';
o16 <='0';
o17 <='0';
o18 <='0';
o19 <='0';
o21 <='0';
o22 <='0';
o23 <='0';
o24 <='0';
o25 <='0';
o26 <='0';
o27 <='0';
o28 <='0';
o29 <='0';
end if;
if(in1= '1') then
temp1 <='1';
end if;
if(in2= '1') then
temp2 <='1';
end if;
if(in3= '1') then
temp3 <='1';
end if;
if(in4= '1') then
temp1 <='1';
end if;
if(in5= '1') then
temp5 <='1';
end if;
if(in6= '1') then
temp6 <='1';
end if;
if(in7= '1') then
temp7 <='1';
end if;
if(in8= '1') then
temp8 <='1';
end if;
if(in9= '1') then
temp9 <='1';
end if;
if(p1_play='0' and temp1='1') then
o11 <= '1';
end if;
if(p1_play='0' and temp2='1') then
o12 <= '1';
end if;
if(p1_play='0' and temp3='1') then
o13 <= '1';
end if;
if(p1_play='0' and temp4='1') then
o14 <= '1';
end if;
if(p1_play='0' and temp5='1') then
o15 <= '1';
end if;
if(p1_play='0' and temp6='1') then
o16 <= '1';
end if;
if(p1_play='0' and temp7='1') then
o17 <= '1';
end if;
if(p1_play='0' and temp8='1') then
o18 <= '1';
end if;
if(p1_play='0' and temp9='1') then
o19 <= '1';
end if;
if(p1_play='1' and temp1='1') then
o21 <= '1';
end if;
if(p1_play='1' and temp2='1') then
o22 <= '1';
end if;
if(p1_play='1' and temp3='1') then
o23 <= '1';
end if;
if(p1_play='1' and temp4='1') then
o24 <= '1';
end if;
if(p1_play='1' and temp5='1') then
o25 <= '1';
end if;
if(p1_play='1' and temp6='1') then
o26 <= '1';
end if;
if(p1_play='1' and temp7='1') then
o27 <= '1';
end if;
if(p1_play='1' and temp8='1') then
o28 <= '1';
end if;
if(p1_play='1' and temp9='1') then
o29 <= '1';
end if;
if((o11='1' and o12='1' and o13='1') or (o14='1' and o15='1' and o16='1') or (o17='1' and o18='1' and o19='1')
or (o11='1' and o14='1' and o17='1') or (o12='1' and o15='1' and o18='1') or (o13='1' and o16='1' and o19='1')
or (o11='1' and o15='1' and o19='1') or (o13='1' and o15='1' and o17='1')) then
p1win <='1';
end if;
if((o21='1' and o22='1' and o23='1') or (o24='1' and o25='1' and o26='1') or (o27='1' and o28='1' and o29='1')
or (o21='1' and o24='1' and o27='1') or (o22='1' and o25='1' and o28='1') or (o23='1' and o26='1' and o29='1')
or (o21='1' and o25='1' and o29='1') or (o23='1' and o25='1' and o27='1')) then
p2win <='1';
end if;
end if;
end process;
ou11 <= o11;
ou12 <= o12;
ou13 <= o13;
ou14 <= o14;
ou15 <= o15;
ou16 <= o16;
ou17 <= o17;
ou18 <= o18;
ou19 <= o19;
ou21 <= o21;
ou22 <= o22;
ou23 <= o23;
ou24 <= o24;
ou25 <= o25;
ou26 <= o26;
ou27 <= o27;
ou28 <= o28;
ou29 <= o29;
p_to_play <= p1_play;
p1_win <= p1win;
p2_win <= p2win;
end Behavior
al;
Processes in VHDL are not the same as processes on a regular programming language. All signal assignments within a process actually occur at the time the process completes (actually a delta time later, which is basically a 0 time difference). Since you are trying to use the value of temp that you just assigned earlier in the process, but it hasn't actually been written yet, you are not triggering your if statement until the next time the process runs.
As an aside, I didn't notice any mechanism to prevent players from playing in spaces that they or their opponent already played.
EDIT: Also, what do you plan to do with this? If you want to put it on a real FPGA with real switches it likely won't work because of an electromechanical phenomenon called switch bouncing that makes each press of a switch seem like many to the hardware.
EDIT2: To fix this (still won't fix switch bouncing) you may want to scrap temp entirely (replacing it with the "in" signals) and put the entire contents of the process, except the reset stuff, inside your if statement that detects rising edges on the in signals.
EDIT3: Here is a VHDL model for a 4x4 tic-tac-toe board with your hardware setup expanded to the 16 squares of a 4x4 board. See if you can understand what is done and why, then adapt it to a 3x3 board.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TicTac is
Port (button : in std_logic_vector(16 downto 1);
reset : in std_logic;
p_to_play : out std_logic;
p1_win : out std_logic := '0';
p2_win : out std_logic := '0';
ou1 : out std_logic_vector(16 downto 1);
ou2 : out std_logic_vector(16 downto 1));
end TicTac;
architecture Behavioral of TicTac is
signal o1 : std_logic_vector(16 downto 1) := (others => '0');
signal o2 : std_logic_vector(16 downto 1) := (others => '0');
signal o : std_logic_vector(16 downto 1) := (others => '0');
signal p : std_logic;
signal win : std_logic;
signal win1 : std_logic;
signal win2 : std_logic;
begin
ou1 <= o1;
ou2 <= o2;
p_to_play <= p;
p1_win <= win1;
p2_win <= win2;
win <= win1 or win2;
gen_spots : for i in 1 to 16 generate --3 flip flops share a clock (button) for every space on the board
process(button(i), reset)
begin
if(reset = '1') then
o(i) <= '0';
o1(i) <= '0';
o2(i) <= '0';
elsif(button(i)'event and button(i)='1' and o(i)='0' and win='0') then
o(i) <= '1';
if (p = '0') then
o1(i) <= '1';
else
o2(i) <= '1';
end if;
end if;
end process;
end generate gen_spots;
process(o) --determines current player by xoring the o values together.
variable ot : std_logic;
begin
ot := '0';
for i in 1 to 16 loop
ot := ot xor o(i);
end loop;
p <= ot;
end process;
process(o1) --checks if player 1 wins
begin
win1 <= '0'; --only happens if none of the win1 <= '1' statements occur
for i in 0 to 3 loop
if (o1(1+i*4)='1' and o1(2+i*4)='1' and o1(3+i*4)='1' and o1(4+i*4)='1') then --rows
win1 <= '1';
end if;
if (o1(1+i)='1' and o1(5+i)='1' and o1(9+i)='1' and o1(13+i)='1') then --columns
win1 <= '1';
end if;
end loop;
if (o1(1)='1' and o1(6)='1' and o1(11)='1' and o1(16)='1') or (o1(4)='1' and o1(7)='1' and o1(10)='1' and o1(13)='1') then --diagonals
win1 <= '1';
end if;
end process;
process(o2) --checks if player 2 wins
begin
win2 <= '0'; --only happens if none of the win2 <= '1' statements occur
for i in 0 to 3 loop
if (o2(1+i*4)='1' and o2(2+i*4)='1' and o2(3+i*4)='1' and o2(4+i*4)='1') then --rows
win2 <= '1';
end if;
if (o2(1+i)='1' and o2(5+i)='1' and o2(9+i)='1' and o2(13+i)='1') then --columns
win2 <= '1';
end if;
end loop;
if (o2(1)='1' and o2(6)='1' and o2(11)='1' and o2(16)='1') or (o2(4)='1' and o2(7)='1' and o2(10)='1' and o2(13)='1') then --diagonals
win2 <= '1';
end if;
end process;
end Behavioral;
I haven't done exhaustive tests, but this compiles and works for a couple test cases.
Please remember to mark this as the correct answer if it solved your problem.
----------------------------------------------------------------------------------
----------------------------- TICTAC TOE GAME ------------------------------------
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity cs_main is
Port ( in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
in3 : in STD_LOGIC;
in4 : in STD_LOGIC;
in5 : in STD_LOGIC;
in6 : in STD_LOGIC;
in7 : in STD_LOGIC;
in8 : in STD_LOGIC;
in9 : in STD_LOGIC;
output1 : out STD_LOGIC_VECTOR (8 downto 0);
output2 : out STD_LOGIC_VECTOR (8 downto 0);
chance_real : out STD_LOGIC;
wing : out STD_LOGIC;
winr : out STD_LOGIC;
reset : in STD_LOGIC);
end cs_main;
architecture Behavioral of cs_main is
signal temp1,out1,out2,out11,out22 :std_logic_vector (8 downto 0):= "000000000";
signal chance : std_logic := '0';
signal wing1,winr1 : std_logic := '0';
begin
tictac :process(in1,in2,in3,in4,in5,in6,in7,in8,in9)
begin
if rising_edge (reset) then
out1 <= "000000000";
out2 <= "000000000";
chance <= '0';
wing1 <= '0';
winr1 <= '0';
else
if (wing1 = '0' and winr1 = '0') then
if rising_edge (in1) then
if (chance = '0') then
out1 <= "000000001";
elsif(chance = '1') then
out2 <= "000000001";
end if;
chance <= not chance ;
elsif rising_edge(in2) then
if (chance = '0') then
out1 <= "000000010";
elsif(chance = '1') then
out2 <= "000000010";
end if;
chance <= not chance ;
elsif rising_edge(in3) then
if (chance = '0') then
out1 <= "000000100";
elsif(chance = '1') then
out2 <= "000000100";
end if;
chance <= not chance ;
elsif rising_edge(in4) then
if (chance = '0') then
out1 <= "000001000";
elsif(chance = '1') then
out2 <= "000001000";
end if;
chance <= not chance ;
elsif rising_edge(in5) then
if (chance = '0') then
out1 <= "000010000";
elsif(chance = '1') then
out2 <= "000010000";
end if;
chance <= not chance ;
elsif rising_edge(in6) then
if (chance = '0') then
out1 <= "000100000";
elsif(chance = '1') then
out2 <= "000100000";
end if;
chance <= not chance ;
elsif rising_edge(in7) then
if (chance = '0') then
out1 <= "001000000";
elsif(chance = '1') then
out2 <= "001000000";
end if;
chance <= not chance ;
elsif rising_edge(in8) then
if (chance = '0') then
out1 <= "010000000";
elsif(chance = '1') then
out2 <= "010000000";
end if;
chance <= not chance ;
elsif rising_edge(in9) then
if (chance = '0') then
out1 <= "100000000";
elsif(chance = '1') then
out2 <= "100000000";
end if;
chance <= not chance ;
end if;
end if;
out11 <= out11 or out1;
out22 <= out22 or out2;
if(((out11 = "000000111" or out11 = "000111000" or out11 = "111000000" or
out11 = "001001001" or out11 = "010010010" or out11 = "100100100" or
out11 = "100010001" or out11 = "001010100" ) and chance ='0') or
((out22 = "000000111" or out22 = "000111000" or out22 = "111000000" or
out22 = "001001001" or out22 = "010010010" or out22 = "100100100" or
out22 = "100010001" or out22 = "001010100" ) and chance = '1')) then
if (chance = '0')then
wing1 <= '1';
winr1 <= '0';
elsif (chance = '1') then
wing1 <= '0';
winr1 <= '1';
end if;
else
wing1 <= '0';
winr1 <= '0';
end if;
end if;
end process tictac;
output1 <= out11 ;
output2 <= out22 ;
chance_real <= chance;
wing <= wing1;
winr <= winr1;
end Behavioral;
The code compiled without an error on my QUARTUS II version 15 software. i programmed it on my ALTERA DE2 FPGA BOARD but it does not display on the monitor. can anyone tell me what to do please
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity TicTac is
Port (button : in std_logic_vector(16 downto 1);
reset : in std_logic;
p_to_play : out std_logic;
p1_win : out std_logic := '0';
p2_win : out std_logic := '0';
ou1 : out std_logic_vector(16 downto 1);
ou2 : out std_logic_vector(16 downto 1));
end TicTac;
architecture Behavioral of TicTac is
signal o1 : std_logic_vector(16 downto 1) := (others => '0');
signal o2 : std_logic_vector(16 downto 1) := (others => '0');
signal o : std_logic_vector(16 downto 1) := (others => '0');
signal p : std_logic;
signal win : std_logic;
signal win1 : std_logic;
signal win2 : std_logic;
begin
ou1 <= o1;
ou2 <= o2;
p_to_play <= p;
p1_win <= win1;
p2_win <= win2;
win <= win1 or win2;
gen_spots : for i in 1 to 16 generate --3 flip flops share a clock (button) for every space on the board
process(button(i), reset)
begin
if(reset = '1') then
o(i) <= '0';
o1(i) <= '0';
o2(i) <= '0';
elsif(button(i)'event and button(i)='1' and o(i)='0' and win='0') then
o(i) <= '1';
if (p = '0') then
o1(i) <= '1';
else
o2(i) <= '1';
end if;
end if;
end process;
end generate gen_spots;
process(o) --determines current player by xoring the o values together.
variable ot : std_logic;
begin
ot := '0';
for i in 1 to 16 loop
ot := ot xor o(i);
end loop;
p <= ot;
end process;
process(o1) --checks if player 1 wins
begin
win1 <= '0'; --only happens if none of the win1 <= '1' statements occur
for i in 0 to 3 loop
if (o1(1+i*4)='1' and o1(2+i*4)='1' and o1(3+i*4)='1' and o1(4+i*4)='1') then --rows
win1 <= '1';
end if;
if (o1(1+i)='1' and o1(5+i)='1' and o1(9+i)='1' and o1(13+i)='1') then --columns
win1 <= '1';
end if;
end loop;
if (o1(1)='1' and o1(6)='1' and o1(11)='1' and o1(16)='1') or (o1(4)='1' and o1(7)='1' and o1(10)='1' and o1(13)='1') then --diagonals
win1 <= '1';
end if;
end process;
process(o2) --checks if player 2 wins
begin
win2 <= '0'; --only happens if none of the win2 <= '1' statements occur
for i in 0 to 3 loop
if (o2(1+i*4)='1' and o2(2+i*4)='1' and o2(3+i*4)='1' and o2(4+i*4)='1') then --rows
win2 <= '1';
end if;
if (o2(1+i)='1' and o2(5+i)='1' and o2(9+i)='1' and o2(13+i)='1') then --columns
win2 <= '1';
end if;
end loop;
if (o2(1)='1' and o2(6)='1' and o2(11)='1' and o2(16)='1') or (o2(4)='1' and o2(7)='1' and o2(10)='1' and o2(13)='1') then --diagonals
win2 <= '1';
end if;
end process;
end Behavioral;
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";