Added Nvme trim/deallocate functionality.
[DuneNvme.git] / src / NvmeSim.vhd
1 --------------------------------------------------------------------------------
2 -- NvmeSim.vhd Nvme storage simulation module
3 -------------------------------------------------------------------------------
4 --!
5 --! @class      NvmeSim
6 --! @author     Terry Barnaby (terry.barnaby@beam.ltd.uk)
7 --! @date       2020-03-13
8 --! @version    0.0.1
9 --!
10 --! @brief
11 --! This is a very basic module to simulate an NVMe device connected via PCIe to
12 --!  the Xilinx PCIe Gen3 IP block.
13 --!
14 --! @details
15 --! This is a very basic module to simulate an NVMe device connected via PCIe to the Xilinx PCIe Gen3 IP block.
16 --! 
17 --! It has a simple AXI4 Stream interface matching that as used by the Xilinx PCIe Gen3 IP block.
18 --! It is designed to help with the testing of the NvmeStorage blocks operation during simulation of the VHDL.
19 --!
20 --! The core responds to specific configuration space writes and specific NVMe register writes (Queue door bell registers).
21 --! The module makes PCIe read/write requests to access the request/reply queues and data input/output memory
22 --!  in a similar manner to a real NVMe device.
23 --!
24 --! Simple interface ignoring actual data values and 32bit dataword positions with 128 bit transfered words.
25 --!
26 --! NVMe requests not pipelined and carried out one at a time, in sequence.
27 --! Currently does not perform configuration or NVMe register read operations.
28 --! Currently does not handle NVMe read data requests.
29 --! Note NvmeSim still pretty basic.
30 --!
31 --! @copyright GNU GPL License
32 --! Copyright (c) Beam Ltd, All rights reserved. <br>
33 --! This code is free software: you can redistribute it and/or modify
34 --! it under the terms of the GNU General Public License as published by
35 --! the Free Software Foundation, either version 3 of the License, or
36 --! (at your option) any later version.
37 --! This program is distributed in the hope that it will be useful,
38 --! but WITHOUT ANY WARRANTY; without even the implied warranty of
39 --! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40 --! GNU General Public License for more details. <br>
41 --! You should have received a copy of the GNU General Public License
42 --! along with this code. If not, see <https://www.gnu.org/licenses/>.
43 --!
44 library ieee;
45 use ieee.std_logic_1164.all;
46 use ieee.numeric_std.all;
47
48 library unisim;
49 use unisim.vcomponents.all;
50
51 library work;
52 use work.NvmeStoragePkg.all;
53 use work.NvmeStorageIntPkg.all;
54
55 entity NvmeSim is
56 generic(
57         Simulate        : boolean := True;
58         BlockSize       : integer := NvmeStorageBlockSize       --! System block size
59 );
60 port (
61         clk             : in std_logic;                                 --! The input clock
62         reset           : in std_logic;                                 --! The reset line
63
64         -- AXIS Interface to PCIE
65         hostReq         : inout AxisStreamType := AxisStreamInput;              --! Host request stream
66         hostReply       : inout AxisStreamType := AxisStreamOutput;             --! Host reply stream
67
68         -- From Nvme reqeuest and reply stream
69         nvmeReq         : inout AxisStreamType := AxisStreamOutput;             --! Nvme request stream (bus master)
70         nvmeReply       : inout AxisStreamType := AxisStreamInput               --! Nvme reply stream
71 );
72 end;
73
74 architecture Behavioral of NvmeSim is
75
76 constant TCQ                    : time := 1 ns;
77 constant NumQueue               : integer := 16;                        --! Number of queue entries
78 constant RegWidth               : integer := 32;
79 constant NumWordsRead           : integer := BlockSize/4;               --! Number of 32bit Dwords in a block
80
81 subtype RegDataType             is std_logic_vector(RegWidth-1 downto 0);
82
83 -- Host requests
84 type ReqStateType               is (REQSTATE_IDLE, REQSTATE_WRITE, REQSTATE_READ, REQSTATE_REPLY);
85 signal reqState                 : ReqStateType := REQSTATE_IDLE;
86 signal hostRequestHead          : PcieRequestHeadType;
87 signal hostRequestHead1         : PcieRequestHeadType := set_PcieRequestHeadType(0, 0, 0, 0, 0);
88 signal hostReplyHead            : PcieReplyHeadType := set_PcieReplyHeadType(0, 0, 0, 0, 0);
89 signal hostReplyHead1           : PcieReplyHeadType := set_PcieReplyHeadType(0, 0, 0, 0, 0);
90 signal reg_pci_command          : RegDataType := (others => '0');
91 signal reg_admin_queue          : RegDataType := (others => '0');
92 signal reg_io1_queue            : RegDataType := (others => '0');
93 signal reg_io2_queue            : RegDataType := (others => '0');
94
95 -- Process queues
96 signal queueAdminIn             : integer range 0 to NumQueue-1 := 0;
97 signal queueAdminOut            : integer range 0 to NumQueue-1 := 0;
98 signal queueWriteIn             : integer range 0 to NumQueue-1 := 0;
99 signal queueWriteOut            : integer range 0 to NumQueue-1 := 0;
100 signal queueReadIn              : integer range 0 to NumQueue-1 := 0;
101 signal queueReadOut             : integer range 0 to NumQueue-1 := 0;
102
103 type StateType                  is (STATE_IDLE, STATE_READ_QUEUE_START, STATE_READ_QUEUE,
104                                         STATE_QUEUE_REPLY_HEAD, STATE_QUEUE_REPLY_DATA,
105                                         STATE_READ_DATA_START, STATE_READ_DATA_RECV_START, STATE_READ_DATA_RECV,
106                                         STATE_WRITE_DATA_START, STATE_WRITE_DATA_HEAD, STATE_WRITE_DATA,
107                                         STATE_REPLY_QUEUE);
108 type QueueRequestType           is array(0 to 15) of std_logic_vector(31 downto 0);
109
110 signal state                    : StateType := STATE_IDLE;
111 signal queue                    : integer range 0 to NumQueue-1 := 0;
112 signal queue_pos                : integer range 0 to NumQueue-1 := 0;
113 signal nvmeReply1               : AxisStreamType;                       --! Nvme reply stream for valid replies
114 signal nvmeRequestHead          : PcieRequestHeadType;
115 signal nvmeReply1Head           : PcieReplyHeadType;
116 signal regData                  : RegDataType := (others => '0');
117 signal streamNum                : integer := 1;
118 signal count                    : unsigned(10 downto 0);
119 signal chunkCount               : unsigned(10 downto 0);
120 signal queueRequest             : QueueRequestType := (others => (others => '0'));
121 signal queueRequestPos          : integer := 0;
122 signal waitingForReply          : std_logic := '0';
123
124 signal data                     : std_logic_vector(127 downto 0);
125 signal readData                 : unsigned(127 downto 0);
126
127 function queueNext(pos: integer) return integer is
128 begin
129         if(pos = (NumQueue - 1)) then
130                 return 0;
131         else
132                 return pos + 1;
133         end if;
134 end;
135
136 begin
137         -- Host requests including register access
138         hostRequestHead         <= to_PcieRequestHeadType(hostReq.data);
139         regData                 <= reg_pci_command when hostRequestHead1.address = x"4" else x"FFFFFFFF";
140
141         hostReplyHead.byteCount <= to_unsigned(4, hostReplyHead.byteCount'length);
142         hostReplyHead.error     <= to_unsigned(0, hostReplyHead.error'length);
143         hostReplyHead.address   <= hostRequestHead1.address(hostReplyHead.address'length-1 downto 0);
144         hostReplyHead.status    <= to_unsigned(0, hostReplyHead.status'length);
145         hostReplyHead.count     <= to_unsigned(1, hostReplyHead.count'length);
146         hostReplyHead.tag       <= hostRequestHead1.tag;
147         hostReplyHead.requesterId       <= hostRequestHead1.requesterId;
148
149         data                    <= concat('0', 32) & to_stl(hostReplyHead);
150         hostReply.data          <= zeros(32) & to_stl(hostReplyHead1) when(reqState = REQSTATE_REPLY)
151                                         else regData & data(95 downto 0);
152                 
153
154
155         nvmeReq.data            <= zeros(16)  & queueRequest(0)(31 downto 16) & zeros(96) when(state = STATE_QUEUE_REPLY_DATA)
156                                         else to_stl(readData) when(state = STATE_WRITE_DATA)
157                                         else to_stl(nvmeRequestHead);
158         nvmeReply1Head          <= to_PcieReplyHeadType(nvmeReply1.data);
159
160         -- Process host requests
161         process(clk)
162         begin
163                 if(rising_edge(clk)) then
164                         if(reset = '1') then
165                                 hostReq.ready   <= '0';
166                                 hostReply.valid <= '0';
167                                 hostReply.last  <= '0';
168                                 reg_pci_command <= (others => '0');
169                                 reg_admin_queue <= (others => '0');
170                                 reg_io1_queue   <= (others => '0');
171                                 reg_io2_queue   <= (others => '0');
172                                 queueAdminIn    <= 0;
173                                 queueWriteIn    <= 0;
174                                 queueReadIn     <= 0;
175                                 reqState        <= REQSTATE_IDLE;
176                         else
177                                 case(reqState) is
178                                 when REQSTATE_IDLE =>
179                                         if(hostReq.ready = '1' and hostReq.valid= '1') then
180                                                 hostRequestHead1 <= hostRequestHead;
181
182                                                 if((hostRequestHead.request = 10) or (hostRequestHead.request = 1)) then
183                                                         reqState <= REQSTATE_WRITE;
184                                                 elsif(hostRequestHead.request = 8) then
185                                                         reqState <= REQSTATE_READ;
186                                                 end if;
187                                         else
188                                                 hostReq.ready   <= '1';
189                                         end if;
190
191                                 when REQSTATE_WRITE =>
192                                         if(hostReq.ready = '1' and hostReq.valid= '1') then
193                                                 if(hostRequestHead1.request = 10) then
194                                                         if(hostRequestHead1.address = x"0004") then
195                                                                 reg_pci_command <= hostReq.data(31 downto 0);
196                                                         end if;
197                                                         reqState <= REQSTATE_REPLY;
198                                                 else 
199                                                         if(hostRequestHead1.address = x"1000") then
200                                                                 reg_admin_queue <= hostReq.data(31 downto 0);
201                                                                 queueAdminIn    <= to_integer(unsigned(hostReq.data(3 downto 0)));
202                                                         elsif(hostRequestHead1.address = x"1008") then
203                                                                 reg_io1_queue   <= hostReq.data(31 downto 0);
204                                                                 queueWriteIn    <= to_integer(unsigned(hostReq.data(3 downto 0)));
205                                                         elsif(hostRequestHead1.address = x"1010") then
206                                                                 reg_io2_queue   <= hostReq.data(31 downto 0);
207                                                                 queueReadIn     <= to_integer(unsigned(hostReq.data(3 downto 0)));
208                                                         end if;
209
210                                                         reqState <= REQSTATE_IDLE;
211                                                 end if;
212
213                                                 hostReq.ready <= '0';
214                                         end if;
215
216                                 when REQSTATE_REPLY =>
217                                         hostReplyHead1.byteCount        <= to_unsigned(0, hostReplyHead1.byteCount'length);
218                                         hostReplyHead1.address          <= to_unsigned(0, hostReplyHead1.address'length);
219                                         hostReplyHead1.error            <= to_unsigned(0, hostReplyHead1.error'length);
220                                         hostReplyHead1.status           <= to_unsigned(0, hostReplyHead1.status'length);
221                                         hostReplyHead1.tag              <= hostRequestHead1.tag;
222                                         hostReplyHead1.requesterId      <= hostRequestHead1.requesterId;
223
224                                         if(hostReply.ready = '1' and hostReply.valid= '1') then
225                                                 hostReply.valid <= '0';
226                                                 hostReply.last  <= '0';
227                                                 reqState        <= REQSTATE_IDLE;
228                                         else
229                                                 hostReply.valid <= '1';
230                                                 hostReply.last  <= '1';
231                                                 hostReply.keep  <= "0111";
232                                         end if;
233                                         
234
235                                 when REQSTATE_READ =>
236                                         if(hostReply.ready = '1' and hostReply.valid= '1') then
237                                                 hostReply.valid <= '0';
238                                                 hostReply.last  <= '0';
239                                                 reqState        <= REQSTATE_IDLE;
240                                         else
241                                                 hostReply.valid <= '1';
242                                                 hostReply.last  <= '1';
243                                                 hostReply.keep  <= ones(hostReply.keep'length);
244                                         end if;
245                                 end case;
246                         end if;
247                 end if;
248         end process;
249
250
251         -- Process requests
252         process(clk)
253         begin
254                 if(rising_edge(clk)) then
255                         if(reset = '1') then
256                                 queueWriteOut   <= 0;
257                                 queueReadOut    <= 0;
258                                 queue           <= 0;
259                                 queue_pos       <= 0;
260                                 nvmeReq.valid   <= '0';
261                                 nvmeReq.last    <= '0';
262                                 nvmeReply1.ready <= '0';
263                                 nvmeRequestHead <= to_PcieRequestHeadType(concat('0', 128));
264                                 state           <= STATE_IDLE;
265                         else
266                                 case(state) is
267                                 when STATE_IDLE =>
268                                         if(queueAdminIn /= queueAdminOut) then
269                                                 queue           <= 0;
270                                                 queue_pos       <= queueAdminOut;
271                                                 queueAdminOut   <= queueNext(queueAdminOut);
272                                                 state           <= STATE_READ_QUEUE_START;
273                                         elsif(queueWriteIn /= queueWriteOut) then
274                                                 queue           <= 1;
275                                                 queue_pos       <= queueWriteOut;
276                                                 queueWriteOut   <= queueNext(queueWriteOut);
277                                                 state           <= STATE_READ_QUEUE_START;
278                                         elsif(queueReadIn /= queueReadOut) then
279                                                 queue           <= 2;
280                                                 queue_pos       <= queueReadOut;
281                                                 queueReadOut    <= queueNext(queueReadOut);
282                                                 state           <= STATE_READ_QUEUE_START;
283                                         end if;
284
285                                 when STATE_READ_QUEUE_START =>
286                                         -- Perform bus master read request for queue data
287                                         nvmeRequestHead.address <= x"020" & to_unsigned(queue, 4) & zeros(6) & to_unsigned(queue_pos, 4) & zeros(6);
288                                         nvmeRequestHead.tag     <= x"44";
289                                         nvmeRequestHead.requesterId     <= to_unsigned(0, nvmeRequestHead.requesterId'length);
290                                         nvmeRequestHead.request <= "0000";
291                                         nvmeRequestHead.count   <= to_unsigned(16#0010#, nvmeRequestHead.count'length);
292                                         nvmeReq.keep            <= ones(nvmeReq.keep'length);
293                                         nvmeReq.valid           <= '1';
294                                         nvmeReq.last            <= '1';
295                                         
296                                         if(nvmeReq.valid = '1' and nvmeReq.ready = '1') then
297                                                 count           <= nvmeRequestHead.count;
298                                                 queueRequestPos <= 0;
299                                                 nvmeReq.valid   <= '0';
300                                                 nvmeReq.last    <= '0';
301                                                 nvmeReply1.ready <= '1';
302                                                 waitingForReply <= '1';
303                                                 state           <= STATE_READ_QUEUE;
304                                         end if;
305
306                                 when STATE_READ_QUEUE =>
307                                         -- Read in queue data, generally ignoring it
308                                         if(nvmeReply1.valid = '1' and nvmeReply1.ready = '1') then
309                                                 if(count = 16) then
310                                                         queueRequest(queueRequestPos)   <= nvmeReply1.data(127 downto 96);
311                                                         queueRequestPos                 <= queueRequestPos + 1;
312                                                 elsif(count = 0) then
313                                                         queueRequest(queueRequestPos)   <= nvmeReply1.data(31 downto 0);
314                                                         queueRequest(queueRequestPos+1) <= nvmeReply1.data(63 downto 32);
315                                                         queueRequest(queueRequestPos+2) <= nvmeReply1.data(95 downto 64);
316                                                         queueRequestPos                 <= queueRequestPos + 3;
317                                                 else
318                                                         queueRequest(queueRequestPos)   <= nvmeReply1.data(31 downto 0);
319                                                         queueRequest(queueRequestPos+1) <= nvmeReply1.data(63 downto 32);
320                                                         queueRequest(queueRequestPos+2) <= nvmeReply1.data(95 downto 64);
321                                                         queueRequest(queueRequestPos+3) <= nvmeReply1.data(127 downto 96);
322                                                         queueRequestPos                 <= queueRequestPos + 4;
323                                                 end if;
324
325                                                 count <= count - 4;
326                                                 if(count = 0) then
327                                                         nvmeReply1.ready        <= '0';
328                                                         waitingForReply         <= '0';
329
330                                                         if(queue = 0) then
331                                                                 -- Writes an entry into the Admin reply queue. Simply uses info in that last queued request. So only one request at a time.
332                                                                 -- Note data sent to queue is just the header reapeated so junk data ATM.
333                                                                 -- Perform bus master read request for data to write to NVMe
334                                                                 nvmeRequestHead.address <= to_unsigned(16#02100000#, nvmeRequestHead.address'length);
335                                                                 nvmeRequestHead.tag     <= x"44";
336                                                                 nvmeRequestHead.request <= "0001";
337                                                                 nvmeRequestHead.count   <= to_unsigned(16#0004#, nvmeRequestHead.count'length); -- 16 Byte queue entry
338                                                                 count                   <= to_unsigned(16#0004#, count'length); -- 16 Byte queue entry
339                                                                 nvmeReq.keep            <= ones(nvmeReq.keep'length);
340                                                                 nvmeReq.valid           <= '1';
341                                                                 state                   <= STATE_QUEUE_REPLY_HEAD;
342                                                         else
343                                                                 if(unsigned(queueRequest(0)(7 downto 0)) = 1) then
344                                                                         state <= STATE_READ_DATA_START;
345                                                                 elsif(unsigned(queueRequest(0)(7 downto 0)) = 2) then
346                                                                         state <= STATE_WRITE_DATA_START;
347                                                                 else
348                                                                         state <= STATE_REPLY_QUEUE;
349                                                                 end if;
350                                                         end if;
351                                                 end if;
352                                         end if;
353
354                                 when STATE_QUEUE_REPLY_HEAD =>
355                                         if(nvmeReq.valid = '1' and nvmeReq.ready = '1') then
356                                                 nvmeReq.last    <= '1';
357                                                 state           <= STATE_QUEUE_REPLY_DATA;
358                                         end if;
359
360                                 when STATE_QUEUE_REPLY_DATA =>
361                                         if(nvmeReq.valid = '1' and nvmeReq.ready = '1') then
362                                                 nvmeReq.last    <= '0';
363                                                 nvmeReq.valid   <= '0';
364                                                 state           <= STATE_IDLE;
365                                         end if;
366
367                                 when STATE_READ_DATA_START =>
368                                         -- Perform bus master read request for data to write to NVMe
369                                         nvmeRequestHead.address <= unsigned(queueRequest(6));
370                                         --nvmeRequestHead.address       <= to_unsigned(16#05000000#, nvmeRequestHead.address'length);
371                                         nvmeRequestHead.tag     <= x"44";
372                                         nvmeRequestHead.request <= "0000";
373                                         nvmeRequestHead.count   <= to_unsigned(NumWordsRead, nvmeRequestHead.count'length);                             -- Test size of 32 DWords
374
375                                         if(nvmeReq.valid = '1' and nvmeReq.ready = '1') then
376                                                 count           <= nvmeRequestHead.count;       -- Note ignoring 1 DWord in first 128 bits
377                                                 nvmeReq.last    <= '0';
378                                                 nvmeReq.valid   <= '0';
379                                                 nvmeReply1.ready <= '1';
380                                                 waitingForReply <= '1';
381                                                 state           <= STATE_READ_DATA_RECV_START;
382                                         else
383                                                 nvmeReq.keep    <= ones(nvmeReq.keep'length);
384                                                 nvmeReq.last    <= '1';
385                                                 nvmeReq.valid   <= '1';
386                                         end if;
387
388                                 when STATE_READ_DATA_RECV_START =>
389                                         -- Read in write data ignoring it
390                                         if(nvmeReply1.valid = '1' and nvmeReply1.ready = '1') then
391                                                 chunkCount      <= nvmeReply1Head.count;
392                                                 state           <= STATE_READ_DATA_RECV;
393                                         end if;
394
395                                 when STATE_READ_DATA_RECV =>
396                                         -- Read in write data ignoring it
397                                         if(nvmeReply1.valid = '1' and nvmeReply1.ready = '1') then
398                                                 if(chunkCount = 4) then
399                                                         if(count = 4) then
400                                                                 nvmeReply1.ready<= '0';
401                                                                 waitingForReply <= '0';
402                                                                 state           <= STATE_REPLY_QUEUE;
403                                                         else
404                                                                 state           <= STATE_READ_DATA_RECV_START;
405                                                         end if;
406                                                 end if;
407
408                                                 count           <= count - 4;
409                                                 chunkCount      <= chunkCount - 4;
410                                         end if;
411
412
413                                 when STATE_WRITE_DATA_START =>
414                                         -- Perform bus master write request for data to write to NVMe
415                                         -- Initialise the header
416                                         nvmeRequestHead.address <= unsigned(queueRequest(6));
417                                         nvmeRequestHead.tag     <= x"44";
418                                         nvmeRequestHead.request <= "0001";
419
420                                         count           <= to_unsigned(NumWordsRead, count'length);     -- Note hard coded length of 1 block
421                                         readData        <= (others => '0');
422                                         waitingForReply <= '0';
423                                         state           <= STATE_WRITE_DATA_HEAD;
424
425                                 when STATE_WRITE_DATA_HEAD =>
426                                         -- Send the updated header
427
428                                         if(count > PcieMaxPayloadSize) then
429                                                 nvmeRequestHead.count   <= to_unsigned(PcieMaxPayloadSize, nvmeRequestHead.count'length);
430                                                 chunkCount              <= to_unsigned(PcieMaxPayloadSize, chunkCount'length);
431                                         else
432                                                 nvmeRequestHead.count   <= count;
433                                                 chunkCount              <= count;
434                                         end if;
435                                         
436                                         if(nvmeReq.valid = '1' and nvmeReq.ready = '1') then
437                                                 nvmeReq.last    <= '0';
438                                                 state           <= STATE_WRITE_DATA;
439                                         else
440                                                 nvmeReq.keep    <= ones(nvmeReq.keep'length);
441                                                 nvmeReq.last    <= '0';
442                                                 nvmeReq.valid   <= '1';
443                                         end if;
444
445                                 when STATE_WRITE_DATA =>
446                                         -- Read in write data ignoring it
447                                         if(nvmeReq.valid = '1' and nvmeReq.ready = '1') then
448                                                 if(chunkCount = 4) then
449                                                         nvmeReq.last    <= '0';
450                                                         nvmeReq.valid   <= '0';
451
452                                                         if(count = 4) then
453                                                                 nvmeReply1.ready<= '0';
454                                                                 state           <= STATE_REPLY_QUEUE;
455                                                         else
456                                                                 nvmeRequestHead.address <= nvmeRequestHead.address + (nvmeRequestHead.count * 4);
457                                                                 state           <= STATE_WRITE_DATA_HEAD;
458                                                         end if;
459                                                 elsif(chunkCount = 8) then
460                                                         nvmeReq.last    <= '1';
461                                                 end if;
462                                                 readData        <= readData + 1;
463                                                 count           <= count - 4;
464                                                 chunkCount      <= chunkCount - 4;
465                                         end if;
466
467
468
469
470                                 when STATE_REPLY_QUEUE =>
471                                         -- Send reply queue header
472                                         -- Writes an entry into the DataWRite reply queue. Simply uses info in that last queued request. So only one request at a time.
473                                         -- Note data sent to queue is just the header reapeated so junk data ATM.
474                                         nvmeRequestHead.address <= x"021" & to_unsigned(queue, 4) & zeros(16);
475                                         nvmeRequestHead.tag     <= x"44";
476                                         nvmeRequestHead.request <= "0001";
477                                         nvmeRequestHead.count   <= to_unsigned(16#0004#, nvmeRequestHead.count'length); -- 16 Byte queue entry
478                                         count                   <= to_unsigned(16#0004#, count'length); -- 16 Byte queue entry
479                                         nvmeReq.keep            <= ones(nvmeReq.keep'length);
480                                         nvmeReq.valid           <= '1';
481                                         state                   <= STATE_QUEUE_REPLY_HEAD;
482
483                                 end case;
484                         end if;
485                 end if;
486         end process; 
487
488         -- Process nvme replies. This keeps the nvmeReply stream open for business to allow the stream multiplexor to work
489         -- with the StreamSwitch.
490         nvmeReply1.valid        <= nvmeReply.valid;
491         nvmeReply1.last         <= nvmeReply.last;
492         nvmeReply1.keep         <= nvmeReply.keep;
493         nvmeReply1.data         <= nvmeReply.data;
494         nvmeReply.ready         <= nvmeReply1.ready when(waitingForReply = '1') else '1';
495
496         process(clk)
497         begin
498                 if(rising_edge(clk)) then
499                         if((nvmeReply.valid = '1') and (waitingForReply = '0')) then
500                                 assert false report "NvmeSim had unexpected nvmeReply" severity failure;
501                         end if;
502                 end if;
503         end process;
504
505 end;