The Designer's Guide Community Forum
https://designers-guide.org/forum/YaBB.pl
Design Languages >> Verilog-AMS >> need help modifying the reset to an oscillator module
https://designers-guide.org/forum/YaBB.pl?num=1299882714

Message started by altaj on Mar 11th, 2011, 2:31pm

Title: need help modifying the reset to an oscillator module
Post by altaj on Mar 11th, 2011, 2:31pm

I have a module for an oscillator that works as follows:  When the ENB (enable_bar, so active low) is set low, the output goes to zero.  Great.  When ENB is set high, the output resumes.  Also great.   However, the timebase of the oscillator is as it was before the reset.  That is to say, it behaves like a continuouslly running oscillator with an outout enable.

I want to modify the module so that when ENB is set low, the oscillator will always start from the same state, regardless of the abstime.  I've tried messing with the n and next variables, making them hold position while ENB is high, but am getting nowhere.

If anyone has a suggestion, I would like to hear it.  I'm a novice, so, as always, if you see something silly or wrong in the module, I'm always open to learning a better way!

Here is the module:
module osc (enb, out);

input enb;
output out;
voltage enb,out;

parameter real      freq=1 from (0:inf),            // output frequency
                                               vl=-1,                        // high output voltage
                                               vh=1,                        // low output voltage
                                               vth=(vh-vl)/2,
                                               tt=0.01/freq from (0:inf);      // transition time of output

integer n, enable;
real next;

analog begin

           @(cross(V(enb) - vth, -1 )) enable = 1;
           @(cross(V(enb) - vth, +1 )) enable = 0;
   
               @(initial_step)
                             next = (0.5/freq + $abstime);
                     
               @(timer(next)) begin
                             n = !n;
                             next = next + 0.5/freq;
                    end
                       
                       V(out) <+ transition(n ? enable*vh : vl, 0, tt);

     end
endmodule


Thanks!
John

Title: Re: need help modifying the reset to an oscillator module
Post by Ken Kundert on Mar 12th, 2011, 8:32am

You should compute next in the cross statement that detects the falling edge on enb.

Also, your approach to detecting whether the block is enabled is problematic because it needs an edge to determine the state of enable. A better approach would be

Code:
enable = V(enb) < vth;
@(cross(Venb)-vth))
   ;

In this way the conditional is run at every time point and so the resulting value of enable is always correct, and the cross is added so that you accurately resolve the time at which the threshold is crossed. To add your phase reset functionality, you could do this:

Code:
enable = V(enb) < vth;
@(cross(Venb)-vth)) begin
   if (V(enb) > vth)
       next = 1000;
   else
       next = $abstime + freq/2;
end

And, shouldn't the output transition statement look more like this?

Code:
V(out) <+ transition(n&&enable ? vh : vl, 0, tt);

-Ken

Title: Re: need help modifying the reset to an oscillator module
Post by Marq Kole on Mar 14th, 2011, 3:06am

Replacing the cross() event function calls in your code by above() event function calls will achieve the same as the conditional outside the event.


Code:
@(above(V(enb) - vth)) enable = 0;
@(above(vth - V(enb))) begin enable = 1; next = $abstime; end


I'm puzzled that you do not use the period argument of the timer() event function and just update the reference on every falling edge of enb.


Code:
@(timer(next, 0.5/freq)) n = !n;


If you want the oscillator to have 0 output voltage when disabled and a voltage that toggles between vh and vl you will need still a different output statement:


Code:
V(out) <+ transition(enable ? (n ? vh : vl) : 0, 0, tt);


Cheers,
Marq

Title: Re: need help modifying the reset to an oscillator module
Post by altaj on Mar 14th, 2011, 11:13am

Thanks.  I got a lot of useful knowledge from both of these  replies.   I used the "@(above" function, which I had not yet encountered.  

I had to modify the "phase reset" block Ken provided slightly, to also reset n.  Otherwise the new start state of the osc was not always the same, as it depends on n :

Code:
@(cross(V(enb)-vth)) begin
           if (V(enb) > vth) begin
                 next = 1000; n=0; end
           else
                 next = $abstime + 0.5/freq;
     end


Question:  Why 1000?   Arbitrary choice?

Thanks again!
John

Title: Re: need help modifying the reset to an oscillator module
Post by Ken Kundert on Mar 14th, 2011, 10:15pm

Yes, 1000 was arbitrary. It just has to be larger than any possible stop time.

-Ken

The Designer's Guide Community Forum » Powered by YaBB 2.2.2!
YaBB © 2000-2008. All Rights Reserved.