![]() |
variable clock frequency generation issue
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 |
Re: variable clock frequency generation issue
On Jul 25, 5:33 am, SB <[email protected]> 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 |
Re: variable clock frequency generation issue
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 |
Re: variable clock frequency generation issue
On Wed, 25 Jul 2007 02:33:14 -0700, SB <[email protected]> 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 [email protected] http://www.MYCOMPANY.com The contents of this message may contain personal views which are not the views of Doulos Ltd., unless specifically stated. |
Re: variable clock frequency generation issue
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. |
Re: variable clock frequency generation issue
On Jul 25, 4:45 pm, Chris Briggs <[email protected]> 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 |
Re: variable clock frequency generation issue
On Jul 25, 6:43 pm, Jonathan Bromley <[email protected]>
wrote: > On Wed, 25 Jul 2007 02:33:14 -0700, SB <[email protected]> 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 > [email protected]://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 |
All times are GMT +1. The time now is 03:28 PM. |
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0
Copyright 2008 @ FPGA Central. All rights reserved