// // Copyright 2021 Ettus Research, A National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // // Module: mb_cpld // // Description: // // Top level file for the X4xx motherboard CPLD. // // Parameters: // // SIMULATION : Set to 1 to speed up simulation. // `default_nettype none module mb_cpld #( parameter SIMULATION = 0 ) ( //--------------------------------------------------------------------------- // Clocking //--------------------------------------------------------------------------- // CPLD's PLL reference clock (differential input; abbreviation: pclk) input wire PLL_REF_CLK, // Reliable clock (100 MHz; differential input) input wire CLK_100, //--------------------------------------------------------------------------- // Power Supplies //--------------------------------------------------------------------------- // Power supply clocks output wire PWR_SUPPLY_CLK_CORE, output wire PWR_SUPPLY_CLK_DDR4_S, output wire PWR_SUPPLY_CLK_DDR4_N, output wire PWR_SUPPLY_CLK_0P9V, output wire PWR_SUPPLY_CLK_1P8V, output wire PWR_SUPPLY_CLK_2P5V, output wire PWR_SUPPLY_CLK_3P3V, output wire PWR_SUPPLY_CLK_3P6V, // Power supply control output wire PWR_EN_5V_OSC_100, output wire PWR_EN_5V_OSC_122_88, output wire IPASS_POWER_DISABLE, input wire [1:0] IPASS_POWER_EN_FAULT, //--------------------------------------------------------------------------- // Interfaces from/to RFSoC //--------------------------------------------------------------------------- // PL SPI slave interface input wire PL_CPLD_SCLK, input wire PL_CPLD_MOSI, output reg PL_CPLD_MISO, input wire [1:0] PL_CPLD_CS_N, // IRQ to PL output wire PL_CPLD_IRQ, // PS SPI slave interface // Chip Selects: // PS_CPLD_CS_N(2:0) -> binary encoded chip select // PS_CPLD_CS_N(3) -> chip select "enable" input wire PS_CPLD_SCLK, input wire PS_CPLD_MOSI, output wire PS_CPLD_MISO, input wire [3:0] PS_CPLD_CS_N, //--------------------------------------------------------------------------- // PL Interfaces to/from Motherboard //--------------------------------------------------------------------------- // Clocking AUX board SPI master interface output wire CLK_DB_SCLK, output wire CLK_DB_MOSI, input wire CLK_DB_MISO, output wire CLK_DB_CS_N, // QSFP LEDs // Port 0 output wire [3:0] QSFP0_LED_ACTIVE, output wire [3:0] QSFP0_LED_LINK, // Port 1 output wire [3:0] QSFP1_LED_ACTIVE, output wire [3:0] QSFP1_LED_LINK, // Daughterboard control interface // 1 -> DB1 / 0 -> DB0 output reg [1:0] DB_CTRL_SCLK, output reg [1:0] DB_CTRL_MOSI, input wire [1:0] DB_CTRL_MISO, output reg [1:0] DB_CTRL_CS_N, output wire [1:0] DB_REF_CLK, output wire [1:0] DB_ARST, // Daughterboards' JTAG master interfaces. // 1 -> DB1 / 0 -> DB0 output wire [1:0] DB_JTAG_TCK, output wire [1:0] DB_JTAG_TDI, // from CPLD to DB input wire [1:0] DB_JTAG_TDO, // from DB to CPLD output wire [1:0] DB_JTAG_TMS, //--------------------------------------------------------------------------- // PS Interfaces to/from Motherboard //--------------------------------------------------------------------------- // LMK04832 SPI master interface output wire LMK32_SCLK, output wire LMK32_MOSI, input wire LMK32_MISO, output wire LMK32_CS_N, // TPM 2.0 SPI master interface // Note: TPM is not currently supported output wire TPM_SCLK, output wire TPM_MOSI, input wire TPM_MISO, output wire TPM_CS_N, // Phase DAC SPI master interface output wire PHASE_DAC_SCLK, output wire PHASE_DAC_MOSI, output wire PHASE_DAC_CS_N, // DIO direction control output wire [11:0] DIO_DIRECTION_A, output wire [11:0] DIO_DIRECTION_B, // Daughterboard calibration EEPROM SPI // 1 -> DB1 / 0 -> DB0 output wire [1:0] DB_CALEEPROM_SCLK, output wire [1:0] DB_CALEEPROM_MOSI, input wire [1:0] DB_CALEEPROM_MISO, output wire [1:0] DB_CALEEPROM_CS_N, //--------------------------------------------------------------------------- // Miscellaneous //--------------------------------------------------------------------------- // This signal enables the 1.8 V and 3.3 V power supply clocks. output wire PS_CLK_ON_CPLD, // iPASS control interface input wire [1:0] IPASS_PRESENT_N, inout wire [1:0] IPASS_SCL, inout wire [1:0] IPASS_SDA, // PCIe reset to FPGA output wire PCIE_RESET, // TPM reset output wire TPM_RESET_n ); // SPI masters (spi_top) are limited to 64 bit transmission length `define SPI_MAX_CHAR_64 `include "../../../lib/rfnoc/core/ctrlport.vh" `include "regmap/mb_cpld_ps_regmap_utils.vh" `include "regmap/mb_cpld_pl_regmap_utils.vh" //--------------------------------------------------------------------------- // Clocks and Resets //--------------------------------------------------------------------------- wire clk40, clk50, clk250; wire pll_ref_clk_int; wire reset_clk50; wire reset_clk40; wire power_on_reset_clk100; wire [0:0] pll_locked_async; wire [0:0] pll_locked_clk50; wire [0:0] pll_locked_clk40; wire pll_ref_clk_en_clk50; wire pll_ref_clk_en_pclk; reset_generator reliable_reset_gen_inst ( .clk (CLK_100), .power_on_reset (power_on_reset_clk100) ); // Divide reliable clock by 2 since the design is not capable of running at // 100 MHz. Multiple by 2.5 to get a fast clock to handle PS SPI chip select // decoding. pll pll_inst ( .inclk0 (CLK_100), .c0 (clk50), .c1 (clk250), .c2 (clk40), .locked (pll_locked_async) ); // Bring pll_ref_clk enable signal to the same clock domain. synchronizer #( .WIDTH (1), .STAGES (2), .INITIAL_VAL (1'b0), .FALSE_PATH_TO_IN (1) ) pll_ref_clk_en_sync ( .clk (PLL_REF_CLK), .rst (1'b0), .in (pll_ref_clk_en_clk50), .out (pll_ref_clk_en_pclk) ); // Enable clock using ALTCLKCTRL IP. clkctrl pll_ref_clk_ctrl_inst ( .inclk (PLL_REF_CLK), .ena (pll_ref_clk_en_pclk), .outclk (pll_ref_clk_int) ); // Use locked signal as reset for clk50 and clk40 clock domain synchronizer #( .WIDTH (1), .STAGES (2), .INITIAL_VAL (1'b0), .FALSE_PATH_TO_IN (1) ) clk50_reset_sync ( .clk (clk50), .rst (1'b0), .in (pll_locked_async), .out (pll_locked_clk50) ); assign reset_clk50 = ~pll_locked_clk50; synchronizer #( .WIDTH (1), .STAGES (2), .INITIAL_VAL (1'b0), .FALSE_PATH_TO_IN (1) ) clk40_reset_sync ( .clk (clk40), .rst (1'b0), .in (pll_locked_async), .out (pll_locked_clk40) ); assign reset_clk40 = ~pll_locked_clk40; //--------------------------------------------------------------------------- // Power Supply Clock //--------------------------------------------------------------------------- `ifdef MFG_SUPPORT assign PWR_SUPPLY_CLK_CORE = 1'b0; assign PWR_SUPPLY_CLK_DDR4_S = 1'b0; assign PWR_SUPPLY_CLK_DDR4_N = 1'b0; assign PWR_SUPPLY_CLK_0P9V = 1'b0; assign PWR_SUPPLY_CLK_1P8V = 1'b0; assign PWR_SUPPLY_CLK_2P5V = 1'b0; assign PWR_SUPPLY_CLK_3P3V = 1'b0; assign PWR_SUPPLY_CLK_3P6V = 1'b0; `else // Frequency definitions localparam SOUCE_CLOCK_FREQUENCY = 100_000_000; localparam TARGET_FREQUENCY_350k = 350_000; localparam TARGET_FREQUENCY_450k = 450_000; localparam TARGET_FREQUENCY_500k = 500_000; localparam TARGET_FREQUENCY_600k = 600_000; localparam TARGET_FREQUENCY_800k = 800_000; localparam TARGET_FREQUENCY_1M = 1_000_000; pwr_supply_clk_gen #( .SOURCE_CLK_FREQ (SOUCE_CLOCK_FREQUENCY), .TARGET_CLK_FREQ (TARGET_FREQUENCY_350k) ) freq_gen_350k ( .clk (CLK_100), .rst (power_on_reset_clk100), .pwr_supply_clk (PWR_SUPPLY_CLK_0P9V) ); wire pwr_supply_clk_450k; pwr_supply_clk_gen #( .SOURCE_CLK_FREQ (SOUCE_CLOCK_FREQUENCY), .TARGET_CLK_FREQ (TARGET_FREQUENCY_450k) ) freq_gen_450k ( .clk (CLK_100), .rst (power_on_reset_clk100), .pwr_supply_clk (pwr_supply_clk_450k) ); assign PWR_SUPPLY_CLK_DDR4_S = pwr_supply_clk_450k; assign PWR_SUPPLY_CLK_DDR4_N = pwr_supply_clk_450k; pwr_supply_clk_gen #( .SOURCE_CLK_FREQ (SOUCE_CLOCK_FREQUENCY), .TARGET_CLK_FREQ (TARGET_FREQUENCY_500k) ) freq_gen_500k ( .clk (CLK_100), .rst (power_on_reset_clk100), .pwr_supply_clk (PWR_SUPPLY_CLK_CORE) ); pwr_supply_clk_gen #( .SOURCE_CLK_FREQ (SOUCE_CLOCK_FREQUENCY), .TARGET_CLK_FREQ (TARGET_FREQUENCY_600k) ) freq_gen_600k ( .clk (CLK_100), .rst (power_on_reset_clk100), .pwr_supply_clk (PWR_SUPPLY_CLK_1P8V) ); pwr_supply_clk_gen #( .SOURCE_CLK_FREQ (SOUCE_CLOCK_FREQUENCY), .TARGET_CLK_FREQ (TARGET_FREQUENCY_800k) ) freq_gen_800k ( .clk (CLK_100), .rst (power_on_reset_clk100), .pwr_supply_clk (PWR_SUPPLY_CLK_2P5V) ); wire pwr_supply_clk_1M; pwr_supply_clk_gen #( .SOURCE_CLK_FREQ (SOUCE_CLOCK_FREQUENCY), .TARGET_CLK_FREQ (TARGET_FREQUENCY_1M) ) freq_gen_1M ( .clk (CLK_100), .rst (power_on_reset_clk100), .pwr_supply_clk (pwr_supply_clk_1M) ); assign PWR_SUPPLY_CLK_3P3V = pwr_supply_clk_1M; assign PWR_SUPPLY_CLK_3P6V = pwr_supply_clk_1M; `endif //--------------------------------------------------------------------------- // PL Interfaces //--------------------------------------------------------------------------- wire [1:0] db_clk_enable; wire [1:0] db_reset; wire [1:0] ipass_cable_present; // Clocks and reset oddr db0_clk_out ( .outclock (clk50), .din ({1'b0, db_clk_enable[0]}), .pad_out (DB_REF_CLK[0]), .aclr (reset_clk50) ); oddr db1_clk_out ( .outclock (clk50), .din ({1'b0, db_clk_enable[1]}), .pad_out (DB_REF_CLK[1]), .aclr (reset_clk50) ); assign DB_ARST[0] = db_reset[0]; assign DB_ARST[1] = db_reset[1]; // PL SPI FPGA -> DB CPLD reg mb_cpld_sclk, mb_cpld_mosi, mb_cpld_cs_n; wire mb_cpld_miso; // PL SPI chip select decoding localparam PL_CS_MB_CPLD = 2'b00; localparam PL_CS_DB0 = 2'b10; localparam PL_CS_DB1 = 2'b01; localparam PL_CS_IDLE = 2'b11; // PL SPI registers do not have a separate reset. // SW is expected to properly setup the DBs before issuing SPI transactions. always @(posedge pll_ref_clk_int) begin : to_db // Default chip selects DB_CTRL_CS_N[0] <= 1'b1; DB_CTRL_CS_N[1] <= 1'b1; mb_cpld_cs_n <= 1'b1; // DB 0 DB_CTRL_SCLK[0] <= PL_CPLD_SCLK; DB_CTRL_MOSI[0] <= PL_CPLD_MOSI; if (PL_CPLD_CS_N == PL_CS_DB0) begin DB_CTRL_CS_N[0] <= 1'b0; end // DB 1 DB_CTRL_SCLK[1] <= PL_CPLD_SCLK; DB_CTRL_MOSI[1] <= PL_CPLD_MOSI; if (PL_CPLD_CS_N == PL_CS_DB1) begin DB_CTRL_CS_N[1] <= 1'b0; end // MB CPLD mb_cpld_sclk <= PL_CPLD_SCLK; mb_cpld_mosi <= PL_CPLD_MOSI; if (PL_CPLD_CS_N == PL_CS_MB_CPLD) begin mb_cpld_cs_n <= 1'b0; end end // SPI DB CPLD -> FPGA always @(posedge pll_ref_clk_int) begin : from_db case (PL_CPLD_CS_N) PL_CS_MB_CPLD : PL_CPLD_MISO <= mb_cpld_miso; // MB CPLD PL_CS_DB1 : PL_CPLD_MISO <= DB_CTRL_MISO[1]; // DB 1 PL_CS_DB0 : PL_CPLD_MISO <= DB_CTRL_MISO[0]; // DB 0 PL_CS_IDLE : PL_CPLD_MISO <= 1'bz; // Inactive endcase end // Local PL SPI target wire [19:0] pl_ctrlport_req_addr; wire [31:0] pl_ctrlport_req_data; wire pl_ctrlport_req_rd; wire pl_ctrlport_req_wr; wire pl_ctrlport_resp_ack; wire [31:0] pl_ctrlport_resp_data; wire [ 1:0] pl_ctrlport_resp_status; spi_slave_to_ctrlport_master #( .CLK_FREQUENCY (50_000_000), .SPI_FREQUENCY (10_666_667) ) pl_spi_endpoint ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .m_ctrlport_req_wr (pl_ctrlport_req_wr), .m_ctrlport_req_rd (pl_ctrlport_req_rd), .m_ctrlport_req_addr (pl_ctrlport_req_addr), .m_ctrlport_req_data (pl_ctrlport_req_data), .m_ctrlport_resp_ack (pl_ctrlport_resp_ack), .m_ctrlport_resp_status (pl_ctrlport_resp_status), .m_ctrlport_resp_data (pl_ctrlport_resp_data), .sclk (mb_cpld_sclk), .cs_n (mb_cpld_cs_n), .mosi (mb_cpld_mosi), .miso (mb_cpld_miso) ); // Split up the PL control port wire [19:0] pl_regs_ctrlport_req_addr; wire [31:0] pl_regs_ctrlport_req_data; wire pl_regs_ctrlport_req_rd; wire pl_regs_ctrlport_req_wr; wire pl_regs_ctrlport_resp_ack; wire [31:0] pl_regs_ctrlport_resp_data; wire [ 1:0] pl_regs_ctrlport_resp_status; wire [19:0] pl_term_ctrlport_req_addr; wire [31:0] pl_term_ctrlport_req_data; wire pl_term_ctrlport_req_rd; wire pl_term_ctrlport_req_wr; wire pl_term_ctrlport_resp_ack; wire [31:0] pl_term_ctrlport_resp_data; wire [ 1:0] pl_term_ctrlport_resp_status; wire pl_jtag0_ctrlport_req_rd; wire pl_jtag0_ctrlport_req_wr; wire pl_jtag0_ctrlport_resp_ack; wire [31:0] pl_jtag0_ctrlport_resp_data; wire [ 1:0] pl_jtag0_ctrlport_resp_status; wire [19:0] pl_jtag0_ctrlport_req_addr; wire [31:0] pl_jtag0_ctrlport_req_data; wire [19:0] pl_jtag1_ctrlport_req_addr; wire [31:0] pl_jtag1_ctrlport_req_data; wire pl_jtag1_ctrlport_req_rd; wire pl_jtag1_ctrlport_req_wr; wire pl_jtag1_ctrlport_resp_ack; wire [31:0] pl_jtag1_ctrlport_resp_data; wire [1:0] pl_jtag1_ctrlport_resp_status; ctrlport_splitter #( .NUM_SLAVES (4) ) pl_ctrlport_splitter ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (pl_ctrlport_req_wr), .s_ctrlport_req_rd (pl_ctrlport_req_rd), .s_ctrlport_req_addr (pl_ctrlport_req_addr), .s_ctrlport_req_data (pl_ctrlport_req_data), .s_ctrlport_req_byte_en (), .s_ctrlport_req_has_time (), .s_ctrlport_req_time (), .s_ctrlport_resp_ack (pl_ctrlport_resp_ack), .s_ctrlport_resp_status (pl_ctrlport_resp_status), .s_ctrlport_resp_data (pl_ctrlport_resp_data), .m_ctrlport_req_wr ({pl_regs_ctrlport_req_wr, pl_term_ctrlport_req_wr, pl_jtag0_ctrlport_req_wr, pl_jtag1_ctrlport_req_wr}), .m_ctrlport_req_rd ({pl_regs_ctrlport_req_rd, pl_term_ctrlport_req_rd, pl_jtag0_ctrlport_req_rd, pl_jtag1_ctrlport_req_rd}), .m_ctrlport_req_addr ({pl_regs_ctrlport_req_addr, pl_term_ctrlport_req_addr, pl_jtag0_ctrlport_req_addr, pl_jtag1_ctrlport_req_addr}), .m_ctrlport_req_data ({pl_regs_ctrlport_req_data, pl_term_ctrlport_req_data, pl_jtag0_ctrlport_req_data, pl_jtag1_ctrlport_req_data}), .m_ctrlport_req_byte_en (), .m_ctrlport_req_has_time (), .m_ctrlport_req_time (), .m_ctrlport_resp_ack ({pl_regs_ctrlport_resp_ack, pl_term_ctrlport_resp_ack, pl_jtag0_ctrlport_resp_ack, pl_jtag1_ctrlport_resp_ack}), .m_ctrlport_resp_status ({pl_regs_ctrlport_resp_status, pl_term_ctrlport_resp_status, pl_jtag0_ctrlport_resp_status, pl_jtag1_ctrlport_resp_status}), .m_ctrlport_resp_data ({pl_regs_ctrlport_resp_data, pl_term_ctrlport_resp_data, pl_jtag0_ctrlport_resp_data, pl_jtag1_ctrlport_resp_data}) ); pl_cpld_regs #( .BASE_ADDRESS (PL_REGISTERS) ) pl_regs ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (pl_regs_ctrlport_req_wr), .s_ctrlport_req_rd (pl_regs_ctrlport_req_rd), .s_ctrlport_req_addr (pl_regs_ctrlport_req_addr), .s_ctrlport_req_data (pl_regs_ctrlport_req_data), .s_ctrlport_resp_ack (pl_regs_ctrlport_resp_ack), .s_ctrlport_resp_status (pl_regs_ctrlport_resp_status), .s_ctrlport_resp_data (pl_regs_ctrlport_resp_data), .qsfp0_led_active (QSFP0_LED_ACTIVE), .qsfp0_led_link (QSFP0_LED_LINK), .qsfp1_led_active (QSFP1_LED_ACTIVE), .qsfp1_led_link (QSFP1_LED_LINK), .ipass_cable_present (ipass_cable_present) ); ctrlport_to_jtag #( .BASE_ADDRESS (JTAG_DB0), .DEFAULT_PRESCALAR (1) ) db0_jtag ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (pl_jtag0_ctrlport_req_wr), .s_ctrlport_req_rd (pl_jtag0_ctrlport_req_rd), .s_ctrlport_req_addr (pl_jtag0_ctrlport_req_addr), .s_ctrlport_req_data (pl_jtag0_ctrlport_req_data), .s_ctrlport_resp_ack (pl_jtag0_ctrlport_resp_ack), .s_ctrlport_resp_status (pl_jtag0_ctrlport_resp_status), .s_ctrlport_resp_data (pl_jtag0_ctrlport_resp_data), .tck (DB_JTAG_TCK[0]), .tdi (DB_JTAG_TDI[0]), .tdo (DB_JTAG_TDO[0]), .tms (DB_JTAG_TMS[0]) ); ctrlport_to_jtag #( .BASE_ADDRESS (JTAG_DB1), .DEFAULT_PRESCALAR (1) ) db1_jtag ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (pl_jtag1_ctrlport_req_wr), .s_ctrlport_req_rd (pl_jtag1_ctrlport_req_rd), .s_ctrlport_req_addr (pl_jtag1_ctrlport_req_addr), .s_ctrlport_req_data (pl_jtag1_ctrlport_req_data), .s_ctrlport_resp_ack (pl_jtag1_ctrlport_resp_ack), .s_ctrlport_resp_status (pl_jtag1_ctrlport_resp_status), .s_ctrlport_resp_data (pl_jtag1_ctrlport_resp_data), .tck (DB_JTAG_TCK[1]), .tdi (DB_JTAG_TDI[1]), .tdo (DB_JTAG_TDO[1]), .tms (DB_JTAG_TMS[1]) ); // Termination of ctrlport request ctrlport_terminator #( .START_ADDRESS (JTAG_DB1 + JTAG_DB1_SIZE), .LAST_ADDRESS (2**CTRLPORT_ADDR_W-1) ) pl_terminator ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (pl_term_ctrlport_req_wr), .s_ctrlport_req_rd (pl_term_ctrlport_req_rd), .s_ctrlport_req_addr (pl_term_ctrlport_req_addr), .s_ctrlport_req_data (pl_term_ctrlport_req_data), .s_ctrlport_resp_ack (pl_term_ctrlport_resp_ack), .s_ctrlport_resp_status (pl_term_ctrlport_resp_status), .s_ctrlport_resp_data (pl_term_ctrlport_resp_data) ); //--------------------------------------------------------------------------- // PS Interfaces //--------------------------------------------------------------------------- // Local PS SPI target wire [19:0] ps_ctrlport_req_addr; wire [31:0] ps_ctrlport_req_data; wire ps_ctrlport_req_rd; wire ps_ctrlport_req_wr; wire ps_ctrlport_resp_ack; wire [31:0] ps_ctrlport_resp_data; wire [ 1:0] ps_ctrlport_resp_status; wire ps_spi_endpoint_sclk; wire ps_spi_endpoint_mosi; wire ps_spi_endpoint_miso; wire ps_spi_endpoint_cs_n; spi_slave_to_ctrlport_master #( .CLK_FREQUENCY (50_000_000), .SPI_FREQUENCY (5_000_000) ) ps_spi_endpoint ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .m_ctrlport_req_wr (ps_ctrlport_req_wr), .m_ctrlport_req_rd (ps_ctrlport_req_rd), .m_ctrlport_req_addr (ps_ctrlport_req_addr), .m_ctrlport_req_data (ps_ctrlport_req_data), .m_ctrlport_resp_ack (ps_ctrlport_resp_ack), .m_ctrlport_resp_status (ps_ctrlport_resp_status), .m_ctrlport_resp_data (ps_ctrlport_resp_data), .sclk (ps_spi_endpoint_sclk), .cs_n (ps_spi_endpoint_cs_n), .mosi (ps_spi_endpoint_mosi), .miso (ps_spi_endpoint_miso) ); // The PS SPI chip select signals are binary encoded. // // The internal SPI slaves as well as external slaves like the LMK04832 // trigger actions or resets based on edges of the chip select signal. // Therefore this implementation has to avoid glitches on the chip select // signal although the SPI protocol is synchronous. // // The chip signals are double synchronized to make sure there is no // meta-stability. Due to different traces lengths there is no guarantee for // the chip select signals to change at the same time. To overcome this issue // register stage 2 and 3 are compared. Only in case of matching values the // change is propagated to the slaves' chip select lines. Once the IDLE state // (all ones) is detected in register stage 2 the slaves' chip select lines // will be deasserted. // Input sync registers (3 stages) wire [3:0] ps_cpld_cs_n_shift2; // Resolving meta-stability, reset on IDLE reg [3:0] ps_cpld_cs_n_shift3 = {4 {1'b1}}; // Stable state detection synchronizer #( .WIDTH (4), .STAGES (2), .INITIAL_VAL (4'b1111), .FALSE_PATH_TO_IN (0) ) ps_spi_input_sync_inst ( .clk (clk250), .rst (1'b0), .in (PS_CPLD_CS_N), .out (ps_cpld_cs_n_shift2) ); always @(posedge clk250) begin ps_cpld_cs_n_shift3 <= ps_cpld_cs_n_shift2; end // SPI binary decoding reg [SPI_ENDPOINT_SIZE-2:0] ps_spi_cs_n_decoded = {SPI_ENDPOINT_SIZE-1 {1'b1}}; always @(posedge clk250) begin // reset in case of IDLE state if (ps_cpld_cs_n_shift2[2:0] == PS_CS_IDLE) begin ps_spi_cs_n_decoded <= {SPI_ENDPOINT_SIZE-1 {1'b1}}; // only apply changes when stable state is detected end else if (ps_cpld_cs_n_shift3[2:0] == ps_cpld_cs_n_shift2[2:0]) begin ps_spi_cs_n_decoded[PS_CS_MB_CPLD] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_MB_CPLD; ps_spi_cs_n_decoded[PS_CS_LMK32] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_LMK32; ps_spi_cs_n_decoded[PS_CS_TPM] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_TPM; ps_spi_cs_n_decoded[PS_CS_PHASE_DAC] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_PHASE_DAC; ps_spi_cs_n_decoded[PS_CS_DB0_CAL_EEPROM] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_DB0_CAL_EEPROM; ps_spi_cs_n_decoded[PS_CS_DB1_CAL_EEPROM] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_DB1_CAL_EEPROM; ps_spi_cs_n_decoded[PS_CS_CLK_AUX_DB] <= ps_cpld_cs_n_shift3[2:0] != PS_CS_CLK_AUX_DB; end end // Local SPI slave assign ps_spi_endpoint_sclk = PS_CPLD_SCLK; assign ps_spi_endpoint_mosi = PS_CPLD_MOSI; assign ps_spi_endpoint_cs_n = ps_spi_cs_n_decoded[PS_CS_MB_CPLD]; // LMK04832 SPI signals assign LMK32_SCLK = PS_CPLD_SCLK; assign LMK32_MOSI = PS_CPLD_MOSI; assign LMK32_CS_N = ps_spi_cs_n_decoded[PS_CS_LMK32]; // TPM SPI signals // Note: TPM is not currently supported assign TPM_SCLK = PS_CPLD_SCLK; assign TPM_MOSI = PS_CPLD_MOSI; assign TPM_CS_N = ps_spi_cs_n_decoded[PS_CS_TPM]; // Phase DAC SPI signals assign PHASE_DAC_SCLK = PS_CPLD_SCLK; assign PHASE_DAC_MOSI = PS_CPLD_MOSI; assign PHASE_DAC_CS_N = ps_spi_cs_n_decoded[PS_CS_PHASE_DAC]; // DB EEPROM 0 SPI signals assign DB_CALEEPROM_SCLK[0] = PS_CPLD_SCLK; assign DB_CALEEPROM_MOSI[0] = PS_CPLD_MOSI; assign DB_CALEEPROM_CS_N[0] = ps_spi_cs_n_decoded[PS_CS_DB0_CAL_EEPROM]; // DB EEPROM 1 SPI signals assign DB_CALEEPROM_SCLK[1] = PS_CPLD_SCLK; assign DB_CALEEPROM_MOSI[1] = PS_CPLD_MOSI; assign DB_CALEEPROM_CS_N[1] = ps_spi_cs_n_decoded[PS_CS_DB1_CAL_EEPROM]; // CLK AUX DB SPI signals assign CLK_DB_SCLK = PS_CPLD_SCLK; assign CLK_DB_MOSI = PS_CPLD_MOSI; assign CLK_DB_CS_N = ps_spi_cs_n_decoded[PS_CS_CLK_AUX_DB]; // Combine SPI responses based on inputs only as this path is captured // synchronously to PS_CPLD_SCLK by the SPI master. assign PS_CPLD_MISO = (PS_CPLD_CS_N[2:0] == PS_CS_MB_CPLD) ? ps_spi_endpoint_miso : (PS_CPLD_CS_N[2:0] == PS_CS_LMK32) ? LMK32_MISO : (PS_CPLD_CS_N[2:0] == PS_CS_TPM) ? TPM_MISO : (PS_CPLD_CS_N[2:0] == PS_CS_DB0_CAL_EEPROM) ? DB_CALEEPROM_MISO[0] : (PS_CPLD_CS_N[2:0] == PS_CS_DB1_CAL_EEPROM) ? DB_CALEEPROM_MISO[1] : (PS_CPLD_CS_N[2:0] == PS_CS_CLK_AUX_DB) ? CLK_DB_MISO : 1'bz; // Default case and PHASE_DAC // Split up the PS control port wire [19:0] ps_regs_ctrlport_req_addr; wire [31:0] ps_regs_ctrlport_req_data; wire ps_regs_ctrlport_req_rd; wire ps_regs_ctrlport_req_wr; wire ps_regs_ctrlport_resp_ack; wire [31:0] ps_regs_ctrlport_resp_data; wire [ 1:0] ps_regs_ctrlport_resp_status; wire [19:0] ps_term_ctrlport_req_addr; wire [31:0] ps_term_ctrlport_req_data; wire ps_term_ctrlport_req_rd; wire ps_term_ctrlport_req_wr; wire ps_term_ctrlport_resp_ack; wire [31:0] ps_term_ctrlport_resp_data; wire [ 1:0] ps_term_ctrlport_resp_status; wire [19:0] ps_reconfig_ctrlport_req_addr; wire [31:0] ps_reconfig_ctrlport_req_data; wire ps_reconfig_ctrlport_req_rd; wire ps_reconfig_ctrlport_req_wr; wire ps_reconfig_ctrlport_resp_ack; wire [31:0] ps_reconfig_ctrlport_resp_data; wire [ 1:0] ps_reconfig_ctrlport_resp_status; wire [19:0] ps_power_ctrlport_req_addr; wire [31:0] ps_power_ctrlport_req_data; wire ps_power_ctrlport_req_rd; wire ps_power_ctrlport_req_wr; wire ps_power_ctrlport_resp_ack; wire [31:0] ps_power_ctrlport_resp_data; wire [ 1:0] ps_power_ctrlport_resp_status; ctrlport_splitter #( .NUM_SLAVES (4) ) ps_ctrlport_splitter ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (ps_ctrlport_req_wr), .s_ctrlport_req_rd (ps_ctrlport_req_rd), .s_ctrlport_req_addr (ps_ctrlport_req_addr), .s_ctrlport_req_data (ps_ctrlport_req_data), .s_ctrlport_req_byte_en (), .s_ctrlport_req_has_time (), .s_ctrlport_req_time (), .s_ctrlport_resp_ack (ps_ctrlport_resp_ack), .s_ctrlport_resp_status (ps_ctrlport_resp_status), .s_ctrlport_resp_data (ps_ctrlport_resp_data), .m_ctrlport_req_wr ({ps_power_ctrlport_req_wr, ps_regs_ctrlport_req_wr, ps_term_ctrlport_req_wr, ps_reconfig_ctrlport_req_wr}), .m_ctrlport_req_rd ({ps_power_ctrlport_req_rd, ps_regs_ctrlport_req_rd, ps_term_ctrlport_req_rd, ps_reconfig_ctrlport_req_rd}), .m_ctrlport_req_addr ({ps_power_ctrlport_req_addr, ps_regs_ctrlport_req_addr, ps_term_ctrlport_req_addr, ps_reconfig_ctrlport_req_addr}), .m_ctrlport_req_data ({ps_power_ctrlport_req_data, ps_regs_ctrlport_req_data, ps_term_ctrlport_req_data, ps_reconfig_ctrlport_req_data}), .m_ctrlport_req_byte_en (), .m_ctrlport_req_has_time (), .m_ctrlport_req_time (), .m_ctrlport_resp_ack ({ps_power_ctrlport_resp_ack, ps_regs_ctrlport_resp_ack, ps_term_ctrlport_resp_ack, ps_reconfig_ctrlport_resp_ack}), .m_ctrlport_resp_status ({ps_power_ctrlport_resp_status, ps_regs_ctrlport_resp_status, ps_term_ctrlport_resp_status, ps_reconfig_ctrlport_resp_status}), .m_ctrlport_resp_data ({ps_power_ctrlport_resp_data, ps_regs_ctrlport_resp_data, ps_term_ctrlport_resp_data, ps_reconfig_ctrlport_resp_data}) ); wire [39:0] serial_num_clk50; wire cmi_ready_clk50; wire cmi_other_side_detected_clk50; ps_cpld_regs #( .BASE_ADDRESS (PS_REGISTERS) ) ps_regs ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (ps_regs_ctrlport_req_wr), .s_ctrlport_req_rd (ps_regs_ctrlport_req_rd), .s_ctrlport_req_addr (ps_regs_ctrlport_req_addr), .s_ctrlport_req_data (ps_regs_ctrlport_req_data), .s_ctrlport_resp_ack (ps_regs_ctrlport_resp_ack), .s_ctrlport_resp_status (ps_regs_ctrlport_resp_status), .s_ctrlport_resp_data (ps_regs_ctrlport_resp_data), .db_clk_enable (db_clk_enable), .db_reset (db_reset), .pll_ref_clk_enable (pll_ref_clk_en_clk50), .dio_direction_a (DIO_DIRECTION_A), .dio_direction_b (DIO_DIRECTION_B), .serial_num (serial_num_clk50), .cmi_ready (cmi_ready_clk50), .cmi_other_side_detected (cmi_other_side_detected_clk50) ); ps_power_regs #( .BASE_ADDRESS (POWER_REGISTERS), .NUM_ADDRESSES (POWER_REGISTERS_SIZE) ) ps_power_regs_inst ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (ps_power_ctrlport_req_wr), .s_ctrlport_req_rd (ps_power_ctrlport_req_rd), .s_ctrlport_req_addr (ps_power_ctrlport_req_addr), .s_ctrlport_req_data (ps_power_ctrlport_req_data), .s_ctrlport_resp_ack (ps_power_ctrlport_resp_ack), .s_ctrlport_resp_status (ps_power_ctrlport_resp_status), .s_ctrlport_resp_data (ps_power_ctrlport_resp_data), .ipass_power_disable (IPASS_POWER_DISABLE), .ipass_power_fault_n (IPASS_POWER_EN_FAULT), .osc_100_en (PWR_EN_5V_OSC_100), .osc_122_88_en (PWR_EN_5V_OSC_122_88) ); // Termination of ctrlport request ctrlport_terminator #( .START_ADDRESS (POWER_REGISTERS + POWER_REGISTERS_SIZE), .LAST_ADDRESS (2**CTRLPORT_ADDR_W-1) ) ps_terminator ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (ps_term_ctrlport_req_wr), .s_ctrlport_req_rd (ps_term_ctrlport_req_rd), .s_ctrlport_req_addr (ps_term_ctrlport_req_addr), .s_ctrlport_req_data (ps_term_ctrlport_req_data), .s_ctrlport_resp_ack (ps_term_ctrlport_resp_ack), .s_ctrlport_resp_status (ps_term_ctrlport_resp_status), .s_ctrlport_resp_data (ps_term_ctrlport_resp_data) ); //--------------------------------------------------------------------------- // Reconfiguration //--------------------------------------------------------------------------- // On-chip flash interface // // Naming is according to Avalon Memory-Mapped Interfaces: // https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/manual/mnl_avalon_spec.pdf wire csr_addr; wire csr_read; wire [31:0] csr_readdata; wire csr_write; wire [31:0] csr_writedata; wire [16:0] data_addr; wire data_read; wire [31:0] data_readdata; wire data_readdatavalid; wire data_waitrequest; wire data_write; wire [31:0] data_writedata; wire reset_clk50_n; assign reset_clk50_n = ~reset_clk50; on_chip_flash flash_inst ( .clock (clk50), .avmm_csr_addr (csr_addr), .avmm_csr_read (csr_read), .avmm_csr_writedata (csr_writedata), .avmm_csr_write (csr_write), .avmm_csr_readdata (csr_readdata), .avmm_data_addr (data_addr), .avmm_data_read (data_read), .avmm_data_writedata (data_writedata), .avmm_data_write (data_write), .avmm_data_readdata (data_readdata), .avmm_data_waitrequest (data_waitrequest), .avmm_data_readdatavalid (data_readdatavalid), .avmm_data_burstcount (4'b0001), .reset_n (reset_clk50_n) ); reconfig_engine #( .BASE_ADDRESS (RECONFIG), .NUM_ADDRESSES (RECONFIG_SIZE), .MEM_INIT (0) ) reconfig_engine_inst ( .ctrlport_clk (clk50), .ctrlport_rst (reset_clk50), .s_ctrlport_req_wr (ps_reconfig_ctrlport_req_wr), .s_ctrlport_req_rd (ps_reconfig_ctrlport_req_rd), .s_ctrlport_req_addr (ps_reconfig_ctrlport_req_addr), .s_ctrlport_req_data (ps_reconfig_ctrlport_req_data), .s_ctrlport_resp_ack (ps_reconfig_ctrlport_resp_ack), .s_ctrlport_resp_status (ps_reconfig_ctrlport_resp_status), .s_ctrlport_resp_data (ps_reconfig_ctrlport_resp_data), .csr_addr (csr_addr), .csr_read (csr_read), .csr_writedata (csr_writedata), .csr_write (csr_write), .csr_readdata (csr_readdata), .data_addr (data_addr), .data_read (data_read), .data_writedata (data_writedata), .data_write (data_write), .data_readdata (data_readdata), .data_waitrequest (data_waitrequest), .data_readdatavalid (data_readdatavalid) ); //--------------------------------------------------------------------------- // CMI Interface //--------------------------------------------------------------------------- // Control and status information clock transition wire [39:0] serial_num_clk40; wire cmi_ready_clk40; wire cmi_other_side_detected_clk40; handshake #( .WIDTH (41) ) cmi_control_hs ( .clk_a (clk50), .rst_a (reset_clk50), .valid_a (1'b1), .data_a ({cmi_ready_clk50, serial_num_clk50}), .busy_a (), .clk_b (clk40), .valid_b (), .data_b ({cmi_ready_clk40, serial_num_clk40}) ); synchronizer #( .WIDTH (1), .STAGES (2), .INITIAL_VAL (1'b0), .FALSE_PATH_TO_IN (1) ) cmi_status_sync ( .clk (clk50), .rst (reset_clk50), .in (cmi_other_side_detected_clk40), .out (cmi_other_side_detected_clk50) ); wire scl_out; wire sda_out; wire [1:0] ipass_cable_present_n = ~ipass_cable_present; PcieCmiWrapper #( .kSimulation (SIMULATION) ) pcie_cmi_inst ( .Clk (clk40), .acReset (reset_clk40), .cSerialNumber (serial_num_clk40), .cBoardIsReady (cmi_ready_clk40), .cCmiReset (PCIE_RESET), .cOtherSideDetected (cmi_other_side_detected_clk40), .aCblPrsnt_n (ipass_cable_present_n[0]), .aSdaIn (IPASS_SDA[0]), .aSdaOut (sda_out), .aSclIn (IPASS_SCL[0]), .aSclOut (scl_out) ); // External pull-ups are used to drive the signal high assign IPASS_SDA[0] = sda_out ? 1'bz : 1'b0; assign IPASS_SCL[0] = scl_out ? 1'bz : 1'b0; // No CMI controller for second interface assign IPASS_SCL[1] = 1'bz; assign IPASS_SDA[1] = 1'bz; //--------------------------------------------------------------------------- // Miscellaneous //--------------------------------------------------------------------------- // Constants assign PS_CLK_ON_CPLD = 1'b0; // Active-low driving of PS clocks assign TPM_RESET_n = 1'b1; // Currently unused ports assign PL_CPLD_IRQ = 1'b0; endmodule `default_nettype wire //XmlParse xml_on // // // // // // // // // This register map is available using the PS CPLD SPI interface. // // // // // // // // // // // // // // // // // // // // // // This register map is available using the PL CPLD SPI interface. // All protocol masters controller by this register map are running with a clock frequency of 50 MHz. // // // // // // JTAG Master connected to first daugherboard's CPLD JTAG interface. // // **Use minimum value of 1 for @.JTAG_REGMAP.prescalar because the DB CPLD JTAG interface maximum clock frequency is 20 MHz.** // // // // // JTAG Master connected to second daugherboard's CPLD JTAG interface. // // **Use minimum value of 1 for @.JTAG_REGMAP.prescalar because the DB CPLD JTAG interface maximum clock frequency is 20 MHz.** // // // // // // // // Basic registers containing version and capabilities information. // // // // This enumeration is used to create the constants held in the basic registers. // // // // // // // // //XmlParse xml_off