altera/alt_serdes: Add support for Cyclone V

main
AndreiGrozav 2016-10-25 20:19:39 +03:00
parent 08cef5a745
commit 6f611e0d10
4 changed files with 340 additions and 88 deletions

View File

@ -41,6 +41,12 @@ set_parameter_property CLKIN_FREQUENCY HDL_PARAMETER false
# these paramteres are needed just because of cross-platform requirments
# are NOT used in the core
add_parameter DEVICE_FAMILY STRING
set_parameter_property DEVICE_FAMILY SYSTEM_INFO {DEVICE_FAMILY}
set_parameter_property DEVICE_FAMILY AFFECTS_GENERATION true
set_parameter_property DEVICE_FAMILY HDL_PARAMETER false
set_parameter_property DEVICE_FAMILY ENABLED false
add_parameter DEVICE_TYPE INTEGER 0
set_parameter_property DEVICE_TYPE DISPLAY_NAME DEVICE_TYPE
set_parameter_property DEVICE_TYPE TYPE INTEGER
@ -95,6 +101,7 @@ proc p_alt_serdes {} {
set m_ddr_or_sdr_n [get_parameter_value "DDR_OR_SDR_N"]
set m_serdes_factor [get_parameter_value "SERDES_FACTOR"]
set m_clkin_frequency [get_parameter_value "CLKIN_FREQUENCY"]
set m_device_family [get_parameter_value DEVICE_FAMILY]
set m_hs_data_rate [expr ($m_clkin_frequency * ($m_ddr_or_sdr_n + 1))]
set m_ls_data_rate [expr ($m_hs_data_rate/$m_serdes_factor)]
@ -109,47 +116,93 @@ proc p_alt_serdes {} {
if {$m_mode == "CLK"} {
add_instance alt_serdes_pll altera_iopll
set_instance_parameter_value alt_serdes_pll {gui_reference_clock_frequency} $m_clkin_frequency
set_instance_parameter_value alt_serdes_pll {gui_use_locked} {1}
set_instance_parameter_value alt_serdes_pll {gui_operation_mode} {lvds}
set_instance_parameter_value alt_serdes_pll {gui_en_lvds_ports} {Enable LVDS_CLK/LOADEN 0}
set_instance_parameter_value alt_serdes_pll {gui_en_phout_ports} {true}
set_instance_parameter_value alt_serdes_pll {gui_en_reconf} {true}
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency0} $m_hs_data_rate
set_instance_parameter_value alt_serdes_pll {gui_ps_units0} {degrees}
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg0} {180.0}
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency1} $m_ls_data_rate
set_instance_parameter_value alt_serdes_pll {gui_ps_units1} {degrees}
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg1} $m_ld_phase
set_instance_parameter_value alt_serdes_pll {gui_duty_cycle1} $m_ld_duty_cycle
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency2} $m_ls_data_rate
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg2} $m_ls_phase
set_instance_parameter_value alt_serdes_pll {gui_ps_units2} {degrees}
add_interface rst reset sink
set_interface_property rst EXPORT_OF alt_serdes_pll.reset
add_interface ref_clk clock sink
set_interface_property ref_clk EXPORT_OF alt_serdes_pll.refclk
add_interface locked conduit end
set_interface_property locked EXPORT_OF alt_serdes_pll.locked
add_interface hs_phase conduit end
set_interface_property hs_phase EXPORT_OF alt_serdes_pll.phout
add_interface hs_clk conduit end
set_interface_property hs_clk EXPORT_OF alt_serdes_pll.lvds_clk
add_interface loaden conduit end
set_interface_property loaden EXPORT_OF alt_serdes_pll.loaden
add_interface ls_clk clock source
set_interface_property ls_clk EXPORT_OF alt_serdes_pll.outclk2
if {$m_device_family == "Arria 10"} {
add_instance alt_serdes_pll altera_iopll
set_instance_parameter_value alt_serdes_pll {gui_reference_clock_frequency} $m_clkin_frequency
set_instance_parameter_value alt_serdes_pll {gui_use_locked} {1}
set_instance_parameter_value alt_serdes_pll {gui_operation_mode} {lvds}
set_instance_parameter_value alt_serdes_pll {gui_en_lvds_ports} {Enable LVDS_CLK/LOADEN 0}
set_instance_parameter_value alt_serdes_pll {gui_en_phout_ports} {true}
set_instance_parameter_value alt_serdes_pll {gui_en_reconf} {true}
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency0} $m_hs_data_rate
set_instance_parameter_value alt_serdes_pll {gui_ps_units0} {degrees}
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg0} {180.0}
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency1} $m_ls_data_rate
set_instance_parameter_value alt_serdes_pll {gui_ps_units1} {degrees}
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg1} $m_ld_phase
set_instance_parameter_value alt_serdes_pll {gui_duty_cycle1} $m_ld_duty_cycle
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency2} $m_ls_data_rate
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg2} $m_ls_phase
set_instance_parameter_value alt_serdes_pll {gui_ps_units2} {degrees}
add_interface rst reset sink
set_interface_property rst EXPORT_OF alt_serdes_pll.reset
add_interface ref_clk clock sink
set_interface_property ref_clk EXPORT_OF alt_serdes_pll.refclk
add_interface locked conduit end
set_interface_property locked EXPORT_OF alt_serdes_pll.locked
add_interface hs_phase conduit end
set_interface_property hs_phase EXPORT_OF alt_serdes_pll.phout
add_interface hs_clk conduit end
set_interface_property hs_clk EXPORT_OF alt_serdes_pll.lvds_clk
add_interface loaden conduit end
set_interface_property loaden EXPORT_OF alt_serdes_pll.loaden
add_interface ls_clk clock source
set_interface_property ls_clk EXPORT_OF alt_serdes_pll.outclk2
add_instance alt_serdes_pll_reconfig altera_pll_reconfig
add_connection alt_serdes_pll.reconfig_from_pll alt_serdes_pll_reconfig.reconfig_from_pll
add_connection alt_serdes_pll_reconfig.reconfig_to_pll alt_serdes_pll.reconfig_to_pll
add_interface drp_clk clock sink
set_interface_property drp_clk EXPORT_OF alt_serdes_pll_reconfig.mgmt_clk
add_interface drp_rst reset sink
set_interface_property drp_rst EXPORT_OF alt_serdes_pll_reconfig.mgmt_reset
add_interface pll_reconfig avalon slave
set_interface_property pll_reconfig EXPORT_OF alt_serdes_pll_reconfig.mgmt_avalon_slave
add_instance alt_serdes_pll_reconfig altera_pll_reconfig
add_connection alt_serdes_pll.reconfig_from_pll alt_serdes_pll_reconfig.reconfig_from_pll
add_connection alt_serdes_pll_reconfig.reconfig_to_pll alt_serdes_pll.reconfig_to_pll
add_interface drp_clk clock sink
set_interface_property drp_clk EXPORT_OF alt_serdes_pll_reconfig.mgmt_clk
add_interface drp_rst reset sink
set_interface_property drp_rst EXPORT_OF alt_serdes_pll_reconfig.mgmt_reset
add_interface pll_reconfig avalon slave
set_interface_property pll_reconfig EXPORT_OF alt_serdes_pll_reconfig.mgmt_avalon_slave
}
if {$m_device_family == "Cyclone V"} {
add_instance alt_serdes_pll altera_pll
set_instance_parameter_value alt_serdes_pll {gui_reference_clock_frequency} $m_clkin_frequency
set_instance_parameter_value alt_serdes_pll {gui_use_locked} {1}
set_instance_parameter_value alt_serdes_pll {gui_operation_mode} {lvds}
set_instance_parameter_value alt_serdes_pll {gui_number_of_clocks} {3}
set_instance_parameter_value alt_serdes_pll {gui_en_phout_ports} {true}
set_instance_parameter_value alt_serdes_pll {gui_en_reconf} {true}
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency0} $m_hs_data_rate
set_instance_parameter_value alt_serdes_pll {gui_ps_units0} {degrees}
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg0} {180.0}
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency1} $m_ls_data_rate
set_instance_parameter_value alt_serdes_pll {gui_ps_units1} {degrees}
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg1} $m_ld_phase
set_instance_parameter_value alt_serdes_pll {gui_duty_cycle1} $m_ld_duty_cycle
set_instance_parameter_value alt_serdes_pll {gui_output_clock_frequency2} $m_ls_data_rate
set_instance_parameter_value alt_serdes_pll {gui_phase_shift_deg2} $m_ls_phase
set_instance_parameter_value alt_serdes_pll {gui_ps_units2} {degrees}
add_interface rst reset sink
set_interface_property rst EXPORT_OF alt_serdes_pll.reset
add_interface ref_clk clock sink
set_interface_property ref_clk EXPORT_OF alt_serdes_pll.refclk
add_interface locked conduit end
set_interface_property locked EXPORT_OF alt_serdes_pll.locked
add_interface hs_phase conduit end
set_interface_property hs_phase EXPORT_OF alt_serdes_pll.phout
add_interface hs_clk clock source
set_interface_property hs_clk EXPORT_OF alt_serdes_pll.outclk0
add_interface loaden clock source
set_interface_property loaden EXPORT_OF alt_serdes_pll.outclk1
add_interface ls_clk clock source
set_interface_property ls_clk EXPORT_OF alt_serdes_pll.outclk2
add_instance alt_serdes_pll_reconfig altera_pll_reconfig
add_connection alt_serdes_pll.reconfig_from_pll alt_serdes_pll_reconfig.reconfig_from_pll
add_connection alt_serdes_pll_reconfig.reconfig_to_pll alt_serdes_pll.reconfig_to_pll
add_interface drp_clk clock sink
set_interface_property drp_clk EXPORT_OF alt_serdes_pll_reconfig.mgmt_clk
add_interface drp_rst reset sink
set_interface_property drp_rst EXPORT_OF alt_serdes_pll_reconfig.mgmt_reset
add_interface pll_reconfig avalon slave
set_interface_property pll_reconfig EXPORT_OF alt_serdes_pll_reconfig.mgmt_avalon_slave
}
}
if {$m_mode == "IN"} {

View File

@ -38,7 +38,11 @@
`timescale 1ps/1ps
module ad_serdes_clk (
module ad_serdes_clk #(
// parameters
parameter DEVICE_TYPE = 0 ) (
// clock and divided clock
@ -64,6 +68,10 @@ module ad_serdes_clk (
output up_drp_ready,
output up_drp_locked);
// local parameter
localparam C5SOC = 1;
// internal registers
reg up_drp_sel_int = 'd0;
@ -81,6 +89,8 @@ module ad_serdes_clk (
wire [31:0] up_drp_rdata_int_s;
wire up_drp_busy_int_s;
wire up_drp_locked_int_s;
wire buf_loaden;
wire buf_lvdsclk;
// defaults
@ -134,25 +144,53 @@ module ad_serdes_clk (
end
end
// instantiations (ip- hw.tcl must generate this core)
generate
if (DEVICE_TYPE == C5SOC) begin
alt_serdes_clk_core i_core (
.rst_reset (rst),
.ref_clk_clk (clk_in_p),
.locked_export (up_drp_locked_int_s),
.hs_phase_phout (phase),
.hs_clk_clk (buf_lvdsclk),
.loaden_clk (buf_loaden),
.ls_clk_clk (div_clk),
.drp_clk_clk (up_clk),
.drp_rst_reset (up_drp_reset),
.pll_reconfig_waitrequest (up_drp_busy_int_s),
.pll_reconfig_read (up_drp_rd_int),
.pll_reconfig_write (up_drp_wr_int),
.pll_reconfig_readdata (up_drp_rdata_int_s),
.pll_reconfig_address (up_drp_addr_int),
.pll_reconfig_writedata (up_drp_wdata_int));
alt_serdes_clk_core i_core (
.rst_reset (rst),
.ref_clk_clk (clk_in_p),
.locked_export (up_drp_locked_int_s),
.hs_phase_phout (phase),
.hs_clk_lvds_clk (clk),
.loaden_loaden (loaden),
.ls_clk_clk (div_clk),
.drp_clk_clk (up_clk),
.drp_rst_reset (up_drp_reset),
.pll_reconfig_waitrequest (up_drp_busy_int_s),
.pll_reconfig_read (up_drp_rd_int),
.pll_reconfig_write (up_drp_wr_int),
.pll_reconfig_readdata (up_drp_rdata_int_s),
.pll_reconfig_address (up_drp_addr_int),
.pll_reconfig_writedata (up_drp_wdata_int));
// clock buffer
cyclonev_pll_lvds_output #(
.pll_loaden_enable_disable("true"),
.pll_lvdsclk_enable_disable("true"))
cyclonev_pll_lvds_output_inst (
.ccout({buf_loaden, buf_lvdsclk}),
.loaden(loaden),
.lvdsclk(clk));
end else begin
alt_serdes_clk_core i_core (
.rst_reset (rst),
.ref_clk_clk (clk_in_p),
.locked_export (up_drp_locked_int_s),
.hs_phase_phout (phase),
.hs_clk_lvds_clk (clk),
.loaden_loaden (loaden),
.ls_clk_clk (div_clk),
.drp_clk_clk (up_clk),
.drp_rst_reset (up_drp_reset),
.pll_reconfig_waitrequest (up_drp_busy_int_s),
.pll_reconfig_read (up_drp_rd_int),
.pll_reconfig_write (up_drp_wr_int),
.pll_reconfig_readdata (up_drp_rdata_int_s),
.pll_reconfig_address (up_drp_addr_int),
.pll_reconfig_writedata (up_drp_wdata_int));
end
endgenerate
endmodule
// ***************************************************************************

View File

@ -81,6 +81,10 @@ module ad_serdes_in #(
input delay_rst,
output delay_locked);
// local parameter
localparam C5SOC = 1;
// internal signals
wire [(DATA_WIDTH-1):0] delay_locked_s;
@ -109,22 +113,117 @@ module ad_serdes_in #(
for (l_order = 0; l_order < SERDES_FACTOR; l_order = l_order + 1) begin: g_order
assign data_sel_s[l_order][l_inst] = data_out_s[8 - SERDES_FACTOR + l_order][l_inst];
end
alt_serdes_in_core i_core (
.clk_export (clk),
.div_clk_export (div_clk),
.hs_phase_export (phase),
.loaden_export (loaden),
.locked_export (locked),
.data_in_export (data_in_p[l_inst]),
.data_s_export ({data_out_s[0][l_inst],
data_out_s[1][l_inst],
data_out_s[2][l_inst],
data_out_s[3][l_inst],
data_out_s[4][l_inst],
data_out_s[5][l_inst],
data_out_s[6][l_inst],
data_out_s[7][l_inst]}),
.delay_locked_export (delay_locked_s[l_inst]));
if (DEVICE_TYPE == C5SOC ) begin
altlvds_rx #(
.buffer_implementation ("RAM"),
.cds_mode ("UNUSED"),
.common_rx_tx_pll ("ON"),
.data_align_rollover (4),
.data_rate ("500.0 Mbps"),
.deserialization_factor (4),
.dpa_initial_phase_value (0),
.dpll_lock_count (0),
.dpll_lock_window (0),
.enable_clock_pin_mode ("UNUSED"),
.enable_dpa_align_to_rising_edge_only ("OFF"),
.enable_dpa_calibration ("ON"),
.enable_dpa_fifo ("UNUSED"),
.enable_dpa_initial_phase_selection ("OFF"),
.enable_dpa_mode ("OFF"),
.enable_dpa_pll_calibration ("OFF"),
.enable_soft_cdr_mode ("OFF"),
.implement_in_les ("OFF"),
.inclock_boost (0),
.inclock_data_alignment ("EDGE_ALIGNED"),
.inclock_period (4000),
.inclock_phase_shift (0),
.input_data_rate (500),
.intended_device_family ("Cyclone V"),
.lose_lock_on_one_change ("UNUSED"),
.lpm_hint ("CBX_MODULE_PREFIX=ad_serdes_in"),
.lpm_type ("altlvds_rx"),
.number_of_channels (DATA_WIDTH),
.outclock_resource ("Regional clock"),
.pll_operation_mode ("NORMAL"),
.pll_self_reset_on_loss_lock ("UNUSED"),
.port_rx_channel_data_align ("PORT_UNUSED"),
.port_rx_data_align ("PORT_UNUSED"),
.refclk_frequency ("250.000000 MHz"),
.registered_data_align_input ("UNUSED"),
.registered_output ("ON"),
.reset_fifo_at_first_lock ("UNUSED"),
.rx_align_data_reg ("RISING_EDGE"),
.sim_dpa_is_negative_ppm_drift ("OFF"),
.sim_dpa_net_ppm_variation (0),
.sim_dpa_output_clock_phase_shift (0),
.use_coreclock_input ("OFF"),
.use_dpll_rawperror ("OFF"),
.use_external_pll ("ON"),
.use_no_phase_shift ("ON"),
.x_on_bitslip ("ON"),
.clk_src_is_pll ("off"))
i_altlvds_rx (
.rx_inclock (clk),
.rx_in (data_in_p[l_inst]),
.rx_outclock (),
.rx_out ({data_out_s[0][l_inst],
data_out_s[1][l_inst],
data_out_s[2][l_inst],
data_out_s[3][l_inst],
data_out_s[4][l_inst],
data_out_s[5][l_inst],
data_out_s[6][l_inst],
data_out_s[7][l_inst]}),
.rx_locked (),
.dpa_pll_cal_busy (),
.dpa_pll_recal (1'b0),
.pll_areset (~locked),
.pll_phasecounterselect (),
.pll_phasedone (1'b1),
.pll_phasestep (),
.pll_phaseupdown (),
.pll_scanclk (),
.rx_cda_max (),
.rx_cda_reset ({7{1'b0}}),
.rx_channel_data_align ({7{1'b0}}),
.rx_coreclk (1'b1),
.rx_data_align (1'b0),
.rx_data_align_reset (1'b0),
.rx_data_reset (1'b0),
.rx_deskew (1'b0),
.rx_divfwdclk (),
.rx_dpa_lock_reset ({7{1'b0}}),
.rx_dpa_locked (),
.rx_dpaclock (1'b0),
.rx_dpll_enable ({7{1'b1}}),
.rx_dpll_hold ({7{1'b0}}),
.rx_dpll_reset ({7{1'b0}}),
.rx_enable (loaden),
.rx_fifo_reset ({7{1'b0}}),
.rx_pll_enable (1'b1),
.rx_readclock (1'b0),
.rx_reset ({7{1'b0}}),
.rx_syncclock (1'b0));
end else begin
alt_serdes_in_core i_core (
.clk_export (clk),
.div_clk_export (div_clk),
.hs_phase_export (phase),
.loaden_export (loaden),
.locked_export (locked),
.data_in_export (data_in_p[l_inst]),
.data_s_export ({data_out_s[0][l_inst],
data_out_s[1][l_inst],
data_out_s[2][l_inst],
data_out_s[3][l_inst],
data_out_s[4][l_inst],
data_out_s[5][l_inst],
data_out_s[6][l_inst],
data_out_s[7][l_inst]}),
.delay_locked_export (delay_locked_s[l_inst]));
end
end
endgenerate

View File

@ -64,6 +64,10 @@ module ad_serdes_out #(
output [(DATA_WIDTH-1):0] data_out_p,
output [(DATA_WIDTH-1):0] data_out_n);
// local parameter
localparam C5SOC = 1;
// internal signals
wire [(DATA_WIDTH-1):0] data_in_s[ 7:0];
@ -94,19 +98,77 @@ module ad_serdes_out #(
genvar l_inst;
generate
for (l_inst = 0; l_inst < DATA_WIDTH; l_inst = l_inst + 1) begin: g_data
alt_serdes_out_core i_core (
.clk_export (clk),
.div_clk_export (div_clk),
.loaden_export (loaden),
.data_out_export (data_out_p[l_inst]),
.data_s_export ({data_in_s2[0][l_inst],
data_in_s2[1][l_inst],
data_in_s2[2][l_inst],
data_in_s2[3][l_inst],
data_in_s2[4][l_inst],
data_in_s2[5][l_inst],
data_in_s2[6][l_inst],
data_in_s2[7][l_inst]}));
if (DEVICE_TYPE == C5SOC) begin
altlvds_tx #(
.center_align_msb ("UNUSED"),
.common_rx_tx_pll ("ON"),
.coreclock_divide_by (1),
.data_rate ("500.0 Mbps"),
.deserialization_factor (4),
.differential_drive (0),
.enable_clock_pin_mode ("UNUSED"),
.implement_in_les ("OFF"),
.inclock_boost (0),
.inclock_data_alignment ("EDGE_ALIGNED"),
.inclock_period (4000),
.inclock_phase_shift (0),
.intended_device_family ("Cyclone V"),
.lpm_hint ("CBX_MODULE_PREFIX=ad_serdes_out"),
.lpm_type ("altlvds_tx"),
.multi_clock ("OFF"),
.number_of_channels (DATA_WIDTH),
.outclock_alignment ("EDGE_ALIGNED"),
.outclock_divide_by (2),
.outclock_duty_cycle (50),
.outclock_multiply_by (1),
.outclock_phase_shift (0),
.outclock_resource ("Regional clock"),
.output_data_rate (500),
.pll_compensation_mode ("AUTO"),
.pll_self_reset_on_loss_lock ("OFF"),
.preemphasis_setting (0),
.refclk_frequency ("250.000000 MHz"),
.registered_input ("TX_CORECLK"),
.use_external_pll ("ON"),
.use_no_phase_shift ("ON"),
.vod_setting (0),
.clk_src_is_pll ("off"))
i_altlvds_tx (
.tx_inclock (clk),
.tx_coreclock (div_clk),
.tx_in ({data_in_s2[0][l_inst],
data_in_s2[1][l_inst],
data_in_s2[2][l_inst],
data_in_s2[3][l_inst],
data_in_s2[4][l_inst],
data_in_s2[5][l_inst],
data_in_s2[6][l_inst],
data_in_s2[7][l_inst]}),
.tx_outclock (),
.tx_out (data_out_p[l_inst]),
.tx_locked (),
.pll_areset (1'b0),
.sync_inclock (1'b0),
.tx_data_reset (1'b0),
.tx_enable (loaden),
.tx_pll_enable (1'b1),
.tx_syncclock (1'b0));
end else begin
alt_serdes_out_core i_core (
.clk_export (clk),
.div_clk_export (div_clk),
.loaden_export (loaden),
.data_out_export (data_out_p[l_inst]),
.data_s_export ({data_in_s2[0][l_inst],
data_in_s2[1][l_inst],
data_in_s2[2][l_inst],
data_in_s2[3][l_inst],
data_in_s2[4][l_inst],
data_in_s2[5][l_inst],
data_in_s2[6][l_inst],
data_in_s2[7][l_inst]}));
end
end
endgenerate