/// 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