Now supports multiple NVMe clock inputs.
[DuneNvme.git] / src / DuneNvmeTestTop.vhd
1 --------------------------------------------------------------------------------
2 -- DuneNvmeTestTop.vhd Simple NVMe access test system
3 --------------------------------------------------------------------------------
4 --!
5 --! @class      DuneNvmeTestTop
6 --! @author     Terry Barnaby (terry.barnaby@beam.ltd.uk)
7 --! @date       2020-05-12
8 --! @version    0.5.1
9 --!
10 --! @brief
11 --! This FPGA bit file allows a host computer to access a NVMe storage device
12 --!  connected to the FPGA via the hosts PCIe interface. It allows a host computer
13 --!  program to communicate with the NVMe device for research and developemnt test work.
14 --!
15 --! @details
16 --!
17 --! @copyright GNU GPL License
18 --! Copyright (c) Beam Ltd, All rights reserved. <br>
19 --! This code is free software: you can redistribute it and/or modify
20 --! it under the terms of the GNU General Public License as published by
21 --! the Free Software Foundation, either version 3 of the License, or
22 --! (at your option) any later version.
23 --! This program is distributed in the hope that it will be useful,
24 --! but WITHOUT ANY WARRANTY; without even the implied warranty of
25 --! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 --! GNU General Public License for more details. <br>
27 --! You should have received a copy of the GNU General Public License
28 --! along with this code. If not, see <https://www.gnu.org/licenses/>.
29 --!
30 library ieee;
31 use ieee.std_logic_1164.all;
32 use ieee.numeric_std.all;
33
34 library unisim;
35 use unisim.vcomponents.all;
36
37 library work;
38 use work.NvmeStoragePkg.all;
39
40 entity DuneNvmeTestTop is
41 generic(
42         Simulate        : boolean       := False
43 );
44 port (
45         sys_clk_p       : in std_logic;
46         sys_clk_n       : in std_logic;
47         sys_reset       : in std_logic;
48
49         pci_clk_p       : in std_logic;
50         pci_clk_n       : in std_logic;
51         pci_reset_n     : in std_logic;
52         
53         pci_exp_txp     : out std_logic_vector(3 downto 0);
54         pci_exp_txn     : out std_logic_vector(3 downto 0);
55         pci_exp_rxp     : in std_logic_vector(3 downto 0);
56         pci_exp_rxn     : in std_logic_vector(3 downto 0);
57
58         nvme_clk_p      : in std_logic;
59         nvme_clk_n      : in std_logic;
60         nvme_reset_n    : out std_logic;
61
62         nvme0_exp_txp   : out std_logic_vector(3 downto 0);
63         nvme0_exp_txn   : out std_logic_vector(3 downto 0);
64         nvme0_exp_rxp   : in std_logic_vector(3 downto 0);
65         nvme0_exp_rxn   : in std_logic_vector(3 downto 0);
66
67         nvme1_exp_txp   : out std_logic_vector(3 downto 0);
68         nvme1_exp_txn   : out std_logic_vector(3 downto 0);
69         nvme1_exp_rxp   : in std_logic_vector(3 downto 0);
70         nvme1_exp_rxn   : in std_logic_vector(3 downto 0);
71
72         leds            : out std_logic_vector(7 downto 0)
73 );
74 end;
75
76 architecture Behavioral of DuneNvmeTestTop is
77
78 component Clk_core is                   
79 port (
80         clk_in1_p       : in std_logic; 
81         clk_in1_n       : in std_logic;
82         clk_out1        : out std_logic;
83         locked          : out std_logic
84 );                                     
85 end component;                 
86
87 component Pcie_host
88 port (
89         sys_clk : in std_logic;
90         sys_clk_gt : in std_logic;
91         sys_rst_n : in std_logic;
92         user_lnk_up : out std_logic;
93         pci_exp_txp : out std_logic_vector(3 downto 0);
94         pci_exp_txn : out std_logic_vector(3 downto 0);
95         pci_exp_rxp : in std_logic_vector(3 downto 0);
96         pci_exp_rxn : in std_logic_vector(3 downto 0);
97         axi_aclk : out std_logic;
98         axi_aresetn : out std_logic;
99         usr_irq_req : in std_logic_vector(0 downto 0);
100         usr_irq_ack : out std_logic_vector(0 downto 0);
101         msi_enable : out std_logic;
102         msi_vector_width : out std_logic_vector(2 downto 0);
103         m_axil_awaddr : out std_logic_vector(31 downto 0);
104         m_axil_awprot : out std_logic_vector(2 downto 0);
105         m_axil_awvalid : out std_logic;
106         m_axil_awready : in std_logic;
107         m_axil_wdata : out std_logic_vector(31 downto 0);
108         m_axil_wstrb : out std_logic_vector(3 downto 0);
109         m_axil_wvalid : out std_logic;
110         m_axil_wready : in std_logic;
111         m_axil_bvalid : in std_logic;
112         m_axil_bresp : in std_logic_vector(1 downto 0);
113         m_axil_bready : out std_logic;
114         m_axil_araddr : out std_logic_vector(31 downto 0);
115         m_axil_arprot : out std_logic_vector(2 downto 0);
116         m_axil_arvalid : out std_logic;
117         m_axil_arready : in std_logic;
118         m_axil_rdata : in std_logic_vector(31 downto 0);
119         m_axil_rresp : in std_logic_vector(1 downto 0);
120         m_axil_rvalid : in std_logic;
121         m_axil_rready : out std_logic;
122         cfg_mgmt_addr : in std_logic_vector(18 downto 0);
123         cfg_mgmt_write : in std_logic;
124         cfg_mgmt_write_data : in std_logic_vector(31 downto 0);
125         cfg_mgmt_byte_enable : in std_logic_vector(3 downto 0);
126         cfg_mgmt_read : in std_logic;
127         cfg_mgmt_read_data : out std_logic_vector(31 downto 0);
128         cfg_mgmt_read_write_done : out std_logic;
129         cfg_mgmt_type1_cfg_reg_access : in std_logic;
130         s_axis_c2h_tdata_0 : in std_logic_vector(127 downto 0);
131         s_axis_c2h_tlast_0 : in std_logic;
132         s_axis_c2h_tvalid_0 : in std_logic;
133         s_axis_c2h_tready_0 : out std_logic;
134         s_axis_c2h_tkeep_0 : in std_logic_vector(15 downto 0);
135         m_axis_h2c_tdata_0 : out std_logic_vector(127 downto 0);
136         m_axis_h2c_tlast_0 : out std_logic;
137         m_axis_h2c_tvalid_0 : out std_logic;
138         m_axis_h2c_tready_0 : in std_logic;
139         m_axis_h2c_tkeep_0 : out std_logic_vector(15 downto 0);
140
141         int_qpll1lock_out : out std_logic_vector(0 to 0);
142         int_qpll1outrefclk_out : out std_logic_vector(0 to 0);
143         int_qpll1outclk_out : out std_logic_vector(0 to 0)
144 );
145 end component;
146
147 -- Clock and controls
148 signal sys_clk                  : std_logic := 'U';
149
150 signal pci_clk                  : std_logic := 'U';
151 signal pci_clk_gt               : std_logic := 'U';
152 signal nvme_clk                 : std_logic := 'U';
153 signal nvme_clk_gt              : std_logic := 'U';
154
155 signal leds_l                   : std_logic_vector(7 downto 0) := (others => '0');
156
157 signal axil_clk                 : std_logic;
158 signal axil_reset_n             : std_logic;
159 signal axil_reset               : std_logic;
160
161 signal axil                     : AxilBusType;                  --! The AXI lite bus
162 signal hostSend                 : AxisType;                     --! AXI stream to send requests from the host
163 signal hostSend_ready           : std_logic;
164 signal hostRecv                 : AxisType;                     --! AXI stream for replies to the host
165 signal hostrecv_ready           : std_logic;
166 signal dataStream               : AxisDataStreamType;           --! AXI stream for test data
167 signal dataStream_ready         : std_logic;
168 signal dataEnabled              : std_logic;                    --! Enabled signal for test data
169
170 begin
171         -- System clock just used for a boot reset
172         sys_clk_buf : Clk_core port map (
173                 clk_in1_p       => sys_clk_p,
174                 clk_in1_n       => sys_clk_n,
175                 clk_out1        => sys_clk
176         );
177
178         -- PCIE Clock, 100MHz
179         pci_clk_buf0 : IBUFDS_GTE3 port map (
180                 I       => pci_clk_p,
181                 IB      => pci_clk_n,
182                 O       => pci_clk_gt,
183                 ODIV2   => pci_clk,
184                 CEB     => '0'
185         );
186         
187         -- NVME PCIE Clock, 100MHz. Clock shared between both Nvme devices
188         nvme_clk_buf0 : IBUFDS_GTE3 port map (
189                 I       => nvme_clk_p,
190                 IB      => nvme_clk_n,
191                 O       => nvme_clk_gt,
192                 ODIV2   => nvme_clk,
193                 CEB     => '0'
194         );
195         
196         -- The PCIe interface to the host
197         pcie_host0 : Pcie_host
198         port map (
199                 sys_clk                 => pci_clk,
200                 sys_clk_gt              => pci_clk_gt,
201                 sys_rst_n               => pci_reset_n,
202                 pci_exp_txp             => pci_exp_txp,
203                 pci_exp_txn             => pci_exp_txn,
204                 pci_exp_rxp             => pci_exp_rxp,
205                 pci_exp_rxn             => pci_exp_rxn,
206                 
207                 user_lnk_up             => leds_l(7),
208
209                 usr_irq_req             => (others => '0'),
210                 --usr_irq_ack           => usr_irq_ack,
211                 --msi_enable            => msi_enable,
212                 --msi_vector_width      => msi_vector_width,
213
214                 axi_aclk                => axil_clk,
215                 axi_aresetn             => axil_reset_n,
216
217                 m_axil_awaddr           => axil.toSlave.awaddr,
218                 m_axil_awprot           => axil.toSlave.awprot,
219                 m_axil_awvalid          => axil.toSlave.awvalid,
220                 m_axil_awready          => axil.toMaster.awready,
221                 m_axil_wdata            => axil.toSlave.wdata,
222                 m_axil_wstrb            => axil.toSlave.wstrb,
223                 m_axil_wvalid           => axil.toSlave.wvalid,
224                 m_axil_wready           => axil.toMaster.wready,
225                 m_axil_bvalid           => axil.toMaster.bvalid,
226                 m_axil_bresp            => axil.toMaster.bresp,
227                 m_axil_bready           => axil.toSlave.bready,
228                 m_axil_araddr           => axil.toSlave.araddr,
229                 m_axil_arprot           => axil.toSlave.arprot,
230                 m_axil_arvalid          => axil.toSlave.arvalid,
231                 m_axil_arready          => axil.toMaster.arready,
232                 m_axil_rdata            => axil.toMaster.rdata,
233                 m_axil_rresp            => axil.toMaster.rresp,
234                 m_axil_rvalid           => axil.toMaster.rvalid,
235                 m_axil_rready           => axil.toSlave.rready,
236                 
237                 cfg_mgmt_addr           => (others => '0'),
238                 cfg_mgmt_write          => '0',
239                 cfg_mgmt_write_data     => (others => '0'),
240                 cfg_mgmt_byte_enable    => (others => '0'),
241                 cfg_mgmt_read           => '0',
242                 --cfg_mgmt_read_data            => cfg_mgmt_read_data,
243                 --cfg_mgmt_read_write_done      => cfg_mgmt_read_write_done,
244                 cfg_mgmt_type1_cfg_reg_access   => '0',
245
246                 s_axis_c2h_tdata_0      => hostRecv.data,
247                 s_axis_c2h_tlast_0      => hostRecv.last,
248                 s_axis_c2h_tvalid_0     => hostRecv.valid,
249                 s_axis_c2h_tready_0     => hostRecv_ready,
250                 s_axis_c2h_tkeep_0      => hostRecv.keep,
251
252                 m_axis_h2c_tdata_0      => hostSend.data,
253                 m_axis_h2c_tlast_0      => hostSend.last,
254                 m_axis_h2c_tvalid_0     => hostSend.valid,
255                 m_axis_h2c_tready_0     => hostSend_ready,
256                 m_axis_h2c_tkeep_0      => hostSend.keep
257         );
258
259         -- NVME Storage interface
260         axil_reset <= not axil_reset_n;
261         
262         nvmeStorage0 : NvmeStorage
263         port map (
264                 clk             => axil_clk,
265                 reset           => axil_reset,
266
267                 -- Control and status interface
268                 axilIn          => axil.toSlave,
269                 axilOut         => axil.toMaster,
270
271                 -- From host to NVMe request/reply streams
272                 hostSend        => hostSend,
273                 hostSend_ready  => hostSend_ready,
274                 hostRecv        => hostRecv,
275                 hostRecv_ready  => hostRecv_ready,
276
277                 -- AXIS data stream input
278                 dataDropBlocks  => '0',
279                 dataEnabledOut  => dataEnabled,
280                 dataIn          => dataStream,
281                 dataIn_ready    => dataStream_ready,
282
283                 -- NVMe interface
284                 nvme_reset_n    => nvme_reset_n,
285
286                 nvme0_clk       => nvme_clk,
287                 nvme0_clk_gt    => nvme_clk_gt,
288                 nvme0_exp_txp   => nvme0_exp_txp,
289                 nvme0_exp_txn   => nvme0_exp_txn,
290                 nvme0_exp_rxp   => nvme0_exp_rxp,
291                 nvme0_exp_rxn   => nvme0_exp_rxn,
292
293                 nvme1_clk       => nvme_clk,
294                 nvme1_clk_gt    => nvme_clk_gt,
295                 nvme1_exp_txp   => nvme1_exp_txp,
296                 nvme1_exp_txn   => nvme1_exp_txn,
297                 nvme1_exp_rxp   => nvme1_exp_rxp,
298                 nvme1_exp_rxn   => nvme1_exp_rxn,
299
300                 -- Debug
301                 leds            => leds_l(5 downto 0)
302         );
303
304         -- The test data interface
305         testData0 : TestData
306         port map (
307                 clk             => axil_clk,
308                 reset           => axil_reset,
309
310                 enable          => dataEnabled,
311
312                 dataOut         => dataStream,
313                 dataOutReady    => dataStream_ready
314         );
315
316         -- Led buffers
317         obuf_leds: for i in 0 to 7 generate
318                 obuf_led_i: OBUF port map (I => leds_l(i), O => leds(i));
319         end generate;
320
321         leds_l(6) <= '0';
322 end;
323