PWM Signal Generation with VHDL to Control Servo Motor
In this article, I aim to explain how a PWM signal can be generated using VHDL to control a Servo Motor in an FPGA. In other words, I will show how to design a servo motor controller in an FPGA.
What is PWM Signal?
Pulse Width Modulation (PWM) is a modulation technique used to encode information or control the average power delivered to a load by varying the duty cycle of a fixed-frequency square wave. In this application, a PWM signal will be used to encode position information for servo motor control.
SG90 Servo Motor
I have aimed to control the SG90 Servo Motor in this application. In the datasheet of this SG90 Servo Motor, it says that it can rotate approximately 180 degrees.
According to the datasheet, the PWM period should be 20 ms. Moreover, the duty cycle should be between 1ms and 2ms. For example, if the duty cycle is 1ms, it means the motor is in the “0 degree” position. If the duty cycle is 1.5 ms, it means the motor is in the “ 90 degree” position. Finally, if the duty cycle is 2 ms, it means the motor is in the “180 degree” position. In some other applications, it is recommended that the duty cycle be between 0.5 ms and 2.5 ms. However, I would like to obey the datasheet. You can change the values if you like.
Thus, the input PWM signal that will control the servo motor should have a 20 ms period and a 1 ms duty cycle for the 0 degree position or a 2 ms duty cycle for the 180 degree position.
Get Alperen Özçelik’s stories in your inbox
Join Medium for free to get updates from this writer.
After analyzing the datasheet of the SG90 servo motor, it is understood what kind pwm signal we need. So it can be designed now in an FPGA.
PWM Signal Controller Design in VHDL
I have designed a generic PWM signal controller using VHDL hardware description language. The state diagram of this RTL code is shared below.
We have 3 states, which are IDLE, UP_COUNT, and DOWN_COUNT. In idle state duty cycle absolutly 1 ms, which is 0 degrees. In the up_count state, the duty cycle time is incrementing in each clock by 1 clock time, up to the duty cycle reaches 2 ms, which is 180 degrees. In the down_count state duty cycle is decremented by 1 clock time in each clock bye 1 clock time, up to the duty cycle reaches 1 ms, which is 0 degrees. Finally, it can be said that the duty cycle will be oscillating between 1ms and 2ms. Thus, 0 degrees and 180 degrees.
Used libraries, generic parameters, and ports of this module are shared below. It has 2 inputs, which are clk and reset, but only 1 output, just a PWM signal.
Used constants and signals are shared below. Constants are derived according to the clock numbers. For example, the PERID_CLKS constant means how many clocks are required to reach 20 ms period.
The whole FSM part of the code is shared below. The calculated new PWM signal value is latched when the period begins. Thus, it latches every 20 ms. Moreover, FSM updates only for the new period.
I have also written a testbench code for this controller design and analyzed it. Complete testbench code is shared below.
The output waveform of the testbench can be seen below in two figures. The controller functions as it is designed. It can be seen from the figures pwm period is as long as 20 ms. Moreover, in the UP_COUNT state duty cycle gradually increments in every PWM period. Also, in the DOWN_COUNT state duty cycle gradually decrements in every PWM period. If you run these codes and analyze it you can also realize these on your own.
Finally, it can be said that the design is working as it is planned.
The complete code can be found on my GitHub page. Also, you can visit my LinkedIn page.





