`include "sd_defines.v"
`include "wb_model_defines.v"

module test_sd;

reg wb_clk;
reg wb_rst;

wire [7:0] wb_dat_i;
wire [7:0] wb_dat_o;
wire [2:0] wb_adr_i;
wire wb_sel_i;
wire wb_we_i;
wire wb_stb_i;
wire wb_cyc_i;
wire wb_ack_o;

wire sd_cmd_oe;
wire sd_cmd_out;
wire sd_dat_oe;
wire sd_clk_pad_o;
wire [3:0] sd_dat_out;
wire [3:0] sd_dat_pad_io;

assign sd_cmd_pad_io = sd_cmd_oe ? sd_cmd_out : 1'bZ ;
assign sd_dat_pad_io = sd_dat_oe ? sd_dat_out : 4'bzzzz ;

// wishbone to SD controller instantiation
//
sd_controller_fifo_wba wish2sd_pio (
	.wb_clk_i	(wb_clk),
	.wb_rst_i	(wb_rst),
	.wb_dat_i	(wb_dat_i),
	.wb_dat_o	(wb_dat_o),
	.wb_adr_i	(wb_adr_i),
	.wb_sel_i	(wb_sel_i),
	.wb_we_i	(wb_we_i),
	.wb_stb_i	(wb_stb_i),
	.wb_cyc_i	(wb_cyc_i),
	.wb_ack_o	(wb_ack_o),

	.sd_cmd_dat_i	(sd_cmd_pad_io),
	.sd_cmd_out_o	(sd_cmd_out  ),
	.sd_cmd_oe_o	(sd_cmd_oe),
	.sd_dat_dat_i	(sd_dat_pad_io),
	.sd_dat_out_o	(sd_dat_out ) ,
	.sd_dat_oe_o	(sd_dat_oe  ),
	.sd_clk_o_pad 	(sd_clk_pad_o)

   `ifdef SD_CLK_EXT
    , .sd_clk_i_pad (sd_clk_i_pad)
   `endif
	 );
  
// SD card model instantiation
//

sdModel sdModel (
	.sdClk		(sd_clk_pad_o),
	.cmd		(sd_cmd_pad_io),
	.dat		(sd_dat_pad_io)
	);
   
// Wishbone master model instantiation
//

WB_MASTER_BEHAVIORAL wb_master (
	.CLK_I		(wb_clk),
	.RST_I		(wb_rst),
	.TAG_I		(5'b0_0000),
	.TAG_O		(),
	.ACK_I		(wb_ack_o),
	.ADR_O		(wb_adr_i),
	.CYC_O		(wb_cyc_i),
	.DAT_I		(wb_dat_o),
	.DAT_O		(wb_dat_i),
	.ERR_I		(1'b0),
	.RTY_I		(1'b0),
	.SEL_O		(wb_sel_i),
	.STB_O		(wb_stb_i),
	.WE_O		(wb_we_i),
	.CAB_O		()
	);
   
// Generate the wb_clk
always
begin
	wb_clk = 1'b0;
	//  forever #2.5 wb_clk = ~wb_clk;  // 2*2.5 ns -> 200.0 MHz    
	//  forever #5 wb_clk = ~wb_clk;  // 2*5 ns -> 100.0 MHz    
	//  forever #10 wb_clk = ~wb_clk;  // 2*10 ns -> 50.0 MHz    
	//  forever #12.5 wb_clk = ~wb_clk;  // 2*12.5 ns -> 40 MHz    
	//  forever #15 wb_clk = ~wb_clk;  // 2*10 ns -> 33.3 MHz    
	  forever #20 wb_clk = ~wb_clk;  // 2*20 ns -> 25 MHz    
	//  forever #25 wb_clk = ~wb_clk;  // 2*25 ns -> 20.0 MHz
	//  forever #31.25wb_clk = ~wb_clk;  // 2*31.25 ns -> 16.0 MHz    
	//  forever #50 wb_clk = ~wb_clk;  // 2*50 ns -> 10.0 MHz
	//  forever #55 wb_clk = ~wb_clk;  // 2*55 ns ->  9.1 MHz    
end

`define TIME $display("  Time: %0t", $time)

// define the 6 target registers
`define tx_cmd_fifo 4'h0 // write only
`define rx_cmd_fifo 4'h1 // read only
`define tx_data_fifo 4'h2 // write only
`define rx_data_fifo 4'h3 // read only
`define status 4'h4 // read only
`define control 4'h5 // write only
`define timer 4'h6 // read only
`define BUSY 8'h80
`define CRC_TOKEN 8'h29


integer tb_log_file;
reg StartTB;
reg [799:0] test_name;
reg          wbm_working; // tasks wbm_write and wbm_read set signal when working and reset it when stop working
integer      tests_successfull;
integer      tests_failed;

reg   [3:0]  wbm_init_waits; // initial wait cycles between CYC_O and STB_O of WB Master
reg   [3:0]  wbm_subseq_waits; // subsequent wait cycles between STB_Os of WB Master
reg   [3:0]  wbs_waits; // wait cycles befor WB Slave responds
reg   [7:0]  wbs_retries; // if RTY response, then this is the number of retries before ACK

reg [((14*8) -1):0] sd_rsp;
//reg [7:0] sd_rsp [0:14];

// Generate the wb_rst
initial
begin
	wb_rst = 1'b1;
	repeat (10) @(posedge wb_clk);
	#1 wb_rst = 1'b0;
	repeat (10) @(posedge wb_clk);
	StartTB = 1'b1;
end

initial
begin
	wait (StartTB)

	// Call tests
	SD_test(0, 0);	// 0 Initialize SD Card
	//SD_test(1, 1);	// 1 Write SD Card
	//SD_test(2, 2);	// 2 Read SD Card
	//SD_test(3, 3);	// 3 compare write buffer and read buffer
	SD_test(1, 3);	// 3 write/read/compare
end

//Tasks
task hard_reset;
begin
  // reset SD registers
  @(posedge wb_clk);
  #2 wb_rst = 1'b1;
  repeat(2) @(posedge wb_clk);
  #2 wb_rst = 1'b0;
end
endtask // hard_reset

task soft_reset;
begin
  wbm_write(`control, 1, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
  repeat(2) @(posedge wb_clk);
  wbm_write(`control, 0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
end
endtask // soft_reset

task sd_tx_cmd;
  input  [7:0] cmd_byte_0;
  input  [7:0] cmd_byte_1;
  input  [7:0] cmd_byte_2;
  input  [7:0] cmd_byte_3;
  input  [7:0] cmd_byte_4;
begin
  wbm_write(`tx_cmd_fifo, cmd_byte_0, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
  wbm_write(`tx_cmd_fifo, cmd_byte_1, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
  wbm_write(`tx_cmd_fifo, cmd_byte_2, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
  wbm_write(`tx_cmd_fifo, cmd_byte_3, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
  wbm_write(`tx_cmd_fifo, cmd_byte_4, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
end
endtask // sd_tx_cmd

task sd_wait_timeout;
  reg [7:0] tmp_data;
  reg [2:0] addr;
begin
  addr = `timer  ; 
  tmp_data = 8'hff;

  while (tmp_data != 0)
  begin
    wbm_read(addr, tmp_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
  end
end
endtask // sd_wait_timeout

task wbm_write;
  input  [31:0] address_i;
  input  [31:0] data_i;
  input  [3:0]  sel_i;
  input  [31:0] size_i;
  input  [3:0]  init_waits_i;
  input  [3:0]  subseq_waits_i;

  reg `WRITE_STIM_TYPE write_data;
  reg `WB_TRANSFER_FLAGS flags;
  reg `WRITE_RETURN_TYPE write_status;
  integer i;
begin
  wbm_working = 1;
  
  write_status = 0;

  flags                    = 0;
  flags`WB_TRANSFER_SIZE   = size_i;
  flags`INIT_WAITS         = init_waits_i;
  flags`SUBSEQ_WAITS       = subseq_waits_i;

  write_data               = 0;
  write_data`WRITE_DATA    = data_i[31:0];
  write_data`WRITE_ADDRESS = address_i;
  write_data`WRITE_SEL     = sel_i;

  for (i = 0; i < size_i; i = i + 1)
  begin
    wb_master.blk_write_data[i] = write_data;
    data_i                      = data_i >> 32;
    write_data`WRITE_DATA       = data_i[31:0];
    write_data`WRITE_ADDRESS    = write_data`WRITE_ADDRESS + 4;
  end

  wb_master.wb_block_write(flags, write_status);

  if (write_status`CYC_ACTUAL_TRANSFER !== size_i)
  begin
    `TIME;
    $display("*E WISHBONE Master was unable to complete the requested write operation to MAC!");
  end

  @(posedge wb_clk);
  #3;
  wbm_working = 0;
  #1;
end
endtask // wbm_write

task wbm_read;
  input  [31:0] address_i;
  output [((`MAX_BLK_SIZE * 32) - 1):0] data_o;
  input  [3:0]  sel_i;
  input  [31:0] size_i;
  input  [3:0]  init_waits_i;
  input  [3:0]  subseq_waits_i;

  reg `READ_RETURN_TYPE read_data;
  reg `WB_TRANSFER_FLAGS flags;
  reg `READ_RETURN_TYPE read_status;
  integer i;
begin
  wbm_working = 1;

  read_status = 0;
  data_o      = 0;

  flags                  = 0;
  flags`WB_TRANSFER_SIZE = size_i;
  flags`INIT_WAITS       = init_waits_i;
  flags`SUBSEQ_WAITS     = subseq_waits_i;

  read_data              = 0;
  read_data`READ_ADDRESS = address_i;
  read_data`READ_SEL     = sel_i;

  for (i = 0; i < size_i; i = i + 1)
  begin
    wb_master.blk_read_data_in[i] = read_data;
    read_data`READ_ADDRESS        = read_data`READ_ADDRESS + 4;
  end

  wb_master.wb_block_read(flags, read_status);

  if (read_status`CYC_ACTUAL_TRANSFER !== size_i)
  begin
    `TIME;
    $display("*E WISHBONE Master was unable to complete the requested read operation from MAC!");
  end

  for (i = 0; i < size_i; i = i + 1)
  begin
    data_o       = data_o << 32;
    read_data    = wb_master.blk_read_data_out[(size_i - 1) - i]; // [31 - i];
    data_o[31:0] = read_data`READ_DATA;
  end

  @(posedge wb_clk);
  #3;
  wbm_working = 0;
  #1;
end
endtask // wbm_read

task sd_get_cmd_rsp;
  output rsp_rcv;
  input [7:0] rsp_size;

  integer arr_cnt;
  reg [7:0] status_data;
  reg [7:0] timer_cnt;
  reg [7:0] fifo_data;

  begin
    sd_rsp = 0;
    arr_cnt = 0;
    rsp_rcv = 0;

    // poll timer register for a timeout
    timer_cnt = 8'hff;

    while (timer_cnt != 0)
    begin
      wbm_read(`timer, timer_cnt, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
      wbm_read(`status, status_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
      if ((status_data & 8'h02) != 8'h02)	// RX CMD fifo not empty
      begin
        wbm_read(`rx_cmd_fifo, fifo_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
        sd_rsp = sd_rsp >> 8;
	if (rsp_size == 15)
          sd_rsp[15*8-1:14*8] = fifo_data;
	else // response size is 5 by default
          sd_rsp[5*8-1:4*8] = fifo_data;
	/*
        sd_rsp[arr_cnt][7:0] = fifo_data;
        */

        arr_cnt = arr_cnt + 1;
        if (arr_cnt == rsp_size)
	begin
	  rsp_rcv = 1;
	  timer_cnt = 0;
	end
      end
    end
  end
endtask

task test_ok ;
  reg [799:0] display_test ;
begin
  tests_successfull = tests_successfull + 1 ;

  display_test = test_name ;
  while ( display_test[799:792] == 0 )
    display_test = display_test << 8 ;

  $fdisplay( tb_log_file, "    *************************************************************************************" ) ;
  $fdisplay( tb_log_file, "    At time: %t ", $time ) ;
  $fdisplay( tb_log_file, "    Test: %s", display_test ) ;
  $fdisplay( tb_log_file, "    reported *SUCCESSFULL*! ") ;
  $fdisplay( tb_log_file, "    *************************************************************************************" ) ;
  $fdisplay( tb_log_file, " " ) ;
end
endtask // test_ok

task test_heading;
  input [799:0] test_heading ;
  reg   [799:0] display_test ;
begin
  display_test = test_heading;
  while ( display_test[799:792] == 0 )
    display_test = display_test << 8 ;
  $fdisplay( tb_log_file, "  ***************************************************************************************" ) ;
  $fdisplay( tb_log_file, "  ***************************************************************************************" ) ;
  $fdisplay( tb_log_file, "  Heading: %s", display_test ) ;
  $fdisplay( tb_log_file, "  ***************************************************************************************" ) ;
  $fdisplay( tb_log_file, "  ***************************************************************************************" ) ;
  $fdisplay( tb_log_file, " " ) ;
end
endtask // test_heading

task SD_test;
  input  [31:0] start_task;
  input  [31:0] end_task;
  integer       tmp_data;
  integer       fail;
  integer       test_num;
  integer	j;
  reg [7:0] status_data;
  reg [2:0] addr;
  reg [7:0] data;
  reg [3:0] sel;
  reg [3:0] rand_sel;
  reg [7:0]	rtn_reg;
  reg	spv_2_0;
  reg	[7:0]	rca_0;
  reg	[7:0]	rca_1;
  //reg	[512*8-1:0] sd_wr_data;
  //reg	[512*8-1:0] sd_rd_data;
  reg	[7:0] sd_wr_data [0:511];
  reg	[7:0] sd_rd_data [0:511];
begin
// test_send_cmd
test_heading("Initialize SD Card");
$display(" ");
fail = 0;
rtn_reg = `BUSY;
spv_2_0 = 0;


//////////////////////////////////////////////////////////////////////
////                                                              ////
////  test_send_cmd:                                              ////
////                                                              ////
////  0:  initialize SD card                                      ////
///   1:  read block from SD card                                 ////
///   2:  write block to SD card                                  ////
///   3:  compare write buffer and read buffer                    ////
///                                                               ////
//////////////////////////////////////////////////////////////////////
for (test_num = start_task; test_num <= end_task; test_num = test_num + 1)
begin
        
  if (test_num == 0) //
  begin
    //////////////////////////////////////////////////////////////////////
    ////                                                              //// 
    //Test 0:  Initialize SD Card                                     ////
    //////////////////////////////////////////////////////////////////////

    test_name   = "0:  Initialize SD Card  ";
    `TIME; $display("  TEST 0: Initialize SD Card  ");
    wbm_init_waits = 0;
    wbm_subseq_waits = {$random} % 5;
    data = 0;
    rand_sel = 0;
    sel = 4'hF;
      
    // reset SD registers
    hard_reset;

    //Reset Core
    soft_reset;

    // reset SD card, CMD 0, no response, wait for timeout
      
    `TIME; $display("Send CMD 0, Idle State, Expect No Response  ");
    sd_tx_cmd(8'h40, 8'h00, 8'h00, 8'h00, 8'h00);

    // poll timer register for a timeout
    sd_wait_timeout;

    // check for SD 2.0 card, no response is 1.x card type
      
    `TIME; $display("Send CMD 8, Send Interface Conditions, Expect Response if V2.0  ");
    sd_tx_cmd(8'h48, 8'h00, 8'h00, 8'h01, 8'haa);

    sd_get_cmd_rsp(tmp_data, 5);
    if (tmp_data == 0)
    begin	// no response means not V2.0 compatible, reset card
      `TIME; $display("V1.x Compatible Card found  ");
      soft_reset;
      `TIME; $display("Send CMD 0, Idle State, Expect No Response  ");
      sd_tx_cmd(8'h40, 8'h00, 8'h00, 8'h00, 8'h00);

      // poll timer register for a timeout
      sd_wait_timeout;
    end
    else
    begin
      // V2.0 compatible card found
      `TIME; $display("V2.0 Compatible Card found  ");
      spv_2_0 = 1;
    end

    if (spv_2_0 == 0)
    begin
      // send CMD55+ACMD41 until busy bit is cleared
      while ((rtn_reg & `BUSY) == `BUSY)
      begin
        `TIME; $display("Send CMD 55, App Specific, Expect Response  ");
        sd_tx_cmd(8'h77, 8'h00, 8'h00, 8'h00, 8'h00);
        sd_get_cmd_rsp(tmp_data, 5);
	if ((tmp_data == 1) && (sd_rsp[5*8-1:4*8] == 0))
	//if ((tmp_data == 1) && (sd_rsp[4][7:0] == 0))
	begin
          `TIME; $display("Send ACMD 41, Operating Conditions, Expect Response  ");
          sd_tx_cmd(8'h69, 8'h00, 8'h00, 8'h00, 8'h00);
          sd_get_cmd_rsp(tmp_data, 5);
	  if (tmp_data == 1)
	  begin
	    rtn_reg = sd_rsp[7:0];
	    //rtn_reg = sd_rsp[0][7:0];
	  end
	  else
	  begin
	    rtn_reg = 0;
	    fail = 1;
	  end
      	end
        else
	begin
	  rtn_reg = 0;
	  fail = 1;
	end
      end
    end

    // CMD 2 - get CSD, 136 bit response
    `TIME; $display("Send CMD 2, get CSD, Expect 136 bit Response  ");
    sd_tx_cmd(8'hC2, 8'h00, 8'h00, 8'h00, 8'h00);
    sd_get_cmd_rsp(tmp_data, 15);
    if (tmp_data == 0)
      fail = 1;

    // CMD 3 - get RCA, RCA in bits 31:24 of response
    `TIME; $display("Send CMD 3, get RCA, Expect 48 bit Response  ");
    sd_tx_cmd(8'h43, 8'h00, 8'h00, 8'h00, 8'h00);
    sd_get_cmd_rsp(tmp_data, 5);
    if (tmp_data == 0)
      fail = 1;
    else
    begin
      rca_0 = sd_rsp[7:0];
      rca_1 = sd_rsp[15:8];
      //rca_0 = sd_rsp[0][7:0];
      //rca_1 = sd_rsp[1][7:0];
      //rca_0 = sd_rsp[23:16]; TBD SD spec indicates 31:16 for RCA position
      //rca_1 = sd_rsp[31:24];
    end

    // CMD 7 - put card in transfer state
    `TIME; $display("Send CMD 7, transfer state Expect 48 bit Response  ");
    sd_tx_cmd(8'h47, rca_0, rca_1, 8'h0f, 8'h0f);
    sd_get_cmd_rsp(tmp_data, 5);
    if (tmp_data == 0)
      fail = 1;

    // CMD 16 - set block size to 512
    `TIME; $display("Send CMD 16, block size 512, Expect 48 bit Response  ");
    sd_tx_cmd(8'h50, 8'h00, 8'h00, 8'h02, 8'h00);
    sd_get_cmd_rsp(tmp_data, 5);
    if (tmp_data == 0)
      fail = 1;

    // CMD 55 - set bus width to 4
    `TIME; $display("Send CMD 55, App Specific, Expect 48 bit Response  ");
    sd_tx_cmd(8'h77, rca_0, rca_1, 8'h00, 8'h00);
    sd_get_cmd_rsp(tmp_data, 5);
    if (tmp_data == 0)
      fail = 1;

    // ACMD 6
    `TIME; $display("Send ACMD 6, bus width 4, Expect 48 bit Response  ");
    sd_tx_cmd(8'h46, 8'h00, 8'h00, 8'h00, 8'h02);
    sd_get_cmd_rsp(tmp_data, 5);
    if (tmp_data == 0)
      fail = 1;
      
    if(fail == 0)
    begin
      test_ok;
      `TIME; $display("SD Intitialization completed normally  ");
    end
    else
    begin
      `TIME; $display("SD Intitialization failed  ");
      fail = 0;
    end
  end

    //////////////////////////////////////////////////////////////////////
    ////                                                              //// 
    //Test 1:  Write block to SD Card                                 ////
    //////////////////////////////////////////////////////////////////////
    else if (test_num == 1)
    begin
      test_name   = "1:  Write Block to SD Card  ";
      `TIME; $display("  TEST 1: Write Block to SD Card  ");
      wbm_init_waits = 0;
      wbm_subseq_waits = {$random} % 5;
      data = 0;
      rand_sel = 0;
      sel = 4'hF;
      
      // create write data
      /*
      sd_wr_data = 0;
      for (j=0; j < 512; j = j +1)
      begin
	sd_wr_data = sd_wr_data << 8;
	sd_wr_data[7:0] = j;
      end
      */
      for (j=0; j < 512; j = j +1)
      begin
	//sd_wr_data[j][7:0] = j;
	sd_wr_data[j][7:0] = {$random} % 255;
      end


      // send the write data to the TX fifo
      for (j=0; j < 512; j = j +1)
      begin
	/*
	data = sd_wr_data[7:0];
	sd_wr_data = sd_wr_data >> 8;
	*/
	data = sd_wr_data[j][7:0];
        wbm_write(`tx_data_fifo, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
      end

      // CMD24 - Single block write
      `TIME; $display("Send CMD 24, Write Block, Expect 48 bit Response  ");
      // block number to write is currently hard coded to 0
      sd_tx_cmd(8'h58, 8'h00, 8'h00, 8'h00, 8'h00);
      sd_get_cmd_rsp(tmp_data, 5);
      if (tmp_data == 0)
        fail = 1;
      
      // wait for tx_data_fifo to go not full
      status_data = 8'h04;
      while ((status_data & 8'h04) == 8'h04)
        wbm_read(`status, status_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 

      // wait for rx_data_fifo to go not empty
      status_data = 8'h08;
      while ((status_data & 8'h08) == 8'h08)
        wbm_read(`status, status_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 

      // read CRC token, expect 0x29
        wbm_read(`rx_data_fifo, rtn_reg, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
	if ((rtn_reg & `CRC_TOKEN) == `CRC_TOKEN)
	begin
          `TIME; $display("Write Block completed normally  ");
	end
	else
	begin
          `TIME; $display("Write Block failed CRC check  ");
          fail = 1;
	end
    end

    //////////////////////////////////////////////////////////////////////
    ////                                                              //// 
    //Test 2:  Read block from SD Card                                ////
    //////////////////////////////////////////////////////////////////////
    else if (test_num == 2)
    begin
      test_name   = "2:  Read Block from SD Card  ";
      `TIME; $display("  TEST 2: Read Block from SD Card  ");
      wbm_init_waits = 0;
      wbm_subseq_waits = {$random} % 5;
      data = 0;
      rand_sel = 0;
      sel = 4'hF;
      
      // CMD17 - Single block read
      `TIME; $display("Send CMD 24, Read Block, Expect 48 bit Response  ");
      // block number to read is currently hard coded to 0
      sd_tx_cmd(8'h51, 8'h00, 8'h00, 8'h00, 8'h00);
      sd_get_cmd_rsp(tmp_data, 5);
      if (tmp_data == 0)
        fail = 1;
      
      // wait for rx_data_fifo to go not empty
      status_data = 8'h08;
      while ((status_data & 8'h08) == 8'h08)
        wbm_read(`status, status_data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 

      // get the 512 bytes of data from SD card
      /*
      sd_rd_data = 0;
      for (j=0; j < 512; j = j +1)
      begin
        wbm_read(`rx_data_fifo, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
	sd_rd_data[7:0] = data;
	sd_rd_data = sd_rd_data << 8;
      end
      */
      for (j=0; j < 512; j = j +1)
      begin
        wbm_read(`rx_data_fifo, data, 4'hF, 1, wbm_init_waits, wbm_subseq_waits); 
	//sd_rd_data[j][7:0] = data;
	sd_rd_data[j] = data;
      end

      `TIME; $display("Read Block completed normally  ");
    end

    //////////////////////////////////////////////////////////////////////
    ////                                                              //// 
    //Test 3:  Compare write buffer and read buffer                   ////
    //////////////////////////////////////////////////////////////////////
    else if (test_num == 3)
    begin
      test_name   = "3:  Compare write and read buffers  ";
      `TIME; $display("  TEST 3: Compare write and read buffers  ");

      fail = 0;
      for (j=0; j < 512; j = j +1)
      begin
	if (sd_wr_data[j] != sd_rd_data[j])
	begin
          $display("Data Comparison Error, offset = %0x, wr = %0x, rd = %0x", j, sd_wr_data[j], sd_rd_data[j]);
	  fail = 1;
        end
      end

      if (fail == 1)
        $display("Data Comparison Failed  ");
      else
        $display("Data Comparison Passed  ");
    end

  end
end
endtask

endmodule   
   
