// ============================================================================
// Copyright (c) 2024 by Terasic Technologies Inc.
// ============================================================================
//
// Permission:
//
//   Terasic grants permission to use and modify this code for use
//   in synthesis for all Terasic Development Boards and Altera Development
//   Kits made by Terasic.  Other use of this code, including the selling
//   ,duplication, or modification of any portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL/Verilog or C/C++ source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Terasic provides no warranty regarding the use
//   or functionality of this code.
//
// ============================================================================
//
//  Terasic Technologies Inc
//  No.80, Fenggong Rd., Hukou Township, Hsinchu County 303035. Taiwan
//
//
//                     web: http://www.terasic.com/
//                     email: support@terasic.com
//
// ============================================================================
//Date:  Wed Apr  3 10:19:18 2024
// ============================================================================

//`define ENABLE_DDR4A
//`define ENABLE_DDR4B
//`define ENABLE_QSFP
//`define ENABLE_FMCP
//`define ENABLE_HPS
//`define ENABLE_HDMI
//`define ENABLE_PCIE
//`define ENABLE_ENET
//`define ENABLE_CAM1
//`define ENABLE_CAM2

module golden_top(

      ///////// CLOCK /////////
      input              CLK_100_B2B_p,
      input              CLK_50_B5A,
      input              CLK_50_B6A,
      input              CLK_50_B6C,

      ///////// Buttons /////////
      input              CPU_RESET_n,
      input    [ 3: 0]   BUTTON, //BUTTON is Low-Active

      ///////// Swtiches /////////
      input    [ 3: 0]   SW,

      ///////// LED /////////
      output   [ 3: 0]   LED, //LED is Low-Active

`ifdef ENABLE_DDR4A
      ///////// DDR4A /////////
      input              DDR4A_REFCLK_p,
      output   [16: 0]   DDR4A_A,
      output   [ 1: 0]   DDR4A_BA,
      output   [ 0: 0]   DDR4A_BG,
      output             DDR4A_CK,
      output             DDR4A_CK_n,
      output             DDR4A_CKE,
      inout    [ 3: 0]   DDR4A_DQS,
      inout    [ 3: 0]   DDR4A_DQS_n,
      inout    [31: 0]   DDR4A_DQ,
      inout    [ 3: 0]   DDR4A_DBI_n,
      output             DDR4A_CS_n,
      output             DDR4A_RESET_n,
      output             DDR4A_ODT,
      output             DDR4A_PAR,
      input              DDR4A_ALERT_n,
      output             DDR4A_ACT_n,
      input              DDR4A_RZQ,
`endif /*ENABLE_DDR4A*/

`ifdef ENABLE_DDR4B
      ///////// DDR4B /////////
      input              DDR4B_REFCLK_p,
      output   [16: 0]   DDR4B_A,
      output   [ 1: 0]   DDR4B_BA,
      output   [ 0: 0]   DDR4B_BG,
      output             DDR4B_CK,
      output             DDR4B_CK_n,
      output             DDR4B_CKE,
      inout    [ 3: 0]   DDR4B_DQS,
      inout    [ 3: 0]   DDR4B_DQS_n,
      inout    [31: 0]   DDR4B_DQ,
      inout    [ 3: 0]   DDR4B_DBI_n,
      output             DDR4B_CS_n,
      output             DDR4B_RESET_n,
      output             DDR4B_ODT,
      output             DDR4B_PAR,
      input              DDR4B_ALERT_n,
      output             DDR4B_ACT_n,
      input              DDR4B_RZQ,
`endif /*ENABLE_DDR4B*/

`ifdef ENABLE_HDMI
      ///////// HDMI /////////
      inout              HDMI_LRCLK,
      inout              HDMI_MCLK,
      inout              HDMI_SCLK,
      output             HDMI_TX_CLK,
      output             HDMI_TX_HS,
      output             HDMI_TX_VS,
      output   [23: 0]   HDMI_TX_D,
      output             HDMI_TX_DE,
      inout              HDMI_I2C_SCL,
      inout              HDMI_I2C_SDA,
      input              HDMI_TX_INT,
      inout              HDMI_I2S,
`endif /*ENABLE_HDMI*/

`ifdef ENABLE_ENET
      ///////// ENET /////////
      output             ENET_88E2110_TX_p,
      output             ENET_88E2110_TX_n,
      input              ENET_88E2110_RX_p,
      input              ENET_88E2110_RX_n,
      input              ENET_88E2110_REFCLK_125M_p,
      input              ENET_88E2110_INT_n,
      output             ENET_88E2110_MDC,
      inout              ENET_88E2110_MDIO,
      output             ENET_88E2110_RESET_n,
`endif /*ENABLE_ENET*/

      ///////// SI5340B /////////
      inout              SI5340B_I2C_SCL,
      inout              SI5340B_I2C_SDA,
      output             SI5340B_OE_n,
      output             SI5340B_RST_n,

      ///////// SI5391B /////////
      inout              SI5391B_I2C_SCL,
      inout              SI5391B_I2C_SDA,
      output             SI5391B_OE_n,
      output             SI5391B_RST_n,

      ///////// GPIO /////////
      inout    [35: 0]   GPIO,

      ///////// TMD /////////
      inout    [ 7: 0]   TMD_D,

`ifdef ENABLE_FMCP
      ///////// FMCP /////////
      inout              FMCP_CLK2_BIDIR_p,
      inout              FMCP_CLK2_BIDIR_n,
      inout              FMCP_CLK3_BIDIR_p,
      inout              FMCP_CLK3_BIDIR_n,
      output   [11: 0]   FMCP_DP_C2M_p,
      output   [11: 0]   FMCP_DP_C2M_n,
      input    [11: 0]   FMCP_DP_M2C_p,
      input    [11: 0]   FMCP_DP_M2C_n,
      inout    [23: 0]   FMCP_HA_p,
      inout    [23: 0]   FMCP_HA_n,
      inout    [21: 0]   FMCP_HB_p,
      inout    [21: 0]   FMCP_HB_n,
      inout    [33: 0]   FMCP_LA_p,
      inout    [33: 0]   FMCP_LA_n,
      input    [ 1: 0]   FMCP_CLK_M2C_p,
      input    [ 2: 0]   FMCP_GBTCLK_M2C_p,
      output             FMCP_REFCLK_C2M_p,
      input              FMCP_REFCLK_M2C_p,
      input    [ 2: 0]   FMCP_REFCLK_p,
      input              FMCP_RES0,
      inout              FMCP_SCL,
      inout              FMCP_SDA,
      output             FMCP_SYNC_C2M_p,
      input              FMCP_SYNC_M2C_p,
`endif /*ENABLE_FMCP*/

`ifdef ENABLE_PCIE
      ///////// PCIE /////////
      output   [ 3: 0]   PCIE_TX_p,
      output   [ 3: 0]   PCIE_TX_n,
      input    [ 3: 0]   PCIE_RX_p,
      input    [ 3: 0]   PCIE_RX_n,
      input              PCIE_OB_REFCLK_p,
      input              PCIE_REFCLK_p,
      input              PCIE_PERST_n,
      output             PCIE_WAKE_n,
`endif /*ENABLE_PCIE*/

`ifdef ENABLE_QSFP
      ///////// QSFP /////////
      output   [ 3: 0]   QSFP_TX_p,
      output   [ 3: 0]   QSFP_TX_n,
      input    [ 3: 0]   QSFP_RX_p,
      input    [ 3: 0]   QSFP_RX_n,
      input              CIPRI_REFCLK_p,
      input              QSFP_REFCLK_p,
      input              QSFP_INTERRUPT_n,
      output             QSFP_LP_MODE,
      input              QSFP_MOD_PRS_n,
      output             QSFP_MOD_SEL_n,
      output             QSFP_RST_n,
      inout              QSFP_SCL,
      inout              QSFP_SDA,
`endif /*ENABLE_QSFP*/

      ///////// CAM /////////
      input              CAM_RZQ,

`ifdef ENABLE_CAM1
      ///////// CAM1 /////////
      input              CAM1_CLK_p,
      input              CAM1_CLK_n,
      input    [ 1: 0]   CAM1_D_p,
      input    [ 1: 0]   CAM1_D_n,
      inout              CAM1_I2C_SCL,
      inout              CAM1_I2C_SDA,
      inout              CAM1_GPIO,
`endif /*ENABLE_CAM1*/

`ifdef ENABLE_CAM2
      ///////// CAM2 /////////
      input              CAM2_CLK_p,
      input              CAM2_CLK_n,
      input    [ 1: 0]   CAM2_D_p,
      input    [ 1: 0]   CAM2_D_n,
      inout              CAM2_I2C_SCL,
      inout              CAM2_I2C_SDA,
      inout              CAM2_GPIO,
`endif /*ENABLE_CAM2*/

`ifdef ENABLE_HPS
      ///////// HPS /////////
      output             HPS_ENET_MDC,
      inout              HPS_ENET_MDIO,
      input              HPS_ENET_RX_CLK,
      input              HPS_ENET_RX_CTL,
      input    [ 3: 0]   HPS_ENET_RX_DATA,
      output             HPS_ENET_TX_CLK,
      output             HPS_ENET_TX_CTL,
      output   [ 3: 0]   HPS_ENET_TX_DATA,
      inout    [ 4: 0]   HPS_GPIO,
      inout              HPS_I2C_SCL,
      inout              HPS_I2C_SDA,
      inout              HPS_KEY,
      inout              HPS_LED,
      input              HPS_OSC_CLK,
      output             HPS_SDMMC_CLK,
      inout              HPS_SDMMC_CMD,
      inout    [ 7: 0]   HPS_SDMMC_DATA,
      input              HPS_UART_RX,
      output             HPS_UART_TX,
      input              HPS_USB3_REFCLK_100M_p,
      input              HPS_USB3_SS_RX_n,
      input              HPS_USB3_SS_RX_p,
      output             HPS_USB3_SS_TX_n,
      output             HPS_USB3_SS_TX_p,
      input              HPS_USB_CLK,
      inout    [ 7: 0]   HPS_USB_DATA,
      input              HPS_USB_DIR,
      input              HPS_USB_ID,
      input              HPS_USB_NXT,
      output             HPS_USB_STP,
      output             HPS_USB_VBUS_CTRL,
      input              HPS_USB_VBUS_DET,
      input              HPS_USB_VBUS_FLT_n,
`endif /*ENABLE_HPS*/

      ///////// INFO /////////
      output             INFO_SPI_SCLK,
      input              INFO_SPI_MISO,
      output             INFO_SPI_MOSI,
      output             INFO_SPI_CS_n

);


//=======================================================
//  REG/WIRE declarations
//=======================================================

assign SI5340B_OE_n = 1'bZ;
assign SI5340B_RST_n = 1'bZ;
assign SI5391B_OE_n = 1'bZ;
assign SI5391B_RST_n = 1'bZ;




//=======================================================
//  Structural coding
//=======================================================

wire clk_50;
wire sys_reset;

//System Monitor IP
//IP interface
wire Info_Valid;
wire [15: 0] Board_Version;     //A~F.ex BOARD_VERSION = 16'h000b ,express to revB
wire [15: 0] MaxCode_Version;   //0~F.ex MAX10_VERSION = 16'h0004 ,express to rev4
wire [15: 0] PowerIn_Voltage;   //unit : mV
wire [15: 0] CORE_Voltage;      //unit : mV
wire [15: 0] CORE_Current;      //unit : 10mA
wire [15: 0] VCC1P2_Voltage;      //unit : mV
wire [15: 0] VCC1P2_Current;      //unit : 10mA
wire [15: 0] Fan_Speed;         //unit : rpm
wire [15: 0] Temp_FPGA;         //unit : Celsius degree
wire [15: 0] Temp_Board;        //unit : Celsius degree
wire [15: 0] Temp_Board2;       //unit : Celsius degree
wire [15: 0] Temp_Power;       //unit : Celsius degree
wire [15: 0] PIN_STATUS;


//----reg
reg [15: 0] rBoard_Version;
reg [15: 0] rMaxCode_Version;
reg [15: 0] rPowerIn_Voltage;
reg [15: 0] rPowerIn_Current;
reg [15: 0] rCORE_Voltage;
reg [15: 0] rCORE_Current;
reg [15: 0] rVCC1P2_Voltage;
reg [15: 0] rVCC1P2_Current;
reg [15: 0] rFan_Speed;
reg [15: 0] rTemp_FPGA;
reg [15: 0] rTemp_Board;
reg [15: 0] rTemp_Board2;
reg [15: 0] rTemp_Power;
reg [15: 0] rPIN_STATUS;
reg [15: 0] rShutdown_flag;



//=======================================================
//  Structural coding
//=======================================================


/////////////////////////// Reset Release IP ////////////////////////////////

wire ninit_done;
reset_release reset_release_int (
    .ninit_done (ninit_done)    //  output,  width = 1, ninit_done.ninit_done
);

assign clk_50 = CLK_50_B5A;
assign sys_reset = ninit_done;

system u0 (
    .clock_in_clk                  (clk_50),      //   input,   width = 1,               clock_in.clk
    .reset_in0_reset               (~CPU_RESET_n | sys_reset),      //   input,   width = 1,              reset_in0.reset
    .reset_in1_reset               (ninit_done),        //   input,   width = 1,              reset_in1.reset
    .power_in_voltage_export       (rPowerIn_Voltage),  //   input,  width = 16,       power_in_voltage.export
    .core_voltage_export           (rCORE_Voltage),     //   input,  width = 16,           core_voltage.export
    .core_current_export           (rCORE_Current),     //   input,  width = 16,           core_current.export
    .vcc1p2_voltage_export         (rVCC1P2_Voltage),     //   input,  width = 16,           core_voltage.export
    .vcc1p2_current_export         (rVCC1P2_Current),     //   input,  width = 16,           core_current.export
    .fan_speed_export             (rFan_Speed),        //   input,  width = 16,             fan_speed1.export
    .temperature_fpga_export       (rTemp_FPGA),        //   input,  width = 16,       temperature_fpga.export
    .temperature_board1_export     (rTemp_Board),       //   input,  width = 16,     temperature_board1.export
    .temperature_board2_export     (rTemp_Board2),      //   input,  width = 16,     temperature_board2.export
    .temperature_power_export     (rTemp_Power),      //   input,  width = 16,     temperature_board2.export
    .pin_status_export             (rPIN_STATUS)        //   input,  width = 16,             pin_status.export
);


BOARD_INFO BOARD_INFO_i(
    .RESET_N (CPU_RESET_n & ~sys_reset),
    .CLK_50  (clk_50),

    // 4-pin SPI master interface
    .SCLK (INFO_SPI_SCLK),  // output
    .MISO (INFO_SPI_MISO),  // input
    .MOSI (INFO_SPI_MOSI),  // output
    .CS_n (INFO_SPI_CS_n),  // output

    // status report (output)
    .Info_Valid          (Info_Valid),      //1: following data is valid
    .Board_Version       (Board_Version),   //A~F.ex BOARD_VERSION = 16'h000b ,express to revB
    .MaxCode_Version     (MaxCode_Version), //0~F.ex MAX10_VERSION = 16'h0004 ,express to rev4
    .PowerIn_Voltage     (PowerIn_Voltage), //unit : Celsius degree
    .CORE_Voltage        (CORE_Voltage),    //unit : mV
    .CORE_Current        (CORE_Current),    //unit : 10mA
    .VCC1P2_Voltage      (VCC1P2_Voltage),    //unit : mV
    .VCC1P2_Current      (VCC1P2_Current),    //unit : 10mA
    .Fan_Speed           (Fan_Speed),       //unit : rpm
    .Temp_FPGA           (Temp_FPGA),       //unit : Celsius degree
    .Temp_Board          (Temp_Board),      //unit : Celsius degree
    .Temp_Board2         (Temp_Board2),      //unit : Celsius degree
	 .Temp_POWER          (Temp_Power),//ltc3888 temperature 	 
    .PIN_STATUS          (PIN_STATUS)
);





always @(posedge clk_50) begin
    if (Info_Valid) begin
        rBoard_Version      <= Board_Version;
        rMaxCode_Version    <= MaxCode_Version;
        rPowerIn_Voltage    <= PowerIn_Voltage;
        rCORE_Voltage       <= CORE_Voltage;
        rCORE_Current       <= CORE_Current;
        rVCC1P2_Voltage       <= VCC1P2_Voltage;
        rVCC1P2_Current       <= VCC1P2_Current;
        rFan_Speed          <= Fan_Speed;
        rTemp_FPGA          <= Temp_FPGA;
        rTemp_Board         <= Temp_Board;
        rTemp_Board2        <= Temp_Board2;
        rTemp_Power         <= Temp_Power;
        rPIN_STATUS         <= PIN_STATUS;
    end
end


/////////////////////////////////////////////////
// User LED Blink

wire blink;

heart_beat led_blink(
	.clk(CLK_50_B5A),
	.led(blink)
);

assign LED = {4{blink}};


endmodule
