Creating my first FSM using VHDL to control 20 leds RGB

Status
Not open for further replies.

kkdelabaca

Full Member level 2
Joined
Apr 18, 2003
Messages
140
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,298
Visit site
Activity points
1,105
Hello,

to control 20 RGB leds I need to create one easy sequence:



This sequence consist in create one Reset of 50us, and then send 480 pulses. I'm using one CPLD from altera and my system clock is 60MHz.

Reset duration = 50us (3000 clock's @60MHz).
The board have 20 leds connected in serial. Each led have 3 registers of 8 bits (one for Red, other for Green and other for Blue). Now to fill all the registers I need to send 480 pulses (20 leds x 3 registers x 8 bits).

Each pulse have one specific duty cycle:
- 400ns at positive duty (24 sys clock) and 850ns at negative duty (51 clock's).

I tried to create this sequence in Quartus II but the result is bad. Is my first program and I think that I have problems of metastability.

Somebody can suggest to me how I can start with this sequence?

Thanks a lot!
 

1. Run a simulation with Modelsim and get that working.
2. Once you have that working, post something more informative than just that it is 'bad'.

Kevin Jennings
 

Hello K-J,

this is the VHDL Code. The main problem is that the counter CountSTATUS is always '0'. Why?
Thanks!

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity ANELL_LEDS_v1 is
	
	port (clk, rst: in std_logic;						-- I/O definitions
		  DataOut : out std_logic);						-- Serial Output
          
end ANELL_LEDS_v1;

architecture FSM_LEDS of ANELL_LEDS_v1 is

	signal CountCLK: std_logic_vector(15 downto 0):= "0000000000000000";  -- Count the number of clk's inside each State
	signal CountSTATUS: std_logic_vector(9 downto 0):= "0000000000";      -- Content the actual State (Reset + 480)
	
begin	
	
	process(clk, rst) begin						
		if rst='0' then										-- WHEN RESET	
			CountCLK <= "0000000000000000";
			CountSTATUS <= "0000000000";	
					
		elsif (clk'event and clk='1') then			
		
			CountCLK <= CountCLK +1;
		
			case CountSTATUS is
				when "0000000000" => if CountCLK = 3000 then
						                 CountSTATUS <= CountSTATUS + 1;
						                 CountCLK <= "0000000000000000";
					                         end if;
					
				when "0000000001" =>  if    CountCLK < 22 then	DataOut <= '1';
						     elsif CountCLK < 76 then	DataOut <= '0';
						      else 	CountSTATUS <= "0000000010";        
					                        CountCLK <= "0000000000000000";	
					                  end if;				
				
				when "0111100010" => CountSTATUS <= "0000000000";       
					                 CountCLK <= "0000000000000000";	 
				 	
				when others =>        if    CountCLK < 22 then	DataOut <= '1';
						elsif CountCLK < 76 then	DataOut <= '0';
						else 	CountSTATUS <= CountSTATUS + 1;       
					                CountCLK <= "0000000000000000";	    
					        end if;		
			end case;	
		end if;
	end process;
		
end FSM_LEDS;
 

In the simulator, set a breakpoint at the start of the process and then single step through each statement. Debugging in that manner will go much quicker than posting to a newsgroup like you're doing now... don't ask people to do work that you're unwilling to even try to do yourself.

Kevin Jennings
 
Thanks for your answers,

sorry but I'm working with Quartus II and I think that this program don't have breakpoints to simulate step by step the source code.

For example, in the next code I don't understand some things:
- Why the output called "FlagOut" is not always '0' when the counter "CountSTATUS" is "0000000000".



- After the state "0000000001", why the CountSTATUS is "0000000000" and not "0000000010"?



- One other question is what the program don't generate error when I'm assigning multiple values to the same signal? For example :
* CountCLK <= CountCLK +1; -- The counter increments her value in each clk
* CountCLK <= "0000000000000000"; -- In some cases the counter is reset

PHP:
	process(clk, rst) begin						
		if rst='0' then											
			CountCLK <= "0000000000000000";
			CountSTATUS <= "0000000000";	
					
		elsif (clk'event and clk='1') then			
		
			CountCLK <= CountCLK +1;
		
			case CountSTATUS is
				when "0000000000" => FlagOut <= '0';
									 if CountCLK = 3000 then
						                CountSTATUS <= CountSTATUS + 1;
						                CountCLK <= "0000000000000000";
					                 end if;			
				
				when "0111100010" => CountSTATUS <= "0000000000";       
					                 CountCLK <= "0000000000000000";	 
				 	
				when "0000000001" => FlagOut <= '1';
									 if    CountCLK < 22 then	DataOut <= '1';
									 elsif CountCLK < 76 then	DataOut <= '0';
									 else  CountSTATUS <= "0000000010";        
					                       CountCLK <= "0000000000000000";	    
					                 end if;	 	
				 	
				when others =>       if CountCLK < 22 then	DataOut <= '1';
									 elsif CountCLK < 76 then	DataOut <= '0';
									 else  CountSTATUS <= CountSTATUS + 1;        
					                        CountCLK <= "0000000000000000";	    
					                 end if;		
			end case;	
		end if;
	end process;

Thanks again for your help!
 

Hello,

Finally I solved the problem! The problem was in the simulation (I just inspected the least significant bit of my data CountSTATUS), not in the VHDL code.

By the way… how I can create one structure of data with 20 leds and in each led 3 bytes corresponding to Red, Green and Blue? And then how I can access to each byte or bit?

Thanks again!
 

By the way… how I can create one structure of data with 20 leds and in each led 3 bytes corresponding to Red, Green and Blue? And then how I can access to each byte or bit?

Here is one method, there are others:
type t_LEDS is (Red, Green, Blue);
type t_LED_BYTES is array(t_LEDS) of unsigned(7 downto 0);
type t_arr_LED_BYTES is array(1 to 20) of t_LED_BYTES;
signal My_Leds: t_arr_LED_BYTES;

My_Leds(1) -- Refers to the first LED
My_Leds(1)(Red) -- Refers to the first 'Red' element
My_Leds(1)(Red)(3 downto 0) -- Refers to the lower nibble of the first 'Red' element

By the way, since you're using Quartus, you should have access to Modelsim as well (or download it from Altera). You should consider using learning how to use Modelsim to debug, then you would be able to compile and debug your source code directly without having to use Quartus.

Kevin Jennings
 
Once again another poster that doesn't know how to count out 3000 clocks starting from 0.

0-2999-0-2999-0 etc cycles for 3000 clocks each time.

if CountCLK = 3000 then
cycles for 0-3000-0-3000-0 etc.
Since you have to reach 3000 before you can make CountCLK 0 again.

What is up with so many posters having problems with simple counting? So if I say count out ten numbers from 20: so 20,21,22,23,24,25,26,27,28,29,30 is the answer? Well here is a hint: It's not!.

- - - Updated - - -

Looking at your code you don't seem to have an idea how to approach the problem. Your FSM should be controlling what the counters are doing. e.g. I'm in the 50us reset phase. I'm in the 480 pulse phase. The FSM would monitor that there have been 480 pulses then return to the reset state.

I see there is a 0-2999 counter that could be used to both count the 0-2999 50us reset and the 0-74 pulse period. Determining which way you are counting is signaled by the FSM. e.g. do_reset and do_pulse.

If the FSM is in do_reset you count from 0-2999 and when you are in do_pulse you count from 0-74 repeatedly. Another counter monitors that you've output 480 pulses. Not 483 like you have in your code now. 0111100010 is 482 and since you start from 0 you generate 483 pulses. When you reach the end of pulse 481. i.e pulse_cnt = 481 and CountCLK = 74 then you go back to the reset state.
 
Thanks a lot of your comments,

The objective of this code is learn and understand how create the program, compile, simulate,… After program the CPLD I have verified the timing, the pulses and I have edited the program.

The next step is send to the leds the information of the array of 20 elements (not only 480 pulses with '1').

For me is completely clear that I'm a beginner and this forum is a good opportunity to learn and ask questions to people more experimented. Thanks!
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…