* Note the the IEEE Std 1364-2005 is "Verilog", not "System Verilog"

  In System Verilog, int is a 32-bit 2-state type, whereas integer is a 32-bit 4-state type
  longint is a new 64-bit 2-state type.

  byte     -->  8-bit, 2-state, signed
  shortint --> 16-bit, 2-state, signed
  int      --> 32-bit, 2-state, signed
  longint  --> 64-bit, 2-state, signed

  integer  --> 32-bit, 4-state, signed

  According to System Verlilog, 2-state variables are initialized to 0 by default
  According to original verilog, 4-state (integer) is initialized to x by default
  According to original Verilog, real and realtime are initialized to 0.0 by default

  You can override the default initial value when you declare a variable, which is good practice
  anyway for clarity.

(From IEEE Std 1364-2005 : 4.2.2 Variable declarations
A variable is an abstraction of a data storage element. A variable shall store a value from one assignment to
the next. An assignment statement in a procedure acts as a trigger that changes the value in the data storage
element. The initialization value for reg, time, and integer data types shall be the unknown value, x. The
default initialization value for real and realtime variable data types shall be 0.0. If a variable declaration
assignment is used (see 6.2.1), the variable shall take this value as if the assignment occurred in a blocking
assignment in an initial construct. It is illegal to redeclare a name already declared by a net, parameter, or
variable declaration. 
)



* IEEE Std 1364-2005 : 4.8.2

  Important note. When reals are converted to integer, they are "rounded". This is different
  than any language I know of.

****************************************************************************************
* Signed Objects (p. 33 of vlogref)
****************************************************************************************

The following rules determine the resulting type of an expression (from p. 34 of vlogref)

* The expression type depends only on the operands. It does not depend on the left-hand
  side (LHS) (if any).

* Decimal numbers are signed.

* If any operand is real, the result is real.

* If all operands are signed, the result is signed, regardless of operator.

* The following list shows objects that are unsigned regardless of the operands:
  o The result of any expression where any operand is unsigned
  o Based numbers
  o Comparison results (1, 0)
  o Bit select results
  o Part select results
  o Concatenate results

* If a signed operand is to be resized to a larger signed width and the value of the sign bit
  is X or Z, the resulting value will be a bit filled with an X value.

* If any nonlogical operation has a bit with a signed value of X or Z, then the result is X for
  the entire value of the expression.

Nets as signed objects only have significance in an expression, in which case the entire
expression is considered a signed value.

Expressions on ports are typed, sized, evaluated, and assigned to the object on the other side
of the port using the same rules as expressions in assignments.

Verilog-XL uses the following steps for evaluating an expression:
  1. Determine the right-hand side (RHS) type, then coerce all RHS operands to this type.

  2. Determine the largest operand size, including the LHS (if any), then resize all RHS
     operands to this size.

  3. Evaluate the RHS expression, producing a result of the type found in
     step 1 and the size found in step 2.

  4. If there is a LHS,
     o Resize the result to the LHS size.
     o Coerce the result to the LHS type.
****************************************************************************************
~


* ----------------------------------------------------

https://www.verilogpro.com/verilog-reg-verilog-wire-systemverilog-logic/

* ----------------------------------------------------

// Random Number Generator from (works with 32-bit integers)
// https://pdfs.semanticscholar.org/8284/542deb19d556c8818e0456cce771a50ed0ff.pdf
// Tables of Linear Congruential Generators of Different Sizes and Good
//   Lattice Structure - Pierre L'Ecuyer
//   m = (2^16 - 15) = 65521
//   a = 17364
//   x_n+1 = (x_n * a) mod m

//   notice a 16 bit 2's comp number x is
//   -2^15  <= x <  2^15
//   -32768 <= x <= 32767
//   The biggest (x * a) would thus be 65521 * 17364 = 1137706644 

//   A 32-bit integer has a range -2^31 <= n < 2^31  = 2147483648
//   We can thus to all the math below which will generate
//   positive numbers from 1 to 65520 (never hits 0 or 65521)

//   We can thus convert this to an analog value between 0.0 and 1.0 by
//   y = (x - 0.5) / 65520.0

//   For example if I had 5 random numbers (1, 2, 3, 4, 5), I could divide
//   up the range 0 to 1.0 into subranges 1.0/5 = 0.2 wide
//   the ranges would be 
//   A --> (0.0 - 0.2)
//   B --> (0.2 - 0.4)
//   C --> (0.4 - 0.6)
//   D --> (0.6 - 0.8)
//   E --> (0.8 - 1.0)

//   Using y = (x - 0.5) / 5
//      1 --> 0.1  (Bin A)
//      2 --> 0.3  (Bin B)
//      3 --> 0.5  (Bin C)
//      4 --> 0.7  (Bin D)
//      5 --> 0.9  (Bin E)


* 10/1/2019

  Ok, not I'm wrapping up my studies on the ztm_lib

  For this library I learned a lot of stuff

  The $random system task does seem to have a global seed,
  so it could be used to break symmetry. This did not seem to be the case
  in VHDL where I had to use the instance name to break symmetry.

  It seems like the way I'm running iverilog, every module I define gets
  called at least once, and thus runs in initial blocks in every module

  This is different than with other verilog simulators, where you need to
  specify which modules are run, including which module is top

  The best way to check sytax or anything is just to put the code you are
  trying to study into a verilog initial module and run it, and print out
  stuff.


  For this release of the models, I will now create :
    fixed delays of 20ps per gate               (specified thru a "tp"  parameter)
    fixed offset delay with a spread of +- 2ps  (specified thru a "tpo" parameter)
    jitter delay with a spread of       +- 20fs (specified thru a "tpj" parameter)

  All gates are forced to a random value

  Gates are release after 1ns + range of (0 to 200ps)
  Flip Flops and Latches are released after 2ns + range of (0 to 200ps)
  (these are specified with parameters tfrc trel)

  



* integer and time

  time is an unsigned 64-bit register
  integer is a signed 32-bit registor

  it seems that sometimes people force an integer to be treated as unsigned
  value by using the concat {} operator as in the random number example below



* strings

  reg [8*10:1] s1, s2;
  
  s1 = "Hello";
  s2 = " world!";

  s1 --> s1 = 000000000048656c6c6f
  s2 --> s2 = 00000020776f726c6421



  ------------------------------------------

  module string_test;

    reg [8*14:1] stringvar;

    initial begin

      stringvar = "Hello world";
      $display("%s is stored as %h", stringvar,stringvar);

      stringvar = {stringvar,"!!!"};
      $display("%s is stored as %h",stringvar,stringvar);

    end

  endmodule

  The result of running Verilog on the previous description is:

    Hello world is stored as 00000048656c6c6f20776f726c64
    Hello world!!! is stored as 48656c6c6f20776f726c64212121

  ------------------------------------------



* verilog $random function
  (see vlogref - System Tasks and Functions, and Apendix D - Stochastic Analysis)

  It returns a 32-bit random number each time it is called
  
  usage :

    $random;
    $random(seed);

    seed must be an integer or register type and must be defined before calling
    (it is a variable, and holds the state of the random number generator)

    shan = ($random % b) gives a number in the range of [-b < shan < b] where b is positive

  example :

    reg [23:0] jack;

    jack = ($random % 60);
    --> jack will be uniformly distributed in domain  (-59 <= jack <= 59)



    reg [23:0] greg;

    greg = ({$random} % 60);     
    --> greg will be uniformly distributed in the domain (0 <= greg <= 59)



   


* blocking vs. non-blocking


    (I found this)


    >> Blocking Assignments
    >> Blocking assignments are the most basic of the assignment operations, and
    >> simply copy the value of the expression at the right hand side of the =
    >> operator to the variable on the left hand side. However, if two assignments
    >> that depend on each other are scheduled at the same time, e.g. an attempt to
    >> swap two variables, such as :

    >>   always @(posedge clk) a = b;

    >>   always @(posedge clk) b = a;

    >> then a race condition occurs, and both a and b will end up with one of the
    >> values. The value that they are both left with will depend on which of the
    >> assignments was scheduled first.

    >> Non-blocking Assignments
    >> Non-blocking assignments eliminate the possibility of race conditions in
    >> situations like this, as at the time that the assignment operation is
    >> executed the expression on the right hand side of the <= operator is copied
    >> to an internal temporary variable, which is then copied to the variable on
    >> the left hand side. All of the `reads' for a particular timestep are carried
    >> out before any of the `writes', and so values can be safely swapped as below

    >>   always @(posedge clk) a <= b;

    >>   always @(posedge clk) b <= a;

    >> This time, the code has the intended effect. 

    I think this is better

      always @(posedge clk) begin
        a <= b;
        b <= a;
      end



* One of the most important things in verilog has to do with
  transport delay and inertial delay


  (from the verilog user manual)

  >> Pulse Handling in Verilog-XL 2.0 and Earlier Versions
  >> In Verilog-XL 2.0 and earlier versions, the simulator
  >> functions only as an inertial delay simulator. This means
  >> that during the period of a module path delay, only one
  >> transition passes through the path\u2019s module input
  >> and propagates from the module output. Inertial delay is
  >> the default behavior of the simulator in version 2.1, but
  >> you can enable transport delay functionality with the
  >> following plus options:
  >>
  >>
  >> * +transport_path_delays
  >>
  >>   Enables transport delay functionality and pulse control
  >>   for module path delays.
  >>
  >>
  >> * +transport_int_delays
  >>
  >>   Enables transport delay functionality and pulse control
  >>   for interconnect delays.

  (I would recommend sticking with the defaults)

  You must be careful in feedback loops like latches.
  A latch is intended to have positive feedback to hold it's value.
  If the positive feedback look has two gates, then the delay
  will be TA+TB. Let TH = (TA+TB)/2. A 50% duty cycle signal of
  peroid 2*TH = (TA+TB) could oscillate, but will be killed by the smaller
  of TA or TB, unless TA==TB==TH

  We can thus avoid oscillation by never letting two gates with idential
  delays form a latch.

  With one non-inverting gate latched to itself, you cannot oscillate



  Inertial delay will kill any closed loop oscillation in a two gate
  loop