53 Commits

Author SHA1 Message Date
36a99d0bf4 Doc: Typo 2021-08-05 11:05:55 +02:00
4322debe14 Add 2nd interrupt latency measurement instance 2021-07-20 13:17:20 +02:00
83c3a4d910 Merge branch 'master' into latency_measure 2021-07-02 08:24:30 +02:00
98ba65bc62 Add open document format, register description of 2nd latency
measurement core
2021-07-02 08:18:36 +02:00
5bf9caae3a Merge branch 'added_robustness' into 'master'
Add robustness to comma-detection and reset generation.

See merge request GFA/Libraries/Firmware/VHDL/evr320!3
2021-03-16 07:44:43 +01:00
13d42baf14 Merge branch 'fix_issue_#5' into 'master'
Amendment: removed 'evr_params.cs_timeout_cnt' assignment

See merge request GFA/Libraries/Firmware/VHDL/evr320!2
2021-02-25 09:45:32 +01:00
till straumann
d135fbddca Add robustness to comma-detection and reset generation.
This patch addresses issues I occasionally observed:

a) I have seen occurrences when the GTX deasserts RXBYTEISALIGNED
   while the RXLOSSOFSYNC is *not* asserted.

   The comma-alignment state machine can be stuck in 'idle' believing
   all is well when in fact RXBYTEISALIGNED is deasserted.

   The proposed patch monitors RXBYTEISALIGNED in addition to
   RXLOSSOFSYNC in 'idle' state.

b) The synchronizer (inst_cdc_fast_stat) which takes the pulse
   width/delay to the EVR clock domain relies on a proper
   reset sequence for correct operation.

   It is possible, however, that the 'evr_clk' (which is generated
   from the recovered RX clock) is not ticking at all when 'xuser_RESET'
   resets said synchronizer. If e.g., there is no GTX reference clock
   present (because it requires i2c initialization which is performed
   later) then the EVR clock may not be ticking and prevent the
   destination side of the synchronizer from being reset. This
   has the consequence of 'width' and 'delay' *never* being
   updated.

   The proposed patch asserts the synchronizer reset while the RX PLL
   and/or MMCM are not locked.
2021-02-24 14:03:16 +01:00
till straumann
badd801839 Amendment: removed 'evr_params.cs_timeout_cnt' assignment
This parameter is a local enhancement and not present on the
master branch.

Also: two small changes which address GHDL issues.
2021-02-24 13:46:29 +01:00
df8522473d Merge branch 'fix_issue_#5' into 'master'
Fix for issue #5 (wrong endianness of data stream in test bed)

See merge request GFA/Libraries/Firmware/VHDL/evr320!1
2021-02-24 11:47:11 +01:00
till straumann
50860b9e20 Fix for issue #5 (wrong endianness of data stream in test bed)
The 'evr320_data_filter' entity presents data in little-endian format.
However, the test is written for big-endian; set the SWAP generic to
fix this.

Also; once this test passes events won't be detected because the checksum
timeout is not reached. Set to zero.

Last: ghdl complains about mem_data(x) indexing when x > C_MEM_DATA_WIDTH.
Replaced hard-coded statements by a simple loop that runs from
0 to C_MEM_DATA_WIDTH/8 - 1.
2021-02-24 11:08:05 +01:00
5bebe6dc41 Doc: Corrected latency counter register 0x38 description 2021-02-03 15:26:50 +01:00
83b6d6562d FIX: event_decoder ports in tb updated. Added Event Flag check for data width = 64. 2020-12-17 09:33:03 +01:00
34b221f62a FIX: typo introduced in rebase 2020-12-02 15:04:20 +01:00
26cc7548a3 FIX: default pulse width of user events set to 4 2020-12-02 10:29:58 +01:00
6d3fa8708a Merge branch 'latfix' 2020-11-18 15:21:13 +01:00
95a88cbba0 FEATURES: Add reset at the output of the ifc1210 wrapper 2020-09-02 08:30:00 +02:00
e6a3441a7a BUGFIX: added write register to stop latency counter 2020-03-05 07:46:30 +01:00
287bfde2e0 FEATURE: Add SWAP generic to filter and correct TB accordingly 2020-01-31 13:58:41 +01:00
3f1b7acc50 DEVEL: filter modification based on address decoding 2020-01-28 13:15:06 +01:00
fdcadda6ed FEATURE: evr320 filter input address settable
DOC: Correct address map for pulse length & delay
2020-01-23 07:27:41 +01:00
0d6457cb77 BIGFIX: For simu initialize delay value to 0 2019-12-13 14:34:37 +01:00
83a4435e41 BUGFIX: std_logic_vector -> std_logic at output of delay (0) 2019-12-12 18:27:50 +01:00
b77484c659 UPDATE: update due to delay modification 2019-12-11 16:28:26 +01:00
071cf50ded DPDCY: due to change in PSI_COMMON suffix 2 -> cfg in ifc1210 wrapper 2019-12-02 15:12:31 +01:00
5a060a160c FEATURE: add to TMEM interface regiter width & delay 2019-11-29 15:13:46 +01:00
6b1f4fbcbc FEATUE: Modify delay & width as registers 2019-11-29 11:48:12 +01:00
ffb3eb6331 FEATURE: add delay/length pulse parameters as generics on ifc1210 wrapper 2019-11-25 16:42:03 +01:00
d5b3545ef2 FEATURE: Add parameters for delay and pulse length on IFC1210 wrapper 2019-11-25 16:38:13 +01:00
2ce1941a6c added gitignore for modelsim 2019-11-06 10:03:57 +01:00
99e2fe462a updated doc with latency measurement register description 2019-11-05 13:18:22 +01:00
16e7d3e9f6 added testbench over ifc wrapper for tmem test 2019-11-04 15:47:49 +01:00
60ad0be56e feature: added register for latency measurement counter since a specific
event occured
2019-11-04 15:26:04 +01:00
740c93fd7a BUGFIX: inserted address delay for read data mux 2019-10-24 17:00:10 +02:00
c846a32902 DEVEL: removed usage of lib ieee.std_logic_unsigned 2019-10-21 11:05:34 +02:00
b171096b8a DEVEL: extended testbench with checks for event recorder 2019-10-18 16:23:28 +02:00
a3ff15adec FIX: rearrange compile order and set LibPath relative to file location to be able source from application project 2019-10-16 15:18:21 +02:00
bc987bee99 DEVL: decouple user event counting from events in the event stream, peparation to simulate event recorder functionality 2019-10-04 13:15:22 +02:00
4f9e87b16d readme: add dependencies 2018-12-06 10:46:24 +01:00
82c023c610 change: split streaming port to data and address 2018-12-06 10:00:53 +01:00
84f23d13ab event event reception check in simulation, fix stimuli 2018-12-05 17:14:04 +01:00
c52673a8ca simulate stream filter, integrated to if1210 wrapper, syntax fixes 2018-12-05 10:08:52 +01:00
d7e669cb75 extended ifc1210_wrapper with data streaming port and replaced frequency
measurement by common lib
2018-12-04 21:13:51 +01:00
84440ce6a0 added data filter from decoder stream 2018-12-04 17:02:10 +01:00
5e79f3f426 self checking segment sent/recv comparison 2018-12-04 17:01:38 +01:00
35077a9d84 self checking testbench: read MGT frame from file and compare data
stream
2018-12-03 17:15:39 +01:00
2634412bd0 added decoder streaming output and UVVM simulation 2018-11-30 16:25:00 +01:00
da6ab3236a added constrain template 2018-11-29 14:07:45 +01:00
6b512782f3 migrate decoder sim from cvs: prints transfered data buffer to terminal 2018-11-29 13:05:15 +01:00
426fa8bc1c added new GTX for Virtex-6 in HIPA Timing System 2018-07-16 15:00:47 +02:00
Oliver Bruendler
30d692b872 Repository was moved from git@git.psi.ch:DigitaleSignalVerarbeitung/Libraries/VHDL/evr320.git 2018-07-09 08:34:33 +02:00
5f1af19d28 signal name updated to introduced sync stage. 2018-06-26 14:52:06 +02:00
77adb7b9e2 reg sync, clean-up comments 2018-06-08 11:25:56 +02:00
4aecb89683 generate pdf from updated documentation 2018-05-03 13:55:23 +02:00
33 changed files with 17068 additions and 2141 deletions

View File

@@ -1,11 +1,23 @@
## 2.1
## 2.3
* Added Features
* Event Recorder functionality implemented as an option
* IFC1210 bindings for tosca2
* Bugfixes
* None
* IFC1210 wrapper includes block to adjust pulse length of individual event and also its delay, both in recovery clock cycles. Set by constant parameter under array format.
## 2.2
* Added Features
* HIPA option for Virtex-6 GTX -> pkg_v6vlx_gtxe1.vhd separated to different files to avoid duplicated code.
* use_MMCM generic is derived from FACILITY generic which implicitly contains line rate (use MMCM when line rate > 2.5Gbps).
* Bugfixes
* signal names in added sync stage were not adapted.
## 2.1
* Added Features
* Event Recorder functionality implemented as an option
* IFC1210 bindings for tosca2
* Bugfixes
* None
## 2.0
* Migration from CVS /G/GPAC/Lib/Vivado_Lib/axi_evr320_2.0
* Migration from CVS /G/GPAC/Lib/Vivado_Lib/axi_evr320_2.0

View File

@@ -1,43 +1,47 @@
## General Information
The EVR320 Embedded Event Receiver (EEVR) is able to connect with a MRF Timing System.
# General Information
The EVR320 Embedded Event Receiver (EEVR) is able to connect with a MRF Timing System.
Mainly the EEVR is used to decode configurable events and use them in firmware as triggers.
## Maintainer
Patric Bucher [patric.bucher@psi.ch]
Patric Bucher [patric.bucher@psi.ch]
Jonas Purtschert [jonas.purtschert@psi.ch]
## Authors
Waldemar Koprek [waldemar.koprek@psi.ch]
Goran Marinkovic [goran.marinkovic@psi.ch]
Patric Bucher [patric.bucher@psi.ch]
Waldemar Koprek [waldemar.koprek@psi.ch]
Goran Marinkovic [goran.marinkovic@psi.ch]
Patric Bucher [patric.bucher@psi.ch]
Jonas Purtschert [jonas.purtschert@psi.ch]
## Documentation
See [EVR320 Documentation](doc/evr320.pdf "doc/evr320.pdf")
See [EVR320 Documentation](doc/evr320.pdf "doc/evr320.pdf")
## Changelog
See [Changelog](Changelog.md)
See [Changelog](Changelog.md)
## What belongs into this Library
All components and wrappers to connect various buses (AXI4, TOSCA-II, ..) and to use on different Xilinx FPGA's.
All components and wrappers to connect various buses (AXI4, TOSCA-II, ..) and to use on different Xilinx FPGA's.
Examples for things that belong into this library:
- Event Decoder / Core Functionality
- Different MGT types
Examples for things that belong into this library:
* Event Decoder / Core Functionality
* Different MGT types
Examples for things that do not belong into this library:
* Vivado IP Packager related files -> belong to separate git repo
Examples for things that do not belong into this library:
- Vivado IP Packager related files -> belong to separate git repo
## Dependencies
### Library
* Libraries/TCL/PsiSim
* Libraries/BoardSupport/ifc1210/tosca2 (with tosca2 only)
### Synthesis
- Libraries/Firmware/VHDL/psi\_common (https://github.com/paulscherrerinstitute/psi_common)
### Simulation
- Libraries/Firmware/TCL/PsiSim
- Libraries/Firmware/VHDL/psi\_common (https://github.com/paulscherrerinstitute/psi_common)
- Libraries/Firmware/VHDL/UVVM (https://github.com/UVVM/UVVM)
### with IFC1210 Bindings
- Libraries/BoardSupport/IFC1210/tosca2

6
constraints/eevr.ucf Normal file
View File

@@ -0,0 +1,6 @@
# FIFO clock crossing for streaming interface:
# constrain to have less delay than one clock cycle of the faster clock:
set_max_delay -datapath_only -from <ClkA> -to <ClkB> <faster_clock_period>
set_max_delay -datapath_only -from <ClkB> -to <ClkA> <faster_clock_period>

BIN
doc/evr320.odt Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -11,7 +11,7 @@
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
@@ -89,7 +89,7 @@ begin
if rising_edge(clka) then
if (ena = '1') then
if (wea = '1') then
RAM(conv_integer(page_addr_clka & addra)) := dia;
RAM(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra)))) := dia;
end if;
end if;
end if;
@@ -99,10 +99,10 @@ begin
begin
if rising_edge(clkb) then
if (enb = '1') then
dob( 7 downto 0) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "00"));
dob(15 downto 8) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "01"));
dob(23 downto 16) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "10"));
dob(31 downto 24) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "11"));
dob( 7 downto 0) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "00"))));
dob(15 downto 8) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "01"))));
dob(23 downto 16) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "10"))));
dob(31 downto 24) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "11"))));
end if;
end if;
end process;
@@ -117,9 +117,9 @@ begin
if (ena = '1') then
if (wea = '1') then
if (addra(0) = '1') then
RAM_ODD (conv_integer(page_addr_clka & addra(addra'high downto 1))) := dia;
RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clka & addra(addra'high downto 1))))) := dia;
else
RAM_EVEN(conv_integer(page_addr_clka & addra(addra'high downto 1))) := dia;
RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra(addra'high downto 1))))) := dia;
end if;
end if;
end if;
@@ -130,14 +130,14 @@ begin
begin
if rising_edge(clkb) then
if (enb = '1') then
dob( 7 downto 0) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "00"));
dob(15 downto 8) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "00"));
dob(23 downto 16) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "01"));
dob(31 downto 24) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "01"));
dob(39 downto 32) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "10"));
dob(47 downto 40) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "10"));
dob(55 downto 48) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "11"));
dob(63 downto 56) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "11"));
dob( 7 downto 0) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "00"))));
dob(15 downto 8) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "00"))));
dob(23 downto 16) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "01"))));
dob(31 downto 24) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "01"))));
dob(39 downto 32) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "10"))));
dob(47 downto 40) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "10"))));
dob(55 downto 48) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "11"))));
dob(63 downto 56) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "11"))));
end if;
end if;
end process;

View File

@@ -0,0 +1,92 @@
------------------------------------------------------------------------------
-- Copyright (c) 2018 by Paul Scherrer Institute, Switzerland
-- All rights reserved.
-- Project: evr320
-- Authors: Jonas Purtschert
-- Description: Filter a specific data field from data buffer stream of the decoder:
-- Modif: Benoit Stef
-- not based on counter anymore but map to LSB into a generic array
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.psi_common_math_pkg.all;
entity evr320_data_filter is
generic (NUM_BYTES : integer := 8;
SWAP : boolean := false ); -- if true byte are swpped at output
port ( -- User stream interface
i_stream_clk : in std_logic; -- user clock
i_stream_data : in std_logic_vector(7 downto 0);
i_stream_addr : in std_logic_vector(10 downto 0);
i_stream_valid : in std_logic;
i_address : in std_logic_vector(11 downto 0);
-- filter output:
o_data : out std_logic_vector(NUM_BYTES*8-1 downto 0) := (others=>'0');
o_valid : out std_logic := '0'
);
end entity;
architecture behavioral of evr320_data_filter is
-- array to store data value prior to map to output
type byte_array_t is array (NUM_BYTES-1 downto 0) of std_logic_vector(i_stream_data'range);
signal table_s : byte_array_t;
--pipe help
signal addr_dff_s : std_logic_vector(10 downto 0) := (others=>'0');
signal data_dff_s : std_logic_vector(i_stream_data'range) := (others=>'0');
signal filt_dff_s : std_logic_vector(i_address'range);
--helper
constant low_bd_c : integer := log2ceil(NUM_BYTES); --compute LSB for address decoding
signal ena_s : std_logic_vector(1 downto 0); --clock enable vector
begin
p : process(i_stream_clk)
begin
if (rising_edge(i_stream_clk)) then
--*** 1st pipe stage ***
ena_s(0) <= i_stream_valid;
filt_dff_s <= i_address;
if (i_stream_valid = '1') then
addr_dff_s <= i_stream_addr;
data_dff_s <= i_stream_data;
end if;
--*** filling the array ***
if ena_s(0) = '1' then
if addr_dff_s(10 downto low_bd_c) = filt_dff_s(10 downto low_bd_c) then
--*** spatial loop ***
ena_s(1) <= '1';
for i in 0 to NUM_BYTES-1 loop
if addr_dff_s(low_bd_c-1 downto 0) = to_uslv(i,low_bd_c) then
table_s(i) <= data_dff_s ;
end if;
end loop;
end if;
else
ena_s(1) <= '0';
end if;
--*** set the output & valid accordingly***
if ena_s(1) = '1' then
if (from_uslv(addr_dff_s) = (from_uslv(filt_dff_s) + NUM_BYTES -1)) then
o_valid <= '1';
--*** spatial loop map output ***
for i in 0 to NUM_BYTES-1 loop
if SWAP then
o_data(NUM_BYTES+i*NUM_BYTES-1 downto 0+i*NUM_BYTES) <= table_s(NUM_BYTES-1-i);
else
o_data(NUM_BYTES+i*NUM_BYTES-1 downto 0+i*NUM_BYTES) <= table_s(i);
end if;
end loop;
else
o_valid <= '0';
end if;
end if;
end if;
end process;
end architecture;

View File

@@ -12,15 +12,15 @@
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
library unisim;
use unisim.vcomponents.all;
library work;
use work.evr320_pkg.all;
entity evr320_decoder is
generic
(
@@ -51,11 +51,20 @@ entity evr320_decoder is
i_mem_addr : in std_logic_vector(11 downto 0);
o_mem_data : out std_logic_vector(MEM_DATA_WIDTH - 1 downto 0);
--------------------------------------------------------------------------
-- User stream interface User clock
--------------------------------------------------------------------------
i_stream_clk : in std_logic;
o_stream_data : out std_logic_vector(7 downto 0);
o_stream_addr : out std_logic_vector(10 downto 0);
o_stream_valid : out std_logic;
--------------------------------------------------------------------------
-- User interface MGT clock
--------------------------------------------------------------------------
o_usr_events : out std_logic_vector( 3 downto 0);
o_usr_events_ext : out std_logic_vector( 3 downto 0);
o_sos_event : out std_logic
o_sos_event : out std_logic;
o_event : out std_logic_vector( 7 downto 0);
o_event_valid : out std_logic
);
end evr320_decoder;
@@ -87,9 +96,9 @@ architecture behavioral of evr320_decoder is
-- Events received
type usr_events_type is array (0 to 3) of std_logic_vector( 3 downto 0);
signal usr_events : usr_events_type := (others => (others => '0'));
signal cs_timeout_cnt : std_logic_vector(23 downto 0) := (others => '0');
signal cs_min_cnt : std_logic_vector(31 downto 0) := (others => '0');
signal cs_min_time : std_logic_vector(31 downto 0) := (others => '0');
signal cs_timeout_cnt : unsigned(23 downto 0) := (others => '0');
signal cs_min_cnt : unsigned(31 downto 0) := (others => '0');
signal cs_min_time : unsigned(31 downto 0) := (others => '0');
signal evr_stable : std_logic := '0';
-- Frame fsm
@@ -117,7 +126,7 @@ architecture behavioral of evr320_decoder is
constant frame_chk2 : std_logic_vector( 3 downto 0) := "1000";
signal frame_fsm : std_logic_vector( 3 downto 0) := "0000";
-- Frame checksum
signal frame_chk : std_logic_vector(15 downto 0) := X"FFFF";
signal frame_chk : unsigned(15 downto 0) := X"FFFF";
signal frame_chk_ok : std_logic := '0';
signal frame_chk1_ok : std_logic := '0';
signal frame_chk2_ok : std_logic := '0';
@@ -142,8 +151,8 @@ architecture behavioral of evr320_decoder is
signal frame_data_rden : std_logic := '0';
signal frame_data_do : std_logic_vector(63 downto 0) := (others => '0');
-- Frame data FIFO write port
signal frame_data_wr_id : std_logic_vector( 7 downto 0) := (others => '0');
signal frame_data_wr_addr_cnt: std_logic_vector(15 downto 0) := (others => '0');
signal frame_data_wr_id : unsigned( 7 downto 0) := (others => '0');
signal frame_data_wr_addr_cnt: unsigned(15 downto 0) := (others => '0');
signal frame_data_wr_addr : std_logic_vector(10 downto 0) := (others => '0');
signal frame_data_wr_byte : std_logic_vector( 7 downto 0) := (others => '0');
-- Frame data FIFO read port
@@ -166,10 +175,12 @@ architecture behavioral of evr320_decoder is
signal mem_fsm : std_logic_vector( 1 downto 0) := "00";
-- Data memory address
signal mem_addr : std_logic_vector(11 downto 0);
signal mem_addr_dly : std_logic_vector(11 downto 0);
-- Data memory write
signal mem_data_wren : std_logic := '0';
signal mem_data_wr_addr : std_logic_vector(10 downto 0) := (others => '0');
signal mem_data_wr_byte : std_logic_vector( 7 downto 0) := (others => '0');
signal mem_data : std_logic_vector(11+8-1 downto 0);
-- Data memory read
signal mem_data_dpram : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0');
signal mem_data_event0 : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0');
@@ -182,16 +193,16 @@ architecture behavioral of evr320_decoder is
signal usr_events_save_dly : std_logic := '0';
signal usr_events_nr : std_logic_vector( 7 downto 0) := (others => '0');
signal usr_events_nr_dly : std_logic_vector( 7 downto 0) := (others => '0');
signal usr_events_addr : std_logic_vector( 7 downto 0) := (others => '0');
signal usr_events_addr : unsigned( 7 downto 0) := (others => '0');
signal usr_events_addr_dly : std_logic_vector( 7 downto 0) := (others => '0');
signal usr_events_cnt : std_logic_vector( 31 downto 0) := (others => '0');
signal usr_events_cnt_d : std_logic_vector( 31 downto 0) := (others => '0');
signal usr_events_cnt : unsigned( 31 downto 0) := (others => '0');
signal usr_events_cnt_d : unsigned( 31 downto 0) := (others => '0');
signal all_events_flags : std_logic_vector(255 downto 0) := (others => '0');
signal all_events_flags_d : std_logic_vector(255 downto 0) := (others => '0');
signal all_events_flags_sync1 : std_logic_vector(255 downto 0) := (others => '0');
signal all_events_flags_sync2 : std_logic_vector(255 downto 0) := (others => '0');
signal timestamp_cnt : std_logic_vector( 31 downto 0) := (others => '0');
signal timestamp_cnt_dly : std_logic_vector( 31 downto 0) := (others => '0');
signal timestamp_cnt : unsigned( 31 downto 0) := (others => '0');
signal timestamp_cnt_dly : unsigned( 31 downto 0) := (others => '0');
signal segment_addr_wren : std_logic;
signal mem_data_valid : std_logic;
signal mem_data_error : std_logic;
@@ -203,7 +214,7 @@ architecture behavioral of evr320_decoder is
signal mem_data_event_nr_timestamp : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0');
signal mem_data_dpram_sos : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0');
signal mem_data_segment_timestamp : std_logic_vector(MEM_DATA_WIDTH - 1 downto 0) := (others => '0');
signal stream_raw : std_logic_vector(18 downto 0);
-- attribute safe_implementation: string;
-- attribute safe_implementation of frame_fsm : signal is "yes";
-- attribute safe_implementation of mem_fsm : signal is "yes";
@@ -220,7 +231,7 @@ begin
debug_clk <= i_mgt_rx_clk;
debug( 15 downto 0) <= i_mgt_rx_data;
debug( 17 downto 16) <= i_mgt_rx_charisk;
debug( 18) <= '0';
debug( 23 downto 18) <= (others=>'0');
debug( 31 downto 24) <= (others => '0');
debug( 35 downto 32) <= "0001" when (frame_fsm = frame_idle ) else
"0010" when (frame_fsm = frame_addr_gap) else
@@ -246,14 +257,14 @@ begin
debug( 65) <= usr_events_save_dly;
debug( 73 downto 66) <= usr_events_nr_dly;
debug( 81 downto 74) <= usr_events_addr_dly;
debug(113 downto 82) <= timestamp_cnt_dly;
debug(113 downto 82) <= std_logic_vector(timestamp_cnt_dly);
debug(114) <= segment_addr_wren;
debug(115) <= mem_data_valid;
debug(116) <= mem_data_error;
debug(117) <= mem_data_read_ack(0);
debug(118) <= mem_data_error_ack(0);
debug(119) <= all_events_flags(27); -- event code 27 (photonics)
debug(127 downto 120) <= usr_events_cnt(7 downto 0);
debug(127 downto 120) <= std_logic_vector(usr_events_cnt(7 downto 0));
end generate dbg_evt_rec;
dbg_no_evt_rec: if not(EVENT_RECORDER) generate
@@ -286,7 +297,9 @@ begin
if (i_mgt_rst = '1') then
evr_stable <= '0';
else
if ((cs_min_cnt > i_evr_params.cs_min_cnt) and (cs_min_time > i_evr_params.cs_min_time) and (cs_timeout_cnt < X"15CA20")) then
if ((std_logic_vector(cs_min_cnt) > i_evr_params.cs_min_cnt) and
(std_logic_vector(cs_min_time) > i_evr_params.cs_min_time) and
(std_logic_vector(cs_timeout_cnt) < X"15CA20")) then
evr_stable <= '1';
else
evr_stable <= '0';
@@ -448,7 +461,7 @@ begin
frame_data_wr_addr_cnt <= (others => '0');
when frame_addr =>
frame_data_wr_id <= frame_data_wr_id + X"01";
frame_data_wr_addr_cnt <= "0000" & i_mgt_rx_data(15 downto 8) & "0000";
frame_data_wr_addr_cnt <= "0000" & unsigned(i_mgt_rx_data(15 downto 8)) & "0000";
segment_addr_wren <= '1';
when frame_data =>
if (((i_mgt_rx_charisk( 1) = '1') and (i_mgt_rx_data(15 downto 8) = C_KCHAR_END)) or
@@ -457,7 +470,7 @@ begin
else
frame_data_wren <= not frame_data_full;
frame_data_wr_addr_cnt <= frame_data_wr_addr_cnt + X"0001";
frame_data_wr_addr <= frame_data_wr_addr_cnt(10 downto 0);
frame_data_wr_addr <= std_logic_vector(frame_data_wr_addr_cnt(10 downto 0));
frame_data_wr_byte <= i_mgt_rx_data(15 downto 8);
end if;
when others =>
@@ -478,7 +491,7 @@ begin
frame_chk <= X"FFFF";
when frame_addr | frame_data =>
if (i_mgt_rx_charisk = "00") then
frame_chk <= frame_chk - (X"00" & i_mgt_rx_data(15 downto 8));
frame_chk <= frame_chk - (X"00" & unsigned(i_mgt_rx_data(15 downto 8)));
end if;
when others =>
null;
@@ -494,11 +507,11 @@ begin
frame_chk1_ok <= '0';
frame_chk2_ok <= '0';
when frame_chk1 =>
if (frame_chk(15 downto 8) = i_mgt_rx_data(15 downto 8)) then
if (frame_chk(15 downto 8) = unsigned(i_mgt_rx_data(15 downto 8))) then
frame_chk1_ok <= '1';
end if;
when frame_chk2 =>
if (frame_chk( 7 downto 0) = i_mgt_rx_data(15 downto 8)) then
if (frame_chk( 7 downto 0) = unsigned(i_mgt_rx_data(15 downto 8))) then
frame_chk2_ok <= '1';
end if;
when others =>
@@ -524,7 +537,7 @@ begin
end if;
end process;
frame_ctrl_wr_id <= frame_data_wr_id;
frame_ctrl_wr_id <= std_logic_vector(frame_data_wr_id);
frame_ctrl_wr_ok <= frame_chk_ok;
frame_ctrl_di( 7 downto 0) <= frame_ctrl_wr_id;
@@ -586,7 +599,7 @@ begin
frame_ctrl_rd_ok <= frame_ctrl_do( 8);
-- Frame data received
frame_data_di( 7 downto 0) <= frame_data_wr_id;
frame_data_di( 7 downto 0) <= std_logic_vector(frame_data_wr_id);
frame_data_di(18 downto 8) <= frame_data_wr_addr;
frame_data_di(23 downto 19) <= "00000";
frame_data_di(31 downto 24) <= frame_data_wr_byte;
@@ -697,14 +710,27 @@ begin
mem_data_wr_addr <= frame_data_rd_addr;
mem_data_wr_byte <= frame_data_rd_byte;
-- concatenate - this avoids an internal error in ghdl v0.37!
mem_data <= mem_data_wr_addr & mem_data_wr_byte;
-----------------------------------------------------------------------------
-- Address delay for read data mux
-----------------------------------------------------------------------------
process(i_usr_clk)
begin
if (i_usr_clk'event and (i_usr_clk = '1')) then
mem_addr_dly <= mem_addr;
end if;
end process;
-----------------------------------------------------------------------------
-- Data memory selector
-----------------------------------------------------------------------------
o_mem_data <= mem_data_dpram when (mem_addr(11 downto 9) = "000") else
mem_data_event0 when (mem_addr(11 downto 9) = "001") else
mem_data_event1 when (mem_addr(11 downto 9) = "010") else
mem_data_event2 when (mem_addr(11 downto 9) = "011") else
mem_data_event3 when (mem_addr(11 downto 9) = "100") else
o_mem_data <= mem_data_dpram when (mem_addr_dly(11 downto 9) = "000") else
mem_data_event0 when (mem_addr_dly(11 downto 9) = "001") else
mem_data_event1 when (mem_addr_dly(11 downto 9) = "010") else
mem_data_event2 when (mem_addr_dly(11 downto 9) = "011") else
mem_data_event3 when (mem_addr_dly(11 downto 9) = "100") else
mem_data_event_recorder;
-----------------------------------------------------------------------------
@@ -826,7 +852,71 @@ begin
dob => mem_data_event3
);
-------------------------------------------------------------------------
-- async fifo for streaming interface
-------------------------------------------------------------------------
strm_fifo_inst : entity work.psi_common_async_fifo
generic map (
Width_g => 11+8,
Depth_g => 2048,
AlmFullOn_g => false,
AlmFullLevel_g => 2,
AlmEmptyOn_g => false,
AlmEmptyLevel_g => 2,
RamStyle_g => "WBR",
RamBehavior_g => "block" -- auto, distributed
)
port map (
-- Control Ports
InClk => i_mgt_rx_clk,
InRst => i_mgt_rst,
OutClk => i_stream_clk,
OutRst => '0',
-- Input Data
InData => mem_data,
InVld => mem_data_wren,
InRdy => open,
-- Output Data
OutData => stream_raw,
OutVld => o_stream_valid,
OutRdy => '1',
-- Input Status
InFull => open,
InEmpty => open,
InAlmFull => open,
InAlmEmpty => open,
InLevel => open,
-- Output Status
OutFull => open,
OutEmpty => open,
OutAlmFull => open,
OutAlmEmpty => open,
OutLevel => open
);
o_stream_data <= stream_raw(7 downto 0);
o_stream_addr <= stream_raw(18 downto 8);
-----------------------------------------------------------------------------
-- Raw Event Output
-----------------------------------------------------------------------------
raw_event_output_proc : process(i_mgt_rx_clk)
begin
if (rising_edge(i_mgt_rx_clk)) then
o_event_valid <= '0';
o_event <= (others=>'0');
if ((i_mgt_rx_charisk(0) = '0') and (evr_stable = '1')) then
o_event_valid <= '1';
o_event <= i_mgt_rx_data(7 downto 0);
end if;
end if;
end process;
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- EVENT RECORDER
@@ -906,7 +996,7 @@ begin
end if;
-- set flag for appeared event
all_events_flags(conv_integer(i_mgt_rx_data(7 downto 0))) <= '1';
all_events_flags(to_integer(unsigned(i_mgt_rx_data(7 downto 0)))) <= '1';
end if;
end if;
@@ -923,7 +1013,7 @@ begin
timestamp_cnt_dly <= timestamp_cnt;
usr_events_save_dly <= usr_events_save;
usr_events_nr_dly <= usr_events_nr;
usr_events_addr_dly <= usr_events_addr;
usr_events_addr_dly <= std_logic_vector(usr_events_addr);
end if;
end process;
@@ -970,11 +1060,11 @@ begin
--------------------------------------------------------------------------
-- Memory Selector Event Recorder
--------------------------------------------------------------------------
mem_data_event_recorder <= mem_data_dpram_sos when (mem_addr(11 downto 9) = B"101") else -- 2K
mem_data_event_nr_timestamp when (mem_addr(11 downto 8) = B"1100") else -- 1K
mem_data_segment_timestamp when (mem_addr(11 downto 7) = B"1101_0") else -- 512B
mem_data_event_nr when (mem_addr(11 downto 6) = B"1101_10") else -- 256B
mem_data_event_flag when (mem_addr(11 downto 6) = B"1101_11") else -- 256B
mem_data_event_recorder <= mem_data_dpram_sos when (mem_addr_dly(11 downto 9) = B"101") else -- 2K
mem_data_event_nr_timestamp when (mem_addr_dly(11 downto 8) = B"1100") else -- 1K
mem_data_segment_timestamp when (mem_addr_dly(11 downto 7) = B"1101_0") else -- 512B
mem_data_event_nr when (mem_addr_dly(11 downto 6) = B"1101_10") else -- 256B
mem_data_event_flag when (mem_addr_dly(11 downto 6) = B"1101_11") else -- 256B
(others => '0');
@@ -1021,8 +1111,8 @@ begin
clka => i_mgt_rx_clk,
ena => HIGH,
wea => segment_addr_wren,
addra => frame_data_wr_addr_cnt(10 downto 4),
dia => timestamp_cnt,
addra => std_logic_vector(frame_data_wr_addr_cnt(10 downto 4)),
dia => std_logic_vector(timestamp_cnt),
page => sos_event(3),
-- port b
clkb => i_usr_clk,
@@ -1047,7 +1137,7 @@ begin
ena => HIGH,
wea => usr_events_save_dly,
addra => usr_events_addr_dly,
dia => timestamp_cnt_dly,
dia => std_logic_vector(timestamp_cnt_dly),
page => sos_event(3),
-- port b
clkb => i_usr_clk,
@@ -1081,7 +1171,6 @@ begin
dob => mem_data_event_nr
);
--------------------------------------------------------------------------
-- Event Flags of all Events
--------------------------------------------------------------------------
@@ -1094,7 +1183,7 @@ begin
all_events_flags_sync2 <= all_events_flags_sync1;
-- address fragment of vector / expand bit to bytes for data read
v_addr := conv_integer(mem_addr(5 downto MEM_ADDR_LSB) & LOW_slv(1 + MEM_ADDR_LSB downto 0));
v_addr := to_integer(unsigned(std_logic_vector'(mem_addr(5 downto MEM_ADDR_LSB) & LOW_slv(1 + MEM_ADDR_LSB downto 0))));
mem_data_event_flag <= bit2byte(all_events_flags_sync2(v_addr + MEM_DATA_BYTES - 1 downto v_addr));
end if;
end process;
@@ -1104,7 +1193,7 @@ begin
-- port mapping
--------------------------------------------------------------------------
o_sos_event <= sos_event(3);
o_event_recorder_stat.usr_events_counter <= usr_events_cnt_d;
o_event_recorder_stat.usr_events_counter <= std_logic_vector(usr_events_cnt_d);
o_event_recorder_stat.data_valid <= mem_data_valid;
o_event_recorder_stat.data_error <= mem_data_error;
@@ -1127,4 +1216,4 @@ end behavioral;
--------------------------------------------------------------------------------
-- End of file
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

View File

@@ -11,7 +11,7 @@
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity evr320_dpram is
@@ -59,7 +59,7 @@ begin
if rising_edge(clka) then
if (ena = '1') then
if (wea = '1') then
RAM(conv_integer(addra)) := dia;
RAM(to_integer(unsigned(addra))) := dia;
end if;
end if;
end if;
@@ -69,10 +69,10 @@ begin
begin
if rising_edge(clkb) then
if (enb = '1') then
dob( 7 downto 0) <= RAM(conv_integer(addrb & "00"));
dob(15 downto 8) <= RAM(conv_integer(addrb & "01"));
dob(23 downto 16) <= RAM(conv_integer(addrb & "10"));
dob(31 downto 24) <= RAM(conv_integer(addrb & "11"));
dob( 7 downto 0) <= RAM(to_integer(unsigned(std_logic_vector'(addrb & "00"))));
dob(15 downto 8) <= RAM(to_integer(unsigned(std_logic_vector'(addrb & "01"))));
dob(23 downto 16) <= RAM(to_integer(unsigned(std_logic_vector'(addrb & "10"))));
dob(31 downto 24) <= RAM(to_integer(unsigned(std_logic_vector'(addrb & "11"))));
end if;
end if;
end process;
@@ -87,9 +87,9 @@ begin
if (ena = '1') then
if (wea = '1') then
if (addra(0) = '1') then
RAM_ODD (conv_integer(addra(addra'high downto 1))) := dia;
RAM_ODD (to_integer(unsigned(addra(addra'high downto 1)))) := dia;
else
RAM_EVEN(conv_integer(addra(addra'high downto 1))) := dia;
RAM_EVEN(to_integer(unsigned(addra(addra'high downto 1)))) := dia;
end if;
end if;
end if;
@@ -100,14 +100,14 @@ begin
begin
if rising_edge(clkb) then
if (enb = '1') then
dob( 7 downto 0) <= RAM_EVEN(conv_integer(addrb & "00"));
dob(15 downto 8) <= RAM_ODD (conv_integer(addrb & "00"));
dob(23 downto 16) <= RAM_EVEN(conv_integer(addrb & "01"));
dob(31 downto 24) <= RAM_ODD (conv_integer(addrb & "01"));
dob(39 downto 32) <= RAM_EVEN(conv_integer(addrb & "10"));
dob(47 downto 40) <= RAM_ODD (conv_integer(addrb & "10"));
dob(55 downto 48) <= RAM_EVEN(conv_integer(addrb & "11"));
dob(63 downto 56) <= RAM_ODD (conv_integer(addrb & "11"));
dob( 7 downto 0) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(addrb & "00"))));
dob(15 downto 8) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(addrb & "00"))));
dob(23 downto 16) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(addrb & "01"))));
dob(31 downto 24) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(addrb & "01"))));
dob(39 downto 32) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(addrb & "10"))));
dob(47 downto 40) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(addrb & "10"))));
dob(55 downto 48) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(addrb & "11"))));
dob(63 downto 56) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(addrb & "11"))));
end if;
end if;
end process;

View File

@@ -2,283 +2,377 @@
-- Paul Scherrer Institute (PSI)
-- ---------------------------------------------------------------------------
-- Unit : evr320_ifc1210_wrapper.vhd
-- Author : Patric Bucher
-- Author : Patric Bucher, Benoit Stef
-- ---------------------------------------------------------------------------
-- Copyright© PSI, Section DSV
-- ---------------------------------------------------------------------------
-- Comment :
-- Comment : Wraps evr320 decoder together with GTX component and TMEM registers.
-- ---------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.tosca2_glb_pkg.all;
use work.evr320_pkg.all;
use work.pkg_v6vlx_gtxe1.all;
library tosca2;
use tosca2.tosca2_glb_pkg.all;
use work.evr320_pkg.all;
use work.v6vlx_gtxe1_pkg.all;
entity evr320_ifc1210_wrapper is
generic(
g_MGT_LOCATION : string := "GTXE1_X0Y16";
g_REFCLK_MHZ : real := 142.8;
g_USE_MMCM : boolean := false;
g_EVENT_RECORDER : boolean := false
g_MGT_LOCATION : string := "GTXE1_X0Y16"; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY : string := "SFEL"; -- "HIPA" | "SFEL"
g_EVENT_RECORDER : boolean := false; -- enable/disable Event Recorder functionality
g_XUSER_CLK_FREQ : natural := 125000000 -- Xuser Clk Frequency in Hz
);
port(
tick1sec_i : in std_logic;
-- ------------------------------------------------------------------------
-- Debug interface
-- ------------------------------------------------------------------------
debug_clk : out std_logic;
debug : out std_logic_vector(127 downto 0);
debug_clk : out std_logic;
debug : out std_logic_vector(127 downto 0);
-- ------------------------------------------------------------------------
-- TOSCA2 TMEM Interface (xuser clock domain, 100-250MHz)
-- ------------------------------------------------------------------------
xuser_CLK : in std_logic;
xuser_RESET : in std_logic;
xuser_TMEM_ENA : in std_logic;
xuser_TMEM_WE : in std_logic_vector( 7 downto 0);
xuser_TMEM_ADD : in std_logic_vector(13 downto 3);
xuser_TMEM_DATW : in std_logic_vector(63 downto 0);
xuser_TMEM_DATR : out std_logic_vector(63 downto 0);
xuser_CLK : in std_logic;
xuser_RESET : in std_logic;
xuser_TMEM_ENA : in std_logic;
xuser_TMEM_WE : in std_logic_vector(7 downto 0);
xuser_TMEM_ADD : in std_logic_vector(13 downto 3);
xuser_TMEM_DATW : in std_logic_vector(63 downto 0);
xuser_TMEM_DATR : out std_logic_vector(63 downto 0);
-- ------------------------------------------------------------------------
-- MGT Interface
-- ------------------------------------------------------------------------
mgt_refclk_i : in std_logic; -- MGT Reference Clock
mgt_sfp_los_i : in std_logic; -- SFP Loss of Signal (light on receiver)
mgt_rx_n : in std_logic; -- MGT RX N
mgt_rx_p : in std_logic; -- MGT RX P
mgt_tx_n : out std_logic; -- MGT TX N
mgt_tx_p : out std_logic; -- MGT TX P
mgt_status_o : out std_logic_vector(31 downto 0); -- MGT Status
mgt_control_i : in std_logic_vector(31 downto 0); -- MGT Control
mgt_refclk_i : in std_logic; -- MGT Reference Clock
mgt_sfp_los_i : in std_logic; -- SFP Loss of Signal (light on receiver)
mgt_rx_n : in std_logic; -- MGT RX N
mgt_rx_p : in std_logic; -- MGT RX P
mgt_tx_n : out std_logic; -- MGT TX N
mgt_tx_p : out std_logic; -- MGT TX P
mgt_status_o : out std_logic_vector(31 downto 0); -- MGT Status
mgt_control_i : in std_logic_vector(31 downto 0); -- MGT Control
---------------------------------------------------------------------------
-- User interface MGT clock
---------------------------------------------------------------------------
clk_evr_o : out std_logic; -- Recovered parallel clock from MGT
usr_events_o : out std_logic_vector( 3 downto 0); -- User defined event pulses with one clock cycle length
usr_events_ext_o : out std_logic_vector( 3 downto 0); -- User defined event pulses with four clock cycle length
sos_event_o : out std_logic -- Start-of-Sequence Event
clk_evr_o : out std_logic; -- Recovered parallel clock from MGT
rst_evr_o : out std_logic; -- reset according to RX Loss of sync
usr_events_o : out std_logic_vector(3 downto 0); -- User defined event pulses with one clock cycles length & no delay
sos_event_o : out std_logic; -- Start-of-Sequence Event
usr_events_adj_o : out std_logic_vector(3 downto 0); -- User defined event pulses adjusted in delay & length
sos_events_adj_o : out std_logic; -- Start-of-Sequence adjusted in delay & length
--------------------------------------------------------------------------
-- Decoder axi stream interface, User clock
--------------------------------------------------------------------------
stream_clk_i : in std_logic := '0';
stream_data_o : out std_logic_vector(7 downto 0);
stream_addr_o : out std_logic_vector(10 downto 0);
stream_valid_o : out std_logic
);
end evr320_ifc1210_wrapper;
architecture rtl of evr320_ifc1210_wrapper is
-- --------------------------------------------------------------------------
-- Parameters
-- --------------------------------------------------------------------------
-- constant c_BYTE : integer := 8;
constant c_TOSCA2_DATA_WIDTH : integer := 64;
-- constant c_EVR_REG64_COUNT : integer := 16;
-- constant c_EVR_MEM_SIZE : integer := 16384;
-- constant c_EVR_ADDR_WIDTH : integer := integer(ceil(log2(real(c_EVR_MEM_SIZE/(c_TOSCA2_DATA_WIDTH/c_BYTE)))));
constant c_TOSCA2_DATA_WIDTH : integer := 64;
constant c_EVR_REG64_COUNT : integer := 16; -- unused, only documentation
constant c_EVR_MEM_SIZE : integer := 16384; -- unused, only documentation
-- --------------------------------------------------------------------------
-- Signal definitions
-- --------------------------------------------------------------------------
signal clk_evr : std_logic;
--signal clk_evr_monitor : std_logic; -- for debugging
signal rst_evr : std_logic;
signal mgt_control : std_logic_vector(31 downto 0) := (others => '0');
signal mgt_control_sync : std_logic_vector(31 downto 0) := (others => '0');
signal mgt_control_sync2 : std_logic_vector(31 downto 0) := (others => '0');
signal mgt_sfp_los : std_logic := '0';
signal mgt_sfp_los_sync : std_logic := '0';
signal mgt_status : std_logic_vector(31 downto 0);
signal mgt_rx_data : std_logic_vector(15 downto 0);
signal mgt_rx_charisk : std_logic_vector( 1 downto 0);
signal mgt_lossofsync : std_logic;
signal mgt_reset_tmem_evr : std_logic; -- for legacy reasons, ifc1210 mgt control is in tmem_psi_generic part
signal mgt_reset_tmem_evr_sync1 : std_logic := '0';
signal mgt_reset_tmem_evr_sync2 : std_logic := '0';
signal mem_clk : std_logic;
signal mem_addr_evr : std_logic_vector(11 downto 0);
signal mem_addr_tosca : std_logic_vector(10 downto 0);
signal mem_data : std_logic_vector(c_TOSCA2_DATA_WIDTH-1 downto 0);
signal evr_params : typ_evr320_params;
signal event_recorder_status : typ_evt_rec_status;
signal event_recorder_control : typ_evt_rec_ctrl;
signal evr_counter_rst : std_logic_vector( 2 downto 0) := (others => '0');
signal evr_clk_counter : std_logic_vector(31 downto 0) := (others => '0');
signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0');
signal debug_data : std_logic_vector(127 downto 0);
signal clk_evr : std_logic;
--signal clk_evr_monitor : std_logic; -- for debugging
signal rst_evr : std_logic;
signal mgt_control : std_logic_vector(31 downto 0) := (others => '0');
signal mgt_status : std_logic_vector(31 downto 0);
signal mgt_rx_data : std_logic_vector(15 downto 0);
signal mgt_rx_charisk : std_logic_vector(1 downto 0);
signal mgt_lossofsync : std_logic;
signal mgt_reset_tmem_evr : std_logic; -- for legacy reasons, ifc1210 mgt control is in tmem_psi_generic part
signal mem_clk : std_logic;
signal mem_addr_evr : std_logic_vector(11 downto 0);
signal mem_addr_tosca : std_logic_vector(10 downto 0);
signal mem_data : std_logic_vector(c_TOSCA2_DATA_WIDTH - 1 downto 0);
signal evr_params : typ_evr320_params;
signal evr_params_sync : typ_evr320_params;
signal evr_params_xuser : typ_evr320_params;
signal event_recorder_status : typ_evt_rec_status;
signal event_recorder_control : typ_evt_rec_ctrl;
signal event_recorder_control_sync : typ_evt_rec_ctrl;
signal event_recorder_control_xuser : typ_evt_rec_ctrl;
signal evr_latency_measure_A_stat : typ_rec_latency_measure_stat;
signal evr_latency_measure_A_ctrl : typ_rec_latency_measure_ctrl;
signal evr_latency_measure_B_stat : typ_rec_latency_measure_stat;
signal evr_latency_measure_B_ctrl : typ_rec_latency_measure_ctrl;
signal evr_frequency : std_logic_vector(31 downto 0) := (others => '0');
signal debug_data : std_logic_vector(127 downto 0);
signal decoder_event_valid : std_logic;
signal decoder_event : std_logic_vector(7 downto 0);
-- --------------------------------------------------------------------------
-- Attribute definitions
-- --------------------------------------------------------------------------
attribute keep : string;
attribute keep of clk_evr : signal is "TRUE";
attribute keep of debug_data : signal is "TRUE";
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- //////////////////// Main Body /////////////////////////
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
attribute keep : string;
attribute keep of clk_evr : signal is "TRUE";
attribute keep of debug_data : signal is "TRUE";
signal usr_events_s : std_logic_vector(3 downto 0);
signal sos_event_s : std_logic;
signal evr_rst_s : std_logic;
signal usr_event_delay_s : typ_arr_delay;
signal usr_event_width_s : typ_arr_width;
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
-- //////////////////// Main Body /////////////////////////
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
begin
-- --------------------------------------------------------------------------
-- static signal assignments
-- --------------------------------------------------------------------------
mgt_lossofsync <= mgt_status(15);
rst_evr <= mgt_status(15);
mem_addr_evr <= '0' & mem_addr_tosca;
mgt_lossofsync <= mgt_status(15);
rst_evr_o <= mgt_status(15);
mem_addr_evr <= '0' & mem_addr_tosca;
mgt_control(c_GTXRESET) <= mgt_control_i(c_GTXRESET) or mgt_sfp_los_i or mgt_reset_tmem_evr;
mgt_control(4 downto 1) <= mgt_control_i(4 downto 1);
mgt_control(c_RXCDRRESET) <= mgt_control_i(c_RXCDRRESET);
mgt_control(31 downto 6) <= mgt_control_i(31 downto 6);
mgt_control(c_GTXRESET) <= mgt_control_i(c_GTXRESET) or mgt_sfp_los_i or mgt_reset_tmem_evr;
mgt_control( 4 downto 1) <= mgt_control_i( 4 downto 1);
mgt_control(c_RXCDRRESET) <= mgt_control_i(c_RXCDRRESET);
mgt_control(31 downto 6) <= mgt_control_i(31 downto 6);
-- --------------------------------------------------------------------------
-- Synchronisation to EVR Clock
-- --------------------------------------------------------------------------
-- prc_sync_evr: process(clk_evr)
-- begin
-- if rising_edge(clk_evr) then
-- ---
-- -- mgt_sfp_los_sync <= mgt_sfp_los_i;
-- -- mgt_sfp_los <= mgt_sfp_los_sync;
-- ---
-- -- mgt_control_sync <= mgt_control_i;
-- -- mgt_control_sync2 <= mgt_control_sync;
-- ---
-- -- mgt_reset_tmem_evr_sync1 <= mgt_reset_tmem_evr;
-- -- mgt_reset_tmem_evr_sync2 <= mgt_reset_tmem_evr_sync1;
-- ---
-- -- evr_params and event_recorder_control add sync here or in evr320_decoder
-- ---
-- -- mgt_control(c_GTXRESET) <= mgt_control_sync2(c_GTXRESET);
-- -- -- mgt_control(c_GTXRESET) <= mgt_control_sync2(c_GTXRESET) or mgt_sfp_los or mgt_reset_tmem_evr_sync2;
-- -- mgt_control( 4 downto 1) <= mgt_control_sync2( 4 downto 1);
-- -- mgt_control(c_RXCDRRESET) <= mgt_control_sync2(c_RXCDRRESET);
-- -- mgt_control(31 downto 6) <= mgt_control_sync2(31 downto 6);
-- ---
-- end if;
-- end process;
prc_sync_evr : process(clk_evr)
begin
if rising_edge(clk_evr) then
---
evr_params_sync <= evr_params_xuser;
evr_params <= evr_params_sync;
---
event_recorder_control_sync <= event_recorder_control_xuser;
event_recorder_control <= event_recorder_control_sync;
---
end if;
end process;
-- --------------------------------------------------------------------------
-- EVR320 Decoder
-- --------------------------------------------------------------------------
evr320_decoder_inst: entity work.evr320_decoder
evr320_decoder_inst : entity work.evr320_decoder
generic map(
EVENT_RECORDER => g_EVENT_RECORDER,
MEM_DATA_WIDTH => c_TOSCA2_DATA_WIDTH )
EVENT_RECORDER => g_EVENT_RECORDER,
MEM_DATA_WIDTH => c_TOSCA2_DATA_WIDTH)
port map(
-- Debug interface
debug_clk => debug_clk,
debug => debug_data,
debug_clk => debug_clk,
debug => debug_data,
-- GTX parallel interface
i_mgt_rst => mgt_lossofsync,
i_mgt_rx_clk => clk_evr,
i_mgt_rx_data => mgt_rx_data,
i_mgt_rx_charisk => mgt_rx_charisk,
i_mgt_rst => mgt_lossofsync,
i_mgt_rx_clk => clk_evr,
i_mgt_rx_data => mgt_rx_data,
i_mgt_rx_charisk => mgt_rx_charisk,
-- User interface CPU clock
i_usr_clk => mem_clk,
i_evr_params => evr_params,
o_event_recorder_stat => event_recorder_status,
i_event_recorder_ctrl => event_recorder_control,
i_mem_addr => mem_addr_evr,
o_mem_data => mem_data,
i_usr_clk => mem_clk,
i_evr_params => evr_params,
o_event_recorder_stat => event_recorder_status,
i_event_recorder_ctrl => event_recorder_control,
i_mem_addr => mem_addr_evr,
o_mem_data => mem_data,
-- user stream interface, user clock
i_stream_clk => stream_clk_i,
o_stream_data => stream_data_o,
o_stream_addr => stream_addr_o,
o_stream_valid => stream_valid_o,
-- User interface MGT clock
o_usr_events => usr_events_o,
o_usr_events_ext => usr_events_ext_o,
o_sos_event => sos_event_o
);
o_usr_events => usr_events_s,
-- o_usr_events_ext => usr_events_ext_o, -- not in use anymore
o_sos_event => sos_event_s,
o_event => decoder_event,
o_event_valid => decoder_event_valid
);
usr_events_o <= usr_events_s;
sos_event_o <= sos_event_s;
-- --------------------------------------------------------------------------
-- MGT Wrapper for GTX Virtex-6
-- --------------------------------------------------------------------------
mgt_wrapper_inst: entity work.v6vlx_gtxe1_wrapper
mgt_wrapper_inst : entity work.v6vlx_gtxe1_wrapper
generic map(
g_MGT_LOCATION => g_MGT_LOCATION,
g_USE_MMCM => g_USE_MMCM )
port map(
g_MGT_LOCATION => g_MGT_LOCATION,
g_FACILITY => g_FACILITY)
port map(
-- MGT serial interface
i_mgt_refclk => mgt_refclk_i,
o_mgt_refclk => open,
i_mgt_rx_p => mgt_rx_p,
i_mgt_rx_n => mgt_rx_n,
o_mgt_tx_p => mgt_tx_p,
o_mgt_tx_n => mgt_tx_n,
i_mgt_refclk => mgt_refclk_i,
o_mgt_refclk => open,
i_mgt_rx_p => mgt_rx_p,
i_mgt_rx_n => mgt_rx_n,
o_mgt_tx_p => mgt_tx_p,
o_mgt_tx_n => mgt_tx_n,
-- MGT parallel interface
o_mgt_status => mgt_status,
i_mgt_control => mgt_control,
o_mgt_recclk => clk_evr,
o_mgt_rx_data => mgt_rx_data,
o_mgt_rx_charisk => mgt_rx_charisk
o_mgt_status => mgt_status,
i_mgt_control => mgt_control,
o_mgt_recclk => clk_evr,
o_mgt_rx_data => mgt_rx_data,
o_mgt_rx_charisk => mgt_rx_charisk
);
-- --------------------------------------------------------------------------
-- TMEM
-- --------------------------------------------------------------------------
evr320_tmem_inst: entity work.evr320_tmem
port map(
-- TOSCA2 TMEM Interface
xuser_CLK => xuser_CLK,
xuser_RESET => xuser_RESET,
xuser_TMEM_ENA => xuser_TMEM_ENA,
xuser_TMEM_WE => xuser_TMEM_WE,
xuser_TMEM_ADD => xuser_TMEM_ADD,
xuser_TMEM_DATW => xuser_TMEM_DATW,
xuser_TMEM_DATR => xuser_TMEM_DATR,
-- EVR320 Memory/Parameter Interface
evr_params_o => evr_params,
evr_frequency_i => evr_frequency,
evr_evt_rec_status_i => event_recorder_status,
evr_evt_rec_control_o => event_recorder_control,
mgt_status_i => mgt_status,
mgt_reset_o => mgt_reset_tmem_evr,
mem_clk_o => mem_clk,
mem_addr_o => mem_addr_tosca,
mem_data_i => mem_data
);
-- --------------------------------------------------------------------------
--formatter:off
evr320_tmem_inst : entity work.evr320_tmem
port map(
-- TOSCA2 TMEM Interface
xuser_CLK => xuser_CLK,
xuser_RESET => xuser_RESET,
xuser_TMEM_ENA => xuser_TMEM_ENA,
xuser_TMEM_WE => xuser_TMEM_WE,
xuser_TMEM_ADD => xuser_TMEM_ADD,
xuser_TMEM_DATW => xuser_TMEM_DATW,
xuser_TMEM_DATR => xuser_TMEM_DATR,
-- EVR320 Memory/Parameter Interface
evr_params_o => evr_params_xuser,
evr_frequency_i => evr_frequency,
evr_evt_rec_status_i => event_recorder_status,
evr_evt_rec_control_o => event_recorder_control_xuser,
evr_latency_measure_A_stat_i => evr_latency_measure_A_stat,
evr_latency_measure_A_ctrl_o => evr_latency_measure_A_ctrl,
evr_latency_measure_B_stat_i => evr_latency_measure_B_stat,
evr_latency_measure_B_ctrl_o => evr_latency_measure_B_ctrl,
mgt_status_i => mgt_status,
mgt_reset_o => mgt_reset_tmem_evr,
mem_clk_o => mem_clk,
mem_addr_o => mem_addr_tosca,
mem_data_i => mem_data,
--
evr_clk_i => clk_evr,
evr_rst_i => evr_rst_s,
evr_pulse_delay_o => usr_event_delay_s,
evr_pulse_width_o => usr_event_width_s);
-- --------------------------------------------------------------------------
-- Measure EVR Clock (based on xuser_CLK)
-- --------------------------------------------------------------------------
prc_count_cycles: process(clk_evr)
clock_meas_inst : entity work.psi_common_clk_meas
generic map(
MasterFrequency_g => g_XUSER_CLK_FREQ,
MaxMeasFrequency_g => 150000000
)
port map(
ClkMaster => xuser_CLK,
Rst => xuser_RESET,
ClkTest => clk_evr,
FrequencyHz => evr_frequency
);
-- --------------------------------------------------------------------------
-- Latency Measurement for IFC1210 Interrupts
-- --------------------------------------------------------------------------
latency_meas_A_inst : entity work.latency_measurement
generic map(
CLK_FREQ_HZ => g_XUSER_CLK_FREQ
)
port map(
evr_clk_i => clk_evr,
xuser_clk_i => xuser_CLK,
decoder_event_valid_i => decoder_event_valid,
decoder_event_i => decoder_event,
status_o => evr_latency_measure_A_stat,
ctrl_i => evr_latency_measure_A_ctrl
);
latency_meas_B_inst : entity work.latency_measurement
generic map(
CLK_FREQ_HZ => g_XUSER_CLK_FREQ
)
port map(
evr_clk_i => clk_evr,
xuser_clk_i => xuser_CLK,
decoder_event_valid_i => decoder_event_valid,
decoder_event_i => decoder_event,
status_o => evr_latency_measure_B_stat,
ctrl_i => evr_latency_measure_B_ctrl
);
-- --------------------------------------------------------------------------
-- Add delay output
-- --------------------------------------------------------------------------
output_delay_block : block
signal rst0_s, rst1_s : std_logic; -- double stage sync for reset
signal usr_evt_shaped_s : std_logic_vector(4 downto 0);
signal usr_events_adj_s : std_logic_vector(4 downto 0);
signal usr_events_concat_s : std_logic_vector(4 downto 0);
signal mmcm_locked : std_logic;
signal rxpll_locked : std_logic;
signal evr_rst_in : std_logic;
begin
if rising_edge(clk_evr) then
if (evr_counter_rst(2 downto 1) = "01") then
evr_frequency <= evr_clk_counter;
evr_clk_counter <= (others => '0');
else
evr_clk_counter <= evr_clk_counter + X"0000_0001";
rxpll_locked <= mgt_status(1);
mmcm_locked <= mgt_status(2);
evr_rst_in <= xuser_RESET or (not rxpll_locked) or (not mmcm_locked);
--*** double stage sync for reset ***--
proc_rst : process(clk_evr)
begin
if rising_edge(clk_evr) then
rst0_s <= evr_rst_in;
rst1_s <= rst0_s;
end if;
-- sync reset and detect edge
evr_counter_rst <= evr_counter_rst(1 downto 0) & tick1sec_i;
end if;
end process;
end process;
evr_rst_s <= rst1_s;
usr_events_concat_s <= usr_events_s & sos_event_s;
gene_adj_out : for i in 0 to 4 generate
--*** Adjust pulse length in clk cycles EVENT 0,1,2,3 ***
inst_pulslength_evt0 : entity work.psi_common_pulse_shaper_cfg
generic map(HoldIn_g => false,
HoldOffEna_g => false,
MaxHoldOff_g => 10,
MaxDuration_g => MaxDuration_c,
RstPol_g => '1')
port map(clk_i => clk_evr,
rst_i => rst1_s,
width_i => usr_event_width_s(i),
hold_i => (others => '0'),
dat_i => usr_events_concat_s(i),
dat_o => usr_evt_shaped_s(i));
--*** delay adjust EVENT 0,1,2,3***
inst_adjdelay_evt0 : entity work.psi_common_delay_cfg
generic map(Width_g => 1,
MaxDelay_g => MaxDelay_c,
RStPol_g => '1',
RamBehavior_g => "RBW",
Hold_g => True)
port map( clk_i => clk_evr,
rst_i => rst1_s,
dat_i(0) => usr_evt_shaped_s(i),
str_i => '1',
del_i => usr_event_delay_s(i),
dat_o(0) => usr_events_adj_s(i));
end generate;
usr_events_adj_o <= usr_events_adj_s(4 downto 1);
sos_events_adj_o <= usr_events_adj_s(0);
end block;
-- --------------------------------------------------------------------------
-- port mapping
-- --------------------------------------------------------------------------
clk_evr_o <= clk_evr;
mgt_status_o <= mgt_status;
debug <= debug_data;
clk_evr_o <= clk_evr;
mgt_status_o <= mgt_status;
debug <= debug_data;
end rtl;
-- ----------------------------------------------------------------------------
-- ////////////////////////////////////////////////////////////////////////////
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------

View File

@@ -12,17 +12,19 @@
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.psi_common_math_pkg.all;
package evr320_pkg is
-- --------------------------------------------------------------------------
-- Constants
-- --------------------------------------------------------------------------
constant c_CHECKSUM_MIN_EVT : std_logic_vector(31 downto 0) := X"00000064"; -- Check sum min count for events 100
constant c_CHECKSUM_MIN_TIME : std_logic_vector(31 downto 0) := X"0015CA20"; -- Check sum min time for events 10 ms
constant c_SOS_EVENT_DEFAULT : std_logic_vector( 7 downto 0) := X"20"; -- decimal 32
constant c_CHECKSUM_MIN_EVT : std_logic_vector(31 downto 0) := X"00000064"; -- Check sum min count for events 100
constant c_CHECKSUM_MIN_TIME : std_logic_vector(31 downto 0) := X"0015CA20"; -- Check sum min time for events 10 ms
constant c_SOS_EVENT_DEFAULT : std_logic_vector( 7 downto 0) := X"26"; -- default start-of-sequence (SOS) event
-- --------------------------------------------------------------------------
-- Type Definitions
-- --------------------------------------------------------------------------
@@ -52,6 +54,23 @@ package evr320_pkg is
error_ack : std_logic;
end record typ_evt_rec_ctrl;
type typ_rec_latency_measure_ctrl is record
event_nr : std_logic_vector(7 downto 0);
counter_arm : std_logic;
end record;
type typ_rec_latency_measure_stat is record
counter_val : std_logic_vector(31 downto 0);
event_detected : std_logic;
end record;
--*** Type record and constant for new feature pulse width & delay ***
constant MaxDuration_c : positive := 2**16-1; -- defines maximum pulse width to add on user events pulse output, in recovery clock cycles
constant MaxDelay_c : positive := 2**16-1; -- defines maximum delay to add on user events pulse output, in recovery clock cycles
constant UsrEventWidthDefault_c : std_logic_vector(log2ceil(MaxDuration_c)-1 downto 0) := std_logic_vector(to_unsigned(4, log2ceil(MaxDuration_c))); -- default pulse width of usr_events_adj_o
type typ_arr_width is array (4 downto 0) of std_logic_vector(log2ceil(MaxDuration_c)-1 downto 0);
type typ_arr_delay is array (4 downto 0) of std_logic_vector(log2ceil(MaxDelay_c)-1 downto 0);
-- --------------------------------------------------------------------------
-- Type Initialisation
@@ -60,7 +79,15 @@ package evr320_pkg is
data_error => '0',
usr_events_counter => (others =>'0'));
constant c_INIT_EVT_REC_CTRL : typ_evt_rec_ctrl := ( event_number => (others=>'0'),
event_enable => '0',
data_ack => '0',
error_ack => '0');
constant c_INIT_REC_LATENCY_MEASURE_CTRL : typ_rec_latency_measure_ctrl := (event_nr => (others =>'0'),
counter_arm => '1');
constant c_INIT_REC_LATENCY_MEASURE_STAT : typ_rec_latency_measure_stat := (counter_val => (others =>'0'),
event_detected => '0');
-- --------------------------------------------------------------------------
-- Function Prototypes
-- --------------------------------------------------------------------------
@@ -95,4 +122,4 @@ package body evr320_pkg is
end package body evr320_pkg;
--------------------------------------------------------------------------------
-- End of file
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

View File

@@ -11,7 +11,7 @@
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
@@ -95,10 +95,10 @@ begin
if rising_edge(clka) then
if (ena = '1') then
if (wea = '1') then
RAM(conv_integer(page_addr_clka & addra & "00")) := dia( 7 downto 0);
RAM(conv_integer(page_addr_clka & addra & "01")) := dia(15 downto 8);
RAM(conv_integer(page_addr_clka & addra & "10")) := dia(23 downto 16);
RAM(conv_integer(page_addr_clka & addra & "11")) := dia(31 downto 24);
RAM(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & "00")))) := dia( 7 downto 0);
RAM(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & "01")))) := dia(15 downto 8);
RAM(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & "10")))) := dia(23 downto 16);
RAM(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & "11")))) := dia(31 downto 24);
end if;
end if;
end if;
@@ -108,10 +108,10 @@ begin
begin
if rising_edge(clkb) then
if (enb = '1') then
dob( 7 downto 0) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "00"));
dob(15 downto 8) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "01"));
dob(23 downto 16) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "10"));
dob(31 downto 24) <= RAM(conv_integer(page_addr_clkb( 3) & addrb & "11"));
dob( 7 downto 0) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "00"))));
dob(15 downto 8) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "01"))));
dob(23 downto 16) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "10"))));
dob(31 downto 24) <= RAM(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "11"))));
end if;
end if;
end process;
@@ -125,10 +125,10 @@ begin
if rising_edge(clka) then
if (ena = '1') then
if (wea = '1') then
RAM_EVEN(conv_integer(page_addr_clka & addra & '0')) := dia( 7 downto 0);
RAM_ODD (conv_integer(page_addr_clka & addra & '0')) := dia(15 downto 8);
RAM_EVEN(conv_integer(page_addr_clka & addra & '1')) := dia(23 downto 16);
RAM_ODD (conv_integer(page_addr_clka & addra & '1')) := dia(31 downto 24);
RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & '0')))) := dia( 7 downto 0);
RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & '0')))) := dia(15 downto 8);
RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & '1')))) := dia(23 downto 16);
RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clka & addra & '1')))) := dia(31 downto 24);
end if;
end if;
end if;
@@ -138,14 +138,14 @@ begin
begin
if rising_edge(clkb) then
if (enb = '1') then
dob( 7 downto 0) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "00"));
dob(15 downto 8) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "00"));
dob(23 downto 16) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "01"));
dob(31 downto 24) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "01"));
dob(39 downto 32) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "10"));
dob(47 downto 40) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "10"));
dob(55 downto 48) <= RAM_EVEN(conv_integer(page_addr_clkb( 3) & addrb & "11"));
dob(63 downto 56) <= RAM_ODD (conv_integer(page_addr_clkb( 3) & addrb & "11"));
dob( 7 downto 0) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "00"))));
dob(15 downto 8) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "00"))));
dob(23 downto 16) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "01"))));
dob(31 downto 24) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "01"))));
dob(39 downto 32) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "10"))));
dob(47 downto 40) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "10"))));
dob(55 downto 48) <= RAM_EVEN(to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "11"))));
dob(63 downto 56) <= RAM_ODD (to_integer(unsigned(std_logic_vector'(page_addr_clkb( 3) & addrb & "11"))));
end if;
end if;
end process;

View File

@@ -2,21 +2,21 @@
-- Paul Scherrer Institute (PSI)
-- ---------------------------------------------------------------------------
-- Unit : evr320_tmem.vhd
-- Author : Patric Bucher
-- Author : Patric Bucher, Benoit Stef
-- ---------------------------------------------------------------------------
-- Copyright© PSI, Section DSV
-- Copyright (c) PSI, Section DSV
-- ---------------------------------------------------------------------------
-- Comment :
-- Comment : TMEM address decoding for register and memory access to evr320.
-- ---------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.tosca2_glb_pkg.all;
use work.evr320_pkg.all;
library tosca2;
use tosca2.tosca2_glb_pkg.all;
use work.evr320_pkg.all;
entity evr320_tmem is
port(
@@ -37,11 +37,22 @@ entity evr320_tmem is
evr_frequency_i : in std_logic_vector(31 downto 0);
evr_evt_rec_status_i : in typ_evt_rec_status;
evr_evt_rec_control_o : out typ_evt_rec_ctrl;
mgt_status_i : in std_logic_vector(31 downto 0);
evr_latency_measure_A_stat_i : in typ_rec_latency_measure_stat;
evr_latency_measure_A_ctrl_o : out typ_rec_latency_measure_ctrl;
evr_latency_measure_B_stat_i : in typ_rec_latency_measure_stat;
evr_latency_measure_B_ctrl_o : out typ_rec_latency_measure_ctrl;
mgt_status_i : in std_logic_vector(31 downto 0) := (others=>'0');
mgt_reset_o : out std_logic;
mem_clk_o : out std_logic;
mem_addr_o : out std_logic_vector(10 downto 0);
mem_data_i : in std_logic_vector(63 downto 0)
mem_data_i : in std_logic_vector(63 downto 0);
---------------------------------------------------------------------------
-- EVR320 pulse output paremters
---------------------------------------------------------------------------
evr_clk_i : in std_logic;
evr_rst_i : in std_logic;
evr_pulse_delay_o : out typ_arr_delay;
evr_pulse_width_o : out typ_arr_width
);
end evr320_tmem;
@@ -52,6 +63,7 @@ architecture rtl of evr320_tmem is
-- Constants
-- ---------------------------------------------------------------------------
constant reserved : std_logic_vector(63 downto 0) := X"0000_0000_0000_0000";
constant c_LOW : std_logic_vector(63 downto 0) := X"0000_0000_0000_0000";
constant NUM_REG64 : integer := 16;
constant TMEM_ADDR_LSB : integer := 3; -- 64 bit
constant REG_ADDR_WIDTH : integer := integer(ceil(log2(real(NUM_REG64)))) + TMEM_ADDR_LSB;
@@ -91,11 +103,16 @@ architecture rtl of evr320_tmem is
signal er_handshake_status : std_logic_vector(31 downto 0) := (others => '0');
signal er_control_concat : std_logic_vector(31 downto 0) := (others => '0');
-- signal evr_force : std_logic_vector(3 downto 0) := (others => '0');
-- signal evr_force_rd : std_logic_vector(3 downto 0) := (others => '0'); -- readback
-- signal evr_force_pulse : typ_arr4(3 downto 0) := (others => (others => '0'));
-- latency measurement
signal lat_A_counter_arm, lat_B_counter_arm : std_logic := '0';
signal lat_A_event_nr, lat_B_event_nr : std_logic_vector(7 downto 0) := c_SOS_EVENT_DEFAULT;
signal lat_A_event_detected, lat_B_event_detected : std_logic_vector(7 downto 0);
signal lat_A_arm, lat_B_arm : std_logic := '0';
signal lat_A_arm_edge, lat_B_arm_edge : std_logic_vector(1 downto 0) := (others=>'0');
-- event pulse config
signal evr_puls_width_cfg_s : typ_arr_width := (others => UsrEventWidthDefault_c);
signal evr_puls_delay_cfg_s : typ_arr_delay := (others => (others => '0'));
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
@@ -111,6 +128,33 @@ begin
er_handshake_status <= X"0000" & bit2byte(er_status.data_error) & bit2byte(er_status.data_valid);
er_control_concat <= X"0000" & er_event_number & bit2byte(er_event_enable);
-- -----------------------------
-- latency measurement, arm
-- -----------------------------
process (xuser_CLK)
begin
if rising_edge(xuser_CLK) then
-- edge detection of latency arm:
lat_A_arm_edge <= lat_A_arm_edge(0) & lat_A_arm;
lat_A_counter_arm <= lat_A_arm_edge(0) and not lat_A_arm_edge(1);
lat_B_arm_edge <= lat_B_arm_edge(0) & lat_B_arm;
lat_B_counter_arm <= lat_B_arm_edge(0) and not lat_B_arm_edge(1);
if (evr_latency_measure_A_stat_i.event_detected = '1') then
lat_A_event_detected <= (others=>'1');
end if;
if (lat_A_counter_arm = '1') then
lat_A_event_detected <= (others=>'0');
end if;
if (evr_latency_measure_B_stat_i.event_detected = '1') then
lat_B_event_detected <= (others=>'1');
end if;
if (lat_B_counter_arm = '1') then
lat_B_event_detected <= (others=>'0');
end if;
end if;
end process;
-- --------------------------------------------------------------------------
-- Synchronisation to xuser_CLK
@@ -136,26 +180,32 @@ begin
end if;
end process;
-- --------------------------------------------------------------------------
-- Read operation
-- --------------------------------------------------------------------------
blk_tmemrd : block
begin
read_tmem_evr: process(xuser_CLK)
begin
if (rising_edge(xuser_CLK)) then
if (xuser_TMEM_ENA_reg = '1') then
if (xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = 0) then
if (xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = c_LOW(13 downto REG_ADDR_WIDTH)) then
case xuser_TMEM_ADD_reg(REG_ADDR_MSB downto TMEM_ADDR_LSB) is
when X"0" => xuser_TMEM_DATR <= event_numbers_concat & X"0000" & mgt_status_evr; -- 64bit / ByteAddr 000
when X"1" => xuser_TMEM_DATR <= reserved(63 downto 32) & X"0000_00" & bit2byte(mgt_reset); -- 64bit / ByteAddr 008 --> 0x00C = not implemented in ifc1210
when X"2" => xuser_TMEM_DATR <= reserved(63 downto 32) & bit2byte(event_enable); -- 64bit / ByteAddr 010 --> 0x014 = Bit0 SW Trigger Event 0, Bit8 SW Trigger Event 1, ... evr_force
when X"3" => xuser_TMEM_DATR <= evr_frequency & reserved(31 downto 0); -- 64bit / ByteAddr 018 --> 0x018 = Implementation Options + c_EVR_Location_vec
when X"4" => xuser_TMEM_DATR <= cs_min_time & cs_min_cnt; -- 64bit / ByteAddr 020
when X"5" => xuser_TMEM_DATR <= reserved(63 downto 0); -- 64bit / ByteAddr 028
when X"6" => xuser_TMEM_DATR <= reserved(63 downto 0); -- 64bit / ByteAddr 030
when X"7" => xuser_TMEM_DATR <= reserved(63 downto 0); -- 64bit / ByteAddr 038
when X"8" => xuser_TMEM_DATR <= er_handshake_status & er_control_concat; -- 64bit / ByteAddr 040
when X"9" => xuser_TMEM_DATR <= reserved(63 downto 32) & er_status.usr_events_counter; -- 64bit / ByteAddr 048
when X"0" => xuser_TMEM_DATR <= event_numbers_concat & X"0000" & mgt_status_evr; -- 64bit / ByteAddr 000
when X"1" => xuser_TMEM_DATR <= reserved(63 downto 32) & X"0000_00" & bit2byte(mgt_reset); -- 64bit / ByteAddr 008 --> 0x00C = not implemented in ifc1210
when X"2" => xuser_TMEM_DATR <= reserved(63 downto 32) & bit2byte(event_enable); -- 64bit / ByteAddr 010 --> 0x014 = Bit0 SW Trigger Event 0, Bit8 SW Trigger Event 1, ...
when X"3" => xuser_TMEM_DATR <= evr_frequency & reserved(31 downto 0); -- 64bit / ByteAddr 018 --> 0x018 = Implementation Options + c_EVR_Location_vec
when X"4" => xuser_TMEM_DATR <= cs_min_time & cs_min_cnt; -- 64bit / ByteAddr 020
when X"5" => xuser_TMEM_DATR <= reserved(63 downto 0); -- 64bit / ByteAddr 028
when X"6" => xuser_TMEM_DATR <= evr_latency_measure_A_stat_i.counter_val &
lat_B_event_detected & lat_A_event_detected & lat_B_event_nr & lat_A_event_nr; -- 64bit / ByteAddr 030
when X"7" => xuser_TMEM_DATR <= evr_latency_measure_B_stat_i.counter_val & reserved(31 downto 0); -- 64bit / ByteAddr 038
when X"8" => xuser_TMEM_DATR <= er_handshake_status & er_control_concat; -- 64bit / ByteAddr 040
when X"9" => xuser_TMEM_DATR <= reserved(63 downto 32) & er_status.usr_events_counter; -- 64bit / ByteAddr 048
when X"A" => xuser_TMEM_DATR <= evr_puls_delay_cfg_s(4) & evr_puls_delay_cfg_s(3) & evr_puls_delay_cfg_s(2) & evr_puls_delay_cfg_s(1) ; -- 64bit / ByteAddr 050
when X"B" => xuser_TMEM_DATR <= evr_puls_width_cfg_s(4) & evr_puls_width_cfg_s(3) & evr_puls_width_cfg_s(2) & evr_puls_width_cfg_s(1) ; --64 bit / ByteAddr 054
when X"C" => xuser_TMEM_DATR <= reserved(63 downto 32) & evr_puls_width_cfg_s(0) & evr_puls_delay_cfg_s(0); -- 64bit / ByteAddr 058
when others => xuser_TMEM_DATR <= (others => '0');
end case;
else --> 0x0080-0x4000
@@ -165,6 +215,7 @@ begin
end if;
end process;
end block;
-- --------------------------------------------------------------------------
-- Write operation - Byte control
@@ -176,9 +227,11 @@ begin
-- default assignments
er_data_ack <= er_data_ack(2 downto 0) & '0';
er_error_ack <= er_error_ack(2 downto 0) & '0';
lat_A_arm <= '0';
lat_B_arm <= '0';
if (xuser_TMEM_ENA_reg = '1' and xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = 0) then
if (xuser_TMEM_ENA_reg = '1' and xuser_TMEM_ADD_reg(13 downto REG_ADDR_WIDTH) = c_LOW(13 downto REG_ADDR_WIDTH)) then
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"0" then --ByteAddr 000
-- if xuser_TMEM_WE_reg(0) = '1' then -read only- <= xuser_TMEM_DATW_reg( 7 downto 0); end if;
@@ -224,6 +277,30 @@ begin
if xuser_TMEM_WE_reg(7) = '1' then cs_min_time(31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if;
end if;
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"6" then --ByteAddr 030 Latency Measurement
if xuser_TMEM_WE_reg(0) = '1' then lat_A_event_nr ( 7 downto 0) <= xuser_TMEM_DATW_reg( 7 downto 0); end if;
if xuser_TMEM_WE_reg(1) = '1' then lat_B_event_nr ( 7 downto 0) <= xuser_TMEM_DATW_reg(15 downto 8); end if;
-- if xuser_TMEM_WE_reg(1) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if;
-- if xuser_TMEM_WE_reg(2) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if;
-- if xuser_TMEM_WE_reg(3) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if;
-- if xuser_TMEM_WE_reg(4) = '1' then -reserved- ( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if;
-- if xuser_TMEM_WE_reg(5) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if;
-- if xuser_TMEM_WE_reg(6) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if;
-- if xuser_TMEM_WE_reg(7) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if;
end if;
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"7" then --ByteAddr 038 Latency Measurement
if xuser_TMEM_WE_reg(0) = '1' then lat_A_arm <= xuser_TMEM_DATW_reg(0); end if;
if xuser_TMEM_WE_reg(1) = '1' then lat_B_arm <= xuser_TMEM_DATW_reg(8); end if;
-- if xuser_TMEM_WE_reg(1) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(15 downto 8); end if;
-- if xuser_TMEM_WE_reg(2) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(23 downto 16); end if;
-- if xuser_TMEM_WE_reg(3) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(31 downto 24); end if;
-- if xuser_TMEM_WE_reg(4) = '1' then -reserved- ( 7 downto 0) <= xuser_TMEM_DATW_reg(39 downto 32); end if;
-- if xuser_TMEM_WE_reg(5) = '1' then -reserved- (15 downto 8) <= xuser_TMEM_DATW_reg(47 downto 40); end if;
-- if xuser_TMEM_WE_reg(6) = '1' then -reserved- (23 downto 16) <= xuser_TMEM_DATW_reg(55 downto 48); end if;
-- if xuser_TMEM_WE_reg(7) = '1' then -reserved- (31 downto 24) <= xuser_TMEM_DATW_reg(63 downto 56); end if;
end if;
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"8" then --ByteAddr 040
if xuser_TMEM_WE_reg(0) = '1' then er_event_enable <= xuser_TMEM_DATW_reg(0); end if;
if xuser_TMEM_WE_reg(1) = '1' then er_event_number <= xuser_TMEM_DATW_reg(15 downto 8); end if;
@@ -235,6 +312,24 @@ begin
if xuser_TMEM_WE_reg(7) = '1' and xuser_TMEM_DATW_reg(56) = '1' then er_error_ack <= (others => '1'); end if;
end if;
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"A" then --ByteAddr 050
if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_delay_cfg_s(1) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- usr evt 0 del
if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_delay_cfg_s(2) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- usr evt 1 del
if xuser_TMEM_WE_reg(5 downto 4) = "11" then evr_puls_delay_cfg_s(3) <= xuser_TMEM_DATW_reg(47 downto 32); end if; -- usr evt 2 del
if xuser_TMEM_WE_reg(7 downto 6) = "11" then evr_puls_delay_cfg_s(4) <= xuser_TMEM_DATW_reg(63 downto 48); end if; -- usr evt 3 del
end if;
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"B" then --ByteAddr 058
if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_width_cfg_s(1) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- usr evt 0 width
if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_width_cfg_s(2) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- usr evt 1 width
if xuser_TMEM_WE_reg(5 downto 4) = "11" then evr_puls_width_cfg_s(3) <= xuser_TMEM_DATW_reg(47 downto 32); end if; -- usr evt 2 width
if xuser_TMEM_WE_reg(7 downto 6) = "11" then evr_puls_width_cfg_s(4) <= xuser_TMEM_DATW_reg(63 downto 48); end if; -- usr evt 3 width
end if;
-----------------------------------------------------------------------------------------------------------------
if xuser_TMEM_ADD_reg(6 downto 3) = X"C" then --ByteAddr 060
if xuser_TMEM_WE_reg(1 downto 0) = "11" then evr_puls_delay_cfg_s(0) <= xuser_TMEM_DATW_reg(15 downto 0); end if; -- sos evt del
if xuser_TMEM_WE_reg(3 downto 2) = "11" then evr_puls_width_cfg_s(0) <= xuser_TMEM_DATW_reg(31 downto 16); end if; -- sos evt width
end if;
end if;
end if;
end process;
@@ -243,15 +338,61 @@ begin
-- --------------------------------------------------------------------------
-- Port mapping
-- --------------------------------------------------------------------------
mem_clk_o <= xuser_CLK;
mem_addr_o <= xuser_TMEM_ADD - MEM_ADDR_START;
evr_params_o <= (event_numbers, event_enable, cs_min_cnt, cs_min_time);
evr_evt_rec_control_o <= (er_event_number, er_event_enable, er_data_ack(3), er_error_ack(3));
mgt_reset_o <= mgt_reset;
mem_clk_o <= xuser_CLK;
mem_addr_o <= std_logic_vector(unsigned(xuser_TMEM_ADD) - unsigned(MEM_ADDR_START));
evr_params_o <= (event_numbers, event_enable, cs_min_cnt, cs_min_time);
evr_evt_rec_control_o <= (er_event_number, er_event_enable, er_data_ack(3), er_error_ack(3));
mgt_reset_o <= mgt_reset;
evr_latency_measure_A_ctrl_o <= (lat_A_event_nr, lat_A_counter_arm);
evr_latency_measure_B_ctrl_o <= (lat_B_event_nr, lat_B_counter_arm);
-- --------------------------------------------------------------------------
-- add CDC output
-- --------------------------------------------------------------------------
block_cdc_evr_puls_param : block
signal input_s, output_s : std_logic_vector(10 * 16 - 1 downto 0);
begin
-- ------------------------------------------------------------------------
-- Assemble Input
-- ------------------------------------------------------------------------
--** pulse delay parameters **
input_s(15 downto 0) <= evr_puls_delay_cfg_s(0);
input_s(31 downto 16) <= evr_puls_delay_cfg_s(1);
input_s(47 downto 32) <= evr_puls_delay_cfg_s(2);
input_s(63 downto 48) <= evr_puls_delay_cfg_s(3);
input_s(79 downto 64) <= evr_puls_delay_cfg_s(4);
--** pulse width parameters **
input_s(95 downto 80) <= evr_puls_width_cfg_s(0);
input_s(111 downto 96) <= evr_puls_width_cfg_s(1);
input_s(127 downto 112) <= evr_puls_width_cfg_s(2);
input_s(143 downto 128) <= evr_puls_width_cfg_s(3);
input_s(159 downto 144) <= evr_puls_width_cfg_s(4);
-- Instance
inst_cdc_fast_stat : entity work.psi_common_status_cc
generic map(DataWidth_g => input_s'length)
port map(ClkA => xuser_CLK,
RstInA => xuser_RESET,
DataA => input_s,
ClkB => evr_clk_i,
RstInB => evr_rst_i,
DataB => output_s);
-- ------------------------------------------------------------------------
-- Disassemble Output
-- ------------------------------------------------------------------------
--** pulse delay parameters **
evr_pulse_delay_o(0) <= output_s(15 downto 0);
evr_pulse_delay_o(1) <= output_s(31 downto 16);
evr_pulse_delay_o(2) <= output_s(47 downto 32);
evr_pulse_delay_o(3) <= output_s(63 downto 48);
evr_pulse_delay_o(4) <= output_s(79 downto 64);
--** pulse width parameters **
evr_pulse_width_o(0) <= output_s(95 downto 80);
evr_pulse_width_o(1) <= output_s(111 downto 96);
evr_pulse_width_o(2) <= output_s(127 downto 112);
evr_pulse_width_o(3) <= output_s(143 downto 128);
evr_pulse_width_o(4) <= output_s(159 downto 144);
end block;
end rtl;
-- ----------------------------------------------------------------------------
-- ////////////////////////////////////////////////////////////////////////////
-- ----------------------------------------------------------------------------

View File

@@ -0,0 +1,98 @@
---------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
-- ---------------------------------------------------------------------------
-- Unit : latency_measurement.vhd
-- Author : Jonas Purtschert
-- ---------------------------------------------------------------------------
-- Copyright© PSI, Section DSV
-- ---------------------------------------------------------------------------
-- Comment : Latency Measurement for IFC1210 Interrupt latency debugging
-- ---------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.evr320_pkg.all;
entity latency_measurement is
generic (
CLK_FREQ_HZ : natural := 125000000 -- Xuser Clk Frequency in Hz
);
port (
evr_clk_i : in std_logic;
xuser_clk_i : in std_logic;
decoder_event_valid_i : in std_logic;
decoder_event_i : in std_logic_vector(7 downto 0);
status_o : out typ_rec_latency_measure_stat;
ctrl_i : in typ_rec_latency_measure_ctrl
);
end latency_measurement;
architecture rtl of latency_measurement is
-- --------------------------------------------------------------------------
-- Signal, Types, Constants
-- --------------------------------------------------------------------------
type state_type is (armed, count);
signal state : state_type;
signal counter : unsigned(31 downto 0);
signal event_nr_sync, event_nr : std_logic_vector(7 downto 0);
signal event_detected : std_logic_vector(3 downto 0);
signal event_detected_sync : std_logic_vector(1 downto 0);
constant MAX_COUNT : unsigned(31 downto 0) := to_unsigned(CLK_FREQ_HZ / 100, 32); -- MAX 10ms
begin
-- Process: filter events for matching event_nr register:
---------------------------------------------------------
ext_event_proc : process(evr_clk_i)
begin
if (rising_edge(evr_clk_i)) then
-- sync to MGT clock domain:
event_nr_sync <= ctrl_i.event_nr;
event_nr <= event_nr_sync;
-- check if event has been detected and stretch pulse:
event_detected <= event_detected(2 downto 0) & '0';
if (decoder_event_valid_i = '1' and decoder_event_i = event_nr) then
event_detected <= (others => '1');
end if;
end if;
end process;
-- Process: Counter when configured event has been detected:
------------------------------------------------------------
lat_meas_proc : process(xuser_clk_i, counter)
begin
if rising_edge(xuser_clk_i) then
-- sync to user clock domain:
event_detected_sync <= event_detected_sync(0) & event_detected(3);
-- counter FSM:
---------------
case state is
-- counter is armed:
when armed =>
counter <= (others => '0');
-- start counting when event detected (rising edge):
if (event_detected_sync(1) = '0' and event_detected_sync(0) = '1') then
state <= count;
end if;
-- counting:
when count =>
-- count only up to 10ms, and stop:
if (counter < MAX_COUNT) then
counter <= counter + 1;
end if;
if (ctrl_i.counter_arm = '1') then
state <= armed;
end if;
end case;
end if;
status_o.counter_val <= std_logic_vector(counter);
status_o.event_detected <= event_detected_sync(event_detected_sync'left);
end process;
end rtl;

View File

@@ -0,0 +1,494 @@
------------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
------------------------------------------------------------------------------
-- Unit : v6vlx_gtxe1_101MHz27_1Gbps0127.vhd
-- Author : Goran Marinkovic, Section Diagnostic
-- : Waldemar Koprek, Section Diagnostic
-- : Patric Bucher, Section DSV
-- Version : $Revision: 1.1 $
------------------------------------------------------------------------------
-- Copyright© PSI, Section Diagnostic
------------------------------------------------------------------------------
-- Comment : Virtex-6 GTXE1 primitive configured for HIPA 50.63282 MHz
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;
use work.v6vlx_gtxe1_pkg.all;
entity v6vlx_gtxe1_101MHz27_1Gbps0127 is
generic(
g_MGT_LOCATION : string
);
port (
i_mgt : in gtxe_in_type;
o_mgt : out gtxe_out_type
);
end v6vlx_gtxe1_101MHz27_1Gbps0127;
architecture RTL of v6vlx_gtxe1_101MHz27_1Gbps0127 is
--**************************** Signal Declarations ****************************
-- ground and tied_to_vcc_i signals
signal tied_to_ground_i : std_logic;
signal tied_to_ground_vec_i : std_logic_vector(63 downto 0);
signal tied_to_vcc_i : std_logic;
--***************************** Main Body of Code *****************************
signal slv_mgtrefclk : std_logic_vector(1 downto 0);
signal debug_refclk : std_logic_vector(1 downto 0);
--************************** Attribute Declarations ***************************
attribute LOC : string;
attribute LOC of gtxe1_i : label is g_MGT_LOCATION;
begin
--------------------------- Static signal Assignments ---------------------
tied_to_ground_i <= '0';
tied_to_ground_vec_i(63 downto 0) <= (others => '0');
tied_to_vcc_i <= '1';
slv_mgtrefclk <= "0" & i_mgt.ctrl.CLKIN;
o_mgt.ctrl.REFCLKOUT <= debug_refclk(1);
--------------------------------- GTX Instance -----------------------------
gtxe1_i :GTXE1
generic map (
--_______________________ Simulation-Only Attributes ___________________
SIM_RECEIVER_DETECT_PASS => (TRUE),
SIM_GTXRESET_SPEEDUP => (1), --(GTX_SIM_GTXRESET_SPEEDUP),
SIM_TX_ELEC_IDLE_LEVEL => ("X"),
SIM_VERSION => ("2.0"),
SIM_TXREFCLK_SOURCE => ("000"),
SIM_RXREFCLK_SOURCE => ("000"),
----------------------------TX PLL----------------------------
TX_CLK_SOURCE => "RXPLL", --
TX_OVERSAMPLE_MODE => FALSE, --
TXPLL_COM_CFG => X"21680A", --
TXPLL_CP_CFG => X"0D", --
TXPLL_DIVSEL_FB => 4, -- 1.2GHz < Fpll < 2.7GHz
TXPLL_DIVSEL_OUT => 4, --
TXPLL_DIVSEL_REF => 1, -- RXPLL_DIVSEL_FB * RXPLL_DIVSEL45_FB
TXPLL_DIVSEL45_FB => 5, -- Fpll = Fclkin -----------------------------------
TXPLL_LKDET_CFG => "111", -- RXPLL_DIVSEL_REF
TX_CLK25_DIVIDER => 4, --
TXPLL_SATA => "00", -- Fpll * 2
TX_TDCC_CFG => "00", -- Flinerate = ------------------
PMA_CAS_CLK_EN => FALSE, -- RXPLL_DIVSEL_OUT(FALSE)
POWER_SAVE => "0000110100", -- [4] '1' = bypass trasmit delay aligner, [5] '1' = bypass receive delay aligner
-------------------------TX Interface-------------------------
GEN_TXUSRCLK => (TRUE), --
TX_DATA_WIDTH => (20), --
TX_USRCLK_CFG => (X"00"), --
TXOUTCLK_CTRL => ("TXOUTCLKPMA_DIV2"), --
TXOUTCLK_DLY => ("0000000000"), --
--------------TX Buffering and Phase Alignment----------------
TX_PMADATA_OPT => ('0'), --
PMA_TX_CFG => (x"80082"), --
TX_BUFFER_USE => (TRUE), --
TX_BYTECLK_CFG => (x"00"), --
TX_EN_RATE_RESET_BUF => (TRUE), --
TX_XCLK_SEL => ("TXOUT"), --
TX_DLYALIGN_CTRINC => ("0100"), --
TX_DLYALIGN_LPFINC => ("0110"), --
TX_DLYALIGN_MONSEL => ("000"), --
TX_DLYALIGN_OVRDSETTING => ("10000000"), --
-------------------------TX Gearbox--------------------------- --
GEARBOX_ENDEC => ("000"), --
TXGEARBOX_USE => (FALSE), --
--
----------------TX Driver and OOB Signalling------------------ --
TX_DRIVE_MODE => ("DIRECT"), --
TX_IDLE_ASSERT_DELAY => ("100"), --
TX_IDLE_DEASSERT_DELAY => ("010"), --
TXDRIVE_LOOPBACK_HIZ => (FALSE), --
TXDRIVE_LOOPBACK_PD => (FALSE), --
--
--------------TX Pipe Control for PCI Express/SATA------------ --
COM_BURST_VAL => ("1111"), --
--
------------------TX Attributes for PCI Express--------------- --
TX_DEEMPH_0 => ("11010"), --
TX_DEEMPH_1 => ("10000"), --
TX_MARGIN_FULL_0 => ("1001110"), --
TX_MARGIN_FULL_1 => ("1001001"), --
TX_MARGIN_FULL_2 => ("1000101"), --
TX_MARGIN_FULL_3 => ("1000010"), --
TX_MARGIN_FULL_4 => ("1000000"), --
TX_MARGIN_LOW_0 => ("1000110"), --
TX_MARGIN_LOW_1 => ("1000100"), --
TX_MARGIN_LOW_2 => ("1000010"), --
TX_MARGIN_LOW_3 => ("1000000"), --
TX_MARGIN_LOW_4 => ("1000000"), --
----------------------------RX PLL----------------------------
RX_OVERSAMPLE_MODE => FALSE, -- 1.2GHz < Fpll < 2.7GHz
RXPLL_COM_CFG => (x"21680a"), --
RXPLL_CP_CFG => (x"0D"), -- RXPLL_DIVSEL_FB * RXPLL_DIVSEL45_FB
RXPLL_DIVSEL_FB => 4, -- Fpll = Fclkin -----------------------------------
RXPLL_DIVSEL_OUT => 4, -- RXPLL_DIVSEL_REF
RXPLL_DIVSEL_REF => 1, --
RXPLL_DIVSEL45_FB => 5, -- Fpll * 2
RXPLL_LKDET_CFG => ("111"), -- Flinerate = ------------------
RX_CLK25_DIVIDER => 4, -- RXPLL_DIVSEL_OUT
-------------------------RX Interface-------------------------
GEN_RXUSRCLK => (TRUE), --
RX_DATA_WIDTH => (20), --
RXRECCLK_CTRL => ("RXRECCLKPMA_DIV2"), --
RXRECCLK_DLY => ("0000000000"), --
RXUSRCLK_DLY => (x"0000"), --
----------RX Driver,OOB signalling,Coupling and Eq.,CDR-------
AC_CAP_DIS => (FALSE), --
CDR_PH_ADJ_TIME => ("10100"), --
OOBDETECT_THRESHOLD => ("011"), --
PMA_CDR_SCAN => (x"640404C"), --
PMA_RX_CFG => (x"05ce008"), --
RCV_TERM_GND => (FALSE), --
RCV_TERM_VTTRX => (TRUE), --
RX_EN_IDLE_HOLD_CDR => (FALSE), --
RX_EN_IDLE_RESET_FR => (FALSE), --
RX_EN_IDLE_RESET_PH => (FALSE), --
TX_DETECT_RX_CFG => (x"1832"), --
TERMINATION_CTRL => ("00000"), --
TERMINATION_OVRD => (FALSE), --
CM_TRIM => ("01"), --
PMA_RXSYNC_CFG => (x"00"), --
PMA_CFG => (x"0040000040000000003"), --
BGTEST_CFG => ("00"), --
BIAS_CFG => (x"00000"), --
--------------RX Decision Feedback Equalizer(DFE)-------------
DFE_CAL_TIME => ("01100"), --
DFE_CFG => ("00011011"), --
RX_EN_IDLE_HOLD_DFE => (TRUE), --
RX_EYE_OFFSET => (x"4C"), --
RX_EYE_SCANMODE => ("00"), --
-------------------------PRBS Detection-----------------------
RXPRBSERR_LOOPBACK => ('0'), --
------------------Comma Detection and Alignment---------------
ALIGN_COMMA_WORD => (2), --(1),
COMMA_10B_ENABLE => ("1111111111"), --
COMMA_DOUBLE => (FALSE), --
DEC_MCOMMA_DETECT => (TRUE), --(FALSE),
DEC_PCOMMA_DETECT => (TRUE), --(FALSE),
DEC_VALID_COMMA_ONLY => (FALSE), --
MCOMMA_10B_VALUE => ("1010000011"), --
MCOMMA_DETECT => (TRUE), --
PCOMMA_10B_VALUE => ("0101111100"), --
PCOMMA_DETECT => (TRUE), --
RX_DECODE_SEQ_MATCH => (FALSE), --
RX_SLIDE_AUTO_WAIT => (5), --
RX_SLIDE_MODE => ("PMA"), --
SHOW_REALIGN_COMMA => (FALSE), --
-----------------RX Loss-of-sync State Machine----------------
RX_LOS_INVALID_INCR => (8), --
RX_LOS_THRESHOLD => (128), --
RX_LOSS_OF_SYNC_FSM => (TRUE), --(FALSE),
-------------------------RX Gearbox---------------------------
RXGEARBOX_USE => (FALSE), --
-------------RX Elastic Buffer and Phase alignment------------
RX_BUFFER_USE => (FALSE), --
RX_EN_IDLE_RESET_BUF => (FALSE), --
RX_EN_MODE_RESET_BUF => (TRUE), --
RX_EN_RATE_RESET_BUF => (TRUE), --
RX_EN_REALIGN_RESET_BUF => (FALSE), --
RX_EN_REALIGN_RESET_BUF2 => (FALSE), --
RX_FIFO_ADDR_MODE => ("FAST"), --
RX_IDLE_HI_CNT => ("1000"), --
RX_IDLE_LO_CNT => ("0000"), --
RX_XCLK_SEL => ("RXUSR"), --
RX_DLYALIGN_CTRINC => ("1110"), --
RX_DLYALIGN_EDGESET => ("00010"), --
RX_DLYALIGN_LPFINC => ("1110"), --
RX_DLYALIGN_MONSEL => ("000"), --
RX_DLYALIGN_OVRDSETTING => ("10000000"), --
------------------------Clock Correction---------------------- --
CLK_COR_ADJ_LEN => (1), --
CLK_COR_DET_LEN => (1), --
CLK_COR_INSERT_IDLE_FLAG => (FALSE), --
CLK_COR_KEEP_IDLE => (FALSE), --
CLK_COR_MAX_LAT => (16), --
CLK_COR_MIN_LAT => (14), --
CLK_COR_PRECEDENCE => (TRUE), --
CLK_COR_REPEAT_WAIT => (0), --
CLK_COR_SEQ_1_1 => ("0000000000"), --
CLK_COR_SEQ_1_2 => ("0000000000"), --
CLK_COR_SEQ_1_3 => ("0000000000"), --
CLK_COR_SEQ_1_4 => ("0000000000"), --
CLK_COR_SEQ_1_ENABLE => ("1111"), --
CLK_COR_SEQ_2_1 => ("0000000000"), --
CLK_COR_SEQ_2_2 => ("0000000000"), --
CLK_COR_SEQ_2_3 => ("0000000000"), --
CLK_COR_SEQ_2_4 => ("0000000000"), --
CLK_COR_SEQ_2_ENABLE => ("1111"), --
CLK_COR_SEQ_2_USE => (FALSE), --
CLK_CORRECT_USE => (FALSE), --
--
------------------------Channel Bonding---------------------- --
CHAN_BOND_1_MAX_SKEW => (1), --
CHAN_BOND_2_MAX_SKEW => (1), --
CHAN_BOND_KEEP_ALIGN => (FALSE), --
CHAN_BOND_SEQ_1_1 => ("0000000000"), --
CHAN_BOND_SEQ_1_2 => ("0000000000"), --
CHAN_BOND_SEQ_1_3 => ("0000000000"), --
CHAN_BOND_SEQ_1_4 => ("0000000000"), --
CHAN_BOND_SEQ_1_ENABLE => ("1111"), --
CHAN_BOND_SEQ_2_1 => ("0000000000"), --
CHAN_BOND_SEQ_2_2 => ("0000000000"), --
CHAN_BOND_SEQ_2_3 => ("0000000000"), --
CHAN_BOND_SEQ_2_4 => ("0000000000"), --
CHAN_BOND_SEQ_2_CFG => ("00000"), --
CHAN_BOND_SEQ_2_ENABLE => ("1111"), --
CHAN_BOND_SEQ_2_USE => (FALSE), --
CHAN_BOND_SEQ_LEN => (1), --
PCI_EXPRESS_MODE => (FALSE), --
--
-------------RX Attributes for PCI Express/SATA/SAS---------- --
SAS_MAX_COMSAS => (52), --
SAS_MIN_COMSAS => (40), --
SATA_BURST_VAL => ("100"), --
SATA_IDLE_VAL => ("100"),
SATA_MAX_BURST => (9),
SATA_MAX_INIT => (27),
SATA_MAX_WAKE => (9),
SATA_MIN_BURST => (5),
SATA_MIN_INIT => (15),
SATA_MIN_WAKE => (5),
TRANS_TIME_FROM_P2 => (x"03c"),
TRANS_TIME_NON_P2 => (x"19"), --
TRANS_TIME_RATE => (x"ff"), --
TRANS_TIME_TO_P2 => (x"064") --
)
port map (
------------------------ Loopback and Powerdown Ports ----------------------
LOOPBACK => i_mgt.CTRL.LOOPBACK, --tied_to_ground_vec_i(2 downto 0),
RXPOWERDOWN => "00", --
TXPOWERDOWN => "00", --
-------------- Receive Ports - 64b66b and 64b67b Gearbox Ports -------------
RXDATAVALID => open, --
RXGEARBOXSLIP => tied_to_ground_i, --
RXHEADER => open, --
RXHEADERVALID => open, --
RXSTARTOFSEQ => open, --
----------------------- Receive Ports - 8b10b Decoder ----------------------
RXCHARISCOMMA => o_mgt.rx.RXCHARISCOMMA, --
RXCHARISK => o_mgt.rx.RXCHARISK, --
RXDEC8B10BUSE => '1', --tied_to_ground_i,
RXDISPERR => o_mgt.rx.RXDISPERR, --rxdisperr_i,
RXNOTINTABLE => o_mgt.rx.RXNOTINTABLE, --
RXRUNDISP => o_mgt.rx.RXRUNDISP, --
USRCODEERR => tied_to_ground_i, --
------------------- Receive Ports - Channel Bonding Ports ------------------
RXCHANBONDSEQ => open, --
RXCHBONDI => tied_to_ground_vec_i(3 downto 0), --
RXCHBONDLEVEL => tied_to_ground_vec_i(2 downto 0), --
RXCHBONDMASTER => tied_to_ground_i, --
RXCHBONDO => open, --
RXCHBONDSLAVE => tied_to_ground_i, --
RXENCHANSYNC => tied_to_ground_i, --
------------------- Receive Ports - Clock Correction Ports -----------------
RXCLKCORCNT => open, --
--------------- Receive Ports - Comma Detection and Alignment --------------
RXBYTEISALIGNED => o_mgt.rx.RXBYTEISALIGNED, --RXBYTEISALIGNED_OUT,
RXBYTEREALIGN => o_mgt.rx.RXBYTEREALIGN, --RXBYTEREALIGN_OUT,
RXCOMMADET => o_mgt.rx.RXCOMMADET, --RXCOMMADET_OUT,
RXCOMMADETUSE => '1', --tied_to_vcc_i,
RXENMCOMMAALIGN => i_mgt.rx.RXENMCOMMAALIGN, --tied_to_ground_i,
RXENPCOMMAALIGN => i_mgt.rx.RXENPCOMMAALIGN, --tied_to_ground_i,
RXSLIDE => i_mgt.rx.RXSLIDE,
----------------------- Receive Ports - PRBS Detection ---------------------
PRBSCNTRESET => tied_to_ground_i, --
RXENPRBSTST => tied_to_ground_vec_i(2 downto 0), --
RXPRBSERR => open, --
------------------- Receive Ports - RX Data Path interface -----------------
RXDATA => o_mgt.rx.RXDATA, --rxdata_i,
RXRECCLK => o_mgt.rx.RXRECCLK, --RXRECCLK_OUT,
RXRECCLKPCS => open,
RXRESET => i_mgt.rx.RXRESET, --tied_to_ground_i,
RXUSRCLK => i_mgt.rx.RXUSRCLK, --tied_to_ground_i,
RXUSRCLK2 => i_mgt.rx.RXUSRCLK2, --RXUSRCLK2_IN,
------------ Receive Ports - RX Decision Feedback Equalizer(DFE) -----------
DFECLKDLYADJ => tied_to_ground_vec_i(5 downto 0), --
DFECLKDLYADJMON => open, --
DFEDLYOVRD => tied_to_ground_i, --
DFEEYEDACMON => open, --
DFESENSCAL => open, --
DFETAP1 => tied_to_ground_vec_i(4 downto 0), --
DFETAP1MONITOR => open, --
DFETAP2 => tied_to_ground_vec_i(4 downto 0), --
DFETAP2MONITOR => open, --
DFETAP3 => tied_to_ground_vec_i(3 downto 0), --
DFETAP3MONITOR => open, --
DFETAP4 => tied_to_ground_vec_i(3 downto 0), --
DFETAP4MONITOR => open, --
DFETAPOVRD => tied_to_vcc_i, --
------- Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR ------
GATERXELECIDLE => tied_to_vcc_i, --
IGNORESIGDET => tied_to_vcc_i, --
RXCDRRESET => i_mgt.rx.RXCDRRESET, --
RXELECIDLE => o_mgt.rx.RXELECIDLE, --open,
RXEQMIX(9 downto 3) => tied_to_ground_vec_i(6 downto 0), --
RXEQMIX(2 downto 0) => "000", --RXEQMIX_IN,
RXN => i_mgt.rx.RXP, --RXN_IN,
RXP => i_mgt.rx.RXN, --RXP_IN,
-------- Receive Ports - RX Elastic Buffer and Phase Alignment Ports -------
RXBUFRESET => tied_to_ground_i, --
RXBUFSTATUS => open, --
RXCHANISALIGNED => open, --
RXCHANREALIGN => open, --
RXDLYALIGNDISABLE => i_mgt.rx.RXDLYALIGNDISABLE, --
RXDLYALIGNMONENB => i_mgt.rx.RXDLYALIGNMONENB, --
RXDLYALIGNMONITOR => o_mgt.rx.RXDLYALIGNMONITOR, --
RXDLYALIGNOVERRIDE => i_mgt.rx.RXDLYALIGNOVERRIDE, --
RXDLYALIGNRESET => i_mgt.rx.RXDLYALIGNRESET, --
RXDLYALIGNSWPPRECURB => tied_to_vcc_i, --
RXDLYALIGNUPDSW => tied_to_ground_i, --
RXENPMAPHASEALIGN => i_mgt.rx.RXENPMAPHASEALIGN, --RXENPMAPHASEALIGN_IN,
RXPMASETPHASE => i_mgt.rx.RXPMASETPHASE, --RXPMASETPHASE_IN,
RXSTATUS => open,
--------------- Receive Ports - RX Loss-of-sync State Machine --------------
RXLOSSOFSYNC => o_mgt.rx.RXLOSSOFSYNC, --
---------------------- Receive Ports - RX Oversampling ---------------------
RXENSAMPLEALIGN => tied_to_ground_i, --
RXOVERSAMPLEERR => open, --
------------------------ Receive Ports - RX PLL Ports ----------------------
GREFCLKRX => '0', --
GTXRXRESET => i_mgt.ctrl.GTXRESET, --GTXRXRESET_IN,
MGTREFCLKRX => slv_mgtrefclk, --MGTREFCLKRX_IN,
NORTHREFCLKRX => "00", --
PERFCLKRX => '0', --
PLLRXRESET => i_mgt.ctrl.PLLRXRESET, --PLLRXRESET_IN,
RXPLLLKDET => o_mgt.ctrl.RXPLLLKDET , --RXPLLLKDET_OUT,
RXPLLLKDETEN => '1', --
RXPLLPOWERDOWN => '0', --
RXPLLREFSELDY => "000", -- GREFCLKRX
RXRATE => "00", --
RXRATEDONE => open, --
RXRESETDONE => o_mgt.ctrl.RXRESETDONE , --RXRESETDONE_OUT,
SOUTHREFCLKRX => "00", --
-------------- Receive Ports - RX Pipe Control for PCI Express ------------- --
PHYSTATUS => open, --
RXVALID => open, --
----------------- Receive Ports - RX Polarity Control Ports ---------------- --
RXPOLARITY => tied_to_ground_i, --
--------------------- Receive Ports - RX Ports for SATA -------------------- --
COMINITDET => open, --
COMSASDET => open, --
COMWAKEDET => open, --
----------------------------------------------------------------------------
------------- Shared Ports - Dynamic Reconfiguration Port (DRP) ------------ --
----------------------------------------------------------------------------
DADDR => tied_to_ground_vec_i(7 downto 0), --
DCLK => tied_to_ground_i, --
DEN => tied_to_ground_i, --
DI => tied_to_ground_vec_i(15 downto 0), --
DRDY => open, --
DRPDO => open, --
DWE => tied_to_ground_i, --
----------------------------------------------------------------------------
-------------- Transmit Ports - 64b66b and 64b67b Gearbox Ports ------------
----------------------------------------------------------------------------
TXGEARBOXREADY => open, --
TXHEADER => tied_to_ground_vec_i(2 downto 0), --
TXSEQUENCE => tied_to_ground_vec_i(6 downto 0), --
TXSTARTSEQ => tied_to_ground_i, --
---------------- Transmit Ports - 8b10b Encoder Control Ports --------------
TXBYPASS8B10B => i_mgt.tx.TXBYPASS8B10B, --tied_to_ground_vec_i(3 downto 0),
TXCHARDISPMODE => i_mgt.tx.TXCHARDISPMODE, --txchardispmode_i,
TXCHARDISPVAL => i_mgt.tx.TXCHARDISPVAL , --txchardispval_i,
TXCHARISK => i_mgt.tx.TXCHARISK , --tied_to_ground_vec_i(3 downto 0),
TXENC8B10BUSE => '1', --tied_to_ground_i,
TXKERR => o_mgt.tx.TXKERR , --open,
TXRUNDISP => o_mgt.tx.TXRUNDISP, --open,
------------------------- Transmit Ports - GTX Ports -----------------------
GTXTEST => "1000000000000", --
MGTREFCLKFAB => debug_refclk, --
TSTCLK0 => tied_to_ground_i, --
TSTCLK1 => tied_to_ground_i, --
TSTIN => "11111111111111111111", --
TSTOUT => open, --
------------------ Transmit Ports - TX Data Path interface -----------------
TXDATA => i_mgt.tx.TXDATA, --txdata_i,
TXOUTCLK => o_mgt.tx.TXOUTCLK, --TXOUTCLK_OUT,
TXOUTCLKPCS => open, --
TXRESET => i_mgt.tx.TXRESET, --tied_to_ground_i,
TXUSRCLK => i_mgt.tx.TXUSRCLK, --tied_to_ground_i,
TXUSRCLK2 => i_mgt.tx.TXUSRCLK2, --TXUSRCLK2_IN,
---------------- Transmit Ports - TX Driver and OOB signaling --------------
TXBUFDIFFCTRL => "100", --
TXDIFFCTRL => i_mgt.tx.TXDIFFCTRL, --TXDIFFCTRL_IN,
TXINHIBIT => tied_to_ground_i, --
TXN => o_mgt.tx.TXP, --TXN_OUT,
TXP => o_mgt.tx.TXN, --TXP_OUT,
TXPOSTEMPHASIS => i_mgt.tx.TXPOSTEMPHASIS, --TXPOSTEMPHASIS_IN,
--------------- Transmit Ports - TX Driver and OOB signalling --------------
TXPREEMPHASIS => i_mgt.tx.TXPREEMPHASIS, --TXPREEMPHASIS_IN,
----------- Transmit Ports - TX Elastic Buffer and Phase Alignment ---------
TXBUFSTATUS => open,
-------- Transmit Ports - TX Elastic Buffer and Phase Alignment Ports ------
TXDLYALIGNDISABLE => tied_to_vcc_i, --
TXDLYALIGNMONENB => tied_to_ground_i, --
TXDLYALIGNMONITOR => open, --
TXDLYALIGNOVERRIDE => tied_to_ground_i, --
TXDLYALIGNRESET => tied_to_ground_i, --
TXDLYALIGNUPDSW => tied_to_vcc_i, --
TXENPMAPHASEALIGN => tied_to_ground_i, --
TXPMASETPHASE => tied_to_ground_i, --
----------------------- Transmit Ports - TX PLL Ports ----------------------
GREFCLKTX => '0', --
GTXTXRESET => i_mgt.ctrl.GTXRESET, --GTXTXRESET_IN,
MGTREFCLKTX => slv_mgtrefclk, --MGTREFCLKTX_IN,
NORTHREFCLKTX => "00", --
PERFCLKTX => '0', --
PLLTXRESET => i_mgt.ctrl.PLLTXRESET, --PLLTXRESET_IN,
SOUTHREFCLKTX => "00", --
TXPLLLKDET => o_mgt.ctrl.TXPLLLKDET, --TXPLLLKDET_OUT,
TXPLLLKDETEN => '1', --
TXPLLPOWERDOWN => '0', --
TXPLLREFSELDY => "000", --
TXRATE => "00", --
TXRATEDONE => open, --
TXRESETDONE => o_mgt.ctrl.TXRESETDONE, --TXRESETDONE_OUT,
--------------------- Transmit Ports - TX PRBS Generator ------------------- --
TXENPRBSTST => tied_to_ground_vec_i(2 downto 0), --
TXPRBSFORCEERR => tied_to_ground_i, --
-------------------- Transmit Ports - TX Polarity Control ------------------ --
TXPOLARITY => tied_to_ground_i, --
----------------- Transmit Ports - TX Ports for PCI Express ---------------- --
TXDEEMPH => tied_to_ground_i, --
TXDETECTRX => tied_to_ground_i, --
TXELECIDLE => tied_to_ground_i, --
TXMARGIN => tied_to_ground_vec_i(2 downto 0), --
TXPDOWNASYNCH => tied_to_ground_i, --
TXSWING => tied_to_ground_i, --
--------------------- Transmit Ports - TX Ports for SATA ------------------- --
COMFINISH => open, --
TXCOMINIT => tied_to_ground_i, --
TXCOMSAS => tied_to_ground_i, --
TXCOMWAKE => tied_to_ground_i --
);
end RTL;

View File

@@ -1,218 +1,26 @@
------------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
------------------------------------------------------------------------------
-- Unit : pkg_v6vlx_gtxe1.vhd
-- Unit : v6vlx_gtxe1_142MHz8_2Gbps856.vhd
-- Author : Goran Marinkovic, Section Diagnostic
-- : Waldemar Koprek, Section Diagnostic
-- : Patric Bucher, Section DSV
-- Version : $Revision: 1.1 $
------------------------------------------------------------------------------
-- Copyright© PSI, Section Diagnostic
------------------------------------------------------------------------------
-- Comment :
-- Comment : Virtex-6 GTXE1 primitive configured for SwissFEL 142.8 MHz
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
--***************************** Entity Declaration ****************************
package pkg_v6vlx_gtxe1 is
library unisim;
use unisim.vcomponents.all;
---------------------------------------------------------------------------
-- Types
---------------------------------------------------------------------------
type gtxe_ctrl_in_type is record
GTXRESET : std_ulogic;
LOOPBACK : std_logic_vector( 2 downto 0);
CLKIN : std_ulogic;
PLLRXRESET : std_ulogic;
PLLTXRESET : std_ulogic;
end record gtxe_ctrl_in_type;
use work.v6vlx_gtxe1_pkg.all;
type gtxe_ctrl_out_type is record
RXPLLLKDET : std_ulogic;
RXRESETDONE : std_ulogic;
TXPLLLKDET : std_ulogic;
TXRESETDONE : std_ulogic;
REFCLKOUT : std_ulogic;
end record gtxe_ctrl_out_type;
-- type mgt_drp_in_type is record
-- -- Dynamic Reconfiguration Port (DRP)
-- DCLK : std_ulogic;
-- DEN : std_ulogic;
-- DWE : std_ulogic;
-- DADDR : std_logic_vector( 6 downto 0);
-- DI : std_logic_vector(15 downto 0);
-- end record mgt_drp_in_type;
--
-- type mgt_drp_out_type is record
-- -- Dynamic Reconfiguration Port (DRP)
-- DO : std_logic_vector(15 downto 0);
-- DRDY : std_ulogic;
-- end record mgt_drp_out_type;
type gtxe_rx_in_type is record
-- Comma Detection and Alignment ------------------------
RXENMCOMMAALIGN : std_ulogic;
RXENPCOMMAALIGN : std_ulogic;
-- RX resets
RXRESET : std_ulogic;
RXCDRRESET : std_ulogic;
-- RX user clocks
RXUSRCLK : std_ulogic;
RXUSRCLK2 : std_ulogic;
-- RX serial ports
RXP : std_ulogic;
RXN : std_ulogic;
-- RX Elastic Buffer and Phase Alignment Ports
RXDLYALIGNDISABLE : std_logic;
RXDLYALIGNMONENB : std_logic;
RXDLYALIGNOVERRIDE : std_logic;
RXDLYALIGNRESET : std_logic;
RXENPMAPHASEALIGN : std_logic;
RXPMASETPHASE : std_logic;
RXSLIDE : std_logic;
end record gtxe_rx_in_type;
type gtxe_rx_out_type is record
-- RX 8b10b Decoder
RXCHARISCOMMA : std_logic_vector( 3 downto 0);
RXCHARISK : std_logic_vector( 3 downto 0);
RXDISPERR : std_logic_vector( 3 downto 0);
RXNOTINTABLE : std_logic_vector( 3 downto 0);
RXRUNDISP : std_logic_vector( 3 downto 0);
-- Comma Detection and Alignment
RXBYTEISALIGNED : std_ulogic;
RXBYTEREALIGN : std_ulogic;
RXCOMMADET : std_ulogic;
-- RX data ports
RXDATA : std_logic_vector(31 downto 0);
-- RX user clocks
RXRECCLK : std_ulogic;
-- RX Out Of Band (OOB)
RXELECIDLE : std_ulogic;
-- RX Elastic Buffer and Phase Alignment Ports
RXDLYALIGNMONITOR : std_logic_vector(7 downto 0);
-- RX loss of sync fsm
RXLOSSOFSYNC : std_logic_vector( 1 downto 0);
end record gtxe_rx_out_type;
type gtxe_tx_in_type is record
-- 8b10b Encoder Control Ports
TXBYPASS8B10B : std_logic_vector( 3 downto 0);
TXCHARDISPMODE : std_logic_vector( 3 downto 0);
TXCHARDISPVAL : std_logic_vector( 3 downto 0);
TXCHARISK : std_logic_vector( 3 downto 0);
-- TX data ports
TXDATA : std_logic_vector(31 downto 0);
-- TX resets
TXRESET : std_ulogic;
-- TX user clocks
TXUSRCLK : std_ulogic;
TXUSRCLK2 : std_ulogic;
-- TX driver
TXDIFFCTRL : std_logic_vector( 3 downto 0);
TXPOSTEMPHASIS : std_logic_vector( 4 downto 0);
TXPREEMPHASIS : std_logic_vector( 3 downto 0);
end record gtxe_tx_in_type;
type gtxe_tx_out_type is record
-- TX serial ports
TXP : std_ulogic;
TXN : std_ulogic;
-- TX 8b10b encoder
TXKERR : std_logic_vector( 3 downto 0);
TXRUNDISP : std_logic_vector( 3 downto 0);
-- TX user clocks
TXOUTCLK : std_ulogic;
end record gtxe_tx_out_type;
type gtxe_in_type is record
ctrl : gtxe_ctrl_in_type;
--drp : mgt_drp_in_type;
rx : gtxe_rx_in_type;
tx : gtxe_tx_in_type;
end record gtxe_in_type;
type gtxe_out_type is record
ctrl : gtxe_ctrl_out_type;
--drp : mgt_drp_out_type;
rx : gtxe_rx_out_type;
tx : gtxe_tx_out_type;
end record gtxe_out_type;
---------------------------------------------------------------------------
-- Module virtex6 GTXE
---------------------------------------------------------------------------
component v6vlx_gtxe1
generic(
g_MGT_LOCATION : string
);
port
(
i_mgt : in gtxe_in_type;
o_mgt : out gtxe_out_type
);
end component;
component virtex6_gtxe_sync is
port
(
RXENPMAPHASEALIGN : out std_logic;
RXPMASETPHASE : out std_logic;
RXDLYALIGNDISABLE : out std_logic;
RXDLYALIGNOVERRIDE : out std_logic;
RXDLYALIGNRESET : out std_logic;
SYNC_DONE : out std_logic;
USER_CLK : in std_logic;
RESET : in std_logic
);
end component;
component v6vlx_gtxe1_wrapper is
generic(
g_MGT_LOCATION : string;
g_USE_MMCM : boolean := false
);
port
(
-- MGT serial interface
i_mgt_refclk : in std_logic;
o_mgt_refclk : out std_logic;
i_mgt_rx_p : in std_logic;
i_mgt_rx_n : in std_logic;
o_mgt_tx_p : out std_logic;
o_mgt_tx_n : out std_logic;
-- MGT parallel interface
o_mgt_status : out std_logic_vector(31 downto 0); -- see lines 134-139 for details
i_mgt_control : in std_logic_vector(31 downto 0); -- see lines 127-131 for details
o_mgt_recclk : out std_logic;
o_mgt_rx_data : out std_logic_vector(15 downto 0);
o_mgt_rx_charisk : out std_logic_vector( 1 downto 0)
);
end component;
end package pkg_v6vlx_gtxe1;
-------------------------------------------------------------------------------
-- virtex6_gtxe --------------------------------------------------------------
-------------------------------------------------------------------------------
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
library ieee;
use ieee.std_logic_1164.all;
use work.pkg_v6vlx_gtxe1.all;
entity v6vlx_gtxe1 is
entity v6vlx_gtxe1_142MHz8_2Gbps856 is
generic(
g_MGT_LOCATION : string
);
@@ -220,9 +28,10 @@ entity v6vlx_gtxe1 is
i_mgt : in gtxe_in_type;
o_mgt : out gtxe_out_type
);
end v6vlx_gtxe1;
end v6vlx_gtxe1_142MHz8_2Gbps856;
architecture RTL of v6vlx_gtxe1 is
architecture RTL of v6vlx_gtxe1_142MHz8_2Gbps856 is
--**************************** Signal Declarations ****************************
@@ -258,8 +67,8 @@ begin
gtxe1_i :GTXE1
generic map (
--_______________________ Simulation-Only Attributes ___________________
SIM_RECEIVER_DETECT_PASS => TRUE,
SIM_GTXRESET_SPEEDUP => 1, --(GTX_SIM_GTXRESET_SPEEDUP),
SIM_RECEIVER_DETECT_PASS => (TRUE),
SIM_GTXRESET_SPEEDUP => (1), --(GTX_SIM_GTXRESET_SPEEDUP),
SIM_TX_ELEC_IDLE_LEVEL => ("X"),
SIM_VERSION => ("2.0"),
SIM_TXREFCLK_SOURCE => ("000"),
@@ -281,39 +90,39 @@ begin
POWER_SAVE => "0000110100", -- [4] '1' = bypass trasmit delay aligner, [5] '1' = bypass receive delay aligner
-------------------------TX Interface-------------------------
GEN_TXUSRCLK => TRUE, --(TRUE),
TX_DATA_WIDTH => 20, --(20),
TX_USRCLK_CFG => X"00", --(x"00"),
TXOUTCLK_CTRL => "TXOUTCLKPMA_DIV2", --("TXOUTCLKPMA_DIV2"),
TXOUTCLK_DLY => "0000000000", --("0000000000"),
GEN_TXUSRCLK => (TRUE), --
TX_DATA_WIDTH => (20), --
TX_USRCLK_CFG => (X"00"), --
TXOUTCLK_CTRL => ("TXOUTCLKPMA_DIV2"), --
TXOUTCLK_DLY => ("0000000000"), --
--------------TX Buffering and Phase Alignment----------------
TX_PMADATA_OPT => '0', --('0'),
PMA_TX_CFG => x"80082", --(x"80082"),
TX_BUFFER_USE => TRUE, --(TRUE),
TX_BYTECLK_CFG => x"00", --(x"00"),
TX_EN_RATE_RESET_BUF => TRUE, --(TRUE),
TX_XCLK_SEL => "TXOUT", --("TXOUT"),
TX_DLYALIGN_CTRINC => "0100", --("0100"),
TX_DLYALIGN_LPFINC => "0110", --("0110"),
TX_DLYALIGN_MONSEL => "000", --("000"),
TX_DLYALIGN_OVRDSETTING => "10000000", --("10000000"),
TX_PMADATA_OPT => ('0'), --
PMA_TX_CFG => (x"80082"), --
TX_BUFFER_USE => (TRUE), --
TX_BYTECLK_CFG => (x"00"), --
TX_EN_RATE_RESET_BUF => (TRUE), --
TX_XCLK_SEL => ("TXOUT"), --
TX_DLYALIGN_CTRINC => ("0100"), --
TX_DLYALIGN_LPFINC => ("0110"), --
TX_DLYALIGN_MONSEL => ("000"), --
TX_DLYALIGN_OVRDSETTING => ("10000000"), --
-------------------------TX Gearbox--------------------------- --
-------------------------TX Gearbox--------------------------- --
GEARBOX_ENDEC => ("000"), --
TXGEARBOX_USE => (FALSE), --
--
----------------TX Driver and OOB Signalling------------------ --
----------------TX Driver and OOB Signalling------------------ --
TX_DRIVE_MODE => ("DIRECT"), --
TX_IDLE_ASSERT_DELAY => ("100"), --
TX_IDLE_DEASSERT_DELAY => ("010"), --
TXDRIVE_LOOPBACK_HIZ => (FALSE), --
TXDRIVE_LOOPBACK_PD => (FALSE), --
--
--------------TX Pipe Control for PCI Express/SATA------------ --
--------------TX Pipe Control for PCI Express/SATA------------ --
COM_BURST_VAL => ("1111"), --
--
------------------TX Attributes for PCI Express--------------- --
------------------TX Attributes for PCI Express--------------- --
TX_DEEMPH_0 => ("11010"), --
TX_DEEMPH_1 => ("10000"), --
TX_MARGIN_FULL_0 => ("1001110"), --
@@ -346,7 +155,7 @@ begin
RXUSRCLK_DLY => (x"0000"), --
----------RX Driver,OOB signalling,Coupling and Eq.,CDR-------
AC_CAP_DIS => FALSE, --(FALSE),
AC_CAP_DIS => (FALSE), --
CDR_PH_ADJ_TIME => ("10100"), --
OOBDETECT_THRESHOLD => ("011"), --
PMA_CDR_SCAN => (x"640404C"), --
@@ -354,10 +163,10 @@ begin
RCV_TERM_GND => (FALSE), --
RCV_TERM_VTTRX => (TRUE), --
RX_EN_IDLE_HOLD_CDR => (FALSE), --
RX_EN_IDLE_RESET_FR => FALSE, --(FALSE),
RX_EN_IDLE_RESET_PH => FALSE, --(FALSE),
RX_EN_IDLE_RESET_FR => (FALSE), --
RX_EN_IDLE_RESET_PH => (FALSE), --
TX_DETECT_RX_CFG => (x"1832"), --
TERMINATION_CTRL => "00000", --("00000"),
TERMINATION_CTRL => ("00000"), --
TERMINATION_OVRD => (FALSE), --
CM_TRIM => ("01"), --
PMA_RXSYNC_CFG => (x"00"), --
@@ -376,11 +185,11 @@ begin
RXPRBSERR_LOOPBACK => ('0'), --
------------------Comma Detection and Alignment---------------
ALIGN_COMMA_WORD => 2, --(1),
ALIGN_COMMA_WORD => (2), --(1),
COMMA_10B_ENABLE => ("1111111111"), --
COMMA_DOUBLE => (FALSE), --
DEC_MCOMMA_DETECT => TRUE, --(FALSE),
DEC_PCOMMA_DETECT => TRUE, --(FALSE),
DEC_MCOMMA_DETECT => (TRUE), --(FALSE),
DEC_PCOMMA_DETECT => (TRUE), --(FALSE),
DEC_VALID_COMMA_ONLY => (FALSE), --
MCOMMA_10B_VALUE => ("1010000011"), --
MCOMMA_DETECT => (TRUE), --
@@ -389,12 +198,12 @@ begin
RX_DECODE_SEQ_MATCH => (FALSE), --
RX_SLIDE_AUTO_WAIT => (5), --
RX_SLIDE_MODE => ("PMA"), --
SHOW_REALIGN_COMMA => (FALSE), --
SHOW_REALIGN_COMMA => (FALSE), --
-----------------RX Loss-of-sync State Machine----------------
RX_LOS_INVALID_INCR => (8), --
RX_LOS_THRESHOLD => (128), --
RX_LOSS_OF_SYNC_FSM => TRUE, --(FALSE),
RX_LOSS_OF_SYNC_FSM => (TRUE), --(FALSE),
-------------------------RX Gearbox---------------------------
RXGEARBOX_USE => (FALSE), --
@@ -416,7 +225,7 @@ begin
RX_DLYALIGN_MONSEL => ("000"), --
RX_DLYALIGN_OVRDSETTING => ("10000000"), --
------------------------Clock Correction---------------------- --
------------------------Clock Correction---------------------- --
CLK_COR_ADJ_LEN => (1), --
CLK_COR_DET_LEN => (1), --
CLK_COR_INSERT_IDLE_FLAG => (FALSE), --
@@ -438,7 +247,7 @@ begin
CLK_COR_SEQ_2_USE => (FALSE), --
CLK_CORRECT_USE => (FALSE), --
--
------------------------Channel Bonding---------------------- --
------------------------Channel Bonding---------------------- --
CHAN_BOND_1_MAX_SKEW => (1), --
CHAN_BOND_2_MAX_SKEW => (1), --
CHAN_BOND_KEEP_ALIGN => (FALSE), --
@@ -457,7 +266,7 @@ begin
CHAN_BOND_SEQ_LEN => (1), --
PCI_EXPRESS_MODE => (FALSE), --
--
-------------RX Attributes for PCI Express/SATA/SAS---------- --
-------------RX Attributes for PCI Express/SATA/SAS---------- --
SAS_MAX_COMSAS => (52), --
SAS_MIN_COMSAS => (40), --
SATA_BURST_VAL => ("100"), --
@@ -682,473 +491,4 @@ begin
TXCOMWAKE => tied_to_ground_i --
);
end RTL;
-------------------------------------------------------------------------------
-- virtex6_gtxe_sync-----------------------------------------------------------
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
entity virtex6_gtxe_sync is
port
(
RXENPMAPHASEALIGN : out std_logic;
RXPMASETPHASE : out std_logic;
RXDLYALIGNDISABLE : out std_logic;
RXDLYALIGNOVERRIDE : out std_logic;
RXDLYALIGNRESET : out std_logic;
SYNC_DONE : out std_logic;
USER_CLK : in std_logic;
RESET : in std_logic
);
end virtex6_gtxe_sync;
architecture RTL of virtex6_gtxe_sync is
--***********************************Parameter Declarations********************
constant DLY : time := 1 ns;
--*******************************Register Declarations************************
signal begin_r : std_logic;
signal phase_align_r : std_logic;
signal ready_r : std_logic;
signal sync_counter_r : unsigned(5 downto 0);
signal sync_done_count_r : unsigned(5 downto 0);
signal align_reset_counter_r : unsigned(4 downto 0);
signal wait_after_sync_r : std_logic;
signal wait_before_setphase_counter_r : unsigned(5 downto 0);
signal wait_before_setphase_r : std_logic;
signal align_reset_r : std_logic;
--*******************************Wire Declarations****************************
signal count_32_setphase_complete_r : std_logic;
signal count_32_wait_complete_r : std_logic;
signal count_align_reset_complete_r : std_logic;
signal next_phase_align_c : std_logic;
signal next_align_reset_c : std_logic;
signal next_ready_c : std_logic;
signal next_wait_after_sync_c : std_logic;
signal next_wait_before_setphase_c : std_logic;
signal sync_32_times_done_r : std_logic;
attribute max_fanout:string;
attribute max_fanout of ready_r : signal is "2";
begin
--*******************************Main Body of Code****************************
--________________________________ State machine __________________________
-- This state machine manages the phase alingment procedure of the GTX on the
-- receive side. The module is held in reset till the usrclk source is stable
-- and RXRESETDONE is asserted. In the case that a MMCM is used to generate
-- rxusrclk, the mmcm_locked signal is used to indicate a stable usrclk source.
-- Once RXRESETDONE and mmcm_locked are asserted, the state machine goes
-- into the align_reset_r state where RXDLYALIGNRESET is asserted for 20 cycles.
-- After this, it goes into the wait_before_setphase_r state for 32 cycles.
-- After asserting RXENPMAPHASEALIGN and waiting 32 cycles, it enters the
-- phase_align_r state where RXPMASETPHASE is asserted for 32 clock cycles.
-- After the port is deasserted, the state machine goes into a wait state for
-- 32 cycles. This procedure is repeated 32 times.
-- State registers
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if(RESET='1') then
begin_r <= '1' after DLY;
align_reset_r <= '0' after DLY;
wait_before_setphase_r <= '0' after DLY;
phase_align_r <= '0' after DLY;
wait_after_sync_r <= '0' after DLY;
ready_r <= '0' after DLY;
else
begin_r <= '0' after DLY;
align_reset_r <= next_align_reset_c after DLY;
wait_before_setphase_r <= next_wait_before_setphase_c after DLY;
phase_align_r <= next_phase_align_c after DLY;
wait_after_sync_r <= next_wait_after_sync_c after DLY;
ready_r <= next_ready_c after DLY;
end if;
end if;
end process;
-- Next state logic
next_align_reset_c <= begin_r or
(align_reset_r and not count_align_reset_complete_r);
next_wait_before_setphase_c <= (align_reset_r and count_align_reset_complete_r) or
(wait_before_setphase_r and not count_32_wait_complete_r);
next_phase_align_c <= (wait_before_setphase_r and count_32_wait_complete_r) or
(phase_align_r and not count_32_setphase_complete_r) or
(wait_after_sync_r and count_32_wait_complete_r and not sync_32_times_done_r);
next_wait_after_sync_c <= (phase_align_r and count_32_setphase_complete_r) or
(wait_after_sync_r and not count_32_wait_complete_r);
next_ready_c <= (wait_after_sync_r and count_32_wait_complete_r and sync_32_times_done_r) or
ready_r;
--______ Counter for holding RXDLYALIGNRESET for 20 RXUSRCLK2 cycles ______
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if (align_reset_r='0') then
align_reset_counter_r <= (others=>'0') after DLY;
else
align_reset_counter_r <= align_reset_counter_r + 1 after DLY;
end if;
end if ;
end process;
count_align_reset_complete_r <= align_reset_counter_r(4)
and align_reset_counter_r(2);
--_______Counter for waiting 32 clock cycles before RXPMASETPHASE _________
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if ((wait_before_setphase_r='0') and (wait_after_sync_r='0')) then
wait_before_setphase_counter_r <= (others=>'0') after DLY;
else
wait_before_setphase_counter_r <= wait_before_setphase_counter_r + 1 after DLY;
end if;
end if;
end process;
count_32_wait_complete_r <= wait_before_setphase_counter_r(5);
--_______________ Counter for holding SYNC for SYNC_CYCLES ________________
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if (phase_align_r='0') then
sync_counter_r <= (others=>'0') after DLY;
else
sync_counter_r <= sync_counter_r + 1 after DLY;
end if;
end if;
end process;
count_32_setphase_complete_r <= sync_counter_r(5);
--__________ Counter for counting number of times sync is done ____________
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if (RESET='1') then
sync_done_count_r <= (others=>'0') after DLY;
elsif((count_32_wait_complete_r ='1') and (phase_align_r = '1')) then
sync_done_count_r <= sync_done_count_r + 1 after DLY;
end if;
end if;
end process;
sync_32_times_done_r <= sync_done_count_r(5);
--_______________ Assign the phase align ports into the GTX _______________
RXDLYALIGNRESET <= align_reset_r;
RXENPMAPHASEALIGN <= (not begin_r) and (not align_reset_r);
RXPMASETPHASE <= phase_align_r;
RXDLYALIGNDISABLE <= '1';
RXDLYALIGNOVERRIDE <= '1';
--_______________________ Assign the sync_done port _______________________
SYNC_DONE <= ready_r;
end RTL;
-------------------------------------------------------------------------------
-- ioxos_mgt_v1 ---------------------------------------------------------------
-------------------------------------------------------------------------------
library UNISIM;
use UNISIM.VCOMPONENTS.ALL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use work.pkg_v6vlx_gtxe1.all;
entity v6vlx_gtxe1_wrapper is
generic(
g_MGT_LOCATION : string;
g_USE_MMCM : boolean := false
);
port(
-- MGT serial interface
i_mgt_refclk : in std_logic;
o_mgt_refclk : out std_logic;
i_mgt_rx_p : in std_logic;
i_mgt_rx_n : in std_logic;
o_mgt_tx_p : out std_logic;
o_mgt_tx_n : out std_logic;
-- MGT parallel interface
o_mgt_status : out std_logic_vector(31 downto 0); -- see lines 134-139 for details
i_mgt_control : in std_logic_vector(31 downto 0); -- see lines 127-131 for details
o_mgt_recclk : out std_logic;
o_mgt_rx_data : out std_logic_vector(15 downto 0);
o_mgt_rx_charisk : out std_logic_vector( 1 downto 0)
);
end v6vlx_gtxe1_wrapper;
architecture RTL of v6vlx_gtxe1_wrapper is
type typ_align_fsm is (
align_idle,
align_slide ,
align_wait_for_sync
);
signal s_align_fsm : typ_align_fsm := align_idle;
-- GTXE
signal i_mgt : gtxe_in_type;
signal o_mgt : gtxe_out_type;
signal sl_txoutclk : std_logic;
--fifo
signal sl_cpu_rx_empty : std_logic;
signal sl_gtxe_fifo_rst : std_logic;
signal sl_gtxe_rx_sync_done : std_logic;
signal slv_rxresetdone : std_logic_vector(7 downto 0);
signal sl_rx_sync_rst : std_logic;
signal sl_rxrecclk : std_logic;
signal sl_rx0_slide : std_logic;
signal slv_cnt : std_logic_vector(5 downto 0);
-- MMCM
signal mmcm_CLKFB : std_logic;
signal mmcm_CLKFBOUT : std_logic;
signal mmcm_LOCKED : std_logic;
signal mmcm_RESET : std_logic;
signal mmcm_CLOCK : std_logic;
begin
-- inst_mgt_refclk_bufg: BUFG
-- port map
-- (
-- I => o_mgt.ctrl.REFCLKOUT,
-- O => o_mgt_refclk
-- );
-- GTXE INSTANCE ------------------------------------------------------------------
ins_v6vlx_gtxe1: v6vlx_gtxe1
generic map (
g_MGT_LOCATION => g_MGT_LOCATION )
port map (
i_mgt => i_mgt,
o_mgt => o_mgt
);
-- GTXE CONTROL IF ----------------------------------------------------------------
i_mgt.ctrl.GTXRESET <= i_mgt_control(0);
i_mgt.ctrl.PLLRXRESET <= '0';
i_mgt.ctrl.PLLTXRESET <= '0';
i_mgt.ctrl.LOOPBACK <= "100"; -- Far-End PMA Loopback --> UG366 page 125
i_mgt.ctrl.CLKIN <= i_mgt_refclk;
-- GTXE STATUS IF (adapted to PSI generic part) -----------------------------------
o_mgt_status( 0) <= o_mgt.ctrl.TXPLLLKDET;
o_mgt_status( 1) <= o_mgt.ctrl.RXPLLLKDET;
o_mgt_status( 2) <= mmcm_LOCKED;
o_mgt_status( 3) <= o_mgt.ctrl.TXRESETDONE;
o_mgt_status( 4) <= o_mgt.ctrl.RXRESETDONE;
o_mgt_status( 5) <= '0'; -- TX_polarity inverted
o_mgt_status( 6) <= '0'; -- RX_polarity inverted
o_mgt_status( 7) <= '0'; -- reserved
o_mgt_status(12 downto 8) <= "00000"; -- DFEEYEDACMON[4:0]
o_mgt_status(13) <= '0'; -- RXPRBSERR
o_mgt_status(14) <= o_mgt.rx.RXBYTEISALIGNED;
o_mgt_status(15) <= o_mgt.rx.RXLOSSOFSYNC(1);
---------- additional status -------------
o_mgt_status(16) <= sl_rx0_slide;
o_mgt_status(17) <= sl_gtxe_rx_sync_done;
o_mgt_status(19 downto 18) <= o_mgt.rx.RXNOTINTABLE(1 downto 0); -- Byte 1 + Byte 0
o_mgt_status(21 downto 20) <= o_mgt.rx.RXDISPERR(1 downto 0); -- Byte 1 + Byte 0
o_mgt_status(31 downto 22) <= B"00_0000_0000"; -- undefined
-- GTXE RX IF ---------------------------------------------------------------------
-- MMCM use model based on AR#39430
gen_MMCM: if g_USE_MMCM generate
begin
-- Use Core Generator to define parameters -> actual frequency 142.8 MHz
mmcm_rxclk : MMCM_BASE
generic map (
CLKFBOUT_MULT_F => 33.000 , -- Counter multiply value, Now supports non-integer values
CLKIN1_PERIOD => 7.002 , -- The reference clock frequency is required for properly configuring the
-- LOCK detect circuit and checking to make sure the VCO is operating within
-- the allowed range. If no value is specified, a warning should be issued
-- stating it was not provided so no error checking will be done.
CLKOUT0_DIVIDE_F => 8.250 , -- Counter divide value, Now supports non-integer values but you lose CLKOUT5
DIVCLK_DIVIDE => 4 -- Counter divide value, always configured for 50% duty cycle
)
port map (
CLKFBOUT => mmcm_CLKFBOUT, -- 1-bit MMCM Feedback clock output
CLKFBOUTB => open, -- 1-bit Inverted MMCM feedback clock output
CLKOUT0 => mmcm_CLOCK, -- 1-bit MMCM clock output 0
CLKOUT0B => open, -- 1-bit Inverted MMCM clock output 0
CLKOUT1 => open, -- 1-bit MMCM clock output 1
CLKOUT1B => open, -- 1-bit Inverted MMCM clock output 1
CLKOUT2 => open, -- 1-bit MMCM clock output 2
CLKOUT2B => open, -- 1-bit Inverted MMCM clock output 2
CLKOUT3 => open, -- 1-bit MMCM clock output 3
CLKOUT3B => open, -- 1-bit Inverted MMCM clock output 3
CLKOUT4 => open, -- 1-bit MMCM clock output 4
CLKOUT5 => open, -- 1-bit MMCM clock output 5, not used if CLKOUT0 is not an integer
CLKOUT6 => open, -- 1-bit MMCM clock output 6, not used if CLKFBOUT_MULT is not an integer
LOCKED => mmcm_LOCKED, -- 1-bit MMC locked signal
CLKFBIN => mmcm_CLKFB, -- 1-bit Feedback clock pin to the MMCM
CLKIN1 => o_mgt.rx.RXRECCLK, -- 1-bit Reference clock pin 1 to the MMCM
PWRDWN => '0', -- 1-bit Power down
RST => mmcm_RESET -- 1-bit MMCM global reset pin
);
mmcm_RESET <= not o_mgt.ctrl.RXPLLLKDET;
rxoutCLKFB_bufg0_i : BUFG
port map (
I => mmcm_CLKFBOUT,
O => mmcm_CLKFB
);
rxoutclk_bufg1_i : BUFG
port map (
I => mmcm_CLOCK,
O => sl_rxrecclk
);
end generate;
gen_BUFG: if not(g_USE_MMCM) generate
begin
rxoutclk_bufg0_i : BUFG
port map (
I => o_mgt.rx.RXRECCLK,
O => sl_rxrecclk
);
-- forward lock state
mmcm_LOCKED <= o_mgt.ctrl.RXPLLLKDET;
-- unused without mmcm
mmcm_CLKFB <= '0';
mmcm_CLKFBOUT <= '0';
mmcm_RESET <= '0';
mmcm_CLOCK <= '0';
end generate;
o_mgt_recclk <= sl_rxrecclk;
ins_virtex6_gtxe_sync : virtex6_gtxe_sync
port map (
RXENPMAPHASEALIGN => i_mgt.rx.RXENPMAPHASEALIGN ,
RXPMASETPHASE => i_mgt.rx.RXPMASETPHASE ,
RXDLYALIGNDISABLE => i_mgt.rx.RXDLYALIGNDISABLE ,
RXDLYALIGNOVERRIDE => i_mgt.rx.RXDLYALIGNOVERRIDE,
RXDLYALIGNRESET => i_mgt.rx.RXDLYALIGNRESET ,
SYNC_DONE => sl_gtxe_rx_sync_done,
USER_CLK => sl_rxrecclk,
RESET => sl_rx_sync_rst
);
prc_rx_reset_done_delay : process ( sl_rxrecclk )
begin
if rising_edge( sl_rxrecclk ) then
slv_rxresetdone <= slv_rxresetdone(6 downto 0) & o_mgt.ctrl.RXRESETDONE;
end if;
end process ;
sl_rx_sync_rst <= not slv_rxresetdone(7);
i_mgt.rx.RXUSRCLK <= sl_rxrecclk;
i_mgt.rx.RXUSRCLK2 <= sl_rxrecclk;
i_mgt.rx.RXP <= i_mgt_rx_p;
i_mgt.rx.RXN <= i_mgt_rx_n;
i_mgt.rx.RXENMCOMMAALIGN <= '0';
i_mgt.rx.RXENPCOMMAALIGN <= '0';
i_mgt.rx.RXRESET <= not mmcm_LOCKED;
i_mgt.rx.RXCDRRESET <= i_mgt_control(5);
i_mgt.rx.RXDLYALIGNMONENB <= '0';
o_mgt_rx_data <= o_mgt.rx.RXDATA(15 downto 0);
o_mgt_rx_charisk <= o_mgt.rx.RXCHARISK( 1 downto 0);
------------------------------------------------------------------------------
--RX comma alignment
------------------------------------------------------------------------------
prc_comma_align : process ( sl_rxrecclk )
begin
if rising_edge( sl_rxrecclk ) then
if o_mgt.ctrl.RXRESETDONE = '0' then
s_align_fsm <= align_idle;
else
case s_align_fsm is
when align_idle =>
if o_mgt.rx.RXLOSSOFSYNC( 1) = '1' then
s_align_fsm <= align_slide;
end if;
when align_slide =>
slv_cnt <= (others => '0');
s_align_fsm <= align_wait_for_sync;
when align_wait_for_sync =>
if slv_cnt(slv_cnt'left) = '1' then
if o_mgt.rx.RXLOSSOFSYNC( 1) = '0' and o_mgt.rx.RXBYTEISALIGNED = '1' then
s_align_fsm <= align_idle;
else
s_align_fsm <= align_slide;
end if;
else
slv_cnt <= slv_cnt + X"1";
end if;
end case;
end if;
end if;
end process ;
sl_rx0_slide <= '1' when s_align_fsm = align_slide or i_mgt_control(2) = '1' else '0';
i_mgt.rx.RXSLIDE <= sl_rx0_slide;
-- GTXE TX IF ---------------------------------------------------------------------
o_mgt_tx_p <= o_mgt.tx.TXP;
o_mgt_tx_n <= o_mgt.tx.TXN;
-- txoutclk_bufg0_i : BUFG
-- port map (
-- I => o_mgt.tx.TXOUTCLK,
-- O => sl_txoutclk
-- );
i_mgt.tx.TXRESET <= not mmcm_LOCKED;
i_mgt.tx.TXBYPASS8B10B <= X"0";
i_mgt.tx.TXCHARDISPMODE <= X"0";
i_mgt.tx.TXCHARDISPVAL <= X"0";
i_mgt.tx.TXUSRCLK <= sl_rxrecclk;
i_mgt.tx.TXUSRCLK2 <= sl_rxrecclk;
i_mgt.tx.TXDIFFCTRL <= "0110";
i_mgt.tx.TXPOSTEMPHASIS <= "00000";
i_mgt.tx.TXPREEMPHASIS <= "0000";
end RTL;

207
hdl/v6vlx_gtxe1_pkg.vhd Normal file
View File

@@ -0,0 +1,207 @@
------------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
------------------------------------------------------------------------------
-- Unit : v6vlx_gtxe1_pkg.vhd
-- Author : Goran Marinkovic, Section Diagnostic
-- : Waldemar Koprek, Section Diagnostic
-- : Patric Bucher, Section DSV
-- Version : $Revision: 1.1 $
------------------------------------------------------------------------------
-- Copyright© PSI, Section Diagnostic
------------------------------------------------------------------------------
-- Comment :
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package v6vlx_gtxe1_pkg is
---------------------------------------------------------------------------
-- Types
---------------------------------------------------------------------------
type gtxe_ctrl_in_type is record
GTXRESET : std_ulogic;
LOOPBACK : std_logic_vector( 2 downto 0);
CLKIN : std_ulogic;
PLLRXRESET : std_ulogic;
PLLTXRESET : std_ulogic;
end record gtxe_ctrl_in_type;
type gtxe_ctrl_out_type is record
RXPLLLKDET : std_ulogic;
RXRESETDONE : std_ulogic;
TXPLLLKDET : std_ulogic;
TXRESETDONE : std_ulogic;
REFCLKOUT : std_ulogic;
end record gtxe_ctrl_out_type;
-- type mgt_drp_in_type is record
-- -- Dynamic Reconfiguration Port (DRP)
-- DCLK : std_ulogic;
-- DEN : std_ulogic;
-- DWE : std_ulogic;
-- DADDR : std_logic_vector( 6 downto 0);
-- DI : std_logic_vector(15 downto 0);
-- end record mgt_drp_in_type;
--
-- type mgt_drp_out_type is record
-- -- Dynamic Reconfiguration Port (DRP)
-- DO : std_logic_vector(15 downto 0);
-- DRDY : std_ulogic;
-- end record mgt_drp_out_type;
type gtxe_rx_in_type is record
-- Comma Detection and Alignment ------------------------
RXENMCOMMAALIGN : std_ulogic;
RXENPCOMMAALIGN : std_ulogic;
-- RX resets
RXRESET : std_ulogic;
RXCDRRESET : std_ulogic;
-- RX user clocks
RXUSRCLK : std_ulogic;
RXUSRCLK2 : std_ulogic;
-- RX serial ports
RXP : std_ulogic;
RXN : std_ulogic;
-- RX Elastic Buffer and Phase Alignment Ports
RXDLYALIGNDISABLE : std_logic;
RXDLYALIGNMONENB : std_logic;
RXDLYALIGNOVERRIDE : std_logic;
RXDLYALIGNRESET : std_logic;
RXENPMAPHASEALIGN : std_logic;
RXPMASETPHASE : std_logic;
RXSLIDE : std_logic;
end record gtxe_rx_in_type;
type gtxe_rx_out_type is record
-- RX 8b10b Decoder
RXCHARISCOMMA : std_logic_vector( 3 downto 0);
RXCHARISK : std_logic_vector( 3 downto 0);
RXDISPERR : std_logic_vector( 3 downto 0);
RXNOTINTABLE : std_logic_vector( 3 downto 0);
RXRUNDISP : std_logic_vector( 3 downto 0);
-- Comma Detection and Alignment
RXBYTEISALIGNED : std_ulogic;
RXBYTEREALIGN : std_ulogic;
RXCOMMADET : std_ulogic;
-- RX data ports
RXDATA : std_logic_vector(31 downto 0);
-- RX user clocks
RXRECCLK : std_ulogic;
-- RX Out Of Band (OOB)
RXELECIDLE : std_ulogic;
-- RX Elastic Buffer and Phase Alignment Ports
RXDLYALIGNMONITOR : std_logic_vector(7 downto 0);
-- RX loss of sync fsm
RXLOSSOFSYNC : std_logic_vector( 1 downto 0);
end record gtxe_rx_out_type;
type gtxe_tx_in_type is record
-- 8b10b Encoder Control Ports
TXBYPASS8B10B : std_logic_vector( 3 downto 0);
TXCHARDISPMODE : std_logic_vector( 3 downto 0);
TXCHARDISPVAL : std_logic_vector( 3 downto 0);
TXCHARISK : std_logic_vector( 3 downto 0);
-- TX data ports
TXDATA : std_logic_vector(31 downto 0);
-- TX resets
TXRESET : std_ulogic;
-- TX user clocks
TXUSRCLK : std_ulogic;
TXUSRCLK2 : std_ulogic;
-- TX driver
TXDIFFCTRL : std_logic_vector( 3 downto 0);
TXPOSTEMPHASIS : std_logic_vector( 4 downto 0);
TXPREEMPHASIS : std_logic_vector( 3 downto 0);
end record gtxe_tx_in_type;
type gtxe_tx_out_type is record
-- TX serial ports
TXP : std_ulogic;
TXN : std_ulogic;
-- TX 8b10b encoder
TXKERR : std_logic_vector( 3 downto 0);
TXRUNDISP : std_logic_vector( 3 downto 0);
-- TX user clocks
TXOUTCLK : std_ulogic;
end record gtxe_tx_out_type;
type gtxe_in_type is record
ctrl : gtxe_ctrl_in_type;
--drp : mgt_drp_in_type;
rx : gtxe_rx_in_type;
tx : gtxe_tx_in_type;
end record gtxe_in_type;
type gtxe_out_type is record
ctrl : gtxe_ctrl_out_type;
--drp : mgt_drp_out_type;
rx : gtxe_rx_out_type;
tx : gtxe_tx_out_type;
end record gtxe_out_type;
---------------------------------------------------------------------------
-- Components
---------------------------------------------------------------------------
component v6vlx_gtxe1_142MHz8_2Gbps856
generic(
g_MGT_LOCATION : string
);
port
(
i_mgt : in gtxe_in_type;
o_mgt : out gtxe_out_type
);
end component;
component v6vlx_gtxe1_101MHz27_1Gbps0127
generic(
g_MGT_LOCATION : string
);
port
(
i_mgt : in gtxe_in_type;
o_mgt : out gtxe_out_type
);
end component;
component v6vlx_gtxe1_sync is
port
(
RXENPMAPHASEALIGN : out std_logic;
RXPMASETPHASE : out std_logic;
RXDLYALIGNDISABLE : out std_logic;
RXDLYALIGNOVERRIDE : out std_logic;
RXDLYALIGNRESET : out std_logic;
SYNC_DONE : out std_logic;
USER_CLK : in std_logic;
RESET : in std_logic
);
end component;
component v6vlx_gtxe1_wrapper is
generic(
g_MGT_LOCATION : string;
g_USE_MMCM : boolean := false
);
port
(
-- MGT serial interface
i_mgt_refclk : in std_logic;
o_mgt_refclk : out std_logic;
i_mgt_rx_p : in std_logic;
i_mgt_rx_n : in std_logic;
o_mgt_tx_p : out std_logic;
o_mgt_tx_n : out std_logic;
-- MGT parallel interface
o_mgt_status : out std_logic_vector(31 downto 0); -- see lines 134-139 for details
i_mgt_control : in std_logic_vector(31 downto 0); -- see lines 127-131 for details
o_mgt_recclk : out std_logic;
o_mgt_rx_data : out std_logic_vector(15 downto 0);
o_mgt_rx_charisk : out std_logic_vector( 1 downto 0)
);
end component;
end package v6vlx_gtxe1_pkg;

191
hdl/v6vlx_gtxe1_sync.vhd Normal file
View File

@@ -0,0 +1,191 @@
------------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
------------------------------------------------------------------------------
-- Unit : v6vlx_gtxe1_sync.vhd
-- Author : Goran Marinkovic, Section Diagnostic
-- : Waldemar Koprek, Section Diagnostic
-- Version : $Revision: 1.1 $
------------------------------------------------------------------------------
-- Copyright© PSI, Section Diagnostic
------------------------------------------------------------------------------
-- Comment : GTX synchronisation and alignment process.
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity v6vlx_gtxe1_sync is
port
(
RXENPMAPHASEALIGN : out std_logic;
RXPMASETPHASE : out std_logic;
RXDLYALIGNDISABLE : out std_logic;
RXDLYALIGNOVERRIDE : out std_logic;
RXDLYALIGNRESET : out std_logic;
SYNC_DONE : out std_logic;
USER_CLK : in std_logic;
RESET : in std_logic
);
end v6vlx_gtxe1_sync;
architecture RTL of v6vlx_gtxe1_sync is
--***********************************Parameter Declarations********************
constant DLY : time := 1 ns;
--*******************************Register Declarations************************
signal begin_r : std_logic;
signal phase_align_r : std_logic;
signal ready_r : std_logic;
signal sync_counter_r : unsigned(5 downto 0);
signal sync_done_count_r : unsigned(5 downto 0);
signal align_reset_counter_r : unsigned(4 downto 0);
signal wait_after_sync_r : std_logic;
signal wait_before_setphase_counter_r : unsigned(5 downto 0);
signal wait_before_setphase_r : std_logic;
signal align_reset_r : std_logic;
--*******************************Wire Declarations****************************
signal count_32_setphase_complete_r : std_logic;
signal count_32_wait_complete_r : std_logic;
signal count_align_reset_complete_r : std_logic;
signal next_phase_align_c : std_logic;
signal next_align_reset_c : std_logic;
signal next_ready_c : std_logic;
signal next_wait_after_sync_c : std_logic;
signal next_wait_before_setphase_c : std_logic;
signal sync_32_times_done_r : std_logic;
attribute max_fanout:string;
attribute max_fanout of ready_r : signal is "2";
begin
--*******************************Main Body of Code****************************
--________________________________ State machine __________________________
-- This state machine manages the phase alingment procedure of the GTX on the
-- receive side. The module is held in reset till the usrclk source is stable
-- and RXRESETDONE is asserted. In the case that a MMCM is used to generate
-- rxusrclk, the mmcm_locked signal is used to indicate a stable usrclk source.
-- Once RXRESETDONE and mmcm_locked are asserted, the state machine goes
-- into the align_reset_r state where RXDLYALIGNRESET is asserted for 20 cycles.
-- After this, it goes into the wait_before_setphase_r state for 32 cycles.
-- After asserting RXENPMAPHASEALIGN and waiting 32 cycles, it enters the
-- phase_align_r state where RXPMASETPHASE is asserted for 32 clock cycles.
-- After the port is deasserted, the state machine goes into a wait state for
-- 32 cycles. This procedure is repeated 32 times.
-- State registers
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if(RESET='1') then
begin_r <= '1' after DLY;
align_reset_r <= '0' after DLY;
wait_before_setphase_r <= '0' after DLY;
phase_align_r <= '0' after DLY;
wait_after_sync_r <= '0' after DLY;
ready_r <= '0' after DLY;
else
begin_r <= '0' after DLY;
align_reset_r <= next_align_reset_c after DLY;
wait_before_setphase_r <= next_wait_before_setphase_c after DLY;
phase_align_r <= next_phase_align_c after DLY;
wait_after_sync_r <= next_wait_after_sync_c after DLY;
ready_r <= next_ready_c after DLY;
end if;
end if;
end process;
-- Next state logic
next_align_reset_c <= begin_r or
(align_reset_r and not count_align_reset_complete_r);
next_wait_before_setphase_c <= (align_reset_r and count_align_reset_complete_r) or
(wait_before_setphase_r and not count_32_wait_complete_r);
next_phase_align_c <= (wait_before_setphase_r and count_32_wait_complete_r) or
(phase_align_r and not count_32_setphase_complete_r) or
(wait_after_sync_r and count_32_wait_complete_r and not sync_32_times_done_r);
next_wait_after_sync_c <= (phase_align_r and count_32_setphase_complete_r) or
(wait_after_sync_r and not count_32_wait_complete_r);
next_ready_c <= (wait_after_sync_r and count_32_wait_complete_r and sync_32_times_done_r) or
ready_r;
--______ Counter for holding RXDLYALIGNRESET for 20 RXUSRCLK2 cycles ______
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if (align_reset_r='0') then
align_reset_counter_r <= (others=>'0') after DLY;
else
align_reset_counter_r <= align_reset_counter_r + 1 after DLY;
end if;
end if ;
end process;
count_align_reset_complete_r <= align_reset_counter_r(4)
and align_reset_counter_r(2);
--_______Counter for waiting 32 clock cycles before RXPMASETPHASE _________
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if ((wait_before_setphase_r='0') and (wait_after_sync_r='0')) then
wait_before_setphase_counter_r <= (others=>'0') after DLY;
else
wait_before_setphase_counter_r <= wait_before_setphase_counter_r + 1 after DLY;
end if;
end if;
end process;
count_32_wait_complete_r <= wait_before_setphase_counter_r(5);
--_______________ Counter for holding SYNC for SYNC_CYCLES ________________
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if (phase_align_r='0') then
sync_counter_r <= (others=>'0') after DLY;
else
sync_counter_r <= sync_counter_r + 1 after DLY;
end if;
end if;
end process;
count_32_setphase_complete_r <= sync_counter_r(5);
--__________ Counter for counting number of times sync is done ____________
process( USER_CLK )
begin
if(USER_CLK'event and USER_CLK = '1') then
if (RESET='1') then
sync_done_count_r <= (others=>'0') after DLY;
elsif((count_32_wait_complete_r ='1') and (phase_align_r = '1')) then
sync_done_count_r <= sync_done_count_r + 1 after DLY;
end if;
end if;
end process;
sync_32_times_done_r <= sync_done_count_r(5);
--_______________ Assign the phase align ports into the GTX _______________
RXDLYALIGNRESET <= align_reset_r;
RXENPMAPHASEALIGN <= (not begin_r) and (not align_reset_r);
RXPMASETPHASE <= phase_align_r;
RXDLYALIGNDISABLE <= '1';
RXDLYALIGNOVERRIDE <= '1';
--_______________________ Assign the sync_done port _______________________
SYNC_DONE <= ready_r;
end RTL;

308
hdl/v6vlx_gtxe1_wrapper.vhd Normal file
View File

@@ -0,0 +1,308 @@
------------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
------------------------------------------------------------------------------
-- Unit : v6vlx_gtxe1_wrapper.vhd
-- Author : Goran Marinkovic, Section Diagnostic
-- : Waldemar Koprek, Section Diagnostic
-- : Patric Bucher, Section DSV
-- Version : $Revision: 1.1 $
------------------------------------------------------------------------------
-- Copyright© PSI, Section Diagnostic
------------------------------------------------------------------------------
-- Comment : Wrapper vor Virtex-6 GTX ready to use in HIPA and SwissFEL (SFEL)
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;
use work.v6vlx_gtxe1_pkg.all;
entity v6vlx_gtxe1_wrapper is
generic(
g_MGT_LOCATION : string; -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY : string -- "HIPA" | "SFEL"
);
port(
-- MGT serial interface
i_mgt_refclk : in std_logic;
o_mgt_refclk : out std_logic;
i_mgt_rx_p : in std_logic;
i_mgt_rx_n : in std_logic;
o_mgt_tx_p : out std_logic;
o_mgt_tx_n : out std_logic;
-- MGT parallel interface
o_mgt_status : out std_logic_vector(31 downto 0); -- see lines 134-139 for details
i_mgt_control : in std_logic_vector(31 downto 0); -- see lines 127-131 for details
o_mgt_recclk : out std_logic;
o_mgt_rx_data : out std_logic_vector(15 downto 0);
o_mgt_rx_charisk : out std_logic_vector( 1 downto 0)
);
end v6vlx_gtxe1_wrapper;
architecture RTL of v6vlx_gtxe1_wrapper is
type typ_align_fsm is (
align_idle,
align_slide ,
align_wait_for_sync
);
signal s_align_fsm : typ_align_fsm := align_idle;
-- GTXE
signal i_mgt : gtxe_in_type;
signal o_mgt : gtxe_out_type;
signal sl_txoutclk : std_logic;
--fifo
signal sl_cpu_rx_empty : std_logic;
signal sl_gtxe_fifo_rst : std_logic;
signal sl_gtxe_rx_sync_done : std_logic;
signal slv_rxresetdone : std_logic_vector(7 downto 0);
signal sl_rx_sync_rst : std_logic;
signal sl_rxrecclk : std_logic;
signal sl_rx0_slide : std_logic;
signal slv_cnt : unsigned(5 downto 0);
-- MMCM
signal mmcm_CLKFB : std_logic;
signal mmcm_CLKFBOUT : std_logic;
signal mmcm_LOCKED : std_logic;
signal mmcm_RESET : std_logic;
signal mmcm_CLOCK : std_logic;
begin
-- inst_mgt_refclk_bufg: BUFG
-- port map
-- (
-- I => o_mgt.ctrl.REFCLKOUT,
-- O => o_mgt_refclk
-- );
-- GTXE INSTANCE ------------------------------------------------------------------
gen_gtxe1_sfel: if g_FACILITY = "SFEL" generate
ins_v6vlx_gtxe1_sfel: entity work.v6vlx_gtxe1_142MHz8_2Gbps856
generic map (
g_MGT_LOCATION => g_MGT_LOCATION )
port map (
i_mgt => i_mgt,
o_mgt => o_mgt
);
end generate;
gen_gtxe1_hipa: if g_FACILITY = "HIPA" generate
ins_v6vlx_gtxe1_hipa: entity work.v6vlx_gtxe1_101MHz27_1Gbps0127
generic map (
g_MGT_LOCATION => g_MGT_LOCATION )
port map (
i_mgt => i_mgt,
o_mgt => o_mgt
);
end generate;
assert not(g_FACILITY /= "HIPA" and g_FACILITY /= "SFEL")
report "Invalid value for g_FACILITY, valid values are 'HIPA'|'SFEL'"
severity failure;
-- GTXE CONTROL IF ----------------------------------------------------------------
i_mgt.ctrl.GTXRESET <= i_mgt_control(0);
i_mgt.ctrl.PLLRXRESET <= '0';
i_mgt.ctrl.PLLTXRESET <= '0';
i_mgt.ctrl.LOOPBACK <= "100"; -- Far-End PMA Loopback --> UG366 page 125
i_mgt.ctrl.CLKIN <= i_mgt_refclk;
-- GTXE STATUS IF (adapted to PSI generic part) -----------------------------------
o_mgt_status( 0) <= o_mgt.ctrl.TXPLLLKDET;
o_mgt_status( 1) <= o_mgt.ctrl.RXPLLLKDET;
o_mgt_status( 2) <= mmcm_LOCKED;
o_mgt_status( 3) <= o_mgt.ctrl.TXRESETDONE;
o_mgt_status( 4) <= o_mgt.ctrl.RXRESETDONE;
o_mgt_status( 5) <= '0'; -- TX_polarity inverted
o_mgt_status( 6) <= '0'; -- RX_polarity inverted
o_mgt_status( 7) <= '0'; -- reserved
o_mgt_status(12 downto 8) <= "00000"; -- DFEEYEDACMON[4:0]
o_mgt_status(13) <= '0'; -- RXPRBSERR
o_mgt_status(14) <= o_mgt.rx.RXBYTEISALIGNED;
o_mgt_status(15) <= o_mgt.rx.RXLOSSOFSYNC(1);
---------- additional status -------------
o_mgt_status(16) <= sl_rx0_slide;
o_mgt_status(17) <= sl_gtxe_rx_sync_done;
o_mgt_status(19 downto 18) <= o_mgt.rx.RXNOTINTABLE(1 downto 0); -- Byte 1 + Byte 0
o_mgt_status(21 downto 20) <= o_mgt.rx.RXDISPERR(1 downto 0); -- Byte 1 + Byte 0
o_mgt_status(31 downto 22) <= B"00_0000_0000"; -- undefined
-- GTXE RX IF ---------------------------------------------------------------------
-- MMCM use model based on AR#39430
gen_MMCM: if g_FACILITY = "SFEL" generate
begin
-- Use Core Generator to define parameters -> actual frequency 142.8 MHz
mmcm_rxclk : MMCM_BASE
generic map (
CLKFBOUT_MULT_F => 33.000 , -- Counter multiply value, Now supports non-integer values
CLKIN1_PERIOD => 7.002 , -- The reference clock frequency is required for properly configuring the
-- LOCK detect circuit and checking to make sure the VCO is operating within
-- the allowed range. If no value is specified, a warning should be issued
-- stating it was not provided so no error checking will be done.
CLKOUT0_DIVIDE_F => 8.250 , -- Counter divide value, Now supports non-integer values but you lose CLKOUT5
DIVCLK_DIVIDE => 4 -- Counter divide value, always configured for 50% duty cycle
)
port map (
CLKFBOUT => mmcm_CLKFBOUT, -- 1-bit MMCM Feedback clock output
CLKFBOUTB => open, -- 1-bit Inverted MMCM feedback clock output
CLKOUT0 => mmcm_CLOCK, -- 1-bit MMCM clock output 0
CLKOUT0B => open, -- 1-bit Inverted MMCM clock output 0
CLKOUT1 => open, -- 1-bit MMCM clock output 1
CLKOUT1B => open, -- 1-bit Inverted MMCM clock output 1
CLKOUT2 => open, -- 1-bit MMCM clock output 2
CLKOUT2B => open, -- 1-bit Inverted MMCM clock output 2
CLKOUT3 => open, -- 1-bit MMCM clock output 3
CLKOUT3B => open, -- 1-bit Inverted MMCM clock output 3
CLKOUT4 => open, -- 1-bit MMCM clock output 4
CLKOUT5 => open, -- 1-bit MMCM clock output 5, not used if CLKOUT0 is not an integer
CLKOUT6 => open, -- 1-bit MMCM clock output 6, not used if CLKFBOUT_MULT is not an integer
LOCKED => mmcm_LOCKED, -- 1-bit MMC locked signal
CLKFBIN => mmcm_CLKFB, -- 1-bit Feedback clock pin to the MMCM
CLKIN1 => o_mgt.rx.RXRECCLK, -- 1-bit Reference clock pin 1 to the MMCM
PWRDWN => '0', -- 1-bit Power down
RST => mmcm_RESET -- 1-bit MMCM global reset pin
);
mmcm_RESET <= not o_mgt.ctrl.RXPLLLKDET;
rxoutCLKFB_bufg0_i : BUFG
port map (
O => mmcm_CLKFB,
I => mmcm_CLKFBOUT
);
rxoutclk_bufg1_i : BUFG
port map (
O => sl_rxrecclk,
I => mmcm_CLOCK
);
end generate;
gen_BUFG: if g_FACILITY = "HIPA" generate
begin
rxoutclk_bufg0_i : BUFG
port map (
O => sl_rxrecclk,
I => o_mgt.rx.RXRECCLK
);
-- forward lock state
mmcm_LOCKED <= o_mgt.ctrl.RXPLLLKDET;
-- unused without mmcm
mmcm_CLKFB <= '0';
mmcm_CLKFBOUT <= '0';
mmcm_RESET <= '0';
mmcm_CLOCK <= '0';
end generate;
o_mgt_recclk <= sl_rxrecclk;
ins_v6vlx_gtxe1_sync : entity work.v6vlx_gtxe1_sync
port map (
RXENPMAPHASEALIGN => i_mgt.rx.RXENPMAPHASEALIGN ,
RXPMASETPHASE => i_mgt.rx.RXPMASETPHASE ,
RXDLYALIGNDISABLE => i_mgt.rx.RXDLYALIGNDISABLE ,
RXDLYALIGNOVERRIDE => i_mgt.rx.RXDLYALIGNOVERRIDE,
RXDLYALIGNRESET => i_mgt.rx.RXDLYALIGNRESET ,
SYNC_DONE => sl_gtxe_rx_sync_done,
USER_CLK => sl_rxrecclk,
RESET => sl_rx_sync_rst
);
prc_rx_reset_done_delay : process ( sl_rxrecclk )
begin
if rising_edge( sl_rxrecclk ) then
slv_rxresetdone <= slv_rxresetdone(6 downto 0) & o_mgt.ctrl.RXRESETDONE;
end if;
end process ;
sl_rx_sync_rst <= not slv_rxresetdone(7);
i_mgt.rx.RXUSRCLK <= sl_rxrecclk;
i_mgt.rx.RXUSRCLK2 <= sl_rxrecclk;
i_mgt.rx.RXP <= i_mgt_rx_p;
i_mgt.rx.RXN <= i_mgt_rx_n;
i_mgt.rx.RXENMCOMMAALIGN <= '0';
i_mgt.rx.RXENPCOMMAALIGN <= '0';
i_mgt.rx.RXRESET <= not mmcm_LOCKED;
i_mgt.rx.RXCDRRESET <= i_mgt_control(5);
i_mgt.rx.RXDLYALIGNMONENB <= '0';
o_mgt_rx_data <= o_mgt.rx.RXDATA(15 downto 0);
o_mgt_rx_charisk <= o_mgt.rx.RXCHARISK( 1 downto 0);
------------------------------------------------------------------------------
--RX comma alignment
------------------------------------------------------------------------------
prc_comma_align : process ( sl_rxrecclk )
begin
if rising_edge( sl_rxrecclk ) then
if o_mgt.ctrl.RXRESETDONE = '0' then
s_align_fsm <= align_idle;
else
case s_align_fsm is
when align_idle =>
if o_mgt.rx.RXLOSSOFSYNC( 1) = '1' or o_mgt.rx.RXBYTEISALIGNED = '0' then
s_align_fsm <= align_slide;
end if;
when align_slide =>
slv_cnt <= (others => '0');
s_align_fsm <= align_wait_for_sync;
when align_wait_for_sync =>
if slv_cnt(slv_cnt'left) = '1' then
if o_mgt.rx.RXLOSSOFSYNC( 1) = '0' and o_mgt.rx.RXBYTEISALIGNED = '1' then
s_align_fsm <= align_idle;
else
s_align_fsm <= align_slide;
end if;
else
slv_cnt <= slv_cnt + X"1";
end if;
end case;
end if;
end if;
end process ;
sl_rx0_slide <= '1' when s_align_fsm = align_slide or i_mgt_control(2) = '1' else '0';
i_mgt.rx.RXSLIDE <= sl_rx0_slide;
-- GTXE TX IF ---------------------------------------------------------------------
o_mgt_tx_p <= o_mgt.tx.TXP;
o_mgt_tx_n <= o_mgt.tx.TXN;
-- txoutclk_bufg0_i : BUFG
-- port map (
-- I => o_mgt.tx.TXOUTCLK,
-- O => sl_txoutclk
-- );
i_mgt.tx.TXRESET <= not mmcm_LOCKED;
i_mgt.tx.TXBYPASS8B10B <= X"0";
i_mgt.tx.TXCHARDISPMODE <= X"0";
i_mgt.tx.TXCHARDISPVAL <= X"0";
i_mgt.tx.TXUSRCLK <= sl_rxrecclk;
i_mgt.tx.TXUSRCLK2 <= sl_rxrecclk;
i_mgt.tx.TXDIFFCTRL <= "0110";
i_mgt.tx.TXPOSTEMPHASIS <= "00000";
i_mgt.tx.TXPREEMPHASIS <= "0000";
end RTL;

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<com.sigasi.hdt.shared.librarymapping.model:LibraryMappings xmlns:com.sigasi.hdt.shared.librarymapping.model="com.sigasi.hdt.vhdl.scoping.librarymapping" Version="2">
<Mappings Location="Common Libraries/IEEE" Library="ieee"/>
<Mappings Location="Common Libraries/IEEE Synopsys" Library="ieee"/>
<Mappings Location="Common Libraries" Library="not mapped"/>
<Mappings Location="Common Libraries/unisim/primitive" Library="not mapped"/>
<Mappings Location="Common Libraries/unisim/secureip" Library="not mapped"/>
<Mappings Location="Common Libraries/STD" Library="std"/>
<Mappings Location="Common Libraries/tosca2" Library="tosca2"/>
<Mappings Location="Common Libraries/unisim" Library="unisim"/>
<Mappings Location="Common Libraries/uvvm_util" Library="uvvm_util"/>
<Mappings Location="" Library="work"/>
<Mappings Location="Common Libraries/psi_common" Library="work"/>
</com.sigasi.hdt.shared.librarymapping.model:LibraryMappings>

75
sigasi/.project Normal file
View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>evr320</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.sigasi.hdt.vhdl.ui.vhdlNature</nature>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>
<linkedResources>
<link>
<name>Common Libraries</name>
<type>2</type>
<locationURI>virtual:/virtual</locationURI>
</link>
<link>
<name>hdl</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/hdl</locationURI>
</link>
<link>
<name>tb</name>
<type>2</type>
<locationURI>PARENT-1-PROJECT_LOC/tb</locationURI>
</link>
<link>
<name>Common Libraries/DRAG_REUSABLE_LIBRARIES_HERE.txt</name>
<type>1</type>
<locationURI>sigasiresource:/vhdl/readme.txt</locationURI>
</link>
<link>
<name>Common Libraries/IEEE</name>
<type>2</type>
<locationURI>sigasiresource:/vhdl/2008/IEEE</locationURI>
</link>
<link>
<name>Common Libraries/IEEE Synopsys</name>
<type>2</type>
<locationURI>sigasiresource:/vhdl/2008/IEEE%20Synopsys</locationURI>
</link>
<link>
<name>Common Libraries/STD</name>
<type>2</type>
<locationURI>sigasiresource:/vhdl/2008/STD</locationURI>
</link>
<link>
<name>Common Libraries/psi_common</name>
<type>2</type>
<locationURI>PARENT-2-PROJECT_LOC/psi_common</locationURI>
</link>
<link>
<name>Common Libraries/tosca2</name>
<type>2</type>
<locationURI>PARENT-4-PROJECT_LOC/BoardSupport/ifc1210/tosca2</locationURI>
</link>
<link>
<name>Common Libraries/unisim</name>
<type>2</type>
<locationURI>SIGASI_TOOLCHAIN_XILINX_ISE/vhdl/src/unisims</locationURI>
</link>
<link>
<name>Common Libraries/uvvm_util</name>
<type>2</type>
<locationURI>PARENT-2-PROJECT_LOC/UVVM/uvvm_util</locationURI>
</link>
</linkedResources>
</projectDescription>

View File

@@ -0,0 +1 @@
<project>=2008

View File

@@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//Common\ Libraries/IEEE=utf-8
encoding//Common\ Libraries/IEEE\ Synopsys=utf-8
encoding//Common\ Libraries/STD=utf-8
encoding/Common\ Libraries=utf-8

22
sim/.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
# ignore ModelSim generated files and directories (temp files and so on)
[_@]*
*.txt
*.mti
*.dat
*.dbs
*.psm
*.bak
*.cmp
*.jpg
*.html
*.bsf
wlf*
*.wlf
*.vstf
*.ucdb
cov*/
Transcript*
transcript*
sc_dpiheader.h
vsim.dbg

View File

@@ -1,2 +1,2 @@
source run.tcl
quit
quit

View File

@@ -1,34 +1,83 @@
#Constants
set LibPath "../../.."
#Import psi::sim library
namespace import psi::sim::*
#Set library
add_library evr320
#suppress messages
compile_suppress 135,1236
run_suppress 8684,3479,3813,8009,3812
#Set library path relative to this config file
variable fileLoc [file normalize [file dirname [info script]]]
variable LibPath $fileLoc/../../../..
# EVR320 Library
add_sources $LibPath/VHDL/evr320/hdl {
# tosca2_glb_pkg dependency
add_library tosca2
add_sources $LibPath/BoardSupport/IFC1210/tosca2/hdl/top_ip/src {
tosca2_glb_pkg.vhd \
} -version 2002
add_sources $LibPath/BoardSupport/IFC1210/tosca2/testbench/utilities {
ifc1210_simu_mapping_xuser_pkg.vhd \
ifc1210_simu_procedures_pkg.vhd \
}
#Set library
add_library evr320
# psi_common dependency:
add_sources $LibPath/Firmware/VHDL/psi_common/hdl {
psi_common_array_pkg.vhd \
psi_common_math_pkg.vhd \
psi_common_logic_pkg.vhd \
psi_common_sdp_ram.vhd \
psi_common_pulse_cc.vhd \
psi_common_async_fifo.vhd \
psi_common_clk_meas.vhd \
psi_common_pulse_shaper_cfg.vhd \
psi_common_delay_cfg.vhd \
psi_common_simple_cc.vhd \
psi_common_status_cc.vhd \
} -tag psi_common
# EVR320 Decoder
add_sources $LibPath/Firmware/VHDL/evr320/hdl {
evr320_pkg.vhd \
evr320_buffer.vhd \
evr320_dpram.vhd \
evr320_timestamp.vhd \
evr320_decoder.vhd \
} -tag lib
evr320_data_filter.vhd \
} -tag evr320_decoder
# Lib tosca2 dependecies
add_sources $LibPath/BoardSupport/IFC1210/tosca2/hdl/top_ip/src/ {
tosca2_glb_pkg.vhd \
} -tag tosca2
# Lib ifc1210
add_sources $LibPath/VHDL/evr320/hdl {
pkg_v6vlx_gtxe1.vhd \
# IFC1210 Bindings
add_sources $LibPath/Firmware/VHDL/evr320/hdl {
v6vlx_gtxe1_pkg.vhd \
v6vlx_gtxe1_101MHz27_1Gbps0127.vhd \
v6vlx_gtxe1_142MHz8_2Gbps856.vhd \
v6vlx_gtxe1_sync.vhd \
v6vlx_gtxe1_wrapper.vhd \
evr320_tmem.vhd \
evr320_ifc1210_wrapper.vhd \
} -tag ifc1210
} -tag evr320_ifc1210
# EVR320 Decoder Testbench
add_sources $LibPath/Firmware/VHDL/evr320/tb {
evr320_decoder_tb.vhd \
} -tag evr320_tb
# EVR320 IFC1210 Wrapper Testbench
#add_sources $LibPath/Firmware/VHDL/evr320/tb {
# evr320_ifc1210_wrapper_tb.vhd \
#} -tag evr320_ifc1210_wrapper_tb
# setup tb runs
create_tb_run "evr320_decoder_tb"
tb_run_add_arguments \
"-gg_EVENT_NR_0=16#0F# -gg_EVENT_NR_1=0 -gg_EVENT_NR_2=0 -gg_EVENT_NR_3=0 -gg_EVENT_NR_SOS=0" \
"-gg_EVENT_NR_0=2 -gg_EVENT_NR_1=4 -gg_EVENT_NR_2=0 -gg_EVENT_NR_3=3 -gg_EVENT_NR_SOS=0" \
"-gg_EVENT_NR_0=0 -gg_EVENT_NR_1=0 -gg_EVENT_NR_2=5 -gg_EVENT_NR_3=0 -gg_EVENT_NR_SOS=6"
add_tb_run
create_tb_run "evr320_ifc1210_wrapper_tb"
add_tb_run

View File

@@ -1,5 +1,16 @@
#Load dependencies
source ../../../TCL/PsiSim/PsiSim.tcl
# Library Path
set LibPath "../../../.."
# Configure UVVM -> until compile when not existing
set uvvm_path $LibPath/Firmware/VHDL/UVVM/uvvm_util
if {[file isdirectory uvvm_util]} {
puts "UVVM directory evr320/sim/uvvm_util is present --> not compiled again!"
} else {
do $uvvm_path/script/compile_src.do $uvvm_path
}
#Load dependencies TODO
source $LibPath/Firmware/TCL/PsiSim/PsiSim.tcl
#Import psi::sim library
namespace import psi::sim::*
@@ -10,15 +21,20 @@ init
#Configure
source ./config.tcl
#Run Simulation
# Run Simulation
puts "------------------------------"
puts "-- Compile EVR320 Core"
puts "-- Compile"
puts "------------------------------"
compile_files -tag lib -clean
#puts "------------------------------"
#puts "-- Compile TOSCA2 Bindings"
#puts "------------------------------"
#compile_files -tag tosca2
#compile_files -tag ifc1210
clean_libraries -all
compile_files -tag psi_common
compile_files -lib tosca2
compile_files -tag evr320_decoder
compile_files -tag evr320_ifc1210
#compile_files -tag evr320_decoder_tb
compile_files -tag evr320_tb
#compile_files -lib evr320
run_check_errors "###ERROR###"
#run_tb -all
run_tb -name evr320_decoder_tb
run_tb -name evr320_ifc1210_wrapper_tb
run_check_errors "###ERROR###"

290
tb/adaptations_pkg.vhd Normal file
View File

@@ -0,0 +1,290 @@
--========================================================================================================================
-- Copyright (c) 2017 by Bitvis AS. All rights reserved.
-- You should have received a copy of the license file containing the MIT License (see LICENSE.TXT), if not,
-- contact Bitvis AS <support@bitvis.no>.
--
-- UVVM AND ANY PART THEREOF ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-- WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
-- OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH UVVM OR THE USE OR OTHER DEALINGS IN UVVM.
--========================================================================================================================
------------------------------------------------------------------------------------------
-- Description : See library quick reference (under 'doc') and README-file(s)
------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;
use work.types_pkg.all;
package adaptations_pkg is
constant C_ALERT_FILE_NAME : string := "_Alert.txt";
constant C_LOG_FILE_NAME : string := "_Log.txt";
constant C_SHOW_UVVM_UTILITY_LIBRARY_INFO : boolean := false; -- Set this to false when you no longer need the initial info
constant C_SHOW_UVVM_UTILITY_LIBRARY_RELEASE_INFO : boolean := false; -- Set this to false when you no longer need the release info
-------------------------------------------------------------------------------
-- Log format
-------------------------------------------------------------------------------
--UVVM: [<ID>] <time> <Scope> Msg
--PPPPPPPPIIIIII TTTTTTTT SSSSSSSSSSSSSS MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
constant C_LOG_PREFIX : string := "UVVM: "; -- Note: ': ' is recommended as final characters
constant C_LOG_PREFIX_WIDTH : natural := C_LOG_PREFIX'length;
constant C_LOG_MSG_ID_WIDTH : natural := 18;
constant C_LOG_TIME_WIDTH : natural := 14; -- 3 chars used for unit eg. " ns"
constant C_LOG_TIME_BASE : time := ns; -- Unit in which time is shown in log (ns | ps)
constant C_LOG_TIME_DECIMALS : natural := 1; -- Decimals to show for given C_LOG_TIME_BASE
constant C_LOG_SCOPE_WIDTH : natural := 16;
constant C_LOG_LINE_WIDTH : natural := 200;
constant C_LOG_INFO_WIDTH : natural := C_LOG_LINE_WIDTH - C_LOG_PREFIX_WIDTH;
constant C_USE_BACKSLASH_N_AS_LF : boolean := true; -- If true interprets '\n' as Line feed
constant C_USE_BACKSLASH_R_AS_LF : boolean := true; -- If true, inserts an empty line if '\r'
-- is the first character of the string.
-- All others '\r' will be printed as is.
constant C_SINGLE_LINE_ALERT : boolean := false; -- If true prints alerts on a single line.
constant C_SINGLE_LINE_LOG : boolean := false; -- If true prints log messages on a single line.
constant C_TB_SCOPE_DEFAULT : string := "TB_SCOPE"; -- Default scope in test sequencer
constant C_LOG_TIME_TRUNC_WARNING : boolean := false; -- Yields a single TB_WARNING if time stamp truncated. Otherwise none
constant C_SHOW_LOG_ID : boolean := true; -- This constant has replaced the global_show_log_id
constant C_SHOW_LOG_SCOPE : boolean := true; -- This constant has replaced the global_show_log_scope
constant C_WARNING_ON_LOG_ALERT_FILE_RUNTIME_RENAME : boolean := false;
constant C_USE_STD_STOP_ON_ALERT_STOP_LIMIT : boolean := true; -- true: break using std.env.stop, false: break using failure
shared variable shared_default_log_destination : t_log_destination := CONSOLE_AND_LOG;
-------------------------------------------------------------------------------
-- Verbosity control
-- NOTE: Do not enter new IDs without proper evaluation:
-- 1. Is it - or could it be covered by an existing ID
-- 2. Could it be combined with other needs for a more general new ID
-- Feel free to suggest new ID for future versions of UVVM Utility Library (support@bitvis.no)
-------------------------------------------------------------------------------
type t_msg_id is (
-- Bitvis utility methods
NO_ID, -- Used as default prior to setting actual ID when transfering ID as a field in a record
ID_UTIL_BURIED, -- Used for buried log messages where msg and scope cannot be modified from outside
ID_BITVIS_DEBUG, -- Bitvis internal ID used for UVVM debugging
ID_UTIL_SETUP, -- Used for Utility setup
ID_LOG_MSG_CTRL, -- Used inside Utility library only - when enabling/disabling msg IDs.
ID_ALERT_CTRL, -- Used inside Utility library only - when setting IGNORE or REGARD on various alerts.
ID_NEVER, -- Used for avoiding log entry. Cannot be enabled.
ID_FINISH_OR_STOP, -- Used when terminating the complete simulation - independent of why
ID_CLOCK_GEN, -- Used for logging when clock generators are enabled or disabled
ID_GEN_PULSE, -- Used for logging when a gen_pulse procedure starts pulsing a signal
ID_BLOCKING, -- Used for logging when using synchronisation flags
-- General
ID_POS_ACK, -- To write a positive acknowledge on a check
-- Directly inside test sequencers
ID_LOG_HDR, -- ONLY allowed in test sequencer, Log section headers
ID_LOG_HDR_LARGE, -- ONLY allowed in test sequencer, Large log section headers
ID_LOG_HDR_XL, -- ONLY allowed in test sequencer, Extra large log section headers
ID_SEQUENCER, -- ONLY allowed in test sequencer, Normal log (not log headers)
ID_SEQUENCER_SUB, -- ONLY allowed in test sequencer, Subprograms defined in sequencer
-- BFMs
ID_BFM, -- Used inside a BFM (to log BFM access)
ID_BFM_WAIT, -- Used inside a BFM to indicate that it is waiting for something (e.g. for ready)
ID_BFM_POLL, -- Used inside a BFM when polling until reading a given value. I.e. to show all reads until expected value found (e.g. for sbi_poll_until())
ID_BFM_POLL_SUMMARY, -- Used inside a BFM when showing the summary of data that has been received while waiting for expected data.
ID_TERMINATE_CMD, -- Typically used inside a loop in a procedure to end the loop (e.g. for sbi_poll_until() or any looped generation of random stimuli
-- Packet related data Ids with three levels of granularity, for differentiating between frames, packets and segments.
-- Segment Ids, finest granularity of packet data
ID_SEGMENT_INITIATE, -- Notify that a packet is about to be transmitted or received
ID_SEGMENT_COMPLETE, -- Notify that a packet has been transmitted or received
ID_SEGMENT_HDR, -- AS ID_SEGMENT_COMPLETE, but also writes header info
ID_SEGMENT_DATA, -- AS ID_SEGMENT_COMPLETE, but also writes packet data (could be huge)
-- Packet Ids, medium granularity of packet data
ID_PACKET_INITIATE, -- Notify that a packet is about to be transmitted or received
ID_PACKET_COMPLETE, -- Notify that a packet has been transmitted or received
ID_PACKET_HDR, -- AS ID_PACKET_COMPLETED, but also writes header info
ID_PACKET_DATA, -- AS ID_PACKET_COMPLETED, but also writes packet data (could be huge)
-- Frame Ids, roughest granularity of packet data
ID_FRAME_INITIATE, -- Notify that a packet is about to be transmitted or received
ID_FRAME_COMPLETE, -- Notify that a packet has been transmitted or received
ID_FRAME_HDR, -- AS ID_FRAME_COMPLETE, but also writes header info
ID_FRAME_DATA, -- AS ID_FRAME_COMPLETE, but also writes packet data (could be huge)
-- OSVVM Ids
ID_COVERAGE_MAKEBIN, -- Log messages from MakeBin (IllegalBin/GenBin/IgnoreBin)
ID_COVERAGE_ADDBIN, -- Log messages from AddBin/AddCross
ID_COVERAGE_ICOVER, -- ICover logging, NB: Very low level debugging. Can result in large amount of data.
ID_COVERAGE_CONFIG, -- Logging of configuration in the coverage package
ID_COVERAGE_SUMMARY, -- Report logging : Summary of coverage, with both covered bins and holes
ID_COVERAGE_HOLES, -- Report logging : Holes only
-- Distributed command systems
ID_UVVM_SEND_CMD,
ID_UVVM_CMD_ACK,
ID_UVVM_CMD_RESULT,
ID_CMD_INTERPRETER, -- Message from VVC interpreter about correctly received and queued/issued command
ID_CMD_INTERPRETER_WAIT, -- Message from VVC interpreter that it is actively waiting for a command
ID_IMMEDIATE_CMD, -- Message from VVC interpreter that an IMMEDIATE command has been executed
ID_IMMEDIATE_CMD_WAIT, -- Message from VVC interpreter that an IMMEDIATE command is waiting for command to complete
ID_CMD_EXECUTOR, -- Message from VVC executor about correctly received command - prior to actual execution
ID_CMD_EXECUTOR_WAIT, -- Message from VVC executor that it is actively waiting for a command
ID_INSERTED_DELAY, -- Message from VVC executor that it is waiting a given delay
-- Distributed data
ID_UVVM_DATA_QUEUE, -- Information about UVVM data FIFO/stack (initialization, put, get, etc)
-- VVC system
ID_CONSTRUCTOR, -- Constructor message from VVCs (or other components/process when needed)
ID_CONSTRUCTOR_SUB, -- Constructor message for lower level constructor messages (like Queue-information and other limitations)
-- SB package
ID_DATA,
ID_CTRL,
-- Special purpose - Not really IDs
ALL_MESSAGES -- Applies to ALL message ID apart from ID_NEVER
);
type t_msg_id_panel is array (t_msg_id'left to t_msg_id'right) of t_enabled;
constant C_TB_MSG_ID_DEFAULT : t_msg_id := ID_SEQUENCER; -- msg ID used when calling the log method without any msg ID switch.
-- Default message Id panel to be used for all message Id panels, except:
-- - VVC message Id panels, see constant C_VVC_MSG_ID_PANEL_DEFAULT
constant C_MSG_ID_PANEL_DEFAULT : t_msg_id_panel := (
ID_NEVER => DISABLED,
ID_UTIL_BURIED => DISABLED,
ID_BITVIS_DEBUG => DISABLED,
ID_COVERAGE_MAKEBIN => DISABLED,
ID_COVERAGE_ADDBIN => DISABLED,
ID_COVERAGE_ICOVER => DISABLED,
others => ENABLED
);
-- If false, OSVVM uses the default message id panel. If true, it uses a separate message id panel.
constant C_USE_LOCAL_OSVVM_MSG_ID_PANELS : boolean := TRUE;
type t_msg_id_indent is array (t_msg_id'left to t_msg_id'right) of string(1 to 4);
constant C_MSG_ID_INDENT : t_msg_id_indent := (
ID_IMMEDIATE_CMD_WAIT => " ..",
ID_CMD_INTERPRETER => " " & NUL & NUL,
ID_CMD_INTERPRETER_WAIT => " ..",
ID_CMD_EXECUTOR => " " & NUL & NUL,
ID_CMD_EXECUTOR_WAIT => " ..",
ID_UVVM_SEND_CMD => "->" & NUL & NUL,
ID_UVVM_CMD_ACK => " ",
others => "" & NUL & NUL & NUL & NUL
);
constant C_MSG_DELIMITER : character := ''';
-------------------------------------------------------------------------
-- Alert counters
-------------------------------------------------------------------------
-- Default values. These can be overwritten in each sequencer by using
-- set_alert_attention or set_alert_stop_limit (see quick ref).
constant C_DEFAULT_ALERT_ATTENTION : t_alert_attention := (others => REGARD);
-- 0 = Never stop
constant C_DEFAULT_STOP_LIMIT : t_alert_counters := (note to manual_check => 0,
others => 1);
-------------------------------------------------------------------------
-- Hierarchical alerts
-------------------------------------------------------------------------
constant C_ENABLE_HIERARCHICAL_ALERTS : boolean := false;
constant C_BASE_HIERARCHY_LEVEL : string(1 to 5) := "Total";
constant C_EMPTY_NODE : t_hierarchy_node := (" ",
(others => (others => 0)),
(others => 0),
(others => true));
-------------------------------------------------------------------------
-- Deprecate
-------------------------------------------------------------------------
-- These values are used to indicate outdated sub-programs
constant C_DEPRECATE_SETTING : t_deprecate_setting := DEPRECATE_ONCE;
shared variable deprecated_subprogram_list : t_deprecate_list := (others=>(others => ' '));
------------------------------------------------------------------------
-- UVVM VVC Framework adaptations
------------------------------------------------------------------------
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT & "(uvvm)";
signal global_show_msg_for_uvvm_cmd : boolean := true;
constant C_CMD_QUEUE_COUNT_MAX : natural := 20; -- (VVC Command queue) May be overwritten for dedicated VVC
constant C_CMD_QUEUE_COUNT_THRESHOLD_SEVERITY : t_alert_level := WARNING;
constant C_CMD_QUEUE_COUNT_THRESHOLD : natural := 18;
constant C_RESULT_QUEUE_COUNT_MAX : natural := 20; -- (VVC Result queue) May be overwritten for dedicated VVC
constant C_RESULT_QUEUE_COUNT_THRESHOLD_SEVERITY : t_alert_level := WARNING;
constant C_RESULT_QUEUE_COUNT_THRESHOLD : natural := 18;
constant C_MAX_VVC_INSTANCE_NUM : natural := 20;
constant C_MAX_NUM_SEQUENCERS : natural := 10; -- Max number of sequencers
-- Maximum allowed length of VVC names
constant C_MAX_VVC_NAME_LENGTH : positive := 20;
-- Minimum width of vvc name and channel displayed in scope.
-- These combined + the length of instance + 2 (commas), cannot exceed C_LOG_SCOPE_WIDTH.
constant C_MINIMUM_CHANNEL_SCOPE_WIDTH : natural := 10;
constant C_MINIMUM_VVC_NAME_SCOPE_WIDTH : natural := 10;
constant C_TOTAL_NUMBER_OF_BITS_IN_DATA_BUFFER : natural := 2048;
constant C_NUMBER_OF_DATA_BUFFERS : natural := 10;
-- Default message Id panel intended for use in the VVCs
constant C_VVC_MSG_ID_PANEL_DEFAULT : t_msg_id_panel := (
ID_NEVER => DISABLED,
ID_UTIL_BURIED => DISABLED,
others => ENABLED
);
type t_data_source is ( -- May add more types of random ++ later
NA,
FROM_BUFFER,
RANDOM,
RANDOM_TO_BUFFER
);
type t_error_injection is ( -- May add more controlled error injection later
NA,
RANDOM_BIT_ERROR,
RANDOM_DATA_ERROR,
RANDOM_ADDRESS_ERROR
);
constant C_CMD_IDX_PREFIX : string := " [";
constant C_CMD_IDX_SUFFIX : string := "]";
type t_channel is ( -- NOTE: Add more types of channels when needed for a VVC
NA, -- When channel is not relevant
ALL_CHANNELS, -- When command shall be received by all channels
RX,
TX);
constant C_VVCT_ALL_INSTANCES, ALL_INSTANCES : integer := -2;
constant ALL_ENABLED_INSTANCES : integer := -3;
constant C_NUM_SEMAPHORE_LOCK_TRIES : natural := 500;
------------------------------------------------------------------------
-- Scoreboard adaptations
------------------------------------------------------------------------
constant C_MAX_QUEUE_INSTANCE_NUM : positive := 100; -- Maximum number of instances
constant C_SB_TAG_WIDTH : positive := 128; -- Number of characters in SB tag
constant C_SB_SOURCE_WIDTH : positive := 128; -- Number of characters in SB source element
constant C_SB_SLV_WIDTH : positive := 8; -- Width of the SLV in the predefined SLV SB
-- Default message Id panel intended for use in SB
constant C_SB_MSG_ID_PANEL_DEFAULT : t_msg_id_panel := (
ID_CTRL => ENABLED,
ID_DATA => DISABLED,
others => DISABLED
);
end package adaptations_pkg;
package body adaptations_pkg is
end package body adaptations_pkg;

585
tb/evr320_decoder_tb.vhd Normal file
View File

@@ -0,0 +1,585 @@
--------------------------------------------------------------------------------
-- Paul Scherrer Institute (PSI)
--------------------------------------------------------------------------------
-- Unit : evr320_decoder_tb.vhd
-- Author : Goran Marinkovic, Section Diagnostic, Jonas Purtschert
-- Version : $Revision: 1.1 $
--------------------------------------------------------------------------------
-- Copyright© PSI, Section Diagnostic
--------------------------------------------------------------------------------
-- Comment : This is the test bench for the evr component.
--------------------------------------------------------------------------------
-- Std. library (platform) -----------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_1164.all;
library std;
use std.env.all;
use std.textio.all;
library uvvm_util;
context uvvm_util.uvvm_util_context;
-- Work library (application) --------------------------------------------------
library work;
use work.evr320_pkg.all;
entity evr320_decoder_tb is
generic (
g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#
);
end entity;
architecture testbench of evr320_decoder_tb is
---------------------------------------------------------------------------
-- System
---------------------------------------------------------------------------
constant C_RXUSRCLK_CYCLE : time:= 7 ns;
constant C_USRCLK_CYCLE : time:= 8 ns;
constant C_EVT_NR : integer := 4;
constant C_MEM_DATA_WIDTH : integer := 32; -- 32|64 (64 bit used for tosca2 on ifc1210)
constant C_EVENT_RECORDER : boolean := true;
constant C_EVENT_REC_FLAGS : std_logic_vector(11 downto 6) := B"1101_11";
---------------------------------------------------------------------------
-- MGT stream
---------------------------------------------------------------------------
type mgt_stream_sample_type is record
data : std_logic_vector(7 downto 0);
data_k : std_logic_vector(0 downto 0);
event : std_logic_vector(7 downto 0);
event_k : std_logic_vector(0 downto 0);
end record mgt_stream_sample_type;
type mgt_stream_type is array (natural range <>) of mgt_stream_sample_type;
signal mgt_stream_index : integer range 0 to 511 := 0;
signal mgt_stream : mgt_stream_type(511 downto 0) := (others=>(others=>(others=>'0')));
-----------------------------------------------------------------------------
-- Timing decoder interface
-----------------------------------------------------------------------------
-- Link status
signal rxlos : std_logic := '0';
-- Clock
signal rxusrclk : std_logic := '0';
-- Data
signal rxdata : std_logic_vector(15 downto 0) := (others => '0');
-- Status 8B/10B decoder
signal rxcharisk : std_logic_vector( 1 downto 0) := (others => '0');
signal usr_clk : std_logic := '0';
signal evr_params : typ_evr320_params;
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
signal mem_data : std_logic_vector(C_MEM_DATA_WIDTH-1 downto 0) := (others => '0');
-- Decoder stream
type dec_stream_type is record
data : std_logic_vector(7 downto 0);
addr : std_logic_vector(10 downto 0);
end record dec_stream_type;
type dec_stream_check_arr is array (natural range <>) of dec_stream_type;
signal dec_stream_data : std_logic_vector(7 downto 0) := (others => '0');
signal dec_stream_addr : std_logic_vector(10 downto 0) := (others => '0');
signal dec_stream_valid : std_logic;
signal dec_stream_check : dec_stream_check_arr(0 to 2047);
signal dec_stream_recv_bytes : integer range 0 to 2047;
type segment_data_arr is array (natural range <>) of std_logic_vector(7 downto 0);
signal segment_addr : std_logic_vector(7 downto 0);
signal segment_data : segment_data_arr(0 to 2047);
signal segment_length : natural range 0 to 2047;
constant FILTER_ADDRESS : std_logic_vector(11 downto 0) := x"028";
constant FILTER_NUM_BYTES : integer := 8;
constant STIMULI_RUNS : integer := 2;
signal filter_data, filter_data_check : std_logic_vector(63 downto 0) := (others => '0');
signal filter_valid : std_logic := '0';
-- Events
signal usr_events : std_logic_vector( 3 downto 0) := (others => '0');
signal sos_event : std_logic := '0';
type typ_arrint is array (natural range <>) of integer;
signal received_events : typ_arrint(0 to C_EVT_NR-1) := (others => 0);
signal expect_events : typ_arrint(0 to C_EVT_NR-1) := (others => 0);
signal expect_events_total : integer := 0;
-- Event Recorder
signal event_recorder_status : typ_evt_rec_status;
signal event_recorder_ctrl : typ_evt_rec_ctrl := c_INIT_EVT_REC_CTRL;
signal check_evt_rec_events : std_logic := '0';
signal all_expected_events : std_logic_vector(255 downto 0) := (others => '0');
signal expected_user_events : integer range 0 to 255 := 0;
begin
-----------------------------------------------------------------------------
-- Timing decoder
-----------------------------------------------------------------------------
evr320_decoder_inst: entity work.evr320_decoder
generic map
(
EVENT_RECORDER => C_EVENT_RECORDER,
MEM_DATA_WIDTH => C_MEM_DATA_WIDTH
)
port map
(
--------------------------------------------------------------------------
-- Debug interface
--------------------------------------------------------------------------
debug_clk => open,
debug => open,
--------------------------------------------------------------------------
-- GTX parallel interface
--------------------------------------------------------------------------
i_mgt_rst => rxlos,
i_mgt_rx_clk => rxusrclk,
i_mgt_rx_data => rxdata,
i_mgt_rx_charisk => rxcharisk,
--------------------------------------------------------------------------
-- User interface CPU clock
--------------------------------------------------------------------------
i_usr_clk => usr_clk,
i_evr_params => evr_params,
o_event_recorder_stat => event_recorder_status,
i_event_recorder_ctrl => event_recorder_ctrl,
i_mem_addr => mem_addr,
o_mem_data => mem_data,
--------------------------------------------------------------------------
-- User stream interface User clock
--------------------------------------------------------------------------
i_stream_clk => usr_clk,
o_stream_data => dec_stream_data,
o_stream_addr => dec_stream_addr,
o_stream_valid => dec_stream_valid,
--------------------------------------------------------------------------
-- User interface MGT clock
--------------------------------------------------------------------------
o_usr_events => usr_events,
o_usr_events_ext => open,
o_sos_event => sos_event,
o_event => open,
o_event_valid => open
);
evr320_data_filter_inst: entity work.evr320_data_filter
generic map (
SWAP => true, -- non-swapped uses LE layout; our check below converts to BE
NUM_BYTES => 8
)
port map (
i_stream_clk => usr_clk,
i_stream_data => dec_stream_data,
i_stream_addr => dec_stream_addr,
i_stream_valid => dec_stream_valid,
i_address => FILTER_ADDRESS,
o_data => filter_data,
o_valid => filter_valid
);
-----------------------------------------------------------------------------
-- MGT / User clock
-----------------------------------------------------------------------------
clock_generator(rxusrclk, C_RXUSRCLK_CYCLE);
clock_generator(usr_clk, C_USRCLK_CYCLE);
-----------------------------------------------------------------------------
-- Decoder reset due to MGT main status
-----------------------------------------------------------------------------
process
begin
rxlos <= '1';
wait for 50 ns;
wait until (falling_edge(rxusrclk));
rxlos <= '0';
wait ;
end process;
-----------------------------------------------------------------------------
-- Read stimuli file
-----------------------------------------------------------------------------
file_blk : block
file file_stimuli : text;
type parse_fsm_state is (idle, seg_start, seg_addr, seg_Wait, seg_payload, seg_payload_wait, seg_done);
begin
process
variable file_line : line;
variable data, event : std_logic_vector(7 downto 0);
variable data_k, event_k : std_logic_vector(0 downto 0);
variable space : character;
variable i : integer;
variable parse_fsm : parse_fsm_state := idle;
variable payload_cnt : integer range 0 to 2047;
variable event_cnt_total : integer := 0;
variable event_cnt_0 : integer := 0;
variable event_cnt_1 : integer := 0;
variable event_cnt_2 : integer := 0;
variable event_cnt_3 : integer := 0;
variable event_cnt_user : integer := 0;
begin
file_open(file_stimuli, "../tb/stimuli_mgt.dat", read_mode);
readline(file_stimuli, file_line); -- comment
readline(file_stimuli, file_line); -- comment
i := 0;
-- read line by line from .dat file:
while not endfile(file_stimuli) loop
readline(file_stimuli, file_line);
hread(file_line, event);
read(file_line, event_k);
read(file_line, space);
read(file_line, space);
hread(file_line, data);
read(file_line, space);
read(file_line, data_k);
-- write to array:
mgt_stream(i).data <= data;
mgt_stream(i).data_k <= data_k;
mgt_stream(i).event <= event;
mgt_stream(i).event_k <= event_k;
mgt_stream_index <= i;
--debug output:
--log(ID_SEGMENT_DATA, "stimuli file: i=" & integer'image(i) & " event=0x" & to_string(event, HEX) & " k=" & to_string(event_k, HEX)
-- & " data=0x" & to_string(data, HEX) & " k=" & to_string(data_k, HEX) & " ");
-- Count Events:
----------------
if (event /= x"00" and event_k = "0") then
event_cnt_total := event_cnt_total + 1;
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_0, 8))) then
event_cnt_0 := event_cnt_0 + 1;
end if;
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_1, 8))) then
event_cnt_1 := event_cnt_1 + 1;
end if;
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_2, 8))) then
event_cnt_2 := event_cnt_2 + 1;
end if;
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_3, 8))) then
event_cnt_3 := event_cnt_3 + 1;
end if;
end if;
expect_events_total <= event_cnt_total * STIMULI_RUNS;
expect_events(0) <= event_cnt_0 * STIMULI_RUNS;
expect_events(1) <= event_cnt_1 * STIMULI_RUNS;
expect_events(2) <= event_cnt_2 * STIMULI_RUNS;
expect_events(3) <= event_cnt_3 * STIMULI_RUNS;
-- Event Recorder:
------------------
if (event_k = "0") then
all_expected_events(to_integer(unsigned(event))) <= '1';
if (event = std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8))) then
log("Start-of-Sequence Event in Stimuli present");
end if;
if (event /= X"00" and event(7 downto 4) /= X"7") then
event_cnt_user := event_cnt_user + 1;
end if;
end if;
expected_user_events <= event_cnt_user;
-- Parse only segment:
----------------------
case (parse_fsm) is
when idle =>
if (data = x"5C" and data_k = "1") then -- check if frame start
parse_fsm := seg_start;
end if;
when seg_start =>
parse_fsm := seg_addr;
when seg_addr =>
segment_addr <= data;
parse_fsm := seg_wait;
when seg_wait =>
parse_fsm := seg_payload;
payload_cnt := 0;
when seg_payload =>
if (data = x"3C" and data_k = "1") then -- check if frame end
parse_fsm := seg_done;
else
segment_data(payload_cnt) <= data;
parse_fsm := seg_payload_wait;
segment_length <= payload_cnt+1;
end if;
when seg_payload_wait =>
payload_cnt := payload_cnt + 1;
parse_fsm := seg_payload;
when seg_done =>
-- done
end case;
i := i + 1;
end loop;
file_close(file_stimuli);
wait;
end process;
end block;
---------------------------------------------------------
-- Receive decoder data stream
---------------------------------------------------------
process
variable addr : std_logic_vector(10 downto 0);
variable data : std_logic_vector(7 downto 0);
variable i : integer := 0;
begin
wait until rising_edge(usr_clk);
if (dec_stream_valid = '1') then
addr := dec_stream_addr;
data := dec_stream_data;
i := to_integer(unsigned(addr)) - to_integer(unsigned(segment_addr))*16;
-- save stream for later comparision:
dec_stream_check(i).addr <= addr;
dec_stream_check(i).data <= data;
log(ID_SEGMENT_DATA, "Recv Decoder Stream: count=" & integer'image(i) & " addr=0x" & to_string(addr, HEX) & " data=0x" & to_string(data, HEX));
i := i + 1;
dec_stream_recv_bytes <= i;
end if;
end process;
---------------------------------------------------------
-- Fetch filter data
---------------------------------------------------------
process
begin
wait until rising_edge(usr_clk);
if (filter_valid = '1') then
filter_data_check <= filter_data;
log(ID_SEGMENT_DATA, "Filter Valid: data=" & to_string(filter_data, HEX, AS_IS, INCL_RADIX));
end if;
end process;
---------------------------------------------------------
-- Wait for User Events
---------------------------------------------------------
process
begin
wait until rising_edge(rxusrclk);
for i in 0 to C_EVT_NR-1 loop
if (usr_events(i) = '1') then
log(ID_CTRL, "Event Received: " & to_string(evr_params.event_numbers(i), HEX, AS_IS, INCL_RADIX) );
received_events(i) <= received_events(i) + 1;
end if;
end loop;
end process;
---------------------------------------------------------
-- Wait for Start of Sequence Event
---------------------------------------------------------
process
begin
wait until rising_edge(rxusrclk);
if (sos_event = '1') then
log(ID_CTRL, "Start of Sequence Event Received: "& to_string(std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8)), HEX, AS_IS, INCL_RADIX) ); -- change to await_value
check_evt_rec_events <= '1';
end if;
end process;
-----------------------------------------------------------------------------
-- Stimulus CPU interface
-----------------------------------------------------------------------------
process
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
constant c_TB_NAME : string := "evr320_decoder_tb";
variable mgt_stream_rep_var : integer := 0;
variable mgt_stream_index_var : integer := 0;
variable i : integer := 0;
type state is (idle, payload, frame_end, segment_nr);
variable mem_base : integer range 0 to 127;
variable segment_data_word : std_logic_vector(C_MEM_DATA_WIDTH-1 downto 0);
variable var_filter_offset : integer range 0 to 2047;
variable var_filter_word : std_logic_vector(FILTER_NUM_BYTES*8-1 downto 0);
variable expected_evt_rec_events : integer range 0 to 255 := 0;
begin
-- init uvvm:
set_log_file_name(c_TB_NAME & "_LOG.txt");
set_alert_file_name(c_TB_NAME & "_ALERT.txt");
set_alert_stop_limit(ERROR, 0); -- never(0) pause simulator on error
set_alert_stop_limit(TB_ERROR, 0); -- never(0) pause simulator on error
enable_log_msg(ALL_MESSAGES);
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Start Simulation of evr320 decoder", C_SCOPE);
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- Get out of reset, enable events
--------------------------------------------------------------------------
evr_params.event_enable( 0) <= '0' when g_EVENT_NR_0 = 0 else '1';
evr_params.event_enable( 1) <= '0' when g_EVENT_NR_1 = 0 else '1';
evr_params.event_enable( 2) <= '0' when g_EVENT_NR_2 = 0 else '1';
evr_params.event_enable( 3) <= '0' when g_EVENT_NR_3 = 0 else '1';
event_recorder_ctrl.event_enable <= '0' when g_EVENT_NR_SOS = 0 else '1';
evr_params.event_numbers( 0) <= std_logic_vector(to_unsigned(g_EVENT_NR_0, 8));
evr_params.event_numbers( 1) <= std_logic_vector(to_unsigned(g_EVENT_NR_1, 8));
evr_params.event_numbers( 2) <= std_logic_vector(to_unsigned(g_EVENT_NR_2, 8));
evr_params.event_numbers( 3) <= std_logic_vector(to_unsigned(g_EVENT_NR_3, 8));
event_recorder_ctrl.event_number <= std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8));
evr_params.cs_min_cnt <= X"00000000";
evr_params.cs_min_time <= X"00000000";
mem_addr <= x"000";
await_value(rxlos, '0', 0 ns, 10 us, FAILURE, "wait for release RX LOS");
--wait until (rxlos = '0');
--------------------------------------------------------------------------
-- Stimuli MGT
--------------------------------------------------------------------------
wait until rising_edge(rxusrclk);
for b in 0 to STIMULI_RUNS-1 loop
log(ID_LOG_HDR, "Send stimuli stream to MGT - RUN " & to_string(b+1));
for idx in 0 to mgt_stream_index loop
--log(ID_FRAME_DATA, to_string(mgt_stream(idx).data, HEX), to_string(mgt_stream(idx).event, HEX));
wait until rising_edge(rxusrclk);
rxdata <= mgt_stream(idx).data & mgt_stream(idx).event;
rxcharisk <= mgt_stream(idx).data_k & mgt_stream(idx).event_k;
end loop;
end loop;
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Check if decoder stream is correct", C_SCOPE);
--------------------------------------------------------------------------
await_value(dec_stream_recv_bytes, segment_length, 0 ns, 5 us, ERROR, "Wait for right number of bytes streamed");
-- loop through segment and compare frame bytes with received decoder-stream:
for idx in 0 to segment_length-1 loop
check_value(dec_stream_check(idx).data, segment_data(idx), ERROR, "Compare Sent and Received Decoder Stream Data");
end loop;
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Check if filter data is correct", C_SCOPE);
--------------------------------------------------------------------------
var_filter_offset := to_integer(unsigned(FILTER_ADDRESS)) - (to_integer(unsigned(segment_addr))*16);
--log(ID_CTRL, "var_filter_offset=" & integer'image(var_filter_offset) & " : " & to_string(FILTER_ADDRESS,HEX) & " : " & to_string(segment_addr, HEX));
for idx in 0 to FILTER_NUM_BYTES-1 loop
var_filter_word := var_filter_word(var_filter_word'high-8 downto 0) & segment_data(var_filter_offset + idx);
end loop;
check_value(filter_data_check, var_filter_word, ERROR, "Check Data Stream Filter "
& "addr=0x" & to_string(FILTER_ADDRESS, HEX)
& " bytes=" & integer'image(FILTER_NUM_BYTES));
--------------------------------------------------------------------------
-- Check if correct number of events has been detected
--------------------------------------------------------------------------
for i in 0 to C_EVT_NR-1 loop
check_value(received_events(i), expect_events(i), ERROR, "Event " & to_string(i) & ": received = " & to_string(received_events(i)) & ", expected = " & to_string(expect_events(i)));
end loop;
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Event Recorder Checks", C_SCOPE);
--------------------------------------------------------------------------
wait for 1 us;
if (C_EVENT_RECORDER) then
if (check_evt_rec_events = '1' and STIMULI_RUNS > 1) then
----------------------------------------------------------------------
log(ID_DATA, "Check expected Event Flags after SOS Event detected");
----------------------------------------------------------------------
wait until rising_edge(usr_clk);
if (C_MEM_DATA_WIDTH = 32) then
for addr in 0 to 63 loop
mem_addr <= C_EVENT_REC_FLAGS & std_logic_vector(to_unsigned(addr, 6));
wait_num_rising_edge_plus_margin(usr_clk, 1, 1 ns);
check_value(mem_data(0), all_expected_events(4*addr), ERROR, "Event " & to_string(4*addr) & " Flag");
check_value(mem_data(8), all_expected_events(4*addr + 1), ERROR, "Event " & to_string(4*addr + 1) & " Flag");
check_value(mem_data(16), all_expected_events(4*addr + 2), ERROR, "Event " & to_string(4*addr + 2) & " Flag");
check_value(mem_data(24), all_expected_events(4*addr + 3), ERROR, "Event " & to_string(4*addr + 3) & " Flag");
wait until rising_edge(usr_clk);
end loop;
elsif (C_MEM_DATA_WIDTH = 64) then
for addr in 0 to 31 loop
mem_addr <= '0' & C_EVENT_REC_FLAGS & std_logic_vector(to_unsigned(addr, 5));
wait_num_rising_edge_plus_margin(usr_clk, 1, 1 ns);
for j in 0 to C_MEM_DATA_WIDTH/8 loop
check_value(mem_data(8*j), all_expected_events(8*addr + j), ERROR, "Event " & to_string(8*addr + j) & " Flag");
end loop;
end loop;
else
error("Unsupported width of C_MEM_DATA_WIDTH");
end if;
-- ----------------------------------------------------------------------
-- log(ID_DATA, "Check Memory block border");
-- ----------------------------------------------------------------------
if (C_MEM_DATA_WIDTH = 32) then
-- read data mux switching made visible with delayed address.
mem_addr <= C_EVENT_REC_FLAGS & "000000";
wait until rising_edge(usr_clk);
wait for C_USRCLK_CYCLE/4;
for addr in 62 to 65 loop
mem_addr <= (C_EVENT_REC_FLAGS & "000000") + std_logic_vector(to_unsigned(addr, 7));
wait until rising_edge(usr_clk);
check_stable(mem_data, C_USRCLK_CYCLE, ERROR, "Read Data stable on Output");
wait for C_USRCLK_CYCLE/4;
if (addr < 64) then
check_value(mem_data(0), all_expected_events(4*addr), ERROR, "Event " & to_string(4*addr) & " Flag");
check_value(mem_data(8), all_expected_events(4*addr + 1), ERROR, "Event " & to_string(4*addr + 1) & " Flag");
check_value(mem_data(16), all_expected_events(4*addr + 2), ERROR, "Event " & to_string(4*addr + 2) & " Flag");
check_value(mem_data(24), all_expected_events(4*addr + 3), ERROR, "Event " & to_string(4*addr + 3) & " Flag");
else
check_value(mem_data, X"0000_0000", ERROR, "After Event Recorder Mem Map");
end if;
end loop;
end if;
----------------------------------------------------------------------
log(ID_DATA, "Check expected Event Recorder User Events");
----------------------------------------------------------------------
check_value(to_integer(unsigned(event_recorder_status.usr_events_counter)), expected_user_events, ERROR, "Total User Events: received = " & to_string(to_integer(unsigned(event_recorder_status.usr_events_counter))) & ", expected = " & to_string(expected_user_events));
end if;
end if;
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Read DPRAM buffer", C_SCOPE);
--------------------------------------------------------------------------
if (C_MEM_DATA_WIDTH = 32) then
wait for 50 * C_USRCLK_CYCLE;
log(ID_DATA, "Read Segment from DPRAM");
-- print 16 words from dpram data buffer:
for offset in 0 to segment_length/4-1 loop
mem_base := to_integer(unsigned(segment_addr));
mem_addr <= std_logic_vector(to_unsigned(4*mem_base + offset , 12));
wait until rising_edge(usr_clk);
wait until rising_edge(usr_clk);
wait until rising_edge(usr_clk);
segment_data_word := segment_data(offset*4+3)
& segment_data(offset*4+2)
& segment_data(offset*4+1)
& segment_data(offset*4);
check_value(mem_data, segment_data_word, ERROR, "Compare DPRAM with Sent Segment");
--log(ID_PACKET_DATA, "Data buffer DPRAM: addr=0x" & to_string(mem_addr, HEX) & " data=0x" & to_string(mem_data, HEX));
end loop;
end if;
--------------------------------------------------------------------------
-- Test Done
--------------------------------------------------------------------------
wait for 1000 ns; -- to allow some time for completion
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
-- ------------------------------------------------------------------------
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
-- ------------------------------------------------------------------------
-- assert error if UVVM mismatch flag is 1 => upstream info for scripts/jenkins
assert shared_uvvm_status.mismatch_on_expected_simulation_errors_or_worse = 0 report "###ERROR### - UVVM Mismatch Errors with Expected Errors -> Check Log for details" severity ERROR;
std.env.stop(0);
wait; -- stop simulation
end process;
end architecture testbench;
--------------------------------------------------------------------------------
-- End of file
--------------------------------------------------------------------------------

View File

@@ -0,0 +1,596 @@
--------------------------------------------------------------------------------
-- ifc1210_wrapper testbench
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_textio.all;
use ieee.std_logic_1164.all;
library std;
use std.env.all;
use std.textio.all;
library tosca2;
use tosca2.ifc1210_simu_procedures_pkg.all;
library uvvm_util;
context uvvm_util.uvvm_util_context;
-- Work library (application) --------------------------------------------------
library work;
use work.evr320_pkg.all;
use work.psi_common_math_pkg.all;
entity evr320_ifc1210_wrapper_tb is
end entity;
architecture testbench of evr320_ifc1210_wrapper_tb is
---------------------------------------------------------------------------
-- System
---------------------------------------------------------------------------
constant C_RXUSRCLK_CYCLE : time := 7 ns;
constant C_USRCLK_CYCLE : time := 8 ns;
constant C_EVT_NR : integer := 4;
constant C_MEM_DATA_WIDTH : integer := 32; -- 32|64 (64 bit used for tosca2 on ifc1210)
constant C_EVENT_RECORDER : boolean := true;
constant C_EVENT_REC_FLAGS : std_logic_vector(11 downto 6) := B"1101_11";
constant g_EVENT_NR_SOS : integer range 0 to 255 := 16#20#;
constant g_EVENT_NR_0 : integer range 0 to 255 := 16#00#;
constant g_EVENT_NR_1 : integer range 0 to 255 := 16#04#;
constant g_EVENT_NR_2 : integer range 0 to 255 := 16#00#;
constant g_EVENT_NR_3 : integer range 0 to 255 := 16#00#;
---------------------------------------------------------------------------
-- MGT stream
---------------------------------------------------------------------------
type mgt_stream_sample_type is record
data : std_logic_vector(7 downto 0);
data_k : std_logic_vector(0 downto 0);
event : std_logic_vector(7 downto 0);
event_k : std_logic_vector(0 downto 0);
end record mgt_stream_sample_type;
type mgt_stream_type is array (natural range <>) of mgt_stream_sample_type;
signal mgt_stream_index : integer range 0 to 511 := 0;
signal mgt_stream : mgt_stream_type(511 downto 0) := (others => (others => (others => '0')));
-----------------------------------------------------------------------------
-- Timing decoder interface
-----------------------------------------------------------------------------
signal usr_clk : std_logic := '0';
signal evr_params : typ_evr320_params;
signal mem_addr : std_logic_vector(11 downto 0) := (others => '0');
signal mem_data : std_logic_vector(31 downto 0) := (others => '0');
-- Decoder stream
type dec_stream_type is record
data : std_logic_vector(7 downto 0);
addr : std_logic_vector(10 downto 0);
end record dec_stream_type;
type dec_stream_check_arr is array (natural range <>) of dec_stream_type;
signal dec_stream_data : std_logic_vector(7 downto 0) := (others => '0');
signal dec_stream_addr : std_logic_vector(10 downto 0) := (others => '0');
signal dec_stream_valid : std_logic;
signal dec_stream_check : dec_stream_check_arr(0 to 2047);
signal dec_stream_recv_bytes : integer range 0 to 2047;
type segment_data_arr is array (natural range <>) of std_logic_vector(7 downto 0);
signal segment_addr : std_logic_vector(7 downto 0);
signal segment_data : segment_data_arr(0 to 2047);
signal segment_length : natural range 0 to 2047;
constant FILTER_ADDRESS : std_logic_vector(11 downto 0) := x"028";
constant FILTER_NUM_BYTES : integer := 8;
constant STIMULI_RUNS : integer := 2;
signal filter_data, filter_data_check : std_logic_vector(63 downto 0) := (others => '0');
signal filter_valid : std_logic := '0';
signal tmem_i : tmem_bus_in_t;
signal tmem_o : tmem_bus_out_t;
signal tmem_clk : std_logic;
signal tmem_rst : std_logic;
signal tmem_data_rd : std_logic_vector(63 downto 0);
signal tick1sec : std_logic;
alias rxlos is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rst : std_logic>>;
alias clk_evr is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.clk_evr : std_logic>>;
alias rxdata is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_data : std_logic_vector(15 downto 0)>>;
alias rxcharisk is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.i_mgt_rx_charisk : std_logic_vector(1 downto 0)>>;
alias sos_event is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_sos_event : std_logic>>;
alias usr_events is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.o_usr_events : std_logic_vector(3 downto 0)>>;
alias evr_stable is <<signal .evr320_ifc1210_wrapper_tb.evr320_ifc1210_wrapper_inst.evr320_decoder_inst.evr_stable : std_logic>>;
--*** stimuli for delay & pulse width ***
signal usr_event_width_sti : typ_arr_width := (to_uslv(2, log2ceil(MaxDuration_c)), --sos set to 2
to_uslv(3, log2ceil(MaxDuration_c)), --0
to_uslv(4, log2ceil(MaxDuration_c)), --1
to_uslv(5, log2ceil(MaxDuration_c)), --2
to_uslv(6, log2ceil(MaxDuration_c)) --3
);
signal usr_event_delay_sti : typ_arr_delay := (to_uslv(2, log2ceil(MaxDelay_c)), --sos set to 2
to_uslv(3, log2ceil(MaxDelay_c)), --0
to_uslv(4, log2ceil(MaxDelay_c)), --1
to_uslv(5, log2ceil(MaxDelay_c)), --2
to_uslv(6, log2ceil(MaxDelay_c)) --3
);
begin
tmem_o.TMEM_BUSY_o <= '0';
tmem_o.TMEM_PIPE_o <= "10";
-----------------------------------------------------------------------------
-- Timing decoder
-----------------------------------------------------------------------------
evr320_ifc1210_wrapper_inst : entity work.evr320_ifc1210_wrapper
generic map(
g_MGT_LOCATION => "GTXE1_X0Y16", -- "GTXE1_X0Y0" to "GTXE1_X0Y11" | "GTXE1_X0Y16" to "GTXE1_X0Y19"
g_FACILITY => "SFEL", -- "HIPA" | "SFEL"
g_EVENT_RECORDER => C_EVENT_RECORDER, -- enable/disable Event Recorder functionality
g_XUSER_CLK_FREQ => 125000000 -- Xuser Clk Frequency in Hz
)
port map(
--------------------------------------------------------------------------
-- Debug interface
--------------------------------------------------------------------------
debug_clk => open,
debug => open,
--------------------------------------------------------------------------
-- TOSCA2 TMEM interface
--------------------------------------------------------------------------
xuser_CLK => tmem_clk,
xuser_RESET => tmem_rst,
xuser_TMEM_ENA => tmem_i.TMEM_ENA_i,
xuser_TMEM_WE => tmem_i.TMEM_WE_i,
xuser_TMEM_ADD => tmem_i.TMEM_ADD_i(13 downto 3),
xuser_TMEM_DATW => tmem_i.TMEM_DATW_i,
xuser_TMEM_DATR => tmem_o.TMEM_DATR_o,
-- ------------------------------------------------------------------------
-- MGT Interface
-- ------------------------------------------------------------------------
mgt_refclk_i => '0',
mgt_sfp_los_i => '0',
mgt_rx_n => '0',
mgt_rx_p => '0',
mgt_tx_n => open,
mgt_tx_p => open,
mgt_status_o => open,
mgt_control_i => (others => '0'),
---------------------------------------------------------------------------
-- User interface MGT clock
---------------------------------------------------------------------------
clk_evr_o => open,
usr_events_o => open,
sos_event_o => open,
usr_events_adj_o => open,
sos_events_adj_o => open,
--------------------------------------------------------------------------
-- Decoder axi stream interface, User clock
--------------------------------------------------------------------------
stream_clk_i => '1',
stream_data_o => open,
stream_addr_o => open,
stream_valid_o => open
);
gen_pulse(tick1sec, '1', usr_clk, 1, "");
-----------------------------------------------------------------------------
-- MGT / User clock
-----------------------------------------------------------------------------
clock_generator(usr_clk, C_USRCLK_CYCLE);
tmem_clk <= usr_clk;
-- Simulate MGT Clock
mgt_clk_proc : process
begin
clk_evr <= force in '0';
loop
wait for C_RXUSRCLK_CYCLE / 2;
clk_evr <= force in not (clk_evr);
end loop;
end process;
-----------------------------------------------------------------------------
-- Decoder reset due to MGT main status
-----------------------------------------------------------------------------
process
begin
rxlos <= force in '1';
tmem_rst <= '1';
wait for 50 ns;
wait until (falling_edge(clk_evr));
rxlos <= force in '0';
tmem_rst <= '0';
wait;
end process;
-----------------------------------------------------------------------------
-- Read stimuli file
-----------------------------------------------------------------------------
file_blk : block
file file_stimuli : text;
type parse_fsm_state is (idle, seg_start, seg_addr, seg_Wait, seg_payload, seg_payload_wait, seg_done);
begin
process
variable file_line : line;
variable data, event : std_logic_vector(7 downto 0);
variable data_k, event_k : std_logic_vector(0 downto 0);
variable space : character;
variable i : integer;
variable parse_fsm : parse_fsm_state := idle;
variable payload_cnt : integer range 0 to 2047;
variable event_cnt_total : integer := 0;
variable event_cnt_0 : integer := 0;
variable event_cnt_1 : integer := 0;
variable event_cnt_2 : integer := 0;
variable event_cnt_3 : integer := 0;
variable event_cnt_user : integer := 0;
begin
file_open(file_stimuli, "../tb/stimuli_mgt.dat", read_mode);
readline(file_stimuli, file_line); -- comment
readline(file_stimuli, file_line); -- comment
i := 0;
-- read line by line from .dat file:
while not endfile(file_stimuli) loop
readline(file_stimuli, file_line);
hread(file_line, event);
read(file_line, event_k);
read(file_line, space);
read(file_line, space);
hread(file_line, data);
read(file_line, space);
read(file_line, data_k);
-- write to array:
mgt_stream(i).data <= data;
mgt_stream(i).data_k <= data_k;
mgt_stream(i).event <= event;
mgt_stream(i).event_k <= event_k;
mgt_stream_index <= i;
--debug output:
--log(ID_SEGMENT_DATA, "stimuli file: i=" & integer'image(i) & " event=0x" & to_string(event, HEX) & " k=" & to_string(event_k, HEX)
-- & " data=0x" & to_string(data, HEX) & " k=" & to_string(data_k, HEX) & " ");
-- Parse only segment:
----------------------
case (parse_fsm) is
when idle =>
if (data = x"5C" and data_k = "1") then -- check if frame start
parse_fsm := seg_start;
end if;
when seg_start =>
parse_fsm := seg_addr;
when seg_addr =>
segment_addr <= data;
parse_fsm := seg_wait;
when seg_wait =>
parse_fsm := seg_payload;
payload_cnt := 0;
when seg_payload =>
if (data = x"3C" and data_k = "1") then -- check if frame end
parse_fsm := seg_done;
else
segment_data(payload_cnt) <= data;
parse_fsm := seg_payload_wait;
segment_length <= payload_cnt + 1;
end if;
when seg_payload_wait =>
payload_cnt := payload_cnt + 1;
parse_fsm := seg_payload;
when seg_done =>
-- done
end case;
i := i + 1;
end loop;
file_close(file_stimuli);
wait;
end process;
end block;
---------------------------------------------------------
-- Wait for Start of Sequence Event
---------------------------------------------------------
process
begin
wait until rising_edge(sos_event);
log(ID_CTRL, "Start of Sequence Event Received: " & to_string(std_logic_vector(to_unsigned(g_EVENT_NR_SOS, 8)), HEX, AS_IS, INCL_RADIX)); -- change to await_value
end process;
--------------------------------------------------------------------------
-- Stimuli MGT
--------------------------------------------------------------------------
process
begin
wait until rising_edge(clk_evr);
for b in 0 to STIMULI_RUNS - 1 loop
log(ID_LOG_HDR, "Send stimuli stream to MGT - RUN " & to_string(b + 1));
for idx in 0 to mgt_stream_index loop
--log(ID_FRAME_DATA, to_string(mgt_stream(idx).data, HEX), to_string(mgt_stream(idx).event, HEX));
wait until rising_edge(clk_evr);
rxdata <= force out mgt_stream(idx).data & mgt_stream(idx).event;
rxcharisk <= force out mgt_stream(idx).data_k & mgt_stream(idx).event_k;
end loop;
wait for 3 us;
end loop;
wait;
end process;
-----------------------------------------------------------------------------
-- Main Process
-----------------------------------------------------------------------------
process
constant C_SCOPE : string := C_TB_SCOPE_DEFAULT;
constant c_TB_NAME : string := "evr320_decoder_tb";
variable latency_cnt_val : unsigned(31 downto 0);
begin
disable_log_msg(ID_GEN_PULSE);
--------------------------------------------------------------------------
log(ID_LOG_HDR, "Start Simulation of evr320 decoder", C_SCOPE);
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- Get out of reset, enable events
--------------------------------------------------------------------------
evr_params.event_enable(0) <= '0' when g_EVENT_NR_0 = 0 else '1';
evr_params.event_enable(1) <= '0' when g_EVENT_NR_1 = 0 else '1';
evr_params.event_enable(2) <= '0' when g_EVENT_NR_2 = 0 else '1';
evr_params.event_enable(3) <= '0' when g_EVENT_NR_3 = 0 else '1';
evr_params.event_numbers(0) <= std_logic_vector(to_unsigned(g_EVENT_NR_0, 8));
evr_params.event_numbers(1) <= std_logic_vector(to_unsigned(g_EVENT_NR_1, 8));
evr_params.event_numbers(2) <= std_logic_vector(to_unsigned(g_EVENT_NR_2, 8));
evr_params.event_numbers(3) <= std_logic_vector(to_unsigned(g_EVENT_NR_3, 8));
evr_params.cs_min_cnt <= X"00000000";
evr_params.cs_min_time <= X"00000000";
mem_addr <= x"000";
await_value(rxlos, '0', 0 ns, 10 us, FAILURE, "wait for release RX LOS");
-- overwrite evr_stable flag:
evr_stable <= force '1';
-- enable sos event and set event number:
TMEM_BUS_WRITE(seqid => "A00_001",
tmem_add => x"00_0040",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_2001",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_001",
tmem_add => x"00_0040",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- ---------------------------------------------------------
-- send delay and width parameters:
TMEM_BUS_WRITE(seqid => "A00_002",
tmem_add => x"00_0050",
tmem_we => x"FF",
tmem_burst => 1,
tmem_data_wr => x"0005_0004_0003_0002",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- read back delay parameters:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0050",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
check_value(tmem_data_rd, x"0005_0004_0003_0002", ERROR, "TMEM Write/Read check: EVR Puls delay Event Cfg");
-- ---------------------------------------------------------
-- ---------------------------------------------------------
-- send width and width parameters:
TMEM_BUS_WRITE(seqid => "A00_003",
tmem_add => x"00_0058",
tmem_we => x"FF",
tmem_burst => 1,
tmem_data_wr => x"0009_0008_0007_0006",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- read back delay parameters:
TMEM_BUS_READ(seqid => "A00_003",
tmem_add => x"00_0058",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
check_value(tmem_data_rd, x"0009_0008_0007_0006", ERROR, "TMEM Write/Read check: EVR Puls Width Event Cfg");
-- ---------------------------------------------------------
-- ---------------------------------------------------------
-- send width and width parameters for SOS:
TMEM_BUS_WRITE(seqid => "A00_004",
tmem_add => x"00_0060",
tmem_we => x"FF",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0001_0001",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- read back delay parameters:
TMEM_BUS_READ(seqid => "A00_004",
tmem_add => x"00_0060",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
check_value(tmem_data_rd, x"0000_0000_0001_0001", ERROR, "TMEM Write/Read check: SOS width & delay Event Cfg");
-- ---------------------------------------------------------
-- latency measurement: set event nr:
TMEM_BUS_WRITE(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_0020",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- latency measurement: set event nr:
TMEM_BUS_WRITE(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_we => x"0F",
tmem_burst => 1,
tmem_data_wr => x"0000_0000_0000_0020",
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
-- read back sos event and event number:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
check_value(tmem_data_rd, x"0000_0000_0000_0020", ERROR, "TMEM Write/Read check: lat. meas. event nr");
-- 1. check latency measurement counter:
----------------------------------------
await_value(sos_event, '1', 0 ns, 2 us, ERROR, "wait for sos event");
wait for 2000 ns;
latency_cnt_val := x"00000000";
-- read latency measurement counter without rearm:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0030",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(63 downto 32));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"000000F5", x"000000FE", ERROR, "Latency Counter Value (no-rearm) Check after 2us");
-- 2. read latency measurement counter again with rearm:
--------------------------------------------------------
latency_cnt_val := x"00000000";
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"000000FA", x"00000102", ERROR, "Latency Counter Value (rearm) Check directly after first read");
-- read 2. time rearm latency counter which should be cleared now:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
check_value(latency_cnt_val, x"00000000", ERROR, "Check if counter is cleared");
-- 4. read latency measurement counter with rearm:
--------------------------------------------------
await_value(sos_event, '1', 0 ns, 3 us, ERROR, "wait for sos event");
wait for 1 us;
-- read counter and rearm:
TMEM_BUS_READ(seqid => "A00_002",
tmem_add => x"00_0038",
tmem_burst => 1,
tmem_data_rd => tmem_data_rd,
xuser_clk_i => tmem_clk,
xuser_tmem_bus_o => tmem_i,
xuser_tmem_bus_i => tmem_o);
wait for 20 ns;
latency_cnt_val := unsigned(tmem_data_rd(31 downto 0));
log(ID_CTRL, "Latency Counter: 0x" & to_string(latency_cnt_val, HEX));
check_value_in_range(latency_cnt_val, x"0000007A", x"00000080", ERROR, "Latency Counter Value (rearm) Check after 1us");
--------------------------------------------------------------------------
-- Test Done
--------------------------------------------------------------------------
wait for 1000 ns; -- to allow some time for completion
report_alert_counters(FINAL); -- Report final counters and print conclusion for simulation (Success/Fail)
-- ------------------------------------------------------------------------
log(ID_LOG_HDR, "SIMULATION COMPLETED", C_SCOPE);
-- ------------------------------------------------------------------------
-- assert error if UVVM mismatch flag is 1 => upstream info for scripts/jenkins
assert shared_uvvm_status.mismatch_on_expected_simulation_errors_or_worse = 0 report "###ERROR### - UVVM Mismatch Errors with Expected Errors -> Check Log for details" severity ERROR;
std.env.stop(0);
wait; -- stop simulation
end process;
end architecture testbench;
--------------------------------------------------------------------------------
-- End of file
--------------------------------------------------------------------------------

187
tb/stimuli_mgt.dat Normal file
View File

@@ -0,0 +1,187 @@
# stimuli timing master frame, hex
# event k data k comment
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 5C 1 frame start
00 0 00 0 gap
00 0 02 0 frame byte
BC 1 00 0 align
00 0 DB 0 frame byte
00 0 00 0 gap
00 0 93 0 frame byte
BC 1 00 0 align
00 0 36 0 frame byte
00 0 00 0 gap
00 0 41 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 A3 0 frame byte
00 0 00 0 gap
00 0 1D 0 frame byte
BC 1 00 0 align
00 0 7F 0 frame byte
00 0 00 0 gap
00 0 33 0 frame byte
BC 1 00 0 align
00 0 9B 0 frame byte
00 0 00 0 gap
00 0 F3 0 frame byte
BC 1 00 0 align
00 0 51 0 frame byte
00 0 00 0 gap
00 0 04 0 frame byte
BC 1 00 0 align
00 0 6B 0 frame byte
00 0 00 0 gap
00 0 7C 0 frame byte
BC 1 00 0 align
00 0 16 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 00 0 frame byte
00 0 00 0 gap
00 0 00 0 frame byte
BC 1 00 0 align
00 0 3C 1 frame end
00 0 00 0 gap
00 0 F9 0 check sum MSB
BC 1 00 0 align
00 0 C6 0 check sum LSB
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
04 0 00 0 event 4
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
70 0 00 0 system event
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
0F 0 00 0 BPM event
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
20 0 00 0 event Start-of-Sequence
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
01 0 00 0 event 1
02 0 00 0 event 2
03 0 00 0 event 3
BC 1 00 0 align
04 0 00 0 event 4
05 0 00 0 event 5
06 0 00 0 event 6
BC 1 00 0 align
07 0 00 0 event 7
08 0 00 0 event 8
09 0 00 0 event 9
BC 1 00 0 align
0A 0 00 0 event 10
0B 0 00 0 event 11
0C 0 00 0 event 12
BC 1 00 0 align
32 0 00 0 event 50
33 0 00 0 event 51
34 0 00 0 event 52
BC 1 00 0 align
35 0 00 0 event 53
36 0 00 0 event 54
37 0 00 0 event 55
BC 1 00 0 align
38 0 00 0 event 56
39 0 00 0 event 57
3A 0 00 0 event 58
BC 1 00 0 align
FA 0 00 0 event 250
FB 0 00 0 event 251
FC 0 00 0 event 252
BC 1 00 0 align
FD 0 00 0 event 253
FE 0 00 0 event 254
FF 0 00 0 event 255
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap
BC 1 00 0 align
00 0 00 0 gap
00 0 00 0 gap
00 0 00 0 gap