/// Notes and demos for LSU EE 4702-1 Spring 2001

//  Material from Ciletti Chapter 4 (Ci 4), Verilog LRM Chapter 2 and 3.

/// Contents  

//  Identifiers
//  Variables   (Incomplete)
//  Data Types  (Incomplete)
//  Constants   (Incomplete)

/// Identifiers

//  Ci 2.10, LRM 2.7

//  Identifiers are used for module names, module instance names, and
//  variable names.

//  Identifiers:

//   First character must be alphabetic or an underscore (_);
//   Following characters may be alphabetic, digit, underscore, or dollar sign.
//   Case is significant. (myvar and Myvar are different identifiers)
//   Maximum length 1024.  That's a limit, not a goal.

//  Identifier Examples (in wire declarations).

module i_am_an_identifier();
   wire this_is_an_identifier;
   wire a, A;  // Two different variables.
   wire a1;
   wire icantreadthis;
   wire his$is$hard$to$read$too;
   wire but_this_I_can_read;
   wire _this_works_too;
   wire this_is_valid_identifier_but_unless_you_were_skilled_with_a_text_editor_it_would_be_really_difficult_to_use_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;

   ModuleName ModuleInstanceName(connection1,connection2);
   I_m_also_an_idenfifier me_too(And,us,too);

endmodule 



/// Variables

// Ci 4.3; LRM 3.2

// Two Kinds of Variables:  Net and Register

// Net (as in wire): used to connect modules and gates.
// Register: holds values.

// It's IMPORTANT to understand the differences between these:
//  Register types are like variables in conventional languages...
//  ... net types are like wires, they are NOT like conventional variables.



/// Register Variable Types

//  Ci 4.3.5 Ci 4.3.6  LRM 3.9 

//  Similar to variables in conventional languages.

//  Despite the name, they DO NOT specify anything about how, where,
//  or even whether registers should be synthesized.

//  Can only be assigned in procedural code ...
//  ... which means they CAN NOT connect to output ports of modules ...
//  ... nor can they be continuously assigned (covered later).

//  Some types of register types: (Types covered soon.)
//    reg:     Holds logic values.  By default, 1 bit.
//    integer: Holds integers.
//    real:    Holds FP values.
//    time:    Holds a simulation time value. (64-bit integer)
//    realtime:Time as a real number.

//  Declaration Syntax:
//  Within a module:
//   reg <identifier1>[,<identifier2>]...;


module reg_demo1(i_am_a_register_type,a);
   input a;
   output i_am_a_register_type;

   reg i_am_a_register_type;
   reg me_too;
   integer i_am_an_integer_a_kind_of_register_variable;
   integer a_change_count;

   initial begin
      // This is procedural code, the only places registers can be
      // assigned.
      i_am_a_register_type = 1;
      me_too = !i_am_a_register_type;
      i_am_an_integer_a_kind_of_register_variable = 12;
      a_change_count = 0;
   end

   always @( a ) begin
      // This is also procedural code.
      a_change_count = a_change_count + 1;
      // Assign bit 3 (LSB = 0) of a_change_count;
      i_am_a_register_type = a_change_count[3];
   end
   
endmodule 

   
module reg_demo2(output_x,input_a);
   input input_a;
   output output_x;

   wire   input_a;
   // (Below) NOT ALLOWED, registers can only be assigned in procedural code.
   // reg input_a;

   reg    reg_b;

   reg    output_x;  // This is perfectly okay.
   // (Below) Syntax error because can only assign registers in procedural code.
   // reg    output_x = reg_b;

   initial begin
      output_x = !input_a;
   end

   always @( input_a ) begin
      output_x = ! input_a;
   end

endmodule 


/// Net Variable Types

// Ci 4.3.1  Ci 4.3.3 (wired logic) LRM 3.7

//  Used to interconnect devices.
//  Do not store values.

//  Can NOT ordinarily be assigned in procedural code.
//  Net types are assigned by:
//   Connecting them to the output of a module (in an instantiation).
//   Using an assignment statement (to be covered).
//   Assigning in the declaration.

// Some net types:
//  wire:  for ordinary connections.
//  tri:   for tri-state logic. (E.g., for busses.)
//  wand:  for wired and connections
//  wor:   for wired or connections.

module net_demo(x,a,b);
   input a,b;
   output x;

   wire   a, b;

   wire wire_1;
   wire wire_2;
   reg  r1;

   // Example of a continuous assignment.
   assign wire_1 = a | b;

   and a1(wire_2,a,b);

   // This is a continuous assignment, NOT an initialization.
   wire   wire_3 = wire_1 ^ r1;

   // Wired and example.  wire_5 = (a | b ) & !wire_2
   wand   wire_5;
   assign wire_5 = a | b;
   assign wire_5 = !wire_2;
   
   wire   wire_4;

   always @( a or b ) begin
      r1 = a;

      // wire_4 = b; // Not allowed.
      
   end

endmodule 

//  Complete List of Net Types (LRM 3.7)
//   Covered above: wire, wand, wor, tri, 
//   Tristate wired logic: triand, trior.  (Equivalent to wand and wor.)
//   Wire with capacitance (not covered): trireg.
//   Wire with pull-down and pull-up resistors (not covered): tri0, tr1
//   Fixed logic levels: supply0, supply1;

//   These will not be covered in detail.
//   An example using tri appears further below.


/// Vectors

// LRM 3.3

// By default variables declared reg and wire are 1 bit.
// A vector is a multiple bit reg or wire.

// To declare a vector include a range specification:
// A vector can have 65536 bits

// reg [MSB:LSB] IDENTIFIER;
// wire [MSB:LSB] IDENTIFIER;

// Vectors are unsigned integers.
// Overflows are silently ignored.

module vector_examples();

   // Range specification examples.
   
   reg [0:31] a;  // Bit zero is most significant.
   reg [31:0] b;  // Bit 31 is most significant.
   reg [32:1] c;  // Some people have a problem with zero.

   wire       a_is_odd = a[31];
   wire       b_is_odd = a[0];
   wire       c_is_odd = a[1];

   
   // OVERFLOWS ARE SILENTLY IGNORED.
   reg [3:0]  i;  // An innocent looking four-bit register.
   integer    j;

   initial begin

      for(i=0; i<16; i=i+1) begin
         j = j + 1;
      end
      
      $display("This line will never be executed. Why?");
      
   end
   
endmodule // vector_examples

/// Vectored and Scalared Declaration Modifiers

//  LRM 3.3 (At end of section.)

//  The *vectored* keyword modifies a net declaration, informing
//  the compiler that one cannot look at individual bits of a
//  net.

module vector_examples2();

   // Range specification examples.
   
   wire  [0:31] a;  // Can examine bits.
   wire scalared [0:31] b;  // Equivalent to above, can examine bits.
   wire vectored [0:31] c;  // Should examine bits.

   wire       a_is_odd = a[31];  // Works
   wire       b_is_odd = a[31];  // Works
   wire       c_is_odd = a[31];  // Error on some compilers, not Modelsim.
   
endmodule // vector_examples

/// Data Types

//  Ci 4.3.5, 4.3.11-4.3.14

// Available types: logic, integer, real, time, realtime

// integer (LRM 3.9)
//  Two's complement signed.
//  Size (number of bits) is system dependent, at least 32 bits.

// Integer Constants
//
//  Can specify radix (base) and size.

// Logic: (Ci 4.2, LRM 3.1)
//   Value Set, Four values, 0, 1, x, z
//    x: Undefined. (Usually does NOT mean don't care or wildcard.)
//    z: High Impedance

// time, realtime  (LRM 3.9)
//  Hold simulator time values.
//  Unsigned integer, at least 64 bits.

module mux_3_to_1(out, select, in_0, in_1, in_2);

   output out;
   input  select, in_0, in_1, in_2;

   tri [7:0] out;
   wire [7:0] in_0, in_1, in_2;
   wire [1:0] select;

   assign     out = select == 0 ? in_0 : 8'bz;
   assign     out = select == 1 ? in_1 : 8'bz;
   assign     out = select == 2 ? in_2 : 8'bz;

endmodule // mux_3_to_1

module demo_mux();

   integer i;
   wire [1:0] s = i[1:0];
   reg [7:0]  i0, i1, i2;
   wire [7:0] o;

   mux_3_to_1 my_multipexor(o, s, i0, i1, i2);

   initial begin

      i0 = 100;
      i1 = 111;
      i2 = 122;

      #10;
      
      for(i=0; i<4; i=i+1) begin
         // Don't print anything, we'll eyeball the output.
         #10;
      end

      $stop;
      
   end

endmodule 



/// Constants

//  Ci 2.11, Ci 4.4 (strings) LRM 2.5

// Strings