From 7e59e9516db51bb06265cce3eb53bbcc55287432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20K=C3=B6hler?= Date: Fri, 5 Feb 2021 13:14:41 -0600 Subject: [PATCH] fpga: x400: cpld: Add support for X410 motherboard CPLD Co-authored-by: Humberto Jimenez Co-authored-by: Javier Valenzuela Original-commit: 7015f5ed2d495f3908773b7c7d74864d0cc3871a --- top/x400/cpld/.gitignore | 7 + top/x400/cpld/Makefile | 77 ++ top/x400/cpld/ctrlport_to_jtag.v | 275 ++++ top/x400/cpld/ctrlport_to_spi.v | 276 ++++ top/x400/cpld/db_spi_shared_constants.sdc | 20 + top/x400/cpld/ip/clkctrl/.gitignore | 3 + top/x400/cpld/ip/clkctrl/clkctrl.qsys | 73 + top/x400/cpld/ip/cmi/.gitignore | 2 + top/x400/cpld/ip/cmi/PcieCmi.qxp | Bin 0 -> 234390 bytes top/x400/cpld/ip/cmi/PcieCmi.vhd | 38 + top/x400/cpld/ip/cmi/PcieCmiWrapper.vhd | 93 ++ top/x400/cpld/ip/flash/.gitignore | 3 + top/x400/cpld/ip/flash/on_chip_flash.qsys | 90 ++ top/x400/cpld/ip/oddr/oddr.qip | 74 + top/x400/cpld/ip/oddr/oddr.v | 124 ++ .../cpld/ip/oddr/oddr/altera_gpio_lite.sv | 1200 +++++++++++++++++ top/x400/cpld/ip/pll/pll.ppf | 12 + top/x400/cpld/ip/pll/pll.qip | 5 + top/x400/cpld/ip/pll/pll.v | 368 +++++ top/x400/cpld/mb_cpld.qpf | 30 + top/x400/cpld/mb_cpld.qsf | 431 ++++++ top/x400/cpld/mb_cpld.sdc | 689 ++++++++++ top/x400/cpld/mb_cpld.v | 1033 ++++++++++++++ top/x400/cpld/pl_cpld_regs.v | 297 ++++ top/x400/cpld/ps_cpld_regs.v | 404 ++++++ top/x400/cpld/ps_power_regs.v | 231 ++++ top/x400/cpld/pwr_supply_clk_gen.v | 73 + top/x400/cpld/raw_conversion.cof | 39 + top/x400/cpld/reconfig_engine.v | 1024 ++++++++++++++ .../cpld/regmap/constants_regmap_utils.vh | 28 + top/x400/cpld/regmap/jtag_regmap_utils.vh | 57 + .../cpld/regmap/mb_cpld_pl_regmap_utils.vh | 36 + .../cpld/regmap/mb_cpld_ps_regmap_utils.vh | 51 + .../cpld/regmap/pl_cpld_base_regmap_utils.vh | 122 ++ .../cpld/regmap/ps_cpld_base_regmap_utils.vh | 183 +++ top/x400/cpld/regmap/ps_power_regmap_utils.vh | 54 + top/x400/cpld/regmap/reconfig_regmap_utils.vh | 135 ++ top/x400/cpld/regmap/spi_regmap_utils.vh | 69 + top/x400/cpld/reset_generator.v | 93 ++ top/x400/cpld/scripts/ps_cs_analysis.tcl | 32 + top/x400/cpld/spi_slave.v | 288 ++++ top/x400/cpld/spi_slave_to_ctrlport_master.v | 238 ++++ 42 files changed, 8377 insertions(+) create mode 100644 top/x400/cpld/.gitignore create mode 100644 top/x400/cpld/Makefile create mode 100644 top/x400/cpld/ctrlport_to_jtag.v create mode 100644 top/x400/cpld/ctrlport_to_spi.v create mode 100644 top/x400/cpld/db_spi_shared_constants.sdc create mode 100644 top/x400/cpld/ip/clkctrl/.gitignore create mode 100644 top/x400/cpld/ip/clkctrl/clkctrl.qsys create mode 100644 top/x400/cpld/ip/cmi/.gitignore create mode 100644 top/x400/cpld/ip/cmi/PcieCmi.qxp create mode 100644 top/x400/cpld/ip/cmi/PcieCmi.vhd create mode 100644 top/x400/cpld/ip/cmi/PcieCmiWrapper.vhd create mode 100644 top/x400/cpld/ip/flash/.gitignore create mode 100644 top/x400/cpld/ip/flash/on_chip_flash.qsys create mode 100644 top/x400/cpld/ip/oddr/oddr.qip create mode 100644 top/x400/cpld/ip/oddr/oddr.v create mode 100644 top/x400/cpld/ip/oddr/oddr/altera_gpio_lite.sv create mode 100644 top/x400/cpld/ip/pll/pll.ppf create mode 100644 top/x400/cpld/ip/pll/pll.qip create mode 100644 top/x400/cpld/ip/pll/pll.v create mode 100644 top/x400/cpld/mb_cpld.qpf create mode 100644 top/x400/cpld/mb_cpld.qsf create mode 100644 top/x400/cpld/mb_cpld.sdc create mode 100644 top/x400/cpld/mb_cpld.v create mode 100644 top/x400/cpld/pl_cpld_regs.v create mode 100644 top/x400/cpld/ps_cpld_regs.v create mode 100644 top/x400/cpld/ps_power_regs.v create mode 100644 top/x400/cpld/pwr_supply_clk_gen.v create mode 100644 top/x400/cpld/raw_conversion.cof create mode 100644 top/x400/cpld/reconfig_engine.v create mode 100644 top/x400/cpld/regmap/constants_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/jtag_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/mb_cpld_pl_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/mb_cpld_ps_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/pl_cpld_base_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/ps_cpld_base_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/ps_power_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/reconfig_regmap_utils.vh create mode 100644 top/x400/cpld/regmap/spi_regmap_utils.vh create mode 100644 top/x400/cpld/reset_generator.v create mode 100644 top/x400/cpld/scripts/ps_cs_analysis.tcl create mode 100644 top/x400/cpld/spi_slave.v create mode 100644 top/x400/cpld/spi_slave_to_ctrlport_master.v diff --git a/top/x400/cpld/.gitignore b/top/x400/cpld/.gitignore new file mode 100644 index 0000000..fcdcdf5 --- /dev/null +++ b/top/x400/cpld/.gitignore @@ -0,0 +1,7 @@ +# Ignore Quartus generated files upon project opening. +*.qws +db/ +incremental_db/ +output_files/ +*.sopcinfo +build/ diff --git a/top/x400/cpld/Makefile b/top/x400/cpld/Makefile new file mode 100644 index 0000000..68c6c89 --- /dev/null +++ b/top/x400/cpld/Makefile @@ -0,0 +1,77 @@ +# +# Copyright 2021 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +GIT_HASH = $(shell ../../../tools/scripts/git-hash.sh) + +build: ip + @echo -ne "\n---- Make: Synthesis ...\n\n"; + @quartus_map mb_cpld --verilog_macro="GIT_HASH=32'h$(GIT_HASH)"; + @echo -ne "\n---- Make: Partition Merge ...\n\n"; + @quartus_cdb mb_cpld --merge=on --incremental_compilation_import + @echo -ne "\n\n---- Make: Implementation ...\n\n"; + @quartus_fit mb_cpld; + @echo -ne "\n\n---- Make: Analyzing timing ...\n\n"; + @quartus_sta mb_cpld; + @# grep for unconstrained path warning + @grep "332102" output_files/mb_cpld.sta.rpt; \ + if [ $$? -eq 0 ]; then false; else true; fi + @# grep for timing closure critical warning + @grep "332148" output_files/mb_cpld.sta.rpt; \ + if [ $$? -eq 0 ]; then false; else true; fi + @# expect no warnings + @grep -iw "warning" output_files/mb_cpld.sta.rpt; \ + if [ $$? -eq 0 ]; then false; else true; fi + @# expect no critical warning except "review power analyzer report file" + @grep -i "critical warning" output_files/* | grep -v 16562; \ + if [ $$? -eq 0 ]; then false; else true; fi + @# PS chip select analysis + @quartus_sta -t scripts/ps_cs_analysis.tcl + @echo -ne "\n\n---- Make: Generating bitfile...\n\n"; + @quartus_asm mb_cpld; + @echo -ne "\n\n---- Make: Converting bitfile to svf format (ISP enabled)...\n\n"; + @quartus_cpf --convert \ + --frequency 10.0MHz \ + --voltage 2.5 \ + --operation p \ + ./output_files/mb_cpld.pof ./output_files/mb_cpld_isp_on.svf -o background_programming=on; + @echo -ne "\n\n---- Make: Converting bitfile to svf format (ISP disabled)...\n\n"; + @quartus_cpf --convert \ + --frequency 10.0MHz \ + --voltage 2.5 \ + --operation p \ + ./output_files/mb_cpld.pof ./output_files/mb_cpld_isp_off.svf; + @echo -ne "\n\n---- Make: Converting bitfile to rdp format...\n\n"; + @quartus_cpf -c raw_conversion.cof + @echo -ne "\n\n---- Make: Copy final files...\n\n"; + @mkdir -p build + @cp output_files/mb_cpld.pof build/usrp_x410_cpld.pof + @cp output_files/mb_cpld_isp_off.svf build/usrp_x410_cpld_isp_off.svf + @cp output_files/mb_cpld_isp_on.svf build/usrp_x410_cpld.svf + @cp output_files/mb_cpld_converted_cfm0_auto.rpd build/usrp_x410_cpld.rpd + @echo -ne "\n\n---- Make: MB CPLD ready!\n"; + @echo -ne " Use build/usrp_x410_cpld.pof via JTAG programmer or\n" + @echo -ne " build/usrp_x410_cpld.svf (ISP on) via PS JTAG-engine (background programming) or\n" + @echo -ne " build/usrp_x410_cpld.rpd via reconfig engine or\n" + @echo -ne " build/usrp_x410_cpld_isp_off.svf via JTAG test points (initial programming)\n" + +clean: + @echo -ne "\nCleaning MB CPLD...\n"; + @git clean -Xdf + +QSYS_PATH=$(subst \,/,$(QSYS_ROOTDIR)) + +ip: ip/flash/on_chip_flash/simulation/on_chip_flash.v \ + ip/clkctrl/clkctrl/simulation/clkctrl.v + +ip/flash/on_chip_flash/simulation/on_chip_flash.v: + $(QSYS_PATH)/qsys-generate ip/flash/on_chip_flash.qsys --simulation=VERILOG + +ip/clkctrl/clkctrl/simulation/clkctrl.v: + $(QSYS_PATH)/qsys-generate ip/clkctrl/clkctrl.qsys --simulation=VERILOG + +all: build + +.PHONY: all build clean ip diff --git a/top/x400/cpld/ctrlport_to_jtag.v b/top/x400/cpld/ctrlport_to_jtag.v new file mode 100644 index 0000000..dedc66e --- /dev/null +++ b/top/x400/cpld/ctrlport_to_jtag.v @@ -0,0 +1,275 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ctrlport_to_jtag +// +// Description: +// +// This module wraps a JTAG master and provides a ControlPort slave +// interface. +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers +// DEFAULT_PRESCALAR : Default clock divider to use +// + +`default_nettype none + + +module ctrlport_to_jtag #( + parameter BASE_ADDRESS = 0, + parameter DEFAULT_PRESCALAR = 0 +) ( + //--------------------------------------------------------------------------- + // ControlPort Slave + //--------------------------------------------------------------------------- + + input wire ctrlport_clk, + input wire ctrlport_rst, + + input wire s_ctrlport_req_wr, + input wire s_ctrlport_req_rd, + input wire [19:0] s_ctrlport_req_addr, + input wire [31:0] s_ctrlport_req_data, + output reg s_ctrlport_resp_ack, + + output reg [ 1:0] s_ctrlport_resp_status = 0, + output reg [31:0] s_ctrlport_resp_data = 0, + + //--------------------------------------------------------------------------- + // JTAG Signals + //--------------------------------------------------------------------------- + + output wire tck, + output wire tdi, + input wire tdo, + output wire tms +); + + `include "../../../lib/rfnoc/core/ctrlport.vh" + `include "./regmap/jtag_regmap_utils.vh" + + //--------------------------------------------------------------------------- + // Local Registers + //--------------------------------------------------------------------------- + + reg [ TX_DATA_SIZE-1:0] tx_data_reg; + reg [ STB_DATA_SIZE-1:0] stb_data_reg; + reg [PRESCALAR_SIZE-1:0] prescalar_reg = DEFAULT_PRESCALAR; + reg [ LENGTH_SIZE-1:0] length_reg; + reg start_reg; + reg soft_rst_stb_reg; + + //--------------------------------------------------------------------------- + // Readback Signals from JTAG Master + //--------------------------------------------------------------------------- + + wire [31:0] rd_data; + wire ready; + + //--------------------------------------------------------------------------- + // Handling of CtrlPort + //--------------------------------------------------------------------------- + + localparam NUM_ADDRESSES = 32; + wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && + (s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES); + wire soft_rst_requested = (s_ctrlport_req_addr == BASE_ADDRESS + CONTROL) && + (s_ctrlport_req_data[RESET] == 1'b1); + + always @(posedge ctrlport_clk) begin + // Reset internal registers and responses + if (ctrlport_rst) begin + tx_data_reg <= {TX_DATA_SIZE {1'b0}}; + stb_data_reg <= {STB_DATA_SIZE {1'b0}}; + prescalar_reg <= DEFAULT_PRESCALAR; + length_reg <= {LENGTH_SIZE {1'b0}}; + start_reg <= 1'b0; + soft_rst_stb_reg <= 1'b0; + s_ctrlport_resp_ack <= 1'b0; + + end else begin + // Request independent default assignments + start_reg <= 1'b0; + soft_rst_stb_reg <= 1'b0; // self-clearing strobe + + // Write requests + if (s_ctrlport_req_wr) begin + // Always issue an ack and no data + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_data <= {CTRLPORT_DATA_W{1'bx}}; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + // Process write requests only in case ready is asserted because JTAG + // module requires these values to be stable when it is not ready. + // + // The one exception is when a soft-reset is requested to reset the + // bitq_fsm, in that case that is a valid write. + if (soft_rst_requested) begin + soft_rst_stb_reg <= 1'b1; + + end else if (ready) begin + case (s_ctrlport_req_addr) + BASE_ADDRESS + TX_DATA: begin + tx_data_reg <= s_ctrlport_req_data; + end + + BASE_ADDRESS + STB_DATA: begin + stb_data_reg <= s_ctrlport_req_data; + end + + BASE_ADDRESS + CONTROL: begin + length_reg <= s_ctrlport_req_data[LENGTH_MSB:LENGTH]; + prescalar_reg <= s_ctrlport_req_data[PRESCALAR_MSB:PRESCALAR]; + // When the RESET bit is high, a soft-reset (i.e. no start strobe) + // must take place, which is handled by the default assignment. + // Otherwise, if the RESET bit is low, a start strobe should be + // issued, triggering a transaction. + start_reg <= (s_ctrlport_req_data[RESET] == 1'b0); + end + + // Error on undefined address + default: begin + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // Error in case ready is not asserted + end else begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + end + + // Read requests + end else if (s_ctrlport_req_rd) begin + // Default assumption: valid request + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + RX_DATA: begin + s_ctrlport_resp_data <= rd_data; + end + + BASE_ADDRESS + CONTROL: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}}; + s_ctrlport_resp_data[LENGTH_MSB:LENGTH] <= length_reg; + s_ctrlport_resp_data[PRESCALAR_MSB:PRESCALAR] <= prescalar_reg; + s_ctrlport_resp_data[READY] <= ready; + end + + // Error on undefined address + default: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'bx}}; + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // No request + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + end + + //--------------------------------------------------------------------------- + // JTAG Master + //--------------------------------------------------------------------------- + + // bitq_fsm reset is asserted by either the ctrlport_rst or the soft-reset + // strobe triggered through software. + wire bitq_resetn = ~(ctrlport_rst | soft_rst_stb_reg); + + bitq_fsm #( + .IDLE_VALUE (1'b0) + ) jtag_master ( + .clk (ctrlport_clk), + .rstn (bitq_resetn), + .prescalar (prescalar_reg), + .bit_clk (tck), + .bit_in (tdo), + .bit_out (tdi), + .bit_stb (tms), + .start (start_reg), + .ready (ready), + .len (length_reg), + .wr_data (tx_data_reg), + .stb_data (stb_data_reg), + .rd_data (rd_data) + ); + +endmodule + + +`default_nettype wire + + +//XmlParse xml_on +// +// +// +// +// This register map is present for each JTAG module. +// +// Basic operation would be: +// +// - poll @.ready until asserted +// - write / read data +// - write @.CONTROL register along with @.reset deasserted to start a transaction +// +// For resetting the BITQ FSM, simply assert @.reset. +// +// This operation seems a little strange, but it is what the axi_bitq driver +// expects. This behavior has been implemented in previous products. +// +// +// +// +// Data to be transmitted (TDI) +// +// +// +// Data to be transmitted (TMS) +// +// +// +// JTAG module status and control +// +// Clock divider. Resulting JTAG frequency will be f_ctrlport / (2*(prescalar + 1)). See window description for details on the initial/minimum value. +// +// +// (Number of bits - 1) to be transferred +// +// +// When asserted ('1') a soft-reset for the bitq FSM is triggered, +// preventing any transactions to take place. +// +// Deassert this bit, along with values for @.prescalar and @.length +// to trigger a new transaction (start strobe). +// +// +// Bitq FSM is ready for input (no data transmission in progress). +// +// +// +// +// Received data (TDO) +// +// +// +// +//XmlParse xml_off diff --git a/top/x400/cpld/ctrlport_to_spi.v b/top/x400/cpld/ctrlport_to_spi.v new file mode 100644 index 0000000..d4b72a7 --- /dev/null +++ b/top/x400/cpld/ctrlport_to_spi.v @@ -0,0 +1,276 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ctrlport_to_spi +// +// Description: +// +// This module wraps a SPI master and provides a ControlPort interface. +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers. +// + +`default_nettype none + + +module ctrlport_to_spi #( + parameter BASE_ADDRESS = 0 +) ( + //--------------------------------------------------------------- + // ControlPort Slave + //--------------------------------------------------------------- + + input wire ctrlport_clk, + input wire ctrlport_rst, + + input wire s_ctrlport_req_wr, + input wire s_ctrlport_req_rd, + input wire [19:0] s_ctrlport_req_addr, + input wire [31:0] s_ctrlport_req_data, + + output reg s_ctrlport_resp_ack, + output reg [ 1:0] s_ctrlport_resp_status = 0, + output reg [31:0] s_ctrlport_resp_data = 0, + + //--------------------------------------------------------------- + // SPI Signals + //--------------------------------------------------------------- + + output wire sclk, + output wire mosi, + output wire [15:0] ss, + input wire miso +); + + `include "../../../lib/rfnoc/core/ctrlport.vh" + `include "./regmap/spi_regmap_utils.vh" + + //--------------------------------------------------------------- + // Translating CtrlPort <-> Wishbone + //--------------------------------------------------------------- + + reg wb_cyc_i; // Active bus cycle + reg wb_we_i = 1'b0; // Write access + reg [ 4:0] wb_adr_i = 5'b0; + reg [31:0] wb_dat_i = 32'b0; + wire wb_ack_o; + wire [31:0] wb_dat_o; + wire wb_err_o; + + // Check for address to be in range [base_addr..base_addr+32) + localparam NUM_ADDRESSES = 32; + wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && + (s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES); + + // Following chapter 3.2.3 (classic standard SINGLE WRITE cycle) of + // https://cdn.opencores.org/downloads/wbspec_b4.pdf + always @(posedge ctrlport_clk) begin + // Reset internal registers and responses + if (ctrlport_rst) begin + wb_cyc_i <= 1'b0; + s_ctrlport_resp_ack <= 1'b0; + + end else begin + // Request independent default assignments + s_ctrlport_resp_ack <= 1'b0; + + // Wait for ack on active bus transactions + if (wb_cyc_i) begin + if (wb_ack_o) begin + // End bus cycle and generate response + wb_cyc_i <= 1'b0; + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_data <= wb_dat_o; + + if (wb_err_o) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + end else begin + s_ctrlport_resp_status <= CTRL_STS_OKAY; + end + end + + // Write requests + end else if (s_ctrlport_req_wr) begin + // Assume there is a valid address + wb_cyc_i <= 1'b1; + wb_we_i <= 1'b1; + wb_dat_i <= s_ctrlport_req_data; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + TX_DATA_LOW: begin + wb_adr_i <= 5'h00; + end + + BASE_ADDRESS + TX_DATA_HIGH: begin + wb_adr_i <= 5'h04; + end + + BASE_ADDRESS + CONTROL: begin + wb_adr_i <= 5'h10; + end + + BASE_ADDRESS + CLOCK_DIVIDER: begin + wb_adr_i <= 5'h14; + end + + BASE_ADDRESS + SLAVE_SELECT: begin + wb_adr_i <= 5'h18; + end + + // Error on undefined address + default: begin + wb_cyc_i <= 1'b0; + + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // Read requests + end else if (s_ctrlport_req_rd) begin + // Assume there is a valid address + wb_cyc_i <= 1'b1; + wb_we_i <= 1'b0; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + RX_DATA_LOW: begin + wb_adr_i <= 5'h00; + end + + BASE_ADDRESS + RX_DATA_HIGH: begin + wb_adr_i <= 5'h04; + end + + BASE_ADDRESS + CONTROL: begin + wb_adr_i <= 5'h10; + end + + BASE_ADDRESS + CLOCK_DIVIDER: begin + wb_adr_i <= 5'h14; + end + + BASE_ADDRESS + SLAVE_SELECT: begin + wb_adr_i <= 5'h18; + end + + // Error on undefined address + default: begin + wb_cyc_i <= 1'b0; + + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // No request + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + end + + //--------------------------------------------------------------- + // SPI Master + //--------------------------------------------------------------- + + spi_top spi_master ( + .wb_clk_i (ctrlport_clk), + .wb_rst_i (ctrlport_rst), + .wb_adr_i (wb_adr_i), + .wb_dat_i (wb_dat_i), + .wb_dat_o (wb_dat_o), + .wb_sel_i (4'hF), + .wb_we_i (wb_we_i), + .wb_stb_i (wb_cyc_i), + .wb_cyc_i (wb_cyc_i), + .wb_ack_o (wb_ack_o), + .wb_err_o (wb_err_o), + .wb_int_o (), + .ss_pad_o (ss), + .sclk_pad_o (sclk), + .mosi_pad_o (mosi), + .miso_pad_i (miso) + ); + +endmodule + + +`default_nettype wire + + +//XmlParse xml_on +// +// +// +// +// This register map is present for each SPI master. +// +// For information about the register content and the way to interact with the core see the +// documentation +// of the SPI master from opencores used internally. +// +// The core is configured to operate with 16 slave signal signals, up to 128 bits per transmission and 8 bit clock divider. +// Only 64 bits of data are available via this register interface. +// +// For the different SPI modes use the following table to derive the bits in @.CONTROL register. Only option 0 (CPOL=0, CPHA=0) has been tested. +// +//| CPOL | CPHA | TX_NEG | RX_NEG | +//| ------- | -------- | -------- | ------- | +//| 0 | 0 | 1 | 0 | +//| 0 | 1 | 0 | 1 | +//| 1 | 0 | 0 | 1 | +//| 1 | 1 | 1 | 0 | +// +// +// +// Lower 32 bits of the received word. (RxWord[31:0]) +// +// +// +// Higher 32 bits of the received word. (RxWord[63:32]) +// +// +// +// Lower 32 bits of the received word. (TxWord[31:0]) +// +// +// +// Higher 32 bits of the received word. (TxWord[63:32]) +// +// +// +// Control register +// + +// +// +// +// Clock Divider. +// +// +// +// +// +// +// Slave select. +// +// +// +// +// +// +//XmlParse xml_off diff --git a/top/x400/cpld/db_spi_shared_constants.sdc b/top/x400/cpld/db_spi_shared_constants.sdc new file mode 100644 index 0000000..21935c2 --- /dev/null +++ b/top/x400/cpld/db_spi_shared_constants.sdc @@ -0,0 +1,20 @@ +# +# Copyright 2021 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# +# Description: +# +# Timing constants for the MB CPLD <-> DB CPLD SPI interface +# + +# Delays are rounded to integer values which leave a slack of >1ns on each setup +# and hold path without requirement for adding hold delays (as reported +# by Quartus fitter report). +# The signal might change before the SCLK edge as the internal +# registers are driven by PLL reference clock rather than the SPI clock used +# for the port timing constaints. +set db_cpld_spi_max_out 14.000 +set db_cpld_spi_min_out 2.000 +set db_cpld_spi_max_in 2.000 +set db_cpld_spi_min_in -2.000 diff --git a/top/x400/cpld/ip/clkctrl/.gitignore b/top/x400/cpld/ip/clkctrl/.gitignore new file mode 100644 index 0000000..9776d9b --- /dev/null +++ b/top/x400/cpld/ip/clkctrl/.gitignore @@ -0,0 +1,3 @@ +# generate files +clkctrl/ +clkctrl.sopcinfo \ No newline at end of file diff --git a/top/x400/cpld/ip/clkctrl/clkctrl.qsys b/top/x400/cpld/ip/clkctrl/clkctrl.qsys new file mode 100644 index 0000000..b9fc219 --- /dev/null +++ b/top/x400/cpld/ip/clkctrl/clkctrl.qsys @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/top/x400/cpld/ip/cmi/.gitignore b/top/x400/cpld/ip/cmi/.gitignore new file mode 100644 index 0000000..f479dbc --- /dev/null +++ b/top/x400/cpld/ip/cmi/.gitignore @@ -0,0 +1,2 @@ +# GUI logfile +PcieCmi.qarlog diff --git a/top/x400/cpld/ip/cmi/PcieCmi.qxp b/top/x400/cpld/ip/cmi/PcieCmi.qxp new file mode 100644 index 0000000000000000000000000000000000000000..c03dfd331323b6e9c37451c20f49c88b6c9276af GIT binary patch literal 234390 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

b`EF7MrA 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 z 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 literal 0 HcmV?d00001 diff --git a/top/x400/cpld/ip/cmi/PcieCmi.vhd b/top/x400/cpld/ip/cmi/PcieCmi.vhd new file mode 100644 index 0000000..8bd0fbb --- /dev/null +++ b/top/x400/cpld/ip/cmi/PcieCmi.vhd @@ -0,0 +1,38 @@ +-- +-- Copyright 2021 Ettus Research, a National Instruments Brand +-- +-- SPDX-License-Identifier: LGPL-3.0-or-later +-- +-- Module: PcieCmi +-- +-- Description: +-- +-- This is an automatically generated file. +-- Do not modify this file directly! +-- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity PcieCmi is + generic ( + kSimulation : natural := 0 + ); + port ( + Clk : in std_logic ; + acReset : in std_logic ; + cSerialNumber : in std_logic_vector (39 downto 0); + cBoardIsReady : in std_logic ; + cCmiReset : out std_logic ; + cOtherSideDetected : out std_logic ; + aCblPrsnt_n : in std_logic ; + aSdaIn : in std_logic ; + aSdaOut : out std_logic ; + aSclIn : in std_logic ; + aSclOut : out std_logic + ); +end entity PcieCmi; +architecture rtl of PcieCmi is +begin +end architecture rtl; diff --git a/top/x400/cpld/ip/cmi/PcieCmiWrapper.vhd b/top/x400/cpld/ip/cmi/PcieCmiWrapper.vhd new file mode 100644 index 0000000..2037d10 --- /dev/null +++ b/top/x400/cpld/ip/cmi/PcieCmiWrapper.vhd @@ -0,0 +1,93 @@ +-- +-- Copyright 2021 Ettus Research, a National Instruments Brand +-- +-- SPDX-License-Identifier: LGPL-3.0-or-later +-- +-- Module: PcieCmiWrapper +-- +-- Description: +-- +-- This is an automatically generated file. +-- Do not modify this file directly! +-- + + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +--synopsys translate_off +--For synthesis, netlist comes from an qxp and there is no external library +--For simulation in client, netlist comes from PcieCmiLib external library +--For simulation in dev branch, netlist comes from work library. +--Binding will work fine in both simulation cases as long as PcieCmi is compiled +-- to either library. In dev branch PcieCmiLib will be an empty library just so +-- ModelSim doesn't complain. +library PcieCmiLib; +--synopsys translate_on + +entity PcieCmiWrapper is + generic ( + kSimulation : natural := 0 -- set to 1 to speedup simulation + ); + port ( + Clk : in std_logic; -- 40 MHz clock + acReset : in std_logic; + + cSerialNumber : in std_logic_vector(39 downto 0); + cBoardIsReady : in std_logic; + cCmiReset : out std_logic; + cOtherSideDetected : out std_logic; + + aCblPrsnt_n : in std_logic; + + aSdaIn : in std_logic; + aSdaOut : out std_logic; + aSclIn : in std_logic; + aSclOut : out std_logic + ); +end PcieCmiWrapper; + +architecture rtl of PcieCmiWrapper is + + component PcieCmi + generic (kSimulation : natural := 0); + port ( + Clk : in std_logic; + acReset : in std_logic; + cSerialNumber : in std_logic_vector(39 downto 0); + cBoardIsReady : in std_logic; + cCmiReset : out std_logic; + cOtherSideDetected : out std_logic; + aCblPrsnt_n : in std_logic; + aSdaIn : in std_logic; + aSdaOut : out std_logic; + aSclIn : in std_logic; + aSclOut : out std_logic); + end component; + +begin + + -- Just forward all signals to lower level entity. + -- Leave the simulation generic in place as it important to be able to + -- simulate the netlist in reasonable time. For the synthesis in the client + -- the generic is ignored as the netlist is translated with kSimulation set to + -- default value and "overwrites" it. + + --vhook PcieCmi + PcieCmix: PcieCmi + generic map (kSimulation => kSimulation) --natural:=0 + port map ( + Clk => Clk, --in std_logic + acReset => acReset, --in std_logic + cSerialNumber => cSerialNumber, --in std_logic_vector(39:0) + cBoardIsReady => cBoardIsReady, --in std_logic + cCmiReset => cCmiReset, --out std_logic + cOtherSideDetected => cOtherSideDetected, --out std_logic + aCblPrsnt_n => aCblPrsnt_n, --in std_logic + aSdaIn => aSdaIn, --in std_logic + aSdaOut => aSdaOut, --out std_logic + aSclIn => aSclIn, --in std_logic + aSclOut => aSclOut); --out std_logic + +end architecture rtl; \ No newline at end of file diff --git a/top/x400/cpld/ip/flash/.gitignore b/top/x400/cpld/ip/flash/.gitignore new file mode 100644 index 0000000..585bc12 --- /dev/null +++ b/top/x400/cpld/ip/flash/.gitignore @@ -0,0 +1,3 @@ +# generate files +on_chip_flash/ +on_chip_flash.sopcinfo diff --git a/top/x400/cpld/ip/flash/on_chip_flash.qsys b/top/x400/cpld/ip/flash/on_chip_flash.qsys new file mode 100644 index 0000000..4cbe872 --- /dev/null +++ b/top/x400/cpld/ip/flash/on_chip_flash.qsys @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Single Compressed Image + Internal Configuration + + + + + + Read and write,Read and write,Read and write,Read and write,Read and write + $${FILENAME}_onchip_flash_0 + + altera_onchip_flash.hex + altera_onchip_flash.dat + + + + + + + diff --git a/top/x400/cpld/ip/oddr/oddr.qip b/top/x400/cpld/ip/oddr/oddr.qip new file mode 100644 index 0000000..206cf7b --- /dev/null +++ b/top/x400/cpld/ip/oddr/oddr.qip @@ -0,0 +1,74 @@ +set_global_assignment -entity "oddr" -library "oddr" -name IP_TOOL_NAME "altera_gpio_lite" +set_global_assignment -entity "oddr" -library "oddr" -name IP_TOOL_VERSION "20.1" +set_global_assignment -entity "oddr" -library "oddr" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "oddr" -name MISC_FILE [file join $::quartus(qip_path) "oddr.cmp"] +set_global_assignment -entity "oddr" -library "oddr" -name IP_TARGETED_DEVICE_FAMILY "MAX 10" +set_global_assignment -entity "oddr" -library "oddr" -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}" +set_global_assignment -entity "oddr" -library "oddr" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_NAME "b2Rkcg==" +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_DISPLAY_NAME "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA=" +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24=" +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_VERSION "MjAuMQ==" +set_global_assignment -entity "oddr" -library "oddr" -name IP_COMPONENT_DESCRIPTION "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_NAME "YWx0ZXJhX2dwaW9fbGl0ZQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_DISPLAY_NAME "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_AUTHOR "SW50ZWwgQ29ycG9yYXRpb24=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_VERSION "MjAuMQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_DESCRIPTION "R1BJTyBMaXRlIEludGVsIEZQR0EgSVA=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "REVWSUNFX0ZBTUlMWQ==::TUFYIDEw::RGV2aWNlIGZhbWlseQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "UElOX1RZUEU=::b3V0cHV0::RGF0YSBkaXJlY3Rpb24=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "U0laRQ==::MQ==::RGF0YSB3aWR0aA==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX3RydWVfZGlmZl9idWY=::ZmFsc2U=::VXNlIHRydWUgZGlmZmVyZW50aWFsIGJ1ZmZlcg==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX3BzZXVkb19kaWZmX2J1Zg==::ZmFsc2U=::VXNlIHBzZXVkbyBkaWZmZXJlbnRpYWwgYnVmZmVy" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2J1c19ob2xk::ZmFsc2U=::VXNlIGJ1cy1ob2xkIGNpcmN1aXRyeQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX29wZW5fZHJhaW4=::ZmFsc2U=::VXNlIG9wZW4gZHJhaW4gb3V0cHV0" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9vZV9wb3J0::ZmFsc2U=::RW5hYmxlIG9lIHBvcnQ=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2lvX3JlZ19tb2Rl::ZGRy::UmVnaXN0ZXIgbW9kZQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9hY2xyX3BvcnQ=::dHJ1ZQ==::RW5hYmxlIGFjbHIgcG9ydA==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2Nsb2NrX2VuYWJsZQ==::ZmFsc2U=::RW5hYmxlIGluY2xvY2tlbi9vdXRjbG9ja2VuIHBvcnRz" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9vdXRwdXQ=::ZmFsc2U=::SW52ZXJ0IGRpbg==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9yZWdpc3Rlcl90b19kcml2ZV9vYnVmX29l::ZmFsc2U=::VXNlIGEgc2luZ2xlIHJlZ2lzdGVyIHRvIGRyaXZlIHRoZSBvdXRwdXQgZW5hYmxlIChvZSkgc2lnbmFsIGF0IHRoZSBJL08gYnVmZmVy" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9kZGlvX3JlZ190b19kcml2ZV9vZQ==::ZmFsc2U=::VXNlIERESU8gcmVnaXN0ZXJzIHRvIGRyaXZlIHRoZSBvdXRwdXQgZW5hYmxlIChvZSkgc2lnbmFsIGF0IHRoZSBJL08gYnVmZmVy" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9hZHZhbmNlZF9kZHJfZmVhdHVyZXM=::ZmFsc2U=::RW5hYmxlIGFkdmFuY2VkIEREUiBmZWF0dXJlcw==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9waGFzZV9kZXRlY3Rvcl9mb3JfY2s=::ZmFsc2U=::RW5hYmxlIFBoYXNlIERldGVjdG9yIGZyb20gQ0sgbG9vcGJhY2sgc2lnbmFs" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9vZV9oYWxmX2N5Y2xlX2RlbGF5::dHJ1ZQ==::QWRkIGhhbGYtY3ljbGUgZGVsYXkgdG8gT0Ugc2lnbmFs" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9ocl9jbG9jaw==::ZmFsc2U=::RW5hYmxlIGhhbGYtcmF0ZSBjbG9jayBwb3J0" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9pbnZlcnRfaHJfY2xvY2tfcG9ydA==::ZmFsc2U=::RW5hYmxlIGludmVydF9ocl9jbG9jayBwb3J0" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9jbGtkaXZfaW5wdXRfY2xvY2s=::ZmFsc2U=::SW52ZXJ0IGNsb2NrIGRpdmlkZXIgaW5wdXQgY2xvY2s=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9vdXRwdXRfY2xvY2s=::ZmFsc2U=::SW52ZXJ0IERESU8gb3V0Y2xvY2s=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "Z3VpX2ludmVydF9vZV9pbmNsb2Nr::ZmFsc2U=::SW52ZXJ0IG91dHB1dCBlbmFibGUgKG9lKSByZWdpc3RlciBpbmNsb2Nr" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "UkVHSVNURVJfTU9ERQ==::ZGRy::UkVHSVNURVJfTU9ERQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "QlVGRkVSX1RZUEU=::c2luZ2xlLWVuZGVk::QlVGRkVSX1RZUEU=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "QVNZTkNfTU9ERQ==::Y2xlYXI=::QVNZTkNfTU9ERQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "U1lOQ19NT0RF::bm9uZQ==::U1lOQ19NT0RF" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "QlVTX0hPTEQ=::ZmFsc2U=::QlVTX0hPTEQ=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "T1BFTl9EUkFJTl9PVVRQVVQ=::ZmFsc2U=::T1BFTl9EUkFJTl9PVVRQVVQ=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX09FX1BPUlQ=::ZmFsc2U=::RU5BQkxFX09FX1BPUlQ=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX05TTEVFUF9QT1JU::ZmFsc2U=::RU5BQkxFX05TTEVFUF9QT1JU" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0NMT0NLX0VOQV9QT1JU::ZmFsc2U=::RU5BQkxFX0NMT0NLX0VOQV9QT1JU" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "U0VUX1JFR0lTVEVSX09VVFBVVFNfSElHSA==::ZmFsc2U=::U0VUX1JFR0lTVEVSX09VVFBVVFNfSElHSA==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "SU5WRVJUX09VVFBVVA==::ZmFsc2U=::SU5WRVJUX09VVFBVVA==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "SU5WRVJUX0lOUFVUX0NMT0NL::ZmFsc2U=::SU5WRVJUX0lOUFVUX0NMT0NL" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "VVNFX09ORV9SRUdfVE9fRFJJVkVfT0U=::ZmFsc2U=::VVNFX09ORV9SRUdfVE9fRFJJVkVfT0U=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "VVNFX0RESU9fUkVHX1RPX0RSSVZFX09F::ZmFsc2U=::VVNFX0RESU9fUkVHX1RPX0RSSVZFX09F" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFUw==::ZmFsc2U=::VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFUw==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFU19GT1JfSU5QVVRfT05MWQ==::ZmFsc2U=::VVNFX0FEVkFOQ0VEX0REUl9GRUFUVVJFU19GT1JfSU5QVVRfT05MWQ==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX09FX0hBTEZfQ1lDTEVfREVMQVk=::dHJ1ZQ==::RU5BQkxFX09FX0hBTEZfQ1lDTEVfREVMQVk=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "SU5WRVJUX0NMS0RJVl9JTlBVVF9DTE9DSw==::ZmFsc2U=::SU5WRVJUX0NMS0RJVl9JTlBVVF9DTE9DSw==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX1BIQVNFX0lOVkVSVF9DVFJMX1BPUlQ=::ZmFsc2U=::RU5BQkxFX1BIQVNFX0lOVkVSVF9DVFJMX1BPUlQ=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX0hSX0NMT0NL::ZmFsc2U=::RU5BQkxFX0hSX0NMT0NL" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "SU5WRVJUX09VVFBVVF9DTE9DSw==::ZmFsc2U=::SU5WRVJUX09VVFBVVF9DTE9DSw==" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "SU5WRVJUX09FX0lOQ0xPQ0s=::ZmFsc2U=::SU5WRVJUX09FX0lOQ0xPQ0s=" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_COMPONENT_PARAMETER "RU5BQkxFX1BIQVNFX0RFVEVDVE9SX0ZPUl9DSw==::ZmFsc2U=::RU5BQkxFX1BIQVNFX0RFVEVDVE9SX0ZPUl9DSw==" + +set_global_assignment -library "oddr" -name VERILOG_FILE [file join $::quartus(qip_path) "oddr.v"] +set_global_assignment -library "oddr" -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) "oddr/altera_gpio_lite.sv"] + +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_TOOL_NAME "altera_gpio_lite" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_TOOL_VERSION "20.1" +set_global_assignment -entity "altera_gpio_lite" -library "oddr" -name IP_TOOL_ENV "mwpim" diff --git a/top/x400/cpld/ip/oddr/oddr.v b/top/x400/cpld/ip/oddr/oddr.v new file mode 100644 index 0000000..7888cbc --- /dev/null +++ b/top/x400/cpld/ip/oddr/oddr.v @@ -0,0 +1,124 @@ +// megafunction wizard: %GPIO Lite Intel FPGA IP v20.1% +// GENERATION: XML +// oddr.v + +// Generated using ACDS version 20.1 711 + +`timescale 1 ps / 1 ps +module oddr ( + input wire outclock, // outclock.export + input wire [1:0] din, // din.export + output wire [0:0] pad_out, // pad_out.export + input wire aclr // aclr.export + ); + + altera_gpio_lite #( + .PIN_TYPE ("output"), + .SIZE (1), + .REGISTER_MODE ("ddr"), + .BUFFER_TYPE ("single-ended"), + .ASYNC_MODE ("clear"), + .SYNC_MODE ("none"), + .BUS_HOLD ("false"), + .OPEN_DRAIN_OUTPUT ("false"), + .ENABLE_OE_PORT ("false"), + .ENABLE_NSLEEP_PORT ("false"), + .ENABLE_CLOCK_ENA_PORT ("false"), + .SET_REGISTER_OUTPUTS_HIGH ("false"), + .INVERT_OUTPUT ("false"), + .INVERT_INPUT_CLOCK ("false"), + .USE_ONE_REG_TO_DRIVE_OE ("false"), + .USE_DDIO_REG_TO_DRIVE_OE ("false"), + .USE_ADVANCED_DDR_FEATURES ("false"), + .USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY ("false"), + .ENABLE_OE_HALF_CYCLE_DELAY ("true"), + .INVERT_CLKDIV_INPUT_CLOCK ("false"), + .ENABLE_PHASE_INVERT_CTRL_PORT ("false"), + .ENABLE_HR_CLOCK ("false"), + .INVERT_OUTPUT_CLOCK ("false"), + .INVERT_OE_INCLOCK ("false"), + .ENABLE_PHASE_DETECTOR_FOR_CK ("false") + ) oddr_inst ( + .outclock (outclock), // outclock.export + .din (din), // din.export + .pad_out (pad_out), // pad_out.export + .aclr (aclr), // aclr.export + .outclocken (1'b1), // (terminated) + .inclock (1'b0), // (terminated) + .inclocken (1'b0), // (terminated) + .fr_clock (), // (terminated) + .hr_clock (), // (terminated) + .invert_hr_clock (1'b0), // (terminated) + .phy_mem_clock (1'b0), // (terminated) + .mimic_clock (), // (terminated) + .dout (), // (terminated) + .pad_io (), // (terminated) + .pad_io_b (), // (terminated) + .pad_in (1'b0), // (terminated) + .pad_in_b (1'b0), // (terminated) + .pad_out_b (), // (terminated) + .aset (1'b0), // (terminated) + .sclr (1'b0), // (terminated) + .nsleep (1'b0), // (terminated) + .oe (1'b0) // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : oddr.vo +// RELATED_FILES: oddr.v, altera_gpio_lite.sv diff --git a/top/x400/cpld/ip/oddr/oddr/altera_gpio_lite.sv b/top/x400/cpld/ip/oddr/oddr/altera_gpio_lite.sv new file mode 100644 index 0000000..7db3694 --- /dev/null +++ b/top/x400/cpld/ip/oddr/oddr/altera_gpio_lite.sv @@ -0,0 +1,1200 @@ +// (C) 2001-2020 Intel Corporation. All rights reserved. +// Your use of Intel Corporation's design tools, logic functions and other +// software and tools, and its AMPP partner logic functions, and any output +// files from any of the foregoing (including device programming or simulation +// files), and any associated documentation or information are expressly subject +// to the terms and conditions of the Intel Program License Subscription +// Agreement, Intel FPGA IP License Agreement, or other applicable +// license agreement, including, without limitation, that your use is for the +// sole purpose of programming logic devices manufactured by Intel and sold by +// Intel or its authorized distributors. Please refer to the applicable +// agreement for further details. + + +`timescale 1 ps / 1 ps + +module altgpio_one_bit( + inclock, + outclock, + phy_mem_clock, + inclocken, + outclocken, + oe, + din, + dout, + pad, + pad_b, + aset, + sclr, + hr_clock, + fr_clock, + mimic_clock, + nsleep +); + + parameter PIN_TYPE = "output"; + parameter BUFFER_TYPE = "single-ended"; + parameter REGISTER_MODE = "bypass"; + parameter ASYNC_MODE = "none"; + parameter SYNC_MODE = "none"; + parameter BUS_HOLD = "false"; + parameter SET_REGISTER_OUTPUTS_HIGH = "false"; + parameter USE_ENHANCED_DDR_HIO_REGISTER = "false"; + parameter BYPASS_THREE_QUARTER_REGISTER = "true"; + parameter INVERT_OUTPUT = "false"; + parameter INVERT_INPUT_CLOCK = "false"; + parameter INVERT_OUTPUT_CLOCK = "false"; + parameter INVERT_OE_INCLOCK = "false"; + parameter USE_ONE_REG_TO_DRIVE_OE = "false"; + parameter USE_DDIO_REG_TO_DRIVE_OE = "false"; + parameter OPEN_DRAIN_OUTPUT = "false"; + parameter ENABLE_OE_HALF_CYCLE_DELAY = "true"; + parameter USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY = "false"; + parameter ENABLE_CLOCK_ENA_PORT = "false"; + parameter ENABLE_HR_CLOCK = "false"; + parameter ENABLE_PHASE_DETECTOR_FOR_CK = "false"; + parameter ENABLE_NSLEEP_PORT = "false"; + + localparam DATA_SIZE = (REGISTER_MODE == "ddr") ? 2:1; + localparam DDIO_REG_POWER_UP = (ASYNC_MODE == "preset" || SET_REGISTER_OUTPUTS_HIGH == "true") ? "high" : "low"; + + input inclock; + input outclock; + input inclocken; + input outclocken; + input oe; + input nsleep; + input [DATA_SIZE - 1:0] din; + output [DATA_SIZE - 1:0] dout; + inout pad; + inout pad_b; + input aset; + input sclr; + input phy_mem_clock; + input hr_clock; + (* altera_attribute = "-name GLOBAL_SIGNAL\"OFF\"" *) output fr_clock; + output mimic_clock; + + wire din_ddr; + wire buf_in; + + wire oe_out; + wire nsleep_in; + + generate + if (PIN_TYPE == "output" || PIN_TYPE == "bidir") + begin + wire [1:0] din_fr; + if (INVERT_OUTPUT == "false") + begin + assign din_fr = din; + end + else + begin + assign din_fr = ~din; + end + + wire outclock_wire; + if (REGISTER_MODE != "bypass") + begin + if (INVERT_OUTPUT_CLOCK == "false") + begin: normal_input_clock + assign outclock_wire = outclock; + end + else + begin: inverted_output_clock + assign outclock_wire = ~outclock; + end + end + + wire outclocken_wire; + assign outclocken_wire = (ENABLE_CLOCK_ENA_PORT == "true") ? outclocken : 1'b1; + + if (REGISTER_MODE == "ddr" && USE_ENHANCED_DDR_HIO_REGISTER == "true") + begin + if (ASYNC_MODE != "none") + begin: async_mode_out_path_enhanced_ddr + fiftyfivenm_ddio_out + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .use_enhanced_ddr_hio(USE_ENHANCED_DDR_HIO_REGISTER), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER), + .power_up(DDIO_REG_POWER_UP), + .use_new_clocking_model("true") + ) fr_out_data_ddio ( + .datainhi(din_fr[0]), + .datainlo(din_fr[1]), + .dataout(din_ddr), + .clkhi(outclock_wire), + .clklo(outclock_wire), + .muxsel(outclock_wire), + .areset(aset), + .ena(outclocken_wire), + .phymemclock(phy_mem_clock) + `ifndef ALTERA_RESERVED_QIS + , + .clk (outclock_wire), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else if (SYNC_MODE != "none") + begin: sync_mode_out_path_enhanced_ddr + fiftyfivenm_ddio_out + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .use_enhanced_ddr_hio(USE_ENHANCED_DDR_HIO_REGISTER), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER), + .power_up(DDIO_REG_POWER_UP), + .use_new_clocking_model("true") + ) fr_out_data_ddio ( + .datainhi(din_fr[0]), + .datainlo(din_fr[1]), + .dataout(din_ddr), + .clkhi(outclock_wire), + .clklo(outclock_wire), + .muxsel(outclock_wire), + .sreset(sclr), + .ena(outclocken_wire), + .phymemclock(phy_mem_clock) + `ifndef ALTERA_RESERVED_QIS + , + .clk (outclock_wire), + .areset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else + begin: out_path_enhanced_ddr + fiftyfivenm_ddio_out + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .use_enhanced_ddr_hio(USE_ENHANCED_DDR_HIO_REGISTER), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER), + .power_up(DDIO_REG_POWER_UP), + .use_new_clocking_model("true") + ) fr_out_data_ddio ( + .datainhi(din_fr[0]), + .datainlo(din_fr[1]), + .dataout(din_ddr), + .clkhi(outclock_wire), + .clklo(outclock_wire), + .muxsel(outclock_wire), + .ena(outclocken_wire), + .phymemclock(phy_mem_clock) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .clk(1'b0), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + end + else if (REGISTER_MODE == "ddr" && USE_ENHANCED_DDR_HIO_REGISTER == "false") + begin + if (ASYNC_MODE != "none") + begin: async_mode_out_path_ddr + fiftyfivenm_ddio_out + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .use_new_clocking_model("true"), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER) + ) fr_out_data_ddio ( + .datainhi(din_fr[0]), + .datainlo(din_fr[1]), + .dataout(din_ddr), + .clkhi(outclock_wire), + .clklo(outclock_wire), + .muxsel(outclock_wire), + .areset(aset), + .ena(outclocken_wire) + `ifndef ALTERA_RESERVED_QIS + , + .clk(1'b0), + .phymemclock(1'b0), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else if (SYNC_MODE != "none") + begin: sync_mode_out_path_ddr + fiftyfivenm_ddio_out + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .use_new_clocking_model("true"), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER) + ) fr_out_data_ddio ( + .datainhi(din_fr[0]), + .datainlo(din_fr[1]), + .dataout(din_ddr), + .clkhi(outclock_wire), + .clklo(outclock_wire), + .muxsel(outclock_wire), + .sreset(sclr), + .ena(outclocken_wire) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .clk(1'b0), + .phymemclock(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else + begin: out_path_ddr + fiftyfivenm_ddio_out + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .use_new_clocking_model("true"), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER) + ) fr_out_data_ddio ( + .datainhi(din_fr[0]), + .datainlo(din_fr[1]), + .dataout(din_ddr), + .clkhi(outclock_wire), + .clklo(outclock_wire), + .muxsel(outclock_wire), + .ena(outclocken_wire) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .clk(1'b0), + .phymemclock(1'b0), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + end + else if (REGISTER_MODE == "single-register") + begin: out_path_sdr + reg reg_data_out /* synthesis altera_attribute="FAST_OUTPUT_REGISTER=on" */; + always @(posedge outclock_wire) + reg_data_out <= din_fr[0]; + + assign din_ddr = reg_data_out; + end + else + begin: out_path_reg_none + assign din_ddr = din_fr[0]; + end + end + endgenerate + + generate + + if (PIN_TYPE == "bidir" || PIN_TYPE == "output") + begin + wire oe_inclk_wire; + if (USE_ONE_REG_TO_DRIVE_OE == "true" || USE_DDIO_REG_TO_DRIVE_OE == "true") + begin + if (INVERT_OE_INCLOCK == "false") + begin: normal_oe_inclock + assign oe_inclk_wire = outclock; + end + else + begin: inverted_oe_inclock + assign oe_inclk_wire = ~outclock; + end + end + + wire oe_outclocken_wire; + assign oe_outclocken_wire = (ENABLE_CLOCK_ENA_PORT == "true") ? outclocken : 1'b1; + + if (USE_DDIO_REG_TO_DRIVE_OE == "true") + begin + if (REGISTER_MODE == "ddr" && USE_ENHANCED_DDR_HIO_REGISTER == "true") + begin + if (ASYNC_MODE != "none") + begin: async_mode_oe_path_enhanced_ddr + fiftyfivenm_ddio_oe + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .use_enhanced_ddr_hio(USE_ENHANCED_DDR_HIO_REGISTER), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER), + .enable_half_cycle_delay(ENABLE_OE_HALF_CYCLE_DELAY), + .power_up(DDIO_REG_POWER_UP) + ) fr_oe_data_ddio ( + .oe(~oe), + .dataout(oe_out), + .clk(oe_inclk_wire), + .areset(aset), + .ena(oe_outclocken_wire), + .phymemclock(phy_mem_clock) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else if (SYNC_MODE != "none") + begin: sync_mode_oe_path_enhanced_ddr + fiftyfivenm_ddio_oe + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .use_enhanced_ddr_hio(USE_ENHANCED_DDR_HIO_REGISTER), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER), + .enable_half_cycle_delay(ENABLE_OE_HALF_CYCLE_DELAY), + .power_up(DDIO_REG_POWER_UP) + ) fr_oe_data_ddio ( + .oe(~oe), + .dataout(oe_out), + .clk(oe_inclk_wire), + .sreset(sclr), + .ena(oe_outclocken_wire), + .phymemclock(phy_mem_clock) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else + begin: oe_path_enhanced_ddr + fiftyfivenm_ddio_oe + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .use_enhanced_ddr_hio(USE_ENHANCED_DDR_HIO_REGISTER), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER), + .enable_half_cycle_delay(ENABLE_OE_HALF_CYCLE_DELAY), + .power_up(DDIO_REG_POWER_UP) + ) fr_oe_data_ddio ( + .oe(~oe), + .dataout(oe_out), + .clk(oe_inclk_wire), + .ena(oe_outclocken_wire), + .phymemclock(phy_mem_clock) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + end + else if (REGISTER_MODE == "ddr" && USE_ENHANCED_DDR_HIO_REGISTER == "false") + begin + if (ASYNC_MODE != "none") + begin: async_mode_oe_path_ddr + fiftyfivenm_ddio_oe + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .enable_half_cycle_delay(ENABLE_OE_HALF_CYCLE_DELAY), + .power_up(DDIO_REG_POWER_UP), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER) + ) fr_oe_data_ddio ( + .oe(~oe), + .dataout(oe_out), + .clk(oe_inclk_wire), + .areset(aset), + .ena(oe_outclocken_wire) + `ifndef ALTERA_RESERVED_QIS + , + .phymemclock(1'b0), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else if (SYNC_MODE != "none") + begin: sync_mode_oe_path_ddr + fiftyfivenm_ddio_oe + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .enable_half_cycle_delay(ENABLE_OE_HALF_CYCLE_DELAY), + .power_up(DDIO_REG_POWER_UP), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER) + ) fr_oe_data_ddio ( + .oe(~oe), + .dataout(oe_out), + .clk(oe_inclk_wire), + .sreset(sclr), + .ena(oe_outclocken_wire) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .phymemclock(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else + begin: oe_path_ddr + fiftyfivenm_ddio_oe + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .enable_half_cycle_delay(ENABLE_OE_HALF_CYCLE_DELAY), + .power_up(DDIO_REG_POWER_UP), + .bypass_three_quarter_register(BYPASS_THREE_QUARTER_REGISTER) + ) fr_oe_data_ddio ( + .oe(~oe), + .dataout(oe_out), + .clk(oe_inclk_wire), + .ena(oe_outclocken_wire) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .phymemclock(1'b0), + .sreset(1'b0), + .dfflo(), + .dffhi(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + end + end + else if (USE_ONE_REG_TO_DRIVE_OE == "true") + begin: oe_path_sdr + fiftyfivenm_ff oe_reg ( + .clk(oe_inclk_wire), + .d(~oe), + .clrn(1'b1), + .ena(1'b1), + .q(oe_out) + ); + end + else if (USE_ONE_REG_TO_DRIVE_OE == "false" && USE_DDIO_REG_TO_DRIVE_OE == "false") + begin: oe_path_reg_none + assign oe_out = ~oe; + end + end + endgenerate + + generate + if (PIN_TYPE == "input" || PIN_TYPE == "bidir") + begin + wire [1:0] ddr_input; + wire inclock_wire; + + if (REGISTER_MODE != "bypass") + begin + if (INVERT_INPUT_CLOCK == "false") + begin: normal_input_clock + assign inclock_wire = inclock; + end + else + begin: inverted_input_clock + assign inclock_wire = ~inclock; + end + end + + wire inclocken_wire; + assign inclocken_wire = (ENABLE_CLOCK_ENA_PORT == "true") ? inclocken : 1'b1; + + if (REGISTER_MODE == "ddr") + begin + if (USE_ENHANCED_DDR_HIO_REGISTER == "true" || USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY == "true") + begin + if (ENABLE_HR_CLOCK == "true") + begin + if (ASYNC_MODE != "none") + begin: async_mode_in_path_enhanced_ddr_with_halfrateresyncclk + fiftyfivenm_ddio_in + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .invert_input_clock(INVERT_INPUT_CLOCK) + ) fr_in_ddio ( + .datain(buf_in), + .clk(inclock_wire), + .ena(inclocken_wire), + .halfrateresyncclk(hr_clock), + .regouthi(ddr_input[1]), + .regoutlo(ddr_input[0]), + .clkout(fr_clock), + .areset(aset) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0), + .dfflo(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else if (SYNC_MODE != "none") + begin:sync_mode_in_path_enhanced_ddr_with_halfrateresyncclk + fiftyfivenm_ddio_in + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .invert_input_clock(INVERT_INPUT_CLOCK) + ) fr_in_ddio ( + .datain(buf_in), + .clk (inclock_wire), + .ena(inclocken_wire), + .sreset(sclr), + .halfrateresyncclk(hr_clock), + .regouthi(ddr_input[1]), + .regoutlo(ddr_input[0]), + .clkout(fr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .dfflo(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + else + begin:in_path_enhanced_ddr_with_halfrateresyncclk + fiftyfivenm_ddio_in + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .invert_input_clock(INVERT_INPUT_CLOCK) + ) fr_in_ddio ( + .datain(buf_in), + .clk (inclock_wire), + .ena(inclocken_wire), + .halfrateresyncclk(hr_clock), + .regouthi(ddr_input[1]), + .regoutlo(ddr_input[0]), + .clkout(fr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0), + .areset(1'b0), + .dfflo(), + .devpor(1'b1), + .devclrn(1'b1) + `endif + ); + end + end + else + begin + if (ASYNC_MODE != "none") + begin: async_mode_in_path_enhanced_ddr + fiftyfivenm_ddio_in + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .invert_input_clock(INVERT_INPUT_CLOCK) + ) fr_in_ddio ( + .datain(buf_in), + .clk(inclock_wire), + .ena(inclocken_wire), + .regouthi(ddr_input[1]), + .regoutlo(ddr_input[0]), + .clkout(fr_clock), + .areset(aset) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0), + .dfflo(), + .devpor(1'b1), + .devclrn(1'b1), + .halfrateresyncclk(1'b0) + `endif + ); + end + else if (SYNC_MODE != "none") + begin:sync_mode_in_path_enhanced_ddr + fiftyfivenm_ddio_in + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .invert_input_clock(INVERT_INPUT_CLOCK) + ) fr_in_ddio ( + .datain(buf_in), + .clk (inclock_wire), + .ena(inclocken_wire), + .sreset(sclr), + .regouthi(ddr_input[1]), + .regoutlo(ddr_input[0]), + .clkout(fr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .areset(1'b0), + .dfflo(), + .devpor(1'b1), + .devclrn(1'b1), + .halfrateresyncclk(1'b0) + `endif + ); + end + else + begin:in_path_enhanced_ddr + fiftyfivenm_ddio_in + #( + .async_mode(ASYNC_MODE), + .sync_mode(SYNC_MODE), + .power_up(DDIO_REG_POWER_UP), + .invert_input_clock(INVERT_INPUT_CLOCK) + ) fr_in_ddio ( + .datain(buf_in), + .clk (inclock_wire), + .ena(inclocken_wire), + .regouthi(ddr_input[1]), + .regoutlo(ddr_input[0]), + .clkout(fr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0), + .areset(1'b0), + .dfflo(), + .devpor(1'b1), + .devclrn(1'b1), + .halfrateresyncclk(1'b0) + `endif + ); + end + end + end + else if (ENABLE_PHASE_DETECTOR_FOR_CK == "true") + begin + assign mimic_clock = buf_in; + end + else + begin: in_path_ddr + wire input_cell_l_q; + wire input_aset; + + assign input_aset = ( ASYNC_MODE == "clear") ? !aset : aset; + + fiftyfivenm_ff input_cell_l ( + .clk(inclock_wire), + .d(buf_in), + .clrn(input_aset), + .ena(inclocken_wire), + .q(input_cell_l_q) + ); + + fiftyfivenm_ff input_latch_l ( + .clk(~inclock_wire), + .d(input_cell_l_q), + .clrn(input_aset), + .ena(inclocken_wire), + .q(ddr_input[0]) + ); + + fiftyfivenm_ff input_cell_h ( + .clk(~inclock_wire), + .d(buf_in), + .clrn(input_aset), + .ena(inclocken_wire), + .q(ddr_input[1]) + ); + + end + end + else if (REGISTER_MODE == "single-register") + begin: in_path_sdr + reg reg_data_in /* synthesis altera_attribute="FAST_INPUT_REGISTER=on" */; + always @(posedge inclock_wire) begin + reg_data_in <= buf_in; + end + assign ddr_input[0] = reg_data_in; + end + else + begin: in_path_reg_none + assign ddr_input[0] = buf_in; + end + + assign dout[DATA_SIZE - 1:0] = ddr_input[DATA_SIZE - 1:0]; + + end + endgenerate + + generate + if (PIN_TYPE == "output" || PIN_TYPE == "bidir") + begin + if(BUFFER_TYPE == "pseudo_differential") + begin: pseudo_diff_output_buf + + wire wire_pseudo_diff_o; + wire wire_pseudo_diff_o_bar; + + fiftyfivenm_io_obuf + #( + .bus_hold(BUS_HOLD), + .open_drain_output(OPEN_DRAIN_OUTPUT) + ) obuf_a ( + .i(wire_pseudo_diff_o), + .oe(~oe_out), + .o(pad), + .obar() + `ifndef ALTERA_RESERVED_QIS + , + .seriesterminationcontrol(16'b0), + .devoe(1'b1) + `endif + ); + + fiftyfivenm_io_obuf + #( + .bus_hold(BUS_HOLD), + .open_drain_output(OPEN_DRAIN_OUTPUT) + ) obuf_a_bar ( + .i(wire_pseudo_diff_o_bar), + .oe(~oe_out), + .o(pad_b), + .obar() + `ifndef ALTERA_RESERVED_QIS + , + .seriesterminationcontrol(16'b0), + .devoe(1'b1) + `endif + ); + + fiftyfivenm_pseudo_diff_out pseudo_diff_a + ( + .i(din_ddr), + .o(wire_pseudo_diff_o), + .obar(wire_pseudo_diff_o_bar) + ); + + + + end + else if (BUFFER_TYPE == "true_differential") + begin: true_diff_output_buf + fiftyfivenm_io_obuf + #( + .bus_hold(BUS_HOLD), + .open_drain_output(OPEN_DRAIN_OUTPUT) + ) obuf ( + .i(din_ddr), + .oe(~oe_out), + .o(pad), + .obar(pad_b) + `ifndef ALTERA_RESERVED_QIS + , + .seriesterminationcontrol(16'b0), + .devoe(1'b1) + `endif + ); + end + else + begin: output_buf + fiftyfivenm_io_obuf + #( + .bus_hold(BUS_HOLD), + .open_drain_output(OPEN_DRAIN_OUTPUT) + ) obuf ( + .i(din_ddr), + .oe(~oe_out), + .o(pad), + .obar() + `ifndef ALTERA_RESERVED_QIS + , + .seriesterminationcontrol(16'b0), + .devoe(1'b1) + `endif + ); + end + end + endgenerate + + assign nsleep_in = (ENABLE_NSLEEP_PORT == "true") ? nsleep : 1'b1; + + generate + if (PIN_TYPE == "input" || PIN_TYPE == "bidir") + begin + if(BUFFER_TYPE == "true_differential" || BUFFER_TYPE == "pseudo_differential") + begin: diff_input_buf + if (ENABLE_NSLEEP_PORT == "true") + begin: diff_input_buf_with_nsleep + fiftyfivenm_io_ibuf + #( + .bus_hold(BUS_HOLD) + ) ibuf ( + .i(pad), + .ibar(pad_b), + .o(buf_in), + .nsleep(nsleep_in) + ); + end + else + begin: diff_input_buf_without_nsleep + fiftyfivenm_io_ibuf + #( + .bus_hold(BUS_HOLD) + ) ibuf ( + .i(pad), + .ibar(pad_b), + .o(buf_in) + ); + end + end + else + begin:input_buf + if (ENABLE_NSLEEP_PORT == "true") + begin: input_buf_with_nsleep + fiftyfivenm_io_ibuf + #( + .bus_hold(BUS_HOLD) + ) ibuf ( + .i(pad), + .o(buf_in), + .nsleep(nsleep_in) + `ifndef ALTERA_RESERVED_QIS + , + .ibar(1'b0) + `endif + ); + end + else + begin: input_buf_without_nsleep + fiftyfivenm_io_ibuf + #( + .bus_hold(BUS_HOLD) + ) ibuf ( + .i(pad), + .o(buf_in) + `ifndef ALTERA_RESERVED_QIS + , + .ibar(1'b0) + `endif + ); + end + end + end + endgenerate + + generate + if (PIN_TYPE == "output") + begin + assign dout = {DATA_SIZE{1'b0}}; + end + + if (PIN_TYPE == "output" || REGISTER_MODE != "ddr" || USE_ENHANCED_DDR_HIO_REGISTER == "false") + begin + assign fr_clock = 1'b0; + end + + if (PIN_TYPE == "input" || PIN_TYPE == "output" || REGISTER_MODE != "ddr" || ENABLE_PHASE_DETECTOR_FOR_CK == "false") + begin + assign mimic_clock = 1'b0; + end + endgenerate + +endmodule + +module altera_gpio_lite( + inclock, + outclock, + inclocken, + outclocken, + oe, + din, + dout, + pad_io, + pad_io_b, + pad_in, + pad_in_b, + pad_out, + pad_out_b, + aset, + aclr, + phy_mem_clock, + sclr, + hr_clock, + fr_clock, + invert_hr_clock, + mimic_clock, + nsleep +); + + parameter PIN_TYPE = "output"; + parameter BUFFER_TYPE = "single-ended"; + parameter REGISTER_MODE = "bypass"; + parameter SIZE = 4; + parameter ASYNC_MODE = "none"; + parameter SYNC_MODE = "none"; + parameter BUS_HOLD = "false"; + parameter SET_REGISTER_OUTPUTS_HIGH = "false"; + parameter INVERT_OUTPUT = "false"; + parameter INVERT_INPUT_CLOCK = "false"; + parameter INVERT_OUTPUT_CLOCK = "false"; + parameter INVERT_OE_INCLOCK = "false"; + parameter USE_ONE_REG_TO_DRIVE_OE = "false"; + parameter USE_DDIO_REG_TO_DRIVE_OE = "false"; + parameter OPEN_DRAIN_OUTPUT = "false"; + parameter USE_ADVANCED_DDR_FEATURES = "false"; + parameter USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY = "false"; + parameter INVERT_CLKDIV_INPUT_CLOCK = "false"; + parameter ENABLE_HR_CLOCK = "false"; + parameter ENABLE_OE_HALF_CYCLE_DELAY = "true"; + parameter ENABLE_OE_PORT = "false"; + parameter ENABLE_CLOCK_ENA_PORT = "false"; + parameter ENABLE_PHASE_INVERT_CTRL_PORT = "false"; + parameter ENABLE_PHASE_DETECTOR_FOR_CK = "false"; + parameter ENABLE_NSLEEP_PORT = "false"; + + localparam USE_ENHANCED_DDR_HIO_REGISTER = USE_ADVANCED_DDR_FEATURES; + localparam BYPASS_THREE_QUARTER_REGISTER = (USE_ADVANCED_DDR_FEATURES == "true") ? "false" : "true"; + localparam DATA_SIZE = (REGISTER_MODE == "ddr") ? 2 : 1; + + input inclock; + input outclock; + input inclocken; + input outclocken; + input [SIZE - 1:0] oe; + input [SIZE - 1:0] nsleep; + input [SIZE * DATA_SIZE - 1:0] din; + output [SIZE * DATA_SIZE - 1:0] dout; + inout [SIZE - 1:0] pad_io; + inout [SIZE - 1:0] pad_io_b; + input [SIZE - 1:0] pad_in; + input [SIZE - 1:0] pad_in_b; + output [SIZE - 1:0] pad_out; + output [SIZE - 1:0] pad_out_b; + input aset; + input aclr; + input sclr; + input phy_mem_clock; + input invert_hr_clock; + output [SIZE - 1:0] fr_clock; + output wire hr_clock; + output [SIZE - 1:0] mimic_clock; + + wire [SIZE * DATA_SIZE - 1:0] din_reordered; + wire [SIZE * DATA_SIZE - 1:0] dout_reordered; + wire aclr_aset_wire; + wire sclr_wire; + wire [SIZE - 1:0] pad_io; + wire [SIZE - 1:0] pad_io_b; + + + assign aclr_aset_wire = (ASYNC_MODE == "clear") ? aclr : (ASYNC_MODE == "preset") ? aset : 1'b1; + assign sclr_wire = (SYNC_MODE == "clear") ? sclr : 1'b0; + + generate + if (PIN_TYPE == "input") + begin + assign pad_io = pad_in; + assign pad_io_b = pad_in_b; + assign pad_out = {SIZE{1'b0}}; + assign pad_out_b = {SIZE{1'b0}}; + end + else if (PIN_TYPE == "output") + begin + assign pad_out = pad_io; + assign pad_out_b = pad_io_b; + end + else begin + assign pad_out = {SIZE{1'b0}}; + assign pad_out_b = {SIZE{1'b0}}; + end + endgenerate + + genvar j, k; + generate + begin : reorder + for(j = 0; j < SIZE ; j = j + 1) begin : j_loop + for(k = 0; k < DATA_SIZE; k = k + 1) begin : k_d_loop + assign din_reordered[j * DATA_SIZE + k] = din[j + k * SIZE]; + assign dout[j + k * SIZE] = dout_reordered[j * DATA_SIZE + k]; + end + end + end + endgenerate + + genvar i; + generate + begin : gpio_one_bit + for(i = 0 ; i < SIZE ; i = i + 1) begin : i_loop + wire oe_wire; + wire nsleep_wire; + + + assign oe_wire = (PIN_TYPE == "output" && ENABLE_OE_PORT == "false") ? 1'b1 : + (PIN_TYPE == "input") ? 1'b0 : oe[i]; + + + assign nsleep_wire = (PIN_TYPE == "input" && ENABLE_NSLEEP_PORT == "false") ? 1'b1 : + (PIN_TYPE == "output") ? 1'b0 : nsleep[i]; + + altgpio_one_bit #( + .PIN_TYPE(PIN_TYPE), + .BUFFER_TYPE(BUFFER_TYPE), + .REGISTER_MODE(REGISTER_MODE), + .ASYNC_MODE(ASYNC_MODE), + .SYNC_MODE(SYNC_MODE), + .BUS_HOLD(BUS_HOLD), + .SET_REGISTER_OUTPUTS_HIGH(SET_REGISTER_OUTPUTS_HIGH), + .USE_ENHANCED_DDR_HIO_REGISTER(USE_ENHANCED_DDR_HIO_REGISTER), + .USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY(USE_ADVANCED_DDR_FEATURES_FOR_INPUT_ONLY), + .BYPASS_THREE_QUARTER_REGISTER(BYPASS_THREE_QUARTER_REGISTER), + .INVERT_OUTPUT(INVERT_OUTPUT), + .INVERT_INPUT_CLOCK(INVERT_INPUT_CLOCK), + .INVERT_OUTPUT_CLOCK(INVERT_OUTPUT_CLOCK), + .INVERT_OE_INCLOCK(INVERT_OE_INCLOCK), + .USE_ONE_REG_TO_DRIVE_OE(USE_ONE_REG_TO_DRIVE_OE), + .USE_DDIO_REG_TO_DRIVE_OE(USE_DDIO_REG_TO_DRIVE_OE), + .OPEN_DRAIN_OUTPUT(OPEN_DRAIN_OUTPUT), + .ENABLE_OE_HALF_CYCLE_DELAY(ENABLE_OE_HALF_CYCLE_DELAY), + .ENABLE_CLOCK_ENA_PORT(ENABLE_CLOCK_ENA_PORT), + .ENABLE_HR_CLOCK(ENABLE_HR_CLOCK), + .ENABLE_PHASE_DETECTOR_FOR_CK(ENABLE_PHASE_DETECTOR_FOR_CK), + .ENABLE_NSLEEP_PORT(ENABLE_NSLEEP_PORT) + ) altgpio_bit_i ( + .inclock(inclock), + .outclock(outclock), + .phy_mem_clock(phy_mem_clock), + .inclocken(inclocken), + .outclocken(outclocken), + .oe(oe_wire), + .din(din_reordered[(i + 1) * DATA_SIZE - 1 : i * DATA_SIZE]), + .dout(dout_reordered[(i + 1) * DATA_SIZE - 1 : i * DATA_SIZE]), + .pad(pad_io[i]), + .pad_b(pad_io_b[i]), + .aset(aclr_aset_wire), + .sclr(sclr_wire), + .fr_clock(fr_clock[i]), + .hr_clock(hr_clock), + .mimic_clock(mimic_clock[i]), + .nsleep(nsleep_wire) + ); + end + end + endgenerate + + generate + if ((PIN_TYPE == "input" || PIN_TYPE == "bidir") && (ENABLE_HR_CLOCK == "true")) + begin + if (ENABLE_PHASE_INVERT_CTRL_PORT == "true") + begin + if (SYNC_MODE == "clear") + begin : clock_divider_sync_mode_invert_hr_clock + fiftyfivenm_io_clock_divider + #( + .invert_input_clock_phase(INVERT_CLKDIV_INPUT_CLOCK), + .use_phasectrlin(ENABLE_PHASE_INVERT_CTRL_PORT), + .sync_mode(SYNC_MODE) + ) io_clkdiv ( + .clk(inclock), + .phaseinvertctrl(invert_hr_clock), + .sreset(sclr_wire), + .clkout(hr_clock) + ); + end + else + begin : clock_divider_invert_hr_clock + fiftyfivenm_io_clock_divider + #( + .invert_input_clock_phase(INVERT_CLKDIV_INPUT_CLOCK), + .use_phasectrlin(ENABLE_PHASE_INVERT_CTRL_PORT), + .sync_mode(SYNC_MODE) + ) io_clkdiv ( + .clk(inclock), + .phaseinvertctrl(invert_hr_clock), + .clkout(hr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0) + `endif + ); + end + end + else + begin + if (SYNC_MODE == "clear") + begin : clock_divider_sync_mode + fiftyfivenm_io_clock_divider + #( + .invert_input_clock_phase(INVERT_CLKDIV_INPUT_CLOCK), + .use_phasectrlin(ENABLE_PHASE_INVERT_CTRL_PORT), + .sync_mode(SYNC_MODE) + ) io_clkdiv ( + .clk(inclock), + .sreset(sclr_wire), + .clkout(hr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .phaseinvertctrl(1'b0) + `endif + ); + end + else + begin : clock_divider + fiftyfivenm_io_clock_divider + #( + .invert_input_clock_phase(INVERT_CLKDIV_INPUT_CLOCK), + .use_phasectrlin(ENABLE_PHASE_INVERT_CTRL_PORT), + .sync_mode(SYNC_MODE) + ) io_clkdiv ( + .clk(inclock), + .clkout(hr_clock) + `ifndef ALTERA_RESERVED_QIS + , + .sreset(1'b0), + .phaseinvertctrl(1'b0) + `endif + ); + end + end + end + else begin + assign hr_clock = 1'b0; + end + endgenerate + +endmodule diff --git a/top/x400/cpld/ip/pll/pll.ppf b/top/x400/cpld/ip/pll/pll.ppf new file mode 100644 index 0000000..a485176 --- /dev/null +++ b/top/x400/cpld/ip/pll/pll.ppf @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/top/x400/cpld/ip/pll/pll.qip b/top/x400/cpld/ip/pll/pll.qip new file mode 100644 index 0000000..6bafc09 --- /dev/null +++ b/top/x400/cpld/ip/pll/pll.qip @@ -0,0 +1,5 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "20.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/top/x400/cpld/ip/pll/pll.v b/top/x400/cpld/ip/pll/pll.v new file mode 100644 index 0000000..36b96bd --- /dev/null +++ b/top/x400/cpld/ip/pll/pll.v @@ -0,0 +1,368 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 20.1.0 Build 711 06/05/2020 SJ Standard Edition +// ************************************************************ + + +//Copyright (C) 2020 Intel Corporation. All rights reserved. +//Your use of Intel Corporation's design tools, logic functions +//and other software and tools, and any partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Intel Program License +//Subscription Agreement, the Intel Quartus Prime License Agreement, +//the Intel FPGA IP License Agreement, or other applicable license +//agreement, including, without limitation, that your use is for +//the sole purpose of programming logic devices manufactured by +//Intel and sold by Intel or its authorized distributors. Please +//refer to the applicable agreement for further details, at +//https://fpgasoftware.intel.com/eula. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + inclk0, + c0, + c1, + c2, + locked); + + input inclk0; + output c0; + output c1; + output c2; + output locked; + + wire [0:0] sub_wire2 = 1'h0; + wire [4:0] sub_wire3; + wire sub_wire7; + wire sub_wire0 = inclk0; + wire [1:0] sub_wire1 = {sub_wire2, sub_wire0}; + wire [2:2] sub_wire6 = sub_wire3[2:2]; + wire [1:1] sub_wire5 = sub_wire3[1:1]; + wire [0:0] sub_wire4 = sub_wire3[0:0]; + wire c0 = sub_wire4; + wire c1 = sub_wire5; + wire c2 = sub_wire6; + wire locked = sub_wire7; + + altpll altpll_component ( + .inclk (sub_wire1), + .clk (sub_wire3), + .locked (sub_wire7), + .activeclock (), + .areset (1'b0), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 2, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 1, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 2, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 5, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk2_divide_by = 5, + altpll_component.clk2_duty_cycle = 50, + altpll_component.clk2_multiply_by = 2, + altpll_component.clk2_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 10000, + altpll_component.intended_device_family = "MAX 10", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_UNUSED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_USED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "2" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "2" +// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "50.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "250.000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "40.000000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "5" +// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "1" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "40.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK3 STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK4 STRING "0" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLK2 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "2" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "1" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "2" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "5" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "5" +// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "2" +// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "10000" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/top/x400/cpld/mb_cpld.qpf b/top/x400/cpld/mb_cpld.qpf new file mode 100644 index 0000000..0e34c0a --- /dev/null +++ b/top/x400/cpld/mb_cpld.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2018 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel FPGA IP License Agreement, or other applicable license +# agreement, including, without limitation, that your use is for +# the sole purpose of programming logic devices manufactured by +# Intel and sold by Intel or its authorized distributors. Please +# refer to the applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 18.1.0 Build 625 09/12/2018 SJ Lite Edition +# Date created = 13:40:17 August 15, 2019 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "18.1" +DATE = "13:40:17 August 15, 2019" + +# Revisions + +PROJECT_REVISION = "mb_cpld" diff --git a/top/x400/cpld/mb_cpld.qsf b/top/x400/cpld/mb_cpld.qsf new file mode 100644 index 0000000..47ab072 --- /dev/null +++ b/top/x400/cpld/mb_cpld.qsf @@ -0,0 +1,431 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2018 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel FPGA IP License Agreement, or other applicable license +# agreement, including, without limitation, that your use is for +# the sole purpose of programming logic devices manufactured by +# Intel and sold by Intel or its authorized distributors. Please +# refer to the applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 18.1.0 Build 625 09/12/2018 SJ Lite Edition +# Date created = 12:02:17 February 20, 2019 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# TopCpld_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus Prime software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +#-------------------------------------------------------------------------- +# Project properties/settings +#-------------------------------------------------------------------------- +set_global_assignment -name FAMILY "MAX 10" +set_global_assignment -name DEVICE 10M04SAU169I7G +set_global_assignment -name TOP_LEVEL_ENTITY mb_cpld +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 18.1.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "12:02:17 FEBRUARY 20, 2019" +set_global_assignment -name LAST_QUARTUS_VERSION "20.1.0 Standard Edition" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON +set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %" +set_global_assignment -name ENABLE_OCT_DONE OFF +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_JTAG_PIN_SHARING ON +set_global_assignment -name GENERATE_SVF_FILE OFF +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top + +set_global_assignment -name NUM_PARALLEL_PROCESSORS 2 + +#-------------------------------------------------------------------------- +# Pin constraints +#-------------------------------------------------------------------------- + +# Clocking. +#------------------------------------------ + +# CPLD's PLL reference clock. +set_location_assignment PIN_H6 -to PLL_REF_CLK +set_location_assignment PIN_G5 -to "PLL_REF_CLK(n)" +set_instance_assignment -name IO_STANDARD "DIFFERENTIAL LVPECL" -to PLL_REF_CLK + +# Reliable clock (100 MHz). +set_location_assignment PIN_H4 -to CLK_100 +set_location_assignment PIN_H5 -to "CLK_100(n)" +set_instance_assignment -name IO_STANDARD "DIFFERENTIAL LVPECL" -to CLK_100 + +# Power supply clocks. +set_location_assignment PIN_H8 -to PWR_SUPPLY_CLK_CORE +set_location_assignment PIN_H9 -to PWR_SUPPLY_CLK_DDR4_S +set_location_assignment PIN_G12 -to PWR_SUPPLY_CLK_DDR4_N +set_location_assignment PIN_L13 -to PWR_SUPPLY_CLK_0P9V +set_location_assignment PIN_G13 -to PWR_SUPPLY_CLK_1P8V +set_location_assignment PIN_K10 -to PWR_SUPPLY_CLK_2P5V +set_location_assignment PIN_J10 -to PWR_SUPPLY_CLK_3P3V +set_location_assignment PIN_L12 -to PWR_SUPPLY_CLK_3P6V +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_0P9V +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_1P8V +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_2P5V +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_3P3V +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_3P6V +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_CORE +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_DDR4_N +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PWR_SUPPLY_CLK_DDR4_S + +# Oscillator power supply +set_location_assignment PIN_L2 -to PWR_EN_5V_OSC_100 +set_location_assignment PIN_N2 -to PWR_EN_5V_OSC_122_88 +set_instance_assignment -name IO_STANDARD "2.5 V" -to PWR_EN_5V_OSC_100 +set_instance_assignment -name IO_STANDARD "2.5 V" -to PWR_EN_5V_OSC_122_88 + + +# Interfaces from/to RFSoC. +#------------------------------------------ + +# PL SPI slave interface. +set_location_assignment PIN_G2 -to PL_CPLD_SCLK +set_location_assignment PIN_F5 -to PL_CPLD_MOSI +set_location_assignment PIN_F6 -to PL_CPLD_MISO +set_location_assignment PIN_G1 -to PL_CPLD_CS_N[0] +set_location_assignment PIN_G4 -to PL_CPLD_CS_N[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to PL_CPLD_SCLK +set_instance_assignment -name IO_STANDARD "1.8 V" -to PL_CPLD_MOSI +set_instance_assignment -name IO_STANDARD "1.8 V" -to PL_CPLD_MISO +set_instance_assignment -name IO_STANDARD "1.8 V" -to PL_CPLD_CS_N[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to PL_CPLD_CS_N[1] + +# IRQ to PL. +set_location_assignment PIN_F4 -to PL_CPLD_IRQ +set_instance_assignment -name IO_STANDARD "1.8 V" -to PL_CPLD_IRQ + +# PS SPI slave interface. +set_location_assignment PIN_E3 -to PS_CPLD_SCLK +set_location_assignment PIN_E1 -to PS_CPLD_MOSI +set_location_assignment PIN_F1 -to PS_CPLD_MISO +set_location_assignment PIN_B1 -to PS_CPLD_CS_N[0] +set_location_assignment PIN_C1 -to PS_CPLD_CS_N[1] +set_location_assignment PIN_E4 -to PS_CPLD_CS_N[2] +set_location_assignment PIN_D1 -to PS_CPLD_CS_N[3] +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_SCLK +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_MOSI +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_MISO +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_CS_N[0] +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_CS_N[1] +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_CS_N[2] +set_instance_assignment -name IO_STANDARD "1.8-V" -to PS_CPLD_CS_N[3] + + +# PL Interfaces to/from motherboard. +#------------------------------------------ + +# White Rabbit DAC SPI master interface. +set_location_assignment PIN_A12 -to CLK_DB_SCLK +set_location_assignment PIN_B13 -to CLK_DB_MOSI +set_location_assignment PIN_D12 -to CLK_DB_MISO +set_location_assignment PIN_D9 -to CLK_DB_CS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLK_DB_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLK_DB_MOSI +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLK_DB_MISO +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLK_DB_CS_N + +# iPASS interfaces. +set_location_assignment PIN_A6 -to IPASS_SCL[0] +set_location_assignment PIN_H2 -to IPASS_SCL[1] +set_location_assignment PIN_A7 -to IPASS_SDA[0] +set_location_assignment PIN_H3 -to IPASS_SDA[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to IPASS_SCL[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to IPASS_SCL[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to IPASS_SDA[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to IPASS_SDA[1] + +set_location_assignment PIN_B11 -to IPASS_PRESENT_N[0] +set_location_assignment PIN_F8 -to IPASS_PRESENT_N[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to IPASS_PRESENT_N[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to IPASS_PRESENT_N[1] + +# QSFP LEDs. +set_location_assignment PIN_E12 -to QSFP0_LED_ACTIVE[0] +set_location_assignment PIN_F12 -to QSFP0_LED_ACTIVE[1] +set_location_assignment PIN_E9 -to QSFP0_LED_ACTIVE[2] +set_location_assignment PIN_J1 -to QSFP0_LED_ACTIVE[3] +set_location_assignment PIN_F10 -to QSFP0_LED_LINK[0] +set_location_assignment PIN_F9 -to QSFP0_LED_LINK[1] +set_location_assignment PIN_N11 -to QSFP0_LED_LINK[2] +set_location_assignment PIN_D13 -to QSFP0_LED_LINK[3] +set_location_assignment PIN_M1 -to QSFP1_LED_ACTIVE[0] +set_location_assignment PIN_N3 -to QSFP1_LED_ACTIVE[1] +set_location_assignment PIN_L3 -to QSFP1_LED_ACTIVE[2] +set_location_assignment PIN_K2 -to QSFP1_LED_ACTIVE[3] +set_location_assignment PIN_M2 -to QSFP1_LED_LINK[0] +set_location_assignment PIN_M3 -to QSFP1_LED_LINK[1] +set_location_assignment PIN_K1 -to QSFP1_LED_LINK[2] +set_location_assignment PIN_L1 -to QSFP1_LED_LINK[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_ACTIVE[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_ACTIVE[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_ACTIVE[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP0_LED_ACTIVE[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_LINK[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_LINK[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_LINK[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to QSFP0_LED_LINK[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_ACTIVE[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_ACTIVE[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_ACTIVE[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_ACTIVE[3] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_LINK[0] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_LINK[1] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_LINK[2] +set_instance_assignment -name IO_STANDARD "2.5 V" -to QSFP1_LED_LINK[3] + +# DIO direction control. +set_location_assignment PIN_N12 -to DIO_DIRECTION_A[0] +set_location_assignment PIN_N10 -to DIO_DIRECTION_A[1] +set_location_assignment PIN_N9 -to DIO_DIRECTION_A[2] +set_location_assignment PIN_M4 -to DIO_DIRECTION_A[3] +set_location_assignment PIN_M5 -to DIO_DIRECTION_A[4] +set_location_assignment PIN_N4 -to DIO_DIRECTION_A[5] +set_location_assignment PIN_N5 -to DIO_DIRECTION_A[6] +set_location_assignment PIN_N7 -to DIO_DIRECTION_A[7] +set_location_assignment PIN_N8 -to DIO_DIRECTION_A[8] +set_location_assignment PIN_M8 -to DIO_DIRECTION_A[9] +set_location_assignment PIN_M9 -to DIO_DIRECTION_A[10] +set_location_assignment PIN_M13 -to DIO_DIRECTION_A[11] +set_location_assignment PIN_L5 -to DIO_DIRECTION_B[0] +set_location_assignment PIN_L4 -to DIO_DIRECTION_B[1] +set_location_assignment PIN_K5 -to DIO_DIRECTION_B[2] +set_location_assignment PIN_J5 -to DIO_DIRECTION_B[3] +set_location_assignment PIN_N6 -to DIO_DIRECTION_B[4] +set_location_assignment PIN_M7 -to DIO_DIRECTION_B[5] +set_location_assignment PIN_J6 -to DIO_DIRECTION_B[6] +set_location_assignment PIN_K6 -to DIO_DIRECTION_B[7] +set_location_assignment PIN_J7 -to DIO_DIRECTION_B[8] +set_location_assignment PIN_K7 -to DIO_DIRECTION_B[9] +set_location_assignment PIN_M12 -to DIO_DIRECTION_B[10] +set_location_assignment PIN_M11 -to DIO_DIRECTION_B[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_A[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DIO_DIRECTION_B[11] + + +# PS Interfaces to/from motherboard. +#------------------------------------------ + +# LMK04832 SPI master interface. +set_location_assignment PIN_J9 -to LMK32_SCLK +set_location_assignment PIN_H13 -to LMK32_MOSI +set_location_assignment PIN_L11 -to LMK32_MISO +set_location_assignment PIN_J13 -to LMK32_CS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LMK32_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LMK32_MOSI +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LMK32_MISO +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LMK32_CS_N + +# TPM 2.0 SPI master interface. +set_location_assignment PIN_D11 -to TPM_SCLK +set_location_assignment PIN_E10 -to TPM_MOSI +set_location_assignment PIN_C13 -to TPM_MISO +set_location_assignment PIN_L10 -to TPM_CS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to TPM_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to TPM_MOSI +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to TPM_MISO +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to TPM_CS_N + +# Phase DAC SPI master interface. +set_location_assignment PIN_K8 -to PHASE_DAC_SCLK +set_location_assignment PIN_J8 -to PHASE_DAC_MOSI +set_location_assignment PIN_M10 -to PHASE_DAC_CS_N +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PHASE_DAC_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PHASE_DAC_MOSI +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to PHASE_DAC_CS_N + +# Daughterboards' JTAG master interfaces. +set_location_assignment PIN_J12 -to DB_JTAG_TCK[0] +set_location_assignment PIN_G9 -to DB_JTAG_TCK[1] +set_location_assignment PIN_K12 -to DB_JTAG_TDI[0] +set_location_assignment PIN_E13 -to DB_JTAG_TDI[1] +set_location_assignment PIN_H10 -to DB_JTAG_TDO[0] +set_location_assignment PIN_F13 -to DB_JTAG_TDO[1] +set_location_assignment PIN_K11 -to DB_JTAG_TMS[0] +set_location_assignment PIN_G10 -to DB_JTAG_TMS[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TCK[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TCK[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TDI[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TDI[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TDO[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TDO[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TMS[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to DB_JTAG_TMS[1] + +# Daughterboards' Calibration EEPROM SPI interfaces. +set_location_assignment PIN_C9 -to DB_CALEEPROM_CS_N[0] +set_location_assignment PIN_B9 -to DB_CALEEPROM_MISO[0] +set_location_assignment PIN_B10 -to DB_CALEEPROM_MOSI[0] +set_location_assignment PIN_A10 -to DB_CALEEPROM_SCLK[0] + +set_location_assignment PIN_B5 -to DB_CALEEPROM_MOSI[1] +set_location_assignment PIN_B6 -to DB_CALEEPROM_SCLK[1] +set_location_assignment PIN_B4 -to DB_CALEEPROM_MISO[1] +set_location_assignment PIN_B3 -to DB_CALEEPROM_CS_N[1] + +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_CS_N[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_MISO[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_MOSI[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_SCLK[0] + +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_MOSI[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_SCLK[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_MISO[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CALEEPROM_CS_N[1] + +# Daughterboards' Control interfaces. +set_location_assignment PIN_C10 -to DB_CTRL_SCLK[0] +set_location_assignment PIN_A9 -to DB_CTRL_MISO[0] +set_location_assignment PIN_A8 -to DB_ARST[0] +set_location_assignment PIN_A11 -to DB_CTRL_CS_N[0] +set_location_assignment PIN_E8 -to DB_CTRL_MOSI[0] +set_location_assignment PIN_D8 -to DB_REF_CLK[0] + +set_location_assignment PIN_A3 -to DB_REF_CLK[1] +set_location_assignment PIN_A4 -to DB_CTRL_MISO[1] +set_location_assignment PIN_D6 -to DB_CTRL_CS_N[1] +set_location_assignment PIN_E6 -to DB_CTRL_SCLK[1] +set_location_assignment PIN_A5 -to DB_CTRL_MOSI[1] +set_location_assignment PIN_B2 -to DB_ARST[1] + +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_SCLK[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_MISO[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_ARST[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_CS_N[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_MOSI[0] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_REF_CLK[0] + +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_REF_CLK[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_MISO[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_CS_N[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_SCLK[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_CTRL_MOSI[1] +set_instance_assignment -name IO_STANDARD "1.8 V" -to DB_ARST[1] + + +# Miscellaneous. +#------------------------------------------ + +# Power supply clocks switch. +set_location_assignment PIN_J2 -to PS_CLK_ON_CPLD +set_instance_assignment -name IO_STANDARD "2.5 V" -to PS_CLK_ON_CPLD + +# iPASS misc. +set_location_assignment PIN_B12 -to IPASS_POWER_DISABLE +set_location_assignment PIN_C11 -to IPASS_POWER_EN_FAULT[0] +set_location_assignment PIN_C12 -to IPASS_POWER_EN_FAULT[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to IPASS_POWER_DISABLE +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to IPASS_POWER_EN_FAULT[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to IPASS_POWER_EN_FAULT[1] + +# PCIe reset to FPGA. +set_location_assignment PIN_A2 -to PCIE_RESET +set_instance_assignment -name IO_STANDARD "1.8 V" -to PCIE_RESET + +# TPM reset. +set_location_assignment PIN_K13 -to TPM_RESET_n +set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to TPM_RESET_n + +# File list. +set_global_assignment -name EXTERNAL_FLASH_FALLBACK_ADDRESS 00000000 +set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE" +set_global_assignment -name EN_USER_IO_WEAK_PULLUP OFF +set_global_assignment -name EN_SPI_IO_WEAK_PULLUP OFF + +set_global_assignment -name VHDL_FILE ip/cmi/PcieCmiWrapper.vhd +set_global_assignment -name VHDL_FILE ip/cmi/PcieCmi.vhd +set_global_assignment -name QSYS_FILE ip/clkctrl/clkctrl.qsys +set_global_assignment -name QSYS_FILE ip/flash/on_chip_flash.qsys +set_global_assignment -name SDC_FILE db_spi_shared_constants.sdc +set_global_assignment -name SDC_FILE mb_cpld.sdc +set_global_assignment -name VERILOG_FILE reconfig_engine.v +set_global_assignment -name VERILOG_FILE mb_cpld.v +set_global_assignment -name VERILOG_FILE ctrlport_to_spi.v +set_global_assignment -name VERILOG_FILE ctrlport_to_jtag.v +set_global_assignment -name VERILOG_FILE pl_cpld_regs.v +set_global_assignment -name VERILOG_FILE pwr_supply_clk_gen.v +set_global_assignment -name VERILOG_FILE ps_cpld_regs.v +set_global_assignment -name VERILOG_FILE reset_generator.v +set_global_assignment -name VERILOG_FILE spi_slave_to_ctrlport_master.v +set_global_assignment -name VERILOG_FILE spi_slave.v +set_global_assignment -name QIP_FILE ip/pll/pll.qip +set_global_assignment -name VERILOG_FILE ../../../lib/control/synchronizer_impl.v +set_global_assignment -name VERILOG_FILE ../../../lib/control/synchronizer.v +set_global_assignment -name VERILOG_FILE ../../../lib/rfnoc/utils/ctrlport_splitter.v +set_global_assignment -name VERILOG_FILE ../../../lib/rfnoc/utils/ctrlport_terminator.v +set_global_assignment -name VERILOG_FILE ../../../lib/wb_spi/rtl/verilog/spi_top.v +set_global_assignment -name VERILOG_FILE ../../../lib/wb_spi/rtl/verilog/spi_shift.v +set_global_assignment -name VERILOG_FILE ../../../lib/wb_spi/rtl/verilog/spi_defines.v +set_global_assignment -name VERILOG_FILE ../../../lib/wb_spi/rtl/verilog/spi_clgen.v +set_global_assignment -name VERILOG_FILE ../../../lib/control/pulse_synchronizer.v +set_global_assignment -name VERILOG_FILE ../../../lib/control/handshake.v +set_global_assignment -name VHDL_FILE ../../../lib/vivado_ipi/axi_bitq/bitq_fsm.vhd +set_global_assignment -name VHDL_FILE ../../../lib/vivado_ipi/axi_bitq/axi_bitq.vhd +set_global_assignment -name QIP_FILE ip/oddr/oddr.qip +set_global_assignment -name SOURCE_FILE db/mb_cpld.cmp.rdb +set_global_assignment -name PARTITION_NETLIST_TYPE POST_FIT -section_id "PcieCmi:PcieCmix" +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id "PcieCmi:PcieCmix" +set_global_assignment -name PARTITION_COLOR 52377 -section_id "PcieCmi:PcieCmix" +set_global_assignment -name PARTITION_IMPORT_FILE ip/cmi/PcieCmi.qxp -section_id "PcieCmi:PcieCmix" +set_global_assignment -name PARTITION_LAST_IMPORTED_FILE ip/cmi/PcieCmi.qxp -section_id "PcieCmi:PcieCmix" +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top +set_instance_assignment -name PARTITION_HIERARCHY pciec_5b6b1 -to "PcieCmiWrapper:pcie_cmi_inst|PcieCmi:PcieCmix" -section_id "PcieCmi:PcieCmix" \ No newline at end of file diff --git a/top/x400/cpld/mb_cpld.sdc b/top/x400/cpld/mb_cpld.sdc new file mode 100644 index 0000000..af291a9 --- /dev/null +++ b/top/x400/cpld/mb_cpld.sdc @@ -0,0 +1,689 @@ +# +# Copyright 2021 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# +# Description: +# +# Timing constraints for the X4xx's motherboard CPLD. +# + +set_time_format -unit ns -decimal_places 3 + +##################################################################### +# General +##################################################################### +# For a couple of 3.3V interfaces the buffer SN74AVC4T774RSVR is used to +# increase the drive strength. For reuse we define the timings constants here. +# For direction A to B and B to A the maximum timing varies by 0.1 ns. Taking +# the maximum of both. +set buffer_prop_min 0.100 +set buffer_prop_max 2.400 + +##################################################################### +# Main Clocks +##################################################################### +## Input clocks. +# Reliable clock: 100.0 MHz +set CLK_100_period 10.000 +create_clock -name CLK_100 -period $CLK_100_period [get_ports CLK_100] + +# internal PLL derived clock +derive_pll_clocks +# provide name for derived clocks +set CLK_250 [get_clocks {*clk[1]}] + +# PLL output pins of the generated 50 MHz clock for internal processing +set clk50_period 20.000 +set pll_clk_out_pin [get_pins {pll_inst|altpll_component|auto_generated|pll1|clk[0]}] + +set clk250_period 4.000 + +# PLL reference clock: 64 MHz (maximum) +set prc_clock_period 15.625 +create_clock -name PLL_REF_CLK -period $prc_clock_period [get_ports PLL_REF_CLK] + +##################################################################### +# Timing exceptions +##################################################################### +## SPI slaves +# Delay path for all synchronizers is based on the period of the +# faster clock domain (50 MHz derived by the PLL from 100 MHz reliable clock). +set clk50_period [expr {$CLK_100_period * 2}] + +set_max_delay -to [get_registers *synchronizer_false_path\|value\[0\]\[*\]] \ + $clk50_period + +# sclk data to CLK_100 +set_max_delay -from [get_registers *spi_slave_async\|received_word\[*\]] \ + -to [get_registers *spi_slave_async\|data_out\[*\]] \ + $clk50_period +# PLL driven data to sclk +set_max_delay -from [get_clocks {pll_inst*}] \ + -to [get_registers *spi_slave_async\|transmit_bits\[*\]] \ + $clk50_period + +##################################################################### +# JTAG to daughterboards +##################################################################### +# Use the worst-case board propagation delays. +# Assuming 170.0 ps/in and usage of X410 DB. +# Longest trace | Trace length | Trace delay +# TDI to DB 0 | 7.625 in | 1.296 ns +# -------------------------------------------- + +# JTAG parameters +# see https://www.intel.com/content/www/us/en/programmable/documentation/mcn1397700832153.html#mcn1399899915639 +set db_jtag_board_delay 1.296 +set db_jtag_setup 3.000 +set db_jtag_hold 10.000 +set db_jtag_clk_to_out 20.000 + +set db0_jtag_outputs [get_ports {DB_JTAG_TDI[0] DB_JTAG_TMS[0]}] +set db0_jtag_inputs [get_ports {DB_JTAG_TDO[0]}] +set db1_jtag_outputs [get_ports {DB_JTAG_TDI[1] DB_JTAG_TMS[1]}] +set db1_jtag_inputs [get_ports {DB_JTAG_TDO[1]}] + +##### DB 0 ##### +# generated jtag clock is at least divided by 4 +# max JTAG clock rate = 20 MHz +# source clock rate = 50 MHz +# only even dividers -> minimum value = 4 +set db0_jtag_clk_register [get_registers {ctrlport_to_jtag:db0_jtag|bitq_fsm:jtag_master|bitq_state.HIGH}] +create_generated_clock -source $pll_clk_out_pin \ + -name db0_jtag_clk $db0_jtag_clk_register \ + -divide_by 4 + +# see White Rabbit DAC for futher explanation +set_false_path -from $db0_jtag_clk_register -to $db0_jtag_clk_register + +create_generated_clock \ + -source $db0_jtag_clk_register \ + -name db0_jtag_out_clk [get_ports {DB_JTAG_TCK[0]}] + +set_output_delay -clock db0_jtag_out_clk \ + -max [expr {$db_jtag_setup + $db_jtag_board_delay + $buffer_prop_max}] \ + $db0_jtag_outputs +set_output_delay -clock db0_jtag_out_clk \ + -min [expr {-$db_jtag_hold - $db_jtag_board_delay - $buffer_prop_min}] \ + $db0_jtag_outputs +# data is driven on CPLD on falling edge, which is 2 clock cycles ahead +# of the latch edge +set_multicycle_path -setup -start -to $db0_jtag_outputs 2 +set_multicycle_path -hold -start -to $db0_jtag_outputs 3 + +# maximum delay accounts for slow clock and data propagation as +# well as clock to out time +set_input_delay -clock_fall -clock db0_jtag_out_clk \ + -max [expr {$db_jtag_clk_to_out + 2*$db_jtag_board_delay + 2*$buffer_prop_max}] \ + $db0_jtag_inputs +# worst-case everything changes immediatelly +set_input_delay -clock_fall -clock db0_jtag_out_clk \ + -min [expr {2*$buffer_prop_min}] \ + $db0_jtag_inputs +set_multicycle_path -setup -end -from $db0_jtag_inputs 2 +set_multicycle_path -hold -end -from $db0_jtag_inputs 3 + +##### DB 1 ##### +# generated jtag clock is at least divided by 4 +set db1_jtag_clk_register [get_registers {ctrlport_to_jtag:db1_jtag|bitq_fsm:jtag_master|bitq_state.HIGH}] +create_generated_clock -source $pll_clk_out_pin \ + -name db1_jtag_clk $db1_jtag_clk_register \ + -divide_by 4 +# see White Rabbit DAC for futher explanation +set_false_path -from $db1_jtag_clk_register -to $db1_jtag_clk_register +create_generated_clock \ + -source $db1_jtag_clk_register \ + -name db1_jtag_out_clk [get_ports {DB_JTAG_TCK[1]}] + +set_output_delay -clock db1_jtag_out_clk \ + -max [expr {$db_jtag_setup + $db_jtag_board_delay + $buffer_prop_max}] \ + $db1_jtag_outputs +set_output_delay -clock db1_jtag_out_clk \ + -min [expr {-$db_jtag_hold - $db_jtag_board_delay - $buffer_prop_min}] \ + $db1_jtag_outputs +set_multicycle_path -setup -start -to $db1_jtag_outputs 2 +set_multicycle_path -hold -start -to $db1_jtag_outputs 3 + +# maximum delay accounts for slow clock and data propagation as +# well as clock to out time +set_input_delay -clock_fall -clock db1_jtag_out_clk \ + -max [expr {$db_jtag_clk_to_out + 2*$db_jtag_board_delay + 2*$buffer_prop_max}] \ + $db1_jtag_inputs +# ideally everything changes immediatelly +set_input_delay -clock_fall -clock db1_jtag_out_clk \ + -min [expr {2*$buffer_prop_min}] \ + $db1_jtag_inputs +set_multicycle_path -setup -end -from $db1_jtag_inputs 2 +set_multicycle_path -hold -end -from $db1_jtag_inputs 3 + +##################################################################### +# FPGA <-> MB CPLD PL SPI interface +##################################################################### +# Create clock for the PL's SPI interface. +# PRC at least divided by 2 by the SPI Master on FPGA +set pl_sclk_period [expr {2 * $prc_clock_period}] +create_clock -name pl_sclk -period $pl_sclk_period [get_registers mb_cpld_sclk] + +# The SPI PL master (on the FPGA) is designed as a system synchronous +# interface using PLL_REF_CLK. +# The FPGA output constraints are required to calculate the windows +# at CPLD of valid data +# They are derived iteratively from the FPGA design ensuring a large +# valid data period. +set pl_spi_fpga_min_out 0.000 +set pl_spi_fpga_max_out 11.000 + +# The longest trace on the PL SPI interface is (sssuming 170.0 ps/in) +# Longest trace | Trace length | Trace delay +# CS_0 | 7.143 in | 1.215 ns +set pl_spi_board_delay 1.215 + +# This path also contains a level translator which has a typical +# switching time of 2.7 ns. Let's add a margin of 1 ns as worst +# case estimation +set pl_level_trans_delay 3.700 + +# CPLD and FPGA both use PLL reference clock from a common clock chip. +# The traces from that clock chip to the ICs are not length matched +# Assume a worst case clock difference of 0.5 ns at the IC inputs. +# There is no direction defined. The clock can arrive faster or slower +# on one IC. +set pl_clock_diff 0.500 + +set pl_slave_inputs [get_ports {PL_CPLD_SCLK PL_CPLD_MOSI PL_CPLD_CS_N[*]}] +# calculate output delays back from capturing edge, add board delay, level translator and clock difference +set_input_delay -clock PLL_REF_CLK \ + -max [expr {$prc_clock_period - $pl_spi_fpga_max_out + $pl_spi_board_delay + $pl_level_trans_delay + $pl_clock_diff}] \ + $pl_slave_inputs +# Assuming data is going without any delay, clock is arriving early at CPLD. +# Negate minimum output delay as it is defined from the change to the start clock edge. +set_input_delay -clock PLL_REF_CLK \ + -min [expr {- $pl_spi_fpga_min_out - $pl_clock_diff}] \ + $pl_slave_inputs + +# ensure large data valid window for the FPGA +# those values are used in the FPGA / DB CPLDs +# to calculate the input delay +# those values are maximum integer values to still meet timing +set pl_spi_cpld_min_out -1.000 +set pl_spi_cpld_max_out 8.000 + +set pl_slave_outputs [get_ports {PL_CPLD_MISO}] +set_output_delay -clock PLL_REF_CLK -max $pl_spi_cpld_max_out $pl_slave_outputs +set_output_delay -clock PLL_REF_CLK -min $pl_spi_cpld_min_out $pl_slave_outputs + +##################################################################### +# DB clock and reset +##################################################################### +# Output clocks for the daughterboards (SPI control) +create_generated_clock -source $pll_clk_out_pin \ + -name db0_ref_clk [get_ports {DB_REF_CLK[0]}] +create_generated_clock -source $pll_clk_out_pin \ + -name db1_ref_clk [get_ports {DB_REF_CLK[1]}] + +# output reset within one clock period +set_max_delay -to [get_ports {DB_ARST[0] DB_ARST[1]}] $CLK_100_period +set_min_delay -to [get_ports {DB_ARST[0] DB_ARST[1]}] 0 + +##################################################################### +# DB SPI interfaces +##################################################################### +# --------- ----------------- ----------------- +# FPGA | CS/SCLK/ | MB CPLD | | DB | +# |-- MOSI ->|--------> R1 ->|--------->| | +# SPI | | | | SPI | +# master |<- MISO --|<- R2 <--------|<---------| slave | +# --------- ----------------- ----------------- +# +# The output clocks are derived from the PLL reference clock (PRC). The SCLK +# edges are aligned with the rising edge of PLL reference clock. There are two +# registers R1 and R2 in the SPI path between FPGA and DB. +# For the transmission of data from master to slave those registers are +# transparent. The overall reception is just delayed by 1 PLL reference clock +# cycle. In the other direction the MISO timing is different. The falling edge +# of SCLK is used for changing the data signals. The propagation of this signal +# to the DB is delayed by 1 PLL reference clock period because of register R1. +# The MISO signal is captured on the rising edge of SCLK on the FPGA. Register +# R2 in the MB CPLD changes the timing in a way that MISO has to be stable on +# the rising edge of PLL reference clock before the SCLK rising edge. +# Additionally a minimum of two PLL reference clock cycles are required for +# processing in the SPI slave. The number of processing cycles is denoted by n. + +# Here is an example for n=2 and SPI bus with CPHA=0 and CPOL=0. +# Data is driven on the falling edge and captured on the rising edge of the +# clock signal. The falling edge of the SCLK@DB is delayed by a clock cycle +# because of R1. The FPGA as SPI master is capturing the data on the rising edge +# of SCLK. The register R2 on the MB CPLD is capturing the data one clock cycle +# earlier. Therefore MISO has to be stable one clock cycle earlier then the +# original SCLK at the MB CPLD input. The effective SCLK signal to use for the +# timing constraints of the DB therefore has a low period which is reduced by 2 +# clock cycles (R1 + R2) of PLL reference clock. It still has the same period as +# SCLK. In this example the low period would be 2 PRC cycles and the high period +# would be 6 PRC cycles. +# The following waveform illustrates the timing for n=2. Based on the defined +# delays denotes the time when the signal is not stable. +# +# <--- R1 --->|<-------- n=2 -------->|<--- R2 ---> +# PRC ___/-----\_____/-----\_____/-----\_____/-----\_____/---- +# SCLK ---\_______________________________________________/---- +# SCLK @ DB (ideal) ---------------\________________________________________ +# SCLK @ DB (effective) ---------------\_______________________/---------------- +# MOSI output @ MB CPLD -------------------------------------------------- +# MISO input @ MB CPLD -------------------------------------------------- +# DB propagation and processing <---------> +# MOSI change @ FPGA ^ +# MOSI change @ MB CPLD ^ +# MISO capture @ MB CPLD ^ +# MISO capture @ FPGA ^ +# +# Although the delays are defined based on PLL reference clock the SPI bus clock +# must be divided by at least n+2, where n>1 to be functional. Increase n in +# case the DB propagation and processing time does not fit into n PLL reference +# clock cycles taking the delays from below into account (see waveform above). +# Make sure you defined the SPI bus clock frequency for the slave to n*PLL clock +# period (effective SPI clock). Set the required SPI DB clock divider on the +# FPGA before starting data transfer. +# +# The constants for this interface are defined in db_spi_shared_constants.sdc + +#### DB 0 #### +create_generated_clock -source [get_ports {PLL_REF_CLK}] \ + -name db0_ctrl_clk_int [get_registers {DB_CTRL_SCLK[0]~reg0}] +create_generated_clock -source [get_registers {DB_CTRL_SCLK[0]~reg0}] \ + -name db0_ctrl_clk [get_ports {DB_CTRL_SCLK[0]}] + +set db0_ctrl_outputs [get_ports {DB_CTRL_MOSI[0] DB_CTRL_CS_N[0]}] +set_output_delay -clock db0_ctrl_clk -max $db_cpld_spi_max_out $db0_ctrl_outputs +set_output_delay -clock db0_ctrl_clk -min $db_cpld_spi_min_out $db0_ctrl_outputs + +set db0_ctrl_inputs [get_ports {DB_CTRL_MISO[0]}] +set_input_delay -clock db0_ctrl_clk -max $db_cpld_spi_max_in $db0_ctrl_inputs +set_input_delay -clock db0_ctrl_clk -min $db_cpld_spi_min_in $db0_ctrl_inputs + +#### DB 1 #### +create_generated_clock -source [get_ports {PLL_REF_CLK}] \ + -name db1_ctrl_clk_int [get_registers {DB_CTRL_SCLK[1]~reg0}] +create_generated_clock -source [get_registers {DB_CTRL_SCLK[1]~reg0}] \ + -name db1_ctrl_clk [get_ports DB_CTRL_SCLK[1]] + +set db1_ctrl_outputs [get_ports {DB_CTRL_MOSI[1] DB_CTRL_CS_N[1]}] +set_output_delay -clock db1_ctrl_clk -max $db_cpld_spi_max_out $db1_ctrl_outputs +set_output_delay -clock db1_ctrl_clk -min $db_cpld_spi_min_out $db1_ctrl_outputs + +set db1_ctrl_inputs [get_ports {DB_CTRL_MISO[1]}] +set_input_delay -clock db1_ctrl_clk -max $db_cpld_spi_max_in $db1_ctrl_inputs +set_input_delay -clock db1_ctrl_clk -min $db_cpld_spi_min_in $db1_ctrl_inputs + +##################################################################### +# Power supply clocks, LEDs, DIO direction +##################################################################### +# Change all output signals in this section within one clock period of the +# driving clocks. + +# Power supply clocks +set power_supply_clocks_outputs [get_ports {PWR_SUPPLY_CLK_*}] +set_min_delay -to $power_supply_clocks_outputs 0 +set_max_delay -to $power_supply_clocks_outputs $CLK_100_period + +# LED signals +set led_outputs [get_ports {QSFP0_LED_ACTIVE[*] QSFP0_LED_LINK[*] \ + QSFP1_LED_ACTIVE[*] QSFP1_LED_LINK[*]}] +set_min_delay -to $led_outputs 0 +set_max_delay -to $led_outputs $prc_clock_period + +# DIO direction +set dio_outputs [get_ports {DIO_DIRECTION_A[*] DIO_DIRECTION_B[*]}] +set_min_delay -to $dio_outputs 0 +set_max_delay -to $dio_outputs $clk50_period + +# Power control +set pwr_ctrl_outputs [get_ports {IPASS_POWER_DISABLE PWR_EN_5V_OSC_100 PWR_EN_5V_OSC_122_88}] +set_min_delay -to $pwr_ctrl_outputs 0 +set_max_delay -to $pwr_ctrl_outputs $clk50_period + +# Power fault inputs +# Virtual clocks for constraining inputs. Using an odd clock period to +# make sure any uncovered paths will result in timing errors due to short setup +# or hold path. +set power_fault_inputs [get_ports {IPASS_POWER_EN_FAULT[*]}] +create_clock -name virtual_async_in_clk -period 4.567 +set_input_delay -clock virtual_async_in_clk 0 $power_fault_inputs + +##################################################################### +# FPGA <-> MB CPLD PS SPI interface +##################################################################### +# Assume the PS SPI clock is maximum 5 MHz. +# It is driven from another source and provided with the data. +set ps_sclk_period 200.000 +create_clock -name ps_sclk -period $ps_sclk_period [get_ports PS_CPLD_SCLK] + +# The SPI PS master (on the FPGA) is wired through the MIO (Multiplexed I/O) +# pins, meaning that the timing characteristics of the interface come from +# the controller itself (i.e. no timed routing through PL). +# Based on the SPI master controller specification (DS925: Table 48), +# one may define the min/max input/output delay constraints. +set ps_spi_tco_min -2.000 +set ps_spi_tco_max 5.000 +set ps_spi_miso_setup -2.000 +set ps_spi_miso_hold [expr {0.3 * $ps_sclk_period}] + +# Use the worst-case board propagation delays. +# Assuming 170.0 ps/in. +# Longest trace | Trace length | Trace delay +# CS0_n | 4.735 in | 0.805 ns +# -------------------------------------------- +set ps_spi_board_delay 0.805 + +set ps_slave_inputs [get_ports {PS_CPLD_MOSI PS_CPLD_CS_N[*]}] +# clock is immediately available, data is taking maximum time +# SPI data in CPOL=CPHA=1 is driven on the falling sclk edge +set ps_sclk_max_in_delay [expr {$ps_spi_tco_max + $ps_spi_board_delay}] +set_input_delay -clock ps_sclk -clock_fall \ + -max $ps_sclk_max_in_delay \ + $ps_slave_inputs +# fast data and clock delayed (reducing data delay) +set_input_delay -clock ps_sclk -clock_fall \ + -min [expr {$ps_spi_tco_min - $ps_spi_board_delay}] \ + $ps_slave_inputs + +set ps_slave_outputs [get_ports {PS_CPLD_MISO}] +# use only half the frequency because falling edge is driving data +set_output_delay -clock ps_sclk \ + -max [expr {$ps_spi_miso_setup + 2*$ps_spi_board_delay}] \ + $ps_slave_outputs +# use hold requirement only as clock and data propagation further +# delay the signal +set_output_delay -clock ps_sclk \ + -min [expr {-$ps_spi_miso_hold}] \ + $ps_slave_outputs + +# Chip select signals are captured for binary decoding in 250 MHz clock domain. +# To be able to specify a maximum delay for the data path only a second set of +# input delays is added to the root clock of the 250 MHz domain. +set_input_delay -add_delay -clock CLK_100 0 [get_ports {PS_CPLD_CS_N[*]}] +# Declare paths between the 2 clock domains as false paths +set_false_path -from [get_clocks {CLK_100}] -to [get_ports {PS_CPLD_MISO}] +set_false_path -from [get_clocks {ps_sclk}] -to [get_registers {synchronizer:ps_spi_input_sync_inst*}] +# Specify maximum data path delay +set_max_delay -from [get_ports {PS_CPLD_CS_N[*]}] -to $CLK_250 $clk250_period + +##################################################################### +# MB CPLD PS SPI passthrough +##################################################################### +###### Binary CS decoding ###### +# The CS outputs for the external SPI slaves are driven from a 250 MHz clock to +# ensure glitch free switching after binary encoding. Additionally those signals +# have to meet the setup and hold requirements of the SPI slaves operating at +# ps_sclk (5 MHz). CS lines typically are asserted half a clock period of sclk +# before any active edge of sclk. The constraints below are using multi-cycle +# paths to provide the placer with information about the clock multiplier from +# ps_sclk to 250 MHz. Furthermore they incorporate the time required for +# decoding by lowering the clock multiplier as shown in the waveform below +# (multiplier is not shown correctly). +# +# ps_sclk -\__________________________________________________/-------- +# 250 MHz _/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\_/-\- +# CS @ CPLD input X>--------------- stable ------------------------------------ +# CS @ CPLD output ----------------------- stable --------------------- +# |<----->| min decoding delay +# |<----->| change window +# --------------->| SPI slave hold requirement +# SPI slave setup requirement |<-------------------------------->| +# +# Get port to apply the multi-cycle constraint. +set binary_cs_ports [get_ports {LMK32_CS_N TPM_CS_N PHASE_DAC_CS_N DB_CALEEPROM_CS_N[*] CLK_DB_CS_N}] +# Determine number of full 250 MHz periods within half a period of ps_sclk. +set ps_spi_clock_divider [expr {int($ps_sclk_period/$clk250_period/2)}] +# Setup multi-cycle accounts for +# - one clock cycle data path delay from port to first register stage +# - one clock cycle to resolve meta-stability +# - up to 3 register stages internally (port to ps_cpld_cs_n_shift3) +# - one output register stage (registers on each $binary_cs_ports) +# Static timing analysis will take the data path from register to output port +# into account. +# The number of 250 MHz periods is reduced by a total of 7 clock cycles (listed +# above) to match the SPI slave setup requirement time shown in the waveform +# above. The slave's setup time in ps_sclk domain is specified below for each +# individual slave. +set ps_spi_setup_multicycle [expr {$ps_spi_clock_divider - 7}] +set_multicycle_path -setup -start -to $binary_cs_ports $ps_spi_setup_multicycle +# Hold multicycle accounts for +# - min 2 synchronization register stages internally (ps_cpld_cs_n_shift2) +# (= min one clock cycle delay as data could arrive just before setup +# requirement of first register stages assuming no data delay) +# - one output register stage +# Static timing analysis will take the data path from register to output port +# into account. +# As the clock edge for hold analysis is shifted with the setup edge the number +# of multi cycles has to be increased by this amount of cycles to get back to +# the falling edge of ps_sclk. Furthermore CS lines are released one half +# ps_sclk period after the last data transfer. So hold delay is increased by an +# additional half clock cycle. +set ps_spi_hold_multicycle [expr {$ps_spi_clock_divider + $ps_spi_setup_multicycle - 2}] +set_multicycle_path -hold -start -to $binary_cs_ports $ps_spi_hold_multicycle + +###### local SPI slave ###### +# The chip select path for the MB CPLD itself is driven in the 250 MHz clock +# domain and captured by registers operating at ps_sclk. Therefore setting the +# path as false path preventing the placer from adding additional routing delay +# to ensure hold timing. The setup path is limited to a maximum extend of one +# clock period. As this path crosses clock domains clock propagation is included +# in this path during static timing analysis. The TCL analysis in +# scripts/ps_cs_analysis.tcl ensures a maximum value for data excluding the +# clocking network. +set_false_path -from [get_registers {ps_spi_cs_n_decoded[0]}] -hold +set_max_delay -from [get_registers {ps_spi_cs_n_decoded[0]}] $clk250_period + +###### LMK04832 ###### +create_generated_clock -source [get_ports PS_CPLD_SCLK] \ + -name lmk_spi_sclk [get_ports LMK32_SCLK] + +# Use the worst-case board propagation delays. +# Assuming 170.0 ps/in. +# Longest trace | Trace length | Trace delay +# LMK32_SCLK | 8.259 in | 1.404 ns +# -------------------------------------------- +set lmk_board_delay 1.404 + +# setup and hold dominated by CS <-> SCK relationship +set lmk_setup 20.000 +set lmk_hold 20.000 +set lmk_tco_max 60.000 + +set lmk_outputs [get_ports {LMK32_MOSI LMK32_CS_N}] +set_output_delay -clock lmk_spi_sclk \ + -max [expr {$lmk_setup + $lmk_board_delay + $buffer_prop_max}] \ + $lmk_outputs +set_output_delay -clock lmk_spi_sclk \ + -min [expr {-$lmk_hold - $lmk_board_delay - $buffer_prop_min}] \ + $lmk_outputs + +set lmk_inputs [get_ports {LMK32_MISO}] +set_input_delay -clock lmk_spi_sclk -clock_fall \ + -max [expr {$lmk_tco_max + 2*$lmk_board_delay + 2*$buffer_prop_max}] \ + $lmk_inputs +set_input_delay -clock lmk_spi_sclk -clock_fall \ + -min [expr {2*$buffer_prop_min}] \ + $lmk_inputs + +###### Phase DAC ###### +create_generated_clock -source [get_ports PS_CPLD_SCLK] \ + -name phase_dac_spi_sclk [get_ports PHASE_DAC_SCLK] + +# Use the worst-case board propagation delays. +# Assuming 170.0 ps/in. +# Longest trace | Trace length | Trace delay +# SpiDCs3v3_n | 8.322 in | 1.415 ns +# -------------------------------------------- +set phase_dac_board_delay 1.415 + +#setup dominated by SYNC signal +set phase_dac_setup 13.000 +set phase_dac_hold 5.000 + +# device captures data on falling clock edge (CPOL = 1) +# constraining it as it would be like all the other SPI modules +# PS SPI master is responsible for changing SPI mode when talking +# to this device +set phase_dac_outputs [get_ports {PHASE_DAC_MOSI PHASE_DAC_CS_N}] +set_output_delay -clock phase_dac_spi_sclk -clock_fall \ + -max [expr {$phase_dac_setup + $phase_dac_board_delay}] \ + $phase_dac_outputs +set_output_delay -clock phase_dac_spi_sclk -clock_fall \ + -min [expr {-$phase_dac_hold - $phase_dac_board_delay}] \ + $phase_dac_outputs + +###### TPM ###### +create_generated_clock -source [get_ports PS_CPLD_SCLK] \ + -name tpm_spi_sclk [get_ports TPM_SCLK] + +# Use the worst-case board propagation delays. +# Assuming 170.0 ps/in. +# Longest trace | Trace length | Trace delay +# TPM_CS_n | 1.128 in | 0.196 ns +# -------------------------------------------- +set tpm_board_delay 0.196 + +#tco dominated by NSS signal +set tpm_setup 5.000 +set tpm_hold 5.000 +set tpm_tco_max 25.000 + +set tpm_outputs [get_ports {TPM_MOSI TPM_CS_N}] +set_output_delay -clock tpm_spi_sclk \ + -max [expr {$tpm_setup + $tpm_board_delay}] \ + $tpm_outputs +set_output_delay -clock tpm_spi_sclk \ + -min [expr {-$tpm_hold - $tpm_board_delay}] \ + $tpm_outputs + +set tpm_inputs [get_ports {TPM_MISO}] +set_input_delay -clock tpm_spi_sclk -clock_fall \ + -max [expr {$tpm_tco_max + 2*$tpm_board_delay}] \ + $tpm_inputs +set_input_delay -clock tpm_spi_sclk -clock_fall \ + -min 0 \ + $tpm_inputs + +###### DB Calibration EEPROM ###### +# Use worst case board propagation delays to estimate input and output +# timing. The longest path assuming 170 ps/in is: +# db0_caleeprom_spi_cs_n | 4.387 in | 0.746 ns +set eeprom_board_prop_delay 0.746 +# Within the path to the EEPROM on the DB there is a level-transistor. +# The maximum propagation delays are 0.1..3.3 ns to the DB and 3.7 ns from the DB. +set eeprom_lvl_trans_to_db_delay_min 0.1 +set eeprom_lvl_trans_to_db_delay_max 3.3 +set eeprom_lvl_trans_from_db_delay_max 3.7 +# Data in setup and hold times of the EEPROM are 5ns (based on the +# CS_N setup and hold times). +set db_eeprom_setup 5 +set db_eeprom_hold 5 +# Ouput valid from SCK is min 0 ns and max 8 ns. +set db_eeprom_output_valid 8 + +# max out path assuming clock delay is 0 and data delay is maximum value +set eeprom_max_out [expr {$eeprom_board_prop_delay + $eeprom_lvl_trans_to_db_delay_max + $db_eeprom_setup}] +# min out path assuming clock delay is maximal and data delay is 0 +set eeprom_min_out [expr {-($eeprom_board_prop_delay + $eeprom_lvl_trans_to_db_delay_min + $db_eeprom_hold)}] +# board propagation to eeprom and back + lvl_translator back and forth + clock to data on eeprom +set eeprom_max_in [expr {$eeprom_board_prop_delay*2 + $eeprom_lvl_trans_to_db_delay_max + $eeprom_lvl_trans_from_db_delay_max + $db_eeprom_output_valid}] +# assuming no delay for everything +set eeprom_min_in 0 + +### DB 0 +create_generated_clock -source [get_ports PS_CPLD_SCLK] \ + -name db0_eeprom_clk [get_ports {DB_CALEEPROM_SCLK[0]}] + +set db0_eeprom_outputs [get_ports {DB_CALEEPROM_MOSI[0] DB_CALEEPROM_CS_N[0]}] +set_output_delay -clock db0_eeprom_clk -max $eeprom_max_out $db0_eeprom_outputs +set_output_delay -clock db0_eeprom_clk -min $eeprom_min_out $db0_eeprom_outputs + +set db0_eeprom_inputs [get_ports {DB_CALEEPROM_MISO[0]}] +# data is changed on the falling edge +set_input_delay -clock db0_eeprom_clk -clock_fall -max $eeprom_max_in $db0_eeprom_inputs +set_input_delay -clock db0_eeprom_clk -clock_fall -min $eeprom_min_in $db0_eeprom_inputs + +### DB 1 +create_generated_clock -source [get_ports PS_CPLD_SCLK] \ + -name db1_eeprom_clk [get_ports {DB_CALEEPROM_SCLK[1]}] + +set db1_eeprom_outputs [get_ports {DB_CALEEPROM_MOSI[1] DB_CALEEPROM_CS_N[1]}] +set_output_delay -clock db1_eeprom_clk -max $eeprom_max_out $db1_eeprom_outputs +set_output_delay -clock db1_eeprom_clk -min $eeprom_min_out $db1_eeprom_outputs + +set db1_eeprom_inputs [get_ports {DB_CALEEPROM_MISO[1]}] +# data is changed on the falling edge +set_input_delay -clock db1_eeprom_clk -clock_fall -max $eeprom_max_in $db1_eeprom_inputs +set_input_delay -clock db1_eeprom_clk -clock_fall -min $eeprom_min_in $db1_eeprom_inputs + +#### Clocking AUX board SPI interface #### +# Rev B clocking aux board uses a LMK05318 connected to this interface +# Using its timing for this interface. +create_generated_clock -source [get_ports PS_CPLD_SCLK] \ + -name clk_db_clk_out [get_ports CLK_DB_SCLK] +set clk_db_setup 10.000 +set clk_db_hold 10.000 +set clk_db_tco_max 20.000 +# Just a worst case assumption based on 2 times the MB trace length CLK_DB_MOSI. +# The multiplier 2 accounts for any traces on the CLK AUX board. +set clk_db_board_delay 4.000 + +set clk_db_outputs [get_ports {CLK_DB_CS_N CLK_DB_MOSI}] +# Output signals have to stable for max setup and propagation time. Clock delay +# to device is expected to be 0 in this equation. +set_output_delay -clock clk_db_clk_out \ + -max [expr {$clk_db_setup + $clk_db_board_delay + $buffer_prop_max}] $clk_db_outputs +# The min output delay is comprised of: +# - device required hold time ($clk_db_hold) +# - max clock propagation delay ($clk_db_board_delay) +# - min data propagation time (0) +# All terms have to be negated as min output delay is defined in opposite +# direction (positive into the past). +set_output_delay -clock clk_db_clk_out \ + -min [expr {-$clk_db_hold - $clk_db_board_delay - $buffer_prop_min}] $clk_db_outputs + +set clk_db_inputs [get_ports {CLK_DB_MISO}] +# Max delay calculated is based on +# - max clock delay ($clk_db_board_delay) +# - max clock to out LMK ($clk_db_tco_max) +# - max data path delay ($clk_db_board_delay) +set_input_delay -clock clk_db_clk_out -clock_fall \ + -max [expr {$clk_db_tco_max + $clk_db_board_delay*2 + 2*$buffer_prop_max}] $clk_db_inputs +# Min delay assumes clock propagates to device and data propagates to CPLD +# without any delays. +set_input_delay -clock clk_db_clk_out -clock_fall \ + -min [expr {2*$buffer_prop_min}] $clk_db_inputs + +##################################################################### +# PCIe signals +##################################################################### +# I²C bus is operated at 100kHz. Constraints would not improve timing +# significantly (typically in the order of nanoseconds, which is negligible +# given the SCL period of 10 us). +# PCI-Express reset signal is not timing critical as it is received +# asynchronously by the FPGA. +set_false_path -to [get_ports {IPASS_SDA[0] IPASS_SCL[0] PCIE_RESET}] +# I²C inputs are only consumed by synchronizers. +# Add exceptions for all known consumers. +set_false_path -to [get_registers {PcieCmiWrapper:pcie_cmi_inst|PcieCmi:PcieCmix|UsfCablePort:UsfCablePortx|CablePort:CablePortx|I2cTop:CableI2cx|I2cMonitor:I2cMonitorx|I2cFilter:I2cFilterx|I2cSigFilter:SclFilterx|fSig_ms}] +set_false_path -to [get_registers {PcieCmiWrapper:pcie_cmi_inst|PcieCmi:PcieCmix|UsfCablePort:UsfCablePortx|CablePort:CablePortx|I2cTop:CableI2cx|I2cMonitor:I2cMonitorx|I2cFilter:I2cFilterx|I2cSigFilter:SdaFilterx|fSig_ms}] +set_false_path -to [get_registers {PcieCmiWrapper:pcie_cmi_inst|PcieCmi:PcieCmix|UsfCablePort:UsfCablePortx|CablePort:CablePortx|StuckBusFixer:StuckBusFixerx|DoubleSyncSlAsyncIn:DoubleSclkx|DoubleSyncAsyncInBase:DoubleSyncAsyncInBasex|DFlopAsync:oSig_msx|lpm_ff:LPM_FFx|dffs[0]}] +set_false_path -to [get_registers {PcieCmiWrapper:pcie_cmi_inst|PcieCmi:PcieCmix|UsfCablePort:UsfCablePortx|CablePort:CablePortx|StuckBusFixer:StuckBusFixerx|DoubleSyncSlAsyncIn:DoubleSdax|DoubleSyncAsyncInBase:DoubleSyncAsyncInBasex|DFlopAsync:oSig_msx|lpm_ff:LPM_FFx|dffs[0]}] + +##################################################################### +# Known Issue of On-Chip Flash +##################################################################### +# see https://www.intel.com/content/www/us/en/programmable/support/support-resources/knowledge-base/tools/2016/warning--332060---node---alteraonchipflash-onchipflash-alteraonc.html +create_generated_clock -name flash_se_neg_reg \ + -source [get_pins { on_chip_flash:flash_inst|altera_onchip_flash:onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|clk }] \ + -divide_by 2 [get_pins { on_chip_flash:flash_inst|altera_onchip_flash:onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|q } ] + +##################################################################### +# Clock uncertainty +##################################################################### +# Assign some uncertainty to all clocks +set clock_uncertainty 0.150 +set_clock_uncertainty -to [get_clocks *] $clock_uncertainty +derive_clock_uncertainty diff --git a/top/x400/cpld/mb_cpld.v b/top/x400/cpld/mb_cpld.v new file mode 100644 index 0000000..4ea5dc5 --- /dev/null +++ b/top/x400/cpld/mb_cpld.v @@ -0,0 +1,1033 @@ +// +// 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 + //--------------------------------------------------------------------------- + + // 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; + + //--------------------------------------------------------------------------- + // 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 diff --git a/top/x400/cpld/pl_cpld_regs.v b/top/x400/cpld/pl_cpld_regs.v new file mode 100644 index 0000000..19acdea --- /dev/null +++ b/top/x400/cpld/pl_cpld_regs.v @@ -0,0 +1,297 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: pl_cpld_regs +// +// Description: +// +// Basic Registers to inform software about version and capabilities. +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers +// + +`default_nettype none + + +module pl_cpld_regs #( + parameter BASE_ADDRESS = 0 +) ( + input wire ctrlport_clk, + input wire ctrlport_rst, + + // Request + input wire s_ctrlport_req_wr, + input wire s_ctrlport_req_rd, + input wire [19:0] s_ctrlport_req_addr, + input wire [31:0] s_ctrlport_req_data, + // Response + output reg s_ctrlport_resp_ack, + output reg [ 1:0] s_ctrlport_resp_status, + output reg [31:0] s_ctrlport_resp_data, + + // 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, + + // iPass status + output wire [ 1:0] ipass_cable_present +); + + `include "regmap/constants_regmap_utils.vh" + `include "regmap/pl_cpld_base_regmap_utils.vh" + `include "../../../lib/rfnoc/core/ctrlport.vh" + + //--------------------------------------------------------------------------- + // Address Calculation + //--------------------------------------------------------------------------- + + localparam NUM_ADDRESSES = 64; + wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && + (s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES); + + //--------------------------------------------------------------------------- + // Internal Registers + //--------------------------------------------------------------------------- + + reg [SCRATCH_REGISTER_SIZE-1:0] scratch_reg; + reg [LED_REGISTER_SIZE-1:0] led_reg; + reg [CABLE_PRESENT_REG_SIZE-1:0] ipass_reg; + + //--------------------------------------------------------------------------- + // Assign Outputs + //--------------------------------------------------------------------------- + + assign qsfp0_led_active = led_reg[QSFP0_LED_ACTIVE+:QSFP0_LED_ACTIVE_SIZE]; + assign qsfp0_led_link = led_reg[QSFP0_LED_LINK+:QSFP0_LED_LINK_SIZE]; + + assign qsfp1_led_active = led_reg[QSFP1_LED_ACTIVE+:QSFP1_LED_ACTIVE_SIZE]; + assign qsfp1_led_link = led_reg[QSFP1_LED_LINK+:QSFP1_LED_LINK_SIZE]; + + assign ipass_cable_present = ipass_reg; + + //--------------------------------------------------------------------------- + // Handling of ControlPort Requests + //--------------------------------------------------------------------------- + + always @(posedge ctrlport_clk) begin + // Reset internal registers and responses + if (ctrlport_rst) begin + scratch_reg <= 0; + led_reg <= 0; + ipass_reg <= 0; + s_ctrlport_resp_ack <= 1'b0; + + // Write requests + end else if (s_ctrlport_req_wr) begin + // Always issue an ack and no data + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'bx}}; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + SCRATCH_REGISTER: + scratch_reg <= s_ctrlport_req_data; + + BASE_ADDRESS + LED_REGISTER: + led_reg <= s_ctrlport_req_data[LED_REGISTER_SIZE-1:0]; + + BASE_ADDRESS + CABLE_PRESENT_REG: begin + ipass_reg[0] <= s_ctrlport_req_data[IPASS0_CABLE_PRESENT]; + ipass_reg[1] <= s_ctrlport_req_data[IPASS1_CABLE_PRESENT]; + end + + // Error on undefined address + default: begin + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // Read request + end else if (s_ctrlport_req_rd) begin + // Default assumption: valid request + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + SIGNATURE_REGISTER: + s_ctrlport_resp_data <= PL_CPLD_SIGNATURE; + + BASE_ADDRESS + REVISION_REGISTER: + s_ctrlport_resp_data <= CPLD_REVISION; + + BASE_ADDRESS + OLDEST_COMPATIBLE_REVISION_REGISTER: + s_ctrlport_resp_data <= OLDEST_CPLD_REVISION; + + BASE_ADDRESS + SCRATCH_REGISTER: + s_ctrlport_resp_data <= scratch_reg; + + BASE_ADDRESS + GIT_HASH_REGISTER: + `ifdef GIT_HASH + s_ctrlport_resp_data <= `GIT_HASH; + `else + s_ctrlport_resp_data <= 32'hDEADBEEF; + `endif + + BASE_ADDRESS + LED_REGISTER: + s_ctrlport_resp_data <= {{(CTRLPORT_DATA_W - LED_REGISTER_SIZE){1'b0}}, led_reg}; + + BASE_ADDRESS + CABLE_PRESENT_REG: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}}; + s_ctrlport_resp_data[IPASS0_CABLE_PRESENT] <= ipass_reg[0]; + s_ctrlport_resp_data[IPASS1_CABLE_PRESENT] <= ipass_reg[1]; + end + + // Error on undefined address + default: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'bx}}; + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // No request + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + +endmodule + + +`default_nettype wire + + +//XmlParse xml_on +// +// +// +// Basic registers containing version and capabilities information. +// +// +// +// Contains the product's signature. +// +// Fixed value PL_CPLD_SIGNATURE of @.CONSTANTS_REGMAP +// +// +// +// +// Contains the CPLD revision (see CPLD_REVISION of @.CONSTANTS_REGMAP) +// +// Contains revision hour code. +// +// +// Contains revision day code. +// +// +// Contains revision month code. +// +// +// Contains revision year code. +// +// +// +// +// +// This register returns (in YYMMDDHH format) the oldest revision +// that is still compatible with this one. Compatible means that +// registers or register bits may have been added, but not +// modified or deleted (see OLDEST_CPLD_REVISION of @.CONSTANTS_REGMAP). +// +// +// Contains revision hour code. +// +// +// Contains revision day code. +// +// +// Contains revision month code. +// +// +// Contains revision year code. +// +// +// +// +// Read/write register for general software use. +// +// +// +// +// Git hash of commit used to build this image.{br} +// Value equals 0xDEADBEEF if the git hash was not used during synthesis. +// +// +// +// 0x0 in case the git status was clean{br} +// 0xF in case there were uncommitted changes +// +// +// +// 7 hex digit hash code of the commit +// +// +// +// +// +// +// Register Map to control QSFP LEDs. +// +// +// +// Provides to the LEDs of the QSFP ports. +// Write access will directly change the LED status. +// The LED lights up if the corresponding bit is set. +// +// +// Link LEDs of QSFP port 0 +// +// +// Active LEDs of QSFP port 0 +// +// +// Link LEDs of QSFP port 1 +// +// +// Active LEDs of QSFP port 1 +// +// +// +// +// +// +// Cable present status register. +// +// +// +// Information from FPGA about the cable present status. +// +// +// Set to 1 if cable present in iPass 0 connector. +// +// +// Set to 1 if cable present in iPass 1 connector. +// +// +// +// +//XmlParse xml_off diff --git a/top/x400/cpld/ps_cpld_regs.v b/top/x400/cpld/ps_cpld_regs.v new file mode 100644 index 0000000..d5f9b1d --- /dev/null +++ b/top/x400/cpld/ps_cpld_regs.v @@ -0,0 +1,404 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ps_cpld_regs +// +// Description: +// +// Basic registers to inform software about version and capabilities. +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers +// + +`default_nettype none + + +module ps_cpld_regs #( + parameter BASE_ADDRESS = 0 +) ( + input wire ctrlport_clk, + input wire ctrlport_rst, + + // Request + input wire s_ctrlport_req_wr, + input wire s_ctrlport_req_rd, + input wire [19:0] s_ctrlport_req_addr, + input wire [31:0] s_ctrlport_req_data, + // Response + output reg s_ctrlport_resp_ack, + output reg [ 1:0] s_ctrlport_resp_status, + output reg [31:0] s_ctrlport_resp_data, + + // Configuration outputs + output reg [ 1:0] db_clk_enable = 2'b00, + output reg [ 1:0] db_reset = 2'b11, + output reg pll_ref_clk_enable = 1'b0, + + output reg [11:0] dio_direction_a = 12'b0, + output reg [11:0] dio_direction_b = 12'b0, + + output reg [39:0] serial_num = 40'b0, + output reg cmi_ready = 1'b0, + input wire cmi_other_side_detected +); + +`include "regmap/constants_regmap_utils.vh" +`include "regmap/ps_cpld_base_regmap_utils.vh" +`include "../../../lib/rfnoc/core/ctrlport.vh" + +//----------------------------------------------------------------------------- +// Address Calculation +//----------------------------------------------------------------------------- + +localparam NUM_ADDRESSES = 64; +wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && + (s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES); + +//----------------------------------------------------------------------------- +// Internal Registers +//----------------------------------------------------------------------------- + +reg [SCRATCH_REGISTER_SIZE-1:0] scratch_reg; + +//----------------------------------------------------------------------------- +// Handling of ControlPort Requests +//----------------------------------------------------------------------------- + +always @(posedge ctrlport_clk) begin + // Reset internal registers and responses + if (ctrlport_rst) begin + scratch_reg <= 0; + db_clk_enable <= 2'b00; + db_reset <= 2'b11; + pll_ref_clk_enable <= 1'b0; + dio_direction_a <= {DIO_DIRECTION_A_SIZE{1'b0}}; + dio_direction_b <= {DIO_DIRECTION_B_SIZE{1'b0}}; + s_ctrlport_resp_ack <= 1'b0; + s_ctrlport_resp_data <= {CTRLPORT_ADDR_W {1'bx}}; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + // Write requests + end else begin + if (s_ctrlport_req_wr) begin + // Always issue an ack and no data + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_data <= {CTRLPORT_ADDR_W {1'bx}}; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + SCRATCH_REGISTER: + scratch_reg <= s_ctrlport_req_data; + + BASE_ADDRESS + PL_DB_REGISTER: begin + if (s_ctrlport_req_data[DISABLE_CLOCK_DB0]) begin + db_clk_enable[0] <= 1'b0; + end else if (s_ctrlport_req_data[ENABLE_CLOCK_DB0]) begin + db_clk_enable[0] <= 1'b1; + end + if (s_ctrlport_req_data[DISABLE_CLOCK_DB1]) begin + db_clk_enable[1] <= 1'b0; + end else if (s_ctrlport_req_data[ENABLE_CLOCK_DB1]) begin + db_clk_enable[1] <= 1'b1; + end + if (s_ctrlport_req_data[DISABLE_PLL_REF_CLOCK]) begin + pll_ref_clk_enable <= 1'b0; + end else if (s_ctrlport_req_data[ENABLE_PLL_REF_CLOCK]) begin + pll_ref_clk_enable <= 1'b1; + end + if (s_ctrlport_req_data[ASSERT_RESET_DB0]) begin + db_reset[0] <= 1'b1; + end else if (s_ctrlport_req_data[RELEASE_RESET_DB0]) begin + db_reset[0] <= 1'b0; + end + if (s_ctrlport_req_data[ASSERT_RESET_DB1]) begin + db_reset[1] <= 1'b1; + end else if (s_ctrlport_req_data[RELEASE_RESET_DB1]) begin + db_reset[1] <= 1'b0; + end + end + + BASE_ADDRESS + DIO_DIRECTION_REGISTER: begin + dio_direction_a <= s_ctrlport_req_data[DIO_DIRECTION_A_MSB:DIO_DIRECTION_A]; + dio_direction_b <= s_ctrlport_req_data[DIO_DIRECTION_B_MSB:DIO_DIRECTION_B]; + end + + BASE_ADDRESS + SERIAL_NUM_LOW_REG: begin + serial_num[31:0] <= s_ctrlport_req_data; + end + + BASE_ADDRESS + SERIAL_NUM_HIGH_REG: begin + serial_num[39:32] <= s_ctrlport_req_data[SERIAL_NUM_HIGH_REG_SIZE-1:0]; + end + + BASE_ADDRESS + CMI_CONTROL_STATUS: begin + cmi_ready <= s_ctrlport_req_data[CMI_READY]; + end + + // Error on undefined address + default: begin + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // Read request + end else if (s_ctrlport_req_rd) begin + // Default assumption: valid request + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}}; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + SIGNATURE_REGISTER: + s_ctrlport_resp_data <= PS_CPLD_SIGNATURE; + + BASE_ADDRESS + REVISION_REGISTER: + s_ctrlport_resp_data <= CPLD_REVISION; + + BASE_ADDRESS + OLDEST_COMPATIBLE_REVISION_REGISTER: + s_ctrlport_resp_data <= OLDEST_CPLD_REVISION; + + BASE_ADDRESS + SCRATCH_REGISTER: + s_ctrlport_resp_data <= scratch_reg; + + BASE_ADDRESS + GIT_HASH_REGISTER: + `ifdef GIT_HASH + s_ctrlport_resp_data <= `GIT_HASH; + `else + s_ctrlport_resp_data <= 32'hDEADBEEF; + `endif + + BASE_ADDRESS + PL_DB_REGISTER: begin + s_ctrlport_resp_data[DB0_CLOCK_ENABLED] <= db_clk_enable[0]; + s_ctrlport_resp_data[DB1_CLOCK_ENABLED] <= db_clk_enable[1]; + s_ctrlport_resp_data[PLL_REF_CLOCK_ENABLED] <= pll_ref_clk_enable; + s_ctrlport_resp_data[DB0_RESET_ASSERTED] <= db_reset[0]; + s_ctrlport_resp_data[DB1_RESET_ASSERTED] <= db_reset[1]; + end + + BASE_ADDRESS + DIO_DIRECTION_REGISTER: begin + s_ctrlport_resp_data[DIO_DIRECTION_A_MSB:DIO_DIRECTION_A] <= dio_direction_a; + s_ctrlport_resp_data[DIO_DIRECTION_B_MSB:DIO_DIRECTION_B] <= dio_direction_b; + end + + BASE_ADDRESS + SERIAL_NUM_LOW_REG: begin + s_ctrlport_resp_data <= serial_num[31:0]; + end + + BASE_ADDRESS + SERIAL_NUM_HIGH_REG: begin + s_ctrlport_resp_data[SERIAL_NUM_HIGH_REG_SIZE-1:0] <= serial_num[39:32]; + end + + BASE_ADDRESS + CMI_CONTROL_STATUS: begin + s_ctrlport_resp_data[CMI_READY] <= cmi_ready; + s_ctrlport_resp_data[OTHER_SIDE_DETECTED] <= cmi_other_side_detected; + end + + // Error on undefined address + default: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'bx}}; + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // No request + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end +end + +endmodule + + +`default_nettype wire + + +//XmlParse xml_on +// +// +// +// Basic registers containing version and capabilites information. +// +// +// +// Contains the product's signature. +// +// Fixed value PS_CPLD_SIGNATURE of @.CONSTANTS_REGMAP +// +// +// +// +// Contains the CPLD revision (see CPLD_REVISION of @.CONSTANTS_REGMAP). +// +// Contains revision hour code. +// +// +// Contains revision day code. +// +// +// Contains revision month code. +// +// +// Contains revision year code. +// +// +// +// +// +// This register returns (in YYMMDDHH format) the oldest revision +// that is still compatible with this one. Compatible means that +// registers or register bits may have been added, but not +// modified or deleted (see OLDEST_CPLD_REVISION of @.CONSTANTS_REGMAP). +// +// +// Contains revision hour code. +// +// +// Contains revision day code. +// +// +// Contains revision month code. +// +// +// Contains revision year code. +// +// +// +// +// Read/write register for general software use. +// +// +// +// +// Git hash of commit used to build this image.{br} +// Value equals 0xDEADBEEF if the git hash was not used during synthesis. +// +// +// +// 0x0 in case the git status was clean{br} +// 0xF in case there were uncommitted changes +// +// +// +// 7 hex digit hash code of the commit +// +// +// +// +// +// +// Register Map to control MB CPLD functions. +// +// +// +// Register to control the PL part DB SPI connection and reset generation. +// The DB connection is clocked with PLL reference clock. Ensure this clock is stable +// and enabled before starting any SPI request. +// The PLL reference clock can be disabled if both DB connections are disabled or inactive. +// To enable the DB connection, enable clock with one write access and release +// reset with the next write access. +// To disable the DB connection, assert reset with one write access and +// disable clocks with the next write access. +// +// +// Indicates if a clock is forwarded to DB 0. +// +// +// Indicates if a clock is forwarded to DB 1. +// +// +// Indicates if the PLL reference clock for the PL interface is enabled. +// +// +// Indicates that reset is asserted for DB 0. +// +// +// Indicates that reset is asserted for DB 1. +// +// +// Writing with this flag set enables DB 0 clock forwarding. (may be overwritten by @.DISABLE_CLOCK_DB0) +// +// +// Writing with this flag set enables DB 1 clock forwarding. (may be overwritten by @.DISABLE_CLOCK_DB1) +// +// +// Writing with this flag set enables the PLL reference clock. Assert this flag after PLL reference clock is stable. (may be overwritten by @.DISABLE_PLL_REF_CLOCK) +// +// +// Writing with this flag set disables DB 0 clock forwarding (overrides @.ENABLE_CLOCK_DB0) +// +// +// Writing with this flag set disables DB 1 clock forwarding (overrides @.ENABLE_CLOCK_DB1) +// +// +// Writing with this flag set disables the PLL reference clock (overrides @.ENABLE_PLL_REF_CLOCK). Assert this flag to reconfigure the clock. +// +// +// Writing with this flag set releases DB 0 reset. (may be overwritten by @.ASSERT_RESET_DB0) +// +// +// Writing with this flag set releases DB 1 reset. (may be overwritten by @.ASSERT_RESET_DB1) +// +// +// Writing with this flag set asserts reset for DB 0 (overrides @.RELEASE_RESET_DB0) +// +// +// Writing with this flag set asserts reset for DB 1 (overrides @.RELEASE_RESET_DB1) +// +// +// +// +// +// +// Registers to control the GPIO buffer direction on the DIO board connected to the FPGA. +// Make sure the GPIO lines between FPGA and GPIO board are not driven by two drivers. +// Set the direction in the FPGA's DIO register appropriately. +// +// +// +// Set the direction of FPGA buffer connected to DIO ports on the DIO board.{br/} +// Each bit represents one signal line. 0 = line is an input to the FPGA, 1 = line is an output driven by the FPGA. +// +// +// +// +// +// +// +// +// Cable present status register. +// +// +// Least significant bytes of 5 byte serial number. +// +// +// Most significant byte of 5 byte serial number. +// +// +// Control CMI communication and delivers information on the CMI link status. +// +// Set if the device is ready to establish a PCI-Express link (affects CMI_CLP_READY bit). +// +// +// 1 if an upstream CMI device has been detected. +// +// +// +// +//XmlParse xml_off diff --git a/top/x400/cpld/ps_power_regs.v b/top/x400/cpld/ps_power_regs.v new file mode 100644 index 0000000..3e1a252 --- /dev/null +++ b/top/x400/cpld/ps_power_regs.v @@ -0,0 +1,231 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ps_power_regs +// +// Description: +// +// Registers to control power supplies on the motherboard. +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers. +// NUM_ADDRESSES : Number of bytes of address space to use. +// + +`default_nettype none + + +module ps_power_regs #( + parameter BASE_ADDRESS = 0, + parameter NUM_ADDRESSES = 32 +) ( + input wire ctrlport_clk, + input wire ctrlport_rst, + + // Request + input wire s_ctrlport_req_wr, + input wire s_ctrlport_req_rd, + input wire [19:0] s_ctrlport_req_addr, + input wire [31:0] s_ctrlport_req_data, + // Response + output reg s_ctrlport_resp_ack, + output reg [ 1:0] s_ctrlport_resp_status, + output reg [31:0] s_ctrlport_resp_data, + + // iPass + output reg ipass_power_disable = 1'b0, + input wire [ 1:0] ipass_power_fault_n, + + // Oscillators + output reg osc_100_en, + output reg osc_122_88_en +); + + `include "regmap/ps_power_regmap_utils.vh" + `include "../../../lib/rfnoc/core/ctrlport.vh" + + //---------------------------------------------------------- + // Address Calculation + //---------------------------------------------------------- + + wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && + (s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES); + + //---------------------------------------------------------- + // Internal Registers + //---------------------------------------------------------- + + reg [1:0] ipass_power_sticky = 2'b00; + reg [1:0] ipass_clear_sticky = 2'b00; + + //---------------------------------------------------------- + // Handling of ControlPort Requests + //---------------------------------------------------------- + + always @(posedge ctrlport_clk) begin + // Reset internal registers and responses + if (ctrlport_rst) begin + ipass_power_disable <= 1'b0; + s_ctrlport_resp_ack <= 1'b0; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + s_ctrlport_resp_data <= {CTRLPORT_ADDR_W {1'bx}}; + + osc_100_en <= 1'b0; + osc_122_88_en <= 1'b0; + + end else begin + // Default assignments + ipass_clear_sticky <= 2'b00; + + // Write requests + if (s_ctrlport_req_wr) begin + // Always issue an ack and no data + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + s_ctrlport_resp_data <= {CTRLPORT_ADDR_W {1'bx}}; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + IPASS_POWER_REG: begin + ipass_power_disable <= s_ctrlport_req_data[IPASS_DISABLE_POWER_BIT]; + ipass_clear_sticky[0] <= s_ctrlport_req_data[IPASS_CLEAR_POWER_FAULT0]; + ipass_clear_sticky[1] <= s_ctrlport_req_data[IPASS_CLEAR_POWER_FAULT1]; + end + + BASE_ADDRESS + OSC_POWER_REG: begin + osc_100_en <= s_ctrlport_req_data[OSC_100]; + osc_122_88_en <= s_ctrlport_req_data[OSC_122_88]; + end + + // Error on undefined address + default: begin + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // Read request + end else if (s_ctrlport_req_rd) begin + // Default assumption: valid request + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}}; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + IPASS_POWER_REG: begin + s_ctrlport_resp_data[IPASS_DISABLE_POWER_BIT] <= ipass_power_disable; + s_ctrlport_resp_data[IPASS_POWER_FAULT0] <= ipass_power_sticky[0]; + s_ctrlport_resp_data[IPASS_POWER_FAULT1] <= ipass_power_sticky[1]; + end + + BASE_ADDRESS + OSC_POWER_REG: begin + s_ctrlport_resp_data[OSC_100] <= osc_100_en; + s_ctrlport_resp_data[OSC_122_88] <= osc_122_88_en; + end + + // Error on undefined address + default: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'bx}}; + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // No request + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + end + + //---------------------------------------------------------- + // Sticky Logic of Power Registers + //---------------------------------------------------------- + + // Synchronize asynchronous inputs + wire [1:0] ipass_power_fault_lcl_n; + synchronizer #( + .WIDTH (2), + .STAGES (2), + .INITIAL_VAL (1'b0), + .FALSE_PATH_TO_IN (1) + ) power_fault_sync ( + .clk (ctrlport_clk), + .rst (ctrlport_rst), + .in (ipass_power_fault_n), + .out (ipass_power_fault_lcl_n) + ); + + always @(posedge ctrlport_clk) begin + if (ctrlport_rst) begin + ipass_power_sticky <= 2'b00; + end else begin + // Keep value if not cleared or set in case of fault + ipass_power_sticky <= (ipass_power_sticky & ~ipass_clear_sticky) | ~ipass_power_fault_lcl_n; + end + end + +endmodule + + +`default_nettype wire + + +//XmlParse xml_on +// +// +// +// Registers to control power supplies on the motherboard. +// +// +// +// Controls the power supplies for the iPass connectors. +// +// Set to 1 to disable power for both iPass connectors. +// +// +// Clear @.IPASS_POWER_FAULT0. +// +// +// Clear @.IPASS_POWER_FAULT1. +// +// +// +// Asserted signal indicates a power fault in power switch for iPass +// connector 0. Sticky bit. Asserted on occurrence. Reset using +// @.IPASS_CLEAR_POWER_FAULT0. +// +// +// +// +// Asserted signal indicates a power fault in power switch for iPass +// connector 1. Sticky bit. Asserted on occurrence. Reset using +// @.IPASS_CLEAR_POWER_FAULT1. +// +// +// +// +// +// Controls the power supplies for the oscillators. +// +// Enables 5V power switch for the 100 MHz oscillator. +// +// +// Enables 5V power switch for the 122.88 MHz oscillator. +// +// +// +// +//XmlParse xml_off diff --git a/top/x400/cpld/pwr_supply_clk_gen.v b/top/x400/cpld/pwr_supply_clk_gen.v new file mode 100644 index 0000000..e69db9d --- /dev/null +++ b/top/x400/cpld/pwr_supply_clk_gen.v @@ -0,0 +1,73 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: pwr_supply_clk_gen +// +// Description: +// +// Generates a clock for one motherboard power supply. +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers. +// NUM_ADDRESSES : Number of bytes of address space to use. +// + +`default_nettype none + + +module pwr_supply_clk_gen#( + parameter SOURCE_CLK_FREQ = 100_000_000, + parameter TARGET_CLK_FREQ = 100_000 +) ( + // Base clock and reset + input wire clk, + input wire rst, + + // Power supply clocks + output reg pwr_supply_clk +); + +//----------------------------------------------------------------------------- +// Counter Calculation / Definition +//----------------------------------------------------------------------------- +// Counter to generate the power supply switching clock + +// Assumption: the ratio between the generated clock and the source clock is +// even, therefore we can produce a 50% DC clock output. +localparam MAX_COUNT = SOURCE_CLK_FREQ / TARGET_CLK_FREQ / 2; +localparam COUNTER_W = $clog2(MAX_COUNT); +reg [COUNTER_W-1:0] counter = 0; + +//----------------------------------------------------------------------------- +// Clock Generation +//----------------------------------------------------------------------------- +// This process implements a simple clock divider for the power supply +// switcher. + +// SAFE COUNTER START! rst is a synchronous reset generated in the +// clk domain; therefore, inherently safe. +always @(posedge clk) begin + if (rst) begin + counter <= 0; + pwr_supply_clk <= 1'b0; + end + else begin + // Add one every cycle to the counter + counter <= counter + 1'b1; + + // When the counter reaches its mid value, it is reset and the output clock + // output is toggled. + if (counter == MAX_COUNT-1) begin + counter <= 0; + pwr_supply_clk <= ~pwr_supply_clk; + end + end +end + +endmodule + + +`default_nettype wire diff --git a/top/x400/cpld/raw_conversion.cof b/top/x400/cpld/raw_conversion.cof new file mode 100644 index 0000000..87ecb15 --- /dev/null +++ b/top/x400/cpld/raw_conversion.cof @@ -0,0 +1,39 @@ + + + output_files/mb_cpld_converted.pof + 1 + 1 + 14 + + Page_0 + 1 + + output_files/mb_cpld.sof1 + + + 10 + 0 + 0 + 1 + 1 + + 1 + + + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + 1 + 2 + 0 + -1 + -1 + 1 + + \ No newline at end of file diff --git a/top/x400/cpld/reconfig_engine.v b/top/x400/cpld/reconfig_engine.v new file mode 100644 index 0000000..a7c94b4 --- /dev/null +++ b/top/x400/cpld/reconfig_engine.v @@ -0,0 +1,1024 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: reconfig_engine +// +// Description: +// +// This file implements the registers and the state machine to interface with +// Intel's IP for the Max 10 FPGA that allows in-field updates to the primary +// FPGA image. This state machine has been designed to provide a level of +// abstraction between the register interface provided to user and the +// details of interfacing with Intel's On-Chip Flash IP block. The user +// simply needs to instruct this state machine to enable/disable write +// protection and perform read/write/erase operations accordingly to load and +// verify a new primary FPGA image. Since the purpose of this file is to +// allow modification to an FPGA image care has been taken to mitigate data +// corruption. +// +// The interface to Intel's On-Chip Flash IP block implemented in this file +// is based on the information found in the Max 10 User Flash Memory User +// Guide found at the link below. +// +// https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/max-10/ug_m10_ufm.pdf +// +// Parameters: +// +// BASE_ADDRESS : Base address for CtrlPort registers. +// NUM_ADDRESSES : Number of bytes of address space to use. +// MEM_INIT : Memory initialization enabled. Set to 0 if MAX10 internal +// configuration set to single compressed image. Set to 1 if +// MAX10 internal configuration set to single compressed +// image with memory initialization. +// + +`default_nettype none + + +module reconfig_engine #( + parameter BASE_ADDRESS = 0, + parameter NUM_ADDRESSES = 32, + parameter MEM_INIT = 0 +) ( + input wire ctrlport_clk, + input wire ctrlport_rst, + + /// Request + input wire s_ctrlport_req_wr, + input wire s_ctrlport_req_rd, + input wire [19:0] s_ctrlport_req_addr, + input wire [31:0] s_ctrlport_req_data, + // Response + output reg s_ctrlport_resp_ack, + output reg [ 1:0] s_ctrlport_resp_status, + output reg [31:0] s_ctrlport_resp_data, + + // Interface to On-Chip Flash IP + output reg csr_addr, + output reg csr_read, + output reg [31:0] csr_writedata, + output reg csr_write, + input wire [31:0] csr_readdata, + output reg [16:0] data_addr, + output reg data_read, + output reg [31:0] data_writedata, + output reg data_write, + input wire [31:0] data_readdata, + input wire data_waitrequest, + input wire data_readdatavalid +); + + `include "regmap/reconfig_regmap_utils.vh" + `include "../../../lib/rfnoc/core/ctrlport.vh" + + //---------------------------------------------------------- + // Flash Interface between Registers and State Machine + //---------------------------------------------------------- + + // Flash Data Interface + reg [16:0] flash_addr = 0; + reg [31:0] flash_write_data = 0; + reg [31:0] flash_read_data; + + // Flash Control Interface - Control + reg flash_read_stb = 1'b0; + reg flash_write_stb = 1'b0; + reg flash_erase_stb = 1'b0; + reg flash_enable_wp_stb = 1'b0; + reg flash_disable_wp_stb = 1'b0; + reg [2:0] flash_sector = 3'b0; + + // Flash Control Interface - Status + reg flash_wp_enabled; + reg flash_read_idle; + reg flash_write_idle; + reg flash_erase_idle; + reg flash_read_err; + reg flash_write_err; + reg flash_erase_err; + reg clear_flash_read_err_stb = 1'b0; + reg clear_flash_write_err_stb = 1'b0; + reg clear_flash_erase_err_stb = 1'b0; + + //---------------------------------------------------------- + // Address Calculation + //---------------------------------------------------------- + + wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && + (s_ctrlport_req_addr < BASE_ADDRESS + NUM_ADDRESSES); + + //---------------------------------------------------------- + // Handling of ControlPort Requests + //---------------------------------------------------------- + + always @(posedge ctrlport_clk) begin + // Default assignments + s_ctrlport_resp_ack <= 1'b0; + + flash_read_stb <= 1'b0; + flash_write_stb <= 1'b0; + flash_erase_stb <= 1'b0; + flash_enable_wp_stb <= 1'b0; + flash_disable_wp_stb <= 1'b0; + clear_flash_read_err_stb <= 1'b0; + clear_flash_write_err_stb <= 1'b0; + clear_flash_erase_err_stb <= 1'b0; + + // Do not acknowledge on reset + if (ctrlport_rst) begin + s_ctrlport_resp_ack <= 1'b0; + s_ctrlport_resp_data <= {32{1'bx}}; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + // Write requests + end else begin + if (s_ctrlport_req_wr) begin + // Always issue an ack and no data + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_data <= {32{1'bx}}; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + FLASH_CONTROL_REG: begin + flash_read_stb <= s_ctrlport_req_data[FLASH_READ_STB]; + flash_write_stb <= s_ctrlport_req_data[FLASH_WRITE_STB]; + flash_erase_stb <= s_ctrlport_req_data[FLASH_ERASE_STB]; + flash_enable_wp_stb <= s_ctrlport_req_data[FLASH_ENABLE_WP_STB]; + flash_disable_wp_stb <= s_ctrlport_req_data[FLASH_DISABLE_WP_STB]; + clear_flash_read_err_stb <= s_ctrlport_req_data[CLEAR_FLASH_READ_ERROR_STB]; + clear_flash_write_err_stb <= s_ctrlport_req_data[CLEAR_FLASH_WRITE_ERROR_STB]; + clear_flash_erase_err_stb <= s_ctrlport_req_data[CLEAR_FLASH_ERASE_ERROR_STB]; + flash_sector <= s_ctrlport_req_data[FLASH_ERASE_SECTOR_MSB:FLASH_ERASE_SECTOR]; + end + + BASE_ADDRESS + FLASH_ADDR_REG: begin + flash_addr <= s_ctrlport_req_data[FLASH_ADDR_MSB:FLASH_ADDR]; + end + + BASE_ADDRESS + FLASH_WRITE_DATA_REG: begin + flash_write_data <= s_ctrlport_req_data[FLASH_WRITE_DATA_MSB:FLASH_WRITE_DATA]; + end + + // Error on undefined address + default: begin + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + + // Read request + end else if (s_ctrlport_req_rd) begin + // Default assumption: valid request + s_ctrlport_resp_ack <= 1'b1; + s_ctrlport_resp_status <= CTRL_STS_OKAY; + + case (s_ctrlport_req_addr) + BASE_ADDRESS + FLASH_STATUS_REG: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}}; + s_ctrlport_resp_data[FLASH_WP_ENABLED] <= flash_wp_enabled; + s_ctrlport_resp_data[FLASH_READ_IDLE] <= flash_read_idle; + s_ctrlport_resp_data[FLASH_READ_ERR] <= flash_read_err; + s_ctrlport_resp_data[FLASH_ERASE_IDLE] <= flash_erase_idle; + s_ctrlport_resp_data[FLASH_ERASE_ERR] <= flash_erase_err; + s_ctrlport_resp_data[FLASH_WRITE_IDLE] <= flash_write_idle; + s_ctrlport_resp_data[FLASH_WRITE_ERR] <= flash_write_err; + s_ctrlport_resp_data[FLASH_MEM_INIT_ENABLED] <= MEM_INIT ? 1'b1 : 1'b0; + end + + BASE_ADDRESS + FLASH_ADDR_REG: begin + s_ctrlport_resp_data <= {CTRLPORT_DATA_W {1'b0}}; + s_ctrlport_resp_data[FLASH_ADDR_MSB:FLASH_ADDR] <= flash_addr; + end + + BASE_ADDRESS + FLASH_READ_DATA_REG: begin + s_ctrlport_resp_data <= flash_read_data; + end + + BASE_ADDRESS + FLASH_CFM0_START_ADDR_REG: begin + s_ctrlport_resp_data <= MEM_INIT ? FLASH_PRIMARY_IMAGE_START_ADDR_MEM_INIT : + FLASH_PRIMARY_IMAGE_START_ADDR; + end + + BASE_ADDRESS + FLASH_CFM0_END_ADDR_REG: begin + s_ctrlport_resp_data <= FLASH_PRIMARY_IMAGE_END_ADDR; + end + + // Error on undefined address + default: begin + s_ctrlport_resp_data <= {32{1'bx}}; + if (address_in_range) begin + s_ctrlport_resp_status <= CTRL_STS_CMDERR; + + // No response if out of range + end else begin + s_ctrlport_resp_ack <= 1'b0; + end + end + endcase + end + end + end + + //---------------------------------------------------------- + // State Machine Constants + //---------------------------------------------------------- + + // Local state + localparam IDLE = 4'h0; + localparam WP_DISABLED = 4'h1; + localparam WAIT_FOR_READ_DATA_VALID = 4'h2; + localparam GET_READ_STATUS = 4'h3; + localparam CHECK_READ_STATUS = 4'h4; + localparam WAIT_FOR_WRITE_COMPLETE = 4'h5; + localparam GET_WRITE_STATUS = 4'h6; + localparam CHECK_WRITE_STATUS = 4'h7; + localparam ERASE_SECTOR = 4'h8; + localparam GET_ERASE_BUSY = 4'h9; + localparam CHECK_ERASE_BUSY = 4'hA; + localparam GET_ERASE_IDLE = 4'hB; + localparam CHECK_ERASE_IDLE = 4'hC; + + // The Intel on-chip flash control interface has two registers, a Status + // Register at address 0 and a Control Register at address 1. The constants + // defined below identify fields and values of interest in each register. + // These are taken directly from the Max 10 Flash Memory User Guide. + localparam STATUS_REG_ADDR = 1'b0; + localparam STATUS_REG_BUSY_STATUS_MSB = 1; + localparam STATUS_REG_BUSY_STATUS_LSB = 0; + localparam STATUS_REG_IDLE = 2'b00; + localparam STATUS_REG_ERASE_BUSY = 2'b01; + localparam STATUS_REG_WRITE_BUSY = 2'b10; + localparam STATUS_REG_READ_BUSY = 2'b11; + localparam STATUS_REG_READ_STATUS = 2; + localparam STATUS_REG_WRITE_STATUS = 3; + localparam STATUS_REG_ERASE_STATUS = 4; + localparam OPERATION_FAILED = 0; + + localparam CONTROL_REG_ADDR = 1'b1; + localparam SECTOR_ERASE_ADDR_MSB = 22; + localparam SECTOR_ERASE_ADDR_LSB = 20; + localparam CFM0_WP_OFFSET_MSB = 26; + localparam CFM0_WP_OFFSET_LSB = 24; + localparam ENABLE_WP = MEM_INIT ? 3'b111 : 3'b100; + localparam DISABLE_WP = 3'b000; + + //---------------------------------------------------------- + // State Machine + //---------------------------------------------------------- + + reg [3:0] state = IDLE; + wire flash_no_errors_detected; + + assign flash_no_errors_detected = ~(flash_read_err | flash_write_err | flash_erase_err); + + always @(posedge ctrlport_clk) begin + if (ctrlport_rst) begin + state <= IDLE; + + // Signals to config registers + flash_wp_enabled <= 1'b1; + flash_read_idle <= 1'b1; + flash_write_idle <= 1'b1; + flash_erase_idle <= 1'b1; + flash_read_err <= 1'b0; + flash_write_err <= 1'b0; + flash_erase_err <= 1'b0; + flash_read_data <= 32'b0; + + // Signals to flash control interface + csr_addr <= 1'b0; + csr_writedata <= {32 {1'b1}}; + csr_read <= 1'b0; + csr_write <= 1'b0; + + // Signals to flash data interface + data_addr <= 17'b0; + data_writedata <= 32'b0; + data_read <= 1'b0; + data_write <= 1'b0; + end + // Rising edge clock + else begin + // Default values + csr_read <= 1'b0; + csr_write <= 1'b0; + csr_addr <= STATUS_REG_ADDR; + csr_writedata <= {32 {1'b1}}; + + data_read <= 1'b0; + data_write <= 1'b0; + + // State handling + case(state) + + // When in IDLE: + // * No operations are in progress and write protection is enabled. + // * Allowed transitions are to either read data from flash or + // disable write protection. + // * Transitions are only allowed if no error bits are asserted. + // * In the event both the *read_stb and *disable_wp_stb bits are + // asserted read operations take priority as these do not open the + // flash to modification. + // * Attempts to both enable and disable write protection + // simultaneously result in the state machine remaining in IDLE + // write protection enabled. + IDLE: begin + flash_wp_enabled <= 1'b1; + + if (flash_read_stb && flash_no_errors_detected) begin + state <= WAIT_FOR_READ_DATA_VALID; + flash_read_idle <= 1'b0; + data_read <= 1'b1; + data_addr <= flash_addr; + end else if (flash_disable_wp_stb && ~flash_enable_wp_stb && flash_no_errors_detected) begin + state <= WP_DISABLED; + csr_write <= 1'b1; + csr_addr <= CONTROL_REG_ADDR; + csr_writedata[CFM0_WP_OFFSET_MSB:CFM0_WP_OFFSET_LSB] <= DISABLE_WP; + end + end + + // Transition from WP_DISABLED when write protection is enabled or when + // write/erase operations are initiated. A few things to note: + // * Enabling write protection takes priority, regardless of what + // other control bits may be asserted simultaneously, followed by + // writes, and lastly erases. + // * The user should not strobe both the *write_stb and *erase_stb + // bits simultaneously, but if they do the state machine returns to + // IDLE (thereby enabling write protection) and the *write_err and + // *erase_err bits are asserted. + // * Performing a write or erase operation is only allowed from + // WP_DISABLED. This allows some mitigation against data corruption + // as multiple steps are required to change the data in the flash. + // First write protection must be disabled, and only then can the + // flash be erased or written. + WP_DISABLED: begin + flash_wp_enabled <= 1'b0; + + if (flash_erase_stb && flash_write_stb) begin + flash_erase_err <= 1'b1; + flash_write_err <= 1'b1; + end + + if (flash_enable_wp_stb || (flash_erase_stb && flash_write_stb)) begin + state <= IDLE; + csr_write <= 1'b1; + csr_addr <= CONTROL_REG_ADDR; + csr_writedata[CFM0_WP_OFFSET_MSB:CFM0_WP_OFFSET_LSB] <= ENABLE_WP; + end else if (flash_write_stb) begin + state <= WAIT_FOR_WRITE_COMPLETE; + flash_write_idle <= 1'b0; + data_write <= 1'b1; + data_writedata <= flash_write_data; + data_addr <= flash_addr; + end else if (flash_erase_stb) begin + state <= ERASE_SECTOR; + flash_erase_idle <= 1'b0; + csr_write <= 1'b1; + csr_addr <= CONTROL_REG_ADDR; + csr_writedata[CFM0_WP_OFFSET_MSB:CFM0_WP_OFFSET_LSB] <= DISABLE_WP; + csr_writedata[SECTOR_ERASE_ADDR_MSB:SECTOR_ERASE_ADDR_LSB] <= flash_sector; + end + end + + + // Read Flash + // -------------- + // Per Intel's Max 10 User Flash Memory User Guide, the Read bit of the + // flash data interface should be pulsed for one clock cycle to start + // the read process from flash. This pulse occurs upon transition from + // IDLE to WAIT_FOR_READ_DATA_VALID. The state machine then waits in + // WAIT_FOR_READ_DATA_VALID until the flash data interface + // data_readdatavalid signal asserts, indicating the data is now valid. + // Intel's documentation does not provide guidance on the expected time + // for data_readdatavalid to assert. From simulation, however, + // data_readdatavalid asserts four clock cycles after the Read pulse + // ends. The data_readdatavalid signal from the flash data interface + // pulses for one clock cycle. Only during this pulse is the data valid. + WAIT_FOR_READ_DATA_VALID: begin + if (data_readdatavalid) begin + state <= GET_READ_STATUS; + flash_read_data <= data_readdata; + csr_read <= 1'b1; + end + end + + // The data_readdatavalid signal determines when the read operation has + // completed in the flash data interface, but Intel's documentation + // does not indicate the relation of this bit to the 'busy' field in + // the flash control interface Status Register. To verify that the read + // operation is complete, the StatusRegister is polled until the 'busy' + // field indicates the flash is idle. This polling operation is + // implemented with CHECK_READ_STATUS below. GET_READ_STATUS exists to + // set the address of the flash control interface to the Status + // Register and pulse the read bit of the flash control interface. + // CHECK_READ_STATUS evaluates the resulting Status Register data and + // steer the state machine accordingly. See Figure 6 in Intel's Max 10 + // User Flash Memory User Guide for a waveform on this request and + // check mechanism. Successful read operations result in the state + // machine returning to IDLE. Failing read operations assert the + // flash_read_err bit before returning to IDLE. From simulation, the + // 'busy' field returns to IDLE on the third read. + GET_READ_STATUS: begin + state <= CHECK_READ_STATUS; + // csr_read set in transactions into this state + // CSR address set as default assignment + end + CHECK_READ_STATUS: begin + if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_IDLE) begin + state <= IDLE; + flash_read_idle <= 1'b1; + flash_read_err <= (csr_readdata[STATUS_REG_READ_STATUS] == OPERATION_FAILED) ? 1'b1 : 1'b0; + end else if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_READ_BUSY) begin + state <= GET_READ_STATUS; + csr_read <= 1'b1; + end + end + + + // Write Flash + //--------------- + // Per Intel's Max 10 User Flash Memory User Guide, the Write bit of + // the flash data interface should be asserted while maintaining + // address and data until the flash interface deasserts the + // data_waitrequest bit. Transition from WP_DISABLED to + // WAIT_FOR_WRITE_COMPLETE causes the write bit to assert and address + // and data to be set. The state machine remains in this state until + // the data_waitrequest bit deasserts. Per Intel's Max 10 User Flash + // Memory User Guide, the data_waitrequest signal is expected to + // deassert within 555 usec. + WAIT_FOR_WRITE_COMPLETE: begin + if (~data_waitrequest) begin + state <= GET_WRITE_STATUS; + csr_read <= 1'b1; + end else begin + // Flash writes require asserting the Write bit of the flash data + // interface until the write is complete. + data_write <= 1'b1; + end + end + + // The data_waitrequest signal determines when the write operation has + // completed in the flash data interface, but Intel's documentation does + // not indicate the relation of this bit to the 'busy' field in the flash + // control interface Status Register. To verify that the write operation + // is complete the StatusRegister is polled until the 'busy' field + // indicates the flash is idle. This polling operation is implemented with + // GET_WRITE_STATUS and CHECK_WRITE_STATUS below, and follows the same + // methodology as the polling operation for reads described above with the + // following two changes: + // * Upon successful completion of a write operation the state + // machine returns to WP_DISABLED. This allows repeated writes of + // new data without having to disable/enable for each write. + // * When a failure is detected the state machine transitions to to + // IDLE thereby enabling write protection. Failure of a write is + // not expected. Write protection is enabled in the event of a + // failure to mitigate further data corruption. + GET_WRITE_STATUS: begin + state <= CHECK_WRITE_STATUS; + // csr_read set in transactions into this state + // CSR address set as default assignment + end + CHECK_WRITE_STATUS: begin + if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_IDLE) begin + if (csr_readdata[STATUS_REG_WRITE_STATUS] == OPERATION_FAILED) begin + state <= IDLE; + csr_write <= 1'b1; + csr_addr <= CONTROL_REG_ADDR; + csr_writedata[CFM0_WP_OFFSET_MSB:CFM0_WP_OFFSET_LSB] <= ENABLE_WP; + end else begin // SUCCESS + state <= WP_DISABLED; + end + flash_write_idle <= 1'b1; + flash_write_err <= (csr_readdata[STATUS_REG_WRITE_STATUS] == OPERATION_FAILED) ? 1'b1 : 1'b0; + end else if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_WRITE_BUSY) begin + state <= GET_WRITE_STATUS; + csr_read <= 1'b1; + end + end + + // Erase Flash + //------------- + // Erasing the primary configuration image requires a single write to + // the flash control interface Control Register. Only one sector needs + // to be erased to erase the entire primary configuration image. + // Transition from WP_DISABLED to ERASE_SECTOR causes data to be + // written to the Control Register to erase this sector and pulse the + // flash control interface write bit. + ERASE_SECTOR: begin + state <= GET_ERASE_BUSY; + csr_read <= 1'b1; + end + + // There is some latency between writing the Control Register and the + // 'busy' field of the flash control interface Status Register + // indicating the erase operation is in progress. After initiating the + // erase operation, GET_ERASE_BUSY and CHECK_ERASE_BUSY implement a + // polling operation to determine when the erase operation has started. + // GET_ERASE_BUSY exists to set the address of the flash control + // interface to the Status Register and pulse the read bit of the flash + // control interface. CHECK_ERASE_BUSY exists to evaluate the resulting + // Status Register data and steer the state machine accordingly. The + // polling operation continues until the 'busy' field indicates the + // erase operation is in progress. Intel's documentation does not + // indicate how long it takes for the Status Register to indicate the + // erase is in progress, but simulation shows the erase is in progress + // after the second read. + GET_ERASE_BUSY: begin + state <= CHECK_ERASE_BUSY; + // csr_read set in transactions into this state + // CSR address set as default assignment + end + CHECK_ERASE_BUSY: begin + if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_ERASE_BUSY) begin + state <= GET_ERASE_IDLE; + csr_read <= 1'b1; + end else if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_IDLE) begin + state <= GET_ERASE_BUSY; + csr_read <= 1'b1; + end + end + + // Once the erase operation is in progress a second polling operation + // defined by GET_ERASE_IDLE and CHECK_ERASE_IDLE is implemented to + // determine when the operation has completed. This polling operation + // follows the same methodology as the polling operation for erase busy + // described above. Intel's documentation indicates that erase + // operations take a maximum of 350 msec. + GET_ERASE_IDLE: begin + state <= CHECK_ERASE_IDLE; + // csr_read set in transactions into this state + // CSR address set as default assignment + end + CHECK_ERASE_IDLE: begin + if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_IDLE) begin + if (csr_readdata[STATUS_REG_ERASE_STATUS] == OPERATION_FAILED) begin + state <= IDLE; + csr_write <= 1'b1; + csr_addr <= CONTROL_REG_ADDR; + csr_writedata[CFM0_WP_OFFSET_MSB:CFM0_WP_OFFSET_LSB] <= ENABLE_WP; + end else begin // SUCCESS + state <= WP_DISABLED; + end + flash_erase_idle <= 1'b1; + flash_erase_err <= (csr_readdata[STATUS_REG_ERASE_STATUS] == OPERATION_FAILED) ? 1'b1 : 1'b0; + end else if (csr_readdata[STATUS_REG_BUSY_STATUS_MSB:STATUS_REG_BUSY_STATUS_LSB] == STATUS_REG_ERASE_BUSY) begin + state <= GET_ERASE_IDLE; + csr_read <= 1'b1; + end + end + + // Default to IDLE in other cases + default: begin + state <= IDLE; + end + endcase + + // Reset errors + if (clear_flash_read_err_stb) begin + flash_read_err <= 1'b0; + end + if (clear_flash_write_err_stb) begin + flash_write_err <= 1'b0; + end + if (clear_flash_erase_err_stb) begin + flash_erase_err <= 1'b0; + end + end + end + +endmodule + + +`default_nettype wire + + +//XmlParse xml_on +// +// +// +// These registers are used to upload and verify a new primary image to the +// Max 10 FPGA on-chip flash when configured to support dual configuration +// images. The steps below outline the process of verifying/preparing the +// new image to be written, erasing the current image, writing the new +// image, and verifying the new image was successfully written. +// {p}{b}Prepare the data...{/b} +// {ol}{li}{p}The Max 10 FPGA build should generate a *cfm0_auto.rpd +// file The *.rpd file is a "raw programming +// data" file holding all data related to the +// configuration image (CFM0). There are two +// important items to note regarding the addresses. +// First the *rpd data uses {b}byte{/b} addresses. +// Second, the start/end addresses defined by +// FLASH_PRIMARY_IMAGE_ADDR_ENUM are 32-bit word addresses{/p}{/li} +// {li}{p}As a sanity check, verify the size of the raw +// programming data for CFM0 correspond to the address +// range of FLASH_PRIMARY_IMAGE_ADDR_ENUM. Do this by +// reading the values from FLASH_CFM0_START_ADDR_REG and +// FLASH_CFM0_END_ADDR, subtract both values, add one and +// multiply by four. +// {/p}{/li} +// {li}{p}Having passed the sanity check the *.rpd data must +// now be manipulated into the form required by Altera's +// on-chip flash IP. Two operations must be performed. +// First the data must be converted from bytes to 32-bit +// words. Second the bit order must be reversed. This is +// illustrated in in the following table which shows byte +// address and data from the *.rpd file compared to the +// word address and data to be written to the on-chip +// flash. +// {table border=1} +// {tr}{td}.Map Addr{/td}{td}.Map Data{/td}{td}Flash Addr{/td}{td}Flash Data{/td}{/tr} +// {tr}{td}0x2B800{/td}{td}0x01{/td}{td rowspan=4}0xAC00{/td}{td rowspan=4}0x8040C020{/td}{/tr} +// {tr}{td}0x2B801{/td}{td}0x02{/td}{/tr} +// {tr}{td}0x2B802{/td}{td}0x03{/td}{/tr} +// {tr}{td}0x2B803{/td}{td}0x04{/td}{/tr} +// {tr}{td}0x2B804{/td}{td}0x05{/td}{td rowspan=4}0xAC01{/td}{td rowspan=4}0xA060E010{/td}{/tr} +// {tr}{td}0x2B805{/td}{td}0x06{/td}{/tr} +// {tr}{td}0x2B806{/td}{td}0x07{/td}{/tr} +// {tr}{td}0x2B807{/td}{td}0x08{/td}{/tr} +// {/table} +// {/p}{/li} +// {li}{p}The resulting set of flash address data pairs should +// be used when writing FLASH_ADDR_REG and +// FLASH_WRITE_DATA_REG to update the CFM0 image. +// However, prior to writing the new image the old image +// must be erased. +// {/p}{/li} +// {/ol} +// {/p} +// {p}{b}Erase the current primary flash image...{/b} +// {ol}{p}{li}Read FLASH_STATUS_REG and verify no error bits are +// asserted and that all read, write, and erase operations +// are idle.{/p}{/li} +// {p}{li}Disable write protection of the flash by strobing the +// FLASH_DISABLE_WP_STB bit of FLASH_CONTROL_REG. +// {/p}{/li} +// {p}{li}Verify write protection is disabled and no errors are +// present by reading FLASH_STATUS_REG.{/p}{/li} +// {p}{li}Initiate the erase operation by setting +// @.FLASH_ERASE_SECTOR and strobing FLASH_ERASE_STB of +// FLASH_CONTROL_REG.{/p}{/li} +// {p}{li}Poll the FLASH_ERASE_IDLE bit of +// FLASH_STATUS_REG until it de-asserts indicating the +// erase operation is complete, then verify the operation +// was successful by checking that the FLASH_ERASE_ERR +// bit is de-asserted. Erase operations are expected to +// take a maximum of 350 msec. Upon completion of the erase +// operation write protection will remain disabled. +// {/p}{/li} +// {p}{li}Erase additional sectors as required (see +// @.FLASH_ERASE_SECTOR for details) by restarting with first +// step.{/p}{/li} +// {/ol} +// {/p} +// {p}{b}Write the new primary flash image...{/b} +// {ol}{p}{li}Read FLASH_STATUS_REG and verify no error bits are +// asserted, all read, write, and erase operations are +// idle, and write protection is disabled.{/li} +// {p}{li}Set the target address for the write to the Max 10 +// on-chip flash by writing value from +// FLASH_CFM0_START_ADDR_REG to FLASH_ADDR_REG.{/li}{/p} +// {p}{li}Set the data to be written to this address by writing +// the new 32-bit word of the new image to +// FLASH_WRITE_DATA_REG.{/li}{/p} +// {p}{li}Initiate the write by strobing FLASH_WRITE_STB of +// FLASH_CONTROL_REG.{/li}{/p} +// {p}{li}Poll the FLASH_WRITE_IDLE bit of +// FLASH_STATUS_REG until it de-asserts indicating the +// write operation is complete, then verify the operation +// was successful by checking that the FLASH_WRITE_ERR +// bit is de-asserted. Write operations are expected to +// take a maximum of 550 usec.{/li}{/p} +// {p}{li}Upon completion of the write operation return to step +// 2, incrementing the target address by one, and writing +// the next 32-bit word to Max10FlashWriteDatReg. If this +// was the last write, indicated by writing to +// FLASH_PRIMARY_IMAGE_END_ADDR, proceed to the next step +// to enable write protection.{/li}{/p} +// {p}{li}After writing the new image enable write protection +// by strobing the FLASH_ENABLE_WP_STB bit of +// FLASH_CONTROL_REG.{/li}{/p} +// {/ol} +// {/p} +// {p}{b}Verify the new primary flash image...{/b} +// {ol}{p}{li}Read FLASH_STATUS_REG and verify no error bits are +// asserted and that all read, write, and erase operations +// are idle.{/li}{/p} +// {p}{li}Set the target address for the read in the Max 10 +// on-chip flash by writing value from +// FLASH_CFM0_START_ADDR_REG to FLASH_ADDR_REG.{/li}{/p} +// {p}{li}Initiate the read by strobing FLASH_READ_STB of +// FLASH_CONTROL_REG.{/li}{/p} +// {p}{li}Poll the FLASH_READ_IDLE bit of +// FLASH_STATUS_REG until it de-asserts indicating the +// read operation is complete, then verify the operation +// was successful by checking that the FLASH_READ_ERR +// bit is de-asserted. There is no guidance on exactly how +// long reads take to complete, but they are expected to be +// fairly quick. A very conservative timeout on this +// polling would be similar to that used for write +// operations.{/li}{/p} +// {p}{li}Upon completion of the read operation the resulting +// data returned by the on-chip flash will be available in +// Max10FlashReadDatReg. Read this register, compare to +// expected value previously written, and ensure they +// match.{/li}{/p} +// {p}{li}Return to step 2, incrementing the target +// address by one. If this was the last read verification +// is complete and no further action is required.{/li}{/p} +// {/ol} +// {/p} +// {p}After the flash has been erased, programmed, and verified, a power +// cycle is required for the new image to become active. +// {/p} +// +// +// +// Those values are the start and end address of the CFM image flash +// sector from Intel's On-Chip Flash IP Generator. Note that the values +// given in the IP generator are byte based where the values of this enum +// are U32 based (divided by 4). +// +// +// +// +// +// +// +// +// This bit is asserted when the flash is write protected and +// de-asserted when write protection is disabled. +// {li}Write protection must be enabled prior to performing read +// operations.{/li} +// {li}Write protection must be disabled prior to performing write and +// erase operations.{/li} +// +// +// +// +// This bit is de-asserted when a read operation is in progress. Poll +// this bit after strobing the FLASH_READ_STB bit of +// FLASH_CONTROL_REG to determine when the read operation has +// completed, then check the FLASH_READ_ERR bit to verify the +// operation was successful. +// +// +// +// +// This bit is asserted when a read operation fails. Clear this error +// by strobing the CLEAR_FLASH_READ_ERROR_STB of this register. In the +// event of a read error... +// {li}the data in FLASH_READ_DATA_REG is invalid.{/li} +// {li}attempts to disable write protection will be ignored.{/li} +// {li}attempts to read/write/erase the flash will be ignored.{/li} +// +// +// +// +// This bit is de-asserted when an erase operation is in progress. Poll +// this bit after strobing the FLASH_ERASE_STB bit of +// FLASH_CONTROL_REG to determine when the erase operation has +// completed, then check the FLASH_ERASE_ERR bit to verify the +// operation was successful. +// +// +// +// +// This bit is asserted when an erase operation fails. Clear this +// error by strobing CLEAR_FLASH_ERASE_ERROR_STB of this register. In +// the event of an erase error... +// {li}{b}the primary configuration image may be corrupted,{/b} and +// power cycling the board may result in unknown behavior.{/li} +// {li}write protection of the flash will automatically be +// re-enabled.{/li} +// {li}attempts to disable write protection will be ignored.{/li} +// {li}attempts to read/write/erase the flash will be ignored.{/li} +// +// +// +// +// This bit is de-asserted when a write operation is in progress. Poll +// this bit after strobing the FLASH_WRITE_STB bit of +// FLASH_CONTROL_REG to determine when the write operation has +// completed, then check the FLASH_WRITE_ERR bit to verify the +// operation was successful. +// +// +// +// +// This bit is asserted when write operation fails. Clear this error +// by strobing the CLEAR_FLASH_WRITE_ERROR_STB bit of this register. In +// the event of a write error... +// {li}{b}the primary configuration image may be corrupted,{/b} and +// power cycling the board may result unknown behavior.{/li} +// {li}write protection of the flash will automatically be +// re-enabled.{/li} +// {li}attempts to disable write protection will be ignored.{/li} +// {li}attempts to read/write/erase the flash will be ignored.{/li} +// +// +// +// +// This bit is asserted when the flash can hold an image with memory +// initialization. +// +// +// +// +// +// +// Strobe this bit to enable write protection to the section of the +// Max 10 on-chip flash storing the primary configuration image +// (CFM0). +// {li}Read the FLASH_WP_ENABLED bit of FLASH_STATUS_REG to +// determine the current state of write protection.{/li} +// {li}Prior to strobing this bit verify no write or erase operations +// are in progress and no error bits are asserted by reading +// FLASH_STATUS_REG.{/li} +// {li}Attempts to enable write protection while erase or write +// operations are in progress will be ignored.{/li} +// {li}Write protection must be enabled prior to performing +// read operations.{/li} +// {li}Write protection should be enabled after completing +// write or erase operations to prevent data corruption.{/li} +// +// +// +// +// Strobe this bit to disable write protection to the section of the +// Max 10 on-chip flash storing the primary configuration image +// (CFM0). +// {li}Read the FLASH_WP_ENABLED bit of FLASH_STATUS_REG to +// determine the current state of write protection.{/li} +// {li}Prior to strobing this bit verify no read operations are in +// progress and no error bits are asserted by reading +// FLASH_STATUS_REG.{/li} +// {li}Attempts to disable write protection while a read is in +// progress will be ignored.{/li} +// {li}Attempts to disable write protection will be ignored if +// this bit is strobed simultaneously with either FLASH_READ_STB +// or FLASH_ENABLE_WP_STB.{/li} +// {li}Write protection must be disabled prior to performing erase or +// write operations.{/li} +// {li}Upon completion of erase/write operations write protection +// will remain disabled. When not actively erasing or writing a new +// image write protection should be enabled to avoid data +// corruption.{/li} +// +// +// +// +// Strobe this bit to read data from the flash address identified in +// FLASH_ADDR_REG. +// {li}Prior to strobing this bit verify no read, write, or erase +// operations are in progress, no error bits are asserted, and +// write protection is enabled by reading FLASH_STATUS_REG.{/li} +// {li}Attempts to read data while other operations are in progress +// or while write protection is disabled will be ignored.{/li} +// {li}After strobing this bit poll the FLASH_READ_IDLE and +// FLASH_READ_ERR bits of FLASH_STATUS_REG to determine when +// the read operation is complete and if it was successful.{/li} +// {li}Upon successful completion the data read from flash will be +// available in FLASH_READ_DATA_REG.{/li} +// +// +// +// +// Strobe this bit to write the data contained in +// FLASH_WRITE_DATA_REG to the flash address identified in +// FLASH_ADDR_REG. +// {li}The flash must be erased before writing new data.{/li} +// {li}Prior to strobing this bit verify write protection is +// disabled, no other write or erase operations are in progress, and +// no error bits are asserted by reading FLASH_STATUS_REG.{/li} +// {li}Attempts to write data while other write or erase operations +// are in progress will be ignored.{/li} +// {li}Attempts to write data with write protection enabled will be +// ignored.{/li} +// {li}Strobing this bit and FLASH_ERASE_STB simultaneously will +// result in both the write and erase operation being ignored, +// both corresponding error bits being set, and write protection +// being re-enabled.{/li} +// {li}After strobing this bit poll theMax10FlashWriteIdle and +// FLASH_WRITE_ERR bits of FLASH_STATUS_REG to determine when +// the write operation is complete and if it was successful.{/li} +// +// +// +// +// Strobe this bit to erase the primary Max10 configuration image +// (CFM0). +// {li}Prior to strobing this bit verify no other write or erase +// operations are in progress, write protection is disabled, and no +// error bits are asserted by reading FLASH_STATUS_REG.{/li} +// {li}Attempts to erase the primary image while other write or erase +// operations are in progress will be ignored. +// {li}Attempts to erase the primary image when write protection is +// enabled will be ignored.{/li} +// {li}Strobing this bit and FLASH_WRITE_STB simultaneously will +// result both the erase and the write operation being ignored, both +// corresponding error bits being set, and write protection being +// re-enabled.{/li} +// {li}After strobing this bit poll the FLASH_ERASE_IDLE and +// FLASH_ERASE_ERR bits of FLASH_STATUS_REG to determine when +// the erase operation is complete and if it was successful.{/li} +// +// +// +// +// Defines the sector to be erased. Has to be set latest with the +// write access which starts the erase operation by strobing +// @.FLASH_ERASE_STB.{br} +// If the flash is configured to support memory initialization (see +// @.FLASH_MEM_INIT_ENABLED flag) the sectors 2 to 4 have to be erased. +// If the flag is not asserted only sector 4 has to be erased. +// +// +// +// +// Strobe this bit to clear a read error. +// +// +// +// +// Strobe this bit to clear a write error. +// +// +// +// +// Strobe this bit to clear an erase error. +// +// +// +// +// +// +// This field holds the target address for the next read or +// write operation. Set this field prior to strobing the +// FLASH_WRITE_STB and FLASH_READ_STB bits of +// FLASH_CONTROL_REG. Valid addresses are defined by the +// FLASH_PRIMARY_IMAGE_ADDR_ENUM enumeration. +// +// +// +// +// +// +// Data in this register will be written to the flash at the address +// identified in FLASH_ADDR_REG when a successful write operation +// is executed. +// +// +// +// +// +// +// This register contains data read from the flash address identified +// in FLASH_ADDR_REG after a successful read operation is executed. +// +// +// +// +// +// +// Start address of CFM0 image within flash memory (as defined in FLASH_PRIMARY_IMAGE_ADDR_ENUM). +// +// +// +// +// +// +// Last address of CFM0 image within flash memory (as defined in FLASH_PRIMARY_IMAGE_ADDR_ENUM). +// +// +// +// +// +//XmlParse xml_off diff --git a/top/x400/cpld/regmap/constants_regmap_utils.vh b/top/x400/cpld/regmap/constants_regmap_utils.vh new file mode 100644 index 0000000..4e5921f --- /dev/null +++ b/top/x400/cpld/regmap/constants_regmap_utils.vh @@ -0,0 +1,28 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: constants_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group CONSTANTS_GROUP +//=============================================================================== + + // Enumerated type CONSTANTS_ENUM + localparam CONSTANTS_ENUM_SIZE = 4; + localparam PS_CPLD_SIGNATURE = 'hA522D27; // CONSTANTS_ENUM:PS_CPLD_SIGNATURE + localparam OLDEST_CPLD_REVISION = 'h20122114; // CONSTANTS_ENUM:OLDEST_CPLD_REVISION + localparam CPLD_REVISION = 'h21012015; // CONSTANTS_ENUM:CPLD_REVISION + localparam PL_CPLD_SIGNATURE = 'h3FDC5C47; // CONSTANTS_ENUM:PL_CPLD_SIGNATURE diff --git a/top/x400/cpld/regmap/jtag_regmap_utils.vh b/top/x400/cpld/regmap/jtag_regmap_utils.vh new file mode 100644 index 0000000..f57e28e --- /dev/null +++ b/top/x400/cpld/regmap/jtag_regmap_utils.vh @@ -0,0 +1,57 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: jtag_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // TX_DATA : 0x0 (ctrlport_to_jtag.v) + // STB_DATA : 0x4 (ctrlport_to_jtag.v) + // CONTROL : 0x8 (ctrlport_to_jtag.v) + // RX_DATA : 0xC (ctrlport_to_jtag.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group JTAG_REGS +//=============================================================================== + + // TX_DATA Register (from ctrlport_to_jtag.v) + localparam TX_DATA = 'h0; // Register Offset + localparam TX_DATA_SIZE = 32; // register width in bits + localparam TX_DATA_MASK = 32'h0; + + // STB_DATA Register (from ctrlport_to_jtag.v) + localparam STB_DATA = 'h4; // Register Offset + localparam STB_DATA_SIZE = 32; // register width in bits + localparam STB_DATA_MASK = 32'h0; + + // CONTROL Register (from ctrlport_to_jtag.v) + localparam CONTROL = 'h8; // Register Offset + localparam CONTROL_SIZE = 32; // register width in bits + localparam CONTROL_MASK = 32'h80001FFF; + localparam PRESCALAR_SIZE = 8; //CONTROL:prescalar + localparam PRESCALAR_MSB = 7; //CONTROL:prescalar + localparam PRESCALAR = 0; //CONTROL:prescalar + localparam LENGTH_SIZE = 5; //CONTROL:length + localparam LENGTH_MSB = 12; //CONTROL:length + localparam LENGTH = 8; //CONTROL:length + localparam RESET_SIZE = 1; //CONTROL:reset + localparam RESET_MSB = 31; //CONTROL:reset + localparam RESET = 31; //CONTROL:reset + localparam READY_SIZE = 1; //CONTROL:ready + localparam READY_MSB = 31; //CONTROL:ready + localparam READY = 31; //CONTROL:ready + + // RX_DATA Register (from ctrlport_to_jtag.v) + localparam RX_DATA = 'hC; // Register Offset + localparam RX_DATA_SIZE = 32; // register width in bits + localparam RX_DATA_MASK = 32'h0; diff --git a/top/x400/cpld/regmap/mb_cpld_pl_regmap_utils.vh b/top/x400/cpld/regmap/mb_cpld_pl_regmap_utils.vh new file mode 100644 index 0000000..d705906 --- /dev/null +++ b/top/x400/cpld/regmap/mb_cpld_pl_regmap_utils.vh @@ -0,0 +1,36 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: mb_cpld_pl_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // PL_REGISTERS : 0x0 (mb_cpld.v) + // JTAG_DB0 : 0x60 (mb_cpld.v) + // JTAG_DB1 : 0x80 (mb_cpld.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group MB_CPLD_PL_WINDOWS +//=============================================================================== + + // PL_REGISTERS Window (from mb_cpld.v) + localparam PL_REGISTERS = 'h0; // Window Offset + localparam PL_REGISTERS_SIZE = 'h40; // size in bytes + + // JTAG_DB0 Window (from mb_cpld.v) + localparam JTAG_DB0 = 'h60; // Window Offset + localparam JTAG_DB0_SIZE = 'h20; // size in bytes + + // JTAG_DB1 Window (from mb_cpld.v) + localparam JTAG_DB1 = 'h80; // Window Offset + localparam JTAG_DB1_SIZE = 'h20; // size in bytes diff --git a/top/x400/cpld/regmap/mb_cpld_ps_regmap_utils.vh b/top/x400/cpld/regmap/mb_cpld_ps_regmap_utils.vh new file mode 100644 index 0000000..9eb044c --- /dev/null +++ b/top/x400/cpld/regmap/mb_cpld_ps_regmap_utils.vh @@ -0,0 +1,51 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: mb_cpld_ps_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // PS_REGISTERS : 0x0 (mb_cpld.v) + // RECONFIG : 0x40 (mb_cpld.v) + // POWER_REGISTERS : 0x60 (mb_cpld.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group MB_CPLD_PS_WINDOWS +//=============================================================================== + + // PS_REGISTERS Window (from mb_cpld.v) + localparam PS_REGISTERS = 'h0; // Window Offset + localparam PS_REGISTERS_SIZE = 'h40; // size in bytes + + // RECONFIG Window (from mb_cpld.v) + localparam RECONFIG = 'h40; // Window Offset + localparam RECONFIG_SIZE = 'h20; // size in bytes + + // POWER_REGISTERS Window (from mb_cpld.v) + localparam POWER_REGISTERS = 'h60; // Window Offset + localparam POWER_REGISTERS_SIZE = 'h20; // size in bytes + +//=============================================================================== +// Register Group PS_SPI_ENDPOINTS +//=============================================================================== + + // Enumerated type SPI_ENDPOINT + localparam SPI_ENDPOINT_SIZE = 8; + localparam PS_CS_MB_CPLD = 'h0; // SPI_ENDPOINT:PS_CS_MB_CPLD + localparam PS_CS_LMK32 = 'h1; // SPI_ENDPOINT:PS_CS_LMK32 + localparam PS_CS_TPM = 'h2; // SPI_ENDPOINT:PS_CS_TPM + localparam PS_CS_PHASE_DAC = 'h3; // SPI_ENDPOINT:PS_CS_PHASE_DAC + localparam PS_CS_DB0_CAL_EEPROM = 'h4; // SPI_ENDPOINT:PS_CS_DB0_CAL_EEPROM + localparam PS_CS_DB1_CAL_EEPROM = 'h5; // SPI_ENDPOINT:PS_CS_DB1_CAL_EEPROM + localparam PS_CS_CLK_AUX_DB = 'h6; // SPI_ENDPOINT:PS_CS_CLK_AUX_DB + localparam PS_CS_IDLE = 'h7; // SPI_ENDPOINT:PS_CS_IDLE diff --git a/top/x400/cpld/regmap/pl_cpld_base_regmap_utils.vh b/top/x400/cpld/regmap/pl_cpld_base_regmap_utils.vh new file mode 100644 index 0000000..820216d --- /dev/null +++ b/top/x400/cpld/regmap/pl_cpld_base_regmap_utils.vh @@ -0,0 +1,122 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: pl_cpld_base_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // SIGNATURE_REGISTER : 0x0 (pl_cpld_regs.v) + // REVISION_REGISTER : 0x4 (pl_cpld_regs.v) + // OLDEST_COMPATIBLE_REVISION_REGISTER : 0x8 (pl_cpld_regs.v) + // SCRATCH_REGISTER : 0xC (pl_cpld_regs.v) + // GIT_HASH_REGISTER : 0x10 (pl_cpld_regs.v) + // LED_REGISTER : 0x20 (pl_cpld_regs.v) + // CABLE_PRESENT_REG : 0x30 (pl_cpld_regs.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group MB_CPLD_LED_REGS +//=============================================================================== + + // LED_REGISTER Register (from pl_cpld_regs.v) + localparam LED_REGISTER = 'h20; // Register Offset + localparam LED_REGISTER_SIZE = 16; // register width in bits + localparam LED_REGISTER_MASK = 16'hFFFF; + localparam QSFP0_LED_LINK_SIZE = 4; //LED_REGISTER:QSFP0_LED_LINK + localparam QSFP0_LED_LINK_MSB = 3; //LED_REGISTER:QSFP0_LED_LINK + localparam QSFP0_LED_LINK = 0; //LED_REGISTER:QSFP0_LED_LINK + localparam QSFP0_LED_ACTIVE_SIZE = 4; //LED_REGISTER:QSFP0_LED_ACTIVE + localparam QSFP0_LED_ACTIVE_MSB = 7; //LED_REGISTER:QSFP0_LED_ACTIVE + localparam QSFP0_LED_ACTIVE = 4; //LED_REGISTER:QSFP0_LED_ACTIVE + localparam QSFP1_LED_LINK_SIZE = 4; //LED_REGISTER:QSFP1_LED_LINK + localparam QSFP1_LED_LINK_MSB = 11; //LED_REGISTER:QSFP1_LED_LINK + localparam QSFP1_LED_LINK = 8; //LED_REGISTER:QSFP1_LED_LINK + localparam QSFP1_LED_ACTIVE_SIZE = 4; //LED_REGISTER:QSFP1_LED_ACTIVE + localparam QSFP1_LED_ACTIVE_MSB = 15; //LED_REGISTER:QSFP1_LED_ACTIVE + localparam QSFP1_LED_ACTIVE = 12; //LED_REGISTER:QSFP1_LED_ACTIVE + +//=============================================================================== +// Register Group PL_CMI_REGS +//=============================================================================== + + // CABLE_PRESENT_REG Register (from pl_cpld_regs.v) + localparam CABLE_PRESENT_REG = 'h30; // Register Offset + localparam CABLE_PRESENT_REG_SIZE = 2; // register width in bits + localparam CABLE_PRESENT_REG_MASK = 2'h3; + localparam IPASS0_CABLE_PRESENT_SIZE = 1; //CABLE_PRESENT_REG:IPASS0_CABLE_PRESENT + localparam IPASS0_CABLE_PRESENT_MSB = 0; //CABLE_PRESENT_REG:IPASS0_CABLE_PRESENT + localparam IPASS0_CABLE_PRESENT = 0; //CABLE_PRESENT_REG:IPASS0_CABLE_PRESENT + localparam IPASS1_CABLE_PRESENT_SIZE = 1; //CABLE_PRESENT_REG:IPASS1_CABLE_PRESENT + localparam IPASS1_CABLE_PRESENT_MSB = 1; //CABLE_PRESENT_REG:IPASS1_CABLE_PRESENT + localparam IPASS1_CABLE_PRESENT = 1; //CABLE_PRESENT_REG:IPASS1_CABLE_PRESENT + +//=============================================================================== +// Register Group PL_CPLD_BASE_REGS +//=============================================================================== + + // SIGNATURE_REGISTER Register (from pl_cpld_regs.v) + localparam SIGNATURE_REGISTER = 'h0; // Register Offset + localparam SIGNATURE_REGISTER_SIZE = 32; // register width in bits + localparam SIGNATURE_REGISTER_MASK = 32'hFFFFFFFF; + localparam PRODUCT_SIGNATURE_SIZE = 32; //SIGNATURE_REGISTER:PRODUCT_SIGNATURE + localparam PRODUCT_SIGNATURE_MSB = 31; //SIGNATURE_REGISTER:PRODUCT_SIGNATURE + localparam PRODUCT_SIGNATURE = 0; //SIGNATURE_REGISTER:PRODUCT_SIGNATURE + + // REVISION_REGISTER Register (from pl_cpld_regs.v) + localparam REVISION_REGISTER = 'h4; // Register Offset + localparam REVISION_REGISTER_SIZE = 32; // register width in bits + localparam REVISION_REGISTER_MASK = 32'hFFFFFFFF; + localparam REVISION_HH_SIZE = 8; //REVISION_REGISTER:REVISION_HH + localparam REVISION_HH_MSB = 7; //REVISION_REGISTER:REVISION_HH + localparam REVISION_HH = 0; //REVISION_REGISTER:REVISION_HH + localparam REVISION_DD_SIZE = 8; //REVISION_REGISTER:REVISION_DD + localparam REVISION_DD_MSB = 15; //REVISION_REGISTER:REVISION_DD + localparam REVISION_DD = 8; //REVISION_REGISTER:REVISION_DD + localparam REVISION_MM_SIZE = 8; //REVISION_REGISTER:REVISION_MM + localparam REVISION_MM_MSB = 23; //REVISION_REGISTER:REVISION_MM + localparam REVISION_MM = 16; //REVISION_REGISTER:REVISION_MM + localparam REVISION_YY_SIZE = 8; //REVISION_REGISTER:REVISION_YY + localparam REVISION_YY_MSB = 31; //REVISION_REGISTER:REVISION_YY + localparam REVISION_YY = 24; //REVISION_REGISTER:REVISION_YY + + // OLDEST_COMPATIBLE_REVISION_REGISTER Register (from pl_cpld_regs.v) + localparam OLDEST_COMPATIBLE_REVISION_REGISTER = 'h8; // Register Offset + localparam OLDEST_COMPATIBLE_REVISION_REGISTER_SIZE = 32; // register width in bits + localparam OLDEST_COMPATIBLE_REVISION_REGISTER_MASK = 32'hFFFFFFFF; + localparam OLD_REVISION_HH_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_HH + localparam OLD_REVISION_HH_MSB = 7; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_HH + localparam OLD_REVISION_HH = 0; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_HH + localparam OLD_REVISION_DD_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_DD + localparam OLD_REVISION_DD_MSB = 15; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_DD + localparam OLD_REVISION_DD = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_DD + localparam OLD_REVISION_MM_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_MM + localparam OLD_REVISION_MM_MSB = 23; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_MM + localparam OLD_REVISION_MM = 16; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_MM + localparam OLD_REVISION_YY_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_YY + localparam OLD_REVISION_YY_MSB = 31; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_YY + localparam OLD_REVISION_YY = 24; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_YY + + // SCRATCH_REGISTER Register (from pl_cpld_regs.v) + localparam SCRATCH_REGISTER = 'hC; // Register Offset + localparam SCRATCH_REGISTER_SIZE = 32; // register width in bits + localparam SCRATCH_REGISTER_MASK = 32'h0; + + // GIT_HASH_REGISTER Register (from pl_cpld_regs.v) + localparam GIT_HASH_REGISTER = 'h10; // Register Offset + localparam GIT_HASH_REGISTER_SIZE = 32; // register width in bits + localparam GIT_HASH_REGISTER_MASK = 32'hFFFFFFFF; + localparam GIT_HASH_SIZE = 28; //GIT_HASH_REGISTER:GIT_HASH + localparam GIT_HASH_MSB = 27; //GIT_HASH_REGISTER:GIT_HASH + localparam GIT_HASH = 0; //GIT_HASH_REGISTER:GIT_HASH + localparam GIT_CLEAN_SIZE = 4; //GIT_HASH_REGISTER:GIT_CLEAN + localparam GIT_CLEAN_MSB = 31; //GIT_HASH_REGISTER:GIT_CLEAN + localparam GIT_CLEAN = 28; //GIT_HASH_REGISTER:GIT_CLEAN diff --git a/top/x400/cpld/regmap/ps_cpld_base_regmap_utils.vh b/top/x400/cpld/regmap/ps_cpld_base_regmap_utils.vh new file mode 100644 index 0000000..a5a067b --- /dev/null +++ b/top/x400/cpld/regmap/ps_cpld_base_regmap_utils.vh @@ -0,0 +1,183 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ps_cpld_base_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // SIGNATURE_REGISTER : 0x0 (ps_cpld_regs.v) + // REVISION_REGISTER : 0x4 (ps_cpld_regs.v) + // OLDEST_COMPATIBLE_REVISION_REGISTER : 0x8 (ps_cpld_regs.v) + // SCRATCH_REGISTER : 0xC (ps_cpld_regs.v) + // GIT_HASH_REGISTER : 0x10 (ps_cpld_regs.v) + // PL_DB_REGISTER : 0x20 (ps_cpld_regs.v) + // DIO_DIRECTION_REGISTER : 0x30 (ps_cpld_regs.v) + // SERIAL_NUM_LOW_REG : 0x34 (ps_cpld_regs.v) + // SERIAL_NUM_HIGH_REG : 0x38 (ps_cpld_regs.v) + // CMI_CONTROL_STATUS : 0x3C (ps_cpld_regs.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group DIO_REGS +//=============================================================================== + + // DIO_DIRECTION_REGISTER Register (from ps_cpld_regs.v) + localparam DIO_DIRECTION_REGISTER = 'h30; // Register Offset + localparam DIO_DIRECTION_REGISTER_SIZE = 32; // register width in bits + localparam DIO_DIRECTION_REGISTER_MASK = 32'hFFF0FFF; + localparam DIO_DIRECTION_A_SIZE = 12; //DIO_DIRECTION_REGISTER:DIO_DIRECTION_A + localparam DIO_DIRECTION_A_MSB = 11; //DIO_DIRECTION_REGISTER:DIO_DIRECTION_A + localparam DIO_DIRECTION_A = 0; //DIO_DIRECTION_REGISTER:DIO_DIRECTION_A + localparam DIO_DIRECTION_B_SIZE = 12; //DIO_DIRECTION_REGISTER:DIO_DIRECTION_B + localparam DIO_DIRECTION_B_MSB = 27; //DIO_DIRECTION_REGISTER:DIO_DIRECTION_B + localparam DIO_DIRECTION_B = 16; //DIO_DIRECTION_REGISTER:DIO_DIRECTION_B + +//=============================================================================== +// Register Group PS_CMI_REGS +//=============================================================================== + + // SERIAL_NUM_LOW_REG Register (from ps_cpld_regs.v) + localparam SERIAL_NUM_LOW_REG = 'h34; // Register Offset + localparam SERIAL_NUM_LOW_REG_SIZE = 32; // register width in bits + localparam SERIAL_NUM_LOW_REG_MASK = 32'h0; + + // SERIAL_NUM_HIGH_REG Register (from ps_cpld_regs.v) + localparam SERIAL_NUM_HIGH_REG = 'h38; // Register Offset + localparam SERIAL_NUM_HIGH_REG_SIZE = 8; // register width in bits + localparam SERIAL_NUM_HIGH_REG_MASK = 8'h0; + + // CMI_CONTROL_STATUS Register (from ps_cpld_regs.v) + localparam CMI_CONTROL_STATUS = 'h3C; // Register Offset + localparam CMI_CONTROL_STATUS_SIZE = 32; // register width in bits + localparam CMI_CONTROL_STATUS_MASK = 32'h80000001; + localparam CMI_READY_SIZE = 1; //CMI_CONTROL_STATUS:CMI_READY + localparam CMI_READY_MSB = 0; //CMI_CONTROL_STATUS:CMI_READY + localparam CMI_READY = 0; //CMI_CONTROL_STATUS:CMI_READY + localparam OTHER_SIDE_DETECTED_SIZE = 1; //CMI_CONTROL_STATUS:OTHER_SIDE_DETECTED + localparam OTHER_SIDE_DETECTED_MSB = 31; //CMI_CONTROL_STATUS:OTHER_SIDE_DETECTED + localparam OTHER_SIDE_DETECTED = 31; //CMI_CONTROL_STATUS:OTHER_SIDE_DETECTED + +//=============================================================================== +// Register Group PS_CONTROL_REGS +//=============================================================================== + + // PL_DB_REGISTER Register (from ps_cpld_regs.v) + localparam PL_DB_REGISTER = 'h20; // Register Offset + localparam PL_DB_REGISTER_SIZE = 32; // register width in bits + localparam PL_DB_REGISTER_MASK = 32'h337737; + localparam DB0_CLOCK_ENABLED_SIZE = 1; //PL_DB_REGISTER:DB0_CLOCK_ENABLED + localparam DB0_CLOCK_ENABLED_MSB = 0; //PL_DB_REGISTER:DB0_CLOCK_ENABLED + localparam DB0_CLOCK_ENABLED = 0; //PL_DB_REGISTER:DB0_CLOCK_ENABLED + localparam DB1_CLOCK_ENABLED_SIZE = 1; //PL_DB_REGISTER:DB1_CLOCK_ENABLED + localparam DB1_CLOCK_ENABLED_MSB = 1; //PL_DB_REGISTER:DB1_CLOCK_ENABLED + localparam DB1_CLOCK_ENABLED = 1; //PL_DB_REGISTER:DB1_CLOCK_ENABLED + localparam PLL_REF_CLOCK_ENABLED_SIZE = 1; //PL_DB_REGISTER:PLL_REF_CLOCK_ENABLED + localparam PLL_REF_CLOCK_ENABLED_MSB = 2; //PL_DB_REGISTER:PLL_REF_CLOCK_ENABLED + localparam PLL_REF_CLOCK_ENABLED = 2; //PL_DB_REGISTER:PLL_REF_CLOCK_ENABLED + localparam DB0_RESET_ASSERTED_SIZE = 1; //PL_DB_REGISTER:DB0_RESET_ASSERTED + localparam DB0_RESET_ASSERTED_MSB = 4; //PL_DB_REGISTER:DB0_RESET_ASSERTED + localparam DB0_RESET_ASSERTED = 4; //PL_DB_REGISTER:DB0_RESET_ASSERTED + localparam DB1_RESET_ASSERTED_SIZE = 1; //PL_DB_REGISTER:DB1_RESET_ASSERTED + localparam DB1_RESET_ASSERTED_MSB = 5; //PL_DB_REGISTER:DB1_RESET_ASSERTED + localparam DB1_RESET_ASSERTED = 5; //PL_DB_REGISTER:DB1_RESET_ASSERTED + localparam ENABLE_CLOCK_DB0_SIZE = 1; //PL_DB_REGISTER:ENABLE_CLOCK_DB0 + localparam ENABLE_CLOCK_DB0_MSB = 8; //PL_DB_REGISTER:ENABLE_CLOCK_DB0 + localparam ENABLE_CLOCK_DB0 = 8; //PL_DB_REGISTER:ENABLE_CLOCK_DB0 + localparam ENABLE_CLOCK_DB1_SIZE = 1; //PL_DB_REGISTER:ENABLE_CLOCK_DB1 + localparam ENABLE_CLOCK_DB1_MSB = 9; //PL_DB_REGISTER:ENABLE_CLOCK_DB1 + localparam ENABLE_CLOCK_DB1 = 9; //PL_DB_REGISTER:ENABLE_CLOCK_DB1 + localparam ENABLE_PLL_REF_CLOCK_SIZE = 1; //PL_DB_REGISTER:ENABLE_PLL_REF_CLOCK + localparam ENABLE_PLL_REF_CLOCK_MSB = 10; //PL_DB_REGISTER:ENABLE_PLL_REF_CLOCK + localparam ENABLE_PLL_REF_CLOCK = 10; //PL_DB_REGISTER:ENABLE_PLL_REF_CLOCK + localparam DISABLE_CLOCK_DB0_SIZE = 1; //PL_DB_REGISTER:DISABLE_CLOCK_DB0 + localparam DISABLE_CLOCK_DB0_MSB = 12; //PL_DB_REGISTER:DISABLE_CLOCK_DB0 + localparam DISABLE_CLOCK_DB0 = 12; //PL_DB_REGISTER:DISABLE_CLOCK_DB0 + localparam DISABLE_CLOCK_DB1_SIZE = 1; //PL_DB_REGISTER:DISABLE_CLOCK_DB1 + localparam DISABLE_CLOCK_DB1_MSB = 13; //PL_DB_REGISTER:DISABLE_CLOCK_DB1 + localparam DISABLE_CLOCK_DB1 = 13; //PL_DB_REGISTER:DISABLE_CLOCK_DB1 + localparam DISABLE_PLL_REF_CLOCK_SIZE = 1; //PL_DB_REGISTER:DISABLE_PLL_REF_CLOCK + localparam DISABLE_PLL_REF_CLOCK_MSB = 14; //PL_DB_REGISTER:DISABLE_PLL_REF_CLOCK + localparam DISABLE_PLL_REF_CLOCK = 14; //PL_DB_REGISTER:DISABLE_PLL_REF_CLOCK + localparam RELEASE_RESET_DB0_SIZE = 1; //PL_DB_REGISTER:RELEASE_RESET_DB0 + localparam RELEASE_RESET_DB0_MSB = 16; //PL_DB_REGISTER:RELEASE_RESET_DB0 + localparam RELEASE_RESET_DB0 = 16; //PL_DB_REGISTER:RELEASE_RESET_DB0 + localparam RELEASE_RESET_DB1_SIZE = 1; //PL_DB_REGISTER:RELEASE_RESET_DB1 + localparam RELEASE_RESET_DB1_MSB = 17; //PL_DB_REGISTER:RELEASE_RESET_DB1 + localparam RELEASE_RESET_DB1 = 17; //PL_DB_REGISTER:RELEASE_RESET_DB1 + localparam ASSERT_RESET_DB0_SIZE = 1; //PL_DB_REGISTER:ASSERT_RESET_DB0 + localparam ASSERT_RESET_DB0_MSB = 20; //PL_DB_REGISTER:ASSERT_RESET_DB0 + localparam ASSERT_RESET_DB0 = 20; //PL_DB_REGISTER:ASSERT_RESET_DB0 + localparam ASSERT_RESET_DB1_SIZE = 1; //PL_DB_REGISTER:ASSERT_RESET_DB1 + localparam ASSERT_RESET_DB1_MSB = 21; //PL_DB_REGISTER:ASSERT_RESET_DB1 + localparam ASSERT_RESET_DB1 = 21; //PL_DB_REGISTER:ASSERT_RESET_DB1 + +//=============================================================================== +// Register Group PS_CPLD_BASE_REGS +//=============================================================================== + + // SIGNATURE_REGISTER Register (from ps_cpld_regs.v) + localparam SIGNATURE_REGISTER = 'h0; // Register Offset + localparam SIGNATURE_REGISTER_SIZE = 32; // register width in bits + localparam SIGNATURE_REGISTER_MASK = 32'hFFFFFFFF; + localparam PRODUCT_SIGNATURE_SIZE = 32; //SIGNATURE_REGISTER:PRODUCT_SIGNATURE + localparam PRODUCT_SIGNATURE_MSB = 31; //SIGNATURE_REGISTER:PRODUCT_SIGNATURE + localparam PRODUCT_SIGNATURE = 0; //SIGNATURE_REGISTER:PRODUCT_SIGNATURE + + // REVISION_REGISTER Register (from ps_cpld_regs.v) + localparam REVISION_REGISTER = 'h4; // Register Offset + localparam REVISION_REGISTER_SIZE = 32; // register width in bits + localparam REVISION_REGISTER_MASK = 32'hFFFFFFFF; + localparam REVISION_HH_SIZE = 8; //REVISION_REGISTER:REVISION_HH + localparam REVISION_HH_MSB = 7; //REVISION_REGISTER:REVISION_HH + localparam REVISION_HH = 0; //REVISION_REGISTER:REVISION_HH + localparam REVISION_DD_SIZE = 8; //REVISION_REGISTER:REVISION_DD + localparam REVISION_DD_MSB = 15; //REVISION_REGISTER:REVISION_DD + localparam REVISION_DD = 8; //REVISION_REGISTER:REVISION_DD + localparam REVISION_MM_SIZE = 8; //REVISION_REGISTER:REVISION_MM + localparam REVISION_MM_MSB = 23; //REVISION_REGISTER:REVISION_MM + localparam REVISION_MM = 16; //REVISION_REGISTER:REVISION_MM + localparam REVISION_YY_SIZE = 8; //REVISION_REGISTER:REVISION_YY + localparam REVISION_YY_MSB = 31; //REVISION_REGISTER:REVISION_YY + localparam REVISION_YY = 24; //REVISION_REGISTER:REVISION_YY + + // OLDEST_COMPATIBLE_REVISION_REGISTER Register (from ps_cpld_regs.v) + localparam OLDEST_COMPATIBLE_REVISION_REGISTER = 'h8; // Register Offset + localparam OLDEST_COMPATIBLE_REVISION_REGISTER_SIZE = 32; // register width in bits + localparam OLDEST_COMPATIBLE_REVISION_REGISTER_MASK = 32'hFFFFFFFF; + localparam OLD_REVISION_HH_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_HH + localparam OLD_REVISION_HH_MSB = 7; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_HH + localparam OLD_REVISION_HH = 0; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_HH + localparam OLD_REVISION_DD_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_DD + localparam OLD_REVISION_DD_MSB = 15; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_DD + localparam OLD_REVISION_DD = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_DD + localparam OLD_REVISION_MM_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_MM + localparam OLD_REVISION_MM_MSB = 23; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_MM + localparam OLD_REVISION_MM = 16; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_MM + localparam OLD_REVISION_YY_SIZE = 8; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_YY + localparam OLD_REVISION_YY_MSB = 31; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_YY + localparam OLD_REVISION_YY = 24; //OLDEST_COMPATIBLE_REVISION_REGISTER:OLD_REVISION_YY + + // SCRATCH_REGISTER Register (from ps_cpld_regs.v) + localparam SCRATCH_REGISTER = 'hC; // Register Offset + localparam SCRATCH_REGISTER_SIZE = 32; // register width in bits + localparam SCRATCH_REGISTER_MASK = 32'h0; + + // GIT_HASH_REGISTER Register (from ps_cpld_regs.v) + localparam GIT_HASH_REGISTER = 'h10; // Register Offset + localparam GIT_HASH_REGISTER_SIZE = 32; // register width in bits + localparam GIT_HASH_REGISTER_MASK = 32'hFFFFFFFF; + localparam GIT_HASH_SIZE = 28; //GIT_HASH_REGISTER:GIT_HASH + localparam GIT_HASH_MSB = 27; //GIT_HASH_REGISTER:GIT_HASH + localparam GIT_HASH = 0; //GIT_HASH_REGISTER:GIT_HASH + localparam GIT_CLEAN_SIZE = 4; //GIT_HASH_REGISTER:GIT_CLEAN + localparam GIT_CLEAN_MSB = 31; //GIT_HASH_REGISTER:GIT_CLEAN + localparam GIT_CLEAN = 28; //GIT_HASH_REGISTER:GIT_CLEAN diff --git a/top/x400/cpld/regmap/ps_power_regmap_utils.vh b/top/x400/cpld/regmap/ps_power_regmap_utils.vh new file mode 100644 index 0000000..e4021b2 --- /dev/null +++ b/top/x400/cpld/regmap/ps_power_regmap_utils.vh @@ -0,0 +1,54 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ps_power_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // IPASS_POWER_REG : 0x0 (ps_power_regs.v) + // OSC_POWER_REG : 0x4 (ps_power_regs.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group PS_POWER_REGS +//=============================================================================== + + // IPASS_POWER_REG Register (from ps_power_regs.v) + localparam IPASS_POWER_REG = 'h0; // Register Offset + localparam IPASS_POWER_REG_SIZE = 32; // register width in bits + localparam IPASS_POWER_REG_MASK = 32'hC0000001; + localparam IPASS_DISABLE_POWER_BIT_SIZE = 1; //IPASS_POWER_REG:IPASS_DISABLE_POWER_BIT + localparam IPASS_DISABLE_POWER_BIT_MSB = 0; //IPASS_POWER_REG:IPASS_DISABLE_POWER_BIT + localparam IPASS_DISABLE_POWER_BIT = 0; //IPASS_POWER_REG:IPASS_DISABLE_POWER_BIT + localparam IPASS_CLEAR_POWER_FAULT0_SIZE = 1; //IPASS_POWER_REG:IPASS_CLEAR_POWER_FAULT0 + localparam IPASS_CLEAR_POWER_FAULT0_MSB = 30; //IPASS_POWER_REG:IPASS_CLEAR_POWER_FAULT0 + localparam IPASS_CLEAR_POWER_FAULT0 = 30; //IPASS_POWER_REG:IPASS_CLEAR_POWER_FAULT0 + localparam IPASS_POWER_FAULT0_SIZE = 1; //IPASS_POWER_REG:IPASS_POWER_FAULT0 + localparam IPASS_POWER_FAULT0_MSB = 30; //IPASS_POWER_REG:IPASS_POWER_FAULT0 + localparam IPASS_POWER_FAULT0 = 30; //IPASS_POWER_REG:IPASS_POWER_FAULT0 + localparam IPASS_CLEAR_POWER_FAULT1_SIZE = 1; //IPASS_POWER_REG:IPASS_CLEAR_POWER_FAULT1 + localparam IPASS_CLEAR_POWER_FAULT1_MSB = 31; //IPASS_POWER_REG:IPASS_CLEAR_POWER_FAULT1 + localparam IPASS_CLEAR_POWER_FAULT1 = 31; //IPASS_POWER_REG:IPASS_CLEAR_POWER_FAULT1 + localparam IPASS_POWER_FAULT1_SIZE = 1; //IPASS_POWER_REG:IPASS_POWER_FAULT1 + localparam IPASS_POWER_FAULT1_MSB = 31; //IPASS_POWER_REG:IPASS_POWER_FAULT1 + localparam IPASS_POWER_FAULT1 = 31; //IPASS_POWER_REG:IPASS_POWER_FAULT1 + + // OSC_POWER_REG Register (from ps_power_regs.v) + localparam OSC_POWER_REG = 'h4; // Register Offset + localparam OSC_POWER_REG_SIZE = 32; // register width in bits + localparam OSC_POWER_REG_MASK = 32'h3; + localparam OSC_100_SIZE = 1; //OSC_POWER_REG:OSC_100 + localparam OSC_100_MSB = 0; //OSC_POWER_REG:OSC_100 + localparam OSC_100 = 0; //OSC_POWER_REG:OSC_100 + localparam OSC_122_88_SIZE = 1; //OSC_POWER_REG:OSC_122_88 + localparam OSC_122_88_MSB = 1; //OSC_POWER_REG:OSC_122_88 + localparam OSC_122_88 = 1; //OSC_POWER_REG:OSC_122_88 diff --git a/top/x400/cpld/regmap/reconfig_regmap_utils.vh b/top/x400/cpld/regmap/reconfig_regmap_utils.vh new file mode 100644 index 0000000..2ddc6a8 --- /dev/null +++ b/top/x400/cpld/regmap/reconfig_regmap_utils.vh @@ -0,0 +1,135 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: reconfig_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // FLASH_STATUS_REG : 0x0 (reconfig_engine.v) + // FLASH_CONTROL_REG : 0x4 (reconfig_engine.v) + // FLASH_ADDR_REG : 0x8 (reconfig_engine.v) + // FLASH_WRITE_DATA_REG : 0xC (reconfig_engine.v) + // FLASH_READ_DATA_REG : 0x10 (reconfig_engine.v) + // FLASH_CFM0_START_ADDR_REG : 0x14 (reconfig_engine.v) + // FLASH_CFM0_END_ADDR_REG : 0x18 (reconfig_engine.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group RECONFIG_REGS +//=============================================================================== + + // Enumerated type FLASH_PRIMARY_IMAGE_ADDR_ENUM + localparam FLASH_PRIMARY_IMAGE_ADDR_ENUM_SIZE = 3; + localparam FLASH_PRIMARY_IMAGE_START_ADDR_MEM_INIT = 'h1000; // FLASH_PRIMARY_IMAGE_ADDR_ENUM:FLASH_PRIMARY_IMAGE_START_ADDR_MEM_INIT + localparam FLASH_PRIMARY_IMAGE_START_ADDR = 'h9C00; // FLASH_PRIMARY_IMAGE_ADDR_ENUM:FLASH_PRIMARY_IMAGE_START_ADDR + localparam FLASH_PRIMARY_IMAGE_END_ADDR = 'h127FF; // FLASH_PRIMARY_IMAGE_ADDR_ENUM:FLASH_PRIMARY_IMAGE_END_ADDR + + // FLASH_STATUS_REG Register (from reconfig_engine.v) + localparam FLASH_STATUS_REG = 'h0; // Register Offset + localparam FLASH_STATUS_REG_SIZE = 32; // register width in bits + localparam FLASH_STATUS_REG_MASK = 32'h13331; + localparam FLASH_WP_ENABLED_SIZE = 1; //FLASH_STATUS_REG:FLASH_WP_ENABLED + localparam FLASH_WP_ENABLED_MSB = 0; //FLASH_STATUS_REG:FLASH_WP_ENABLED + localparam FLASH_WP_ENABLED = 0; //FLASH_STATUS_REG:FLASH_WP_ENABLED + localparam FLASH_READ_IDLE_SIZE = 1; //FLASH_STATUS_REG:FLASH_READ_IDLE + localparam FLASH_READ_IDLE_MSB = 4; //FLASH_STATUS_REG:FLASH_READ_IDLE + localparam FLASH_READ_IDLE = 4; //FLASH_STATUS_REG:FLASH_READ_IDLE + localparam FLASH_READ_ERR_SIZE = 1; //FLASH_STATUS_REG:FLASH_READ_ERR + localparam FLASH_READ_ERR_MSB = 5; //FLASH_STATUS_REG:FLASH_READ_ERR + localparam FLASH_READ_ERR = 5; //FLASH_STATUS_REG:FLASH_READ_ERR + localparam FLASH_ERASE_IDLE_SIZE = 1; //FLASH_STATUS_REG:FLASH_ERASE_IDLE + localparam FLASH_ERASE_IDLE_MSB = 8; //FLASH_STATUS_REG:FLASH_ERASE_IDLE + localparam FLASH_ERASE_IDLE = 8; //FLASH_STATUS_REG:FLASH_ERASE_IDLE + localparam FLASH_ERASE_ERR_SIZE = 1; //FLASH_STATUS_REG:FLASH_ERASE_ERR + localparam FLASH_ERASE_ERR_MSB = 9; //FLASH_STATUS_REG:FLASH_ERASE_ERR + localparam FLASH_ERASE_ERR = 9; //FLASH_STATUS_REG:FLASH_ERASE_ERR + localparam FLASH_WRITE_IDLE_SIZE = 1; //FLASH_STATUS_REG:FLASH_WRITE_IDLE + localparam FLASH_WRITE_IDLE_MSB = 12; //FLASH_STATUS_REG:FLASH_WRITE_IDLE + localparam FLASH_WRITE_IDLE = 12; //FLASH_STATUS_REG:FLASH_WRITE_IDLE + localparam FLASH_WRITE_ERR_SIZE = 1; //FLASH_STATUS_REG:FLASH_WRITE_ERR + localparam FLASH_WRITE_ERR_MSB = 13; //FLASH_STATUS_REG:FLASH_WRITE_ERR + localparam FLASH_WRITE_ERR = 13; //FLASH_STATUS_REG:FLASH_WRITE_ERR + localparam FLASH_MEM_INIT_ENABLED_SIZE = 1; //FLASH_STATUS_REG:FLASH_MEM_INIT_ENABLED + localparam FLASH_MEM_INIT_ENABLED_MSB = 16; //FLASH_STATUS_REG:FLASH_MEM_INIT_ENABLED + localparam FLASH_MEM_INIT_ENABLED = 16; //FLASH_STATUS_REG:FLASH_MEM_INIT_ENABLED + + // FLASH_CONTROL_REG Register (from reconfig_engine.v) + localparam FLASH_CONTROL_REG = 'h4; // Register Offset + localparam FLASH_CONTROL_REG_SIZE = 32; // register width in bits + localparam FLASH_CONTROL_REG_MASK = 32'h7FF; + localparam FLASH_ENABLE_WP_STB_SIZE = 1; //FLASH_CONTROL_REG:FLASH_ENABLE_WP_STB + localparam FLASH_ENABLE_WP_STB_MSB = 0; //FLASH_CONTROL_REG:FLASH_ENABLE_WP_STB + localparam FLASH_ENABLE_WP_STB = 0; //FLASH_CONTROL_REG:FLASH_ENABLE_WP_STB + localparam FLASH_DISABLE_WP_STB_SIZE = 1; //FLASH_CONTROL_REG:FLASH_DISABLE_WP_STB + localparam FLASH_DISABLE_WP_STB_MSB = 1; //FLASH_CONTROL_REG:FLASH_DISABLE_WP_STB + localparam FLASH_DISABLE_WP_STB = 1; //FLASH_CONTROL_REG:FLASH_DISABLE_WP_STB + localparam FLASH_READ_STB_SIZE = 1; //FLASH_CONTROL_REG:FLASH_READ_STB + localparam FLASH_READ_STB_MSB = 2; //FLASH_CONTROL_REG:FLASH_READ_STB + localparam FLASH_READ_STB = 2; //FLASH_CONTROL_REG:FLASH_READ_STB + localparam FLASH_WRITE_STB_SIZE = 1; //FLASH_CONTROL_REG:FLASH_WRITE_STB + localparam FLASH_WRITE_STB_MSB = 3; //FLASH_CONTROL_REG:FLASH_WRITE_STB + localparam FLASH_WRITE_STB = 3; //FLASH_CONTROL_REG:FLASH_WRITE_STB + localparam FLASH_ERASE_STB_SIZE = 1; //FLASH_CONTROL_REG:FLASH_ERASE_STB + localparam FLASH_ERASE_STB_MSB = 4; //FLASH_CONTROL_REG:FLASH_ERASE_STB + localparam FLASH_ERASE_STB = 4; //FLASH_CONTROL_REG:FLASH_ERASE_STB + localparam FLASH_ERASE_SECTOR_SIZE = 3; //FLASH_CONTROL_REG:FLASH_ERASE_SECTOR + localparam FLASH_ERASE_SECTOR_MSB = 7; //FLASH_CONTROL_REG:FLASH_ERASE_SECTOR + localparam FLASH_ERASE_SECTOR = 5; //FLASH_CONTROL_REG:FLASH_ERASE_SECTOR + localparam CLEAR_FLASH_READ_ERROR_STB_SIZE = 1; //FLASH_CONTROL_REG:CLEAR_FLASH_READ_ERROR_STB + localparam CLEAR_FLASH_READ_ERROR_STB_MSB = 8; //FLASH_CONTROL_REG:CLEAR_FLASH_READ_ERROR_STB + localparam CLEAR_FLASH_READ_ERROR_STB = 8; //FLASH_CONTROL_REG:CLEAR_FLASH_READ_ERROR_STB + localparam CLEAR_FLASH_WRITE_ERROR_STB_SIZE = 1; //FLASH_CONTROL_REG:CLEAR_FLASH_WRITE_ERROR_STB + localparam CLEAR_FLASH_WRITE_ERROR_STB_MSB = 9; //FLASH_CONTROL_REG:CLEAR_FLASH_WRITE_ERROR_STB + localparam CLEAR_FLASH_WRITE_ERROR_STB = 9; //FLASH_CONTROL_REG:CLEAR_FLASH_WRITE_ERROR_STB + localparam CLEAR_FLASH_ERASE_ERROR_STB_SIZE = 1; //FLASH_CONTROL_REG:CLEAR_FLASH_ERASE_ERROR_STB + localparam CLEAR_FLASH_ERASE_ERROR_STB_MSB = 10; //FLASH_CONTROL_REG:CLEAR_FLASH_ERASE_ERROR_STB + localparam CLEAR_FLASH_ERASE_ERROR_STB = 10; //FLASH_CONTROL_REG:CLEAR_FLASH_ERASE_ERROR_STB + + // FLASH_ADDR_REG Register (from reconfig_engine.v) + localparam FLASH_ADDR_REG = 'h8; // Register Offset + localparam FLASH_ADDR_REG_SIZE = 32; // register width in bits + localparam FLASH_ADDR_REG_MASK = 32'h1FFFF; + localparam FLASH_ADDR_SIZE = 17; //FLASH_ADDR_REG:FLASH_ADDR + localparam FLASH_ADDR_MSB = 16; //FLASH_ADDR_REG:FLASH_ADDR + localparam FLASH_ADDR = 0; //FLASH_ADDR_REG:FLASH_ADDR + + // FLASH_WRITE_DATA_REG Register (from reconfig_engine.v) + localparam FLASH_WRITE_DATA_REG = 'hC; // Register Offset + localparam FLASH_WRITE_DATA_REG_SIZE = 32; // register width in bits + localparam FLASH_WRITE_DATA_REG_MASK = 32'hFFFFFFFF; + localparam FLASH_WRITE_DATA_SIZE = 32; //FLASH_WRITE_DATA_REG:FLASH_WRITE_DATA + localparam FLASH_WRITE_DATA_MSB = 31; //FLASH_WRITE_DATA_REG:FLASH_WRITE_DATA + localparam FLASH_WRITE_DATA = 0; //FLASH_WRITE_DATA_REG:FLASH_WRITE_DATA + + // FLASH_READ_DATA_REG Register (from reconfig_engine.v) + localparam FLASH_READ_DATA_REG = 'h10; // Register Offset + localparam FLASH_READ_DATA_REG_SIZE = 32; // register width in bits + localparam FLASH_READ_DATA_REG_MASK = 32'hFFFFFFFF; + localparam FLASH_READ_DATA_SIZE = 32; //FLASH_READ_DATA_REG:FLASH_READ_DATA + localparam FLASH_READ_DATA_MSB = 31; //FLASH_READ_DATA_REG:FLASH_READ_DATA + localparam FLASH_READ_DATA = 0; //FLASH_READ_DATA_REG:FLASH_READ_DATA + + // FLASH_CFM0_START_ADDR_REG Register (from reconfig_engine.v) + localparam FLASH_CFM0_START_ADDR_REG = 'h14; // Register Offset + localparam FLASH_CFM0_START_ADDR_REG_SIZE = 32; // register width in bits + localparam FLASH_CFM0_START_ADDR_REG_MASK = 32'hFFFFFFFF; + localparam FLASH_CFM0_START_ADDR_SIZE = 32; //FLASH_CFM0_START_ADDR_REG:FLASH_CFM0_START_ADDR + localparam FLASH_CFM0_START_ADDR_MSB = 31; //FLASH_CFM0_START_ADDR_REG:FLASH_CFM0_START_ADDR + localparam FLASH_CFM0_START_ADDR = 0; //FLASH_CFM0_START_ADDR_REG:FLASH_CFM0_START_ADDR + + // FLASH_CFM0_END_ADDR_REG Register (from reconfig_engine.v) + localparam FLASH_CFM0_END_ADDR_REG = 'h18; // Register Offset + localparam FLASH_CFM0_END_ADDR_REG_SIZE = 32; // register width in bits + localparam FLASH_CFM0_END_ADDR_REG_MASK = 32'hFFFFFFFF; + localparam FLASH_CFM0_END_ADDR_SIZE = 32; //FLASH_CFM0_END_ADDR_REG:FLASH_CFM0_END_ADDR + localparam FLASH_CFM0_END_ADDR_MSB = 31; //FLASH_CFM0_END_ADDR_REG:FLASH_CFM0_END_ADDR + localparam FLASH_CFM0_END_ADDR = 0; //FLASH_CFM0_END_ADDR_REG:FLASH_CFM0_END_ADDR diff --git a/top/x400/cpld/regmap/spi_regmap_utils.vh b/top/x400/cpld/regmap/spi_regmap_utils.vh new file mode 100644 index 0000000..bf25b6f --- /dev/null +++ b/top/x400/cpld/regmap/spi_regmap_utils.vh @@ -0,0 +1,69 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: spi_regmap_utils.vh +// Description: +// The constants in this file are autogenerated by XmlParse. + +//=============================================================================== +// A numerically ordered list of registers and their HDL source files +//=============================================================================== + + // RX_DATA_LOW : 0x0 (ctrlport_to_spi.v) + // RX_DATA_HIGH : 0x4 (ctrlport_to_spi.v) + // TX_DATA_LOW : 0x8 (ctrlport_to_spi.v) + // TX_DATA_HIGH : 0xC (ctrlport_to_spi.v) + // CONTROL : 0x10 (ctrlport_to_spi.v) + // CLOCK_DIVIDER : 0x14 (ctrlport_to_spi.v) + // SLAVE_SELECT : 0x18 (ctrlport_to_spi.v) + +//=============================================================================== +// RegTypes +//=============================================================================== + +//=============================================================================== +// Register Group SPI_REGS +//=============================================================================== + + // RX_DATA_LOW Register (from ctrlport_to_spi.v) + localparam RX_DATA_LOW = 'h0; // Register Offset + localparam RX_DATA_LOW_SIZE = 32; // register width in bits + localparam RX_DATA_LOW_MASK = 32'h0; + + // RX_DATA_HIGH Register (from ctrlport_to_spi.v) + localparam RX_DATA_HIGH = 'h4; // Register Offset + localparam RX_DATA_HIGH_SIZE = 32; // register width in bits + localparam RX_DATA_HIGH_MASK = 32'h0; + + // TX_DATA_LOW Register (from ctrlport_to_spi.v) + localparam TX_DATA_LOW = 'h8; // Register Offset + localparam TX_DATA_LOW_SIZE = 32; // register width in bits + localparam TX_DATA_LOW_MASK = 32'h0; + + // TX_DATA_HIGH Register (from ctrlport_to_spi.v) + localparam TX_DATA_HIGH = 'hC; // Register Offset + localparam TX_DATA_HIGH_SIZE = 32; // register width in bits + localparam TX_DATA_HIGH_MASK = 32'h0; + + // CONTROL Register (from ctrlport_to_spi.v) + localparam CONTROL = 'h10; // Register Offset + localparam CONTROL_SIZE = 32; // register width in bits + localparam CONTROL_MASK = 32'h0; + + // CLOCK_DIVIDER Register (from ctrlport_to_spi.v) + localparam CLOCK_DIVIDER = 'h14; // Register Offset + localparam CLOCK_DIVIDER_SIZE = 8; // register width in bits + localparam CLOCK_DIVIDER_MASK = 8'hFF; + localparam DIVIDER_SIZE = 8; //CLOCK_DIVIDER:Divider + localparam DIVIDER_MSB = 7; //CLOCK_DIVIDER:Divider + localparam DIVIDER = 0; //CLOCK_DIVIDER:Divider + + // SLAVE_SELECT Register (from ctrlport_to_spi.v) + localparam SLAVE_SELECT = 'h18; // Register Offset + localparam SLAVE_SELECT_SIZE = 16; // register width in bits + localparam SLAVE_SELECT_MASK = 16'hFFFF; + localparam SS_SIZE = 16; //SLAVE_SELECT:SS + localparam SS_MSB = 15; //SLAVE_SELECT:SS + localparam SS = 0; //SLAVE_SELECT:SS diff --git a/top/x400/cpld/reset_generator.v b/top/x400/cpld/reset_generator.v new file mode 100644 index 0000000..dd3a560 --- /dev/null +++ b/top/x400/cpld/reset_generator.v @@ -0,0 +1,93 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: reset_generator +// +// Description: +// +// Generates a power-on reset signal that is asserted at startup and stays +// asserted for at least CYCLES_IN_RESET clock cycles. +// +// Internally, it generates a 1-bit synchronous signal (initialize) to safely +// initialize the power_on_reset_counter incremental counter to 0's. +// +// A delayed version of the initializing signal is also generated +// (counter_enable) to start counting. +// +// 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_ 9_ +// clk _| |_| |_| |_| |_| |_| |_| |_| |_| +// _____________________ +// initialize _____________| +// _________ +// counter_enable _________________________| +// + +`default_nettype none + + +module reset_generator ( + input wire clk, + output reg power_on_reset = 1'b1 +); + + wire [0:0] counter_enable; + wire [0:0] initialize; + + synchronizer #( + .WIDTH (1), + .STAGES (3), + .INITIAL_VAL (1'b0), + .FALSE_PATH_TO_IN (0) + ) init_sync_inst ( + .clk (clk), + .rst (1'b0), + .in (1'b1), + .out (initialize) + ); + + synchronizer #( + .WIDTH (1), + .STAGES (3), + .INITIAL_VAL (1'b0), + .FALSE_PATH_TO_IN (0) + ) counter_en_sync_inst ( + .clk (clk), + .rst (1'b0), + .in (initialize), + .out (counter_enable) + ); + + // Internal synchronous reset generator. + localparam CYCLES_IN_RESET = 20; + reg [7:0] power_on_reset_counter = 8'b0; + + // This block generates a synchronous reset in the clk domain that can be + // used by downstream logic. + // + // power_on_reset_counter is first initialized to 0's upon assertion of + // initialize. Some cycles later (3), upon assertion if counter_enable, + // power_on_reset_counter starts to increment. + // + // power_on_reset will remain asserted until power_on_reset_counter reaches + // cycles_in_reset, resulting in the deassertion of power_on_reset. + always @(posedge clk) begin : power_on_reset_gen + if (counter_enable) begin + if (power_on_reset_counter == CYCLES_IN_RESET-1) begin + power_on_reset <= 1'b0; + end else begin + power_on_reset_counter <= power_on_reset_counter + 1'b1; + power_on_reset <= 1'b1; + end + end + else if (initialize) begin + power_on_reset_counter <= 8'b0; + power_on_reset <= 1'b1; + end + end + +endmodule + + +`default_nettype wire diff --git a/top/x400/cpld/scripts/ps_cs_analysis.tcl b/top/x400/cpld/scripts/ps_cs_analysis.tcl new file mode 100644 index 0000000..03ff77d --- /dev/null +++ b/top/x400/cpld/scripts/ps_cs_analysis.tcl @@ -0,0 +1,32 @@ +# +# Copyright 2021 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# +# Module: ps_cs_analysis +# +# Description: +# +# Analyze false path in PS SPI logic to ensure an upper delay boundary. +# + +# get project to a working state +project_open -force "mb_cpld.qpf" +create_timing_netlist +update_timing_netlist + +# Determine data path delay from MB CPLD chip select signal to MB CPLD internal +# SPI slave +set paths [report_path -from [get_registers {ps_spi_cs_n_decoded[0]}] -multi_corner] +set spiSlaveCsPathDelay [lindex $paths 1] + +# clock period at 250 MHz (clock driving the decoding registers) +set maxDelay 4 + +# compare path from above with maximum delay +if ([expr {$maxDelay < $spiSlaveCsPathDelay}]) { + puts "MB CPLD SPI CS line longer than expected." + exit 1 +} + +exit 0 diff --git a/top/x400/cpld/spi_slave.v b/top/x400/cpld/spi_slave.v new file mode 100644 index 0000000..ab2f16f --- /dev/null +++ b/top/x400/cpld/spi_slave.v @@ -0,0 +1,288 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: spi_slave +// +// Description: +// +// SPI slave for configuration CPOL = CPHA = 0. +// Transfers 8 bit = 1 byte MSB first. Parallel data has to be +// provided and consumed immediately when flags are asserted. +// +// Limitation: clk frequency <= 2*sclk frequency +// +// Data request from sclk domain is triggered towards the clk domain ahead of +// time. This is due to the clock domain crossing using the synchronizer and +// processing pipeline stages. +// +// The worst case propagation delay of the used synchronizer is: +// +// 4 'clk' clock cycles: +// 1 clock cycle of signal propagation to synchronizer +// (data_request_sclk assertion) +// 1 clock cycle to capture data with instability in first stage +// 1 clock cycle to stabilize first stage +// 1 clock cycle to capture data in second stage +// (data_request_clk available in 'clk' domain) +// +// Once synchronized in 'clk' domain, there is one additional clock cycle to +// derive data_out_valid and data_in_required. To ensure that transmit data +// is registered a 'clk' cycle ahead of the actual transmission we need 2 +// more 'clk' clock cycles. This ensures that transmit_word has changed and +// is stable for at least one 'clk' cycle before 'sclk' asserts again. Any +// additional time required externally to respond to the control port +// requests should be considered in this crossing as well. This is a total of +// 7 clock cycles (+ctrlport response margin) @ clk domain. The minimum +// required time in sclk domain to issue the request is calculated based on +// the clock frequencies. +// +// Parameters: +// +// CLK_FREQUENCY : Frequency of "clk" +// SPI_FREQUENCY : Frequency of "sclk" +// + +`default_nettype none + + +module spi_slave #( + parameter CLK_FREQUENCY = 50000000, + parameter SPI_FREQUENCY = 10000000 +) ( + //--------------------------------------------------------------- + // SPI Interface + //--------------------------------------------------------------- + + input wire sclk, + input wire cs_n, + input wire mosi, + output wire miso, + + //--------------------------------------------------------------- + // Parallel Interface + //--------------------------------------------------------------- + + input wire clk, + input wire rst, + + output reg data_in_required, + input wire data_in_valid, + input wire [7:0] data_in, + + output reg data_out_valid, + output reg [7:0] data_out, + + output wire active +); + + wire [0:0] data_request_clk; + wire [0:0] reception_complete_clk; + + //--------------------------------------------------------------- + // SPI Receiver @ sclk + //--------------------------------------------------------------- + + reg [7:0] receiver_reg; + reg [2:0] current_bit_index; + reg reception_complete_sclk = 1'b0; + reg [7:0] received_word; + + always @(posedge sclk or posedge cs_n) begin + // Reset logic on positive cs_n edge = slave idle + if (cs_n) begin + receiver_reg <= 8'b0; + end + // Rising edge of sclk + else begin + // Capture bits into shift register MSBs first + receiver_reg <= {receiver_reg[6:0], mosi}; + end + end + + // Reset with cs_n might occur too early during clk sync. + // Reset half way through the reception. + always @(posedge sclk) begin + // Complete word was received + if (current_bit_index == 7) begin + reception_complete_sclk <= 1'b1; + received_word <= {receiver_reg[6:0], mosi}; + + // Reset after half transaction + end else if (current_bit_index == 3) begin + reception_complete_sclk <= 1'b0; + end + end + + //--------------------------------------------------------------- + // Handover of data sclk -> clk + //--------------------------------------------------------------- + + synchronizer #( + .WIDTH (1), + .STAGES (2), + .INITIAL_VAL (1'b0), + .FALSE_PATH_TO_IN (1) + ) data_sync_inst ( + .clk (clk), + .rst (1'b0), + .in (reception_complete_sclk), + .out (reception_complete_clk) + ); + + //--------------------------------------------------------------- + // Parallel interface data output @ clk + //--------------------------------------------------------------- + + reg reception_complete_clk_delayed = 1'b0; + + // Propagate toggling signal without reset to ensure stability on reset + always @(posedge clk) begin + // Capture last state of reception + reception_complete_clk_delayed <= reception_complete_clk; + end + + // Derive data and control signal + always @(posedge clk) begin + if (rst) begin + data_out_valid <= 1'b0; + data_out <= 8'b0; + end + else begin + // Default assignment + data_out_valid <= 1'b0; + + // Provide data to output on rising_edge + if (reception_complete_clk & ~reception_complete_clk_delayed) begin + // Data can simply be captured as the reception complete signal + // indicates stable values in received_word. + data_out <= received_word; + data_out_valid <= 1'b1; + end + end + end + + //--------------------------------------------------------------- + // SPI Transmitter @ sclk + //--------------------------------------------------------------- + + // Data request calculation: + // SCLK_CYCLES_DURING_DATA_REQ = 8 clk period / sclk period + // Clock periods are expressed by reciprocal of frequencies. + // Term "+CLK_FREQUENCY-1" is used to round up the result in integer logic. + localparam SCLK_CYCLES_DURING_DATA_REQ = (8*SPI_FREQUENCY + CLK_FREQUENCY-1)/CLK_FREQUENCY; + // subtract from 8 bits per transfer to get target index + localparam DATA_REQ_BIT_INDEX = 8 - SCLK_CYCLES_DURING_DATA_REQ; + + reg [7:0] transmit_bits; + reg [7:0] transmit_word; + reg data_request_sclk = 1'b0; + + always @(negedge sclk or posedge cs_n) begin + // Reset logic on positive cs_n edge = slave idle + if (cs_n) begin + current_bit_index <= 3'b0; + data_request_sclk <= 1'b0; + transmit_bits <= 8'b0; + end + // Falling edge of sclk + else begin + // Fill or move shift register for byte transmissions + if (current_bit_index == 7) begin + transmit_bits <= transmit_word; + end else begin + transmit_bits <= {transmit_bits[6:0], 1'b0}; + end + + // Update bit index + current_bit_index <= current_bit_index + 1'b1; + + // Trigger request for new word at start of calculated index + if (current_bit_index == DATA_REQ_BIT_INDEX-1) begin + data_request_sclk <= 1'b1; + // Reset after half the reception in case cs_n is not changed in between + // two transactions. + end else if (current_bit_index == (DATA_REQ_BIT_INDEX+4-1)%8) begin + data_request_sclk <= 1'b0; + end + end + end + + // Drive miso output with data when cs_n low + assign miso = cs_n ? 1'bz : transmit_bits[7]; + + //--------------------------------------------------------------- + // Handover of Data Request sclk -> clk + //--------------------------------------------------------------- + + synchronizer #( + .WIDTH (1), + .STAGES (2), + .INITIAL_VAL (1'b0), + .FALSE_PATH_TO_IN (1) + ) request_sync_inst ( + .clk (clk), + .rst (rst), + .in (data_request_sclk), + .out (data_request_clk) + ); + + //--------------------------------------------------------------- + // Parallel Interface Data Input Control + //--------------------------------------------------------------- + + reg data_request_clk_delayed; + + always @(posedge clk) begin + if (rst) begin + data_request_clk_delayed <= 1'b0; + data_in_required <= 1'b0; + transmit_word <= 8'b0; + end + else begin + // Default assignment + data_in_required <= 1'b0; + + // Capture last state of data request + data_request_clk_delayed <= data_request_clk; + + // Request data from input + if (~data_request_clk_delayed & data_request_clk) begin + data_in_required <= 1'b1; + end + + // Capture new data if valid data available, 0 otherwise. + if (data_in_required) begin + if (data_in_valid) begin + transmit_word <= data_in; + end else begin + transmit_word <= 8'b0; + end + end + end + end + + //--------------------------------------------------------------- + // Chip Select + //--------------------------------------------------------------- + // Driven as active signal in parallel clock domain + + wire cs_n_clk; + assign active = ~cs_n_clk; + synchronizer #( + .WIDTH (1), + .STAGES (2), + .INITIAL_VAL (1'b1), + .FALSE_PATH_TO_IN (1) + ) active_sync_inst ( + .clk (clk), + .rst (rst), + .in (cs_n), + .out (cs_n_clk) + ); + +endmodule + + +`default_nettype wire diff --git a/top/x400/cpld/spi_slave_to_ctrlport_master.v b/top/x400/cpld/spi_slave_to_ctrlport_master.v new file mode 100644 index 0000000..6f624fe --- /dev/null +++ b/top/x400/cpld/spi_slave_to_ctrlport_master.v @@ -0,0 +1,238 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: spi_slave_to_ctrlport_master +// +// Description: +// +// SPI slave to ContolPort master conversion in order to tunnel control port +// request through an SPI bus. +// +// The request format on SPI is defined as: +// +// Write request: +// 1'b1 = write, 15 bit address, 32 bit data (MOSI), 8 bit processing gap, +// 5 bit padding, 1 bit ack, 2 bit status +// +// Read request: +// 1'b0 = read, 15 bit address, 8 bit processing gap, 32 bit data (MISO), +// 5 bit padding, 1 bit ack, 2 bit status +// +// Parameters: +// +// CLK_FREQUENCY : Frequency of "clk" +// SPI_FREQUENCY : Frequency of "sclk" +// + +`default_nettype none + + +module spi_slave_to_ctrlport_master #( + parameter CLK_FREQUENCY = 50000000, + parameter SPI_FREQUENCY = 10000000 +) ( + //--------------------------------------------------------------- + // ControlPort Master + //--------------------------------------------------------------- + + input wire ctrlport_clk, + input wire ctrlport_rst, + + output wire m_ctrlport_req_wr, + output wire m_ctrlport_req_rd, + output wire [19:0] m_ctrlport_req_addr, + output wire [31:0] m_ctrlport_req_data, + + input wire m_ctrlport_resp_ack, + input wire [ 1:0] m_ctrlport_resp_status, + input wire [31:0] m_ctrlport_resp_data, + + //--------------------------------------------------------------- + // SPI Slave + //--------------------------------------------------------------- + + input wire sclk, + input wire cs_n, + input wire mosi, + output wire miso +); + + `include "../../../lib/rfnoc/core/ctrlport.vh" + + //--------------------------------------------------------------- + // SPI Slave + //--------------------------------------------------------------- + + wire [7:0] data_in; + wire [7:0] data_out; + wire data_in_valid; + wire data_out_valid; + wire data_in_required; + wire spi_slave_active; + + spi_slave #( + .CLK_FREQUENCY (CLK_FREQUENCY), + .SPI_FREQUENCY (SPI_FREQUENCY) + ) spi_slave_async ( + .sclk (sclk), + .cs_n (cs_n), + .mosi (mosi), + .miso (miso), + .clk (ctrlport_clk), + .rst (ctrlport_rst), + .data_in_required (data_in_required), + .data_in_valid (data_in_valid), + .data_in (data_in), + .data_out_valid (data_out_valid), + .data_out (data_out), + .active (spi_slave_active) + ); + + //--------------------------------------------------------------- + // Reset Generation from SPI Slave + //--------------------------------------------------------------- + + reg spi_slave_active_delayed = 1'b0; + always @(posedge ctrlport_clk) begin + if (ctrlport_rst) begin + spi_slave_active_delayed <= 1'b0; + end + else begin + spi_slave_active_delayed <= spi_slave_active; + end + end + + // Trigger reset on falling edge of active signal (rising edge of cs_n) + wire spi_slave_reset; + assign spi_slave_reset = spi_slave_active_delayed & (~spi_slave_active); + + //--------------------------------------------------------------- + // Transfer Constants + //--------------------------------------------------------------- + + localparam NUM_BYTES_TRANSACTION = 8; + localparam NUM_BYTES_WRITE_REQUEST_PAYLOAD = 6; + localparam NUM_BYTES_READ_REQUEST_PAYLOAD = 2; + localparam MAX_BYTES_RESPONSE_PAYLOAD = 5; + + //--------------------------------------------------------------- + // Data Receiver + //--------------------------------------------------------------- + + reg [3:0] num_bytes_received; + reg request_received; + reg write_request; + reg provide_response; + reg [NUM_BYTES_WRITE_REQUEST_PAYLOAD*8-1:0] request_reg = {NUM_BYTES_WRITE_REQUEST_PAYLOAD*8 {1'b0}}; + + always @(posedge ctrlport_clk) begin + if (ctrlport_rst || spi_slave_reset) begin + num_bytes_received <= 4'b0; + request_received <= 1'b0; + write_request <= 1'b0; + provide_response <= 1'b0; + end + else begin + // Counter number of received bytes + if (data_out_valid) begin + // Increment counter + num_bytes_received <= num_bytes_received + 1'b1; + + if (num_bytes_received == NUM_BYTES_TRANSACTION-1) begin + num_bytes_received <= 4'b0; + end + end + + // Check for read / write on first received byte's MSB + if (data_out_valid && (num_bytes_received == 0)) begin + write_request <= data_out[7]; + end + + // Detect complete request + request_received <= 1'b0; + if (data_out_valid) begin + if (write_request && (num_bytes_received == NUM_BYTES_WRITE_REQUEST_PAYLOAD-1)) begin + request_received <= 1'b1; + provide_response <= 1'b1; + end else if (~write_request && (num_bytes_received == NUM_BYTES_READ_REQUEST_PAYLOAD-1)) begin + request_received <= 1'b1; + provide_response <= 1'b1; + end + end + + // Detect end of response on last received byte + if (num_bytes_received == NUM_BYTES_TRANSACTION-1) begin + provide_response <= 1'b0; + end + + // Capture data into shift register + if (data_out_valid) begin + request_reg <= {request_reg[NUM_BYTES_WRITE_REQUEST_PAYLOAD*8-8-1:0], data_out}; + end + end + end + + // Drive ControlPort + localparam SPI_TRANSFER_ADDRESS_WIDTH = 15; + assign m_ctrlport_req_wr = request_received && write_request; + assign m_ctrlport_req_rd = request_received && ~write_request; + assign m_ctrlport_req_data = request_reg[CTRLPORT_DATA_W-1:0]; + assign m_ctrlport_req_addr = (write_request) ? + {5'b0, request_reg[CTRLPORT_DATA_W+:SPI_TRANSFER_ADDRESS_WIDTH]} : + {5'b0, request_reg[0+:SPI_TRANSFER_ADDRESS_WIDTH]}; + + //--------------------------------------------------------------- + // Response Handling + //--------------------------------------------------------------- + + reg [MAX_BYTES_RESPONSE_PAYLOAD*8-1:0] response_reg; + reg ready_for_response; // active during processing gap + wire write_response_byte; + + always @(posedge ctrlport_clk) begin + if (ctrlport_rst || spi_slave_reset) begin + response_reg <= {8*MAX_BYTES_RESPONSE_PAYLOAD {1'b0}}; + ready_for_response <= 1'b0; + end + else begin + // Reset response on new request + if (request_received) begin + ready_for_response <= 1'b1; + if (write_request) begin + // Just last byte -> padding, ack flag, CMDERR, padding (data length) + response_reg <= {5'b0, 1'b1, CTRL_STS_CMDERR, {CTRLPORT_DATA_W{1'b0}}}; + end else begin + // Last 5 bytes -> data = 0, Padding, ack flag, CMDERR + response_reg <= {{CTRLPORT_DATA_W{1'b0}}, 5'b0, 1'b1, CTRL_STS_CMDERR}; + end + + // Capture response within processing gap, leave default response from above otherwise + end else if (m_ctrlport_resp_ack && ready_for_response) begin + if (write_request) begin + response_reg <= {5'b0, m_ctrlport_resp_ack, m_ctrlport_resp_status, {CTRLPORT_DATA_W{1'b0}}}; + end else begin + response_reg <= {m_ctrlport_resp_data, 5'b0, m_ctrlport_resp_ack, m_ctrlport_resp_status}; + end + end + + // Shift data after writing to slave + if (write_response_byte) begin + response_reg <= {response_reg[0+:(MAX_BYTES_RESPONSE_PAYLOAD-1)*8], 8'b0}; + ready_for_response <= 1'b0; + end + end + end + + // Response is written after request part has been transferred + assign write_response_byte = data_in_required && provide_response; + + // Assign SPI slave inputs + assign data_in = response_reg[(MAX_BYTES_RESPONSE_PAYLOAD-1)*8+:8]; + assign data_in_valid = write_response_byte; + +endmodule + + +`default_nettype wire