• 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. Issues in accuracy of clock generation in Verilog-AMS with...

Stats

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

Issues in accuracy of clock generation in Verilog-AMS with white noise jitter

RFStuff
RFStuff over 4 years ago

Dear All,

I am trying to generate a jittery clock with white noise (normal distribution) jitter of zero mean and 10m UI sigma or standard deviation. 

To check the clock generation is proper, I also generate the clean clock.  I write the -ve edge instants of the clean and jittery clocks into two separate files. I then find difference between the corresponding instants. The distribution of this difference must be gussian as the random jitter.  The code in Verilog-AMS is attached below.

But, I find that the -ve edge instants of the jittery clock are not accurate. The error ( from the expected -ve edge instants ) increases as I increase the transient simulation times. For example, 30th clock edge instant has an error of 3 fs while 300050th clock edge instant has an error of 1.77 ps !! form the expected value.

The  expected -ve edge instants  obtained by adding the CLK_PERIOD_JITTER values  (as in the blow code) of each jitter clock cycles.

The distribution of the expected one  (see Figure 1) and the one obtained from the difference of the clean clock edge instants and the jittery clock edge instants  (see Figure 2) are as below.

Is there any way the accuracy can be improved as this is a very basic and simple code ?

  

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


`timescale 1ns/1fs


module CLK_w_JITTER (clk_jitter,clk_clean);


output clk_clean, clk_jitter ;


reg clk_jitter_x , clk_clean_x;


parameter UI=31p;


parameter sigma_rand_jitter_UI=10m;


parameter fileName_to_write1="/A/CDR_JITTER/file_with_jitter.csv";

parameter fileName_to_write2="/A/CDR_JITTER/file_without_jitter.csv";


real CLK_PERIOD_CLEAN, CLK_PERIOD_JITTER;

real jitter_old;


real jitter;



integer seed, fhandle1, fhandle2;


initial begin
          fhandle = $fopen(fileName_to_write,"w");
          seed=5;
          clk_jitter_x =1'b0;      

          clk_clean_x =1'b0;     
          
          jitter=0;
          jitter_old=0;


          CLK_PERIOD_CLEAN= UI*1e9 ;   // Expressing in ns

          CLK_PERIOD_JITTER= UI*1e9 ;   // Expressing in ns
end

// JITTERY CLOCK GENERATION


always begin
       #(CLK_PERIOD_JITTER/2.0)
          clk_jitter_x = 1'b0;
          jitter_old=jitter;
          jitter = (1e9*sigma_rand_jitter_UI* UI/1000) * $dist_normal(seed,0,1000);     
    
         $fwrite(fhandle1,"%1.12g, ",  jitter*1e-9 );   // First column of the file is the random jitter value that is added with the clean clock period

         CLK_PERIOD_JITTER= CLK_PERIOD_CLEAN+ ((jitter-jitter_old));

    
         $fwrite(fhandle1,"%1.12g, %1.12g \n",CLK_PERIOD_JITTER*1e-9,  $realtime*1e-9 );   // Second column of the file is the jittery clock period and Third column of the file is the -ve clock edge instant of the jittery clock

      #(CLK_PERIOD_JITTER/2.0)   
         clk_jitter_x = 1'b1;

end

// CLEAN CLOCK GENERATION


always begin
       #(CLK_PERIOD_CLEAN/2.0)
          clk_clean_x = 1'b0;          
    
         
         $fwrite(fhandle2,"%1.12g \n",  $realtime*1e-9 );   // Second column of the file is the -ve clock edge instant of the clean clock

      #(CLK_PERIOD_CLEAN/2.0)   
        clk_clean_x = 1'b1;

end


assign clk_jitter=clk_jitter_x ;


assign clk_clean=clk_clean_x ;

endmodule

Kind Regards,

  • Cancel
Parents
  • Andrew Beckett
    Andrew Beckett over 4 years ago

    My guess is that you're running out of resolution in the output file. I started playing with it, and corrected the mistake in the code (it uses fhandle1 and fhandle2, but opens just fhandle, which isn't defined). It would also be useful to know how you're processing the output file (mainly because I don't want to be spending a while figuring out what you've written where, how you're analysing it, and so on; I'm being lazy - especially as I am on vacation this week!).

    So please provide some detail on how long you're running the simulation for, the MATLAB scripts you're using the analyse the output (I assume it's MATLAB from the graphs), and so on...

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • RFStuff
    RFStuff over 4 years ago in reply to Andrew Beckett

    Dear Andrew,

    I have attached the AMS and the MATLAB codes here.

    Also, the AMS code calculates the expected -ve clock edge instants of the jittery clocks by adding all the previous jittery clock periods. These values are then written into the file.

    If I find the clock jitter form these values ( i.e. by subtracting the -ve clock edge instants of the clean clock form the expected -ve edge instances), the distribution comes as expected with zero mean and 10mUI sigma.

    The distribution plot is shown in figure 3.

    Figure 2 shows the distribution plot of the clock jitter obtained by subtracting the -ve clock edge instants of the clean clock form the actual -ve edge instances generated by AMS simulation.

    Figure 1 shows the distribution plot of the jitter values generated by $dist_normal() command in the code.

    I ran the AMS simulation for 10 us that took 65 s in my machine.

    The AMS code:-

    //Verilog-AMS HDL for "EXAMPLE", "CLK_JITTER_ANA" "verilogams"

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


    `timescale 1ns/1fs


    module CLK_JITTER_ANA (clk_jitter,clk_clean);


    output clk_clean, clk_jitter ;


    reg clk_jitter_x , clk_clean_x;


    parameter UI=31p;


    parameter sigma_rand_jitter_UI=10m;


    parameter fileName_to_write1="/A/CDR_JITTER/file_with_jitter.csv";

    parameter fileName_to_write2="/A/CDR_JITTER/file_without_jitter.csv";


    real CLK_PERIOD_CLEAN, CLK_PERIOD_JITTER;

    real jitter_previous;


    real jitter_current;

    real neg_edge_instant;

    integer seed, fhandle1, fhandle2, first_edge;


    initial begin

    fhandle1 = $fopen(fileName_to_write1,"w");

    fhandle2 = $fopen(fileName_to_write2,"w");

    seed=5;

    clk_jitter_x =1'b0;

    clk_clean_x =1'b0;

    jitter_current=0;

    jitter_previous=0;


    CLK_PERIOD_CLEAN= UI*1e9 ; // Expressing in ns

    CLK_PERIOD_JITTER= UI*1e9 ; // Expressing in ns

    first_edge=1;
    end

    // JITTERY CLOCK GENERATION


    always begin

    #(CLK_PERIOD_JITTER/2.0)

    clk_jitter_x = 1'b1;


    #(CLK_PERIOD_JITTER/2.0)

    clk_jitter_x = 1'b0;

    // Below if-else portion of the code is to write the first -ve clock edge instant for which jitter is NOT added.
    if (first_edge > 0) begin

    neg_edge_instant=$realtime*1e-9;

    $fwrite(fhandle1,"%1.12g, %1.12g, %1.12g, %1.12g \n", jitter_current*1e-9, CLK_PERIOD_JITTER*1e-9, neg_edge_instant, $realtime*1e-9 );

    // First column of the file is the jitter added to the edge
    // Second column of the file is the jittery clock period for the current cycle
    // Third column of the file is the expected -ve colck edge instant of the jittery clock
    // Fourth column of the file is the actual -ve colck edge instant of the jittery clock generated by the code

    first_edge=0;
    end
    else begin

    $fwrite(fhandle1,"%1.12g, %1.12g, %1.12g, %1.12g \n", jitter_current*1e-9, CLK_PERIOD_JITTER*1e-9, neg_edge_instant, $realtime*1e-9 );

    // First column of the file is the jitter added to the edge
    // Second column of the file is the jittery clock period for the current cycle
    // Third column of the file is the expected -ve colck edge instant of the jittery clock
    // Fourth column of the file is the actual -ve colck edge instant of the jittery clock generated by the code

    end

    jitter_previous=jitter_current;

    jitter_current = (1e9*sigma_rand_jitter_UI* UI/1000) * $dist_normal(seed,0,1000);


    CLK_PERIOD_JITTER= CLK_PERIOD_CLEAN + ((jitter_current-jitter_previous)); // jitter_previous is substracted in order to bring the nth -ve jittery clock edge to that of the clean clock

    // and then jitter_current is added to shift it by jitte_current form the clean clock edge.



    neg_edge_instant=neg_edge_instant + (CLK_PERIOD_JITTER*1e-9); // Expected -ve clock edge instants are obtained by adding the past values of CLK_PERIOD_JITTER

    end

    // CLEAN CLOCK GENERATION


    always begin

    #(CLK_PERIOD_CLEAN/2.0)

    clk_clean_x = 1'b1;


    #(CLK_PERIOD_CLEAN/2.0)

    clk_clean_x = 1'b0;


    $fwrite(fhandle2,"%1.12g \n", $realtime*1e-9 ); // First column of the file is the -ve clock edge instant of the clean clock

    end


    assign clk_jitter=clk_jitter_x ;


    assign clk_clean=clk_clean_x ;

    endmodule

    The MATLAB code:-

    clear all;
    close all;

    % Read the data from the files

    CLK_WITH_JITTER_DATA= readmatrix('/A/CDR_JITTER/file_with_jitter.csv');
    CLK_WITHOUT_JITTER_DATA= readmatrix('/A/CDR_JITTER/file_without_jitter.csv');

    % White Gaussian Jitter statistics
    mu=0; % mean =0
    sigma=0.01*31e-12; % sigma= 10mUI and UI=31ps


    % The expected ranges of jitter values given sigma=10mUI.
    x=-1e-12:0.01e-12:1e-12;

    %Calculated Gaussian pdf
    g=(1/(sqrt(2*pi)*sigma))*exp(-((x-mu).^2)/(2*sigma^2));

    %Simulated jitter values by AMS
    JITTER_VALUES=CLK_WITH_JITTER_DATA(:,1); % First column is the jitter values added

    %Calculate the mean and sigma of the jitter generated by AMS
    mean_jitter_sim = mean(JITTER_VALUES)
    sigma_jitter_sim = (var(JITTER_VALUES))^0.5

    %Plotting the distribution of the random jitter values generated by AMS
    figure(1)
    histogram(JITTER_VALUES,100,'Normalization','pdf');
    hold on;
    plot(x,g);
    grid on;
    title(['Distribution of the Jitter Generated by AMS : \mu_x=',num2str(mu),' \sigma=',num2str(sigma) 's' ])
    xlabel('Jitter [s]')
    ylabel('PDF [ ]')
    grid on;

    % Now let's plot the clock jitter from AMS simulation.
    % We find the clock jitter by subatracting the -ve edge instances of the clean clock
    % from the -ve edge instances of the jirttery clock

    %The -ve clock edge isntances of the clean clock
    CLEAN_CLK_NEG_EDGES = CLK_WITHOUT_JITTER_DATA(:,1);
    JITTERY_CLK_NEG_EDGES = CLK_WITH_JITTER_DATA(:,4);

    JITTER_CLK_VALUES = JITTERY_CLK_NEG_EDGES-CLEAN_CLK_NEG_EDGES; % Clock jitter values obtained from AMS simulation

    %Calculate the mean and sigma of the jitter generated by AMS
    mean_clk_jitter_sim = mean(JITTER_CLK_VALUES)
    sigma_clk_jitter_sim = (var(JITTER_CLK_VALUES))^0.5


    %Plotting the distribution of the random clock jitter values generated by AMS
    figure(2)
    histogram(JITTER_CLK_VALUES,100,'Normalization','pdf');
    hold on;
    plot(x,g);
    grid on;
    title(['Distribution of the Clock Jitter Generated by AMS : \mu_x=',num2str(mu),' \sigma=',num2str(sigma) 's'])
    xlabel('Jitter [s]')
    ylabel('PDF [ ]')
    grid on;

    % Now let's plot the EXPECTED clock jitter from AMS simulation.
    % We find the EXPECTED -ve clocke edge instances of the jitter clock by
    % summing all previous JITTERY_CLOCK_PEIORDs in AMS
    % from the -ve edge instances of the jirttery clock
    % We then find the EXPECTED clock jitter by subatracting the -ve edge instances of the clean clock
    % from the EXPECTED -ve clocke edge instances of the jirttery clock

    %The EXPECTED -ve clock edge isntances of the JITTERY clock
    EXPECTED_JITTERY_CLK_NEG_EDGES = CLK_WITH_JITTER_DATA(:,3);

    EXPECTED_JITTER_CLK_VALUES = EXPECTED_JITTERY_CLK_NEG_EDGES-CLEAN_CLK_NEG_EDGES; % EXPECTED Clock jitter values obtained from AMS simulation

    %Calculate the mean and sigma of the jitter generated by AMS
    EXPECTED_mean_clk_jitter_sim = mean(EXPECTED_JITTER_CLK_VALUES)
    EXPECTED_sigma_clk_jitter_sim = (var(EXPECTED_JITTER_CLK_VALUES))^0.5


    %Plotting the distribution of the random clock jitter values generated by AMS
    figure(4)
    histogram(EXPECTED_JITTER_CLK_VALUES,100,'Normalization','pdf');
    hold on;
    plot(x,g);
    grid on;
    title(['Distribution of the EXPECTED Clock Jitter Generated by AMS : \mu_x=',num2str(mu),' \sigma=',num2str(sigma) 's'])
    xlabel('Jitter [s]')
    ylabel('PDF [ ]')
    grid on;

    Kind Regards,

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to RFStuff

    I think (and I spent way too long on this!) that the issue is that you are accumulating the floating point errors and your jittery is gradually wandering away from the main clock. Looking at the code, I see you're doing this:

    CLK_PERIOD_JITTER= CLK_PERIOD_CLEAN + ((jitter_current-jitter_previous)); // jitter_previous is substracted in order to bring the nth -ve jittery clock edge to that of the clean clock

    If you plot clk_clean and clk_jitter in SimVision you'll see that it gradually wanders away from it - I think your code to "correct" the synchronisation with the clean clock is sensitive to small numerical errors and so that is causing it to gradually get out of sync.  You need to remember that floating point numbers have finite resolution (they only have about 15 digits), and so those small errors could accumulate. It might not necessarily be that (could be some coding error) - but essentially I don't think it's the simulator - it's how your model is attempting to resynchronise with the main clock.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • RFStuff
    RFStuff over 4 years ago in reply to Andrew Beckett

    Dear Andrew,

    Thanks  a lot.  As mentioned by you, the resolution is 15 digits or 1 fs in time.

    I investigated and found that CLK_PERIOD_JITTER is expressed in more than 15 digits in the write file. So, calculation wise the resolution is more than 15 digits. (Please correct me if this conclusion is wrong)

    But, the problem arises in the wait statements used for clock generation ( always begin #(CLK_PERIOD_JITTER/2.0)  clk_jitter_x = 1'b1;  #(CLK_PERIOD_JITTER/2.0) clk_jitter_x = 1'b0; ).

    In the #( ) statement, AMS quantizes CLK_PERIOD_JITTER/2.0 to nearest value in multiple of fs. For example, let's say if CLK_PERIOD_JITTER=31.5 fs, CLK_PERIOD_JITTER/2=15.75 fs.

    AMS quantizes it to 15 fs. This results in .75 fs error.

    So, I think if all the operands are multiple of 1fs and the result is also multiple of  1fs after the operation, there will be no issue. (Please correct me if this conclusion is wrong).

    In the code if we ensure CLK_PERIOD_CLEAN , jitter_current and jitter_previous are multiple of 2 fs (2 fs as we are doing #(CLK_PERIOD_JITTER/2.0) ), there will be no issue.

    Kind Regards,

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to RFStuff

    My assumption that it was precision-related was correct, but I was looking at the wrong place. I think you've correctly identified the root cause.

    The time in Verilog (due to the `timescale directive) is a fixed point number, which means that it has an absolute precision of 1fs, whereas the real numbers are floating point numbers and so have a relative precision of 1e-15. I had in my mind that the time in Verilog is represented as a 64-bit integer (if my memory is correct) and so the precision of the timescale is absolute as I mentioned - but I spent too long thinking about this being a floating point precision issue. From my thinking about it, I couldn't work out how the small numerical errors would accumulate to enough to cause the deviation, plus that numerical error would not be one-sided and so wouldn't necessarily cause the drift that you saw. The snapping of the delays in the # statements would absolutely cause it though, since these are truncated downwards as you've observed.

    I guess I spent too long figuring out what your code was doing, and how you were analysing it in MATLAB, and not enough time investigating the details of what happened in each period!

    Glad you figured out the root cause!

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • RFStuff
    RFStuff over 4 years ago in reply to Andrew Beckett

    Dear Andrew,

    I have observed one more thing:- 

    The  snapping of delay value in # statement has a resolution upto 1e-15. But if I read the rise or fall edge instant of the clock, it gives much higher precision. 

    For example, if I use --> fwrite(fhandle1,"%1.64g n", $realtime*1e-9  ) at the falling instant of the clock (the expected value is 100.25ns), I get a value of 1.002500000000000010221519269014434083686637677601538598537445068e-07.

    I wonder how AMS gets the extra precision.

    Is there any I can limit the precision to certain value say 15 decimal point and will then assign to a variable in the code.

    Kind Regards,

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • RFStuff
    RFStuff over 4 years ago in reply to Andrew Beckett

    Dear Andrew,

    I have observed one more thing:- 

    The  snapping of delay value in # statement has a resolution upto 1e-15. But if I read the rise or fall edge instant of the clock, it gives much higher precision. 

    For example, if I use --> fwrite(fhandle1,"%1.64g n", $realtime*1e-9  ) at the falling instant of the clock (the expected value is 100.25ns), I get a value of 1.002500000000000010221519269014434083686637677601538598537445068e-07.

    I wonder how AMS gets the extra precision.

    Is there any I can limit the precision to certain value say 15 decimal point and will then assign to a variable in the code.

    Kind Regards,

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to RFStuff

    OK, the resolution in the # statement is based on the second part of the `timescale directive. The first part is the units, and the second part is the precision. As I mentioned before, the time in the event-driven engine is fixed-point (i.e. it's represented as an integer multiple of the precision).

    The time in the analog solver (or in the $realtime function) is a double-precision real number. That is a floating point number represented with a 53 bit mantissa and 11 bit exponent. A 53 mantissa gives you 53*log10(2) digits of precision - which is a little under 16 digits. That means that anything beyond about 15 digits is fiction - you're merely seeing numerical garbage caused by trying to convert the 64-bit floating point number to more decimal digits than it can actually represent. So it really makes no sense to use that number of digits in your fwrite.

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • RFStuff
    RFStuff over 4 years ago in reply to Andrew Beckett

    Dear Andrew,

     As in the below code, I generated the clean clock using #( ) statements.The clock period is given as a parameter -->  UI and it is multiple of 2 fs. For example I have used UI=500 ps here.

    To compare:--> I have captured the -ve clock edge instances from $realtime and also calculated the -ve edge instances by adding the clock periods as in the variable "neg_edge_instant_clean".

    Interestingly, the differences (see the output "edge_error") are zero for UI=500 ps but if UI=200 ps,  the error gradually increases and becomes in the order of fs if I run the simulation for 500 us.

    I suspect this is coming if AMS considers the garbage beyond 15 decimal point during the addition process.

     I have shown below the simVision plot of the error:-->

    For UI=500 ps

    For UI=200 ps,

    //Verilog-AMS HDL for "EXAMPLE", "CLK_JITTER_ANA" "verilogams" `include "constants.vams" `include "disciplines.vams" `timescale 1ns/1fs module FLOATING_PT_ERR_CLK_GEN (clk_clean,edge_error); output clk_clean ; output wreal edge_error; reg clk_jitter_x , clk_clean_x, data_x; parameter UI=500p; parameter fileName_to_write2="/A/CDR_JITTER/file_without_jitter.csv"; real CLK_PERIOD_CLEAN, CLK_PERIOD_JITTER; real neg_edge_instant; integer fhandle1 ; real neg_edge_instant_clean; real floating_point_err; integer first_edge; initial begin clk_jitter_x =1'b0; clk_clean_x =1'b0; CLK_PERIOD_CLEAN= UI*1e9 ; // Expressing in ns CLK_PERIOD_JITTER= UI*1e9 ; // Expressing in ns first_edge=1; end // JITTERY CLOCK GENERATION (Here I am NOT adding any Jitter Though) always begin #(CLK_PERIOD_JITTER/2.0) clk_jitter_x = 1'b1; #(CLK_PERIOD_JITTER/2.0) clk_jitter_x = 1'b0; // Below if-else portion of the code is to write the first -ve clock edge instant. if (first_edge > 0) begin neg_edge_instant_clean=$realtime; //$display("NEG-EDGE TIME-CAL->%1.12g\n", neg_edge_instant_clean); first_edge=0; end // current_time=$realtime; floating_point_err= $realtime - neg_edge_instant_clean ; // We are here using the clean -ve clock edge instances to bring jittery clock edge back to the clean clock edge $fwrite(fhandle1,"%1.15g, %1.15g, %1.15g, %1.15g\n", $realtime*1e-9, CLK_PERIOD_CLEAN*1e-9, neg_edge_instant_clean*1e-9, floating_point_err*1e-9 ); CLK_PERIOD_JITTER= CLK_PERIOD_CLEAN ; // One can add jitter here // Below is the calculated -ve edge instant from the clean clock period. neg_edge_instant_clean=neg_edge_instant_clean + CLK_PERIOD_CLEAN; // Expected -ve clock edge instants are obtained by adding the past values of CLK_PERIOD_JITTER end assign clk_clean=clk_jitter_x ; assign edge_error=floating_point_err; endmodule

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 4 years ago in reply to RFStuff

    I can't really look at the model since the formatting has got completely messed up. In general you have to be rather careful with floating point precision; repeated additions of small errors could certainly accumulate. I think the approach would be the wrong one if you're going to rely on keeping track of the time both as a floating point number and as a fixed point number. It might be better to keep an integer which is your model's concept of time (in fS) and increment that in your # delay statements rather than relying on $realtime. 

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • RFStuff
    RFStuff over 4 years ago in reply to Andrew Beckett

    Dear Andrew,

    1:-

    I am still not able to understand why floating point number addition will cause error when the numbers are  in multiple of 1 fs ( maximum 15 decimal point resolution) and the addition would also result in a resolution of 15 decimal point. I am not doing any division or multiplication unlike in # () statement (#(CLK_PERIOD_JITTER/2.0) ).

    2:-

    I could not figure out how to keep an integer for finding the -ve edge instants in the code below. 

    In the code I do it in floating point format :- neg_edge_instant_clean=neg_edge_instant_clean + CLK_PERIOD_CLEAN;

    Could you please tell how to do in the below code.

    //Verilog-AMS HDL for "EXAMPLE", "CLK_JITTER_ANA" "verilogams"

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


    `timescale 1ns/1fs


    module FLOATING_PT_ERR_CLK_GEN (clk_clean,edge_error);


    output clk_clean ;

    output wreal edge_error;

    reg clk_clean_x;


    parameter UI=500p;


    parameter fileName_to_write2="/A/CDR_JITTER/file_without_jitter.csv";


    real CLK_PERIOD_CLEAN, CLK_PERIOD_JITTER;

    real neg_edge_instant;

    integer fhandle1 ;

    real neg_edge_instant_clean;

    real floating_point_err;

    integer first_edge;


    initial begin

    clk_clean_x =1'b0;

    CLK_PERIOD_CLEAN= UI*1e9 ; // Expressing in ns

    CLK_PERIOD_JITTER= CLK_PERIOD_CLEAN;


    first_edge=1;

    end

    // CLOCK GENERATION


    always begin

    #(CLK_PERIOD_JITTER/2.0)

              clk_clean_x = 1'b1;


    #(CLK_PERIOD_JITTER/2.0)

             clk_clean_x = 1'b0;


    // Below if-else portion of the code is to note the first -ve clock edge instant.

    if (first_edge > 0) begin

             neg_edge_instant_clean=$realtime;

             first_edge=0;
    end

    floating_point_err= $realtime - neg_edge_instant_clean ; // We are here using the clean -ve clock edge instances to bring jittery clock edge back to the clean clock edge

    $fwrite(fhandle1,"%1.15g, %1.15g, %1.15g, %1.15g\n", $realtime*1e-9, CLK_PERIOD_CLEAN*1e-9, neg_edge_instant_clean*1e-9, floating_point_err*1e-9 );

    CLK_PERIOD_JITTER= CLK_PERIOD_CLEAN ;   // If required jitter can be added to this.

    neg_edge_instant_clean=neg_edge_instant_clean + CLK_PERIOD_CLEAN; // Expected next -ve clock edge instant is obtained by adding the clock period with the current clock edge                                                                                                                                           // instant.

    end

    assign clk_clean=clk_clean_x ;

    assign edge_error=floating_point_err;

    endmodule

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

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