Forum Discussion
Trying to get State Machine to Stop Glitching
Currently I am developing a sequencer that every 16 clock ticks one of the tx enables are high while the rx enables are kept high all the time. My state machine is working occasionally although I have sudden glitches in it which causes for my code to go off course. I have attached the signal scope of this to the forum post. Does anyone have an idea of what could have caused this?
http://www.alteraforum.com/forum/attachment.php?attachmentid=11082&stc=1 code LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_textio.ALL; USE IEEE.numeric_bit.ALL; USE IEEE.numeric_std.ALL; LIBRARY STD; USE STD.textio; ENTITY TOP IS GENERIC (txNum : INTEGER := 5); PORT ( clkrx : IN std_logic; txen_1 : OUT std_logic; txen_2 : OUT std_logic; txen_3 : OUT std_logic; txen_4 : OUT std_logic; txen_5 : OUT std_logic; rxen_1 : OUT std_logic; rxen_2 : OUT std_logic; rxen_3 : OUT std_logic; rxen_4 : OUT std_logic; rxen_5 : OUT std_logic; clkout : OUT std_logic ); END TOP; ARCHITECTURE behavioral OF TOP IS CONSTANT s0 : STD_LOGIC_vector(2 DOWNTO 0) := "000"; CONSTANT s1 : STD_LOGIC_vector(2 DOWNTO 0) := "001"; CONSTANT s2 : STD_LOGIC_vector(2 DOWNTO 0) := "010"; CONSTANT s3 : STD_LOGIC_vector(2 DOWNTO 0) := "011"; CONSTANT s4 : STD_LOGIC_vector(2 DOWNTO 0) := "100"; CONSTANT s5 : STD_LOGIC_vector(2 DOWNTO 0) := "101"; SIGNAL current_s : STD_LOGIC_vector(2 DOWNTO 0) := s5; --current and next state declaration. SIGNAL next_s : STD_LOGIC_vector(2 DOWNTO 0) := s0; SIGNAL cnt : INTEGER RANGE 0 TO 16 := 0; SIGNAL p : BOOLEAN := false; BEGIN PROCESS (clkrx) BEGIN IF (rising_edge(clkrx)) THEN IF (cnt = 0) THEN current_s <= next_s; cnt <= cnt + 1; p <= true; ELSIF (cnt = 16) THEN current_s <= next_s; cnt <= cnt + 2; ELSE cnt <= cnt + 1; END IF; END IF; END PROCESS; PROCESS (clkrx, current_s, p) BEGIN IF (p) THEN clkout <= clkrx; END IF; END PROCESS; --state machine process. PROCESS (current_s) BEGIN CASE current_s IS WHEN s0 => --when current state is "s0" rxen_1 <= '1'; rxen_2 <= '1'; rxen_3 <= '1'; rxen_4 <= '1'; rxen_5 <= '1'; txen_1 <= '1'; txen_2 <= '0'; txen_3 <= '0'; txen_4 <= '0'; txen_5 <= '0'; IF (txNum = 1) THEN next_s <= s0; ELSE next_s <= s1; END IF; WHEN s1 => --when current state is "s1" rxen_1 <= '1'; rxen_2 <= '1'; rxen_3 <= '1'; txen_1 <= '0'; txen_2 <= '1'; txen_3 <= '0'; txen_4 <= '0'; txen_5 <= '0'; IF (txNum = 2) THEN next_s <= s0; ELSE next_s <= s2; END IF; WHEN s2 => --when current state is "s2" rxen_1 <= '1'; rxen_2 <= '1'; rxen_3 <= '1'; rxen_4 <= '1'; rxen_5 <= '1'; txen_1 <= '0'; txen_2 <= '0'; txen_3 <= '1'; txen_4 <= '0'; txen_5 <= '0'; IF (txNum = 3) THEN next_s <= s0; ELSE next_s <= s3; END IF; WHEN s3 => --when current state is "s3" rxen_1 <= '1'; rxen_2 <= '1'; rxen_3 <= '1'; rxen_4 <= '1'; rxen_5 <= '1'; txen_1 <= '0'; txen_2 <= '0'; txen_3 <= '0'; txen_4 <= '1'; txen_5 <= '0'; IF (txNum = 4) THEN next_s <= s0; ELSE next_s <= s4; END IF; WHEN s4 => rxen_1 <= '1'; rxen_2 <= '1'; rxen_3 <= '1'; rxen_4 <= '1'; rxen_5 <= '1'; txen_1 <= '0'; txen_2 <= '0'; txen_3 <= '0'; txen_4 <= '0'; txen_5 <= '1'; next_s <= s0; WHEN OTHERS => rxen_1 <= '1'; rxen_2 <= '1'; rxen_3 <= '1'; rxen_4 <= '1'; rxen_5 <= '1'; txen_1 <= '1'; txen_2 <= '0'; txen_3 <= '0'; txen_4 <= '0'; txen_5 <= '0'; next_s <= s0; END CASE; END PROCESS; END behavioral;4 Replies
- Altera_Forum
Honored Contributor
I'm not sure what's causing the problem, but you have a bug in your counter code:
You are defining a range from 0 to 16, but when you reach 16 you still increase the counter, getting out of range. This kind of behaviour is undefined in VHDL (and will cause an error in a simulator). I'm not sure what Quartus synthesizes in this case, but it's quite possible that it's an +1 adder that works fine with numbers from 0 to 16 and gives strange results for other values. Try this instead:SIGNAL cnt : INTEGER RANGE 0 TO 16 := 0; PROCESS (clkrx) BEGIN IF (rising_edge(clkrx)) THEN IF (cnt = 0) THEN current_s <= next_s; cnt <= cnt + 1; p <= true; ELSIF (cnt = 16) THEN current_s <= next_s; cnt <= cnt + 2; ELSE cnt <= cnt + 1; END IF; END IF; END PROCESS;
It will synthesize as a regular adder, and uses one bit less. Which clock frequency are you using for this design? Did you constrain your project for Timequest?SIGNAL cnt : INTEGER RANGE 0 TO 15 := 0; PROCESS (clkrx) BEGIN IF (rising_edge(clkrx)) THEN IF (cnt = 0) THEN current_s <= next_s; cnt <= cnt + 1; p <= true; ELSIF (cnt = 15) THEN cnt <= 0; ELSE cnt <= cnt + 1; END IF; END IF; END PROCESS; - Altera_Forum
Honored Contributor
There are some issues with this code:
The rxen_x and txen_x signals are not all assigned in every state - this is going to form latches that could cause odd timing problems,. With an asynchronous process ALL signals must be assigned in ALL starts to prevent the formation of latches.The easy way around this is to assign each signal a default (including next_s) before the case statement. This gives each signal a value should it not be assigned somewhere else (it also must be an explicit value, not itself - that is a latch). Where does clkrx come from? Why is clkout assigned from clkrx based on p? p is true after the first clock. Routing clocks like this is a really bad idea. Apart from latching the clock (which is a bad idea), when you simulate the design, clkout is going to be 1 delta behind clkrx, which is going to do some odd things in your simulation and you probably wont have a clue whats going on. Moral of the story - use the same clock everywhere, dont use assigned versions. - Altera_Forum
Honored Contributor
I began to rewrite the code to get rid of some of the unnecessary factors mentioned above and developed this code bellow. Even after doing all that my code still glitches.
https://www.alteraforum.com/forum/attachment.php?attachmentid=11099 library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_textio.all; use IEEE.std_logic_unsigned.all; library STD; use STD.textio; ENTITY state_machine IS generic(txNum:integer:=5); PORT( clk : IN STD_LOGIC; reset : IN STD_LOGIC; txen_1 : out std_logic; txen_2 : out std_logic; txen_3 : out std_logic; txen_4 : out std_logic; txen_5 : out std_logic; rxen_1 : out std_logic; rxen_2 : out std_logic; rxen_3 : out std_logic; rxen_4 : out std_logic; rxen_5 : out std_logic); END state_machine; ARCHITECTURE a OF state_machine IS constant s0:STD_LOGIC_vector(2 downto 0):="000"; constant s1:STD_LOGIC_vector(2 downto 0):="001"; constant s2:STD_LOGIC_vector(2 downto 0):="010"; constant s3:STD_LOGIC_vector(2 downto 0):="011"; constant s4:STD_LOGIC_vector(2 downto 0):="100"; constant s5:STD_LOGIC_vector(2 downto 0):="101"; signal state: STD_LOGIC_vector(2 downto 0):=s0; signal cnt:STD_LOGIC_VECTOR(3 DOWNTO 0):="0000"; BEGIN process(clk) begin if(rising_edge(clk))then cnt<=cnt+1; end if; end process; PROCESS (clk,reset) BEGIN IF reset = '1' THEN state <= s0; ELSIF (rising_edge(clk)) THEN CASE state IS WHEN s0=> state <= s1; WHEN s1=> if(cnt="1111")then if(txNum=1)then state <= s1; else state <= s2; end if; else state <= s1; end if; WHEN s2=> if(cnt="1111")then if(txNum=2)then state <= s1; else state <= s3; end if; else state <= s2; end if; WHEN s3=> if(cnt="1111")then if(txNum=3)then state <= s1; else state <= s4; end if; else state <= s3; end if; WHEN s4=> if(cnt="1111")then if(txNum=4)then state <= s1; else state <= s5; end if; else state <= s4; end if; WHEN s5=> if(cnt="1111")then state <= s1; end if; when others=> state<=s1; END CASE; END IF; END PROCESS; PROCESS (state) BEGIN rxen_1<='1'; rxen_2<='1'; rxen_3<='1'; rxen_4<='1'; rxen_5<='1'; CASE state IS WHEN s0 => txen_1<='0'; txen_2<='0'; txen_3<='0'; txen_4<='0'; txen_5<='0'; WHEN s1 => txen_1<='1'; txen_2<='0'; txen_3<='0'; txen_4<='0'; txen_5<='0'; WHEN s2 => txen_1<='0'; txen_2<='1'; txen_3<='0'; txen_4<='0'; txen_5<='0'; when s3=> txen_1<='0'; txen_2<='0'; txen_3<='1'; txen_4<='0'; txen_5<='0'; when s4=> txen_1<='0'; txen_2<='0'; txen_3<='0'; txen_4<='1'; txen_5<='0'; when s5=> txen_1<='0'; txen_2<='0'; txen_3<='0'; txen_4<='0'; txen_5<='1'; when others=> txen_1<='1'; txen_2<='0'; txen_3<='0'; txen_4<='0'; txen_5<='0'; END CASE; END PROCESS; END a; - Altera_Forum
Honored Contributor
These are not glitches, these are functions of your code. Glitches are when you get small changes in signal usually less than 1 clock period due to analogue signal operations.
Here, you have problems because of bugs in your code. You need to write a testbench to debug the design without going on to hardware.