Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • dg/fofb/com_bpm
1 result
Select Git revision
Show changes
Commits on Source (48)
Showing
with 1857 additions and 4848 deletions
# Ignore generated package file
hdl/pkg_version.vhd
include::doc/main.adoc[]
This diff is collapsed.
This diff is collapsed.
= COMBPM module documentation
// ================================================================================
== Description
This module provides several logic blocks to allow communication with BPM (Beam Position Monitor) electronics.
This has been built for a very precise situation (libera electron, damc-fmc2zup), but the architecture should allow modification and portability.
For now, it only provides RX communication from the DLS CC protocol (ITech libera electron).
The module has been designed for DAMC-FMC2ZUP targets, populated with a 4SFP+ FMC board (CAENels).
// ================================================================================
== Overview
=== Main operation: Top level
The basics of this module is in three blocs that are essentials for the application.
* *Transceiver bloc*. Used to deserialize the communication stream from the BPM. +
_For now it is a Xilinx GTWizard, configured for the Libera Electron DLS CC protocol specs (2Gbps, 16b words...)._
_This is tied to a specific transceiver input of the FPGA._
* *Protocol decoder bloc*. From the deserialized words, it decode the stream and get the essential data (BPM number, position, timestamp...).
It outputs it on a AXI-Stream interface. +
_For now, it parses Libera Electron DLS CC._
* *AXI-MM register interface*. Used to configure and monitor everything from an AXI-MM interface (CPU).
These three blocs are depicted in the image below.
It is to note that the clock domain used is the data clock, even for the register interface.
This clock is provided and can be used to clock the rest of the application and/or clock CDC on the AXI-MM and AXIS interface. +
_The actual __top_combpm_electron.vhd__ file provides these three blocs configured and connected for the Libera Electron and damc-fmc2zup application._
.Basic overview of combpm module
image::images/overview.svg[]
=== Additionnal blocs
The module provide additionnal blocs usefull for the application.
* Packet filter
=== Package
A package describing the AXIS packet at the module output is present.
It helps to automatically pack or unpack the packet (functions _bpmpacket2slv()_ or _slv2bpmpacket()_ ).
A zero packet (_C_BPMPACKET_ZERO) is also declared.
.t_bpmpacket record type
[cols="1,1,1"]
[%autowidth]
|===
|Member name | Type | Description
|pos_x | std_logic_vector(31 downto 0) | X position
|pos_y | std_logic_vector(31 downto 0) | Y position
|bpm_id | std_logic_vector(15 downto 0) | ID of the source BPM
|mc_timestamp | std_logic_vector(39 downto 0) | Timestamp at machine clock frequency
|fa_seq | std_logic_vector(7 downto 0) | FA sequence number, LSB only
|===
.Some usage of pkg_bpmpacket.vhd
[example]
[source,vhdl]
----
signal my_packet : t_bpmpacket;
(...)
my_packet <= slv2bpmpacket(axis_tdata); -- Convert from AXIS tdata to a BPM packet
id <= my_packet.bpm_id; -- Access packet fields
pos_x <= my_packet.pos_x;
axis_tdata_o <= bpmpacket(my_packet); -- Convert back to logic vector for AXIS tdata
----
// ================================================================================
== Details
=== Protocol decoder (electron)
* CRC check. If fails: drop the frame, pulse frame_error output and increase the error counter.
* Counts and gives the number of frame in the last DLS CC sequence receive.
* DLS CC Sequence number check. If discontinuous: pulse seq_discontinuity output and increase
=== BPM packet AXIS stream
The AXIS data provided by the protocol decoder is descibed in the file _pkg_bpmpacket_stream.vhd_.
See this file to have up to date fields info.
* Packets are not cut into packets (TLAST always '1').
* No FIFO on output (TREADY is not used).
The application needs to either implement FIFO or accepts every packet (AXIS packet).
The packet rate depends on the signal input.
=== Transceivers
The TCL script combpm_gtwizard.tcl is used to create the GTWizard IP, wich is instanciated in the top level.
=== AXI-MM register interface
We use DESYRDL to generate a AXI4L slave decoder.
=== Packet filter
This block can drop BPM packets from the AXIS by looking up their BPM_ID field.
A simple memory block is used and programmed via the AXI-MM interface.
The block is adressed by the BPM ID (0 to 255).
The msb (bit 7) gives the forward signal.
If '1' then the packet is transfered, else it is blocked.
The 6 lsb (bit 6-0) is filled into the TDEST field of the AXIS stream.
This can be used to further routing.
.Structural schematic of combpm_packet_filter.
image::images/combpm_packet_filter.svg[]
// ================================================================================
== Registers map
include::regmap.adoc[]
// ================================================================================
== TODO/Future of this module
* Add configuration feature to allow the choice of the transceiver (for now only X0Y4 GTH).
* The application should be able to instanciate several transceiver interface, with one decoder for each.
* At SOLEIL, the BPM electronics will change by 2025.
At that point, it will be necessary to change the *Transceivers* and *Protocol decoder* blocs to match the new equipments.
.Registers
[.tab-addr-reg,cols="5,1,1,2,1,9"]
|===
|Name | N | bits | type | RW | Description
| ID | 1 | 32 | uint | RO | +++Module identifier.+++
| VERSION | 1 | 32 | uint | RO | +++Module version.+++
| SFP | 1 | 2 | bitfields | RO | +++SFP module status+++ +
- RXLOS [0:0] sw:RO uint : +++RX lost signal+++ +
- MODABS [1:1] sw:RO uint : +++Module is absent+++
| GT | 1 | 11 | bitfields | RW | +++GT transceivers status and control+++ +
- POWERGOOD [0:0] sw:RO uint : +++Powergood signal+++ +
- QPLLLOCK [1:1] sw:RO uint : +++PLL lock signal+++ +
- RXCLKACTIVE [2:2] sw:RO uint : +++RX clk active signal+++ +
- RXCDRLOCK [3:3] sw:RO uint : +++RX CDR lock signal+++ +
- RXRESETDONE [4:4] sw:RO uint : +++RX reset done signal+++ +
- RXBYTEISALIGNED [5:5] sw:RO uint : +++RX byte is aligned signal+++ +
- RXBYTEREALIGN [6:6] sw:RO uint : +++RX byte realign signal+++ +
- RXCOMMADET [7:7] sw:RO uint : +++RX comma detected signal+++ +
- RXCOMMADETEN [8:8] sw:RW uint : +++RX comma detection enable signal+++ +
- RXRSTDATAPATH [9:9] sw:RW uint : +++Reset RX datapath+++ +
- RXRSTPLLDATAPATH [10:10] sw:RW uint : +++Reset RX PLL and datapath+++
| PROTOCOL | 1 | 4 | bitfields | RW | +++BPM protocol status and control+++ +
- FRAMEERROR [0:0] sw:RO uint : +++Frame error+++ +
- SEQFRAMECNTERROR [1:1] sw:RO uint : +++Sequence frame count mismatch+++ +
- SEQFRAMEDISCONT [2:2] sw:RO uint : +++Sequence frame discontinuity+++ +
- SOFTRESET [3:3] sw:RW uint : +++Soft reset+++
| VALIDFRAMECNT | 1 | 32 | uint | RO | +++BPM protocol valid frame counters+++
| INVALIDFRAMECNT | 1 | 32 | uint | RO | +++BPM protocol invalid frame counters+++
| VALIDFRAMERATE | 1 | 32 | uint | RO | +++BPM protocol valid frame rate+++
| INVALIDFRAMERATE | 1 | 32 | uint | RO | +++BPM protocol invalid frame rate+++
| FRAMESEQ | 1 | 16 | uint | RO | +++BPM protocol frame sequence+++
|===
This diff is collapsed.
This diff is collapsed.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.pkg_bpmpacket_stream.all;
entity combpm_packet_filter is
generic(
G_B_ADDR_W : natural := 14
);
port(
axis_clk : in std_logic;
axi_clk : in std_logic;
axis_rst_n : in std_logic;
axi_rst_n : in std_logic;
-- AXIS SLAVE INTERFACE
s_axis_tdest : in std_logic_vector(C_TDEST_W-1 downto 0);
s_axis_tdata : in std_logic_vector(C_TDATA_W-1 downto 0);
s_axis_tlast : in std_logic;
s_axis_tvalid : in std_logic;
s_axis_tready : out std_logic;
-- AXIS SLAVE INTERFACE
m_axis_tdest : out std_logic_vector(C_TDEST_W-1 downto 0);
m_axis_tdata : out std_logic_vector(C_TDATA_W-1 downto 0);
m_axis_tlast : out std_logic;
m_axis_tvalid : out std_logic;
-- AXI bus interface
s_axi_awaddr : IN STD_LOGIC_VECTOR(G_B_ADDR_W-1 DOWNTO 0);
s_axi_awlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
s_axi_awsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_awburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_awlock : IN STD_LOGIC;
s_axi_awcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
s_axi_awprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_awvalid : IN STD_LOGIC;
s_axi_awready : OUT STD_LOGIC;
s_axi_wdata : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
s_axi_wstrb : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
s_axi_wlast : IN STD_LOGIC;
s_axi_wvalid : IN STD_LOGIC;
s_axi_wready : OUT STD_LOGIC;
s_axi_bresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_bvalid : OUT STD_LOGIC;
s_axi_bready : IN STD_LOGIC;
s_axi_araddr : IN STD_LOGIC_VECTOR(G_B_ADDR_W-1 DOWNTO 0);
s_axi_arlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
s_axi_arsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_arburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_arlock : IN STD_LOGIC;
s_axi_arcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
s_axi_arprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_arvalid : IN STD_LOGIC;
s_axi_arready : OUT STD_LOGIC;
s_axi_rdata : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
s_axi_rresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_rlast : OUT STD_LOGIC;
s_axi_rvalid : OUT STD_LOGIC;
s_axi_rready : IN STD_LOGIC
);
end combpm_packet_filter;
architecture rtl of combpm_packet_filter is
---------------------------
-- COMPONENT DECLARATION --
---------------------------
COMPONENT combpm_packet_filter_axi_bram_ctrl
PORT (
s_axi_aclk : IN STD_LOGIC;
s_axi_aresetn : IN STD_LOGIC;
s_axi_awaddr : IN STD_LOGIC_VECTOR(G_B_ADDR_W-1 DOWNTO 0);
s_axi_awlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
s_axi_awsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_awburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_awlock : IN STD_LOGIC;
s_axi_awcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
s_axi_awprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_awvalid : IN STD_LOGIC;
s_axi_awready : OUT STD_LOGIC;
s_axi_wdata : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
s_axi_wstrb : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
s_axi_wlast : IN STD_LOGIC;
s_axi_wvalid : IN STD_LOGIC;
s_axi_wready : OUT STD_LOGIC;
s_axi_bresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_bvalid : OUT STD_LOGIC;
s_axi_bready : IN STD_LOGIC;
s_axi_araddr : IN STD_LOGIC_VECTOR(G_B_ADDR_W-1 DOWNTO 0);
s_axi_arlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
s_axi_arsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_arburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_arlock : IN STD_LOGIC;
s_axi_arcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
s_axi_arprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
s_axi_arvalid : IN STD_LOGIC;
s_axi_arready : OUT STD_LOGIC;
s_axi_rdata : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
s_axi_rresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
s_axi_rlast : OUT STD_LOGIC;
s_axi_rvalid : OUT STD_LOGIC;
s_axi_rready : IN STD_LOGIC;
bram_rst_a : OUT STD_LOGIC;
bram_clk_a : OUT STD_LOGIC;
bram_en_a : OUT STD_LOGIC;
bram_we_a : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
bram_addr_a : OUT STD_LOGIC_VECTOR(G_B_ADDR_W-1 DOWNTO 0);
bram_wrdata_a : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
bram_rddata_a : IN STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END COMPONENT;
COMPONENT combpm_packet_filter_blk_mem
PORT (
clka : IN STD_LOGIC;
ena : IN STD_LOGIC;
wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
addra : IN STD_LOGIC_VECTOR(G_B_ADDR_W-3 DOWNTO 0);
dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
clkb : IN STD_LOGIC;
enb : IN STD_LOGIC;
web : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
addrb : IN STD_LOGIC_VECTOR(G_B_ADDR_W-1 DOWNTO 0);
dinb : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
doutb : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
------------------------
-- SIGNAL DECLARATION --
------------------------
signal in_packet : t_bpmpacket;
signal out_packet : t_bpmpacket;
signal bram_clk_a : STD_LOGIC;
signal bram_en_a : STD_LOGIC;
signal bram_we_a : STD_LOGIC_VECTOR(3 DOWNTO 0);
signal bram_addr_a : STD_LOGIC_VECTOR(G_B_ADDR_W-3 DOWNTO 0);
signal bram_wrdata_a : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal bram_rddata_a : STD_LOGIC_VECTOR(31 DOWNTO 0);
signal table_data : std_logic_vector(7 downto 0);
signal tvalid_r : std_logic_vector(1 downto 0);
signal zero_packet : std_logic_vector(C_TDATA_W-1 downto 0);
begin
zero_packet <= (others => '0');
-- always ready
s_axis_tready <= '1';
----------------------
-- STREAM REGISTERS --
----------------------
p_main: process(axis_clk, axis_rst_n)
begin
if axis_rst_n = '0' then
in_packet <= slv2bpmpacket(zero_packet);
out_packet <= slv2bpmpacket(zero_packet);
elsif rising_edge(axis_clk) then
-- Register input packet
if s_axis_tvalid = '1' then
in_packet <= slv2bpmpacket(s_axis_tdata);
end if;
tvalid_r(tvalid_r'left downto 1) <= tvalid_r(tvalid_r'left-1 downto 0);
tvalid_r(0) <= s_axis_tvalid;
out_packet <= in_packet;
end if;
end process;
-----------------
-- AXIS OUTPUT --
-----------------
m_axis_tdest <= std_logic_vector(resize(unsigned(table_data(6 downto 0)), C_TDEST_W));
m_axis_tdata <= bpmpacket2slv(out_packet);
m_axis_tlast <= '1'; -- Packet is one tdata only
m_axis_tvalid <= tvalid_r(tvalid_r'left) and table_data(7);
---------------------
-- BRAM CONTROLLER --
---------------------
inst_bram_ctrl : combpm_packet_filter_axi_bram_ctrl
port map (
s_axi_aclk => axi_clk,
s_axi_aresetn => axi_rst_n,
s_axi_awaddr => s_axi_awaddr,
s_axi_awlen => s_axi_awlen,
s_axi_awsize => s_axi_awsize,
s_axi_awburst => s_axi_awburst,
s_axi_awlock => s_axi_awlock,
s_axi_awcache => s_axi_awcache,
s_axi_awprot => s_axi_awprot,
s_axi_awvalid => s_axi_awvalid,
s_axi_awready => s_axi_awready,
s_axi_wdata => s_axi_wdata,
s_axi_wstrb => s_axi_wstrb,
s_axi_wlast => s_axi_wlast,
s_axi_wvalid => s_axi_wvalid,
s_axi_wready => s_axi_wready,
s_axi_bresp => s_axi_bresp,
s_axi_bvalid => s_axi_bvalid,
s_axi_bready => s_axi_bready,
s_axi_araddr => s_axi_araddr,
s_axi_arlen => s_axi_arlen,
s_axi_arsize => s_axi_arsize,
s_axi_arburst => s_axi_arburst,
s_axi_arlock => s_axi_arlock,
s_axi_arcache => s_axi_arcache,
s_axi_arprot => s_axi_arprot,
s_axi_arvalid => s_axi_arvalid,
s_axi_arready => s_axi_arready,
s_axi_rdata => s_axi_rdata,
s_axi_rresp => s_axi_rresp,
s_axi_rlast => s_axi_rlast,
s_axi_rvalid => s_axi_rvalid,
s_axi_rready => s_axi_rready,
bram_rst_a => open,
bram_clk_a => bram_clk_a,
bram_en_a => bram_en_a,
bram_we_a => bram_we_a,
bram_addr_a(1 downto 0) => open,
bram_addr_a(G_B_ADDR_W-1 downto 2) => bram_addr_a,
bram_wrdata_a => bram_wrdata_a,
bram_rddata_a => bram_rddata_a
);
-------------------
-- BRAM INSTANCE --
-------------------
inst_bram : combpm_packet_filter_blk_mem
port map(
clka => bram_clk_a,
ena => bram_en_a,
wea => bram_we_a,
addra => bram_addr_a,
dina => bram_wrdata_a,
douta => bram_rddata_a,
clkb => axis_clk,
enb => '1',
web => "0",
addrb => in_packet.bpm_id(G_B_ADDR_W-1 downto 0),
dinb => (others => '0'),
doutb => table_data
);
end architecture rtl;
......@@ -3,92 +3,38 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library xpm;
use xpm.vcomponents.all;
use work.pkg_bpmpacket_stream.all;
entity combpm_protocol_electron is
port(
rst_n : in std_logic;
clk : in std_logic;
rst_n : in std_logic; -- Asynchronous active low reset.
clk : in std_logic; -- Clock synchronous to data input.
pps : in std_logic; -- One pulse per second. Used for frame rate estimation.
mc_time : in std_logic_vector(39 downto 0); -- Machine clock time for frame time stamping.
-- GT interface
gt_datarx : in std_logic_vector(15 downto 0);
gt_datatx : out std_logic_vector(15 downto 0);
gt_powergood : in std_logic;
gt_qplllock : in std_logic;
gt_txclkactive : in std_logic;
gt_rxclkactive : in std_logic;
gt_txresetdone : in std_logic;
gt_rxresetdone : in std_logic;
gt_rxcdrlock : in std_logic;
gt_rxbyteisaligned : in std_logic;
gt_rxbyterealign : in std_logic;
gt_rxcommadet : in std_logic;
gt_txfault : in std_logic;
gt_rxlos : in std_logic;
gt_modabs : in std_logic;
gt_rstall : out std_logic;
gt_rxcommadeten : out std_logic;
gt_txdisable : out std_logic;
gt_datarx : in std_logic_vector(15 downto 0); -- Deserialized data.
-- AXIS interface
m_axi_tid : out std_logic_vector(0 downto 0);
m_axi_tdest : out std_logic_vector(9 downto 0);
m_axi_tdata : out std_logic_vector(127 downto 0);
m_axi_tstrb : out std_logic_vector(15 downto 0);
m_axi_tkeep : out std_logic_vector(15 downto 0);
m_axi_tlast : out std_logic;
m_axi_tuser : out std_logic_vector(0 downto 0);
m_axi_tvalid : out std_logic;
m_axi_tready : in std_logic;
m_axis_m2s : out t_bpmpacket_axis_m2s;
m_axis_s2m : in t_bpmpacket_axis_s2m;
-- Status and control interface
tx_disable_i : in std_logic;
rx_commadeten_i : in std_logic;
srst_gt_i : in std_logic;
frame_counter_o : out std_logic_vector(15 downto 0);
frame_error_o : out std_logic
soft_reset : in std_logic; -- Reset all counters.
frame_seq_cnt : out std_logic_vector(15 downto 0); -- Number of frame in last sequence.
frame_valid_cnt : out std_logic_vector(31 downto 0); -- Count of valid frames.
frame_invalid_cnt : out std_logic_vector(31 downto 0); -- Count of invalid frames.
frame_valid_rate : out std_logic_vector(31 downto 0); -- Valid frame rate.
frame_invalid_rate : out std_logic_vector(31 downto 0); -- Invalid frame rate.
cnt_seq_mismatch : out std_logic; -- Pulse for number of frame in sequence mismatch.
seq_discontinuity : out std_logic; -- Pulse for discontinuity in sequence number.
frame_error : out std_logic -- Pulse for frame error.
);
end entity combpm_protocol_electron;
architecture rtl of combpm_protocol_electron is
--------------------------
-- INTERFACE ATTRIBUTES --
--------------------------
ATTRIBUTE X_INTERFACE_INFO : STRING;
ATTRIBUTE X_INTERFACE_PARAMETER : STRING;
ATTRIBUTE X_INTERFACE_INFO of m_axi_tid : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tdest : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TDEST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tdata : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TDATA";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tstrb : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TSTRB";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tkeep : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TKEEP";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tlast : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TLAST";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tuser : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TUSER";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tvalid : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TVALID";
ATTRIBUTE X_INTERFACE_INFO of m_axi_tready : SIGNAL is "xilinx.com:interface:axis:1.0 M_AXI TREADY";
ATTRIBUTE X_INTERFACE_INFO of gt_datarx : SIGNAL is "soleil:user:gtsfp:1.0 GT datarx";
ATTRIBUTE X_INTERFACE_INFO of gt_datatx : SIGNAL is "soleil:user:gtsfp:1.0 GT datatx";
ATTRIBUTE X_INTERFACE_INFO of gt_powergood : SIGNAL is "soleil:user:gtsfp:1.0 GT powergood";
ATTRIBUTE X_INTERFACE_INFO of gt_qplllock : SIGNAL is "soleil:user:gtsfp:1.0 GT qplllock";
ATTRIBUTE X_INTERFACE_INFO of gt_txclkactive : SIGNAL is "soleil:user:gtsfp:1.0 GT txclkactive";
ATTRIBUTE X_INTERFACE_INFO of gt_rxclkactive : SIGNAL is "soleil:user:gtsfp:1.0 GT rxclkactive";
ATTRIBUTE X_INTERFACE_INFO of gt_txresetdone : SIGNAL is "soleil:user:gtsfp:1.0 GT txresetdone";
ATTRIBUTE X_INTERFACE_INFO of gt_rxresetdone : SIGNAL is "soleil:user:gtsfp:1.0 GT rxresetdone";
ATTRIBUTE X_INTERFACE_INFO of gt_rxcdrlock : SIGNAL is "soleil:user:gtsfp:1.0 GT rxcdrlock";
ATTRIBUTE X_INTERFACE_INFO of gt_rxbyteisaligned : SIGNAL is "soleil:user:gtsfp:1.0 GT rxbyteisaligned";
ATTRIBUTE X_INTERFACE_INFO of gt_rxbyterealign : SIGNAL is "soleil:user:gtsfp:1.0 GT rxbyterealign";
ATTRIBUTE X_INTERFACE_INFO of gt_rxcommadet : SIGNAL is "soleil:user:gtsfp:1.0 GT rxcommadet";
ATTRIBUTE X_INTERFACE_INFO of gt_txfault : SIGNAL is "soleil:user:gtsfp:1.0 GT txfault";
ATTRIBUTE X_INTERFACE_INFO of gt_rxlos : SIGNAL is "soleil:user:gtsfp:1.0 GT rxlos";
ATTRIBUTE X_INTERFACE_INFO of gt_modabs : SIGNAL is "soleil:user:gtsfp:1.0 GT modabs";
ATTRIBUTE X_INTERFACE_INFO of rst_n : SIGNAL is "xilinx.com:signal:reset:1.0 rst_n RST";
ATTRIBUTE X_INTERFACE_PARAMETER of rst_n : SIGNAL is "POLARITY ACTIVE_LOW";
--------------------------
-- CONSTANT DECLARATION --
--------------------------
......@@ -101,7 +47,6 @@ architecture rtl of combpm_protocol_electron is
------------------------
-- SIGNAL DECLARATION --
------------------------
signal S_AXI_RESET : std_logic;
signal packet_reg : std_logic_vector(14*16-1 downto 0); -- Register to hold one packet
signal flag_sop_inc : std_logic;
......@@ -111,7 +56,7 @@ architecture rtl of combpm_protocol_electron is
signal flag_rsvd : std_logic;
signal flag_crc : std_logic;
signal flag_all : std_logic;
signal flag_any : std_logic;
signal flag_frame : std_logic;
signal packet_bpmid : std_logic_vector(9 downto 0);
signal packet_startframe : std_logic;
......@@ -128,10 +73,17 @@ architecture rtl of combpm_protocol_electron is
signal crc_cnt : unsigned(3 downto 0);
signal d : std_logic_vector(15 downto 0);
signal frame_counter : unsigned(15 downto 0);
signal gt_rxcommadeten_s : std_logic;
signal last_seq : std_logic_vector(15 downto 0);
signal last_cnt_seq_r : unsigned(15 downto 0);
signal cnt_frame_seq_r : unsigned(15 downto 0);
signal cnt_valid_r : unsigned(31 downto 0);
signal cnt_invalid_r : unsigned(31 downto 0);
signal rate_valid_r : unsigned(31 downto 0);
signal rate_invalid_r : unsigned(31 downto 0);
signal itf_ready : std_logic;
signal packet : t_bpmpacket;
signal m_axi_tvalid : std_logic;
begin
......@@ -176,8 +128,8 @@ begin
'0';
-- Any and all flag
flag_all <= flag_sop and flag_eop and flag_dummy and flag_rsvd and flag_crc and itf_ready;
flag_any <= flag_sop or flag_eop or flag_crc;
flag_all <= flag_sop and flag_eop and flag_dummy and flag_rsvd and flag_crc;
flag_frame <= flag_sop and flag_eop;
----------------------------
-- FRAME FIELD EXTRACTION --
......@@ -223,23 +175,25 @@ begin
crc_reg <= C_CRCINIT;
crc_cnt <= (others => '0');
elsif rising_edge(clk) then
if crc_cnt = 0 then
if flag_sop_inc = '1' then
case crc_cnt is
when "0000" =>
if flag_sop_inc = '1' then
crc_cnt <= crc_cnt+1;
crc_reg <= C_CRCINIT;
else
crc_cnt <= (others => '0');
end if;
when "1011" =>
crc_reg <= crc_reg;
crc_cnt <= crc_cnt+1;
crc_reg <= C_CRCINIT;
else
crc_cnt <= (others => '0');
end if;
else
if crc_cnt = 10 then
when "1100" =>
crc_reg <= crc_reg;
crc_cnt <= (others => '0');
else
crc_cnt <= crc_cnt +1;
end if;
crc_reg <= lfsr_c;
when others =>
crc_reg <= lfsr_c;
crc_cnt <= crc_cnt+1;
end case;
end if;
end if;
end process p_crc;
......@@ -281,39 +235,34 @@ begin
--------------
-- AXIS OUT --
--------------
-- Static data
m_axi_tstrb <= (others => '1');
m_axi_tkeep <= (others => '1');
m_axi_tid <= "0";
m_axi_tuser <= "0";
m_axi_tlast <= '1'; -- One transfer is One packet.
m_axis_m2s.tdest <= (others => '0');
m_axis_m2s.tdata <= bpmpacket2slv(packet);
m_axis_m2s.tlast <= '1'; -- One transfer is One packet.
m_axis_m2s.tvalid <= m_axi_tvalid;
p_axis:process(clk, rst_n)
begin
if rst_n = '0' then
m_axi_tdata <= (others => '0');
packet <= C_BPMPACKET_ZERO;
m_axi_tvalid <= '0';
m_axi_tdest <= (others => '0');
elsif rising_edge(clk) then
if flag_all = '1' then
-- Make AXIS packet
m_axi_tdata(31 downto 0) <= packet_ypos;
m_axi_tdata(63 downto 32) <= packet_xpos;
m_axi_tdata(95 downto 64) <= x"0000" & packet_timestamp;
m_axi_tdata(111 downto 96) <= (others => '0');
m_axi_tdata(127 downto 112) <= "000000" & packet_bpmid;
-- AXIS ancillary data
m_axi_tdest <= packet_bpmid;
packet.pos_x <= packet_xpos;
packet.pos_y <= packet_ypos;
packet.bpm_id <= "000000" & packet_bpmid;
packet.mc_timestamp <= mc_time;
packet.fa_seq <= packet_timestamp(7 downto 0);
-- AXIS TVALID
m_axi_tvalid <= '1';
else
-- Acknowledge transfer
if m_axi_tready = '1' then
if m_axis_s2m.tready = '1' then
m_axi_tvalid <= '0';
end if;
end if;
......@@ -325,28 +274,97 @@ begin
------------------------
-- CONTROL AND STATUS --
------------------------
frame_error_o <= flag_any xor flag_all;
frame_counter_o <= std_logic_vector(frame_counter);
itf_ready <= gt_txresetdone and gt_rxresetdone and gt_powergood and gt_qplllock
and gt_rxbyteisaligned and (not srst_gt_i);
frame_error <= flag_frame and not flag_all;
frame_valid_cnt <= std_logic_vector(cnt_valid_r);
frame_invalid_cnt <= std_logic_vector(cnt_invalid_r);
frame_seq_cnt <= std_logic_vector(last_cnt_seq_r);
-- frame counter
p_framecnt:process(clk, rst_n)
begin
if rst_n = '0' then
frame_counter <= (others => '0');
cnt_frame_seq_r <= (others => '0');
cnt_valid_r <= (others => '0');
cnt_invalid_r <= (others => '0');
rate_valid_r <= (others => '0');
rate_invalid_r <= (others => '0');
frame_valid_rate<= (others => '0');
frame_invalid_rate<= (others => '0');
last_seq <= (others => '0');
last_cnt_seq_r <= (others => '0');
seq_discontinuity <= '0';
cnt_seq_mismatch <= '0';
elsif rising_edge(clk) then
if flag_all = '1' then
frame_counter <= frame_counter+1;
if soft_reset = '1' then
cnt_frame_seq_r <= (others => '0');
cnt_valid_r <= (others => '0');
cnt_invalid_r <= (others => '0');
rate_valid_r <= (others => '0');
rate_invalid_r <= (others => '0');
frame_valid_rate<= (others => '0');
frame_invalid_rate<= (others => '0');
last_seq <= (others => '0');
last_cnt_seq_r <= (others => '0');
seq_discontinuity <= '0';
cnt_seq_mismatch <= '0';
else
-- Valid frame counter
if flag_all = '1' then
cnt_valid_r <= cnt_valid_r+1;
end if;
-- Invalid frame counter
if (flag_frame and not flag_all) = '1' then
cnt_invalid_r <= cnt_invalid_r+1;
end if;
-- Rate counter
if pps = '1' then
frame_valid_rate <= std_logic_vector(rate_valid_r);
frame_invalid_rate <= std_logic_vector(rate_invalid_r);
rate_valid_r <= (others => '0');
rate_invalid_r <= (others => '0');
else
-- Valid frame rate counter
if flag_all = '1' then
rate_valid_r <= rate_valid_r+1;
end if;
-- Invalid frame rate counter
if (flag_frame and not flag_all) = '1' then
rate_invalid_r <= rate_invalid_r+1;
end if;
end if;
-- Sequence detection
cnt_seq_mismatch <= '0'; -- Supercharged in logic below
seq_discontinuity <= '0'; -- Supercharged in logic below
if flag_all = '1' then
if last_seq = packet_timestamp then
-- Same sequence
cnt_frame_seq_r <= cnt_frame_seq_r+1;
else
-- New sequence
cnt_frame_seq_r <= (others => '0');
last_seq <= packet_timestamp;
last_cnt_seq_r <= cnt_frame_seq_r;
-- Check sequence increment
if unsigned(packet_timestamp) - unsigned(last_seq) /= 1 then
seq_discontinuity <= '1';
end if;
-- Check number of frame in sequence
if last_cnt_seq_r /= cnt_frame_seq_r then
cnt_seq_mismatch <= '1';
end if;
end if;
end if;
end if;
end if;
end process p_framecnt;
-- Direct connexion to GT/SFP
gt_txdisable <= tx_disable_i;
gt_rstall <= srst_gt_i;
gt_rxcommadeten <= rx_commadeten_i;
end architecture rtl;
-- This file was automatically generated with HECTARE
--
-- DO NOT EDIT
--
-- input_filename = combpm_protocol_electron_ctrl.rdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity combpm_protocol_electron_ctrl_axi is
generic(
G_ADDR_W: integer := 8
);
port (
sfp_txfault_i : in std_logic;
sfp_rxlos_i : in std_logic;
sfp_modabs_i : in std_logic;
sfp_txdisable_o : out std_logic;
gt_powergood_i : in std_logic;
gt_qplllock_i : in std_logic;
gt_txclkactive_i : in std_logic;
gt_rxclkactive_i : in std_logic;
gt_rxcdrlock_i : in std_logic;
gt_txresetdone_i : in std_logic;
gt_rxresetdone_i : in std_logic;
gt_rxbyteisaligned_i : in std_logic;
gt_rxbyterealign_i : in std_logic;
gt_rxcommadet_i : in std_logic;
gt_rxcommadeten_o : out std_logic;
gt_rstall_o : out std_logic;
protocol_framecnt_i : in std_logic_vector(15 downto 0);
protocol_frameerror_i : in std_logic;
clk : in std_logic;
reset : in std_logic;
S_AXI_AWADDR : in std_logic_vector(G_ADDR_W-1 downto 0);
S_AXI_AWPROT : in std_logic_vector(2 downto 0);
S_AXI_AWVALID : in std_logic;
S_AXI_AWREADY : out std_logic;
S_AXI_WDATA : in std_logic_vector(32-1 downto 0);
S_AXI_WSTRB : in std_logic_vector(32/8-1 downto 0);
S_AXI_WVALID : in std_logic;
S_AXI_WREADY : out std_logic;
S_AXI_BRESP : out std_logic_vector(1 downto 0);
S_AXI_BVALID : out std_logic;
S_AXI_BREADY : in std_logic;
S_AXI_ARADDR : in std_logic_vector(G_ADDR_W-1 downto 0);
S_AXI_ARPROT : in std_logic_vector(2 downto 0);
S_AXI_ARVALID : in std_logic;
S_AXI_ARREADY : out std_logic;
S_AXI_RDATA : out std_logic_vector(32-1 downto 0);
S_AXI_RRESP : out std_logic_vector(1 downto 0);
S_AXI_RVALID : out std_logic;
S_AXI_RREADY : in std_logic
);
end entity;
architecture arch of combpm_protocol_electron_ctrl_axi is
-- address constants
constant C_ADDR_SFP : integer := 0;
constant C_ADDR_GT : integer := 1;
constant C_ADDR_PROTOCOL : integer := 2;
-- field ranges constants
constant C_FIELD_SFP_TXFAULT_MSB : integer := 0;
constant C_FIELD_SFP_TXFAULT_LSB : integer := 0;
constant C_FIELD_SFP_RXLOS_MSB : integer := 1;
constant C_FIELD_SFP_RXLOS_LSB : integer := 1;
constant C_FIELD_SFP_MODABS_MSB : integer := 2;
constant C_FIELD_SFP_MODABS_LSB : integer := 2;
constant C_FIELD_SFP_TXDISABLE_MSB : integer := 3;
constant C_FIELD_SFP_TXDISABLE_LSB : integer := 3;
constant C_FIELD_GT_POWERGOOD_MSB : integer := 0;
constant C_FIELD_GT_POWERGOOD_LSB : integer := 0;
constant C_FIELD_GT_QPLLLOCK_MSB : integer := 1;
constant C_FIELD_GT_QPLLLOCK_LSB : integer := 1;
constant C_FIELD_GT_TXCLKACTIVE_MSB : integer := 2;
constant C_FIELD_GT_TXCLKACTIVE_LSB : integer := 2;
constant C_FIELD_GT_RXCLKACTIVE_MSB : integer := 3;
constant C_FIELD_GT_RXCLKACTIVE_LSB : integer := 3;
constant C_FIELD_GT_RXCDRLOCK_MSB : integer := 4;
constant C_FIELD_GT_RXCDRLOCK_LSB : integer := 4;
constant C_FIELD_GT_TXRESETDONE_MSB : integer := 5;
constant C_FIELD_GT_TXRESETDONE_LSB : integer := 5;
constant C_FIELD_GT_RXRESETDONE_MSB : integer := 6;
constant C_FIELD_GT_RXRESETDONE_LSB : integer := 6;
constant C_FIELD_GT_RXBYTEISALIGNED_MSB : integer := 7;
constant C_FIELD_GT_RXBYTEISALIGNED_LSB : integer := 7;
constant C_FIELD_GT_RXBYTEREALIGN_MSB : integer := 8;
constant C_FIELD_GT_RXBYTEREALIGN_LSB : integer := 8;
constant C_FIELD_GT_RXCOMMADET_MSB : integer := 9;
constant C_FIELD_GT_RXCOMMADET_LSB : integer := 9;
constant C_FIELD_GT_RXCOMMADETEN_MSB : integer := 10;
constant C_FIELD_GT_RXCOMMADETEN_LSB : integer := 10;
constant C_FIELD_GT_RSTALL_MSB : integer := 11;
constant C_FIELD_GT_RSTALL_LSB : integer := 11;
constant C_FIELD_PROTOCOL_FRAMECNT_MSB : integer := 15;
constant C_FIELD_PROTOCOL_FRAMECNT_LSB : integer := 0;
constant C_FIELD_PROTOCOL_FRAMEERROR_MSB : integer := 16;
constant C_FIELD_PROTOCOL_FRAMEERROR_LSB : integer := 16;
-- registers
signal reg_sfp : std_logic_vector(32-1 downto 0);
signal reg_gt : std_logic_vector(32-1 downto 0);
signal reg_protocol : std_logic_vector(32-1 downto 0);
-- read
type t_state_read is (sReadIdle, sReadValid);
signal state_read : t_state_read;
signal rdata_reg : std_logic_vector(31 downto 0);
signal raddr_word : integer;
signal arready_wire : std_logic;
signal rvalid_wire : std_logic;
-- write
type t_state_write is (sWriteIdle, sWriteWaitData, sWriteWaitAddr, sWriteResp);
signal state_write : t_state_write;
signal state_write_prev : t_state_write;
signal waddr_reg : std_logic_vector(G_ADDR_W-1 downto 0);
signal wdata_reg : std_logic_vector(31 downto 0);
signal waddr_word : integer;
signal awready_wire : std_logic;
signal wready_wire : std_logic;
signal bvalid_wire : std_logic;
begin
reg_sfp(0) <= sfp_txfault_i when rising_edge(clk);
reg_sfp(1) <= sfp_rxlos_i when rising_edge(clk);
reg_sfp(2) <= sfp_modabs_i when rising_edge(clk);
sfp_txdisable_o <= reg_sfp(3);
reg_gt(0) <= gt_powergood_i when rising_edge(clk);
reg_gt(1) <= gt_qplllock_i when rising_edge(clk);
reg_gt(2) <= gt_txclkactive_i when rising_edge(clk);
reg_gt(3) <= gt_rxclkactive_i when rising_edge(clk);
reg_gt(4) <= gt_rxcdrlock_i when rising_edge(clk);
reg_gt(5) <= gt_txresetdone_i when rising_edge(clk);
reg_gt(6) <= gt_rxresetdone_i when rising_edge(clk);
reg_gt(7) <= gt_rxbyteisaligned_i when rising_edge(clk);
reg_gt(8) <= gt_rxbyterealign_i when rising_edge(clk);
reg_gt(9) <= gt_rxcommadet_i when rising_edge(clk);
gt_rxcommadeten_o <= reg_gt(10);
gt_rstall_o <= reg_gt(11);
reg_protocol(15 downto 0) <= protocol_framecnt_i when rising_edge(clk);
reg_protocol(16) <= protocol_frameerror_i when rising_edge(clk);
proc_state_read: process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
state_read <= sReadIdle;
else
case state_read is
when sReadIdle =>
if S_AXI_ARVALID = '1' then
state_read <= sReadValid;
end if;
when sReadValid =>
if S_AXI_RREADY = '1' then
state_read <= sReadIdle;
end if;
end case;
end if;
end if;
end process;
raddr_word <= to_integer(unsigned(S_AXI_ARADDR(G_ADDR_W-1 downto 2)));
-- ### read logic
proc_rdata_reg: process (clk)
begin
if rising_edge(clk) then
rdata_reg <= (others => '0');
case raddr_word is
when C_ADDR_SFP =>
rdata_reg(0 downto 0) <= reg_sfp(0 downto 0);
rdata_reg(1 downto 1) <= reg_sfp(1 downto 1);
rdata_reg(2 downto 2) <= reg_sfp(2 downto 2);
rdata_reg(3 downto 3) <= reg_sfp(3 downto 3);
when C_ADDR_GT =>
rdata_reg(0 downto 0) <= reg_gt(0 downto 0);
rdata_reg(1 downto 1) <= reg_gt(1 downto 1);
rdata_reg(2 downto 2) <= reg_gt(2 downto 2);
rdata_reg(3 downto 3) <= reg_gt(3 downto 3);
rdata_reg(4 downto 4) <= reg_gt(4 downto 4);
rdata_reg(5 downto 5) <= reg_gt(5 downto 5);
rdata_reg(6 downto 6) <= reg_gt(6 downto 6);
rdata_reg(7 downto 7) <= reg_gt(7 downto 7);
rdata_reg(8 downto 8) <= reg_gt(8 downto 8);
rdata_reg(9 downto 9) <= reg_gt(9 downto 9);
rdata_reg(10 downto 10) <= reg_gt(10 downto 10);
rdata_reg(11 downto 11) <= reg_gt(11 downto 11);
when C_ADDR_PROTOCOL =>
rdata_reg(15 downto 0) <= reg_protocol(15 downto 0);
rdata_reg(16 downto 16) <= reg_protocol(16 downto 16);
when others =>
-- decode error
rdata_reg <= x"badc0fee";
end case;
end if;
end process;
proc_read_output: process (state_read)
begin
case state_read is
when sReadIdle =>
arready_wire <= '1';
rvalid_wire <= '0';
when sReadValid =>
arready_wire <= '0';
rvalid_wire <= '1';
when others =>
arready_wire <= '0';
rvalid_wire <= '0';
end case;
end process;
S_AXI_ARREADY <= arready_wire;
S_AXI_RVALID <= rvalid_wire;
S_AXI_RDATA <= rdata_reg;
S_AXI_RRESP <= "00";
proc_state_write_prev: process (clk) begin
if rising_edge(clk) then
state_write_prev <= state_write;
end if;
end process;
proc_state_write: process (clk) begin
if rising_edge (clk) then
if reset = '1' then
state_write <= sWriteIdle;
else
case state_write is
when sWriteIdle =>
if S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' then
state_write <= sWriteResp;
waddr_reg <= S_AXI_AWADDR;
wdata_reg <= S_AXI_WDATA;
elsif S_AXI_AWVALID = '1' and S_AXI_WVALID = '0' then
state_write <= sWriteWaitData;
waddr_reg <= S_AXI_AWADDR;
elsif S_AXI_AWVALID = '0' and S_AXI_WVALID = '1' then
state_write <= sWriteWaitAddr;
wdata_reg <= S_AXI_WDATA;
end if;
when sWriteWaitData =>
if S_AXI_WVALID = '1' then
state_write <= sWriteResp;
wdata_reg <= S_AXI_WDATA;
end if;
when sWriteWaitAddr =>
if S_AXI_AWVALID = '1' then
state_write <= sWriteResp;
waddr_reg <= S_AXI_AWADDR;
end if;
when sWriteResp =>
if S_AXI_BREADY = '1' then
state_write <= sWriteIdle;
end if;
end case;
end if;
end if;
end process;
waddr_word <= to_integer(unsigned(waddr_reg(G_ADDR_W-1 downto 2)));
-- ### write logic (use waddr_word and wdata_reg)
proc_write: process (clk) begin
if rising_edge(clk) then
if reset = '1' then
reg_sfp(3 downto 3) <= "0";
reg_gt(10 downto 10) <= "1";
reg_gt(11 downto 11) <= "1";
else
-- default (pulse)
-- default (swmod)
-- default (woclr)
if state_write = sWriteResp and state_write_prev /= sWriteResp then
case waddr_word is
when C_ADDR_SFP =>
reg_sfp(3 downto 3) <= wdata_reg(3 downto 3);
when C_ADDR_GT =>
reg_gt(10 downto 10) <= wdata_reg(10 downto 10);
reg_gt(11 downto 11) <= wdata_reg(11 downto 11);
when C_ADDR_PROTOCOL =>
null;
when others =>
null;
end case;
end if;
end if;
end if;
end process;
proc_write_output: process (state_write) begin
case state_write is
when sWriteIdle =>
awready_wire <= '1';
wready_wire <= '1';
bvalid_wire <= '0';
when sWriteWaitData =>
awready_wire <= '0';
wready_wire <= '1';
bvalid_wire <= '0';
when sWriteWaitAddr =>
awready_wire <= '1';
wready_wire <= '0';
bvalid_wire <= '0';
when sWriteResp =>
awready_wire <= '0';
wready_wire <= '0';
bvalid_wire <= '1';
when others =>
awready_wire <= '0';
wready_wire <= '0';
bvalid_wire <= '0';
end case;
end process;
S_AXI_AWREADY <= awready_wire;
S_AXI_WREADY <= wready_wire;
S_AXI_BRESP <= "00";
S_AXI_BVALID <= bvalid_wire;
end architecture;
-- Package BPMPACKET STREAM
-- this package describe the format of the AXI-Stream interface used by blocs of the module COMBPM.
--
-- The usefull things are :
-- * Two record types for port interfaces: t_bpmpacket_axis_m2s and t_bpmpacket_axis_s2m.
-- * One record type for frame fields: t_bpmpacket.
-- * Two functions to transform TDATA (std_logic_vector) to/from t_bpmpacket: slv2bpmpacket and bpmpacket2slv.
library ieee;
use ieee.std_logic_1164.all;
package pkg_bpmpacket_stream is
----------------------
-- MACRO PARAMETERS --
----------------------
constant C_TDEST_W : natural := 7;
constant C_TDATA_W : natural := 128;
---------------------------------
-- AXIS MASTER/SLAVE INTERFACE --
---------------------------------
type t_bpmpacket_axis_m2s is record
tdest : std_logic_vector(C_TDEST_W-1 downto 0);
tdata : std_logic_vector(C_TDATA_W-1 downto 0);
tlast : std_logic;
tvalid : std_logic;
end record t_bpmpacket_axis_m2s;
type t_bpmpacket_axis_s2m is record
tready : std_logic;
end record t_bpmpacket_axis_s2m;
------------------------
-- AXIS STREAM PACKET --
------------------------
type t_bpmpacket is record
pos_x : std_logic_vector(31 downto 0);
pos_y : std_logic_vector(31 downto 0);
bpm_id : std_logic_vector(15 downto 0);
mc_timestamp : std_logic_vector(39 downto 0);
fa_seq : std_logic_vector(7 downto 0);
end record t_bpmpacket;
constant C_BPMPACKET_ZERO : t_bpmpacket := (
pos_x => (others => '0'),
pos_y => (others => '0'),
bpm_id => (others => '0'),
mc_timestamp => (others => '0'),
fa_seq => (others => '0')
);
function slv2bpmpacket(
signal tdata : std_logic_vector(C_TDATA_W-1 downto 0)
)
return t_bpmpacket;
function bpmpacket2slv(
signal packet : t_bpmpacket
)
return std_logic_vector;
end package;
package body pkg_bpmpacket_stream is
function slv2bpmpacket(
signal tdata : std_logic_vector(C_TDATA_W-1 downto 0)
)
return t_bpmpacket is
variable packet : t_bpmpacket;
begin
packet.pos_x := tdata(31 downto 0);
packet.pos_y := tdata(63 downto 32);
packet.bpm_id := tdata(79 downto 64);
packet.mc_timestamp := tdata(119 downto 80);
packet.fa_seq := tdata(127 downto 120);
return packet;
end function;
function bpmpacket2slv(
signal packet : t_bpmpacket
)
return std_logic_vector is
begin
return packet.fa_seq & packet.mc_timestamp & packet.bpm_id & packet.pos_y & packet.pos_x;
end function;
end package body;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
`include "combpm.vh" // Auto generated from FWK
addrmap combpm {
desyrdl_generate_hdl = true;
desyrdl_interface = "AXI4L";
name="BPM protocol decoder controller";
reg {
desc="Module identifier.";
field {hw=w;sw=r;} data[32];
} ID;
reg {
desc="Module version.";
field {hw=w;sw=r;} data[32];
} VERSION;
reg {
desc="SFP module status";
desyrdl_data_type="bitfields";
field {desc="RX lost signal";hw=w;sw=r;
} RXLOS;
field {desc="Module is absent";hw=w;sw=r;
} MODABS;
} SFP;
reg {
desc="GT transceivers status and control";
desyrdl_data_type="bitfields";
field {desc="Powergood signal";hw=w;sw=r;
} POWERGOOD;
field {desc="PLL lock signal";hw=w;sw=r;
} QPLLLOCK;
field {desc="RX clk active signal";hw=w;sw=r;
} RXCLKACTIVE;
field {desc="RX CDR lock signal";hw=w;sw=r;
} RXCDRLOCK;
field {desc="RX reset done signal";hw=w;sw=r;
} RXRESETDONE;
field {desc="RX byte is aligned signal";hw=w;sw=r;
} RXBYTEISALIGNED;
field {desc="RX byte realign signal";hw=w;sw=r;
} RXBYTEREALIGN;
field {desc="RX comma detected signal";hw=w;sw=r;
} RXCOMMADET;
field {desc="RX comma detection enable signal";hw=r;sw=rw;
} RXCOMMADETEN = 1;
field {desc="Reset RX datapath";hw=r;sw=rw;
} RXRSTDATAPATH = 1;
field {desc="Reset RX PLL and datapath";hw=r;sw=rw;
} RXRSTPLLDATAPATH = 1;
} GT;
reg {
desc="BPM protocol status and control";
desyrdl_data_type="bitfields";
field {desc="Frame error";hw=w;sw=r;
} FRAMEERROR;
field {desc="Sequence frame count mismatch";hw=w;sw=r;
} SEQFRAMECNTERROR;
field {desc="Sequence frame discontinuity";hw=w;sw=r;
} SEQFRAMEDISCONT;
field {desc="Soft reset";hw=r;sw=rw;
} SOFTRESET;
} PROTOCOL;
reg {
desc="BPM protocol valid frame counters";
field {hw=w;sw=r;} data[32];
} VALIDFRAMECNT;
reg {
desc="BPM protocol invalid frame counters";
field {hw=w;sw=r;} data[32];
} INVALIDFRAMECNT;
reg {
desc="BPM protocol valid frame rate";
field {hw=w;sw=r;} data[32];
} VALIDFRAMERATE;
reg {
desc="BPM protocol invalid frame rate";
field {hw=w;sw=r;} data[32];
} INVALIDFRAMERATE;
reg {
desc="BPM protocol frame sequence";
field {hw=w;sw=r;} data[16];
} FRAMESEQ;
};
addrmap combpm_protocol_electron_ctrl {
name="BPM Electron protocol decoder controller";
reg {
name="SFP status and control";
field {
desc="SFP TX fault signal";
hw=w;
sw=r;
} TXFAULT;
field {
desc="SFP RX lost signal";
hw=w;
sw=r;
} RXLOS;
field {
desc="SFP module absent signal";
hw=w;
sw=r;
} MODABS;
field {
desc="SFP TX disable signal";
hw=r;
sw=rw;
} TXDISABLE = 0;
} SFP;
reg {
name="GT status and control";
field {
desc="Powergood signal";
hw=w;
sw=r;
} POWERGOOD;
field {
desc="PLL lock signal";
hw=w;
sw=r;
} QPLLLOCK;
field {
desc="TX clk active signal";
hw=w;
sw=r;
} TXCLKACTIVE;
field {
desc="RX clk active signal";
hw=w;
sw=r;
} RXCLKACTIVE;
field {
desc="RX CDR lock signal";
hw=w;
sw=r;
} RXCDRLOCK;
field {
desc="TX reset done signal";
hw=w;
sw=r;
} TXRESETDONE;
field {
desc="RX reset done signal";
hw=w;
sw=r;
} RXRESETDONE;
field {
desc="RX byte is aligned signal";
hw=w;
sw=r;
} RXBYTEISALIGNED;
field {
desc="RX byte realign signal";
hw=w;
sw=r;
} RXBYTEREALIGN;
field {
desc="RX comma detected signal";
hw=w;
sw=r;
} RXCOMMADET;
field {
desc="RX comma detection enable signal";
hw=r;
sw=rw;
} RXCOMMADETEN = 1;
field {
desc="Reset all";
hw=r;
sw=rw;
} RSTALL = 1;
} GT;
reg {
name="Protocol status and control";
field {
desc="Frame counter";
hw=w;
sw=r;
} FRAMECNT[16];
field {
desc="Frame counter";
hw=w;
sw=r;
} FRAMEERROR;
} PROTOCOL;
};
#!/bin/bash
# Perform compilation of all vhdl sources
# For test, only two are needed, but it helps to check syntax
# This will create xsim.dir/work
xvhdl --log test.log hdl/combpm_protocol_electron_ctrl.vhd
xvhdl --log test.log hdl/combpm_protocol_electron.vhd
xvhdl --log test.log hdl/top_combpm_electron.vhd
xvhdl --log test.log test/tb_combpm_protocol_electron.vhd
# Perform Elaboration and snapshot creation
# This will create xsim.dir/work.tb_combpm_protocol_electron
xelab tb_combpm_protocol_electron -debug typical
# Launch simulation
xsim work.tb_combpm_protocol_electron -view test/tb_combpm_protocol_electron_behav.wcfg -gui
# Create a GTWizard IP for one quad.
set quad_name "X0Y4"
set module_name "combpm_gtwizard"
set gt_ip_config [ list \
CONFIG.CHANNEL_ENABLE $quad_name \
CONFIG.TX_MASTER_CHANNEL $quad_name \
CONFIG.RX_MASTER_CHANNEL $quad_name \
CONFIG.TX_LINE_RATE {2.125} \
CONFIG.TX_PLL_TYPE {QPLL1} \
CONFIG.TX_REFCLK_FREQUENCY {156.2500001} \
CONFIG.TX_DATA_ENCODING {8B10B} \
CONFIG.TX_USER_DATA_WIDTH {16} \
CONFIG.TX_INT_DATA_WIDTH {20} \
CONFIG.TX_QPLL_FRACN_NUMERATOR {6710886} \
CONFIG.RX_LINE_RATE {2.125} \
CONFIG.RX_PLL_TYPE {QPLL1} \
CONFIG.RX_REFCLK_FREQUENCY {156.2500001} \
CONFIG.RX_DATA_DECODING {8B10B} \
CONFIG.RX_USER_DATA_WIDTH {16} \
CONFIG.RX_INT_DATA_WIDTH {20} \
CONFIG.RX_QPLL_FRACN_NUMERATOR {6710886} \
CONFIG.RX_JTOL_FC {1.2717457} \
CONFIG.RX_OUTCLK_SOURCE {RXOUTCLKPMA} \
CONFIG.RX_COMMA_M_VAL {1010000011} \
CONFIG.RX_COMMA_P_VAL {0101111100} \
CONFIG.RX_COMMA_P_ENABLE {true} \
CONFIG.RX_COMMA_M_ENABLE {true} \
CONFIG.RX_COMMA_MASK {1111111111} \
CONFIG.RX_COMMA_ALIGN_WORD {2} \
CONFIG.RX_COMMA_SHOW_REALIGN_ENABLE {false} \
CONFIG.RX_CC_NUM_SEQ {1} \
CONFIG.RX_CC_LEN_SEQ {2} \
CONFIG.RX_CC_VAL {00000000000000000000000000000000000000000000000000000000000000100101010010111100} \
CONFIG.RX_CC_VAL_0_0 {10111100} \
CONFIG.RX_CC_K_0_0 {true} \
CONFIG.RX_CC_VAL_0_1 {10010101} \
CONFIG.RX_CC_K_0_1 {false} \
CONFIG.RX_CC_PERIODICITY {100} \
CONFIG.ENABLE_OPTIONAL_PORTS {rxcdrlock_out} \
CONFIG.RX_REFCLK_SOURCE "$quad_name clk1" \
CONFIG.TX_REFCLK_SOURCE "$quad_name clk1" \
CONFIG.LOCATE_TX_USER_CLOCKING {CORE} \
CONFIG.LOCATE_RX_USER_CLOCKING {CORE} \
CONFIG.LOCATE_COMMON {EXAMPLE_DESIGN} \
CONFIG.LOCATE_RESET_CONTROLLER {CORE} \
CONFIG.LOCATE_USER_DATA_WIDTH_SIZING {CORE} \
CONFIG.TXPROGDIV_FREQ_SOURCE {QPLL1} \
CONFIG.TXPROGDIV_FREQ_VAL {106.25} \
CONFIG.FREERUN_FREQUENCY {100} \
CONFIG.SECONDARY_QPLL_ENABLE {true} \
CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY {156.25} \
]
# Create IP
create_ip -name gtwizard_ultrascale -vendor xilinx.com -library ip -version 1.7 -module_name ${module_name}
# Configure the IP
set_property -dict $gt_ip_config [get_ips ${module_name}]
# If using 2 ports
# CONFIG.CHANNEL_ENABLE {${quad_name} X0Y5}
# CONFIG.RX_REFCLK_SOURCE {X0Y5 clk1 ${quad_name} clk1}
# CONFIG.TX_REFCLK_SOURCE {X0Y5 clk1 ${quad_name} clk1}
# Address width, on logic side (8 bits data access)
set b_addr_w 14
# Address width on AXI MM side (32 bits access)
set a_addr_w [expr $b_addr_w-2]
set a_depth [expr 1<<$a_addr_w]
set b_depth [expr 1<<$b_addr_w]
set xcipath [create_ip -name axi_bram_ctrl -vendor xilinx.com -library ip -version 4.1 -module_name combpm_packet_filter_axi_bram_ctrl]
set_property -dict [list \
CONFIG.PROTOCOL {AXI4} \
CONFIG.SUPPORTS_NARROW_BURST {0} \
CONFIG.SINGLE_PORT_BRAM {1} \
CONFIG.USE_ECC {0} \
CONFIG.BMG_INSTANCE {EXTERNAL} \
CONFIG.MEM_DEPTH $a_depth \
CONFIG.CLKIF.FREQ_HZ 250000000 \
CONFIG.DATA_WIDTH 32 \
] [get_ips combpm_packet_filter_axi_bram_ctrl]
set_property GENERATE_SYNTH_CHECKPOINT 0 [get_files $xcipath]
set xcipath [create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name combpm_packet_filter_blk_mem]
set_property -dict [list \
CONFIG.Memory_Type {True_Dual_Port_RAM} \
CONFIG.Use_Byte_Write_Enable {true} \
CONFIG.Byte_Size {8} \
CONFIG.Write_Width_A {32} \
CONFIG.Write_Depth_A $a_depth \
CONFIG.Read_Width_A {32} \
CONFIG.Operating_Mode_A {WRITE_FIRST} \
CONFIG.Write_Width_B {8} \
CONFIG.Read_Width_B {8} \
CONFIG.Operating_Mode_B {WRITE_FIRST} \
CONFIG.Enable_B {Use_ENB_Pin} \
CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \
CONFIG.Register_PortA_Output_of_Memory_Core {false} \
CONFIG.Register_PortB_Output_of_Memory_Primitives {false} \
CONFIG.Port_B_Clock {250} \
CONFIG.Port_B_Write_Rate {0} \
CONFIG.Port_B_Enable_Rate {100} \
] [get_ips combpm_packet_filter_blk_mem]
set_property GENERATE_SYNTH_CHECKPOINT 0 [get_files $xcipath]