//-------------------------------------------------------------------
//
//  Filename      : GFP.v
//  Author        : Huang Lei Lei
//  Created       : 2015-09-09
//  Description   : module general fpga platform
//
//-------------------------------------------------------------------

`include "GFP_defines.v"

module GFP(
  // clk & rst i
  clk                   ,
  rstn                  ,
  // clk & rst o
  sys_clk               ,
  sys_rst               ,
  // rd
  rd_ena_i              ,
  rd_adr_i              ,
  rd_dat_o              ,
  rd_ack_o              ,
  // wr
  wr_ena_i              ,
  wr_adr_i              ,
  wr_byt_i              ,
  wr_dat_i              ,
  wr_ack_o              ,
  // sdram
  sdram_clk             ,
  sdram_addr            ,
  sdram_dq              ,
  sdram_bank_addr       ,
  sdram_dqm             ,
  sdram_ras_n           ,
  sdram_cas_n           ,
  sdram_cke             ,
  sdram_we_n            ,
  sdram_sel_n           ,
  );


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

  parameter    AXI_DW       = 64                ,
               AXI_AW       = 32                ,
               AXI_MIDW     = 4                 ,
               AXI_SIDW     = 8                 ;

  parameter    AXI_WID      = 0                 ,
               AXI_RID      = 0                 ;


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

  // clk & rst oI
  input                     clk                 ;
  input                     rstn                ;

  // clk & rst o
  output                    sys_clk             ;
  output                    sys_rst             ;

  // rd
  input                     rd_ena_i            ;
  input   [31       : 0]    rd_adr_i            ;
  output  [63       : 0]    rd_dat_o            ;
  output                    rd_ack_o            ;
  // wr
  input                     wr_ena_i            ;
  input   [31       : 0]    wr_adr_i            ;
  input   [7        : 0]    wr_byt_i            ;
  input   [63       : 0]    wr_dat_i            ;
  output                    wr_ack_o            ;

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


//*** WIRE DECLARATION *********************************************************

  // gen_m
  wire  [AXI_AW-1   : 0]    gen_m_rd_maddr      , gen_m_wr_maddr      ;
  wire  [1          : 0]    gen_m_rd_mburst     , gen_m_wr_mburst     ;
  wire  [3          : 0]    gen_m_rd_mcache     , gen_m_wr_mcache     ;
  wire  [AXI_DW-1   : 0]    gen_m_rd_mdata      , gen_m_wr_mdata      ;
  wire  [AXI_MIDW-1 : 0]    gen_m_rd_mid        , gen_m_wr_mid        ;
  wire  [3          : 0]    gen_m_rd_mlen       , gen_m_wr_mlen       ;
  wire                      gen_m_rd_mlock      , gen_m_wr_mlock      ;
  wire  [2          : 0]    gen_m_rd_mprot      , gen_m_wr_mprot      ;
  wire                                            gen_m_wr_mread      ;
  reg                       gen_m_rd_mread      ; 
  wire                      gen_m_rd_mready     , gen_m_wr_mready     ;
  wire  [2          : 0]    gen_m_rd_msize      , gen_m_wr_msize      ;
  wire                      gen_m_rd_mwrite     , gen_m_wr_mwrite     ;
  wire  [AXI_DW/8-1 : 0]    gen_m_rd_mwstrb     , gen_m_wr_mwstrb     ;
  wire                      gen_m_rd_saccept    , gen_m_wr_saccept    ;
  wire  [AXI_DW-1   : 0]    gen_m_rd_sdata      , gen_m_wr_sdata      ;
  wire  [AXI_MIDW-1 : 0]    gen_m_rd_sid        , gen_m_wr_sid        ;
  wire                      gen_m_rd_slast      , gen_m_wr_slast      ;
  wire  [2          : 0]    gen_m_rd_sresp      , gen_m_wr_sresp      ;
  wire                      gen_m_rd_svalid     , gen_m_wr_svalid     ;

  reg                                             rd_flag             ;

  // sdram ctrl_line
  wire  [3          : 0]    sdram_dout_valid    ;
  wire  [31         : 0]    sdram_rd_data       ;
  wire  [31         : 0]    sdram_wr_data       ;

  // rstn
  wire                      sys_rstn            ;


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

//*** GLOBAL *************************************

  assign sys_rstn = !sys_rst  ;


//*** RD2GENAXI **********************************

  assign gen_m_rd_maddr  = rd_adr_i ;
  assign gen_m_rd_mburst = 2'b01    ;
  assign gen_m_rd_mcache = 4'b0000  ;
  assign gen_m_rd_mdata  = 0        ;
  assign gen_m_rd_mid    = AXI_RID  ;
  assign gen_m_rd_mlen   = 0        ;
  assign gen_m_rd_mlock  = 0        ;
  assign gen_m_rd_mprot  = 3'b000   ;
  assign gen_m_rd_mready = 1        ;
  assign gen_m_rd_msize  = 3'b011   ;
  assign gen_m_rd_mwrite = 0        ;
  assign gen_m_rd_mwstrb = 8'hff    ;

  always @(posedge sys_clk or negedge sys_rstn ) begin
    if( !sys_rstn )
      gen_m_rd_mread <= 0 ;
    else if( gen_m_rd_mread & gen_m_rd_saccept )
      gen_m_rd_mread <= 0 ;
    else if( rd_ena_i & rd_flag ) begin
      gen_m_rd_mread <= 1 ;
    end
  end

  always @(posedge sys_clk or negedge sys_rstn ) begin
    if( !sys_rstn )
      rd_flag <= 1 ;
    else if( gen_m_rd_mread )
      rd_flag <= 0 ;
    else if( gen_m_rd_svalid ) begin
      rd_flag <= 1 ;
    end
  end

  assign rd_ack_o = gen_m_rd_svalid ;
  assign rd_dat_o = gen_m_rd_sdata  ;


//*** WR2GENAXI **********************************

  assign gen_m_wr_maddr  = wr_adr_i  ;
  assign gen_m_wr_mburst = 2'b01     ;
  assign gen_m_wr_mcache = 4'b0000   ;
  assign gen_m_wr_mdata  = wr_dat_i  ;
  assign gen_m_wr_mid    = AXI_WID   ;
  assign gen_m_wr_mlen   = 0         ;
  assign gen_m_wr_mlock  = 0         ;
  assign gen_m_wr_mprot  = 3'b000    ;
  assign gen_m_wr_mread  = 0         ;
  assign gen_m_wr_mready = 1         ;
  assign gen_m_wr_msize  = 3'b011    ;
  assign gen_m_wr_mwrite = wr_ena_i  ;
  assign gen_m_wr_mwstrb = wr_byt_i  ;

  assign wr_ack_o = gen_m_wr_saccept & gen_m_wr_mwrite ;


//*** CLKGEN *************************************

  GFP_clkgen GFP_clkgen0(
    // clk&rst in
    .board_clk                ( clk                 ),
    .board_rst                (!rstn                ),
    // clk&rst out
    .sys_clk                  ( sys_clk             ),
    .sys_rst                  ( sys_rst             )
    );

  assign sdram_clk = sys_clk ;


//*** AXI BUS ************************************

  axi u_axi_bus(
    // clk & rstn
    .ACLK_aclk                ( sys_clk             ),
    .ARESETn_aresetn          (!sys_rst             ),
    .HCLK_hclk                ( sys_clk             ),
    .HRESETn_hresetn          (!sys_rst             ),
    // remap
    .i_axi_remap_n            ( 1                   ),
    // clk enable
    .gm_rd_gclken             ( 1                   ),
    .gm_wr_gclken             ( 1                   ),
    // gen master
    .gen_m_rd_maddr           ( gen_m_rd_maddr      ),
    .gen_m_rd_mburst          ( gen_m_rd_mburst     ),
    .gen_m_rd_mcache          ( gen_m_rd_mcache     ),
    .gen_m_rd_mdata           ( gen_m_rd_mdata      ),
    .gen_m_rd_mid             ( gen_m_rd_mid        ),
    .gen_m_rd_mlen            ( gen_m_rd_mlen       ),
    .gen_m_rd_mlock           ( gen_m_rd_mlock      ),
    .gen_m_rd_mprot           ( gen_m_rd_mprot      ),
    .gen_m_rd_mread           ( gen_m_rd_mread      ),
    .gen_m_rd_mready          ( gen_m_rd_mready     ),
    .gen_m_rd_msize           ( gen_m_rd_msize      ),
    .gen_m_rd_mwrite          ( gen_m_rd_mwrite     ),
    .gen_m_rd_mwstrb          ( gen_m_rd_mwstrb     ),
    .gen_m_rd_saccept         ( gen_m_rd_saccept    ),
    .gen_m_rd_sdata           ( gen_m_rd_sdata      ),
    .gen_m_rd_sid             ( gen_m_rd_sid        ),
    .gen_m_rd_slast           ( gen_m_rd_slast      ),
    .gen_m_rd_sresp           ( gen_m_rd_sresp      ),
    .gen_m_rd_svalid          ( gen_m_rd_svalid     ),
    // gen master
    .gen_m_wr_maddr           ( gen_m_wr_maddr      ),
    .gen_m_wr_mburst          ( gen_m_wr_mburst     ),
    .gen_m_wr_mcache          ( gen_m_wr_mcache     ),
    .gen_m_wr_mdata           ( gen_m_wr_mdata      ),
    .gen_m_wr_mid             ( gen_m_wr_mid        ),
    .gen_m_wr_mlen            ( gen_m_wr_mlen       ),
    .gen_m_wr_mlock           ( gen_m_wr_mlock      ),
    .gen_m_wr_mprot           ( gen_m_wr_mprot      ),
    .gen_m_wr_mread           ( gen_m_wr_mread      ),
    .gen_m_wr_mready          ( gen_m_wr_mready     ),
    .gen_m_wr_msize           ( gen_m_wr_msize      ),
    .gen_m_wr_mwrite          ( gen_m_wr_mwrite     ),
    .gen_m_wr_mwstrb          ( gen_m_wr_mwstrb     ),
    .gen_m_wr_saccept         ( gen_m_wr_saccept    ),
    .gen_m_wr_sdata           ( gen_m_wr_sdata      ),
    .gen_m_wr_sid             ( gen_m_wr_sid        ),
    .gen_m_wr_slast           ( gen_m_wr_slast      ),
    .gen_m_wr_sresp           ( gen_m_wr_sresp      ),
    .gen_m_wr_svalid          ( gen_m_wr_svalid     ),
    // sdram ports from memctl
    .i_memctl_clear_sr_dp     ( 1'b0                ),
    .i_memctl_gpi             ( 8'b0                ),
    .i_memctl_power_down      ( 1'b0                ),
    .i_memctl_remap           ( 1'b0                ),
    .i_memctl_s_rd_data       ( sdram_rd_data       ),
    .i_memctl_s_rd_ready      ( 1'b0                ),
    .i_memctl_s_sda_in        ( 1'b0                ),
    .i_memctl_s_cas_n         ( sdram_cas_n         ),
    .i_memctl_s_cke           ( sdram_cke           ),
    .i_memctl_s_dout_valid    ( sdram_dout_valid    ),
    .i_memctl_s_dqm           ( sdram_dqm           ),
    .i_memctl_s_ras_n         ( sdram_ras_n         ),
    .i_memctl_s_addr          ( sdram_addr          ),
    .i_memctl_s_bank_addr     ( sdram_bank_addr     ),
    .i_memctl_s_sel_n         ( sdram_sel_n         ),
    .i_memctl_s_we_n          ( sdram_we_n          ),
    .i_memctl_s_wr_data       ( sdram_wr_data       )
    );


//*** I/O PAD ************************************

  // for sdram
  sdram_data_ctrl sdram_data_ctrl0(
    .datain         ( sdram_wr_data                 ),
    .oe             ( { {8{sdram_dout_valid[3]}},
                        {8{sdram_dout_valid[2]}},
                        {8{sdram_dout_valid[1]}},
                        {8{sdram_dout_valid[0]}}  } ),
    .dataio         ( sdram_dq                      ),
    .dataout        ( sdram_rd_data                 )
    );


endmodule