/* * File: Harness.v * Module: Harness * Author: Herman Schmit * Date: Dec 22, 1997 * * Purpose: * This is the Verilog executable specification for Lab 1. It * instantiates a multiplier with two input operands (a & b), * a valid signal (valid), a clock (clk), and an output (c). * * How it works: * Random operands for a and b are generated every cycle. The valid * signal is asserted every "period" cycles and tells the multiplier * to multiply a and b. Harness expects this result will be available * after "latency" cycles. If there is an error, the simulation stops. * After testing three hundred pairs of operands, the simulation finishes. * */ module Harness; parameter width = 12, // width of input operands. // Valid range 0 < width <= 32. latency = 4, // The latency of the multiplier. period = 1; // The period of the multiplier. reg [width-1:0] a,b; // The random input operands. wire [2*width-1:0] c; // The output from the multiplier. reg clk; // The clock signal. wire valid; // The valid line, indicating valid // input operands. reg [2*width-1:0] c_expect[latency-1:0]; /* * The memory used to store the expected values from c. * This is necessary because if latency is greater than period, * there will be multiple operands "in flight" at any one time. */ integer c_ptr,f_ptr; multiplier u1(a,b,valid,c,clk); // Instantiate the multiplier. initial // Initial conditions. begin clk = 0; f_ptr = -1; // Set to -1 so that first cycle gets valid. c_ptr =0; $shm_open("waves"); // Open waves database. $shm_probe("AS"); repeat(300 * period) @(posedge clk); $finish; // Stop the simulation. end // Generate the valid line: assign valid = (f_ptr == 0)? 1:0; always @(posedge clk) f_ptr <= (f_ptr + 1) % period; // Generate the Clock: always begin #50; clk = ~clk; end // Generate a & b, store expected values, and test c. always @(posedge clk) begin /* * The test: * If c_expect contains "don't cares" it hasn't been written, * therefore don't check it. Otherwise, check c_expect against * c. If there's a mismatch, display the error and stop the * simulation. * * Note: the !== operator does a exact comparison including * "don't care" (x) and "high impedence" (z) values. If we * used the conventional comparison operations, == or !=, the * x's or z's in the operands cause the result of the comparison * to be x, which isn't good. */ if ((c_expect[c_ptr] !== 24'bx) && (c_expect[c_ptr] !== c)) begin $display("Error: c == %d, c_expect == %d",c,c_expect[c_ptr]); $stop; end a <= $random; b <= $random; if (valid === 1) c_expect[c_ptr] <= a * b; else c_expect[c_ptr] <= 24'bx; c_ptr <= (c_ptr + 1)%latency; end endmodule /* test_harness */