UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor lhochstetter
Visitor
4,524 Views
Registered: ‎08-18-2016

LED pulse width modulation

Hi everyone,

 

me once again with another problem (predecessor can be found here): I want to drive 8 LEDs at different frequencies and came up with the following code:

 

#include <stdbool.h>

#include "led_controller.h"
#include "../../shared/data_structures.h"

unsigned char led_o;

struct led_bitfield {
	unsigned char led_0 : 1;
	unsigned char led_1 : 1;
	unsigned char led_2 : 1;
	unsigned char led_3 : 1;
	unsigned char led_4 : 1;
	unsigned char led_5 : 1;
	unsigned char led_6 : 1;
	unsigned char led_7 : 1;
};

union leds {
	struct led_bitfield led_bits;
	unsigned char led_mask;
};

void apply_led_config(struct led_config config[LED_COUNT])
{
	static unsigned int ticks[LED_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	static bool toggle[LED_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	static union leds led_states;
////////////////////////////////////////////////////////////////////////////////
	if (config[0].threshold_on == ticks[0] && toggle[0]) {
		toggle[0] = 0;
		ticks[0] = 0;
	} else if (config[0].threshold_off == ticks[0] && !toggle[0]) {
		toggle[0] = 1;
		ticks[0] = 0;
	}

	if (0 == ticks[0]) {
		led_states.led_bits.led_0 = toggle[0];
	}
	ticks[0]++;
////////////////////////////////////////////////////////////////////////////////
...
	led_o = led_states.led_mask;
}

The code contained in /'s (first LED) is replicated for the remaining 7 LEDs.

 

My idea is quite simple: each LED has its own configuration (struct led_config config[LED_COUNT], led_config is a simple struct containing two unsigned ints: threshold_on and threshold_off) which allows to define a number of ticks the LED is lit / dark.

 

I have 8 independent counters (ticks), which are set to 0 when the corresponding LED is toggled.

 

The bit field / union holds the led states inbetween to clock signals.

 

led_o = led_states.led_mask;

 writes the LED states to the physical LED pins.

 

I did achice II=1 to count the clock cycles but my execution time is to high

 

	WARNING: [SCHED 204-21] Estimated clock period (11ns) exceeds the target (target clock period: 10ns, clock uncertainty: 1.25ns, effective delay budget: 8.75ns).
WARNING: [SCHED 204-21] The critical path consists of the following:
    'phi' operation ('toggle_0_loc', led_controller.c:32) with incoming values : ('toggle_0_load', led_controller.c:32) (0 ns)
    'bitconcatenate' operation ('tmp_7', led_controller.c:41) (0 ns)
    'select' operation ('led_states_loc', led_controller.c:40) (1.37 ns)
    'select' operation ('led_states_new_1', led_controller.c:55) (1.37 ns)
    'select' operation ('led_states_new_2', led_controller.c:70) (1.37 ns)
    'select' operation ('led_states_new_3', led_controller.c:85) (1.37 ns)
    'select' operation ('led_states_new_4', led_controller.c:101) (1.37 ns)
    'select' operation ('led_states_new_5', led_controller.c:116) (1.37 ns)
    'select' operation ('led_states_new_6', led_controller.c:131) (1.37 ns)
    'select' operation ('led_states_new_7', led_controller.c:146) (1.37 ns)

 I understand that the if's which assign new values in the bit field are the issuse, but I don't know how to access the bits of the unsigned char I'm using to write the LED states to the physical pins idependently and concurrently.

 

Any ideas how I can meet the target clock while maintaining II=1? (I'd also like to keep the unsigned char for easy writing to the LEDs - however if there is a "better" way like using a bitfield all the way etc. which will result in a single port on the IP I'll go with it ... and HDL isn't an option unfortunately)

0 Kudos
2 Replies
Xilinx Employee
Xilinx Employee
4,499 Views
Registered: ‎08-01-2008

Re: LED pulse width modulation

use DDS core

http://www.xilinx.com/support/documentation/ip_documentation/dds_compiler/v6_0/pg141-dds-compiler.pdf
Thanks and Regards
Balkrishan
--------------------------------------------------------------------------------------------
Please mark the post as an answer "Accept as solution" in case it helped resolve your query.
Give kudos in case a post in case it guided to the solution.
0 Kudos
Visitor lhochstetter
Visitor
4,410 Views
Registered: ‎08-18-2016

Re: LED pulse width modulation

Thanks for your reply, I skimmed the linked document. The DDS core is a little bit overkill for what I intend to do.

I managed to get the time down to 8.9ns while maintaining II=1

 

#include <stdbool.h>

#include "led_controller.h"
#include "../../shared/data_structures.h"

bool led_o[LED_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0 };

void apply_led_config(struct led_config config[LED_COUNT]) {
	static unsigned int ticks[LED_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0 };
	static bool toggle[LED_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0 };

	for (char i = 0; i < LED_COUNT; i++) {

		if (config[i].threshold_on == ticks[i] && toggle[i]) {
			toggle[i] = 0;
			led_o[i] = 0;
			ticks[i] = 0;
		} else if (config[i].threshold_off == ticks[i] && !toggle[i]) {
			toggle[i] = 1;
			led_o[i] = 1;
			ticks[i] = 0;
		}

		ticks[i]++;
	}
}
set_directive_array_partition -type complete -factor 8 -dim 1 "apply_led_config" config
set_directive_interface -mode s_axilite -bundle a "apply_led_config" config

set_directive_interface -mode s_axilite -bundle a "apply_led_config"
set_directive_pipeline -II 1 "apply_led_config"

set_directive_array_partition -type complete -factor 8 -dim 1 "apply_led_config" led_o
set_directive_interface -mode ap_none -register "apply_led_config" led_o

The code is pretty straight forward.You need the toggle array, otherwise VHLS complains when performing reads / writes on led_o IIRC due to data races.


I used a xlconcat IP Core to combine the led_o_i[0:0] ports to one led_o[7:0] port.

Interesstingly enough, Vivado doesn't complain about timing issues. How accurate are the VHLS estimates?

0 Kudos