module testbench();
  
  logic clk;
  logic nReset;
  
  logic [19:0] FRAM_Adr;
  logic [7:0] FRAM_DATA_OUT;
  logic [7:0] FRAM_DATA_IN;
  logic FRAM_RW;
  logic FRAM_RSTATUS;
  logic FRAM_hbn;
  logic FRAM_go;
  logic FRAM_busy;
  
  logic SPI_CLK;
  logic SPI_MISO;
  logic SPI_MOSI;
  logic SPI_CS;
  
  logic [2:0]test;
  logic test_running;
  logic starttesting;
  
  localparam TESTS_cnt = 5;  
  
  initial begin    
    // Required for EDA Playground
    $dumpfile("dump.vcd"); 
    $dumpvars;
    
    clk = 1'h0;
    nReset = 1'h0;
    
    FRAM_Adr <= 20'h0;
    FRAM_DATA_IN <= 8'h0;
  	FRAM_RW = 0;
  	FRAM_RSTATUS = 0;
  	FRAM_hbn = 0;
  	FRAM_go = 0;  
  
    test <= 2'h0;    
    
    repeat(10) @(posedge clk);
    nReset = 1'h1;
    
    starttesting <= 1'h1;
    test_running <= 1'h0;    
    
  end //initial end  
  
  
  
  // Clock Generation:
  always #(5) clk = ~clk; //clk 100MHz
  // end Clock Generation
  
  
  always @ (posedge starttesting or posedge FRAM_busy) begin
    
    repeat(10) @(posedge clk);
    if(test_running == 1'h0 & FRAM_busy == 1'h1) begin
      
        if(test == TESTS_cnt+1) begin
      	  test_running <= 1'h0;
          $display("Tests Finished");
          $finish;
  		end
    
    	case(test) inside
          3'b000: begin Test1(); test <= test + 1'h1; end
          3'b001: begin Test2(); test <= test + 1'h1; end 
          3'b010: begin Test3(); test <= test + 1'h1; end  
          3'b011: begin Test4(); test <= test + 1'h1; end      
         
    	endcase 
    end // endif   
  end // end always
  
  
  
  
  task Test1();
    test_running <= 1'h1;
    $display("DEBUG: %0tns: Test_1_Hibernation",$realtime);
    FRAM_hbn <= 1'h1; //Enter Hibernation
    FRAM_go <= 1'h1;
    #10; 
    FRAM_hbn <= 1'h0; //Reset Hibernation Flag
    FRAM_go <= 1'h0;
    $display("DEBUG: %0tns: Test_1_Hibernation__-END",$realtime);
    test_running <= 1'h0;
  endtask
  
  task Test2();
    test_running <= 1'h1;
    $display("DEBUG: %0tns: Test_2_ReadStatus",$realtime);
    FRAM_RSTATUS <= 1'h1; //Read Status
    FRAM_go <= 1'h1; //Go
    #10;
    FRAM_RSTATUS <= 1'h0; //Read Status
    FRAM_go <= 1'h0; //reset Go   
    $display("DEBUG: %0tns: Test_2_ReadStatus__-END",$realtime);
    test_running <= 1'h0;
  endtask
  
  task Test3();
    test_running <= 1'h1;
  	$display("DEBUG: %0tns: Test_3_FRAM_WRITE",$realtime);
    FRAM_Adr <= 20'h8FFF1; //Load 8FFF1 as adress
    FRAM_DATA_IN <= 8'hAA; //Load AA as Data to Write into FRAM
    FRAM_RW <= 1'h0; //Write Operation
    FRAM_go <= 1'h1; //Go
    #10;
    FRAM_go <= 1'h0; //resetGo   
    $display("DEBUG: %0tns: Test_3_FRAM_WRITE__-END",$realtime);
    test_running <= 1'h0;
  endtask
  
  task Test4();
  	test_running <= 1'h1;
    $display("DEBUG: %0tns: Test_4_FRAM_READ",$realtime);
    FRAM_Adr <= 20'h8FFF1; //Load 8FFF1 as adress
    FRAM_RW <= 1'h1; //Read
    FRAM_go <= 1'h1; //Go
    #10;
    FRAM_go <= 1'h0; //resetGo 
    FRAM_RW <= 1'h0; //Read
    $display("DEBUG: %0tns: Test_4_FRAM_READ__-END",$realtime);
    test_running <= 1'h0;
  endtask
  
  
  
  FRAM FRAM_ut(
    .i_clk(clk),
    .i_nreset(nReset),
    .i_adr(FRAM_Adr),
    .i_data(FRAM_DATA_IN),
    .o_data(FRAM_DATA_OUT),
    .i_rw(FRAM_RW),
    .i_status(FRAM_RSTATUS),
    .i_hbn(FRAM_hbn),
    .i_cready(FRAM_go),
    .o_busy(FRAM_busy),
    
    .o_SPI_Clk(SPI_CLK),
    .i_SPI_MISO(SPI_MOSI), // !!! only for Testing!!!
    .o_SPI_MOSI(SPI_MOSI), //
    .o_SPI_CS_n(SPI_CS)
  );
  
   
   
  
    
  
  
  
  
  
  
endmodule

 

  
  
  