///  LSU EE 4755 -- Fall 2016 -- Digital Design / HDL
//
/// Verilog Notes -- Synthesis of Combinational Logic: Structural

/// Under Construction
 // Time-stamp: <28 September 2016, 11:44:43 CDT, koppel@cyc.ece.lsu.edu>


/// Contents
//
 // Inference of Expressions

/// References

// :SV12: IEEE 1800-2012 -- The SystemVerilog Standard
//        http://standards.ieee.org/getieee/1800/download/1800-2012.pdf
//
// :BV3:  Brown & Vranesic, Fundamentals of Digital Logic with Verilog, 3rd Ed.
//        The text used in LSU EE 4720, 4730, and 4740.




////////////////////////////////////////////////////////////////////////////////
/// Inference of Expressions
//
 // :Def: Expression
 // An arrangement of operators and operands which returns a result, as
 // defined by some language, such as C++11 or SystemVerilog 2012.
 //
 // :Sample: x = a + b * ( c - d );
 //
 // We should be familiar with expressions in many computer languages.
 //

 // :Def: Operator Syntax
 // The rules for using the operator in code written in the language.

 // :Def: Operator Semantics
 // A description of how an operator transforms its operands into a result.
 //
 // :Sample: int a,b; ... a + b;
 // Semantics of +: Result is signed integer sum, overflow ignored.


 /// SystemVerilog Operator Treatment -- Simulation
 //
 //  SystemVerilog 2012 defines operators and expressions in Chapter 12.
 //  Syntax and semantics must (shall!) follow standard.
 //  Semantics exactly described.


 /// SystemVerilog Operator Treatment -- Synthesis
 //
 //  Each synthesis program defines a synthesizable subset.
 //
 //  Cadence Encounter
 //
 //    Synthesizable Subset Described In
 //      HDL Modeling in Encounter RTL Compiler
 //        See Chapter 4, "Supported" sections.


 // :Def: Synthesizable Operator
 // An operator that's synthesizable by a particular synthesis program.


 /// Arithmetic Operators v. Other Operators
 //
 //  For most operators it is easy to infer hardware,
 //   for example  assign x = a && b; would be inferred as an AND gate.
 //
 //  Arithmetic operators inference is not so simple because of:
 //   Operand width (number of bits).
 //   Operand type (signed v. unsigned).
 //   Need to provide optimization flexibility.
 //
 //  Inference of arithmetic and non-arithmetic operators covered in
 //  this set.


////////////////////////////////////////////////////////////////////////////////
/// Synthesis of Arbitrary Expressions

 /// Steps
 //
 //  - Use precedence and association to determine order.
 //  - Draw diagram.


module arb_exp
  ( output [7:0] x,
    input [8:0] a,
    input [6:0] b, c,
    input [2:0] e, f );

   assign x = a + b * c << ( e + f );

   /// Based on precedence and association:
   //
   // i1 = b*c;
   // i2 = a + i1;
   // i3 = e + f;
   // x = i2 << i3;

endmodule

 // 


////////////////////////////////////////////////////////////////////////////////
/// Inference of Non-Arithmetic Operators
///


 /// Boolean Two-Operand Logical Operators
 //
 //  &&, ||, ->, <->, ...
 //
 //  - Both arguments are Boolean types.
 //  - Result is a 1-bit unsigned integer.
 //  - Arguments are converted into Boolean types if necessary.
 //
 //  All these can be inferred in a straightforward manner.
 //  Synthesizes into the gate that you would expect.
 //  Cadence Encounter RC 142 won't synthesize ->, <->.

module example_boolop();

   wire a, b;
   logic x;

   initial begin

      // Familiar AND and OR operators.
      //
      x = a && b;
      x = a || b;
      //
      // Note: equivalent to & and | when both operands are 1 bit.

      // Less familiar implication operator.
      x = a -> b;  // Equivalent to x = (!a) || b;

      // Boolean exclusive nor.
      x = a <-> b;
      //
      // Note: equivalent to ~^ when both operands are 1 bit.

   end

endmodule


 /// Bitwise Logical Operators
 //
 //  &, |, ^, ~^
 //
 //  - Both arguments are bit vectors.
 //  - Result is a bit vector at least as large as larger operand.
 //
 //  All these can be inferred in a straightforward manner.
 //  Synthesizes into a collection of gates, one gate for each bit.

module example_bitlop();

   wire [3:0] a;
   wire [7:0] b;
   logic [5:0] x;

   initial begin

      // Familiar AND and OR operators.
      //
      x = a & b;
      x = a | b;
      //
      // Notes:
      //  Bad style due to size mismatch: a, b, and c should all be same size.
      //  a is widened to 8 bits (to match b).
      //  Low 6 bits of result assigned to x.

      // Bitwise Exclusive Or
      x = a ^ b;

   end

endmodule


 /// Reduction Operators
 //
 //  &, ~&, |, ~|, ^, ~^
 //
 //  - There is one argument, a bit vector.
 //  - Result is one bit.
 //
 //  All these can be inferred in a straightforward manner.
 //  Synthesizes into a w-input gate, where w is the width of the operand.

module example_redlop();

   wire [2:0] a;
   wire [7:0] b;
   logic x;
   logic [7:0] y;

   initial begin

      x = &a;   // Equivalent to x = a[2] && a[1] && a[0];
      x = |b;   // An 8-input OR gate.
      x = ~|a;  // An 8-input NOR gate.

      // Note: Bad style because of size mismatch.
      y = &b;   // One-bit result is converted to an 8-bit result.

   end

endmodule



 /// Shift
 //
 //  <<, <<<,

 /// Concatenation
 //
 // {}




////////////////////////////////////////////////////////////////////////////////
/// Synthesis of The Conditional Operator, Index Op

 /// The conditional operator (s?a:b) is synthesized as a multiplexor.
//
// :Sample: assign x = s ? a : b;
// Two-input mux, x is control, a and b are data inputs,

module mux2
  ( output [7:0] x,
    input s,
    input [7:0] a, b );

   assign x = s == 0 ? a : b;

endmodule

// 



// The following code containing chained conditional operators
// usually synthesizes to a single multiple-input multiplexor.
//
// :Example:

module mux4
  ( output [7:0] x,
    input [1:0] s,
    input [7:0] a0, a1, a2, a3 );

    assign x =  s==0 ? a0 : s==1 ? a1 : s==2 ? a2 : a3;

endmodule

// 


 /// The index operator [s] is synthesized as a mux.

module mux16
  ( output wire [7:0] x,
    input wire [3:0] s,
    input wire [15:0][7:0] a );

   assign      x = a[s];

endmodule




////////////////////////////////////////////////////////////////////////////////
/// Inference of Comparison Operators
///

 /// Comparison
 //
 //  Ordinary comparison:  ==, !=, >, >=, <, <=
 //  Four-state compare: ===, !==, ==?, !=?
 //
 //  - Result of all comparisons is one bit.
 //  - Several argument types possible: bit vectors, reals.
 //
 //  
 //  Synthesis programs will only work with ordinary comparisons of int types.
 //  Typically inferred into a library module.

module example_comparison();

   wire logic [7:0] a;
   wire logic [7:0] b;
   var logic x, y;

   initial begin

      x = a > b; // Relatively hard.

   end

endmodule


 /// Arithmetic Operators
 //
 //  +, -, /, *, **, %
 //
 //  - Multiple argument types, eg, signed bit vector, integer, real.
 //  - Result type and width depends on operands.
 //
 //  Synthesis programs (so far) limit operator and operand combinations.
 //  Typically inferred into a library module.
 //
 /// Be Careful
 //
 //  - Pay attention to rules on bit widths.
 //  - Pay attention to rules on sign/unsigned integers.
 //  - Don't impede optimization by limiting widths or by touching bits.

module example_arithmetic();

   wire logic [7:0] a;
   int a1;
   integer a2;
   wire logic [7:0] b;
   var logic x, y;

   always_comb begin

      x = a + b;

   end

endmodule

 // :Example: Example of how helping hurts.
 //
 // Goal is to compute (a+b)/2  ...
 // ... but using formula a + (b-a)/2.
 //
 // We would like efficient hardware with a + (b-a)/2.
 //
 // If arithmetic expression written cleanly ..
 // .. synthesis program will transform a+(b-a)/2 to (a+b)/2.
 //
 // If arithmetic expression mixed with logic ..
 // .. synthesis program may not be able to transform expression.

module example_avg_helping_hurt
  ( output wire [7:0] avg,
    input wire [7:0] a, b );

   wire [7:0]   a_inv = ~a;
   wire [7:0]   minus_a = a_inv + 1;

   wire logic [7:0] diff = b + minus_a;
   assign avg = diff[7:1] + a;

endmodule

module example_avg_good
  ( output wire signed [7:0] avg,
    input wire signed [7:0] a, b );

   wire   logic [1:0];

   assign avg = a + ( b - a ) / 2 + c ** x;

endmodule




 /// Pay Attention To
 //
 //  Data type and number of bits of inputs.
 //  Data type and number of bits of outputs.
 //
 //  Changes in the number of bits.
 //  Interpretation of integer as signed or unsigned.

 /// Widths (Size)
 //
 //  :Def: Self-Determined Expression Context
 //  Context in which size determined by expression itself, not the context.
 //
 //  :Example:
 //
 //  x = a << E;   // E is in a self-determined context (by def of << operator).
 //                // Therefore size of E does not depend on a or x.
 //
 //
 //  :Def: Context-Determined Expression Context
 //  Size determined by expression itself, and by how or where it is used.
 //
 //  :Example:
 //
 //  x = E << b;  // E is in a context-determined context.
 //               // Size of E depends on size of x.

module example;

   wire [3:0] a, b;
   wire [6:0] c;
   wire [4:0] x1, x2;

   assign x1 = 0 + a + b + c;
   //
   // Operands of + are context-determined,
   //  therefore width of adder inputs and outputs will be max(4,5,7) = 7;
   // x1 gets 5 LSB of result, the rest is discarded.

   assign x2 = a + b << c;
   //
   // c is self-determined, so its size stays at 7 (which is overkill).
   // Size of others is max(4,5) = 5.
   // Shifter's data input and outputs are 5 bits, shift amt is 7 bits.

endmodule




module bool_v_1bit
  ( output y1, output y2,
    input [7:0] a, b );

   // Consider
   //
   assign y1 = a && b;
   //
   //  The && is defined for 1-bit operands.
   //  


   assign y2 = a & b;
   //
   // Note: y2's size should match a and b's.


endmodule











////////////////////////////////////////////////////////////////////////////////
/// ALU Example


//
// Verilog description for ALU module.
//    a + b if input op = 0
//    a - b if input op = 1.
//    a     if input op = 2
//    b     otherwise.


// :Example:
//
// Human-written code for an ALU module.

module alu
  ( output [8:0] x,
    input [1:0] op,
    input [7:0] a, b );

   assign       x =
                op == 0 ? a + b :
                op == 1 ? a - b :
                op == 2 ? a     : b;

endmodule


// :Example:
//
// Simplified output of inference stage.
//
// Note that conditional operator replaced with a multiplexor.
// (Leonardo uses the conditional operator in its inferred code.)

module alu_inf_simple(x,a,b,op);
   input [7:0] a,b;
   input [1:0] op;
   output [8:0] x;

   wire [8:0]   aplusb,aminusb;

   generic_sum_8 gs1(aplusb,a,b);
   generic_diff_8 gd1(aminusb,a,b);
   generic_mux_9_4 mux(x,op,aplusb,aminusb,a,b);

endmodule


// :Example:
//
// The actual output of the inference stage.  Leonardo still uses a
// conditional operator in places and uses a data selector with one
// bit of control for each data input rather than a mux with a binary
// control input

module alu_inf_real ( x, a, b, op ) ;

    output [8:0]x ;
    input [7:0]a ;
    input [7:0]b ;
    input [1:0]op ;

    wire GND, nx5, nx6, nx7, nx8, nx9, nx10, nx11, nx12, nx13, PWR, nx19, nx20,
         nx21, nx22, nx23, nx24, nx25, nx26, nx27, nx46, nx120, nx121, nx122,
         nx123, nx132, nx134, NOT_nx134;
    wire [2:0] \$dummy ;

    assign GND = 0 ;
    eq_2u_2u x_eq_0 (.a ({op[1],op[0]}), .b ({GND,GND}), .d (nx120)) ;
    add_9u_9u_9u_0_0 x_add_1 (.cin (GND), .a ({GND,a[7],a[6],a[5],a[4],a[3],a[2]
                     ,a[1],a[0]}), .b ({GND,b[7],b[6],b[5],b[4],b[3],b[2],b[1],
                     b[0]}), .d ({nx5,nx6,nx7,nx8,nx9,nx10,nx11,nx12,nx13}), .cout (
                     \$dummy [0])) ;
    assign PWR = 1 ;
    eq_2u_2u x_eq_2 (.a ({op[1],op[0]}), .b ({GND,PWR}), .d (nx121)) ;
    sub_10s_10s_10s_0 x_sub_3 (.cin (PWR), .a ({GND,GND,a[7],a[6],a[5],a[4],a[3]
                      ,a[2],a[1],a[0]}), .b ({GND,GND,b[7],b[6],b[5],b[4],b[3],
                      b[2],b[1],b[0]}), .d ({\$dummy [1],nx19,nx20,nx21,nx22,
                      nx23,nx24,nx25,nx26,nx27}), .cout (\$dummy [2])) ;
    eq_2u_2u x_eq_4 (.a ({op[1],op[0]}), .b ({PWR,GND}), .d (nx122)) ;
    assign x[8] = nx120 ? nx5 : nx46 ;
    and (nx46, nx19, nx121) ;
    select_4_4 modgen_select_6 (.a ({nx120,nx121,nx122,nx123}), .b ({nx6,nx20,
               a[7],b[7]}), .d (x[7])) ;
    select_4_4 modgen_select_7 (.a ({nx120,nx121,nx122,nx123}), .b ({nx7,nx21,
               a[6],b[6]}), .d (x[6])) ;
    select_4_4 modgen_select_8 (.a ({nx120,nx121,nx122,nx123}), .b ({nx8,nx22,
               a[5],b[5]}), .d (x[5])) ;
    select_4_4 modgen_select_9 (.a ({nx120,nx121,nx122,nx123}), .b ({nx9,nx23,
               a[4],b[4]}), .d (x[4])) ;
    select_4_4 modgen_select_10 (.a ({nx120,nx121,nx122,nx123}), .b ({nx10,nx24,
               a[3],b[3]}), .d (x[3])) ;
    select_4_4 modgen_select_11 (.a ({nx120,nx121,nx122,nx123}), .b ({nx11,nx25,
               a[2],b[2]}), .d (x[2])) ;
    select_4_4 modgen_select_12 (.a ({nx120,nx121,nx122,nx123}), .b ({nx12,nx26,
               a[1],b[1]}), .d (x[1])) ;
    select_4_4 modgen_select_13 (.a ({nx120,nx121,nx122,nx123}), .b ({nx13,nx27,
               a[0],b[0]}), .d (x[0])) ;
    or (nx132, nx120, nx121) ;
    or (nx134, nx132, nx122) ;
    assign NOT_nx134 = ~nx134 ;
    and (nx123, NOT_nx134, PWR) ;
endmodule


// :Example:
//
// Simplified output of technology mapping.
//
// Unfortunately, Fab Fab does not have a 9-bit multiplexor in their
// technology library and so a 12-bit mux is used instead.

module alu_tech(x,a,b,op);
   input [7:0] a,b;
   input [1:0] op;
   output [8:0] x;

   wire [8:0]   aplusb,aminusb;
   wire [2:0]   dummy;

   fab_fab_sum_8 gs1(aplusb,a,b);
   fab_fab_diff_8 gd1(aminusb,a,b);
   fab_fab_mux_12_4 mux({dummy,x},op,{3'b0,aminusb},{3'b0,aplusb},
                        {3'b0,a},{3'b0,b});


endmodule


// :Example:
//
// Simplified output of optimization step:
//
// In this case the (fictional) optimizer is clever. Instead of using
// an adder and a subtractor, it just negates b and uses a mux to
// select the negated b or the regular b.

module alu_opt(x,a,b,op);
   input [7:0] a,b;
   input [1:0] op;
   output [8:0] x;

   wire [7:0]   minusb, adder_input_1, adder_input_2;
   wire         zip;

   fab_fab_neg_8 neg(minusb,b);
   fab_fab_and_2 and1(zip,op[0],op[1]);
   fab_fab_mux_8_2 mux1(adder_input_1,zip,a,8'b0);
   fab_fab_mux_8_4 mux2(adder_input_2,op,b,minusb,8'b0,b);
   fab_fab_sum_8 gs1(x,adder_input_1,adder_input_2);

endmodule

// :Example:
//
// The actual optimized description.  The synthesis program decided
// to break everything down into gates and optimize that.  There
// is no need to trace through the module below to see how it works.

module alu_opt_real ( x, a, b, op ) ;

    output [8:0]x ;
    input [7:0]a ;
    input [7:0]b ;
    input [1:0]op ;

    wire nx2, nx4, nx10, nx12, nx14, nx16, nx18, nx20, nx26, nx32, nx40, nx48,
         nx60, nx74, nx80, nx90, nx122, nx152, nx178, nx186, nx208, nx234, nx254,
         nx274, nx288, nx308, nx257, nx261, nx263, nx265, nx269, nx275, nx277,
         nx279, nx281, nx285, nx287, nx297, nx299, nx301, nx303, nx307, nx311,
         nx313, nx315, nx325, nx327, nx331, nx333, nx335, nx337, nx339, nx345,
         nx350, nx352, nx355, nx357, nx360, nx362, nx364, nx366, nx369, nx371,
         nx373, nx375, nx378, nx381, nx383, nx386, nx388, nx391, nx395, nx397,
         nx401, nx403, nx407, nx409, nx432, nx434, nx436, nx440, nx454, nx455,
         nx456, nx457, nx458, nx459, nx460, nx461, nx462, nx427, nx463, nx464,
         nx465, nx466, nx467, nx468, nx160, nx414, nx293, nx469, nx470, nx471,
         nx472, nx473, nx474, nx475, nx476, nx273, nx393, nx477, nx478, nx479;

    OAI3N0 ix207 (.X (x[0]), .A1 (nx32), .A2 (op[1]), .B1 (nx261), .B2 (nx269)
           ) ;
    ND2N0 ix33 (.X (nx32), .A1 (b[0]), .A2 (nx257)) ;
    IV1N0 ix258 (.X (nx257), .A (a[0])) ;
    AOA4I0 ix262 (.X (nx261), .A1 (nx263), .A2 (nx265), .B (nx478), .C (a[0])) ;
    IV1N0 ix264 (.X (nx263), .A (b[0])) ;
    IV1N0 ix266 (.X (nx265), .A (op[1])) ;
    NR2R1 ix179 (.X (nx178), .A1 (nx265), .A2 (op[0])) ;
    ND3N0 ix270 (.X (nx269), .A1 (b[0]), .A2 (op[0]), .A3 (op[1])) ;
    OAI3N0 ix227 (.X (x[1]), .A1 (nx273), .A2 (nx275), .B1 (nx281), .B2 (nx287)
           ) ;
    XN2R0 ix276 (.X (nx275), .A1 (nx277), .A2 (nx279)) ;
    XR2T0 ix278 (.X (nx277), .A1 (a[1]), .A2 (b[1])) ;
    NR2R0 ix280 (.X (nx279), .A1 (nx263), .A2 (a[0])) ;
    AO2I0 ix282 (.X (nx281), .A1 (b[1]), .A2 (nx477), .B1 (a[1]), .B2 (nx478)) ;
    IV1N0 ix187 (.X (nx186), .A (nx285)) ;
    ND2N0 ix286 (.X (nx285), .A1 (op[0]), .A2 (op[1])) ;
    ND2N0 ix288 (.X (nx287), .A1 (nx208), .A2 (nx293)) ;
    XN2R0 ix209 (.X (nx208), .A1 (nx26), .A2 (nx277)) ;
    ND2N0 ix27 (.X (nx26), .A1 (b[0]), .A2 (a[0])) ;
    OAI3N0 ix247 (.X (x[2]), .A1 (nx297), .A2 (nx4), .B1 (nx313), .B2 (nx315)) ;
    XN2R0 ix298 (.X (nx297), .A1 (nx299), .A2 (nx307)) ;
    OAI2N0 ix300 (.X (nx299), .A1 (nx301), .A2 (nx303), .B1 (nx20), .B2 (nx26)
           ) ;
    IV1N0 ix302 (.X (nx301), .A (b[1])) ;
    IV1N0 ix304 (.X (nx303), .A (a[1])) ;
    XN2R0 ix21 (.X (nx20), .A1 (a[1]), .A2 (b[1])) ;
    XR2T0 ix308 (.X (nx307), .A1 (a[2]), .A2 (b[2])) ;
    ND2N0 ix5 (.X (nx4), .A1 (nx311), .A2 (nx265)) ;
    IV1N0 ix312 (.X (nx311), .A (op[0])) ;
    AO2I0 ix314 (.X (nx313), .A1 (b[2]), .A2 (nx477), .B1 (a[2]), .B2 (nx478)) ;
    ND2N0 ix316 (.X (nx315), .A1 (nx2), .A2 (nx234)) ;
    NR2R0 ix3 (.X (nx2), .A1 (op[1]), .A2 (nx311)) ;
    XN2R0 ix235 (.X (nx234), .A1 (nx307), .A2 (nx40)) ;
    OAI2N1 ix41 (.X (nx40), .A1 (nx303), .A2 (b[1]), .B1 (nx277), .B2 (nx279)) ;
    OAI3N0 ix267 (.X (x[3]), .A1 (nx325), .A2 (nx4), .B1 (nx337), .B2 (nx339)) ;
    XN2R0 ix326 (.X (nx325), .A1 (nx327), .A2 (nx122)) ;
    XR2T0 ix328 (.X (nx327), .A1 (a[3]), .A2 (b[3])) ;
    OAI1A0 ix123 (.X (nx122), .A1 (nx331), .A2 (nx333), .B (nx335)) ;
    IV1N0 ix332 (.X (nx331), .A (a[2])) ;
    IV1N0 ix334 (.X (nx333), .A (b[2])) ;
    ND2N0 ix336 (.X (nx335), .A1 (nx299), .A2 (nx307)) ;
    AO2I0 ix338 (.X (nx337), .A1 (b[3]), .A2 (nx477), .B1 (a[3]), .B2 (nx478)) ;
    ND2N0 ix340 (.X (nx339), .A1 (nx2), .A2 (nx254)) ;
    XN2R0 ix255 (.X (nx254), .A1 (nx327), .A2 (nx48)) ;
    OAI1A0 ix49 (.X (nx48), .A1 (nx331), .A2 (b[2]), .B (nx345)) ;
    ND2N0 ix346 (.X (nx345), .A1 (nx18), .A2 (nx40)) ;
    XN2R0 ix19 (.X (nx18), .A1 (a[2]), .A2 (b[2])) ;
    OAI3N0 ix287 (.X (x[4]), .A1 (nx350), .A2 (nx4), .B1 (nx355), .B2 (nx357)) ;
    XN2R0 ix351 (.X (nx350), .A1 (nx352), .A2 (nx14)) ;
    AO2I0 ix353 (.X (nx352), .A1 (a[3]), .A2 (b[3]), .B1 (nx327), .B2 (nx122)) ;
    XN2R0 ix15 (.X (nx14), .A1 (a[4]), .A2 (b[4])) ;
    AO2I0 ix356 (.X (nx355), .A1 (b[4]), .A2 (nx477), .B1 (a[4]), .B2 (nx478)) ;
    ND2N0 ix358 (.X (nx357), .A1 (nx2), .A2 (nx274)) ;
    XN2R0 ix275 (.X (nx274), .A1 (nx360), .A2 (nx362)) ;
    XR2T0 ix361 (.X (nx360), .A1 (a[4]), .A2 (b[4])) ;
    OAI2N0 ix363 (.X (nx362), .A1 (b[3]), .A2 (nx364), .B1 (nx366), .B2 (nx327)
           ) ;
    IV1N0 ix365 (.X (nx364), .A (a[3])) ;
    AO2I0 ix367 (.X (nx366), .A1 (a[2]), .A2 (nx333), .B1 (nx18), .B2 (nx40)) ;
    OAI3N0 ix307 (.X (x[5]), .A1 (nx273), .A2 (nx369), .B1 (nx381), .B2 (nx383)
           ) ;
    XR2T0 ix370 (.X (nx369), .A1 (nx371), .A2 (nx373)) ;
    XR2T0 ix372 (.X (nx371), .A1 (a[5]), .A2 (b[5])) ;
    OAI2N1 ix374 (.X (nx373), .A1 (b[4]), .A2 (nx375), .B1 (nx60), .B2 (nx360)
           ) ;
    IV1N0 ix376 (.X (nx375), .A (a[4])) ;
    AO2I0 ix61 (.X (nx60), .A1 (nx378), .A2 (a[3]), .B1 (nx48), .B2 (nx16)) ;
    IV1N0 ix379 (.X (nx378), .A (b[3])) ;
    XN2R0 ix17 (.X (nx16), .A1 (a[3]), .A2 (b[3])) ;
    AO2I0 ix382 (.X (nx381), .A1 (b[5]), .A2 (nx477), .B1 (a[5]), .B2 (nx478)) ;
    ND2N0 ix384 (.X (nx383), .A1 (nx288), .A2 (nx293)) ;
    XR2T0 ix289 (.X (nx288), .A1 (nx371), .A2 (nx386)) ;
    OAI2N0 ix387 (.X (nx386), .A1 (nx388), .A2 (nx375), .B1 (nx14), .B2 (nx352)
           ) ;
    IV1N0 ix389 (.X (nx388), .A (b[4])) ;
    OAI3N0 ix327 (.X (x[6]), .A1 (nx273), .A2 (nx391), .B1 (nx401), .B2 (nx403)
           ) ;
    XR2T0 ix392 (.X (nx391), .A1 (nx393), .A2 (nx395)) ;
    OAI1A0 ix396 (.X (nx395), .A1 (b[5]), .A2 (nx397), .B (nx74)) ;
    IV1N0 ix398 (.X (nx397), .A (a[5])) ;
    ND2N0 ix75 (.X (nx74), .A1 (nx373), .A2 (nx12)) ;
    XN2R0 ix13 (.X (nx12), .A1 (a[5]), .A2 (b[5])) ;
    AO2I0 ix402 (.X (nx401), .A1 (b[6]), .A2 (nx477), .B1 (a[6]), .B2 (nx478)) ;
    ND2N0 ix404 (.X (nx403), .A1 (nx308), .A2 (nx293)) ;
    XR2T0 ix309 (.X (nx308), .A1 (nx393), .A2 (nx479)) ;
    OAI1A0 ix153 (.X (nx152), .A1 (nx397), .A2 (nx407), .B (nx409)) ;
    IV1N0 ix408 (.X (nx407), .A (b[5])) ;
    ND2N0 ix410 (.X (nx409), .A1 (nx371), .A2 (nx386)) ;
    AO2I0 ix81 (.X (nx80), .A1 (nx407), .A2 (a[5]), .B1 (nx373), .B2 (nx12)) ;
    OAI2N0 ix175 (.X (x[8]), .A1 (nx432), .A2 (nx434), .B1 (nx4), .B2 (nx440)) ;
    ND2N0 ix433 (.X (nx432), .A1 (nx265), .A2 (op[0])) ;
    OAI2N0 ix435 (.X (nx434), .A1 (b[7]), .A2 (nx436), .B1 (nx90), .B2 (nx414)
           ) ;
    IV1N0 ix437 (.X (nx436), .A (a[7])) ;
    AO2I0 ix91 (.X (nx90), .A1 (nx427), .A2 (a[6]), .B1 (nx395), .B2 (nx10)) ;
    XN2R0 ix11 (.X (nx10), .A1 (a[6]), .A2 (b[6])) ;
    AO2I0 ix441 (.X (nx440), .A1 (a[7]), .A2 (b[7]), .B1 (nx414), .B2 (nx160)) ;
    IV1NP ix480 (.X (nx454), .A (b[7])) ;
    IV1N2 ix481 (.X (nx455), .A (nx477)) ;
    IV1NP ix482 (.X (nx456), .A (a[7])) ;
    IV1N2 ix483 (.X (nx457), .A (nx478)) ;
    IV1NP ix484 (.X (nx458), .A (a[7])) ;
    IV1NP ix485 (.X (nx459), .A (b[7])) ;
    AO2I1 ix486 (.X (nx460), .A1 (b[7]), .A2 (nx458), .B1 (a[7]), .B2 (nx459)) ;
    IV1NP ix487 (.X (nx461), .A (a[6])) ;
    NR2Q1 ix488 (.X (nx462), .A1 (nx461), .A2 (b[6])) ;
    IV1NP nx427_rename (.X (nx427), .A (b[6])) ;
    NR2Q1 ix489 (.X (nx463), .A1 (nx427), .A2 (a[6])) ;
    NR2R1 ix490 (.X (nx464), .A1 (nx463), .A2 (nx80)) ;
    AN2T0 ix491 (.X (nx465), .A1 (nx265), .A2 (op[0])) ;
    OAI1A1 ix492 (.X (nx466), .A1 (nx462), .A2 (nx464), .B (nx465)) ;
    OR2T0 ix493 (.X (nx467), .A1 (b[6]), .A2 (a[6])) ;
    AN2T0 ix494 (.X (nx468), .A1 (b[6]), .A2 (a[6])) ;
    AO1A0 nx160_rename (.X (nx160), .A1 (nx479), .A2 (nx467), .B (nx468)) ;
    OAI2N1 nx414_rename (.X (nx414), .A1 (nx454), .A2 (a[7]), .B1 (nx456), .B2 (
           b[7])) ;
    NR2Q1 nx293_rename (.X (nx293), .A1 (op[0]), .A2 (op[1])) ;
    ND2N1 ix495 (.X (nx469), .A1 (nx414), .A2 (nx293)) ;
    IV1NP ix496 (.X (nx470), .A (b[6])) ;
    ND2Q1 ix497 (.X (nx471), .A1 (a[6]), .A2 (nx470)) ;
    OAI3N1 ix498 (.X (nx472), .A1 (nx463), .A2 (nx80), .B1 (nx465), .B2 (nx471)
           ) ;
    AO1I1 ix499 (.X (nx473), .A1 (nx479), .A2 (nx467), .B (nx468)) ;
    IV1NP ix500 (.X (nx474), .A (op[0])) ;
    IV1NP ix501 (.X (nx475), .A (op[1])) ;
    ND3N1 ix502 (.X (nx476), .A1 (nx460), .A2 (nx474), .A3 (nx475)) ;
    AOA6I0 x_7__rename_rename (.X (x[7]), .A1 (nx454), .A2 (nx455), .B1 (nx456)
           , .B2 (nx457), .C1 (nx460), .C2 (nx466), .D1 (nx160), .D2 (nx469), .E1 (
           nx414), .E2 (nx472), .F1 (nx473), .F2 (nx476)) ;
    ND2Q1 nx273_rename (.X (nx273), .A1 (nx265), .A2 (op[0])) ;
    OAI2N1 nx393_rename (.X (nx393), .A1 (nx427), .A2 (a[6]), .B1 (nx461), .B2 (
           b[6])) ;
    WGT1 ix503 (.X (nx477), .CK (nx186)) ;
    WGT1 ix504 (.X (nx478), .CK (nx178)) ;
    WGT1 ix505 (.X (nx479), .CK (nx152)) ;
endmodule



////////////////////////////////////////////////////////////////////////////////
/// Synthesis of Delays

 /// Delays

//  Synthesis programs ignore delays.  (Do not use delays in Verilog
//  intended for synthesis.)


// :Example:
//
//  Human-written Verilog code to implement an AND gate with a 3 cycle delay.

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

   assign #3 x = a & b;

endmodule


// :Example:
//
// Simplified output of inference step.
//
// Note that the delay is gone.  The synthesized logic will very
// likely not have a delay of three.  The delay is determined by the
// target technology, fanout, routing, etc; the human-inserted delay
// is ignored.

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

   and a1(x,a,b);

endmodule