This reference design shows how to fade LEDs using pulse width modulation. In this design, the two LEDs on the MAX V CPLD Development Board will fade up and down in response to input from the two push buttons. Fading is accomplished by pulse width modulation (PWM) with a configurable number of duty cycles, which correspond to fade levels. The number of fade levels, the number of LEDs and the total fade time between fully off and fully on are set as parameters to the led_fader module. For this design, the led_fader module is instantiated with parameters set for two LEDs, 25 fade steps, and a total fade time of one second. The push buttons are connected to the control inputs of the led_fader module, so each LED will fade on when the corresponding button is pressed and fade off when the button is released. In addition to the Quartus II project, a test bench file and related TCL scripts are included for simulation in ModelSim.
The top level module of this design is the led_fader_example module. As shown in Figure 1, this module instantiates the led_fader module and contains ports for the system clock (clk), the push button inputs (pb0, pb1), and the LED outputs (led0, led1). On the MAX V CPLD Development Board, these ports correspond to pins H5 (clk), M9 (pb0), R3 (pb1), P4 (led0), and R1 (led1). Parameters of the led_fader module are used to set the number of LEDs, the number of discrete fade levels and the total fade time. Details about these parameters are provided in the next section.
Figure 1 – The led_fader module instantiating clk_div and led_single_fader modules Led_fader_fig1.png (Click here for image)
The led_fader module instantiates a clock divider (clkdiv) and a configurable number of individual LED controllers (led_single_fader). The ce output of the clock divider triggers the transition between fade levels for each individual LED controller.
The led_fader module has three ports: a clock input (clk), control input (ctrl), and LED output (led). The clock input is driven by the system clock and is used to drive the PWM modules and the fading logic. Both the control input and the LED output are active low, corresponding to the active low push buttons and LEDs on the MAX V CPLD Development Board.
The led_fader module has three parameters used to control the behavior of the module: the number of LEDs (NUM_LEDS), the number of fade levels (FADE_LEVELS), and the total fade time (FADE_TIME). The NUM_LEDS parameter controls the width of both the ctrl input and the led output. The NUM_LEDS parameter defaults to 1, yielding a single control input and a single LED output. The FADE_LEVELS parameter sets the number of fade levels, excluding fully on and fully off. For example, the default value 3 results in five total states, including fully on and fully off: 0%, 25%, 50%, 75% and 100% brightness. The FADE_TIME parameter sets the total time in clock cycles for each LED to fade from fully on to fully off. A note on using the FADE_TIME parameter: FADE_TIME should be divisible by FADE_LEVELS as FADE_TIME/FADE_LEVELS is used as the number of clock cycles between each fade value. For example, the default FADE_TIME value 300, along with the default FADE_LEVELS value 3, results in 100 clock cycles per fade level.
The clkdiv module is used in this reference design to control fade timing. The ce output of the clock divider will go high for one clock cycle every PERIOD clock cycles, triggering a change in fade level for each fading LED. The reset input (rst_n) is active low.
As shown in Figure 2, each led_single_fader module contains a PWM module (pwm) and the fading control logic. Because the LEDs are active low, the output of the led_single_fader module (led) is assigned to the inverse of the output of the PWM (out). On the positive edge of fader_clk, the current fade value (fade_level) will be updated in accordance with the state of the control signal (ctrl), which is active low. The fade level corresponds to the duty cycle of the PWM module. The PERIOD parameter of the PWM module is set to TOTAL_FADE_LEVELS, which equals FADE_LEVLES + 2, to include fully on and fully off.
Figure 2 – The led_single_fader module instantiating the pwm module Led_fader_fig2.png (Click here for image)
The pwm module outputs a pulse width modulation signal used to create fade levels. The duty cycle of the PWM signal is equal to pulse_duration/(NUM_LEVELS - 1). In other words, the output (out) will be driven high for pulse_duration clock cycles every (NUM_LEVELS – 1) clock cycles. As an example, setting NUM_LEVELS to 5 would yield possible duty cycle values of 0%, 25%, 50%, 75%, and 100%, corresponding to 0, 1, 2, 3, and 4 cycles on per 4 cycle period.
Set enable high to enable pulse width modulation on the output. Driving enable low will stop and reset the internal counter, disabling pulse width modulation. When PWM is disabled, the output will stay fully off when pulse_duration is set to 0, and will stay fully on for any other value of pulse_duration.
The example design is configured as follows:
Parameters (to the led_fader module):
In the example design, the main clock frequency is 10 MHz. A FADE_TIME setting of 10,000,000 * 1/10 MHz = 1 second of total fade time. The FADE_LEVELS setting of 25, results in 27 total fade levels (full on and full off plus 25 steps in between). Each fade step is 1/25 of a second or 400,000 system clocks (10 MHz).
In many of the lower modules, the SystemVerilog clog2 function (ceiling log base 2) is used to determine vector widths. This function is evaluated at compile time. For instance, in the led_single_fader module, TOTAL_FADE_LEVELS is 27. The clog2 function returns 5, making the register fade_level [4:0] or 5 bits in width - the correct width to store values up to TOTAL_FADE_LEVELS.
As shown in Figure 3, the included simulation files demonstrate the functionality of the led_fader module. These files, including the test bench and related TCL scripts, can be found in the “simulation” folder. For simplicity, the number of fade levels in this test bench is reduced to eight, and the fade time is set to show three PWM periods per fade level. The control signals vary to show the two LEDs fading independently.
Figure 3 – Simulating the led_fader module Led_fader_fig3.png (Click here for image)
To run the simulation, open ModelSim, click onFile > Change Directory, and point to the “simulation” folder . Type “do dosim.do” in the Transcript window at the bottom of the ModelSim GUI. The simulation script will compile the necessary files and will load the appropriate waves into the wave viewer.