• 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. Custom IC Design
  3. VerilogA issues -- transition function

Stats

  • Locked Locked
  • Replies 10
  • Subscribers 125
  • Views 10564
  • 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

VerilogA issues -- transition function

funfet
funfet over 8 years ago

Hello,

I'm creating a verilogA model for a circuit component and wish to have smoothly transitioning variables. The variables are of the real data type and I can't seem to use the transition function on them without the simulation returning an error. Is there some equivalent of the transition function that I can use on real data types just like I can use for currents (e.g.). Above I have pictures showing the variables that I wish to smooth out. I'm trying to eliminate the flat plateaus where the variables are constant.

Thank you

Paul

  • Cancel
Parents
  • funfet
    funfet over 8 years ago
    I found some bugs in the code above. This is the revised code.

    I think sometimes the derivates do not evaluate correctly, specifically:

    (polarization_next-polarization_prev)/(time_next-time_prev)

    I was hoping that there would be a bit of a lag between the polarization_next and polarization_prev when the polarization variable is changing but sometimes they are equal. Is there a better way to take a derivative? I was trying to use the ddt function but I think it only works for voltages and currents, not variables. I think part of the problem may be that the variables are updated too often and so sometimes can evaluate to the same value when the incremental change in transient time is small enough even though the polarization may be changing but not quickly enough to register a change.

    For transient simulations for example the polarization_next and polarization prev variables may evaluate to be the same for times 1 s and 1.001 s but may be different at 1 s and 1.1 s. Is there a way to force verilogA to limit how often it evaluate the variables (i.e. limit the minimum resolution of the time step of the transient time)?

    #################### revised code ######################################

    /*

    This file implements the extraction of csv data into a verilog variable and then implements a Preisach implemenatation of a FE capacitor SPICE
    model based on the Preisach data.

    */

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

    module test_func(p,n);

    inout p,n;
    electrical p,n;

    //files for reading/writing
    integer mcd, fp;

    real data, v_present, v_step;

    real preisach_density[0:1024];// all elements should add up to 1
    real domain_states[0:1024];// all elements should be -1 or +1 (depending on polarity)
    real polarization;//polarization (between -Pr and +Pr)

    real polarization_prev, polarization_next;
    real time_prev, time_next;
    real v_prev, v_next;

    integer row_offset, column_offset;

    real current_calc;

    integer i, j, k;//used in loops

    integer rows, columns;//describes area scanned from applied voltage
    integer rows_total, columns_total;//gives number of rows and columns in the grid ("rows" and "columns" should not exceed these values)

    analog begin

    @(initial_step) begin

    //read data from csv file and transfer it to verilog-A array variable
    //data stored in csv file should be preisach distribution
    //csv file should have the same number of elements as arrays "preisach_density" and "domain_states"
    mcd=$fopen("whole_preisach_dist_5_1_2017.csv","r");

    while (!$feof(mcd)) begin

    $fscanf(mcd,"%f", preisach_density[i]);
    domain_states[i] = 0;

    i = i+1;
    end

    v_step = 0.1; // resolution

    rows_total = 3.2/v_step;//the maximum anticipated applied input voltage swing divided by the resolution of the grid cells
    columns_total = 3.2/v_step;//the maximum anticipated applied input voltage swing divided by the resolution of the grid cells

    v_next = V(p,n);

    time_prev = 0;
    time_next = 0;

    // centers the indiciess to the beginning of the fourth quadrant of the Preisach distribution (i.e. half of row_total or columns total plus 1)
    row_offset = 17;
    column_offset = 17;

    end



    if (v_next < v_prev) begin // negative voltage derivative

    rows = row_offset + V(p,n)/(-v_step);

    begin
    if(rows > rows_total)
    rows = rows_total;
    else if(rows < 0)
    rows = 0;
    end

    //for all columns
    for(j = 0; j < columns_total; j=j+1) begin

    //for all rows with a smaller value than "rows"
    for(k=0; k<rows; k=k+1) begin

    domain_states[k*columns_total + j] = -1;
    end
    end
    end

    if (v_next > v_prev) begin // positive voltage derivative

    columns = column_offset + V(p,n)/(v_step);

    begin
    if(columns > columns_total)
    columns = columns_total;
    else if(columns < 0)
    columns = 0;
    end

    for (j=0; j<columns; j=j+1) begin

    for(k=0; k < rows_total; k=k+1) begin

    domain_states[k*columns_total + j] = 1;

    end

    end
    end

    //calculate the present polarization across the device
    polarization = 0;
    for (i=0; i<columns_total*rows_total; i = i+1) begin

    polarization = polarization + preisach_density[i]*domain_states[i];
    end

    //used for calculating derivatives
    polarization_prev = polarization_next;
    polarization_next = polarization;
    v_prev = v_next;
    v_next = V(p,n);
    time_prev = time_next;
    time_next = $abstime;

    begin
    if (time_next == 0)

    current_calc = 0;

    else
    current_calc = (polarization_next - polarization_prev)/(time_next - time_prev)*0.000000001;//0.000000001 is arbitrary

    end

    I(p,n) <+ current_calc;

    end

    endmodule
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • funfet
    funfet over 8 years ago
    I found some bugs in the code above. This is the revised code.

    I think sometimes the derivates do not evaluate correctly, specifically:

    (polarization_next-polarization_prev)/(time_next-time_prev)

    I was hoping that there would be a bit of a lag between the polarization_next and polarization_prev when the polarization variable is changing but sometimes they are equal. Is there a better way to take a derivative? I was trying to use the ddt function but I think it only works for voltages and currents, not variables. I think part of the problem may be that the variables are updated too often and so sometimes can evaluate to the same value when the incremental change in transient time is small enough even though the polarization may be changing but not quickly enough to register a change.

    For transient simulations for example the polarization_next and polarization prev variables may evaluate to be the same for times 1 s and 1.001 s but may be different at 1 s and 1.1 s. Is there a way to force verilogA to limit how often it evaluate the variables (i.e. limit the minimum resolution of the time step of the transient time)?

    #################### revised code ######################################

    /*

    This file implements the extraction of csv data into a verilog variable and then implements a Preisach implemenatation of a FE capacitor SPICE
    model based on the Preisach data.

    */

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

    module test_func(p,n);

    inout p,n;
    electrical p,n;

    //files for reading/writing
    integer mcd, fp;

    real data, v_present, v_step;

    real preisach_density[0:1024];// all elements should add up to 1
    real domain_states[0:1024];// all elements should be -1 or +1 (depending on polarity)
    real polarization;//polarization (between -Pr and +Pr)

    real polarization_prev, polarization_next;
    real time_prev, time_next;
    real v_prev, v_next;

    integer row_offset, column_offset;

    real current_calc;

    integer i, j, k;//used in loops

    integer rows, columns;//describes area scanned from applied voltage
    integer rows_total, columns_total;//gives number of rows and columns in the grid ("rows" and "columns" should not exceed these values)

    analog begin

    @(initial_step) begin

    //read data from csv file and transfer it to verilog-A array variable
    //data stored in csv file should be preisach distribution
    //csv file should have the same number of elements as arrays "preisach_density" and "domain_states"
    mcd=$fopen("whole_preisach_dist_5_1_2017.csv","r");

    while (!$feof(mcd)) begin

    $fscanf(mcd,"%f", preisach_density[i]);
    domain_states[i] = 0;

    i = i+1;
    end

    v_step = 0.1; // resolution

    rows_total = 3.2/v_step;//the maximum anticipated applied input voltage swing divided by the resolution of the grid cells
    columns_total = 3.2/v_step;//the maximum anticipated applied input voltage swing divided by the resolution of the grid cells

    v_next = V(p,n);

    time_prev = 0;
    time_next = 0;

    // centers the indiciess to the beginning of the fourth quadrant of the Preisach distribution (i.e. half of row_total or columns total plus 1)
    row_offset = 17;
    column_offset = 17;

    end



    if (v_next < v_prev) begin // negative voltage derivative

    rows = row_offset + V(p,n)/(-v_step);

    begin
    if(rows > rows_total)
    rows = rows_total;
    else if(rows < 0)
    rows = 0;
    end

    //for all columns
    for(j = 0; j < columns_total; j=j+1) begin

    //for all rows with a smaller value than "rows"
    for(k=0; k<rows; k=k+1) begin

    domain_states[k*columns_total + j] = -1;
    end
    end
    end

    if (v_next > v_prev) begin // positive voltage derivative

    columns = column_offset + V(p,n)/(v_step);

    begin
    if(columns > columns_total)
    columns = columns_total;
    else if(columns < 0)
    columns = 0;
    end

    for (j=0; j<columns; j=j+1) begin

    for(k=0; k < rows_total; k=k+1) begin

    domain_states[k*columns_total + j] = 1;

    end

    end
    end

    //calculate the present polarization across the device
    polarization = 0;
    for (i=0; i<columns_total*rows_total; i = i+1) begin

    polarization = polarization + preisach_density[i]*domain_states[i];
    end

    //used for calculating derivatives
    polarization_prev = polarization_next;
    polarization_next = polarization;
    v_prev = v_next;
    v_next = V(p,n);
    time_prev = time_next;
    time_next = $abstime;

    begin
    if (time_next == 0)

    current_calc = 0;

    else
    current_calc = (polarization_next - polarization_prev)/(time_next - time_prev)*0.000000001;//0.000000001 is arbitrary

    end

    I(p,n) <+ current_calc;

    end

    endmodule
    • 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