module BrockTB
     #(parameter DATA_WIDTH = 12)
      () ;
      
      logic clk, reset, start, ready ;
      logic [DATA_WIDTH-1:0] p ;
      logic [DATA_WIDTH-1:0] q ;
      logic [2*DATA_WIDTH-1:0] result ;
      
      ancienttimes #(DATA_WIDTH) dut(clk, reset, start, p, q, result, ready) ;
      
      // start ancienttimes and make sure it asserts ready
      task startMultiply() ;
        int i ;
        $display("Reseting test module") ;
        start = 0 ;
        p = 0 ;
        q = 0 ;
        reset = 0 ;
        #320 reset = 1 ;
        #320 reset = 0 ;
        for (i=0; i<10; ++i) 
        begin
          @(negedge clk)
          ;
        end
        assert (ready == 1) else $error("Test module did not assert ready") ;
      endtask 
      
      // Test a multiplication
      task doMultiply(int unsigned pt, int unsigned qt) ;
        int i ;
        // These are silly names
        int unsigned ptt, qtt, rtt ;
        ptt = pt[DATA_WIDTH-1:0] ;
        qtt = qt[DATA_WIDTH-1:0] ;
        rtt = ptt*qtt ;
        assert (ready == 1) else $error("ready must be asserted before calling multiply") ;
        // load p, q, and start
        $display("Multiplying %d by %d, expecting %d", ptt, qtt, rtt) ;
        @(negedge clk)
        p = ptt ;
        q = qtt ;
        start = 1 ;
        // leave start asserted for three cycles
        for (i=0; i<3; ++i)
        begin
          @(negedge clk)
          ;
        end
        // now deassert start and wait
        start = 0 ;
        i = 0;
        while (i<1000 && !ready)
        begin
          @(negedge clk)
          ++i ;
        end
        assert (ready == 1) else $error("ready not asserted") ;
        assert (rtt == result) else $error("wrong result") ;
        $display("result = %d", result) ;
      endtask

      always
      begin
        #100 clk = 0 ;
        #100 clk = 1 ;
      end
      
      initial
      begin
        int i ;
        startMultiply() ;
        // the case from the homework description
        doMultiply(42, 255) ;
        // 5 fencepost cases
        doMultiply(0, 0) ;
        doMultiply(1, 1) ;
        doMultiply(0, 320) ;
        doMultiply(320, 0) ;
        doMultiply(~0, ~0) ;
        // And 94 random cases
        for (i=6; i<100; ++i)
          doMultiply($urandom(), $urandom()) ;
        $stop ;
      end
      
endmodule // end of moduel
