///////////////////////////////////////////////////////////////////////
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ====================================================================
// Copyright 2002 (c) Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
//
// This confidential and proprietary software may be used only as
// authorised by a licensing agreement from Lattice Semiconductor
// Corporation.
// The entire notice above must be reproduced on all authorized
// copies and copies may only be made to the extent permitted
// by a licensing agreement from Lattice Semiconductor Corporation.
//

// ====================================================================
// File Details
// ====================================================================
// Project              :       ORSPII
// Filename             :       body.v
// Author               :       Ben_Kerr,bkerr@latticesemi.com
// Created on           :       Tuesday July 09 2002 (WW27)
// Last Modified By     :       $Author: bkerr $
// Last Modified On     :       $Date: Mon Jan  6 11:12:14 2003 $
// Revision             :       $Revision: 1.34 $
// Status               :       Development
// Dependencies         :       None
//=====================================================================

//=====================================================================
// Description          :
//=====================================================================
// Body file used in the middle of the automatically created toptest.v
//
// After running the simany_ph1 script, toptest.v is created
// This file is built from the following files:
//
//   +-----------------------------------+
//   | `defines generated by script      |  Time of day, user information & configuration feedback
//   +-----------------------------------+
//   |                                   |  top level module statement, global variables
//   |            header.v               |  module instantiations, clock & reset generation
//   |                                   |  initial ....
//   +-----------------------------------+
//   |                                   |    DUT register settings (configuration specific)
//   |     SFnn - from command line      |
//   |                                   |
//   +-----------------------------------+
//   |                                   |    DUT memory configurations (configuration specific)
//   |     Mnn - from command line       |
//   |                                   |
//   +-----------------------------------+
//   |                                   |    Task calls to configure DUT
//   |       body.v (this file)          |    Task calls to enable checkers
//   |                                   |    Task calls to perform data format tests
//   +-----------------------------------+
//   |                                   |    Report pass/fail. Terminate simulation
//   |            footer.v               |    `include common tasks
//   |                                   |  endmodule
//   +-----------------------------------+
//
//
//=====================================================================

//=====================================================================
// Revision History
//=====================================================================
// $Log: body.v.rca $
// 
//  Revision: 1.34 Mon Jan  6 11:12:14 2003 bkerr
//  Added additional spi4_reset after register configuration to
//  reset DPRAM control logic after changing partition mode
// 
//  Revision: 1.33 Thu Nov 21 09:19:14 2002 bkerr
//  Added LOOPBACK_FE register bit
// 
//  Revision: 1.32 Fri Nov 15 10:01:55 2002 bkerr
//  Increased delays when running DF18-DF21 due to extra time required
//  to synchronise to long calendar sequence
// 
//  Revision: 1.31 Fri Nov  8 03:32:21 2002 bkerr
//  More delay after enableing HS & LS loopback to prevent packet
//  loss in testcase 17.
//  Added dummy write to prime the AHB slave
// 
//  Revision: 1.30 Thu Nov  7 12:10:28 2002 bkerr
//  Changed start-up order of BFMs. tx_cal should be started first to
//  allow the DUT to synchronise to the calendar and stop sending
//  training
// 
//  Revision: 1.29 Tue Nov  5 12:52:53 2002 bkerr
//  Enabled all tests
//  Increased delay following write to enable HS and LS loopback to prevent
//  packet loss
// 
//  Revision: 1.28 Fri Nov  1 05:14:41 2002 bkerr
//  Increased delay after changing loopback mode
// 
//  Revision: 1.27 Wed Oct 23 12:19:38 2002 bkerr
//  Increased delay after enabling loopback to allow the write to be completed
// 
//  Revision: 1.26 Tue Oct 22 08:50:00 2002 bkerr
//  Moved LatSPI4 Tx calendar Rx start control to Rx tests, as the TSTAT
//  output is not stable when switching into LS and HS loopback
// 
//  Revision: 1.25 Tue Oct 22 06:46:56 2002 bkerr
//  Brought in changes from branch
// 
//  Revision: 1.24.1.1 Tue Oct 22 06:34:57 2002 bkerr
//  Moved start of Rx fpga_bfm's to top of file
//  Turned off credit checking for 18,19,20 & 21 as DUT will not
//  obey credit in this mode
// 
//  Revision: 1.24 Mon Oct 21 05:52:51 2002 bkerr
//  Reordered tests to do RX test after all Tx tests
//  Increased delays to allow data to propogate through DUT
//  Increased delay to wait for calendar synchronisation
// 
//  Revision: 1.23 Fri Oct 18 09:30:44 2002 bkerr
//  Moved all BFM start-up to one place. All BFMs are enabled throughout
//  the test
// 
//  Revision: 1.22 Thu Oct 17 07:52:18 2002 bkerr
//  Don't do Rx or FPGA loopback tests for tests 18,19,20 & 21 as they
//  currently do not work correctly
//  Removed force to fix issue #43
// 
//  Revision: 1.21 Wed Oct 16 11:28:24 2002 bkerr
//  Added `defines to allow individual tests to be disabled easily
//  Incorporated latest changes to FPGA loopback test
// 
//  Revision: 1.20 Tue Oct 15 11:03:39 2002 bkerr
//  Uncommented low-speed and high-speed loopback tests as this
//  function is useable in top4 release
// 
//  Revision: 1.19 Fri Oct 11 09:49:31 2002 bkerr
//  Corrected calendar_tx stop after Tx tests.
// 
//  Revision: 1.18 Wed Oct  9 03:51:24 2002 bkerr
//  Modified tx tests to only run df05 for testcases 18,19,20 & 21
// 
//  Revision: 1.17 Wed Oct  2 06:26:38 2002 rproudlo
//  commented out FPGA_LB phase
// 
//  Revision: 1.16 Wed Oct  2 06:03:12 2002 rproudlo
//  Added FPGA_LB suite of tests
// 
//  Revision: 1.15 Tue Oct  1 11:51:18 2002 bkerr
//  Added call to df04 (ERR bit testing)
//  Renamed previous df04 call to df05
// 
//  Revision: 1.14 Mon Sep 30 12:35:46 2002 bkerr
//  Added $display of FPSC_ID register
// 
//  Revision: 1.13 Wed Sep 25 11:07:05 2002 bkerr
//  Increased time-delay at end of test to allow all data to flush out
//  Changed check_stats task call to check_stats_tx
// 
//  Revision: 1.12 Wed Sep 18 12:49:50 2002 bkerr
//  Increased delay at end of test due to increase in FPGA clock
//  frequency
// 
//  Revision: 1.11 Mon Sep 16 05:38:03 2002 rproudlo
//  DebuggingInitial testing
// 
//  Revision: 1.10 Fri Sep 13 11:49:42 2002 rproudlo
//  debugginginitial debugging
// 
//  Revision: 1.9 Fri Sep 13 09:12:13 2002 rproudlo
//  Added verify tasks
// 
//  Revision: 1.8 Wed Sep 11 03:47:25 2002 bkerr
//  Run DF04 for SF19-SF21
// 
//  Revision: 1.7 Tue Sep 10 09:27:45 2002 bkerr
//  Added call to df04 when running SF18
// 
//  Revision: 1.6 Mon Sep  9 05:02:41 2002 bkerr
//  Pass max_length/num_times parameter to fpga_bfm_tx_df task calls
// 
//  Revision: 1.5 Wed Sep  4 05:51:34 2002 bkerr
//  Removed fpga_bfm_tx.df00 call
//  Added call to check_stats
// 
//  Revision: 1.4 Fri Aug 23 08:05:44 2002 bkerr
//  Commented out Rx path tests as only Tx is currently instantiated
// 
//  Revision: 1.3 Tue Aug 20 12:04:27 2002 bkerr
//  Grouped the FPGA Tx -> LatSPI4 Rx and LatSPI4 Tx -> FPGA Rx tasks
//  together. Forked these two tasks to allow both directions to be
//  tested simulataneously
//
//  Revision: 1.2 Wed Jul 10 11:43:16 2002 bkerr
//  Changed name of df task call as df22 was added
//
//  Revision: 1.1 Tue Jul  9 11:59:12 2002 bkerr
//  Initial creation
//=====================================================================

// Test control - use to control which tests are run
// Comment out `define to prevent test from running
`define DO_TX
`define DO_LS_LB
`define DO_HS_LB
`define DO_RX
`define DO_FPGA_LB

// Comment out to prevent registers & memory from being verified
`define DO_VERIFY

`include "qspi3_define.v"

// ---------------------------------------------------------------------------
// DUT version
// ---------------------------------------------------------------------------
   MPI_Read( 18'h30b28,read_reg );   
   $display("%t: ASB Version: FPSC_ID(30b28)=%h (%b)",$time,read_reg,read_reg); 

   // Dummy write to prime the AHB slave
   MPI_Write( 18'h30b28,read_reg );   
 
// ---------------------------------------------------------------------------
// Read/Write FPGA Registers
// ---------------------------------------------------------------------------

   MPI_Read( 18'h08000,read_reg );   
   $display("%t: Address(08000)=%h (%b)",$time,read_reg,read_reg); 

   MPI_Read( 18'h08001,read_reg );   
   $display("%t: Address(08001)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08002,read_reg );   
   $display("%t: Address(08002)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08003,read_reg );   
   $display("%t: Address(08003)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08004,read_reg );   
   $display("%t: Address(08004)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08005,read_reg );   
   $display("%t: Address(08005)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08006,read_reg );   
   $display("%t: Address(08006)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08007,read_reg );   
   $display("%t: Address(08007)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08008,read_reg );   
   $display("%t: Address(08008)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Write( 18'h08001,8'h3c );   
   MPI_Write( 18'h08003,8'hf0 );   
   MPI_Write( 18'h08004,8'h1e );   
   MPI_Write( 18'h08005,8'h2d );   
   MPI_Write( 18'h08006,8'h4b );   
   MPI_Write( 18'h08007,8'h5a );   

   MPI_Read( 18'h08000,read_reg );   
   $display("%t: Address(08000)=%h (%b)",$time,read_reg,read_reg); 

   MPI_Read( 18'h08001,read_reg );   
   $display("%t: Address(08001)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08003,read_reg );   
   $display("%t: Address(08003)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08004,read_reg );   
   $display("%t: Address(08004)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08005,read_reg );   
   $display("%t: Address(08005)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08006,read_reg );   
   $display("%t: Address(08006)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08007,read_reg );   
   $display("%t: Address(08007)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Write( 18'h08004,8'h00 );   

   rx_pe = `BURST_LEN/8;
   rx_pf = (2048/`NUM_FIFO * 0.75)/8;
   tx_pf = (2048/`NUM_FIFO - `BURST_LEN)/8;

   MPI_Write( 18'h08005,rx_pf);   
   MPI_Write( 18'h08006,tx_pf);   
   MPI_Write( 18'h08007,rx_pe);   
    
   MPI_Read( 18'h08004,read_reg );   
   $display("%t: Address(08004)=%h (%b)",$time,read_reg,read_reg);

   MPI_Read( 18'h08005,read_reg );   
   $display("%t: Address(08005)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08006,read_reg );   
   $display("%t: Address(08006)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Read( 18'h08007,read_reg );   
   $display("%t: Address(08007)=%h (%b)",$time,read_reg,read_reg);
    
   MPI_Write( 18'h0800c,8'h00);   
   MPI_Write( 18'h0800d,8'h01);   
   MPI_Write( 18'h0800e,8'h02);   
   MPI_Write( 18'h0800f,8'h03);   
   MPI_Write( 18'h08010,8'h00);   
   MPI_Write( 18'h08011,8'h00);   
   MPI_Write( 18'h08012,8'h01);   
   MPI_Write( 18'h08013,8'h01);   
   MPI_Write( 18'h08014,8'h02);   
   MPI_Write( 18'h08015,8'h02);   
   MPI_Write( 18'h08016,8'h02);   
   MPI_Write( 18'h08017,8'h03);   
   MPI_Write( 18'h08018,8'h03);   
   MPI_Write( 18'h08019,8'h03);   
   MPI_Write( 18'h0801a,8'h03);   
   MPI_Write( 18'h0801b,8'h00);   
// ---------------------------------------------------------------------------
// DUT register configuration
// ---------------------------------------------------------------------------
   $display("%t: DUT register configuration",$time);
   config_regs;

// Additional SPI-4 reset to reset DPRAM control logic
// All MPIF register values will not be affected
   spi4_reset = 1'b1;
   #(100);
   spi4_reset = 1'b0;
   
   $display("%t: DUT memory configuration",$time);
   config_mem;
   
   #1000;

`ifdef DO_VERIFY   
   $display("%t: DUT register verification",$time);
   verify_regs;
   
   $display("%t: DUT memory verification",$time);   
   verify_mem;
   
   #1000;
`endif
   
   $display("%t: DUT register & memory configuration complete",$time);

// ---------------------------------------------------------------------------
// Start-up all the BFMs
// ---------------------------------------------------------------------------
   a_latspi4.tx.idle(10);
   a_latspi4.rx.cal_tx(1'b1,1'b0,1'b0,2'b00);   // start sending the calendar
   wait(a_tdat === 16'h000f);                   // wait for DUT to send IDLE
   a_latspi4.rx.rx(1'b1,1'b0);                  // start-up the Rx data process
//   a_fpga_bfm_tx.start;                         // Start up the Tx FPGA BFM      
//
//   fork   
//      a_fpga_bfm_rx.fpga_bfm_rx32_0.start; 
//      a_fpga_bfm_rx.fpga_bfm_rx32_1.start; 
//      a_fpga_bfm_rx.fpga_bfm_rx32_2.start; 
//      a_fpga_bfm_rx.fpga_bfm_rx32_3.start; 
//      a_fpga_bfm_rx.fpga_bfm_rx64_0.start;
//      a_fpga_bfm_rx.fpga_bfm_rx64_2.start;  
//      a_fpga_bfm_rx.fpga_bfm_rx128_0.start;      
//   join


/* 

// ---------------------------------------------------------------------------
// Transmit
//    FPGA Tx -> LatSPI4 Rx
// ---------------------------------------------------------------------------

`ifdef DO_TX

   $display("%t: *******************************************************",$time);
   $display("%t: ****                     Transmit                  ****",$time);
   $display("%t: ****               FPGA Tx -> LatSPI4 Rx           ****",$time);
   $display("%t: *******************************************************",$time);
   
   #6000;                                      // wait for calendar to synchronise

   if(`SF != "sf18" &&
      `SF != "sf19" &&
      `SF != "sf20" &&
      `SF != "sf21")
   begin
      a_fpga_bfm_tx.df01(400);                 // Do the FPGA data formats
      a_fpga_bfm_tx.df02(400);
      a_fpga_bfm_tx.df03(400);
      a_fpga_bfm_tx.df04(400);
   end

   if(`SF == "sf18" ||
      `SF == "sf19" ||
      `SF == "sf20" ||
      `SF == "sf21")
   begin
      a_latspi4.rx.check_credit = 1'b0;        // Disable credit checking for these tests
      a_fpga_bfm_tx.df05(1000);
   end

   #14000;                                     // Wait for all data to flush out

   check_stats_tx;
   clear_stats;
   
   a_latspi4.rx.check_credit = 1'b1;           // turn on credit checking
  
`endif
   
// ---------------------------------------------------------------------------
// Low-speed loopback
//    FPGA Tx -> FPGA Rx
// ---------------------------------------------------------------------------

`ifdef DO_LS_LB

   $display("%t: *******************************************************",$time);
   $display("%t: ****    Low-speed loopback - FPGA Tx -> FPGA Rx    ****",$time);
   $display("%t: *******************************************************",$time);

   LOOPBACK_LS = 1'b1;
   
   LS_STIO_LB_FERR = {LOOPBACK_FE,
                      LOW_SPEED_DATA_SEL,
                      STATUS_IO_SEL,
	                   LOOPBACK_HS,
		                LOOPBACK_LS,
		                FORCE_DIP4_ERR,
		                FORCE_DIP2_ERR};
                      
   MPI_Write (18'h30915, {1'b0,LS_STIO_LB_FERR});
   MPI_Write (18'h30a15, {1'b0,LS_STIO_LB_FERR});
                                    
   a_latspi4.rx.check_credit = 1'b0;           // turn off credit checking
   if(`SF != "sf18" &&
      `SF != "sf19" &&
      `SF != "sf20" &&
      `SF != "sf21")
   begin
      #30000;                                  // Wait for MPI writes to take effect & calendar to synchronise
      a_fpga_bfm_tx.df01(400);                 // Do the FPGA data formats
      a_fpga_bfm_tx.df02(400);
      a_fpga_bfm_tx.df03(400);
   end

   if(`SF == "sf18" ||
      `SF == "sf19" ||
      `SF == "sf20" ||
      `SF == "sf21")
   begin      
      #50000;                                 // Wait for MPI writes to take effect & calendar to synchroise
      a_latspi4.rx.rx(1'b0,1'b1);             // stop the Rx data process
      a_fpga_bfm_tx.df05(1000);
   end
   
   #30000;                                    // Wait for all data to flush out            

   check_stats_tx;
   clear_stats;
  
   LOOPBACK_LS = 1'b0;
   
   LS_STIO_LB_FERR = {LOOPBACK_FE,
                      LOW_SPEED_DATA_SEL,
                      STATUS_IO_SEL,
	                   LOOPBACK_HS,
		                LOOPBACK_LS,
		                FORCE_DIP4_ERR,
		                FORCE_DIP2_ERR};
                      
   MPI_Write (18'h30915, {1'b0,LS_STIO_LB_FERR});
   MPI_Write (18'h30a15, {1'b0,LS_STIO_LB_FERR});
   
   a_latspi4.rx.check_credit = 1'b1;           // turn on credit checking
   
`endif
  
// ---------------------------------------------------------------------------
// High-speed loopback
//    FPGA Tx -> FPGA Rx
// ---------------------------------------------------------------------------

`ifdef DO_HS_LB

   $display("%t: *******************************************************",$time);
   $display("%t: ****    High-speed loopback - FPGA Tx -> FPGA Rx   ****",$time);
   $display("%t: *******************************************************",$time);

   LOOPBACK_HS = 1'b1;
   
   LS_STIO_LB_FERR = {LOOPBACK_FE,
                      LOW_SPEED_DATA_SEL,
                      STATUS_IO_SEL,
	                   LOOPBACK_HS,
		                LOOPBACK_LS,
		                FORCE_DIP4_ERR,
		                FORCE_DIP2_ERR};
                      
   MPI_Write (18'h30915, {1'b0,LS_STIO_LB_FERR});
   MPI_Write (18'h30a15, {1'b0,LS_STIO_LB_FERR});
                                    
   a_latspi4.rx.check_credit = 1'b0;           // turn off credit checking      
   if(`SF != "sf18" &&
      `SF != "sf19" &&
      `SF != "sf20" &&
      `SF != "sf21")
   begin               
      #30000;                                  // Wait for MPI writes to take effect & calendar to synchronise
      a_fpga_bfm_tx.df01(400);                 // Do the FPGA data formats
      a_fpga_bfm_tx.df02(400);
      a_fpga_bfm_tx.df03(400);
   end

   if(`SF == "sf18" ||
      `SF == "sf19" ||
      `SF == "sf20" ||
      `SF == "sf21")
   begin
      #50000;                                 // Wait for MPI writes to take effect & calendar to synchronise
      a_latspi4.rx.rx(1'b0,1'b1);             // stop the Rx data process
      a_fpga_bfm_tx.df05(1000);
   end

   #30000;                                     // Wait for all data to flush out            

   check_stats_tx;
   clear_stats;
  
   LOOPBACK_HS = 1'b0;
   
   LS_STIO_LB_FERR = {LOOPBACK_FE,
                      LOW_SPEED_DATA_SEL,
                      STATUS_IO_SEL,
	                   LOOPBACK_HS,
		                LOOPBACK_LS,
		                FORCE_DIP4_ERR,
		                FORCE_DIP2_ERR};
                      
   MPI_Write (18'h30915, {1'b0,LS_STIO_LB_FERR});
   MPI_Write (18'h30a15, {1'b0,LS_STIO_LB_FERR});
  
   a_latspi4.rx.check_credit = 1'b1;           // turn on credit checking
 
`endif

// ---------------------------------------------------------------------------
// Receive
//    LatSPI4 Tx -> FPGA Rx  
// ---------------------------------------------------------------------------

`ifdef DO_RX

   // Don't do Rx test for 18,19,20 or 21
   if(`SF != "sf18" &&
      `SF != "sf19" &&
      `SF != "sf20" &&
      `SF != "sf21")
      begin
         $display("%t: *******************************************************",$time);
         $display("%t: ****                     Receive                   ****",$time);
         $display("%t: ****             LatSPI4 Tx -> FPGA BFM Rx         ****",$time);
         $display("%t: *******************************************************",$time);

         wait(a_rstat == 2'b11);                      // wait for SYNC before starting to receive calendar 
         a_latspi4.tx.cal_rx(1'b1,1'b0);              // start up the Rx calendar process

         #10000;                                        // wait for calendar synchronisation
         a_latspi4.df.df00(16,1);                      // transmit the Data Formats
         a_latspi4.df.df01_df22(16,0);                 // transmit the Data Formats

         a_latspi4.df.df00(64,0);                      // transmit the Data Formats
         a_latspi4.df.df01_df22(64,0);                 // transmit the Data Formats

         #16000;                                                                              

         check_stats_rx;
         clear_stats;
      end

`endif

*/
  
// ---------------------------------------------------------------------------
// FPGA loopback
//    LatSPI Tx -> LatSPI Rx
// ---------------------------------------------------------------------------

`ifdef DO_FPGA_LB

   // Don't do FPGA loopback test for 18,19,20 or 21
   if(`SF != "sf18" &&
      `SF != "sf19" &&
      `SF != "sf20" &&
      `SF != "sf21")
      begin
         $display("%t: ******************************************************",$time);
         $display("%t: ****    FPGA loopback - LatSPI Tx -> LatSPI Rx   ****",$time);
         $display("%t: ******************************************************",$time);

         FPGA_LB   = 1'b1;

         wait(a_rstat == 2'b11);                      // wait for SYNC before starting to receive calendar 
         a_latspi4.tx.cal_rx(1'b1,1'b0);              // start up the Rx calendar process

         #10000;                                        
         a_latspi4.df.df00(16,1);                        
         a_latspi4.df.df01_df22(16,0);

         a_latspi4.df.df00(64,0);                        
         a_latspi4.df.df01_df22(64,0);

         #16000; 

         check_stats_rx;
         
         FPGA_LB   = 1'b0;
      end

`endif
