/// Bean Counter Testbench Using Macro for Module Name `ifdef BEANMOD `else `define BEANMOD beancount `endif `ifdef clock_period `else `define clock_period 7 `endif `ifdef BEANTESTMOD `else `define BEANTESTMOD beantest `endif module `BEANTESTMOD(); integer beantime; // Time for bean to move from pd1 to pd2. integer beans, beans1; // Number of beans simulated by testbench. reg pd1, pd2, clk; wire [15:0] cnt; integer errors; integer last_error; // Difference between executed and actual. reg reset; // Instantiate a bean counter. `BEANMOD bc(cnt,pd1,pd2,clk,reset); initial begin:INIT integer inter_clump; // Time between beans. integer min_bean_time; // Fastest bean speed. integer max_bean_time; // Slowest bean speed. integer oldbeantime; // Initialize simulation variables. min_bean_time = 10 * `clock_period; // Fastest bean speed. max_bean_time = 10 * min_bean_time; // Slowest bean speed. beantime = min_bean_time; oldbeantime = 0; beans = 0; // Testbench bean count. errors = 0; last_error = 0; // Initialize simulated hardware. pd1 = 0; pd2 = 0; clk = 0; // Generate reset signal. reset = 0; #1; reset = 1; # (2 * `clock_period); reset = 0; # (2 * `clock_period); // Simulate at least 50 beans. while( beans < 50 ) begin // End of previous clump reaches pd1. pd1 <= 0; // Choose amount of time between bean clumps. inter_clump = ($random>>1) % ( 5 * max_bean_time ); # inter_clump; // Beginning of new clump reaches pd1; pd1 <= 1; // Choose bean speed, amount of time for one bean to pass // a point. (E.g., pd1.) beantime = min_bean_time + ($random>>1) % ( max_bean_time - min_bean_time ); // Prevent new clump from smashing into previous clump // between photodetectors. if( inter_clump + beantime < oldbeantime ) beantime = oldbeantime + inter_clump ; oldbeantime = beantime; begin:CLUMP forever begin // Bean arrives at pd1. # beantime; // Bean arrives at pd2. beans = beans + 1; if( $random & 'b1 ) disable CLUMP; end end end // while ( beans < 50 ) // Wait for last bean, plus time for circuit to count it. # ( 2 * beantime ); if( errors === 0 ) $display("Beans counted properly.\n"); else $display("*** ERROR: bean count off by %d.\n", beans - cnt); $stop; end // block: INIT // Clock for bean counter circuit. always #`clock_period clk = ~clk; // Make sure bean counter count agrees with testbench . always @ ( beans ) beans1 <= #(beantime * 0.75 ) beans; always @( beans1 ) if( cnt - beans1 !== last_error ) begin errors = errors + 1; last_error = cnt - beans1; if( errors <= 5 ) $display("Wrong bean count, %d should be %d.\n", cnt,beans1); if( errors == 5 ) $display("Ignoring future errors.\n"); $stop; end // Set pd2 to lag pd1 by a beantime. always @( posedge pd1 ) pd2 <= #beantime 1; always @( negedge pd1 ) pd2 <= #beantime 0; endmodule // beantest