Documentation updates in VHDL.
authorTerry Barnaby <terry.barnaby@beam.beam.ltd.uk>
Mon, 1 Jun 2020 08:16:27 +0000 (09:16 +0100)
committerTerry Barnaby <terry.barnaby@beam.beam.ltd.uk>
Mon, 1 Jun 2020 08:16:27 +0000 (09:16 +0100)
Improved PcieStreamMux implementation.

28 files changed:
Config.mk
docsrc/fpga_overview.dox
docsrc/host_overview.dox
sim/testbench/test009-packets.sav
sim/testbench/test009-packets.vhd
src/AxilClockConverter.vhd
src/AxisClockConverter.vhd
src/AxisDataConvertFifo.vhd
src/Cdc.vhd
src/DuneNvmeTestTop.vhd
src/DuneNvmeTestUnitTop.vhd [deleted file]
src/DuneNvmeTestUnitTop.xdc [deleted file]
src/NvmeConfig.vhd
src/NvmeQueues.vhd
src/NvmeRead.vhd
src/NvmeSim.vhd
src/NvmeStorage.vhd
src/NvmeStorageIntPkg.vhd
src/NvmeStoragePkg.vhd
src/NvmeStorageUnit.vhd
src/NvmeStreamMux.vhd
src/NvmeWrite.vhd
src/PcieStreamMux.vhd
src/Ram.vhd
src/RegAccessClockConvertor.vhd
src/StreamSwitch.vhd
src/TestData.vhd
src/TestDataStream.vhd

index a2723f2370a4c45409f35b84bc7eca40f9eaa536..f8fc97ac2e694df218c5bba93568f1ed35a08505 100644 (file)
--- a/Config.mk
+++ b/Config.mk
@@ -4,5 +4,5 @@
 ################################################################################
 #
 PROJECT                = DuneNvme
-VERSION                = 0.4.1
+VERSION                = 1.0.0
 DOCDIR         ?= 
index 2dedac1913909d68451658c363408aa2d0693ca1..fea74ad8730c7bf5da02426f81cd7fcb9ff7c211 100644 (file)
@@ -4,8 +4,8 @@
  */
 /**
 \author Dr Terry Barnaby
-\version 0.4.1
-\date 2020-05-21
+\version 1.0.0
+\date 2020-05-30
 
 \mainpage
 
index dbf1c199818b9c9199d0c3250f25681955b31d0c..437edf1402ef38ddf0307a1e781a1f04104b6a3f 100644 (file)
@@ -4,8 +4,8 @@
  */
 /**
 \author Dr Terry Barnaby
-\version 0.4.1
-\date 2020-05-21
+\version 1.0.0
+\date 2020-05-30
 
 \mainpage
 
@@ -30,8 +30,10 @@ and <a href="../../DuneNvmeStorageDesign.pdf">DuneNvmeStorageDesign</a> document
 
 \section The Test Program
 The test Linux host program is in the test directory and is called nvme_test. This program communicates with an NVMe devices
-through the FPGA connected to the host machines PCIe bus. This program allows experimentation with the NVMe low level PCIe interface.
+through the FPGA connected to the host machines PCIe bus. This program provides the ability to test the NvmeStorage module as
+well as allowing experimentation with the NVMe low level PCIe interface.
 Included is a simple Linux driver, bfpga, that interfaces to the Xilinx PCIe DMA core.
+See the <a href="../../DuneNvmeStorageManual.pdf">DuneNvmeStorageManual</a> for details on the test software and its usage.
 
 \section Building the test software
 <ol>
index 659f63d1808df96a5a67e5feaafa332973a0073e..2d3bd6147719f3b561a8824a8d32bd6d1232a22a 100644 (file)
@@ -1,15 +1,15 @@
 [*]
 [*] GTKWave Analyzer v3.3.105 (w)1999-2020 BSI
-[*] Sun May 24 09:24:55 2020
+[*] Mon Jun  1 07:14:57 2020
 [*]
-[dumpfile] "/src/dune/FpgaPlay/test032-nvmewrite-tim3-1/sim/simu/test.ghw"
-[dumpfile_mtime] "Sun May 24 09:24:21 2020"
-[dumpfile_size] 10539
-[savefile] "/src/dune/FpgaPlay/test032-nvmewrite-tim3-1/sim/testbench/test009-packets.sav"
-[timestart] 0
+[dumpfile] "/src/dune/FpgaPlay/test032-nvmewrite-t3/sim/simu/test.ghw"
+[dumpfile_mtime] "Mon Jun  1 07:12:33 2020"
+[dumpfile_size] 16897
+[savefile] "/src/dune/FpgaPlay/test032-nvmewrite-t3/sim/testbench/test009-packets.sav"
+[timestart] 147500000
 [size] 1920 1171
 [pos] -1 -1
-*-25.411741 179200000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-25.411741 170200000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [treeopen] top.
 [treeopen] top.test.
 [treeopen] top.test.fromhost.
 [treeopen] top.test.nvmereply.
 [treeopen] top.test.nvmereq.
 [treeopen] top.test.pciestreammux0.
-[treeopen] top.test.pciestreammux0.demuxreg.
-[treeopen] top.test.pciestreammux0.muxreg.
+[treeopen] top.test.pciestreammux0.reg.
+[treeopen] top.test.pciestreammux0.reg.axisfifo1.
+[treeopen] top.test.pciestreammux0.reg.axisfifo1.reg0.
+[treeopen] top.test.pciestreammux0.reg.axisfifo1.streamout.
 [treeopen] top.test.pciestreammux0.stream1out.
+[treeopen] top.test.pciestreammux0.stream1outfeed.
+[treeopen] top.test.pciestreammux0.stream3outfeed.
 [treeopen] top.test.tohost.
 [sst_width] 248
-[signals_width] 402
+[signals_width] 632
 [sst_expanded] 1
 [sst_vpaned_height] 670
 @28
@@ -52,11 +56,6 @@ top.test.hostreply.last
 #{top.test.hostreply.data[127:0]} top.test.hostreply.data[127] top.test.hostreply.data[126] top.test.hostreply.data[125] top.test.hostreply.data[124] top.test.hostreply.data[123] top.test.hostreply.data[122] top.test.hostreply.data[121] top.test.hostreply.data[120] top.test.hostreply.data[119] top.test.hostreply.data[118] top.test.hostreply.data[117] top.test.hostreply.data[116] top.test.hostreply.data[115] top.test.hostreply.data[114] top.test.hostreply.data[113] top.test.hostreply.data[112] top.test.hostreply.data[111] top.test.hostreply.data[110] top.test.hostreply.data[109] top.test.hostreply.data[108] top.test.hostreply.data[107] top.test.hostreply.data[106] top.test.hostreply.data[105] top.test.hostreply.data[104] top.test.hostreply.data[103] top.test.hostreply.data[102] top.test.hostreply.data[101] top.test.hostreply.data[100] top.test.hostreply.data[99] top.test.hostreply.data[98] top.test.hostreply.data[97] top.test.hostreply.data[96] top.test.hostreply.data[95] top.test.hostreply.data[94] top.test.hostreply.data[93] top.test.hostreply.data[92] top.test.hostreply.data[91] top.test.hostreply.data[90] top.test.hostreply.data[89] top.test.hostreply.data[88] top.test.hostreply.data[87] top.test.hostreply.data[86] top.test.hostreply.data[85] top.test.hostreply.data[84] top.test.hostreply.data[83] top.test.hostreply.data[82] top.test.hostreply.data[81] top.test.hostreply.data[80] top.test.hostreply.data[79] top.test.hostreply.data[78] top.test.hostreply.data[77] top.test.hostreply.data[76] top.test.hostreply.data[75] top.test.hostreply.data[74] top.test.hostreply.data[73] top.test.hostreply.data[72] top.test.hostreply.data[71] top.test.hostreply.data[70] top.test.hostreply.data[69] top.test.hostreply.data[68] top.test.hostreply.data[67] top.test.hostreply.data[66] top.test.hostreply.data[65] top.test.hostreply.data[64] top.test.hostreply.data[63] top.test.hostreply.data[62] top.test.hostreply.data[61] top.test.hostreply.data[60] top.test.hostreply.data[59] top.test.hostreply.data[58] top.test.hostreply.data[57] top.test.hostreply.data[56] top.test.hostreply.data[55] top.test.hostreply.data[54] top.test.hostreply.data[53] top.test.hostreply.data[52] top.test.hostreply.data[51] top.test.hostreply.data[50] top.test.hostreply.data[49] top.test.hostreply.data[48] top.test.hostreply.data[47] top.test.hostreply.data[46] top.test.hostreply.data[45] top.test.hostreply.data[44] top.test.hostreply.data[43] top.test.hostreply.data[42] top.test.hostreply.data[41] top.test.hostreply.data[40] top.test.hostreply.data[39] top.test.hostreply.data[38] top.test.hostreply.data[37] top.test.hostreply.data[36] top.test.hostreply.data[35] top.test.hostreply.data[34] top.test.hostreply.data[33] top.test.hostreply.data[32] top.test.hostreply.data[31] top.test.hostreply.data[30] top.test.hostreply.data[29] top.test.hostreply.data[28] top.test.hostreply.data[27] top.test.hostreply.data[26] top.test.hostreply.data[25] top.test.hostreply.data[24] top.test.hostreply.data[23] top.test.hostreply.data[22] top.test.hostreply.data[21] top.test.hostreply.data[20] top.test.hostreply.data[19] top.test.hostreply.data[18] top.test.hostreply.data[17] top.test.hostreply.data[16] top.test.hostreply.data[15] top.test.hostreply.data[14] top.test.hostreply.data[13] top.test.hostreply.data[12] top.test.hostreply.data[11] top.test.hostreply.data[10] top.test.hostreply.data[9] top.test.hostreply.data[8] top.test.hostreply.data[7] top.test.hostreply.data[6] top.test.hostreply.data[5] top.test.hostreply.data[4] top.test.hostreply.data[3] top.test.hostreply.data[2] top.test.hostreply.data[1] top.test.hostreply.data[0]
 @420
 top.test.pciestreammux0.demuxstate
-@28
-top.test.pciestreammux0.demuxreg.valid
-top.test.pciestreammux0.demuxreg.last
-@22
-#{top.test.pciestreammux0.demuxreg.data[127:0]} top.test.pciestreammux0.demuxreg.data[127] top.test.pciestreammux0.demuxreg.data[126] top.test.pciestreammux0.demuxreg.data[125] top.test.pciestreammux0.demuxreg.data[124] top.test.pciestreammux0.demuxreg.data[123] top.test.pciestreammux0.demuxreg.data[122] top.test.pciestreammux0.demuxreg.data[121] top.test.pciestreammux0.demuxreg.data[120] top.test.pciestreammux0.demuxreg.data[119] top.test.pciestreammux0.demuxreg.data[118] top.test.pciestreammux0.demuxreg.data[117] top.test.pciestreammux0.demuxreg.data[116] top.test.pciestreammux0.demuxreg.data[115] top.test.pciestreammux0.demuxreg.data[114] top.test.pciestreammux0.demuxreg.data[113] top.test.pciestreammux0.demuxreg.data[112] top.test.pciestreammux0.demuxreg.data[111] top.test.pciestreammux0.demuxreg.data[110] top.test.pciestreammux0.demuxreg.data[109] top.test.pciestreammux0.demuxreg.data[108] top.test.pciestreammux0.demuxreg.data[107] top.test.pciestreammux0.demuxreg.data[106] top.test.pciestreammux0.demuxreg.data[105] top.test.pciestreammux0.demuxreg.data[104] top.test.pciestreammux0.demuxreg.data[103] top.test.pciestreammux0.demuxreg.data[102] top.test.pciestreammux0.demuxreg.data[101] top.test.pciestreammux0.demuxreg.data[100] top.test.pciestreammux0.demuxreg.data[99] top.test.pciestreammux0.demuxreg.data[98] top.test.pciestreammux0.demuxreg.data[97] top.test.pciestreammux0.demuxreg.data[96] top.test.pciestreammux0.demuxreg.data[95] top.test.pciestreammux0.demuxreg.data[94] top.test.pciestreammux0.demuxreg.data[93] top.test.pciestreammux0.demuxreg.data[92] top.test.pciestreammux0.demuxreg.data[91] top.test.pciestreammux0.demuxreg.data[90] top.test.pciestreammux0.demuxreg.data[89] top.test.pciestreammux0.demuxreg.data[88] top.test.pciestreammux0.demuxreg.data[87] top.test.pciestreammux0.demuxreg.data[86] top.test.pciestreammux0.demuxreg.data[85] top.test.pciestreammux0.demuxreg.data[84] top.test.pciestreammux0.demuxreg.data[83] top.test.pciestreammux0.demuxreg.data[82] top.test.pciestreammux0.demuxreg.data[81] top.test.pciestreammux0.demuxreg.data[80] top.test.pciestreammux0.demuxreg.data[79] top.test.pciestreammux0.demuxreg.data[78] top.test.pciestreammux0.demuxreg.data[77] top.test.pciestreammux0.demuxreg.data[76] top.test.pciestreammux0.demuxreg.data[75] top.test.pciestreammux0.demuxreg.data[74] top.test.pciestreammux0.demuxreg.data[73] top.test.pciestreammux0.demuxreg.data[72] top.test.pciestreammux0.demuxreg.data[71] top.test.pciestreammux0.demuxreg.data[70] top.test.pciestreammux0.demuxreg.data[69] top.test.pciestreammux0.demuxreg.data[68] top.test.pciestreammux0.demuxreg.data[67] top.test.pciestreammux0.demuxreg.data[66] top.test.pciestreammux0.demuxreg.data[65] top.test.pciestreammux0.demuxreg.data[64] top.test.pciestreammux0.demuxreg.data[63] top.test.pciestreammux0.demuxreg.data[62] top.test.pciestreammux0.demuxreg.data[61] top.test.pciestreammux0.demuxreg.data[60] top.test.pciestreammux0.demuxreg.data[59] top.test.pciestreammux0.demuxreg.data[58] top.test.pciestreammux0.demuxreg.data[57] top.test.pciestreammux0.demuxreg.data[56] top.test.pciestreammux0.demuxreg.data[55] top.test.pciestreammux0.demuxreg.data[54] top.test.pciestreammux0.demuxreg.data[53] top.test.pciestreammux0.demuxreg.data[52] top.test.pciestreammux0.demuxreg.data[51] top.test.pciestreammux0.demuxreg.data[50] top.test.pciestreammux0.demuxreg.data[49] top.test.pciestreammux0.demuxreg.data[48] top.test.pciestreammux0.demuxreg.data[47] top.test.pciestreammux0.demuxreg.data[46] top.test.pciestreammux0.demuxreg.data[45] top.test.pciestreammux0.demuxreg.data[44] top.test.pciestreammux0.demuxreg.data[43] top.test.pciestreammux0.demuxreg.data[42] top.test.pciestreammux0.demuxreg.data[41] top.test.pciestreammux0.demuxreg.data[40] top.test.pciestreammux0.demuxreg.data[39] top.test.pciestreammux0.demuxreg.data[38] top.test.pciestreammux0.demuxreg.data[37] top.test.pciestreammux0.demuxreg.data[36] top.test.pciestreammux0.demuxreg.data[35] top.test.pciestreammux0.demuxreg.data[34] top.test.pciestreammux0.demuxreg.data[33] top.test.pciestreammux0.demuxreg.data[32] top.test.pciestreammux0.demuxreg.data[31] top.test.pciestreammux0.demuxreg.data[30] top.test.pciestreammux0.demuxreg.data[29] top.test.pciestreammux0.demuxreg.data[28] top.test.pciestreammux0.demuxreg.data[27] top.test.pciestreammux0.demuxreg.data[26] top.test.pciestreammux0.demuxreg.data[25] top.test.pciestreammux0.demuxreg.data[24] top.test.pciestreammux0.demuxreg.data[23] top.test.pciestreammux0.demuxreg.data[22] top.test.pciestreammux0.demuxreg.data[21] top.test.pciestreammux0.demuxreg.data[20] top.test.pciestreammux0.demuxreg.data[19] top.test.pciestreammux0.demuxreg.data[18] top.test.pciestreammux0.demuxreg.data[17] top.test.pciestreammux0.demuxreg.data[16] top.test.pciestreammux0.demuxreg.data[15] top.test.pciestreammux0.demuxreg.data[14] top.test.pciestreammux0.demuxreg.data[13] top.test.pciestreammux0.demuxreg.data[12] top.test.pciestreammux0.demuxreg.data[11] top.test.pciestreammux0.demuxreg.data[10] top.test.pciestreammux0.demuxreg.data[9] top.test.pciestreammux0.demuxreg.data[8] top.test.pciestreammux0.demuxreg.data[7] top.test.pciestreammux0.demuxreg.data[6] top.test.pciestreammux0.demuxreg.data[5] top.test.pciestreammux0.demuxreg.data[4] top.test.pciestreammux0.demuxreg.data[3] top.test.pciestreammux0.demuxreg.data[2] top.test.pciestreammux0.demuxreg.data[1] top.test.pciestreammux0.demuxreg.data[0]
 @1000200
 -DeMux
 @800200
@@ -79,10 +78,8 @@ top.test.hostreq.last
 top.test.tohost.ready
 top.test.tohost.valid
 top.test.tohost.last
-@23
-#{top.test.tohost.data[127:0]} top.test.tohost.data[127] top.test.tohost.data[126] top.test.tohost.data[125] top.test.tohost.data[124] top.test.tohost.data[123] top.test.tohost.data[122] top.test.tohost.data[121] top.test.tohost.data[120] top.test.tohost.data[119] top.test.tohost.data[118] top.test.tohost.data[117] top.test.tohost.data[116] top.test.tohost.data[115] top.test.tohost.data[114] top.test.tohost.data[113] top.test.tohost.data[112] top.test.tohost.data[111] top.test.tohost.data[110] top.test.tohost.data[109] top.test.tohost.data[108] top.test.tohost.data[107] top.test.tohost.data[106] top.test.tohost.data[105] top.test.tohost.data[104] top.test.tohost.data[103] top.test.tohost.data[102] top.test.tohost.data[101] top.test.tohost.data[100] top.test.tohost.data[99] top.test.tohost.data[98] top.test.tohost.data[97] top.test.tohost.data[96] top.test.tohost.data[95] top.test.tohost.data[94] top.test.tohost.data[93] top.test.tohost.data[92] top.test.tohost.data[91] top.test.tohost.data[90] top.test.tohost.data[89] top.test.tohost.data[88] top.test.tohost.data[87] top.test.tohost.data[86] top.test.tohost.data[85] top.test.tohost.data[84] top.test.tohost.data[83] top.test.tohost.data[82] top.test.tohost.data[81] top.test.tohost.data[80] top.test.tohost.data[79] top.test.tohost.data[78] top.test.tohost.data[77] top.test.tohost.data[76] top.test.tohost.data[75] top.test.tohost.data[74] top.test.tohost.data[73] top.test.tohost.data[72] top.test.tohost.data[71] top.test.tohost.data[70] top.test.tohost.data[69] top.test.tohost.data[68] top.test.tohost.data[67] top.test.tohost.data[66] top.test.tohost.data[65] top.test.tohost.data[64] top.test.tohost.data[63] top.test.tohost.data[62] top.test.tohost.data[61] top.test.tohost.data[60] top.test.tohost.data[59] top.test.tohost.data[58] top.test.tohost.data[57] top.test.tohost.data[56] top.test.tohost.data[55] top.test.tohost.data[54] top.test.tohost.data[53] top.test.tohost.data[52] top.test.tohost.data[51] top.test.tohost.data[50] top.test.tohost.data[49] top.test.tohost.data[48] top.test.tohost.data[47] top.test.tohost.data[46] top.test.tohost.data[45] top.test.tohost.data[44] top.test.tohost.data[43] top.test.tohost.data[42] top.test.tohost.data[41] top.test.tohost.data[40] top.test.tohost.data[39] top.test.tohost.data[38] top.test.tohost.data[37] top.test.tohost.data[36] top.test.tohost.data[35] top.test.tohost.data[34] top.test.tohost.data[33] top.test.tohost.data[32] top.test.tohost.data[31] top.test.tohost.data[30] top.test.tohost.data[29] top.test.tohost.data[28] top.test.tohost.data[27] top.test.tohost.data[26] top.test.tohost.data[25] top.test.tohost.data[24] top.test.tohost.data[23] top.test.tohost.data[22] top.test.tohost.data[21] top.test.tohost.data[20] top.test.tohost.data[19] top.test.tohost.data[18] top.test.tohost.data[17] top.test.tohost.data[16] top.test.tohost.data[15] top.test.tohost.data[14] top.test.tohost.data[13] top.test.tohost.data[12] top.test.tohost.data[11] top.test.tohost.data[10] top.test.tohost.data[9] top.test.tohost.data[8] top.test.tohost.data[7] top.test.tohost.data[6] top.test.tohost.data[5] top.test.tohost.data[4] top.test.tohost.data[3] top.test.tohost.data[2] top.test.tohost.data[1] top.test.tohost.data[0]
 @22
-#{top.test.pciestreammux0.muxreg.data[127:0]} top.test.pciestreammux0.muxreg.data[127] top.test.pciestreammux0.muxreg.data[126] top.test.pciestreammux0.muxreg.data[125] top.test.pciestreammux0.muxreg.data[124] top.test.pciestreammux0.muxreg.data[123] top.test.pciestreammux0.muxreg.data[122] top.test.pciestreammux0.muxreg.data[121] top.test.pciestreammux0.muxreg.data[120] top.test.pciestreammux0.muxreg.data[119] top.test.pciestreammux0.muxreg.data[118] top.test.pciestreammux0.muxreg.data[117] top.test.pciestreammux0.muxreg.data[116] top.test.pciestreammux0.muxreg.data[115] top.test.pciestreammux0.muxreg.data[114] top.test.pciestreammux0.muxreg.data[113] top.test.pciestreammux0.muxreg.data[112] top.test.pciestreammux0.muxreg.data[111] top.test.pciestreammux0.muxreg.data[110] top.test.pciestreammux0.muxreg.data[109] top.test.pciestreammux0.muxreg.data[108] top.test.pciestreammux0.muxreg.data[107] top.test.pciestreammux0.muxreg.data[106] top.test.pciestreammux0.muxreg.data[105] top.test.pciestreammux0.muxreg.data[104] top.test.pciestreammux0.muxreg.data[103] top.test.pciestreammux0.muxreg.data[102] top.test.pciestreammux0.muxreg.data[101] top.test.pciestreammux0.muxreg.data[100] top.test.pciestreammux0.muxreg.data[99] top.test.pciestreammux0.muxreg.data[98] top.test.pciestreammux0.muxreg.data[97] top.test.pciestreammux0.muxreg.data[96] top.test.pciestreammux0.muxreg.data[95] top.test.pciestreammux0.muxreg.data[94] top.test.pciestreammux0.muxreg.data[93] top.test.pciestreammux0.muxreg.data[92] top.test.pciestreammux0.muxreg.data[91] top.test.pciestreammux0.muxreg.data[90] top.test.pciestreammux0.muxreg.data[89] top.test.pciestreammux0.muxreg.data[88] top.test.pciestreammux0.muxreg.data[87] top.test.pciestreammux0.muxreg.data[86] top.test.pciestreammux0.muxreg.data[85] top.test.pciestreammux0.muxreg.data[84] top.test.pciestreammux0.muxreg.data[83] top.test.pciestreammux0.muxreg.data[82] top.test.pciestreammux0.muxreg.data[81] top.test.pciestreammux0.muxreg.data[80] top.test.pciestreammux0.muxreg.data[79] top.test.pciestreammux0.muxreg.data[78] top.test.pciestreammux0.muxreg.data[77] top.test.pciestreammux0.muxreg.data[76] top.test.pciestreammux0.muxreg.data[75] top.test.pciestreammux0.muxreg.data[74] top.test.pciestreammux0.muxreg.data[73] top.test.pciestreammux0.muxreg.data[72] top.test.pciestreammux0.muxreg.data[71] top.test.pciestreammux0.muxreg.data[70] top.test.pciestreammux0.muxreg.data[69] top.test.pciestreammux0.muxreg.data[68] top.test.pciestreammux0.muxreg.data[67] top.test.pciestreammux0.muxreg.data[66] top.test.pciestreammux0.muxreg.data[65] top.test.pciestreammux0.muxreg.data[64] top.test.pciestreammux0.muxreg.data[63] top.test.pciestreammux0.muxreg.data[62] top.test.pciestreammux0.muxreg.data[61] top.test.pciestreammux0.muxreg.data[60] top.test.pciestreammux0.muxreg.data[59] top.test.pciestreammux0.muxreg.data[58] top.test.pciestreammux0.muxreg.data[57] top.test.pciestreammux0.muxreg.data[56] top.test.pciestreammux0.muxreg.data[55] top.test.pciestreammux0.muxreg.data[54] top.test.pciestreammux0.muxreg.data[53] top.test.pciestreammux0.muxreg.data[52] top.test.pciestreammux0.muxreg.data[51] top.test.pciestreammux0.muxreg.data[50] top.test.pciestreammux0.muxreg.data[49] top.test.pciestreammux0.muxreg.data[48] top.test.pciestreammux0.muxreg.data[47] top.test.pciestreammux0.muxreg.data[46] top.test.pciestreammux0.muxreg.data[45] top.test.pciestreammux0.muxreg.data[44] top.test.pciestreammux0.muxreg.data[43] top.test.pciestreammux0.muxreg.data[42] top.test.pciestreammux0.muxreg.data[41] top.test.pciestreammux0.muxreg.data[40] top.test.pciestreammux0.muxreg.data[39] top.test.pciestreammux0.muxreg.data[38] top.test.pciestreammux0.muxreg.data[37] top.test.pciestreammux0.muxreg.data[36] top.test.pciestreammux0.muxreg.data[35] top.test.pciestreammux0.muxreg.data[34] top.test.pciestreammux0.muxreg.data[33] top.test.pciestreammux0.muxreg.data[32] top.test.pciestreammux0.muxreg.data[31] top.test.pciestreammux0.muxreg.data[30] top.test.pciestreammux0.muxreg.data[29] top.test.pciestreammux0.muxreg.data[28] top.test.pciestreammux0.muxreg.data[27] top.test.pciestreammux0.muxreg.data[26] top.test.pciestreammux0.muxreg.data[25] top.test.pciestreammux0.muxreg.data[24] top.test.pciestreammux0.muxreg.data[23] top.test.pciestreammux0.muxreg.data[22] top.test.pciestreammux0.muxreg.data[21] top.test.pciestreammux0.muxreg.data[20] top.test.pciestreammux0.muxreg.data[19] top.test.pciestreammux0.muxreg.data[18] top.test.pciestreammux0.muxreg.data[17] top.test.pciestreammux0.muxreg.data[16] top.test.pciestreammux0.muxreg.data[15] top.test.pciestreammux0.muxreg.data[14] top.test.pciestreammux0.muxreg.data[13] top.test.pciestreammux0.muxreg.data[12] top.test.pciestreammux0.muxreg.data[11] top.test.pciestreammux0.muxreg.data[10] top.test.pciestreammux0.muxreg.data[9] top.test.pciestreammux0.muxreg.data[8] top.test.pciestreammux0.muxreg.data[7] top.test.pciestreammux0.muxreg.data[6] top.test.pciestreammux0.muxreg.data[5] top.test.pciestreammux0.muxreg.data[4] top.test.pciestreammux0.muxreg.data[3] top.test.pciestreammux0.muxreg.data[2] top.test.pciestreammux0.muxreg.data[1] top.test.pciestreammux0.muxreg.data[0]
+#{top.test.tohost.data[127:0]} top.test.tohost.data[127] top.test.tohost.data[126] top.test.tohost.data[125] top.test.tohost.data[124] top.test.tohost.data[123] top.test.tohost.data[122] top.test.tohost.data[121] top.test.tohost.data[120] top.test.tohost.data[119] top.test.tohost.data[118] top.test.tohost.data[117] top.test.tohost.data[116] top.test.tohost.data[115] top.test.tohost.data[114] top.test.tohost.data[113] top.test.tohost.data[112] top.test.tohost.data[111] top.test.tohost.data[110] top.test.tohost.data[109] top.test.tohost.data[108] top.test.tohost.data[107] top.test.tohost.data[106] top.test.tohost.data[105] top.test.tohost.data[104] top.test.tohost.data[103] top.test.tohost.data[102] top.test.tohost.data[101] top.test.tohost.data[100] top.test.tohost.data[99] top.test.tohost.data[98] top.test.tohost.data[97] top.test.tohost.data[96] top.test.tohost.data[95] top.test.tohost.data[94] top.test.tohost.data[93] top.test.tohost.data[92] top.test.tohost.data[91] top.test.tohost.data[90] top.test.tohost.data[89] top.test.tohost.data[88] top.test.tohost.data[87] top.test.tohost.data[86] top.test.tohost.data[85] top.test.tohost.data[84] top.test.tohost.data[83] top.test.tohost.data[82] top.test.tohost.data[81] top.test.tohost.data[80] top.test.tohost.data[79] top.test.tohost.data[78] top.test.tohost.data[77] top.test.tohost.data[76] top.test.tohost.data[75] top.test.tohost.data[74] top.test.tohost.data[73] top.test.tohost.data[72] top.test.tohost.data[71] top.test.tohost.data[70] top.test.tohost.data[69] top.test.tohost.data[68] top.test.tohost.data[67] top.test.tohost.data[66] top.test.tohost.data[65] top.test.tohost.data[64] top.test.tohost.data[63] top.test.tohost.data[62] top.test.tohost.data[61] top.test.tohost.data[60] top.test.tohost.data[59] top.test.tohost.data[58] top.test.tohost.data[57] top.test.tohost.data[56] top.test.tohost.data[55] top.test.tohost.data[54] top.test.tohost.data[53] top.test.tohost.data[52] top.test.tohost.data[51] top.test.tohost.data[50] top.test.tohost.data[49] top.test.tohost.data[48] top.test.tohost.data[47] top.test.tohost.data[46] top.test.tohost.data[45] top.test.tohost.data[44] top.test.tohost.data[43] top.test.tohost.data[42] top.test.tohost.data[41] top.test.tohost.data[40] top.test.tohost.data[39] top.test.tohost.data[38] top.test.tohost.data[37] top.test.tohost.data[36] top.test.tohost.data[35] top.test.tohost.data[34] top.test.tohost.data[33] top.test.tohost.data[32] top.test.tohost.data[31] top.test.tohost.data[30] top.test.tohost.data[29] top.test.tohost.data[28] top.test.tohost.data[27] top.test.tohost.data[26] top.test.tohost.data[25] top.test.tohost.data[24] top.test.tohost.data[23] top.test.tohost.data[22] top.test.tohost.data[21] top.test.tohost.data[20] top.test.tohost.data[19] top.test.tohost.data[18] top.test.tohost.data[17] top.test.tohost.data[16] top.test.tohost.data[15] top.test.tohost.data[14] top.test.tohost.data[13] top.test.tohost.data[12] top.test.tohost.data[11] top.test.tohost.data[10] top.test.tohost.data[9] top.test.tohost.data[8] top.test.tohost.data[7] top.test.tohost.data[6] top.test.tohost.data[5] top.test.tohost.data[4] top.test.tohost.data[3] top.test.tohost.data[2] top.test.tohost.data[1] top.test.tohost.data[0]
 @1000200
 -Mux
 [pattern_trace] 1
index 221b6e97fabd79ef24f2153b3223ee32c879115d..d4137288b0fd76c8daf94c4e82d7c73b2b66e8ed 100644 (file)
@@ -102,13 +102,14 @@ begin
                
                if(true) then
                        -- Send a PCIe write request
+                       wait until rising_edge(clk);
                        pcieRequestWrite(clk, fromHost, 1, 1, 4, 16#44#, 16, 16#0000100#);
 
                        -- Send a PCIe reply
-                       pcieReply(clk, fromHost, 1, 16#AAAA#, 4, 16#44#, 16, 16#0000100#);
+                       pcieReply(clk, fromHost, 1, 3, 4, 16#44#, 16, 16#0000100#);
 
                        -- Send a PCIe reply
-                       pcieReply(clk, fromHost, 1, 16#AAAA#, 4, 16#44#, 1, 16#0000100#);
+                       pcieReply(clk, fromHost, 1, 3, 4, 16#44#, 1, 16#0000100#);
                end if;
 
                wait;
@@ -139,7 +140,7 @@ begin
                                end loop;
                        end if;
 
-                       if(True) then
+                       if(true) then
                                wait for 50 ns;
                                for i in 0 to 4 loop
                                        wait until rising_edge(clk);
@@ -160,7 +161,7 @@ begin
 
                wait until reset = '0';
                
-               if(false) then
+               if(true) then
                        -- Send a PCIe reply
                        --pcieReply(clk, hostReq, 1, 16#AAAA#, 4, 16#44#, 4, 16#0000100#);
                        --wait;
@@ -170,15 +171,15 @@ begin
 
                        -- Send a PCIe reply
                        wait until rising_edge(clk);
-                       pcieReply(clk, hostReq, 1, 16#AAAA#, 4, 16#44#, 16, 16#0000100#);
+                       pcieReply(clk, hostReq, 1, 3, 4, 16#44#, 16, 16#0000100#);
 
                        -- Send a PCIe reply
                        wait until rising_edge(clk);
-                       pcieReply(clk, hostReq, 1, 16#AAAA#, 4, 16#44#, 4, 16#0000100#);
+                       pcieReply(clk, hostReq, 1, 3, 4, 16#44#, 4, 16#0000100#);
 
                        -- Send a PCIe reply
                        wait until rising_edge(clk);
-                       pcieReply(clk, hostReq, 1, 16#AAAA#, 4, 16#44#, 1, 16#0000100#);
+                       pcieReply(clk, hostReq, 1, 3, 4, 16#44#, 1, 16#0000100#);
 
                        -- Send a PCIe write request
                        wait until rising_edge(clk);
@@ -192,20 +193,20 @@ begin
        begin
                toHost.ready <= '0';
                
-               if(false) then
-                       if(false) then
+               if(true) then
+                       if(true) then
                                toHost.ready    <= '1';
                                wait;
                        end if;
 
-                       if(true) then
+                       if(false) then
                                wait for 50 ns;
                                wait until rising_edge(clk);
                                toHost.ready <= '1';
                                wait;
                        end if;
 
-                       if(True) then
+                       if(false) then
                                wait for 50 ns;
                                for i in 0 to 16 loop
                                        wait until rising_edge(clk);
@@ -213,7 +214,7 @@ begin
                                end loop;
                        end if;
 
-                       if(True) then
+                       if(true) then
                                wait for 50 ns;
                                for i in 0 to 16 loop
                                        wait until rising_edge(clk);
index 1de478181c93d83f98d54c73284c0686ea162902..9adc57ca5806ea85f8e5f68db48dc8ffb6dd104e 100644 (file)
@@ -5,12 +5,14 @@
 --! @class     AxilClockConverter
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-02-28
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! AXI Lite "bus" clock domain crossing module
 --!
 --! @details
+--! This module provides a clock domain crossing implementation for an AXI4 lite "bus" interface.
+--! It uses the Xilinx IP in order to perform this.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
index 62278ebc2bba44b29a2e4262c004f674815d9e4b..351028d66f55d39d516e34f026b88cc922014fb2 100644 (file)
@@ -5,12 +5,17 @@
 --! @class     AxisClockConverter
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-03-28
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
---! AXI Stream clock domain crossing module
+--! AxisStream clock domain crossing module.
 --!
 --! @details
+--! This module implements a clock crossing for an AXI4 stream encoded using
+--! the AxisStream record type. It uses the Xilinx AXI4 stream CDC IP to
+--! implement this.
+--! The Simulate parameter reduces the functionality to a simple pass through
+--! for simple system simulations.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -42,13 +47,14 @@ generic(
        Simulate        : boolean       := False
 );
 port (
-       clkRx           : in std_logic;
-       resetRx         : in std_logic;
-       streamRx        : inout AxisStreamType := AxisStreamInput;                        
+       clkRx           : in std_logic;                                 --! The input stream clock line
+       resetRx         : in std_logic;                                 --! The input stream reset
 
-       clkTx           : in std_logic;
-       resetTx         : in std_logic;
-       streamTx        : inout AxisStreamType := AxisStreamOutput
+       streamRx        : inout AxisStreamType := AxisStreamInput;      --! The input stream
+
+       clkTx           : in std_logic;                                 --! The output stream clock line
+       resetTx         : in std_logic;                                 --! The output stream reset
+       streamTx        : inout AxisStreamType := AxisStreamOutput      --! The output stream
 );
 end;
 
index d920a8aea6971da600e9c8378f937073d1cb24cf..ae8c8ed6c8329bc25b1cea47acaf803ffff36539 100644 (file)
@@ -5,7 +5,7 @@
 --! @class     AxisDataConvertFifo
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-15
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
 --! AXI Stream data Fifo with conversion from 256 to 128 bits.
@@ -14,6 +14,9 @@
 --! This module accepts an AxisDataStreamType AXI4 type data stream with 256 bit width data.
 --! It performs a Fifo function outputing the data on a 128 bit wide AxisStreamType AXI4 type stream.
 --! The last signal is passed through the Fifo.
+--! The FIFO depth is configurable with the FifoSizeBytes parameter which is in Bytes. For the NvmeStorage
+--! system this is normally set to the block size of 4096 Bytes.
+--! The modules uses block RAM to store the data.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -97,7 +100,7 @@ signal readDataHigh  : std_logic_vector(127 downto 0) := (others => '0');
 signal readHigh                : boolean := False;
 
 begin
-       -- Fifo memory
+       --! Fifo memory
        fifoMem : Ram
        port map (
                clk             => clk,
@@ -112,7 +115,7 @@ begin
                readData        => readData
        );
 
-       -- Fifo input
+       --! Fifo input
        streamRx_readyl         <= '1' when(not posLooped or (readPos /= writePos)) else '0';
        streamRx_ready          <= streamRx_readyl;
        writeEnable             <= streamRx.valid and streamRx_readyl when((not posLooped) or (writePos /= readPos)) else '0';
@@ -120,7 +123,7 @@ begin
        
        readEnable              <= readDataReady when((readDataValid = '1') and ((posLooped) or (writePos /= readPos))) else '0';
 
-       -- Data bit width conversion and output
+       --! Data bit width conversion and output
        readDataReady           <= streamTx.ready when(not readHigh) else '0';
        streamTx.valid          <= readDataValid;
        streamTx.last           <= readData(256) when(readHigh) else '0';
index 3f95baed7a313c120a971355002b59562cbd729f..93588dfb2a2c0bb5ece51c3075cfd01e953a9ed7 100644 (file)
@@ -5,7 +5,7 @@
 --! @class     Cdc
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-18
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This is a simple module to pass a set of signals across a clock domain
 --! of handshake system is needed on top of this.
 --! A simple method of acheiving this would be to have one of the signals be a valid signal that is
 --! activated/deactivated one clock cycle after the rest of the signals have changed state.
+--! It uses two clock synchronisation registers.
+--! Note it doesn't have an integral input clock domain register and thus it expects the input signals
+--! to be stable for at least two input clock cycles prior to a valid signal going high.
+--!
+--! Note this module requires appropriate timing constraints for the CDC applied. This would normally
+--! a set_max_delay or set_false_path constraint on the timing to the sendCdcReg1 and recvCdcReg1 registers.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -85,6 +91,31 @@ end;
 
 
 
+--! @class     CdcSingle
+--! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
+--! @date      2020-05-18
+--! @version   1.0.0
+--!
+--! @brief
+--! This is a simple module to pass a single bit wide signal across a clock domain
+--!
+--! @details
+--! This is a very simple, low utilisation clock domain crossing unit for a single bit wide signal.
+--! It uses two clock synchronisation registers.
+--!
+--! @copyright GNU GPL License
+--! Copyright (c) Beam Ltd, All rights reserved. <br>
+--! This code is free software: you can redistribute it and/or modify
+--! it under the terms of the GNU General Public License as published by
+--! the Free Software Foundation, either version 3 of the License, or
+--! (at your option) any later version.
+--! This program is distributed in the hope that it will be useful,
+--! but WITHOUT ANY WARRANTY; without even the implied warranty of
+--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--! GNU General Public License for more details. <br>
+--! You should have received a copy of the GNU General Public License
+--! along with this code. If not, see <https://www.gnu.org/licenses/>.
+--!
 library ieee;
 use ieee.std_logic_1164.all;
 use ieee.numeric_std.all;
index 990206a5203be5326ed7e65afde9e6208c36f99d..5357234c44a08e428ab7dfd6497d71cab450e969 100644 (file)
@@ -5,14 +5,18 @@
 --! @class     DuneNvmeTestTop
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-12
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
---! This FPGA bit file allows a host computer to access a NVMe storage device
---!  connected to the FPGA via the hosts PCIe interface. It allows a host computer
---!  program to communicate with the NVMe device for research and developemnt test work.
+--! This module implements a complete test design for the NvmeStorage system.
 --!
 --! @details
+--! The FPGA bit file produced allows a host computer to access a NVMe storage device
+--! connected to the FPGA via the hosts PCIe interface. It has a simple test data source
+--! and allows a host computer program to communicate with the NVMe device for research
+--! and development test work.
+--! See the DuneNvmeStorageManual for more details.
+--! 
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -171,7 +175,7 @@ signal dataStream_ready             : std_logic;
 signal dataEnabled             : std_logic;                    --! Enabled signal for test data
 
 begin
-       -- System clock just used for a boot reset
+       -- System clock just used for a boot reset if needed
        sys_clk_buf : Clk_core port map (
                clk_in1_p       => sys_clk_p,
                clk_in1_n       => sys_clk_n,
diff --git a/src/DuneNvmeTestUnitTop.vhd b/src/DuneNvmeTestUnitTop.vhd
deleted file mode 100644 (file)
index 07716f6..0000000
+++ /dev/null
@@ -1,571 +0,0 @@
---------------------------------------------------------------------------------
--- DuneNvmeTestUnitTop.vhd Simple NVMe access test system
---------------------------------------------------------------------------------
---!
---! @class     DuneNvmeTestTop
---! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
---! @date      2020-02-18
---! @version   0.0.1
---!
---! @brief
---! This FPGA bit file allows a host computer to access a single NVMe storage device
---!  connected to the FPGA via the hosts PCIe interface. It allows a host computer
---!  program to communicate with the NVMe device for research and developemnt test work.
---!
---! @details
---!
---! @copyright GNU GPL License
---! Copyright (c) Beam Ltd, All rights reserved. <br>
---! This code is free software: you can redistribute it and/or modify
---! it under the terms of the GNU General Public License as published by
---! the Free Software Foundation, either version 3 of the License, or
---! (at your option) any later version.
---! This program is distributed in the hope that it will be useful,
---! but WITHOUT ANY WARRANTY; without even the implied warranty of
---! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
---! GNU General Public License for more details. <br>
---! You should have received a copy of the GNU General Public License
---! along with this code. If not, see <https://www.gnu.org/licenses/>.
---!
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.numeric_std.all;
-
-library unisim;
-use unisim.vcomponents.all;
-
-library work;
-use work.NvmeStoragePkg.all;
-use work.NvmeStorageIntPkg.all;
-
-entity DuneNvmeTestUnitTop is
-generic(
-       Simulate        : boolean       := False
-);
-port (
-       sys_clk_p       : in std_logic;
-       sys_clk_n       : in std_logic;
-       sys_reset       : in std_logic;
-
-       pci_clk_p       : in std_logic;
-       pci_clk_n       : in std_logic;
-       pci_reset_n     : in std_logic;
-       
-       pci_exp_txp     : out std_logic_vector(3 downto 0);
-       pci_exp_txn     : out std_logic_vector(3 downto 0);
-       pci_exp_rxp     : in std_logic_vector(3 downto 0);
-       pci_exp_rxn     : in std_logic_vector(3 downto 0);
-
-       nvme_clk_p      : in std_logic;
-       nvme_clk_n      : in std_logic;
-       nvme_reset_n    : out std_logic;
-       nvme0_exp_txp   : out std_logic_vector(3 downto 0);
-       nvme0_exp_txn   : out std_logic_vector(3 downto 0);
-       nvme0_exp_rxp   : in std_logic_vector(3 downto 0);
-       nvme0_exp_rxn   : in std_logic_vector(3 downto 0);
-
-       leds            : out std_logic_vector(7 downto 0)
-);
-end;
-
-architecture Behavioral of DuneNvmeTestUnitTop is
-
-component Clk_core is                   
-       port (
-               clk_in1_p       : in std_logic; 
-               clk_in1_n       : in std_logic;
-               clk_out1        : out std_logic;
-               locked          : out std_logic
-       );                                     
-end component;                 
-
-component Pcie_host
-       port (
-       sys_clk : in std_logic;
-       sys_clk_gt : in std_logic;
-       sys_rst_n : in std_logic;
-       user_lnk_up : out std_logic;
-       pci_exp_txp : out std_logic_vector(3 downto 0);
-       pci_exp_txn : out std_logic_vector(3 downto 0);
-       pci_exp_rxp : in std_logic_vector(3 downto 0);
-       pci_exp_rxn : in std_logic_vector(3 downto 0);
-       axi_aclk : out std_logic;
-       axi_aresetn : out std_logic;
-       usr_irq_req : in std_logic_vector(0 downto 0);
-       usr_irq_ack : out std_logic_vector(0 downto 0);
-       msi_enable : out std_logic;
-       msi_vector_width : out std_logic_vector(2 downto 0);
-       m_axil_awaddr : out std_logic_vector(31 downto 0);
-       m_axil_awprot : out std_logic_vector(2 downto 0);
-       m_axil_awvalid : out std_logic;
-       m_axil_awready : in std_logic;
-       m_axil_wdata : out std_logic_vector(31 downto 0);
-       m_axil_wstrb : out std_logic_vector(3 downto 0);
-       m_axil_wvalid : out std_logic;
-       m_axil_wready : in std_logic;
-       m_axil_bvalid : in std_logic;
-       m_axil_bresp : in std_logic_vector(1 downto 0);
-       m_axil_bready : out std_logic;
-       m_axil_araddr : out std_logic_vector(31 downto 0);
-       m_axil_arprot : out std_logic_vector(2 downto 0);
-       m_axil_arvalid : out std_logic;
-       m_axil_arready : in std_logic;
-       m_axil_rdata : in std_logic_vector(31 downto 0);
-       m_axil_rresp : in std_logic_vector(1 downto 0);
-       m_axil_rvalid : in std_logic;
-       m_axil_rready : out std_logic;
-       cfg_mgmt_addr : in std_logic_vector(18 downto 0);
-       cfg_mgmt_write : in std_logic;
-       cfg_mgmt_write_data : in std_logic_vector(31 downto 0);
-       cfg_mgmt_byte_enable : in std_logic_vector(3 downto 0);
-       cfg_mgmt_read : in std_logic;
-       cfg_mgmt_read_data : out std_logic_vector(31 downto 0);
-       cfg_mgmt_read_write_done : out std_logic;
-       cfg_mgmt_type1_cfg_reg_access : in std_logic;
-       s_axis_c2h_tdata_0 : in std_logic_vector(127 downto 0);
-       s_axis_c2h_tlast_0 : in std_logic;
-       s_axis_c2h_tvalid_0 : in std_logic;
-       s_axis_c2h_tready_0 : out std_logic;
-       s_axis_c2h_tkeep_0 : in std_logic_vector(15 downto 0);
-       m_axis_h2c_tdata_0 : out std_logic_vector(127 downto 0);
-       m_axis_h2c_tlast_0 : out std_logic;
-       m_axis_h2c_tvalid_0 : out std_logic;
-       m_axis_h2c_tready_0 : in std_logic;
-       m_axis_h2c_tkeep_0 : out std_logic_vector(15 downto 0);
-
-       s_axis_c2h_tdata_1 : in std_logic_vector(127 downto 0);
-       s_axis_c2h_tlast_1 : in std_logic;
-       s_axis_c2h_tvalid_1 : in std_logic;
-       s_axis_c2h_tready_1 : out std_logic;
-       s_axis_c2h_tkeep_1 : in std_logic_vector(15 downto 0);
-       m_axis_h2c_tdata_1 : out std_logic_vector(127 downto 0);
-       m_axis_h2c_tlast_1 : out std_logic;
-       m_axis_h2c_tvalid_1 : out std_logic;
-       m_axis_h2c_tready_1 : in std_logic;
-       m_axis_h2c_tkeep_1 : out std_logic_vector(15 downto 0);
-
-       int_qpll1lock_out : out std_logic_vector(0 to 0);
-       int_qpll1outrefclk_out : out std_logic_vector(0 to 0);
-       int_qpll1outclk_out : out std_logic_vector(0 to 0)
-       );
-end component;
-
-component blk_mem_gen_0
-       port (
-       rsta_busy : out std_logic;
-       rstb_busy : out std_logic;
-       s_aclk : in std_logic;
-       s_aresetn : in std_logic;
-       s_axi_awaddr : in std_logic_vector(31 downto 0);
-       s_axi_awvalid : in std_logic;
-       s_axi_awready : out std_logic;
-       s_axi_wdata : in std_logic_vector(31 downto 0);
-       s_axi_wstrb : in std_logic_vector(3 downto 0);
-       s_axi_wvalid : in std_logic;
-       s_axi_wready : out std_logic;
-       s_axi_bresp : out std_logic_vector(1 downto 0);
-       s_axi_bvalid : out std_logic;
-       s_axi_bready : in std_logic;
-       s_axi_araddr : in std_logic_vector(31 downto 0);
-       s_axi_arvalid : in std_logic;
-       s_axi_arready : out std_logic;
-       s_axi_rdata : out std_logic_vector(31 downto 0);
-       s_axi_rresp : out std_logic_vector(1 downto 0);
-       s_axi_rvalid : out std_logic;
-       s_axi_rready : in std_logic
-       );
-end component;
-
-component NvmeStorageUnit is
-generic(
-       Simulate        : boolean       := False;               --! Generate simulation core
-       ClockPeriod     : time          := 8 ns;                --! Clock period for timers (125 MHz)
-       BlockSize       : integer       := NvmeStorageBlockSize --! System block size
-);
-port (
-       clk             : in std_logic;                         --! The interface clock line
-       reset           : in std_logic;                         --! The active high reset line
-
-       -- Control and status interface
-       axilIn          : in AxilToSlaveType;                   --! Axil bus input signals
-       axilOut         : out AxilToMasterType;                 --! Axil bus output signals
-
-       -- From host to NVMe request/reply streams
-       hostSend        : inout AxisStreamType := AxisStreamInput;      --! Host request stream
-       hostRecv        : inout AxisStreamType := AxisStreamOutput;     --! Host reply stream
-
-       -- AXIS data stream input
-       dataEnabledOut  : out std_logic;                        --! Indicates that data ingest is enabled
-       dataIn          : inout AxisStreamType := AxisStreamInput;      --! Raw data to save stream
-
-       -- NVMe interface
-       nvme_clk        : in std_logic;                         --! Nvme external clock
-       nvme_clk_gt     : in std_logic;                         --! Nvme external GT clock
-       nvme_reset_n    : out std_logic;                        --! Nvme reset output to reset NVMe devices
-       nvme_exp_txp    : out std_logic_vector(3 downto 0);     --! nvme PCIe TX plus lanes
-       nvme_exp_txn    : out std_logic_vector(3 downto 0);     --! nvme PCIe TX minus lanes
-       nvme_exp_rxp    : in std_logic_vector(3 downto 0);      --! nvme PCIe RX plus lanes
-       nvme_exp_rxn    : in std_logic_vector(3 downto 0);      --! nvme PCIe RX minus lanes
-
-       -- Debug
-       leds            : out std_logic_vector(5 downto 0)
-);
-end component;
-
-component TestDataStream is
-generic(
-       BlockSize       : integer := NvmeStorageBlockSize       --! The block size in Bytes.
-);
-port (
-       clk             : in std_logic;                         --! The interface clock line
-       reset           : in std_logic;                         --! The active high reset line
-
-       -- Control and status interface
-       enable          : in std_logic;                         --! Enable production of data
-
-       -- AXIS data output
-       dataOut         : inout AxisStreamType := AxisStreamOutput      --! Output data stream
-);
-end component;
-
--- Clock and controls
-signal sys_clk                 : std_logic := 'U';
-signal sys_reset_buf_n         : std_logic := 'U';
-
-signal pci_clk                 : std_logic := 'U';
-signal pci_clk_gt              : std_logic := 'U';
-signal leds_l                  : std_logic_vector(7 downto 0) := (others => '0');
-
-signal nvme_clk                        : std_logic := 'U';
-signal nvme_clk_gt             : std_logic := 'U';
-
-signal reset_n                 : std_logic := '0';
-signal boot_reset              : std_logic := '1';
-constant boot_reset_count      : natural := 2000000;   -- 10ms
-
-signal axil_clk                        : std_logic;
-signal axil_reset_n            : std_logic;
-signal axil_reset              : std_logic;
-
---signal usr_irq_req           : std_logic;
---signal usr_irq_ack           : std_logic;
---signal msi_enable            : std_logic;
---signal msi_vector_width      : std_logic;
-
-signal axil                    : AxilBusType;
-signal hostSend                        : AxisStreamType;
-signal hostSend_keep           : std_logic_vector(15 downto 0);
-signal hostRecv                        : AxisStreamType;
-signal hostRecv_keep           : std_logic_vector(15 downto 0);
-signal nvmeReq                 : AxisStreamType;
-signal nvmeReq_keep            : std_logic_vector(15 downto 0);
-signal nvmeReply               : AxisStreamType;
-signal nvmereply_keep          : std_logic_vector(15 downto 0);
-signal testDataStream          : AxisStreamType;
-signal dataEnabled             : std_logic;
-
-signal hostSend1               : AxisStreamType := AxisStreamInput;
-signal hostRecv1               : AxisStreamType := AxisStreamOutput;
-
-begin
-       -- System clock just used for a boot reset
-       sys_clk_buf : Clk_core port map (
-               clk_in1_p       => sys_clk_p,
-               clk_in1_n       => sys_clk_n,
-               clk_out1        => sys_clk
-       );
-
-       -- Early testing special resets
-       --reset_n <= not (sys_reset or not pci_reset_n or boot_reset);
-       --reset_n <= not (sys_reset or not pci_reset_n);
-       --reset_n <= pci_reset_n;
-
-       --sys_reset_buf : BUFG port map (
-       --      I               => reset_n,
-       --      O               => sys_reset_buf_n
-       --);
-       
-       sys_reset_buf_n <= pci_reset_n;
-
-       -- PCIE Clock, 100MHz
-       pci_clk_buf0 : IBUFDS_GTE3 port map(
-               I       => pci_clk_p,
-               IB      => pci_clk_n,
-               O       => pci_clk_gt,
-               ODIV2   => pci_clk,
-               CEB     => '0'
-       );
-       
-       -- Boot Reset from power up
-       process(sys_clk, boot_reset)
-               variable count : natural range 0 to boot_reset_count;
-       begin
-               if(rising_edge(sys_clk)) then
-                       if(boot_reset = '1') then
-                               if(count >= boot_reset_count) then
-                                       boot_reset      <= '0';
-                                       count           := 0;
-                               else
-                                       count           := count + 1;
-                               end if;
-                       end if;
-               end if;
-       end process;
-       
-       -- Convert from 32bit to 8bit keeps
-       hostRecv_keep   <= concat(hostRecv.keep(3), 4) & concat(hostRecv.keep(2), 4) & concat(hostRecv.keep(1), 4) & concat(hostRecv.keep(0), 4);
-       hostSend.keep   <= hostSend_keep(12) & hostSend_keep(8) & hostSend_keep(4) & hostSend_keep(0);
-       nvmeReq_keep    <= concat(nvmeReq.keep(3), 4) & concat(nvmeReq.keep(2), 4) & concat(nvmeReq.keep(1), 4) & concat(nvmeReq.keep(0), 4);
-       nvmeReply.keep  <= nvmeReply_keep(12) & nvmeReply_keep(8) & nvmeReply_keep(4) & nvmeReply_keep(0);
-
-       -- The PCIe interface to the host
-       pcie_host0 : Pcie_host
-       port map (
-               sys_clk                 => pci_clk,
-               sys_clk_gt              => pci_clk_gt,
-               sys_rst_n               => sys_reset_buf_n,
-               pci_exp_txp             => pci_exp_txp,
-               pci_exp_txn             => pci_exp_txn,
-               pci_exp_rxp             => pci_exp_rxp,
-               pci_exp_rxn             => pci_exp_rxn,
-               
-               user_lnk_up             => leds_l(7),
-
-               usr_irq_req             => (others => '0'),
-               --usr_irq_ack           => usr_irq_ack,
-               --msi_enable            => msi_enable,
-               --msi_vector_width      => msi_vector_width,
-
-               axi_aclk                => axil_clk,
-               axi_aresetn             => axil_reset_n,
-
-               m_axil_awaddr           => axil.toSlave.awaddr,
-               m_axil_awprot           => axil.toSlave.awprot,
-               m_axil_awvalid          => axil.toSlave.awvalid,
-               m_axil_awready          => axil.toMaster.awready,
-               m_axil_wdata            => axil.toSlave.wdata,
-               m_axil_wstrb            => axil.toSlave.wstrb,
-               m_axil_wvalid           => axil.toSlave.wvalid,
-               m_axil_wready           => axil.toMaster.wready,
-               m_axil_bvalid           => axil.toMaster.bvalid,
-               m_axil_bresp            => axil.toMaster.bresp,
-               m_axil_bready           => axil.toSlave.bready,
-               m_axil_araddr           => axil.toSlave.araddr,
-               m_axil_arprot           => axil.toSlave.arprot,
-               m_axil_arvalid          => axil.toSlave.arvalid,
-               m_axil_arready          => axil.toMaster.arready,
-               m_axil_rdata            => axil.toMaster.rdata,
-               m_axil_rresp            => axil.toMaster.rresp,
-               m_axil_rvalid           => axil.toMaster.rvalid,
-               m_axil_rready           => axil.toSlave.rready,
-               
-               cfg_mgmt_addr           => (others => '0'),
-               cfg_mgmt_write          => '0',
-               cfg_mgmt_write_data     => (others => '0'),
-               cfg_mgmt_byte_enable    => (others => '0'),
-               cfg_mgmt_read           => '0',
-               --cfg_mgmt_read_data            => cfg_mgmt_read_data,
-               --cfg_mgmt_read_write_done      => cfg_mgmt_read_write_done,
-               cfg_mgmt_type1_cfg_reg_access   => '0',
-
-               s_axis_c2h_tdata_0      => hostRecv.data,
-               s_axis_c2h_tlast_0      => hostRecv.last,
-               s_axis_c2h_tvalid_0     => hostRecv.valid,
-               s_axis_c2h_tready_0     => hostRecv.ready,
-               s_axis_c2h_tkeep_0      => hostRecv_keep,
-               m_axis_h2c_tdata_0      => hostSend.data,
-               m_axis_h2c_tlast_0      => hostSend.last,
-               m_axis_h2c_tvalid_0     => hostSend.valid,
-               m_axis_h2c_tready_0     => hostSend.ready,
-               m_axis_h2c_tkeep_0      => hostSend_keep,
-
-               s_axis_c2h_tdata_1      => nvmeReq.data,
-               s_axis_c2h_tlast_1      => nvmeReq.last,
-               s_axis_c2h_tvalid_1     => nvmeReq.valid,
-               s_axis_c2h_tready_1     => nvmeReq.ready,
-               s_axis_c2h_tkeep_1      => nvmeReq_keep,
-               m_axis_h2c_tdata_1      => nvmeReply.data,
-               m_axis_h2c_tlast_1      => nvmeReply.last,
-               m_axis_h2c_tvalid_1     => nvmeReply.valid,
-               m_axis_h2c_tready_1     => nvmeReply.ready,
-               m_axis_h2c_tkeep_1      => nvmeReply_keep
-       );
-
-       zap10: if false generate
-       -- Echo back AXI streaming ports
-       hostRecv.valid  <= hostSend.valid;   
-       hostRecv.last   <= hostSend.last;   
-       hostRecv.keep   <= hostSend.keep;   
-       hostRecv.data   <= hostSend.data;  
-       hostSend.ready  <= hostRecv.ready;
-
-       nvmeReply.valid <= nvmeReq.valid;   
-       nvmeReply.last  <= nvmeReq.last;   
-       nvmeReply.keep  <= nvmeReq.keep;   
-       nvmeReply.data  <= nvmeReq.data;  
-       nvmeReq.ready   <= nvmeReply.ready;
-       end generate;
-
-       zap11: if false generate
-       -- Test Axil bus interface using blockram write/read accesses
-       bram0 : blk_mem_gen_0
-       port map (
-               --rsta_busy             => rsta_busy,
-               --rstb_busy             => rstb_busy,
-               s_aclk                  => axil_clk,
-               s_aresetn               => axil_reset_n,
-               
-               s_axi_awaddr            => axil.toSlave.awaddr,
-               s_axi_awvalid           => axil.toSlave.awvalid,
-               s_axi_awready           => axil.toMaster.awready,
-               s_axi_wdata             => axil.toSlave.wdata,
-               s_axi_wstrb             => axil.toSlave.wstrb,
-               s_axi_wvalid            => axil.toSlave.wvalid,
-               s_axi_wready            => axil.toMaster.wready,
-               s_axi_bresp             => axil.toMaster.bresp,
-               s_axi_bvalid            => axil.toMaster.bvalid,
-               s_axi_bready            => axil.toSlave.bready,
-               s_axi_araddr            => axil.toSlave.araddr,
-               s_axi_arvalid           => axil.toSlave.arvalid,
-               s_axi_arready           => axil.toMaster.arready,
-               s_axi_rdata             => axil.toMaster.rdata,
-               s_axi_rresp             => axil.toMaster.rresp,
-               s_axi_rvalid            => axil.toMaster.rvalid,
-               s_axi_rready            => axil.toSlave.rready
-       );      
-       end generate;
-       
-       zap12: if false generate
-       -- NVME Storage interface
-
-       -- NVME PCIE Clock, 100MHz
-       nvme_clk_buf0 : IBUFDS_GTE3
-       port map (
-               I       => nvme_clk_p,
-               IB      => nvme_clk_n,
-               O       => nvme_clk_gt,
-               ODIV2   => nvme_clk,
-               CEB     => '0'
-       );
-       axil_reset <= not axil_reset_n;
-       
-       hostSend.ready  <= '1';
-
-       hostSend1.valid <= '0';
-       hostSend1.last  <= '0';
-       hostSend1.keep  <= (others => '0');
-       hostSend1.data  <= (others => '0');
-       hostRecv1.ready <= '0';
-       
-       nvmeStorageUnit1 : NvmeStorageUnit
-       port map (
-               clk             => axil_clk,
-               reset           => axil_reset,
-
-               -- Control and status interface
-               axilIn          => axil.toSlave,
-               axilOut         => axil.toMaster,
-
-               -- From host to NVMe request/reply streams
-               hostSend        => hostSend1,
-               hostRecv        => hostRecv1,
-
-               -- AXIS data stream input
-               dataEnabledOut  => dataEnabled,
-               dataIn          => testDataStream,
-
-               -- NVMe interface
-               nvme_clk        => nvme_clk,
-               nvme_clk_gt     => nvme_clk_gt,
-               nvme_reset_n    => nvme_reset_n,
-               nvme_exp_txp    => nvme0_exp_txp,
-               nvme_exp_txn    => nvme0_exp_txn,
-               nvme_exp_rxp    => nvme0_exp_rxp,
-               nvme_exp_rxn    => nvme0_exp_rxn,
-
-               -- Debug
-               leds            => leds_l(3 downto 0)
-       );
-
-       -- Echo this stream     
-       nvmeReply.valid <= nvmeReq.valid;   
-       nvmeReply.last  <= nvmeReq.last;   
-       nvmeReply.keep  <= nvmeReq.keep;   
-       nvmeReply.data  <= nvmeReq.data;  
-       nvmeReq.ready   <= nvmeReply.ready;
-
-       -- The test data interface
-       testData1 : TestData
-       port map (
-               clk             => axil_clk,
-               reset           => axil_reset,
-
-               enable          => '1',
-
-               dataOut         => hostRecv
-       );
-       end generate;
-
-       zap13: if true generate
-       -- NVME Storage interface
-       axil_reset <= not axil_reset_n;
-       
-       nvmeStorageUnit0 : NvmeStorageUnit
-       port map (
-               clk             => axil_clk,
-               reset           => axil_reset,
-
-               -- Control and status interface
-               axilIn          => axil.toSlave,
-               axilOut         => axil.toMaster,
-
-               -- From host to NVMe request/reply streams
-               hostSend        => hostSend,
-               hostRecv        => hostRecv,
-
-               -- AXIS data stream input
-               dataEnabledOut  => dataEnabled,
-               dataIn          => testDataStream,
-
-               -- NVMe interface
-               nvme_clk_p      => nvme_clk_p,
-               nvme_clk_n      => nvme_clk_n,
-               nvme_reset_n    => nvme_reset_n,
-               nvme_exp_txp    => nvme0_exp_txp,
-               nvme_exp_txn    => nvme0_exp_txn,
-               nvme_exp_rxp    => nvme0_exp_rxp,
-               nvme_exp_rxn    => nvme0_exp_rxn,
-
-               -- Debug
-               leds            => leds_l(3 downto 0)
-       );
-
-       -- Echo this stream     
-       nvmeReply.valid <= nvmeReq.valid;   
-       nvmeReply.last  <= nvmeReq.last;   
-       nvmeReply.keep  <= nvmeReq.keep;   
-       nvmeReply.data  <= nvmeReq.data;  
-       nvmeReq.ready   <= nvmeReply.ready;
-
-       -- The test data interface
-       testData0 : TestData
-       port map (
-               clk             => axil_clk,
-               reset           => axil_reset,
-
-               enable          => dataEnabled,
-
-               dataOut         => testDataStream
-       );
-       end generate;
-       
-
-
-       -- Led buffers
-       obuf_leds: for i in 0 to 7 generate
-               obuf_led_i: OBUF port map (I => leds_l(i), O => leds(i));
-       end generate;
-
-       leds_l(4) <= sys_reset_buf_n;
-end;
-
diff --git a/src/DuneNvmeTestUnitTop.xdc b/src/DuneNvmeTestUnitTop.xdc
deleted file mode 100644 (file)
index 80db594..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-###############################################################################\r
-#      DuneNvmeTestTop.xdc     Constraints for DuneNvmeTestTop on a KCU105\r
-#      T.Barnaby,      Beam Ltd.       2020-02-23\r
-###############################################################################\r
-#\r
-\r
-# System timings\r
-#create_clock -period 5.000 -name sys_clk_p -waveform {0.000 2.500} [get_ports sys_clk_p]\r
-create_clock -period 10.000 -name pci_clk [get_ports pci_clk_p]\r
-create_clock -period 10.000 -name nvme_clk [get_ports nvme_clk_p]\r
-\r
-# Asyncronous resets\r
-set_false_path -from [get_ports sys_reset]\r
-set_false_path -from [get_ports pci_reset_n]\r
-#set_false_path -through [get_nets boot_reset]\r
-#set_false_path -through [get_nets reset_n]\r
-#set_false_path -through [get_nets sys_reset_buf_n]\r
-\r
-# PCIe Host\r
-#set_false_path -through [get_pins pcie_host0/inst/pcie3_ip_i/inst/pcie3_uscale_top_inst/pcie3_uscale_wrapper_inst/PCIE_3_1_inst/CFGMAX*]\r
-set_false_path -through [get_pins pcie_host0/inst/pcie3_ip_i/U0/pcie3_uscale_top_inst/pcie3_uscale_wrapper_inst/PCIE_3_1_inst/CFGMAX*]\r
-set_false_path -through [get_nets pcie_host0/inst/cfg_max*]\r
-set_false_path -to [get_pins -hier *sync_reg[0]/D]\r
-\r
-set_false_path -to [get_ports -filter NAME=~leds*]\r
-\r
-# General settings\r
-set_property CONFIG_VOLTAGE 1.8 [current_design]\r
-set_property CFGBVS GND [current_design]\r
-set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]\r
-\r
-# PCIe Host interface\r
-set_property PACKAGE_PIN K22 [get_ports pci_reset_n]\r
-set_property PULLUP true [get_ports pci_reset_n]\r
-set_property IOSTANDARD LVCMOS18 [get_ports pci_reset_n]\r
-set_property LOC GTHE3_COMMON_X0Y1 [get_cells pci_clk_buf0]\r
-\r
-# CPU Reset\r
-set_property PACKAGE_PIN AN8 [get_ports sys_reset]\r
-set_property PULLUP false [get_ports sys_reset]\r
-set_property IOSTANDARD LVCMOS18 [get_ports sys_reset]\r
-\r
-# LED's\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[0]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[1]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[2]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[3]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[4]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[5]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[6]}]\r
-set_property IOSTANDARD LVCMOS18 [get_ports {leds[7]}]\r
-set_property DRIVE 12 [get_ports {leds[0]}]\r
-set_property DRIVE 12 [get_ports {leds[1]}]\r
-set_property DRIVE 12 [get_ports {leds[2]}]\r
-set_property DRIVE 12 [get_ports {leds[3]}]\r
-set_property DRIVE 12 [get_ports {leds[4]}]\r
-set_property DRIVE 12 [get_ports {leds[5]}]\r
-set_property DRIVE 12 [get_ports {leds[6]}]\r
-set_property DRIVE 12 [get_ports {leds[7]}]\r
-set_property SLEW SLOW [get_ports {leds[0]}]\r
-set_property SLEW SLOW [get_ports {leds[1]}]\r
-set_property SLEW SLOW [get_ports {leds[2]}]\r
-set_property SLEW SLOW [get_ports {leds[3]}]\r
-set_property SLEW SLOW [get_ports {leds[4]}]\r
-set_property SLEW SLOW [get_ports {leds[5]}]\r
-set_property SLEW SLOW [get_ports {leds[6]}]\r
-set_property SLEW SLOW [get_ports {leds[7]}]\r
-set_property PACKAGE_PIN AP8 [get_ports {leds[0]}]\r
-set_property PACKAGE_PIN H23 [get_ports {leds[1]}]\r
-set_property PACKAGE_PIN P20 [get_ports {leds[2]}]\r
-set_property PACKAGE_PIN P21 [get_ports {leds[3]}]\r
-set_property PACKAGE_PIN N22 [get_ports {leds[4]}]\r
-set_property PACKAGE_PIN M22 [get_ports {leds[5]}]\r
-set_property PACKAGE_PIN R23 [get_ports {leds[6]}]\r
-set_property PACKAGE_PIN P23 [get_ports {leds[7]}]\r
-\r
-# PCIe Nvme0 interface\r
-set_property PACKAGE_PIN H11 [get_ports nvme_reset_n]\r
-set_property PULLUP true [get_ports nvme_reset_n]\r
-set_property IOSTANDARD LVCMOS18 [get_ports nvme_reset_n]\r
-#set_property LOC GTHE3_COMMON_X0Y1 [get_cells nvme_clk_buf0]\r
-\r
-set_property PACKAGE_PIN K6 [get_ports {nvme_clk_p}]\r
-set_property PACKAGE_PIN K5 [get_ports {nvme_clk_n}]\r
index 3f952e98dc9f3d14c331ececd3e43193dd1b4ad1..6f438ddd669450335a434465584f301ba3b9e70f 100644 (file)
@@ -5,18 +5,23 @@
 --! @class     NvmeConfig
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-12
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module configures a Nvme device for operation.
 --!
 --! @details
 --! This has a set of PCIe requests hard coded in a ROM that are sent out on the
---!  streamOut stream when the configStart signal is set high for one clock period.
+--! streamOut stream when the configStart signal is set high for one clock period.
 --! The module ignores all replies and assumes all requests complete with no errors.
 --! The configComplete signal is set high on completion.
---! The ROM's contents have a list of 128 bit words. There will be a set of a PCIe TLP header word followed by its data words.
---! The TLP headers count field specifires how many 32 bit words of data follow the header.
+--! The ROM's contents have a list of 128 bit words. There will be a set of a requests
+--! consisting of a PCIe TLP header followed by its data words.
+--! The TLP headers count field specifies how many 32 bit words of data follow the header.
+--! A 128 bit entry of all 0's terminates the list of Pcie requests.
+--! The module will wait 100ms before starting configuration to allow its use directly after a device reset.
+--! This time allows the Nvme device to complete its internal initialisation.
+--! The ClockPeriod parameter should be set to the clocks period to achieve the correct delay timing.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -44,7 +49,7 @@ use work.NvmeStorageIntPkg.all;
 
 entity NvmeConfig is
 generic(
-       ClockPeriod     : time := 8 ns                          --! Clock period for timers (125 MHz)
+       ClockPeriod     : time := 8 ns                          --! Clock period for timers (250 MHz)
 );
 port (
        clk             : in std_logic;                         --! The interface clock line
@@ -55,7 +60,7 @@ port (
 
        -- From host to NVMe request/reply streams
        streamOut       : inout AxisStreamType := AxisStreamOutput;     --! Nvme request stream
-       streamIn        : inout AxisStreamType := AxisStreamInput               --! Nvme reply stream
+       streamIn        : inout AxisStreamType := AxisStreamInput       --! Nvme reply stream
 );
 end;
 
@@ -101,7 +106,7 @@ constant rom        : RomType(0 to 41) := (
        -- Notify queue entry to Nvme
        setHeader(1, 16#1000#, 1, 0), to_stl(1, 128),
        
-       -- Wait for reply in queue, how to do this ???
+       -- Could Wait for reply in queue
 
        -- Create DataWrite request queue by sending 64byte request to Admin queue
        setHeader(12, 16#02000000#, 16, 0),
@@ -113,7 +118,7 @@ constant rom        : RomType(0 to 41) := (
        -- Notify queue entry to Nvme
        setHeader(1, 16#1000#, 1, 0), to_stl(2, 128),
        
-       -- Wait for reply in queue, how to do this ???
+       -- Could Wait for reply in queue
        
        -- Create DataRead reply queue (8 entries)  by sending 64byte request to Admin queue
        setHeader(12, 16#02000000#, 16, 0),
@@ -125,7 +130,7 @@ constant rom        : RomType(0 to 41) := (
        -- Notify queue entry to Nvme
        setHeader(1, 16#1000#, 1, 0), to_stl(1, 128),
        
-       -- Wait for reply in queue, how to do this ???
+       -- Could Wait for reply in queue
 
        -- Create DataRead request queue by sending 64byte request to Admin queue
        setHeader(12, 16#02000000#, 16, 0),
@@ -137,8 +142,7 @@ constant rom        : RomType(0 to 41) := (
        -- Notify queue entry to Nvme
        setHeader(1, 16#1000#, 1, 0), to_stl(2, 128),
        
-       -- Wait for reply in queue, how to do this ???
-       
+       -- Could Wait for reply in queue
 
        -- Start controller
        setHeader(1, 16#0014#, 1, 0), to_stl(x"00460001", 128),
@@ -177,7 +181,7 @@ begin
                                        if(configStart = '1') then
                                                count           <= 0;
                                                configComplete  <= '0';
-                                               delay           <= 100 ms / ClockPeriod;        -- Started from reset, delay for 100ms
+                                               delay           <= 100 ms / ClockPeriod;        --! Started from reset, delay for 100ms
                                                state           <= STATE_DELAY;
                                        end if;
 
index 77dbcfb24e7fce28e08ea3e4dd782db1446204e9..99449dcfa88cafebf33d4b42a167e550da83d452 100644 (file)
@@ -5,23 +5,27 @@
 --! @class     NvmeQueues
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-04-08
---! @version   0.2.0
+--! @version   1.0.0
 --!
 --! @brief
 --! This module implements the Nvme request/reply queues in RAM
 --!
 --! @details
---! This module provides the ability to write a request to one of the 4 Nvme request queues
+--! This module provides the ability to write a request to one of 4 Nvme request queues
 --! and receive the queued replies. This engine handles the queue location and informs
 --! the Nvme of the new queue entry by writing to the appropriate doorbell register.
 --! It supports queue memory reads from the Nvme device.
---! When the Nvme writes to a reply queue, the queue reply messages is directly sent to
---! the originator of the request as given in the CID field.
---! The process sending a requests simply uses a PcieWrite request to the appropriate queue memory location.
---! The NvmeQueue engine handles wrting this to the next available queue entry slot.
---! The queue replies are sent to the originator as a PcieWrite request with the address set to the reply
---! queues address (0x0201XXXXX).
---! 
+--! When the Nvme writes to a reply queue, the queue reply message is directly sent on to
+--! the originator of the request as given in the CID field rather than stored in RAM.
+--! The process sending a requests simply uses a PcieWrite request to the appropriate queue's starting
+--! memory location.
+--! The NvmeQueue engine handles writing the queue entry data to the next available queue entry slot in RAM.
+--! The queue replies are converted into a PcieWrite request packet and sent on to the engine that
+--! created the original queue request. The address in the packet is set to the reply queues address (0x0201XXXXX)
+--! so that the originating engine can determine that this is a reply to its queued request.
+--! The module needs to know the dooerbell register stride of the actual NVMe devices in use. This is passed
+--! in as the NvmeRegStride parameter.
+--! The NumQueueEntries parameter defines the size of all queues.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -58,7 +62,7 @@ port (
        reset           : in std_logic;                         --! The active high reset line
        
        streamIn        : inout AxisStreamType := AxisStreamInput;      --! Request queue entries
-       streamOut       : inout AxisStreamType := AxisStreamOutput      --! replies and requests
+       streamOut       : inout AxisStreamType := AxisStreamOutput      --! Replies and requests
 );
 end;
 
@@ -74,7 +78,7 @@ generic (
        DataWidth       : integer := 128;                       --! The data width of the RAM in bits
        Size            : integer := RAM_SIZE;                  --! The size in RAM locations
        AddressWidth    : integer := log2(RAM_SIZE);
-       RegisterOutputs : boolean := False                      --! Register the outputs
+       RegisterOutputs : boolean := False                      --! Don't register the outputs to reduce latency
 );
 port (
        clk             : in std_logic;                         --! The interface clock line
index 65fbddcb705dd1592e6c6a01ece76854298455c0..23e5d811c07a82543446cd592b3ef957ff1eb70f 100644 (file)
@@ -5,13 +5,23 @@
 --! @class     NvmeRead
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-14
---! @version   0.4.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module performs the Nvme read data functionality.
 --!
 --! @details
---! TBD
+--! This is a simple module that provides a set of host accessible registers that can be
+--! used to read data from the Nvme device.
+--! It requires the NvmeBlockSize and NvmeTotalBlocks parameters to be set for the Nvme device
+--! in use.
+--! To use the host sets the starting 4k block number to read, the number of blocks to read and
+--! then sets the enable bit is set in the control register.
+--! the NvmeRead module will then start sending NVme block read requests to the Nvme device.
+--! These requests have the Pcie read data address set to 0x01FXXXXX with XXXXX set to the byte
+--! address of the block. The Nvme will send Pcie write requests to this address and hence
+--! the host will receive a set of Pcie write request packets with the address 0x01FXXXXX.
+--! These packets will contain the block data and be sized to the Pcie max payload size.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
index 751206fa408008c55626b22ad38de15f2601b2e9..1a1d75c3be3c5669f4de45637c2f2bc7748bd916 100644 (file)
@@ -5,11 +5,11 @@
 --! @class     NvmeSim
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-03-13
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This is a very basic module to simulate an NVMe device connected via PCIe to
---!  the Xilinx PCIe Gen3 IP block.
+--! the Xilinx PCIe Gen3 IP block.
 --!
 --! @details
 --! This is a very basic module to simulate an NVMe device connected via PCIe to the Xilinx PCIe Gen3 IP block.
 --!
 --! The core responds to specific configuration space writes and specific NVMe register writes (Queue door bell registers).
 --! The module makes PCIe read/write requests to access the request/reply queues and data input/output memory
---!  in a similar manner to a real NVMe device.
+--! in a similar manner to a real NVMe device.
 --!
---! Simple interface ignoring actual data values and 32bit dataword positions with 128 bit transfered words.
+--! It has a simple interface ignoring actual data values and 32bit dataword positions within 128 bit transfered words.
 --!
---! NVMe requests not pipelined and carried out one at a time, in sequence.
+--! NVMe requests are not pipelined and carried out one at a time, in sequence.
 --! Currently does not perform configuration or NVMe register read operations.
---! Currently does not handle NVMe read data requests.
---! Note NvmeSim still pretty basic.
+--! NvmeSim is still pretty basic.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -134,7 +133,7 @@ begin
 end;
 
 begin
-       -- Host requests including register access
+       --! Host requests including register access
        hostRequestHead         <= to_PcieRequestHeadType(hostReq.data);
        regData                 <= reg_pci_command when hostRequestHead1.address = x"4" else x"FFFFFFFF";
 
@@ -157,7 +156,7 @@ begin
                                        else to_stl(nvmeRequestHead);
        nvmeReply1Head          <= to_PcieReplyHeadType(nvmeReply1.data);
 
-       -- Process host requests
+       --! Process host request packets
        process(clk)
        begin
                if(rising_edge(clk)) then
@@ -248,7 +247,7 @@ begin
        end process;
 
 
-       -- Process requests
+       --! Process queued requests
        process(clk)
        begin
                if(rising_edge(clk)) then
index e37b078d4417e127ee96efb9ba252cff34d4b688..24bea15b4d657098b4880e957ab29824fa7d56a6 100644 (file)
@@ -5,7 +5,7 @@
 --! @class     NvmeStorage
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-12
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This is the main top level NvmeStorage module that provides access to the NVMe devices
 --!
 --! @details
 --! The main Nvme working module is NvmeStorageUnit. This NvmeStorage module splits the incomming
---! data stream into two at the NvmeStoargeBlock level (8k) passing alternate blocks into the two
+--! data stream into two at the NvmeStoargeBlock level (4k) passing alternate blocks into the two
 --! NvmeStorageUnit engines.
---! At the moment, during development, it just passes the data through to a single NvmeStorageUnit module.
+--! It passes register access signals to both NvmeStorageUnit's and multiplexes/de-multiplexes the
+--! AXI4 Streams from/to these.
+--!
+--! The module accepts a 250 MHz clock input to which all input and output signals are syncronised with.
+--! The Platform parameter is available to handle alternative Pcie hard block interface types.
+--! The UseConfigure parameter sets the system to automatically configure the Nvme device on reset.
+--! Parameters for the actual Nvme device in use need to be set in the NvmeBlockSize, NvmeTotalBlocks and
+--! NvmeRegStride parameters.
 --! See the DuneNvmeStorageManual for more details.
 --!
 --! @copyright GNU GPL License
@@ -161,8 +168,8 @@ end component;
 
 component NvmeStreamMux is
 port (
-       clk             : in std_logic;                         --! The interface clock line
-       reset           : in std_logic;                         --! The active high reset line
+       clk             : in std_logic;                                 --! The interface clock line
+       reset           : in std_logic;                                 --! The active high reset line
        
        hostIn          : inout AxisStreamType := AxisStreamInput;      --! Host multiplexed Input stream
        hostOut         : inout AxisStreamType := AxisStreamOutput;     --! Host multiplexed Ouput stream
@@ -273,6 +280,7 @@ begin
        dataIn1.last    <= dataIn.last;
        dataIn1.data    <= dataIn.data;
 
+       --! Store incomming block for Nvme0
        dataConvert0 : AxisDataConvertFifo
        port map (
                clk             => clk,
@@ -284,6 +292,7 @@ begin
                streamTx        => data0
        );
 
+       --! Store incomming block for Nvme1
        dataConvert1 : AxisDataConvertFifo
        port map (
                clk             => clk,
@@ -295,6 +304,7 @@ begin
                streamTx        => data1
        );
        
+       --! Implement input block dropping on request.
        process(clk)
        begin
                if(rising_edge(clk)) then
@@ -332,6 +342,7 @@ begin
        axisConnect(hostSend0, hostSend, hostSend_ready);
        axisConnect(hostRecv, hostRecv_ready, hostRecv0);
 
+       --! Multiplex/de-multiplex Pcie packet streams to the two NvmeStorageUnits
        nvmeStreamMux0 : NvmeStreamMux
        port map (
                clk             => clk,
@@ -347,6 +358,7 @@ begin
                nvme1Out        => nvme1Recv
        );
 
+       --! Nvme0 storage unit
        nvmeStorageUnit0 : NvmeStorageUnit
        generic map (
                PcieCore        => 0                    --! The Pcie hardblock block to use
@@ -378,6 +390,7 @@ begin
                leds            => leds(2 downto 0)
        );
 
+       --! Nvme1 storage unit
        nvmeStorageUnit1 : NvmeStorageUnit
        generic map (
                PcieCore        => 1                    --! The Pcie hardblock block to use
index 662035ff7df480e7024a33218eb7877a7ad9044f..55ab34119754ab2aa30c4055f6ff67d4432a2943 100644 (file)
@@ -6,12 +6,13 @@
 --! @class     NvmeStorageIntPkg
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-03-18
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This package provides definitions for the NvmeStorage system internals.
 --!
 --! @details
+--! Included are useful functions, core system types and overal system parameters.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -35,7 +36,7 @@ use work.NvmeStoragePkg.all;
 
 package NvmeStorageIntPkg is
        --! System constants
-       constant NvmeQueueNum           : integer := 16;        --! The number of queue entries. Has to be greater than NvmeWriteNum
+       constant NvmeQueueNum           : integer := 16;        --! The number of queue entries. Has to be greater than NvmeWriteNum and number of trim requests
        constant NvmeWriteNum           : integer := 8;         --! The number of concurrent data write's.
        constant PcieMaxPayloadSize     : integer := 32;        --! The maximum Pcie packet size in 32bit DWords
 
@@ -54,9 +55,9 @@ package NvmeStorageIntPkg is
        function keepBits(numWords: integer) return std_logic_vector;
 
        --! AXI Stream interface
-       --! This implemtation of Axis makes it easy to pass and manipulate streams in VHDL. It's not not nice as it uses inout
+       --! This implemtation of Axis makes it easy to pass and manipulate streams in VHDL. It's not nice as it uses inout
        --! to acheive this as VHDL is very limited when using records especialy as module in's and out's.
-       --! However this scheme simplifies the code syntax a lot at the expense of less in/out validation in initial compilation stages.
+       --! However this scheme simplifies the code syntax a lot at the expense of less in/out validation in the initial compilation stages.
        constant AxisStreamDataWidth    : integer := 128;
        constant AxisStreamKeepWidth    : integer := 4;
 
@@ -79,7 +80,7 @@ package NvmeStorageIntPkg is
        procedure axisConnect(signal streamOut: inout AxisStreamType; signal streamIn: in AxisType; signal ready: out std_logic);
        
 
-       --! PCIe request packet head
+       --! PCIe request packet head. This uses the Xilinx Pcie Gen3 IP Pcie packet header style.
        type PcieRequestHeadType is record
                reply           : std_logic;                    --! This is a reply header
                address         : unsigned(31 downto 0);
@@ -93,7 +94,7 @@ package NvmeStorageIntPkg is
        function to_PcieRequestHeadType(v: std_logic_vector) return PcieRequestHeadType;
        function set_PcieRequestHeadType(requesterId: integer; request: integer; address: integer; count: integer; tag: integer) return PcieRequestHeadType;
 
-       --! PCIe reply packet head
+       --! PCIe reply packet head. This uses the Xilinx Pcie Gen3 IP Pcie packet header style.
        type PcieReplyHeadType is record
                reply           : std_logic;                    --! This is a reply header
                byteCount       : unsigned(12 downto 0);
index 4c7486754764fc557426c3b0cd48dbd8a76e5ad5..3fe88f55eb5d039da9bdcc3930e3b59ab82e54d0 100644 (file)
@@ -5,12 +5,13 @@
 --! @class     NvmeStoragePkg
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-12
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This package provides external interface definitions for the NvmeStorage module.
 --!
 --! @details
+--! Includes the record types and parameters for the NvmeStorage modules interface to external logic.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
index 436d24ef7afbe569acd4076657fc39e6e6391a7e..0eae66e39fb008b558927d59989e2f327a82bb2c 100644 (file)
@@ -5,17 +5,28 @@
 --! @class     NvmeStorageUnit
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-12
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This is the main Nvme control module for a single Nvme device.
 --!
 --! @details
---! This module manages a single Nvme device. It is controlled via a simple regsiter access interface
+--! This module manages a single Nvme device. It is controlled via a simple register access interface
 --! and an optional bi-directional PCIe packet stream.
 --! An AXI4 data stream, blocked into BlockSize Bytes using the "last" signal, is written sequentially
---! to the Nvme device. The DataChunkStart and DataChunkSize registers define the starting block number
+--! to the Nvme device's blocks. The DataChunkStart and DataChunkSize registers define the starting block number
 --! and the number of blocks to write.
+--! It accepts a 250 MHz clock input to which all input and output signals are syncronised with.
+--! Internally it uses a 250 MHz clock generated from the Nvme devices PCIe clock. The module
+--! handles the necessary clock domain crossings for this.
+--! The PcieCore parameter defines which Pcie Gen3 IP block to use allowing muliple NvmeStorageUnit's to be used
+--! in a design. Note that this is required due to the nature of the Xilinx Pcie Gen3 IP blocks implementation.
+--! It would be nice to use a generic Xilinx Pcie Gen3 IP component and set the locations of this in a system
+--! constraints file.
+--! The Platform parameter is available to handle alternative Pcie hard block interface types.
+--! The UseConfigure parameter sets the system to automatically configure the Nvme device on reset.
+--! Parameters for the actual Nvme device in use need to be set in the NvmeBlockSize, NvmeTotalBlocks and
+--! NvmeRegStride parameters.
 --! See the NvmeStorageManual for more details.
 --!
 --! @copyright GNU GPL License
@@ -553,6 +564,10 @@ begin
        
        -- Perform reset of Nvme subsystem. This implements a 100ms reset suitable for the Nvme Pcie reset.
        -- Local state machines and external Nvme devices use this reset_local signal.
+       -- Note this is asynchronous as generated by an external reset signal or on an interface clock
+       -- It would be possible to synchronise this to nvme_clk but a BUFG_GT buffer would be needed to
+       -- access the clock line for this. It is only used by the Pcie Gen3 hard block which expects an
+       -- asynchronous reset. The nvme_user_reset is generated by the hard block.
        reset_local             <= reset or reset_local_active;
        nvme_reset_local_n      <= not reset_local;
        nvme_reset_n            <= nvme_reset_local_n;
index 9d43f50fc0131e89668f5fca3b2bca50bb79fac3..722e13c57a4f815b323b9cace77c29653a059c87 100644 (file)
@@ -5,13 +5,17 @@
 --! @class     NvmeStreamMux
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-04-08
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
---! This module Multiplex/De-multiplex a stream a 128bit Axis stream into two streams using the 128bit header
+--! This module Multiplexes/De-multiplexes a 128bit Axis stream into two streams based on which Nvme device the packets are for/from.
 --!
 --! @details
---! This uses bit 96 in the Pcie header to determine which Nume device the packet should be sent too.
+--! When de-multiplexing the packets the module uses bit 80 in request packets and bit 28 in
+--! reply packets to determine which Nume device the packet should be sent too.
+--! Reply packets are determined by bit 95 being set in the packets header.
+--! When multplexing the packets to the host it sets the appropriate Pcie header bits to indicate to the
+--! host where the packet is from.
 --! It is used to pass requests from the host to the appropriate NvmeStorageUnit engine and get replies.
 --!
 --! @copyright GNU GPL License
@@ -40,8 +44,8 @@ use work.NvmeStorageIntPkg.all;
 
 entity NvmeStreamMux is
 port (
-       clk             : in std_logic;                         --! The interface clock line
-       reset           : in std_logic;                         --! The active high reset line
+       clk             : in std_logic;                                 --! The interface clock line
+       reset           : in std_logic;                                 --! The active high reset line
        
        hostIn          : inout AxisStreamType := AxisStreamInput;      --! Host multiplexed Input stream
        hostOut         : inout AxisStreamType := AxisStreamOutput;     --! Host multiplexed Ouput stream
@@ -129,7 +133,6 @@ begin
        
        
        -- Multiplex streams. Sets the Nvme number to 1 in the Nvme1 reply streams in appropriate location for request and reply packets
-       --nvme1Stream <= '0' when(((muxState = MUX_STATE_START) and (nvme0In.valid = '1')) or (muxState = MUX_STATE_SENDPACKET0)) else '1';
        nvme1Stream <= '1' when(((muxState = MUX_STATE_START) and (nvme1In.valid = '1')) or (muxState = MUX_STATE_SENDPACKET1)) else '0';
 
        nvme1StreamData <= nvme1In.data(127 downto 81) & '1' & nvme1In.data(79 downto 0) when((muxState = MUX_STATE_START) and (nvme1In.data(95) = '1'))
index f6eb9cf6d3b30f2398c4b16fb3175a87762b67ab..6046624c2a001c2cfe3e472f1f97a3dffc5c91ab 100644 (file)
@@ -5,41 +5,49 @@
 --! @class     NvmeWrite
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-11
---! @version   0.3.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module performs the Nvme write data functionality.
 --!
 --! @details
---! This module is the heart of the DuneNvme system. Its purpose is to write
+--! This module is the heart of the DuneNvmeStorage system. It's purpose is to write
 --! the incomming data blocks to the Nvme device.
 --! For performance it will concurrently write NvmeWriteNum (8) blocks.
---! It implements a set of NvmeWriteNum x 4k buffers in a single BlockRAM.
---! An input process chooses a free buffer and then writes the data from the input
---! AXIS stream into this buffer. Once complete the input process adds the buffer number
---! to a processing queue.
---! A processing process takes buffer numbers from the processing queue. When available an
+--! It implements a set of NvmeWriteNum x 4k buffers in RAM.
+--!
+--! The module is controlled by the enable line, which enables the processing of input data, and
+--! the dataChunkStart and dataChunkSize registers. The dataChunkSize register specifies how many
+--! blocks to capture. It will continue to capture whilst the enable line is high and the number
+--! of blocks captured is less than the number of blocks in the dataChunkSize register.
+--!
+--! On the start of a new data chunk capture, when the enable line goes high, the module will begin
+--! sending Trim/Deallocate requests to the Nvme drive as well as the data block data as it arrives.
+--! The unit sends the first Trim/Deallocate request before any data blocks and queues a maximum
+--! of 4 trim requests active at a time untill the entire data chunk region has been deallocated.
+--! Each trim request deallocates up to 32768 Nvme sized data blocks at a time.
+--!
+--! For the incomming data blocks, an input process chooses a free buffer and then writes the data
+--! from the data input AXIS stream into this buffer. Once complete, when the last signal is set, the
+--! input process adds the buffer's number to a processing queue.
+--! A process then takes buffer number requests from the processing queue. When available an
 --! Nvme write request is sent to the Nvme write queue.
---! On the Nvme reading the queue entry it will perform "bus master" memory reads from the
---! appropriate data buffer.
+--! On the Nvme reading the queue entry (from the NvmeQueue engine) it will perform "bus master"
+--! memory reads from the appropriate data buffer.
 --! Once the Nvme has completed the write (well taken in the write data) it will send
 --! a reply to the reply queue. The NvmeWrite's reply process will process these, storing
---! any error status, and then free the buffer that was used.
---!
---! The module is controlled by the enable line, which enables the processing of input data, and
---!  the dataChunkSize register which specifies how many blocks to capture.
---!  It will continue to capture whist the enable line is high and the number of blocks captured
---!  is less than the number of blocks in the dataChunkSize register.
+--! any error status, and then will free the buffer that was used.
 --!
 --! As the system allows up to NvmeWriteNum concurrent writes, it is able to hide ittermitant
 --! large write latencies.
 --! Notes:
---!   The parameter NvmeWriteNum should be less than NvmeQueueNum.
---!   It assumes the DuneDvme block size is set in NvmeStorageBlockSize and the DataIn stream's
+--!   The parameter NvmeWriteNum should be less than NvmeQueueNum and leave room for 4 trim requests.
+--!   It assumes the DuneDvme block size is set in BlockSize and the DataIn stream's
 --!     last signal is synchonised with the end of each input block.
---!   At the moment it assumes the Nvme's internal block size is 512 Bytes.
---!   At the moment it stores the first status reply error but continues ignoring the error.
+--!   At the moment it assumes the Nvme's internal block size is NvmeBlockSize Bytes (typically 512).
+--!   At the moment it stores the first status reply error but continues running ignoring the error.
 --!   There are no timeouts or any other error handling.
+--!   It will limit the dataChunkSize to the value of the parameter NvmeTotalBlocks.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -100,11 +108,11 @@ architecture Behavioral of NvmeWrite is
 constant TCQ           : time := 1 ns;
 constant SimDelay      : boolean := False;                     --! Input data delay after each packet for simulation tests
 constant SimWaitReply  : boolean := False;                     --! Wait for each write command to return a reply
-constant DoWrite       : boolean := True;                      --! Perform write blocks
 constant DoTrim                : boolean := True;                      --! Perform trim/deallocate functionality
+constant DoWrite       : boolean := True;                      --! Perform write blocks
 
 constant NvmeBlocks    : integer := BlockSize / NvmeBlockSize;         --! The number of Nvme blocks per NvmeStorage system block
-constant RamSize       : integer := (NvmeWriteNum * BlockSize) / 16;   -- One block per write buffer
+constant RamSize       : integer := (NvmeWriteNum * BlockSize) / 16;   --! One block per write buffer
 constant AddressWidth  : integer := log2(RamSize);
 constant BlockSizeWidth        : integer := log2(BlockSize);
 constant TrimNum       : integer := (32768 / NvmeBlocks);      --! The number of 4k blocks trimmed in one trim instructions
@@ -113,7 +121,8 @@ component Ram is
 generic(
        DataWidth       : integer := 128;
        Size            : integer := RamSize;                   --! The Buffer size in 128 bit words
-       AddressWidth    : integer := AddressWidth
+       AddressWidth    : integer := AddressWidth;
+       RegisterOutputs : boolean := False                      --! Don't register the outputs to reduce latency
 );
 port (
        clk             : in std_logic;                         --! The interface clock line
@@ -182,8 +191,8 @@ signal memRequestHead       : PcieRequestHeadType;
 signal memRequestHead1 : PcieRequestHeadType;
 signal memReplyHead    : PcieReplyHeadType;
 signal nvmeReplyHead   : NvmeReplyHeadType;
-signal memCount                : unsigned(10 downto 0);                        -- DWord data send count
-signal memChunkCount   : unsigned(10 downto 0);                        -- DWord data send within a chunk count
+signal memCount                : unsigned(10 downto 0);                -- DWord data send count
+signal memChunkCount   : unsigned(10 downto 0);                -- DWord data send within a chunk count
 signal memData         : std_logic_vector(127 downto 0);
 
 -- Register information
@@ -209,16 +218,19 @@ begin
        end if;
 end;
 
+--! The RAM start address for a particular numbered buffer
 function bufferAddress(bufferNum: integer) return unsigned is
 begin
        return to_unsigned(bufferNum, log2(NvmeWriteNum)) & to_unsigned(0, AddressWidth-log2(NvmeWriteNum));
 end;
 
+--! The Pcie address for a particular numbered buffer to give to the Nvme device
 function pcieAddress(bufferNum: integer) return std_logic_vector is
 begin
        return x"05" & zeros(32-8-log2(NvmeWriteNum)-(BlockSizeWidth)) & to_stl(bufferNum, log2(NvmeWriteNum)) & zeros(BlockSizeWidth);
 end;
 
+--! The number of blocks to trim based on how many 4k blocks left to trim
 function numTrimBlocks(total: unsigned; current: unsigned) return unsigned is
 begin
        if((current + TrimNum) > total) then
@@ -368,8 +380,8 @@ begin
                end if;
        end process;
 
-       -- Process data write. This takes the input buffers and sends a write request to the Nvme for each one that is full and
-       -- not already processed
+       -- Process data write. This implements the Trim requests and takes the input buffers and sends a write request to
+       -- the Nvme for each one that is full and not already processed
        process(clk)
        begin
                if(rising_edge(clk)) then
@@ -634,7 +646,6 @@ begin
        -- Process Nvme read data requests
        -- This processes the Nvme Pcie memory read requests for the data buffers memory.
        readEnable <= '1';
-       -- readEnable <= memReplyOut.ready and not memReplyOut.last when((memState = MEMSTATE_READHEAD) or (memState = MEMSTATE_READDATA)) else '0';
        memRequestHead  <= to_PcieRequestHeadType(memReqIn.data);
        memReplyOut.data <= memData(31 downto 0) & to_stl(memReplyHead) when(memState = MEMSTATE_READHEAD)
                else readData(31 downto 0) & memData(127 downto 32);
index fda8fa244f32f181342627e0ff5b42af92d2c9cb..581af6120c766d20b5fcd8df3deb131122b704aa 100644 (file)
@@ -5,14 +5,26 @@
 --! @class     PcieStreamMux
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-04-08
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module Multiplexes/De-multiplexes a PCIe 128 bit stream into two streams using the 128bit header
 --!
 --! @details
---! This uses bit 95 in the Pcie header to determine if packets are Pcie requests or replies and then
---! routes the packets appropriately. It is used to handle the quad stream nature of the Xilinx Pcie Gen3 hardblock.
+--! This module will multiplex two bi-directional AxisStream's into a single bi-directional stream and de-multiplex
+--! a single bi-directional stream into two such streams.
+--! It is used to handle the quad stream nature of the Xilinx Pcie Gen3 hardblock merging the two streams into one for
+--! easy processing. The Xilinx Pcie Gen3 IP uses a pair of streams for host requests to the Pcie device (stream2) and
+--! a pair of streams for Pcie device requests to the host (stream3).
+--! Because of the 4 streams and their usage each will solely transport request or reply packets. This module
+--! sets and uses the state of bit 95 in the Pcie request and reply headers when multiplexing/de-muliplexing packets
+--! to/from the single stream (stream1).
+--! When muliplexing the packets bit 95 is set in the header on any reply packets and when de-multiplexing it looks
+--! at bit 95 in the header to determine which stream to send the packet on.
+--! The RegisterOutputs parameter allows the output data streams to be latched for better system timing
+--! at the expence of a 1 clock cycle latency.
+--! the module prioritises packet replies from the Pcie device when multiplexing.
+--! The multiplex and de-multiplex processes are separate and function independantly.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -40,11 +52,11 @@ use work.NvmeStorageIntPkg.all;
 
 entity PcieStreamMux is
 generic (
-       RegisterOutputs : boolean := True                       --! Register the outputs
+       RegisterOutputs : boolean := True                               --! Register the outputs
 );
 port (
-       clk             : in std_logic;                         --! The interface clock line
-       reset           : in std_logic;                         --! The active high reset line
+       clk             : in std_logic;                                 --! The interface clock line
+       reset           : in std_logic;                                 --! The active high reset line
        
        stream1In       : inout AxisStreamType := AxisStreamInput;      --! Single multiplexed Input stream
        stream1Out      : inout AxisStreamType := AxisStreamOutput;     --! Single multiplexed Ouput stream
@@ -61,35 +73,47 @@ architecture Behavioral of PcieStreamMux is
 
 constant TCQ           : time := 1 ns;
 
-type DemuxStateType    is (DEMUX_STATE_START, DEMUX_STATE_SENDPACKET2, DEMUX_STATE_SENDPACKET3);
-signal demuxState      : DemuxStateType := DEMUX_STATE_START;
+component PcieStreamMuxFifo is
+port (
+       clk             : in std_logic;                         --! The interface clock line
+       reset           : in std_logic;                         --! The active high reset line
+       
+       streamIn        : inout AxisStreamType := AxisStreamInput;      --! Single multiplexed Input stream
+       streamOut       : inout AxisStreamType := AxisStreamOutput      --! Single multiplexed Ouput stream
+);
+end component;
+
+type DemuxStateType    is (DEMUX_STATE_HEAD, DEMUX_STATE_SENDPACKET2, DEMUX_STATE_SENDPACKET3);
+signal demuxState      : DemuxStateType := DEMUX_STATE_HEAD;
 signal demuxReply      : std_logic;
-signal demuxReg                : AxisStreamType;
+signal stream2OutFeed  : AxisStreamType;
+signal stream3OutFeed  : AxisStreamType;
 
-type MuxStateType      is (MUX_STATE_START, MUX_STATE_SENDPACKET2, MUX_STATE_SENDPACKET3);
-signal muxState                : MuxStateType := MUX_STATE_START;
-signal muxReply                : std_logic;
+type MuxStateType      is (MUX_STATE_HEAD, MUX_STATE_SENDPACKET2, MUX_STATE_SENDPACKET3);
+signal muxState                : MuxStateType := MUX_STATE_HEAD;
 signal muxStream2      : std_logic;
 signal muxStream2Data  : std_logic_vector(127 downto 0);
-signal muxReg          : AxisStreamType;
+signal stream1OutFeed  : AxisStreamType;
+
 
 begin
        noreg: if(not RegisterOutputs) generate
-       -- De-multiplex host -> nvme streams. Expects 128 bit header word providing destination stream number
+
+       -- De-multiplex host -> nvme streams. Expects 128 bit header word providing destination stream number and bit 95 to indicate replies.
        demuxReply <= stream1In.data(95);
 
-       stream1In.ready <= stream3Out.ready when((demuxState = DEMUX_STATE_START) and (stream1In.valid = '1') and (demuxReply = '1'))
-               else stream2Out.ready when((demuxState = DEMUX_STATE_START) and (stream1In.valid = '1') and (demuxReply = '0'))
+       stream1In.ready <= stream3Out.ready when((demuxState = DEMUX_STATE_HEAD) and (stream1In.valid = '1') and (demuxReply = '1'))
+               else stream2Out.ready when((demuxState = DEMUX_STATE_HEAD) and (stream1In.valid = '1') and (demuxReply = '0'))
                else stream2Out.ready when(demuxState = DEMUX_STATE_SENDPACKET2)
                else stream3Out.ready when(demuxState = DEMUX_STATE_SENDPACKET3)
                else stream2Out.ready and stream3Out.ready;
                
-       stream2Out.valid <= stream1In.valid when((demuxState = DEMUX_STATE_SENDPACKET2) or ((demuxState = DEMUX_STATE_START) and (demuxReply = '0'))) else '0';
+       stream2Out.valid <= stream1In.valid when((demuxState = DEMUX_STATE_SENDPACKET2) or ((demuxState = DEMUX_STATE_HEAD) and (demuxReply = '0'))) else '0';
        stream2Out.last <= stream1In.last;
        stream2Out.keep <= stream1In.keep;
        stream2Out.data <= stream1In.data;
        
-       stream3Out.valid <= stream1In.valid when((demuxState = DEMUX_STATE_SENDPACKET3) or ((demuxState = DEMUX_STATE_START) and (demuxReply = '1'))) else '0';
+       stream3Out.valid <= stream1In.valid when((demuxState = DEMUX_STATE_SENDPACKET3) or ((demuxState = DEMUX_STATE_HEAD) and (demuxReply = '1'))) else '0';
        stream3Out.last <= stream1In.last;
        stream3Out.keep <= stream1In.keep;
        stream3Out.data <= stream1In.data;
@@ -99,13 +123,13 @@ begin
        begin
                if(rising_edge(clk)) then
                        if(reset = '1') then
-                               demuxState <= DEMUX_STATE_START;
+                               demuxState <= DEMUX_STATE_HEAD;
                        else
                                case(demuxState) is
-                               when DEMUX_STATE_START =>
+                               when DEMUX_STATE_HEAD =>
                                        if((stream1In.valid = '1') and (stream1In.ready = '1')) then
                                                if(stream1In.last = '1') then
-                                                       demuxState <= DEMUX_STATE_START;
+                                                       demuxState <= DEMUX_STATE_HEAD;
                                                elsif(demuxReply = '1') then
                                                        demuxState <= DEMUX_STATE_SENDPACKET3;
                                                else
@@ -115,12 +139,12 @@ begin
 
                                when DEMUX_STATE_SENDPACKET2 =>
                                        if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream1In.last = '1')) then
-                                               demuxState <= DEMUX_STATE_START;
+                                               demuxState <= DEMUX_STATE_HEAD;
                                        end if;
 
                                when DEMUX_STATE_SENDPACKET3 =>
                                        if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream1In.last = '1')) then
-                                               demuxState <= DEMUX_STATE_START;
+                                               demuxState <= DEMUX_STATE_HEAD;
                                        end if;
                                end case;
                        end if;
@@ -128,9 +152,9 @@ begin
        end process;
        
        
-       -- Multiplex streams.
-       muxStream2 <= '1' when(((muxState = MUX_STATE_START) and (stream2In.valid = '1')) or (muxState = MUX_STATE_SENDPACKET2)) else '0';
-       muxStream2Data <= stream2In.data(127 downto 96) & '1' & stream2In.data(94 downto 0) when(muxState = MUX_STATE_START) else stream2In.data;
+       -- Multiplex streams, setting bit 95 to indicate replies.
+       muxStream2 <= '1' when(((muxState = MUX_STATE_HEAD) and (stream2In.valid = '1')) or (muxState = MUX_STATE_SENDPACKET2)) else '0';
+       muxStream2Data <= stream2In.data(127 downto 96) & '1' & stream2In.data(94 downto 0) when(muxState = MUX_STATE_HEAD) else stream2In.data;
        
        stream1Out.valid <= stream2In.valid when(muxStream2 = '1') else stream3In.valid;
        stream1Out.last <= stream2In.last when(muxStream2 = '1') else stream3In.last;
@@ -144,19 +168,19 @@ begin
        begin
                if(rising_edge(clk)) then
                        if(reset = '1') then
-                               muxState <= MUX_STATE_START;
+                               muxState <= MUX_STATE_HEAD;
                        else
                                case(muxState) is
-                               when MUX_STATE_START =>
+                               when MUX_STATE_HEAD =>
                                        if((stream2In.valid = '1') and (stream2In.ready = '1')) then
                                                if(stream2In.last = '1') then
-                                                       muxState <= MUX_STATE_START;
+                                                       muxState <= MUX_STATE_HEAD;
                                                else
                                                        muxState <= MUX_STATE_SENDPACKET2;
                                                end if;
                                        elsif((stream3In.valid = '1') and (stream3In.ready = '1')) then
                                                if(stream3In.last = '1') then
-                                                       muxState <= MUX_STATE_START;
+                                                       muxState <= MUX_STATE_HEAD;
                                                else
                                                        muxState <= MUX_STATE_SENDPACKET3;
                                                end if;
@@ -164,12 +188,12 @@ begin
 
                                when MUX_STATE_SENDPACKET2 =>
                                        if((stream2In.valid = '1') and (stream2In.ready = '1') and (stream2In.last = '1')) then
-                                               muxState <= MUX_STATE_START;
+                                               muxState <= MUX_STATE_HEAD;
                                        end if;
 
                                when MUX_STATE_SENDPACKET3 =>
                                        if((stream3In.valid = '1') and (stream3In.ready = '1') and (stream3In.last = '1')) then
-                                               muxState <= MUX_STATE_START;
+                                               muxState <= MUX_STATE_HEAD;
                                        end if;
 
                                end case;
@@ -180,99 +204,62 @@ begin
 
 
        reg: if(RegisterOutputs) generate
-       -- De-multiplex host -> nvme streams. Expects 128 bit header word providing destination stream number
-       demuxReply      <= stream1In.data(95);
-       stream1In.ready <= not demuxReg.valid;
+
+       -- De-multiplex host -> nvme streams. Expects 128 bit header word providing destination stream number and bit 95 to indicate replies.
+       demuxReply              <= stream1In.data(95);
+
+       stream1In.ready         <= stream2OutFeed.ready and stream3OutFeed.ready;
+
+       stream2OutFeed.valid    <= stream1In.valid when(((demuxState = DEMUX_STATE_HEAD) and (demuxReply = '0')) or (demuxState = DEMUX_STATE_SENDPACKET2)) else '0';
+       stream2OutFeed.keep     <= stream1In.keep;
+       stream2OutFeed.last     <= stream1In.last;
+       stream2OutFeed.data     <= stream1In.data;
+       
+       axisFifo2 : PcieStreamMuxFifo port map (
+               clk             => clk,
+               reset           => reset,
+
+               streamIn        => stream2OutFeed,
+               streamOut       => stream2Out
+       );
+
+       stream3OutFeed.valid    <= stream1In.valid when(((demuxState = DEMUX_STATE_HEAD) and (demuxReply = '1')) or (demuxState = DEMUX_STATE_SENDPACKET3)) else '0';
+       stream3OutFeed.keep     <= stream1In.keep;
+       stream3OutFeed.last     <= stream1In.last;
+       stream3OutFeed.data     <= stream1In.data;
+       
+       axisFifo3 : PcieStreamMuxFifo port map (
+               clk             => clk,
+               reset           => reset,
+
+               streamIn        => stream3OutFeed,
+               streamOut       => stream3Out
+       );
 
        process(clk)
        begin
                if(rising_edge(clk)) then
                        if(reset = '1') then
-                               demuxState <= DEMUX_STATE_START;
-                               stream2Out.valid <= '0';
-                               stream2Out.last <= '0';
-                               stream3Out.valid <= '0';
-                               stream3Out.last <= '0';
-                               demuxReg.valid <= '1';
+                               demuxState <= DEMUX_STATE_HEAD;
                        else
                                case(demuxState) is
-                               when DEMUX_STATE_START =>
-                                       demuxReg.valid <= '0';
-
-                                       if((stream1In.valid = '1') and (stream1In.ready = '1')) then
+                               when DEMUX_STATE_HEAD =>
+                                       if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream1In.last = '0')) then
                                                if(demuxReply = '1') then
-                                                       stream3Out.valid <= '1';
-                                                       stream3Out.last <= stream1In.last;
-                                                       stream3Out.keep <= stream1In.keep;
-                                                       stream3Out.data <= stream1In.data;
                                                        demuxState <= DEMUX_STATE_SENDPACKET3;
                                                else
-                                                       stream2Out.valid <= '1';
-                                                       stream2Out.last <= stream1In.last;
-                                                       stream2Out.keep <= stream1In.keep;
-                                                       stream2Out.data <= stream1In.data;
                                                        demuxState <= DEMUX_STATE_SENDPACKET2;
                                                end if;
                                        end if;
 
                                when DEMUX_STATE_SENDPACKET2 =>
-                                       if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream2Out.valid = '1') and (stream2Out.ready = '0')) then
-                                               demuxReg.valid  <= '1';
-                                               demuxReg.last   <= stream1In.last;
-                                               demuxReg.keep   <= stream1In.keep;
-                                               demuxReg.data   <= stream1In.data;
-                                       elsif(stream2Out.ready = '1') then
-                                               demuxReg.valid <= '0';
-                                       end if;
-
-                                       if((stream2Out.valid = '0') or (stream2Out.ready = '1')) then
-                                               stream2Out.valid <= stream1In.valid or demuxReg.valid;
-                                               if(demuxReg.valid = '1') then
-                                                       stream2Out.last <= demuxReg.last;
-                                                       stream2Out.keep <= demuxReg.keep;
-                                                       stream2Out.data <= demuxReg.data;
-                                               else
-                                                       stream2Out.last <= stream1In.last;
-                                                       stream2Out.keep <= stream1In.keep;
-                                                       stream2Out.data <= stream1In.data;
-                                               end if;
-                                       end if;
-                                       
-                                       if((stream2Out.valid = '1') and (stream2Out.ready = '1') and (stream2Out.last = '1')) then
-                                               demuxReg.valid  <= '0';
-                                               stream2Out.last <= '0';
-                                               stream2Out.valid<= '0';
-                                               demuxState      <= DEMUX_STATE_START;
+                                       if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream1In.last = '1')) then
+                                               demuxState      <= DEMUX_STATE_HEAD;
                                        end if;
 
                                when DEMUX_STATE_SENDPACKET3 =>
-                                       if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream3Out.valid = '1') and (stream3Out.ready = '0')) then
-                                               demuxReg.valid  <= '1';
-                                               demuxReg.last   <= stream1In.last;
-                                               demuxReg.keep   <= stream1In.keep;
-                                               demuxReg.data   <= stream1In.data;
-                                       elsif(stream3Out.ready = '1') then
-                                               demuxReg.valid <= '0';
-                                       end if;
-
-                                       if((stream3Out.valid = '0') or (stream3Out.ready = '1')) then
-                                               stream3Out.valid <= stream1In.valid or demuxReg.valid;
-                                               if(demuxReg.valid = '1') then
-                                                       stream3Out.last <= demuxReg.last;
-                                                       stream3Out.keep <= demuxReg.keep;
-                                                       stream3Out.data <= demuxReg.data;
-                                               else
-                                                       stream3Out.last <= stream1In.last;
-                                                       stream3Out.keep <= stream1In.keep;
-                                                       stream3Out.data <= stream1In.data;
-                                               end if;
-                                       end if;
-                                       
-                                       if((stream3Out.valid = '1') and (stream3Out.ready = '1') and (stream3Out.last = '1')) then
-                                               demuxReg.valid  <= '0';
-                                               stream3Out.last <= '0';
-                                               stream3Out.valid<= '0';
-                                               demuxState      <= DEMUX_STATE_START;
+                                       if((stream1In.valid = '1') and (stream1In.ready = '1') and (stream1In.last = '1')) then
+                                               demuxState      <= DEMUX_STATE_HEAD;
                                        end if;
 
                                end case;
@@ -281,134 +268,148 @@ begin
        end process;
        
        
-       -- Multiplex streams.
-       muxStream2 <= '1' when(((muxState = MUX_STATE_START) and (stream2In.valid = '1')) or (muxState = MUX_STATE_SENDPACKET2)) else '0';
-       muxStream2Data <= stream2In.data(127 downto 96) & '1' & stream2In.data(94 downto 0) when(muxState = MUX_STATE_START) else stream2In.data;
+       -- Multiplex streams, setting bit 95 to indicate replies.
+       muxStream2 <= '1' when(((muxState = MUX_STATE_HEAD) and (stream2In.valid = '1')) or (muxState = MUX_STATE_SENDPACKET2)) else '0';
+       muxStream2Data <= stream2In.data(127 downto 96) & '1' & stream2In.data(94 downto 0) when(muxState = MUX_STATE_HEAD) else stream2In.data;
+
+       stream2In.ready         <= stream1OutFeed.ready when(muxStream2 = '1') else '0';
+       stream3In.ready         <= stream1OutFeed.ready when(muxStream2 = '0') else '0';
+
+       stream1OutFeed.valid    <= stream2In.valid when(muxStream2 = '1') else stream3In.valid;
+       stream1OutFeed.last     <= stream2In.last when(muxStream2 = '1') else stream3In.last;
+       stream1OutFeed.keep     <= stream2In.keep when(muxStream2 = '1') else stream3In.keep;
+       stream1OutFeed.data     <= muxStream2Data when(muxStream2 = '1') else stream3In.data;
+
+       axisFifo1 : PcieStreamMuxFifo port map (
+               clk             => clk,
+               reset           => reset,
+
+               streamIn        => stream1OutFeed,
+               streamOut       => stream1Out
+       );
 
        process(clk)
        begin
                if(rising_edge(clk)) then
                        if(reset = '1') then
-                               muxState <= MUX_STATE_START;
-                               stream2In.ready <= '0';
-                               stream3In.ready <= '0';
-                               stream1Out.valid <= '0';
-                               muxReg.valid    <= '1';
+                               muxState <= MUX_STATE_HEAD;
                                
                        else
                                case(muxState) is
-                               when MUX_STATE_START =>
-                                       stream2In.ready <= '0';
-                                       stream3In.ready <= '0';
-                                       stream1Out.valid <= '0';
-                                       stream1Out.last <= '0';
-                                       muxReg.valid    <= '0';
-
-                                       if((stream2In.valid = '1') and (stream1In.ready = '1')) then
-                                               muxReg.valid    <= '1';
-                                               muxReg.last     <= stream2In.last;
-                                               muxReg.keep     <= stream2In.keep;
-                                               muxReg.data     <= muxStream2Data;
-                                               stream2In.ready <= '1';
+                               when MUX_STATE_HEAD =>
+                                       if((stream2In.valid = '1') and (stream2In.ready = '1') and (stream2In.last = '0')) then
                                                muxState <= MUX_STATE_SENDPACKET2;
 
-                                       elsif((stream3In.valid = '1') and (stream1In.ready = '1')) then
-                                               muxReg.valid    <= '1';
-                                               muxReg.last     <= stream3In.last;
-                                               muxReg.keep     <= stream3In.keep;
-                                               muxReg.data     <= stream3In.data;
-                                               stream3In.ready <= '1';
+                                       elsif((stream3In.valid = '1') and (stream3In.ready = '1') and (stream3In.last = '0')) then
                                                muxState <= MUX_STATE_SENDPACKET3;
                                        end if;
 
                                when MUX_STATE_SENDPACKET2 =>
-                                       if((stream2In.valid = '1') and (stream2In.ready = '1') and (stream1Out.valid = '1') and (stream1Out.ready = '0')) then
-                                               muxReg.valid    <= '1';
-                                               stream2In.ready <= '0';
-                                               muxReg.last     <= stream2In.last;
-                                               muxReg.keep     <= stream2In.keep;
-                                               muxReg.data     <= stream2In.data;
-                                       elsif(stream1Out.ready = '1') then
-                                               if((muxReg.valid = '1') and (muxReg.last = '1')) then
-                                                       stream2In.ready <= '0';
-                                               elsif((muxReg.valid = '0') and (stream2In.last = '1')) then
-                                                       stream2In.ready <= '0';
-                                               else
-                                                       stream2In.ready <= '1';
-                                               end if;
-                                               muxReg.valid <= '0';
+                                       if((stream2In.valid = '1') and (stream2In.ready = '1') and (stream2In.last = '1')) then
+                                               muxState <= MUX_STATE_HEAD;
                                        end if;
 
-                                       if((stream1Out.valid = '0') or (stream1Out.ready = '1')) then
-                                               stream1Out.valid <= stream2In.valid or muxReg.valid;
-                                               if(muxReg.valid = '1') then
-                                                       stream1Out.last <= muxReg.last;
-                                                       stream1Out.keep <= muxReg.keep;
-                                                       stream1Out.data <= muxReg.data;
-                                               else
-                                                       stream1Out.last <= stream2In.last;
-                                                       stream1Out.keep <= stream2In.keep;
-                                                       stream1Out.data <= stream2In.data;
-                                               end if;
+                               when MUX_STATE_SENDPACKET3 =>
+                                       if((stream3In.valid = '1') and (stream3In.ready = '1') and (stream3In.last = '1')) then
+                                               muxState <= MUX_STATE_HEAD;
                                        end if;
 
-                                       if((stream2In.valid = '1') and (stream2In.ready = '1') and (stream2In.last = '1')) then
-                                               stream2In.ready <= '0';
-                                       end if;
-                                       
-                                       if((stream1Out.valid = '1') and (stream1Out.ready = '1') and (stream1Out.last = '1')) then
-                                               stream1Out.last <= '0';
-                                               stream1Out.valid <= '0';
-                                               stream2In.ready <= '0';
-                                               muxState <= MUX_STATE_START;
-                                       end if;
+                               end case;
+                       end if;
+               end if;
+       end process;
+       end generate;
+end;
 
 
-                               when MUX_STATE_SENDPACKET3 =>
-                                       if((stream3In.valid = '1') and (stream3In.ready = '1') and (stream1Out.valid = '1') and (stream1Out.ready = '0')) then
-                                               muxReg.valid    <= '1';
-                                               stream3In.ready <= '0';
-                                               muxReg.last     <= stream3In.last;
-                                               muxReg.keep     <= stream3In.keep;
-                                               muxReg.data     <= stream3In.data;
-                                       elsif(stream1Out.ready = '1') then
-                                               if((muxReg.valid = '1') and (muxReg.last = '1')) then
-                                                       stream3In.ready <= '0';
-                                               elsif((muxReg.valid = '0') and (stream3In.last = '1')) then
-                                                       stream3In.ready <= '0';
-                                               else
-                                                       stream3In.ready <= '1';
-                                               end if;
-                                               muxReg.valid <= '0';
-                                       end if;
+--------------------------------------------------------------------------------
+-- PcieStreamMuxFifo.vhd Simple 1/2 stage Fifo
+-------------------------------------------------------------------------------
+--!
+--! @class     PcieStreamMuxFifo
+--! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
+--! @date      2020-05-31
+--! @version   1.0.0
+--!
+--! @brief
+--! This module implements a simple 1/2 stage Fifo for the PcieStreamMux module
+--!
+--! @details
+--! This is a simple 1/2 register FIFO of AxisStream's.
+--!
+--! @copyright GNU GPL License
+--! Copyright (c) Beam Ltd, All rights reserved. <br>
+--! This code is free software: you can redistribute it and/or modify
+--! it under the terms of the GNU General Public License as published by
+--! the Free Software Foundation, either version 3 of the License, or
+--! (at your option) any later version.
+--! This program is distributed in the hope that it will be useful,
+--! but WITHOUT ANY WARRANTY; without even the implied warranty of
+--! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+--! GNU General Public License for more details. <br>
+--! You should have received a copy of the GNU General Public License
+--! along with this code. If not, see <https://www.gnu.org/licenses/>.
+--!
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
 
-                                       if((stream1Out.valid = '0') or (stream1Out.ready = '1')) then
-                                               stream1Out.valid <= stream3In.valid or muxReg.valid;
-                                               if(muxReg.valid = '1') then
-                                                       stream1Out.last <= muxReg.last;
-                                                       stream1Out.keep <= muxReg.keep;
-                                                       stream1Out.data <= muxReg.data;
-                                               else
-                                                       stream1Out.last <= stream3In.last;
-                                                       stream1Out.keep <= stream3In.keep;
-                                                       stream1Out.data <= stream3In.data;
-                                               end if;
-                                       end if;
+library unisim;
+use unisim.vcomponents.all;
 
-                                       if((stream3In.valid = '1') and (stream3In.ready = '1') and (stream3In.last = '1')) then
-                                               stream3In.ready <= '0';
-                                       end if;
+library work;
+use work.NvmeStoragePkg.all;
+use work.NvmeStorageIntPkg.all;
 
-                                       if((stream1Out.valid = '1') and (stream1Out.ready = '1') and (stream1Out.last = '1')) then
-                                               stream1Out.last <= '0';
-                                               stream1Out.valid <= '0';
-                                               stream3In.ready <= '0';
-                                               muxState <= MUX_STATE_START;
-                                       end if;
+entity PcieStreamMuxFifo is
+port (
+       clk             : in std_logic;                                 --! The interface clock line
+       reset           : in std_logic;                                 --! The active high reset line
+       
+       streamIn        : inout AxisStreamType := AxisStreamInput;      --! Single multiplexed Input stream
+       streamOut       : inout AxisStreamType := AxisStreamOutput      --! Single multiplexed Ouput stream
+);
+end;
 
-                               end case;
+architecture Behavioral of PcieStreamMuxFifo is
+
+constant TCQ           : time := 1 ns;
+signal reg0            : AxisStreamType;
+
+begin
+       process(clk)
+       begin
+               if(rising_edge(clk)) then
+                       if(reset = '1') then
+                               streamIn.ready  <= '1';
+                               streamOut.valid <= '0';
+                               reg0.valid      <= '0';
+                               
+                       else
+                               if((streamIn.valid = '1') and (streamIn.ready = '1') and (streamOut.valid = '1') and (streamOut.ready = '0')) then
+                                       streamIn.ready  <= '0';
+                                       reg0.valid      <= '1';
+                                       reg0.last       <= streamIn.last;
+                                       reg0.keep       <= streamIn.keep;
+                                       reg0.data       <= streamIn.data;
+                               elsif(streamOut.ready = '1') then
+                                       streamIn.ready  <= '1';
+                                       reg0.valid      <= '0';
+                               end if;
+
+                               if((streamOut.valid = '0') or (streamOut.ready = '1')) then
+                                       streamOut.valid <= streamIn.valid or reg0.valid;
+                                       if(reg0.valid = '1') then
+                                               streamOut.last <= reg0.last;
+                                               streamOut.keep <= reg0.keep;
+                                               streamOut.data <= reg0.data;
+                                       else
+                                               streamOut.last <= streamIn.last;
+                                               streamOut.keep <= streamIn.keep;
+                                               streamOut.data <= streamIn.data;
+                                       end if;
+                               end if;
                        end if;
                end if;
        end process;
-       end generate;
 end;
index e62867373ca84b35749e93cc33194b2d0c47ca49..7f673348214a7d53c4bf6338cca8d497bf58ae9f 100644 (file)
 --! This module provides a simple dual ported RAM module that will be implemented in blockram if large enough.
 --!
 --! @details
---! This is a simple RAM element written so that blockram can be easily infered by synthesis tools.
---! 
+--! This is a simple single clock dual ported RAM element written so that blockram can be easily infered by synthesis tools.
+--! The data width and size of the RAM are configurable parameters.
+--! Writes to memory happen in 1 clock cycle when the writeEnable signal is high.
+--! Reads from memory take two clock cycles. One to latch the read address and one for the readData to become available.
+--! There is a RegisterOutputs option on the readData output that will use the block RAM's
+--! internal data register for better system timing. This will add an additional 1 cycle latency on
+--! memory reads.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
index 3f048d26c5c24d0ad1929d9ce2c95657c4b7d080..2d5f401813f43830d2538e612bd3000c3bded93b 100644 (file)
@@ -5,17 +5,20 @@
 --! @class     RegAccessClockConvertor
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-18
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module passes register access signals across a clock domain
 --!
 --! @details
---! This is a very simple, low utilisation clock domain crossing unit for the register interface.
+--! This is a very simple, low utilisation, clock domain crossing unit for the register interface.
 --! It is designed to work with asynchronous clocks of the same frequency.
 --! It assumes the write signal is delayed by 1 cycle from the address and data transitions to
 --! make sure all bits are stable before the actual register write.
---! For reads you need to wait 5 cycles.
+--! For reads you need to wait 6 cycles for the read data to be latched and sent across the clock
+--! domains.
+--! Note this module requires appropriate timing constraints for the CDC applied. This would normally
+--! a set_max_delay or set_false_path constraint on the timing to the sendCdcReg1 and recvCdcReg1 registers.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
@@ -54,7 +57,7 @@ port (
        clk2            : in std_logic;                         --! The interface clock line
        reset2          : in std_logic;                         --! The active high reset line
 
-       regWrite2       : out std_logic;                                --! Enable write to register
+       regWrite2       : out std_logic;                        --! Enable write to register
        regAddress2     : out unsigned(5 downto 0);             --! Register to read/write
        regDataIn2      : out std_logic_vector(31 downto 0);    --! Register write data
        regDataOut2     : in std_logic_vector(31 downto 0)      --! Register contents
@@ -92,6 +95,7 @@ attribute async_reg   of recvCdcReg1 : signal is "true";
 attribute async_reg    of recvCdcReg2 : signal is "true";
 
 begin
+       --! The send process
        regWrite2       <= sendCdcReg2(38);
        regAddress2     <= unsigned(sendCdcReg2(37 downto 32));
        regDataIn2      <= sendCdcReg2(31 downto 0);
@@ -112,6 +116,7 @@ begin
                end if;
        end process;
 
+       --! The receive process
        regDataOut1 <= recvCdcReg2;
 
        process(clk1)
index af8b20870868f545747a6aa7e741b2f1f6928776..d5aa6b3ff7814c25f1e63241b8507cef956cfda9 100644 (file)
@@ -5,7 +5,7 @@
 --! @class     StreamSwitch
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-04-08
---! @version   0.2
+--! @version   1.0.0
 --!
 --! @brief
 --! This module implements a PCIe packet switch transfering packets between streams.
 --! It expects Xilinx PCIe Gen3 PCIe packet headers to be used.
 --! Packets are switched based on the address fields bits 27 downto 24 in the case of request packets
 --! and on the requesterId field in the case of replies.
+--! A special bit, 29, is set in the reply header to indicate that the packet is a reply type.
 --! The switch uses a priority based on the input stream number, with 0 being the highest priority.
 --! When the switch sees a valid signal on one of the streams and its desitation stream is ready then
 --! the switch will send a complete packet, using the "last" signal to denote the end of packet.
 --! Note this simple implementation can only send one packet at a time.
+--! This simple switch only allows one packet to be transfered at a time and uses unregistered outputs
+--! to reduce latency.
 --!
 --! @copyright GNU GPL License
 --! Copyright (c) Beam Ltd, All rights reserved. <br>
index 4ff722add7f6c3c78530d965de1f080474a92ffc..ccd7a6da2ca68135355e8b1800b024db69fd2345 100644 (file)
@@ -5,13 +5,13 @@
 --! @class     TestData
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-05-12
---! @version   0.5.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module provides a simple test data source for testing the NvmeStorage system.
 --!
 --! @details
---! This module provides a sequence of 32bit incrementing values over a n bit wide AXI4 stream (multiple of 32 bits).
+--! This module provides a sequence of 32bit incrementing values over a <n> bit wide AXI4 stream (multiple of 32 bits).
 --! It sets the AXI4 streams last signal in the last word transfer of a configurable BlockSize block of data.
 --! the enable signal enables its operation and when set to 0 clears its state back to intial reset state.
 --!
index 65a9c69097a863c4cd9e93ff22511b700f7f02fd..886f900753304f96a3e49f8b047c995ffdaba109 100644 (file)
@@ -5,7 +5,7 @@
 --! @class     TestDataStream
 --! @author    Terry Barnaby (terry.barnaby@beam.ltd.uk)
 --! @date      2020-04-07
---! @version   0.0.1
+--! @version   1.0.0
 --!
 --! @brief
 --! This module provides a simple test data source for testing the NvmeStorage system.