///  LSU EE 4755 -- Fall 2019 -- Digital Design / HDL
///
///  Descriptive Styles

/// Contents


/// References

// :SV12: IEEE 1800-2017 -- The SystemVerilog Standard
//        https://ieeexplore.ieee.org/document/8299595/
//        This is for those already familiar with Verilog.
//
// :BV3:  Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed.
//        The text used in LSU EE 2740.
//        This is for those who need to review basic Verilog.


////////////////////////////////////////////////////////////////////////////////
/// Descriptive Styles

// :Def: Descriptive Style
//
//  A set of rules for writing Verilog code.
//
//  The descriptive styles here are informally defined.

 ///  Four Major Styles
//
//    Explicit Structural:       Most restrictive.
//    Implicit Structural:       Still restrictive.
//    Synthesizable Behavioral:  Less restrictive, depends on synth prog.
//    Non-synthesizable Behavioral: No restrictions. No synthesis either.



////////////////////////////////////////////////////////////////////////////////
/// Explicit Structural Form

// :Def: Explicit Structural Form
//
//  A descriptive style in which a module can not use continuous
//  assignment statements (assign) or procedural statements (code
//  within (initial and always). The module can instantiate primitives
//  and other modules.
//
//  This style is easiest for synthesis programs to work with but
//  extremely tedious to write.
//
 ///  Rules:
//     No operators ( +, &, ~, >>, etc.)
//     No continuous assignments. (No use of assign.)
//     No structured procedures. (No use of initial, always*, final.)
//     Can instantiate primitives and modules.

// :Example:
//
// The pie module in explicit structural form. This is a good example
// of where the explicit structural form should *not* be used, that's
// because pie can be much more clearly expressed in implicit
// structural form.
//
module pie( output uwire x, y, input uwire a, b, c );
   uwire t1, t2;
   xor x1(t1,a,b);
   not n1(x,t1);
   and a1(t2,x,c);
   or  o1(y,t2,b);
   /// Don't forget: don't use primitives unless you are forced to.
endmodule

// :Example:
//
// The two_pie module below is also in explicit structural form. This
// is a good use of the form.
//
module two_pie( output uwire o1, o2, input uwire f, g, h, a );
   uwire   i1, i2;
   pie apple (i1, i2,  f,  g,  h );
   pie cherry(o1, o2,  i1, i2, a );
endmodule



////////////////////////////////////////////////////////////////////////////////
/// Implicit Structural Form

// :Def: Implicit Structural Form
//
//  A descriptive style in which a module can not use procedural
//  statements (code within (initial and always). The module can
//  instantiate primitives and other modules, and can use continuous
//  assignments.
//
//  This style is also easy for synthesis programs to work with
//  but can be tedious to write.

 /// Rules:
//     No structured procedures. (No use of initial, always*, final.)
//     Can use continuous assignments. (assign's are okay)
//     Can instantiate primitives and modules.


// :Example:
//
// The module below is equivalent to the pie module, except that
// it is in implicit structural form. 
//
module pie_implicit_structural
  ( output uwire x, y,
    input uwire a, b, c );

   assign x = !( a ^ b );
   assign y = x && c || b;

endmodule


////////////////////////////////////////////////////////////////////////////////
/// Behavioral Form

// Easiest to write.

// Cannot always be synthesized.
// (More restrictive behavioral styles can be synthesized, these
//  will be covered later.)

 /// Rules:
//    


// :Example:
//
//  The module below is behavioral and is neither explicit nor
//  implicit structural.
//
//  Because of the $display system task, the module below is not in
//  synthesizable behavioral form, nor in any other descriptive style
//  defined above. Obviously, that's easy to fix in this case.
// 
module pie_procedural
  ( output logic x, y,
    input uwire a, b, c );

   initial begin
      $display("Hello, from the pie_procedural module!\n");
   end

   always_comb begin // Live in objects: a, b, c
      // Note: x is not live in.
      x = !( a ^ b );
      y = x && c || b;

   end

endmodule


// :Example: Unnecessarily Complicated Behavioral Shifter Description
//
// This description is correct but unnecessarily complicated and so
// should not be used. It is also not synthesizable for reasons to be
// covered later. (If you must know: it's because the number of
// iterations in the loops depends upon a non-constant value, the
// module amt input.)
//
module shift_right_behavioral
   ( output logic [15:0] shifted,
     input uwire [15:0] unshifted,
     input uwire [3:0] amt );

   localparam int width = 16;

   always_comb begin
      for ( int i=0; i<width-amt; i++ ) shifted[i] = unshifted[i+amt];
      for ( int i=width-amt; i<width; i++ ) shifted[i] = 0;
   end

endmodule




////////////////////////////////////////////////////////////////////////////////
/// Synthesizable Behavioral Form

// :Def: Synthesizable Behavioral Form
//
// A descriptive style in which a module can use procedural code, but
// following some set of rules for synthesizability. 
//
// Synthesizability rules are determined by the particular synthesis
// program being used. Examples of these rules will be covered
// throughout the semester.

 /// Typical Rules
//    No code reading and writing files or console messages.
//    No use of delays, limited use of event controls.
//    The number of iterations in a loop must be an elaboration-time constant.
//    No floating point types.
//
//   More details in later lectures.

//
// The rules forbid Verilog code usages for which there is no
// reasonable hardware equivalent, or for which the synthesis program
// is not capable of generating hardware.
//
// For example, there is no reasonable hardware equivalent for the use
// of $display in pie_procedural. An unreasonable hardware equivalent
// would be a little LCD display showing the "Hello" message, which of
// course would be a silly thing to add to a simple piece of
// combinational logic.
//
// Verilog code using floating-point numbers is an example of code for
// which a particular synthesis program is not capable of inferring
// hardware. This is simply a design decision on the part of those
// directing the development of those programs. Perhaps they felt that
// FP would not be used as frequently as integer calculations and so
// they focused there development resources on other features. (Those
// needing FP could instantiate modules from a library.)


// :Example:
//
// The module below is equivalent to the pie module, except that
// it is in synthesizable behavioral form. 

module pie_behavioral
  ( output logic x, y,
    input uwire a, b, c );

   always_comb begin

      x = !( a ^ b );
      y = x && c || b;

   end

endmodule