The Designer's Guide Community
Forum
Welcome, Guest. Please Login or Register. Please follow the Forum guidelines.
May 17th, 2022, 7:36am
Pages: 1
Send Topic Print
Verilog AMS sine generator (Read 453 times)
Praseetha Pn
New Member
*
Offline



Posts: 6

Verilog AMS sine generator
Jan 14th, 2022, 12:10am
 
module rxbb_lp_wrapper


 (
   VDD1V8BB ,
   VSS1V8A ,
   VSS1V8BB ,
   VSS_SUB ,
   bbmux_lp_n_ai_amplitude ,
   bbmux_lp_n_ai_frequency ,
   bbmux_lp_n_ai_phase ,
   bbmux_lp_p_ai_amplitude ,
   bbmux_lp_p_ai_frequency ,
   bbmux_lp_p_ai_phase ,
   lp_n_ai_amplitude ,
   lp_n_ai_frequency ,
   lp_n_ai_phase ,
   lp_p_ai_amplitude ,
   lp_p_ai_frequency ,
   lp_p_ai_phase ,
   ibg_lp_untrim_50u_p_ai ,
   iptat_lp_untrim_50u_p_ai ,
   lp_en_i ,
   lp_noise_filter_en_i ,
   lp_test_sel_i ,
   trim_lp_fb_fc_i ,
   trim_lp_pass_fc_i ,
   vcm1_750m_ai ,
   vcm3_600m_ai ,
   lp1_n_amux_ao,
   lp1_p_amux_ao,
   lp2_n_amux_ao,
   lp2_p_amux_ao,
   lp_n_ao,
   lp_p_ao
   );
       
 input   VDD1V8BB;
 input   VSS1V8A;
 input   VSS1V8BB;
 input   VSS_SUB;
 input   bbmux_lp_n_ai_amplitude ;
 input   bbmux_lp_n_ai_frequency ;
 input   bbmux_lp_n_ai_phase ;
 input   bbmux_lp_p_ai_amplitude ;
 input   bbmux_lp_p_ai_frequency ;
 input   bbmux_lp_p_ai_phase ;
 input   lp_n_ai_amplitude ;
 input   lp_n_ai_frequency ;
 input   lp_n_ai_phase ;
 input   lp_p_ai_amplitude ;
 input   lp_p_ai_frequency ;
 input   lp_p_ai_phase ;
 input   [1:0] ibg_lp_untrim_50u_p_ai;
 input   [1:0] iptat_lp_untrim_50u_p_ai;
 input   lp_en_i;
 input   lp_noise_filter_en_i;
 input   lp_test_sel_i;
 input   [2:0] trim_lp_fb_fc_i;
 input   [3:0] trim_lp_pass_fc_i;
 input   vcm1_750m_ai;
 input   vcm3_600m_ai;
 output  lp1_n_amux_ao;
 output  lp1_p_amux_ao;
 output  lp2_n_amux_ao;
 output  lp2_p_amux_ao;
 output  lp_n_ao;
 output  lp_p_ao;
 
 wreal    VDD1V8BB;
 wreal    VSS1V8A;
 wreal    VSS1V8BB;
 wreal    VSS_SUB;
 wreal    bbmux_lp_n_ai_amplitude ;
 wreal    bbmux_lp_n_ai_frequency ;
 wreal    bbmux_lp_n_ai_phase ;
 wreal    bbmux_lp_p_ai_amplitude ;
 wreal    bbmux_lp_p_ai_frequency ;
 wreal    bbmux_lp_p_ai_phase ;
 wreal    lp_n_ai_amplitude ;
 wreal    lp_n_ai_frequency ;
 wreal    lp_n_ai_phase ;
 wreal    lp_p_ai_amplitude ;
 wreal    lp_p_ai_frequency ;
 wreal    lp_p_ai_phase ;
 wreal    ibg_lp_untrim_50u_p_ai[1:0];
 wreal    iptat_lp_untrim_50u_p_ai[1:0];
 wreal    lp_en_i;
 wreal    lp_noise_filter_en_i;
 wreal    lp_test_sel_i;
 wreal    trim_lp_fb_fc_i[2:0];
 wreal    trim_lp_pass_fc_i[3:0];
 wreal    vcm1_750m_ai;
 wreal    vcm3_600m_ai;
 wreal    lp1_n_amux_ao;
 wreal    lp1_p_amux_ao;
 wreal    lp2_n_amux_ao;
 wreal    lp2_p_amux_ao;
 wreal    lp_n_ao;
 wreal    lp_p_ao;
 electrical      bbmux_lp_n_ai;
 electrical      bbmux_lp_p_ai;
 electrical      lp_n_ai;
 electrical      lp_p_ai;
 
 real       offset = 2.5;
 
 
 
  v(bbmux_lp_n_ai)  <+ (offset + (bbmux_lp_n_ai_amplitude * sin(2*3.14159265358979323846*bbmux_lp_n_ai_frequency*$abstime)));
  v(bbmux_lp_p_ai)  <+ (offset + (bbmux_lp_p_ai_amplitude * sin(2*3.14159265358979323846*bbmux_lp_p_ai_frequency*$abstime)));
  v(lp_n_ai)        <+ (offset + (lp_n_ai_amplitude * sin(2*3.14159265358979323846*lp_n_ai_frequency*$abstime)));
  v(lp_p_ai)        <+ (offset + (lp_p_ai_amplitude * sin(2*3.14159265358979323846*lp_p_ai_frequency*$abstime)));
     $bound_step(0.05/lp_p_ai_frequency);
 
 

 
 
   // Instantiate the analog netlist
 rxbb_lp rxbb_lp_inst(
   .VDD1V8BB(VDD1V8BB) ,
   .VSS1V8A(VSS1V8A) ,
   .VSS1V8BB(VSS1V8BB) ,
   .VSS_SUB(VSS_SUB) ,
   .bbmux_lp_n_ai(bbmux_lp_n_ai) ,
   .bbmux_lp_p_ai(bbmux_lp_p_ai) ,
   .ibg_lp_untrim_50u_p_ai(ibg_lp_untrim_50u_p_ai) ,
   .iptat_lp_untrim_50u_p_ai(iptat_lp_untrim_50u_p_ai) ,
   .lp_en_i(lp_en_i) ,
   .lp_n_ai(lp_n_ai) ,
   .lp_noise_filter_en_i(lp_noise_filter_en_i) ,
   .lp_p_ai(lp_p_ai) ,
   .lp_test_sel_i(lp_test_sel_i) ,
   .trim_lp_fb_fc_i(trim_lp_fb_fc_i) ,
   .trim_lp_pass_fc_i(trim_lp_pass_fc_i) ,
   .vcm1_750m_ai(vcm1_750m_ai) ,
   .vcm3_600m_ai(vcm3_600m_ai) ,
   .lp1_n_amux_ao(lp1_n_amux_ao) ,
   .lp1_p_amux_ao(lp1_p_amux_ao) ,
   .lp2_n_amux_ao(lp2_n_amux_ao) ,
   .lp2_p_amux_ao(lp2_p_amux_ao) ,
   .lp_n_ao(lp_n_ao) ,
   .lp_p_ao(lp_p_ao)
 );
 

endmodule

I am trying to create a wrapper for my rxbb_lp module, the input of the wrapper is diffrent from the input of the module and I want to generate a signal(sine wave in my wrapper).
is this the correct way to do it?
Back to top
 
 
View Profile   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2335
Silicon Valley
Re: Verilog AMS sine generator
Reply #1 - Jan 14th, 2022, 12:56am
 
Generally it is not very productive to dump 140 lines of code in a post and then ask a non-specific question like "is this the best way to do this.  It is hard to comment because I have no idea what you are trying to do, and yet I have lots of comments based on obvious problems in the code, but I am not sure what you are looking for. So I risk investing my time in a long response that of little value to you.

When posting, try to make you code fragments much shorter and your questions specific and bounded.

-Ken
Back to top
 
 
View Profile WWW   IP Logged
Praseetha Pn
New Member
*
Offline



Posts: 6

Re: Verilog AMS sine generator
Reply #2 - Jan 14th, 2022, 1:03am
 
Hi Ken,
In short this is what I am trying to do.. I have created a wrapper around my  .vams netlist of an anlog circuit. I want to drive a signal as an input from the digital domain to my analog netlist hence I created a wrapper.
The input to the wrapper is a frequency ,phase and amplitude but I want to drive a sine wave as input to my analog netlist, hence I am creating this in my wrapper and trying to feed that as input to my vams netlist as it needs a signal as an input.

This is the part of the code which I need help with:
electrical      bbmux_lp_n_ai;
 electrical      bbmux_lp_p_ai;
 electrical      lp_n_ai;
 electrical      lp_p_ai;
 
 real       offset = 2.5;
 
 assign  bbmux_lp_n_ai = offset + (bbmux_lp_n_ai_amplitude * $cos(2*3.14159265358979323846*bbmux_lp_n_ai_frequency*$abstime));
 assign  bbmux_lp_p_ai = offset + (bbmux_lp_p_ai_amplitude * $cos(2*3.14159265358979323846*bbmux_lp_p_ai_frequency*$abstime));
 assign  lp_n_ai = offset + (lp_n_ai_amplitude * $cos(2*3.14159265358979323846*lp_n_ai_frequency*$abstime));
 assign  lp_p_ai = offset + (lp_p_ai_amplitude * $cos(2*3.14159265358979323846*lp_p_ai_frequency*$abstime));
 

 
 
   // Instantiate the analog netlist
 rxbb_lp rxbb_lp_inst(
   .bbmux_lp_n_ai(bbmux_lp_n_ai) ,
   .bbmux_lp_p_ai(bbmux_lp_p_ai) ,
   .lp_n_ai(lp_n_ai) ,
   .lp_p_ai(lp_p_ai)
);
Back to top
 
 
View Profile   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2335
Silicon Valley
Re: Verilog AMS sine generator
Reply #3 - Jan 14th, 2022, 11:55am
 
Okay, that helps. But you did not ask a question.

The fact that you instantiated the DUT in a wrapper model seem to be of no consequence, correct?  You asking about how to generate a sine wave?

-Ken
Back to top
 
 
View Profile WWW   IP Logged
Praseetha Pn
New Member
*
Offline



Posts: 6

Re: Verilog AMS sine generator
Reply #4 - Jan 14th, 2022, 12:20pm
 
Hi,
Yes as of now I do not see an issue with that.
1. The input to my wrapper is amplitude, frequency and phase
2. But my DUT is an Low pass filter  and I want to drive a signal as input (sine signal).
I want to know how to generate this sine wave in my wrapper ?
what should be the type of this variable be, as it is not an input/output to my wrapper, but only an input to my DUT.

I have tried to create it in my previous code snip but does not work.
Back to top
 
 
View Profile   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2335
Silicon Valley
Re: Verilog AMS sine generator
Reply #5 - Jan 14th, 2022, 1:01pm
 
Let me focus on a simplified example.

First consider the sine generator as a simple component with no hierarchy.  Conceptually it is as simple as this:
Code:
    module sinegen(out, freq, ampl, phase, offset);
    output electrical out;
    input wreal freq, ampl, phase, offset;

    analog V(out) <+ ampl*sin(freq*$abstime + phase) + offset;
    endmodule
 



I'm don't really understand why you want to instantiate the filter in the generator, but conceptually here is how you would do it:
Code:
    module sinegen(out, freq, ampl, phase, offset);
    output electrical out;
    input wreal freq, ampl, phase, offset;
    electrical in;

    lpf(.o(out), .i(.in));

    analog V(in) <+ ampl*sin(freq*$abstime + phase) + offset;
    endmodule
 



Having said that, this generator has a number of issues.  First, it is filled with discontinuities.  They should be eliminated with transition functions.
Code:
    module sinegen(out, freq, ampl, phase, offset);
    output electrical out;
    input wreal freq, ampl, phase, offset;
    parameter tt=1u from [0:inf);

    analog V(out) <+ transition(ampl, 0, tt)*sin(transition(freq, 0, tt)*$abstime + transition(phase, 0, tt)) + transition(offset, 0, tt);
    endmodule
 



For efficiency sake you want to make the transition time tt as long as possible.

Second, when you are generating a high frequency output when there is no corresponding high frequency input, you need to inform the simulator so you don't get aliasing.  You do that by adding a bound on the time step.
Code:
    module sinegen(out, freq, ampl, phase, offset);
    output electrical out;
    input wreal freq, ampl, phase, offset;
    parameter tt=1u from [0:inf);

    analog begin
	  V(out) <+ transition(ampl, 0, tt)*sin(transition(freq, 0, tt)*$abstime + transition(phase, 0, tt)) + transition(offset, 0, tt);
	  $bound_step(10/freq);
    endmodule
 



I use ten points per period.  You probably need at least 4, but realize that the larger you make this number the slower you simulation will be.

Finally, you need to synchronize your kernels, meaning that you need to force the analog simulator to place time points at the events in the digital inputs.  Conceptually you can do that with:
Code:
    module sinegen(out, freq, ampl, phase, offset);
    output electrical out;
    input wreal freq, ampl, phase, offset;
    parameter tt=1u from [0:inf);

    analog begin
	  @(freq or ampl or phase or offset)
		;
	  V(out) <+ transition(ampl, 0, tt)*sin(transition(freq, 0, tt)*$abstime + transition(phase, 0, tt)) + transition(offset, 0, tt);
	  $bound_step(10/freq);
    endmodule
 



I say conceptually because even though that is legal Verilog-AMS code, Cadence has never supported arbitrary events in the analog block, so it must be rewritten as:
Code:
    module sinegen(out, freq, ampl, phase, offset);
    output electrical out;
    input wreal freq, ampl, phase, offset;
    parameter tt=1u from [0:inf);
    reg break = 0;

    always @(freq or ampl or phase or offset) break <= !break;

    analog begin
	  @(posedge break or negedge break)
		;
	  V(out) <+ transition(ampl, 0, tt)*sin(transition(freq, 0, tt)*$abstime + transition(phase, 0, tt)) + transition(offset, 0, tt);
	  $bound_step(10/freq);
    endmodule
 



I just typed this code in from memory, so it might not work as given. But hopefully you find it useful.

Back to top
 
 
View Profile WWW   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2335
Silicon Valley
Re: Verilog AMS sine generator
Reply #6 - Jan 14th, 2022, 1:09pm
 
Oh, one last thing.  The argument to a sine function is phase, and phase is the integral  of frequency.  You can only use sin(ωt) if ω is a constant.  If you are only interested in the output of the generator when ω is constant and you are okay with either very high or very low frequencies during changes, then you can continue to use sin(ωt).  This is generally preferred when creating testbench components.  Otherwise you should compute the phase using the idtmod operator.  You would need to do this when modeling a VCO.
Back to top
 
 
View Profile WWW   IP Logged
Praseetha Pn
New Member
*
Offline



Posts: 6

Re: Verilog AMS sine generator
Reply #7 - Jan 15th, 2022, 1:17pm
 
Hi ken,
Thank you so much for the method and help.
I have used it in a similar way now, but modified as I need 4 signal sources.
Code:
module rxbb_lp_wrapper


  (

  
    bbmux_lp_n_ai_amplitude ,
    bbmux_lp_n_ai_frequency ,
    bbmux_lp_n_ai_phase ,
    bbmux_lp_p_ai_amplitude ,
    bbmux_lp_p_ai_frequency ,
    bbmux_lp_p_ai_phase ,
    lp_n_ai_amplitude ,
    lp_n_ai_frequency ,
    lp_n_ai_phase ,
    lp_p_ai_amplitude ,
    lp_p_ai_frequency ,
    lp_p_ai_phase ,
    lp1_n_amux_ao,
    lp1_p_amux_ao,
    lp2_n_amux_ao,
    lp2_p_amux_ao,
    lp_n_ao,
    lp_p_ao
    );
	  
  input   bbmux_lp_n_ai_amplitude ;
  input   bbmux_lp_n_ai_frequency ;
  input   bbmux_lp_n_ai_phase ;
  input   bbmux_lp_p_ai_amplitude ;
  input   bbmux_lp_p_ai_frequency ;
  input   bbmux_lp_p_ai_phase ;
  input   lp_n_ai_amplitude ;
  input   lp_n_ai_frequency ;
  input   lp_n_ai_phase ;
  input   lp_p_ai_amplitude ;
  input   lp_p_ai_frequency ;
  input   lp_p_ai_phase ;

  output  lp1_n_amux_ao;
  output  lp1_p_amux_ao;
  output  lp2_n_amux_ao;
  output  lp2_p_amux_ao;
  output  lp_n_ao;
  output  lp_p_ao;
  

  wreal   bbmux_lp_n_ai_amplitude ;
  wreal   bbmux_lp_n_ai_frequency ;
  wreal   bbmux_lp_n_ai_phase ;
  wreal   bbmux_lp_p_ai_amplitude ;
  wreal   bbmux_lp_p_ai_frequency ;
  wreal   bbmux_lp_p_ai_phase ;
  wreal   lp_n_ai_amplitude ;
  wreal   lp_n_ai_frequency ;
  wreal   lp_n_ai_phase ;
  wreal   lp_p_ai_amplitude ;
  wreal   lp_p_ai_frequency ;
  wreal   lp_p_ai_phase ;
  
  electrical  lp1_n_amux_ao;
  electrical  lp1_p_amux_ao;
  electrical  lp2_n_amux_ao;
  electrical  lp2_p_amux_ao;
  electrical  lp_n_ao;
  electrical  lp_p_ao;
  
  electrical	bbmux_lp_n_ai;
  electrical	bbmux_lp_p_ai;
  electrical	lp_n_ai;
  electrical	lp_p_ai;
  

   parameter tt=1u from [0:inf);

    analog begin
    V(bbmux_lp_n_ai) <+ transition(bbmux_lp_n_ai_amplitude, 0, tt)*sin(transition(bbmux_lp_n_ai_frequency, 0, tt)*$abstime + transition(bbmux_lp_n_ai_phase, 0, tt)) + transition(0, 0, tt);
    $bound_step(10/bbmux_lp_n_ai_frequency);
    V(bbmux_lp_p_ai) <+ transition(bbmux_lp_p_ai_amplitude, 0, tt)*sin(transition(bbmux_lp_p_ai_frequency, 0, tt)*$abstime + transition(bbmux_lp_p_ai_phase, 0, tt)) + transition(0, 0, tt);
    $bound_step(10/bbmux_lp_p_ai_frequency);
    V(lp_n_ai) <+ transition(lp_n_ai_amplitude, 0, tt)*sin(transition(lp_n_ai_frequency, 0, tt)*$abstime + transition(lp_n_ai_phase, 0, tt)) + transition(0, 0, tt);
    $bound_step(10/lp_n_ai_frequency);
    V(lp_p_ai) <+ transition(lp_p_ai_amplitude, 0, tt)*sin(transition(lp_p_ai_frequency, 0, tt)*$abstime + transition(lp_p_ai_phase, 0, tt)) + transition(0, 0, tt);
    $bound_step(10/lp_p_ai_frequency);
    end
    
  
    // Instantiate the analog netlist
  rxbb_lp rxbb_lp_inst(
    .bbmux_lp_n_ai(bbmux_lp_n_ai) ,
    .bbmux_lp_p_ai(bbmux_lp_p_ai) ,
    .lp_n_ai(lp_n_ai) ,

    .lp_p_ai(lp_p_ai) ,
    .lp1_n_amux_ao(lp1_n_amux_ao) ,
    .lp1_p_amux_ao(lp1_p_amux_ao) ,
    .lp2_n_amux_ao(lp2_n_amux_ao) ,
    .lp2_p_amux_ao(lp2_p_amux_ao) ,
    .lp_n_ao(lp_n_ao) ,
    .lp_p_ao(lp_p_ao)
  );
  

endmodule 



I have declared the inputs of the wrapper as wreal and my intermediate inputs as electrical and my final outputs as electrical.
When I execute this model, which is actually being instantiated in a bigger model;
I come across this error:
xmelab: *E,CUVNCM (../rxbb_lp_wrapper_13_puducodenarp/vams/testfixture_reference_rxbb_lp_model_wra
pper.vams,190|39): No connection module found:Need an input port of continuous discipline electrical, and a wreal output port of discrete discipline logic, at instance tb_rxbb_lp_model_wrapper.converter_shell_reference_rxbb_lp_model_wrapper_inst.te
stfixture_reference_rxbb_lp_model_wrapper_inst.reference_rxbb_lp_wrapper_inst, between actual port lp_p_ai_frequency and formal port lp_p_ai_frequency.
   .lp_p_ai_phase(lp_p_ai_phase) ,
For all the 12 input parameters I have used:
should be defined as wreal or can I change it to a suitabe option ?
The module that instantiates this module has defined it as
electrical  bbmux_lp_p_ai_phase.
Back to top
 
 
View Profile   IP Logged
Praseetha Pn
New Member
*
Offline



Posts: 6

Re: Verilog AMS sine generator
Reply #8 - Jan 26th, 2022, 6:09am
 
Hi again,
I tried the exact code and it works well for the first frequency rage.
I am using a for loop in my test bench to increase the frequency from 1mhz to 100mhz in steps of 10, when I do so the frequency of the second set of sine wave should be 11mhz but it is in ghz range! is there any reason for that ?
Back to top
 
 
View Profile   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2335
Silicon Valley
Re: Verilog AMS sine generator
Reply #9 - Jan 26th, 2022, 4:58pm
 
Asking someone to help you spot a bug in code you have not disclosed is a ridiculous request.
Back to top
 
 
View Profile WWW   IP Logged
Praseetha Pn
New Member
*
Offline



Posts: 6

Re: Verilog AMS sine generator
Reply #10 - Jan 31st, 2022, 12:12am
 
Hi,
This works fine,
  V(bbmux_lp_n_ai) <+ bbmux_lp_n_ai_amplitude * sin(2*`M_PI* bbmux_lp_n_ai_frequency*$abstime) + 0.75;
  $bound_step(0.1/bbmux_lp_n_ai_frequency);
  V(bbmux_lp_p_ai) <+ bbmux_lp_p_ai_amplitude * sin(2*`M_PI* bbmux_lp_p_ai_frequency*$abstime)+ 0.75;
  $bound_step(0.1/bbmux_lp_n_ai_frequency);
  V(lp_n_ai) <+ lp_n_ai_amplitude * sin(2*`M_PI* lp_n_ai_frequency*$abstime) + 0.75;
  $bound_step(0.1/bbmux_lp_n_ai_frequency);
  V(lp_p_ai) <+ lp_p_ai_amplitude * sin(2*`M_PI* lp_p_ai_frequency*$abstime) +0.75;
  $bound_step(0.1/bbmux_lp_n_ai_frequency);

It was the extra features like the transition that caused the issue.
Back to top
 
 
View Profile   IP Logged
Ken Kundert
Global Moderator
*****
Offline



Posts: 2335
Silicon Valley
Re: Verilog AMS sine generator
Reply #11 - Feb 1st, 2022, 1:22pm
 
The transition functions should only be applied to the values that change abruptly  Not to the values that change continuously.  So, you code should look like this:
Code:
V(out) <+ transtition(ampl, 0, tt) * sin(6.28*transition(freq, 0, t)*$abstime) + transition(offset, 0 tt); 


Notice that the sine function is outside any transition funciton.

-Ken
Back to top
 
 
View Profile WWW   IP Logged
Pages: 1
Send Topic Print
Copyright 2002-2022 Designer’s Guide Consulting, Inc. Designer’s Guide® is a registered trademark of Designer’s Guide Consulting, Inc. All rights reserved. Send comments or questions to editor@designers-guide.org. Consider submitting a paper or model.