`timescale 1ps/1ps

module AdcTb;

    `include "tb.vh"

    parameter           CLOCK_PERIOD_24             = 41666;
    parameter           CLOCK_PERIOD_50             = 20000;
    parameter           UUT_CLOCK_PERIOD            = 10000;    //  100 MHz
    parameter           ADC_DATA_CLOCK              = 1428;

    localparam          TOP_BULK_PACKET_WIDTH       = 16;           //  Packet width
    localparam          TOP_FX3_DQ_W                = 16;           //  FX3 bus width
    localparam          TOP_FX3_CONTROL_BIT_SIZE    = 2*8192;       //  FX3 control endpoint bit size
    localparam          TOP_FX3_BULK_BIT_SIZE       = 8192;         //  FX3 bulk endpoint bit size
    localparam          TOP_FX3_WR_WATERMARK        = 4;            //  FX3 write watermark value
    localparam          TOP_FX3_RD_WATERMARK        = 4;            //  FX3 read watermark value
    localparam  [1:0]   TOP_FX3_RD_ID0_ADDR         = 2'b00;        //  FX3 bus address for bulk ep. transfer
    localparam  [1:0]   TOP_FX3_RD_ID1_ADDR         = 2'b11;        //  FX3 bus address for control ep. transfer
    localparam          TOP_CMD_NUM                 = 32;           //  Must be equal to power of 2
    localparam          TOP_CONTROL_CMD_NUM         = 32;           //  Must be equal to power of 2
    localparam          TOP_CMD_ID_NORM             = 224;
    localparam          TOP_AUX_IN_TRIG_NUM         = 1;            //  Number of aux. input triggers
    localparam          TOP_AUX_OUT_TRIG_NUM        = 1;            //  Number of aux. output triggers
    localparam          TOP_MODULATOR_NUM           = 3;            //  Number of modulators
    localparam          TOP_PULSE_GEN_NUM           = 3;            //  Number of pulse generators
    localparam  [1:0]   TOP_FX3_WR_ID0_ADDR         = 2'b01;        //  FX3 bus address for bulk ep. transfer
    localparam  [1:0]   TOP_FX3_WR_ID1_ADDR         = 2'b10;        //  FX3 bus address for control ep. transfe
    localparam  [6:0]   ADC_CLOCK_PATTERN           = 7'b1111110;

    localparam          TOP_DSP_CH_NUM              = 8;            //  Number of input data channels
    localparam          TOP_DSP_IDAT_W              = 14;           //  Input data width
    localparam          TOP_DSP_IQ_W                = 14;           //  I and Q width
    localparam          TOP_DSP_OMULT_W             = 16;           //  sin window nultiplier output width
    localparam          TOP_DSP_ODAT_W              = 48;           //  Output data width
    localparam          TOP_DSP_EN_DEBUG            = "YES";        //  YES or NO

    reg                 test_clk_24mhz;
    reg                 test_clk_50mhz;

    wire                adc1_ctrl_sck_o;
    wire                adc1_ctrl_sdata_o;
    wire                adc1_ctrl_ss_o;
    wire                adc1_ctrl_reset_o;

    wire                adc2_ctrl_sck_o;
    wire                adc2_ctrl_sdata_o;
    wire                adc2_ctrl_ss_o;
    wire                adc2_ctrl_reset_o;

    wire                adc3_ctrl_sck_o;
    wire                adc3_ctrl_sdata_o;
    wire                adc3_ctrl_ss_o;
    wire                adc3_ctrl_reset_o;

    wire                adc4_ctrl_sck_o;
    wire                adc4_ctrl_sdata_o;
    wire                adc4_ctrl_ss_o;
    wire                adc4_ctrl_reset_o;

    wire                ref_clk_lmx_cs_o;
    wire                ref_clk_lmk_cs_o;
    wire                ref_clk_sck_o;
    wire                ref_clk_sdata_o;
    wire                ref_clk_lmx_lock_i;
    wire                ref_clk_switch_o;

    wire    [15:0]      mcb5_dram_dq;
    wire    [12:0]      mcb5_dram_a;
    wire    [2:0]       mcb5_dram_ba;
    wire                mcb5_dram_ras_n;
    wire                mcb5_dram_cas_n;
    wire                mcb5_dram_we_n;
    wire                mcb5_dram_odt;
    wire                mcb5_dram_reset_n;
    wire                mcb5_dram_cke;
    wire                mcb5_dram_dm;
    wire                mcb5_dram_udqs;
    wire                mcb5_dram_udqs_n;
    wire                mcb5_rzq;
    wire                mcb5_zio;
    wire                mcb5_dram_udm;
    wire                mcb5_dram_dqs;
    wire                mcb5_dram_dqs_n;
    wire                mcb5_dram_ck;
    wire                mcb5_dram_ck_n;
    wire    [15:0]      mcb1_dram_dq;
    wire    [12:0]      mcb1_dram_a;
    wire    [2:0]       mcb1_dram_ba;
    wire                mcb1_dram_ras_n;
    wire                mcb1_dram_cas_n;
    wire                mcb1_dram_we_n;
    wire                mcb1_dram_odt;
    wire                mcb1_dram_reset_n;
    wire                mcb1_dram_cke;
    wire                mcb1_dram_dm;
    wire                mcb1_dram_udqs;
    wire                mcb1_dram_udqs_n;
    wire                mcb1_rzq;
    wire                mcb1_zio;
    wire                mcb1_dram_udm;
    wire                mcb1_dram_dqs;
    wire                mcb1_dram_dqs_n;
    wire                mcb1_dram_ck;
    wire                mcb1_dram_ck_n;

    //  Cypress FX3

    wire                        fx3_pclk_o;
    wire                        fx3_slcs_o;
    wire                        fx3_slrd_o;
    wire                        fx3_slwr_o;
    wire                        fx3_sloe_o;
    wire                        fx3_pktend_o; 
    wire                        fx3_flaga_i;
    wire                        fx3_flagb_i;
    wire    [1:0]               fx3_addr_o;
    wire    [TOP_FX3_DQ_W-1:0]  fx3_dq_io;

    wire                        lo_sdata1_o;
    wire                        lo_sdata2_o;
    wire                        lo_cs_o;
    wire                        lo_sck_o;
    wire                        rf1_sdata1_o;
    wire                        rf1_sdata2_o;
    wire                        rf1_cs_o;
    wire                        rf1_sck_o;
    wire                        rf2_sdata1_o;
    wire                        rf2_sdata2_o;
    wire                        rf2_cs_o;
    wire                        rf2_sck_o;

    reg     [TOP_FX3_DQ_W-1:0]  fx3_ram_rd0_data_i;
    reg                         fx3_ram_rd0_val_i;
    wire                        fx3_ram_rd0_rdy_o;
    reg                         fx3_ram_rd0_eop_i;

    reg     [TOP_FX3_DQ_W-1:0]  fx3_ram_rd1_data_i;
    reg                         fx3_ram_rd1_val_i;
    wire                        fx3_ram_rd1_rdy_o;
    reg                         fx3_ram_rd1_eop_i;

    wire    [TOP_FX3_DQ_W-1:0]  fx3_ram_wr0_data_o;
    wire                        fx3_ram_wr0_val_o;
    reg                         fx3_ram_wr0_rdy_i;

    wire    [TOP_FX3_DQ_W-1:0]  fx3_ram_wr1_data_o;
    wire                        fx3_ram_wr1_val_o;
    reg                         fx3_ram_wr1_rdy_i;

    wire                        ext_clk_24mhz_gbl       = uut.ext_clk_24mhz_gbl;
    wire                        init_rst_signal         = uut.init_rst_signal;
    wire                        lmx_lmk_filtered_rst    = uut.lmx_lmk_filtered_rst;
    wire                        ddr3_mic_filtered_rst   = uut.ddr3_mic_filtered_rst;
    wire                        adc_done                = uut.adc_done;
    wire                        adc_rst                 = uut.adc_rst;
    wire                        adc_rst_done            = uut.adc_rst_done;
    wire                        adc_filtered_rst        = uut.adc_filtered_rst;
    wire                        adc_init_valid          = uut.adc_init_valid;
    wire                        main_pll_100_mhz_locked = uut.main_pll_100_mhz_locked;
    wire                        main_pll_rst_signal     = uut.main_pll_rst_signal;

    wire                        main_pll_100mhz         = uut.main_pll_100mhz;
    wire                        main_pll_locked         = uut.main_pll_locked;
    wire                        c1_calib_done           = uut.c1_calib_done;
    wire                        c5_calib_done           = uut.c5_calib_done;
    wire                        cmd_handler_ready       = uut.cmd_handler_ready;
/*
    wire    [735:0]             ddr3_mic_wrapper_data_i     = uut.ddr3_mic_wrapper_data_i ;
    wire    [22:0]              ddr3_mic_wrapper_valid_i    = uut.ddr3_mic_wrapper_valid_i;
    wire    [22:0]              ddr3_mic_wrapper_ready_o    = uut.ddr3_mic_wrapper_ready_o;

    wire    [31:0]              ch1_i                       = ddr3_mic_wrapper_data_i[703:672];       
    wire    [31:0]              ch1_q                       = ddr3_mic_wrapper_data_i[671:640];
    
    wire    [31:0]              ch2_i                       = ddr3_mic_wrapper_data_i[639:608];       
    wire    [31:0]              ch2_q                       = ddr3_mic_wrapper_data_i[607:576];       

    wire    [TOP_FX3_DQ_W-1:0]  out_stream_data_piped   = uut.out_stream_data_piped;
    wire                        out_stream_valid_piped  = uut.out_stream_valid_piped;
    wire                        out_stream_ready_piped  = uut.out_stream_ready_piped;
    wire                        out_stream_last_piped   = uut.out_stream_last_piped;
    wire                        out_stream_id_piped     = uut.out_stream_id_piped;
    wire    [3:0]               sm_curr_state           = uut.cmd_handler_inst.sm_curr_state;

    wire                        lo_init_done    = uut.lo_init_done;
    wire                        lo_done         = uut.lo_done;
    wire                        rf1_init_done   = uut.rf1_init_done;
    wire                        rf1_done        = uut.rf1_done;
    wire                        rf2_init_done   = uut.rf2_init_done;
    wire                        rf2_done        = uut.rf2_done;
    wire    [15:0]              rf1_data        = uut.rf1_data;
    wire                        rf1_valid       = uut.rf1_valid;
    wire    [15:0]              rf2_data        = uut.rf2_data;
    wire                        rf2_valid       = uut.rf2_valid;

    wire    [7:0]                                   cmd_ffe1_logic_channel_o                = uut.cmd_ffe1_logic_channel_o;
    wire    [7:0]                                   cmd_ffe1_mode_o                         = uut.cmd_ffe1_mode_o;
    wire    [31:0]                                  cmd_ffe1_filter_band_o                  = uut.cmd_ffe1_filter_band_o;
    wire    [31:0]                                  cmd_ffe1_meas_num_o                     = uut.cmd_ffe1_meas_num_o;
    wire    [31:0]                                  cmd_ffe1_meas_delay_o                   = uut.cmd_ffe1_meas_delay_o;
    wire    [31:0]                                  cmd_ffe1_meas_period_o                  = uut.cmd_ffe1_meas_period_o;
    wire    [7:0]                                   cmd_ffe1_analog_filter_o                = uut.cmd_ffe1_analog_filter_o;
    wire    [7:0]                                   cmd_ffe1_set_ftw_o                      = uut.cmd_ffe1_set_ftw_o;
    wire    [31:0]                                  cmd_ffe1_demod_ftw_o                    = uut.cmd_ffe1_demod_ftw_o;
    wire                                            cmd_ffe1_new_flag_o                     = uut.cmd_ffe1_new_flag_o;

    wire    [31:0]                                  filter_meas_width_o                     = uut.filter_meas_width_o;
    wire    [31:0]                                  filter_phase_inc_o                      = uut.filter_phase_inc_o;
    wire    [31:0]                                  filter_norm_value_o                     = uut.filter_norm_value_o;
    wire                                            filter_data_valid_o                     = uut.filter_data_valid_o;

    wire    [TOP_DSP_CH_NUM*32-1:0]                 fp_dsp_data_i_o                         = uut.fp_dsp_data_i_o;
    wire    [TOP_DSP_CH_NUM*32-1:0]                 fp_dsp_data_q_o                         = uut.fp_dsp_data_q_o;
    wire    [TOP_DSP_CH_NUM-1:0]                    fp_dsp_valid_i_o                        = uut.fp_dsp_valid_i_o;
    wire    [TOP_DSP_CH_NUM-1:0]                    fp_dsp_valid_q_o                        = uut.fp_dsp_valid_q_o;
/*
    wire    [15:0]                                  cmd_fff7_rf_data_o                      = uut.cmd_fff7_rf_data_o;
    wire                                            cmd_fff7_rf_valid_o                     = uut.cmd_fff7_rf_valid_o;
    wire                                            cmd_fff7_new_flag_o                     = uut.cmd_fff7_new_flag_o;

    wire    [15:0]                                  cmd_fff8_rf_data_o                      = uut.cmd_fff8_rf_data_o;
    wire                                            cmd_fff8_rf_valid_o                     = uut.cmd_fff8_rf_valid_o;
    wire                                            cmd_fff8_new_flag_o                     = uut.cmd_fff8_new_flag_o;

    wire    [31:0]                                  cmd_fffc_delay_code_o                   = uut.cmd_fffc_delay_code_o;
    wire    [7:0]                                   cmd_fffc_port_o                         = uut.cmd_fffc_port_o;
    wire    [7:0]                                   cmd_fffc_rf_load_mask_o                 = uut.cmd_fffc_rf_load_mask_o;
    wire    [31:0]                                  cmd_fffc_port_switch_delay_o            = uut.cmd_fffc_port_switch_delay_o;
    wire                                            cmd_fffc_new_flag_o                     = uut.cmd_fffc_new_flag_o;
    wire                                            cmd_fffc_port_switch_flag_o             = uut.cmd_fffc_port_switch_flag_o;
    wire    [3:0]                                   cmd_fffc_curr_port_o                    = uut.cmd_fffc_curr_port_o;
    wire    [31:0]                                  cmd_fffc_curr_delay_o                   = uut.cmd_fffc_curr_delay_o;

    wire    [15:0]                                  cmd_meas_lo_data_o                      = uut.cmd_meas_lo_data_o;
    wire                                            cmd_meas_lo_valid_o                     = uut.cmd_meas_lo_valid_o;
    wire    [15:0]                                  cmd_meas_rf_data_o                      = uut.cmd_meas_rf_data_o;
    wire                                            cmd_meas_rf_valid_o                     = uut.cmd_meas_rf_valid_o;
    wire                                            cmd_meas_new_flag_o                     = uut.cmd_meas_new_flag_o;

    wire    [TOP_FX3_DQ_W-1:0]                      cmd_demuxed_meas_data                   = uut.cmd_demuxed_meas_data ;
    wire                                            cmd_demuxed_meas_valid                  = uut.cmd_demuxed_meas_valid;
    wire                                            cmd_demuxed_meas_last                   = uut.cmd_demuxed_meas_last ;

    wire    [TOP_FX3_DQ_W-1:0]                      cmd_handler_m_data_o                    = uut.cmd_handler_m_data_o;
    wire                                            cmd_handler_m_valid_o                   = uut.cmd_handler_m_valid_o;
    wire                                            cmd_handler_m_ready_i                   = uut.cmd_handler_m_ready_i;
    wire                                            cmd_handler_m_last_o                    = uut.cmd_handler_m_last_o;
    wire    [7:0]                                   cmd_handler_m_id_o                      = uut.cmd_handler_m_id_o;

    wire                                            cmd_handler_block_req_o                 = uut.cmd_handler_block_req_o;
    wire    [2:0]                                   cmd_handler_block_mask_o                = uut.cmd_handler_block_mask_o;
    wire                                            cmd_handler_block_ack_i                 = uut.cmd_handler_block_ack_i;
    wire                                            cmd_handler_meas_req_o                  = uut.cmd_handler_meas_req_o;
    wire                                            cmd_handler_meas_ack_i                  = uut.cmd_handler_meas_ack_i;
    wire                                            cmd_handler_ans_req_o                   = uut.cmd_handler_ans_req_o;
    wire                                            cmd_handler_ans_ack_i                   = uut.cmd_handler_ans_ack_i;
    wire    [31:0]                                  cmd_handler_cmd_head_o                  = uut.cmd_handler_cmd_head_o;
    wire    [15:0]                                  cmd_handler_cmd_data_o                  = uut.cmd_handler_cmd_data_o;

    wire                                            cmd_handler_perm_before_meas_i          = uut.cmd_handler_perm_before_meas_i;
    wire                                            cmd_handler_perm_after_meas_i           = uut.cmd_handler_perm_after_meas_i;
    wire                                            cmd_handler_perm_after_sweep_i          = uut.cmd_handler_perm_after_sweep_i;
    wire                                            cmd_handler_event_meas_req_o            = uut.cmd_handler_event_meas_req_o;
    wire                                            cmd_handler_event_before_meas_o         = uut.cmd_handler_event_before_meas_o;
    wire                                            cmd_handler_event_after_meas_o          = uut.cmd_handler_event_after_meas_o;
    wire                                            cmd_handler_event_sweep_end_o           = uut.cmd_handler_event_sweep_end_o;
*/

/*
always @(negedge fx3_pclk_o) begin
    if (cmd_ffe1_new_flag_o) begin
        $display("cmd_ffe1_logic_channel_o      = %h", cmd_ffe1_logic_channel_o);
        $display("cmd_ffe1_mode_o               = %h", cmd_ffe1_mode_o);
        $display("cmd_ffe1_filter_band_o        = %h", cmd_ffe1_filter_band_o);
        $display("cmd_ffe1_meas_num_o           = %h", cmd_ffe1_meas_num_o);
        $display("cmd_ffe1_meas_delay_o         = %h", cmd_ffe1_meas_delay_o);
        $display("cmd_ffe1_meas_period_o        = %h", cmd_ffe1_meas_period_o);
        $display("cmd_ffe1_analog_filter_o      = %h", cmd_ffe1_analog_filter_o);
        $display("cmd_ffe1_set_ftw_o            = %h", cmd_ffe1_set_ftw_o);
        $display("cmd_ffe1_demod_ftw_o          = %h", cmd_ffe1_demod_ftw_o);
    end
end

always @(negedge fx3_pclk_o) begin
    if (cmd_fffc_new_flag_o) begin
        $display("cmd_fffc_delay_code_o         = %h", cmd_fffc_delay_code_o);
        $display("cmd_fffc_port_o               = %h", cmd_fffc_port_o);
        $display("cmd_fffc_rf_load_mask_o       = %h", cmd_fffc_rf_load_mask_o);
        $display("cmd_fffc_port_switch_delay_o  = %h", cmd_fffc_port_switch_delay_o);
        $display("cmd_fffc_port_switch_flag_o   = %h", cmd_fffc_port_switch_flag_o);
        $display("cmd_fffc_curr_port_o          = %h", cmd_fffc_curr_port_o);
        $display("cmd_fffc_curr_delay_o         = %h", cmd_fffc_curr_delay_o);
    end
end    

always @(negedge fx3_pclk_o) begin
    if (cmd_fff7_rf_valid_o) begin
        $display("FFF7 data                     = %h", cmd_fff7_rf_data_o);
    end
end

always @(negedge fx3_pclk_o) begin
    if (cmd_fff8_rf_valid_o) begin
        $display("FFF8 data                     = %h", cmd_fff8_rf_data_o);
    end
end

always @(negedge fx3_pclk_o) begin
    if (cmd_meas_lo_valid_o) begin
        $display("MEAS LO DATA                  = %h", cmd_meas_lo_data_o);
    end

    if (cmd_meas_rf_valid_o) begin
        $display("MEAS RF DATA                  = %h", cmd_meas_rf_data_o);
    end

end
*/

    integer fid0_in;
    integer fid1_in;
    integer len;
    integer i;

    assign  ref_clk_lmx_lock_i  = 1'b0;

    task automatic read_data;
        input   integer         fid;
        output  reg     [15:0]  data;
        output  integer         len;
        begin
            len = $fread(data, fid);
        end
    endtask

c3420_main uut(
    .ext_clk_24mhz_i        (test_clk_24mhz),

    .adc1_ctrl_sck_o        (adc1_ctrl_sck_o),
    .adc1_ctrl_sdata_o      (adc1_ctrl_sdata_o),
    .adc1_ctrl_ss_o         (adc1_ctrl_ss_o),
/*
    .adc1_ctrl_gain_a_o     (),
    .adc1_ctrl_gain_b_o     (),
    .adc1_ctrl_filter_o     (),
    .adc1_ctrl_dither_o     (),
*/
    .adc1_ctrl_reset_o      (adc1_ctrl_reset_o),

    .adc1_fclk_i_p          (test_clk_50mhz),
    .adc1_fclk_i_n          (~test_clk_50mhz),
    .adc1_ch_a0_i_p         (),
    .adc1_ch_a0_i_n         (),
    .adc1_ch_a1_i_p         (),
    .adc1_ch_a1_i_n         (),
    .adc1_ch_b0_i_p         (),
    .adc1_ch_b0_i_n         (),
    .adc1_ch_b1_i_p         (),
    .adc1_ch_b1_i_n         (),

    .adc2_ctrl_sck_o        (adc2_ctrl_sck_o),
    .adc2_ctrl_sdata_o      (adc2_ctrl_sdata_o),
    .adc2_ctrl_ss_o         (adc2_ctrl_ss_o),
/*
    .adc2_ctrl_gain_a_o     (),
    .adc2_ctrl_gain_b_o     (),
    .adc2_ctrl_filter_o     (),
    .adc2_ctrl_dither_o     (),
*/
    .adc2_ctrl_reset_o      (adc2_ctrl_reset_o),
/*
    .adc2_ch_a0_i_p         (),
    .adc2_ch_a0_i_n         (),
    .adc2_ch_a1_i_p         (),
    .adc2_ch_a1_i_n         (),
    .adc2_ch_b0_i_p         (),
    .adc2_ch_b0_i_n         (),
    .adc2_ch_b1_i_p         (),
    .adc2_ch_b1_i_n         (),
*/
    .adc3_ctrl_sck_o        (adc3_ctrl_sck_o),
    .adc3_ctrl_sdata_o      (adc3_ctrl_sdata_o),
    .adc3_ctrl_ss_o         (adc3_ctrl_ss_o),
/*
    .adc3_ctrl_gain_a_o     (),
    .adc3_ctrl_gain_b_o     (),
    .adc3_ctrl_filter_o     (),
    .adc3_ctrl_dither_o     (),
*/
    .adc3_ctrl_reset_o      (adc3_ctrl_reset_o),

    .adc3_fclk_i_p          (test_clk_50mhz),
    .adc3_fclk_i_n          (~test_clk_50mhz),

    .adc3_ch_a0_i_p         (1'b1),
    .adc3_ch_a0_i_n         (1'b0),
    .adc3_ch_a1_i_p         (1'b0),
    .adc3_ch_a1_i_n         (1'b1),
    .adc3_ch_b0_i_p         (1'b1),
    .adc3_ch_b0_i_n         (1'b0),
    .adc3_ch_b1_i_p         (1'b1),
    .adc3_ch_b1_i_n         (1'b0),

    .adc4_ctrl_sck_o        (adc4_ctrl_sck_o),
    .adc4_ctrl_sdata_o      (adc4_ctrl_sdata_o),
    .adc4_ctrl_ss_o         (adc4_ctrl_ss_o),
/*
    .adc4_ctrl_gain_a_o     (),
    .adc4_ctrl_gain_b_o     (),
    .adc4_ctrl_filter_o     (),
    .adc4_ctrl_dither_o     (),
*/
    .adc4_ctrl_reset_o      (adc4_ctrl_reset_o),
/*
    .adc4_fclk_i_p          (),
    .adc4_fclk_i_n          (),
    .adc4_ch_a0_i_p         (),
    .adc4_ch_a0_i_n         (),
    .adc4_ch_a1_i_p         (),
    .adc4_ch_a1_i_n         (),
    .adc4_ch_b0_i_p         (),
    .adc4_ch_b0_i_n         (),
    .adc4_ch_b1_i_p         (),
    .adc4_ch_b1_i_n         (),
*/
    .pg_pulse0_o            (),
    .pg_pulse1_o            (),
    .pg_pulse2_o            (),
    .pg_pulse3_o            (),

    .mod_pulse0_o           (),
    .mod_pulse1_o           (),

    .ref_clk_lmx_cs_o       (ref_clk_lmx_cs_o),
    .ref_clk_lmk_cs_o       (ref_clk_lmk_cs_o),
    .ref_clk_sck_o          (ref_clk_sck_o),
    .ref_clk_sdata_o        (ref_clk_sdata_o),
    .ref_clk_lmx_lock_i     (ref_clk_lmx_lock_i),
    .ref_clk_switch_o       (ref_clk_switch_o),

    .ref_clk_i2c_scl_o      (),
    .ref_clk_i2c_sda_io     (),

    .mcb5_dram_dq           (mcb5_dram_dq),
    .mcb5_dram_a            (mcb5_dram_a),
    .mcb5_dram_ba           (mcb5_dram_ba),
    .mcb5_dram_ras_n        (mcb5_dram_ras_n),
    .mcb5_dram_cas_n        (mcb5_dram_cas_n),
    .mcb5_dram_we_n         (mcb5_dram_we_n),
    .mcb5_dram_odt          (mcb5_dram_odt),
    .mcb5_dram_reset_n      (mcb5_dram_reset_n),
    .mcb5_dram_cke          (mcb5_dram_cke),
    .mcb5_dram_dm           (mcb5_dram_dm),
    .mcb5_dram_udqs         (mcb5_dram_udqs),
    .mcb5_dram_udqs_n       (mcb5_dram_udqs_n),
    .mcb5_rzq               (mcb5_rzq),
    .mcb5_zio               (mcb5_zio),
    .mcb5_dram_udm          (mcb5_dram_udm),
    .mcb5_dram_dqs          (mcb5_dram_dqs),
    .mcb5_dram_dqs_n        (mcb5_dram_dqs_n),
    .mcb5_dram_ck           (mcb5_dram_ck),
    .mcb5_dram_ck_n         (mcb5_dram_ck_n),

    .mcb1_dram_dq           (mcb1_dram_dq),
    .mcb1_dram_a            (mcb1_dram_a),
    .mcb1_dram_ba           (mcb1_dram_ba),
    .mcb1_dram_ras_n        (mcb1_dram_ras_n),
    .mcb1_dram_cas_n        (mcb1_dram_cas_n),
    .mcb1_dram_we_n         (mcb1_dram_we_n),
    .mcb1_dram_odt          (mcb1_dram_odt),
    .mcb1_dram_reset_n      (mcb1_dram_reset_n),
    .mcb1_dram_cke          (mcb1_dram_cke),
    .mcb1_dram_dm           (mcb1_dram_dm),
    .mcb1_dram_udqs         (mcb1_dram_udqs),
    .mcb1_dram_udqs_n       (mcb1_dram_udqs_n),
    .mcb1_rzq               (mcb1_rzq),
    .mcb1_zio               (mcb1_zio),
    .mcb1_dram_udm          (mcb1_dram_udm),
    .mcb1_dram_dqs          (mcb1_dram_dqs),
    .mcb1_dram_dqs_n        (mcb1_dram_dqs_n),
    .mcb1_dram_ck           (mcb1_dram_ck),
    .mcb1_dram_ck_n         (mcb1_dram_ck_n),

    .fx3_pclk_o             (fx3_pclk_o),
    .fx3_slcs_o             (fx3_slcs_o),
    .fx3_slrd_o             (fx3_slrd_o),
    .fx3_slwr_o             (fx3_slwr_o),
    .fx3_sloe_o             (fx3_sloe_o),
    .fx3_pktend_o           (fx3_pktend_o), 
    .fx3_flaga_i            (fx3_flaga_i),
    .fx3_flagb_i            (fx3_flagb_i),
    .fx3_addr_o             (fx3_addr_o),
    .fx3_dq_io              (fx3_dq_io),

    .lo_sdata1_o            (lo_sdata1_o),
    .lo_sdata2_o            (lo_sdata2_o),
    .lo_cs_o                (lo_cs_o),
    .lo_sck_o               (lo_sck_o),
    .rf1_sdata1_o           (rf1_sdata1_o),
    .rf1_sdata2_o           (rf1_sdata2_o),
    .rf1_cs_o               (rf1_cs_o),
    .rf1_sck_o              (rf1_sck_o),
    .rf2_sdata1_o           (rf2_sdata1_o),
    .rf2_sdata2_o           (rf2_sdata2_o),
    .rf2_cs_o               (rf2_cs_o),
    .rf2_sck_o              (rf2_sck_o)
);

fx3_slfifo_model #(
    .DQ_W           (TOP_FX3_DQ_W),             //
    .RD_IDO_WM      (TOP_FX3_RD_WATERMARK),     //
    .RD_ID1_WM      (TOP_FX3_RD_WATERMARK),     //
    .WR_ID0_WM      (TOP_FX3_WR_WATERMARK),     //
    .WR_ID1_WM      (TOP_FX3_WR_WATERMARK),     //
    .RD_ID0_ADDR    (TOP_FX3_RD_ID0_ADDR),      //
    .RD_ID1_ADDR    (TOP_FX3_RD_ID1_ADDR),      //
    .WR_ID0_ADDR    (TOP_FX3_WR_ID0_ADDR),      //
    .WR_ID1_ADDR    (TOP_FX3_WR_ID1_ADDR),      // 
    .CLOCK_PERIOD   (10000)                     //  10000 ps <-> 100 MHz
) fx3_slfifo_model_inst (
    //  FX3 ports
    .PCLK               (fx3_pclk_o),
    .SLCS               (fx3_slcs_o),
    .SLRD               (fx3_slrd_o),
    .SLOE               (fx3_sloe_o),
    .SLWR               (fx3_slwr_o),
    .A                  (fx3_addr_o),
    .DQ                 (fx3_dq_io),
    .FLAGA              (fx3_flaga_i),
    .FLAGB              (fx3_flagb_i),
    .PKTEND             (fx3_pktend_o),

    .ram_rd0_data_i     (fx3_ram_rd0_data_i),
    .ram_rd0_val_i      (fx3_ram_rd0_val_i),
    .ram_rd0_rdy_o      (fx3_ram_rd0_rdy_o),
    .ram_rd0_eop_i      (fx3_ram_rd0_eop_i),

    .ram_rd1_data_i     (fx3_ram_rd1_data_i),
    .ram_rd1_val_i      (fx3_ram_rd1_val_i),
    .ram_rd1_rdy_o      (fx3_ram_rd1_rdy_o),
    .ram_rd1_eop_i      (fx3_ram_rd1_eop_i),

    .ram_wr0_data_o     (fx3_ram_wr0_data_o),
    .ram_wr0_val_o      (fx3_ram_wr0_val_o),
    .ram_wr0_rdy_i      (fx3_ram_wr0_rdy_i),

    .ram_wr1_data_o     (fx3_ram_wr1_data_o),
    .ram_wr1_val_o      (fx3_ram_wr1_val_o),
    .ram_wr1_rdy_i      (fx3_ram_wr1_rdy_i)
);

always @(negedge fx3_pclk_o) begin
    if (fx3_ram_wr0_val_o) begin
        $display("FX3 ID0 WR DATA   = %h", {fx3_ram_wr0_data_o[7:0], fx3_ram_wr0_data_o[15:8]});
    end

    if (fx3_ram_wr1_val_o) begin
        $display("FX3 ID1 WR DATA   = %h", fx3_ram_wr1_data_o);
    end
end

    ddr3_model_c5 u_mem_c5(
        .ck         (mcb5_dram_ck),
        .ck_n       (mcb5_dram_ck_n),
        .cke        (mcb5_dram_cke),
        .cs_n       (1'b0),
        .ras_n      (mcb5_dram_ras_n),
        .cas_n      (mcb5_dram_cas_n),
        .we_n       (mcb5_dram_we_n),
        .dm_tdqs    ({mcb5_dram_udm,mcb5_dram_dm}),
        .ba         (mcb5_dram_ba),
        .addr       (mcb5_dram_a),
        .dq         (mcb5_dram_dq),
        .dqs        ({mcb5_dram_udqs,mcb5_dram_dqs}),
        .dqs_n      ({mcb5_dram_udqs_n,mcb5_dram_dqs_n}),
        .tdqs_n     (),
        .odt        (mcb5_dram_odt),
        .rst_n      (mcb5_dram_reset_n)
        );

    ddr3_model_c1 u_mem_c1(
        .ck         (mcb1_dram_ck),
        .ck_n       (mcb1_dram_ck_n),
        .cke        (mcb1_dram_cke),
        .cs_n       (1'b0),
        .ras_n      (mcb1_dram_ras_n),
        .cas_n      (mcb1_dram_cas_n),
        .we_n       (mcb1_dram_we_n),
        .dm_tdqs    ({mcb1_dram_udm,mcb1_dram_dm}),
        .ba         (mcb1_dram_ba),
        .addr       (mcb1_dram_a),
        .dq         (mcb1_dram_dq),
        .dqs        ({mcb1_dram_udqs,mcb1_dram_dqs}),
        .dqs_n      ({mcb1_dram_udqs_n,mcb1_dram_dqs_n}),
        .tdqs_n     (),
        .odt        (mcb1_dram_odt),
        .rst_n      (mcb1_dram_reset_n)
        );

reg [31:0]  data_buf;
integer     data_cnt;

initial begin
    fid0_in             = $fopen("./src/tb/in_data.bin", "rb");
    fid1_in             = $fopen("./src/tb/in_control_data.bin", "rb");

    data_cnt            = 0;

    fx3_ram_rd0_data_i  = 0;
    fx3_ram_rd0_val_i   = 0;
    fx3_ram_rd0_eop_i   = 0;
    fx3_ram_rd1_data_i  = 0;
    fx3_ram_rd1_val_i   = 0;
    fx3_ram_rd1_eop_i   = 0;
    fx3_ram_wr0_rdy_i   = 1;
    fx3_ram_wr1_rdy_i   = 1;

    //  rd1

    wait (fx3_pclk_o);
    #(UUT_CLOCK_PERIOD*20);

    @(posedge fx3_pclk_o) begin
        fx3_ram_rd1_val_i   = 1'b1;
        read_data(fid1_in, fx3_ram_rd1_data_i, len);
    end

    repeat(CONTROL_DATA_NUM-2) begin
        #(UUT_CLOCK_PERIOD/2);
        wait(fx3_ram_rd1_rdy_o);
        @(posedge fx3_pclk_o) begin
            fx3_ram_rd1_val_i   = 1'b1;
            read_data(fid1_in, fx3_ram_rd1_data_i, len);
        end
    end

    #(UUT_CLOCK_PERIOD/2);
    wait(fx3_ram_rd1_rdy_o);
    @(posedge fx3_pclk_o) begin
        fx3_ram_rd1_val_i   = 1'b1;
        fx3_ram_rd1_eop_i   = 1'b1;
        read_data(fid1_in, fx3_ram_rd1_data_i, len);
    end

    #(UUT_CLOCK_PERIOD/2);
    wait(fx3_ram_rd1_rdy_o);
    @(posedge fx3_pclk_o) begin
        fx3_ram_rd1_val_i   = 1'b0;
        fx3_ram_rd1_eop_i   = 1'b0;
        fx3_ram_rd1_data_i  = 16'b0;
    end

    //  End rd1

    #(UUT_CLOCK_PERIOD*20);

    wait (fx3_pclk_o);
    #(UUT_CLOCK_PERIOD*20);

    @(posedge fx3_pclk_o) begin
        fx3_ram_rd0_val_i   = 1'b1;
        read_data(fid0_in, fx3_ram_rd0_data_i, len);
    end

    repeat(BULK_DATA_NUM-2) begin
        #(UUT_CLOCK_PERIOD/2);
        wait(fx3_ram_rd0_rdy_o);
        @(posedge fx3_pclk_o) begin
            fx3_ram_rd0_val_i   = 1'b1;
            read_data(fid0_in, fx3_ram_rd0_data_i, len);
        end
    end

    #(UUT_CLOCK_PERIOD/2);
    wait(fx3_ram_rd0_rdy_o);
    @(posedge fx3_pclk_o) begin
        fx3_ram_rd0_val_i   = 1'b1;
        fx3_ram_rd0_eop_i   = 1'b1;
        read_data(fid0_in, fx3_ram_rd0_data_i, len);
    end

    #(UUT_CLOCK_PERIOD/2);
    wait(fx3_ram_rd0_rdy_o);
    @(posedge fx3_pclk_o) begin
        fx3_ram_rd0_val_i   = 1'b0;
        fx3_ram_rd0_eop_i   = 1'b0;
        fx3_ram_rd0_data_i  = 16'b0;
    end

end

initial begin
    test_clk_24mhz  = 1'b0;
    forever begin
        #(CLOCK_PERIOD_24/2) test_clk_24mhz = ~test_clk_24mhz;
    end
end

initial begin
    test_clk_50mhz  = 1'b1;
    forever begin
        #(CLOCK_PERIOD_50/2) test_clk_50mhz = ~test_clk_50mhz;
    end
end

endmodule