- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
11 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ups, sorry, my mistake.
I will try this out. Thank you.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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??- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
did you verify the issues I pointed out in my previous post?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Okay, shame on me.
With the D-FF it is working perfectly. Thank you very much.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page