1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
-------------------------------------------------------------------------------
--
-- File: PkgJesdConfig.vhd
-- Author: National Instruments
-- Original Project: N32x
-- Date: 15 Dec 2017
--
-------------------------------------------------------------------------------
-- Copyright 2016-2018 Ettus Research, A National Instruments Company
-- SPDX-License-Identifier: LGPL-3.0
-------------------------------------------------------------------------------
--
-- Purpose: JESD204B setup constants and functions. These constants are shared
-- between RX and TX JESD cores.
--
-- vreview_group JesdCoreN32x
-- vreview_reviewers djepson wfife
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.PkgRegs.all;
package PkgJesdConfig is
-- "JESD" in ASCII - with the core number 0 or 1 on the LSb.
constant kJesdSignature : std_logic_vector(31 downto 0) := x"4a455344";
-- Register endpoints
constant kJesdDrpRegsInEndpoint : RegOffset_t := (kOffset => 16#0800#, -- 0x2800 to
kWidth => 16#0800#); -- 0x2FFF
-- Selects the UsrClk2 for the transceivers. For 64-bit wide transceivers, the
-- UsrClk = 2*UserClk2 frequency. For 32-bit wide transceivers, UsrClk = UserClk2
-- frequency. This is a generalization, the clock ratio should be confirmed based on
-- the transceiver configuration.
-- The N310 transceivers use the single rate reference, hence = false.
constant kDoubleRateUsrClk : boolean := false;
-- For the N32x, all lanes are in one quad and we use the QPLL.
constant kJesdUseQpll : boolean := true;
constant kAdcDataWidth : integer := 14; -- ADC data width in bits
constant kDacDataWidth : integer := 16; -- DAC data width in bits
constant kSamplesPerCycle : integer := 2; -- Number of samples per SampleClk1x
constant kGtxDrpAddrWidth : natural := 9;
constant kGtxAddrLsbPosition : natural := 2;
constant kQpllDrpAddrWidth : natural := 8;
constant kGtxDrpDataWidth : natural := 16;
-- Max supported number of lanes
constant kMaxNumLanes : natural := 4;
-- Max supported number of quads (normally there is 1 quad per 4 lanes but disconnect
-- the definitions to allow quad sharing)
constant kMaxNumQuads : natural := 1;
-- Rhodium:
-- JESD shared setup - LMFS = 4211, HD = 1 (Samples are split across multiple lanes).
constant kNumLanes : natural := 4; -- L
constant kNumConvs : positive := 2; -- M
constant kOctetsPerFrame : natural := 1; -- F
constant kDacJesdSamplesPerCycle : integer := 1; -- S
constant kOctetsPerLane : natural := 2; -- MGT data is kOctetsPerLane*8 = 16 bits wide
constant kNumQuads : natural := kNumLanes / 4; -- 4 lanes per quad
constant kHighDensity : boolean := true; -- HD
constant kConvResBits : positive := kDacDataWidth; -- Converter resolution in bits
constant kConvSampleBits : positive := 16; -- Sample Length in bits
constant kInitLaneAlignCnt : positive := 4;
constant kFramesPerMulti : natural := 24; -- K
-- Rhodium:
-- The converters are running at 400/491.52/500 MSPS (DeviceClk), and the sampling
-- clock at the FPGA (UserClk) is 200/245.76/250 MHz; so UsrClk = (DeviceClk / 2).
-- The frame rate = DeviceClk, and the Multiframe rate = (frame rate / kFramesPerMulti)
-- Thus, kUserClksPerMulti = (UsrClk / Multiframe rate)
-- = (UsrClk / (DeviceClk / kFramesPerMulti))
-- since UsrClk = DeviceClk / 2 then,
-- kUserClksPerMulti = ((DeviceClk / 2) / (DeviceClk / kFramesPerMulti))
-- therefore,
-- kUserClksPerMulti = kFramesPerMulti / 2
constant kUserClksPerMulti : integer := kFramesPerMulti / 2;
type NaturalVector is array ( natural range <>) of natural;
-- The PCB connections are are passed trough, any swapping is handled somewhere else.
--
-- Transceiver MGT Channel ADC Lane DAC Lane
-- *********** *********** ******** ********
-- GT0: X0Y8 0 0 0
-- GT1: X0Y9 1 1 1
-- GT2: X0Y10 2 2 2
-- GT3: X0Y11 3 3 3
constant kRxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) :=
(
-- MGT => ADC (in above table)
0 => 0,
1 => 1,
2 => 2,
3 => 3
);
constant kTxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) :=
(
-- MGT => DAC lane
0 => 0,
1 => 1,
2 => 2,
3 => 3
);
constant kLaneToQuadMap : NaturalVector(kNumLanes - 1 downto 0) :=
(
-- All lanes are in one quad
0 => 0,
1 => 0,
2 => 0,
3 => 0
);
-- The master transceiver channel for channel bonding. E(kMasterBondingChannel)
-- must have the highest value decrementing to b"000" for that last channels to bond.
constant kMasterBondingChannel : integer := 1;
-- Channel bonding occurs when a master detects a K-char sequence and aligns its
-- internal FIFO to the start of this sequence. A signal is then generated to other
-- slave transceivers that cause them to bond to the sequence - this bonding signal is
-- cascaded from master to slave to slave to slave, etc where each slave must know how
-- many levels to the master there are. The last slave to bond must be at level b"000"
-- and the master is at the highest level; the number of levels in the sequence is
-- governed by the size of the transceiver FIFO (see the Xilinx user guides for more
-- information).
type BondLevels_t is array(0 to kNumLanes - 1) of std_logic_vector(2 downto 0);
constant kBondLevel : BondLevels_t := (
0 => b"000", -- Control from 1
1 => b"001", -- Master
2 => b"000", -- Control from 1
3 => b"000" -- Control from 1
);
-- User Rx Data
-- ADC Word data width: 14 sample bits + 2 tails bits
constant kAdcWordWidth : integer := 16;
subtype AdcWord_t is std_logic_vector(kAdcWordWidth - 1 downto 0);
type AdcWordArray_t is array(kSamplesPerCycle*2 - 1 downto 0) of AdcWord_t; -- The *2 is because there are two samples (I and Q) per "sample"
-- Constants to specify the contents of the AdcWord_t vector.
constant kAdcWordDataMsb : integer := 15;
constant kAdcWordDataLsb : integer := 2;
constant kAdcWordOver : integer := 1;
constant kAdcWordCBit1 : integer := 0;
-- Option to pipeline stages to improve timing, if needed
constant kPipelineDetectCharsStage : boolean := false;
constant kPipelineCharReplStage : boolean := false;
end package;
|