Commit 1868f086 authored by Evangelia Gousiou's avatar Evangelia Gousiou

added nanofip code as submodule;

parent 7bb81e37
......@@ -4,3 +4,6 @@
[submodule "ip_cores/general-cores"]
path = ip_cores/general-cores
url = git://ohwr.org/hdl-core-lib/general-cores.git
[submodule "ip_cores/nanofip"]
path = ip_cores/nanofip
url = git://ohwr.org/cern-fip/nanofip/nanofip-gateware.git
nanofip @ 752512a8
Subproject commit 752512a82a05ce5ac4c69ad19f68921762bdd512
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_crc |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_crc.vhd |
-- |
-- Description The unit creates the modules for: |
-- o the generation of the CRC of serial data, |
-- o the verification of an incoming CRC syndrome. |
-- The unit is instantiated in both the wf_fd_transmitter, for the generation of the |
-- FCS field of produced RP_DAT frames, and the wf_fd_receiver for the validation of |
-- of an incoming ID_DAT or consumed RP_DAT frame. |
-- |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Date 23/02/2011 |
-- Version v0.04 |
-- Depends on wf_reset_unit |
-- wf_rx_deserializer |
-- wf_tx_serializer |
---------------- |
-- Last changes |
-- 07/08/2009 v0.02 PAS Entity Ports added, start of architecture content |
-- 08/2010 v0.03 EG Data_FCS_select and crc_ready_p_o signals removed, |
-- variable v_q_check_mask replaced with a signal, |
-- code cleaned-up+commented |
-- 02/2011 v0.04 EG s_q_check_mask was not in Syndrome_Verification sensitivity list! |
-- xor replaced with if(Syndrome_Verification); processes rewritten; |
-- delay on data_bit_ready_p_i removed. |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_crc
--=================================================================================================
entity wf_crc is port(
-- INPUTS
-- nanoFIP User Interface, General signals
uclk_i : in std_logic; -- 40 MHz clock
-- Signal from the wf_reset_unit
nfip_rst_i : in std_logic; -- nanoFIP internal reset
-- Signals from the wf_rx_deserializer/ wf_tx_serializer units
data_bit_i : in std_logic; -- incoming data bit stream
data_bit_ready_p_i : in std_logic; -- indicates the sampling moment of data_bit_i
start_crc_p_i : in std_logic; -- beginning of the CRC calculation
-- OUTPUTS
-- Signal to the wf_rx_deserializer unit
crc_ok_p_o : out std_logic; -- signals a correct received CRC syndrome
-- Signal to the wf_tx_serializer unit
crc_o : out std_logic_vector (c_CRC_POLY_LGTH-1 downto 0)); -- calculated CRC
end entity wf_crc;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_crc is
signal s_q, s_q_nx : std_logic_vector (c_CRC_POLY_LGTH - 1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- CRC Calculation --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- The Gen_16_bit_Register_and_Interconnections generator, follows the scheme of figure A.1
-- of the Annex A 61158-4-7 IEC:2007 and constructs a register of 16 master-slave flip-flops which
-- are interconnected as a linear feedback shift register.
Generate_16_bit_Register_and_Interconnections:
s_q_nx(0) <= data_bit_i xor s_q(s_q'left);
G: for I in 1 to c_CRC_GENER_POLY'left generate
s_q_nx(I) <= s_q(I-1) xor (c_CRC_GENER_POLY(I) and (data_bit_i xor s_q(s_q'left)));
end generate;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Synchronous process CRC_calculation: the process "moves" the shift register described
-- above, for the calculation of the CRC.
CRC_calculation: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
s_q <= (others => '0');
else
if start_crc_p_i = '1' then
s_q <= (others => '1'); -- register initialization
-- (initially preset, according to the Annex)
elsif data_bit_ready_p_i = '1' then -- new bit to be considered for the CRC calculation
s_q <= s_q_nx; -- data propagation
end if;
end if;
end if;
end process;
-- -- -- -- --
crc_o <= not s_q;
---------------------------------------------------------------------------------------------------
-- CRC Verification --
---------------------------------------------------------------------------------------------------
-- During reception, the CRC is being calculated as data is arriving (same as in the transmission)
-- and at the same time it is being compared to the predefined c_CRC_VERIF_POLY. When the CRC
-- calculated from the received data matches the c_CRC_VERIF_POLY, it is implied that a correct CRC
-- word has been received for the preceded data and the signal crc_ok_p_o gives a 1 uclk-wide pulse.
crc_ok_p_o <= data_bit_ready_p_i when s_q = not c_CRC_VERIF_POLY else '0';
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_decr_counter |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_decr_counter.vhd |
-- Description Decreasing counter with synchronous reset, load enable and decrease enable |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 10/2010 |
-- Version v0.01 |
-- Depends on - |
---------------- |
-- Last changes |
-- 10/2010 EG v0.01 first version |
-- 10/2011 EG v0.01b nfip_rst_i renamed to counter_rst_i; counter_top renamed to |
-- counter_top_i; initial value after reset is all '1'; |
-- counter_decr_p_i renamed to counter_decr_i |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_decr_counter
--=================================================================================================
entity wf_decr_counter is
generic(g_counter_lgth : natural := 4); -- default length
port(
-- INPUTS
-- nanoFIP User Interface general signal
uclk_i : in std_logic; -- 40 MHz clock
-- Signal from the wf_reset_unit
counter_rst_i : in std_logic; -- resets counter to all '1'
-- Signals from any unit
counter_decr_i : in std_logic; -- decrement enable
counter_load_i : in std_logic; -- load enable; loads counter to counter_top_i
counter_top_i : in unsigned (g_counter_lgth-1 downto 0); -- load value
-- OUTPUTS
-- Signal to any unit
counter_o : out unsigned (g_counter_lgth-1 downto 0); -- counter
counter_is_zero_o : out std_logic); -- empty counter indication
end entity wf_decr_counter;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_decr_counter is
signal s_counter : unsigned (g_counter_lgth-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Synchronous process Decr_Counter
Decr_Counter: process (uclk_i)
begin
if rising_edge (uclk_i) then
if counter_rst_i = '1' then
s_counter <= (others => '1');
else
if counter_load_i = '1' then
s_counter <= counter_top_i;
elsif counter_decr_i = '1' then
s_counter <= s_counter - 1;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
counter_o <= s_counter;
counter_is_zero_o <= '1' when s_counter = to_unsigned(0, s_counter'length) else '0';
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_incr_counter |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_incr_counter.vhd |
-- Description Increasing counter with synchronous reinitialise and increase enable |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 01/2011 |
-- Version v0.011 |
-- Depends on - |
---------------- |
-- Last changes |
-- 10/2010 EG v0.01 first version |
-- 01/2011 EG v0.011 counter_full became a constant |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_incr_counter
--=================================================================================================
entity wf_incr_counter is
generic(g_counter_lgth : natural := 4); -- default length
port(
-- INPUTS
-- nanoFIP User Interface general signal
uclk_i : in std_logic; -- 40 MHz clock
-- Signals from any unit
counter_incr_i : in std_logic; -- increment enable
counter_reinit_i : in std_logic; -- reinitializes counter to 0
-- OUTPUT
-- Signal to any unit
counter_o : out unsigned (g_counter_lgth-1 downto 0); -- counter
counter_is_full_o : out std_logic); -- counter full indication
-- (all bits to '1')
end entity wf_incr_counter;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_incr_counter is
constant c_COUNTER_FULL : unsigned (g_counter_lgth-1 downto 0) := (others => '1');
signal s_counter : unsigned (g_counter_lgth-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Synchronous process Incr_Counter
Incr_Counter: process (uclk_i)
begin
if rising_edge (uclk_i) then
if counter_reinit_i = '1' then
s_counter <= (others => '0');
elsif counter_incr_i = '1' then
s_counter <= s_counter + 1;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
counter_o <= s_counter;
counter_is_full_o <= '1' when s_counter = c_COUNTER_FULL else '0';
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_rx_deglitcher |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_rx_deglitcher.vhd |
-- |
-- Description The unit applies a glitch filter to the nanoFIP FIELDRIVE input FD_RXD. |
-- It is capable of cleaning glitches up to c_DEGLITCH_THRESHOLD uclk ticks long. |
-- |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 14/02/2011 |
-- Version v0.03 |
-- Depends on wf_reset_unit |
---------------- |
-- Last changes |
-- 07/08/2009 v0.01 PAS Entity Ports added, start of architecture content |
-- 23/08/2010 v0.02 EG code cleaned-up+commented |
-- 14/02/2011 v0.03 EG complete change, no dependency on osc; |
-- fd_rxd deglitched right at reception |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_rx_deglitcher
--=================================================================================================
entity wf_rx_deglitcher is port(
-- INPUTS
-- nanoFIP User Interface general signal
uclk_i : in std_logic; -- 40 MHz clock
-- Signal from the wf_reset_unit
nfip_rst_i : in std_logic; -- nanoFIP internal reset
-- nanoFIP FIELDRIVE (synchronized with uclk)
fd_rxd_a_i : in std_logic; -- receiver data
-- OUTPUTS
-- Signals to the wf_rx_deserializer unit
fd_rxd_filt_o : out std_logic; -- filtered output signal
fd_rxd_filt_edge_p_o : out std_logic; -- indicates an edge on the filtered signal
fd_rxd_filt_f_edge_p_o : out std_logic);-- indicates a falling edge on the filtered signal
end wf_rx_deglitcher;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_rx_deglitcher is
signal s_fd_rxd_synch : std_logic_vector (1 downto 0);
signal s_fd_rxd_filt, s_fd_rxd_filt_d1 : std_logic;
signal s_fd_rxd_filt_r_edge_p, s_fd_rxd_filt_f_edge_p : std_logic;
signal s_filt_c : unsigned (3 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- FD_RXD synchronization --
---------------------------------------------------------------------------------------------------
-- Synchronous process FD_RXD_synchronizer: Synchronization of the nanoFIP FIELDRIVE input
-- FD_RXD to the uclk, using a set of 2 registers.
FD_RXD_synchronizer: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
s_fd_rxd_synch <= (others => '0');
else
s_fd_rxd_synch <= s_fd_rxd_synch(0) & fd_rxd_a_i;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Deglitching --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- Synchronous process FD_RXD_deglitcher: the output signal s_fd_rxd_filt is updated only
-- after the accumulation of a sufficient (c_DEGLITCH_THRESHOLD + 1) amount of identical bits.
-- The signal is therefore cleaned of any glitches up to c_DEGLITCH_THRESHOLD uclk ticks long.
FD_RXD_deglitcher: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
s_filt_c <= to_unsigned (c_DEGLITCH_THRESHOLD, s_filt_c'length) srl 1;-- middle value
s_fd_rxd_filt <= '0';
s_fd_rxd_filt_d1 <= '0';
else
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
if s_fd_rxd_synch(1) = '0' then -- arrival of a '0'
if s_filt_c /= 0 then -- counter updated
s_filt_c <= s_filt_c - 1;
else
s_fd_rxd_filt <= '0'; -- output updated
end if; -- if counter = 0
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
elsif s_fd_rxd_synch(1) = '1' then -- arrival of a '1'
if s_filt_c /= c_DEGLITCH_THRESHOLD then
s_filt_c <= s_filt_c + 1; -- counter updated
else
s_fd_rxd_filt <= '1'; -- output updated
end if; -- if counter = c_DEGLITCH_THRESHOLD
end if;
s_fd_rxd_filt_d1 <= s_fd_rxd_filt; -- used for the edges detection
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- Concurrent signal assignments
s_fd_rxd_filt_r_edge_p <= (not s_fd_rxd_filt_d1) and s_fd_rxd_filt; -- pulse upon detection
-- of a falling edge
s_fd_rxd_filt_f_edge_p <= s_fd_rxd_filt_d1 and (not s_fd_rxd_filt); -- pulse upon detection
-- of a rising edge
fd_rxd_filt_edge_p_o <= s_fd_rxd_filt_f_edge_p or s_fd_rxd_filt_r_edge_p;
fd_rxd_filt_f_edge_p_o <= s_fd_rxd_filt_f_edge_p;
fd_rxd_filt_o <= s_fd_rxd_filt;
end rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_rx_deserializer |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_rx_deserializer.vhd |
-- |
-- Description De-serialization of the deglitched "nanoFIP FIELDRIVE" input signal FD_RXD and |
-- construction of bytes of data to be provided to: |
-- o the wf_engine_control unit, for the contents of ID_DAT frames |
-- o the wf_consumption unit, for the contents of consumed RP_DAT frames. |
-- The unit is also responsible for the identification of the FSS and FES fields of |
-- ID_DAT and RP_DAT frames and the verification of their CRC. |
-- At the end of a frame (FES detection) either the fss_crc_fes_ok_p_o pulse |
-- is assserted, indicating a frame with with correct FSS, CRC and FES |
-- or the pulse crc_wrong_p_o is asserted indicating an error on the CRC. |
-- If a FES is not detected after the reception of more than 8 bytes for an ID_DAT |
-- or more than 133 bytes for a RP_DAT the unit is reset by the wf_engine_control. |
-- The unit also remains reset during data production. |
-- |
-- Remark: We refer to |
-- o a significant edge : for the edge of a manch. encoded bit |
-- (bit 0: _|-, bit 1: -|_). |
-- |
-- o a transition : for the moment in between two adjacent bits, that|
-- may or may not result in an edge (eg. a 0 followed by a 0 will give an edge: |
-- _|-|_|-, but a 0 followed by a 1 will not: _|--|_ ). |
-- |
-- o the sampling of a manch. bit: for the moments when a manch. encoded bit should |
-- be sampled, before and after a significant edge. |
-- |
-- o the sampling of a bit : for the sampling of only the 1st part, |
-- before the transition. |
-- |
-- Example: |
-- bits : 0 1 |
-- manch. encoded : _|- -|_ |
-- significant edge : ^ ^ |
-- transition : ^ |
-- sample_manch_bit_p: ^ ^ ^ ^ |
-- sample_bit_p : ^ ^ (this sampling will give the 0 and the 1) |
-- |
-- |
-- Reminder of the consumed RP_DAT frame structure: |
-- _______ _______ ______ _______ ______ ________________ _______ ___________ _______ |
-- |__PRE__|__FSD__|_CTRL_||__PDU__|_LGTH_|_..ApplicData.._|__MPS__||____FCS____|__FES__| |
-- |
-- |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 15/02/2011 |
-- Version v0.05 |
-- Depends on wf_reset_unit |
-- wf_rx_osc |
-- wf_rx_deglitcher |
-- wf_engine_control |
---------------- |
-- Last changes |
-- 09/2009 v0.01 PAS First version |
-- 10/2010 v0.02 EG state switch_to_deglitched added; |
-- output signal rx_osc_rst_o added; signals renamed; |
-- state machine rewritten (moore style); |
-- units wf_rx_manch_code_check and Incoming_Bits_Index created; |
-- each manch bit of FES checked (bf was just each bit, so any D5 was FES) |
-- code cleaned-up + commented. |
-- 12/2010 v0.03 EG CRC_ok pulse transfered 16 bits later to match the FES; |
-- like this we confirm that the CRC_ok_p arrived just before the FES, |
-- and any 2 bytes that could by chanche be seen as CRC, are neglected. |
-- FSM data_field_byte state: redundant code removed: |
-- "s_fes_wrong_bit = '1' and s_manch_code_viol_p = '1' then IDLE" |
-- code(more!)cleaned-up |
-- 01/2011 v0.04 EG changed way of detecting the FES to be able to detect a FES even if |
-- bytes with size different than 8 have preceeded. |
-- crc_wrong_p_o replaced the crc_wrong_p_o. |
-- 02/2011 v0.05 EG changed crc pulse transfer; removed switch to deglitch state |
-- s_fes_detected removed and s_byte_ready_p_d1; if bytes arrive with |
-- bits not x8, the fss_crc_fes_ok_p_o stays 0 (bc of s_byte_ready_p_d1) |
-- and the crc_wrong_p_o is asserted (bc of s_sample_manch_bit_p_d1); |
-- unit reset during production; |
-- check for code vilations completely removed! |
-- 10/2011 v0.05b EG moved session_timedout in the synchronous FSM process |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_rx_deserializer
--=================================================================================================
entity wf_rx_deserializer is port(
-- INPUTS
-- nanoFIP User Interface general signal
uclk_i : in std_logic; -- 40 MHz clock
-- Signal from the wf_reset_unit
nfip_rst_i : in std_logic; -- nanoFIP internal reset
-- Signal from the wf_engine_control unit
rx_rst_i : in std_logic; -- reset during production or
-- reset pulse when during reception a frame is rejected
-- by the engine_control (example: ID_DAT > 8 bytes,
-- RP_DAT > 133 bytes, wrong ID_DAT CTRL/ VAR/ SUBS bytes)
-- Signals from the wf_rx_deglitcher
fd_rxd_f_edge_p_i : in std_logic; -- indicates a falling edge on the deglitched FD_RXD
fd_rxd_r_edge_p_i : in std_logic; -- indicates a rising edge on the deglitched FD_RXD
fd_rxd_i : in std_logic; -- deglitched FD_RXD
-- Signals from the wf_rx_osc unit
sample_manch_bit_p_i : in std_logic; -- pulse indicating the sampling of a manch. bit
sample_bit_p_i : in std_logic; -- pulse indicating the sampling of a bit
signif_edge_window_i : in std_logic; -- time window where a significant edge is expected
adjac_bits_window_i : in std_logic; -- time window where a transition between adjacent
-- bits is expected
-- OUTPUTS
-- Signals to the wf_consumption and the wf_engine_control units
byte_o : out std_logic_vector (7 downto 0) ; -- retrieved data byte
byte_ready_p_o : out std_logic; -- pulse indicating a new retrieved data byte
fss_crc_fes_ok_p_o : out std_logic; -- indication of a frame (ID_DAT or RP_DAT) with
-- correct FSS, FES and CRC
-- Signal to the wf_production and the wf_engine_control units
crc_wrong_p_o : out std_logic; -- indication of a frame (ID_DAT or RP_DAT) with a
-- wrong CRC; pulse upon FES detection
-- Signal to the wf_engine_control unit
fss_received_p_o : out std_logic; -- pulse upon reception of a correct FSS (ID/RP)
-- Signal to the wf_rx_osc unit
rx_osc_rst_o : out std_logic);-- resets the clk recovery procedure
end entity wf_rx_deserializer;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_rx_deserializer is
-- FSM
type rx_st_t is (IDLE, PRE_FIELD_FIRST_F_EDGE, PRE_FIELD_R_EDGE, PRE_FIELD_F_EDGE, FSD_FIELD,
CTRL_DATA_FCS_FES_FIELDS);
signal rx_st, nx_rx_st : rx_st_t;
signal s_idle, s_receiving_pre, s_receiving_fsd, s_receiving_bytes : std_logic;
-- PRE detection
signal s_manch_r_edge_p, s_manch_f_edge_p, s_bit_r_edge_p, s_edge_out_manch_window_p : std_logic;
-- FSD, FES detection
signal s_fsd_bit, s_fsd_wrong_bit, s_fsd_last_bit, s_fes_detected : std_logic;
signal s_arriving_fes : std_logic_vector (15 downto 0);
-- bytes construction
signal s_write_bit_to_byte_p,s_byte_ready_p,s_byte_ready_p_d1,s_sample_manch_bit_p_d1: std_logic;
signal s_manch_bit_index_load_p, s_manch_bit_index_decr_p, s_manch_bit_index_is_zero : std_logic;
signal s_manch_bit_index, s_manch_bit_index_top : unsigned (3 downto 0);
signal s_byte : std_logic_vector (7 downto 0);
-- CRC calculation
signal s_CRC_ok_p, s_CRC_ok_p_d, s_CRC_ok_p_found : std_logic;
-- independent timeout counter
signal s_session_timedout : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Deserializer's FSM --
---------------------------------------------------------------------------------------------------
-- Receiver's state machine: The state machine is divided in three parts (a clocked process
-- to store the current state, a combinatorial process to manage state transitions and finally a
-- combinatorial process to manage the output signals), which are the three processes that follow.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Synchronous process Deserializer_FSM_Sync: storage of the current state of the FSM
-- A robust protection, that depends only on the system clock, has been implemented:
-- knowing that at any bit rate the reception of a frame should not last more than 35ms (this
-- corresponds to the consumption of 133 bytes at 31.25 Kbps), a counter has been implemented,
-- responsible for bringing the machine back to IDLE if more than 52ms (complete 21 bit counter)
-- have passed since the machine left the IDLE state.
Deserializer_FSM_Sync: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' or rx_rst_i = '1' or s_session_timedout = '1' then
rx_st <= IDLE;
else
rx_st <= nx_rx_st;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Combinatorial process Deserializer_FSM_Comb_State_Transitions: Definition of the state
-- transitions of the FSM.
Deserializer_FSM_Comb_State_Transitions: process (s_bit_r_edge_p, s_edge_out_manch_window_p,
fd_rxd_f_edge_p_i, s_manch_r_edge_p, rx_st,
s_fsd_wrong_bit, s_manch_f_edge_p,
s_fsd_last_bit, s_fes_detected)
begin
case rx_st is
-- During the PRE, the wf_rx_osc is trying to synchronize to the transmitter's clock and every
-- edge detected in the FD_RXD is taken into account. At this phase, the unit uses
-- the wf_rx_osc signals: adjac_bits_window_i and signif_edge_window_i and if edges are found
-- outside those windows the unit goes back to IDLE and the wf_rx_osc is reset.
-- For the rest of the frame, the unit is just sampling the deglitched FD_RXD on the moments
-- specified by the wf_rx_osc signals: sample_manch_bit_p_i and sample_bit_p_i.
when IDLE =>
if fd_rxd_f_edge_p_i = '1' then -- falling edge detection
nx_rx_st <= PRE_FIELD_FIRST_F_EDGE;
else
nx_rx_st <= IDLE;
end if;
when PRE_FIELD_FIRST_F_EDGE =>
if s_manch_r_edge_p = '1' then -- arrival of a manch.
nx_rx_st <= PRE_FIELD_R_EDGE; -- rising edge
elsif s_edge_out_manch_window_p = '1' then -- arrival of any other edge
nx_rx_st <= IDLE;
else
nx_rx_st <= PRE_FIELD_FIRST_F_EDGE;
end if;
when PRE_FIELD_R_EDGE =>
if s_manch_f_edge_p = '1' then -- arrival of a manch. falling edge
nx_rx_st <= PRE_FIELD_F_EDGE; -- note: several loops between
-- a rising and a falling edge are
-- expected for the PRE
elsif s_edge_out_manch_window_p = '1' then -- arrival of any other edge
nx_rx_st <= IDLE;
else
nx_rx_st <= PRE_FIELD_R_EDGE;
end if;
when PRE_FIELD_F_EDGE =>
if s_manch_r_edge_p = '1' then -- arrival of a manch. rising edge
nx_rx_st <= PRE_FIELD_R_EDGE;
elsif s_bit_r_edge_p = '1' then -- arrival of a rising edge between
nx_rx_st <= FSD_FIELD; -- adjacent bits, signaling the
-- beginning of the 1st V+ violation
-- of the FSD
elsif s_edge_out_manch_window_p = '1' then -- arrival of any other edge
nx_rx_st <= IDLE;
else
nx_rx_st <= PRE_FIELD_F_EDGE;
end if;
-- For the monitoring of the FSD, the unit is sampling each manch. bit of the incoming
-- FD_RXD and it is comparing it to the nominal bit of the FSD; the signal s_fsd_wrong_bit
-- is doing this comparison. If a wrong bit is received, the state machine jumps back to IDLE,
-- whereas if the complete byte is correctly received, it jumps to the CTRL_DATA_FCS_FES_FIELDS.
when FSD_FIELD =>
if s_fsd_last_bit = '1' then -- reception of the last (15th)
nx_rx_st <= CTRL_DATA_FCS_FES_FIELDS;-- FSD bit
elsif s_fsd_wrong_bit = '1' then -- wrong bit
nx_rx_st <= IDLE;
else
nx_rx_st <= FSD_FIELD;
end if;
-- The state machine stays in the CTRL_DATA_FCS_FES_FIELDS state until a FES detection (or
-- a reset rx_rst_i signal or a s_session_timeout signal). In this state bytes are "blindly"
-- being constructed and it is the wf_engine_control unit that supervises what is being received;
-- if for example an ID_DAT is being received without a FES detected after 8 bytes or an
-- RP_DAT without a FES after 133 bytes, or if the CTRL byte of an ID_DAT is wrong, the
-- engine_control will discard the current reception and reset the FSM through the rx_rst_i.
when CTRL_DATA_FCS_FES_FIELDS =>
if s_fes_detected = '1' then
nx_rx_st <= IDLE;
else
nx_rx_st <= CTRL_DATA_FCS_FES_FIELDS;
end if;
when OTHERS =>
nx_rx_st <= IDLE;
end case;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Combinatorial process Deserializer_FSM_Comb_Output_Signals: Definition of the output
-- signals of the FSM
Deserializer_FSM_Comb_Output_Signals: process (rx_st)
begin
case rx_st is
when IDLE =>
------------------------------------
s_idle <= '1';
------------------------------------
s_receiving_pre <= '0';
s_receiving_fsd <= '0';
s_receiving_bytes <= '0';
when PRE_FIELD_FIRST_F_EDGE | PRE_FIELD_R_EDGE | PRE_FIELD_F_EDGE =>
s_idle <= '0';
------------------------------------
s_receiving_pre <= '1';
------------------------------------
s_receiving_fsd <= '0';
s_receiving_bytes <= '0';
when FSD_FIELD =>
s_idle <= '0';
s_receiving_pre <= '0';
------------------------------------
s_receiving_fsd <= '1';
------------------------------------
s_receiving_bytes <= '0';
when CTRL_DATA_FCS_FES_FIELDS =>
s_idle <= '0';
s_receiving_pre <= '0';
s_receiving_fsd <= '0';
------------------------------------
s_receiving_bytes <= '1';
------------------------------------
when OTHERS =>
------------------------------------
s_idle <= '1';
------------------------------------
s_receiving_pre <= '0';
s_receiving_fsd <= '0';
s_receiving_bytes <= '0';
end case;
end process;
---------------------------------------------------------------------------------------------------
-- Bytes Creation --
---------------------------------------------------------------------------------------------------
-- Synchronous process Append_Bit_To_Byte: Creation of bytes of data.
-- A new bit of the FD_RXD is appended to the output byte that is being formed when the FSM is in
-- the "CTRL_DATA_FCS_FES_FIELDS" state, on the "sample_bit_p_i" moments.
Append_Bit_To_Byte: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
s_byte_ready_p_d1 <= '0';
s_sample_manch_bit_p_d1 <= '0';
s_byte <= (others => '0');
else
s_byte_ready_p_d1 <= s_byte_ready_p;
s_sample_manch_bit_p_d1 <= sample_manch_bit_p_i;
if s_write_bit_to_byte_p = '1' then
s_byte <= s_byte(6 downto 0) & fd_rxd_i;
end if;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
s_write_bit_to_byte_p <= s_receiving_bytes and sample_bit_p_i;
s_byte_ready_p <= s_receiving_bytes and s_manch_bit_index_is_zero and sample_manch_bit_p_i
and (not s_fes_detected);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of a counter that manages the position of an incoming FD_RXD bit inside a manch.
-- encoded byte (16 bits).
Incoming_Bits_Index: wf_decr_counter
generic map(g_counter_lgth => 4)
port map(
uclk_i => uclk_i,
counter_rst_i => nfip_rst_i,
counter_top_i => s_manch_bit_index_top,
counter_load_i => s_manch_bit_index_load_p,
counter_decr_i => s_manch_bit_index_decr_p,
---------------------------------------------------
counter_o => s_manch_bit_index,
counter_is_zero_o => s_manch_bit_index_is_zero);
---------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
s_manch_bit_index_top <= to_unsigned (c_FSD'left-2, s_manch_bit_index_top'length) when s_receiving_pre = '1' else
to_unsigned (15, s_manch_bit_index_top'length) when s_receiving_bytes ='1' else
to_unsigned (0, s_manch_bit_index_top'length);
s_manch_bit_index_load_p <= '1' when (s_idle ='1') else
s_manch_bit_index_is_zero and sample_manch_bit_p_i when (s_receiving_pre = '1') or (s_receiving_bytes = '1') else --reloading for every new byte
'0';
s_manch_bit_index_decr_p <= sample_manch_bit_p_i when (s_receiving_fsd = '1') or (s_receiving_bytes = '1') else '0';
---------------------------------------------------------------------------------------------------
-- FSD detection --
---------------------------------------------------------------------------------------------------
-- FSD aux signals concurrent assignments:
s_fsd_bit <= s_receiving_fsd and c_FSD (to_integer(s_manch_bit_index));
s_fsd_last_bit <= s_manch_bit_index_is_zero and sample_manch_bit_p_i;
s_fsd_wrong_bit <= (s_fsd_bit xor fd_rxd_i) and sample_manch_bit_p_i;
---------------------------------------------------------------------------------------------------
-- FES detection --
---------------------------------------------------------------------------------------------------
-- Synchronous process FES_Detector: The s_arriving_fes register is storing the last 16
-- manch. encoded bits received and the s_fes_detected indicates whether they match the FES.
FES_Detector: process (uclk_i)
begin
if rising_edge (uclk_i) then
if s_receiving_bytes = '0' then
s_arriving_fes <= (others =>'0');
elsif s_receiving_bytes = '1' and sample_manch_bit_p_i = '1' then
s_arriving_fes <= s_arriving_fes (14 downto 0) & fd_rxd_i;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- --
s_fes_detected <= '1' when s_arriving_fes = c_FES else '0';
---------------------------------------------------------------------------------------------------
-- CRC Verification --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of the CRC calculator unit that verifies the received FCS field.
CRC_Verification : wf_crc
port map(
uclk_i => uclk_i,
nfip_rst_i => nfip_rst_i,
start_crc_p_i => s_receiving_fsd,
data_bit_ready_p_i => s_write_bit_to_byte_p,
data_bit_i => fd_rxd_i,
crc_o => open,
---------------------------------------------------
crc_ok_p_o => s_CRC_ok_p);
---------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Synchronous process that checks the position of the CRC bytes in the frame: The 1 uclk-
-- wide crc_ok_p coming from the CRC calculator is delayed for 1 complete byte. The matching of
-- this delayed pulse with the end of frame pulse (s_fes_detected), would confirm that the two
-- last bytes received before the FES were the correct CRC.
CRC_OK_pulse_delay: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' or s_receiving_bytes = '0' then
s_CRC_ok_p_d <= '0';
s_CRC_ok_p_found <= '0';
else
if s_CRC_ok_p = '1' then
s_CRC_ok_p_found <= '1';
end if;
if s_byte_ready_p = '1' and s_CRC_ok_p_found = '1' then -- arrival of the next byte
s_CRC_ok_p_d <= '1'; -- (FES normally)
s_CRC_ok_p_found <= '0';
else
s_CRC_ok_p_d <= '0';
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Independent Timeout Counter --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of a wf_decr_counter relying only on the system clock, as an additional
-- way to go back to IDLE state, in case any other logic is being stuck. The length of the counter
-- is defined using the slowest bit rate and considering reception of the upper limit of 133 bytes.
Session_Timeout_Counter: wf_decr_counter
generic map(g_counter_lgth => c_SESSION_TIMEOUT_C_LGTH)
port map(
uclk_i => uclk_i,
counter_rst_i => nfip_rst_i,
counter_top_i => (others => '1'),
counter_load_i => s_idle,
counter_decr_i => '1', -- on each uclk tick
counter_o => open,
---------------------------------------------------
counter_is_zero_o => s_session_timedout);
---------------------------------------------------
---------------------------------------------------------------------------------------------------
-- Concurrent signal assignments --
---------------------------------------------------------------------------------------------------
-- aux signals concurrent assignments :
s_manch_r_edge_p <= signif_edge_window_i and fd_rxd_r_edge_p_i;
s_manch_f_edge_p <= signif_edge_window_i and fd_rxd_f_edge_p_i;
s_bit_r_edge_p <= adjac_bits_window_i and fd_rxd_r_edge_p_i;
s_edge_out_manch_window_p <= (not signif_edge_window_i)and(fd_rxd_r_edge_p_i or fd_rxd_f_edge_p_i);
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- output signals concurrent assignments :
byte_o <= s_byte;
byte_ready_p_o <= s_byte_ready_p_d1;
rx_osc_rst_o <= s_idle;
fss_received_p_o <= s_receiving_fsd and s_fsd_last_bit;
-- frame with correct FSS, CRC, FES (plus with number of bits multiple of 8)
fss_crc_fes_ok_p_o <= s_fes_detected and s_byte_ready_p_d1 and s_CRC_ok_p_d;
-- frame with wrong CRC; pulse upon FES detection
-- here the s_sample_manch_bit_p_d1 and not the s_byte_ready_p_d1 is used, so that frames
-- with number of bits not multiple of 8, but with correct FES, can be detected.
crc_wrong_p_o <= s_fes_detected and s_sample_manch_bit_p_d1 and (not s_CRC_ok_p_d);
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_rx_osc |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_rx_osc.vhd |
-- |
-- Description Generation of the clock signals needed for the FIELDRIVE reception |
-- |
-- Even if the bit rate of the communication is known, jitter is expected to affect |
-- the arriving time of the incoming signal. The main idea of the unit is to |
-- recalculate the expected arrival time of the next incoming bit, based on the |
-- arrival of the previous one, so that drifts are not accumulated. The clock |
-- recovery is based on the Manchester 2 coding which ensures that there is one edge |
-- (transition) for each bit. |
-- |
-- In this unit, we refer to |
-- o a significant edge: for the edge of a manch. encoded bit (bit 0:_|-, bit 1: -|_)|
-- o a transition : for the moment in between two adjacent bits, that may or |
-- may not result in an edge (eg. a 0 followed by a 0 will give an edge _|-|_|-, |
-- but a 0 followed by a 1 will not _|--|_ ). |
-- |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 14/02/2011 |
-- Version v0.04 |
-- Depends on wf_reset_unit |
-- wf_deglitcher |
-- wf_rx_deserializer |
------------------ |
-- Last changes |
-- 08/2009 v0.01 PS Entity Ports added, start of architecture content |
-- 07/2010 v0.02 EG rx counter changed from 20 bits signed, to 11 bits unsigned; |
-- rx clk generation depends on edge detection;code cleanedup+commented |
-- rst_rx_osc signal clearified |
-- 12/2010 v0.03 EG code cleaned-up |
-- 01/2011 v0.031 EG rxd_edge_i became fd_rxd_edge_p_i; small correctiond on comments |
-- 02/2011 v0.04 EG 2 units wf_rx_osc and wf_tx_osc; process replaced by wf_incr_counter |
-- check for code violations removed completely |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_rx_osc
--=================================================================================================
entity wf_rx_osc is port(
-- INPUTS
-- nanoFIP User Interface, General signals
uclk_i : in std_logic; -- 40 MHz clock
rate_i : in std_logic_vector (1 downto 0); -- WorldFIP bit rate
-- Signal from the wf_reset_unit
nfip_rst_i : in std_logic; -- nanoFIP internal reset
-- Signal from the wf_deglitcher unit
fd_rxd_edge_p_i : in std_logic; -- indication of an edge on fd_rxd
-- Signal from wf_rx_deserializer unit
rx_osc_rst_i : in std_logic; -- resets the clock recovery procedure
-- OUTPUTS
-- Signals to the wf_rx_deserializer
rx_manch_clk_p_o : out std_logic; -- signal with uclk-wide pulses
-- o on a significant edge
-- o between adjacent bits
-- ____|-|___|-|___|-|___
rx_bit_clk_p_o : out std_logic; -- signal with uclk-wide pulses
-- o between adjacent bits
-- __________|-|_________
rx_signif_edge_window_o : out std_logic; -- time window where a significant edge is expected
rx_adjac_bits_window_o : out std_logic); -- time window where a transition between adjacent
-- bits is expected
end entity wf_rx_osc;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_rx_osc is
-- reception period counter
signal s_period_c, s_period, s_margin : unsigned (c_PERIODS_COUNTER_LGTH-1 downto 0);
signal s_half_period : unsigned (c_PERIODS_COUNTER_LGTH-1 downto 0);
signal s_period_c_reinit, s_period_c_is_full : std_logic;
-- windows formed, based on the counter
signal s_adjac_bits_window, s_signif_edge_window : std_logic;
-- fd_rxd signal combined with the windows
signal s_adjac_bits_edge_found, s_signif_edge_found : std_logic;
-- clocks
signal s_bit_clk, s_bit_clk_d1, s_manch_clk, s_manch_clk_d1 : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Generation of windows where edges/ transitions are expected --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- # uclk ticks for a bit period, defined by the WorldFIP bit rate
s_period <= c_BIT_RATE_UCLK_TICKS(to_integer(unsigned(rate_i)));
s_half_period <= s_period srl 1; -- 1/2 s_period
s_margin <= s_period srl 3; -- margin for jitter defined as 1/8 of the period
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of a wf_incr_counter unit : the rx_counter starts counting after the
-- release of the reset signal rx_osc_rst_i. This takes place after a falling edge on the
-- filtered FD_RXD; this edge should be representing the 1st Manchester 2 (manch.) encoded bit '1'
-- of the PREamble. Starting from this edge, other falling or rising significant edges, are
-- expected around one period (s_period) later. A time window around the expected arrival time is
-- set and its length is defined as 1/4th of the period (1/8th before and 1/8th after the expected
-- time). When the actual edge arrives, the counter is reset.
-- If that first falling edge of FD_RXD is finally proven not to belong to a valid PRE the counter
-- is reinitialialized through the rx_osc_rst_i signal from the wf_rx_deserializer.
rx_periods_count: wf_incr_counter
generic map(g_counter_lgth => c_PERIODS_COUNTER_LGTH)
port map(
uclk_i => uclk_i,
counter_reinit_i => s_period_c_reinit,
counter_incr_i => '1',
counter_is_full_o => open,
------------------------------------------
counter_o => s_period_c);
------------------------------------------
s_period_c_is_full <= '1' when s_period_c = s_period -1 else '0'; -- counter full indicator
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- counter reinitialized: if nfip_rst_i is active or
-- if rx_osc_rst_i is active or
-- if an edge is detected in the expected window or
-- if it fills up
s_period_c_reinit <= nfip_rst_i or rx_osc_rst_i or (s_signif_edge_window and fd_rxd_edge_p_i)
or s_period_c_is_full;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Concurrent signal assignments: creation of the windows where
-- "significant edges" and "adjacent bits transitions" are expected on the input signal.
-- o s_signif_edge_window: extends s_margin uclk ticks before and s_margin uclk ticks after
-- the completion of a period, where significant edges are expected.
-- o s_adjac_bits_window : extends s_margin uclk ticks before and s_margin uclk ticks after
-- the middle of a period, where transitions between adjacent bits are expected.
s_signif_edge_window <= '1' when ((s_period_c < s_margin) or
(s_period_c > s_period-1 - s_margin-1)) else '0';
s_adjac_bits_window <= '1' when ((s_period_c >= s_half_period-s_margin-1) and
(s_period_c < s_half_period+s_margin)) else '0';
---------------------------------------------------------------------------------------------------
-- Clocks Generation --
---------------------------------------------------------------------------------------------------
-- Synchronous process rx_clks: the process rx_clk is following the edges that appear on the fd_rxd
-- and constructs two clock signals: rx_manch_clk & rx_bit_clk.
-- The signal rx_manch_clk: is inverted on each significant edge, as well as between adjacent bits
-- The signal rx_bit_clk : is inverted only between adjacent bits
-- The significant edges are normally expected inside the signif_edge_window. In the cases of a
-- code violation (V+ or V-) no edge will arrive in this window. In this situation rx_manch_clk
-- is inverted right after the end of the signif_edge_window.
-- Edges between adjacent bits are expected inside the adjac_bits_window; if they do not arrive
-- the rx_manch_clk and rx_bit_clk are inverted right after the end of the adjac_bits_window.
rx_clks: process (uclk_i)
begin
if rising_edge (uclk_i) then
if (nfip_rst_i = '1') then
s_manch_clk <= '0';
s_bit_clk <= '0';
s_bit_clk_d1 <= '0';
s_manch_clk_d1 <= '0';
s_signif_edge_found <= '0';
s_adjac_bits_edge_found <= '0';
else
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- regarding significant edges:
-- looking for a significant edge inside the corresponding window
if (s_signif_edge_window='1') and (fd_rxd_edge_p_i='1') and (s_signif_edge_found='0') then
s_manch_clk <= not s_manch_clk; -- inversion of rx_manch_clk
s_signif_edge_found <= '1'; -- indication that the edge was found
s_adjac_bits_edge_found <= '0';
-- if a significant edge is not found where expected (code violation), the rx_manch_clk
-- is inverted right after the end of the signif_edge_window.
elsif (s_signif_edge_found = '0') and (s_period_c = s_margin) then
s_manch_clk <= not s_manch_clk;
s_adjac_bits_edge_found <= '0'; -- re-initialization before the
-- next cycle
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
-- regarding edges between adjacent bits:
-- looking for an edge inside the corresponding window
elsif (s_adjac_bits_window = '1') and (fd_rxd_edge_p_i = '1') then
s_manch_clk <= not s_manch_clk; -- inversion of rx_manch_clk
s_bit_clk <= not s_bit_clk; -- inversion of rx_bit_clk
s_adjac_bits_edge_found <= '1'; -- indication that an edge was found
s_signif_edge_found <= '0'; -- re-initialization before next cycle
-- if no edge is detected inside the adjac_bits_edge_window, both clks are inverted right
-- after the end of it
elsif (s_adjac_bits_edge_found = '0') and (s_period_c = s_half_period + s_margin) then
s_manch_clk <= not s_manch_clk;
s_bit_clk <= not s_bit_clk;
s_signif_edge_found <= '0'; -- re-initialization before next cycle
end if;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
s_manch_clk_d1 <= s_manch_clk;
-- s_manch_clk : ____|-----|_____|-----|____
-- s_manch_clk_d1 : ______|-----|_____|-----|__
-- rx_manch_clk_p_o : ____|-|___|-|___|-|___|-|__
s_bit_clk_d1 <= s_bit_clk;
-- s_bit_clk : ____|-----------|__________
-- s_bit_clk_d1 : ______|-----------|________
-- rx_bit_clk_p_o : ____|-|_________|-|________
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Concurrent signal assignments --
---------------------------------------------------------------------------------------------------
rx_manch_clk_p_o <= s_manch_clk_d1 xor s_manch_clk; -- a 1 uclk-wide pulse, after
-- o a significant edge and
-- o a new bit
-- ___|-|___|-|___|-|___
rx_bit_clk_p_o <= s_bit_clk xor s_bit_clk_d1; -- a 1 uclk-wide pulse, after
-- o a new bit
-- _________|-|_________
rx_signif_edge_window_o <= s_signif_edge_window;
rx_adjac_bits_window_o <= s_adjac_bits_window;
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_tx_osc |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_tx_osc.vhd |
-- |
-- Description Generation of the clock signals needed for the FIELDRIVE transmission. |
-- |
-- The unit generates the nanoFIP FIELDRIVE output FD_TXCK (line driver half bit |
-- clock) and the nanoFIP internal signal tx_sched_p_buff: |
-- |
-- uclk : _|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-|_|-| |
-- FD_TXCK : _____|--------...--------|________...________|--------...--- |
-- tx_sched_p_buff(3): 0 0 0 1 0 0 0 1 |
-- tx_sched_p_buff(2): 0 0 1 0 0 0 1 0 |
-- tx_sched_p_buff(1): 0 1 0 0 0 1 0 0 |
-- tx_sched_p_buff(0): 1 0 0 0 1 0 0 0 |
-- |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 14/02/2011 |
-- Version v0.04 |
-- Depends on wf_reset_unit |
---------------- |
-- Last changes |
-- 08/2009 v0.01 PS Entity Ports added, start of architecture content |
-- 07/2010 v0.02 EG tx counter changed from 20 bits signed, to 11 bits unsigned; |
-- c_TX_SCHED_BUFF_LGTH got 1 bit more |
-- 12/2010 v0.03 EG code cleaned-up |
-- 01/2011 v0.04 EG wf_tx_osc as different unit; use of wf_incr_counter;added tx_osc_rst_p_i
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_tx_osc
--=================================================================================================
entity wf_tx_osc is
port (
-- INPUTS
-- nanoFIP User Interface, General signals
uclk_i : in std_logic; -- 40 MHz clock
rate_i : in std_logic_vector (1 downto 0); -- WorldFIP bit rate
-- Signal from the wf_reset_unit
nfip_rst_i : in std_logic; -- nanoFIP internal reset
-- Signals from the wf_engine_control
tx_osc_rst_p_i : in std_logic; -- transmitter timeout
-- OUTPUTS
-- nanoFIP FIELDRIVE output
tx_clk_o : out std_logic; -- line driver half bit clock
-- Signal to the wf_tx_serializer unit
tx_sched_p_buff_o : out std_logic_vector (c_TX_SCHED_BUFF_LGTH -1 downto 0));
-- buffer of pulses used for the scheduling
-- of the actions of the wf_tx_serializer
end entity wf_tx_osc;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_tx_osc is
-- transmission periods counter
signal s_period_c, s_period : unsigned (c_PERIODS_COUNTER_LGTH -1 downto 0);
signal s_one_forth_period : unsigned (c_PERIODS_COUNTER_LGTH -1 downto 0);
signal s_period_c_is_full, s_period_c_reinit : std_logic;
-- clocks
signal s_tx_clk_d1, s_tx_clk, s_tx_clk_p : std_logic;
signal s_tx_sched_p_buff : std_logic_vector (c_TX_SCHED_BUFF_LGTH-1 downto 0);
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
---------------------------------------------------------------------------------------------------
-- Periods Counter --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
s_period <= c_BIT_RATE_UCLK_TICKS(to_integer(unsigned(rate_i)));-- # uclk ticks for a
-- transmission period
s_one_forth_period <= s_period srl 2; -- 1/4 s_period
s_period_c_is_full <= '1' when s_period_c = s_period -1 else '0'; -- counter full
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of a wf_incr_counter counting transmission periods.
tx_periods_count: wf_incr_counter
generic map(g_counter_lgth => c_PERIODS_COUNTER_LGTH)
port map(
uclk_i => uclk_i,
counter_reinit_i => s_period_c_reinit,
counter_incr_i => '1',
counter_is_full_o => open,
------------------------------------------
counter_o => s_period_c);
------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- counter reinitialized : if the nfip_rst_i is active or
-- if the tx_osc_rst_p_i is active or
-- if it fills up
s_period_c_reinit <= nfip_rst_i or tx_osc_rst_p_i or s_period_c_is_full;
---------------------------------------------------------------------------------------------------
-- Clocks Construction --
---------------------------------------------------------------------------------------------------
-- Concurrent signals assignments and a synchronous process that use
-- the s_period_c to construct the tx_clk_o clock and the buffer of pulses tx_sched_p_buff_o.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Creation of the clock for the transmitter with period: 1/2 transmission period
s_tx_clk <= '1' when ((s_period_c < s_one_forth_period) or
((s_period_c > (2*s_one_forth_period)-1) and
(s_period_c < 3*s_one_forth_period)))
else '0';
-- transm. period : _|-----------|___________|--
-- tx_counter : 0 1/4 1/2 3/4 1
-- s_tx_clk : _|-----|_____|-----|_____|--
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Edge detector for s_tx_clk
s_tx_clk_p <= s_tx_clk and (not s_tx_clk_d1);
-- s_tx_clk : _|-----|_____|-----|_____
-- tx_clk_o/ s_tx_clk_d1: ___|-----|_____|-----|___
-- not s_tx_clk_d1 : ---|_____|-----|_____|---
-- s_tx_clk_p : _|-|___|-|___|-|___|-|___
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
clk_Signals_Construction: process (uclk_i)
begin
if rising_edge (uclk_i) then
if (nfip_rst_i = '1') or (tx_osc_rst_p_i = '1') then
s_tx_sched_p_buff <= (others => '0');
s_tx_clk_d1 <= '0';
else
s_tx_clk_d1 <= s_tx_clk;
s_tx_sched_p_buff <= s_tx_sched_p_buff (s_tx_sched_p_buff'left-1 downto 0) & s_tx_clk_p;
-- buffering of the s_tx_clk_p pulses
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Output signals
tx_clk_o <= s_tx_clk_d1;
tx_sched_p_buff_o <= s_tx_sched_p_buff;
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
--_________________________________________________________________________________________________
-- |
-- |The nanoFIP| |
-- |
-- CERN,BE/CO-HT |
--________________________________________________________________________________________________|
---------------------------------------------------------------------------------------------------
-- |
-- wf_tx_serializer |
-- |
---------------------------------------------------------------------------------------------------
-- File wf_tx_serializer.vhd |
-- |
-- Description The unit is generating the nanoFIP FIELDRIVE outputs FD_TXD and FD_TXENA. |
-- It is retreiving bytes of data from: |
-- o the wf_production (from the CTRL byte until the MPS) |
-- o WF_PACKAGE (FSS and FES bytes) |
-- o and the wf_crc (FCS bytes). |
-- |
-- It encodes the bytes to the Manchester 2 (manch.)scheme and outputs one by one the|
-- encoded bits on the moments indicated by the wf_tx_osc unit. |
-- |
-- Reminder of the Produced RP_DAT frame structure : |
-- ___________ ______ _______ ______ _________________ _______ _______ ___________ _______ |
-- |____FSS____|_CTRL_||__PDU__|_LGTH_|__..User-Data..__|_nstat_|__MPS__||____FCS____|__FES__| |
-- |
-- |------------- Bytes from the wf_production -------------| |
-- |
-- |
-- Authors Pablo Alvarez Sanchez (Pablo.Alvarez.Sanchez@cern.ch) |
-- Evangelia Gousiou (Evangelia.Gousiou@cern.ch) |
-- Date 07/2011 |
-- Version v0.05 |
-- Depends on wf_engine_control |
-- wf_production |
-- wf_tx_osc |
-- wf_reset_unit |
---------------- |
-- Last changes |
-- v0.02 2009 PAS Entity Ports added, start of architecture content |
-- v0.03 07/2010 EG timing changes; tx_sched_p_buff_i got 1 more bit |
-- briefly byte_index_i needed to arrive 1 clock tick earlier |
-- renamed from tx to tx_serializer; |
-- STOP_TRANSMISSION state added for the synch of txena |
-- v0.04 01/2011 EG SYNC_TO_TXCK state added to start always with the bits 1,2,3 of the |
-- clock buffer available(tx_start_p_i may arrive at any time) |
-- tx_completed_p_o signal added |
-- v0.05 07/2011 EG bits_to_txd unit removed |
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE |
-- ------------------------------------ |
-- This source file is free software; you can redistribute it and/or modify it under the terms of |
-- the GNU Lesser General Public License as published by the Free Software Foundation; either |
-- version 2.1 of the License, or (at your option) any later version. |
-- This source 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 Lesser General Public License for more details. |
-- You should have received a copy of the GNU Lesser General Public License along with this |
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html |
---------------------------------------------------------------------------------------------------
--=================================================================================================
-- Libraries & Packages
--=================================================================================================
-- Standard library
library IEEE;
use IEEE.STD_LOGIC_1164.all; -- std_logic definitions
use IEEE.NUMERIC_STD.all; -- conversion functions
-- Specific library
library work;
use work.WF_PACKAGE.all; -- definitions of types, constants, entities
--=================================================================================================
-- Entity declaration for wf_tx_serializer
--=================================================================================================
entity wf_tx_serializer is port(
-- INPUTS
-- nanoFIP User Interface, General signals
uclk_i : in std_logic; -- 40 MHz clock
-- Signal from the wf_reset_unit
nfip_rst_i : in std_logic; -- nanoFIP internal reset
-- Signals from the wf_production
byte_i : in std_logic_vector (7 downto 0); -- byte to be delivered
-- Signals from the wf_engine_control unit
tx_start_p_i : in std_logic; -- indication for the start of the production
byte_request_accept_p_i : in std_logic; -- indication that a byte is ready to be delivered
last_byte_p_i : in std_logic; -- indication of the last data byte
-- (CRC, FES not included)
-- Signal from the wf_tx_osc
tx_sched_p_buff_i : in std_logic_vector (c_TX_SCHED_BUFF_LGTH-1 downto 0);
-- pulses for the transmission synchronization
-- OUTPUTS
-- Signal to the wf_engine_control unit
tx_byte_request_p_o : out std_logic; -- request for a new byte
tx_completed_p_o : out std_logic; -- pulse upon the end of transmission
-- Signal to the wf_tx_osc unit
tx_osc_rst_p_o : out std_logic; -- oscillator reset after a transmission error
-- nanoFIP FIELDRIVE outputs
tx_data_o : out std_logic; -- transmitter serial data
tx_enable_o : out std_logic);-- transmitter enable
end entity wf_tx_serializer;
--=================================================================================================
-- architecture declaration
--=================================================================================================
architecture rtl of wf_tx_serializer is
-- FSM
type tx_st_t is (IDLE, SYNC_TO_TXCK, SEND_FSS, SEND_DATA_BYTE,
SEND_CRC_BYTES, SEND_FES, STOP_TRANSMISSION);
signal tx_st, nx_tx_st : tx_st_t;
signal s_prepare_to_produce, s_sending_fss, s_sending_data : std_logic;
signal s_sending_crc, s_sending_fes, s_stop_transmission : std_logic;
-- bits counter
signal s_bit_index_decr_p,s_bit_index_load, s_bit_index_is_zero : std_logic;
signal s_bit_index, s_bit_index_top : unsigned (4 downto 0);
-- transmitter output
signal s_txd : std_logic;
-- byte to be transmitted
signal s_data_byte : std_logic_vector (7 downto 0);
signal s_data_byte_manch : std_logic_vector (15 downto 0);
-- CRC calculations
signal s_start_crc_p, s_data_bit_to_crc_p : std_logic;
signal s_crc_bytes : std_logic_vector (15 downto 0);
signal s_crc_bytes_manch : std_logic_vector (31 downto 0);
-- independent timeout counter
signal s_session_timedout : std_logic;
--=================================================================================================
-- architecture begin
--=================================================================================================
begin
-- The signal tx_sched_p_buff_i is used for the scheduling of the state transitions of the machine
-- as well as of the actions on the output signals.
-- The following drawing shows the transitions of the signal tx_sched_p_buff_i with respect to
-- the nanoFIP FIELDRIVE output FD_TXCK (line driver half bit clock).
-- FD_TXCK : _________|-------...---------|________...________|-------...---------|____
-- tx_sched_p_buff(3): |0|0|0|1 |0|0|0|1
-- tx_sched_p_buff(2): |0|0|1|0 |0|0|1|0
-- tx_sched_p_buff(1): |0|1|0|0 |0|1|0|0
-- tx_sched_p_buff(0): |1|0|0|0 |1|0|0|0
----------------------
-- new byte request : ^
-- new byte ready : . . ^
-- 1st bit of new . . . . . . . . . . . . . . . . . .^
-- byte delivery :
-- bit counter : [ 15 . . .][ 14
-- A new bit is delivered after the assertion of tx_sched_p_buff (1).
-- The counter Outgoing_Bits_Index that keeps the index of a bit being delivered is updated after
-- the delivery of the bit, after the tx_sched_p_buff (3) assertion. The counter is ahead of the
-- bit being sent.
-- In the sending_bytes state, where the unit is expecting data bytes from the wf_production,
-- the unit delivers a request for a new byte after the tx_sched_p_buff (0) assertion,
-- and when the Outgoing_Bits_Index counter is empty (which means that the last bit of a previous
-- byte is now being delivered).
-- The wf_engine_control responds to the request by sending a new address to the wf_production
-- for the retrieval of a byte from the memory or the stand-alone bus.
-- The byte becomes available at the byte_request_accept_p_i pulse, 2 cycles after the request,
-- and starts being transmitted at the tx_sched_p_buff (1) of the next FD_TXCK cycle.
-- The wf_engine_control is the one keeping track of the amount of bytes delivered and asserts
-- the last_byte_p_i signal accordingly; after the arrival of this signal the serializer's FSM
-- proceeds with the transmission of the CRC and the FES bytes and then goes back to IDLE.
-- To add a robust layer of protection to the FSM, we have implemented a counter, dependent only
-- on the system clock, that from any state can bring the FSM back to IDLE. At any bit rate the
-- transmission of the longest RP_DAT should not last more than 35ms. Hence, we have generated a
-- 21 bits (c_SESSION_TIMEOUT_C_LGTH) counter that will reset the machine if more than 52ms
-- (complete 21 bit counter) have passed since it has left this IDLE state.
---------------------------------------------------------------------------------------------------
-- Serializer's FSM --
---------------------------------------------------------------------------------------------------
-- Serializer's state machine: the state machine is divided in three parts (a clocked
-- process to store the current state, a combinatorial process to manage state transitions and
-- finally a combinatorial process to manage the output signals), which are the 3 processes that
-- follow.
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Synchronous process Serializer_FSM_Sync:
Serializer_FSM_Sync: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' or s_session_timedout = '1' then
tx_st <= IDLE;
else
tx_st <= nx_tx_st;
end if;
end if;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Combinatorial process Serializer_FSM_Comb_State_Transitions
Serializer_FSM_Comb_State_Transitions: process (tx_st, tx_start_p_i, last_byte_p_i,
s_bit_index_is_zero, tx_sched_p_buff_i)
begin
case tx_st is
when IDLE =>
if tx_start_p_i = '1' then -- trigger from wf_engine_control
nx_tx_st <= SYNC_TO_TXCK;
else
nx_tx_st <= IDLE;
end if;
when SYNC_TO_TXCK => -- synch to the free running FD_TXTCK
if tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-4) = '1' then
nx_tx_st <= SEND_FSS;
else
nx_tx_st <= SYNC_TO_TXCK;
end if;
when SEND_FSS => -- delivery of 2 FSS bytes
if (s_bit_index_is_zero = '1') and (tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-1) = '1') then
nx_tx_st <= SEND_DATA_BYTE;
else
nx_tx_st <= SEND_FSS;
end if;
when SEND_DATA_BYTE => -- delivery of several data bytes
-- until the last_byte_p_i notification
if last_byte_p_i = '1' then
nx_tx_st <= SEND_CRC_BYTES;
else
nx_tx_st <= SEND_DATA_BYTE;
end if;
when SEND_CRC_BYTES => -- delivery of 2 CRC bytes
if (s_bit_index_is_zero = '1') and (tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-2) = '1') then
nx_tx_st <= SEND_FES; -- state change early enough (tx_sched_p_buff_i(2))
-- for the Outgoing_Bits_Index, that is loaded on
-- tx_sched_p_buff_i(3), to get the 31 as top value
else
nx_tx_st <= SEND_CRC_BYTES;
end if;
when SEND_FES => -- delivery of 1 FES byte
if (s_bit_index_is_zero = '1') and (tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-2) = '1') then
nx_tx_st <= STOP_TRANSMISSION; -- state change early enough (tx_sched_p_buff_i(2))
-- for the Outgoing_Bits_Index that is loaded on
-- tx_sched_p_buff_i(3) to get the 15 as top value
else
nx_tx_st <= SEND_FES;
end if;
when STOP_TRANSMISSION =>
-- end of transmission synchronous to the FD_TXCK
if tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-2) = '1' then
nx_tx_st <= IDLE;
else
nx_tx_st <= STOP_TRANSMISSION;
end if;
when OTHERS =>
nx_tx_st <= IDLE;
end case;
end process;
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Combinatorial process Serializer_FSM_Comb_Output_Signals
Serializer_FSM_Comb_Output_Signals: process ( tx_st )
begin
case tx_st is
when IDLE | SYNC_TO_TXCK =>
---------------------------------
s_prepare_to_produce <= '1';
---------------------------------
s_sending_fss <= '0';
s_sending_data <= '0';
s_sending_crc <= '0';
s_sending_fes <= '0';
s_stop_transmission <= '0';
when SEND_FSS =>
s_prepare_to_produce <= '0';
---------------------------------
s_sending_fss <= '1';
---------------------------------
s_sending_data <= '0';
s_sending_crc <= '0';
s_sending_fes <= '0';
s_stop_transmission <= '0';
when SEND_DATA_BYTE =>
s_prepare_to_produce <= '0';
s_sending_fss <= '0';
---------------------------------
s_sending_data <= '1';
---------------------------------
s_sending_crc <= '0';
s_sending_fes <= '0';
s_stop_transmission <= '0';
when SEND_CRC_BYTES =>
s_prepare_to_produce <= '0';
s_sending_fss <= '0';
s_sending_data <= '0';
---------------------------------
s_sending_crc <= '1';
---------------------------------
s_sending_fes <= '0';
s_stop_transmission <= '0';
when SEND_FES =>
s_prepare_to_produce <= '0';
s_sending_fss <= '0';
s_sending_data <= '0';
s_sending_crc <= '0';
---------------------------------
s_sending_fes <= '1';
---------------------------------
s_stop_transmission <= '0';
when STOP_TRANSMISSION =>
s_prepare_to_produce <= '0';
s_sending_fss <= '0';
s_sending_data <= '0';
s_sending_crc <= '0';
s_sending_fes <= '0';
---------------------------------
s_stop_transmission <= '1';
---------------------------------
when OTHERS =>
---------------------------------
s_prepare_to_produce <= '1';
---------------------------------
s_sending_fss <= '0';
s_sending_data <= '0';
s_sending_crc <= '0';
s_sending_fes <= '0';
s_stop_transmission <= '0';
end case;
end process;
---------------------------------------------------------------------------------------------------
-- Input Byte Retrieval --
---------------------------------------------------------------------------------------------------
Input_Byte_Retrieval: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
s_data_byte <= (others => '0');
else
if byte_request_accept_p_i = '1' then
s_data_byte <= byte_i;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Manchester Encoding --
---------------------------------------------------------------------------------------------------
s_data_byte_manch <= f_manch_encoder (s_data_byte);
s_crc_bytes_manch <= f_manch_encoder (s_crc_bytes);
---------------------------------------------------------------------------------------------------
-- CRC calculation --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of the CRC unit
crc_generation: wf_crc
port map(
uclk_i => uclk_i,
nfip_rst_i => nfip_rst_i,
start_crc_p_i => s_start_crc_p,
data_bit_ready_p_i => s_data_bit_to_crc_p,
data_bit_i => s_txd,
crc_ok_p_o => open,
-------------------------------------------------
crc_o => s_crc_bytes);
-------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- concurrent signals assignement for the crc_generator inputs
s_start_crc_p <= s_sending_fss and s_bit_index_is_zero and tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-1);
-- the CRC calculation starts when at the end of th e FSS (beginning of data bytes delivery)
s_data_bit_to_crc_p <= s_sending_data and s_bit_index(0) and tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-1);
-- only the 1st part of a manchester encoded bit goes to the CRC calculator
---------------------------------------------------------------------------------------------------
-- Bits counter --
---------------------------------------------------------------------------------------------------
-- Managment of the pointer that indicates which bit of a manchester encoded byte is to be
-- delivered. According to the state of the FSM, a byte may be a FSS one, or a data byte or a
-- CRC or a FES byte.
Outgoing_Bits_Index: wf_decr_counter
generic map(g_counter_lgth => 5)
port map(
uclk_i => uclk_i,
counter_rst_i => nfip_rst_i,
counter_top_i => s_bit_index_top,
counter_load_i => s_bit_index_load,
counter_decr_i => s_bit_index_decr_p,
-----------------------------------------------
counter_o => s_bit_index,
counter_is_zero_o => s_bit_index_is_zero);
-----------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
s_bit_index_top <= to_unsigned (15, s_bit_index'length) when s_sending_fss = '1' or s_sending_data = '1' else
to_unsigned (s_crc_bytes_manch'length-1, s_bit_index'length) when s_sending_crc = '1' else
to_unsigned (c_FES'length - 1, s_bit_index'length) when s_sending_fes = '1' else
to_unsigned (c_FSS'length - 1, s_bit_index'length);
s_bit_index_load <= (s_bit_index_is_zero and tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-1)) when
(s_sending_fss = '1' or s_sending_data = '1' or s_sending_crc = '1' or s_sending_fes = '1') else
'1' when s_prepare_to_produce ='1' else
'0';
s_bit_index_decr_p <= tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-1) when
(s_sending_fss = '1' or s_sending_data = '1' or s_sending_crc = '1' or s_sending_fes = '1') else '0';
---------------------------------------------------------------------------------------------------
-- Bits delivery --
---------------------------------------------------------------------------------------------------
-- Synchronous process Bits_Delivery: handling of nanoFIP output signal FD_TXD by
-- placing bits of data according to the state of wf_tx_serializer's state machine and to the
-- counter s_bit_index. The delivery takes place upon a tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-3)
-- pulse.
Bits_Delivery: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
s_txd <= '0';
else
if tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-3) = '1' then
if s_sending_fss = '1' then
s_txd <= c_FSS (to_integer (s_bit_index)); -- FSS: 2 bytes long (no need to resize)
elsif s_sending_data = '1' then
s_txd <= s_data_byte_manch (to_integer (resize(s_bit_index, 4))); -- 1 data-byte at a time
elsif s_sending_crc = '1' then
s_txd <= s_crc_bytes_manch (to_integer (s_bit_index)); -- CRC: 2 bytes long
elsif s_sending_fes = '1' then
s_txd <= c_FES(to_integer (resize(s_bit_index,4))); -- FES: 1 byte
else
s_txd <= '0';
end if;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- TXENA generation --
---------------------------------------------------------------------------------------------------
-- Synchronous process FD_TXENA_Generator: The nanoFIP output FD_TXENA is activated at the
-- same moment as the first bit of the FSS starts being delivered and stays asserted until the
-- end of the delivery of the last FES bit.
FD_TXENA_Generator: process (uclk_i)
begin
if rising_edge (uclk_i) then
if nfip_rst_i = '1' then
tx_enable_o <= '0';
else
if ((s_sending_fss = '1') or (s_sending_data = '1') or (s_sending_crc = '1') or
(s_sending_fes = '1') or (s_stop_transmission = '1')) then -- tx sending bits
if tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-3) = '1' then
-- in order to synchronise the
tx_enable_o <= '1'; -- activation of tx_enable with the
-- the delivery of the 1st FSS bit
end if; -- FD_TXD (FSS) :________|-----|___________|--------
-- tx_sched_p_buff(1):______|-|___|-|___|-|___|-|___|-|__
-- sending_FSS :___|-------------------------------
-- FD_TXENA :________|--------------------------
else
tx_enable_o <= '0';
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------------------------------
-- Independent Timeout Counter --
---------------------------------------------------------------------------------------------------
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Instantiation of a wf_decr_counter relying only on the system clock as an additional
-- way to go back to IDLE state, in case any other logic is being stuck.
Session_Timeout_Counter: wf_decr_counter
generic map(g_counter_lgth => c_SESSION_TIMEOUT_C_LGTH)
port map(
uclk_i => uclk_i,
counter_rst_i => nfip_rst_i,
counter_top_i => (others => '1'),
counter_load_i => s_prepare_to_produce,
counter_decr_i => '1', -- on each uclk tick
counter_o => open,
---------------------------------------------------
counter_is_zero_o => s_session_timedout);
---------------------------------------------------
---------------------------------------------------------------------------------------------------
-- Outputs --
---------------------------------------------------------------------------------------------------
tx_data_o <= s_txd;
tx_osc_rst_p_o <= s_session_timedout;
tx_completed_p_o <= s_stop_transmission and tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-2);
tx_byte_request_p_o <= s_sending_data and s_bit_index_is_zero and tx_sched_p_buff_i(c_TX_SCHED_BUFF_LGTH-4);
-- request for a new byte from the wf_prod_bytes_retriever unit (passing from wf_engine_control)
end architecture rtl;
--=================================================================================================
-- architecture end
--=================================================================================================
---------------------------------------------------------------------------------------------------
-- E N D O F F I L E
---------------------------------------------------------------------------------------------------
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment