This website uses cookies. By using this site, you consent to the use of cookies. For more information, please take a look at our Privacy Policy.
Home > FPGA Technical Tutorials > Programming FPGAs Getting Started with Verilog > PWM and Servomotors > A PWM Module

A PWM Module

FONT SIZE : AAA

It is surprisingly easy to implement a PWM module. You use a counter and compare the value of duty with the counter. If the counter is below the duty value, the  output is high, and as soon as this isn’t true, the output is set low.

You can find the code for this module along with a module to test it in the  downloads for this book (see Chapter 2). The project is called “ch07_pwm.”

PWM Module Inputs and Outputs

The PWM module is called just “pwm” and has two inputs, pwm_clk and duty.  Its single output, PWM_PIN, will be connected to the GPIO pin on which you want  the PWM output:


module pwm(

 input pwm_clk,

 input [7:0] duty,

 output reg PWM_PIN

 );

The pwm_clk input is not the same as the system-wide clock of the FPGA.  Generally, the PWM frequency is a lot lower than the 12 to 50 MHz of this book’s  example boards. A common PWM frequency range is 500 Hz to several kilohertz.  This PWM module uses an 8-bit counter, so the frequency at pwm_clk needs to  be 256 times the desired PWM frequency. When you look at testing the module,  you will see how you can use a prescaler counter to derive a lower clock frequency  to use for the PWM module.

The remainder of the code for the PWM module is as follows:


reg [7:0] count = 0;

always @(posedge pwm_clk)

begin

 count <= count + 1;

 PWM_PIN <= (count < duty);

end

endmodule

The 8-bit counter count is incremented with the positive edge of the pwm_clk signal. Output PWM_PIN is then set to be the result of (count < duty). In other  words, if count is less than duty, PWM_PIN will be 1; otherwise, it will be 0.

A Tester of the PWM Module

In this case, the module to test the PWM module so that you can see that it is  working is more complicated than the pwm module itself. It will change the  brightness of a LED (D1 on the Elbert 2, LED 0 on the Mojo IO Shield, and LED0  on the Papilio with LogicStart MegaWing) when you press the “Up” and “Down”  buttons (SW1 and SW6 on the Elbert 2).

The UCF for Mojo is as follows:


# User Constraint File for PWM on Mojo with IO Shield

NET "CLK" LOC = P56; 

# Switches

NET "switch_up" LOC = "P137" | PULLDOWN;

NET "switch_dn" LOC = "P139" | PULLDOWN;

# Output

NET "PWM_PIN" LOC = P97; # LED1

The tester module has inputs of the system clock (CLK) and two switch pins to  vary the brightness of the LED up and down. The output will link to the LED  whose brightness is to be changed. The code for the tester module is contained in  the file pwm_tester.v:


module pwm_tester(

 input CLK,

 input switch_up,

 input switch_dn,

 output PWM_PIN

 );

Wires and debouncer modules are defined in what should now be a familiar way:

wire s_up, s_dn;

debouncer d1(.CLK (CLK), .switch_input (switch_up), .trans_up (s_up));

debouncer d2(.CLK (CLK), .switch_input (switch_dn), .trans_up (s_dn));

A register duty is used to keep a value of duty cycle (0 to 255) that will be set using  the “Up” and “Down” push switches.

The prescaler register is a 7-bit counter that will be used to divide the system  clock frequency (50 MHz on the Mojo, 12 MHz on the Elbert 2, and 32 MHz on  Papilio One) by 128. With a further division of 256 from the 8-bit counter in the  PWM module, this will result in PWM frequencies of:

• Elbert 2: 12 MHz/128/256 = 366 Hz.

• Papilio One: 32 MHz/128/256 = 975 Hz

• Mojo: 50 MHz/128/256 = 1.53 kHz

The pwm module instance uses the output of bit 6 of the prescaler to provide  the pwm_clk input to the PWM module:


reg [7:0] duty = 0;

reg [6:0] prescaler = 0; / CLK freq / 128 / 256 = 1.5kHz

pwm p(.pwm_clk (prescaler[6]), .duty (duty), .PWM_PIN (PWM_PIN));

The always block of the tester module increments the prescaler and then  checks for any switch presses. The “Up” and “Down” switch presses increase or  decrease the value of duty by 5:


always @(posedge CLK)

begin

 prescaler <= prescaler + 1;

 if (s_up)

 begin

 duty <= duty + 5;

 end

 if (s_dn)

 begin

 duty <= duty - 5;

 end 

end

endmodule

To keep the Verilog simple, there is no test to see if the value of duty exceeds  255. If it does, it will simply wrap around because only 8 bits are used for the duty,  allowing a maximum range of 255.

Trying It Out

Generate the bit file for the project, and load it onto your board. You will see how  the “Up” and “Down” buttons increase and decrease the brightness of the LED. If  you want to get a feel for how PWM works, try slowing the whole thing down by  a factor of approximately 1000. To do this, change lines 13 and 14 of pwm_tester.v  to add another 10 stages to the prescaler counter. The changes are highlighted in  boldface here:


reg [16:0] prescaler = 0;

pwm p(.pwm_clk (prescaler[16]), .duty (duty), .PWM_PIN (PWM_PIN));

  • XC5215-5HQ208C

    Manufacturer:Xilinx

  • FPGA XC5200 Family 23K Gates 1936 Cells 83MHz 0.5um Technology 5V 208-Pin HSPQFP EP
  • Product Categories: FPGAs

    Lifecycle:Obsolete -

    RoHS: No RoHS

  • XC3S50-5VQ100C

    Manufacturer:Xilinx

  • FPGA Spartan-3 Family 50K Gates 1728 Cells 725MHz 90nm Technology 1.2V 100-Pin VTQFP
  • Product Categories: FPGAs

    Lifecycle:Active Active

    RoHS: No RoHS

  • XC3S50A-4FTG256I

    Manufacturer:Xilinx

  • FPGA Spartan-3A Family 50K Gates 1584 Cells 667MHz 90nm Technology 1.2V 256-Pin FTBGA
  • Product Categories: FPGAs

    Lifecycle:Active Active

    RoHS:

  • XC3S50A-4VQ100I

    Manufacturer:Xilinx

  • FPGA Spartan-3A Family 50K Gates 1584 Cells 667MHz 90nm Technology 1.2V 100-Pin VTQFP
  • Product Categories: FPGAs

    Lifecycle:Active Active

    RoHS: No RoHS

  • XC3S50A-5VQ100C

    Manufacturer:Xilinx

  • FPGA Spartan-3A Family 50K Gates 1584 Cells 770MHz 90nm Technology 1.2V 100-Pin VTQFP
  • Product Categories: FPGAs (Field Programmable Gate Array)

    Lifecycle:Active Active

    RoHS: No RoHS

Need Help?

Support

If you have any questions about the product and related issues, Please contact us.