1 |
2 |
danv |
-------------------------------------------------------------------------------
|
2 |
|
|
--
|
3 |
3 |
danv |
-- Copyright 2020
|
4 |
2 |
danv |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
5 |
|
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
6 |
3 |
danv |
--
|
7 |
|
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
|
|
-- you may not use this file except in compliance with the License.
|
9 |
|
|
-- You may obtain a copy of the License at
|
10 |
|
|
--
|
11 |
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
12 |
|
|
--
|
13 |
|
|
-- Unless required by applicable law or agreed to in writing, software
|
14 |
|
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
|
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
|
|
-- See the License for the specific language governing permissions and
|
17 |
|
|
-- limitations under the License.
|
18 |
2 |
danv |
--
|
19 |
|
|
-------------------------------------------------------------------------------
|
20 |
|
|
|
21 |
|
|
-- Purpose: MM data buffer and Rx seq for multiple parallel SOSI streams
|
22 |
|
|
-- Description:
|
23 |
|
|
-- . g_use_db
|
24 |
|
|
-- The mms_diag_data_buffer can capture data from an input stream in a data
|
25 |
|
|
-- buffer when g_use_db=TRUE. Dependend on g_buf_use_sync the data buffer
|
26 |
|
|
-- is rewritten after each in_sync or when the last word was read via MM.
|
27 |
|
|
-- . g_use_rx_seq
|
28 |
|
|
-- The mms_diag_data_buffer can continously verify a input Rx data sequence
|
29 |
|
|
-- when g_use_rx_seq=TRUE. The expected sequence data is typically generated
|
30 |
|
|
-- by an remote upstream tx_seq source.
|
31 |
|
|
-- . The advantage of the rx_seq is that is can continously verify the
|
32 |
|
|
-- correctness of all rx data in hardware, whereas the DB can only take a
|
33 |
|
|
-- snapshot that then needs to be examined via MM. The advandage of the DB
|
34 |
|
|
-- is that it can take a snapshot of the values of the received data. The
|
35 |
|
|
-- DB requires RAM resources and the rx_seq does not.
|
36 |
|
|
--
|
37 |
|
|
-- Block diagram:
|
38 |
|
|
--
|
39 |
|
|
-- g_use_db
|
40 |
|
|
-- g_buf_use_sync
|
41 |
|
|
-- .
|
42 |
|
|
-- . g_use_tx_seq
|
43 |
|
|
-- . .
|
44 |
|
|
-- . .
|
45 |
|
|
-- /-------------> Rx seq
|
46 |
|
|
-- | . |
|
47 |
|
|
-- in_sosi_arr -----*---> DB RAM |
|
48 |
|
|
-- in_sync -------------> DB reg |
|
49 |
|
|
-- || |
|
50 |
|
|
-- || |
|
51 |
|
|
-- MM ================================
|
52 |
|
|
--
|
53 |
|
|
-- Remark:
|
54 |
|
|
-- . A nice new feature would be to continuously write the DB and to stop
|
55 |
|
|
-- writting it on a trigger. This trigger can then eg. be when the rx_seq
|
56 |
|
|
-- detects an error. By delaying the trigger somewhat it the DB can then
|
57 |
|
|
-- capture some data before and after the trigger event.
|
58 |
|
|
|
59 |
|
|
LIBRARY IEEE, common_pkg_lib, technology_lib, dp_pkg_lib, common_ram_lib, mm_lib;
|
60 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
61 |
|
|
USE IEEE.NUMERIC_STD.ALL;
|
62 |
|
|
USE common_pkg_lib.common_pkg.ALL;
|
63 |
|
|
USE common_ram_lib.common_ram_pkg.ALL;
|
64 |
|
|
USE dp_pkg_lib.dp_stream_pkg.ALL;
|
65 |
|
|
USE work.diag_pkg.ALL;
|
66 |
|
|
USE technology_lib.technology_select_pkg.ALL;
|
67 |
|
|
|
68 |
|
|
ENTITY mms_diag_data_buffer IS
|
69 |
|
|
GENERIC (
|
70 |
|
|
g_technology : NATURAL := c_tech_select_default;
|
71 |
|
|
-- Generate configurations
|
72 |
|
|
g_use_db : BOOLEAN := TRUE;
|
73 |
|
|
g_use_rx_seq : BOOLEAN := FALSE;
|
74 |
|
|
-- General
|
75 |
|
|
g_nof_streams : POSITIVE := 16; -- each stream gets an data buffer
|
76 |
|
|
-- DB settings
|
77 |
|
|
g_data_type : t_diag_data_type_enum := e_data; -- define the sosi field that gets stored: e_data=data, e_complex=im&re, e_real=re, e_imag=im
|
78 |
|
|
g_data_w : NATURAL := 32; -- the g_data_w is the width of the data, re, im values or of the combined im&re value
|
79 |
|
|
g_buf_nof_data : NATURAL := 1024; -- nof words per data buffer
|
80 |
|
|
g_buf_use_sync : BOOLEAN := FALSE; -- when TRUE start filling the buffer at the in_sync, else after the last word was read
|
81 |
|
|
-- Rx_seq
|
82 |
|
|
g_use_steps : BOOLEAN := FALSE;
|
83 |
|
|
g_nof_steps : NATURAL := c_diag_seq_rx_reg_nof_steps;
|
84 |
|
|
g_seq_dat_w : NATURAL := 32 -- >= 1, test sequence data width. Choose g_seq_dat_w <= g_data_w
|
85 |
|
|
);
|
86 |
|
|
PORT (
|
87 |
|
|
-- System
|
88 |
|
|
mm_rst : IN STD_LOGIC;
|
89 |
|
|
mm_clk : IN STD_LOGIC;
|
90 |
|
|
dp_rst : IN STD_LOGIC;
|
91 |
|
|
dp_clk : IN STD_LOGIC;
|
92 |
|
|
-- MM interface
|
93 |
|
|
reg_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- DB control register (one per stream)
|
94 |
|
|
reg_data_buf_miso : OUT t_mem_miso;
|
95 |
|
|
|
96 |
|
|
ram_data_buf_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- DB buffer RAM (one per streams)
|
97 |
|
|
ram_data_buf_miso : OUT t_mem_miso;
|
98 |
|
|
|
99 |
|
|
reg_rx_seq_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- Rx seq control register (one per streams)
|
100 |
|
|
reg_rx_seq_miso : OUT t_mem_miso;
|
101 |
|
|
|
102 |
|
|
-- ST interface
|
103 |
|
|
in_sync : IN STD_LOGIC := '0'; -- input sync pulse in ST dp_clk domain that starts data buffer when g_use_in_sync = TRUE
|
104 |
|
|
in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0)
|
105 |
|
|
);
|
106 |
|
|
END mms_diag_data_buffer;
|
107 |
|
|
|
108 |
|
|
ARCHITECTURE str OF mms_diag_data_buffer IS
|
109 |
|
|
|
110 |
|
|
CONSTANT c_buf_mm_factor : NATURAL := ceil_div(g_data_w, c_word_w);
|
111 |
|
|
CONSTANT c_buf_nof_data_mm : NATURAL := g_buf_nof_data*c_buf_mm_factor;
|
112 |
|
|
|
113 |
|
|
CONSTANT c_buf_adr_w : NATURAL := ceil_log2(c_buf_nof_data_mm);
|
114 |
|
|
CONSTANT c_reg_adr_w : NATURAL := c_diag_db_reg_adr_w;
|
115 |
|
|
|
116 |
|
|
TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
117 |
|
|
|
118 |
|
|
SIGNAL in_data_arr : t_data_arr(g_nof_streams-1 DOWNTO 0);
|
119 |
|
|
|
120 |
|
|
SIGNAL ram_data_buf_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
|
121 |
|
|
SIGNAL ram_data_buf_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0);
|
122 |
|
|
|
123 |
|
|
SIGNAL reg_data_buf_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
|
124 |
|
|
SIGNAL reg_data_buf_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0);
|
125 |
|
|
|
126 |
|
|
BEGIN
|
127 |
|
|
|
128 |
|
|
no_db : IF g_use_db=FALSE GENERATE
|
129 |
|
|
ram_data_buf_miso <= c_mem_miso_rst;
|
130 |
|
|
reg_data_buf_miso <= c_mem_miso_rst;
|
131 |
|
|
END GENERATE;
|
132 |
|
|
|
133 |
|
|
gen_db : IF g_use_db=TRUE GENERATE
|
134 |
|
|
-- Combine the internal array of mm interfaces for the data_buf to one array that is connected to the port of the MM bus
|
135 |
|
|
u_mem_mux_data_buf : ENTITY mm_lib.common_mem_mux
|
136 |
|
|
GENERIC MAP (
|
137 |
|
|
g_nof_mosi => g_nof_streams,
|
138 |
|
|
g_mult_addr_w => c_buf_adr_w
|
139 |
|
|
)
|
140 |
|
|
PORT MAP (
|
141 |
|
|
mosi => ram_data_buf_mosi,
|
142 |
|
|
miso => ram_data_buf_miso,
|
143 |
|
|
mosi_arr => ram_data_buf_mosi_arr,
|
144 |
|
|
miso_arr => ram_data_buf_miso_arr
|
145 |
|
|
);
|
146 |
|
|
|
147 |
|
|
u_mem_mux_reg : ENTITY mm_lib.common_mem_mux
|
148 |
|
|
GENERIC MAP (
|
149 |
|
|
g_nof_mosi => g_nof_streams,
|
150 |
|
|
g_mult_addr_w => c_reg_adr_w
|
151 |
|
|
)
|
152 |
|
|
PORT MAP (
|
153 |
|
|
mosi => reg_data_buf_mosi,
|
154 |
|
|
miso => reg_data_buf_miso,
|
155 |
|
|
mosi_arr => reg_data_buf_mosi_arr,
|
156 |
|
|
miso_arr => reg_data_buf_miso_arr
|
157 |
|
|
);
|
158 |
|
|
|
159 |
|
|
gen_stream : FOR I IN 0 TO g_nof_streams-1 GENERATE
|
160 |
|
|
in_data_arr(I) <= in_sosi_arr(I).im(g_data_w/2-1 DOWNTO 0) & in_sosi_arr(I).re(g_data_w/2-1 DOWNTO 0) WHEN g_data_type=e_complex ELSE
|
161 |
|
|
in_sosi_arr(I).re(g_data_w-1 DOWNTO 0) WHEN g_data_type=e_real ELSE
|
162 |
|
|
in_sosi_arr(I).im(g_data_w-1 DOWNTO 0) WHEN g_data_type=e_imag ELSE
|
163 |
|
|
in_sosi_arr(I).data(g_data_w-1 DOWNTO 0); -- g_data_type=e_data is default
|
164 |
|
|
|
165 |
|
|
u_diag_data_buffer : ENTITY work.diag_data_buffer
|
166 |
|
|
GENERIC MAP (
|
167 |
|
|
g_technology => g_technology,
|
168 |
|
|
g_data_w => g_data_w,
|
169 |
|
|
g_nof_data => g_buf_nof_data,
|
170 |
|
|
g_use_in_sync => g_buf_use_sync -- when TRUE start filling the buffer at the in_sync, else after the last word was read
|
171 |
|
|
)
|
172 |
|
|
PORT MAP (
|
173 |
|
|
-- Memory-mapped clock domain
|
174 |
|
|
mm_rst => mm_rst,
|
175 |
|
|
mm_clk => mm_clk,
|
176 |
|
|
|
177 |
|
|
ram_mm_mosi => ram_data_buf_mosi_arr(I),
|
178 |
|
|
ram_mm_miso => ram_data_buf_miso_arr(I),
|
179 |
|
|
|
180 |
|
|
reg_mm_mosi => reg_data_buf_mosi_arr(I),
|
181 |
|
|
reg_mm_miso => reg_data_buf_miso_arr(I),
|
182 |
|
|
|
183 |
|
|
-- Streaming clock domain
|
184 |
|
|
st_rst => dp_rst,
|
185 |
|
|
st_clk => dp_clk,
|
186 |
|
|
|
187 |
|
|
in_data => in_data_arr(I),
|
188 |
|
|
in_sync => in_sync,
|
189 |
|
|
in_val => in_sosi_arr(I).valid
|
190 |
|
|
);
|
191 |
|
|
END GENERATE;
|
192 |
|
|
END GENERATE;
|
193 |
|
|
|
194 |
|
|
no_rx_seq : IF g_use_rx_seq=FALSE GENERATE
|
195 |
|
|
reg_rx_seq_miso <= c_mem_miso_rst;
|
196 |
|
|
END GENERATE;
|
197 |
|
|
|
198 |
|
|
gen_rx_seq : IF g_use_rx_seq=TRUE GENERATE
|
199 |
|
|
u_mms_diag_rx_seq : ENTITY work.mms_diag_rx_seq
|
200 |
|
|
GENERIC MAP (
|
201 |
|
|
g_nof_streams => g_nof_streams,
|
202 |
|
|
g_use_steps => g_use_steps,
|
203 |
|
|
g_nof_steps => g_nof_steps,
|
204 |
|
|
g_seq_dat_w => g_seq_dat_w, -- >= 1, test sequence data width
|
205 |
|
|
g_data_w => g_data_w -- >= g_seq_dat_w, user data width
|
206 |
|
|
)
|
207 |
|
|
PORT MAP (
|
208 |
|
|
-- Clocks and reset
|
209 |
|
|
mm_rst => mm_rst,
|
210 |
|
|
mm_clk => mm_clk,
|
211 |
|
|
dp_rst => dp_rst,
|
212 |
|
|
dp_clk => dp_clk,
|
213 |
|
|
|
214 |
|
|
-- Memory Mapped Slave
|
215 |
|
|
reg_mosi => reg_rx_seq_mosi, -- multiplexed port for g_nof_streams MM control/status registers
|
216 |
|
|
reg_miso => reg_rx_seq_miso,
|
217 |
|
|
|
218 |
|
|
-- Streaming interface
|
219 |
|
|
rx_snk_in_arr => in_sosi_arr
|
220 |
|
|
);
|
221 |
|
|
END GENERATE;
|
222 |
|
|
|
223 |
|
|
END str;
|