diff --git a/library/altera/jesd204_phy/jesd204_phy_glue.v b/library/altera/jesd204_phy/jesd204_phy_glue.v new file mode 100644 index 000000000..9c6fd64d3 --- /dev/null +++ b/library/altera/jesd204_phy/jesd204_phy_glue.v @@ -0,0 +1,50 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// 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. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +module jesd204_glue #( + parameter WIDTH = 20, + parameter CONST_WIDTH = 1 +) ( + input [WIDTH-1:0] in, + output [WIDTH-1:0] out, + output [CONST_WIDTH-1:0] const_out +); + +/* There really should be a standard component in Qsys that allows to do this */ + +assign out = in; +assign const_out = {CONST_WIDTH{1'b0}}; + +endmodule diff --git a/library/altera/jesd204_phy/jesd204_phy_glue_hw.tcl b/library/altera/jesd204_phy/jesd204_phy_glue_hw.tcl new file mode 100644 index 000000000..54da7006d --- /dev/null +++ b/library/altera/jesd204_phy/jesd204_phy_glue_hw.tcl @@ -0,0 +1,271 @@ +# +# 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 +# . +# +# 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 + +# +# For whatever strange reason all the interface of the native PHY become +# conduits when it is instantiated in a compose callback. This glue logic module +# converts the interfaces to their proper type. +# + +ad_ip_create jesd204_phy_glue {Native PHY to JESD204 glue logic} \ + jesd204_phy_glue_elab +set_module_property INTERNAL true + +# files + +ad_ip_files jesd204_glue [list \ + jesd204_phy_glue.v \ +] + +# parameters + +ad_ip_parameter TX_OR_RX_N BOOLEAN false false +ad_ip_parameter SOFT_PCS BOOLEAN false false +ad_ip_parameter NUM_OF_LANES POSITIVE 4 false +ad_ip_parameter WIDTH NATURAL 20 true { \ + DERIVED true \ +} +ad_ip_parameter CONST_WIDTH NATURAL 1 true { \ + DERIVED true \ +} + +proc glue_add_if {num name type dir {bcast false}} { + if {$bcast} { + add_interface ${name} $type $dir + } else { + for {set i 0} {$i < $num} {incr i} { + add_interface ${name}_${i} $type $dir + } + } + add_interface phy_${name} conduit end +} + +proc glue_add_if_port {num ifname port role dir width {bcast false}} { + variable sig_offset + + set phy_width [expr $num * $width] + if {$dir == "Input"} { + set sig "in" + set phy_dir "Output" + set phy_sig "out" + } else { + set sig "out" + set phy_dir "Input" + set phy_sig "in" + } + + if {$bcast} { + add_interface_port ${ifname} ${port} $role $dir $width + set_port_property ${port} fragment_list \ + [format "%s(%d:%d)" $sig [expr $sig_offset + $width - 1] $sig_offset] + } else { + for {set i 0} {$i < $num} {incr i} { + set base [expr $sig_offset + $width * $i] + + add_interface_port ${ifname}_${i} ${port}_${i} $role $dir $width + set_port_property ${port}_${i} fragment_list \ + [format "%s(%d:%d)" $sig [expr $base + $width - 1] $base] + } + } + + add_interface_port phy_${ifname} phy_${port} $role $phy_dir $phy_width + + if {$bcast} { + set _frag [format "%s(%d:%d)" $phy_sig [expr $sig_offset + $width - 1] $sig_offset] + set sig_offset [expr $sig_offset + $width] + set frag "${_frag}" + for {set i 1} {$i < $num} {incr i} { + set frag [concat ${frag} ${_frag}] + } + } else { + set frag [format "%s(%d:%d)" $phy_sig [expr $sig_offset + $phy_width - 1] $sig_offset] + set sig_offset [expr $sig_offset + $phy_width] + } + + set_port_property phy_${port} fragment_list $frag +} + +proc glue_add_if_port_conduit {num ifname port phy_port dir width} { + variable sig_offset + + set phy_width [expr $num * $width] + if {$dir == "Input"} { + set sig "in" + set phy_dir "Output" + set phy_sig "out" + } else { + set sig "out" + set phy_dir "Input" + set phy_sig "in" + } + + for {set i 0} {$i < $num} {incr i} { + set base [expr $sig_offset + $width * $i] + + add_interface_port ${ifname}_${i} ${ifname}_${port}_${i} $port $dir $width + set_port_property ${ifname}_${port}_${i} fragment_list \ + [format "%s(%d:%d)" $sig [expr $base + $width - 1] $base] + } + + add_interface phy_${phy_port} conduit end + add_interface_port phy_${phy_port} phy_${phy_port} $phy_port $phy_dir $phy_width + + set_port_property phy_${phy_port} fragment_list \ + [format "%s(%d:%d)" $phy_sig [expr $sig_offset + $phy_width - 1] $sig_offset] + + set sig_offset [expr $sig_offset + $phy_width] +} + +proc glue_add_const_conduit {port width} { + variable const_offset + + set ifname phy_${port} + add_interface $ifname conduit end + add_interface_port $ifname $ifname $port Output $width + set_port_property $ifname fragment_list [format "const_out(%d:%d)" \ + [expr $const_offset + $width - 1] $const_offset] + + set const_offset [expr $const_offset + $width] +} + +proc jesd204_phy_glue_elab {} { + variable sig_offset + variable const_offset + + set soft_pcs [get_parameter SOFT_PCS] + set num_of_lanes [get_parameter NUM_OF_LANES] + + set sig_offset 0 + set const_offset 0 + + glue_add_if $num_of_lanes reconfig_clk clock sink true + glue_add_if_port $num_of_lanes reconfig_clk reconfig_clk clk Input 1 true + + glue_add_if $num_of_lanes reconfig_reset reset sink true + glue_add_if_port $num_of_lanes reconfig_reset reconfig_reset reset Input 1 true + + glue_add_if $num_of_lanes reconfig_avmm avalon sink + for {set i 0} {$i < $num_of_lanes} {incr i} { + set_interface_property reconfig_avmm_${i} associatedClock reconfig_clk + set_interface_property reconfig_avmm_${i} associatedReset reconfig_reset + } + glue_add_if_port $num_of_lanes reconfig_avmm reconfig_address address Input 10 + glue_add_if_port $num_of_lanes reconfig_avmm reconfig_read read Input 1 + glue_add_if_port $num_of_lanes reconfig_avmm reconfig_readdata readdata Output 32 + glue_add_if_port $num_of_lanes reconfig_avmm reconfig_waitrequest waitrequest Output 1 + glue_add_if_port $num_of_lanes reconfig_avmm reconfig_write write Input 1 + glue_add_if_port $num_of_lanes reconfig_avmm reconfig_writedata writedata Input 32 + + if {[get_parameter TX_OR_RX_N]} { + glue_add_if $num_of_lanes tx_clkout clock source + glue_add_if_port $num_of_lanes tx_clkout tx_clkout clk Output 1 + + glue_add_if $num_of_lanes tx_coreclkin clock sink true + glue_add_if_port $num_of_lanes tx_coreclkin tx_coreclkin clk Input 1 true + + glue_add_if $num_of_lanes tx_serial_clk0 hssi_serial_clock sink true + glue_add_if_port $num_of_lanes tx_serial_clk0 tx_serial_clk0 clk Input 1 true + + if {$soft_pcs} { + set unused_width [expr $num_of_lanes * 88] + + glue_add_const_conduit tx_enh_data_valid $num_of_lanes + + for {set i 0} {$i < $num_of_lanes} {incr i} { + add_interface tx_raw_data_${i} conduit start + } + glue_add_if_port_conduit $num_of_lanes tx_raw_data raw_data tx_parallel_data Input 40 + } else { + set unused_width [expr $num_of_lanes * 92] + + for {set i 0} {$i < $num_of_lanes} {incr i} { + add_interface tx_phy_${i} conduit start + } + glue_add_if_port_conduit $num_of_lanes tx_phy char tx_parallel_data Input 32 + glue_add_if_port_conduit $num_of_lanes tx_phy charisk tx_datak Input 4 + } + + glue_add_const_conduit unused_tx_parallel_data $unused_width + } else { + glue_add_if 1 rx_cdr_refclk0 clock sink true + glue_add_if_port 1 rx_cdr_refclk0 rx_cdr_refclk0 clk Input 1 true + + glue_add_if $num_of_lanes rx_coreclkin clock sink true + glue_add_if_port $num_of_lanes rx_coreclkin rx_coreclkin clk Input 1 true + + glue_add_if $num_of_lanes rx_clkout clock source + glue_add_if_port $num_of_lanes rx_clkout rx_clkout clk Output 1 + + if {$soft_pcs} { + for {set i 0} {$i < $num_of_lanes} {incr i} { + add_interface rx_raw_data_${i} conduit start + } + glue_add_if_port_conduit $num_of_lanes rx_raw_data raw_data rx_parallel_data Output 40 + } else { + for {set i 0} {$i < $num_of_lanes} {incr i} { + add_interface rx_phy_${i} conduit start + } + glue_add_if_port_conduit $num_of_lanes rx_phy char rx_parallel_data Output 32 + glue_add_if_port_conduit $num_of_lanes rx_phy charisk rx_datak Output 4 + glue_add_if_port_conduit $num_of_lanes rx_phy disperr rx_disperr Output 4 + glue_add_if_port_conduit $num_of_lanes rx_phy notintable rx_errdetect Output 4 + glue_add_if_port_conduit $num_of_lanes rx_phy patternalign_en rx_std_wa_patternalign Input 1 + } + + add_interface const_out conduit end + add_interface_port const_out const_out const_out Output 1 + set_port_property const_out TERMINATION true + set const_offset 1 + } + + set_interface_property reconfig_reset associatedClock reconfig_clk + set_interface_property reconfig_reset synchronousEdges DEASSERT + + set_parameter_value WIDTH $sig_offset + set_parameter_value CONST_WIDTH $const_offset +} diff --git a/library/altera/jesd204_phy/jesd204_phy_hw.tcl b/library/altera/jesd204_phy/jesd204_phy_hw.tcl new file mode 100644 index 000000000..82bc13dbd --- /dev/null +++ b/library/altera/jesd204_phy/jesd204_phy_hw.tcl @@ -0,0 +1,228 @@ +# +# 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 +# . +# +# 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 $ad_hdl_dir/library/scripts/adi_ip_alt.tcl + +# +# Instantiates the Arria 10 native PHY and configures it for JESD204 operation. +# The datapath width is configured for 4 octets per beat. +# +# Optionally a soft-logic PCS is instantiated, this can be used if the lane rate +# is too high for the hard-logic PCS. +# + +ad_ip_create jesd204_phy "ADI JESD204 PHY" +set_module_property COMPOSITION_CALLBACK jesd204_phy_composition_callback +set_module_property INTERNAL true + +# parameters + +ad_ip_parameter ID NATURAL 0 false +ad_ip_parameter SOFT_PCS BOOLEAN false false +ad_ip_parameter TX_OR_RX_N BOOLEAN false false +ad_ip_parameter LANE_RATE FLOAT 10000 false +ad_ip_parameter REFCLK_FREQUENCY FLOAT 500.0 false +ad_ip_parameter NUM_OF_LANES POSITIVE 4 false + +proc jesd204_phy_composition_callback {} { + set soft_pcs [get_parameter_value "SOFT_PCS"] + set tx [get_parameter_value "TX_OR_RX_N"] + set lane_rate [get_parameter_value "LANE_RATE"] + set refclk_frequency [get_parameter_value "REFCLK_FREQUENCY"] + set id [get_parameter_value "ID"] + set num_of_lanes [get_parameter_value "NUM_OF_LANES"] + + set link_clk_frequency [expr $lane_rate / 40] + + add_instance link_clock clock_source + set_instance_parameter_value link_clock {clockFrequency} [expr $link_clk_frequency*1000000] + add_interface link_clk clock sink + set_interface_property link_clk EXPORT_OF link_clock.clk_in + add_interface link_reset reset sink + set_interface_property link_reset EXPORT_OF link_clock.clk_in_reset + + add_instance native_phy altera_xcvr_native_a10 + set_instance_property native_phy SUPPRESS_ALL_WARNINGS true + set_instance_property native_phy SUPPRESS_ALL_INFO_MESSAGES true + if {$soft_pcs} { + set_instance_parameter_value native_phy {protocol_mode} "basic_enh" + } else { + set_instance_parameter_value native_phy {protocol_mode} "basic_std" + set_instance_parameter_value native_phy {std_pcs_pma_width} 20 + + if {$tx} { + set_instance_parameter_value native_phy {std_tx_byte_ser_mode} "Serialize x2" + set_instance_parameter_value native_phy {std_tx_8b10b_enable} 1 + } else { + set_instance_parameter_value native_phy {std_rx_byte_deser_mode} "Deserialize x2" + set_instance_parameter_value native_phy {std_rx_8b10b_enable} 1 + set_instance_parameter_value native_phy {std_rx_word_aligner_mode} "manual (PLD controlled)" + set_instance_parameter_value native_phy {std_rx_word_aligner_pattern_len} 20 + set_instance_parameter_value native_phy {std_rx_word_aligner_pattern} 0xA0D7C + set_instance_parameter_value native_phy {enable_port_rx_std_wa_patternalign} 1 + } + } + + if {$tx} { + set_instance_parameter_value native_phy {duplex_mode} "tx" + set_instance_parameter_value native_phy {bonded_mode} "not_bonded" + set_instance_parameter_value native_phy {enable_port_tx_pma_elecidle} 0 + set_instance_parameter_value native_phy {enh_txfifo_mode} "Phase compensation" + } else { + set_instance_parameter_value native_phy {duplex_mode} "rx" + set_instance_parameter_value native_phy {set_cdr_refclk_freq} $refclk_frequency + set_instance_parameter_value native_phy {enable_port_rx_is_lockedtodata} 1 + set_instance_parameter_value native_phy {enable_port_rx_is_lockedtoref} 0 + set_instance_parameter_value native_phy {enable_ports_rx_manual_cdr_mode} 0 + set_instance_parameter_value native_phy {enh_rxfifo_mode} "Phase compensation" + } + + set_instance_parameter_value native_phy {channels} $num_of_lanes + set_instance_parameter_value native_phy {set_data_rate} $lane_rate + set_instance_parameter_value native_phy {enable_simple_interface} 1 + set_instance_parameter_value native_phy {enh_pcs_pma_width} 40 + set_instance_parameter_value native_phy {enh_pld_pcs_width} 40 + set_instance_parameter_value native_phy {rcfg_enable} 1 + set_instance_parameter_value native_phy {rcfg_shared} 0 + set_instance_parameter_value native_phy {rcfg_jtag_enable} 0 + set_instance_parameter_value native_phy {rcfg_sv_file_enable} 0 + set_instance_parameter_value native_phy {rcfg_h_file_enable} 0 + set_instance_parameter_value native_phy {rcfg_mif_file_enable} 0 + set_instance_parameter_value native_phy {set_user_identifier} $id + set_instance_parameter_value native_phy {set_capability_reg_enable} 1 + set_instance_parameter_value native_phy {set_csr_soft_logic_enable} 1 + set_instance_parameter_value native_phy {set_prbs_soft_logic_enable} 0 + + add_instance phy_glue jesd204_phy_glue + set_instance_parameter_value phy_glue TX_OR_RX_N $tx + set_instance_parameter_value phy_glue SOFT_PCS $soft_pcs + set_instance_parameter_value phy_glue NUM_OF_LANES $num_of_lanes + + add_interface reconfig_clk clock sink + set_interface_property reconfig_clk EXPORT_OF phy_glue.reconfig_clk + + add_interface reconfig_reset reset sink + set_interface_property reconfig_reset EXPORT_OF phy_glue.reconfig_reset + + if {$tx} { + add_interface serial_clk hssi_serial_clock end + set_interface_property serial_clk EXPORT_OF phy_glue.tx_serial_clk0 + + add_connection link_clock.clk phy_glue.tx_coreclkin + + if {$soft_pcs} { + add_connection phy_glue.phy_tx_enh_data_valid native_phy.tx_enh_data_valid + } + + foreach x {reconfig_clk reconfig_reset reconfig_avmm tx_coreclkin \ + tx_clkout tx_serial_clk0 tx_parallel_data unused_tx_parallel_data} { + add_connection phy_glue.phy_${x} native_phy.${x} + } + + foreach x {serial_data analogreset digitalreset cal_busy} { + add_interface ${x} conduit end + set_interface_property ${x} EXPORT_OF native_phy.tx_${x} + } + + if {$soft_pcs == false} { + add_connection phy_glue.phy_tx_datak native_phy.tx_datak + } + } else { + add_interface ref_clk clock sink + set_interface_property ref_clk EXPORT_OF phy_glue.rx_cdr_refclk0 + + add_connection link_clock.clk phy_glue.rx_coreclkin + + foreach x {serial_data analogreset digitalreset cal_busy is_lockedtodata} { + add_interface ${x} conduit end + set_interface_property ${x} EXPORT_OF native_phy.rx_${x} + } + + foreach x {reconfig_clk reconfig_reset reconfig_avmm rx_coreclkin \ + rx_clkout rx_parallel_data rx_cdr_refclk0} { + add_connection phy_glue.phy_${x} native_phy.${x} + } + + if {$soft_pcs == false} { + foreach x {rx_datak rx_disperr rx_errdetect rx_std_wa_patternalign} { + add_connection phy_glue.phy_${x} native_phy.${x} + } + } + } + + for {set i 0} {$i < $num_of_lanes} {incr i} { + add_interface reconfig_avmm_${i} avalon slave + set_interface_property reconfig_avmm_${i} EXPORT_OF phy_glue.reconfig_avmm_${i} + + add_interface phy_${i} conduit start + + if {$tx} { + if {$soft_pcs} { + add_instance soft_pcs_${i} jesd204_soft_pcs_tx + add_connection link_clock.clk soft_pcs_${i}.clock + add_connection link_clock.clk_reset soft_pcs_${i}.reset + add_connection soft_pcs_${i}.tx_raw_data phy_glue.tx_raw_data_${i} + + set_interface_property phy_${i} EXPORT_OF soft_pcs_${i}.tx_phy + } else { + set_interface_property phy_${i} EXPORT_OF phy_glue.tx_phy_${i} + } + } else { + + if {$soft_pcs} { + add_instance soft_pcs_${i} jesd204_soft_pcs_rx + add_connection link_clock.clk soft_pcs_${i}.clock + add_connection link_clock.clk_reset soft_pcs_${i}.reset + add_connection phy_glue.rx_raw_data_${i} soft_pcs_${i}.rx_raw_data + + set_interface_property phy_${i} EXPORT_OF soft_pcs_${i}.rx_phy + } else { + set_interface_property phy_${i} EXPORT_OF phy_glue.rx_phy_${i} + } + } + } +}