duty cycle of clock divider

P

promach

Guest
http://www.fpga4fun.com/MusicBox1.html

The frequency is 440Hz, as expected, but the output duty cycle is not 50% anymore. The low level goes from counter=0 to counter=32767 (when bit 15 of counter is low) and then high level from 32768 to 56817. That gives us "speaker" being high only 42% of the time. The easiest way to get a 50% duty cycle is to add a stage that divides the output by 2. So first we divide by 28409 (instead of 56818) and then by 2. ????

I do not understand why we need to divide by 2.
Could anyone explain the above reasoning in more laymen way ?
 
On 21/09/2017 13:32, promach wrote:
http://www.fpga4fun.com/MusicBox1.html

The frequency is 440Hz, as expected, but the output duty cycle is not 50% anymore. The low level goes from counter=0 to counter=32767 (when bit 15 of counter is low) and then high level from 32768 to 56817. That gives us "speaker" being high only 42% of the time. The easiest way to get a 50% duty cycle is to add a stage that divides the output by 2. So first we divide by 28409 (instead of 56818) and then by 2. ????

I do not understand why we need to divide by 2.
Could anyone explain the above reasoning in more laymen way ?

He means divide the frequency by 2, implemented by a single stage
counter flip flop. This will then always give a 50% duty cycle.
 
I do not get how just dividing by 2 could get 50% duty cycle instead of 42% ?
 
On 21/09/2017 15:29, promach wrote:
I do not get how just dividing by 2 could get 50% duty cycle instead of 42% ?
Assuming the input frequency to the divider is constant, then:-
that frequency is defined by the reciprocal of the time period that
elapses between successive rising or falling or some fixed point in the
repetitive waveform ...
True or false ...

If true then if you clock a flip flop at the fixed point in the repetive
waveform then the outout will toggle high for one complete period of the
input waveform, and toggle low for one complete period of the input
waveform.
If the frequency is constant, then the period of successive cycle of the
input waveform will be the same.
Therefore the output of the flip flop divider will have a 50% duty cycle.

If false then it is not a constant input frequency and all the above
does not apply.

Andy
 
Strange, I have the clock divider coding at http://www.edaplayground.com/x/gXC

but it does not divide accordingly as mentioned in the article.

Any idea about what I missed out ?



// Adapted from http://www.fpga4fun.com/MusicBox1.html

module clk_div (i_clk, ck_stb);

input i_clk;
output reg ck_stb = 0;

localparam THRESHOLD = 3; // divides i_clk by (2*THRESHOLD = 6) to obtain ck_stb which is the divided clock signal

reg [($clog2(THRESHOLD)-1):0] counter = 0;
reg counter_reset = 0;

always @(posedge i_clk)
counter_reset <= (counter == THRESHOLD-1'b1);

always @(posedge i_clk)
begin
if(counter_reset)
counter <= 1;
else
counter <= counter + 1;

//$display("$clog2(THRESHOLD) = ", $clog2(THRESHOLD));
end

always @(posedge i_clk)
ck_stb <= ~ck_stb;

endmodule
 
I have tried clock divider at http://www.edaplayground.com/x/gXC , but it does not divide accordingly as mentioned in the article.

Any idea about what I missed out ?

// Adapted from http://www.fpga4fun.com/MusicBox1.html

module clk_div (i_clk, ck_stb);

input i_clk;
output reg ck_stb = 0;

localparam THRESHOLD = 3; // divides i_clk by (2*THRESHOLD = 6) to obtain ck_stb which is the divided clock signal

reg [($clog2(THRESHOLD)-1):0] counter = 0;
reg counter_reset = 0;

always @(posedge i_clk)
counter_reset <= (counter == THRESHOLD-1'b1);

always @(posedge i_clk)
begin
if(counter_reset)
counter <= 1;
else
counter <= counter + 1;

//$display("$clog2(THRESHOLD) = ", $clog2(THRESHOLD));
end

always @(posedge i_clk)
ck_stb <= ~ck_stb;

endmodule
 
I have found out the bug.

The last always block should look like the following:


always @(posedge i_clk)
if(counter_reset)
ck_stb <= ~ck_stb;
 
@Andy

For ambulance siren at http://www.fpga4fun.com/MusicBox2.html and http://www.edaplayground.com/x/5aSK , could you comment on the simulation waveform https://i.imgur.com/gN0cqAJ.png ?

Note: I will do the actual hardware (speaker) audio testing tomorrow.



// http://www.fpga4fun.com/MusicBox2.html - Ambulance siren

module clk_div (i_clk, ck_stb);

input i_clk;
output reg ck_stb = 0;

localparam THRESHOLD = 6; // divides i_clk by 6 to obtain ck_stb which is the divided clock signal
localparam TOGGLE_FREQUENCY_RATIO = 4; // MSB bit of "tone" toggles with a frequency of about [i_clk / 2^4]

reg [($clog2(THRESHOLD) - 1):0] counter = 0;
reg counter_reset = 0;

reg [(TOGGLE_FREQUENCY_RATIO - 1):0] tone = 0;

always @(posedge i_clk)
tone <= tone+1;

always @(posedge i_clk)
if(tone[TOGGLE_FREQUENCY_RATIO-1])
counter_reset <= (counter == THRESHOLD - 1'b1);
else
counter_reset <= (counter == (THRESHOLD >> 1) - 1'b1);

always @(posedge i_clk)
begin
if(counter_reset)
counter <= 1;
else
counter <= counter + 1;

//$display("$clog2(THRESHOLD) = ", $clog2(THRESHOLD));
end

always @(posedge i_clk)
if(counter_reset)
ck_stb <= ~ck_stb;

endmodule
 
On 21/09/2017 17:52, promach wrote:
I have tried clock divider at http://www.edaplayground.com/x/gXC , but it does not divide accordingly as mentioned in the article.

Any idea about what I missed out ?

// Adapted from http://www.fpga4fun.com/MusicBox1.html

module clk_div (i_clk, ck_stb);

input i_clk;
output reg ck_stb = 0;

localparam THRESHOLD = 3; // divides i_clk by (2*THRESHOLD = 6) to obtain ck_stb which is the divided clock signal

reg [($clog2(THRESHOLD)-1):0] counter = 0;
reg counter_reset = 0;

always @(posedge i_clk)
counter_reset <= (counter == THRESHOLD-1'b1);

always @(posedge i_clk)
begin
if(counter_reset)
counter <= 1;
else
counter <= counter + 1;

//$display("$clog2(THRESHOLD) = ", $clog2(THRESHOLD));
end

always @(posedge i_clk)
ck_stb <= ~ck_stb;

endmodule

I'm guessing you have declared output register, which just defines the
output state.
You should have just declared a register (reg?) which has both an input
and output state.
 

Welcome to EDABoard.com

Sponsor

Back
Top