variable clock frequency generation issue

S

SB

Guest
Hi there,

I am working with a verilog behavioral model of a variable frequency
clock.
The model has two parts. The first part, through a series of case
statements selects the period
of the output clock signal. The second part of the model the
generates
the clock signal using the newly defined clock period.

Hence the second part looks similar to:
always
begin
#(half_period) clk_sig <= ~clk_sig;
end

The "half_period" term is a "real" quantity and its
value is decided by a set of case statements of inputs
to the block. I am using a real as the half_period is often assigned
very large decimal values with fractional components.

I wish that once the half_period value is updated, that the
clock signal generation code in the always block uses this new value
immediately. However, I
am finding that the clk_sig waveform does not use a new
value of half_period until the previous value of half_period has
completely
elapsed in the timing waveform.

Can anybody suggest what how I should correct this and
ensure that the "always" block will instantaneously pick-up
the new value of the "half_period"?

I have tried using $realtobits on the half_period and using
the resulting wire in a sensitivity list on the always statement
but this does not work.

Thanks in advance

SB
 
On Jul 25, 5:33 am, SB <smartba...@yahoo.com> wrote:
Hi there,

I am working with a verilog behavioral model of a variable frequency
clock.
The model has two parts. The first part, through a series of case
statements selects the period
of the output clock signal. The second part of the model the
generates
the clock signal using the newly defined clock period.

Hence the second part looks similar to:
always
begin
#(half_period) clk_sig <= ~clk_sig;
end
I wouldn't use a non-blocking assignment for this. In fact
I suspect you didn't either or your clock wouldn't work at
all.

The "half_period" term is a "real" quantity and its
value is decided by a set of case statements of inputs
to the block. I am using a real as the half_period is often assigned
very large decimal values with fractional components.

I wish that once the half_period value is updated, that the
clock signal generation code in the always block uses this new value
immediately. However, I
am finding that the clk_sig waveform does not use a new
value of half_period until the previous value of half_period has
completely
elapsed in the timing waveform.

Can anybody suggest what how I should correct this and
ensure that the "always" block will instantaneously pick-up
the new value of the "half_period"?

I have tried using $realtobits on the half_period and using
the resulting wire in a sensitivity list on the always statement
but this does not work.
This sounds similar to what I would suggest. In what way
didn't it work? Did the compiler give an error or does it
just not do what you want? Did you write something like...

always @ (clk_sig or half_period_bits)
begin
clk_sig = #(half_period) ~clk_sig;
end

Thanks in advance

SB
 
SB wrote:
I am working with a verilog behavioral model of a variable frequency
clock.
The model has two parts. The first part, through a series of case
statements selects the period
of the output clock signal. The second part of the model the
generates
the clock signal using the newly defined clock period.

Hence the second part looks similar to:
always
begin
#(half_period) clk_sig <= ~clk_sig;
end
Has nothing to do with it being a real value. Has to do with that
thread blocking on a # delay and you can't change it while it's
waiting. However, you can abort it using disable. After the begin-end
is disabled, the always will restart it and it will use the new
half_period. Note: disable is non-synthesizable, but then, so are #
delays.

First, label the clock generator block, as in:

always begin : clock_gen
#(half_period) clk_sig = ~clk_sig;
end

And then, whenever half_period is updated, disable the block, as in:

always @(half_period)
disable clock_gen;

Alternatively, you could just add 'disable clock_gen;' after the
line(s) that changes half_period.

Also, as the other poster mentioned, there's usually no reason to use
a nonblocking assign in a clock generator.

-cb
 
On Wed, 25 Jul 2007 02:33:14 -0700, SB <smartbadge@yahoo.com> wrote:

Can anybody suggest what how I should correct this and
ensure that the "always" block will instantaneously pick-up
the new value of the "half_period"?
This is actually much trickier than it sounds - tricky to
specify correctly. Suppose your current "half-period" is
10. Suppose, too, that the last transition happened at
time 10, so the next transition is going to happen at 20.
Consider the following possibilities:

1) At time 15, change the half-period to 7.
I think you're saying that you want to have the next
transitions happen at 17, 24, ... whereas at present
your code of course waits until 20 before doing
anything, so you get transitions at 20, 27, 34, ...

2) At time 15, change the half-period to 20.
In this case, I guess you want the next transitions
to be 30, 50, ... whereas your existing code
would give 20, 40, 60, ...

3) At time 15, change the half-period to 2.
What do you want to happen here? The only sensible
behaviour I can see is to put transitions at 15, 17, 19 ...
but that has the odd effect that you get a half-period of
5 (10->15) which is neither of the two values.

So here's the algorithm I see:

- At any given time, the next transition should happen
at (previous transition) + half_period.
- If that next-transition time is earlier than "now",
we have case (3) - the half-period was suddenly made
much shorter - and we should make a transition
immediately.

In any case, this means that whenever the half-period
changes, you need to kill off the code that would otherwise
generate the next transition, and replace it. Something
like this...

integer half_period; // external controller can set this
reg clock; // this is the clock signal

initial begin : special_clock_generator

// internal variables for the clock generator
integer generator_delay;
time last_transition;

// Common initialisations
clock = 0;
half_period = <appropriate initial value>;
generator_delay = half_period;

// Parallel threads to monitor half_period and to generate clock
fork
forever begin : transition_generator
#generator_delay clock = ~clock;
last_transition = $time;
generator_delay = half_period;
end
forever @(half_period) begin : transition_calculator
integer next_transition;
// compute appropriate delay
next_transition = (last_transition + half_period) - $time;
if (next_transition < 0) next_transition = 0;
generator_delay = next_transition;
disable transition_generator; // kill off generator
end
join
end

Does this make sense?
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
SB wrote:
Can anybody suggest what how I should correct this and
ensure that the "always" block will instantaneously pick-up
the new value of the "half_period"?
When the #(half_period) is executed, the delay will be evaluated and
the process scheduled for that time in the future. Changing the delay
value will have no effect after that. As someone else said, the only
way to get it to wake up before that time would be a disable
statement.

I assume that when the half_period is modified, you want the time from
the previous edge to the next edge to become the half_period. You
don't say what should happen if the half_period gets changed at a time
that is already delayed from the previous edge by more than the new
delay. I would assume that you want the next edge to occur
immediately, since that is the best you can do in that situation.

As someone said, you can get the old delay to terminate with a
disable. But then you still need to get the next edge scheduled at
the proper time. The best mechanism I can see is to record the time
of each edge when you generate it. You need that information when the
delay gets disabled due to half_period changing, to figure out when
the next edge needs to be. With the time of the last edge plus the
new half_period, you can determine the new time for the next edge.
Then you can subtract the current time to get the required delay. If
the result is negative, you should delay by 0, since that is the best
you can do. This will be messy code. You should be considering
whether you really need this capability to respond before the next
edge.
 
On Jul 25, 4:45 pm, Chris Briggs <ch...@engim.com> wrote:
SB wrote:
I am working with a verilog behavioral model of a variable frequency
clock.
The model has two parts. The first part, through a series of case
statements selects the period
of the output clock signal. The second part of the model the
generates
the clock signal using the newly defined clock period.

Hence the second part looks similar to:
always
begin
#(half_period) clk_sig <= ~clk_sig;
end

Has nothing to do with it being a real value. Has to do with that
thread blocking on a # delay and you can't change it while it's
waiting. However, you can abort it using disable. After the begin-end
is disabled, the always will restart it and it will use the new
half_period. Note: disable is non-synthesizable, but then, so are #
delays.

First, label the clock generator block, as in:

always begin : clock_gen
#(half_period) clk_sig = ~clk_sig;
end

And then, whenever half_period is updated, disable the block, as in:

always @(half_period)
disable clock_gen;

Alternatively, you could just add 'disable clock_gen;' after the
line(s) that changes half_period.

Also, as the other poster mentioned, there's usually no reason to use
a nonblocking assign in a clock generator.

-cb


Hi All,

I tried the method of labelling the always block and then
aborting the wait time with a disable command when the new
half_period has been defined. The labelled always
block then picks up the new half_period value and it
progresses properly. This has worked for the
preliminary testing so far. I will test this with further
values going forward and update soon if there are any further
issues.

Thank you to everyone for taking an interest in this.

SB
 
On Jul 25, 6:43 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
On Wed, 25 Jul 2007 02:33:14 -0700, SB <smartba...@yahoo.com> wrote:
Can anybody suggest what how I should correct this and
ensure that the "always" block will instantaneously pick-up
the new value of the "half_period"?

This is actually much trickier than it sounds - tricky to
specify correctly. Suppose your current "half-period" is
10. Suppose, too, that the last transition happened at
time 10, so the next transition is going to happen at 20.
Consider the following possibilities:

1) At time 15, change the half-period to 7.
I think you're saying that you want to have the next
transitions happen at 17, 24, ... whereas at present
your code of course waits until 20 before doing
anything, so you get transitions at 20, 27, 34, ...

2) At time 15, change the half-period to 20.
In this case, I guess you want the next transitions
to be 30, 50, ... whereas your existing code
would give 20, 40, 60, ...

3) At time 15, change the half-period to 2.
What do you want to happen here? The only sensible
behaviour I can see is to put transitions at 15, 17, 19 ...
but that has the odd effect that you get a half-period of
5 (10->15) which is neither of the two values.

So here's the algorithm I see:

- At any given time, the next transition should happen
at (previous transition) + half_period.
- If that next-transition time is earlier than "now",
we have case (3) - the half-period was suddenly made
much shorter - and we should make a transition
immediately.

In any case, this means that whenever the half-period
changes, you need to kill off the code that would otherwise
generate the next transition, and replace it. Something
like this...

integer half_period; // external controller can set this
reg clock; // this is the clock signal

initial begin : special_clock_generator

// internal variables for the clock generator
integer generator_delay;
time last_transition;

// Common initialisations
clock = 0;
half_period = <appropriate initial value>;
generator_delay = half_period;

// Parallel threads to monitor half_period and to generate clock
fork
forever begin : transition_generator
#generator_delay clock = ~clock;
last_transition = $time;
generator_delay = half_period;
end
forever @(half_period) begin : transition_calculator
integer next_transition;
// compute appropriate delay
next_transition = (last_transition + half_period) - $time;
if (next_transition < 0) next_transition = 0;
generator_delay = next_transition;
disable transition_generator; // kill off generator
end
join
end

Does this make sense?
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.

Hi Jonathan

I have replied to the other post whose solution
got me out of this particular rut. I like the
analysis that you have done on the problem and I
must adopt this method to other problems in future.

SB
 

Welcome to EDABoard.com

Sponsor

Back
Top