library: Add ADI JESD204 wrapper for Altera/Intel platforms
Add a wrapper module for Altera/Intel platforms that instantiates and connects all the components required to for a JESD204 link. The following components are created: * Transceiver for each lane * Transceiver lane PLL (TX only) * Transceiver reset controller * Link PLL * JESD204 link layer processing * JESD204 link layer processing control interface * axi_adxcvr link management peripheral Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>main
parent
0108d01043
commit
9c5b48c151
|
@ -0,0 +1,401 @@
|
|||
#
|
||||
# The ADI JESD204 Core is released under the following license, which is
|
||||
# different than all other HDL cores in this repository.
|
||||
#
|
||||
# Please read this, and understand the freedoms and responsibilities you have
|
||||
# by using this source code/core.
|
||||
#
|
||||
# The JESD204 HDL, is copyright © 2016-2017 Analog Devices Inc.
|
||||
#
|
||||
# This core is free software, you can use run, copy, study, change, ask
|
||||
# questions about and improve this core. Distribution of source, or resulting
|
||||
# binaries (including those inside an FPGA or ASIC) require you to release the
|
||||
# source of the entire project (excluding the system libraries provide by the
|
||||
# tools/compiler/FPGA vendor). These are the terms of the GNU General Public
|
||||
# License version 2 as published by the Free Software Foundation.
|
||||
#
|
||||
# This core 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 version 2
|
||||
# along with this source code, and binary. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Commercial licenses (with commercial support) of this JESD204 core are also
|
||||
# available under terms different than the General Public License. (e.g. they
|
||||
# do not require you to accompany any image (FPGA or ASIC) using the JESD204
|
||||
# core with any corresponding source code.) For these alternate terms you must
|
||||
# purchase a license from Analog Devices Technology Licensing Office. Users
|
||||
# interested in such a license should contact jesd204-licensing@analog.com for
|
||||
# more information. This commercial license is sub-licensable (if you purchase
|
||||
# chips from Analog Devices, incorporate them into your PCB level product, and
|
||||
# purchase a JESD204 license, end users of your product will also have a
|
||||
# license to use this core in a commercial setting without releasing their
|
||||
# source code).
|
||||
#
|
||||
# In addition, we kindly ask you to acknowledge ADI in any program, application
|
||||
# or publication in which you use this JESD204 HDL core. (You are not required
|
||||
# to do so; it is up to your common sense to decide whether you want to comply
|
||||
# with this request or not.) For general publications, we suggest referencing :
|
||||
# “The design and implementation of the JESD204 HDL Core used in this project
|
||||
# is copyright © 2016-2017, Analog Devices, Inc.”
|
||||
#
|
||||
|
||||
package require qsys
|
||||
source ../../scripts/adi_env.tcl
|
||||
source ../../scripts/adi_ip_alt.tcl
|
||||
|
||||
#
|
||||
# Wrapper module that instantiates and connects all the components required to
|
||||
# for a JESD204 link.
|
||||
#
|
||||
# The following components are created:
|
||||
# * Transceiver for each lane
|
||||
# * Transceiver lane PLL (TX only)
|
||||
# * Transceiver reset controller
|
||||
# * Link PLL
|
||||
# * JESD204 link layer processing
|
||||
# * JESD204 link layer processing control interface
|
||||
# * axi_adxcvr link management peripheral
|
||||
#
|
||||
|
||||
ad_ip_create adi_jesd204 {Analog Devices JESD204}
|
||||
set_module_property VALIDATION_CALLBACK jesd204_validate
|
||||
set_module_property COMPOSITION_CALLBACK jesd204_compose
|
||||
|
||||
# parameters
|
||||
|
||||
ad_ip_parameter DEVICE_FAMILY STRING "" false {
|
||||
VISIBLE false
|
||||
}
|
||||
|
||||
ad_ip_parameter DEVICE STRING "" false {
|
||||
SYSTEM_INFO DEVICE
|
||||
VISIBLE false
|
||||
}
|
||||
|
||||
ad_ip_parameter TX_OR_RX_N BOOLEAN 0 false { \
|
||||
DISPLAY_HINT "radio" \
|
||||
DISPLAY_NAME "Data Path" \
|
||||
ALLOWED_RANGES { "0:Receive" "1:Transmit" }
|
||||
}
|
||||
|
||||
ad_ip_parameter ID NATURAL 0 false { \
|
||||
DISPLAY_NAME "Core ID" \
|
||||
}
|
||||
|
||||
ad_ip_parameter LANE_RATE FLOAT 10000 false { \
|
||||
DISPLAY_NAME "Lane Rate" \
|
||||
DISPLAY_UNITS "Mbps" \
|
||||
}
|
||||
|
||||
ad_ip_parameter SYSCLK_FREQUENCY FLOAT 100.0 false { \
|
||||
DISPLAY_NAME "System Clock Frequency" \
|
||||
UNITS Megahertz
|
||||
}
|
||||
|
||||
ad_ip_parameter REFCLK_FREQUENCY FLOAT 500.0 false { \
|
||||
DISPLAY_NAME "Reference Clock Frequency" \
|
||||
UNITS Megahertz \
|
||||
}
|
||||
|
||||
ad_ip_parameter NUM_OF_LANES POSITIVE 4 false { \
|
||||
DISPLAY_NAME "Number of Lanes" \
|
||||
ALLOWED_RANGES 1:8
|
||||
}
|
||||
|
||||
ad_ip_parameter LANE_MAP STRING "" false { \
|
||||
DISPLAY_NAME "Lane Mapping" \
|
||||
}
|
||||
|
||||
ad_ip_parameter SOFT_PCS BOOLEAN true false { \
|
||||
DISPLAY_NAME "Enable Soft PCS" \
|
||||
}
|
||||
|
||||
proc create_phy_reset_control {tx num_of_lanes sysclk_frequency} {
|
||||
add_instance phy_reset_control altera_xcvr_reset_control
|
||||
set_instance_property phy_reset_control SUPPRESS_ALL_WARNINGS true
|
||||
set_instance_parameter_value phy_reset_control {CHANNELS} $num_of_lanes
|
||||
set_instance_parameter_value phy_reset_control {SYS_CLK_IN_MHZ} $sysclk_frequency
|
||||
set_instance_parameter_value phy_reset_control {TX_PLL_ENABLE} $tx
|
||||
set_instance_parameter_value phy_reset_control {TX_ENABLE} $tx
|
||||
set_instance_parameter_value phy_reset_control {RX_ENABLE} [expr !$tx]
|
||||
set_instance_parameter_value phy_reset_control {SYNCHRONIZE_RESET} {0}
|
||||
add_connection sys_clock.clk phy_reset_control.clock
|
||||
add_connection link_reset.out_reset phy_reset_control.reset
|
||||
add_connection sys_clock.clk_reset phy_reset_control.reset
|
||||
|
||||
if {$tx} {
|
||||
set_instance_parameter_value phy_reset_control {T_PLL_POWERDOWN} {1000}
|
||||
set_instance_parameter_value phy_reset_control {gui_pll_cal_busy} {1}
|
||||
set_instance_parameter_value phy_reset_control {T_TX_ANALOGRESET} {70000}
|
||||
set_instance_parameter_value phy_reset_control {T_TX_DIGITALRESET} {70000}
|
||||
|
||||
add_connection phy_reset_control.tx_ready axi_xcvr.ready
|
||||
} else {
|
||||
set_instance_parameter_value phy_reset_control {T_RX_ANALOGRESET} {70000}
|
||||
set_instance_parameter_value phy_reset_control {T_RX_DIGITALRESET} {4000}
|
||||
|
||||
add_connection phy_reset_control.rx_ready axi_xcvr.ready
|
||||
}
|
||||
}
|
||||
|
||||
proc create_lane_pll {id pllclk_frequency refclk_frequency} {
|
||||
add_instance lane_pll altera_xcvr_atx_pll_a10
|
||||
set_instance_property lane_pll SUPPRESS_ALL_INFO_MESSAGES true
|
||||
set_instance_parameter_value lane_pll {enable_pll_reconfig} {1}
|
||||
set_instance_parameter_value lane_pll {rcfg_separate_avmm_busy} {1}
|
||||
set_instance_parameter_value lane_pll {set_capability_reg_enable} {1}
|
||||
set_instance_parameter_value lane_pll {set_user_identifier} $id
|
||||
set_instance_parameter_value lane_pll {set_csr_soft_logic_enable} {1}
|
||||
set_instance_parameter_value lane_pll {set_output_clock_frequency} $pllclk_frequency
|
||||
set_instance_parameter_value lane_pll {set_auto_reference_clock_frequency} $refclk_frequency
|
||||
add_connection phy_reset_control.pll_powerdown lane_pll.pll_powerdown
|
||||
add_connection lane_pll.pll_locked phy_reset_control.pll_locked
|
||||
add_connection lane_pll.pll_cal_busy phy_reset_control.pll_cal_busy
|
||||
add_connection ref_clock.out_clk lane_pll.pll_refclk0
|
||||
add_connection sys_clock.clk lane_pll.reconfig_clk0
|
||||
add_connection sys_clock.clk_reset lane_pll.reconfig_reset0
|
||||
add_interface lane_pll_reconfig avalon slave
|
||||
set_interface_property lane_pll_reconfig EXPORT_OF lane_pll.reconfig_avmm0
|
||||
}
|
||||
|
||||
proc jesd204_get_max_lane_rate {device soft_pcs} {
|
||||
if {[string range $device 0 2] == "10A"} {
|
||||
set device_speedgrade [string range $device 13 13]
|
||||
set pma_speedgrade [string range $device 8 8]
|
||||
} else {
|
||||
# Assume fastest speed grade
|
||||
set device_speedgrade 1
|
||||
set pma_speedgrade 1
|
||||
}
|
||||
|
||||
if {$soft_pcs} {
|
||||
if {$pma_speedgrade == 1 || $pma_speedgrade == 2} {
|
||||
return "15000"
|
||||
} elseif {$pma_speedgrade == 3} {
|
||||
return "14200"
|
||||
} else {
|
||||
return "12500"
|
||||
}
|
||||
} else {
|
||||
if {$device_speedgrade == 1} {
|
||||
return "12000"
|
||||
} elseif {$device_speedgrade == 2} {
|
||||
return "9830"
|
||||
} else {
|
||||
return "8936"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc jesd204_validate {{quiet false}} {
|
||||
set soft_pcs [get_parameter_value "SOFT_PCS"]
|
||||
set device_family [get_parameter_value "DEVICE_FAMILY"]
|
||||
set device [get_parameter_value "DEVICE"]
|
||||
set lane_rate [get_parameter_value "LANE_RATE"]
|
||||
|
||||
if {$device_family != "Arria 10"} {
|
||||
if {!$quiet} {
|
||||
send_message error "Only Arria 10 is supported."
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
set max_lane_rate [jesd204_get_max_lane_rate $device $soft_pcs]
|
||||
|
||||
if {$lane_rate < 2000 || $lane_rate > $max_lane_rate} {
|
||||
if {!$quiet} {
|
||||
send_message error "Lane rate must be in the range 2000-${max_lane_rate} Mbps."
|
||||
if {!$soft_pcs} {
|
||||
send_message error "Consider enabling soft PCS for a higher maximum lane rate."
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
proc jesd204_compose {} {
|
||||
set id [get_parameter_value "ID"]
|
||||
set lane_rate [get_parameter_value "LANE_RATE"]
|
||||
set tx_or_rx_n [get_parameter_value "TX_OR_RX_N"]
|
||||
set num_of_lanes [get_parameter_value "NUM_OF_LANES"]
|
||||
set sysclk_frequency [get_parameter_value "SYSCLK_FREQUENCY"]
|
||||
set refclk_frequency [get_parameter_value "REFCLK_FREQUENCY"]
|
||||
set lane_map [get_parameter_value "LANE_MAP"]
|
||||
set soft_pcs [get_parameter_value "SOFT_PCS"]
|
||||
set device_family [get_parameter_value "DEVICE_FAMILY"]
|
||||
set device [get_parameter_value "DEVICE"]
|
||||
|
||||
set pllclk_frequency [expr $lane_rate / 2]
|
||||
set linkclk_frequency [expr $lane_rate / 40]
|
||||
|
||||
if {![jesd204_validate true]} {
|
||||
return
|
||||
}
|
||||
|
||||
add_instance sys_clock clock_source
|
||||
set_instance_parameter_value sys_clock {clockFrequency} [expr $sysclk_frequency*1000000]
|
||||
set_instance_parameter_value sys_clock {resetSynchronousEdges} {deassert}
|
||||
add_interface sys_clk clock sink
|
||||
set_interface_property sys_clk EXPORT_OF sys_clock.clk_in
|
||||
add_interface sys_resetn reset sink
|
||||
set_interface_property sys_resetn EXPORT_OF sys_clock.clk_in_reset
|
||||
|
||||
add_instance ref_clock altera_clock_bridge
|
||||
set_instance_parameter_value ref_clock {EXPLICIT_CLOCK_RATE} [expr $refclk_frequency*1000000]
|
||||
add_interface ref_clk clock sink
|
||||
set_interface_property ref_clk EXPORT_OF ref_clock.in_clk
|
||||
|
||||
add_instance link_pll altera_xcvr_fpll_a10
|
||||
set_instance_property link_pll SUPPRESS_ALL_WARNINGS true
|
||||
set_instance_property link_pll SUPPRESS_ALL_INFO_MESSAGES true
|
||||
set_instance_parameter_value link_pll {gui_fpll_mode} {0}
|
||||
set_instance_parameter_value link_pll {gui_reference_clock_frequency} $refclk_frequency
|
||||
set_instance_parameter_value link_pll {gui_number_of_output_clocks} 2
|
||||
set_instance_parameter_value link_pll {gui_enable_phase_alignment} 1
|
||||
set_instance_parameter_value link_pll {gui_desired_outclk0_frequency} $linkclk_frequency
|
||||
set pfdclk_frequency [get_instance_parameter_value link_pll gui_pfd_frequency]
|
||||
set_instance_parameter_value link_pll {gui_desired_outclk1_frequency} $pfdclk_frequency
|
||||
set_instance_parameter_value link_pll {enable_pll_reconfig} {1}
|
||||
set_instance_parameter_value link_pll {set_capability_reg_enable} {1}
|
||||
set_instance_parameter_value link_pll {set_csr_soft_logic_enable} {1}
|
||||
add_connection ref_clock.out_clk link_pll.pll_refclk0
|
||||
|
||||
add_instance link_clock altera_clock_bridge
|
||||
set_instance_parameter_value link_clock {EXPLICIT_CLOCK_RATE} [expr $linkclk_frequency*1000000]
|
||||
set_instance_parameter_value link_clock {NUM_CLOCK_OUTPUTS} 2
|
||||
add_connection link_pll.outclk0 link_clock.in_clk
|
||||
add_interface link_clk clock source
|
||||
set_interface_property link_clk EXPORT_OF link_clock.out_clk
|
||||
|
||||
add_instance link_reset altera_reset_bridge
|
||||
add_connection sys_clock.clk link_reset.clk
|
||||
|
||||
add_connection sys_clock.clk_reset link_pll.reconfig_reset0
|
||||
add_connection sys_clock.clk link_pll.reconfig_clk0
|
||||
|
||||
add_instance axi_xcvr axi_adxcvr
|
||||
set_instance_parameter_value axi_xcvr {ID} $id
|
||||
set_instance_parameter_value axi_xcvr {TX_OR_RX_N} $tx_or_rx_n
|
||||
set_instance_parameter_value axi_xcvr {NUM_OF_LANES} $num_of_lanes
|
||||
|
||||
add_connection sys_clock.clk axi_xcvr.s_axi_clock
|
||||
add_connection sys_clock.clk_reset axi_xcvr.s_axi_reset
|
||||
add_connection axi_xcvr.if_up_rst link_reset.in_reset
|
||||
add_connection link_pll.pll_locked axi_xcvr.core_pll_locked
|
||||
|
||||
add_interface link_management axi4lite slave
|
||||
set_interface_property link_management EXPORT_OF axi_xcvr.s_axi
|
||||
|
||||
add_interface link_pll_reconfig avalon slave
|
||||
set_interface_property link_pll_reconfig EXPORT_OF link_pll.reconfig_avmm0
|
||||
|
||||
add_instance link_pll_reset_control altera_xcvr_reset_control
|
||||
set_instance_parameter_value link_pll_reset_control {SYS_CLK_IN_MHZ} $sysclk_frequency
|
||||
set_instance_parameter_value link_pll_reset_control {TX_PLL_ENABLE} {1}
|
||||
set_instance_parameter_value link_pll_reset_control {T_PLL_POWERDOWN} {1000}
|
||||
set_instance_parameter_value link_pll_reset_control {TX_ENABLE} {0}
|
||||
set_instance_parameter_value link_pll_reset_control {RX_ENABLE} {0}
|
||||
set_instance_parameter_value link_pll_reset_control {SYNCHRONIZE_RESET} {0}
|
||||
add_connection sys_clock.clk link_pll_reset_control.clock
|
||||
add_connection link_reset.out_reset link_pll_reset_control.reset
|
||||
add_connection sys_clock.clk_reset link_pll_reset_control.reset
|
||||
add_connection link_pll_reset_control.pll_powerdown link_pll.pll_powerdown
|
||||
|
||||
create_phy_reset_control $tx_or_rx_n $num_of_lanes $sysclk_frequency
|
||||
|
||||
add_instance phy jesd204_phy
|
||||
set_instance_parameter_value phy ID $id
|
||||
set_instance_parameter_value phy SOFT_PCS $soft_pcs
|
||||
set_instance_parameter_value phy TX_OR_RX_N $tx_or_rx_n
|
||||
set_instance_parameter_value phy LANE_RATE $lane_rate
|
||||
set_instance_parameter_value phy REFCLK_FREQUENCY $refclk_frequency
|
||||
set_instance_parameter_value phy NUM_OF_LANES $num_of_lanes
|
||||
|
||||
add_connection link_clock.out_clk_1 phy.link_clk
|
||||
add_connection link_reset.out_reset phy.link_reset
|
||||
add_connection sys_clock.clk phy.reconfig_clk
|
||||
add_connection sys_clock.clk_reset phy.reconfig_reset
|
||||
|
||||
if {$tx_or_rx_n} {
|
||||
set tx_rx "tx"
|
||||
set data_direction sink
|
||||
set jesd204_intfs {config control ilas_config event status}
|
||||
set phy_reset_intfs {analogreset digitalreset cal_busy}
|
||||
|
||||
create_lane_pll $id $pllclk_frequency $refclk_frequency
|
||||
add_connection lane_pll.tx_serial_clk phy.serial_clk
|
||||
} else {
|
||||
set tx_rx "rx"
|
||||
set data_direction source
|
||||
set jesd204_intfs {config ilas_config event status}
|
||||
set phy_reset_intfs {analogreset digitalreset cal_busy is_lockedtodata}
|
||||
|
||||
add_connection ref_clock.out_clk phy.ref_clk
|
||||
}
|
||||
|
||||
add_instance axi_jesd204_${tx_rx} axi_jesd204_${tx_rx}
|
||||
set_instance_parameter_value axi_jesd204_${tx_rx} {NUM_LANES} $num_of_lanes
|
||||
|
||||
add_connection sys_clock.clk axi_jesd204_${tx_rx}.s_axi_clock
|
||||
add_connection sys_clock.clk_reset axi_jesd204_${tx_rx}.s_axi_reset
|
||||
|
||||
add_connection link_clock.out_clk_1 axi_jesd204_${tx_rx}.core_clock
|
||||
add_connection link_reset.out_reset axi_jesd204_${tx_rx}.core_reset_ext
|
||||
|
||||
add_instance jesd204_${tx_rx} jesd204_${tx_rx}
|
||||
set_instance_parameter_value jesd204_${tx_rx} {NUM_LANES} $num_of_lanes
|
||||
|
||||
add_connection link_clock.out_clk_1 jesd204_${tx_rx}.clock
|
||||
add_connection axi_jesd204_${tx_rx}.core_reset jesd204_${tx_rx}.reset
|
||||
|
||||
foreach intf $jesd204_intfs {
|
||||
add_connection axi_jesd204_${tx_rx}.${intf} jesd204_${tx_rx}.${intf}
|
||||
}
|
||||
|
||||
foreach intf $phy_reset_intfs {
|
||||
add_connection phy_reset_control.${tx_rx}_${intf} phy.${intf}
|
||||
}
|
||||
|
||||
set lane_map [regexp -all -inline {\S+} $lane_map]
|
||||
for {set i 0} {$i < $num_of_lanes} {incr i} {
|
||||
if {$lane_map != {}} {
|
||||
set j [lindex $lane_map $i]
|
||||
} else {
|
||||
set j $i
|
||||
}
|
||||
|
||||
add_connection jesd204_${tx_rx}.${tx_rx}_phy${j} phy.phy_${i}
|
||||
}
|
||||
|
||||
for {set i 0} {$i < $num_of_lanes} {incr i} {
|
||||
add_interface phy_reconfig_${i} avalon slave
|
||||
set_interface_property phy_reconfig_${i} EXPORT_OF phy.reconfig_avmm_${i}
|
||||
}
|
||||
|
||||
add_interface interrupt interrupt end
|
||||
set_interface_property interrupt EXPORT_OF axi_jesd204_${tx_rx}.interrupt
|
||||
add_interface link_reconfig axi4lite slave
|
||||
set_interface_property link_reconfig EXPORT_OF axi_jesd204_${tx_rx}.s_axi
|
||||
|
||||
add_interface link_data avalon_streaming $data_direction
|
||||
set_interface_property link_data EXPORT_OF jesd204_${tx_rx}.${tx_rx}_data
|
||||
|
||||
if {!$tx_or_rx_n} {
|
||||
add_interface link_sof conduit end
|
||||
set_interface_property link_sof EXPORT_OF jesd204_rx.rx_sof
|
||||
}
|
||||
|
||||
add_interface sysref conduit end
|
||||
set_interface_property sysref EXPORT_OF jesd204_${tx_rx}.sysref
|
||||
|
||||
add_interface sync conduit end
|
||||
set_interface_property sync EXPORT_OF jesd204_${tx_rx}.sync
|
||||
|
||||
add_interface serial_data conduit end
|
||||
set_interface_property serial_data EXPORT_OF phy.serial_data
|
||||
}
|
Loading…
Reference in New Issue