From 359aff8281e145c82857878b8500cb1bffb50d44 Mon Sep 17 00:00:00 2001 From: Erik Kooistra <kooistra@astron.nl> Date: Tue, 3 Jun 2014 09:45:59 +0000 Subject: [PATCH] Ported the gigabit transceiver from tr_nonbonded phy_gx.vhd to tech_transceiver_gx_stratixiv.vhd. The tech_transceiver_gx_stratixiv.vhd is instantiated in tech_transceiver_gx.vhd when g_technology=c_tech_stratixiv. The tech_transceiver_gx.vhd is the technology independent component for the user. --- libraries/technology/transceiver/hdllib.cfg | 18 + .../tech_transceiver_component_pkg.vhd | 154 +++++ .../transceiver/tech_transceiver_gx.vhd | 81 +++ .../tech_transceiver_gx_stratixiv.vhd | 531 ++++++++++++++++++ .../transceiver/tech_transceiver_rx_align.vhd | 163 ++++++ .../transceiver/tech_transceiver_rx_order.vhd | 106 ++++ .../transceiver/tech_transceiver_rx_rst.vhd | 156 +++++ .../transceiver/tech_transceiver_tx_align.vhd | 129 +++++ .../transceiver/tech_transceiver_tx_rst.vhd | 139 +++++ 9 files changed, 1477 insertions(+) create mode 100644 libraries/technology/transceiver/hdllib.cfg create mode 100644 libraries/technology/transceiver/tech_transceiver_component_pkg.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_gx.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_gx_stratixiv.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_rx_align.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_rx_order.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_rx_rst.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_tx_align.vhd create mode 100644 libraries/technology/transceiver/tech_transceiver_tx_rst.vhd diff --git a/libraries/technology/transceiver/hdllib.cfg b/libraries/technology/transceiver/hdllib.cfg new file mode 100644 index 0000000000..9ab90cf369 --- /dev/null +++ b/libraries/technology/transceiver/hdllib.cfg @@ -0,0 +1,18 @@ +hdl_lib_name = tech_transceiver +hdl_library_clause_name = tech_transceiver_lib +hdl_lib_uses = technology ip_altera_mf ip_stratixiv_hssi + +build_sim_dir = $HDL_BUILD_DIR +build_synth_dir = + +synth_files = + tech_transceiver_component_pkg.vhd + tech_transceiver_rx_order.vhd + tech_transceiver_rx_align.vhd + tech_transceiver_rx_rst.vhd + tech_transceiver_tx_align.vhd + tech_transceiver_tx_rst.vhd + tech_transceiver_gx_stratixiv.vhd + tech_transceiver_gx.vhd + +test_bench_files = diff --git a/libraries/technology/transceiver/tech_transceiver_component_pkg.vhd b/libraries/technology/transceiver/tech_transceiver_component_pkg.vhd new file mode 100644 index 0000000000..46e268c3d3 --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_component_pkg.vhd @@ -0,0 +1,154 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +------------------------------------------------------------------------------- + +-- Purpose: IP components declarations for various devices that get wrapped by the tech components + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; + +PACKAGE tech_transceiver_component_pkg IS + + ------------------------------------------------------------------------------ + -- stratixiv_hssi + ------------------------------------------------------------------------------ + + COMPONENT ip_stratixiv_hssi_gx_generic IS + GENERIC ( + g_mbps : NATURAL; + starting_channel_number : NATURAL := 0 + ); + PORT ( + cal_blk_clk : IN STD_LOGIC ; + gxb_powerdown : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + pll_inclk : IN STD_LOGIC ; + pll_powerdown : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + reconfig_clk : IN STD_LOGIC ; + reconfig_togxb : IN STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_analogreset : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_datain : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_digitalreset : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_enapatternalign : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_seriallpbken : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + tx_ctrlenable : IN STD_LOGIC_VECTOR (3 DOWNTO 0); + tx_datain : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + tx_digitalreset : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + pll_locked : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + reconfig_fromgxb : OUT STD_LOGIC_VECTOR (16 DOWNTO 0); + rx_byteorderalignstatus : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_clkout : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_ctrldetect : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_dataout : OUT STD_LOGIC_VECTOR (31 DOWNTO 0); + rx_disperr : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_errdetect : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_freqlocked : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_patterndetect : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + tx_clkout : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + tx_dataout : OUT STD_LOGIC_VECTOR (0 DOWNTO 0) + ); + END COMPONENT; + + COMPONENT ip_stratixiv_hssi_tx_generic IS + GENERIC( + g_mbps : NATURAL + ); + PORT ( + cal_blk_clk : IN STD_LOGIC ; + gxb_powerdown : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + pll_inclk : IN STD_LOGIC ; + pll_powerdown : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + tx_ctrlenable : IN STD_LOGIC_VECTOR (3 DOWNTO 0); + tx_datain : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + tx_digitalreset : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + pll_locked : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + tx_clkout : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + tx_dataout : OUT STD_LOGIC_VECTOR (0 DOWNTO 0) + ); + END COMPONENT; + + COMPONENT ip_stratixiv_hssi_rx_generic IS + GENERIC ( + g_mbps : NATURAL; + starting_channel_number : NATURAL := 0 + ); + PORT ( + cal_blk_clk : IN STD_LOGIC ; + gxb_powerdown : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + reconfig_clk : IN STD_LOGIC ; + reconfig_togxb : IN STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_analogreset : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_cruclk : IN STD_LOGIC_VECTOR (0 DOWNTO 0) := (OTHERS => '0'); + rx_datain : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_digitalreset : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_enapatternalign : IN STD_LOGIC_VECTOR (0 DOWNTO 0); + reconfig_fromgxb : OUT STD_LOGIC_VECTOR (16 DOWNTO 0); + rx_byteorderalignstatus : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_clkout : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_ctrldetect : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_dataout : OUT STD_LOGIC_VECTOR (31 DOWNTO 0); + rx_disperr : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_errdetect : OUT STD_LOGIC_VECTOR (3 DOWNTO 0); + rx_freqlocked : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); + rx_patterndetect : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); + END COMPONENT; + + + ------------------------------------------------------------------------------ + -- altera_mf + ------------------------------------------------------------------------------ + + COMPONENT ip_altera_mf_gxb_reconfig_12_stratixiv IS + PORT ( + reconfig_clk : IN STD_LOGIC ; + reconfig_fromgxb : IN STD_LOGIC_VECTOR (203 DOWNTO 0); + busy : OUT STD_LOGIC ; + reconfig_togxb : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); + END COMPONENT; + + COMPONENT ip_altera_mf_gxb_reconfig_8_stratixiv IS + PORT ( + reconfig_clk : IN STD_LOGIC ; + reconfig_fromgxb : IN STD_LOGIC_VECTOR (135 DOWNTO 0); + busy : OUT STD_LOGIC ; + reconfig_togxb : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); + END COMPONENT; + + COMPONENT ip_altera_mf_gxb_reconfig_4_stratixiv IS + PORT ( + reconfig_clk : IN STD_LOGIC ; + reconfig_fromgxb : IN STD_LOGIC_VECTOR (67 DOWNTO 0); + busy : OUT STD_LOGIC ; + reconfig_togxb : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); + END COMPONENT; + + COMPONENT ip_altera_mf_gxb_reconfig_2_stratixiv IS + PORT ( + reconfig_clk : IN STD_LOGIC ; + reconfig_fromgxb : IN STD_LOGIC_VECTOR (33 DOWNTO 0); + busy : OUT STD_LOGIC ; + reconfig_togxb : OUT STD_LOGIC_VECTOR (3 DOWNTO 0) + ); + END COMPONENT; + +END tech_transceiver_component_pkg; diff --git a/libraries/technology/transceiver/tech_transceiver_gx.vhd b/libraries/technology/transceiver/tech_transceiver_gx.vhd new file mode 100644 index 0000000000..357476ca0c --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_gx.vhd @@ -0,0 +1,81 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, technology_lib, common_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.STD_LOGIC_UNSIGNED.ALL; +USE work.tech_transceiver_component_pkg.ALL; +USE technology_lib.technology_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; +USE common_lib.common_pkg.ALL; +USE work.tr_nonbonded_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY tech_transceiver_gx IS + GENERIC( + g_technology : NATURAL := c_tech_select_default; + g_data_w : NATURAL := 32; -- Supported: 32, 16. + g_nof_gx : NATURAL; + g_mbps : NATURAL; -- Supported: 6250, 5000, 3125, 2500 when g_data_w=32, else 2500 when g_data_w=16 + g_sim : BOOLEAN; + g_tx : BOOLEAN; + g_rx : BOOLEAN + ); + PORT( + cal_rec_clk : IN STD_LOGIC; + tr_clk : IN STD_LOGIC; + + rx_clk : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + rx_rst : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + rx_sosi_arr : OUT t_dp_sosi_arr(g_nof_gx-1 DOWNTO 0); + rx_siso_arr : IN t_dp_siso_arr(g_nof_gx-1 DOWNTO 0); + + tx_clk : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + tx_rst : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + tx_sosi_arr : IN t_dp_sosi_arr(g_nof_gx-1 DOWNTO 0); + tx_siso_arr : OUT t_dp_siso_arr(g_nof_gx-1 DOWNTO 0); + + --Serial I/O + rx_datain : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + tx_dataout : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + + -- Ctrl&stat + tx_state : OUT STD_LOGIC_VECTOR(2*g_nof_gx-1 DOWNTO 0); + tx_align_en : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + + rx_state : OUT STD_LOGIC_VECTOR(2*g_nof_gx-1 DOWNTO 0); + rx_align_en : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0) + ); + +END tech_transceiver_gx; + +ARCHITECTURE str OF tech_transceiver_gx IS +BEGIN + + gen_stratixiv_hssi : IF g_technology=c_tech_stratixiv GENERATE + u0 : ENTITY work.tech_transceiver_gx_stratix_iv + GENERIC MAP (g_data_w, g_nof_gx, g_mbps, g_sim, g_tx, g_rx) + PORT MAP (cal_rec_clk, tr_clk, rx_clk, rx_rst, rx_sosi_arr, rx_siso_arr, tx_clk, tx_rst, tx_sosi_arr, tx_siso_arr, rx_datain, tx_dataout, tx_state, tx_align_en, rx_state, rx_align_en); + END GENERATE; + +END str; + diff --git a/libraries/technology/transceiver/tech_transceiver_gx_stratixiv.vhd b/libraries/technology/transceiver/tech_transceiver_gx_stratixiv.vhd new file mode 100644 index 0000000000..598b0e1b6a --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_gx_stratixiv.vhd @@ -0,0 +1,531 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.STD_LOGIC_UNSIGNED.ALL; +USE work.tech_transceiver_component_pkg.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +-- Declare IP libraries to ensure default binding in simulation. The IP library clause is ignored by synthesis. +LIBRARY ip_altera_mf_lib; +LIBRARY ip_stratixiv_hssi_lib; + +ENTITY tech_transceiver_gx_stratix_iv IS + GENERIC( + g_data_w : NATURAL := 32; -- Supported: 32, 16. + g_nof_gx : NATURAL; + g_mbps : NATURAL; -- Supported: 6250, 5000, 3125, 2500 when g_data_w=32, else 2500 when g_data_w=16 + g_sim : BOOLEAN; + g_tx : BOOLEAN; + g_rx : BOOLEAN + ); + PORT( + cal_rec_clk : IN STD_LOGIC; + tr_clk : IN STD_LOGIC; + + rx_clk : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + rx_rst : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + rx_sosi_arr : OUT t_dp_sosi_arr(g_nof_gx-1 DOWNTO 0); + rx_siso_arr : IN t_dp_siso_arr(g_nof_gx-1 DOWNTO 0); + + tx_clk : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + tx_rst : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + tx_sosi_arr : IN t_dp_sosi_arr(g_nof_gx-1 DOWNTO 0); + tx_siso_arr : OUT t_dp_siso_arr(g_nof_gx-1 DOWNTO 0); + + --Serial I/O + rx_datain : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + tx_dataout : OUT STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + + -- Ctrl&stat + tx_state : OUT STD_LOGIC_VECTOR(2*g_nof_gx-1 DOWNTO 0); + tx_align_en : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + + rx_state : OUT STD_LOGIC_VECTOR(2*g_nof_gx-1 DOWNTO 0); + rx_align_en : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0) + ); + +END tech_transceiver_gx_stratix_iv; + +ARCHITECTURE str OF tech_transceiver_gx_stratix_iv IS + + CONSTANT c_align_pattern_32 : STD_LOGIC_VECTOR := x"0000BC1C"; --Change in megafunction first. BC is std. comma symbol (K.28.5). + CONSTANT c_inval_pattern_32 : STD_LOGIC_VECTOR := x"3C3C3C3C"; --comma symbol K.28.1 (decoded as 3C) is used as invalid data indicator. + + CONSTANT c_align_pattern_16 : STD_LOGIC_VECTOR := x"BCBC"; --Change in megafunction first. BC is std. comma symbol (K.28.5). + CONSTANT c_inval_pattern_16 : STD_LOGIC_VECTOR := x"BCBC"; + + CONSTANT c_align_pattern : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := sel_a_b(g_data_w=16, c_align_pattern_16, c_align_pattern_32); + CONSTANT c_inval_pattern : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := sel_a_b(g_data_w=16, c_inval_pattern_16, c_inval_pattern_32); + + CONSTANT c_reconf_togxb_bus_w : NATURAL := 4; + CONSTANT c_reconf_fromgxb_bus_w : NATURAL := 17; + + CONSTANT c_nof_ctrl_bytes : NATURAL := g_data_w / c_byte_w; + + TYPE t_data_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + TYPE t_ctrl_arr IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(c_nof_ctrl_bytes-1 DOWNTO 0); + + SIGNAL reconfig_togxb : STD_LOGIC_VECTOR(c_reconf_togxb_bus_w-1 DOWNTO 0); + SIGNAL reconfig_fromgxb : STD_LOGIC_VECTOR(c_reconf_fromgxb_bus_w*g_nof_gx-1 DOWNTO 0); + + SIGNAL rx_freq_locked : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL tx_pll_locked : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL rec_busy : STD_LOGIC; + + SIGNAL trc_tx_pll_powerdown : STD_LOGIC; + SIGNAL trc_tx_digital_rst : STD_LOGIC; + + SIGNAL trc_rx_analog_rst : STD_LOGIC; + SIGNAL trc_rx_digital_rst : STD_LOGIC; + + SIGNAL i_tx_clk : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + SIGNAL i_rx_clk : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + + SIGNAL i_tx_rst : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + SIGNAL i_rx_rst : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + + SIGNAL tr_rst : STD_LOGIC; + + SIGNAL trc_tx_rdy : STD_LOGIC; + SIGNAL trc_rx_rdy : STD_LOGIC; + + SIGNAL not_trc_tx_rdy : STD_LOGIC; + SIGNAL not_trc_rx_rdy : STD_LOGIC; + + SIGNAL tx_align_en_out : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0) := (OTHERS=>'0'); + + SIGNAL tx_datain : t_data_arr(g_nof_gx-1 DOWNTO 0); + SIGNAL rx_dataout : t_data_arr(g_nof_gx-1 DOWNTO 0); + + SIGNAL txc_tx_ctrlenable : t_ctrl_arr(g_nof_gx-1 DOWNTO 0); + SIGNAL rxc_rx_ctrldetect : t_ctrl_arr(g_nof_gx-1 DOWNTO 0); + + SIGNAL rxc_rx_align_en : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); --edge sensitive + SIGNAL rxc_rx_aligned : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0) := (OTHERS=>'1'); + +BEGIN + + ------------------------------------------------------------------------------ + -- ALTGX Megafunction + ------------------------------------------------------------------------------ + + gen_altgx: FOR i IN 0 to g_nof_gx-1 GENERATE --Generate g_nof_gx one-channel ALTGX instances + + gen_tr : IF g_tx = TRUE AND g_rx = TRUE GENERATE --Generate duplex transceivers + + gen_32b : IF g_data_w = 32 GENERATE + u_gx: ENTITY ip_stratixiv_hssi_lib.ip_stratixiv_hssi_gx_generic + GENERIC MAP ( + g_mbps => g_mbps, + starting_channel_number => i*4 --Starting channel numbers must be 0,4,8,12 etc for individual ALTGX instances + ) --Reconfig megawizard: regenerate with 'number of channels' = 4*nof_gx + PORT MAP ( + -- Clocks, in + pll_inclk => tr_clk, + cal_blk_clk => cal_rec_clk, + reconfig_clk => cal_rec_clk, + + -- Clocks, generated (out) + sl(tx_clkout) => i_tx_clk(i), + sl(rx_clkout) => i_rx_clk(i), + + -- Parallel data I/O + rx_dataout => rx_sosi_arr(i).data(g_data_w-1 DOWNTO 0), + tx_datain => tx_datain(i), + + -- Serial data I/O + rx_datain => slv(rx_datain(i)), + sl(tx_dataout) => tx_dataout(i), + + -- Initialization I/O + sl(rx_freqlocked) => rx_freq_locked(i), + sl(pll_locked) => tx_pll_locked(i), + pll_powerdown => slv(trc_tx_pll_powerdown), + rx_digitalreset => slv(trc_rx_digital_rst), + rx_analogreset => slv(trc_rx_analog_rst), + tx_digitalreset => slv(trc_tx_digital_rst), + + -- 8b/10b related + tx_ctrlenable => txc_tx_ctrlenable(i), --8b10b + rx_ctrldetect => rxc_rx_ctrldetect(i), --8b10b + rx_enapatternalign => slv(rxc_rx_align_en(i)), + + -- Reconfig block connections + reconfig_togxb => reconfig_togxb, + reconfig_fromgxb => reconfig_fromgxb(c_reconf_fromgxb_bus_w*(i+1)-1 DOWNTO c_reconf_fromgxb_bus_w*(i+1)-c_reconf_fromgxb_bus_w), + + rx_seriallpbken => slv('0'), + gxb_powerdown => (OTHERS=>'0') + ); + END GENERATE; + + gen_16b : IF g_data_w = 16 GENERATE + u_gx: ENTITY ip_stratixiv_hssi_lib.ip_stratixiv_hssi_gx_16b + GENERIC MAP ( + starting_channel_number => i*4 --Starting channel numbers must be 0,4,8,12 etc for individual ALTGX instances + ) --Reconfig megawizard: regenerate with 'number of channels' = 4*nof_gx + PORT MAP ( + -- Clocks, in + pll_inclk => tr_clk, + cal_blk_clk => cal_rec_clk, + reconfig_clk => cal_rec_clk, + + -- Clocks, generated (out) + sl(tx_clkout) => i_tx_clk(i), + sl(rx_clkout) => i_rx_clk(i), + + -- Parallel data I/O + rx_dataout => rx_dataout(i), + tx_datain => tx_datain(i), + + -- Serial data I/O + rx_datain => slv(rx_datain(i)), + sl(tx_dataout) => tx_dataout(i), + + -- Initialization I/O + sl(rx_freqlocked) => rx_freq_locked(i), + sl(pll_locked) => tx_pll_locked(i), + pll_powerdown => slv(trc_tx_pll_powerdown), + rx_digitalreset => slv(trc_rx_digital_rst), + rx_analogreset => slv(trc_rx_analog_rst), + tx_digitalreset => slv(trc_tx_digital_rst), + + -- 8b/10b related + tx_ctrlenable => txc_tx_ctrlenable(i), --8b10b + rx_ctrldetect => rxc_rx_ctrldetect(i), --8b10b + + -- Reconfig block connections + reconfig_togxb => reconfig_togxb, + reconfig_fromgxb => reconfig_fromgxb(c_reconf_fromgxb_bus_w*(i+1)-1 DOWNTO c_reconf_fromgxb_bus_w*(i+1)-c_reconf_fromgxb_bus_w) + ); + END GENERATE; + END GENERATE; + + gen_rx : IF g_tx = FALSE AND g_rx = TRUE GENERATE --Generate receivers only + + gen_32b : IF g_data_w = 32 GENERATE + u_rx: ENTITY ip_stratixiv_hssi_lib.ip_stratixiv_hssi_rx_generic + GENERIC MAP ( + g_mbps => g_mbps, + starting_channel_number => i*4 --Starting channel numbers must be 0,4,8,12 etc for individual ALTGX instances + ) --Reconfig megawizard: regenerate with 'number of channels' = 4*nof_gx + PORT MAP ( + cal_blk_clk => cal_rec_clk, + gxb_powerdown => (OTHERS=>'0'), + reconfig_clk => cal_rec_clk, + reconfig_togxb => reconfig_togxb, + rx_analogreset => slv(trc_rx_analog_rst), + rx_datain => slv(rx_datain(i)), + rx_digitalreset => slv(trc_rx_digital_rst), + reconfig_fromgxb => reconfig_fromgxb(c_reconf_fromgxb_bus_w*(i+1)-1 DOWNTO c_reconf_fromgxb_bus_w*(i+1)-c_reconf_fromgxb_bus_w), + sl(rx_clkout) => i_rx_clk(i), + rx_ctrldetect => rxc_rx_ctrldetect(i), + rx_dataout => rx_sosi_arr(i).data(g_data_w-1 DOWNTO 0), + sl(rx_freqlocked) => rx_freq_locked(i), + rx_enapatternalign => slv(rxc_rx_align_en(i)), + + --ADDITTIONAL SIGNAL: + rx_cruclk => slv(tr_clk) + ); + END GENERATE; + + gen_16b : IF g_data_w = 16 GENERATE + u_rx: ENTITY ip_stratixiv_hssi_lib.ip_stratixiv_hssi_rx_16b + GENERIC MAP ( + starting_channel_number => i*4 --Starting channel numbers must be 0,4,8,12 etc for individual ALTGX instances + ) --Reconfig megawizard: regenerate with 'number of channels' = 4*nof_gx + PORT MAP ( + -- Clocks, in + cal_blk_clk => cal_rec_clk, + reconfig_clk => cal_rec_clk, + + -- Clocks, generated (out) + sl(rx_clkout) => i_rx_clk(i), + + -- Parallel data I/O + rx_dataout => rx_dataout(i), + + -- Serial data I/O + rx_datain => slv(rx_datain(i)), + + -- Initialization I/O + sl(rx_freqlocked) => rx_freq_locked(i), + rx_digitalreset => slv(trc_rx_digital_rst), + rx_analogreset => slv(trc_rx_analog_rst), + + -- 8b/10b related + rx_ctrldetect => rxc_rx_ctrldetect(i), --8b10b + + -- Reconfig block connections + reconfig_togxb => reconfig_togxb, + reconfig_fromgxb => reconfig_fromgxb(c_reconf_fromgxb_bus_w*(i+1)-1 DOWNTO c_reconf_fromgxb_bus_w*(i+1)-c_reconf_fromgxb_bus_w), + + --ADDITTIONAL SIGNAL: + rx_cruclk => slv(tr_clk) + ); + END GENERATE; + END GENERATE; + + gen_tx : IF g_tx = TRUE AND g_rx = FALSE GENERATE + gen_32b : IF g_data_w = 32 GENERATE + u_tx: ENTITY ip_stratixiv_hssi_lib.ip_stratixiv_hssi_tx_generic + GENERIC MAP ( + g_mbps => g_mbps + ) + PORT MAP ( + cal_blk_clk => cal_rec_clk, + gxb_powerdown => (OTHERS=>'0'), + pll_inclk => tr_clk, + pll_powerdown => slv(trc_tx_pll_powerdown), + tx_ctrlenable => txc_tx_ctrlenable(i), + tx_datain => tx_datain(i), + tx_digitalreset => slv(trc_tx_digital_rst), + sl(pll_locked) => tx_pll_locked(i), + sl(tx_clkout) => i_tx_clk(i), + sl(tx_dataout) => tx_dataout(i) + ); + END GENERATE; + + gen_16b : IF g_data_w = 16 GENERATE + u_tx: ENTITY ip_stratixiv_hssi_lib.ip_stratixiv_hssi_tx_16b + PORT MAP ( + -- Clocks, in + pll_inclk => tr_clk, + cal_blk_clk => cal_rec_clk, + + -- Clocks, generated (out) + sl(tx_clkout) => i_tx_clk(i), + + -- Parallel data I/O + tx_datain => tx_datain(i), + + -- Serial data I/O + sl(tx_dataout) => tx_dataout(i), + + -- Initialization I/O + sl(pll_locked) => tx_pll_locked(i), + pll_powerdown => slv(trc_tx_pll_powerdown), + tx_digitalreset => slv(trc_tx_digital_rst), + + -- 8b/10b related + tx_ctrlenable => txc_tx_ctrlenable(i) --8b10b + ); + END GENERATE; + END GENERATE; + END GENERATE; + + + ------------------------------------------------------------------------------ + -- Reset and alignment + ------------------------------------------------------------------------------ + + u_areset_tr_rst : ENTITY common_lib.common_areset + GENERIC MAP( + g_rst_level => '1' + ) + PORT MAP( + clk => tr_clk, + in_rst => '0', + out_rst => tr_rst + ); + + gen_tx : IF g_tx = TRUE GENERATE + + tx_clk <= i_tx_clk; + tx_rst <= i_tx_rst; + + not_trc_tx_rdy <= NOT(trc_tx_rdy); + + u_tech_transceiver_tx_rst : ENTITY work.tech_transceiver_tx_rst + GENERIC MAP( + g_nof_gx => g_nof_gx + ) + PORT MAP ( + tr_clk => tr_clk, + tr_rst => tr_rst, + trc_tx_pll_powerdown => trc_tx_pll_powerdown, + tx_pll_locked => tx_pll_locked, + trc_tx_digital_rst => trc_tx_digital_rst, + trc_tx_rdy => trc_tx_rdy + ); + + gen_altgx: FOR i IN 0 to g_nof_gx-1 GENERATE + + u_areset_tx_rst : ENTITY common_lib.common_areset + GENERIC MAP( + g_rst_level => '1' + ) + PORT MAP( + clk => i_tx_clk(i), + in_rst => not_trc_tx_rdy, + out_rst => i_tx_rst(i) + ); + + -- ALTGX in 16-bit mode supports and uses internal auto alignment state machine. + gen_tx_align: IF g_data_w=32 GENERATE + u_tech_transceiver_tx_align : ENTITY work.tech_transceiver_tx_align + GENERIC MAP( + g_sim => g_sim, + g_data_w => g_data_w, + g_mbps => g_mbps + ) + PORT MAP ( + tx_clk => i_tx_clk(i), + tx_rst => i_tx_rst(i), + tx_align_en_in => tx_align_en(i), + tx_align_en_out => tx_align_en_out(i), + tx_state => tx_state(2*i+1 DOWNTO 2*i) + ); + END GENERATE; + + -- TX is ready when it's not sending the alignment pattern + tx_siso_arr(i).ready <= NOT tx_align_en_out(i); + tx_siso_arr(i).xon <= NOT tx_align_en_out(i); + tx_datain(i) <= c_align_pattern WHEN tx_align_en_out(i) = '1' ELSE tx_sosi_arr(i).data(g_data_w-1 DOWNTO 0) WHEN tx_sosi_arr(i).valid = '1' ELSE c_inval_pattern; + txc_tx_ctrlenable(i) <= (OTHERS=>'1') WHEN tx_align_en_out(i) = '1' ELSE (OTHERS=>'0') WHEN tx_sosi_arr(i).valid = '1' ELSE (OTHERS=>'1'); + + END GENERATE; + END GENERATE; + + gen_rx : IF g_rx = TRUE GENERATE + + rx_clk <= i_rx_clk; + rx_rst <= i_rx_rst; + + u_tech_transceiver_rx_rst : ENTITY work.tech_transceiver_rx_rst + GENERIC MAP( + g_nof_gx => g_nof_gx + ) + PORT MAP ( + tr_clk => tr_clk, + tr_rst => tr_rst, + rec_busy => rec_busy, + rx_freq_locked => rx_freq_locked, + trc_rx_analog_rst => trc_rx_analog_rst, + trc_rx_digital_rst => trc_rx_digital_rst, + trc_rx_rdy => trc_rx_rdy + ); + + not_trc_rx_rdy <= NOT(trc_rx_rdy); + + i_rx_rst_align: FOR i IN 0 to g_nof_gx-1 GENERATE + + u_areset_i_rx_rst : ENTITY common_lib.common_areset + GENERIC MAP( + g_rst_level => '1' + ) + PORT MAP( + clk => i_rx_clk(i), + in_rst => not_trc_rx_rdy, + out_rst => i_rx_rst(i) + ); + + -- ALTGX in 16-bit mode supports and uses internal auto alignment state machine. + gen_rx_align: IF g_data_w=32 GENERATE + u_tech_transceiver_rx_align : ENTITY work.tech_transceiver_rx_align + GENERIC MAP( + g_sim => g_sim, + g_data_w => g_data_w, + g_mbps => g_mbps + ) + PORT MAP ( + rx_clk => i_rx_clk(i), + rx_rst => i_rx_rst(i), + rx_align_en_in => rx_align_en(i), + rx_align_en_out => rxc_rx_align_en(i), + rxc_rx_aligned => rxc_rx_aligned(i), + rx_state => rx_state(2*i+1 DOWNTO 2*i) + ); + + -- The transmitters will represent gaps as the control-encoded c_inval pattern + rx_sosi_arr(i).valid <= NOT(orv(rxc_rx_ctrldetect(i))) WHEN rxc_rx_aligned(i) = '1' ELSE '0'; + END GENERATE; + + gen_rx_order: IF g_data_w=16 GENERATE + u_tech_transceiver_rx_align : ENTITY work.tech_transceiver_rx_order + GENERIC MAP( + g_data_w => g_data_w + ) + PORT MAP ( + rx_clk => i_rx_clk(i), + rx_rst => i_rx_rst(i), + + rx_data_in => rx_dataout(i), + rx_ctrl_in => rxc_rx_ctrldetect(i), + + rx_data_out => rx_sosi_arr(i).data(g_data_w-1 DOWNTO 0), + rx_valid_out => rx_sosi_arr(i).valid + ); + END GENERATE; + END GENERATE; + END GENERATE; + + + ------------------------------------------------------------------------------ + -- ALTGX_RECONFIG Megafunction + ------------------------------------------------------------------------------ + + gen_cond_reconfig : IF g_nof_gx = 12 GENERATE + u_reconfig : ENTITY ip_altera_mf_lib.ip_altera_mf_gxb_reconfig_12_stratixiv --Create one reconfig module for all ALTGX instances + PORT MAP ( + reconfig_clk => cal_rec_clk, + reconfig_fromgxb => reconfig_fromgxb, + busy => rec_busy, + reconfig_togxb => reconfig_togxb + ); + END GENERATE; + + gen_cond_reconfig_8 : IF g_nof_gx = 8 GENERATE + u_reconfig : ENTITY ip_altera_mf_lib.ip_altera_mf_gxb_reconfig_8_stratixiv --Create one reconfig module for all ALTGX instances + PORT MAP ( + reconfig_clk => cal_rec_clk, + reconfig_fromgxb => reconfig_fromgxb, + busy => rec_busy, + reconfig_togxb => reconfig_togxb + ); + END GENERATE; + + gen_cond_reconfig_4 : IF g_nof_gx = 4 GENERATE + u_reconfig : ENTITY ip_altera_mf_lib.ip_altera_mf_gxb_reconfig_4_stratixiv --Create one reconfig module for all ALTGX instances + PORT MAP ( + reconfig_clk => cal_rec_clk, + reconfig_fromgxb => reconfig_fromgxb, + busy => rec_busy, + reconfig_togxb => reconfig_togxb + ); + END GENERATE; + + gen_cond_reconfig_sim : IF g_nof_gx = 2 GENERATE + u_reconfig_sim : ENTITY ip_altera_mf_lib.ip_altera_mf_gxb_reconfig_2_stratixiv -- The sim version is meant for 2 transceivers + PORT MAP ( + reconfig_clk => cal_rec_clk, + reconfig_fromgxb => reconfig_fromgxb, + busy => rec_busy, + reconfig_togxb => reconfig_togxb + ); + END GENERATE; + +END str; + diff --git a/libraries/technology/transceiver/tech_transceiver_rx_align.vhd b/libraries/technology/transceiver/tech_transceiver_rx_align.vhd new file mode 100644 index 0000000000..c26c78cafa --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_rx_align.vhd @@ -0,0 +1,163 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2012 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE work.tr_nonbonded_pkg.ALL; + +ENTITY tech_transceiver_rx_align IS + GENERIC( + g_sim : BOOLEAN; + g_data_w : NATURAL; + g_mbps : NATURAL + ); + PORT( + rx_clk : IN STD_LOGIC; + rx_rst : IN STD_LOGIC; + rx_align_en_in : IN STD_LOGIC; + rx_align_en_out : OUT STD_LOGIC; + rxc_rx_aligned : OUT STD_LOGIC; + rx_state : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); +END tech_transceiver_rx_align; + +ARCHITECTURE rtl OF tech_transceiver_rx_align IS + + CONSTANT c_rx_clk_freq : NATURAL := (g_mbps / g_data_w) / 10 * 8 *1000000; + + CONSTANT c_timeout_1ms : NATURAL := c_rx_clk_freq/1000; + CONSTANT c_timeout_sim : NATURAL := 100; + CONSTANT c_timeout : NATURAL := sel_a_b(g_sim, c_timeout_sim, 200*c_timeout_1ms); + CONSTANT c_timeout_w : NATURAL := ceil_log2(c_timeout); + + TYPE t_state_enum IS (s_init, s_wait, s_word_align, s_deassert_word_align, s_byte_order, s_deassert_byte_order, s_rx_aligned); + + SIGNAL state : t_state_enum; + SIGNAL nxt_state : t_state_enum; + + SIGNAL i_rx_align_en_out : STD_LOGIC; + SIGNAL nxt_rx_align_en_out : STD_LOGIC; + + SIGNAL i_rxc_rx_aligned : STD_LOGIC; + SIGNAL nxt_rxc_rx_aligned : STD_LOGIC; + + SIGNAL cycle_cnt : STD_LOGIC_VECTOR(c_timeout_w-1 DOWNTO 0); + SIGNAL nxt_cycle_cnt : STD_LOGIC_VECTOR(c_timeout_w-1 DOWNTO 0); + + SIGNAL nxt_rx_state : STD_LOGIC_VECTOR(1 DOWNTO 0); + SIGNAL i_rx_state : STD_LOGIC_VECTOR(1 DOWNTO 0); + +BEGIN + + rx_state <= i_rx_state; + + rx_align_en_out <= i_rx_align_en_out; + rxc_rx_aligned <= i_rxc_rx_aligned; + + p_clk : PROCESS(rx_rst, rx_clk) + BEGIN + IF rx_rst='1' THEN + state <= s_init; + i_rx_align_en_out <= '0'; + i_rxc_rx_aligned <= '0'; + cycle_cnt <= (OTHERS=>'0'); + i_rx_state <= (OTHERS=>'0'); + ELSIF rising_edge(rx_clk) THEN + state <= nxt_state; + i_rx_align_en_out <= nxt_rx_align_en_out; + i_rxc_rx_aligned <= nxt_rxc_rx_aligned; + cycle_cnt <= nxt_cycle_cnt; + i_rx_state <= nxt_rx_state; + END IF; + END PROCESS; + + p_state : PROCESS(state, i_rx_align_en_out, i_rxc_rx_aligned, cycle_cnt, i_rx_state, rx_align_en_in) + BEGIN + nxt_state <= state; + nxt_rx_align_en_out <= i_rx_align_en_out; + nxt_rxc_rx_aligned <= i_rxc_rx_aligned; + nxt_cycle_cnt <= cycle_cnt; + nxt_rx_state <= i_rx_state; + + CASE state IS + WHEN s_init => + nxt_state <= s_wait; + + WHEN s_wait => + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_timeout, c_timeout_w) THEN + nxt_state <= s_word_align; + nxt_cycle_cnt <= (OTHERS=>'0'); + END IF; + + WHEN s_word_align => -- First assertion of rx_align_en to perform word alignment + nxt_rx_state <= "01"; + nxt_rx_align_en_out <= '1'; + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_timeout, c_timeout_w) THEN + nxt_state <= s_deassert_word_align; + nxt_cycle_cnt <= (OTHERS=>'0'); + END IF; + + WHEN s_deassert_word_align => -- Deasssert rx_align_en, re-assert after delay + nxt_rx_align_en_out <= '0'; + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_timeout, c_timeout_w) THEN + nxt_state <= s_byte_order; + nxt_cycle_cnt <= (OTHERS=>'0'); + END IF; + + WHEN s_byte_order => -- Assert rx_align_en a second time to order the bytes + nxt_rx_state <= "10"; + nxt_rx_align_en_out <= '1'; + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_timeout, c_timeout_w) THEN + nxt_state <= s_deassert_byte_order; + nxt_cycle_cnt <= (OTHERS=>'0'); + END IF; + + WHEN s_deassert_byte_order => -- Deasssert rx_align_en + nxt_rx_align_en_out <= '0'; + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_timeout, c_timeout_w) THEN + nxt_state <= s_rx_aligned; + nxt_cycle_cnt <= (OTHERS=>'0'); + END IF; + + WHEN s_rx_aligned => -- Asserting rx_aligned on next cycle. + nxt_rx_state <= "11"; + nxt_rx_align_en_out <= '0'; + nxt_rxc_rx_aligned <= '1'; + IF rx_align_en_in = '1' THEN + nxt_state <= s_wait; + nxt_rxc_rx_aligned <= '0'; + END IF; + + WHEN OTHERS => + nxt_state <= s_init; + END CASE; + END PROCESS; + +END rtl; + diff --git a/libraries/technology/transceiver/tech_transceiver_rx_order.vhd b/libraries/technology/transceiver/tech_transceiver_rx_order.vhd new file mode 100644 index 0000000000..1f15e0a01a --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_rx_order.vhd @@ -0,0 +1,106 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2013 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY tech_transceiver_rx_order IS + GENERIC ( + g_data_w : NATURAL := 16 + ); + PORT ( + rx_clk : IN STD_LOGIC; + rx_rst : IN STD_LOGIC; + + rx_data_in : IN STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + rx_ctrl_in : IN STD_LOGIC_VECTOR(g_data_w/c_byte_w-1 DOWNTO 0); + + rx_data_out : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + rx_valid_out : OUT STD_LOGIC + ); +END ENTITY; + +ARCHITECTURE rtl OF tech_transceiver_rx_order IS + + SIGNAL in_hi_dat : STD_LOGIC_VECTOR(g_data_w/2-1 DOWNTO 0); + SIGNAL in_lo_dat : STD_LOGIC_VECTOR(g_data_w/2-1 DOWNTO 0); + SIGNAL in_hi_val : STD_LOGIC; + SIGNAL in_lo_val : STD_LOGIC; + + SIGNAL nxt_rx_data_out : STD_LOGIC_VECTOR(rx_data_out'RANGE); + SIGNAL nxt_rx_valid_out : STD_LOGIC; + SIGNAL odd_dat : STD_LOGIC_VECTOR(in_lo_dat'RANGE); + SIGNAL nxt_odd_dat : STD_LOGIC_VECTOR(odd_dat'RANGE); + SIGNAL odd_val : STD_LOGIC; + SIGNAL nxt_odd_val : STD_LOGIC; + +BEGIN + + in_hi_dat <= rx_data_in(g_data_w-1 DOWNTO g_data_w/2); + in_hi_val <= NOT rx_ctrl_in(rx_ctrl_in'HIGH); + + in_lo_dat <= rx_data_in(g_data_w/2-1 DOWNTO 0); + in_lo_val <= NOT rx_ctrl_in(rx_ctrl_in'LOW); + + regs: PROCESS (rx_rst, rx_clk) + BEGIN + IF rx_rst='1' THEN + rx_valid_out <= '0'; + rx_data_out <= (OTHERS => '0'); + odd_val <= '0'; + odd_dat <= (OTHERS => '0'); + ELSIF rising_edge(rx_clk) THEN + rx_valid_out <= nxt_rx_valid_out; + rx_data_out <= nxt_rx_data_out; + odd_val <= nxt_odd_val; + odd_dat <= nxt_odd_dat; + END IF; + END PROCESS; + + odd_proc : PROCESS (in_hi_dat, in_hi_val, in_lo_dat, in_lo_val, odd_dat, odd_val) + BEGIN + nxt_odd_val <= '0'; + + IF in_hi_val = '1' AND in_lo_val = '0' AND odd_val = '0' THEN + nxt_odd_val <= '1'; + ELSIF in_hi_val = '1' AND in_lo_val = '1' AND odd_val = '1' THEN + nxt_odd_val <= '1'; + END IF; + + nxt_odd_dat <= in_hi_dat; + END PROCESS; + + + out_proc : PROCESS (in_hi_dat, in_hi_val, in_lo_dat, in_lo_val, odd_dat, odd_val) + BEGIN + nxt_rx_valid_out <= (in_hi_val AND in_lo_val) OR (odd_val AND (in_hi_val OR in_lo_val)); + nxt_rx_data_out <= (OTHERS => '0'); + + IF odd_val='0' THEN + nxt_rx_data_out(2*g_data_w/2-1 DOWNTO 0) <= in_hi_dat & in_lo_dat; + ELSE + nxt_rx_data_out(2*g_data_w/2-1 DOWNTO 0) <= in_lo_dat & odd_dat; + END IF; + END PROCESS; + +END rtl; diff --git a/libraries/technology/transceiver/tech_transceiver_rx_rst.vhd b/libraries/technology/transceiver/tech_transceiver_rx_rst.vhd new file mode 100644 index 0000000000..97e3f487ec --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_rx_rst.vhd @@ -0,0 +1,156 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2012 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY tech_transceiver_rx_rst IS + GENERIC( + g_nof_gx : NATURAL + ); + PORT( + tr_clk : IN STD_LOGIC; + tr_rst : IN STD_LOGIC; + rec_busy : IN STD_LOGIC; + rx_freq_locked : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + trc_rx_analog_rst : OUT STD_LOGIC; + trc_rx_digital_rst : OUT STD_LOGIC; + trc_rx_rdy : OUT STD_LOGIC + ); +END tech_transceiver_rx_rst; + +ARCHITECTURE rtl OF tech_transceiver_rx_rst IS + + -- tLTD_auto: 4us. At 156.25MHz this equals 625 clock cycles. + CONSTANT c_ltd_auto : NATURAL := 625; + CONSTANT c_ltd_auto_w : NATURAL := ceil_log2(c_ltd_auto); + + TYPE t_state_enum IS (s_init, s_wait_while_busy, s_wait_for_freq_lock, s_wait_for_tltd_auto, s_rx_rdy); + + SIGNAL state : t_state_enum; + SIGNAL nxt_state : t_state_enum; + + SIGNAL i_trc_rx_digital_rst : STD_LOGIC; + SIGNAL nxt_trc_rx_digital_rst : STD_LOGIC; + + SIGNAL i_trc_rx_analog_rst : STD_LOGIC; + SIGNAL nxt_trc_rx_analog_rst : STD_LOGIC; + + SIGNAL i_trc_rx_rdy : STD_LOGIC; + SIGNAL nxt_trc_rx_rdy : STD_LOGIC; + + SIGNAL cycle_cnt : STD_LOGIC_VECTOR(c_ltd_auto_w-1 DOWNTO 0); + SIGNAL nxt_cycle_cnt : STD_LOGIC_VECTOR(c_ltd_auto_w-1 DOWNTO 0); + + SIGNAL trc_rx_freq_locked : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + SIGNAL trc_rec_busy : STD_LOGIC; + +BEGIN + + trc_rx_digital_rst <= i_trc_rx_digital_rst; + trc_rx_analog_rst <= i_trc_rx_analog_rst; + trc_rx_rdy <= i_trc_rx_rdy; + + p_clk : PROCESS(tr_rst, tr_clk) + BEGIN + IF tr_rst='1' THEN + state <= s_init; + i_trc_rx_analog_rst <= '1'; + i_trc_rx_digital_rst <= '1'; + i_trc_rx_rdy <= '0'; + cycle_cnt <= (OTHERS=>'0'); + ELSIF rising_edge(tr_clk) THEN + state <= nxt_state; + i_trc_rx_digital_rst <= nxt_trc_rx_digital_rst; + i_trc_rx_analog_rst <= nxt_trc_rx_analog_rst; + i_trc_rx_rdy <= nxt_trc_rx_rdy; + cycle_cnt <= nxt_cycle_cnt; + END IF; + END PROCESS; + + p_state : PROCESS(state, i_trc_rx_analog_rst, i_trc_rx_digital_rst, i_trc_rx_rdy, cycle_cnt, trc_rec_busy, trc_rx_freq_locked) + BEGIN + nxt_state <= state; + nxt_trc_rx_analog_rst <= i_trc_rx_analog_rst; + nxt_trc_rx_digital_rst <= i_trc_rx_digital_rst; + nxt_trc_rx_rdy <= i_trc_rx_rdy; + nxt_cycle_cnt <= cycle_cnt; + + CASE state IS + WHEN s_init => + nxt_state <= s_wait_for_freq_lock; + + WHEN s_wait_while_busy => -- Make sure there is no ALTGX reconfiguring going on. + IF trc_rec_busy = '0' THEN + nxt_state <= s_wait_for_freq_lock; + END IF; + + WHEN s_wait_for_freq_lock => -- Release analog receiver portion and wait for it to lock a an incoming frequency + nxt_trc_rx_analog_rst <= '0'; + IF andv(trc_rx_freq_locked) = '1' THEN + nxt_state <= s_wait_for_tltd_auto; + END IF; + + WHEN s_wait_for_tltd_auto => -- Wait for the parallel clock to be stable + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_ltd_auto, c_ltd_auto_w) THEN + nxt_trc_rx_digital_rst <= '0'; + nxt_state <= s_rx_rdy; + END IF; + + WHEN s_rx_rdy => -- Transmitter ready to use. + nxt_trc_rx_rdy <= '1'; + + WHEN OTHERS => + nxt_state <= s_wait_while_busy; + END CASE; + + END PROCESS; + + u_async_busy : ENTITY common_lib.common_async + GENERIC MAP( + g_rst_level => '0' + ) + PORT MAP( + rst => tr_rst, + clk => tr_clk, + din => rec_busy, + dout => trc_rec_busy + ); + + gen_asyncs: FOR i IN 0 TO g_nof_gx-1 GENERATE + u_async_rx_freqlocked: ENTITY common_lib.common_async + GENERIC MAP( + g_rst_level => '0' + ) + PORT MAP( + rst => tr_rst, + clk => tr_clk, + din => rx_freq_locked(i), + dout => trc_rx_freq_locked(i) + ); + END GENERATE; + +END rtl; + diff --git a/libraries/technology/transceiver/tech_transceiver_tx_align.vhd b/libraries/technology/transceiver/tech_transceiver_tx_align.vhd new file mode 100644 index 0000000000..662fdd72cc --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_tx_align.vhd @@ -0,0 +1,129 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2012 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE work.tr_nonbonded_pkg.ALL; + +ENTITY tech_transceiver_tx_align IS + GENERIC( + g_sim : BOOLEAN; + g_data_w : NATURAL; + g_mbps : NATURAL + ); + PORT( + tx_clk : IN STD_LOGIC; + tx_rst : IN STD_LOGIC; + tx_align_en_in : IN STD_LOGIC; + tx_align_en_out : OUT STD_LOGIC; + tx_state : OUT STD_LOGIC_VECTOR(1 DOWNTO 0) + ); +END tech_transceiver_tx_align; + +ARCHITECTURE rtl OF tech_transceiver_tx_align IS + + CONSTANT c_tx_clk_freq : NATURAL := (g_mbps / g_data_w) / 10 * 8 *1000000; + + CONSTANT c_timeout_1s : NATURAL := c_tx_clk_freq; + CONSTANT c_timeout_sim : NATURAL := 1000; + CONSTANT c_timeout : NATURAL := sel_a_b(g_sim, c_timeout_sim, 2*c_timeout_1s); + CONSTANT c_timeout_w : NATURAL := ceil_log2(c_timeout); + + TYPE t_state_enum IS (s_init, s_init_send_pattern, s_send_user_data, s_force_pattern); + + SIGNAL state : t_state_enum; + SIGNAL nxt_state : t_state_enum; + + SIGNAL i_tx_align_en : STD_LOGIC; + SIGNAL nxt_tx_align_en : STD_LOGIC; + + SIGNAL cycle_cnt : STD_LOGIC_VECTOR(c_timeout_w-1 DOWNTO 0); + SIGNAL nxt_cycle_cnt : STD_LOGIC_VECTOR(c_timeout_w-1 DOWNTO 0); + + SIGNAL nxt_tx_state : STD_LOGIC_VECTOR(1 DOWNTO 0); + SIGNAL i_tx_state : STD_LOGIC_VECTOR(1 DOWNTO 0); + +BEGIN + + tx_state <= i_tx_state; + tx_align_en_out <= i_tx_align_en; + + p_clk : PROCESS(tx_rst, tx_clk) + BEGIN + IF tx_rst='1' THEN + state <= s_init; + i_tx_align_en <= '1'; + cycle_cnt <= (OTHERS=>'0'); + i_tx_state <= (OTHERS=>'0'); + ELSIF rising_edge(tx_clk) THEN + state <= nxt_state; + i_tx_align_en <= nxt_tx_align_en; + cycle_cnt <= nxt_cycle_cnt; + i_tx_state <= nxt_tx_state; + END IF; + END PROCESS; + + p_state : PROCESS(state, i_tx_align_en, cycle_cnt, i_tx_state, tx_align_en_in) + BEGIN + nxt_state <= state; + nxt_tx_align_en <= i_tx_align_en; + nxt_cycle_cnt <= cycle_cnt; + nxt_tx_state <= i_tx_state; + + CASE state IS + WHEN s_init => + nxt_state <= s_init_send_pattern; + + WHEN s_init_send_pattern => + nxt_tx_align_en <= '1'; + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_timeout, c_timeout_w) THEN + nxt_state <= s_send_user_data; + nxt_cycle_cnt <= (OTHERS=>'0'); + END IF; + nxt_tx_state <= "01"; + + WHEN s_send_user_data => + nxt_tx_align_en <= '0'; + IF tx_align_en_in = '1' THEN + nxt_tx_align_en <= '1'; + nxt_state <= s_force_pattern; + END IF; + nxt_tx_state <= "11"; + + WHEN s_force_pattern => + nxt_tx_align_en <= '1'; + IF tx_align_en_in = '0' THEN + nxt_tx_align_en <= '0'; + nxt_state <= s_send_user_data; + END IF; + nxt_tx_state <= "10"; + + WHEN OTHERS => + nxt_state <= s_init_send_pattern; + END CASE; + END PROCESS; + +END rtl; + diff --git a/libraries/technology/transceiver/tech_transceiver_tx_rst.vhd b/libraries/technology/transceiver/tech_transceiver_tx_rst.vhd new file mode 100644 index 0000000000..d59b4367ba --- /dev/null +++ b/libraries/technology/transceiver/tech_transceiver_tx_rst.vhd @@ -0,0 +1,139 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2012 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- 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 <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY tech_transceiver_tx_rst IS + GENERIC( + g_nof_gx : NATURAL + ); + PORT( + tr_clk : IN STD_LOGIC; + tr_rst : IN STD_LOGIC; + trc_tx_pll_powerdown : OUT STD_LOGIC; + tx_pll_locked : IN STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + trc_tx_digital_rst : OUT STD_LOGIC; + trc_tx_rdy : OUT STD_LOGIC + ); +END tech_transceiver_tx_rst; + +ARCHITECTURE rtl OF tech_transceiver_tx_rst IS + + -- The minimum pulse width in to keep trc_tx_pll_powerdown asserted = 1us (stratix iv device datasheet). + -- At 156.25Mhz (6.4ns) this takes 156.25 cycles. As a lower data rate increases the tx_clk period, + -- we're already on the safe side using this value. + CONSTANT c_pll_powerdown : NATURAL := 157; -- 156.25 cycles + CONSTANT c_pll_powerdown_w : NATURAL := ceil_log2(c_pll_powerdown); + + TYPE t_state_enum IS (s_init, s_power_down_pll, s_wait_for_pll_lock, s_trc_tx_rdy); + + SIGNAL state : t_state_enum; + SIGNAL nxt_state : t_state_enum; + + SIGNAL i_trc_tx_pll_powerdown : STD_LOGIC; + SIGNAL nxt_trc_tx_pll_powerdown : STD_LOGIC; + + SIGNAL i_trc_tx_digital_rst : STD_LOGIC; + SIGNAL nxt_trc_tx_digital_rst : STD_LOGIC; + + SIGNAL i_trc_tx_rdy : STD_LOGIC; + SIGNAL nxt_trc_tx_rdy : STD_LOGIC; + + SIGNAL cycle_cnt : STD_LOGIC_VECTOR(c_pll_powerdown_w-1 DOWNTO 0); + SIGNAL nxt_cycle_cnt : STD_LOGIC_VECTOR(c_pll_powerdown_w-1 DOWNTO 0); + + SIGNAL trc_tx_pll_locked : STD_LOGIC_VECTOR(g_nof_gx-1 DOWNTO 0); + +BEGIN + + trc_tx_pll_powerdown <= i_trc_tx_pll_powerdown; + trc_tx_digital_rst <= i_trc_tx_digital_rst; + trc_tx_rdy <= i_trc_tx_rdy; + + p_clk : PROCESS(tr_rst, tr_clk) + BEGIN + IF tr_rst='1' THEN + state <= s_init; + i_trc_tx_pll_powerdown <= '1'; + i_trc_tx_digital_rst <= '1'; + i_trc_tx_rdy <= '0'; + cycle_cnt <= (OTHERS=>'0'); + ELSIF rising_edge(tr_clk) THEN + state <= nxt_state; + i_trc_tx_pll_powerdown <= nxt_trc_tx_pll_powerdown; + i_trc_tx_digital_rst <= nxt_trc_tx_digital_rst; + i_trc_tx_rdy <= nxt_trc_tx_rdy; + cycle_cnt <= nxt_cycle_cnt; + END IF; + END PROCESS; + + p_state : PROCESS(state, i_trc_tx_pll_powerdown, i_trc_tx_digital_rst, i_trc_tx_rdy, cycle_cnt, trc_tx_pll_locked) + BEGIN + nxt_state <= state; + nxt_trc_tx_pll_powerdown <= i_trc_tx_pll_powerdown; + nxt_trc_tx_digital_rst <= i_trc_tx_digital_rst; + nxt_trc_tx_rdy <= i_trc_tx_rdy; + nxt_cycle_cnt <= cycle_cnt; + + CASE state IS + WHEN s_init => + nxt_state <= s_power_down_pll; + + WHEN s_power_down_pll => -- Wait until we're sure the PLL is powered down, then power it up + nxt_cycle_cnt <= INCR_UVEC(cycle_cnt, 1); + IF cycle_cnt = TO_UVEC(c_pll_powerdown, c_pll_powerdown_w) THEN + nxt_trc_tx_pll_powerdown <= '0'; + nxt_state <= s_wait_for_pll_lock; + END IF; + + WHEN s_wait_for_pll_lock => -- Wait until PLL is locked + IF andv(trc_tx_pll_locked) = '1' THEN + nxt_trc_tx_digital_rst <= '0'; + nxt_state <= s_trc_tx_rdy; + END IF; + + WHEN s_trc_tx_rdy => -- Transmitter ready to use. + nxt_trc_tx_rdy <= '1'; + + WHEN OTHERS => + nxt_state <= s_power_down_pll; + END CASE; + END PROCESS; + + gen_asyncs: FOR i IN 0 TO g_nof_gx-1 GENERATE + u_async_pll_locked : ENTITY common_lib.common_async + GENERIC MAP( + g_rst_level => '0' + ) + PORT MAP( + rst => tr_rst, + clk => tr_clk, + din => tx_pll_locked(i), + dout => trc_tx_pll_locked(i) + ); + END GENERATE; + +END rtl; + -- GitLab