//-------------------------------------------------------------------
//
//  Filename      : tb_GFP.v
//  Author        : Huang Lei Lei
//  Created       : 2015-09-09
//  Description   : testbench for test_GFP.v
//
//-------------------------------------------------------------------

`include "GFP_defines.v"

//`define AUTO_CHECK
        `define CHECK_FILE_I    "./check_data/check_i.dat"
        `define CHECK_FILE_O    "./check_data/check_o.dat"
        `define SIMUL_FILE_W_O  "./simul_data/simul_w_o.dat"
        `define SIMUL_FILE_R_O  "./simul_data/simul_r_o.dat"
`define DUMP_FSDB
        `define DUMP_FILE       "./simul_data/wave_form.fsdb"
        `define DUMP_TIME       0
//`define FORCE_FINISH
        `define FINISH_TIME     20000
`define HALF_CLK 10
`define FULL_CLK (2*`HALF_CLK)

`define PROG_FILE "./scripts/img_o.dat"


module tb_GFP ;

//*** PARAMETER DECLARATION ****************************************************

  parameter    MEMSIZE = 640*480-1   ;


//*** INPUT/OUTPUT DECLARATION *************************************************

  // global
  reg              clk               ;
  reg              rstn              ;

  // control
  reg              key               ;
  wire             led               ;

  // sdram
  wire             sdram_clk         ;
  wire [12 : 0]    sdram_addr        ;
  wire [31 : 0]    sdram_dq          ;
  wire [1  : 0]    sdram_bank_addr   ;
  wire [3  : 0]    sdram_dqm         ;
  wire             sdram_ras_n       ;
  wire             sdram_cas_n       ;
  wire             sdram_cke         ;
  wire             sdram_we_n        ;
  wire             sdram_sel_n       ;


//*** WIRE & REG DECLARATION ***************************************************


//*** MAIN BODY ****************************************************************

  // clk
  initial begin
    clk = 0 ;
    forever begin
      #`HALF_CLK ;
      clk = !clk ;
    end
  end

  // rstn
  initial begin
    rstn = 'd0 ;
    #(10*`FULL_CLK) ;
    rstn = 'd1 ;
    $display( "\n\n*** CHECK GFP ! ***\n" );
  end

  // inputs
  initial begin
    key = 1 ;
    #2000 ;
    key = 0 ;
  end

  // outputs

  // dut
  test_GFP dut (
    // clk & rst
    .clk                 ( clk                 ),
    .rstn                ( rstn                ),
    // key & led
    .key                 ( key                 ),
    .led                 ( led                 ),
    // sdram
    .sdram_clk           ( sdram_clk           ),
    .sdram_addr          ( sdram_addr          ),
    .sdram_dq            ( sdram_dq            ),
    .sdram_bank_addr     ( sdram_bank_addr     ),
    .sdram_dqm           ( sdram_dqm           ),
    .sdram_ras_n         ( sdram_ras_n         ),
    .sdram_cas_n         ( sdram_cas_n         ),
    .sdram_cke           ( sdram_cke           ),
    .sdram_we_n          ( sdram_we_n          ),
    .sdram_sel_n         ( sdram_sel_n         )
    );

  // sdram_model
  mt48lc4m16a2 #(
    .mem_sizes           ( 32*1024*1024        ),    // 64 MB for each chip
    .DEBUG               ( 0                   )     //       = 32*1024*1024*16/8
    ) u_mt48lc4m16a2a(
    .Dq                  ( sdram_dq[15:0]      ),
    .Addr                ( sdram_addr          ),
    .Ba                  ( sdram_bank_addr     ),
    .Clk                 ( sdram_clk           ),
    .Cke                 ( sdram_cke           ),
    .Cs_n                ( sdram_sel_n         ),
    .Ras_n               ( sdram_ras_n         ),
    .Cas_n               ( sdram_cas_n         ),
    .We_n                ( sdram_we_n          ),
    .Dqm                 ( sdram_dqm[1:0]      )
    );

  mt48lc4m16a2 #(
    .mem_sizes           ( 32*1024*1024        ),
    .DEBUG               ( 0                   )
    ) u_mt48lc4m16a2b(
    .Dq                  ( sdram_dq[31:16]     ),
    .Addr                ( sdram_addr          ),
    .Ba                  ( sdram_bank_addr     ),
    .Clk                 ( sdram_clk           ),
    .Cke                 ( sdram_cke           ),
    .Cs_n                ( sdram_sel_n         ),
    .Ras_n               ( sdram_ras_n         ),
    .Cas_n               ( sdram_cas_n         ),
    .We_n                ( sdram_we_n          ),
    .Dqm                 ( sdram_dqm[3:2]      )
    );


//*** INITIALIZE SDRAM *********************************************************

  reg [31 : 0]  dat_32bit ;

  integer mem_cnt ;
  integer ram0_fp ;
  integer ram0_tp ;

  initial begin
    ram0_fp = $fopen(`PROG_FILE,"rb");
    for(mem_cnt=0; mem_cnt<(MEMSIZE); mem_cnt=mem_cnt+1) begin
      ram0_tp = $fread(dat_32bit ,ram0_fp);
`ifdef BIG_ENDIAN_MIF
      u_mt48lc4m16a2a.Bank0[mem_cnt] = {dat_32bit[23:16], dat_32bit[31:24] };
      u_mt48lc4m16a2b.Bank0[mem_cnt] = {dat_32bit[07:00], dat_32bit[15:08] };
`else
      u_mt48lc4m16a2a.Bank0[mem_cnt] = {dat_32bit[15:08], dat_32bit[07:00] };
      u_mt48lc4m16a2b.Bank0[mem_cnt] = {dat_32bit[31:24], dat_32bit[23:16] };
`endif
    end
    // valid when use HIGHER ahb address-bits for sdram bank
  end


//*** AUTO CHECK ***************************************************************

  `ifdef AUTO_CHECK

    integer    fp_check_i   ;
    integer    fp_check_o   ;
    integer    tp_check     ;
    reg        result_check ;

    initial begin
      fp_check_i = $fopen( `CHECK_FILE_I , "r" );
      fp_check_o = $fopen( `CHECK_FILE_O , "r" );
      #(10*`FULL_CLK) ;
      $display( "\t\t auto check is on" );
      #(10*`FULL_CLK) ;

      tp_check = $fscanf( fp_check_o, "%x", result_check    );

      #`FULL_CLK ;
      $display( "\n\n*** CHECK FINISHED ! ***\n" );
      $fclose( fp_check_i );
      $fclose( fp_check_o );
      #(10*`FULL_CLK) ;
      $finish ;
    end

  `endif


//*** DISPLAY ******************************************************************

  `ifdef DISPLAY

    initial begin
      #(10*`FULL_CLK) ;
      $display( "\t\t display to i/o is on" );
    end

    initial begin
    end

  `endif


//*** DUMP FSDB ****************************************************************

  `ifdef DUMP_FSDB

    initial begin
      #`DUMP_TIME ;
      $fsdbDumpfile( `DUMP_FILE );
      $fsdbDumpvars( 0, tb_GFP );
      #(10*`FULL_CLK) ;
      $display( "\t\t dump to this test is on !\n" );
    end

  `endif


//*** FORCE_FINISH *************************************************************

  `ifdef FORCE_FINISH

    initial begin
      #`FINISH_TIME ;
      $finish ;
    end

  `endif


//*** OTHER TESTBENCH **********************************************************


endmodule
