The Designer's Guide Community Forum
Design Languages >> Verilog-AMS >> Random Real number from analog block

Message started by Lala878 on Jan 4th, 2023, 4:03am

Title: Random Real number from analog block
Post by Lala878 on Jan 4th, 2023, 4:03am

Hi all,

I have some experience with Verilog AMS, mainly wreal. I almost never really used analog blocks, but I can understand what's going on when I read through the code...

My question is about generating a random number with $rdist_normal() function.
I read through the manual and I can't get it to work.
I made a real random number using the discrete approach.

The goal is to generate a random number following a normal distribution to represent jitter I'll be adding to my period when forming a signal.

This is what works for me:

`timescale 1ps/1fs

integer real stddev = 20;
parameter integer dscale = 1e12;
integer seed = 11;
real random_d;

always #1000 begin // every 1ns calculate a random number within normal distribution fashion

random_d = ($dist_normal(seed, 0, sigma1*dscale) + 0.0)/(dscale/sigma1); // if I divide with dscale I only get numbers close to zero

$display("random_d = %f\n", random_d);


My question is how can I get it to work with $rdist_normal() function?

i thought a simple analog block would be sufficient:

`timescale 1ps/1fs

real random_a;
integer seed = 11;

analog begin
     @(timer(0)) begin //      this would mean to do what's inside analog block at every analog time step, presuming it's the same as in the `timescale?      
           random_a = $rdist_normal(seed, 0, sigma1);
           $display("random_a = %.2f\n", random_a);
     end //timer
end //analog

The idea is to use the random_a further by some other always block.

But it seems I am using the analog block wrongly somehow. I get a parser error in AMS Designer saying random_a identifier has conflicting context.

Any thoughts?


Title: Re: Random Real number from analog block
Post by Ken Kundert on Jan 7th, 2023, 10:26pm

It is very difficult to figure out what you are trying to accomplish.  In general, it is better to give a complete module so we don't have to guess about code not shown.  Since I don't know what you are trying to do, I cannot give examples.  However, the use of the timer block is wrong; the argument should not be 0.  If you want generate a new random number on every time point, you don't need the timer block at all.

analog begin
   random_a = $rdist_normal(seed, 0, sigma1);
   $display("random_a = %.2f\n", random_a);

You mention that you used the timer function to try to mimic the effect of `timescale.  I did not understand that statement.  You should be aware that `timecale has absolutely no effect on the analog block.  If what you really want is to update the random number every 1ns like in the discrete implementation, then you should use 1n rather than 0 in the timer function:

analog begin
   @(timer(1n)) begin
       random_a = $rdist_normal(seed, 0, sigma1);
       $display("random_a = %.2f\n", random_a);

I don't understand why the simulator is complaining about the conflicting context for random_a.  Perhaps if you gave a complete module it would make more sense.


Title: Re: Random Real number from analog block
Post by Lala878 on Jan 10th, 2023, 3:46am

Hello Ken,

thanks for a reply.

I'm making a simple model with a voltage pulse input and a voltage pulse with jitter output (an oscillator with jitter).
The input frequency in this case is predetermined, and it could be given as a parameter probably, but for some other reasons I chose not to have it as a parameter but to calculate it continuously throughout the simulation.

Here's the model:

`include "constants.vams"
`include "disciplines.vams"

`timescale 1ps/1fs

module ClkWithJitter (out, in );

input wreal in;
output wreal out;

wire clkin_d;

reg clkout_d;

parameter real Vhi = 1.2;
parameter real Vlo = 0;
parameter real jitter = 0;      // 1-sigma standard deviation period jitter value
                              //  must be input in [ps] in reference to the `timescale / dscale updated accordingly

real Vth, random, period, dpj;
real tr1, tr2;

parameter integer dscale = 1e12; // the jitter value scale
parameter integer seednum = 10;
integer seed;

initial begin
seed = seednum;
Vth = (Vhi + Vlo)/2.0;
period = 0.001;
dpj = 0.0;
tr1 = 0;
tr2 = 0;
clkout_d = 1;

end //initial

assign clkin_d = in > Vth;

always begin
     @(posedge clkin_d) tr1 = $realtime; $display("tr1 = %.3f", tr1);
     @(negedge clkin_d) tr2 = $realtime; $display("tr2 = %.3f", tr2);
     period = 2*(tr2 - tr1); $display("period = %.3f", period);

       random =  ($dist_normal(seed, 0, jitter*dscale) + 0.0)/(dscale/jitter);
     dpj = random;
end //always

always begin
     #((period+dpj)/2) clkout_d = ~clkout_d;

assign out = (period < 1) ? in : clkout_d ? Vhi : Vlo; // the first halfperiod is copied "as is" to the output
                                                                        // this way correct pariod calculation is ensured
                                                                        // and the first halfperiod can always be taken as a reference halfperiod


It's not ideal in quite a few points actually.

I am using Virtuoso and AMS Designer. My testbench is a schematic view. For example, when I instantiate my model in the testbench I can't input "2ps" for jitter, but just a number. I remember being able to do that couple of years ago, so I don't know why I can't do that now, but anyway I got around it at this point...

So, in this example I am generating a random number with $dist_normal() function and sometimes the simulator complains I can't pass it a real parameter but only integers, and sometimes it doesn't complain and continue even though I have jitter defined as a real parameter.
I realized at some point when I exclude an xrun additional argument -disable_sem2009 (which is for compiling SystemVerilog and not VerilogAMS, it works ok...(systemVerilog part of this story is yet another story for itself...))

The other part that is not ideal is the whole "period" implementation I would say.
Since I am making a continuous always block with "period" as a delay parameter, then "period" has to be defined as something other than zero, and at this point it's a value that I know it won't interfere with the specification.
As well as the final assignment with that "if period < 1" line, it's because I assumed (not too rightfully) that the real calculated period will most probably always be bigger than 1ns.

Title: Re: Random Real number from analog block
Post by Lala878 on Jan 10th, 2023, 4:00am

I forgot to comment on the analog block part of the original problem...

I have this code example, I think it can even be found on this site with Veirlog-AMS examples.

// VerilogA for Jitter_gen

`include "constants.vams"
`include "disciplines.vams"

module Jitter_gen(out,in);

input in;
output out;
electrical in, out;

parameter real Vlo=0, Vhi=1.2;
parameter integer ratio=2 from [2:inf);
parameter integer dir=1 from [-1:1] exclude 0;
parameter integer seednum=0;

// dir=1 for positive edge trigger
// dir=-1 for negative edge trigger

parameter real tt=1n from (0:inf);
parameter real td=0 from (0:inf);
parameter real jitter=0 from [0:td/5); // edge-to-edge jitter
parameter real ttol=1p from [0:td/5); // recommend ttol << jitter

integer count, n, seed;
real dt;

analog begin
@(initial_step) seed = seednum;
@(cross(V(in)-(Vhi + Vlo)/2, dir, ttol)) begin
// count input transitions
count = count + 1;
if (count >= ratio)
count = 0;
n = (2*count >= ratio);
// add jitter
dt = jitter*$rdist_normal(seed,0,1);      
V(out) <+ transition(n ? Vhi : Vlo, td+dt, tt);


When I tried this code, the output had a period that was twice as long than the input period, so you would have to account for that. Which is not problematic, but I thought it could be done differently.
If time delay "td" was 0 and you add a "dt" with jitter that was in some case calculated as negative since we're picking up random numbers around 0 then the transition() function would object saying you can't put negative delay and the simulation fails in that case.

I would like to avoid using an analog solver, so I would prefer not to use an analog block at all, but I was curious anyway since I wanted to generate a real random number with the $rdist_normal() function but I didn't know how to trigger an analog block effectively and if I can use the calculated value outside analog block.

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