Large update to new architecture and board files

This commit is contained in:
bsdevlin 2019-03-11 15:21:45 -04:00
parent 8128e982ee
commit 86a8db4df3
24 changed files with 2617 additions and 68 deletions

View File

@ -0,0 +1,827 @@
#**************************************************************************
#************* BittWare Incorporated *************
#************* 45 S. Main Street, Concord, NH 03301 *************
#**************************************************************************
# LEGAL NOTICE:
# Copyright (c) 2018 BittWare, Inc.
# The user is hereby granted a non-exclusive license to use and or
# modify this code provided that it runs on BittWare hardware.
# Usage of this code on non-BittWare hardware without the express
# written permission of BittWare is strictly prohibited.
#
# E-mail: support@bittware.com Tel: 603-226-0404
#**************************************************************************
##############################################
########## Configuration ##########
##############################################
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.USR_ACCESS TIMESTAMP [current_design] # Bitstream configuration settings
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] # Must set to "NO" if loading from backup flash partition
set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
##############################################
########## Board Clocks/Reset ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports sys_rst_l] # Active Low Global Reset
set_property PACKAGE_PIN F18 [get_ports sys_rst_l]
##############################################
########## Misc. Board-specific ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports fpga_i2c_master_l] # FPGA I2C Master. 0 = FPGA has control of I2C chains shared with the BMC.
set_property PACKAGE_PIN E17 [get_ports fpga_i2c_master_l]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_ctl_en] # QSFP I2C Control Enable. 1 = Connect QSFP I2C/Status to FPGA
set_property PACKAGE_PIN C18 [get_ports qsfp_ctl_en]
set_property IOSTANDARD LVCMOS18 [get_ports sas_ctl_en] # SAS I2C Control Enable. 1 = Connect SAS GPIO to FPGA
set_property PACKAGE_PIN C17 [get_ports sas_ctl_en]
set_property IOSTANDARD LVCMOS18 [get_ports rd_prsnt_l_1] # Active Low RDIMM 1 Presence
set_property PACKAGE_PIN D17 [get_ports rd_prsnt_l_1]
set_property IOSTANDARD LVCMOS18 [get_ports rd_prsnt_l_2] # Active Low RDIMM 2 Presence
set_property PACKAGE_PIN D16 [get_ports rd_prsnt_l_2]
set_property IOSTANDARD LVCMOS18 [get_ports pcie_bp_l] # Active Low Back Plane Detect
set_property PACKAGE_PIN C20 [get_ports pcie_bp_l]
set_property IOSTANDARD LVCMOS18 [get_ports xtp1] # Test Point 1
set_property PACKAGE_PIN F16 [get_ports xtp1]
set_property IOSTANDARD LVCMOS18 [get_ports xtp2] # Test Point 2
set_property PACKAGE_PIN E16 [get_ports xtp2]
set_property IOSTANDARD LVCMOS18 [get_ports xtp3] # Test Point 3
set_property PACKAGE_PIN E21 [get_ports xtp3]
set_property IOSTANDARD LVCMOS18 [get_ports xtp4] # Test Point 4
set_property PACKAGE_PIN D21 [get_ports xtp4]
##############################################
########## UART I/F's ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports avr_rxd] # AVR UART Rx Data
set_property PACKAGE_PIN F19 [get_ports avr_rxd]
set_property IOSTANDARD LVCMOS18 [get_ports avr_txd] # AVR UART Tx Data
set_property PACKAGE_PIN J16 [get_ports avr_txd]
set_property IOSTANDARD LVCMOS18 [get_ports usb_uart_txd] # FTDI UART Tx Data
set_property PACKAGE_PIN G21 [get_ports usb_uart_txd]
set_property IOSTANDARD LVCMOS18 [get_ports usb_uart_rxd] # FTDI UART Rx Data
set_property PACKAGE_PIN F21 [get_ports usb_uart_rxd]
##############################################
########## I2C I/F's ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports i2c_sda_3] # I2C SDA 3 MAC-ID
set_property PACKAGE_PIN K16 [get_ports i2c_sda]
set_property IOSTANDARD LVCMOS18 [get_ports i2c_scl_3] # I2C SCL 3 MAC-ID
set_property PACKAGE_PIN K17 [get_ports i2c_scl]
##############################################
########## USB-C Misc. ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports usbc_cbl_dir] # USB C Cable Direction (input from connector)
set_property PACKAGE_PIN G18 [get_ports usbc_cbl_dir]
set_property IOSTANDARD LVCMOS18 [get_ports usbc_pps] USB C PPS
set_property PACKAGE_PIN G17 [get_ports usbc_pps]
set_property IOSTANDARD LVCMOS18 [get_ports usbc_clk] USB C CLK
set_property PACKAGE_PIN F20 [get_ports usbc_clk]
##############################################
########## QSFP Status & Control ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_prsnt_l_1] # QSFP 1 Active Low Present
set_property PACKAGE_PIN B17 [get_ports qsfp_prsnt_l_1]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_rst_l_1] # QSFP 1 Active Low Reset
set_property PACKAGE_PIN A21 [get_ports qsfp_rst_l_1]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_prsnt_l_2] # QSFP 2 Active Low Present
set_property PACKAGE_PIN A20 [get_ports qsfp_prsnt_l_2]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_rst_l_2] # QSFP 2 Active Low Reset
set_property PACKAGE_PIN A19 [get_ports qsfp_rst_l_2]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_prsnt_l_3] # QSFP 3 Active Low Present
set_property PACKAGE_PIN A18 [get_ports qsfp_prsnt_l_3]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_rst_l_3] # QSFP 3 Active Low Reset
set_property PACKAGE_PIN B16 [get_ports qsfp_rst_l_3]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_prsnt_l_4] # QSFP 4 Active Low Present
set_property PACKAGE_PIN A16 [get_ports qsfp_prsnt_l_4]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_rst_l_4] # QSFP 4 Active Low Reset
set_property PACKAGE_PIN C19 [get_ports qsfp_rst_l_4]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_lp] # QSFP Low Power Mode Enable (output to all QSFPs)
set_property PACKAGE_PIN B18 [get_ports qsfp_lp]
set_property IOSTANDARD LVCMOS18 [get_ports qsfp_int_l] # QSFP Active Low Interrupt (wire-OR'ed input from all QSFPs)
set_property PACKAGE_PIN B20 [get_ports qsfp_int_l]
##############################################
########## SAS GPIO ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports sas1_gprx[0]] # SAS1 GPRX 0
set_property PACKAGE_PIN K19 [get_ports sas1_gprx[0]]
set_property IOSTANDARD LVCMOS18 [get_ports sas1_gprx[1]] # SAS1 GPRX 1
set_property PACKAGE_PIN K18 [get_ports sas1_gprx[1]]
set_property IOSTANDARD LVCMOS18 [get_ports sas1_gptx[0]] # SAS1 GPTX 0
set_property PACKAGE_PIN K21 [get_ports sas1_gptx[0]]
set_property IOSTANDARD LVCMOS18 [get_ports sas1_gptx[1]] # SAS1 GPTX 1
set_property PACKAGE_PIN J21 [get_ports sas1_gptx[1]]
set_property IOSTANDARD LVCMOS18 [get_ports sas1_gpio[0]] # SAS1 GPIO 0
set_property PACKAGE_PIN J20 [get_ports sas1_gpio[0]]
set_property IOSTANDARD LVCMOS18 [get_ports sas1_gpio[1]] # SAS1 GPIO 1
set_property PACKAGE_PIN J19 [get_ports sas1_gpio[1]]
set_property IOSTANDARD LVCMOS18 [get_ports sas2_gprx[0]] # SAS2 GPRX 0
set_property PACKAGE_PIN J17 [get_ports sas2_gprx[0]]
set_property IOSTANDARD LVCMOS18 [get_ports sas2_gprx[1]] # SAS2 GPRX 1
set_property PACKAGE_PIN H17 [get_ports sas2_gprx[1]]
set_property IOSTANDARD LVCMOS18 [get_ports sas2_gptx[0]] # SAS2 GPTX 0
set_property PACKAGE_PIN G16 [get_ports sas2_gptx[0]]
set_property IOSTANDARD LVCMOS18 [get_ports sas2_gptx[1]] # SAS2 GPTX 1
set_property PACKAGE_PIN H20 [get_ports sas2_gptx[1]]
set_property IOSTANDARD LVCMOS18 [get_ports sas2_gpio[0]] # SAS2 GPIO 0
set_property PACKAGE_PIN G20 [get_ports sas2_gpio[0]]
set_property IOSTANDARD LVCMOS18 [get_ports sas2_gpio[1]] # SAS2 GPIO 1
set_property PACKAGE_PIN H19 [get_ports sas2_gpio[1]]
##############################################
########## LEDs ##########
##############################################
set_property IOSTANDARD LVCMOS18 [get_ports {led_l[0]}] # Active Low Led 0
set_property PACKAGE_PIN L19 [get_ports {led_l[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led_l[1]}] # Active Low Led 1
set_property PACKAGE_PIN L18 [get_ports {led_l[1]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led_l[2]}] # Active Low Led 2
set_property PACKAGE_PIN L21 [get_ports {led_l[2]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led_l[3]}] # Active Low Led 3
set_property PACKAGE_PIN L20 [get_ports {led_l[3]}]
##############################################
########## PCIe ##########
##############################################
set_property PACKAGE_PIN BJ26 [get_ports progclk_b5_p] # SI5341B_P_5
set_property PACKAGE_PIN BJ25 [get_ports progclk_b5_n] # SI5341B_N_5
set_property IOSTANDARD DIFF_SSTL18_I [get_ports progclk_b5_p]
set_property PACKAGE_PIN BG23 [get_ports pcie_sys_reset_l] # PCIE Active Low Reset
set_property IOSTANDARD LVCMOS12 [get_ports pcie_sys_reset_l]
set_property PULLUP true [get_ports pcie_sys_reset_l]
set_property PACKAGE_PIN AR15 [get_ports pcie_sys_clkn] # PCIE Reference Clock 0
set_property PACKAGE_PIN AR14 [get_ports pcie_sys_clkp]
#set_property PACKAGE_PIN AL15 [get_ports pcie_sys_clkn] # PCIE Reference Clock 1
#set_property PACKAGE_PIN AL14 [get_ports pcie_sys_clkp]
create_clock -period 10.000 -name refclk_100 [get_ports pcie_sys_clkp] # PCIe Reference Clock Frequency (100 MHz)
# NOTE: All GTY pins are automatically assigned by Vivado. Shown here for reference only.
#GTH BANK 227 PCIE 3:0
#set_property PACKAGE_PIN AL2 [get_ports pcie_7x_mgt_rxp[0]] # PCIE_RX_P_0
#set_property PACKAGE_PIN AL1 [get_ports pcie_7x_mgt_rxn[0]] # PCIE_RX_N_0
#set_property PACKAGE_PIN AM4 [get_ports pcie_7x_mgt_rxp[1]] # PCIE_RX_P_1
#set_property PACKAGE_PIN AM3 [get_ports pcie_7x_mgt_rxn[1]] # PCIE_RX_N_1
#set_property PACKAGE_PIN AN5 [get_ports pcie_7x_mgt_rxp[2]] # PCIE_RX_P_2
#set_property PACKAGE_PIN AN6 [get_ports pcie_7x_mgt_rxn[2]] # PCIE_RX_N_2
#set_property PACKAGE_PIN AN2 [get_ports pcie_7x_mgt_rxp[3]] # PCIE_RX_P_3
#set_property PACKAGE_PIN AN1 [get_ports pcie_7x_mgt_rxn[3]] # PCIE_RX_N_3
#set_property PACKAGE_PIN AL11 [get_ports pcie_7x_mgt_txp[0]] # PCIE_TX_P_0
#set_property PACKAGE_PIN AL10 [get_ports pcie_7x_mgt_txn[0]] # PCIE_TX_N_0
#set_property PACKAGE_PIN AM9 [get_ports pcie_7x_mgt_txp[1]] # PCIE_TX_P_1
#set_property PACKAGE_PIN AM8 [get_ports pcie_7x_mgt_txn[1]] # PCIE_TX_N_1
#set_property PACKAGE_PIN AN11 [get_ports pcie_7x_mgt_txp[2]] # PCIE_TX_P_2
#set_property PACKAGE_PIN AN10 [get_ports pcie_7x_mgt_txn[2]] # PCIE_TX_N_2
#set_property PACKAGE_PIN AP9 [get_ports pcie_7x_mgt_txp[3]] # PCIE_TX_P_3
#set_property PACKAGE_PIN AP8 [get_ports pcie_7x_mgt_txn[3]] # PCIE_TX_N_3
#GTH BANK 226 PCIE 7:4
#set_property PACKAGE_PIN AP4 [get_ports pcie_7x_mgt_rxp[4]] # PCIE_RX_P_4
#set_property PACKAGE_PIN AP3 [get_ports pcie_7x_mgt_rxn[4]] # PCIE_RX_N_4
#set_property PACKAGE_PIN AR2 [get_ports pcie_7x_mgt_rxp[5]] # PCIE_RX_P_5
#set_property PACKAGE_PIN AR1 [get_ports pcie_7x_mgt_rxn[5]] # PCIE_RX_N_5
#set_property PACKAGE_PIN AT4 [get_ports pcie_7x_mgt_rxp[6]] # PCIE_RX_P_6
#set_property PACKAGE_PIN AT3 [get_ports pcie_7x_mgt_rxn[6]] # PCIE_RX_N_6
#set_property PACKAGE_PIN AU2 [get_ports pcie_7x_mgt_rxp[7]] # PCIE_RX_P_7
#set_property PACKAGE_PIN AU1 [get_ports pcie_7x_mgt_rxn[7]] # PCIE_RX_N_7
#set_property PACKAGE_PIN AR11 [get_ports pcie_7x_mgt_txp[4]] # PCIE_TX_P_4
#set_property PACKAGE_PIN AR10 [get_ports pcie_7x_mgt_txn[4]] # PCIE_TX_N_4
#set_property PACKAGE_PIN AR7 [get_ports pcie_7x_mgt_txp[5]] # PCIE_TX_P_5
#set_property PACKAGE_PIN AR6 [get_ports pcie_7x_mgt_txn[5]] # PCIE_TX_N_5
#set_property PACKAGE_PIN AT9 [get_ports pcie_7x_mgt_txp[6]] # PCIE_TX_P_6
#set_property PACKAGE_PIN AT8 [get_ports pcie_7x_mgt_txn[6]] # PCIE_TX_N_6
#set_property PACKAGE_PIN AU11 [get_ports pcie_7x_mgt_txp[7]] # PCIE_TX_P_7
#set_property PACKAGE_PIN AU10 [get_ports pcie_7x_mgt_txn[7]] # PCIE_TX_N_7
#GTH BANK 225 PCIE Lanes 11:8
#set_property PACKAGE_PIN AV4 [get_ports pcie_7x_mgt_rxp[8]] # PCIE_RX_P_8
#set_property PACKAGE_PIN AV3 [get_ports pcie_7x_mgt_rxn[8]] # PCIE_RX_N_8
#set_property PACKAGE_PIN AW6 [get_ports pcie_7x_mgt_rxp[9]] # PCIE_RX_P_9
#set_property PACKAGE_PIN AW5 [get_ports pcie_7x_mgt_rxn[9]] # PCIE_RX_N_9
#set_property PACKAGE_PIN AW2 [get_ports pcie_7x_mgt_rxp[10]] # PCIE_RX_P_10
#set_property PACKAGE_PIN AW1 [get_ports pcie_7x_mgt_rxn[10]] # PCIE_RX_N_10
#set_property PACKAGE_PIN AY4 [get_ports pcie_7x_mgt_rxp[11]] # PCIE_RX_P_11
#set_property PACKAGE_PIN AY3 [get_ports pcie_7x_mgt_rxn[11]] # PCIE_RX_N_11
#set_property PACKAGE_PIN AU7 [get_ports pcie_7x_mgt_txp[8]] # PCIE_TX_P_8
#set_property PACKAGE_PIN AU6 [get_ports pcie_7x_mgt_txn[8]] # PCIE_TX_N_8
#set_property PACKAGE_PIN AV9 [get_ports pcie_7x_mgt_txp[9]] # PCIE_TX_P_9
#set_property PACKAGE_PIN AV8 [get_ports pcie_7x_mgt_txn[9]] # PCIE_TX_N_9
#set_property PACKAGE_PIN AW11 [get_ports pcie_7x_mgt_txp[10]] # PCIE_TX_P_10
#set_property PACKAGE_PIN AW10 [get_ports pcie_7x_mgt_txn[10]] # PCIE_TX_N_10
#set_property PACKAGE_PIN AY9 [get_ports pcie_7x_mgt_txp[11]] # PCIE_TX_P_11
#set_property PACKAGE_PIN AY8 [get_ports pcie_7x_mgt_txn[11]] # PCIE_TX_N_11
#GTH BANK 224 PCIE Lanes 15:12
#set_property PACKAGE_PIN BA6 [get_ports pcie_7x_mgt_rxp[12]] # PCIE_RX_P_12
#set_property PACKAGE_PIN BA5 [get_ports pcie_7x_mgt_rxn[12]] # PCIE_RX_N_12
#set_property PACKAGE_PIN BA2 [get_ports pcie_7x_mgt_rxp[13]] # PCIE_RX_P_13
#set_property PACKAGE_PIN BA1 [get_ports pcie_7x_mgt_rxn[13]] # PCIE_RX_N_13
#set_property PACKAGE_PIN BB4 [get_ports pcie_7x_mgt_rxp[14]] # PCIE_RX_P_14
#set_property PACKAGE_PIN BB3 [get_ports pcie_7x_mgt_rxn[14]] # PCIE_RX_N_14
#set_property PACKAGE_PIN BC2 [get_ports pcie_7x_mgt_rxp[15]] # PCIE_RX_P_15
#set_property PACKAGE_PIN BC1 [get_ports pcie_7x_mgt_rxn[15]] # PCIE_RX_N_15
#set_property PACKAGE_PIN BA11 [get_ports pcie_7x_mgt_txp[12]] # PCIE_TX_P_12
#set_property PACKAGE_PIN BA10 [get_ports pcie_7x_mgt_txn[12]] # PCIE_TX_N_12
#set_property PACKAGE_PIN BB9 [get_ports pcie_7x_mgt_txp[13]] # PCIE_TX_P_13
#set_property PACKAGE_PIN BB8 [get_ports pcie_7x_mgt_txn[13]] # PCIE_TX_N_13
#set_property PACKAGE_PIN BC11 [get_ports pcie_7x_mgt_txp[14]] # PCIE_TX_P_14
#set_property PACKAGE_PIN BC10 [get_ports pcie_7x_mgt_txn[14]] # PCIE_TX_N_14
#set_property PACKAGE_PIN BC7 [get_ports pcie_7x_mgt_txp[15]] # PCIE_TX_P_15
#set_property PACKAGE_PIN BC6 [get_ports pcie_7x_mgt_txn[15]] # PCIE_TX_N_15
##############################################
########## Memory Clocks ##########
##############################################
set_property PACKAGE_PIN G35 [get_ports ddr4_sys_clk_1_p] # DIMM 1 Reference Clock
set_property PACKAGE_PIN G36 [get_ports ddr4_sys_clk_1_n]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports ddr4_sys_clk_1_p]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports ddr4_sys_clk_1_n]
set_property ODT RTT_48 [get_ports ddr4_sys_clk_1_p]
set_property PACKAGE_PIN BK43 [get_ports ddr4_sys_clk_2_p] # DIMM 2 Reference Clock
set_property PACKAGE_PIN BK44 [get_ports ddr4_sys_clk_2_n]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports ddr4_sys_clk_2_p]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports ddr4_sys_clk_2_n]
set_property ODT RTT_48 [get_ports ddr4_sys_clk_2_p]
##############################################
########## Memory DIMM Pins ##########
##############################################
# NOTE: The following assignments are for two 16GB RDIMMs. Please see example projects for other memory type pinouts
### RDIMM 1
set_property PACKAGE_PIN J34 [get_ports "m0_ddr4_act_n"] # Dimm 1 Activation Command Low
set_property PACKAGE_PIN D35 [get_ports "m0_ddr4_adr[0]"] # Dimm 1 Address Pin 0
set_property PACKAGE_PIN D36 [get_ports "m0_ddr4_adr[1]"] # Dimm 1 Address Pin 10
set_property PACKAGE_PIN B38 [get_ports "m0_ddr4_adr[10]"] # Dimm 1 Address Pin 11
set_property PACKAGE_PIN C35 [get_ports "m0_ddr4_adr[11]"] # Dimm 1 Address Pin 12
set_property PACKAGE_PIN B36 [get_ports "m0_ddr4_adr[12]"] # Dimm 1 Address Pin 13
set_property PACKAGE_PIN B35 [get_ports "m0_ddr4_adr[13]"] # Dimm 1 Address Pin 14
set_property PACKAGE_PIN A36 [get_ports "m0_ddr4_adr[14]"] # Dimm 1 Address Pin 15
set_property PACKAGE_PIN A34 [get_ports "m0_ddr4_adr[15]"] # Dimm 1 Address Pin 16
set_property PACKAGE_PIN A35 [get_ports "m0_ddr4_adr[16]"] # Dimm 1 Address Pin 17
#set_property PACKAGE_PIN C38 [get_ports "m0_ddr4_adr[17]"] # Dimm 1 Address Pin 1
set_property PACKAGE_PIN F34 [get_ports "m0_ddr4_adr[2]"] # Dimm 1 Address Pin 2
set_property PACKAGE_PIN E34 [get_ports "m0_ddr4_adr[3]"] # Dimm 1 Address Pin 3
set_property PACKAGE_PIN E36 [get_ports "m0_ddr4_adr[4]"] # Dimm 1 Address Pin 4
set_property PACKAGE_PIN D37 [get_ports "m0_ddr4_adr[5]"] # Dimm 1 Address Pin 5
set_property PACKAGE_PIN C39 [get_ports "m0_ddr4_adr[6]"] # Dimm 1 Address Pin 6
set_property PACKAGE_PIN D34 [get_ports "m0_ddr4_adr[7]"] # Dimm 1 Address Pin 7
set_property PACKAGE_PIN C34 [get_ports "m0_ddr4_adr[8]"] # Dimm 1 Address Pin 8
set_property PACKAGE_PIN C37 [get_ports "m0_ddr4_adr[9]"] # Dimm 1 Address Pin 9
#set_property PACKAGE_PIN B37 [get_ports "m0_ddr4_alert_n"] # Dimm 1 Active Low Alert
set_property PACKAGE_PIN F35 [get_ports "m0_ddr4_ba[0]"] # Dimm 1 Bank Address 0
set_property PACKAGE_PIN F36 [get_ports "m0_ddr4_ba[1]"] # Dimm 1 Bank Address 1
set_property PACKAGE_PIN E37 [get_ports "m0_ddr4_bg[0]"] # Dimm 1 Bank Group 0
set_property PACKAGE_PIN E38 [get_ports "m0_ddr4_bg[1]"] # Dimm 1 Bank Address 1
#set_property PACKAGE_PIN H39 [get_ports "m0_ddr4_c[0]"] # Dimm 1 Active Low Chip Select2
#set_property PACKAGE_PIN H37 [get_ports "m0_ddr4_c[1]"] # Dimm 1 Active Low Chip Select3
#set_property PACKAGE_PIN A38 [get_ports "m0_ddr4_c[2]"] # Dimm 1 Die Select
#set_property PACKAGE_PIN C33 [get_ports "m0_ddr4_c[3]"] # Dimm 1 RFU
#set_property PACKAGE_PIN B43 [get_ports "m0_ddr4_c[4]"] # Dimm 1 RFU
set_property PACKAGE_PIN D39 [get_ports "m0_ddr4_ck_c"] # Dimm 1 Clock
set_property PACKAGE_PIN H35 [get_ports "m0_ddr4_cke[0]"] # Dimm 1 Clock Enable 0
#set_property PACKAGE_PIN G38 [get_ports "m0_ddr4_cke[1]"] # Dimm 1 Clock Enable 1
set_property PACKAGE_PIN E39 [get_ports "m0_ddr4_ck_t"] # Dimm 1 Clock
set_property PACKAGE_PIN H38 [get_ports "m0_ddr4_cs_n[0]"] # Dimm 1 Active Low Chip Select0
#set_property PACKAGE_PIN H34 [get_ports "m0_ddr4_cs_n[1]"] # Dimm 1 Active Low Chip Select1
set_property PACKAGE_PIN A28 [get_ports "m0_ddr4_dq[0]"] # Dimm 1 Data pin 0
set_property PACKAGE_PIN B28 [get_ports "m0_ddr4_dq[1]"] # Dimm 1 Data pin 10
set_property PACKAGE_PIN C32 [get_ports "m0_ddr4_dq[10]"] # Dimm 1 Data pin 11
set_property PACKAGE_PIN D32 [get_ports "m0_ddr4_dq[11]"] # Dimm 1 Data pin 12
set_property PACKAGE_PIN E33 [get_ports "m0_ddr4_dq[12]"] # Dimm 1 Data pin 13
set_property PACKAGE_PIN F33 [get_ports "m0_ddr4_dq[13]"] # Dimm 1 Data pin 14
set_property PACKAGE_PIN E29 [get_ports "m0_ddr4_dq[14]"] # Dimm 1 Data pin 15
set_property PACKAGE_PIN F29 [get_ports "m0_ddr4_dq[15]"] # Dimm 1 Data pin 16
set_property PACKAGE_PIN F30 [get_ports "m0_ddr4_dq[16]"] # Dimm 1 Data pin 17
set_property PACKAGE_PIN G30 [get_ports "m0_ddr4_dq[17]"] # Dimm 1 Data pin 18
set_property PACKAGE_PIN F31 [get_ports "m0_ddr4_dq[18]"] # Dimm 1 Data pin 19
set_property PACKAGE_PIN G31 [get_ports "m0_ddr4_dq[19]"] # Dimm 1 Data pin 1
set_property PACKAGE_PIN A30 [get_ports "m0_ddr4_dq[2]"] # Dimm 1 Data pin 20
set_property PACKAGE_PIN G32 [get_ports "m0_ddr4_dq[20]"] # Dimm 1 Data pin 21
set_property PACKAGE_PIN H32 [get_ports "m0_ddr4_dq[21]"] # Dimm 1 Data pin 22
set_property PACKAGE_PIN H30 [get_ports "m0_ddr4_dq[22]"] # Dimm 1 Data pin 23
set_property PACKAGE_PIN H29 [get_ports "m0_ddr4_dq[23]"] # Dimm 1 Data pin 24
set_property PACKAGE_PIN J29 [get_ports "m0_ddr4_dq[24]"] # Dimm 1 Data pin 25
set_property PACKAGE_PIN K29 [get_ports "m0_ddr4_dq[25]"] # Dimm 1 Data pin 26
set_property PACKAGE_PIN J31 [get_ports "m0_ddr4_dq[26]"] # Dimm 1 Data pin 27
set_property PACKAGE_PIN J30 [get_ports "m0_ddr4_dq[27]"] # Dimm 1 Data pin 28
set_property PACKAGE_PIN K31 [get_ports "m0_ddr4_dq[28]"] # Dimm 1 Data pin 29
set_property PACKAGE_PIN L31 [get_ports "m0_ddr4_dq[29]"] # Dimm 1 Data pin 2
set_property PACKAGE_PIN A29 [get_ports "m0_ddr4_dq[3]"] # Dimm 1 Data pin 30
set_property PACKAGE_PIN L30 [get_ports "m0_ddr4_dq[30]"] # Dimm 1 Data pin 31
set_property PACKAGE_PIN L29 [get_ports "m0_ddr4_dq[31]"] # Dimm 1 Data pin 32
set_property PACKAGE_PIN A40 [get_ports "m0_ddr4_dq[32]"] # Dimm 1 Data pin 33
set_property PACKAGE_PIN A39 [get_ports "m0_ddr4_dq[33]"] # Dimm 1 Data pin 34
set_property PACKAGE_PIN B42 [get_ports "m0_ddr4_dq[34]"] # Dimm 1 Data pin 35
set_property PACKAGE_PIN B41 [get_ports "m0_ddr4_dq[35]"] # Dimm 1 Data pin 36
set_property PACKAGE_PIN D41 [get_ports "m0_ddr4_dq[36]"] # Dimm 1 Data pin 37
set_property PACKAGE_PIN E41 [get_ports "m0_ddr4_dq[37]"] # Dimm 1 Data pin 38
set_property PACKAGE_PIN C40 [get_ports "m0_ddr4_dq[38]"] # Dimm 1 Data pin 39
set_property PACKAGE_PIN D40 [get_ports "m0_ddr4_dq[39]"] # Dimm 1 Data pin 3
set_property PACKAGE_PIN A33 [get_ports "m0_ddr4_dq[4]"] # Dimm 1 Data pin 40
set_property PACKAGE_PIN A44 [get_ports "m0_ddr4_dq[40]"] # Dimm 1 Data pin 41
set_property PACKAGE_PIN A43 [get_ports "m0_ddr4_dq[41]"] # Dimm 1 Data pin 42
set_property PACKAGE_PIN B45 [get_ports "m0_ddr4_dq[42]"] # Dimm 1 Data pin 43
set_property PACKAGE_PIN C44 [get_ports "m0_ddr4_dq[43]"] # Dimm 1 Data pin 44
set_property PACKAGE_PIN B46 [get_ports "m0_ddr4_dq[44]"] # Dimm 1 Data pin 45
set_property PACKAGE_PIN C45 [get_ports "m0_ddr4_dq[45]"] # Dimm 1 Data pin 46
set_property PACKAGE_PIN C43 [get_ports "m0_ddr4_dq[46]"] # Dimm 1 Data pin 47
set_property PACKAGE_PIN D42 [get_ports "m0_ddr4_dq[47]"] # Dimm 1 Data pin 48
set_property PACKAGE_PIN D45 [get_ports "m0_ddr4_dq[48]"] # Dimm 1 Data pin 49
set_property PACKAGE_PIN D44 [get_ports "m0_ddr4_dq[49]"] # Dimm 1 Data pin 4
set_property PACKAGE_PIN B32 [get_ports "m0_ddr4_dq[5]"] # Dimm 1 Data pin 50
set_property PACKAGE_PIN E44 [get_ports "m0_ddr4_dq[50]"] # Dimm 1 Data pin 51
set_property PACKAGE_PIN F44 [get_ports "m0_ddr4_dq[51]"] # Dimm 1 Data pin 52
set_property PACKAGE_PIN G45 [get_ports "m0_ddr4_dq[52]"] # Dimm 1 Data pin 53
set_property PACKAGE_PIN H45 [get_ports "m0_ddr4_dq[53]"] # Dimm 1 Data pin 54
set_property PACKAGE_PIN F46 [get_ports "m0_ddr4_dq[54]"] # Dimm 1 Data pin 55
set_property PACKAGE_PIN F45 [get_ports "m0_ddr4_dq[55]"] # Dimm 1 Data pin 56
set_property PACKAGE_PIN G43 [get_ports "m0_ddr4_dq[56]"] # Dimm 1 Data pin 57
set_property PACKAGE_PIN H43 [get_ports "m0_ddr4_dq[57]"] # Dimm 1 Data pin 58
set_property PACKAGE_PIN G42 [get_ports "m0_ddr4_dq[58]"] # Dimm 1 Data pin 59
set_property PACKAGE_PIN G41 [get_ports "m0_ddr4_dq[59]"] # Dimm 1 Data pin 5
set_property PACKAGE_PIN C29 [get_ports "m0_ddr4_dq[6]"] # Dimm 1 Data pin 60
set_property PACKAGE_PIN J41 [get_ports "m0_ddr4_dq[60]"] # Dimm 1 Data pin 61
set_property PACKAGE_PIN J40 [get_ports "m0_ddr4_dq[61]"] # Dimm 1 Data pin 62
set_property PACKAGE_PIN H42 [get_ports "m0_ddr4_dq[62]"] # Dimm 1 Data pin 63
set_property PACKAGE_PIN J42 [get_ports "m0_ddr4_dq[63]"] # Dimm 1 Data pin 64
set_property PACKAGE_PIN J37 [get_ports "m0_ddr4_dq[64]"] # Dimm 1 Data pin 65
set_property PACKAGE_PIN K37 [get_ports "m0_ddr4_dq[65]"] # Dimm 1 Data pin 66
set_property PACKAGE_PIN K34 [get_ports "m0_ddr4_dq[66]"] # Dimm 1 Data pin 67
set_property PACKAGE_PIN L34 [get_ports "m0_ddr4_dq[67]"] # Dimm 1 Data pin 68
set_property PACKAGE_PIN J36 [get_ports "m0_ddr4_dq[68]"] # Dimm 1 Data pin 69
set_property PACKAGE_PIN K36 [get_ports "m0_ddr4_dq[69]"] # Dimm 1 Data pin 6
set_property PACKAGE_PIN C28 [get_ports "m0_ddr4_dq[7]"] # Dimm 1 Data pin 70
set_property PACKAGE_PIN K39 [get_ports "m0_ddr4_dq[70]"] # Dimm 1 Data pin 71
set_property PACKAGE_PIN L39 [get_ports "m0_ddr4_dq[71]"] # Dimm 1 Data pin 7
set_property PACKAGE_PIN D29 [get_ports "m0_ddr4_dq[8]"] # Dimm 1 Data pin 8
set_property PACKAGE_PIN E28 [get_ports "m0_ddr4_dq[9]"] # Dimm 1 Data pin 9
set_property PACKAGE_PIN A31 [get_ports "m0_ddr4_dqs_c[0]"] # Dimm 1 Data Strobe 0
set_property PACKAGE_PIN B31 [get_ports "m0_ddr4_dqs_c[1]"] # Dimm 1 Data Strobe 10
set_property PACKAGE_PIN A46 [get_ports "m0_ddr4_dqs_c[10]"] # Dimm 1 Data Strobe 11
set_property PACKAGE_PIN E43 [get_ports "m0_ddr4_dqs_c[11]"] # Dimm 1 Data Strobe 12
set_property PACKAGE_PIN D46 [get_ports "m0_ddr4_dqs_c[12]"] # Dimm 1 Data Strobe 13
set_property PACKAGE_PIN H44 [get_ports "m0_ddr4_dqs_c[13]"] # Dimm 1 Data Strobe 14
set_property PACKAGE_PIN G40 [get_ports "m0_ddr4_dqs_c[14]"] # Dimm 1 Data Strobe 15
set_property PACKAGE_PIN K42 [get_ports "m0_ddr4_dqs_c[15]"] # Dimm 1 Data Strobe 16
set_property PACKAGE_PIN K38 [get_ports "m0_ddr4_dqs_c[16]"] # Dimm 1 Data Strobe 17
set_property PACKAGE_PIN L36 [get_ports "m0_ddr4_dqs_c[17]"] # Dimm 1 Data Strobe 1
set_property PACKAGE_PIN D31 [get_ports "m0_ddr4_dqs_c[2]"] # Dimm 1 Data Strobe 2
set_property PACKAGE_PIN E32 [get_ports "m0_ddr4_dqs_c[3]"] # Dimm 1 Data Strobe 3
set_property PACKAGE_PIN F28 [get_ports "m0_ddr4_dqs_c[4]"] # Dimm 1 Data Strobe 4
set_property PACKAGE_PIN G33 [get_ports "m0_ddr4_dqs_c[5]"] # Dimm 1 Data Strobe 5
set_property PACKAGE_PIN J32 [get_ports "m0_ddr4_dqs_c[6]"] # Dimm 1 Data Strobe
set_property PACKAGE_PIN K33 [get_ports "m0_ddr4_dqs_c[7]"] # Dimm 1 Data Strobe 7
set_property PACKAGE_PIN A41 [get_ports "m0_ddr4_dqs_c[8]"] # Dimm 1 Data Strobe 8
set_property PACKAGE_PIN F41 [get_ports "m0_ddr4_dqs_c[9]"] # Dimm 1 Data Strobe 9
set_property PACKAGE_PIN B30 [get_ports "m0_ddr4_dqs_t[0]"] # Dimm 1 Data Strobe 0
set_property PACKAGE_PIN C30 [get_ports "m0_ddr4_dqs_t[1]"] # Dimm 1 Data Strobe 10
set_property PACKAGE_PIN A45 [get_ports "m0_ddr4_dqs_t[10]"] # Dimm 1 Data Strobe 11
set_property PACKAGE_PIN E42 [get_ports "m0_ddr4_dqs_t[11]"] # Dimm 1 Data Strobe 12
set_property PACKAGE_PIN E46 [get_ports "m0_ddr4_dqs_t[12]"] # Dimm 1 Data Strobe 13
set_property PACKAGE_PIN J44 [get_ports "m0_ddr4_dqs_t[13]"] # Dimm 1 Data Strobe 14
set_property PACKAGE_PIN H40 [get_ports "m0_ddr4_dqs_t[14]"] # Dimm 1 Data Strobe 15
set_property PACKAGE_PIN K41 [get_ports "m0_ddr4_dqs_t[15]"] # Dimm 1 Data Strobe 16
set_property PACKAGE_PIN L38 [get_ports "m0_ddr4_dqs_t[16]"] # Dimm 1 Data Strobe 17
set_property PACKAGE_PIN L35 [get_ports "m0_ddr4_dqs_t[17]"] # Dimm 1 Data Strobe 1
set_property PACKAGE_PIN D30 [get_ports "m0_ddr4_dqs_t[2]"] # Dimm 1 Data Strobe 2
set_property PACKAGE_PIN E31 [get_ports "m0_ddr4_dqs_t[3]"] # Dimm 1 Data Strobe 3
set_property PACKAGE_PIN G28 [get_ports "m0_ddr4_dqs_t[4]"] # Dimm 1 Data Strobe 4
set_property PACKAGE_PIN H33 [get_ports "m0_ddr4_dqs_t[5]"] # Dimm 1 Data Strobe 5
set_property PACKAGE_PIN K32 [get_ports "m0_ddr4_dqs_t[6]"] # Dimm 1 Data Strobe 6
set_property PACKAGE_PIN L33 [get_ports "m0_ddr4_dqs_t[7]"] # Dimm 1 Data Strobe 7
set_property PACKAGE_PIN B40 [get_ports "m0_ddr4_dqs_t[8]"] # Dimm 1 Data Strobe 8
set_property PACKAGE_PIN F40 [get_ports "m0_ddr4_dqs_t[9]"] # Dimm 1 Data Strobe 9
set_property PACKAGE_PIN F39 [get_ports "m0_ddr4_odt[0]"] # Dimm 1 On Die Termination 0
#set_property PACKAGE_PIN G37 [get_ports "m0_ddr4_odt[1]"] # Dimm 1 On Die Termination 1
set_property PACKAGE_PIN F38 [get_ports "m0_ddr4_parity"] # Dimm 1 Parity
set_property PACKAGE_PIN J39 [get_ports "m0_ddr4_reset_n"] # Dimm 1 Active Low Reset
### RDIMM 2
set_property PACKAGE_PIN BM42 [get_ports "m1_ddr4_act_n"] # Dimm 2 Activation Command Low
set_property PACKAGE_PIN BJ41 [get_ports "m1_ddr4_adr[0]"] # Dimm 2 Address 0
set_property PACKAGE_PIN BK41 [get_ports "m1_ddr4_adr[1]"] # Dimm 2 Address 10
set_property PACKAGE_PIN BF46 [get_ports "m1_ddr4_adr[10]"] # Dimm 2 Address 11
set_property PACKAGE_PIN BF42 [get_ports "m1_ddr4_adr[11]"] # Dimm 2 Address 12
set_property PACKAGE_PIN BF43 [get_ports "m1_ddr4_adr[12]"] # Dimm 2 Address 13
set_property PACKAGE_PIN BC42 [get_ports "m1_ddr4_adr[13]"] # Dimm 2 Address 14
set_property PACKAGE_PIN BD42 [get_ports "m1_ddr4_adr[14]"] # Dimm 2 Address 15
set_property PACKAGE_PIN BE43 [get_ports "m1_ddr4_adr[15]"] # Dimm 2 Address 16
set_property PACKAGE_PIN BE44 [get_ports "m1_ddr4_adr[16]"] # Dimm 2 Address 17
#set_property PACKAGE_PIN BF41 [get_ports "m1_ddr4_adr[17]"] # Dimm 2 Address 1
set_property PACKAGE_PIN BG42 [get_ports "m1_ddr4_adr[2]"] # Dimm 2 Address 2
set_property PACKAGE_PIN BG43 [get_ports "m1_ddr4_adr[3]"] # Dimm 2 Address 3
set_property PACKAGE_PIN BG44 [get_ports "m1_ddr4_adr[4]"] # Dimm 2 Address 4
set_property PACKAGE_PIN BG45 [get_ports "m1_ddr4_adr[5]"] # Dimm 2 Address 5
set_property PACKAGE_PIN BH41 [get_ports "m1_ddr4_adr[6]"] # Dimm 2 Address 6
set_property PACKAGE_PIN BD41 [get_ports "m1_ddr4_adr[7]"] # Dimm 2 Address 7
set_property PACKAGE_PIN BE41 [get_ports "m1_ddr4_adr[8]"] # Dimm 2 Address 8
set_property PACKAGE_PIN BF45 [get_ports "m1_ddr4_adr[9]"] # Dimm 2 Address 9
#set_property PACKAGE_PIN BE45 [get_ports "m1_ddr4_alert_n"] # Dimm 2 Active Low Alert
set_property PACKAGE_PIN BH42 [get_ports "m1_ddr4_ba[0]"] # Dimm 2 Bank Address 0
set_property PACKAGE_PIN BJ42 [get_ports "m1_ddr4_ba[1]"] # Dimm 2 Bank Address 1
set_property PACKAGE_PIN BH44 [get_ports "m1_ddr4_bg[0]"] # Dimm 2 Bank Group 0
set_property PACKAGE_PIN BH45 [get_ports "m1_ddr4_bg[1]"] # Dimm 2 Bank Group 1
#set_property PACKAGE_PIN BM47 [get_ports "m1_ddr4_c[0]"] # Dimm 2 Active Low Chip Select2
#set_property PACKAGE_PIN BL45 [get_ports "m1_ddr4_c[1]"] # Dimm 2 Active Low Chip Select3
#set_property PACKAGE_PIN BE46 [get_ports "m1_ddr4_c[2]"] # Dimm 2 Die Select
#set_property PACKAGE_PIN BG33 [get_ports "m1_ddr4_c[3]"] # Dimm 2 RFU
#set_property PACKAGE_PIN BF53 [get_ports "m1_ddr4_c[4]"] # Dimm 2 RFU
set_property PACKAGE_PIN BJ46 [get_ports "m1_ddr4_ck_c"] # Dimm 2 Clock
set_property PACKAGE_PIN BL43 [get_ports "m1_ddr4_cke[0]"] # Dimm 2 Clock Enable 0
#set_property PACKAGE_PIN BK45 "5 [get_ports "m1_ddr4_cke[1]"] # Dimm 2 Clock Enable 1
set_property PACKAGE_PIN BH46 [get_ports "m1_ddr4_ck_t"] # Dimm 2 Clock
set_property PACKAGE_PIN BL46 [get_ports "m1_ddr4_cs_n[0]"] # Dimm 2 Active Low Chip Select0
#set_property PACKAGE_PIN BL42 "2 [get_ports "m1_ddr4_cs_n[1]"] # Dimm 2 Active Low Chip Select1
set_property PACKAGE_PIN BJ31 [get_ports "m1_ddr4_dq[0]"] # Dimm 2 Data Pin 0
set_property PACKAGE_PIN BH31 [get_ports "m1_ddr4_dq[1]"] # Dimm 2 Data Pin 10
set_property PACKAGE_PIN BF36 [get_ports "m1_ddr4_dq[10]"] # Dimm 2 Data Pin 11
set_property PACKAGE_PIN BF35 [get_ports "m1_ddr4_dq[11]"] # Dimm 2 Data Pin 12
set_property PACKAGE_PIN BG35 [get_ports "m1_ddr4_dq[12]"] # Dimm 2 Data Pin 13
set_property PACKAGE_PIN BG34 [get_ports "m1_ddr4_dq[13]"] # Dimm 2 Data Pin 14
set_property PACKAGE_PIN BJ34 [get_ports "m1_ddr4_dq[14]"] # Dimm 2 Data Pin 15
set_property PACKAGE_PIN BJ33 [get_ports "m1_ddr4_dq[15]"] # Dimm 2 Data Pin 16
set_property PACKAGE_PIN BL33 [get_ports "m1_ddr4_dq[16]"] # Dimm 2 Data Pin 17
set_property PACKAGE_PIN BK33 [get_ports "m1_ddr4_dq[17]"] # Dimm 2 Data Pin 18
set_property PACKAGE_PIN BL31 [get_ports "m1_ddr4_dq[18]"] # Dimm 2 Data Pin 19
set_property PACKAGE_PIN BK31 [get_ports "m1_ddr4_dq[19]"] # Dimm 2 Data Pin 1
set_property PACKAGE_PIN BF33 [get_ports "m1_ddr4_dq[2]"] # Dimm 2 Data Pin 20
set_property PACKAGE_PIN BM33 [get_ports "m1_ddr4_dq[20]"] # Dimm 2 Data Pin 21
set_property PACKAGE_PIN BL32 [get_ports "m1_ddr4_dq[21]"] # Dimm 2 Data Pin 22
set_property PACKAGE_PIN BP34 [get_ports "m1_ddr4_dq[22]"] # Dimm 2 Data Pin 23
set_property PACKAGE_PIN BN34 [get_ports "m1_ddr4_dq[23]"] # Dimm 2 Data Pin 24
set_property PACKAGE_PIN BP32 [get_ports "m1_ddr4_dq[24]"] # Dimm 2 Data Pin 25
set_property PACKAGE_PIN BN32 [get_ports "m1_ddr4_dq[25]"] # Dimm 2 Data Pin 26
set_property PACKAGE_PIN BM30 [get_ports "m1_ddr4_dq[26]"] # Dimm 2 Data Pin 27
set_property PACKAGE_PIN BL30 [get_ports "m1_ddr4_dq[27]"] # Dimm 2 Data Pin 28
set_property PACKAGE_PIN BP31 [get_ports "m1_ddr4_dq[28]"] # Dimm 2 Data Pin 29
set_property PACKAGE_PIN BN31 [get_ports "m1_ddr4_dq[29]"] # Dimm 2 Data Pin 2
set_property PACKAGE_PIN BF32 [get_ports "m1_ddr4_dq[3]"] # Dimm 2 Data Pin 30
set_property PACKAGE_PIN BP29 [get_ports "m1_ddr4_dq[30]"] # Dimm 2 Data Pin 31
set_property PACKAGE_PIN BP28 [get_ports "m1_ddr4_dq[31]"] # Dimm 2 Data Pin 32
set_property PACKAGE_PIN BE51 [get_ports "m1_ddr4_dq[32]"] # Dimm 2 Data Pin 33
set_property PACKAGE_PIN BD51 [get_ports "m1_ddr4_dq[33]"] # Dimm 2 Data Pin 34
set_property PACKAGE_PIN BE50 [get_ports "m1_ddr4_dq[34]"] # Dimm 2 Data Pin 35
set_property PACKAGE_PIN BE49 [get_ports "m1_ddr4_dq[35]"] # Dimm 2 Data Pin 36
set_property PACKAGE_PIN BF52 [get_ports "m1_ddr4_dq[36]"] # Dimm 2 Data Pin 37
set_property PACKAGE_PIN BF51 [get_ports "m1_ddr4_dq[37]"] # Dimm 2 Data Pin 38
set_property PACKAGE_PIN BG50 [get_ports "m1_ddr4_dq[38]"] # Dimm 2 Data Pin 39
set_property PACKAGE_PIN BF50 [get_ports "m1_ddr4_dq[39]"] # Dimm 2 Data Pin 3
set_property PACKAGE_PIN BG32 [get_ports "m1_ddr4_dq[4]"] # Dimm 2 Data Pin 40
set_property PACKAGE_PIN BE54 [get_ports "m1_ddr4_dq[40]"] # Dimm 2 Data Pin 41
set_property PACKAGE_PIN BE53 [get_ports "m1_ddr4_dq[41]"] # Dimm 2 Data Pin 42
set_property PACKAGE_PIN BG54 [get_ports "m1_ddr4_dq[42]"] # Dimm 2 Data Pin 43
set_property PACKAGE_PIN BG53 [get_ports "m1_ddr4_dq[43]"] # Dimm 2 Data Pin 44
set_property PACKAGE_PIN BK54 [get_ports "m1_ddr4_dq[44]"] # Dimm 2 Data Pin 45
set_property PACKAGE_PIN BK53 [get_ports "m1_ddr4_dq[45]"] # Dimm 2 Data Pin 46
set_property PACKAGE_PIN BH52 [get_ports "m1_ddr4_dq[46]"] # Dimm 2 Data Pin 47
set_property PACKAGE_PIN BG52 [get_ports "m1_ddr4_dq[47]"] # Dimm 2 Data Pin 48
set_property PACKAGE_PIN BH50 [get_ports "m1_ddr4_dq[48]"] # Dimm 2 Data Pin 49
set_property PACKAGE_PIN BH49 [get_ports "m1_ddr4_dq[49]"] # Dimm 2 Data Pin 4
set_property PACKAGE_PIN BF31 [get_ports "m1_ddr4_dq[5]"] # Dimm 2 Data Pin 50
set_property PACKAGE_PIN BJ51 [get_ports "m1_ddr4_dq[50]"] # Dimm 2 Data Pin 51
set_property PACKAGE_PIN BH51 [get_ports "m1_ddr4_dq[51]"] # Dimm 2 Data Pin 52
set_property PACKAGE_PIN BJ49 [get_ports "m1_ddr4_dq[52]"] # Dimm 2 Data Pin 53
set_property PACKAGE_PIN BJ48 [get_ports "m1_ddr4_dq[53]"] # Dimm 2 Data Pin 54
set_property PACKAGE_PIN BK51 [get_ports "m1_ddr4_dq[54]"] # Dimm 2 Data Pin 55
set_property PACKAGE_PIN BK50 [get_ports "m1_ddr4_dq[55]"] # Dimm 2 Data Pin 56
set_property PACKAGE_PIN BL53 [get_ports "m1_ddr4_dq[56]"] # Dimm 2 Data Pin 57
set_property PACKAGE_PIN BL52 [get_ports "m1_ddr4_dq[57]"] # Dimm 2 Data Pin 58
set_property PACKAGE_PIN BM52 [get_ports "m1_ddr4_dq[58]"] # Dimm 2 Data Pin 59
set_property PACKAGE_PIN BL51 [get_ports "m1_ddr4_dq[59]"] # Dimm 2 Data Pin 5
set_property PACKAGE_PIN BH30 [get_ports "m1_ddr4_dq[6]"] # Dimm 2 Data Pin 60
set_property PACKAGE_PIN BN49 [get_ports "m1_ddr4_dq[60]"] # Dimm 2 Data Pin 61
set_property PACKAGE_PIN BM48 [get_ports "m1_ddr4_dq[61]"] # Dimm 2 Data Pin 62
set_property PACKAGE_PIN BN51 [get_ports "m1_ddr4_dq[62]"] # Dimm 2 Data Pin 63
set_property PACKAGE_PIN BN50 [get_ports "m1_ddr4_dq[63]"] # Dimm 2 Data Pin 64
set_property PACKAGE_PIN BN45 [get_ports "m1_ddr4_dq[64]"] # Dimm 2 Data Pin 65
set_property PACKAGE_PIN BM45 [get_ports "m1_ddr4_dq[65]"] # Dimm 2 Data Pin 66
set_property PACKAGE_PIN BN44 [get_ports "m1_ddr4_dq[66]"] # Dimm 2 Data Pin 67
set_property PACKAGE_PIN BM44 [get_ports "m1_ddr4_dq[67]"] # Dimm 2 Data Pin 68
set_property PACKAGE_PIN BP44 [get_ports "m1_ddr4_dq[68]"] # Dimm 2 Data Pin 69
set_property PACKAGE_PIN BP43 [get_ports "m1_ddr4_dq[69]"] # Dimm 2 Data Pin 6
set_property PACKAGE_PIN BH29 [get_ports "m1_ddr4_dq[7]"] # Dimm 2 Data Pin 70
set_property PACKAGE_PIN BP47 [get_ports "m1_ddr4_dq[70]"] # Dimm 2 Data Pin 71
set_property PACKAGE_PIN BN47 [get_ports "m1_ddr4_dq[71]"] # Dimm 2 Data Pin 7
set_property PACKAGE_PIN BH35 [get_ports "m1_ddr4_dq[8]"] # Dimm 2 Data Pin 8
set_property PACKAGE_PIN BH34 [get_ports "m1_ddr4_dq[9]"] # Dimm 2 Data Pin 9
set_property PACKAGE_PIN BK30 [get_ports "m1_ddr4_dqs_c[0]"] # Dimm 2 Data Strobe 0
set_property PACKAGE_PIN BG30 [get_ports "m1_ddr4_dqs_c[1]"] # Dimm 2 Data Strobe 10
set_property PACKAGE_PIN BJ54 [get_ports "m1_ddr4_dqs_c[10]"] # Dimm 2 Data Strobe 11
set_property PACKAGE_PIN BJ53 [get_ports "m1_ddr4_dqs_c[11]"] # Dimm 2 Data Strobe 12
set_property PACKAGE_PIN BJ47 [get_ports "m1_ddr4_dqs_c[12]"] # Dimm 2 Data Strobe 13
set_property PACKAGE_PIN BK49 [get_ports "m1_ddr4_dqs_c[13]"] # Dimm 2 Data Strobe 14
set_property PACKAGE_PIN BM50 [get_ports "m1_ddr4_dqs_c[14]"] # Dimm 2 Data Strobe 15
set_property PACKAGE_PIN BP49 [get_ports "m1_ddr4_dqs_c[15]"] # Dimm 2 Data Strobe 16
set_property PACKAGE_PIN BP46 [get_ports "m1_ddr4_dqs_c[16]"] # Dimm 2 Data Strobe 17
set_property PACKAGE_PIN BP42 [get_ports "m1_ddr4_dqs_c[17]"] # Dimm 2 Data Strobe 1
set_property PACKAGE_PIN BK35 [get_ports "m1_ddr4_dqs_c[2]"] # Dimm 2 Data Strobe 2
set_property PACKAGE_PIN BJ32 [get_ports "m1_ddr4_dqs_c[3]"] # Dimm 2 Data Strobe 3
set_property PACKAGE_PIN BM35 [get_ports "m1_ddr4_dqs_c[4]"] # Dimm 2 Data Strobe 4
set_property PACKAGE_PIN BN35 [get_ports "m1_ddr4_dqs_c[5]"] # Dimm 2 Data Strobe 5
set_property PACKAGE_PIN BN30 [get_ports "m1_ddr4_dqs_c[6]"] # Dimm 2 Data Strobe 6
set_property PACKAGE_PIN BM29 [get_ports "m1_ddr4_dqs_c[7]"] # Dimm 2 Data Strobe 7
set_property PACKAGE_PIN BF48 [get_ports "m1_ddr4_dqs_c[8]"] # Dimm 2 Data Strobe 8
set_property PACKAGE_PIN BG49 [get_ports "m1_ddr4_dqs_c[9]"] # Dimm 2 Data Strobe 9
set_property PACKAGE_PIN BJ29 [get_ports "m1_ddr4_dqs_t[0]"] # Dimm 2 Data Strobe 0
set_property PACKAGE_PIN BG29 [get_ports "m1_ddr4_dqs_t[1]"] # Dimm 2 Data Strobe 10
set_property PACKAGE_PIN BH54 [get_ports "m1_ddr4_dqs_t[10]"] # Dimm 2 Data Strobe 11
set_property PACKAGE_PIN BJ52 [get_ports "m1_ddr4_dqs_t[11]"] # Dimm 2 Data Strobe 12
set_property PACKAGE_PIN BH47 [get_ports "m1_ddr4_dqs_t[12]"] # Dimm 2 Data Strobe 13
set_property PACKAGE_PIN BK48 [get_ports "m1_ddr4_dqs_t[13]"] # Dimm 2 Data Strobe 14
set_property PACKAGE_PIN BM49 [get_ports "m1_ddr4_dqs_t[14]"] # Dimm 2 Data Strobe 15
set_property PACKAGE_PIN BP48 [get_ports "m1_ddr4_dqs_t[15]"] # Dimm 2 Data Strobe 16
set_property PACKAGE_PIN BN46 [get_ports "m1_ddr4_dqs_t[16]"] # Dimm 2 Data Strobe 17
set_property PACKAGE_PIN BN42 [get_ports "m1_ddr4_dqs_t[17]"] # Dimm 2 Data Strobe 1
set_property PACKAGE_PIN BK34 [get_ports "m1_ddr4_dqs_t[2]"] # Dimm 2 Data Strobe 2
set_property PACKAGE_PIN BH32 [get_ports "m1_ddr4_dqs_t[3]"] # Dimm 2 Data Strobe 3
set_property PACKAGE_PIN BL35 [get_ports "m1_ddr4_dqs_t[4]"] # Dimm 2 Data Strobe 4
set_property PACKAGE_PIN BM34 [get_ports "m1_ddr4_dqs_t[5]"] # Dimm 2 Data Strobe 5
set_property PACKAGE_PIN BN29 [get_ports "m1_ddr4_dqs_t[6]"] # Dimm 2 Data Strobe 6
set_property PACKAGE_PIN BM28 [get_ports "m1_ddr4_dqs_t[7]"] # Dimm 2 Data Strobe 7
set_property PACKAGE_PIN BF47 [get_ports "m1_ddr4_dqs_t[8]"] # Dimm 2 Data Strobe 8
set_property PACKAGE_PIN BG48 [get_ports "m1_ddr4_dqs_t[9]"] # Dimm 2 Data Strobe 9
set_property PACKAGE_PIN BK46 [get_ports "m1_ddr4_odt[0]"] # Dimm 2 On Die Termination 0
#set_property PACKAGE_PIN BJ43 [get_ports "m1_ddr4_odt[1]"] # Dimm 2 On Die Termination 1
set_property PACKAGE_PIN BJ44 [get_ports "m1_ddr4_parity"] # Dimm 2 Parity
set_property PACKAGE_PIN BL47 [get_ports "m1_ddr4_reset_n"] # Dimm 2 Active Low Reset
##############################################
########## HBM Clocks ##########
##############################################
set_property PACKAGE_PIN BH27 [get_ports hbm_ref_clk_0_p] # HBM Refclk 0
set_property PACKAGE_PIN BJ27 [get_ports hbm_ref_clk_0_n]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports hbm_ref_clk_0_p]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports hbm_ref_clk_0_n]
set_property ODT RTT_48 [get_ports hbm_ref_clk_0_p]
set_property PACKAGE_PIN BH26 [get_ports hbm_ref_clk_1_p] # HBM Refclk 1
set_property PACKAGE_PIN BH25 [get_ports hbm_ref_clk_1_n]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports hbm_ref_clk_1_p]
set_property IOSTANDARD DIFF_SSTL12_DCI [get_ports hbm_ref_clk_1_n]
set_property ODT RTT_48 [get_ports hbm_ref_clk_1_p]
##############################################
########## GTY Reference Clocks ##########
##############################################
# NOTE: Period constraint represents 322/265625 MHz reference clock - Modify as necessary
set_property PACKAGE_PIN AJ15 [get_ports gty_refclk0p_i[0]] # GTY Bank 228 Refclk 0 / SI5341A CLK 3
set_property PACKAGE_PIN AJ14 [get_ports gty_refclk0n_i[0]]
create_clock -name gtrefclk0_22 -period 3.104 [get_ports gty_refclk0p_i[0]]
set_property PACKAGE_PIN AH13 [get_ports gty_refclk1p_i[0]] # GTY Bank 228 Refclk 1 / SI5341B CLK 9
set_property PACKAGE_PIN AH12 [get_ports gty_refclk1n_i[0]]
create_clock -name gtrefclk1_22 -period 3.104 [get_ports gty_refclk1p_i[0]]
set_property PACKAGE_PIN AD13 [get_ports gty_refclk0p_i[1]] # GTY Bank 229 Refclk 0 / SI5341A CLK 2
set_property PACKAGE_PIN AD12 [get_ports gty_refclk0n_i[1]]
create_clock -name gtrefclk0_23 -period 3.104 [get_ports gty_refclk0p_i[1]]
set_property PACKAGE_PIN AC15 [get_ports gty_refclk1p_i[1]] # GTY Bank 229 Refclk 1 / SI5341B CLK 8
set_property PACKAGE_PIN AC14 [get_ports gty_refclk1n_i[1]]
create_clock -name gtrefclk1_23 -period 3.104 [get_ports gty_refclk1p_i[1]]
set_property PACKAGE_PIN V13 [get_ports gty_refclk0p_i[2]] # GTY Bank 232 Refclk 0 / SI5341A CLK 1
set_property PACKAGE_PIN V12 [get_ports gty_refclk0n_i[2]]
create_clock -name gtrefclk0_26 -period 3.104 [get_ports gty_refclk0p_i[2]]
set_property PACKAGE_PIN U15 [get_ports gty_refclk1p_i[2]] # GTY Bank 232 Refclk 1 / SI5341B CLK 7
set_property PACKAGE_PIN U14 [get_ports gty_refclk1n_i[2]]
create_clock -name gtrefclk1_26 -period 3.104 [get_ports gty_refclk1p_i[2]]
set_property PACKAGE_PIN P13 [get_ports gty_refclk0p_i[3]] # GTY Bank 233 Refclk 0 / SI5341A CLK 0
set_property PACKAGE_PIN P12 [get_ports gty_refclk0n_i[3]]
create_clock -name gtrefclk0_26 -period 3.104 [get_ports gty_refclk0p_i[3]]
set_property PACKAGE_PIN M13 [get_ports gty_refclk1p_i[3]] # GTY Bank 233 Refclk 1 / SI5341 CLK 6
set_property PACKAGE_PIN M12 [get_ports gty_refclk1n_i[3]]
create_clock -name gtrefclk1_27 -period 3.104 [get_ports gty_refclk1p_i[3]]
##############################################
########## GTY QSFP Connector Pins ##########
##############################################
# NOTE: All GTY pins are automatically assigned by Vivado. Shown here for reference only.
#GTY BANK 228 QSFP4 3:0
#set_property PACKAGE_PIN AL6 [get_ports gty_rxp_i[0]] # QSFP4_RX_P_0 QSFP Port 3 Input Pin 0
#set_property PACKAGE_PIN AL5 [get_ports gty_rxn_i[0]] # QSFP4_RX_N_0
#set_property PACKAGE_PIN AK4 [get_ports gty_rxp_i[1]] # QSFP4_RX_P_1 QSFP Port 3 Input Pin 1
#set_property PACKAGE_PIN AK3 [get_ports gty_rxn_i[1]] # QSFP4_RX_N_1
#set_property PACKAGE_PIN AJ2 [get_ports gty_rxp_i[2]] # QSFP4_RX_P_2 QSFP Port 3 Input Pin 2
#set_property PACKAGE_PIN AJ1 [get_ports gty_rxn_i[2]] # QSFP4_RX_N_2
#set_property PACKAGE_PIN AH4 [get_ports gty_rxp_i[3]] # QSFP4_RX_P_3 QSFP Port 3 Input Pin 3
#set_property PACKAGE_PIN AH3 [get_ports gty_rxn_i[3]] # QSFP4_RX_N_3
#set_property PACKAGE_PIN AK9 [get_ports gty_txp_o[0]] # QSFP4_TX_P_0 QSFP Port 3 Output Pin 0
#set_property PACKAGE_PIN AK8 [get_ports gty_txn_o[0]] # QSFP4_TX_N_0
#set_property PACKAGE_PIN AJ7 [get_ports gty_txp_o[1]] # QSFP4_TX_P_1 QSFP Port 3 Output Pin 1
#set_property PACKAGE_PIN AJ6 [get_ports gty_txn_o[1]] # QSFP4_TX_N_1
#set_property PACKAGE_PIN AJ11 [get_ports gty_txp_o[2]] # QSFP4_TX_P_2 QSFP Port 3 Output Pin 2
#set_property PACKAGE_PIN AJ10 [get_ports gty_txn_o[2]] # QSFP4_TX_N_2
#set_property PACKAGE_PIN AD9 [get_ports gty_txp_o[3]] # QSFP4_TX_P_3 QSFP Port 3 Output Pin 3
#set_property PACKAGE_PIN AD8 [get_ports gty_txn_o[3]] # QSFP4_TX_N_3
#GTY BANK 230 QSFP3 3:0
#set_property PACKAGE_PIN AD4 [get_ports gty_rxp_i[4]] # QSFP3_RX_P_0 QSFP Port 1 Input Pin 0
#set_property PACKAGE_PIN AD3 [get_ports gty_rxn_i[4]] # QSFP3_RX_N_0
#set_property PACKAGE_PIN AC2 [get_ports gty_rxp_i[5]] # QSFP3_RX_P_1 QSFP Port 1 Input Pin 1
#set_property PACKAGE_PIN AC1 [get_ports gty_rxn_i[5]] # QSFP3_RX_N_1
#set_property PACKAGE_PIN AC6 [get_ports gty_rxp_i[6]] # QSFP3_RX_P_2 QSFP Port 1 Input Pin 2
#set_property PACKAGE_PIN AC5 [get_ports gty_rxn_i[6]] # QSFP3_RX_N_2
#set_property PACKAGE_PIN AB4 [get_ports gty_rxp_i[7]] # QSFP3_RX_P_3 QSFP Port 1 Input Pin 3
#set_property PACKAGE_PIN AB3 [get_ports gty_rxn_i[7]] # QSFP3_RX_N_3
#set_property PACKAGE_PIN AD9 [get_ports gty_txp_o[4]] # QSFP3_TX_P_0 QSFP Port 1 Output Pin 0
#set_property PACKAGE_PIN AD8 [get_ports gty_txn_o[4]] # QSFP3_TX_N_0
#set_property PACKAGE_PIN AC11 [get_ports gty_txp_o[5]] # QSFP3_TX_P_1 QSFP Port 1 Output Pin 1
#set_property PACKAGE_PIN AC10 [get_ports gty_txn_o[5]] # QSFP3_TX_N_1
#set_property PACKAGE_PIN AB9 [get_ports gty_txp_o[6]] # QSFP3_TX_P_2 QSFP Port 1 Output Pin 2
#set_property PACKAGE_PIN AB8 [get_ports gty_txn_o[6]] # QSFP3_TX_N_2
#set_property PACKAGE_PIN AA7 [get_ports gty_txp_o[7]] # QSFP3_TX_P_3 QSFP Port 1 Output Pin 3
#set_property PACKAGE_PIN AA6 [get_ports gty_txn_o[7]] # QSFP3_TX_N_3
#GTY BANK 233 QSFP2 3:0
#set_property PACKAGE_PIN R6 [get_ports gty_rxp_i[8]] # QSFP2_RX_P_0 QSFP Port 2 Input Pin 0
#set_property PACKAGE_PIN R5 [get_ports gty_rxn_i[8]] # QSFP2_RX_N_0
#set_property PACKAGE_PIN P4 [get_ports gty_rxp_i[9]] # QSFP2_RX_P_1 QSFP Port 2 Input Pin 1
#set_property PACKAGE_PIN P3 [get_ports gty_rxn_i[9]] # QSFP2_RX_N_1
#set_property PACKAGE_PIN N2 [get_ports gty_rxp_i[10]] # QSFP2_RX_P_2 QSFP Port 2 Input Pin 2
#set_property PACKAGE_PIN N1 [get_ports gty_rxn_i[10]] # QSFP2_RX_N_2
#set_property PACKAGE_PIN M4 [get_ports gty_rxp_i[11]] # QSFP2_RX_P_3 QSFP Port 2 Input Pin 3
#set_property PACKAGE_PIN M3 [get_ports gty_rxn_i[11] # QSFP2_RX_P_3
#set_property PACKAGE_PIN P9 [get_ports gty_txp_o[8]] # QSFP2_TX_P_0 QSFP Port 2 Output Pin 0
#set_property PACKAGE_PIN P8 [get_ports gty_txn_o[8]] # QSFP2_TX_N_0
#set_property PACKAGE_PIN N7 [get_ports gty_txp_o[9]] # QSFP2_TX_P_1 QSFP Port 2 Output Pin 1
#set_property PACKAGE_PIN N6 [get_ports gty_txn_o[9]] # QSFP2_TX_N_1
#set_property PACKAGE_PIN N11 [get_ports gty_txp_o[10]] # QSFP2_TX_P_2 QSFP Port 2 Output Pin 2
#set_property PACKAGE_PIN N10 [get_ports gty_txn_o[10]] # QSFP2_TX_N_2
#set_property PACKAGE_PIN M9 [get_ports gty_txp_o[11]] # QSFP2_TX_P_3 QSFP Port 2 Output Pin 3
#set_property PACKAGE_PIN M8 [get_ports gty_txn_o[11]] # QSFP2_TX_N_3
#GTY BANK 235 QSFP1 3:0
#set_property PACKAGE_PIN G2 [get_ports gty_rxp_i[12]] # QSFP1_RX_P_0 QSFP Port 0 Input Pin 0
#set_property PACKAGE_PIN G1 [get_ports gty_rxn_i[12]] # QSFP1_RX_N_0
#set_property PACKAGE_PIN F4 [get_ports gty_rxp_i[13]] # QSFP1_RX_P_1 QSFP Port 0 Input Pin 1
#set_property PACKAGE_PIN F3 [get_ports gty_rxn_i[13]] # QSFP1_RX_N_1
#set_property PACKAGE_PIN E2 [get_ports gty_rxp_i[14]] # QSFP1_RX_P_2 QSFP Port 0 Input Pin 2
#set_property PACKAGE_PIN E1 [get_ports gty_rxn_i[14]] # QSFP1_RX_N_2
#set_property PACKAGE_PIN D4 [get_ports gty_rxp_i[15]] # QSFP1_RX_P_3 QSFP Port 0 Input Pin 3
#set_property PACKAGE_PIN D3 [get_ports gty_rxn_i[15]] # QSFP1_RX_P_3
#set_property PACKAGE_PIN G7 [get_ports gty_txp_o[12]] # QSFP1_TX_P_0 QSFP Port 0 Output Pin 0
#set_property PACKAGE_PIN G6 [get_ports gty_txn_o[12]] # QSFP1_TX_N_0
#set_property PACKAGE_PIN E7 [get_ports gty_txp_o[13]] # QSFP1_TX_P_1 QSFP Port 0 Output Pin 1
#set_property PACKAGE_PIN E6 [get_ports gty_txn_o[13]] # QSFP1_TX_N_1
#set_property PACKAGE_PIN C7 [get_ports gty_txp_o[14]] # QSFP1_TX_P_2 QSFP Port 0 Output Pin 2
#set_property PACKAGE_PIN C6 [get_ports gty_txn_o[14]] # QSFP1_TX_N_2
#set_property PACKAGE_PIN A6 [get_ports gty_txp_o[15]] # QSFP1_TX_P_3 QSFP Port 0 Output Pin 3
#set_property PACKAGE_PIN A5 [get_ports gty_txn_o[15]] # QSFP1_TX_N_3
##############################################
########## GTY SAS Reference Clocks ##########
##############################################
# NOTE: Clock periods below assume a 322.265625 MHz clock, please adjust as necessary based on your application
set_property PACKAGE_PIN AN40 [get_ports gty_sas_refclk0p_i[0]] # GTY Bank 120 SAS 2 OSC 1
set_property PACKAGE_PIN AN41 [get_ports gty_sas_refclk0n_i[0]]
create_clock -name gtrefclk0_1 -period 3.104 [get_ports gty_sas_refclk0p_i[0]]
set_property PACKAGE_PIN AM42 [get_ports gty_sas_refclk1p_i[0]] # GTY Bank 120 SAS 2 CLK 0
set_property PACKAGE_PIN AM43 [get_ports gty_sas_refclk1n_i[0]]
create_clock -name gtrefclk1_1 -period 3.104 [get_ports gty_sas_refclk1p_i[0]]
set_property PACKAGE_PIN AL40 [get_ports gty_sas_refclk0p_i[1]] # GTY Bank 121 SAS 2 OSC 0
set_property PACKAGE_PIN AL41 [get_ports gty_sas_refclk0n_i[1]]
create_clock -name gtrefclk0_3 -period 3.104 [get_ports gty_sas_refclk0p_i[1]]
set_property PACKAGE_PIN AK42 [get_ports gty_sas_refclk1p_i[1]] # GTY Bank 121 SAS 2 CLK 1
set_property PACKAGE_PIN AK43 [get_ports gty_sas_refclk1n_i[1]]
create_clock -name gtrefclk1_3 -period 3.104 [get_ports gty_sas_refclk1p_i[1]]
set_property PACKAGE_PIN AD42 [get_ports gty_sas_refclk0p_i[2]] # GTY Bank 129 SAS 1 OSC 0
set_property PACKAGE_PIN AD43 [get_ports gty_sas_refclk0n_i[2]]
create_clock -name gtrefclk0_6 -period 3.104 [get_ports gty_sas_refclk0p_i[2]]
set_property PACKAGE_PIN AC40 [get_ports gty_sas_refclk1p_i[2]] # GTY Bank 129 SAS 1 CLK 0
set_property PACKAGE_PIN AC41 [get_ports gty_sas_refclk1n_i[2]]
create_clock -name gtrefclk1_6 -period 3.104 [get_ports gty_sas_refclk1p_i[2]]
set_property PACKAGE_PIN V42 [get_ports gty_sas_refclk0p_i[3]] # GTY Bank 133 SAS 1 OSC 1
set_property PACKAGE_PIN V43 [get_ports gty_sas_refclk0n_i[3]]
create_clock -name gtrefclk0_8 -period 3.104 [get_ports gty_sas_refclk0p_i[3]]
set_property PACKAGE_PIN U40 [get_ports gty_sas_refclk1p_i[3]] # GTY Bank 133 SAS 1 CLK 1
set_property PACKAGE_PIN U41 [get_ports gty_sas_refclk1n_i[3]]
create_clock -name gtrefclk1_8 -period 3.104 [get_ports gty_sas_refclk1p_i[3]]
##############################################
########## GTY SAS Pins ##########
##############################################
# NOTE: All GTY pins are automatically assigned by Vivado. Shown here for reference only.
#GTY BANK 126 SAS 2 3:0
#set_property PACKAGE_PIN AU53 [get_ports gty_sas_rxp_i[0]] # SAS2_RX_P_0
#set_property PACKAGE_PIN AU54 [get_ports gty_sas_rxn_i[0]] # SAS2_RX_N_0
#set_property PACKAGE_PIN AT51 [get_ports gty_sas_rxp_i[1]] # SAS2_RX_P_1
#set_property PACKAGE_PIN AT52 [get_ports gty_sas_rxn_i[1]] # SAS2_RX_N_1
#set_property PACKAGE_PIN AR53 [get_ports gty_sas_rxp_i[2]] # SAS2_RX_P_2
#set_property PACKAGE_PIN AR54 [get_ports gty_sas_rxn_i[2]] # SAS2_RX_N_2
#set_property PACKAGE_PIN AP51 [get_ports gty_sas_rxp_i[3]] # SAS2_RX_P_3
#set_property PACKAGE_PIN AP52 [get_ports gty_sas_rxn_i[3]] # SAS2_RX_P_3
#set_property PACKAGE_PIN AU48 [get_ports gty_sas_txp_o[0]] # SAS2_TX_P_0
#set_property PACKAGE_PIN AU49 [get_ports gty_sas_txn_o[0]] # SAS2_TX_N_0
#set_property PACKAGE_PIN AT46 [get_ports gty_sas_txp_o[1]] # SAS2_TX_P_1
#set_property PACKAGE_PIN AT47 [get_ports gty_sas_txn_o[1]] # SAS2_TX_N_1
#set_property PACKAGE_PIN AR48 [get_ports gty_sas_txp_o[2]] # SAS2_TX_P_2
#set_property PACKAGE_PIN AR49 [get_ports gty_sas_txn_o[2]] # SAS2_TX_N_2
#set_property PACKAGE_PIN AR44 [get_ports gty_sas_txp_o[3]] # SAS2_TX_P_3
#set_property PACKAGE_PIN AR45 [get_ports gty_sas_txn_o[3]] # SAS2_TX_N_3
#GTY BANK 127 SAS 2 7:4
#set_property PACKAGE_PIN AN53 [get_ports gty_sas_rxp_i[4]] # SAS2_RX_P_4
#set_property PACKAGE_PIN AN54 [get_ports gty_sas_rxn_i[4]] # SAS2_RX_N_4
#set_property PACKAGE_PIN AN49 [get_ports gty_sas_rxp_i[5]] # SAS2_RX_P_5
#set_property PACKAGE_PIN AN50 [get_ports gty_sas_rxn_i[5]] # SAS2_RX_N_5
#set_property PACKAGE_PIN AM51 [get_ports gty_sas_rxp_i[6]] # SAS2_RX_P_6
#set_property PACKAGE_PIN AM52 [get_ports gty_sas_rxn_i[6]] # SAS2_RX_N_6
#set_property PACKAGE_PIN AL53 [get_ports gty_sas_rxp_i[7]] # SAS2_RX_P_7
#set_property PACKAGE_PIN AL54 [get_ports gty_sas_rxn_i[7]] # SAS2_RX_N_7
#set_property PACKAGE_PIN AP46 [get_ports gty_sas_txp_o[4]] # SAS2_TX_P_4
#set_property PACKAGE_PIN AP47 [get_ports gty_sas_txn_o[4]] # SAS2_TX_N_4
#set_property PACKAGE_PIN AN44 [get_ports gty_sas_txp_o[5]] # SAS2_TX_P_5
#set_property PACKAGE_PIN AN45 [get_ports gty_sas_txn_o[5]] # SAS2_TX_N_5
#set_property PACKAGE_PIN AM46 [get_ports gty_sas_txp_o[6]] # SAS2_TX_P_6
#set_property PACKAGE_PIN AM47 [get_ports gty_sas_txn_o[6]] # SAS2_TX_N_6
#set_property PACKAGE_PIN AL44 [get_ports gty_sas_txp_o[7]] # SAS2_TX_P_7
#set_property PACKAGE_PIN AL45 [get_ports gty_sas_txn_o[7]] # SAS2_TX_N_7
#GTY BANK 130 SAS 1 3:0
#set_property PACKAGE_PIN AD46 [get_ports gty_sas_rxp_i[8]] # SAS1_RX_P_0
#set_property PACKAGE_PIN AD47 [get_ports gty_sas_rxn_i[8]] # SAS1_RX_N_0
#set_property PACKAGE_PIN AC53 [get_ports gty_sas_rxp_i[9]] # SAS1_RX_P_1
#set_property PACKAGE_PIN AC54 [get_ports gty_sas_rxn_i[9]] # SAS1_RX_N_1
#set_property PACKAGE_PIN AC49 [get_ports gty_sas_rxp_i[10]] # SAS1_RX_P_2
#set_property PACKAGE_PIN AC50 [get_ports gty_sas_rxn_i[10]] # SAS1_RX_N_2
#set_property PACKAGE_PIN AB51 [get_ports gty_sas_rxp_i[11]] # SAS1_RX_P_3
#set_property PACKAGE_PIN AB52 [get_ports gty_sas_rxn_i[11]] # SAS1_RX_N_3
#set_property PACKAGE_PIN AD46 [get_ports gty_sas_txp_o[8]] # SAS1_TX_P_0
#set_property PACKAGE_PIN AD47 [get_ports gty_sas_txn_o[8]] # SAS1_TX_N_0
#set_property PACKAGE_PIN AC44 [get_ports gty_sas_txp_o[9]] # SAS1_TX_P_1
#set_property PACKAGE_PIN AC45 [get_ports gty_sas_txn_o[9]] # SAS1_TX_N_1
#set_property PACKAGE_PIN AB46 [get_ports gty_sas_txp_o[10]] # SAS1_TX_P_2
#set_property PACKAGE_PIN AB47 [get_ports gty_sas_txn_o[10]] # SAS1_TX_N_2
#set_property PACKAGE_PIN AA48 [get_ports gty_sas_txp_o[11]] # SAS1_TX_P_3
#set_property PACKAGE_PIN AA49 [get_ports gty_sas_txn_o[11]] # SAS1_TX_N_3
#GTY BANK 133 SAS 1 7:4
#set_property PACKAGE_PIN R49 [get_ports gty_sas_rxp_i[12]] # SAS1_RX_P_4
#set_property PACKAGE_PIN R50 [get_ports gty_sas_rxn_i[12]] # SAS1_RX_N_4
#set_property PACKAGE_PIN P51 [get_ports gty_sas_rxp_i[13]] # SAS1_RX_P_5
#set_property PACKAGE_PIN P52 [get_ports gty_sas_rxn_i[13]] # SAS1_RX_N_5
#set_property PACKAGE_PIN N53 [get_ports gty_sas_rxp_i[14]] # SAS1_RX_P_6
#set_property PACKAGE_PIN N54 [get_ports gty_sas_rxn_i[14]] # SAS1_RX_N_6
#set_property PACKAGE_PIN M51 [get_ports gty_sas_rxp_i[15]] # SAS1_RX_P_7
#set_property PACKAGE_PIN M52 [get_ports gty_sas_rxn_i[15]] # SAS1_RX_N_7
#set_property PACKAGE_PIN P46 [get_ports gty_sas_txp_o[12]] # SAS1_TX_P_4
#set_property PACKAGE_PIN P47 [get_ports gty_sas_txn_o[12]] # SAS1_TX_N_4
#set_property PACKAGE_PIN N48 [get_ports gty_sas_txp_o[13]] # SAS1_TX_P_5
#set_property PACKAGE_PIN N49 [get_ports gty_sas_txn_o[13]] # SAS1_TX_N_5
#set_property PACKAGE_PIN N44 [get_ports gty_sas_txp_o[14]] # SAS1_TX_P_6
#set_property PACKAGE_PIN N45 [get_ports gty_sas_txn_o[14]] # SAS1_TX_N_6
#set_property PACKAGE_PIN M46 [get_ports gty_sas_txp_o[15]] # SAS1_TX_P_7
#set_property PACKAGE_PIN M47 [get_ports gty_sas_txn_o[15]] # SAS1_TX_N_7
###############################################
########## GTY USB C Reference Clocks ##########
###############################################
# NOTE: Clock periods below assume a 322.265625 MHz clock, please adjust as necessary based on your application
set_property PACKAGE_PIN Y13 [get_ports gty_usbc_refclk0p_i[0]] # GTY Bank 230 Clk 0
set_property PACKAGE_PIN Y12 [get_ports gty_usbc_refclk0n_i[0]]
create_clock -name gtrefclk0_usbc_24 -period 3.104 [get_ports gty_usbc_refclk0p_i[0]]
set_property PACKAGE_PIN W15 [get_ports gty_usbc_refclk1p_i[0]] # GTY Bank 230 Clk 1
set_property PACKAGE_PIN W14 [get_ports gty_usbc_refclk1n_i[0]]
create_clock -name gtrefclk1_usbc_24 -period 3.104 [get_ports gty_usbc_refclk1p_i[0]]
##############################################
########## GTY USB C Pins ##########
##############################################
# NOTE: All GTY pins are automatically assigned by Vivado. Shown here for reference only.
#GTY BANK 230 USBC
#set_property PACKAGE_PIN U2 [get_ports gty_usbc_rxp_i[0]] # USBC_RX_P_1
#set_property PACKAGE_PIN U1 [get_ports gty_usbc_rxn_i[0]] # USBC_RX_N_1
#set_property PACKAGE_PIN U6 [get_ports gty_usbc_rxp_i[1]] # USBC_RX_P_2
#set_property PACKAGE_PIN U5 [get_ports gty_usbc_rxn_i[1]] # USBC_RX_N_2
#set_property PACKAGE_PIN V9 [get_ports gty_usbc_txp_i[1]] # USBC_TX_P_1
#set_property PACKAGE_PIN V8 [get_ports gty_usbc_txn_i[1]] # USBC_TX_N_1
#set_property PACKAGE_PIN U11 [get_ports gty_usbc_txp_i[2]] # USBC_TX_P_2
#set_property PACKAGE_PIN U10 [get_ports gty_usbc_txn_i[2]] # USBC_TX_N_2

View File

@ -24,7 +24,7 @@ interface if_axi_stream # (
parameter DAT_BITS = DAT_BYTS*8,
parameter CTL_BYTS = 1,
parameter CTL_BITS = CTL_BYTS*8,
parameter MOD_BITS = $clog2(DAT_BYTS)
parameter MOD_BITS = DAT_BYTS == 1 ? 1 : $clog2(DAT_BYTS)
)(
input i_clk
);
@ -38,8 +38,10 @@ interface if_axi_stream # (
logic [DAT_BITS-1:0] dat;
logic [MOD_BITS-1:0] mod;
modport sink (input val, err, sop, eop, ctl, dat, mod, i_clk, output rdy);
modport source (output val, err, sop, eop, ctl, dat, mod, input rdy, i_clk, import task reset_source());
modport sink (input val, err, sop, eop, ctl, dat, mod, i_clk, output rdy,
import function to_struct() );
modport source (output val, err, sop, eop, ctl, dat, mod, input rdy, i_clk,
import task reset_source(), import task copy_if(in), import function to_struct());
// Task to reset a source interface signals to all 0
task reset_source();
@ -51,6 +53,37 @@ interface if_axi_stream # (
ctl <= 0;
mod <= 0;
endtask
typedef struct packed {
logic val;
logic err;
logic sop;
logic eop;
logic [CTL_BITS-1:0] ctl;
logic [DAT_BITS-1:0] dat;
logic [MOD_BITS-1:0] mod;
} if_t;
function if_t to_struct();
to_struct.val = val;
to_struct.err = err;
to_struct.sop = sop;
to_struct.eop = eop;
to_struct.ctl = ctl;
to_struct.dat = dat;
to_struct.mod = mod;
endfunction
// Task to apply signals from one task to another in a clocked process
task copy_if(if_t in);
dat <= in.dat;
val <= in.val;
sop <= in.sop;
eop <= in.eop;
mod <= in.mod;
ctl <= in.ctl;
err <= in.err;
endtask
// Task used in simulation to drive data on a source interface
task automatic put_stream(input logic [common_pkg::MAX_SIM_BYTS*8-1:0] data, input integer signed len);
@ -74,6 +107,10 @@ interface if_axi_stream # (
reset_source();
endtask
task print();
$display("@ %t Interface values .val %h .sop %h .eop %h .err %h .mod 0x%h\n.dat 0x%h", $time, val, sop, eop, err, mod, dat);
endtask;
// Task used in simulation to get data from a sink interface
task automatic get_stream(ref logic [common_pkg::MAX_SIM_BYTS*8-1:0] data, ref integer signed len);
logic sop_l = 0;
@ -85,15 +122,16 @@ interface if_axi_stream # (
while (1) begin
if (val && rdy) begin
sop_l = sop_l || sop;
if (!sop_l) $warning("%m %t:WARNING, get_stream() .val without seeing .sop", $time);
if (!sop_l) begin
print();
$fatal(1, "%m %t:ERROR, get_stream() .val without seeing .sop", $time);
end
data[len*8 +: DAT_BITS] = dat;
len = len + (eop ? (mod == 0 ? DAT_BYTS : mod) : DAT_BYTS);
if (eop) break;
end
@(posedge i_clk);
end
endtask
endinterface

View File

@ -40,6 +40,13 @@ package common_pkg;
end
endtask
// Return a random vector
function [MAX_SIM_BYTS*8-1:0] random_vector(input integer unsigned in_len);
random_vector = 0;
for (int i = 0; i < in_len; i++)
random_vector[i*8 +:8] = $random();
endfunction
// Parse a string which is a file path and remove the file name (so return the directory)
function string get_file_dir(input string str);
int npos = 0;
@ -48,4 +55,5 @@ package common_pkg;
npos = i;
return str.substr(0,npos-1);
endfunction
endpackage

View File

@ -0,0 +1,46 @@
/*
A synchronizer block that can be used for clock crossings.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module synchronizer #(
parameter DAT_BITS = 1,
parameter NUM_CLKS = 2
) (
input i_clk_a,
input i_clk_b,
input [DAT_BITS-1:0] i_dat_a,
output logic [DAT_BITS-1:0] o_dat_b
);
logic [NUM_CLKS:0][DAT_BITS-1:0] dat;
always_ff @ (posedge i_clk_a) begin
dat[0] <= i_dat_a;
end
always_ff @ (posedge i_clk_b) begin
for(int i = 1; i <= NUM_CLKS; i++)
dat[i] <= dat[i-1];
end
always_comb begin
o_dat_b = dat[NUM_CLKS];
end
endmodule

View File

@ -0,0 +1,42 @@
# Find all the cdc_fifos and correctly set constraints for the rd and wr pointers that cross clock domains.
#
# Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
set cdc_fifo_instance [get_cells -hierarchical -filter { ORIG_REF_NAME =~ "cdc_fifo" || REF_NAME =~ "cdc_fifo" } ]
foreach child $cdc_fifo_instance {
set name [get_property NAME $child]
set wr_ptr_cells [get_cells -hierarchical -filter "NAME =~ $name/synchronizer_wr_ptr/* "]
set clock [get_clocks -of_objects [get_pins -filter { NAME =~ "*dat_reg[1]*C" } -of_objects $wr_ptr_cells]]
set clock_period [get_property PERIOD $clock]
set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects $wr_ptr_cells] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects $wr_ptr_cells] [expr $clock_period/2]
set_max_delay -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects $wr_ptr_cells] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects $wr_ptr_cells] -datapath_only [expr $clock_period/2]
set rd_ptr_cells [get_cells -hierarchical -filter "NAME =~ $name/synchronizer_rd_ptr/* "]
set clock [get_clocks -of_objects [get_pins -filter { NAME =~ "*dat_reg[1]*C" } -of_objects $rd_ptr_cells]]
set clock_period [get_property PERIOD $clock]
set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects $rd_ptr_cells] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects $rd_ptr_cells] [expr $clock_period/2]
set_max_delay -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects $rd_ptr_cells] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects $rd_ptr_cells] -datapath_only [expr $clock_period/2]
set all_cells [get_cells -hierarchical -filter "NAME =~ $name/* "]
set_bus_skew -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects $all_cells] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects $all_cells] [expr $clock_period/2]
set_max_delay -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects $all_cells] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects $all_cells] -datapath_only [expr $clock_period/2]
}

View File

@ -0,0 +1,188 @@
/*
Fifo used for CDC crossing.
Uses either BRAM or registers for the memory, and grey coding for the rd/wr pointers.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module cdc_fifo #(
parameter SIZE = 4, // Needs to be a power of 2
parameter DAT_BITS = 8,
parameter USE_BRAM = 0 // If using BRAM there is an extra cycle delay between reads
) (
input i_clk_a, i_rst_a,
input i_clk_b, i_rst_b,
input i_val_a,
input [DAT_BITS-1:0] i_dat_a,
output logic o_rdy_a,
output logic o_full_a,
output logic o_val_b,
output logic [DAT_BITS-1:0] o_dat_b,
input i_rdy_b,
output logic o_emp_b,
output logic [ABITS:0] o_rd_wrds_b
);
localparam ABITS = $clog2(SIZE);
logic [ABITS:0] rd_ptr_b, wr_ptr_a, rd_ptrg_a, rd_ptr_a, wr_ptrg_b, wr_ptr_b;
generate
if (USE_BRAM == 0) begin: BRAM_GEN
logic [SIZE-1:0][DAT_BITS-1:0] ram;
always_ff @ (posedge i_clk_a) begin
if (i_val_a && o_rdy_a) begin
ram [wr_ptr_a[ABITS-1:0]] <= i_dat_a;
end
end
always_ff @ (posedge i_clk_b) begin
if (i_rst_b) begin
o_val_b <= 0;
o_dat_b <= 0;
end else begin
if (~o_val_b || (o_val_b && i_rdy_b)) begin
if (o_val_b && i_rdy_b) begin
o_val_b <= ~(wr_ptr_b == (rd_ptr_b + 1) % (1 << (ABITS+1)));
o_dat_b <= ram [(rd_ptr_b[ABITS-1:0]+1) % SIZE];
end else begin
o_val_b <= ~(wr_ptr_b == rd_ptr_b);
o_dat_b <= ram [rd_ptr_b[ABITS-1:0]];
end
end
end
end
end else begin
logic [DAT_BITS-1:0] dat_b;
if_ram #(.RAM_WIDTH(DAT_BITS), .RAM_DEPTH(SIZE)) bram_if_rd (i_clk_b, i_rst_b);
if_ram #(.RAM_WIDTH(DAT_BITS), .RAM_DEPTH(SIZE)) bram_if_wr (i_clk_a, i_rst_a);
bram #(
.RAM_WIDTH ( DAT_BITS ),
.RAM_DEPTH ( SIZE ),
.RAM_PERFORMANCE ( "LOW_LATENCY" )
) bram_i (
.a ( bram_if_rd ),
.b ( bram_if_wr )
);
always_ff @ (posedge i_clk_b) begin
o_val_b <= 0;
if (~o_emp_b) o_val_b <= 1;
if (o_val_b && i_rdy_b) o_val_b <= 0;
end
always_comb begin
bram_if_rd.re = 1;
bram_if_rd.a = rd_ptr_b[ABITS-1:0];
bram_if_rd.d = 0;
bram_if_rd.we = 0;
bram_if_rd.en = 1;
bram_if_wr.re = 0;
bram_if_wr.a = wr_ptr_a[ABITS-1:0];
bram_if_wr.d = i_dat_a;
bram_if_wr.we = i_val_a && o_rdy_a;
bram_if_wr.en = 1;
o_dat_b = bram_if_rd.q;
end
end
endgenerate
// i_clk_a
always_ff @ (posedge i_clk_a) begin
if (i_rst_a) begin
wr_ptr_a <= 0;
end else begin
if (i_val_a && o_rdy_a) begin
wr_ptr_a <= wr_ptr_a + 1;
end
end
end
// i_clk_b
always_ff @ (posedge i_clk_b) begin
if (i_rst_b) begin
rd_ptr_b <= 0;
end else begin
if (o_val_b && i_rdy_b) begin
rd_ptr_b <= rd_ptr_b + 1;
end
end
end
always_comb begin
rd_ptr_a = grey_to_bin(rd_ptrg_a);
wr_ptr_b = grey_to_bin(wr_ptrg_b);
end
always_comb begin
o_emp_b = wr_ptr_b == rd_ptr_b;
o_full_a = wr_ptr_a == {~rd_ptr_a[ABITS], rd_ptr_a[ABITS-1:0]};
end
always_comb begin
o_rdy_a = ~o_full_a;
o_rd_wrds_b = o_emp_b ? (1 << ABITS) : wr_ptr_b[ABITS-1:0] - rd_ptr_b[ABITS-1:0];
end
// Synchronizers
synchronizer #(
.DAT_BITS ( ABITS + 1 ),
.NUM_CLKS ( 2 )
)
synchronizer_wr_ptr (
.i_clk_a ( i_clk_a ),
.i_clk_b ( i_clk_b ),
.i_dat_a ( bin_to_grey(wr_ptr_a) ),
.o_dat_b ( wr_ptrg_b )
);
synchronizer #(
.DAT_BITS ( ABITS + 1 ),
.NUM_CLKS ( 2 )
)
synchronizer_rd_ptr (
.i_clk_a ( i_clk_b ),
.i_clk_b ( i_clk_a ),
.i_dat_a ( bin_to_grey(rd_ptr_b) ),
.o_dat_b ( rd_ptrg_a )
);
// Functions to convert to grey counter and back
function [ABITS:0] grey_to_bin(input logic [ABITS:0] in);
grey_to_bin[ABITS] = in[ABITS];
for(int i = ABITS-1; i >= 0; i--) begin
grey_to_bin[i] = in[i] ^ grey_to_bin[i+1];
end
endfunction
function [ABITS:0] bin_to_grey(input logic [ABITS:0] in);
bin_to_grey[ABITS] = in[ABITS];
for (int i = ABITS; i > 0; i--)
bin_to_grey[i-1] = in[i] ^ in[i-1];
endfunction
endmodule

View File

@ -0,0 +1,163 @@
/*
Changes the width between two streams (must be powers of 2).
Goes through a clock crossing FIFO so can run on different
clock domains.
Input and output widths need to be a multiple of each other
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module width_change_cdc_fifo # (
parameter IN_DAT_BYTS,
parameter OUT_DAT_BYTS,
parameter CTL_BITS,
parameter FIFO_ABITS,
parameter USE_BRAM
) (
input i_clk_a, i_rst_a,
input i_clk_b, i_rst_b,
if_axi_stream.sink i_axi_a,
if_axi_stream.source o_axi_b
);
localparam SHIFT_DOWN = IN_DAT_BYTS > OUT_DAT_BYTS;
localparam SHIFT_RATIO = SHIFT_DOWN ? IN_DAT_BYTS/OUT_DAT_BYTS : OUT_DAT_BYTS/IN_DAT_BYTS;
localparam MAX_BYTS = SHIFT_DOWN ? IN_DAT_BYTS : OUT_DAT_BYTS;
localparam MIN_BYTS = SHIFT_DOWN ? OUT_DAT_BYTS : IN_DAT_BYTS;
localparam IN_DAT_BITS = IN_DAT_BYTS*8;
localparam IN_MOD_BITS = IN_DAT_BYTS == 1 ? 1 : $clog2(IN_DAT_BYTS);
localparam OUT_DAT_BITS = OUT_DAT_BYTS*8;
localparam OUT_MOD_BITS = OUT_DAT_BYTS == 1 ? 1 : $clog2(OUT_DAT_BYTS);
if_axi_stream #(.DAT_BYTS(IN_DAT_BYTS), .CTL_BITS(CTL_BITS)) o_axi_int (i_clk_b);
logic [$clog2(MAX_BYTS)-1:0] byt_cnt;
logic sop_l;
// Logic to take words out of the CDC and form packets
always_comb begin
if (SHIFT_DOWN) begin
o_axi_int.rdy = (byt_cnt + OUT_DAT_BYTS == IN_DAT_BYTS) && o_axi_b.rdy ||
(o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod));
end else begin
o_axi_int.rdy = (~o_axi_b.val && (byt_cnt + IN_DAT_BYTS < OUT_DAT_BYTS)) ||
o_axi_b.rdy;
end
end
always_ff @ (posedge i_clk_b) begin
if (i_rst_b) begin
o_axi_b.reset_source();
byt_cnt <= 0;
sop_l <= 0;
end else begin
if (~o_axi_b.val || (o_axi_b.val && o_axi_b.rdy)) begin
if (o_axi_b.val && o_axi_b.rdy) begin
o_axi_b.reset_source();
end
if (o_axi_int.val) begin
if (byt_cnt == 0 && o_axi_int.sop) begin
sop_l <= 1;
if (SHIFT_DOWN)
o_axi_b.sop <= 1;
end
if (SHIFT_DOWN)
o_axi_b.dat <= o_axi_int.dat[byt_cnt*8 +: OUT_DAT_BITS];
else
o_axi_b.dat[byt_cnt*8 +: IN_DAT_BITS] <= o_axi_int.dat;
if (SHIFT_DOWN) begin
if (o_axi_int.val)
byt_cnt <= byt_cnt + OUT_DAT_BYTS;
end else begin
if (o_axi_int.rdy && o_axi_int.val)
byt_cnt <= byt_cnt + IN_DAT_BYTS;
end
if ((byt_cnt + IN_DAT_BYTS) % OUT_DAT_BYTS == 0 ||
o_axi_int.eop ||
SHIFT_DOWN ) begin
o_axi_b.val <= 1;
if (~SHIFT_DOWN)
o_axi_b.sop <= sop_l || o_axi_int.sop;
sop_l <= 0;
if (SHIFT_DOWN) begin
if((byt_cnt + OUT_DAT_BYTS) % IN_DAT_BYTS == 0 ||
(o_axi_int.mod != 0 && (byt_cnt + OUT_DAT_BYTS >= o_axi_int.mod))) begin
o_axi_b.eop <= o_axi_int.eop;
byt_cnt <= 0;
end
end else begin
o_axi_b.eop <= o_axi_int.eop;
byt_cnt <= 0;
end
o_axi_b.mod <= o_axi_int.mod == 0 ? 0 : (byt_cnt + o_axi_int.mod);
end
end
end
end
end
cdc_fifo #(
.SIZE ( 1<<FIFO_ABITS ),
.DAT_BITS ( IN_DAT_BYTS*8 + IN_MOD_BITS + CTL_BITS + 3 ),
.USE_BRAM ( USE_BRAM )
)
cdc_fifo (
.i_clk_a ( i_clk_a ),
.i_rst_a ( i_rst_a ),
.i_clk_b ( i_clk_b ),
.i_rst_b ( i_rst_b ),
.i_val_a( i_axi_a.val ),
.i_dat_a({i_axi_a.dat,
i_axi_a.mod,
i_axi_a.sop,
i_axi_a.eop,
i_axi_a.err,
i_axi_a.ctl}),
.o_rdy_a( i_axi_a.rdy ),
.o_full_a(),
.o_val_b( o_axi_int.val ),
.o_dat_b({o_axi_int.dat,
o_axi_int.mod,
o_axi_int.sop,
o_axi_int.eop,
o_axi_int.err,
o_axi_int.ctl}),
.i_rdy_b( o_axi_int.rdy ),
.o_emp_b(),
.o_rd_wrds_b()
);
endmodule

View File

@ -0,0 +1,178 @@
/*
The width_change testbench.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
`timescale 1ps/1ps
module width_change_cdc_fifo_tb();
import common_pkg::*;
logic clk_a, rst_a;
logic clk_b, rst_b;
parameter DAT_BYTS_IN = 4;
parameter DAT_BYTS_OUT = 12;
parameter CLK_A_PERIOD = 1000;
parameter CLK_B_PERIOD = 1500;
if_axi_stream #(.DAT_BYTS(DAT_BYTS_IN), .CTL_BITS(8)) in_if(clk_a);
if_axi_stream #(.DAT_BYTS(DAT_BYTS_OUT), .CTL_BITS(8)) out_if(clk_b);
if_axi_stream #(.DAT_BYTS(DAT_BYTS_OUT), .CTL_BITS(8)) in1_if(clk_a);
if_axi_stream #(.DAT_BYTS(DAT_BYTS_IN), .CTL_BITS(8)) out1_if(clk_b);
initial begin
rst_a = 0;
repeat(10) #CLK_A_PERIOD rst_a = ~rst_a;
end
initial begin
rst_b = 0;
repeat(10) #CLK_B_PERIOD rst_b = ~rst_b;
end
initial begin
clk_a = 0;
forever #(CLK_A_PERIOD/2) clk_a = ~clk_a;
end
initial begin
clk_b = 0;
forever #(CLK_B_PERIOD/2) clk_b = ~clk_b;
end
width_change_cdc_fifo #(
.IN_DAT_BYTS ( DAT_BYTS_IN ),
.OUT_DAT_BYTS( DAT_BYTS_OUT ),
.CTL_BITS ( 8 ),
.FIFO_ABITS ( 4 ),
.USE_BRAM (1)
)
DUT0 (
.i_clk_a ( clk_a ),
.i_rst_a ( rst_a ),
.i_clk_b ( clk_b ),
.i_rst_b ( rst_b ),
.i_axi_a ( in_if ),
.o_axi_b ( out_if )
);
// This one has the in and out swapped
width_change_cdc_fifo #(
.IN_DAT_BYTS ( DAT_BYTS_OUT ),
.OUT_DAT_BYTS( DAT_BYTS_IN ),
.CTL_BITS ( 8 ),
.FIFO_ABITS ( 4 ),
.USE_BRAM (0)
)
DUT1 (
.i_clk_a ( clk_a ),
.i_rst_a ( rst_a ),
.i_clk_b ( clk_b ),
.i_rst_b ( rst_b ),
.i_axi_a ( in1_if ),
.o_axi_b ( out1_if )
);
task test0();
begin
integer signed get_len, in_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] data, get_dat;
$display("Running test0...");
data = 'hbeefdead12341234aa55aa55deadbeef;
fork
in_if.put_stream(data, 32);
out_if.get_stream(get_dat, get_len);
join
common_pkg::compare_and_print(get_dat, data);
data = 'hbeef;
fork
in_if.put_stream(data, 2);
out_if.get_stream(get_dat, get_len);
join
common_pkg::compare_and_print(get_dat, data);
in_len = 100;
data = random_vector(in_len);
fork
in_if.put_stream(data, in_len);
out_if.get_stream(get_dat, get_len);
join
common_pkg::compare_and_print(get_dat, data);
$display("test0 PASSED");
end
endtask
task test1();
begin
integer signed get_len, in_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] data, get_dat;
$display("Running test1...");
data = 'hbeefdead12341234aa55aa55deadbeef;
fork
in1_if.put_stream(data, 32);
out1_if.get_stream(get_dat, get_len);
join
common_pkg::compare_and_print(get_dat, data);
data = 'hbeef;
fork
in1_if.put_stream(data, 2);
out1_if.get_stream(get_dat, get_len);
join
common_pkg::compare_and_print(get_dat, data);
in_len = 100;
data = random_vector(in_len);
fork
in1_if.put_stream(data, in_len);
out1_if.get_stream(get_dat, get_len);
join
common_pkg::compare_and_print(get_dat, data);
$display("test1 PASSED");
end
endtask
// Main testbench calls
initial begin
$srandom(10);
out_if.rdy = 0;
in_if.val = 0;
out1_if.rdy = 0;
in1_if.val = 0;
#(10*CLK_A_PERIOD + 10*CLK_B_PERIOD);
test0();
test1();
#10us $finish();
end
endmodule

View File

@ -21,9 +21,9 @@
*/
module file_to_axi #(
parameter BINARY, // 0 for ASCII, 1 for binary
parameter DAT_BYTS,
parameter FP = 0 // Forward pressure, if this is non-zero then this is the % of cycles o_axi.val will be low
parameter BINARY, // 0 for ASCII, 1 for binary
parameter DAT_BYTS,
parameter FP = 0 // Forward pressure, if this is non-zero then this is the % of cycles o_axi.val will be low
) (
input i_clk, i_rst,
input string i_file, // Path to file to read from

View File

@ -18,8 +18,8 @@
*/
module header_adder #(
parameter HDR_BYTS,
parameter DAT_BYTS
parameter HDR_BYTS,
parameter DAT_BYTS
) (
input i_clk, i_rst,

View File

@ -0,0 +1,92 @@
/*
This takes in a AXI stream, removes N bytes, and outputs the resulting stream.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module header_remover #(
parameter MAX_HDR_BYTS,
parameter DAT_BYTS
) (
input i_clk, i_rst,
input [$clog2(MAX_HDR_BYTS)-1:0] i_hdr_byts, // Can change during packet
input i_hdr_val,
if_axi_stream.sink i_axi,
if_axi_stream.source o_axi
);
localparam DAT_BITS = DAT_BYTS*8;
logic [(DAT_BITS*2)-1:0] dat_buff;
logic [$clog2(MAX_HDR_BYTS):0] hdr_byts, hdr_byts_l, byt_cnt;
logic o_sop_l;
always_comb begin
hdr_byts = i_hdr_val ? i_hdr_byts : hdr_byts_l;
i_axi.rdy = ~i_rst && ((hdr_byts >= byt_cnt) || o_axi.rdy);
o_axi.dat = dat_buff[(hdr_byts % DAT_BYTS)*8 +: DAT_BITS];
o_axi.sop = ~o_sop_l;
end
always_ff @ (posedge i_clk) begin
if (i_rst) begin
o_axi.val <= 0;
o_axi.eop <= 0;
o_axi.mod <= 0;
o_axi.err <= 0;
o_axi.ctl <= 0;
byt_cnt <= 0;
hdr_byts_l <= MAX_HDR_BYTS;
o_sop_l <= 0;
end else begin
if (~o_axi.val || (o_axi.val && o_axi.rdy)) begin
if (i_axi.val && i_axi.rdy)
byt_cnt <= (byt_cnt >= hdr_byts) ? byt_cnt : byt_cnt + DAT_BYTS;
if (i_axi.sop && i_axi.val && i_axi.rdy) begin
hdr_byts_l <= MAX_HDR_BYTS;
o_axi.ctl <= i_axi.ctl;
end
dat_buff <= {i_axi.dat, dat_buff[DAT_BITS +: DAT_BITS]};
o_axi.val <= i_axi.val && (byt_cnt >= hdr_byts);
o_sop_l <= o_sop_l | (o_axi.sop && o_axi.val && o_axi.rdy);
if (o_axi.eop && o_axi.val && o_axi.rdy) begin
o_sop_l <= 0;
o_axi.eop <= 0;
o_axi.val <= 0;
byt_cnt <= 0;
end
if (i_axi.eop && i_axi.val && i_axi.rdy) begin
hdr_byts_l <= MAX_HDR_BYTS;
o_axi.eop <= i_axi.eop;
o_axi.mod <= -(hdr_byts % DAT_BYTS) + i_axi.mod;
end
end
if (i_hdr_val)
hdr_byts_l <= i_hdr_byts;
end
end
endmodule

View File

@ -0,0 +1,99 @@
/*
This implements the SHA256d hash algorithm (double SHA256).
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module sha256d_top
import sha256_pkg::*;
(
input i_clk, i_rst,
if_axi_stream.sink i_block, // Message stream to be hashed, must be 512 bits
if_axi_stream.source o_hash // Resulting hash digest (32 bytes)
);
localparam DAT_BYTS = 64;
localparam DAT_BITS = DAT_BYTS*8; // Must be 512
if_axi_stream #(.DAT_BYTS(64)) hash_in_if(i_clk);
if_axi_stream #(.DAT_BYTS(32)) hash_out_if(i_clk);
enum {IDLE = 0,
SHA0 = 1,
SHA1 = 2,
SHA1_WAIT = 3} sha_state;
always_ff @ (posedge i_clk) begin
if (i_rst) begin
sha_state <= IDLE;
o_hash.reset_source();
hash_in_if.reset_source();
hash_out_if.rdy <= 0;
end else begin
case (sha_state)
IDLE: begin
if (i_block.sop && i_block.val && i_block.rdy) begin
sha_state <= SHA0;
hash_in_if.copy_if(i_block.to_struct());
end
end
SHA0: begin
if (~hash_in_if.val || (hash_in_if.val && hash_in_if.rdy)) begin
hash_in_if.copy_if(i_block.to_struct());
if (hash_in_if.eop) begin
sha_state <= SHA1;
end
end
end
SHA1: begin
hash_in_if.val <= 0;
if (hash_out_if.val && hash_out_if.rdy && hash_out_if.sop) begin
hash_in_if.copy_if(hash_out_if.to_struct());
sha_state <= SHA1_WAIT;
end
end
SHA1_WAIT: begin
hash_in_if.val <= 0;
if (~o_hash.val || (o_hash.val && o_hash.rdy)) begin
o_hash.copy_if(hash_out_if.to_struct());
if (o_hash.val && o_hash.rdy)
sha_state <= IDLE;
end
end
endcase
end
end
always_comb begin
i_block.rdy = (sha_state == IDLE || sha_state == SHA0) ? hash_in_if.rdy : 0;
end
// SHA256 block
sha256_top sha256_top (
.i_clk ( i_clk ),
.i_rst ( i_rst ),
.i_block ( hash_in_if ),
.o_hash ( hash_out_if )
);
// Check that input size is correct
initial begin
assert ($bits(i_block.dat) == DAT_BITS) else $fatal(1, "%m %t ERROR: sha256_top DAT_BITS (%d) does not match interface .dat (%d)", $time, DAT_BITS, $bits(i_block.dat));
end
endmodule

View File

@ -0,0 +1,84 @@
/*
Takes in multiple streams and round robins between them.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module packet_arb # (
parameter NUM_IN
) (
input i_clk, i_rst,
if_axi_stream.sink i_axi [NUM_IN-1:0],
if_axi_stream.source o_axi
);
logic [$clog2(NUM_IN)-1:0] idx;
logic locked;
logic [NUM_IN-1:0] rdy, val, eop;
generate
genvar g;
for (g = 0; g < NUM_IN; g++) begin: GEN
always_comb begin
i_axi[g].rdy = rdy[g];
val[g] = i_axi[g].val;
eop[g] = i_axi[g].eop;
end
always_ff @ (posedge i_clk) begin
if(g == idx)
o_axi.copy_if(i_axi[g].to_struct());
end
end
endgenerate
always_comb begin
rdy = 0;
rdy[idx] = o_axi.rdy;
end
always_ff @ (posedge i_clk) begin
if (i_rst) begin
locked <= 0;
idx <= 0;
end else begin
if (~locked) begin
idx <= get_next(idx);
if (val[idx] && rdy[idx]) begin
idx <= idx;
locked <= 1;
end
end else if (eop[idx] && val[idx] && rdy[idx]) begin
idx <= get_next(idx);
locked <= 0;
end
end
end
// Get next input with valid
function [$clog2(NUM_IN)-1:0] get_next(input [NUM_IN-1:0] idx);
get_next = idx;
for (int i = 0; i < NUM_IN; i++)
if (val[(idx+i+1) % NUM_IN]) begin
get_next = i;
break;
end
endfunction
endmodule

View File

@ -0,0 +1,375 @@
/*
This module is the top level for the FPGA interface to SW. It takes in commands
from SW, running the commands, and then building the replies back to SW.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module control_top
import zcash_fpga_pkg::*, equihash_pkg::*;
#(
parameter IN_DAT_BYTS,
parameter [63:0] BUILD_HOST = "test",
parameter [63:0] BUILD_DATE = "20180311"
)(
input i_clk_core, i_rst_core,
input i_clk_if, i_rst_if,
// User is able to reset custom logic on FPGA
output logic o_usr_rst,
// Interface inputs and outputs
if_axi_stream.sink rx_if,
if_axi_stream.source tx_if,
// Used when verifying equihash soltion
if_axi_stream.source o_equihash_axi,
input equihash_bm_t i_equihash_mask,
input i_equihash_mask_val
);
localparam CORE_DAT_BYTS = 8; // Only tested at 8 byte data width
localparam IN_DAT_BITS = IN_DAT_BYTS*8;
localparam CORE_DAT_BITS = CORE_DAT_BYTS*8;
// When a command comes in it is put through a clock crossing, and then stored in a command
// FIFO to be processed. There are two FIFOS - one for processing status / reset commands (msg_type == 0),
// and one for everything else. This is so we can process these messages even if we are
// running something else.
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) rx_int_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) rx_int0_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) rx_int1_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) rx_typ0_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) rx_typ1_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) tx_typ0_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) tx_typ1_if (i_clk_core);
if_axi_stream #(.DAT_BYTS(CORE_DAT_BYTS), .CTL_BYTS(1)) tx_int_if (i_clk_core);
enum {TYP0_IDLE = 0,
TYP0_SEND_STATUS = 1,
TYP0_RESET_FPGA = 2,
TYP0_IGNORE = 3} typ0_msg_state;
enum {TYP1_IDLE = 0,
TYP1_VERIFY_EQUIHASH = 1,
TYP1_IGNORE = 2} typ1_msg_state;
header_t header, header0, header1, header0_l, header1_l;
fpga_status_rpl_t fpga_status_rpl;
fpga_reset_rpl_t fpga_reset_rpl;
verify_equihash_rpl_t verify_equihash_rpl;
logic [7:0] typ0_wrd_cnt, typ1_wrd_cnt, reset_cnt;
logic [63:0] equihash_index;
logic equihash_index_val, rx_typ1_if_rdy, verify_equihash_rpl_val;
fpga_state_t fpga_state;
always_comb begin
fpga_state = 0;
fpga_state.error = 0;
fpga_state.typ1_state = TYP1_IDLE;
header = rx_int_if.dat;
header0 = rx_typ0_if.dat;
header1 = rx_typ0_if.dat;
end
// Logic for processing msg_type == 0 messages
always_ff @ (posedge i_clk_core) begin
if (i_rst_core) begin
rx_typ0_if.rdy <= 0;
typ0_msg_state <= TYP0_IDLE;
header0_l <= 0;
tx_typ0_if.reset_source();
fpga_status_rpl <= 0;
fpga_reset_rpl <= 0;
typ0_wrd_cnt <= 0;
o_usr_rst <= 0;
reset_cnt <= 0;
end else begin
rx_typ0_if.rdy <= 1;
case (typ0_msg_state)
TYP0_IDLE: begin
fpga_status_rpl <= get_fpga_status_rpl(BUILD_HOST, BUILD_DATE, fpga_state);
fpga_reset_rpl <= get_fpga_reset_rpl();
if (rx_typ0_if.val && rx_typ0_if.rdy) begin
header0_l <= header0;
rx_typ0_if.rdy <= 0;
case(header0.cmd)
RESET_FPGA: begin
typ0_wrd_cnt <= $bits(fpga_reset_rpl_t)/8;
typ0_msg_state <= TYP0_RESET_FPGA;
o_usr_rst <= 1;
reset_cnt <= -1;
end
FPGA_STATUS: begin
typ0_wrd_cnt <= $bits(fpga_status_rpl_t)/8;
typ0_msg_state <= TYP0_SEND_STATUS;
end
default:
if (~rx_typ0_if.eop)
typ0_msg_state <= TYP0_IGNORE;
endcase
end
end
TYP0_SEND_STATUS: begin
rx_typ0_if.rdy <= 0;
if (~tx_typ0_if.val || (tx_typ0_if.rdy && tx_typ0_if.val)) begin
tx_typ0_if.dat <= fpga_status_rpl;
tx_typ0_if.val <= 1;
tx_typ0_if.sop <= typ0_wrd_cnt == $bits(fpga_status_rpl_t)/8;
tx_typ0_if.eop <= typ0_wrd_cnt <= CORE_DAT_BYTS;
tx_typ0_if.mod <= typ0_wrd_cnt < CORE_DAT_BYTS ? typ0_wrd_cnt : 0;
typ0_wrd_cnt <= (typ0_wrd_cnt > CORE_DAT_BYTS) ? (typ0_wrd_cnt - CORE_DAT_BYTS) : 0;
fpga_status_rpl <= fpga_status_rpl >> CORE_DAT_BITS;
if (typ0_wrd_cnt == 0) begin
tx_typ0_if.val <= 0;
typ0_msg_state <= TYP0_IDLE;
end
end
end
TYP0_RESET_FPGA: begin
rx_typ0_if.rdy <= 0;
if (reset_cnt == 0)
o_usr_rst <= 0;
else
reset_cnt <= reset_cnt - 1;
if (~o_usr_rst) begin
if (~tx_typ0_if.val || (tx_typ0_if.rdy && tx_typ0_if.val)) begin
tx_typ0_if.dat <= fpga_reset_rpl;
tx_typ0_if.val <= 1;
tx_typ0_if.sop <= typ0_wrd_cnt == $bits(fpga_reset_rpl_t)/8;
tx_typ0_if.eop <= typ0_wrd_cnt <= CORE_DAT_BYTS;
tx_typ0_if.mod <= typ0_wrd_cnt < CORE_DAT_BYTS ? typ0_wrd_cnt : 0;
typ0_wrd_cnt <= (typ0_wrd_cnt > CORE_DAT_BYTS) ? (typ0_wrd_cnt - CORE_DAT_BYTS) : 0;
fpga_reset_rpl <= fpga_reset_rpl >> CORE_DAT_BITS;
if (typ0_wrd_cnt == 0) begin
tx_typ0_if.val <= 0;
typ0_msg_state <= TYP0_IDLE;
end
end
end
end
TYP0_IGNORE: begin
rx_typ0_if.rdy <= 1;
if (rx_typ0_if.rdy && rx_typ0_if.eop && rx_typ0_if.val)
typ0_msg_state <= TYP0_IDLE;
end
endcase
end
end
always_comb begin
case(typ1_msg_state)
TYP1_IDLE: rx_typ1_if.rdy = rx_typ1_if_rdy;
VERIFY_EQUIHASH: rx_typ1_if.rdy = rx_typ1_if_rdy && o_equihash_axi.rdy;
default: rx_typ1_if.rdy = rx_typ1_if_rdy;
endcase
end
// Logic for processing msg_type == 1 messages
always_ff @ (posedge i_clk_core) begin
if (i_rst_core) begin
rx_typ1_if_rdy <= 0;
typ1_msg_state <= TYP1_IDLE;
header1_l <= 0;
tx_typ1_if.reset_source();
o_equihash_axi.reset_source();
verify_equihash_rpl <= 0;
typ1_wrd_cnt <= 0;
equihash_index <= 0;
verify_equihash_rpl_val <= 0;
end else begin
rx_typ1_if.rdy <= 1;
case (typ1_msg_state)
TYP1_IDLE: begin
verify_equihash_rpl_val <= 0;
if (rx_typ1_if.val && rx_typ1_if.rdy) begin
header1_l <= header1;
rx_typ1_if_rdy <= 0;
case(header1.cmd)
VERIFY_EQUIHASH: begin
rx_typ1_if_rdy <= 1;
typ1_wrd_cnt <= $bits(verify_equihash_rpl_t)/8;
typ1_msg_state <= TYP1_VERIFY_EQUIHASH;
end
default:
if (~rx_typ1_if.eop)
typ1_msg_state <= TYP1_IGNORE;
endcase
end
end
TYP1_VERIFY_EQUIHASH: begin
if (rx_typ1_if.eop && rx_typ1_if.val && rx_typ1_if.rdy)
rx_typ1_if_rdy <= 0;
if (~equihash_index_val) begin
if (rx_typ1_if.rdy && rx_typ1_if.val)
equihash_index <= equihash_index_val;
end else begin
// First load block data (this might be bypassed if loading from memory)
if (~o_equihash_axi.val || (o_equihash_axi.rdy && o_equihash_axi.val)) begin
o_equihash_axi.copy_if(rx_typ1_if.to_struct());
end
end
// Wait for reply with result
if (i_equihash_mask_val) begin
verify_equihash_rpl <= get_verify_equihash_rpl(i_equihash_mask, equihash_index);
verify_equihash_rpl_val <= 1;
end
// Send result
if (verify_equihash_rpl_val) begin
if (~tx_typ1_if.val || (tx_typ1_if.rdy && tx_typ1_if.val)) begin
tx_typ1_if.dat <= verify_equihash_rpl;
tx_typ1_if.val <= 1;
tx_typ1_if.sop <= typ1_wrd_cnt == $bits(verify_equihash_rpl_t)/8;
tx_typ1_if.eop <= typ1_wrd_cnt <= CORE_DAT_BYTS;
tx_typ1_if.mod <= typ1_wrd_cnt < CORE_DAT_BYTS ? typ1_wrd_cnt : 0;
typ1_wrd_cnt <= (typ1_wrd_cnt > CORE_DAT_BYTS) ? (typ1_wrd_cnt - CORE_DAT_BYTS) : 0;
verify_equihash_rpl <= verify_equihash_rpl >> CORE_DAT_BITS;
if (typ1_wrd_cnt == 0) begin
tx_typ1_if.val <= 0;
typ1_msg_state <= TYP1_IDLE;
end
end
end
end
TYP1_IGNORE: begin
rx_typ1_if_rdy <= 1;
if (rx_typ1_if.rdy && rx_typ1_if.eop && rx_typ1_if.val)
typ1_msg_state <= TYP1_IDLE;
end
endcase
end
end
// Logic to mux the packet depending on its command type
logic msg_type, msg_type_l;
always_comb begin
rx_int0_if.copy_if(rx_int_if.to_struct());
rx_int1_if.copy_if(rx_int_if.to_struct());
rx_int0_if.val = 0;
rx_int1_if.val = 0;
rx_int_if.rdy = 0;
if (rx_int_if.sop && rx_int_if.val && rx_int_if.rdy) begin
if(header.cmd[8 +: 8] == 8'd0) begin
msg_type = 0;
rx_int0_if.val = rx_int_if.val;
rx_int_if.rdy = rx_int0_if.rdy;
end else begin
msg_type = 1;
rx_int1_if.val = rx_int_if.val;
rx_int_if.rdy = rx_int1_if.rdy;
end
end else begin
rx_int0_if.val = rx_int_if.val && (msg_type_l == 0);
rx_int1_if.val = rx_int_if.val && (msg_type_l == 1);
rx_int_if.rdy = msg_type_l == 0 ? rx_int0_if.rdy : rx_int1_if.rdy;
msg_type = msg_type_l;
end
end
always_ff @ (posedge i_clk_core) begin
if (i_rst_core || o_usr_rst) begin
msg_type_l <= 0;
end else begin
if (rx_int_if.val && rx_int_if.rdy) begin
if (rx_int_if.sop)
msg_type_l <= msg_type;
end
end
end
// FIFO control queues for different message types
axi_stream_fifo #(
.SIZE ( 64 ),
.DAT_BITS ( CORE_DAT_BITS )
)
cmd_fifo0 (
.i_clk ( i_clk_core ),
.i_rst ( i_rst_core || o_usr_rst ),
.i_axi ( rx_int0_if ),
.o_axi ( rx_typ0_if )
);
axi_stream_fifo #(
.SIZE ( 64 ),
.DAT_BITS ( CORE_DAT_BITS )
)
cmd_fifo1 (
.i_clk ( i_clk_core ),
.i_rst ( i_rst_core || o_usr_rst ),
.i_axi ( rx_int1_if ),
.o_axi ( rx_typ1_if )
);
width_change_cdc_fifo #(
.IN_DAT_BYTS ( IN_DAT_BYTS ),
.OUT_DAT_BYTS ( CORE_DAT_BYTS ),
.CTL_BITS ( 8 ),
.FIFO_ABITS ( $clog2(16*1024/IN_DAT_BITS) ),
.USE_BRAM ( 1 )
)
cdc_fifo_rx (
.i_clk_a ( i_clk_if ),
.i_rst_a ( i_rst_if || o_usr_rst ),
.i_clk_b ( i_clk_core ),
.i_rst_b ( i_rst_core || o_usr_rst ),
.i_axi_a ( rx_if ),
.o_axi_b ( rx_int_if )
);
// Arbitrator for sending messages back
packet_arb # (
.NUM_IN ( 2 )
)
packet_arb_tx (
.i_clk ( i_clk_core ),
.i_rst ( i_rst_core || o_usr_rst ),
.i_axi ({tx_typ1_if, tx_typ0_if}),
.o_axi ( tx_int_if )
);
// Width change back to tx interface
width_change_cdc_fifo #(
.IN_DAT_BYTS ( CORE_DAT_BYTS ),
.OUT_DAT_BYTS ( IN_DAT_BYTS ),
.CTL_BITS ( 8 ),
.FIFO_ABITS ( $clog2(16*1024/CORE_DAT_BYTS) ),
.USE_BRAM ( 1 )
)
cdc_fifo_tx (
.i_clk_a ( i_clk_core ),
.i_rst_a ( i_rst_core || o_usr_rst ),
.i_clk_b ( i_clk_if ),
.i_rst_b ( i_rst_if || o_usr_rst ),
.i_axi_a ( tx_int_if ),
.o_axi_b ( tx_if )
);
endmodule

View File

@ -17,7 +17,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package zcash_verif_pkg;
package equihash_pkg;
// Variables used in the equihash PoW
parameter [31:0] N = 32'd200;
@ -27,18 +27,24 @@ package zcash_verif_pkg;
parameter [7:0] BLAKE2B_DIGEST_BYTS = (N*INDICIES_PER_HASH)/8;
parameter SOL_BITS = COLLISION_BIT_LEN+1;
parameter SOL_LIST_LEN = 1 << K;
parameter SOL_LIST_BYTS = 3 + SOL_LIST_LEN*SOL_BITS/8;
parameter [127:0] POW_TAG = {K, N, "WoPhsacZ"}; // ZcashPoW is reversed here
parameter SOL_LIST_ENC = (SOL_LIST_LEN*SOL_BITS/8 < 8'hFD ? 1 : 3); // 3 Bytes used to encode size for N = 200, K = 9.
parameter SOL_LIST_BYTS = SOL_LIST_ENC + SOL_LIST_LEN*SOL_BITS/8;
parameter MAX_BLOCK_BYTS = 2*1024*1024; // 2MB
// Values used for resulting error masks
typedef struct packed {
logic [2:0] padding;
logic DUPLICATE_FND;
logic BAD_ZERO_ORDER;
logic BAD_IDX_ORDER;
logic XOR_NON_ZERO;
logic DIFFICULTY_FAIL;
} equihash_bm_t;
} equihash_bm_t;
// Format for equihash input - should be 144 bytes
typedef struct packed {
@ -54,7 +60,7 @@ package zcash_verif_pkg;
typedef struct packed {
logic [SOL_LIST_LEN-1:0][SOL_BITS-1:0] sol;
logic [3*8-1:0] size; // Contains size of solution array - should be 1347 for (200,9)
logic [SOL_LIST_ENC*8-1:0] size; // Contains size of solution array - should be 1347 for (200,9)
} equihash_sol_t;
// Header format for block header (CBlockheader)
@ -73,6 +79,6 @@ package zcash_verif_pkg;
equihash_sol_t equihash_sol;
cblockheader_t cblockheader;
} cblockheader_sol_t;
endpackage

View File

@ -23,8 +23,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module zcash_verif_equihash_difficulty
import zcash_verif_pkg::*;
module equihash_verif_difficulty
import equihash_pkg::*;
#(
parameter DAT_BYTS = 8
)(

View File

@ -23,8 +23,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module zcash_verif_equihash_order
import zcash_verif_pkg::*;
module equihash_verif_order
import equihash_pkg::*;
(
input i_clk, i_rst,

View File

@ -2,8 +2,8 @@
This verifies that a Zcash equihash solution is correct,
input is an axi stream of the block header. This block checks:
1. XOR of EquihashGen() is 0
2. Ordering
3. No duplicates
2. Ordering correct of leafs
3. No duplicate index
4. Difficulty passes
Code is split up into 3 main always blocks, one for loading RAM, one for parsing
@ -25,14 +25,15 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module zcash_verif_equihash
import zcash_verif_pkg::*;
module equihash_verif_top
import equihash_pkg::*;
#(
parameter DAT_BYTS = 8,
parameter CHECK_UNIQUE_INDEX = 1
parameter DAT_BYTS = 8
)(
input i_clk, i_rst,
input i_clk_300, i_rst_300, // Faster clock
if_axi_stream.sink i_axi,
output equihash_bm_t o_mask,
output logic o_mask_val
@ -40,6 +41,7 @@ module zcash_verif_equihash
localparam [7:0] EQUIHASH_GEN_BYTS = $bits(equihash_gen_in_t)/8;
localparam DAT_BITS = DAT_BYTS*8;
localparam MOD_BITS = $clog2(DAT_BYTS);
cblockheader_t cblockheader;
logic cblockheader_val;
@ -71,7 +73,9 @@ logic dup_chk_done, order_chk_done, diff_chk_done, xor_check_done;
logic difficulty_fail, difficulty_fail_val;
if_axi_stream #(.DAT_BITS(SOL_BITS), .CTL_BITS(1), .MOD_BITS(1)) dup_check_if_in(i_clk);
if_axi_stream #(.DAT_BITS(SOL_BITS), .CTL_BITS(1), .MOD_BITS(1)) dup_check_if_in_sync(i_clk_300);
if_axi_stream #(.DAT_BITS(1), .CTL_BITS(1), .MOD_BITS(1)) dup_check_if_out(i_clk);
if_axi_stream #(.DAT_BITS(1), .CTL_BITS(1), .MOD_BITS(1)) dup_check_if_out_sync(i_clk);
if_axi_stream #(.DAT_BITS(SOL_BITS), .MOD_BITS(1), .CTL_BITS(1)) equihash_order_if(i_clk);
logic equihash_order_val, equihash_order_wrong;
@ -308,8 +312,6 @@ always_ff @ (posedge i_clk) begin
sol_cnt_out <= sol_cnt_out + 1;
//TODO here we also need to check the ordering, and duplicate indixe?
//TODO some additional order requirements on the indexies < for certain ones
// We also check the order is correct
o_mask.BAD_ZERO_ORDER <= bad_order_check(sol_hash_xor, sol_cnt_out) | o_mask.BAD_ZERO_ORDER;
end
@ -391,10 +393,10 @@ always_comb begin
difficulty_if_in.ctl = 0;
end
zcash_verif_equihash_difficulty #(
equihash_verif_difficulty #(
.DAT_BYTS ( DAT_BYTS )
)
zcash_verif_equihash_difficulty (
equihash_verif_difficulty (
.i_clk ( i_clk ),
.i_rst ( i_rst ),
.i_axi ( difficulty_if_in ),
@ -435,7 +437,7 @@ bram #(
.b ( equihash_sol_bram_if_b )
);
zcash_verif_equihash_order
equihash_verif_order
equihash_order (
.i_clk ( i_clk ),
.i_rst ( i_rst ),
@ -445,29 +447,84 @@ equihash_order (
.o_val ( equihash_order_val )
);
generate
if (CHECK_UNIQUE_INDEX == 1) begin: GEN_INDEX_CHECK
dup_check #(
.IN_BITS ( SOL_BITS ),
.LIST_SIZE ( SOL_LIST_LEN )
)
dup_check(
.i_clk ( i_clk ),
.i_rst ( i_rst ),
// We use a clock crossing on the dup_check as it takes longer
cdc_fifo #(
.SIZE ( 16 ),
.DAT_BITS ( SOL_BITS + 2 ),
.USE_BRAM ( 0 )
)
dup_check_fifo_in (
.i_clk_a ( i_clk ),
.i_rst_a ( i_rst ),
.i_clk_b ( i_clk_300 ),
.i_rst_b ( i_rst_300 ),
.i_val_a ( dup_check_if_in.val ),
.o_rdy_a ( dup_check_if_in.rdy ),
.i_dat_a ( {dup_check_if_in.dat,
dup_check_if_in.sop,
dup_check_if_in.eop} ),
.o_full_a(),
.i_rdy_b ( dup_check_if_in_sync.rdy ),
.o_val_b ( dup_check_if_in_sync.val ),
.o_dat_b ( {dup_check_if_in_sync.dat,
dup_check_if_in_sync.sop,
dup_check_if_in_sync.eop} ),
.o_emp_b()
);
always_comb begin
dup_check_if_in_sync.ctl = 0;
dup_check_if_in_sync.err = 0;
dup_check_if_in_sync.mod = 0;
dup_check_if_out.ctl = 0;
dup_check_if_out.mod = 0;
end
dup_check #(
.IN_BITS ( SOL_BITS ),
.LIST_SIZE ( SOL_LIST_LEN )
)
dup_check(
.i_clk ( i_clk_300 ),
.i_rst ( i_rst_300 ),
.i_axi ( dup_check_if_in_sync ),
.o_axi ( dup_check_if_out_sync )
);
// Clock crossing on output to get result
cdc_fifo #(
.SIZE ( 4 ),
.DAT_BITS ( 4 ),
.USE_BRAM ( 0 )
)
dup_check_fifo_out (
.i_clk_a ( i_clk_300 ),
.i_rst_a ( i_rst_300 ),
.i_clk_b ( i_clk ),
.i_rst_b ( i_rst ),
.i_val_a ( dup_check_if_out_sync.val ),
.o_rdy_a ( dup_check_if_out_sync.rdy ),
.i_dat_a ( {dup_check_if_out_sync.dat,
dup_check_if_out_sync.sop,
dup_check_if_out_sync.eop,
dup_check_if_out_sync.err} ),
.o_full_a(),
.i_rdy_b ( dup_check_if_out.rdy ),
.o_val_b ( dup_check_if_out.val ),
.o_dat_b ( {dup_check_if_out.dat,
dup_check_if_out.sop,
dup_check_if_out.eop,
dup_check_if_out.err} ),
.o_emp_b()
);
.i_axi ( dup_check_if_in ),
.o_axi ( dup_check_if_out )
);
end else begin
always_comb begin
dup_check_if_in.rdy = 1;
dup_check_if_out.val = 1;
dup_check_if_out.eop = 1;
dup_check_if_out.sop = 1;
dup_check_if_out.dat = 0;
end
end
endgenerate
// Some checks to make sure our data structures are correct:
initial begin
assert ($bits(equihash_gen_in_t)/8 == 144) else $fatal(1, "%m %t ERROR: equihash_gen_in_t is not 144 bytes in size", $time);

View File

@ -0,0 +1,102 @@
/*
Parameter values and tasks for the FPGA system.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package zcash_fpga_pkg;
import equihash_pkg::equihash_bm_t;
import equihash_pkg::cblockheader_sol_t;
parameter FPGA_VERSION = 32'h0;
localparam [63:0] FPGA_CMD_CAP = 64'h0;
// These are all the command types the FPGA supports
// Reply messages from the FPGA to host all have the last
// bit set (start at 0x80000000). Messages with bits [31:16] == 0 are processed by a different state machine
typedef enum logic [31:0] {
RESET_FPGA = 'h0000_00_00,
FPGA_STATUS = 'h0000_00_01,
VERIFY_EQUIHASH = 'h0000_01_00,
// Replies from the FPGA
RESET_FPGA_RPL = 'h80_00_00_00,
FPGA_STATUS_RPL = 'h80_00_00_01,
VERIFY_EQUIHASH_RPL = 'h80_00_01_00
} command_t;
// Data sent to the FPGA must start with a header aligned to
// a 8 byte boundary.
typedef struct packed {
command_t cmd;
logic [31:0] len;
} header_t;
typedef struct packed {
header_t hdr;
} fpga_reset_rpl_t;
// These are registers we use for debug
typedef struct packed {
logic [3:0] padding;
logic [2:0] typ1_state;
logic error; // Any error on FPGA will have this set
} fpga_state_t;
typedef struct packed {
fpga_state_t fpga_state;
logic [63:0] cmd_cap;
logic [63:0] build_host;
logic [63:0] build_date;
logic [31:0] version;
header_t hdr;
} fpga_status_rpl_t;
typedef struct packed {
cblockheader_sol_t cblockheader_sol;
logic [63:0] index;
header_t hdr;
} verify_equihash_t;
typedef struct packed {
equihash_bm_t bm;
logic [63:0] index;
header_t hdr;
} verify_equihash_rpl_t;
// We have a function for building each type of reply from the FPGA
function fpga_reset_rpl_t get_fpga_reset_rpl();
get_fpga_reset_rpl.hdr = '{cmd:RESET_FPGA_RPL, len:$bits(fpga_reset_rpl_t)/8};
endfunction
function fpga_status_rpl_t get_fpga_status_rpl(input [63:0] build_host, build_date, fpga_state_t fpga_state);
get_fpga_status_rpl.cmd_cap = FPGA_CMD_CAP;
get_fpga_status_rpl.hdr = '{cmd:FPGA_STATUS_RPL, len:$bits(fpga_status_rpl_t)/8};
get_fpga_status_rpl.version = FPGA_VERSION;
get_fpga_status_rpl.build_host = build_host;
get_fpga_status_rpl.build_date = build_date;
get_fpga_status_rpl.fpga_state = fpga_state;
endfunction
function verify_equihash_rpl_t get_verify_equihash_rpl(input equihash_bm_t mask, logic [63:0] equihash_index);
get_verify_equihash_rpl.hdr = '{cmd:VERIFY_EQUIHASH_RPL, len:$bits(verify_equihash_rpl_t)/8};
get_verify_equihash_rpl.index = equihash_index;
get_verify_equihash_rpl.bm = mask;
endfunction
endpackage

View File

@ -1,8 +1,8 @@
/*
This takes in an AXI stream of a block and runs verification
checks (detailed in the architecture document). When all the checks are
completed the o_val will go high, and o_mask bit mask will be 1 for any
checks that failed.
This is the top level of the Zcash FPGA acceleration engine.
We have different interfaces that are all muxed together to provide FPGA
with commands and data.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
@ -20,14 +20,42 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module zcash_verif_system #(
module zcash_fpga_top
import zcash_verif_pkg::*;
#(
parameter DAT_BYTS = 8
)(
input i_clk, i_rst,
if_axi_stream.sink i_axi,
output logic [31:0] o_mask,
output logic o_val
// Clocks and resets
input i_clk_100, i_rst_100,
// Interface inputs and outputs
// UART
if_axi_stream.sink uart_if_rx,
if_axi_stream.source uart_if_tx,
// Ethernet
if_axi_stream.sink eth_if_rx,
if_axi_stream.source eth_if_tx,
// PCIe
if_axi_stream.sink pcie_if_rx,
if_axi_stream.source pcie_if_tx
);
// This block is used to verify a equihash solution
zcash_verif_equihash #(
.DAT_BYTS(DAT_BYTS)
)
equihash_verif_top (
.i_clk ( i_clk ),
.i_rst ( i_rst ),
.i_clk_300 ( i_clk_300 ),
.i_rst_300 ( i_rst_300 ), // Faster clock
.i_axi ( equihash_verif_if ),
.o_mask ( equihash_verif_mask ),
.o_mask_val ( equihash_verif_mask_val )
);
endmodule

View File

@ -0,0 +1,188 @@
/*
The control top testbench.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
`timescale 1ps/1ps
module control_top_tb();
import common_pkg::*;
import zcash_fpga_pkg::*;
import equihash_pkg::*;
localparam CORE_CLK_PERIOD = 600;
localparam UART_CLK_PERIOD = 1000;
localparam CORE_BYTS = 8;
localparam UART_BYTS = 4; // Use real value TODO
logic core_clk, core_rst, uart_clk, uart_rst, usr_rst;
equihash_bm_t equihash_mask;
logic equihash_mask_val;
if_axi_stream #(.DAT_BYTS(CORE_BYTS)) equihash_axi(core_clk);
if_axi_stream #(.DAT_BYTS(UART_BYTS)) uart_rx_if (uart_clk);
if_axi_stream #(.DAT_BYTS(UART_BYTS)) uart_tx_if (uart_clk);
initial begin
core_rst = 0;
repeat(10) #CORE_CLK_PERIOD core_rst = ~core_rst;
end
initial begin
core_clk = 0;
forever #CORE_CLK_PERIOD core_clk = ~core_clk;
end
initial begin
uart_rst = 0;
repeat(10) #UART_CLK_PERIOD uart_rst = ~uart_rst;
end
initial begin
uart_clk = 0;
forever #UART_CLK_PERIOD uart_clk = ~uart_clk;
end
control_top #(
.IN_DAT_BYTS(UART_BYTS)
)
DUT (
.i_clk_core ( core_clk ),
.i_rst_core ( core_rst ),
.o_usr_rst ( usr_rst ),
.i_clk_if ( uart_clk ),
.i_rst_if ( uart_rst ),
.rx_if ( uart_tx_if ),
.tx_if ( uart_rx_if ),
.o_equihash_axi ( equihash_axi ),
.i_equihash_mask ( equihash_mask ),
.i_equihash_mask_val ( equihash_mask_val )
);
// This is a tests sending a request for FPGA status
task test_status_message();
begin
header_t header;
fpga_status_rpl_t fpga_status_rpl;
integer signed get_len, in_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat;
logic fail = 0;
$display("Running test_status_message...");
header.cmd = FPGA_STATUS;
header.len = $bits(header_t)/8;
fork
uart_tx_if.put_stream(header, $bits(header)/8);
uart_rx_if.get_stream(get_dat, get_len);
join
fpga_status_rpl = get_dat;
fail |= fpga_status_rpl.hdr.cmd != FPGA_STATUS_RPL;
fail |= fpga_status_rpl.hdr.len != $bits(fpga_status_rpl_t)/8;
fail |= fpga_status_rpl.hdr.len != get_len;
fail |= fpga_status_rpl.version != FPGA_VERSION;
fail |= fpga_status_rpl.build_host != "test";
fail |= fpga_status_rpl.build_date != "20180311";
fail |= fpga_status_rpl.fpga_state != 0;
assert (~fail) else $fatal(1, "%m %t ERROR: test_status_message status reply was wrong:\n%p", $time, fpga_status_rpl);
$display("test_status_message PASSED");
end
endtask
// Test sending a reset command to the FPGA
task test_reset_message();
begin
header_t header;
fpga_reset_rpl_t fpga_reset_rpl;
integer signed get_len, in_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat;
$display("Running test_reset_message...");
header.cmd = RESET_FPGA;
header.len = $bits(header_t)/8;
fork
uart_tx_if.put_stream(header, $bits(header)/8);
uart_rx_if.get_stream(get_dat, get_len);
begin
while (!usr_rst) @(posedge core_clk);
while (usr_rst) @(posedge core_clk);
end
join
fpga_reset_rpl = get_dat;
$display("test_reset_message PASSED");
end
endtask
// Test sending a eh command to the FPGA
task test_eh_verify_message();
begin
verify_equihash_t msg;
verify_equihash_rpl_t verify_equihash_rpl;
integer signed get_len, in_len;
logic [common_pkg::MAX_SIM_BYTS*8-1:0] get_dat;
logic fail = 0;
$display("Running test_eh_verify_message...");
msg.hdr.cmd = VERIFY_EQUIHASH;
msg.hdr.len = $bits(verify_equihash_t)/8;
msg.index = 1;
fork
uart_tx_if.put_stream(msg, $bits(msg)/8);
uart_rx_if.get_stream(get_dat, get_len);
begin
while (!usr_rst) @(posedge core_clk);
while (usr_rst) @(posedge core_clk);
end
join
verify_equihash_rpl = get_dat;
fail |= verify_equihash_rpl.hdr.cmd != VERIFY_EQUIHASH_RPL;
fail |= verify_equihash_rpl.hdr.len != $bits(fpga_status_rpl_t)/8;
fail |= verify_equihash_rpl.index != 1;
assert (~fail) else $fatal(1, "%m %t ERROR: test_eh_verify_message was wrong:\n%p", $time, verify_equihash_rpl);
$display("test_eh_verify_message PASSED");
end
endtask
// Main testbench calls
initial begin
equihash_axi.rdy = 1;
equihash_mask_val = 0;
equihash_mask = 0;
uart_tx_if.val = 0;
uart_rx_if.rdy = 0;
#200ns;
test_reset_message();
test_status_message();
test_eh_verify_message();
#10us $finish();
end
endmodule

View File

@ -1,5 +1,5 @@
/*
The zcash_verif_equihash testbench.
The equihash_verif_top testbench.
Copyright (C) 2019 Benjamin Devlin and Zcash Foundation
@ -17,12 +17,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
module zcash_verif_equihash_tb();
module equihash_verif_top_tb();
import zcash_verif_pkg::*;
import equihash_pkg::*;
import common_pkg::*;
logic clk, rst;
logic clk_300, rst_300;
equihash_bm_t mask;
logic mask_val;
logic start_346 = 0;
@ -72,11 +73,22 @@ initial begin
#100ns rst = 0;
end
initial begin
rst_300 = 0;
#100ns rst_300 = 1;
#100ns rst_300 = 0;
end
initial begin
clk = 0;
forever #10ns clk = ~clk;
end
initial begin
clk_300 = 0;
forever #3ns clk_300 = ~clk_300;
end
file_to_axi #(
.BINARY ( 1 ),
.DAT_BYTS ( DAT_BYTS ),
@ -105,10 +117,12 @@ file_to_axi_block346_error (
.o_axi ( header_346_error )
);
zcash_verif_equihash
equihash_verif_top
DUT (
.i_clk ( clk ),
.i_rst ( rst ),
.i_clk_300 ( clk_300 ),
.i_rst_300 ( rst_300 ),
.i_axi ( header ),
.o_mask ( mask ),
.o_mask_val ( mask_val )

View File

@ -1 +1,15 @@
create_clock -period 5.000 -name i_clk -waveform {0.000 2.500} [get_ports -filter { NAME =~ "*i_clk*" && DIRECTION == "IN" }]
create_clock -period 2.500 -name i_clk_300 -waveform {0.000 1.250} [get_ports -filter { NAME =~ "i_clk_300" && DIRECTION == "IN" }]
set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_wr_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_wr_ptr/* }]] 1.667
set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_wr_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_wr_ptr/* }]] 1.667
set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_rd_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_rd_ptr/* }]] 2.500
set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_rd_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/synchronizer_rd_ptr/* }]] 2.500
set_bus_skew -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/* }]] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/* }]] 2.500
set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/* }]] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_in/* }]] 2.500
set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_wr_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_wr_ptr/* }]] 2.500
set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_wr_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_wr_ptr/* }]] 2.500
set_bus_skew -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_rd_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_rd_ptr/* }]] 1.667
set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*dat_reg[0]*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_rd_ptr/* }]] -to [get_pins -filter { NAME =~ "*dat_reg[1]*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/synchronizer_rd_ptr/* }]] 1.667
set_bus_skew -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/* }]] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/* }]] 1.667
set_max_delay -datapath_only -from [get_pins -filter { NAME =~ "*ram*C" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/* }]] -to [get_pins -filter { NAME =~ "*o_dat_b*D" } -of_objects [get_cells -hierarchical -filter {NAME =~ dup_check_fifo_out/* }]] 1.667