/// Sample Code for LSU EE 4702-1 Spring 2001 /// /// Synthesizable Population Modules and Testbench /// /// Input: a, an 8-bit vector. /// Output: pop, the number of 1's in a. // All population modules are synthesizable. // The pop_sequential modules are done in several ways (at least one // Form 1, Form 2, and Form 3). The comments next to the module // describe the form and the characteristics of the module. // Form 1, Combinational Logic. // `define xCOMB `ifdef COMB module pop_combinational(pop,a); input a; output pop; // Number of gates : 266 // data arrival time 3.59 wire [7:0] a; reg [3:0] pop; reg [7:0] a_work; reg [3:0] pop_work; integer i; always @( a ) begin pop_work = 0; a_work = a; for(i=0; i<8; i=i+1) begin pop_work = pop_work + a_work[0]; a_work = a_work >> 1; end pop = pop_work; end endmodule `endif // Form 3, Implicit State Machine. Performs one iteration per cycle, // with additional cycles needed before and after the population count. // `define SEQ `ifdef SEQ // exemplar encoding gray module pop_sequential(pop,rdy,a,clk); // Specify pin number (on chip) for clk. (Not tested.) // exemplar attribute clk pin_number 1 input a, clk; output pop, rdy; // Number of gates : 739 // clk : 294.7 MHz reg rdy; wire [7:0] a; reg [3:0] pop; reg [7:0] a_work, a_copy; always @( posedge clk ) if( a_copy !== a ) @( posedge clk ) begin rdy = 0; pop = 0; a_work = a; a_copy = a; @( posedge clk ); while( a_work ) begin @( posedge clk ); pop = pop + a_work[0]; a_work = a_work >> 1; end @( posedge clk ); rdy = a_copy == a; end endmodule `endif // Form 2. Code uses an (explicit) state machine, one iteration per // clock cycle. This is the version written during the lecture. // `define xSEQ3 `ifdef SEQ3 module pop_sequential(pop,rdy,a,clk); input a, clk; output pop, rdy; reg rdy; wire [7:0] a; reg [3:0] pop; reg [7:0] a_work, a_copy; reg state; parameter st_idle = 0; parameter st_count = 1; always @( posedge clk ) case( state ) st_idle: if( a_copy !== a ) begin rdy = 0; pop = 0; a_work = a; a_copy = a; state = st_count; end st_count: begin pop = pop + a_work[0]; a_work = a_work >> 1; if( !a_work ) begin rdy = a_copy == a; state = st_idle; end end endcase endmodule `endif // Form 2. Code does entire population count in one cycle. // `define xSEQ2 `ifdef SEQ2 module pop_sequential(pop,rdy,a,clk); input a, clk; output pop, rdy; reg rdy; wire [7:0] a; reg [3:0] pop; reg [7:0] a_work, a_copy; always @( posedge clk ) if( a_copy !== a ) begin rdy = 0; pop = 0; a_work = a; a_copy = a; repeat( 8 ) begin pop = pop + a_work[0]; a_work = a_work >> 1; end rdy = a_copy == a; end endmodule `endif // Form 2. Code uses an (explicit) state machine, one iteration per // clock cycle. This was prepared before the lecture. // `define xSEQE `ifdef SEQE module pop_sequential_expl(pop,rdy,a,clk); input a, clk; output pop, rdy; reg rdy; wire [7:0] a; reg [3:0] pop; reg [7:0] a_work, a_copy; parameter st_ready = 0; parameter st_loop = 1; parameter st_finish = 2; reg [1:0] state, next_state; always @( posedge clk ) begin case( state ) st_ready: if( a_copy !== a ) begin rdy = 0; pop = 0; a_work = a; a_copy = a; next_state = st_loop; end st_loop: if( a_work ) begin pop = pop + a_work[0]; a_work = a_work >> 1; end else next_state = st_finish; st_finish: begin rdy = a_copy == a; next_state = st_ready; end default: begin next_state = st_ready; a_copy = 0; pop = 0; end endcase state = next_state; end endmodule `endif // exemplar translate_off module test_pop(); wire [3:0] pc, psi, pse; integer i; wire [7:0] a = i[7:0]; integer check; integer popf; wire rdy, rdye; reg clk; function integer pop; input [7:0] a; begin pop = 0; while( a ) begin pop = pop + a[0]; a = a >> 1; end end endfunction initial clk = 0; always #2 clk = !clk; pop_combinational p_c(pc,a); pop_sequential p_si(psi,rdy,a,clk); pop_sequential_expl p_se(pse,rdye,a,clk); task checkp; input [3:0] p; input [159:0] name; if( p !== popf ) $display("%s has wrong value for %d, %h",name,a,p); endtask initial begin check = 0; i = 5; wait(!rdy);wait(rdy); wait(!rdye);wait(rdye); for(i=0; i<256; i=i+1) begin wait(!rdy); wait(!rdye);wait(rdy);wait(rdye); popf = pop(a); checkp(pc,"Combinational"); checkp(psi,"Sequential Impl."); checkp(pse,"Sequential Expl."); check = check + popf; end // for (i=0; i<255; i=i+1) if( check != 256 * 4 ) begin $display("Incorrect check."); $stop; end $display("Done with tests."); $stop; end endmodule // exemplar translate_on