Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
742 Views

Synchronization problem in PWM generation

I am using the DE2 board to generate a 20 kHz PWM signal. The duty ratio is constant 20%. The device is implemented by verilog. My method is to use DE2 board to generate a 20 kHz * 1000 = 20 MHz clock signal. The 20 kHz synchronization signal is an external signal from a master DSP board, 50% duty ratio square wave. We have to use external synchronization signal. 

I set a variable a = 500. During the time when the 20 kHz synchronization signal is in its positive half cycle, let a = a-1 for each clock cycle (20 MHz). During the negative half cycle, a=a+1 for each clock cycle. Therefore, I have a triangle carrier signal and by comparing a with 100, I get the PWM output of 20 % duty ratio. I set the limits for a: the upper limit is 500 and the lower limit is 0. 

 

 

In normal case, during the 1st 40% of the 20kHz synchronization cycle, the PWM output is 0. The next 20% is 1 and the final 40% is 0. However, every tens of normal cycles, we can observe an abnormal cycle. The 1st half cycle PWM is 0 or 1, the next 10% is 1 and the last 40% is 0. Therefore, the PWM output is wrong during the half positive cycle of the synchronization signal and is correct in the negative half cycle. 

 

I can not figure out the reason for this problem. A possible reason is that the frequency of the 20MHz clk signal is not exactly 1000 times of that of 20 kHz signal. But how does this cause the abnormal cycle? How to solve the problem? 

 

Thank you very much!
0 Kudos
6 Replies
Highlighted
Valued Contributor III
3 Views

I paste my code here. It may be helpful. 

// PWM Generation. 

 

module PWM_Unit ( duty_ratio,pwm_trig, clk, pwm_output, output_b); 

input [15:0] duty_ratio; 

input pwm_trig, clk; 

output pwm_output, output_b; 

integer a=0; 

integer b=-1, ref_level=400; 

integer pwm_level; 

integer half_cycle=0; 

reg pwm_output;//output of pwm 

reg output_b;//for debug, not related to pwm generation. 

parameter steps=500; 

 

always 

begin 

pwm_output<=pwm_level; 

if (b>0) 

output_b<=1; 

else 

output_b<=0; 

end 

//initialize the pwm unit at the beginning of each switching cycle 

always @(posedge pwm_trig) 

begin 

ref_level=100; // read the duty ratio. this is constant for test and will be change in future. 

 

end 

//increase variable a at each clk rising edge 

always @(posedge clk) 

begin 

 

if (a<ref_level) 

pwm_level=1; 

else 

pwm_level=0; 

 

if (pwm_trig==1) //control the slope of the triangle wave. 

b=-1; 

if (pwm_trig==1) 

b=1; 

 

a=a+b; 

 

if (a<1) 

begin 

a=0; 

end 

if (a>(steps-1)) 

begin 

a=steps; 

end 

 

end 

endmodule
0 Kudos
Highlighted
Valued Contributor III
3 Views

I guess, pwm_trig is unrelated to clk, at least not guaranteed to meet the required setup and hold time? Then it's not correct to use it, as you do in your logic, it has to be synchronized to clk by two flip-flops. 

 

I assume, this is not the real code. 

if (pwm_trig==1) //control the slope of the triangle wave. b=-1; if (pwm_trig==1) b=1
0 Kudos
Highlighted
Valued Contributor III
3 Views

Oh, I am sorry. The code is wrong. This is correct: 

 

if (pwm_trig==1) //control the slope of the triangle wave. 

b=-1; 

if (pwm_trig==0)//triangle wave is rising when synchronization signal is 0 

b=1; 

 

The pwm_trig is the 20kHz synchronization signal. It comes from a master dsp controller. What is the meaning of “the required setup and hold time”? Due to the structure of our system, I have to use the external synchronization signal (20kHz) and internal clk signal (20 MHz). Is there any solution? 

 

Thank you!
0 Kudos
Highlighted
Valued Contributor III
3 Views

Please check altera.com I think there is a proven PWM generator. The example is n-bit resolution.

0 Kudos
Highlighted
Valued Contributor III
3 Views

You should use a synchronization chain as described in the Quartus Software Handbook and logic design text books. 

 

always @(posedge clk) begin pwm_trig_s0 <= pwm_trig; pwm_trig_s1 <= pwm_trig_s0; if (pwm_trig_s1==1) //control the slope of the triangle wave. b=-1; else b=1; //.... end
0 Kudos
Highlighted
Valued Contributor III
3 Views

Thank you very much! 

It works, although I do not understand why....
0 Kudos