1 |
33 |
magro732 |
-------------------------------------------------------------------------------
|
2 |
36 |
magro732 |
--
|
3 |
|
|
-- RapidIO IP Library Core
|
4 |
|
|
--
|
5 |
|
|
-- This file is part of the RapidIO IP library project
|
6 |
|
|
-- http://www.opencores.org/cores/rio/
|
7 |
|
|
--
|
8 |
|
|
-- Description
|
9 |
48 |
magro732 |
-- Contains a platform to build endpoints on. It handles CRC insertion/removal
|
10 |
|
|
-- and unpacks the deviceId in a packet into a fixed 32-bit to make the parsing
|
11 |
|
|
-- of packets in higher layers easier. It also discards packets that does not
|
12 |
|
|
-- have a handler.
|
13 |
36 |
magro732 |
--
|
14 |
|
|
-- To Do:
|
15 |
48 |
magro732 |
-- - 8-bit deviceId has not been implemented, fix either as seperate
|
16 |
|
|
-- architecture or an architecture with combined 8- and 16-bit support.
|
17 |
46 |
magro732 |
-- - Egress; Place packets in different queues depending on the packet priority?
|
18 |
36 |
magro732 |
--
|
19 |
|
|
-- Author(s):
|
20 |
|
|
-- - Magnus Rosenius, magro732@opencores.org
|
21 |
|
|
--
|
22 |
|
|
-------------------------------------------------------------------------------
|
23 |
|
|
--
|
24 |
|
|
-- Copyright (C) 2013 Authors and OPENCORES.ORG
|
25 |
|
|
--
|
26 |
|
|
-- This source file may be used and distributed without
|
27 |
|
|
-- restriction provided that this copyright statement is not
|
28 |
|
|
-- removed from the file and that any derivative work contains
|
29 |
|
|
-- the original copyright notice and the associated disclaimer.
|
30 |
|
|
--
|
31 |
|
|
-- This source file is free software; you can redistribute it
|
32 |
|
|
-- and/or modify it under the terms of the GNU Lesser General
|
33 |
|
|
-- Public License as published by the Free Software Foundation;
|
34 |
|
|
-- either version 2.1 of the License, or (at your option) any
|
35 |
|
|
-- later version.
|
36 |
|
|
--
|
37 |
|
|
-- This source is distributed in the hope that it will be
|
38 |
|
|
-- useful, but WITHOUT ANY WARRANTY; without even the implied
|
39 |
|
|
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
40 |
|
|
-- PURPOSE. See the GNU Lesser General Public License for more
|
41 |
|
|
-- details.
|
42 |
|
|
--
|
43 |
|
|
-- You should have received a copy of the GNU Lesser General
|
44 |
|
|
-- Public License along with this source; if not, download it
|
45 |
|
|
-- from http://www.opencores.org/lgpl.shtml
|
46 |
|
|
--
|
47 |
|
|
-------------------------------------------------------------------------------
|
48 |
|
|
|
49 |
47 |
magro732 |
|
50 |
36 |
magro732 |
-------------------------------------------------------------------------------
|
51 |
33 |
magro732 |
-- RioLogicalCommon.
|
52 |
|
|
-------------------------------------------------------------------------------
|
53 |
|
|
-- Ingress:
|
54 |
48 |
magro732 |
-- * Removes in-the-middle CRC. The trailing CRC is not removed since it is not
|
55 |
|
|
-- possible to know in which half-word it is placed without knowing how the
|
56 |
|
|
-- packet should be parsed.
|
57 |
|
|
-- * Forwards packets to logical-layer handlers depending on ftype. The
|
58 |
|
|
-- ftype-field is output as address.
|
59 |
|
|
-- * Outputs header and deviceIDs in seperate accesses to facilitate supporting
|
60 |
|
|
-- different deviceId sizes. All fields are right-justified.
|
61 |
|
|
-- * stall_i is used to stop the flow of data. The flow will continue when
|
62 |
|
|
-- stall_i is deasserted. The stall_i signals should not be registered. If
|
63 |
|
|
-- there is no handler for a packet, stall_i will not go high and the packet
|
64 |
|
|
-- will be automatically discarded.
|
65 |
33 |
magro732 |
-- Egress:
|
66 |
35 |
magro732 |
-- * Adds in-the-middle and trailing CRC.
|
67 |
48 |
magro732 |
-- * Receives packets from a configurable number of logical-layer handlers.
|
68 |
|
|
-- This enables more complex endpoints with several independent
|
69 |
|
|
-- funtionalities.
|
70 |
|
|
-- * Receives header and deviceId in seperate accesses to facilitate
|
71 |
|
|
-- supporting different deviceId sizes. All fields are right-justified. The
|
72 |
|
|
-- size of the deviceId is indicated by the TT-field in the header.
|
73 |
|
|
-- * The adr_i-input signal on the egress side is used to indicate if the last
|
74 |
|
|
-- word contains one or two half-words. This is used to know where to insert
|
75 |
|
|
-- the trailing CRC. It should be set at the start of the frame. If all
|
76 |
|
|
-- frames always have the CRC in the same place it is ok to set this signal
|
77 |
|
|
-- constant.
|
78 |
|
|
-- Examples of how to write a handler for a packet can be found in
|
79 |
|
|
-- RioLogicalPackets.vhd.
|
80 |
33 |
magro732 |
-------------------------------------------------------------------------------
|
81 |
36 |
magro732 |
library ieee;
|
82 |
|
|
use ieee.std_logic_1164.all;
|
83 |
|
|
use ieee.numeric_std.all;
|
84 |
|
|
use work.rio_common.all;
|
85 |
|
|
|
86 |
|
|
|
87 |
38 |
magro732 |
-------------------------------------------------------------------------------
|
88 |
47 |
magro732 |
-- Entity for RioLogicalCommon.
|
89 |
38 |
magro732 |
-------------------------------------------------------------------------------
|
90 |
36 |
magro732 |
entity RioLogicalCommon is
|
91 |
45 |
magro732 |
generic(
|
92 |
48 |
magro732 |
PORTS : natural := 1);
|
93 |
36 |
magro732 |
port(
|
94 |
|
|
clk : in std_logic;
|
95 |
|
|
areset_n : in std_logic;
|
96 |
|
|
enable : in std_logic;
|
97 |
|
|
|
98 |
|
|
readFrameEmpty_i : in std_logic;
|
99 |
|
|
readFrame_o : out std_logic;
|
100 |
|
|
readContent_o : out std_logic;
|
101 |
|
|
readContentEnd_i : in std_logic;
|
102 |
|
|
readContentData_i : in std_logic_vector(31 downto 0);
|
103 |
39 |
magro732 |
|
104 |
36 |
magro732 |
writeFrameFull_i : in std_logic;
|
105 |
|
|
writeFrame_o : out std_logic;
|
106 |
|
|
writeFrameAbort_o : out std_logic;
|
107 |
|
|
writeContent_o : out std_logic;
|
108 |
|
|
writeContentData_o : out std_logic_vector(31 downto 0);
|
109 |
|
|
|
110 |
45 |
magro732 |
inboundStb_o : out std_logic;
|
111 |
48 |
magro732 |
inboundAdr_o : out std_logic_vector(3 downto 0);
|
112 |
45 |
magro732 |
inboundDat_o : out std_logic_vector(31 downto 0);
|
113 |
48 |
magro732 |
inboundStall_i : in std_logic;
|
114 |
39 |
magro732 |
|
115 |
45 |
magro732 |
outboundStb_i : in std_logic_vector(PORTS-1 downto 0);
|
116 |
48 |
magro732 |
outboundAdr_i : in std_logic_vector(PORTS-1 downto 0);
|
117 |
45 |
magro732 |
outboundDat_i : in std_logic_vector(32*PORTS-1 downto 0);
|
118 |
48 |
magro732 |
outboundStall_o : out std_logic_vector(PORTS-1 downto 0));
|
119 |
36 |
magro732 |
end entity;
|
120 |
|
|
|
121 |
|
|
|
122 |
38 |
magro732 |
-------------------------------------------------------------------------------
|
123 |
47 |
magro732 |
-- Architecture for RioLogicalCommon.
|
124 |
38 |
magro732 |
-------------------------------------------------------------------------------
|
125 |
36 |
magro732 |
architecture RioLogicalCommon of RioLogicalCommon is
|
126 |
|
|
|
127 |
45 |
magro732 |
component RioLogicalCommonInterconnect is
|
128 |
|
|
generic(
|
129 |
|
|
WIDTH : natural);
|
130 |
|
|
port(
|
131 |
|
|
clk : in std_logic;
|
132 |
|
|
areset_n : in std_logic;
|
133 |
|
|
|
134 |
|
|
stb_i : in std_logic_vector(WIDTH-1 downto 0);
|
135 |
48 |
magro732 |
adr_i : in std_logic_vector(WIDTH-1 downto 0);
|
136 |
|
|
data_i : in std_logic_vector(32*WIDTH-1 downto 0);
|
137 |
|
|
stall_o : out std_logic_vector(WIDTH-1 downto 0);
|
138 |
45 |
magro732 |
|
139 |
|
|
stb_o : out std_logic;
|
140 |
48 |
magro732 |
adr_o : out std_logic;
|
141 |
|
|
data_o : out std_logic_vector(31 downto 0);
|
142 |
|
|
stall_i : in std_logic);
|
143 |
45 |
magro732 |
end component;
|
144 |
|
|
|
145 |
36 |
magro732 |
component RioLogicalCommonIngress is
|
146 |
|
|
port(
|
147 |
|
|
clk : in std_logic;
|
148 |
|
|
areset_n : in std_logic;
|
149 |
|
|
|
150 |
|
|
readFrameEmpty_i : in std_logic;
|
151 |
|
|
readFrame_o : out std_logic;
|
152 |
|
|
readContent_o : out std_logic;
|
153 |
|
|
readContentEnd_i : in std_logic;
|
154 |
|
|
readContentData_i : in std_logic_vector(31 downto 0);
|
155 |
|
|
|
156 |
48 |
magro732 |
stb_o : out std_logic;
|
157 |
|
|
adr_o : out std_logic_vector(3 downto 0);
|
158 |
|
|
dat_o : out std_logic_vector(31 downto 0);
|
159 |
|
|
stall_i : in std_logic);
|
160 |
36 |
magro732 |
end component;
|
161 |
|
|
|
162 |
|
|
component RioLogicalCommonEgress is
|
163 |
|
|
port(
|
164 |
|
|
clk : in std_logic;
|
165 |
|
|
areset_n : in std_logic;
|
166 |
|
|
|
167 |
|
|
writeFrameFull_i : in std_logic;
|
168 |
|
|
writeFrame_o : out std_logic;
|
169 |
|
|
writeFrameAbort_o : out std_logic;
|
170 |
|
|
writeContent_o : out std_logic;
|
171 |
|
|
writeContentData_o : out std_logic_vector(31 downto 0);
|
172 |
|
|
|
173 |
48 |
magro732 |
stb_i : in std_logic;
|
174 |
|
|
adr_i : in std_logic;
|
175 |
|
|
dat_i : in std_logic_vector(31 downto 0);
|
176 |
|
|
stall_o : out std_logic);
|
177 |
36 |
magro732 |
end component;
|
178 |
|
|
|
179 |
45 |
magro732 |
signal outboundStb : std_logic;
|
180 |
48 |
magro732 |
signal outboundAdr : std_logic;
|
181 |
45 |
magro732 |
signal outboundDat : std_logic_vector(31 downto 0);
|
182 |
48 |
magro732 |
signal outboundStall : std_logic;
|
183 |
45 |
magro732 |
|
184 |
36 |
magro732 |
begin
|
185 |
|
|
|
186 |
38 |
magro732 |
Ingress: RioLogicalCommonIngress
|
187 |
|
|
port map(
|
188 |
|
|
clk=>clk, areset_n=>areset_n,
|
189 |
|
|
readFrameEmpty_i=>readFrameEmpty_i,
|
190 |
|
|
readFrame_o=>readFrame_o,
|
191 |
|
|
readContent_o=>readContent_o,
|
192 |
|
|
readContentEnd_i=>readContentEnd_i,
|
193 |
|
|
readContentData_i=>readContentData_i,
|
194 |
48 |
magro732 |
stb_o=>inboundStb_o,
|
195 |
|
|
adr_o=>inboundAdr_o,
|
196 |
|
|
dat_o=>inboundDat_o,
|
197 |
|
|
stall_i=>inboundStall_i);
|
198 |
38 |
magro732 |
|
199 |
45 |
magro732 |
EgressInterconnect: RioLogicalCommonInterconnect
|
200 |
|
|
generic map(WIDTH=>PORTS)
|
201 |
|
|
port map(
|
202 |
|
|
clk=>clk, areset_n=>areset_n,
|
203 |
48 |
magro732 |
stb_i=>outboundStb_i,
|
204 |
|
|
adr_i=>outboundAdr_i,
|
205 |
|
|
data_i=>outboundDat_i,
|
206 |
|
|
stall_o=>outboundStall_o,
|
207 |
|
|
stb_o=>outboundStb,
|
208 |
|
|
adr_o=>outboundAdr,
|
209 |
|
|
data_o=>outboundDat,
|
210 |
|
|
stall_i=>outboundStall);
|
211 |
45 |
magro732 |
|
212 |
36 |
magro732 |
Egress: RioLogicalCommonEgress
|
213 |
|
|
port map(
|
214 |
|
|
clk=>clk, areset_n=>areset_n,
|
215 |
|
|
writeFrameFull_i=>writeFrameFull_i,
|
216 |
|
|
writeFrame_o=>writeFrame_o,
|
217 |
|
|
writeFrameAbort_o=>writeFrameAbort_o,
|
218 |
|
|
writeContent_o=>writeContent_o,
|
219 |
|
|
writeContentData_o=>writeContentData_o,
|
220 |
48 |
magro732 |
stb_i=>outboundStb,
|
221 |
|
|
adr_i=>outboundAdr,
|
222 |
|
|
dat_i=>outboundDat,
|
223 |
|
|
stall_o=>outboundStall);
|
224 |
36 |
magro732 |
|
225 |
|
|
end architecture;
|
226 |
|
|
|
227 |
|
|
|
228 |
|
|
|
229 |
34 |
magro732 |
-------------------------------------------------------------------------------
|
230 |
|
|
-- RioLogicalCommonIngress.
|
231 |
|
|
-------------------------------------------------------------------------------
|
232 |
33 |
magro732 |
library ieee;
|
233 |
34 |
magro732 |
use ieee.std_logic_1164.all;
|
234 |
33 |
magro732 |
use ieee.numeric_std.all;
|
235 |
|
|
use work.rio_common.all;
|
236 |
|
|
|
237 |
47 |
magro732 |
|
238 |
33 |
magro732 |
-------------------------------------------------------------------------------
|
239 |
|
|
-- Entity for RioLogicalCommonIngress.
|
240 |
|
|
-------------------------------------------------------------------------------
|
241 |
|
|
entity RioLogicalCommonIngress is
|
242 |
|
|
port(
|
243 |
|
|
clk : in std_logic;
|
244 |
|
|
areset_n : in std_logic;
|
245 |
|
|
|
246 |
|
|
readFrameEmpty_i : in std_logic;
|
247 |
|
|
readFrame_o : out std_logic;
|
248 |
|
|
readContent_o : out std_logic;
|
249 |
|
|
readContentEnd_i : in std_logic;
|
250 |
|
|
readContentData_i : in std_logic_vector(31 downto 0);
|
251 |
|
|
|
252 |
48 |
magro732 |
stb_o : out std_logic;
|
253 |
|
|
adr_o : out std_logic_vector(3 downto 0);
|
254 |
|
|
dat_o : out std_logic_vector(31 downto 0);
|
255 |
|
|
stall_i : in std_logic);
|
256 |
33 |
magro732 |
end entity;
|
257 |
|
|
|
258 |
|
|
|
259 |
|
|
-------------------------------------------------------------------------------
|
260 |
48 |
magro732 |
-- Architecture for RioLogicalCommonIngress16.
|
261 |
|
|
-- Only 16-bit deviceId are supported.
|
262 |
33 |
magro732 |
-------------------------------------------------------------------------------
|
263 |
48 |
magro732 |
architecture RioLogicalCommonIngress16 of RioLogicalCommonIngress is
|
264 |
33 |
magro732 |
|
265 |
48 |
magro732 |
signal packetPosition : natural range 0 to 74;
|
266 |
|
|
|
267 |
|
|
signal loadValue, loadValue16 : std_logic_vector(63 downto 0);
|
268 |
36 |
magro732 |
signal packetContent : std_logic_vector(63 downto 0);
|
269 |
|
|
|
270 |
|
|
signal tt : std_logic_vector(1 downto 0);
|
271 |
|
|
signal ftype : std_logic_vector(3 downto 0);
|
272 |
48 |
magro732 |
|
273 |
|
|
signal readContent : std_logic;
|
274 |
|
|
signal readFrame : std_logic;
|
275 |
36 |
magro732 |
|
276 |
33 |
magro732 |
begin
|
277 |
48 |
magro732 |
readContent_o <= readContent;
|
278 |
|
|
readFrame_o <= readFrame;
|
279 |
|
|
|
280 |
|
|
adr_o <= ftype;
|
281 |
|
|
dat_o <= packetContent(63 downto 32);
|
282 |
33 |
magro732 |
|
283 |
48 |
magro732 |
loadValue16 <=
|
284 |
|
|
(x"0000" & packetContent(31 downto 16) & readContentData_i) when (packetPosition = 4) else
|
285 |
|
|
(x"0000" & packetContent(31 downto 0) & x"0000") when (packetPosition = 5) else
|
286 |
|
|
(packetContent(31 downto 16) & readContentData_i & x"0000") when (packetPosition < 24) else
|
287 |
|
|
(packetContent(31 downto 16) & readContentData_i(15 downto 0) & x"00000000") when (packetPosition = 24) else
|
288 |
|
|
(readContentData_i & x"00000000");
|
289 |
|
|
loadValue <= loadValue16 when (tt = "01") else (x"0000" & readContentData_i & x"0000");
|
290 |
|
|
shifter: process(clk, areset_n)
|
291 |
33 |
magro732 |
begin
|
292 |
|
|
if (areset_n = '0') then
|
293 |
48 |
magro732 |
packetContent <= (others=>'0');
|
294 |
|
|
elsif (clk'event and clk = '1') then
|
295 |
|
|
if ((stall_i = '0') and (readFrameEmpty_i = '0')) then
|
296 |
|
|
packetContent <= loadValue;
|
297 |
|
|
end if;
|
298 |
|
|
end if;
|
299 |
|
|
end process;
|
300 |
|
|
|
301 |
|
|
packetCounter: process(clk, areset_n)
|
302 |
|
|
begin
|
303 |
|
|
if (areset_n = '0') then
|
304 |
36 |
magro732 |
packetPosition <= 0;
|
305 |
48 |
magro732 |
elsif (clk'event and clk = '1') then
|
306 |
|
|
if (readFrame = '1') or (readFrameEmpty_i = '1') then
|
307 |
|
|
packetPosition <= 0;
|
308 |
|
|
elsif (stall_i = '0') then
|
309 |
|
|
packetPosition <= packetPosition + 1;
|
310 |
|
|
end if;
|
311 |
|
|
end if;
|
312 |
|
|
end process;
|
313 |
|
|
|
314 |
|
|
headerRegister: process(clk, areset_n)
|
315 |
|
|
begin
|
316 |
|
|
if (areset_n = '0') then
|
317 |
36 |
magro732 |
tt <= "00";
|
318 |
|
|
ftype <= "0000";
|
319 |
48 |
magro732 |
elsif (clk'event and clk = '1') then
|
320 |
|
|
if (readFrame = '1') then
|
321 |
|
|
tt <= "00";
|
322 |
|
|
ftype <= "0000";
|
323 |
|
|
elsif (stall_i = '0') and (packetPosition = 3) then
|
324 |
|
|
tt <= readContentData_i(21 downto 20);
|
325 |
|
|
ftype <= readContentData_i(19 downto 16);
|
326 |
|
|
end if;
|
327 |
|
|
end if;
|
328 |
|
|
end process;
|
329 |
38 |
magro732 |
|
330 |
48 |
magro732 |
controller: process(clk, areset_n)
|
331 |
|
|
begin
|
332 |
|
|
if (areset_n = '0') then
|
333 |
|
|
readContent <= '0';
|
334 |
|
|
readFrame <= '0';
|
335 |
|
|
stb_o <= '0';
|
336 |
33 |
magro732 |
elsif (clk'event and clk = '1') then
|
337 |
48 |
magro732 |
if (stall_i = '0') then
|
338 |
|
|
case packetPosition is
|
339 |
|
|
when 0 =>
|
340 |
|
|
readContent <= '0';
|
341 |
|
|
readFrame <= '0';
|
342 |
|
|
stb_o <= '0';
|
343 |
|
|
when 1 =>
|
344 |
|
|
readContent <= '1';
|
345 |
|
|
when 2 =>
|
346 |
|
|
readContent <= '1';
|
347 |
|
|
when 3 =>
|
348 |
|
|
readContent <= '0';
|
349 |
|
|
stb_o <= '1';
|
350 |
|
|
when others =>
|
351 |
|
|
if (readFrame = '0') then
|
352 |
|
|
stb_o <= not readContentEnd_i;
|
353 |
|
|
readFrame <= readContentEnd_i;
|
354 |
|
|
readContent <= not readContentEnd_i;
|
355 |
36 |
magro732 |
else
|
356 |
48 |
magro732 |
readFrame <= '0';
|
357 |
36 |
magro732 |
end if;
|
358 |
48 |
magro732 |
end case;
|
359 |
|
|
end if;
|
360 |
33 |
magro732 |
end if;
|
361 |
|
|
end process;
|
362 |
|
|
|
363 |
|
|
end architecture;
|
364 |
|
|
|
365 |
|
|
|
366 |
47 |
magro732 |
|
367 |
34 |
magro732 |
-------------------------------------------------------------------------------
|
368 |
|
|
-- RioLogicalCommonEgress.
|
369 |
|
|
-------------------------------------------------------------------------------
|
370 |
|
|
library ieee;
|
371 |
|
|
use ieee.std_logic_1164.all;
|
372 |
|
|
use ieee.numeric_std.all;
|
373 |
|
|
use work.rio_common.all;
|
374 |
33 |
magro732 |
|
375 |
47 |
magro732 |
|
376 |
34 |
magro732 |
-------------------------------------------------------------------------------
|
377 |
|
|
-- Entity for RioLogicalCommonEgress.
|
378 |
|
|
-------------------------------------------------------------------------------
|
379 |
|
|
entity RioLogicalCommonEgress is
|
380 |
|
|
port(
|
381 |
|
|
clk : in std_logic;
|
382 |
|
|
areset_n : in std_logic;
|
383 |
33 |
magro732 |
|
384 |
34 |
magro732 |
writeFrameFull_i : in std_logic;
|
385 |
|
|
writeFrame_o : out std_logic;
|
386 |
|
|
writeFrameAbort_o : out std_logic;
|
387 |
|
|
writeContent_o : out std_logic;
|
388 |
|
|
writeContentData_o : out std_logic_vector(31 downto 0);
|
389 |
|
|
|
390 |
48 |
magro732 |
stb_i : in std_logic;
|
391 |
|
|
adr_i : in std_logic;
|
392 |
|
|
dat_i : in std_logic_vector(31 downto 0);
|
393 |
|
|
stall_o : out std_logic);
|
394 |
34 |
magro732 |
end entity;
|
395 |
|
|
|
396 |
|
|
|
397 |
33 |
magro732 |
-------------------------------------------------------------------------------
|
398 |
48 |
magro732 |
-- Architecture for RioLogicalCommonEgress16.
|
399 |
|
|
-- Only 16-bit deviceId are supported. The first write must contain
|
400 |
|
|
-- the 16-bit header, the second write must contain the destination address and
|
401 |
|
|
-- the third must contain the source address.
|
402 |
|
|
-- CRC is calculated during the transfer and is inserted at byte 81 and 82 and
|
403 |
|
|
-- appended to the packet when it ends.
|
404 |
34 |
magro732 |
-------------------------------------------------------------------------------
|
405 |
48 |
magro732 |
architecture RioLogicalCommonEgress16 of RioLogicalCommonEgress is
|
406 |
34 |
magro732 |
|
407 |
48 |
magro732 |
signal stb, cycleEndCurrent, cycleEndNext : std_logic;
|
408 |
36 |
magro732 |
|
409 |
48 |
magro732 |
signal packetPosition : natural range 0 to 72;
|
410 |
37 |
magro732 |
|
411 |
48 |
magro732 |
signal loadValue : std_logic_vector(47 downto 0);
|
412 |
|
|
signal packetContent : std_logic_vector(47 downto 0);
|
413 |
|
|
signal packetContentReady : std_logic;
|
414 |
|
|
signal packetContentOdd : std_logic;
|
415 |
|
|
signal packetContentLong : std_logic;
|
416 |
|
|
signal packetContentEnd : std_logic;
|
417 |
|
|
signal packetContentPending : std_logic;
|
418 |
|
|
|
419 |
44 |
magro732 |
signal writeContent : std_logic;
|
420 |
48 |
magro732 |
signal writeFrame : std_logic;
|
421 |
|
|
signal writeContentData : std_logic_vector(31 downto 0);
|
422 |
44 |
magro732 |
|
423 |
48 |
magro732 |
signal crcCurrent, crcTemp, crcNext: std_logic_vector(15 downto 0);
|
424 |
|
|
|
425 |
34 |
magro732 |
begin
|
426 |
|
|
|
427 |
48 |
magro732 |
-----------------------------------------------------------------------------
|
428 |
|
|
-- Packet cycle end detection.
|
429 |
|
|
-----------------------------------------------------------------------------
|
430 |
|
|
stbDelayFF: process(clk, areset_n)
|
431 |
34 |
magro732 |
begin
|
432 |
|
|
if (areset_n = '0') then
|
433 |
48 |
magro732 |
stb <= '0';
|
434 |
44 |
magro732 |
elsif (clk'event and clk = '1') then
|
435 |
48 |
magro732 |
if (writeFrame = '1') then
|
436 |
|
|
stb <= '0';
|
437 |
|
|
elsif (writeFrameFull_i = '0') then
|
438 |
|
|
stb <= stb_i;
|
439 |
44 |
magro732 |
end if;
|
440 |
|
|
end if;
|
441 |
|
|
end process;
|
442 |
48 |
magro732 |
cycleEndNext <= (stb and (not stb_i));
|
443 |
|
|
cycleEndFF: process(clk, areset_n)
|
444 |
44 |
magro732 |
begin
|
445 |
|
|
if (areset_n = '0') then
|
446 |
48 |
magro732 |
cycleEndCurrent <= '0';
|
447 |
|
|
elsif (clk'event and clk = '1') then
|
448 |
|
|
if (writeFrame = '1') then
|
449 |
|
|
cycleEndCurrent <= '0';
|
450 |
|
|
elsif (cycleEndNext = '1') then
|
451 |
|
|
cycleEndCurrent <= '1';
|
452 |
|
|
end if;
|
453 |
|
|
end if;
|
454 |
|
|
end process;
|
455 |
|
|
packetContentEnd <= cycleEndNext or cycleEndCurrent;
|
456 |
|
|
|
457 |
|
|
-----------------------------------------------------------------------------
|
458 |
|
|
-- Packet positioning.
|
459 |
|
|
-----------------------------------------------------------------------------
|
460 |
|
|
packetPositionCounter: process(clk, areset_n)
|
461 |
|
|
begin
|
462 |
|
|
if (areset_n = '0') then
|
463 |
44 |
magro732 |
packetPosition <= 0;
|
464 |
48 |
magro732 |
elsif (clk'event and clk = '1') then
|
465 |
|
|
if (writeFrame = '1') then
|
466 |
|
|
packetPosition <= 0;
|
467 |
|
|
elsif (stb_i = '1') and (writeFrameFull_i = '0') then
|
468 |
|
|
packetPosition <= packetPosition + 1;
|
469 |
|
|
end if;
|
470 |
|
|
end if;
|
471 |
|
|
end process;
|
472 |
38 |
magro732 |
|
473 |
48 |
magro732 |
-----------------------------------------------------------------------------
|
474 |
|
|
-- Packet content creation.
|
475 |
|
|
-----------------------------------------------------------------------------
|
476 |
|
|
-- REMARK: The critical path is the crcNext through the loadValue-mux into
|
477 |
|
|
-- packetContent. Register this path if possible.
|
478 |
|
|
loadValue <=
|
479 |
|
|
(packetContent(31 downto 0) & dat_i(15 downto 0)) when (packetContentReady = '0') else
|
480 |
|
|
(packetContent(15 downto 0) & dat_i) when (packetContentLong = '0') else
|
481 |
|
|
(crcNext & packetContent(15 downto 0) & x"0000") when (packetContentPending = '1') else
|
482 |
|
|
(dat_i & x"0000");
|
483 |
|
|
packetContentPlace: process(clk, areset_n)
|
484 |
|
|
begin
|
485 |
|
|
if (areset_n = '0') then
|
486 |
|
|
packetContent <= (others=>'0');
|
487 |
|
|
elsif (clk'event and clk = '1') then
|
488 |
|
|
if (stb_i = '1') or (stb = '1') then
|
489 |
|
|
packetContent <= loadValue;
|
490 |
|
|
end if;
|
491 |
|
|
end if;
|
492 |
|
|
end process;
|
493 |
44 |
magro732 |
|
494 |
48 |
magro732 |
-----------------------------------------------------------------------------
|
495 |
|
|
-- Packet content generation controller.
|
496 |
|
|
-----------------------------------------------------------------------------
|
497 |
|
|
stall_o <= writeFrameFull_i when (packetContentReady = '0') else
|
498 |
|
|
packetContentPending or packetContentEnd;
|
499 |
|
|
controller: process(clk, areset_n)
|
500 |
|
|
begin
|
501 |
|
|
if (areset_n = '0') then
|
502 |
|
|
packetContentReady <= '0';
|
503 |
|
|
packetContentPending <= '0';
|
504 |
|
|
packetContentLong <= '0';
|
505 |
|
|
packetContentOdd <= '0';
|
506 |
|
|
elsif (clk'event and clk = '1') then
|
507 |
|
|
if (writeFrame = '1') then
|
508 |
|
|
packetContentReady <= '0';
|
509 |
|
|
packetContentPending <= '0';
|
510 |
|
|
packetContentLong <= '0';
|
511 |
|
|
packetContentOdd <= adr_i;
|
512 |
|
|
elsif (stb_i = '1') and (writeFrameFull_i = '0') then
|
513 |
|
|
packetContentOdd <= adr_i;
|
514 |
|
|
|
515 |
|
|
case packetPosition is
|
516 |
|
|
when 2 =>
|
517 |
|
|
packetContentReady <= '1';
|
518 |
|
|
when 21 =>
|
519 |
|
|
packetContentPending <= '1';
|
520 |
|
|
packetContentLong <= '1';
|
521 |
|
|
when 22 =>
|
522 |
|
|
packetContentPending <= '0';
|
523 |
|
|
packetContentLong <= '1';
|
524 |
|
|
when others =>
|
525 |
|
|
end case;
|
526 |
|
|
end if;
|
527 |
|
|
end if;
|
528 |
|
|
end process;
|
529 |
38 |
magro732 |
|
530 |
48 |
magro732 |
-----------------------------------------------------------------------------
|
531 |
|
|
-- CRC calculation and interface towards the packet queue.
|
532 |
|
|
-----------------------------------------------------------------------------
|
533 |
|
|
crcCalculation: process(clk, areset_n)
|
534 |
|
|
begin
|
535 |
|
|
if (areset_n = '0') then
|
536 |
|
|
crcCurrent <= x"0000";
|
537 |
34 |
magro732 |
elsif (clk'event and clk = '1') then
|
538 |
48 |
magro732 |
if (packetContentReady = '0') then
|
539 |
|
|
crcCurrent <= x"ffff";
|
540 |
|
|
elsif (packetContentReady = '1') then
|
541 |
|
|
crcCurrent <= crcNext;
|
542 |
|
|
end if;
|
543 |
|
|
end if;
|
544 |
|
|
end process;
|
545 |
|
|
Crc16High: Crc16CITT
|
546 |
|
|
port map(
|
547 |
|
|
d_i=>packetContent(47 downto 32), crc_i=>crcCurrent, crc_o=>crcTemp);
|
548 |
|
|
Crc16Low: Crc16CITT
|
549 |
|
|
port map(
|
550 |
|
|
d_i=>packetContent(31 downto 16), crc_i=>crcTemp, crc_o=>crcNext);
|
551 |
|
|
|
552 |
|
|
-----------------------------------------------------------------------------
|
553 |
|
|
-- Frame buffer output interface.
|
554 |
|
|
-----------------------------------------------------------------------------
|
555 |
|
|
-- REMARK: This process needs to be optimized further. It is not part of the critical
|
556 |
|
|
-- path though.
|
557 |
|
|
writeFrameContent: process(clk, areset_n)
|
558 |
|
|
variable flush : std_logic;
|
559 |
|
|
variable appendCrc : std_ulogic;
|
560 |
|
|
variable appendHigh : std_ulogic;
|
561 |
|
|
variable endFrame : std_ulogic;
|
562 |
|
|
begin
|
563 |
|
|
if (areset_n = '0') then
|
564 |
|
|
writeFrame <= '0';
|
565 |
44 |
magro732 |
writeContent <= '0';
|
566 |
48 |
magro732 |
writeContentData <= (others=>'0');
|
567 |
|
|
flush := '0';
|
568 |
|
|
appendCrc := '0';
|
569 |
|
|
appendHigh := '0';
|
570 |
|
|
endFrame := '0';
|
571 |
|
|
elsif (clk'event and clk = '1') then
|
572 |
|
|
if (writeFrame = '1') then
|
573 |
|
|
writeFrame <= '0';
|
574 |
|
|
writeContent <= '0';
|
575 |
|
|
writeContentData <= (others=>'0');
|
576 |
|
|
flush := '0';
|
577 |
|
|
appendCrc := '0';
|
578 |
|
|
appendHigh := '0';
|
579 |
|
|
endFrame := '0';
|
580 |
|
|
else
|
581 |
|
|
if (flush = '1') then
|
582 |
|
|
writeContent <= '1';
|
583 |
|
|
writeContentData <= packetContent(47 downto 16);
|
584 |
|
|
flush := '0';
|
585 |
|
|
elsif (appendCrc = '1') then
|
586 |
|
|
writeContent <= '1';
|
587 |
|
|
if (appendHigh = '0') then
|
588 |
|
|
writeContentData <= packetContent(47 downto 32) & crcTemp;
|
589 |
34 |
magro732 |
else
|
590 |
48 |
magro732 |
writeContentData <= crcCurrent & x"0000";
|
591 |
34 |
magro732 |
end if;
|
592 |
48 |
magro732 |
appendCrc := '0';
|
593 |
|
|
elsif (endFrame = '1') then
|
594 |
|
|
writeContent <= '0';
|
595 |
|
|
writeFrame <= '1';
|
596 |
|
|
endFrame := '0';
|
597 |
|
|
elsif (packetContentPending = '1') and (packetContentEnd = '1') then
|
598 |
|
|
writeContent <= '1';
|
599 |
|
|
writeContentData <= packetContent(47 downto 16);
|
600 |
|
|
flush := not packetContentOdd;
|
601 |
|
|
appendCrc := '1';
|
602 |
|
|
appendHigh := '1';
|
603 |
|
|
endFrame := '1';
|
604 |
|
|
elsif (packetContentEnd = '1') then
|
605 |
|
|
if (packetContentLong = '0') then
|
606 |
44 |
magro732 |
writeContent <= '1';
|
607 |
48 |
magro732 |
writeContentData <= packetContent(47 downto 16);
|
608 |
|
|
flush := '0';
|
609 |
|
|
appendCrc := '1';
|
610 |
|
|
appendHigh := packetContentOdd;
|
611 |
|
|
endFrame := '1';
|
612 |
34 |
magro732 |
else
|
613 |
48 |
magro732 |
if (packetContentOdd = '1') then
|
614 |
44 |
magro732 |
writeContent <= '1';
|
615 |
48 |
magro732 |
writeContentData <= packetContent(47 downto 32) & crcTemp;
|
616 |
|
|
flush := '0';
|
617 |
|
|
appendCrc := '0';
|
618 |
|
|
appendHigh := '0';
|
619 |
|
|
endFrame := '1';
|
620 |
|
|
else
|
621 |
44 |
magro732 |
writeContent <= '1';
|
622 |
48 |
magro732 |
writeContentData <= packetContent(47 downto 16);
|
623 |
|
|
flush := '0';
|
624 |
|
|
appendCrc := '1';
|
625 |
|
|
appendHigh := '1';
|
626 |
|
|
endFrame := '1';
|
627 |
44 |
magro732 |
end if;
|
628 |
34 |
magro732 |
end if;
|
629 |
48 |
magro732 |
elsif (packetContentReady = '1') then
|
630 |
|
|
writeContent <= '1';
|
631 |
|
|
writeContentData <= packetContent(47 downto 16);
|
632 |
|
|
else
|
633 |
|
|
writeContent <= '0';
|
634 |
|
|
writeFrame <= '0';
|
635 |
|
|
end if;
|
636 |
|
|
end if;
|
637 |
34 |
magro732 |
end if;
|
638 |
|
|
end process;
|
639 |
48 |
magro732 |
|
640 |
|
|
writeContent_o <= writeContent;
|
641 |
|
|
writeFrame_o <= writeFrame;
|
642 |
|
|
writeFrameAbort_o <= '0';
|
643 |
|
|
writeContentData_o <= writeContentData;
|
644 |
|
|
|
645 |
34 |
magro732 |
end architecture;
|
646 |
45 |
magro732 |
|
647 |
|
|
|
648 |
|
|
|
649 |
48 |
magro732 |
--------------------------------------------------------------------------------
|
650 |
|
|
-- RioLogicalCommonInterconnect.
|
651 |
45 |
magro732 |
-------------------------------------------------------------------------------
|
652 |
|
|
library ieee;
|
653 |
|
|
use ieee.std_logic_1164.all;
|
654 |
|
|
use ieee.numeric_std.all;
|
655 |
|
|
use work.rio_common.all;
|
656 |
|
|
|
657 |
|
|
|
658 |
|
|
-------------------------------------------------------------------------------
|
659 |
47 |
magro732 |
-- Entity for RioLogicalCommonInterconnect.
|
660 |
45 |
magro732 |
-------------------------------------------------------------------------------
|
661 |
|
|
entity RioLogicalCommonInterconnect is
|
662 |
|
|
generic(
|
663 |
|
|
WIDTH : natural);
|
664 |
|
|
port(
|
665 |
|
|
clk : in std_logic;
|
666 |
|
|
areset_n : in std_logic;
|
667 |
|
|
|
668 |
|
|
stb_i : in std_logic_vector(WIDTH-1 downto 0);
|
669 |
48 |
magro732 |
adr_i : in std_logic_vector(WIDTH-1 downto 0);
|
670 |
|
|
data_i : in std_logic_vector(32*WIDTH-1 downto 0);
|
671 |
|
|
stall_o : out std_logic_vector(WIDTH-1 downto 0);
|
672 |
45 |
magro732 |
|
673 |
|
|
stb_o : out std_logic;
|
674 |
48 |
magro732 |
adr_o : out std_logic;
|
675 |
|
|
data_o : out std_logic_vector(31 downto 0);
|
676 |
|
|
stall_i : in std_logic);
|
677 |
45 |
magro732 |
end entity;
|
678 |
|
|
|
679 |
|
|
|
680 |
|
|
-------------------------------------------------------------------------------
|
681 |
47 |
magro732 |
-- Architecture for RioLogicalCommonInterconnect.
|
682 |
45 |
magro732 |
-------------------------------------------------------------------------------
|
683 |
|
|
architecture RioLogicalCommonInterconnectImpl of RioLogicalCommonInterconnect is
|
684 |
48 |
magro732 |
signal activeCycle : std_logic := '0';
|
685 |
|
|
signal selectedMaster : natural range 0 to WIDTH-1 := 0;
|
686 |
45 |
magro732 |
begin
|
687 |
|
|
|
688 |
|
|
-----------------------------------------------------------------------------
|
689 |
|
|
-- Arbitration.
|
690 |
|
|
-----------------------------------------------------------------------------
|
691 |
|
|
Arbiter: process(areset_n, clk)
|
692 |
|
|
begin
|
693 |
|
|
if (areset_n = '0') then
|
694 |
|
|
activeCycle <= '0';
|
695 |
|
|
selectedMaster <= 0;
|
696 |
|
|
elsif (clk'event and clk = '1') then
|
697 |
|
|
if (activeCycle = '0') then
|
698 |
|
|
for i in 0 to WIDTH-1 loop
|
699 |
|
|
if (stb_i(i) = '1') then
|
700 |
|
|
activeCycle <= '1';
|
701 |
|
|
selectedMaster <= i;
|
702 |
|
|
end if;
|
703 |
|
|
end loop;
|
704 |
|
|
else
|
705 |
|
|
if (stb_i(selectedMaster) = '0') then
|
706 |
|
|
activeCycle <= '0';
|
707 |
|
|
end if;
|
708 |
|
|
end if;
|
709 |
|
|
end if;
|
710 |
|
|
end process;
|
711 |
|
|
|
712 |
|
|
-----------------------------------------------------------------------------
|
713 |
|
|
-- Interconnection.
|
714 |
|
|
-----------------------------------------------------------------------------
|
715 |
|
|
stb_o <= stb_i(selectedMaster) and activeCycle;
|
716 |
48 |
magro732 |
adr_o <= adr_i(selectedMaster);
|
717 |
|
|
data_o <= data_i(32*(selectedMaster+1)-1 downto 32*selectedMaster);
|
718 |
45 |
magro732 |
|
719 |
|
|
Interconnect: for i in 0 to WIDTH-1 generate
|
720 |
48 |
magro732 |
stall_o(i) <= stall_i when (selectedMaster = i) and (activeCycle = '1') else '1';
|
721 |
45 |
magro732 |
end generate;
|
722 |
|
|
|
723 |
|
|
end architecture;
|
724 |
|
|
|
725 |
|
|
|