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!
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
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
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!