CPLD LED Fading

Program Download:

VHDL/Project Archive
cpld_led_fading.vhd
PLD_DIM_LED.zip

The Software
           The VHDL module we'll write to fade LEDs is surprisingly and thankfully simple. It's a combo of our log table and a few counters, thus the code is split into two main parts:
    -Logrithmic Value Table
    -PWM Generation Counters

           The table of values is hardcoded in a ROM inside the VHDL. Then when a value is needed the PWM counters insert an address into the ROM and the ROM spits out the correlating logarithmic value.

VHDL ROM

------------« Begin Code »------------
type nums is array(0 to 31) of integer;
constant my_nums : nums := (
	0	=>		0,
	1	=>		2,
	2	=>		4,
	3	=>		6,
	4	=>		8,
	5	=>		10,
	6	=>		12,
	7	=>		15,
	8	=>		18,
	9	=>		21,
	10	=>		24,
	11	=>		28,
	12	=>		31,
	13	=>		34,
	14	=>		38,
	15	=>		42,
	16	=>		46,
	17	=>		51,
	18	=>		56,
	19	=>		61,
	20	=>		66,
	21	=>		72,
	22	=>		85,
	23	=>		93,
	24	=>		102,
	25	=>		112,
	26	=>		123,
	27	=>		137,
	28	=>		153,
	29	=>		174,
	30	=>		204,
	31	=>		255
);		
------------« End Code »------------

           The Main PWM generation code uses some counters and a constant period of 256 clock cycles. A seperate counter constantly counts up to 31 and back to 0, this is what tells the ROM which 0-255 value to use in the main PWM loop.

PWM Pulse Generation

------------« Begin Code »------------
	IF(RISING_EDGE(clk))THEN

	--1 Period = 512 Clock Cycles
		--Nevative Duty Cycle
		IF(pwm_cnt = 256-my_nums(int_cnt_0))THEN
			pwm_cnt := pwm_cnt + 1;
			LED_OUTPUT(9 DOWNTO 5) <= "00000";
			LED_OUTPUT(4 DOWNTO 0) <= "11111";
		--Positive Duty Cycle
		ELSIF(pwm_cnt = 256+my_nums(int_cnt_0))THEN
			pwm_cnt := 0;
			LED_OUTPUT(9 DOWNTO 5) <= "11111";			
			LED_OUTPUT(4 DOWNTO 0) <= "00000";
		ELSE
			pwm_cnt := pwm_cnt + 1;
		END IF;
		
		--Clk_Cnt here will set how fast the LEDs fade in and out.
		IF(clk_cnt = 500000)THEN
		
			--Increment
			IF(direction = 0)THEN
				IF(int_cnt_0 = 31)THEN
					direction := 1;
				ELSE
					int_cnt_0 := int_cnt_0 + 1;
				END IF;	
					clk_cnt := 0;
			--Decrement
			ELSE
				IF(int_cnt_0 = 1)THEN
					direction := 0;
				ELSE
					int_cnt_0 := int_cnt_0 - 1;
				END IF;	
					clk_cnt := 0;			
			END IF;
					
		ELSE	
			clk_cnt := clk_cnt + 1;
		END IF;	
	
	END IF;
------------« End Code »------------

           After all that wire wrapping and code writing, let's program the CPLD and see how well it works!