VHDL Traffic Light - vhdl

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Traffic_Light is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
input : in STD_LOGIC;
output : out STD_LOGIC_VECTOR(1 DOWNTO 0));
end Traffic_Light;
architecture Behavioral of Traffic_Light is
type state_type is (S0,S1,S2); --type of state machine.
signal present_state, next_state: state_type; --current and next state declaration.
begin
process
begin
wait until clk'event and clk = '0';
present_state <= next_state;
end process;
process (clk,reset)
begin
if (reset='1') then
current_state <= S0; --default state on reset.
end if;
end process;
process (present_state, input)
begin
case present_state is
when S0 => --when current state is s0
if(input = '0') then
output <= "10";
next_state <= S1;
else
output <= "00";
next_state <= S2;
end if;
when S1 => --when current state is s1
if(input = '0') then
output <= "01";
next_state <= S0;
else
output <= "00";
next_state <= S2;
end if;
when S2 => --when current state is s2
if(input = '0') then
output <= "01";
next_state <= S0;
else
output <= "11";
next_state <= S2;
end if;
end case;
end process;
end Behavioral;
I cant seem to get every state change to occur only at the falling edge of the clock.
The simulation does not show the various changes in the present state, it just shows S0 all the way through.
All the state changes have been entered correctly. It just requires the synchronous reset an state changes to occur at the falling edge.

First replace current_state with present_state. Then you can't drive present_state from two processes since it's not a resolved type. You have to do something like
process (clk,reset)
begin
if (reset='1') then
present_state <= S0; --default state on reset.
elsif clk'event and clk = '0' then
present_state <= next_state;
end if;
end process;

Related

VHDL process get activated when the sensitivity list isn't changing

Process 2 keeps getting activated when there isn't a change. I have a board to test my code, and the state will change when I flip the clock(I set the clock as a button). In my code, the state will only change if I flip Qin. So it isn't doing what I wish it to do, and I spent a lot of time trying to find out what's causing it, but I can't. Please help.
This is the testbench graph TESTBENCH GRAPH
As you can see, in the graph, the output of the PS(present_state) is correct, but in the board, it isn't output right. There is one thing I found that is really important, I tried to output next_state on board, when I flip Qin to '1', the state shows "001", and then I flip clk to '1', the state become "010", which is not suppose to happen. I hope this is an important information.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity VendingMechine is
Port ( Clk : in STD_LOGIC;
Reset : in STD_LOGIC;
Cr : in STD_LOGIC;
Qin : in STD_LOGIC;
S : in STD_LOGIC;
CB : in STD_LOGIC;
W : in STD_LOGIC;
CRo : out STD_LOGIC_VECTOR(1 DOWNTO 0);
Qo : out STD_LOGIC;
PS : out STD_LOGIC_VECTOR(2 DOWNTO 0);
Wo : out STD_LOGIC;
CBo : out STD_LOGIC;
So : out STD_LOGIC);
end VendingMechine;
architecture Behavioral of VendingMechine is
TYPE state IS(Idle, S1, S2, S3, Soda, Candy, Water);
Signal Next_State : state;
Signal Present_State : state := Idle;
begin
Process1:Process(clk, reset)
begin
if(reset = '1') THEN
Present_State <= Idle;
elsif rising_edge(clk) THEN Present_State <= Next_State;
end if;
end process;
Process2:Process(Qin, Present_State, Cr, S, w)
begin
Next_State <= Present_State;
CRo <= "00"; Qo <= '0'; PS <= "000"; Wo <= '0'; CBo <= '0'; So <= '0';
CASE Present_State IS
When Idle =>
PS <= "000";
if Qin='1' Then Next_State <= S1;
else Next_State <= Idle;
end if;
When S1 =>
PS <= "001";
if Qin='1' Then Next_State <= S2;
elsif Cr = '1' Then Cro <= "01"; Next_State <= Idle;
else Next_State <= S1;
end if;
When S2 =>
PS <= "010";
if Qin='1' Then Next_State <= S3;
elsif Cr = '1' Then CRo <="10"; Next_State <= Idle;
elsif S = '1' Then Next_State <= Soda;
elsif CB = '1' Then Next_State <= Candy;
else Next_State <= S2;
end if;
When S3 =>
PS <= "011";
if Cr = '1' Then CRo <= "11"; Next_State <= Idle;
elsif S = '1' Then Qo <= '1'; Next_State <= Soda;
elsif CB = '1' Then Qo <= '1'; Next_State <= Candy;
elsif W = '1' Then Next_State <= Water;
elsif Qin = '1' Then Qo <= '1';
else Next_State <= S3;
end if;
When Soda =>
PS <= "100";
So <= '1';
Next_State <= Idle;
When Candy =>
PS <= "101";
CBo <= '1';
Next_State <= Idle;
When Water =>
PS <= "110";
Wo <= '1';
Next_State <= Idle;
END CASE;
end process;
end Behavioral;
Process will launch not only when signals changes, but every time you assign something to signal, even if it has same value as before. That may be the reason. In parallel process you can't rely on times launch, but on result in case of some conditions, that came in inputs.
Is Qin connected to an external switch? If yes, you should implement clock-domain synchronization (and possible debouncing) on the inputs.
Please let me know in the comments if you don't know how.
Lack of clock-synchronous signals will cause glitches and thus hang-ups in the state-machine. Lack of debouncing will cause multiple switch pulses ("bouncing")

VHDL FSM with a counter inside

I am new here and here is my question:
I have a state machine with 3 states(s0,s1.s2) and input:(reset, clk, start) and output (done). My state machine works like this: on reset it comes to s0, and then if start = '1' goes to s2 and in this state I want it to stay there for 12 clock cycles (12 clock cycle delay) and then goes to s2 and done ='1' here and then back to s0.
My codes goes like this :
My code seems fine but my simulation result is not ok.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY fsm_count IS
port(clk : in std_logic;
reset : in std_logic;
start : in std_logic ;
don : out std_logic );
END ENTITY fsm_count;
--
ARCHITECTURE arc OF fsm_count IS
type statetype is (s0,s1,s2);
signal pr_state,nx_state : statetype;
signal s_counter : std_logic_vector (3 downto 0):=(others=>'0'); -- zero
begin
fsmcount: process(clk,reset,pr_state,start)
begin
if reset = '1'then pr_state <= s0;
elsif (clk'event and clk='1') then
case pr_state is
when s0 =>
if start ='1' then nx_state <=s1;
else nx_state <= s0;
end if;
when s1 =>
s_counter <= s_counter + '1';
if (s_counter = "1100") then
nx_state <= s2;
s_counter <=(others =>'0'); -- initializing the counter back to zero
else nx_state <=s1;
end if;
when s2 =>
nx_state<= s0;
end case;
end if;
end process fsmcount;
don <= '1' when (pr_state = s2) else '0';
END ARCHITECTURE arc;
I haven't synthetized it, but I think it should work. I you are not using VHDL2008, modify conditions so that bool types are returned:
ARCHITECTURE arc OF fsm_count IS
type statetype is (s0,s1,s2);
signal pr_state,nx_state: statetype;
signal s_counter: std_logic_vector (3 downto 0);
begin
process(clk) begin if rising_edge(clk) then
if rst then pr_state <= s0; else pr_state <= nx_state; end if;
end if; end process;
process(clk) begin if rising_edge(clk) then
if pr_state/=s1 then s_counter <= (others=>'0');
else s_counter <= s_counter+1; end if;
end if; end process;
process(all) begin
case pr_state is
when s0 =>
if start then nx_state <= s1;
else nx_state <= pr_state; end if;
when s1 =>
if s_counter?=12 then nx_state <= s2;
else nx_state <= pr_state; end if;
when s2 =>
nx_state<= s0;
end case;
end process;
don <= '1' when (pr_state = s2) else '0';
END arc;
EDIT
Alternatively, you can save s2 (i replaced pr_state with sta, nx_state with stn, and s_counter with cnt:
ARCHITECTURE arc OF fsm_count IS
signal idon: std_logic;
type t_st is (s0,s1);
signal sta, stn: t_st;
signal cnt: std_logic_vector (3 downto 0);
begin
process(clk) begin if rising_edge(clk) then
if rst then sta <= s0; else sta <= stn; end if;
end if; end process;
process(clk) begin if rising_edge(clk) then
if sta/=s1 then cnt <= (others=>'0');
else cnt <= cnt+1; end if;
end if; end process;
process(all) begin
case sta is
when s0 =>
if start then stn <= s1; else stn<=sta; end if;
when s1 =>
if idon then stn <= s0; else stn<=sta; end if;
end case;
end process;
idon <= cnt?=12;
don <= idon;
END arc;
Or, you can just use a flag:
ARCHITECTURE arc OF fsm_count IS
signal st, idon: std_logic;
signal cnt: std_logic_vector (3 downto 0);
begin
process(clk) begin if rising_edge(clk) then
if sta/=s1 then cnt <= (others=>'0');
else cnt <= cnt+1; end if;
end if; end process;
idon <= cnt?=12;
process(clk) begin if rising_edge(clk) then
if rst then st <= '0';
elsif not st and start then st <= '1';
elsif st and idon then st <= '0'; end if;
end if; end process;
don <= idon;
END arc;

VHDL code works in ModelSim but not on FPGA

My VHDL-Code is functionaly correct, in ModelSim every thing works fine. I tested it with many variations and the code is functionaly correct.
But when I put it on the Altera board it displays a "3" on the 7-segment display, but it should show "0".
If I put RESET to "1" it breaks completly and displays only a line in the top segment.
My Inputs X, CLK, RESET are connected to the switches.
LOAD ist connected to a button and DIGIT to the 7-segment display.
It should have a clock signal as I swtich the CLK-switch.
Here my full code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET: IN std_logic;
LOAD: IN std_logic;
DIGIT: OUT std_logic_vector(6 DOWNTO 0) := "1111110";
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state: statetype:=s0;
SIGNAL next_state: statetype;
SIGNAL counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0):= (OTHERS => '0');
SIGNAL so: std_logic := 'U';
-------------------Aktualisierung des Zustandes--------------------------------
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
---------------------Counter---------------------------------------------------
COUNT: PROCESS (state, RESET)
BEGIN
IF (RESET = '1') THEN
counter <= (OTHERS => '0');
ELSIF (state = s4) THEN
counter <= counter + '1';
END IF;
END PROCESS COUNT;
-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15);
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
-------------------Zustandsabfrage und Berechnung------------------------------
STATE_CAL: PROCESS (so,state)
BEGIN
next_state <= state;
Y <= '0';
CASE state IS
WHEN s0 =>
IF so = '1' THEN
next_state <= s0 ;
END IF;
WHEN s1 =>
IF so = '1' THEN
next_state <= s1;
END IF;
WHEN s2 =>
IF so = '0' THEN
next_state <= s3 ;
END IF;
WHEN s3 =>
IF so = '0' THEN
next_state <= s0 ;
ELSE
next_state <= s4 ;
END IF;
WHEN s4 =>
Y <= '1';
IF so = '0' THEN
next_state <= s0;
ELSE
next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
-------------------7 Segment---------------------------------------------------
SEVEN_SEG: PROCESS (counter)
BEGIN
CASE counter IS
WHEN "000" => DIGIT <= "1111110";
WHEN "001" => DIGIT <= "0110000";
WHEN "010" => DIGIT <= "1101101";
WHEN "011" => DIGIT <= "1111001";
WHEN "100" => DIGIT <= "0110011";
WHEN "101" => DIGIT <= "1011011";
WHEN OTHERS => NULL;
END CASE;
END PROCESS SEVEN_SEG;
END SEQ;
I am pretty new to VHDL and am pretty sure it hase to do something with the timings, cause the functional part should be fine, as already said.
Hope for some hints, tips or even solutions.
EDIT: new code without LOAD, is this a valid idea? (non the less the whole code is not working on the FPGA....)
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET: IN std_logic;
LOAD: IN std_logic;
DIGIT: OUT std_logic_vector(0 TO 6) := "0000001";
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state: statetype:=s0;
SIGNAL next_state: statetype;
SIGNAL counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0):= (OTHERS => '0');
SIGNAL so: std_logic := 'U';
-------------------Aktualisierung des Zustandes--------------------------------
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
---------------------Counter---------------------------------------------------
COUNT: PROCESS (state, RESET)
BEGIN
IF (RESET = '1') THEN
counter <= (OTHERS => '0');
ELSIF (state = s4) THEN
counter <= counter + '1';
END IF;
END PROCESS COUNT;
-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (CLK'event and CLK='1') THEN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSE
so <= temp(15);
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END IF;
END PROCESS PISO;
-------------------Zustandsabfrage und Berechnung------------------------------
STATE_CAL: PROCESS (so,state)
BEGIN
next_state <= state;
Y <= '0';
CASE state IS
WHEN s0 =>
IF so = '1' THEN
next_state <= s1 ;
END IF;
WHEN s1 =>
IF so = '1' THEN
next_state <= s2;
END IF;
WHEN s2 =>
IF so = '0' THEN
next_state <= s3 ;
END IF;
WHEN s3 =>
IF so = '0' THEN
next_state <= s0 ;
ELSE
next_state <= s4 ;
END IF;
WHEN s4 =>
Y <= '1';
IF so = '0' THEN
next_state <= s0;
ELSE
next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
-------------------7 Segment---------------------------------------------------
SEVEN_SEG: PROCESS (counter)
BEGIN
CASE counter IS
WHEN "000" => DIGIT <= "0000001";
WHEN "001" => DIGIT <= "1001111";
WHEN "010" => DIGIT <= "0010010";
WHEN "011" => DIGIT <= "0000110";
WHEN "100" => DIGIT <= "1001100";
WHEN "101" => DIGIT <= "0100100";
WHEN OTHERS => DIGIT <= "0000001";
END CASE;
END PROCESS SEVEN_SEG;
END SEQ;
EDIT: This is now my version.
It will still show a "0" no matter what I do.
I would assume it has to do with the COUNT and counter.
should i realize this as synchronous too?
Is the numeric and unsigned really that big of a problem? We did it that way at university.
And will it work when i put LOAD onto a slide switch???
Best regards
Adrian
Your code has several problems. Btw. a running simulation does not mean your design is correct, because you can simulate actions which can not be implemented in hardware.
Here is a list of problems:
You can not use a switch button as a clock signal. Buttons are no clock source! Either you implement a signal cleanup circuit (at least a debounce circuit, which requires another clock) or you use you clk signal as an enable.
Moreover, each of your signals needs a debounce circuit if connected to external switch buttons or toggle buttons unless your test board has debounced buttons...
Your state machine has an init state (that's OK), but you must assign the state to state instead of next_state.
Your code uses std_logic_unsigned, which is obsolete. You should use numeric_std and the type unsigned for your counter signal.
Your code intoduces an additional register for COUT is this intended?
Your PISO process uses an asynchronous LOAD signal this is not supported in hardware (assuming an FPGA as target device).
Depending on your synthesis tool it's possible that it will not recognize a FSM because your case statement does not fit the pattern for FSMs.
Seeing a fixed output pattern can be causes by an FSM fault. If your synthesizer recognizes a FSM, you can go to the state diagram and identify false edges or false terminal states.
More ...
Your 7-segment decoder is a combinatorical process. It can not be reset.
Moreover, this process is not sensitive to CLK, just to counter. This cause a mismatch between simulation and hardware. (Synthesis ignores sensitivity lists)
If you fix this, your simulation should have another behavior and, if fixed, work as your hardware :).
The FSM
STATE_CAL : process(state, so)
begin
-- Standardzuweisungen
next_state <= state; -- Bleib im Zustand falls in CASE nichts abweichendes bestimmt wird
Y <= '0';
-- Zustandswechsel
CASE state IS
WHEN s0 =>
IF (so = '1' THEN
next_state <= s1;
END IF;
WHEN s1 =>
IF (so = '1') THEN
next_state <= s2;
END IF;
WHEN s2 =>
IF (so = '0') THEN
next_state <= s3;
END IF;
WHEN s3 =>
IF (so = '0') THEN
next_state <= s0;
else
next_state <= s4;
END IF;
WHEN s4 =>
Y <= '1'; -- Moore-Ausgabe
IF (so = '0') THEN
next_state <= s0;
else
next_state <= s2;
END IF;
END CASE;
END PROCESS;
Paebbels already described many issues of your code. Please check also the warnings of your synthesis tool. They often indicate where the synthesizer actually outputs different logic than you have described in VHDL.
I suspect you have made another two mistakes which are not directly related to VHDL:
Your 7-segment display control lines seem to be low-active because you see only one active segment when you press RESET. This matches the only zero in the vector "1111110" you assigned in this case (via reseting counter to "000").
But even in this case, the enlighted segment should be in the middle instead on the top. Thus, your pin assignments seem to be in the reverse order.

if statement not working as expected in vhdl

Below is the a part of a code describing a FSM.
clk_process : process
begin
wait until clk'event ;
if(clk ='0') then
if( state = s2) then
state <= nextstate;
end if;
elsif clk='1' then
state <= nextstate;
end if;
end process clk_process;
state <= nextstate statement is not being executed even when clk='0' , state=s2 and clk event has occurred.
Can anyone reason why this weird behavior is should. What can I do no to do what i intent to do.
Thanx
Edit 1:
library ieee;
use ieee.std_logic_1164.all;
entity machine is
port(clk : in std_logic; out1,out2 : out std_logic);
end entity;
architecture behave of machine is
type statetype is (s0,s1,s2,s3,s4);
signal state,nextstate : statetype :=s0;
begin
-- nextstate<=s0;
comb_process: process(state)
begin
case state is
when s0 =>
nextstate <= s1;
when s1 =>
nextstate <=s2;
out1 <= '1';
out2 <= '1';
when s2 =>
if(clk ='0') then
nextstate <= s3;
out2 <='1';
else
nextstate <=s2;
out1<='0';
out2<='0';
end if;
when s3 =>
nextstate <= s4;
when s4=>
nextstate <= s1;
end case;
end process comb_process;
clk_process : process
begin
wait until clk'event ;
if(clk ='0') then
if( state = s2) then
state <= nextstate;
end if;
elsif clk='1' then
state <= nextstate;
end if;
end process clk_process;
end behave;
This is my full code. What i am trying to do is when state is S2 it should be both positive and negative edge triggered
The problem with your code seems to be that your state machine will get stuck when state = s1 and nextstate = s2. When it gets to this point, the next rising clock edge will cause the clk_process block to change state <= s2. This will cause your comb_process block to trigger while clk = '1', thus causing nextstate <= s2. Once state is equal to nextstate, comb_process will never trigger again.
If you don't care about the number of states bits used for you FSM, you could simply create a state for each clock transition event.

FSM in vhdl using counter as output

I am currently writing my first FSM and am unsure of if I have the logic correct. I am tasked with creating a state diagram for the following logic:
A = 00
B = 01
C = 10
D = 11
Output is 1 when:
BDA
BAA
BAD
So I created the following vhdl code to accomplish this:
So every time I get it to output 1 I send it back to B and make count + 1. This is supposed to display on the LED as the number of times it is found in an 18 bit sequence.
Did I approach this in the correct way? I am confused on how I move it through the 18 bit sequence. I am supposed to us the swtiches on the board as my 18 bits which is represented as SW. Would I replace data_in with SW(17 downto 0)?
This is a comment not an answer I putting it in answer as I am not eligible to comment yet.
I think you have some problem in FSM concepts. Also as in the comment said data_in is std_logic not a vector.
you are taking input serially one bit at a time so accordingly write the processes. you can write code to detect the sequences BDA, BAA, BAD that is sequences "011100","010000" and "010011". I would write a simple FSM code so that you can clear you concepts then you can try.
library ieee;
use IEEE.std_logic_1164.all;
entity mealy is
port (clk : in std_logic;
reset : in std_logic;
input : in std_logic;
output : out std_logic
);
end mealy;
architecture behavioral of mealy is
type state_type is (s0,s1,s2,s3); --type of state machine.
signal current_s,next_s: state_type; --current and next state declaration.
begin
process (clk,reset)
begin
if (reset='1') then
current_s <= s0; --default state on reset.
elsif (rising_edge(clk)) then
current_s <= next_s; --state change.
end if;
end process;
--state machine process.
process (current_s,input)
begin
case current_s is
when s0 => --when current state is "s0"
if(input ='0') then
output <= '0';
next_s <= s1;
else
output <= '1';
next_s <= s2;
end if;
when s1 =>; --when current state is "s1"
if(input ='0') then
output <= '0';
next_s <= s3;
else
output <= '0';
next_s <= s1;
end if;
when s2 => --when current state is "s2"
if(input ='0') then
output <= '1';
next_s <= s2;
else
output <= '0';
next_s <= s3;
end if;
when s3 => --when current state is "s3"
if(input ='0') then
output <= '1';
next_s <= s3;
else
output <= '1';
next_s <= s0;
end if;
end case;
end process;
end behavioral;

Resources