/// Sample Code for LSU EE 4702-1 Spring 2001
///
/// Population Modules and Testbench
///
 /// Input:       a,  an 8-bit vector.
 /// Output:    pop, the number of 1's in a.

 /// Three descriptions:  behavioral, implicit structural, and explicit structural.

module pop_behavioral_8(pop,a);
   input a;
   output pop;

   wire [7:0] a;
   reg [3:0]  pop;
   integer    a_work, pop_work;

   // Executes whenever a changes.
   always @( a ) begin

      pop_work = 0;
      a_work   = a;

      while( a_work ) 
        begin 
           pop_work = pop_work + a_work[0];
           a_work   = a_work >> 1;
        end

      // Note: pop changes once per change in a.
      pop = pop_work;

   end

endmodule

module pop_implicit_structural_8(pop,a);
   input a;
   output pop;

   wire [7:0] a;
   // Alas, there is no reduction addition operator.
   wire [3:0] pop = a[7] + a[6] + a[5] + a[4] + a[3] + a[2] + a[1] + a[0];

endmodule // pop_implicit_structural

// And what if a is 128-bits? 
// (loop for i from 0 to 127 concat (format " + a[%d]" i))

module pop_explicit_structural_8(pop,a);
   input a;
   output pop;
   wire [7:0] a;
   wire [3:0] pop;

   wire [2:0] pop03, pop47;

   pop_explicit_structural_4 p03(pop03,a[3:0]);
   pop_explicit_structural_4 p47(pop47,a[7:4]);

   add_3 adder(pop[3],pop[2:0],pop03,pop47);

endmodule // pop_explicit_structural_8

module pop_explicit_structural_4(pop,a);
   input a;
   output pop;
   wire [3:0] a;
   wire [2:0] pop;

   wire [1:0] pop03, pop47;

   bfa_structural bfa0(a0,a1,a[0],a[1],1'b0);
   bfa_structural bfa1(b0,b1,a[2],a[3],1'b0);
   
   bfa_structural bfa2(pop[0],cout0,a0,b0,1'b0);
   bfa_structural bfa3(pop[1],pop[2],a1,b1,cout0);

endmodule // pop_explicit_structural_4


//
// Binary Full Adder Explicit Structural Description
//

module bfa_structural(sum,cout,a,b,c);
   input a,b,c;
   output sum,cout;

   wire   term001, term010, term100,term111;
   wire   ab, bc, ac;
   wire   na, nb, nc;

   or o1(sum,term001,term010,term100,term111);
   or o2(cout,ab,bc,ac);

   and a1(term001,na,nb,c);
   and a2(term010,na,b,nc);
   and a3(term100,a,nb,nc);
   and a4(term111,a,b,c);

   not n1(na,a); 
   not n2(nb,b); 
   not n3(nc,c);

   and a10(ab,a,b);
   and a11(bc,b,c);
   and a12(ac,a,c);

endmodule 

module add_3(c_out,sum,a,b);
   input a, b;
   output c_out, sum;
   wire [2:0] a, b;
   wire       c_out;
   wire [2:0] sum;

   bfa_structural bfa0(sum[0],cout1,a[0],b[0],1'b0);
   bfa_structural bfa1(sum[1],cout2,a[1],b[1],cout1);
   bfa_structural bfa2(sum[2],c_out,a[2],b[2],cout2);

endmodule


module test_pop();

   wire [3:0] pb, pis, pes;
   integer    i;
   wire [7:0] a = i[7:0];
   integer    check;

   pop_behavioral_8 p_b(pb,a);
   pop_implicit_structural_8 p_is(pis,a);
   pop_explicit_structural_8 p_es(pes,a);

   initial begin

      check = 0;

      for(i=0; i<256; i=i+1)
        begin
           #1;
           if( (^pb) === 1'bx ) begin
              $display("Behavioral has unknown value.");
              $stop;
           end

           check = check + pb;

           if( (^pis) === 1'bx ) begin
              $display("Implicit structural has unknown value.");
              $stop;
           end

           if( pis != pb ) begin
              $display("Implicit structural has wrong value.");
              $stop;
           end
          
           if( (^pes) === 1'bx ) begin
              $display("Explicit structural has unknown value.");
              $stop;
           end

           if( pes != pb ) begin
              $display("Explicit structural has wrong value.");
              $stop;
           end
        end // for (i=0; i<255; i=i+1)

      if( check != 256 * 4 ) begin
         $display("Incorrect check.");
         $stop;
      end

      $display("Passed all tests.");
      $stop;
      
   end
   

endmodule