Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
19 years ago

Cyclone II is not working correct???

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

11 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.