Now supports multiple NVMe clock inputs.
[DuneNvme.git] / src / NvmeStorageUnit.vhd
1 --------------------------------------------------------------------------------
2 -- NvmeStorageUnit.vhd Nvme storage access module
3 -------------------------------------------------------------------------------
4 --!
5 --! @class      NvmeStorageUnit
6 --! @author     Terry Barnaby (terry.barnaby@beam.ltd.uk)
7 --! @date       2020-05-12
8 --! @version    0.5.1
9 --!
10 --! @brief
11 --! This is the main Nvme control module for a single Nvme device.
12 --!
13 --! @details
14 --! This module manages a single Nvme device. It is controlled via a simple regsiter access interface
15 --! and an optional bi-directional PCIe packet stream.
16 --! An AXI4 data stream, blocked into BlockSize Bytes using the "last" signal, is written sequentially
17 --! to the Nvme device. The DataChunkStart and DataChunkSize registers define the starting block number
18 --! and the number of blocks to write.
19 --! See the NvmeStorageManual for more details.
20 --!
21 --! @copyright GNU GPL License
22 --! Copyright (c) Beam Ltd, All rights reserved. <br>
23 --! This code is free software: you can redistribute it and/or modify
24 --! it under the terms of the GNU General Public License as published by
25 --! the Free Software Foundation, either version 3 of the License, or
26 --! (at your option) any later version.
27 --! This program is distributed in the hope that it will be useful,
28 --! but WITHOUT ANY WARRANTY; without even the implied warranty of
29 --! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30 --! GNU General Public License for more details. <br>
31 --! You should have received a copy of the GNU General Public License
32 --! along with this code. If not, see <https://www.gnu.org/licenses/>.
33 --!
34 library ieee;
35 use ieee.std_logic_1164.all;
36 use ieee.numeric_std.all;
37
38 library unisim;
39 use unisim.vcomponents.all;
40
41 library work;
42 use work.NvmeStoragePkg.all;
43 use work.NvmeStorageIntPkg.all;
44
45 entity NvmeStorageUnit is
46 generic(
47         Simulate        : boolean       := False;               --! Generate simulation core
48         ClockPeriod     : time          := 4 ns;                --! Clock period for timers (250 MHz)
49         BlockSize       : integer       := NvmeStorageBlockSize;        --! System block size
50         PcieCore        : integer       := 0;                   --! The Pcie hardblock block to use
51         UseConfigure    : boolean       := False                --! The module configures the Nvme's on reset
52 );
53 port (
54         clk             : in std_logic;                         --! The interface clock line
55         reset           : in std_logic;                         --! The active high reset line
56
57         -- Control and status interface
58         regWrite        : in std_logic;                         --! Enable write to register
59         regAddress      : in unsigned(5 downto 0);              --! Register to read/write
60         regDataIn       : in std_logic_vector(31 downto 0);     --! Register write data
61         regDataOut      : out std_logic_vector(31 downto 0);    --! Register contents
62
63         -- From host to NVMe request/reply streams
64         hostSend        : inout AxisStreamType := AxisStreamInput;      --! Host request stream
65         hostRecv        : inout AxisStreamType := AxisStreamOutput;     --! Host reply stream
66
67         -- AXIS data stream input
68         dataEnabledOut  : out std_logic;                        --! Indicates that data ingest is enabled
69         dataIn          : inout AxisStreamType := AxisStreamInput;      --! Raw data to save stream
70
71         -- NVMe interface
72         nvme_clk        : in std_logic;                         --! Nvme external clock
73         nvme_clk_gt     : in std_logic;                         --! Nvme external GT clock
74         nvme_reset_n    : out std_logic;                        --! Nvme reset output to reset NVMe devices
75
76         nvme_exp_txp    : out std_logic_vector(3 downto 0);     --! nvme PCIe TX plus lanes
77         nvme_exp_txn    : out std_logic_vector(3 downto 0);     --! nvme PCIe TX minus lanes
78         nvme_exp_rxp    : in std_logic_vector(3 downto 0);      --! nvme PCIe RX plus lanes
79         nvme_exp_rxn    : in std_logic_vector(3 downto 0);      --! nvme PCIe RX minus lanes
80
81         -- Debug
82         leds            : out std_logic_vector(2 downto 0)
83 );
84 end;
85
86 architecture Behavioral of NvmeStorageUnit is
87
88 constant TCQ            : time := 1 ns;
89 constant NumStreams     : integer := 8;
90 constant ResetCycles    : integer := (100 ms / ClockPeriod);
91
92 component RegAccessClockConvertor is
93 port (
94         clk1            : in std_logic;                         --! The interface clock line
95         reset1          : in std_logic;                         --! The active high reset line
96         
97         regWrite1       : in std_logic;                         --! Enable write to register
98         regAddress1     : in unsigned(5 downto 0);              --! Register to read/write
99         regDataIn1      : in std_logic_vector(31 downto 0);     --! Register write data
100         regDataOut1     : out std_logic_vector(31 downto 0);    --! Register contents
101
102         clk2            : in std_logic;                         --! The interface clock line
103         reset2          : in std_logic;                         --! The active high reset line
104
105         regWrite2       : out std_logic;                                --! Enable write to register
106         regAddress2     : out unsigned(5 downto 0);             --! Register to read/write
107         regDataIn2      : out std_logic_vector(31 downto 0);    --! Register write data
108         regDataOut2     : in std_logic_vector(31 downto 0)      --! Register contents
109 );
110 end component;
111
112 component AxisClockConverter is
113 generic(
114         Simulate        : boolean       := Simulate
115 );
116 port (
117         clkRx           : in std_logic;
118         resetRx         : in std_logic;
119         streamRx        : inout AxisStreamType := AxisStreamInput;                        
120
121         clkTx           : in std_logic;
122         resetTx         : in std_logic;
123         streamTx        : inout AxisStreamType := AxisStreamOutput
124 );
125 end component;
126
127 component Pcie_nvme0
128 port (
129         pci_exp_txn : out std_logic_vector ( 3 downto 0 );
130         pci_exp_txp : out std_logic_vector ( 3 downto 0 );
131         pci_exp_rxn : in std_logic_vector ( 3 downto 0 );
132         pci_exp_rxp : in std_logic_vector ( 3 downto 0 );
133         user_clk : out std_logic;
134         user_reset : out std_logic;
135         user_lnk_up : out std_logic;
136         s_axis_rq_tdata : in std_logic_vector ( 127 downto 0 );
137         s_axis_rq_tkeep : in std_logic_vector ( 3 downto 0 );
138         s_axis_rq_tlast : in std_logic;
139         s_axis_rq_tready : out std_logic_vector ( 3 downto 0 );
140         s_axis_rq_tuser : in std_logic_vector ( 59 downto 0 );
141         s_axis_rq_tvalid : in std_logic;
142         m_axis_rc_tdata : out std_logic_vector ( 127 downto 0 );
143         m_axis_rc_tkeep : out std_logic_vector ( 3 downto 0 );
144         m_axis_rc_tlast : out std_logic;
145         m_axis_rc_tready : in std_logic;
146         m_axis_rc_tuser : out std_logic_vector ( 74 downto 0 );
147         m_axis_rc_tvalid : out std_logic;
148         m_axis_cq_tdata : out std_logic_vector ( 127 downto 0 );
149         m_axis_cq_tkeep : out std_logic_vector ( 3 downto 0 );
150         m_axis_cq_tlast : out std_logic;
151         m_axis_cq_tready : in std_logic;
152         m_axis_cq_tuser : out std_logic_vector ( 84 downto 0 );
153         m_axis_cq_tvalid : out std_logic;
154         s_axis_cc_tdata : in std_logic_vector ( 127 downto 0 );
155         s_axis_cc_tkeep : in std_logic_vector ( 3 downto 0 );
156         s_axis_cc_tlast : in std_logic;
157         s_axis_cc_tready : out std_logic_vector ( 3 downto 0 );
158         s_axis_cc_tuser : in std_logic_vector ( 32 downto 0 );
159         s_axis_cc_tvalid : in std_logic;
160         cfg_interrupt_int : in std_logic_vector ( 3 downto 0 );
161         cfg_interrupt_pending : in std_logic_vector ( 3 downto 0 );
162         cfg_interrupt_sent : out std_logic;
163         sys_clk : in std_logic;
164         sys_clk_gt : in std_logic;
165         sys_reset : in std_logic;
166         int_qpll1lock_out : out std_logic_vector ( 0 to 0 );
167         int_qpll1outrefclk_out : out std_logic_vector ( 0 to 0 );
168         int_qpll1outclk_out : out std_logic_vector ( 0 to 0 );
169         phy_rdy_out : out std_logic
170 );
171 end component;
172
173 component Pcie_nvme1
174 port (
175         pci_exp_txn : out std_logic_vector ( 3 downto 0 );
176         pci_exp_txp : out std_logic_vector ( 3 downto 0 );
177         pci_exp_rxn : in std_logic_vector ( 3 downto 0 );
178         pci_exp_rxp : in std_logic_vector ( 3 downto 0 );
179         user_clk : out std_logic;
180         user_reset : out std_logic;
181         user_lnk_up : out std_logic;
182         s_axis_rq_tdata : in std_logic_vector ( 127 downto 0 );
183         s_axis_rq_tkeep : in std_logic_vector ( 3 downto 0 );
184         s_axis_rq_tlast : in std_logic;
185         s_axis_rq_tready : out std_logic_vector ( 3 downto 0 );
186         s_axis_rq_tuser : in std_logic_vector ( 59 downto 0 );
187         s_axis_rq_tvalid : in std_logic;
188         m_axis_rc_tdata : out std_logic_vector ( 127 downto 0 );
189         m_axis_rc_tkeep : out std_logic_vector ( 3 downto 0 );
190         m_axis_rc_tlast : out std_logic;
191         m_axis_rc_tready : in std_logic;
192         m_axis_rc_tuser : out std_logic_vector ( 74 downto 0 );
193         m_axis_rc_tvalid : out std_logic;
194         m_axis_cq_tdata : out std_logic_vector ( 127 downto 0 );
195         m_axis_cq_tkeep : out std_logic_vector ( 3 downto 0 );
196         m_axis_cq_tlast : out std_logic;
197         m_axis_cq_tready : in std_logic;
198         m_axis_cq_tuser : out std_logic_vector ( 84 downto 0 );
199         m_axis_cq_tvalid : out std_logic;
200         s_axis_cc_tdata : in std_logic_vector ( 127 downto 0 );
201         s_axis_cc_tkeep : in std_logic_vector ( 3 downto 0 );
202         s_axis_cc_tlast : in std_logic;
203         s_axis_cc_tready : out std_logic_vector ( 3 downto 0 );
204         s_axis_cc_tuser : in std_logic_vector ( 32 downto 0 );
205         s_axis_cc_tvalid : in std_logic;
206         cfg_interrupt_int : in std_logic_vector ( 3 downto 0 );
207         cfg_interrupt_pending : in std_logic_vector ( 3 downto 0 );
208         cfg_interrupt_sent : out std_logic;
209         sys_clk : in std_logic;
210         sys_clk_gt : in std_logic;
211         sys_reset : in std_logic;
212         int_qpll1lock_out : out std_logic_vector ( 0 to 0 );
213         int_qpll1outrefclk_out : out std_logic_vector ( 0 to 0 );
214         int_qpll1outclk_out : out std_logic_vector ( 0 to 0 );
215         phy_rdy_out : out std_logic
216 );
217 end component;
218
219 component StreamSwitch is
220 generic(
221         NumStreams      : integer       := NumStreams           --! The number of stream
222 );
223 port (
224         clk             : in std_logic;                         --! The interface clock line
225         reset           : in std_logic;                         --! The active high reset line
226         
227         streamIn        : inout AxisStreamArrayType(0 to NumStreams-1) := (others => AxisStreamInput);  --! Input stream
228         streamOut       : inout AxisStreamArrayType(0 to NumStreams-1) := (others => AxisStreamOutput)  --! Output stream
229 );
230 end component;
231
232 component NvmeQueues is
233 generic(
234         NumQueueEntries : integer       := NvmeQueueNum;        --! The number of entries per queue
235         Simulate        : boolean       := False
236 );
237 port (
238         clk             : in std_logic;                         --! The interface clock line
239         reset           : in std_logic;                         --! The active high reset line
240         
241         streamIn        : inout AxisStreamType := AxisStreamInput;      --! Request queue entries
242         streamOut       : inout AxisStreamType := AxisStreamOutput      --! replies and requests
243 );
244 end component;
245
246 component NvmeConfig is
247 generic(
248         ClockPeriod     : time := ClockPeriod                   --! Clock period for timers (125 MHz)
249 );
250 port (
251         clk             : in std_logic;                         --! The interface clock line
252         reset           : in std_logic;                         --! The active high reset line
253
254         configStart     : in std_logic;                         --! Start the initialisation (1 clk cycle only)
255         configComplete  : out std_logic;                        --! Initialisation is complete
256
257         -- From host to NVMe request/reply streams
258         streamOut       : inout AxisStreamType := AxisStreamOutput;     --! Nvme request stream
259         streamIn        : inout AxisStreamType := AxisStreamInput       --! Nvme reply stream
260 );
261 end component;
262
263 component PcieStreamMux is
264 port (
265         clk             : in std_logic;                         --! The interface clock line
266         reset           : in std_logic;                         --! The active high reset line
267         
268         stream1In       : inout AxisStreamType := AxisStreamInput;      --! Single multiplexed Input stream
269         stream1Out      : inout AxisStreamType := AxisStreamOutput;     --! Single multiplexed Ouput stream
270
271         stream2Out      : inout AxisStreamType := AxisStreamOutput;     --! Host Requests output stream
272         stream2In       : inout AxisStreamType := AxisStreamInput;      --! Host Replies input stream
273
274         stream3In       : inout AxisStreamType := AxisStreamInput;      --! Nvme Requests input stream
275         stream3Out      : inout AxisStreamType := AxisStreamOutput      --! Nvme replies output stream
276 );
277 end component;
278
279 component NvmeSim is
280 generic(
281         Simulate        : boolean := True;
282         BlockSize       : integer := BlockSize                  --! System block size
283 );
284 port (
285         clk             : in std_logic;
286         reset           : in std_logic;
287
288         -- AXIS Interface to PCIE
289         hostReq         : inout AxisStreamType := AxisStreamInput;
290         hostReply       : inout AxisStreamType := AxisStreamOutput;                        
291         
292         -- From Nvme reqeuest and reply stream
293         nvmeReq         : inout AxisStreamType := AxisStreamOutput;
294         nvmeReply       : inout AxisStreamType := AxisStreamInput
295 );
296 end component;
297
298 component NvmeWrite is
299 generic(
300         Simulate        : boolean := Simulate;                  --! Generate simulation core
301         ClockPeriod     : time := ClockPeriod;                  --! The clocks period
302         BlockSize       : integer := BlockSize                  --! System block size
303 );
304 port (
305         clk             : in std_logic;                         --! The interface clock line
306         reset           : in std_logic;                         --! The active high reset line
307
308         enable          : in std_logic;                         --! Enable the data writing process
309         dataIn          : inout AxisStreamType := AxisStreamInput;      --! Raw data to save stream
310
311         -- To Nvme Request/reply streams
312         requestOut      : inout AxisStreamType := AxisStreamOutput;     --! To Nvme request stream (3)
313         replyIn         : inout AxisStreamType := AxisStreamInput;      --! from Nvme reply stream
314
315         -- From Nvme Request/reply streams
316         memReqIn        : inout AxisStreamType := AxisStreamInput;      --! From Nvme request stream (4)
317         memReplyOut     : inout AxisStreamType := AxisStreamOutput;     --! To Nvme reply stream
318         
319         regWrite        : in std_logic;                         --! Enable write to register
320         regAddress      : in unsigned(3 downto 0);              --! Register to read/write
321         regDataIn       : in std_logic_vector(31 downto 0);     --! Register write data
322         regDataOut      : out std_logic_vector(31 downto 0)     --! Register contents
323 );
324 end component;
325
326 component NvmeRead is
327 generic(
328         Simulate        : boolean := False;                     --! Generate simulation core
329         BlockSize       : integer := NvmeStorageBlockSize       --! System block size
330 );
331 port (
332         clk             : in std_logic;                         --! The interface clock line
333         reset           : in std_logic;                         --! The active high reset line
334
335         -- To Nvme Request/reply streams
336         requestOut      : inout AxisStreamType := AxisStreamOutput;     --! To Nvme request stream (3)
337         replyIn         : inout AxisStreamType := AxisStreamInput;      --! from Nvme reply stream
338
339         regWrite        : in std_logic;                         --! Enable write to register
340         regAddress      : in unsigned(3 downto 0);              --! Register to read/write
341         regDataIn       : in std_logic_vector(31 downto 0);     --! Register write data
342         regDataOut      : out std_logic_vector(31 downto 0)     --! Register contents
343 );
344 end component;
345
346 signal reset_local              : std_logic := '0';
347 signal reset_local_active       : std_logic := '0';
348 signal reset_local_counter      : integer range 0 to ResetCycles := 0;
349
350 -- Streams
351 signal streamSend               : AxisStreamArrayType(0 to NumStreams-1);
352 signal streamRecv               : AxisStreamArrayType(0 to NumStreams-1);
353
354 alias nvmeSend                  is streamSend(0);
355 alias nvmeRecv                  is streamRecv(0);
356 alias hostSend1                 is streamSend(1);
357 alias hostRecv1                 is streamRecv(1);
358 alias queueSend                 is streamSend(2);
359 alias queueRecv                 is streamRecv(2);
360 alias configSend                is streamSend(3);
361 alias configRecv                is streamRecv(3);
362 alias writeSend                 is streamSend(4);
363 alias writeRecv                 is streamRecv(4);
364 alias writeMemSend              is streamSend(5);
365 alias writeMemRecv              is streamRecv(5);
366 alias readSend                  is streamSend(6);
367 alias readRecv                  is streamRecv(6);
368
369 signal dataIn1                  : AxisStreamType;
370 signal streamNone               : AxisStreamType := AxisStreamOutput;
371 signal streamSink               : AxisStreamType := AxisStreamSink;
372
373 -- Nvme PCIe interface
374 signal hostReq                  : AxisStreamType;
375 signal hostReq_ready            : std_logic_vector(3 downto 0);
376 signal hostReq_morethan1        : std_logic;
377 signal hostReq_user             : std_logic_vector(59 downto 0);
378
379 signal hostReply                : AxisStreamType;
380
381 signal nvmeReq                  : AxisStreamType;
382
383 signal nvmeReply                : AxisStreamType;
384 signal nvmeReply_ready          : std_logic_vector(3 downto 0);
385 signal nvmeReply_user           : std_logic_vector(32 downto 0);
386
387 -- Register interface
388 constant RegWidth               : integer := 32;
389 subtype RegDataType             is std_logic_vector(RegWidth-1 downto 0);
390
391 type StateType                  is (STATE_START, STATE_IDLE, STATE_WRITE, STATE_READ1, STATE_READ2);
392 signal state                    : StateType := STATE_START;
393
394 signal regWrite1                : std_logic;                            --! Enable write to register
395 signal regAddress1              : unsigned(5 downto 0) := (others => '0');      --! Register to read/write
396 signal regDataIn1               : std_logic_vector(31 downto 0);        --! Register write data
397 signal regDataOut0              : std_logic_vector(31 downto 0);        --! Register contents
398 signal regDataOut1              : std_logic_vector(31 downto 0);        --! Register contents
399
400 signal reg_id                   : RegDataType := x"56010200";
401 signal reg_control              : RegDataType := (others => '0');
402 signal reg_status               : RegDataType := (others => '0');
403 signal reg_totalBlocks          : RegDataType := to_stl(NvmeTotalBlocks, RegWidth);
404 signal reg_blocksLost           : RegDataType := (others => '0');
405 signal reg_nvmeWrite            : RegDataType := (others => '0');
406 signal reg_nvmeRead             : RegDataType := (others => '0');
407 signal nvmeWrite_write          : std_logic := '0';
408 signal nvmeRead_write           : std_logic := '0';
409
410 -- Nvme configuration signals
411 signal configStart              : std_logic := 'U';
412 signal configStartDone          : std_logic := 'U';
413 signal configComplete           : std_logic := 'U';
414
415 -- Nvme data write signals
416 signal writeEnable              : std_logic := 'U';
417
418
419 -- Pcie_nvme signals
420 signal nvme_reset_local_n       : std_logic := '0';
421 signal nvme_user_clk            : std_logic := 'U';
422 signal nvme_user_reset          : std_logic := 'U';
423
424 signal cfg_mgmt_addr                    : std_logic_vector(18 downto 0);
425 signal cfg_mgmt_write                   : std_logic;
426 signal cfg_mgmt_write_data              : std_logic_vector(31 downto 0);
427 signal cfg_mgmt_read                    : std_logic;
428 signal cfg_mgmt_read_data               : std_logic_vector(31 downto 0);
429 signal cfg_mgmt_read_write_done         : std_logic;
430 signal cfg_mgmt_type1_cfg_reg_access    : std_logic;
431
432 signal dummy1                   : AxisStreamType := AxisStreamInput;
433 signal dummy2                   : AxisStreamType := AxisStreamOutput;
434 signal dummy3                   : AxisStreamType := AxisStreamOutput;
435
436
437 begin
438         -- Register access over clock domain crossing
439         regClockConvertor : RegAccessClockConvertor
440         port map (
441                 clk1            => clk,
442                 reset1          => reset,
443
444                 regWrite1       => regWrite,
445                 regAddress1     => regAddress,
446                 regDataIn1      => regDataIn,
447                 regDataOut1     => regDataOut0,
448
449                 --clk2          => clk,                         --! **** Needs to operate from Nvme clock
450                 --reset2        => reset,
451                 clk2            => nvme_user_clk,
452                 reset2          => nvme_user_reset,
453
454                 regWrite2       => regWrite1,
455                 regAddress2     => regAddress1,
456                 regDataIn2      => regDataIn1,
457                 regDataOut2     => regDataOut1
458         );
459
460         -- Host request packets across clock domain crossing
461         axisClockConverter0 :  AxisClockConverter
462         port map (
463                 clkRx           => clk,
464                 resetRx         => reset,
465                 streamRx        => hostSend,
466
467                 clkTx           => nvme_user_clk,
468                 resetTx         => nvme_user_reset,
469                 streamTx        => hostSend1
470         );
471
472         -- Host reply packets across clock domain crossing
473         axisClockConverter1 :  AxisClockConverter
474         port map (
475                 clkRx           => nvme_user_clk,
476                 resetRx         => nvme_user_reset,
477                 streamRx        => hostRecv1,
478
479                 clkTx           => clk,
480                 resetTx         => reset,
481                 streamTx        => hostRecv
482         );
483         
484         -- Data stream across clock domain crossing
485         axisClockConverter2 :  AxisClockConverter
486         port map (
487                 clkRx           => clk,
488                 resetRx         => reset,
489                 streamRx        => dataIn,
490
491                 clkTx           => nvme_user_clk,
492                 resetTx         => nvme_user_reset,
493                 streamTx        => dataIn1
494         );
495
496         -- Register access
497         regDataOut1 <= reg_id when(regAddress1 = 0) else
498                         reg_control when(regAddress1 = 1) else
499                         reg_status when(regAddress1 = 2) else
500                         reg_totalBlocks when(regAddress1 = 3) else
501                         reg_blocksLost when(regAddress1 = 4) else
502                         reg_nvmeWrite when((regAddress1 >= 16) and (regAddress1 < 32)) else
503                         reg_nvmeRead when((regAddress1 >= 32) and (regAddress1 < 48)) else
504                         x"FFFFFFFF";
505
506         regDataOut <= zeros(31) & reset_local_active when(reset_local_active = '1') else regDataOut0;
507         nvmeWrite_write <= regWrite1 when((regAddress1 >= 16) and (regAddress1 < 32)) else '0';
508         nvmeRead_write <= regWrite1 when((regAddress1 >= 32) and (regAddress1 < 48)) else '0';
509         
510         -- Status register bits
511         reg_status(0)           <= '0';
512         reg_status(1)           <= configComplete;
513         reg_status(2)           <= '0';
514         reg_status(3)           <= '0';                                         -- **** Needs setting
515         reg_status(31 downto 4) <= (others => '0');
516         
517         -- Perform reset of Nvme subsystem. This implements a 100ms reset suitable for the Nvme Pcie reset.
518         -- Local state machines and external Nvme devices use this reset_local signal.
519         reset_local             <= reset or reset_local_active;
520         nvme_reset_local_n      <= not reset_local;
521         nvme_reset_n            <= nvme_reset_local_n;
522         
523         -- Process reset
524         process(clk)
525         begin
526                 if(rising_edge(clk)) then
527                         if(reset = '1') then
528                                 reset_local_active <= '0';
529                         else
530                                 if((regWrite = '1') and (regAddress = 1)) then
531                                         if(regDataIn(0) = '1') then
532                                                 reset_local_counter     <= ResetCycles;
533                                                 reset_local_active      <= '1';
534                                         end if;
535                                 end if;
536                                 
537                                 if(reset_local_active = '1') then
538                                         if(reset_local_counter = 0) then
539                                                 reset_local_active      <= '0';
540                                         else
541                                                 reset_local_counter <= reset_local_counter - 1;
542                                         end if;
543                                 end if;
544                         end if;
545                 end if;
546         end process;
547
548         -- Process register access
549         process(nvme_user_clk)
550         begin
551                 if(rising_edge(nvme_user_clk)) then
552                         if(nvme_user_reset = '1') then
553                                 reg_control     <= (others => '0');
554                         else
555                                 if(regWrite1 = '1') then
556                                         if(regAddress1 = 1) then
557                                                 reg_control <= regDataIn1;
558                                         end if;
559                                 end if;
560                         end if;
561                 end if;
562         end process; 
563         
564         -- Host to Nvme stream Mux/DeMux
565         pcieStreamMux0 : PcieStreamMux
566         port map (
567                 clk             => nvme_user_clk,
568                 reset           => nvme_user_reset,
569
570                 stream1In       => nvmeRecv,
571                 stream1Out      => nvmeSend,
572
573                 stream2Out      => hostReq,
574                 stream2In       => hostReply,
575                 
576                 stream3In       => nvmeReq,
577                 stream3Out      => nvmeReply
578         );
579
580         sim: if (Simulate = True) generate
581         nvme_user_clk   <= clk;
582         nvme_user_reset <= reset_local;
583
584         nvmeSim0 : NvmeSim
585         port map (
586                 clk             => nvme_user_clk,
587                 reset           => nvme_user_reset,
588
589                 hostReq         => hostReq,
590                 hostReply       => hostReply,
591
592                 nvmeReq         => nvmeReq,
593                 nvmeReply       => nvmeReply
594         );
595         end generate;
596         
597         synth: if (Simulate = False) generate
598
599         genpci0: if(PcieCore = 0) generate
600         -- The PCIe to NVMe interface
601         pcie_nvme_0 : Pcie_nvme0
602         port map (
603                 sys_clk                 => nvme_clk,
604                 sys_clk_gt              => nvme_clk_gt,
605                 sys_reset               => nvme_reset_local_n,
606                 phy_rdy_out             => leds(0),
607
608                 pci_exp_txn             => nvme_exp_txn,
609                 pci_exp_txp             => nvme_exp_txp,
610                 pci_exp_rxn             => nvme_exp_rxn,
611                 pci_exp_rxp             => nvme_exp_rxp,
612
613                 user_clk                => nvme_user_clk,
614                 user_reset              => nvme_user_reset,
615                 user_lnk_up             => leds(1),
616
617                 s_axis_rq_tdata         => hostReq.data,
618                 s_axis_rq_tkeep         => hostReq.keep,
619                 s_axis_rq_tlast         => hostReq.last,
620                 s_axis_rq_tready        => hostReq_ready,
621                 s_axis_rq_tuser         => hostReq_user,
622                 s_axis_rq_tvalid        => hostReq.valid,
623                 
624                 m_axis_rc_tdata         => hostReply.data,
625                 m_axis_rc_tkeep         => hostReply.keep,
626                 m_axis_rc_tlast         => hostReply.last,
627                 m_axis_rc_tready        => hostReply.ready,
628                 --m_axis_rc_tuser       => hostReply_user,
629                 m_axis_rc_tvalid        => hostReply.valid,
630                 
631                 m_axis_cq_tdata         => nvmeReq.data,
632                 m_axis_cq_tkeep         => nvmeReq.keep,
633                 m_axis_cq_tlast         => nvmeReq.last,
634                 m_axis_cq_tready        => nvmeReq.ready,
635                 --m_axis_cq_tuser       => nvmeReq_user,
636                 m_axis_cq_tvalid        => nvmeReq.valid,
637                 
638                 s_axis_cc_tdata         => nvmeReply.data,
639                 s_axis_cc_tkeep         => nvmeReply.keep,
640                 s_axis_cc_tlast         => nvmeReply.last,
641                 s_axis_cc_tready        => nvmeReply_ready,
642                 s_axis_cc_tuser         => nvmeReply_user,
643                 s_axis_cc_tvalid        => nvmeReply.valid,
644
645                 cfg_interrupt_int       => "0000",
646                 cfg_interrupt_pending   => "0000"
647                 --cfg_interrupt_sent    => --cfg_interrupt_sent,
648         );
649         end generate;
650         
651         genpci1: if(PcieCore = 1) generate
652         -- The PCIe to NVMe interface
653         pcie_nvme_1 : Pcie_nvme1
654         port map (
655                 sys_clk                 => nvme_clk,
656                 sys_clk_gt              => nvme_clk_gt,
657                 sys_reset               => nvme_reset_local_n,
658                 phy_rdy_out             => leds(0),
659
660                 pci_exp_txn             => nvme_exp_txn,
661                 pci_exp_txp             => nvme_exp_txp,
662                 pci_exp_rxn             => nvme_exp_rxn,
663                 pci_exp_rxp             => nvme_exp_rxp,
664
665                 user_clk                => nvme_user_clk,
666                 user_reset              => nvme_user_reset,
667                 user_lnk_up             => leds(1),
668
669                 s_axis_rq_tdata         => hostReq.data,
670                 s_axis_rq_tkeep         => hostReq.keep,
671                 s_axis_rq_tlast         => hostReq.last,
672                 s_axis_rq_tready        => hostReq_ready,
673                 s_axis_rq_tuser         => hostReq_user,
674                 s_axis_rq_tvalid        => hostReq.valid,
675                 
676                 m_axis_rc_tdata         => hostReply.data,
677                 m_axis_rc_tkeep         => hostReply.keep,
678                 m_axis_rc_tlast         => hostReply.last,
679                 m_axis_rc_tready        => hostReply.ready,
680                 --m_axis_rc_tuser       => hostReply_user,
681                 m_axis_rc_tvalid        => hostReply.valid,
682                 
683                 m_axis_cq_tdata         => nvmeReq.data,
684                 m_axis_cq_tkeep         => nvmeReq.keep,
685                 m_axis_cq_tlast         => nvmeReq.last,
686                 m_axis_cq_tready        => nvmeReq.ready,
687                 --m_axis_cq_tuser       => nvmeReq_user,
688                 m_axis_cq_tvalid        => nvmeReq.valid,
689                 
690                 s_axis_cc_tdata         => nvmeReply.data,
691                 s_axis_cc_tkeep         => nvmeReply.keep,
692                 s_axis_cc_tlast         => nvmeReply.last,
693                 s_axis_cc_tready        => nvmeReply_ready,
694                 s_axis_cc_tuser         => nvmeReply_user,
695                 s_axis_cc_tvalid        => nvmeReply.valid,
696
697                 cfg_interrupt_int       => "0000",
698                 cfg_interrupt_pending   => "0000"
699                 --cfg_interrupt_sent    => --cfg_interrupt_sent,
700         );
701         end generate;
702         
703         
704         -- Interface between Axis streams and PCIe Gen3 streams
705         hostReq.ready <= hostReq_ready(0);
706
707         -- The last_be bits in hostReq_user should be 0 when reading/writing less than 2 words due to the daft PCIe Gen3 core.
708         -- This code peeks at the PCIe TLP headers numDwords field and sets the be bits appropriately. Only valid in the first
709         -- beat of the 128bit wide data stream packet.
710         -- Warning: This may not be valid for message and atomic packets.
711         --hostReq_morethan1 <= reg_control(31);
712         hostReq_morethan1 <= '1' when(unsigned(hostReq.data(74 downto 64)) > 1) else '0';
713         hostReq_user <= x"00000000" & "0000" & "00000000" & "0" & "00" & "0" & "0" & "000" & "1111" & "1111" when(hostReq_morethan1 = '1')
714                 else x"00000000" & "0000" & "00000000" & "0" & "00" & "0" & "0" & "000" & "0000" & "1111";
715
716         nvmeReply.ready <= nvmeReply_ready(0) and nvmeReply_ready(1) and nvmeReply_ready(2) and nvmeReply_ready(3);
717         nvmeReply_user <= (others => '0');
718         
719         cfg_mgmt_addr <= (others => '0');
720         cfg_mgmt_write <= '0';
721         cfg_mgmt_write_data <= (others => '0');
722         cfg_mgmt_read <= '0';
723         cfg_mgmt_type1_cfg_reg_access <= '0';
724         
725
726         leds(2) <= '0';
727         end generate;
728         
729         -- Raw Host to Nvme communications
730         gen02: if false generate
731                 axisConnect(nvmeRecv, hostSend1);
732                 axisConnect(hostRecv1, nvmeSend);
733         end generate;
734         
735         -- Full switched communications
736         gen03: if true generate
737         set1: for i in 7 to 7 generate
738                 streamSend(i).valid     <= '0';
739                 streamRecv(i).ready     <= '1';
740         end generate;
741
742         streamSwitch0 : StreamSwitch
743         port map (
744                 clk             => nvme_user_clk,
745                 reset           => nvme_user_reset,
746
747                 streamIn        => streamSend,
748                 streamOut       => streamRecv
749         );
750         
751         nvmeQueues0: NvmeQueues
752         port map (
753                 clk             => nvme_user_clk,
754                 reset           => nvme_user_reset,
755
756                 streamIn        => queueRecv,
757                 streamOut       => queueSend
758         );
759
760         nvmeConfig0: NvmeConfig
761         port map (
762                 clk             => nvme_user_clk,
763                 reset           => nvme_user_reset,
764
765                 configStart     => configStart,
766                 configComplete  => configComplete,
767
768                 streamOut       => configSend,
769                 streamIn        => configRecv
770         );
771
772         -- Start config after reset
773         process(nvme_user_clk)
774         begin
775                 if(rising_edge(nvme_user_clk)) then
776                         if(nvme_user_reset = '1') then
777                                 configStart     <= '0';
778                                 configStartDone <= '0';
779                         else
780                                 if(UseConfigure and (configStartDone = '0')) then
781                                         configStart     <= '1';         -- Start the Nvme configuration
782                                         configStartDone <= '1';
783                                 elsif((configStartDone = '0') and (configComplete = '0') and (reg_control(1) = '1')) then
784                                         configStart     <= '1';         -- Start the Nvme configuration
785                                         configStartDone <= '1';
786                                 else
787                                         configStart     <= '0';
788                                 end if;
789                         end if;
790                 end if;
791         end process;
792         
793         -- The Data write processing
794         writeEnable     <= reg_control(2);
795         dataEnabledOut  <= writeEnable;
796         
797         nvmeWrite0: NvmeWrite
798         port map (
799                 clk             => nvme_user_clk,
800                 reset           => nvme_user_reset,
801
802                 enable          => writeEnable,
803                 dataIn          => dataIn1,
804
805                 requestOut      => writeSend,
806                 replyIn         => writeRecv,
807
808                 memReqIn        => writeMemRecv,
809                 memReplyOut     => writeMemSend,
810
811                 regWrite        => nvmeWrite_write,
812                 regAddress      => regAddress1(3 downto 0),
813                 regDataIn       => regDataIn1,
814                 regDataOut      => reg_nvmeWrite
815         );
816
817         -- The Data read processing
818         nvmeRead0: NvmeRead
819         port map (
820                 clk             => nvme_user_clk,
821                 reset           => nvme_user_reset,
822
823                 requestOut      => readSend,
824                 replyIn         => readRecv,
825
826                 regWrite        => nvmeRead_write,
827                 regAddress      => regAddress1(3 downto 0),
828                 regDataIn       => regDataIn1,
829                 regDataOut      => reg_nvmeRead
830         );
831
832         end generate;
833 end;