• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Mixed-Signal Design
  3. Verilog A: analog event needed to create a decimal to binary...

Stats

  • Locked Locked
  • Replies 3
  • Subscribers 65
  • Views 16647
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Verilog A: analog event needed to create a decimal to binary block

NewScreenName
NewScreenName over 3 years ago

Hi,

I am trxing to create a VerilogA model of a decimal to binary converter. Basically I would like to give an input Vin via vdc voltage source and get it converted to an output bus of N nets being the binary representation.

For example if Vin net has a voltage of  5V and the model has 4 bits, then the output bus will be out[3:0] with out=0,Vdd,0,Vdd.

I could do this with the code shown below, but that works only for a DC simulation, because the @(initial_step) forces the model to calculate the output at the beginning of the simulation. To make it work for a transient simulation I would need an analog event to check at any change in V(Vin) (voltage at Vin net), while I am aware only of "cross" or "above" functions to use in the sensitivity, and of course it isn't practical to define the all 2^bits number of thresholds V(in) might cross.

Is there any way to trigger an analog event at any change on a given voltage? (in this case V(in))

Thank you

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

module decimal2binary(in, out);

parameter real vlogic_high = 0.6 from [0:inf);
parameter real vlogic_low = 0.0 from [0:inf);
parameter real td = 1p from [0:inf);
parameter real tt = 10p from [0:inf);

input in;
output [16:0] out;

electrical in;
electrical [16:0] out; 

real vd[16:0];
real V_FS=pow(2,17)-1;
real halfref=V_FS/2;
real unconverted;
integer i;
genvar j;

analog begin

@(initial_step) begin
     unconverted=V(in);
     for (i=16; i>=0; i=i-1) begin
          if(unconverted>halfref) begin
             vd[i]=vlogic_high;
             unconverted = unconverted - halfref;
          end else begin
             vd[i] = vlogic_low;
          end
          unconverted = unconverted * 2;
      end

end
      for(j=16; j>=0; j=j-1) begin
            V(out[j])<+transition(vd[j], td, tt);
       end

end


endmodule

  • Cancel
Parents
  • ShawnLogan
    ShawnLogan over 3 years ago

    Dear NewScreenName,

    NewScreenName said:
    I am trxing to create a VerilogA model of a decimal to binary converter. Basically I would like to give an input Vin via vdc voltage source and get it converted to an output bus of N nets being the binary representation.

    NewScreenName said:
    I could do this with the code shown below, but that works only for a DC simulation, because the @(initial_step) forces the model to calculate the output at the beginning of the simulation.

    I have a few veriloga based subcircuits to implement an A/D converter which function as desired for a transient simulation when the input signal signal VIN changes value as a function of time. I posted an example of a 3 bit version very recently in response to a Forum question not related to yours, but as it may be of use to you NewScreenName, I am including an 8 bit version. It does not contain a loop to determine the output code from the input decimal value as does your code (emulating an SAR based ADC), but is implemented as a flash ADC. If you were to extend it to just over twice its current size (essentially creating an output bus <16:0> in lieu of the <7:0> bus it provides), I believe it would provide a potential solution for the issue you are wrestling with. Hopefully, I understood your question correctly!

    Shawn


    // VerilogA for simple transient compatible eightbit_ad,
    // sml 8/10/2020


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

    module eightbit_ad(VOUT, VDD, VIN, VSS);
    output [7:0] VOUT;
    electrical [7:0] VOUT;
    input VDD;
    electrical VDD;
    input VIN;
    electrical VIN;
    input VSS;
    electrical VSS;
    integer vin_integer;
    parameter real rise_fall_time = 50e-12;
    integer vout[7:0];

    analog begin

    vin_integer = V(VIN,VSS);

    if (vin_integer%256<128) V(VOUT[7],VSS)<+V(VSS);
    else V(VOUT[7],VSS)<+V(VDD,VSS);
    V(VOUT[7],VSS)<+ transition(V(VDD)*vout[7],rise_fall_time,rise_fall_time);

    if (vin_integer%128<64) V(VOUT[6],VSS)<+V(VSS);
    else V(VOUT[6],VSS)<+V(VDD,VSS);
    V(VOUT[6],VSS)<+ transition(V(VDD)*vout[6],rise_fall_time,rise_fall_time);

    if (vin_integer%64<32) V(VOUT[5],VSS)<+V(VSS);
    else V(VOUT[5],VSS)<+V(VDD,VSS);
    V(VOUT[5],VSS)<+ transition(V(VDD)*vout[5],rise_fall_time,rise_fall_time);

    if (vin_integer%32<16) V(VOUT[4],VSS)<+V(VSS);
    else V(VOUT[4],VSS)<+V(VDD,VSS);
    V(VOUT[4],VSS)<+ transition(V(VDD)*vout[4],rise_fall_time,rise_fall_time);

    if (vin_integer%16<8) V(VOUT[3],VSS)<+V(VSS);
    else V(VOUT[3],VSS)<+V(VDD,VSS);
    V(VOUT[3],VSS)<+ transition(V(VDD)*vout[3],rise_fall_time,rise_fall_time);

    if (vin_integer%8<4) V(VOUT[2],VSS)<+V(VSS);
    else V(VOUT[2],VSS)<+V(VDD,VSS);
    V(VOUT[2],VSS)<+ transition(V(VDD)*vout[2],rise_fall_time,rise_fall_time);

    if (vin_integer%4<2) vout[1]=0;
    else vout[1]=1;
    V(VOUT[1],VSS)<+ transition(V(VDD)*vout[1],rise_fall_time,rise_fall_time);

    if (vin_integer%2<1) vout[0]=0;
    else vout[0]=1;
    V(VOUT[0],VSS)<+ transition(V(VDD)*vout[0],rise_fall_time,rise_fall_time);

    end

    endmodule

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 3 years ago in reply to ShawnLogan

    First thing, it's a pretty bad idea to have voltages of around 131072V (full scale) in your circuit at the same time as realistic IC voltages - this will kill accuracy and performance; the "highvoltage=yes" option might help, but it's a pretty bad idea to have such big signals (as voltages) at the same time - otherwise it tends to limit Spectre's ability to use a global reference for local truncation error control.

    In principle you should just remove the @(initial_step) from around your first code block, which means that it does it at every timestep. In essence that's what 's code is doing (without using genvar and a for loop). This wouldn't try to force time steps due to the changing input signal - so you'd (in principle) only get an output bus value at the time steps the simulator has chosen. However, the challenge is likely to be that the output transitions will cause additional time steps which would then lead to the Verilog-A code triggering more conversions and hence more time steps and it can easily get pretty slow (especially for a converter with 2**17 steps).

    Similarly you could potentially devise an @(cross) statement something like V(in)-floor(V(in))-0.5 - I didn't check this - but that's going to be bad too because it would force a tilmestep for each potential code - again, that will kill performance.

    It would probably be better to just make your verilog-a mode clocked in some way so that it only does the conversion on a clocked signal rather than at arbitrary time?

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • ShawnLogan
    ShawnLogan over 3 years ago in reply to Andrew Beckett

    Dear Andrew,

    Andrew Beckett said:
    First thing, it's a pretty bad idea to have voltages of around 131072V (full scale) in your circuit at the same time as realistic IC voltages - this will kill accuracy and performance; the "highvoltage=yes" option might help, but it's a pretty bad idea to have such big signals (as voltages) at the same time - otherwise it tends to limit Spectre's ability to use a global reference for local truncation error control.

    You are absolutely correct Andrew! I am aware of this issue with this code as with even values as high as the 256 value in it, accuracy is impacted and I encourage those using it to use the "high voltage" option. Thank you for pointing this out! I should have included a comment to that effect - my oversight totally!

    An alternative that I believe avoids this issue is to introduce a scale factor (i.e., SCALE_FACTOR) following the input signal VIN within the veriloga block. Although the input signal will have then still have a dynamic range of 2^17/SCALE_FACTOR to 1/SCALE_FACTOR, the value of 2^17/SCALE_FACTOR can be chosen to be a more realistic value. For example, SCALE_FACTOR might be set to 2^15 such that VIN will span 4V to 2^(-15) = 30.5175 uV

    Shawn

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • ShawnLogan
    ShawnLogan over 3 years ago in reply to Andrew Beckett

    Dear Andrew,

    Andrew Beckett said:
    First thing, it's a pretty bad idea to have voltages of around 131072V (full scale) in your circuit at the same time as realistic IC voltages - this will kill accuracy and performance; the "highvoltage=yes" option might help, but it's a pretty bad idea to have such big signals (as voltages) at the same time - otherwise it tends to limit Spectre's ability to use a global reference for local truncation error control.

    You are absolutely correct Andrew! I am aware of this issue with this code as with even values as high as the 256 value in it, accuracy is impacted and I encourage those using it to use the "high voltage" option. Thank you for pointing this out! I should have included a comment to that effect - my oversight totally!

    An alternative that I believe avoids this issue is to introduce a scale factor (i.e., SCALE_FACTOR) following the input signal VIN within the veriloga block. Although the input signal will have then still have a dynamic range of 2^17/SCALE_FACTOR to 1/SCALE_FACTOR, the value of 2^17/SCALE_FACTOR can be chosen to be a more realistic value. For example, SCALE_FACTOR might be set to 2^15 such that VIN will span 4V to 2^(-15) = 30.5175 uV

    Shawn

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
No Data

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information