driver.v 6.17 KB
//
//  Driver for Verilog version of RDP
//
//
//  mod 10/20/94  hal Added random delay in between fetches of 10 command words.
//  cre  9/16/94  RJM
//

`define DMA_LENGTH	9

`define WAIT 		0
`define OUTPUT_WORD	1
`define RANDOM_DELAY	2
`define MAXIMUM_DELAY	5000
`define MAX_16BIT_INT	65536

module driver(gclk, reset, xbus_valid, xbus_data, request);
  //
  //  Inputs
  //
  input		request;

  //
  //  Outputs
  //
  output			gclk;
  output			reset;
  output			xbus_valid;
  output	[63:0]		xbus_data;

  //
  //  Registers
  //
  reg				gclk;
  reg				reset;
  reg				xbus_valid;
  reg		[63:0]		xbus_data;

  //
  //  Internal Variables
  //
  integer			read_value;
  integer			reset_clocks;
  integer			sim_clocks;
  integer			done;
  integer			count;
  integer			fp;        // file pointer for display list file
  reg		[1:256*8]	filename;
  reg		[63:0]		mem_word;
  reg		[1:0]		dma_state;
  event				EndVectors;
  event				WriteFrameBuffer;

  integer			max_delay; // max # glocks to delay
  integer			rand_seed; // seed for $random()
  integer	delay_value;		   // number of glclocks to delay
  integer	rand_value;		   // value returned by $random()

  //
  //  Get number of simulation clocks
  //
  initial
  begin
    if ($getnum$plusarg("simclk=", sim_clocks) != 1)
    begin
      sim_clocks  = 500;
    end
    $write("Running simulation for %d clocks\n", sim_clocks);
  end

  //
  //  Read in the seed for the random number generator, if one was supplied
  //  on the command line.  If not, generate a random seed.  Report what seed
  //  was used, so that if an error developed during the simulation run, we'd
  //  be able to repeat the behavior.
  //
  initial
  begin
    if ($getnum$plusarg("seed=", rand_seed) != 1)
    begin
      rand_seed = $random;
    end
    $display("Random number generator seed = %d", rand_seed);
  end

  //
  //  Read in the maximum number of gclocks to delay in between fetches of
  //  10 words from the file (which is faking out a dma from memory).  If
  //  the user didn't specify otherwise, use 100.
  //
  initial
  begin
    if ($getnum$plusarg("max_delay=", max_delay) != 1)
      begin
	max_delay = 100;
      end
    else
      begin
	if ((max_delay < 0) || (max_delay > `MAXIMUM_DELAY))
	  begin
	  $display("WARNING: max_display value %d not in the range 0..5000.", 
	      max_delay);
       #1 max_delay = 100;
	  end
      end
 #1 $display("Maximum number of clocks to delay dma = %d", max_delay);
  end

  //
  //  Load Display List Memory File
  //
  initial
  begin
  if ($getstr$plusarg("dlmem=", filename) == 1)
    begin
      //
      //  Save off the file pointer returned by open_mem_file(), for use
      //  by read_mem_file() later on in this simulation...
      //
      fp = $open_mem_file(filename);
      if (fp == 0)
      begin
        $write("Cannot open display list memory file\n");
        $finish();
      end
    end
  end

  //
  //  Initialize registers
  //
  initial 
  begin
    reset_clocks  = 60;
    read_value = 0;
    mem_word   = 64'ha5a5a5a5b3b3b3b3;

    reset      = 0;
    xbus_data  = 64'hfeedbeefdeaddeed;
    xbus_valid = 0;
    dma_state  = `WAIT;
    done       = 0;
    count      = 0;
    delay_value = 0;
    rand_value = 0;
  end


  //
  //  Generate Clock
  //
  always
  begin
    gclk = 1;
    #800;
    gclk = 0;
    #800;
  end

  //
  //  Run Test
  //
  always @(posedge gclk)
  begin

    if(reset_clocks > 0)
    begin
      reset <= 0;
      reset_clocks = reset_clocks - 1;
      sim_clocks = sim_clocks - 1;
    end
    else if(sim_clocks > 0)
    begin

      reset <= 1;

      //  DMA state machine
      case (dma_state[1:0])

        `WAIT:
	begin
	  if(request && read_value != -1)
	  begin
	    dma_state <= `OUTPUT_WORD;
	    count <= `DMA_LENGTH;
	  end   
	  else
	    dma_state <= `WAIT;
	end

        `OUTPUT_WORD:
	begin
	  if ((done) || (count == 0))
	    begin
	      dma_state <= `RANDOM_DELAY;
	      if (max_delay > 0)
	        begin
		  //
		  // Compute a new random value each time we've completed a read
		  // (partial or complete).  Change the seed value in a 
		  // deterministic way so that we can repeat a simulation run 
		  // for debugging if need be.
		  //
		  // The modulus operator retains the sign of the first operand.
		  // It also overflows when dividing large integer values.
		  // Since the random number generator can return LARGE negative
		  // values, clamp it to a smallish positive value first, then 
		  // do the modulus operation.
		  //
		  rand_value <= $random(rand_seed);

	       #1 if (rand_value < 0)
		    begin
		      rand_value <= -(rand_value);
		    end

	       #1 while (rand_value > `MAX_16BIT_INT)
		    begin
		   #1 rand_value <= (rand_value / 2);
		    end

	       #1 delay_value <= (rand_value % max_delay);

//	       #1 $display(
//"delaying %d clocks, $random return val = %d, rand_value = %d", 
//		    delay_value, ($random(rand_seed)), rand_value);

	       //
	       // Add in the number of additional delay clocks to the 
	       // base simulation clock counter.
	       //
	       #1 sim_clocks <= sim_clocks + delay_value;

		  rand_seed <= rand_seed + 1;
		end
	      else
		begin
		  delay_value <= 0;
		end
	    end
          else
	    dma_state <= `OUTPUT_WORD;
	end

        `RANDOM_DELAY:
	  //
	  // wait the number of clocks computed when we exited from the 
	  // OUTPUT_WORD state.
	  //
	begin
	  if (delay_value > 0)
	    begin
	      delay_value <= delay_value - 1;
	      dma_state <= `RANDOM_DELAY;
	    end
	  else
	    begin
	      dma_state <= `WAIT;
	    end
	end
        
	default:
	  dma_state <= `WAIT;

      endcase

   //
   // Delay this assignment, in case we assigned a new value to sim_clocks
   // in the OUTPUT_WORD state above.
   //
   #1 sim_clocks <= sim_clocks - 1;
    end
    else // end simulation
    begin
      ->WriteFrameBuffer;
    end

    if(dma_state == `OUTPUT_WORD && !done)
    begin
      read_value = $read_mem_file(fp, mem_word);
      count = count - 1;
      if (read_value == -1)
      begin
	done = 1;
	xbus_valid <= 0;
        $write("Done reading input data.\n");
        -> EndVectors;
      end
      else
      begin
	xbus_valid <= 1;
        xbus_data[63:0] <= mem_word[63:0];
      end
    end
    else
      xbus_valid <= 0;

  end
endmodule