Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20705 Discussions

Cyclone II is not working correct???

Altera_Forum
Honored Contributor II
1,846 Views

Hello, 

 

I have written a small process, which should read a dmx-signal (seriell signal with special timings).  

THe whole thing is working realy good, but sometimes it makes things, which i haven`t programmed. 

The dmx-reader is a state machine and sometimes, one state changes into another, which i haven`t writen (states which are never assigned occurs or the state change is not correct). 

 

This is the source code for the state machine (it runs at 10MHz). 

 

process (pwm_clock) variable divider : integer := 0; variable state : bit_vector (3 downto 0) :="0000"; variable dmx_data : std_logic_vector (0 to 7) :="00000000"; variable dmx_bit_value : integer := 0; variable dmx_bit_count : integer := 0; variable dmx_data_count : integer range 0 to 255 := 0; variable dmx_data_position : integer range 0 to 511 := 0; begin if (rising_edge(pwm_clock)) then divider := divider +1; if(divider > 1) then divider := 0; -- different states case state is -- waiting for startbit when "0000" => case check(dmx_in) is when '0' => dmx_bit_value := dmx_bit_value +1; when '1'=> if(dmx_bit_value > 430) then state := "0001"; elsif(dmx_bit_value > 200) and (dmx_data = "00000000") then state := "0001"; end if; dmx_bit_value := 0; dmx_data_position := 0; when others => null; end case; -- waiting for Mark after Break when "0001" => case check(dmx_in) is when '1' => dmx_data_count := dmx_data_count +1; when '0' => if(dmx_data_count > 38) then state := "0010"; dmx_data_count := 0; else dmx_data_count := 0; end if; when others => null; end case; -- waiting for Start Byte and startbit when "0010" => case check(dmx_in) is when '0' => dmx_data_count := dmx_data_count +1; when '1'=> if(dmx_data_count > 178) then state := "0011"; dmx_data_count := 0; else state := "0000"; dmx_data_count := 0; end if; when others => null; end case; -- waiting for 2 stopbits when "0011" => case check(dmx_in) is when '1'=> dmx_data_count := dmx_data_count +1; when '0'=> if(dmx_data_count > 38) then state := "0100"; dmx_data_count := 0; else state := "0000"; dmx_data_count := 0; end if; when others => state := "0000"; dmx_data_count := 0; end case; --receive startbit, after the startbit, you have to wait for 2 clocks, to sync back to the signal when "0100" => dmx_data_count := dmx_data_count +1; if(dmx_data_count > 17) then if(dmx_bit_value > 13)then state := "0101"; else state:="0000"; end if; dmx_data_count := 0; dmx_bit_value := 0; end if; case check(dmx_in) is when '0' => dmx_bit_value := dmx_bit_value +1; when others => null; end case; -- Wait 2 clock (to avoid the signal flanks) when "0101" => dmx_data_count := dmx_data_count +1; if(dmx_data_count > 1) then state :="0110"; dmx_data_count := 0; dmx_bit_value := 0; dmx_bit_count :=0; end if; -- Receive the data_bytes when "0110" => -- Receive for 19 Clocks and check the signal case check(dmx_in) is when '1'=> dmx_bit_value := dmx_bit_value +1; when others => null; end case; dmx_data_count := dmx_data_count +1; if(dmx_data_count > 17) then -- if more then 14 received bits are '1' then the transmitted bit is 1 if(dmx_bit_value > 13) then dmx_data(7-dmx_bit_count) := '1'; else dmx_data(7-dmx_bit_count) := '0'; end if; dmx_data_count := 0; dmx_bit_count := dmx_bit_count +1; state :="0111"; end if; -- wait for 2 Clocks (to avoid the signal flanks) when "0111" => dmx_data_count := dmx_data_count +1; if(dmx_data_count > 1) then state :="0110"; dmx_data_count := 0; dmx_bit_value := 0; -- check if 8 bits are received if(dmx_bit_count > 7) then dmx_bit_count := 0; dmx_data_count := 0; state:="1000"; end if; end if; -- wait for the 2 Stopbits and check, if the signal is correct, or if it is a new start signal when "1000" => case check(dmx_in) is when '1' => dmx_bit_value := dmx_bit_value +1; when others => null; end case; dmx_data_count := dmx_data_count +1; if(dmx_data_count > 38) then if(dmx_bit_value > 30) then dmx_pwm_integer_value(dmx_data_position) := conv_integer(dmx_data); --leds <= dmx_data; dmx_data_position := dmx_data_position +1; dmx_bit_value := 0; state :="1001"; else state :="0000"; end if; dmx_data_count := 0; end if; -- wait for the next startbit when "1001" => if(check(dmx_in) = '0') then state := "0100"; end if; when others =>state:="0000"; end case; end if; end if; end process; 

 

Examples of wrong state changes: 

Here the State machine changes from 1001b to 1010b which is not declared (it should change to 0100b. 

 

http://ej-lighting.at/stp1.jpg  

 

A change from 1001b to 1011b which is never declared!! 

 

http://ej-lighting.at/stp2.jpg  

 

 

At the moment I have no Idea what could be wrong in this implementation. 

 

Thanks 

 

Thomas Brunner
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
562 Views

Without having looked into any details of your design I would ask:  

are all inputs to you statemachine syncronized before entering? I.e. they should pass at least one DFF clocked at the same clock as the SM. If not, you may end up having metastable state FF's, which will manifest exactly what you see: Erratic performance now and then. 

Second point is: Check for warnings in timing analyser.
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

 

--- Quote Start ---  

Hello, 

Examples of wrong state changes: 

Here the State machine changes from 1001b to 1010b which is not declared (it should change to 0100b. 

 

A change from 1001b to 1011b which is never declared!! 

 

Thanks 

 

Thomas Brunner 

--- Quote End ---  

 

Took a quick look; 

 

First, according to the simulation image. The state does not change from 1001b to 1010b. It chages to 0101b (5 hexadecimal as it is shown in simulation top row). Remember STATE is declared 3 DOWNTO 0. Same in the next image. It changes to 1101b (D.hex). Those states are declared. 

 

I suggest using signals instead of variables. Especially for the STATE vector. 

Use signals for everything that should keep their assigned value until the next time the process is evaluated. See variables as temporary storage within a process only.
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

Ups, sorry, my mistake. 

I will try this out.  

Thank you.
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

QuartusII has some features to assist with Finite State Machine development: 

 

(1) "Tools / Netlist viewers / State Machine viewer" shows a graphical and table based interpretation of your synthesized state machine. This allows you to see how the tool interprets your design. Left-click to select any state and the viewer also highlights it in the state transition table; conversely you can select a state in the table and the corresponding bubble will be highlighted. The normal zoom hotkeys also work here (CNTL-Space, CNTL-Shift-Space, etc.). 

 

(2) In the report file (CNTL-R to open) under "Analysis & Synthesis / State Machines" you should see a list of any state machines in the project. For each FSM the tool shows a table of the encoded state variables. If your state machine is encoded for one-hot, note that the LSB will be inverted; this allows the register clear after configuration to place the FSM into a legal state. 

 

(3) To influence how your design is processed you can work with two assignments, both under "Assignments / Settings / Analysis & Synthesis / More Settings". The first is "Safe State Machine" which when enabled adds additional logic to account for and recover from undefined states. The second is "State Machine Processing" which controls the state bit encoding scheme.
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

In addition QuartusII has some settings to Auto Set up State Machine and which FSM has to generate if you set AUTO to ON. (ex. One Shot). 

When QII recognize a FSM, it converts and increase the efficiency of the states coding by itself. If you don't want this, set the variable to OFF. 

 

Have a look in the Assignments in QII. 

bye
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

I have changed the state into a signal, but the situation haven`t changed.  

Furthermore Quartus II doesn´t recognizes my state machine and there are no timing warnings. I have also changed the settings for state machines. 

 

For me the confusing thing is, that sometimes, the whole dmx-read-process is working very well, and then it changes into a state which isn`t assigned at this step. 

(last state "1001" should change the state into "0100", but sometimes it changes into "0000"). 

And obviously there are some illegal states, because when i delete the "when others" section, the dmx-read_process is not responding after a short period of time).  

 

I have tried to create the state machine as described in the Quartus II documentation with a own type for state, but if i do so, the whole thing is working only for a short period of time and then it is not longer responding to input data. 

 

So, are there any other suggestions??
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

did you verify the issues I pointed out in my previous post?

0 Kudos
Altera_Forum
Honored Contributor II
562 Views

 

--- Quote Start ---  

did you verify the issues I pointed out in my previous post? 

--- Quote End ---  

 

 

I am sorry, but I have no idea how to use a D-FF to synchronize the state??? I could use 4 of them as a storage, but this makes no sense to me.
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

Larsen has a point here.  

Take a look at the "check(dmx_in)". What is the source of the dmx_in signal? Is it clocked somewhere before entering the state machine? Or is it an external signal coming directly from a pin or from another clock domain? 

Sounds like a timing or meta-stability problem when the behaviour is erratic.
0 Kudos
Altera_Forum
Honored Contributor II
562 Views

The dmx_in is an external signal. I will try to use a d-ff to store it, put i don`t think that this could be the problem.

0 Kudos
Altera_Forum
Honored Contributor II
562 Views

Okay, shame on me. 

With the D-FF it is working perfectly. 

 

Thank you very much.
0 Kudos
Reply