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