FPGARelated.com
Forums

Frequency divider?

Started by Unknown December 17, 2006
I need to divide my clock by 10, can someone confirm
if my verilog module will work:

//divide oscillator clock by 10 (xc9536)
module clk_div10 (in,out)
input in;
output out;
reg[0..3] cnt;
always @ (in)
begin
    cnt=cnt+1;
    if (cnt ==10)
    begin
        cnt =0;
        out =out +1;
    end
end
endmodule


Correction, this is wrong
         out =out +1;
Put this in instead
        out =!out


222 wrote:
> I need to divide my clock by 10, can someone confirm > if my verilog module will work: > > //divide oscillator clock by 10 (xc9536) > module clk_div10 (in,out) > input in; > output out; > reg[0..3] cnt; > always @ (in) > begin > cnt=cnt+1; > if (cnt ==10) > begin > cnt =0; > out =out +1; > end > end > endmodule > >
The short answer is 'NO' I can see a few issues. Do you need a 50% duty cycle on the output clock? That would bring up another issue. I'll be generous and assume this is not homework, but if it is, realise you're not really learning anything if you don't make your own mistakes; that way the lesson sticks ;) //divide oscillator clock by 10 (xc9536) module clk_div10 (in,out) input in; // input clock output out; // output clock = input/10 reg[0..3] cnt; assign out = cnt[3]; // map MSB to output - previous code needed a // reg // statement, which may or may not have // been absorbed. // always @ (in) always @ (posedge in) // use the edge. The previous statement was a //static sensitivity list, as used in // combinational assignments begin // cnt=cnt+1; // let's not use a blocking assignment if (cnt[3] & (cnt[2:0])) // test for increment or // reset at top begin cnt <= 4'b0; // count == 9 normally, and also //guarantees // to move the counter to a valid state if it // somehow was in the range of 10 - 15 // Also need to tell some tools explicitly // about the number of 0s // I also added a little trickery to the test // which you will need to understand if you are // presenting this as homework ;) end else begin // just increment cnt <= cnt+1; end end endmodule I did a number of things, as you can see - now figure out why :) If you want a 50% duty cycle, it's a different matter. Cheers PeteS
PeteS wrote:
> 222 wrote: >> I need to divide my clock by 10, can someone confirm >> if my verilog module will work: >> >> //divide oscillator clock by 10 (xc9536) >> module clk_div10 (in,out) >> input in; >> output out; >> reg[0..3] cnt; >> always @ (in) >> begin >> cnt=cnt+1; >> if (cnt ==10) >> begin >> cnt =0; >> out =out +1; >> end >> end >> endmodule >> >> > The short answer is 'NO' > > I can see a few issues. Do you need a 50% duty cycle on the output > clock? That would bring up another issue. > > I'll be generous and assume this is not homework, but if it is, realise > you're not really learning anything if you don't make your own mistakes; > that way the lesson sticks ;) > > > //divide oscillator clock by 10 (xc9536) > module clk_div10 (in,out) > input in; // input clock > output out; // output clock = input/10 > reg[0..3] cnt; > > assign out = cnt[3]; // map MSB to output - previous code needed > a // reg > // statement, which may or may not have > // been absorbed. > // always @ (in) > always @ (posedge in) // use the edge. The previous statement was > a //static sensitivity list, as used in > // combinational assignments > begin > // cnt=cnt+1; // let's not use a blocking assignment >
// > if (cnt[3] & (cnt[2:0])) // test for increment if (cnt[3] & (&cnt[2:0])) // test for increment - fixed
> or // reset at top > begin > cnt <= 4'b0; // count == 9 normally, and > also //guarantees > // to move the counter to a valid state if it > // somehow was in the range of 10 - 15 > // Also need to tell some tools explicitly > // about the number of 0s > // I also added a little trickery to the test > // which you will need to understand if you are > // presenting this as homework ;) > end > else begin // just increment > cnt <= cnt+1; > end > end > endmodule > > > I did a number of things, as you can see - now figure out why :) > > > If you want a 50% duty cycle, it's a different matter. > > Cheers > > PeteS
One fix in the test - more coffee!!!
222 wrote:
> Correction, this is wrong > out =out +1; > Put this in instead > out =!out > >
Since you toggle "out" every time your counter reaches 10, you are actually creating a waveform with twice the period you intended. Also, because counting starts at 0 and you compare with 10, there are actually 11 counts between toggles instead of 10. So, unless I am mistaken (I have not touched verilog much, everything I have worked on so far has been in VHDL), your code would be dividing the clock by 22 instead of 10, assuming it is otherwise functional.
> > Correction, this is wrong > > out =out +1; > > Put this in instead > > out =!out > > > > > > Since you toggle "out" every time your counter reaches 10, you are > actually creating a waveform with twice the period you intended. Also,
Does "always @(x)" work on _any_ change, i.e. it should react twice on each clock, which would make it right, or does it default to positive edge, which would make it twice the period?
> because counting starts at 0 and you compare with 10, there are actually > 11 counts between toggles instead of 10.
Correct, I need to count to 9.
> > So, unless I am mistaken (I have not touched verilog much, everything I > have worked on so far has been in VHDL), your code would be dividing the > clock by 22 instead of 10, assuming it is otherwise functional.
> > The short answer is 'NO' > > > > I can see a few issues. Do you need a 50% duty cycle on the output > > clock? That would bring up another issue.
Can you please explain why I will not have 50% duty cycle?
> > > > I'll be generous and assume this is not homework, but if it is, realise
No.
> > you're not really learning anything if you don't make your own mistakes; > > that way the lesson sticks ;) > > > > > > //divide oscillator clock by 10 (xc9536) > > module clk_div10 (in,out) > > input in; // input clock > > output out; // output clock = input/10 > > reg[0..3] cnt; > > > > assign out = cnt[3]; // map MSB to output - previous code > > needed a reg statement, which may or may not have been absorbed.
Please explain, what is the purpose of this?
> > // always @ (in) > > always @ (posedge in) // use the edge. The previous statement was > > a //static sensitivity list, as used in > > // combinational assignments
Please explain why I should use the edge-trigger logic rather than combinational statements?
> > begin > > // cnt=cnt+1; // let's not use a blocking assignment > > > // > if (cnt[3] & (cnt[2:0])) // test for increment > if (cnt[3] & (&cnt[2:0])) // test for increment - fixed > > or // reset at top > > begin > > cnt <= 4'b0; // count == 9 normally, and
What is happening here, why are you testing up to 4 and not 9 ?
> > also //guarantees > > // to move the counter to a valid state if it > > // somehow was in the range of 10 - 15 > > // Also need to tell some tools explicitly > > // about the number of 0s > > // I also added a little trickery to the test > > // which you will need to understand if you are > > // presenting this as homework ;) > > end > > else begin // just increment > > cnt <= cnt+1; > > end > > end > > endmodule > > > > > > I did a number of things, as you can see - now figure out why :) > > > > > > If you want a 50% duty cycle, it's a different matter. > > > > Cheers > > > > PeteS > > One fix in the test - more coffee!!!
Here's my half-penny's worth:

########################
module div10(in,out);
input in;
output out;

//put your ratio in here
`define RATIO 10

// need 4 regs, because three will only give 8 states
reg [3:0]Q;

//  at each rising edge of clock
always @(posedge in)

// if Q=9, next state is 0, else Q<=Q+1
Q<=(Q==`RATIO-1)?4'b0:Q+1;

assign out=Q[3];

endmodule
########################

The above counts 0 1 2 ...7 8 9

Output is high 2 states in 10 -states 8 and 9 so not 1:1ratio

If you want 1:1 ratio

########################
module div10(in,out);
input in;
output out;

//put your ratio in here
`define RATIO 10

// need 4 regs, because three will only give 8 states
reg [3:0]Q;

reg out;

//  at each rising edge of clock
always @(posedge in)

begin
// if Q=9, next state is 0, else Q<=Q+1
Q<=(Q==`RATIO-1)?4'b0:Q+1;

// output high for states 5 6 7 8 9
out<=(Q>4);
end

endmodule
########################
--
Per ardua ad nauseam
"tersono" <ethel.thefrog@ntlworld.com> wrote in message
news:ff6bo29ov2ee3j9e30qkge4skuqt9hru9t@4ax.com...
> > Here's my half-penny's worth: > > ######################## > module div10(in,out); > input in; > output out; > > //put your ratio in here > `define RATIO 10 > > // need 4 regs, because three will only give 8 states > reg [3:0]Q; > > // at each rising edge of clock > always @(posedge in) > > // if Q=9, next state is 0, else Q<=Q+1 > Q<=(Q==`RATIO-1)?4'b0:Q+1; > > assign out=Q[3]; > > endmodule > ######################## > > The above counts 0 1 2 ...7 8 9 > > Output is high 2 states in 10 -states 8 and 9 so not 1:1ratio > > If you want 1:1 ratio > > ######################## > module div10(in,out); > input in; > output out; > > //put your ratio in here > `define RATIO 10 > > // need 4 regs, because three will only give 8 states > reg [3:0]Q; > > reg out; > > // at each rising edge of clock > always @(posedge in) > > begin > // if Q=9, next state is 0, else Q<=Q+1 > Q<=(Q==`RATIO-1)?4'b0:Q+1; > > // output high for states 5 6 7 8 9 > out<=(Q>4); > end
I don't like this notation, it forces me to delve deep into C-like syntax which focuses my mind away from hardware, but everyone and their own styles.
> > endmodule > ######################## > -- > Per ardua ad nauseam
222 wrote:
>>> Correction, this is wrong >>> out =out +1; >>> Put this in instead >>> out =!out >>> >>> >> Since you toggle "out" every time your counter reaches 10, you are >> actually creating a waveform with twice the period you intended. Also, > > Does "always @(x)" work on _any_ change, i.e. it should react twice > on each clock, which would make it right, or does it default to positive > edge, > which would make it twice the period?
As I said, I have only poked into verilog with a pole... I overlooked that little detail and yes, this does appear to be equivalent to clk'event in VHDL. In this case, try synthesizing your code with free tools from most FPGA vendors and I think you will get an error saying that you have to pick an edge - the FFs in all FPGAs I know of do not work with both edges, even the DDR IOBs are implemented with two register banks clocked on opposite edges. It might work the way you intended in simulation but I am almost 100% certain that it will fail in synthesis.
>> because counting starts at 0 and you compare with 10, there are actually >> 11 counts between toggles instead of 10. > > Correct, I need to count to 9.