summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/Makefile7
-rw-r--r--linux/phy_conf.h728
-rw-r--r--linux/raptor.c940
-rw-r--r--netfpga10g/constraints.ucf52
-rw-r--r--netfpga10g/hdl/buff.vhd192
-rw-r--r--netfpga10g/hdl/dma.vhd640
-rw-r--r--netfpga10g/hdl/engine.vhd570
-rw-r--r--netfpga10g/hdl/eth.vhd219
-rw-r--r--netfpga10g/hdl/eth_rx.vhd84
-rw-r--r--netfpga10g/hdl/eth_tx.vhd68
-rw-r--r--netfpga10g/hdl/mdio.vhd223
-rw-r--r--netfpga10g/hdl/pcie.vhd268
-rw-r--r--netfpga10g/hdl/pcie_rx.vhd98
-rw-r--r--netfpga10g/hdl/pcie_tx.vhd178
-rw-r--r--netfpga10g/hdl/pcie_wrapper.vhd358
-rw-r--r--netfpga10g/hdl/port_fifo.vhd94
-rw-r--r--netfpga10g/hdl/recv_mux.vhd86
-rw-r--r--netfpga10g/hdl/rx_eth.vhd168
-rw-r--r--netfpga10g/hdl/send_mux.vhd77
-rw-r--r--netfpga10g/hdl/system_loop.vhd253
-rw-r--r--netfpga10g/hdl/top.vhd243
-rw-r--r--netfpga10g/hdl/tx_eth.vhd96
-rw-r--r--netfpga10g/tests/buff_test.vhd151
-rw-r--r--netfpga10g/tests/engine_test.vhd1123
-rw-r--r--netfpga10g/tests/eth_buff_loop_test.vhd173
-rw-r--r--netfpga10g/tests/eth_rx_test.vhd225
-rw-r--r--netfpga10g/tests/eth_tx_test.vhd126
-rw-r--r--netfpga10g/tests/pcie_rx_test.vhd322
-rw-r--r--netfpga10g/tests/pcie_tx_test.vhd561
-rw-r--r--netfpga10g/tests/queue_test.vhd149
-rw-r--r--netfpga10g/tests/send_mux_test.vhd199
-rw-r--r--netfpga10g/tests/system_loop_test.vhd285
32 files changed, 8956 insertions, 0 deletions
diff --git a/linux/Makefile b/linux/Makefile
new file mode 100644
index 0000000..9c7b2b9
--- /dev/null
+++ b/linux/Makefile
@@ -0,0 +1,7 @@
+obj-m += raptor.o
+
+all:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
+
+clean:
+ make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
diff --git a/linux/phy_conf.h b/linux/phy_conf.h
new file mode 100644
index 0000000..71997ed
--- /dev/null
+++ b/linux/phy_conf.h
@@ -0,0 +1,728 @@
+
+#ifndef _PHY_CONF_H
+#define _PHY_CONF_H
+
+//#include "nf10driver.h"
+
+#define MDIO_BASE_ADDR 0x7a000000ULL // Check the Xilinx XPS Address Space if the hw changed
+
+#define PMA_MDIO_DEVICE_ADDRESS 1
+#define PCS_MDIO_DEVICE_ADDRESS 3
+#define PHY_XS_MDIO_DEVICE_ADDRESS 4
+
+#define PMA_CTL_REGISTER_ADDRESS 0x0
+#define PMA_STATUS_REGISTER_ADDRESS 0x1
+#define PMA_RESET_REGISTER_VALUE 0x8000
+#define PMA_SYS_LOOPBACK_REGISTER_VALUE 0x1
+#define PMA_RCV_SIG_DETECTED_ADDRESS 0xa
+
+#define PCS_STATUS_REGISTER_ADDRESS 0x1
+#define PHY_XS_STATUS_REGISTER_ADDRESS 0x1
+
+#define AEL_MICRO_CONTROLLER_CTL_ADDRESS 0xc04a
+
+#define AEL_I2C_CTRL 0xc30a
+#define AEL_I2C_DATA 0xc30b
+#define AEL_I2C_STAT 0xc30c
+
+#define XEL_MDIOCNTR_OFFSET 0x07F0 //< MDIO Control
+#define XEL_MDIOCNTR_STATUS_MASK 0x00000001 //< MDIO transfer in
+#define XEL_MDIO_ADDRESS_SHIFT 0x5 /**< PHY Address shift*/
+#define XEL_MDIO_ADDRESS_MASK 0x00003E0 /**< PHY Address mask */
+#define XEL_MDIOADDR_OFFSET 0x07E4 // < MDIO Address offset
+#define XEL_MDIOWR_OFFSET 0x07E8 //< MDIO write data
+#define XEL_MDIOCNTR_ENABLE_MASK 0x00000008 /**< MDIO Enable */
+#define XEL_MDIORD_OFFSET 0x07EC //< MDIO read data
+#define XEL_MDIO_OP_45_ADDRESS 0x00000000 /**< PHY address access */
+#define XEL_MDIO_OP_45_WRITE 0x00000400 /**< PHY write access */
+#define XEL_MDIO_OP_45_READ_INC 0x00000800 /**< PHY read inc access */
+#define XEL_MDIO_OP_45_READ 0x00000C00 /**< PHY read access */
+#define XEL_MDIO_CLAUSE_45 0x00001000 /**< PHY Clause type access */
+
+/* PHY module I2C device address */
+#define MODULE_DEV_ADDR 0xa0
+#define SFF_DEV_ADDR 0xa2
+
+enum {
+ MODE_TWINAX,
+ MODE_SR,
+ MODE_LR, // Not supported
+ MODE_LRM // Not supported
+};
+
+const uint16_t regs0[] = {
+ 0xc220, 0x711C
+ };
+
+const uint16_t regs1_1g[] = {
+ 0xc220, 0x744C
+ };
+
+// software reset and magic registers
+const uint16_t reset[] = {
+ 0x0000, 0xa040,
+ 0xc001, 0x0428,
+ 0xc017, 0xfeb0,
+ 0xc013, 0xf341,
+ 0xc210, 0x8000,
+ 0xc210, 0x8100,
+ 0xc210, 0x8000,
+ 0xc210, 0x0000
+ };
+
+// unpause the microprocessor
+const uint16_t regs1[] = {
+ 0xca00, 0x0080,
+ 0xca12, 0x0000
+ };
+
+// main Twinax EDC program
+const uint16_t twinax_edc[] = {
+ 0xc04a, 0x5a00,
+ 0xcc00, 0x4009,
+ 0xcc01, 0x27ff,
+ 0xcc02, 0x300f,
+ 0xcc03, 0x40aa,
+ 0xcc04, 0x401c,
+ 0xcc05, 0x401e,
+ 0xcc06, 0x2ff4,
+ 0xcc07, 0x3cd4,
+ 0xcc08, 0x2035,
+ 0xcc09, 0x3145,
+ 0xcc0a, 0x6524,
+ 0xcc0b, 0x26a2,
+ 0xcc0c, 0x3012,
+ 0xcc0d, 0x1002,
+ 0xcc0e, 0x29c2,
+ 0xcc0f, 0x3002,
+ 0xcc10, 0x1002,
+ 0xcc11, 0x2072,
+ 0xcc12, 0x3012,
+ 0xcc13, 0x1002,
+ 0xcc14, 0x22cd,
+ 0xcc15, 0x301d,
+ 0xcc16, 0x2e52,
+ 0xcc17, 0x3012,
+ 0xcc18, 0x1002,
+ 0xcc19, 0x28e2,
+ 0xcc1a, 0x3002,
+ 0xcc1b, 0x1002,
+ 0xcc1c, 0x628f,
+ 0xcc1d, 0x2ac2,
+ 0xcc1e, 0x3012,
+ 0xcc1f, 0x1002,
+ 0xcc20, 0x5553,
+ 0xcc21, 0x2ae2,
+ 0xcc22, 0x3002,
+ 0xcc23, 0x1302,
+ 0xcc24, 0x401e,
+ 0xcc25, 0x2be2,
+ 0xcc26, 0x3012,
+ 0xcc27, 0x1002,
+ 0xcc28, 0x2da2,
+ 0xcc29, 0x3012,
+ 0xcc2a, 0x1002,
+ 0xcc2b, 0x2ba2,
+ 0xcc2c, 0x3002,
+ 0xcc2d, 0x1002,
+ 0xcc2e, 0x5ee3,
+ 0xcc2f, 0x305,
+ 0xcc30, 0x400e,
+ 0xcc31, 0x2bc2,
+ 0xcc32, 0x3002,
+ 0xcc33, 0x1002,
+ 0xcc34, 0x2b82,
+ 0xcc35, 0x3012,
+ 0xcc36, 0x1002,
+ 0xcc37, 0x5663,
+ 0xcc38, 0x302,
+ 0xcc39, 0x401e,
+ 0xcc3a, 0x6f72,
+ 0xcc3b, 0x1002,
+ 0xcc3c, 0x628f,
+ 0xcc3d, 0x2be2,
+ 0xcc3e, 0x3012,
+ 0xcc3f, 0x1002,
+ 0xcc40, 0x22cd,
+ 0xcc41, 0x301d,
+ 0xcc42, 0x2e52,
+ 0xcc43, 0x3012,
+ 0xcc44, 0x1002,
+ 0xcc45, 0x2522,
+ 0xcc46, 0x3012,
+ 0xcc47, 0x1002,
+ 0xcc48, 0x2da2,
+ 0xcc49, 0x3012,
+ 0xcc4a, 0x1002,
+ 0xcc4b, 0x2ca2,
+ 0xcc4c, 0x3012,
+ 0xcc4d, 0x1002,
+ 0xcc4e, 0x2fa4,
+ 0xcc4f, 0x3cd4,
+ 0xcc50, 0x6624,
+ 0xcc51, 0x410b,
+ 0xcc52, 0x56b3,
+ 0xcc53, 0x3c4,
+ 0xcc54, 0x2fb2,
+ 0xcc55, 0x3002,
+ 0xcc56, 0x1002,
+ 0xcc57, 0x220b,
+ 0xcc58, 0x303b,
+ 0xcc59, 0x56b3,
+ 0xcc5a, 0x3c3,
+ 0xcc5b, 0x866b,
+ 0xcc5c, 0x400c,
+ 0xcc5d, 0x23a2,
+ 0xcc5e, 0x3012,
+ 0xcc5f, 0x1002,
+ 0xcc60, 0x2da2,
+ 0xcc61, 0x3012,
+ 0xcc62, 0x1002,
+ 0xcc63, 0x2ca2,
+ 0xcc64, 0x3012,
+ 0xcc65, 0x1002,
+ 0xcc66, 0x2fb4,
+ 0xcc67, 0x3cd4,
+ 0xcc68, 0x6624,
+ 0xcc69, 0x56b3,
+ 0xcc6a, 0x3c3,
+ 0xcc6b, 0x866b,
+ 0xcc6c, 0x401c,
+ 0xcc6d, 0x2205,
+ 0xcc6e, 0x3035,
+ 0xcc6f, 0x5b53,
+ 0xcc70, 0x2c52,
+ 0xcc71, 0x3002,
+ 0xcc72, 0x13c2,
+ 0xcc73, 0x5cc3,
+ 0xcc74, 0x317,
+ 0xcc75, 0x2522,
+ 0xcc76, 0x3012,
+ 0xcc77, 0x1002,
+ 0xcc78, 0x2da2,
+ 0xcc79, 0x3012,
+ 0xcc7a, 0x1002,
+ 0xcc7b, 0x2b82,
+ 0xcc7c, 0x3012,
+ 0xcc7d, 0x1002,
+ 0xcc7e, 0x5663,
+ 0xcc7f, 0x303,
+ 0xcc80, 0x401e,
+ 0xcc81, 0x004,
+ 0xcc82, 0x2c42,
+ 0xcc83, 0x3012,
+ 0xcc84, 0x1002,
+ 0xcc85, 0x6f72,
+ 0xcc86, 0x1002,
+ 0xcc87, 0x628f,
+ 0xcc88, 0x2304,
+ 0xcc89, 0x3c84,
+ 0xcc8a, 0x6436,
+ 0xcc8b, 0xdff4,
+ 0xcc8c, 0x6436,
+ 0xcc8d, 0x2ff5,
+ 0xcc8e, 0x3005,
+ 0xcc8f, 0x8656,
+ 0xcc90, 0xdfba,
+ 0xcc91, 0x56a3,
+ 0xcc92, 0xd05a,
+ 0xcc93, 0x21c2,
+ 0xcc94, 0x3012,
+ 0xcc95, 0x1392,
+ 0xcc96, 0xd05a,
+ 0xcc97, 0x56a3,
+ 0xcc98, 0xdfba,
+ 0xcc99, 0x383,
+ 0xcc9a, 0x6f72,
+ 0xcc9b, 0x1002,
+ 0xcc9c, 0x28c5,
+ 0xcc9d, 0x3005,
+ 0xcc9e, 0x4178,
+ 0xcc9f, 0x5653,
+ 0xcca0, 0x384,
+ 0xcca1, 0x22b2,
+ 0xcca2, 0x3012,
+ 0xcca3, 0x1002,
+ 0xcca4, 0x2be5,
+ 0xcca5, 0x3005,
+ 0xcca6, 0x41e8,
+ 0xcca7, 0x5653,
+ 0xcca8, 0x382,
+ 0xcca9, 0x002,
+ 0xccaa, 0x4258,
+ 0xccab, 0x2474,
+ 0xccac, 0x3c84,
+ 0xccad, 0x6437,
+ 0xccae, 0xdff4,
+ 0xccaf, 0x6437,
+ 0xccb0, 0x2ff5,
+ 0xccb1, 0x3c05,
+ 0xccb2, 0x8757,
+ 0xccb3, 0xb888,
+ 0xccb4, 0x9787,
+ 0xccb5, 0xdff4,
+ 0xccb6, 0x6724,
+ 0xccb7, 0x866a,
+ 0xccb8, 0x6f72,
+ 0xccb9, 0x1002,
+ 0xccba, 0x2d01,
+ 0xccbb, 0x3011,
+ 0xccbc, 0x1001,
+ 0xccbd, 0xc620,
+ 0xccbe, 0x14e5,
+ 0xccbf, 0xc621,
+ 0xccc0, 0xc53d,
+ 0xccc1, 0xc622,
+ 0xccc2, 0x3cbe,
+ 0xccc3, 0xc623,
+ 0xccc4, 0x4452,
+ 0xccc5, 0xc624,
+ 0xccc6, 0xc5c5,
+ 0xccc7, 0xc625,
+ 0xccc8, 0xe01e,
+ 0xccc9, 0xc627,
+ 0xccca, 0x000,
+ 0xcccb, 0xc628,
+ 0xcccc, 0x000,
+ 0xcccd, 0xc62b,
+ 0xccce, 0x000,
+ 0xcccf, 0xc62c,
+ 0xccd0, 0x000,
+ 0xccd1, 0x000,
+ 0xccd2, 0x2d01,
+ 0xccd3, 0x3011,
+ 0xccd4, 0x1001,
+ 0xccd5, 0xc620,
+ 0xccd6, 0x000,
+ 0xccd7, 0xc621,
+ 0xccd8, 0x000,
+ 0xccd9, 0xc622,
+ 0xccda, 0x0ce,
+ 0xccdb, 0xc623,
+ 0xccdc, 0x07f,
+ 0xccdd, 0xc624,
+ 0xccde, 0x032,
+ 0xccdf, 0xc625,
+ 0xcce0, 0x000,
+ 0xcce1, 0xc627,
+ 0xcce2, 0x000,
+ 0xcce3, 0xc628,
+ 0xcce4, 0x000,
+ 0xcce5, 0xc62b,
+ 0xcce6, 0x000,
+ 0xcce7, 0xc62c,
+ 0xcce8, 0x000,
+ 0xcce9, 0x000,
+ 0xccea, 0x2d01,
+ 0xcceb, 0x3011,
+ 0xccec, 0x1001,
+ 0xcced, 0xc502,
+ 0xccee, 0x609f,
+ 0xccef, 0xc600,
+ 0xccf0, 0x2a6e,
+ 0xccf1, 0xc601,
+ 0xccf2, 0x2a2c,
+ 0xccf3, 0xc60c,
+ 0xccf4, 0x5400,
+ 0xccf5, 0xc710,
+ 0xccf6, 0x700,
+ 0xccf7, 0xc718,
+ 0xccf8, 0x700,
+ 0xccf9, 0xc720,
+ 0xccfa, 0x4700,
+ 0xccfb, 0xc728,
+ 0xccfc, 0x700,
+ 0xccfd, 0xc729,
+ 0xccfe, 0x1207,
+ 0xccff, 0xc801,
+ 0xcd00, 0x7f50,
+ 0xcd01, 0xc802,
+ 0xcd02, 0x7760,
+ 0xcd03, 0xc803,
+ 0xcd04, 0x7fce,
+ 0xcd05, 0xc804,
+ 0xcd06, 0x520e,
+ 0xcd07, 0xc805,
+ 0xcd08, 0x5c11,
+ 0xcd09, 0xc806,
+ 0xcd0a, 0x3c51,
+ 0xcd0b, 0xc807,
+ 0xcd0c, 0x4061,
+ 0xcd0d, 0xc808,
+ 0xcd0e, 0x49c1,
+ 0xcd0f, 0xc809,
+ 0xcd10, 0x3840,
+ 0xcd11, 0xc80a,
+ 0xcd12, 0x000,
+ 0xcd13, 0xc821,
+ 0xcd14, 0x002,
+ 0xcd15, 0xc822,
+ 0xcd16, 0x046,
+ 0xcd17, 0xc844,
+ 0xcd18, 0x182f,
+ 0xcd19, 0xc013,
+ 0xcd1a, 0xf341,
+ 0xcd1b, 0xc01a,
+ 0xcd1c, 0x446,
+ 0xcd1d, 0xc024,
+ 0xcd1e, 0x1000,
+ 0xcd1f, 0xc025,
+ 0xcd20, 0xa00,
+ 0xcd21, 0xc026,
+ 0xcd22, 0xc0c,
+ 0xcd23, 0xc027,
+ 0xcd24, 0xc0c,
+ 0xcd25, 0xc029,
+ 0xcd26, 0x0a0,
+ 0xcd27, 0xc030,
+ 0xcd28, 0xa00,
+ 0xcd29, 0xc03c,
+ 0xcd2a, 0x01c,
+ 0xcd2b, 0x000,
+ 0xcd2c, 0x2b84,
+ 0xcd2d, 0x3c74,
+ 0xcd2e, 0x6435,
+ 0xcd2f, 0xdff4,
+ 0xcd30, 0x6435,
+ 0xcd31, 0x2806,
+ 0xcd32, 0x3006,
+ 0xcd33, 0x8565,
+ 0xcd34, 0x2b24,
+ 0xcd35, 0x3c24,
+ 0xcd36, 0x6436,
+ 0xcd37, 0x1002,
+ 0xcd38, 0x2b24,
+ 0xcd39, 0x3c24,
+ 0xcd3a, 0x6436,
+ 0xcd3b, 0x4045,
+ 0xcd3c, 0x8656,
+ 0xcd3d, 0x1002,
+ 0xcd3e, 0x2807,
+ 0xcd3f, 0x31a7,
+ 0xcd40, 0x20c4,
+ 0xcd41, 0x3c24,
+ 0xcd42, 0x6724,
+ 0xcd43, 0x1002,
+ 0xcd44, 0x2807,
+ 0xcd45, 0x3187,
+ 0xcd46, 0x20c4,
+ 0xcd47, 0x3c24,
+ 0xcd48, 0x6724,
+ 0xcd49, 0x1002,
+ 0xcd4a, 0x2514,
+ 0xcd4b, 0x3c64,
+ 0xcd4c, 0x6436,
+ 0xcd4d, 0xdff4,
+ 0xcd4e, 0x6436,
+ 0xcd4f, 0x1002,
+ 0xcd50, 0x2806,
+ 0xcd51, 0x3cb6,
+ 0xcd52, 0xc161,
+ 0xcd53, 0x6134,
+ 0xcd54, 0x6135,
+ 0xcd55, 0x5443,
+ 0xcd56, 0x303,
+ 0xcd57, 0x6524,
+ 0xcd58, 0x00b,
+ 0xcd59, 0x1002,
+ 0xcd5a, 0xd019,
+ 0xcd5b, 0x2104,
+ 0xcd5c, 0x3c24,
+ 0xcd5d, 0x2105,
+ 0xcd5e, 0x3805,
+ 0xcd5f, 0x6524,
+ 0xcd60, 0xdff4,
+ 0xcd61, 0x4005,
+ 0xcd62, 0x6524,
+ 0xcd63, 0x2e8d,
+ 0xcd64, 0x303d,
+ 0xcd65, 0x5dd3,
+ 0xcd66, 0x306,
+ 0xcd67, 0x2ff7,
+ 0xcd68, 0x38f7,
+ 0xcd69, 0x60b7,
+ 0xcd6a, 0xdffd,
+ 0xcd6b, 0x00a,
+ 0xcd6c, 0x1002,
+ 0xcd6d, 0
+ };
+
+// main SR EDC program
+const uint16_t sr_edc[] = {
+ 0xc003, 0x181,
+ 0xc010, 0x448a,
+ 0xc04a, 0x5200,
+ 0xcc00, 0x2ff4,
+ 0xcc01, 0x3cd4,
+ 0xcc02, 0x2015,
+ 0xcc03, 0x3105,
+ 0xcc04, 0x6524,
+ 0xcc05, 0x27ff,
+ 0xcc06, 0x300f,
+ 0xcc07, 0x2c8b,
+ 0xcc08, 0x300b,
+ 0xcc09, 0x4009,
+ 0xcc0a, 0x400e,
+ 0xcc0b, 0x2f72,
+ 0xcc0c, 0x3002,
+ 0xcc0d, 0x1002,
+ 0xcc0e, 0x2172,
+ 0xcc0f, 0x3012,
+ 0xcc10, 0x1002,
+ 0xcc11, 0x25d2,
+ 0xcc12, 0x3012,
+ 0xcc13, 0x1002,
+ 0xcc14, 0xd01e,
+ 0xcc15, 0x27d2,
+ 0xcc16, 0x3012,
+ 0xcc17, 0x1002,
+ 0xcc18, 0x2004,
+ 0xcc19, 0x3c84,
+ 0xcc1a, 0x6436,
+ 0xcc1b, 0x2007,
+ 0xcc1c, 0x3f87,
+ 0xcc1d, 0x8676,
+ 0xcc1e, 0x40b7,
+ 0xcc1f, 0xa746,
+ 0xcc20, 0x4047,
+ 0xcc21, 0x5673,
+ 0xcc22, 0x2982,
+ 0xcc23, 0x3002,
+ 0xcc24, 0x13d2,
+ 0xcc25, 0x8bbd,
+ 0xcc26, 0x2862,
+ 0xcc27, 0x3012,
+ 0xcc28, 0x1002,
+ 0xcc29, 0x2092,
+ 0xcc2a, 0x3012,
+ 0xcc2b, 0x1002,
+ 0xcc2c, 0x5cc3,
+ 0xcc2d, 0x314,
+ 0xcc2e, 0x2942,
+ 0xcc2f, 0x3002,
+ 0xcc30, 0x1002,
+ 0xcc31, 0xd019,
+ 0xcc32, 0x2032,
+ 0xcc33, 0x3012,
+ 0xcc34, 0x1002,
+ 0xcc35, 0x2a04,
+ 0xcc36, 0x3c74,
+ 0xcc37, 0x6435,
+ 0xcc38, 0x2fa4,
+ 0xcc39, 0x3cd4,
+ 0xcc3a, 0x6624,
+ 0xcc3b, 0x5563,
+ 0xcc3c, 0x2d42,
+ 0xcc3d, 0x3002,
+ 0xcc3e, 0x13d2,
+ 0xcc3f, 0x464d,
+ 0xcc40, 0x2862,
+ 0xcc41, 0x3012,
+ 0xcc42, 0x1002,
+ 0xcc43, 0x2032,
+ 0xcc44, 0x3012,
+ 0xcc45, 0x1002,
+ 0xcc46, 0x2fb4,
+ 0xcc47, 0x3cd4,
+ 0xcc48, 0x6624,
+ 0xcc49, 0x5563,
+ 0xcc4a, 0x2d42,
+ 0xcc4b, 0x3002,
+ 0xcc4c, 0x13d2,
+ 0xcc4d, 0x2ed2,
+ 0xcc4e, 0x3002,
+ 0xcc4f, 0x1002,
+ 0xcc50, 0x2fd2,
+ 0xcc51, 0x3002,
+ 0xcc52, 0x1002,
+ 0xcc53, 0x004,
+ 0xcc54, 0x2942,
+ 0xcc55, 0x3002,
+ 0xcc56, 0x1002,
+ 0xcc57, 0x2092,
+ 0xcc58, 0x3012,
+ 0xcc59, 0x1002,
+ 0xcc5a, 0x5cc3,
+ 0xcc5b, 0x317,
+ 0xcc5c, 0x2f72,
+ 0xcc5d, 0x3002,
+ 0xcc5e, 0x1002,
+ 0xcc5f, 0x2942,
+ 0xcc60, 0x3002,
+ 0xcc61, 0x1002,
+ 0xcc62, 0x22cd,
+ 0xcc63, 0x301d,
+ 0xcc64, 0x2862,
+ 0xcc65, 0x3012,
+ 0xcc66, 0x1002,
+ 0xcc67, 0x2ed2,
+ 0xcc68, 0x3002,
+ 0xcc69, 0x1002,
+ 0xcc6a, 0x2d72,
+ 0xcc6b, 0x3002,
+ 0xcc6c, 0x1002,
+ 0xcc6d, 0x628f,
+ 0xcc6e, 0x2112,
+ 0xcc6f, 0x3012,
+ 0xcc70, 0x1002,
+ 0xcc71, 0x5aa3,
+ 0xcc72, 0x2dc2,
+ 0xcc73, 0x3002,
+ 0xcc74, 0x1312,
+ 0xcc75, 0x6f72,
+ 0xcc76, 0x1002,
+ 0xcc77, 0x2807,
+ 0xcc78, 0x31a7,
+ 0xcc79, 0x20c4,
+ 0xcc7a, 0x3c24,
+ 0xcc7b, 0x6724,
+ 0xcc7c, 0x1002,
+ 0xcc7d, 0x2807,
+ 0xcc7e, 0x3187,
+ 0xcc7f, 0x20c4,
+ 0xcc80, 0x3c24,
+ 0xcc81, 0x6724,
+ 0xcc82, 0x1002,
+ 0xcc83, 0x2514,
+ 0xcc84, 0x3c64,
+ 0xcc85, 0x6436,
+ 0xcc86, 0xdff4,
+ 0xcc87, 0x6436,
+ 0xcc88, 0x1002,
+ 0xcc89, 0x40a4,
+ 0xcc8a, 0x643c,
+ 0xcc8b, 0x4016,
+ 0xcc8c, 0x8c6c,
+ 0xcc8d, 0x2b24,
+ 0xcc8e, 0x3c24,
+ 0xcc8f, 0x6435,
+ 0xcc90, 0x1002,
+ 0xcc91, 0x2b24,
+ 0xcc92, 0x3c24,
+ 0xcc93, 0x643a,
+ 0xcc94, 0x4025,
+ 0xcc95, 0x8a5a,
+ 0xcc96, 0x1002,
+ 0xcc97, 0x2731,
+ 0xcc98, 0x3011,
+ 0xcc99, 0x1001,
+ 0xcc9a, 0xc7a0,
+ 0xcc9b, 0x100,
+ 0xcc9c, 0xc502,
+ 0xcc9d, 0x53ac,
+ 0xcc9e, 0xc503,
+ 0xcc9f, 0xd5d5,
+ 0xcca0, 0xc600,
+ 0xcca1, 0x2a6d,
+ 0xcca2, 0xc601,
+ 0xcca3, 0x2a4c,
+ 0xcca4, 0xc602,
+ 0xcca5, 0x111,
+ 0xcca6, 0xc60c,
+ 0xcca7, 0x5900,
+ 0xcca8, 0xc710,
+ 0xcca9, 0x700,
+ 0xccaa, 0xc718,
+ 0xccab, 0x700,
+ 0xccac, 0xc720,
+ 0xccad, 0x4700,
+ 0xccae, 0xc801,
+ 0xccaf, 0x7f50,
+ 0xccb0, 0xc802,
+ 0xccb1, 0x7760,
+ 0xccb2, 0xc803,
+ 0xccb3, 0x7fce,
+ 0xccb4, 0xc804,
+ 0xccb5, 0x5700,
+ 0xccb6, 0xc805,
+ 0xccb7, 0x5f11,
+ 0xccb8, 0xc806,
+ 0xccb9, 0x4751,
+ 0xccba, 0xc807,
+ 0xccbb, 0x57e1,
+ 0xccbc, 0xc808,
+ 0xccbd, 0x2700,
+ 0xccbe, 0xc809,
+ 0xccbf, 0x000,
+ 0xccc0, 0xc821,
+ 0xccc1, 0x002,
+ 0xccc2, 0xc822,
+ 0xccc3, 0x014,
+ 0xccc4, 0xc832,
+ 0xccc5, 0x1186,
+ 0xccc6, 0xc847,
+ 0xccc7, 0x1e02,
+ 0xccc8, 0xc013,
+ 0xccc9, 0xf341,
+ 0xccca, 0xc01a,
+ 0xcccb, 0x446,
+ 0xcccc, 0xc024,
+ 0xcccd, 0x1000,
+ 0xccce, 0xc025,
+ 0xcccf, 0xa00,
+ 0xccd0, 0xc026,
+ 0xccd1, 0xc0c,
+ 0xccd2, 0xc027,
+ 0xccd3, 0xc0c,
+ 0xccd4, 0xc029,
+ 0xccd5, 0x0a0,
+ 0xccd6, 0xc030,
+ 0xccd7, 0xa00,
+ 0xccd8, 0xc03c,
+ 0xccd9, 0x01c,
+ 0xccda, 0xc005,
+ 0xccdb, 0x7a06,
+ 0xccdc, 0x000,
+ 0xccdd, 0x2731,
+ 0xccde, 0x3011,
+ 0xccdf, 0x1001,
+ 0xcce0, 0xc620,
+ 0xcce1, 0x000,
+ 0xcce2, 0xc621,
+ 0xcce3, 0x03f,
+ 0xcce4, 0xc622,
+ 0xcce5, 0x000,
+ 0xcce6, 0xc623,
+ 0xcce7, 0x000,
+ 0xcce8, 0xc624,
+ 0xcce9, 0x000,
+ 0xccea, 0xc625,
+ 0xcceb, 0x000,
+ 0xccec, 0xc627,
+ 0xcced, 0x000,
+ 0xccee, 0xc628,
+ 0xccef, 0x000,
+ 0xccf0, 0xc62c,
+ 0xccf1, 0x000,
+ 0xccf2, 0x000,
+ 0xccf3, 0x2806,
+ 0xccf4, 0x3cb6,
+ 0xccf5, 0xc161,
+ 0xccf6, 0x6134,
+ 0xccf7, 0x6135,
+ 0xccf8, 0x5443,
+ 0xccf9, 0x303,
+ 0xccfa, 0x6524,
+ 0xccfb, 0x00b,
+ 0xccfc, 0x1002,
+ 0xccfd, 0x2104,
+ 0xccfe, 0x3c24,
+ 0xccff, 0x2105,
+ 0xcd00, 0x3805,
+ 0xcd01, 0x6524,
+ 0xcd02, 0xdff4,
+ 0xcd03, 0x4005,
+ 0xcd04, 0x6524,
+ 0xcd05, 0x1002,
+ 0xcd06, 0x5dd3,
+ 0xcd07, 0x306,
+ 0xcd08, 0x2ff7,
+ 0xcd09, 0x38f7,
+ 0xcd0a, 0x60b7,
+ 0xcd0b, 0xdffd,
+ 0xcd0c, 0x00a,
+ 0xcd0d, 0x1002,
+ 0xcd0e, 0
+ };
+
+#endif
diff --git a/linux/raptor.c b/linux/raptor.c
new file mode 100644
index 0000000..cb28c44
--- /dev/null
+++ b/linux/raptor.c
@@ -0,0 +1,940 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2017
+ *
+ * Raptor device driver
+ *
+ * Alexander D'hoore <[email protected]>
+ * Dimitri Staessens <[email protected]>
+ * Sander Vrijders <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/string.h>
+#include <linux/cdev.h>
+#include <linux/kthread.h>
+#include <linux/uaccess.h>
+
+#include "phy_conf.h"
+
+MODULE_LICENSE("GPL");
+
+#define RAPTOR_VENDOR_ID 0x10EE
+#define RAPTOR_DEVICE_ID 0xAD02
+#define RAPTOR_BAR 0
+
+#define BAR_MDIO 30
+
+#define CMD_STATUS 0
+#define CMD_SEND 1
+#define CMD_RECV 2
+#define CMD_MDIO 3
+
+#define IOCTL_SEND 0xAD420000
+#define IOCTL_RECV 0xAD430000
+#define IOCTL_SEND_DONE 0xAD440000
+#define IOCTL_RECV_DONE 0xAD450000
+#define IOCTL_RECV_NEED 0xAD460000
+#define IOCTL_DEBUG 0xAD470000
+
+#define BUFF_COUNT 16
+
+#define BUFF_EMPTY 0
+#define BUFF_ADDR 1
+#define BUFF_DATA 2
+#define BUFF_FULL 3
+
+#define PACKET_COUNT 1000
+
+struct packet;
+
+struct packet {
+ uint64_t u_addr;
+ uint16_t length;
+ struct page* page;
+ dma_addr_t dma_addr;
+ struct packet* next;
+};
+
+struct queue {
+ struct packet* first;
+ struct packet* last;
+ uint64_t count;
+};
+
+struct raptor {
+ dev_t base;
+ struct class * class;
+
+ dev_t dev;
+ struct device * device;
+ struct cdev cdev;
+
+ uint64_t *bar;
+ struct pci_dev *pdev;
+
+ bool interrupt;
+
+ struct queue send_queue;
+ struct queue recv_queue;
+ struct queue send_done_queue;
+ struct queue recv_done_queue;
+ struct queue send_free_queue;
+ struct queue recv_free_queue;
+
+ struct packet* send_packets;
+ struct packet* recv_packets;
+
+ uint64_t recv_need;
+
+ spinlock_t lock;
+ wait_queue_head_t wait;
+
+ struct task_struct* kthread;
+
+ uint64_t int_count;
+ uint64_t send_busy;
+ uint64_t recv_busy;
+};
+
+struct raptor raptor;
+
+// -------------------------------------------
+
+static void queue_push(struct queue* queue, struct packet* packet)
+{
+ spin_lock_irq(&raptor.lock);
+
+ if (queue->count == 0) {
+ queue->first = packet;
+ queue->last = packet;
+ }
+ else {
+ queue->last->next = packet;
+ queue->last = packet;
+ }
+ queue->count++;
+
+ spin_unlock_irq(&raptor.lock);
+ wake_up(&raptor.wait);
+}
+
+static struct packet* queue_pop(struct queue* queue, bool block)
+{
+ struct packet* packet;
+
+ spin_lock_irq(&raptor.lock);
+
+ if (block) {
+ if (wait_event_interruptible_lock_irq_timeout(
+ raptor.wait, queue->count > 0, raptor.lock, HZ) <= 0) {
+
+ spin_unlock_irq(&raptor.lock);
+ return NULL;
+ }
+ }
+ else {
+ if (queue->count == 0) {
+ spin_unlock_irq(&raptor.lock);
+ return NULL;
+ }
+ }
+
+ packet = queue->first;
+ queue->first = packet->next;
+ queue->count--;
+
+ spin_unlock_irq(&raptor.lock);
+ wake_up(&raptor.wait);
+ return packet;
+}
+
+// -------------------------------------------
+
+uint64_t raptor_read(uint64_t offset)
+{
+ return raptor.bar[offset];
+}
+
+void raptor_write(uint64_t offset, uint64_t data)
+{
+ raptor.bar[offset] = data;
+}
+
+uint64_t endian64(uint64_t data)
+{
+ uint64_t byte0 = (data & 0x00000000000000FF) << 7*8;
+ uint64_t byte1 = (data & 0x000000000000FF00) << 5*8;
+ uint64_t byte2 = (data & 0x0000000000FF0000) << 3*8;
+ uint64_t byte3 = (data & 0x00000000FF000000) << 1*8;
+ uint64_t byte4 = (data & 0x000000FF00000000) >> 1*8;
+ uint64_t byte5 = (data & 0x0000FF0000000000) >> 3*8;
+ uint64_t byte6 = (data & 0x00FF000000000000) >> 5*8;
+ uint64_t byte7 = (data & 0xFF00000000000000) >> 7*8;
+
+ return byte0 | byte1 | byte2 | byte3 | byte4 | byte5 | byte6 | byte7;
+}
+
+static irqreturn_t raptor_interrupt(int irq, void *dev_id)
+{
+ spin_lock(&raptor.lock);
+ raptor.interrupt = true;
+ spin_unlock(&raptor.lock);
+ wake_up(&raptor.wait);
+
+ return IRQ_HANDLED;
+}
+
+void mdio_raw(unsigned operation, unsigned phy_addr, unsigned dev_addr, unsigned data)
+{
+ unsigned command = (operation << 26) | (phy_addr << 21) | (dev_addr << 16) | (data & 0xFFFF);
+
+ raptor_write(CMD_MDIO, endian64((uint64_t)command));
+ msleep(1);
+}
+
+void mdio_write(unsigned phy_addr, unsigned dev_addr, unsigned data_addr, unsigned data)
+{
+ mdio_raw(0, phy_addr, dev_addr, data_addr);
+ mdio_raw(1, phy_addr, dev_addr, data);
+}
+
+unsigned mdio_read(unsigned phy_addr, unsigned dev_addr, unsigned data_addr)
+{
+ mdio_raw(0, phy_addr, dev_addr, data_addr);
+ mdio_raw(3, phy_addr, dev_addr, 0);
+
+ return (unsigned)endian64(raptor_read(BAR_MDIO));
+}
+
+int mdio_i2c_read(uint32_t phy_addr, uint16_t dev_addr, uint16_t word_addr, uint16_t * data)
+{
+ uint16_t stat;
+ int i;
+
+ mdio_write(phy_addr, 1, AEL_I2C_CTRL, (dev_addr << 8) | (1 << 8) | word_addr);
+
+ for (i = 0; i < 20; i++) {
+ msleep(2);
+ stat = mdio_read(phy_addr, 1, AEL_I2C_STAT);
+
+ if ((stat & 3) == 1){
+ stat = mdio_read(phy_addr, 1, AEL_I2C_DATA);
+
+ *data = stat >> 8;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void mdio_initialize(uint32_t phy_addr, int mode)
+{
+ int size, i;
+
+ // Step 1
+ size = sizeof(reset) / sizeof(uint16_t);
+
+ for(i = 0; i < size; i += 2) {
+ mdio_write(phy_addr, PMA_MDIO_DEVICE_ADDRESS, reset[i], reset[i+1]);
+ }
+
+ msleep(5);
+
+ // Step 2
+ if (mode == MODE_SR) {
+ size = sizeof(sr_edc) / sizeof(uint16_t);
+
+ for(i = 0; i < size; i += 2) {
+ mdio_write(phy_addr, PMA_MDIO_DEVICE_ADDRESS, sr_edc[i], sr_edc[i+1]);
+ }
+ }
+ else if (mode == MODE_TWINAX) {
+ size = sizeof(twinax_edc) / sizeof(uint16_t);
+
+ for(i = 0; i < size; i += 2) {
+ mdio_write(phy_addr, PMA_MDIO_DEVICE_ADDRESS, twinax_edc[i], twinax_edc[i+1]);
+ }
+ }
+
+ // Step 3
+ size = sizeof(regs1) / sizeof(uint16_t);
+ for(i = 0; i < size; i+=2) {
+ mdio_write(phy_addr, PMA_MDIO_DEVICE_ADDRESS, regs1[i], regs1[i+1]);
+ }
+
+ msleep(5);
+}
+
+int phy_configuration(void)
+{
+ int port, dev;
+ uint16_t value = 0;
+ char port_mode;
+
+ // check if we need initialization
+ value = mdio_read(2, PMA_MDIO_DEVICE_ADDRESS, AEL_MICRO_CONTROLLER_CTL_ADDRESS);
+
+ //printk(KERN_INFO "raptor: 0xc04a: %04x\n",value);
+ if (value & 0x8000) { // uC held in reset
+ printk(KERN_INFO "raptor: Programming the AEL2005 PHY chips...\n");
+
+ for (port = 0; port < 4; port++) {
+ if (port == 0) dev = 2;
+ else if (port == 1) dev = 1;
+ else if (port == 2) dev = 0;
+ else dev = 3;
+
+ value = 0;
+
+ // check if we have a 10GBASE-SR cable
+ mdio_i2c_read(dev, MODULE_DEV_ADDR, 0x3, &value);
+
+ if((value >> 4) == 1) {
+ port_mode = MODE_SR;
+ }
+ else {
+ port_mode = MODE_TWINAX;
+ }
+
+ printk(KERN_INFO "raptor: Programming PHY %d...\n", port);
+
+ mdio_initialize(dev, port_mode);
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+static void read_debug(void)
+{
+ uint64_t status;
+ uint64_t address;
+ uint64_t data;
+ uint64_t cmd;
+ uint64_t buff;
+ uint64_t length;
+ uint64_t cmpl_count;
+ uint64_t cmpl_data;
+ uint64_t cmpl_tag;
+ uint64_t cmpl_state;
+ uint64_t write_count;
+ uint64_t write_length;
+ uint64_t write_addr;
+ uint64_t write_data;
+ uint64_t accept_count;
+ uint64_t done_count;
+
+ status = endian64(raptor_read(0));
+ address = endian64(raptor_read(1));
+ data = endian64(raptor_read(2));
+ cmd = endian64(raptor_read(3));
+ buff = endian64(raptor_read(4));
+ length = endian64(raptor_read(5));
+ cmpl_count = endian64(raptor_read(10));
+ cmpl_data = endian64(raptor_read(11));
+ cmpl_tag = endian64(raptor_read(12));
+ cmpl_state = endian64(raptor_read(13));
+
+ write_count = endian64(raptor_read(20));
+ write_length = endian64(raptor_read(21));
+ write_addr = endian64(raptor_read(22));
+ write_data = endian64(raptor_read(23));
+ accept_count = endian64(raptor_read(24));
+ done_count = endian64(raptor_read(25));
+
+ printk(KERN_INFO "raptor: read_debug:\n");
+ printk(KERN_INFO "raptor: status = 0x%llx.\n", status);
+ printk(KERN_INFO "raptor: address = 0x%llx.\n", address);
+ printk(KERN_INFO "raptor: data = 0x%llx.\n", data);
+ printk(KERN_INFO "raptor: cmd = 0x%llx.\n", cmd);
+ printk(KERN_INFO "raptor: buff = 0x%llx.\n", buff);
+ printk(KERN_INFO "raptor: length = %llu.\n", length);
+ printk(KERN_INFO "raptor: cmpl_count = %llu.\n", cmpl_count);
+ printk(KERN_INFO "raptor: cmpl_data = 0x%llx.\n", cmpl_data);
+ printk(KERN_INFO "raptor: cmpl_tag = 0x%llx.\n", cmpl_tag);
+ printk(KERN_INFO "raptor: cmpl_state = 0x%llx.\n", cmpl_state);
+ printk(KERN_INFO "raptor: write_count = %llu.\n", write_count);
+ printk(KERN_INFO "raptor: write_length = %llu.\n", write_length);
+ printk(KERN_INFO "raptor: write_addr = 0x%llx.\n", write_addr);
+ printk(KERN_INFO "raptor: write_data = 0x%llx.\n", write_data);
+ printk(KERN_INFO "raptor: accept_count = %llu.\n", accept_count);
+ printk(KERN_INFO "raptor: done_count = %llu.\n", done_count);
+}
+
+#define get_send(status, i) ((status >> (i * 4 + 0)) & 0x3)
+#define get_recv(status, i) ((status >> (i * 4 + 2)) & 0x3)
+
+struct packet* send_packets[BUFF_COUNT];
+struct packet* recv_packets[BUFF_COUNT];
+uint8_t send_buff[BUFF_COUNT];
+uint8_t recv_buff[BUFF_COUNT];
+
+static int raptor_kthread(void* data)
+{
+ bool interrupt;
+ uint64_t status = 0;
+ uint8_t send_new;
+ uint8_t recv_new;
+ uint8_t send_old;
+ uint8_t recv_old;
+ uint64_t i;
+ bool send_full = false;
+ bool recv_full = false;
+ struct packet* packet;
+ struct device* dev = &raptor.pdev->dev;
+ uint64_t offset;
+ uint64_t rest;
+
+ printk(KERN_INFO "raptor_kthread: started\n");
+
+ memset(send_packets, 0, sizeof(send_packets));
+ memset(recv_packets, 0, sizeof(recv_packets));
+
+ raptor.interrupt = true;
+
+ while (true) {
+ spin_lock_irq(&raptor.lock);
+
+ if (wait_event_interruptible_lock_irq(
+ raptor.wait,
+ kthread_should_stop() ||
+ raptor.interrupt ||
+ (! send_full && raptor.send_queue.count > 0) ||
+ (! recv_full && raptor.recv_queue.count > 0),
+ raptor.lock) != 0) {
+
+ printk(KERN_ERR "raptor_kthread: wait_event failed\n");
+ spin_unlock_irq(&raptor.lock);
+ break;
+ }
+
+ interrupt = raptor.interrupt;
+ raptor.interrupt = false;
+ spin_unlock_irq(&raptor.lock);
+
+ if (kthread_should_stop())
+ break;
+
+ if (interrupt) {
+ // read status
+ // update done_queues
+ // incr recv_need
+ status = endian64(raptor_read(0));
+
+ raptor.int_count++;
+
+ for (i = 0; i < BUFF_COUNT; i++) {
+ send_new = get_send(status, i);
+ recv_new = get_recv(status, i);
+ send_old = send_buff[i];
+ recv_old = recv_buff[i];
+
+ if (send_new != BUFF_EMPTY)
+ raptor.send_busy++;
+ if (recv_new != BUFF_EMPTY)
+ raptor.recv_busy++;
+
+ if ((send_old == BUFF_ADDR || send_old == BUFF_DATA) &&
+ (send_new == BUFF_FULL || send_new == BUFF_EMPTY) &&
+ send_packets[i] != NULL) {
+
+ packet = send_packets[i];
+ offset = packet->u_addr & (~PAGE_MASK);
+ rest = PAGE_SIZE - offset;
+
+ dma_unmap_page(dev, packet->dma_addr, rest, DMA_TO_DEVICE);
+ queue_push(&raptor.send_done_queue, packet);
+ send_packets[i] = NULL;
+ }
+ if ((recv_old == BUFF_ADDR || recv_old == BUFF_DATA) &&
+ (recv_new == BUFF_FULL || recv_new == BUFF_EMPTY) &&
+ recv_packets[i] != NULL) {
+
+ packet = recv_packets[i];
+ offset = packet->u_addr & (~PAGE_MASK);
+ rest = PAGE_SIZE - offset;
+
+ dma_unmap_page(dev, packet->dma_addr, rest, DMA_FROM_DEVICE);
+ queue_push(&raptor.recv_done_queue, packet);
+ recv_packets[i] = NULL;
+ }
+ if (recv_old != BUFF_FULL && recv_new == BUFF_FULL) {
+ spin_lock_irq(&raptor.lock);
+ raptor.recv_need++;
+ spin_unlock_irq(&raptor.lock);
+ wake_up(&raptor.wait);
+ }
+
+ send_buff[i] = send_new;
+ recv_buff[i] = recv_new;
+ }
+ }
+
+ // handle send_queue
+ send_full = true;
+
+ for (i = 0; i < BUFF_COUNT; i++) {
+ if (send_buff[i] == BUFF_EMPTY && send_packets[i] == NULL) {
+
+ packet = queue_pop(&raptor.send_queue, false);
+
+ if (packet == NULL) {
+ send_full = false;
+ break;
+ }
+
+ // map page to dma_addr
+ // write that to hardware
+
+ offset = packet->u_addr & (~PAGE_MASK);
+ rest = PAGE_SIZE - offset;
+
+ packet->dma_addr = dma_map_page(dev, packet->page, offset, rest, DMA_TO_DEVICE);
+
+ raptor_write(CMD_SEND | (i << 2) | (packet->length << 7), endian64(packet->dma_addr));
+
+ send_buff[i] = BUFF_ADDR;
+ send_packets[i] = packet;
+ }
+ }
+
+ // handle recv_queue
+ recv_full = true;
+
+ for (i = 0; i < BUFF_COUNT; i++) {
+ if (recv_buff[i] == BUFF_FULL && recv_packets[i] == NULL) {
+
+ packet = queue_pop(&raptor.recv_queue, false);
+
+ if (packet == NULL) {
+ recv_full = false;
+ break;
+ }
+
+ // map page to dma_addr
+ // write that to hardware
+
+ offset = packet->u_addr & (~PAGE_MASK);
+ rest = PAGE_SIZE - offset;
+
+ packet->dma_addr = dma_map_page(dev, packet->page, offset, rest, DMA_FROM_DEVICE);
+
+ raptor_write(CMD_RECV | (i << 2), endian64(packet->dma_addr));
+
+ recv_buff[i] = BUFF_ADDR;
+ recv_packets[i] = packet;
+ }
+ }
+ }
+
+ printk(KERN_INFO "raptor_kthread: stopped\n");
+ return 0;
+}
+
+static int pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ if (pci_enable_device(pdev) != 0)
+ goto error_no_cleanup;
+
+ if (pci_request_region(pdev, RAPTOR_BAR, "raptor") != 0)
+ goto error_disable_device;
+
+ if ((raptor.bar = pci_ioremap_bar(pdev, RAPTOR_BAR)) == NULL)
+ goto error_release_region;
+
+ if (pci_enable_msi(pdev) < 0)
+ goto error_iounmap;
+
+ if (request_irq(pdev->irq, raptor_interrupt, 0, "raptor", NULL) < 0)
+ goto error_disable_msi;
+
+ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) < 0)
+ goto error_free_irq;
+
+ if (dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)) < 0)
+ goto error_free_irq;
+
+ pci_set_master(pdev);
+ raptor.pdev = pdev;
+
+ phy_configuration();
+
+ read_debug();
+
+ raptor.kthread = kthread_run(raptor_kthread, NULL, "raptor_kthread");
+
+ if (IS_ERR(raptor.kthread))
+ goto error_clear_master;
+
+ printk(KERN_INFO "raptor: pci_probe succes\n");
+
+ return 0;
+
+error_clear_master:
+ pci_clear_master(pdev);
+error_free_irq:
+ free_irq(pdev->irq, NULL);
+error_disable_msi:
+ pci_disable_msi(pdev);
+error_iounmap:
+ iounmap(raptor.bar);
+error_release_region:
+ pci_release_region(pdev, 0);
+error_disable_device:
+ pci_disable_device(pdev);
+error_no_cleanup:
+ raptor.bar = NULL;
+ raptor.pdev = NULL;
+ printk(KERN_ALERT "raptor: pci_probe FAILED\n");
+ return -1;
+}
+
+static void pci_remove(struct pci_dev *pdev)
+{
+ printk(KERN_INFO "raptor: pci_remove started...\n");
+
+ (void)kthread_stop(raptor.kthread);
+
+ pci_clear_master(pdev);
+ free_irq(pdev->irq, NULL);
+ pci_disable_msi(pdev);
+ iounmap(raptor.bar);
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ raptor.bar = NULL;
+ raptor.pdev = NULL;
+
+ printk(KERN_INFO "raptor: pci_remove done\n");
+}
+
+static pci_ers_result_t pci_error_detected(struct pci_dev *pdev, enum pci_channel_state state)
+{
+ printk(KERN_ALERT "raptor: pcie error %d\n", state);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static int raptor_send(uint64_t count, uint64_t* u_addrs)
+{
+ uint64_t i;
+ uint64_t u_addr;
+ uint16_t bytes;
+ uint16_t length;
+ struct page* page;
+ struct packet* packet;
+
+ for (i = 0; i < count; i++) {
+ if (copy_from_user(&u_addr, &u_addrs[i], sizeof(u_addr)) != 0) {
+ printk(KERN_ERR "raptor_send: copy_from_user u_addr failed\n");
+ return i;
+ }
+
+ if (copy_from_user(&bytes, (void*)u_addr, sizeof(bytes)) != 0) {
+ printk(KERN_ERR "raptor_send: copy_from_user bytes failed\n");
+ return i;
+ }
+
+ if (get_user_pages_fast(u_addr, 1, false, &page) != 1) {
+ printk(KERN_ERR "raptor_send: get_user_pages_fast failed\n");
+ return i;
+ }
+
+ packet = queue_pop(&raptor.send_free_queue, true);
+
+ if (packet == NULL) {
+ printk(KERN_ERR "raptor_send: queue_pop send_free_queue failed\n");
+ put_page(page);
+ return i;
+ }
+
+ length = (bytes >> 3);
+
+ if (bytes & 0x7)
+ length += 1;
+
+ packet->u_addr = u_addr;
+ packet->length = length;
+ packet->page = page;
+
+ queue_push(&raptor.send_queue, packet);
+ }
+ return count;
+}
+
+static int raptor_recv(uint64_t count, uint64_t* u_addrs)
+{
+ uint64_t i;
+ uint64_t u_addr;
+ struct page* page;
+ struct packet* packet;
+
+ for (i = 0; i < count; i++) {
+ if (copy_from_user(&u_addr, &u_addrs[i], sizeof(u_addr)) != 0) {
+ printk(KERN_ERR "raptor_recv: copy_from_user u_addr failed\n");
+ return i;
+ }
+
+ if (get_user_pages_fast(u_addr, 1, true, &page) != 1) {
+ printk(KERN_ERR "raptor_recv: get_user_pages_fast failed\n");
+ return i;
+ }
+
+ packet = queue_pop(&raptor.recv_free_queue, true);
+
+ if (packet == NULL) {
+ printk(KERN_ERR "raptor_recv: queue_pop recv_free_queue failed\n");
+ put_page(page);
+ return i;
+ }
+
+ packet->u_addr = u_addr;
+ packet->page = page;
+
+ queue_push(&raptor.recv_queue, packet);
+ }
+ return count;
+}
+
+static int raptor_send_done(uint64_t count, uint64_t* u_addrs)
+{
+ uint64_t i;
+ struct packet* packet;
+
+ for (i = 0; i < count; i++) {
+ packet = queue_pop(&raptor.send_done_queue, i == 0);
+
+ if (packet == NULL)
+ return i;
+
+ put_page(packet->page);
+
+ if (copy_to_user(&u_addrs[i], &packet->u_addr, sizeof(packet->u_addr)) != 0) {
+ printk(KERN_ERR "raptor_send_done: copy_to_user u_addr failed\n");
+ return i;
+ }
+
+ queue_push(&raptor.send_free_queue, packet);
+ }
+ return count;
+}
+
+static int raptor_recv_done(uint64_t count, uint64_t* u_addrs)
+{
+ uint64_t i;
+ struct packet* packet;
+
+ for (i = 0; i < count; i++) {
+ packet = queue_pop(&raptor.recv_done_queue, i == 0);
+
+ if (packet == NULL)
+ return i;
+
+ put_page(packet->page);
+
+ if (copy_to_user(&u_addrs[i], &packet->u_addr, sizeof(packet->u_addr)) != 0) {
+ printk(KERN_ERR "raptor_recv_done: copy_to_user u_addr failed\n");
+ return i;
+ }
+
+ queue_push(&raptor.recv_free_queue, packet);
+ }
+ return count;
+}
+
+static int raptor_recv_need(uint64_t count)
+{
+ uint64_t ret;
+
+ spin_lock_irq(&raptor.lock);
+
+ if (wait_event_interruptible_lock_irq_timeout(
+ raptor.wait, raptor.recv_need > 0, raptor.lock, HZ) <= 0) {
+
+ spin_unlock_irq(&raptor.lock);
+ return -1;
+ }
+
+ if (raptor.recv_need > count) {
+ ret = count;
+ raptor.recv_need -= count;
+ }
+ else {
+ ret = raptor.recv_need;
+ raptor.recv_need = 0;
+ }
+
+ spin_unlock_irq(&raptor.lock);
+ return ret;
+}
+
+static int raptor_debug(uint64_t* u_array)
+{
+ if (copy_to_user(&u_array[0], &raptor.int_count, sizeof(uint64_t)) ||
+ copy_to_user(&u_array[1], &raptor.send_busy, sizeof(uint64_t)) ||
+ copy_to_user(&u_array[2], &raptor.recv_busy, sizeof(uint64_t))) {
+
+ printk(KERN_ERR "raptor_debug: copy_to_user failed\n");
+ return -1;
+ }
+
+ raptor.int_count = 0;
+ raptor.send_busy = 0;
+ raptor.recv_busy = 0;
+
+ return 0;
+}
+
+
+static long raptor_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
+{
+ uint64_t type = cmd & 0xFFFF0000;
+ uint64_t count = cmd & 0x0000FFFF;
+
+ if (raptor.bar == NULL) {
+ printk(KERN_ERR "raptor: no pcie device\n");
+ return -1;
+ }
+
+ switch (type) {
+ case IOCTL_SEND:
+ return raptor_send(count, (uint64_t*)arg);
+ case IOCTL_RECV:
+ return raptor_recv(count, (uint64_t*)arg);
+ case IOCTL_SEND_DONE:
+ return raptor_send_done(count, (uint64_t*)arg);
+ case IOCTL_RECV_DONE:
+ return raptor_recv_done(count, (uint64_t*)arg);
+ case IOCTL_RECV_NEED:
+ return raptor_recv_need(count);
+ case IOCTL_DEBUG:
+ return raptor_debug((uint64_t*)arg);
+ default:
+ printk(KERN_ERR "raptor: unknown ioctl\n");
+ return -1;
+ }
+}
+
+static struct pci_device_id pci_id_table[] = {
+ {PCI_DEVICE(RAPTOR_VENDOR_ID, RAPTOR_DEVICE_ID)},
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, pci_id_table);
+
+static struct pci_error_handlers pci_err_handlers = {
+ .error_detected = pci_error_detected
+};
+
+static struct pci_driver pci_driver = {
+ .name = "raptor",
+ .id_table = pci_id_table,
+ .probe = pci_probe,
+ .remove = pci_remove,
+ .err_handler = &pci_err_handlers
+};
+
+static struct file_operations raptor_fops = {
+ .unlocked_ioctl = raptor_ioctl,
+};
+
+int init_module(void)
+{
+ int i;
+
+ printk(KERN_INFO "raptor: inserting module...\n");
+
+ memset(&raptor, 0, sizeof(raptor));
+
+ spin_lock_init(&raptor.lock);
+ init_waitqueue_head(&raptor.wait);
+
+ raptor.send_packets = kmalloc(PACKET_COUNT * sizeof(struct packet), GFP_KERNEL);
+ raptor.recv_packets = kmalloc(PACKET_COUNT * sizeof(struct packet), GFP_KERNEL);
+
+ if (raptor.send_packets == NULL || raptor.recv_packets == NULL) {
+ printk(KERN_ERR "raptor: failed to allocate packets\n");
+ return -1;
+ }
+
+ for (i = 0; i < PACKET_COUNT; i++) {
+ queue_push(&raptor.send_free_queue, &raptor.send_packets[i]);
+ queue_push(&raptor.recv_free_queue, &raptor.recv_packets[i]);
+ }
+
+ if (alloc_chrdev_region(&raptor.base, 0, 1, "raptor") < 0) {
+ printk(KERN_ERR "raptor: alloc_chrdev_region failed\n");
+ return -1;
+ }
+
+ raptor.class = class_create(THIS_MODULE, "raptor");
+
+ if (IS_ERR(raptor.class)) {
+ printk(KERN_ERR "raptor: class_create failed\n");
+ return -1;
+ }
+
+ raptor.dev = MKDEV(MAJOR(raptor.base), 0);
+
+ raptor.device = device_create(raptor.class, NULL, raptor.dev, NULL, "raptor");
+
+ if (IS_ERR(raptor.device)) {
+ printk(KERN_ERR "raptor: device_create failed\n");
+ return -1;
+ }
+
+ cdev_init(&raptor.cdev, &raptor_fops);
+
+ if (cdev_add(&raptor.cdev, raptor.dev, 1) < 0) {
+ printk(KERN_ERR "raptor: cdev_add failed\n");
+ return -1;
+ }
+
+ if (pci_register_driver(&pci_driver) != 0) {
+ printk(KERN_ALERT "raptor: pci driver NOT loaded\n");
+ return -1;
+ }
+
+ printk(KERN_INFO "raptor: module inserted\n");
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ printk(KERN_INFO "raptor: removing module...\n");
+
+ pci_unregister_driver(&pci_driver);
+
+ cdev_del(&raptor.cdev);
+ device_destroy(raptor.class, raptor.dev);
+
+ class_destroy(raptor.class);
+ unregister_chrdev_region(raptor.base, 1);
+
+ kfree(raptor.send_packets);
+ kfree(raptor.recv_packets);
+
+ memset(&raptor, 0, sizeof(raptor));
+
+ printk(KERN_INFO "raptor: module removed\n");
+}
diff --git a/netfpga10g/constraints.ucf b/netfpga10g/constraints.ucf
new file mode 100644
index 0000000..9f16110
--- /dev/null
+++ b/netfpga10g/constraints.ucf
@@ -0,0 +1,52 @@
+
+CONFIG PART = xc5vtx240tff1759-2;
+
+NET "clk25" LOC = "AJ25" | IOSTANDARD = LVCMOS33;
+NET "clk100" LOC = "AN25" | IOSTANDARD = LVCMOS33;
+
+NET "clk25" TNM_NET=TNM_NET_CLK25;
+TIMESPEC TS_CLK25 = PERIOD TNM_NET_CLK25 25 MHz;
+
+NET "clk100" TNM_NET=TNM_NET_CLK100;
+TIMESPEC TS_CLK100 = PERIOD TNM_NET_CLK100 100 MHz;
+
+NET "led1" LOC = "AK25" | IOSTANDARD = LVCMOS33;
+NET "led2" LOC = "AM24" | IOSTANDARD = LVCMOS33;
+NET "led3" LOC = "AP20" | IOSTANDARD = LVCMOS33;
+
+# PCI express
+NET "pcie_clk_p" LOC = "AT4";
+NET "pcie_clk_n" LOC = "AT3";
+INST "pcie_wrapper/pcie_clk_ibuf" DIFF_TERM = "TRUE";
+
+INST "pcie_wrapper/ep/pcie_ep0/pcie_blk/SIO/.pcie_gt_wrapper_i/GTD[0].GT_i" LOC = GTX_DUAL_X1Y5;
+INST "pcie_wrapper/ep/pcie_ep0/pcie_blk/SIO/.pcie_gt_wrapper_i/GTD[2].GT_i" LOC = GTX_DUAL_X1Y4;
+INST "pcie_wrapper/ep/pcie_ep0/pcie_blk/SIO/.pcie_gt_wrapper_i/GTD[4].GT_i" LOC = GTX_DUAL_X1Y3;
+INST "pcie_wrapper/ep/pcie_ep0/pcie_blk/SIO/.pcie_gt_wrapper_i/GTD[6].GT_i" LOC = GTX_DUAL_X1Y2;
+
+NET "clk125" TNM_NET=TNM_NET_CLK125;
+TIMESPEC TS_CLK125 = PERIOD TNM_NET_CLK125 125 MHz;
+
+# mdio
+
+NET "phy_reset_n" LOC = "AR20" | IOSTANDARD = LVCMOS33;
+NET "mdc" LOC = "AK23" | IOSTANDARD = LVCMOS33;
+NET "mdio" LOC = "AL20" | IOSTANDARD = LVCMOS33;
+
+# xaui
+
+NET "xaui/txoutclk" TNM_NET="clk156_top";
+TIMESPEC "TS_clk156_top" = PERIOD "clk156_top" 156.25 MHz;
+
+NET "clk50" TNM_NET=DCLK_CLK;
+TIMESPEC TS_DCLK_CLK = PERIOD DCLK_CLK 50 MHz;
+
+NET *xaui_block/rocketio_wrapper_i/tile1_rxrecclk0_i TNM_NET=clk156_rec;
+TIMESPEC TS_clk156_rec = PERIOD clk156_rec 156.25MHz;
+
+INST xaui/xaui_block/rocketio_wrapper_i/tile0_xaui_v10_4_rocketio_wrapper_i/YES_REVERSE_LANES.gtx_dual_i LOC=GTX_DUAL_X1Y6;
+INST xaui/xaui_block/rocketio_wrapper_i/tile1_xaui_v10_4_rocketio_wrapper_i/YES_REVERSE_LANES.gtx_dual_i LOC=GTX_DUAL_X1Y7;
+
+NET "xaui0_clk_p" LOC = "M4" ;
+NET "xaui0_clk_n" LOC = "M3" ;
+
diff --git a/netfpga10g/hdl/buff.vhd b/netfpga10g/hdl/buff.vhd
new file mode 100644
index 0000000..39b3a80
--- /dev/null
+++ b/netfpga10g/hdl/buff.vhd
@@ -0,0 +1,192 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+library UNISIM;
+use UNISIM.VComponents.all;
+
+entity buff is
+ Port ( wr_clk : in STD_LOGIC;
+ wr_en : in STD_LOGIC;
+ wr_data : in STD_LOGIC_VECTOR (63 downto 0);
+ wr_done : in STD_LOGIC;
+ wr_cancel : in std_logic := '0';
+ wr_accept : out STD_LOGIC;
+ rd_clk : in STD_LOGIC;
+ rd_en : in STD_LOGIC;
+ rd_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ rd_length : out STD_LOGIC_VECTOR (8 downto 0) := (others => '0');
+ rd_valid : out STD_LOGIC := '0');
+end buff;
+
+architecture arch of buff is
+
+ COMPONENT ram_4kB
+ PORT (
+ clka : IN STD_LOGIC;
+ wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
+ addra : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
+ dina : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
+ clkb : IN STD_LOGIC;
+ addrb : IN STD_LOGIC_VECTOR(8 DOWNTO 0);
+ doutb : OUT STD_LOGIC_VECTOR(63 DOWNTO 0)
+ );
+ END COMPONENT;
+
+ signal ram_wr_en : std_logic_vector(0 downto 0);
+ signal ram_wr_addr : std_logic_vector(8 downto 0);
+ signal ram_wr_data : std_logic_vector(63 downto 0);
+
+ signal ram_rd_addr : std_logic_vector(8 downto 0);
+ signal ram_rd_data : std_logic_vector(63 downto 0);
+
+ constant W1 : std_logic_vector(1 downto 0) := "00";
+ constant W2 : std_logic_vector(1 downto 0) := "11";
+ constant R1 : std_logic_vector(1 downto 0) := "01";
+ constant R2 : std_logic_vector(1 downto 0) := "10";
+
+ signal wr_owner : std_logic_vector(1 downto 0) := W1;
+ signal rd_owner : std_logic_vector(1 downto 0) := W1;
+ signal wr_owner_tmp : std_logic_vector(1 downto 0) := W1;
+ signal wr_owner_sync : std_logic_vector(1 downto 0) := W1;
+
+ -- MAX: 256 bytes less than 4kB, for ouroboros
+ -- 4kB = 512 x 64 bits
+ -- 256 bytes = 32 x 64 bits
+ -- 512 - 32 = 480
+ -- 480 = "111100000"
+
+ constant MAX : std_logic_vector(8 downto 0) := "111100000";
+ constant ZERO : std_logic_vector(8 downto 0) := "000000000";
+ constant ONE : std_logic_vector(8 downto 0) := "000000001";
+
+ type state_t is (state_empty, state_wait, state_full, state_first, state_valid);
+
+ signal rd_state : state_t := state_empty;
+ signal rd_addr : std_logic_vector(8 downto 0) := MAX;
+
+begin
+
+ ram : ram_4kB
+ PORT MAP (
+ clka => wr_clk,
+ wea => ram_wr_en,
+ addra => ram_wr_addr,
+ dina => ram_wr_data,
+ clkb => rd_clk,
+ addrb => ram_rd_addr,
+ doutb => ram_rd_data
+ );
+
+ wr_accept <= '1' when (wr_owner = W1 or wr_owner = W2) and wr_done = '0' and wr_cancel = '0' else '0';
+
+ process (wr_clk)
+ variable wr_count : std_logic_vector(8 downto 0) := ZERO;
+ begin
+ if rising_edge(wr_clk) then
+ ram_wr_en(0) <= '0';
+ ram_wr_addr <= (others => '0');
+ ram_wr_data <= (others => '0');
+
+ if wr_owner = W1 or wr_owner = W2 then
+ if wr_cancel = '1' then
+ wr_count := ZERO;
+
+ elsif wr_done = '1' then
+ if wr_count /= ZERO then
+ if wr_owner = W1 then
+ wr_owner <= R1;
+ ram_wr_data(1 downto 0) <= R1;
+ else
+ wr_owner <= R2;
+ ram_wr_data(1 downto 0) <= R2;
+ end if;
+
+ ram_wr_en(0) <= '1';
+ ram_wr_addr <= MAX;
+ ram_wr_data(10 downto 2) <= wr_count;
+ wr_count := ZERO;
+ end if;
+
+ elsif wr_en = '1' then
+ if wr_count /= MAX then
+ ram_wr_en(0) <= '1';
+ ram_wr_addr <= wr_count;
+ ram_wr_data <= wr_data;
+ wr_count := std_logic_vector(unsigned(wr_count) + 1);
+ end if;
+ end if;
+ elsif wr_owner = R1 then
+ if wr_owner_sync = W2 then
+ wr_owner <= W2;
+ end if;
+ elsif wr_owner = R2 then
+ if wr_owner_sync = W1 then
+ wr_owner <= W1;
+ end if;
+ end if;
+
+ wr_owner_tmp <= rd_owner;
+ wr_owner_sync <= wr_owner_tmp;
+ end if;
+ end process;
+
+ ram_rd_addr <= std_logic_vector(unsigned(rd_addr) + 1)
+ when rd_state = state_valid and rd_en = '1'
+ else rd_addr;
+
+ process (rd_clk)
+ variable rd_count : std_logic_vector(8 downto 0) := ZERO;
+ variable tmp : std_logic_vector(1 downto 0);
+ begin
+ if rising_edge(rd_clk) then
+ if rd_state = state_empty then
+ rd_state <= state_wait;
+
+ elsif rd_state = state_wait then
+ tmp := ram_rd_data(1 downto 0);
+
+ if (rd_owner = W1 and tmp = R1) or
+ (rd_owner = W2 and tmp = R2) then
+
+ rd_state <= state_full;
+ rd_addr <= ZERO;
+ rd_count := ram_rd_data(10 downto 2);
+ rd_owner <= tmp;
+ end if;
+
+ elsif rd_state = state_full then
+ rd_state <= state_first;
+ rd_addr <= ONE;
+
+ elsif rd_state = state_first then
+ rd_state <= state_valid;
+ rd_valid <= '1';
+ rd_data <= ram_rd_data;
+ rd_length <= rd_count;
+
+ elsif rd_state = state_valid then
+ if rd_en = '1' then
+ if rd_addr = rd_count then
+ rd_state <= state_empty;
+ rd_addr <= MAX;
+ rd_valid <= '0';
+ rd_data <= (others => '0');
+ rd_length <= ZERO;
+ rd_count := ZERO;
+
+ if rd_owner = R1 then
+ rd_owner <= W2;
+ else
+ rd_owner <= W1;
+ end if;
+ else
+ rd_addr <= ram_rd_addr;
+ rd_data <= ram_rd_data;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/dma.vhd b/netfpga10g/hdl/dma.vhd
new file mode 100644
index 0000000..4c7e4f8
--- /dev/null
+++ b/netfpga10g/hdl/dma.vhd
@@ -0,0 +1,640 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity dma is
+generic (
+ BITS : integer := 14
+);
+port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ rx_read : in std_logic;
+ rx_write : in std_logic;
+ rx_complete : in std_logic;
+ rx_data : in std_logic_vector(63 downto 0);
+ rx_address : in std_logic_vector(28 downto 0);
+
+ tx_read : out std_logic;
+ tx_write : out std_logic;
+ tx_complete : out std_logic;
+ tx_data : out std_logic_vector(63 downto 0);
+ tx_address : out std_logic_vector(28 downto 0);
+ tx_length : out std_logic_vector(8 downto 0);
+ tx_accept : in std_logic;
+ tx_done : in std_logic;
+
+ port0_read : out std_logic;
+ port0_rd_data : in std_logic_vector(63 downto 0);
+ port0_rd_empty : in std_logic;
+ port0_rd_count : in std_logic_vector(BITS downto 0);
+
+ port0_write : out std_logic;
+ port0_wr_data : out std_logic_vector(63 downto 0);
+ port0_wr_full : in std_logic;
+ port0_wr_count : in std_logic_vector(BITS downto 0);
+
+ port1_read : out std_logic;
+ port1_rd_data : in std_logic_vector(63 downto 0);
+ port1_rd_empty : in std_logic;
+ port1_rd_count : in std_logic_vector(BITS downto 0);
+
+ port1_write : out std_logic;
+ port1_wr_data : out std_logic_vector(63 downto 0);
+ port1_wr_full : in std_logic;
+ port1_wr_count : in std_logic_vector(BITS downto 0);
+
+ port2_read : out std_logic;
+ port2_rd_data : in std_logic_vector(63 downto 0);
+ port2_rd_empty : in std_logic;
+ port2_rd_count : in std_logic_vector(BITS downto 0);
+
+ port2_write : out std_logic;
+ port2_wr_data : out std_logic_vector(63 downto 0);
+ port2_wr_full : in std_logic;
+ port2_wr_count : in std_logic_vector(BITS downto 0);
+
+ port3_read : out std_logic;
+ port3_rd_data : in std_logic_vector(63 downto 0);
+ port3_rd_empty : in std_logic;
+ port3_rd_count : in std_logic_vector(BITS downto 0);
+
+ port3_write : out std_logic;
+ port3_wr_data : out std_logic_vector(63 downto 0);
+ port3_wr_full : in std_logic;
+ port3_wr_count : in std_logic_vector(BITS downto 0);
+
+ max_read : in std_logic_vector(2 downto 0);
+ max_write : in std_logic_vector(2 downto 0);
+
+ interrupt : out std_logic;
+ interrupt_rdy : in std_logic;
+
+ mdio_command : out std_logic_vector(0 to 27);
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic;
+ mdio_done : in std_logic;
+
+ leds : out std_logic_vector(2 downto 0)
+);
+end dma;
+
+architecture arch of dma is
+ type state_t is (state_idle, state_tx_read, state_tx_write, state_tx_complete, state_rx_complete,
+ state_dma_read, state_dma_write, state_interrupt, state_command,
+ state_test_write_head, state_test_write,
+ state_test_read_head, state_test_read, state_test_complete,
+ state_mdio);
+ signal state : state_t;
+
+ signal fifo_read : std_logic;
+ signal fifo_write : std_logic;
+ signal fifo_din : std_logic_vector(63 downto 0);
+ signal fifo_dout : std_logic_vector(63 downto 0);
+ signal fifo_full : std_logic;
+ signal fifo_empty : std_logic;
+ signal fifo_count : std_logic_vector(BITS downto 0);
+
+ component simple_fifo port (
+ clk : in std_logic;
+ rst : in std_logic;
+ rd_en : in std_logic;
+ wr_en : in std_logic;
+ din : in std_logic_vector(63 downto 0);
+ dout : out std_logic_vector(63 downto 0);
+ full : out std_logic;
+ empty : out std_logic;
+ data_count : out std_logic_vector(BITS downto 0)
+ );
+ end component;
+
+ signal cmd_read : std_logic;
+ signal cmd_write : std_logic;
+ signal cmd_din : std_logic_vector(63 downto 0);
+ signal cmd_dout : std_logic_vector(63 downto 0);
+ signal cmd_full : std_logic;
+ signal cmd_empty : std_logic;
+
+ component cmd_fifo port (
+ clk : in std_logic;
+ rst : in std_logic;
+ rd_en : in std_logic;
+ wr_en : in std_logic;
+ din : in std_logic_vector(63 downto 0);
+ dout : out std_logic_vector(63 downto 0);
+ full : out std_logic;
+ empty : out std_logic
+ );
+ end component;
+
+ signal test_completion : std_logic_vector(63 downto 0);
+begin
+ process (clk, reset)
+ variable bar_addr : unsigned(BITS downto 0);
+ variable dma_addr : unsigned(28 downto 0);
+ variable length : unsigned(BITS downto 0);
+ variable remain : unsigned(BITS downto 0);
+ variable cycles : unsigned(BITS downto 0);
+ variable backup_addr : unsigned(28 downto 0);
+ variable backup_length : unsigned(BITS downto 0);
+ begin
+ if reset = '1' then
+ state <= state_idle;
+ tx_read <= '0';
+ tx_write <= '0';
+ tx_complete <= '0';
+ tx_data <= (others => '0');
+ tx_address <= (others => '0');
+ tx_length <= (others => '0');
+ fifo_read <= '0';
+ fifo_write <= '0';
+ fifo_din <= (others => '0');
+ interrupt <= '0';
+ cmd_read <= '0';
+ cmd_write <= '0';
+ cmd_din <= (others => '0');
+ test_completion <= (others => '0');
+ port0_read <= '0';
+ port0_write <= '0';
+ port0_wr_data <= (others => '0');
+ port1_read <= '0';
+ port1_write <= '0';
+ port1_wr_data <= (others => '0');
+ port2_read <= '0';
+ port2_write <= '0';
+ port2_wr_data <= (others => '0');
+ port3_read <= '0';
+ port3_write <= '0';
+ port3_wr_data <= (others => '0');
+ mdio_enable <= '0';
+ mdio_command <= (others => '0');
+
+ elsif rising_edge(clk) then
+ fifo_read <= '0';
+ fifo_write <= '0';
+ fifo_din <= (others => '0');
+ cmd_read <= '0';
+ cmd_write <= '0';
+ cmd_din <= (others => '0');
+ port0_read <= '0';
+ port0_write <= '0';
+ port1_read <= '0';
+ port1_write <= '0';
+ port2_read <= '0';
+ port2_write <= '0';
+ port3_read <= '0';
+ port3_write <= '0';
+
+ -- bar read
+ if state = state_idle and rx_read = '1' then
+ state <= state_tx_complete;
+ tx_complete <= '1';
+ tx_data <= (others => '0');
+ tx_address <= rx_address;
+ bar_addr := unsigned(rx_address(BITS downto 0));
+
+ -- read fifo
+ if bar_addr = 0 then
+ if fifo_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= fifo_dout;
+ fifo_read <= '1';
+ end if;
+
+ -- read command
+ elsif bar_addr = 1 then
+ if cmd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= cmd_dout;
+ cmd_read <= '1';
+ end if;
+
+ -- other
+ elsif bar_addr = 3 then
+ tx_data(BITS downto 0) <= fifo_count;
+
+ elsif bar_addr = 4 then
+ tx_data(2 downto 0) <= max_read;
+
+ elsif bar_addr = 5 then
+ tx_data(2 downto 0) <= max_write;
+
+ elsif bar_addr = 6 then
+ tx_data <= test_completion;
+
+ -- read ports
+ elsif bar_addr = 10 then
+ if port0_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port0_rd_data;
+ port0_read <= '1';
+ end if;
+
+ elsif bar_addr = 11 then
+ if port1_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port1_rd_data;
+ port1_read <= '1';
+ end if;
+
+ elsif bar_addr = 12 then
+ if port2_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port2_rd_data;
+ port2_read <= '1';
+ end if;
+
+ elsif bar_addr = 13 then
+ if port3_rd_empty = '1' then
+ tx_data <= (others => '1');
+ else
+ tx_data <= port3_rd_data;
+ port3_read <= '1';
+ end if;
+
+ -- read counts
+ elsif bar_addr = 20 then
+ tx_data(BITS downto 0) <= port0_rd_count;
+
+ elsif bar_addr = 21 then
+ tx_data(BITS downto 0) <= port0_wr_count;
+
+ elsif bar_addr = 22 then
+ tx_data(BITS downto 0) <= port1_rd_count;
+
+ elsif bar_addr = 23 then
+ tx_data(BITS downto 0) <= port1_wr_count;
+
+ elsif bar_addr = 24 then
+ tx_data(BITS downto 0) <= port2_rd_count;
+
+ elsif bar_addr = 25 then
+ tx_data(BITS downto 0) <= port2_wr_count;
+
+ elsif bar_addr = 26 then
+ tx_data(BITS downto 0) <= port3_rd_count;
+
+ elsif bar_addr = 27 then
+ tx_data(BITS downto 0) <= port3_wr_count;
+
+ -- read mdio
+ elsif bar_addr = 30 then
+ tx_data(15 downto 0) <= mdio_data;
+ end if;
+
+ elsif state = state_tx_complete then
+ if tx_done = '1' then
+ state <= state_idle;
+ end if;
+
+ -- bar write
+ elsif state = state_idle and rx_write = '1' then
+ bar_addr := unsigned(rx_address(BITS downto 0));
+
+ -- write fifo
+ if bar_addr = 0 then
+ if fifo_full = '0' then
+ fifo_din <= rx_data;
+ fifo_write <= '1';
+ end if;
+
+ -- write command
+ elsif bar_addr = 1 then
+ if cmd_full = '0' then
+ cmd_din <= rx_data;
+ cmd_write <= '1';
+ end if;
+
+ if rx_data(0) = '1' then
+ state <= state_command;
+ end if;
+
+ -- write test
+ elsif bar_addr = 2 then
+ dma_addr := unsigned(rx_data(31 downto 3));
+ length := unsigned(rx_data(BITS+32 downto 32));
+ cycles := unsigned(rx_data(BITS+48 downto 48));
+ backup_addr := dma_addr;
+ backup_length := length;
+
+ if rx_data(1) = '0' then
+ state <= state_test_read_head;
+ else
+ state <= state_test_write_head;
+ end if;
+
+ -- write ports
+ elsif bar_addr = 10 then
+ if port0_wr_full = '0' then
+ port0_wr_data <= rx_data;
+ port0_write <= '1';
+ end if;
+
+ elsif bar_addr = 11 then
+ if port1_wr_full = '0' then
+ port1_wr_data <= rx_data;
+ port1_write <= '1';
+ end if;
+
+ elsif bar_addr = 12 then
+ if port2_wr_full = '0' then
+ port2_wr_data <= rx_data;
+ port2_write <= '1';
+ end if;
+
+ elsif bar_addr = 13 then
+ if port3_wr_full = '0' then
+ port3_wr_data <= rx_data;
+ port3_write <= '1';
+ end if;
+
+ -- write mdio
+ elsif bar_addr = 30 then
+ state <= state_mdio;
+ mdio_enable <= '1';
+ mdio_command <= rx_data(27 downto 0);
+ end if;
+
+ -- mdio
+ elsif state = state_mdio then
+ if mdio_done = '1' then
+ mdio_enable <= '0';
+ state <= state_interrupt;
+ interrupt <= '1';
+ end if;
+
+ -- test read
+ elsif state = state_test_read_head then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_read = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_read = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_read = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_read = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_read = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_test_read;
+ tx_read <= '1';
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+
+ elsif state = state_test_read then
+ if tx_done = '1' then
+ state <= state_test_complete;
+ end if;
+
+ elsif state = state_test_complete then
+ if rx_complete = '1' then
+ test_completion <= rx_data;
+ remain := remain - 1;
+
+ if remain = 0 then
+ if length > 0 then
+ state <= state_test_read_head;
+
+ elsif cycles > 1 then
+ state <= state_test_read_head;
+ dma_addr := backup_addr;
+ length := backup_length;
+ cycles := cycles - 1;
+ else
+ state <= state_interrupt;
+ interrupt <= '1';
+ end if;
+ end if;
+ end if;
+
+ -- test write
+ elsif state = state_test_write_head then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_write = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_write = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_write = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_write = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_write = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_test_write;
+ tx_write <= '1';
+ tx_data <= x"FFEEDDCC00000000";
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+
+ elsif state = state_test_write then
+ if tx_done = '1' then
+ if length > 0 then
+ state <= state_test_write_head;
+
+ elsif cycles > 1 then
+ state <= state_test_write_head;
+ dma_addr := backup_addr;
+ length := backup_length;
+ cycles := cycles - 1;
+ else
+ state <= state_interrupt;
+ interrupt <= '1';
+ end if;
+ end if;
+
+ -- command
+ elsif state = state_command then
+ if cmd_empty = '1' then
+ state <= state_interrupt;
+ interrupt <= '1';
+ else
+ cmd_read <= '1';
+
+ if cmd_dout(1) = '0' then
+ state <= state_dma_read;
+ dma_addr := unsigned(cmd_dout(31 downto 3));
+ length := unsigned(cmd_dout(BITS+32 downto 32));
+ fifo_din <= std_logic_vector(resize(length, fifo_din'length));
+ fifo_write <= '1';
+ else
+ state <= state_dma_write;
+ dma_addr := unsigned(cmd_dout(31 downto 3));
+ length := unsigned(fifo_dout(BITS downto 0)) + 1;
+ end if;
+ end if;
+
+ elsif state = state_interrupt then
+ if interrupt_rdy = '1' then
+ state <= state_idle;
+ interrupt <= '0';
+ end if;
+
+ -- dma read
+ elsif state = state_dma_read then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_read = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_read = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_read = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_read = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_read = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_tx_read;
+ tx_read <= '1';
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+
+ elsif state = state_tx_read then
+ if tx_done = '1' then
+ state <= state_rx_complete;
+ end if;
+
+ elsif state = state_rx_complete then
+ if rx_complete = '1' then
+ fifo_din <= rx_data;
+ fifo_write <= '1';
+ remain := remain - 1;
+
+ if remain = 0 then
+ if length > 0 then
+ state <= state_dma_read;
+ else
+ state <= state_command;
+ end if;
+ end if;
+ end if;
+
+ -- dma write
+ elsif state = state_dma_write then
+ remain := 16 - resize(dma_addr(3 downto 0), remain'length);
+
+ if max_write = "001" then
+ remain := 32 - resize(dma_addr(4 downto 0), remain'length);
+ elsif max_write = "010" then
+ remain := 64 - resize(dma_addr(5 downto 0), remain'length);
+ elsif max_write = "011" then
+ remain := 128 - resize(dma_addr(6 downto 0), remain'length);
+ elsif max_write = "100" then
+ remain := 256 - resize(dma_addr(7 downto 0), remain'length);
+ elsif max_write = "101" then
+ remain := 512 - resize(dma_addr(8 downto 0), remain'length);
+ end if;
+
+ if remain > length then
+ remain := length;
+ end if;
+
+ state <= state_tx_write;
+ tx_write <= '1';
+ tx_data <= fifo_dout;
+ tx_address <= std_logic_vector(dma_addr);
+ tx_length <= std_logic_vector(remain(8 downto 0));
+ fifo_read <= '1';
+ length := length - remain;
+ dma_addr := dma_addr + remain;
+ remain := remain - 1;
+
+ elsif state = state_tx_write then
+ if tx_done = '1' then
+ if length > 0 then
+ state <= state_dma_write;
+ else
+ state <= state_command;
+ end if;
+
+ elsif tx_accept = '1' and remain > 0 then
+ tx_data <= fifo_dout;
+ fifo_read <= '1';
+ remain := remain - 1;
+ end if;
+ end if;
+
+ if tx_done = '1' then
+ tx_read <= '0';
+ tx_write <= '0';
+ tx_complete <= '0';
+ tx_data <= (others => '0');
+ tx_address <= (others => '0');
+ tx_length <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+ fifo : entity work.port_fifo port map (
+ reset => reset,
+
+ rd_clk => clk,
+ rd_read => fifo_read,
+ rd_data => fifo_dout,
+ rd_empty => fifo_empty,
+ rd_count => fifo_count,
+
+ wr_write => fifo_write,
+ wr_data => fifo_din,
+ wr_full => fifo_full
+ --wr_count => wr_count
+ );
+
+ commands : cmd_fifo port map (
+ clk => clk,
+ rst => reset,
+ rd_en => cmd_read,
+ wr_en => cmd_write,
+ din => cmd_din,
+ dout => cmd_dout,
+ full => cmd_full,
+ empty => cmd_empty
+ );
+
+ leds <= "000" when state = state_idle else
+ -- bar read
+ "001" when state = state_tx_complete else
+ -- dma read
+ "010" when state = state_dma_read or state = state_tx_read or state = state_rx_complete else
+ -- dma write
+ "011" when state = state_dma_write or state = state_tx_write else
+ -- mdio
+ "100" when state = state_mdio else
+ -- interrupt
+ "101" when state = state_interrupt else
+ -- other
+ "111";
+end arch;
+
diff --git a/netfpga10g/hdl/engine.vhd b/netfpga10g/hdl/engine.vhd
new file mode 100644
index 0000000..16f0a8b
--- /dev/null
+++ b/netfpga10g/hdl/engine.vhd
@@ -0,0 +1,570 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+library UNISIM;
+use UNISIM.VComponents.all;
+
+entity engine is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4; -- 2^4 = 16
+ BAR_BITS : integer := 17;
+ TIME_BITS : integer := 20
+);
+port (
+ clk : in STD_LOGIC;
+
+ rd_buff : out STD_LOGIC_VECTOR (BUFF_BITS - 1 downto 0) := (others => '0');
+ rd_en : out STD_LOGIC := '0';
+ rd_data : in STD_LOGIC_VECTOR (63 downto 0);
+ rd_length : in STD_LOGIC_VECTOR (8 downto 0);
+ rd_valid : in STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+
+ wr_buff : out STD_LOGIC_VECTOR (BUFF_BITS - 1 downto 0) := (others => '0');
+ wr_en : out STD_LOGIC := '0';
+ wr_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ wr_done : out STD_LOGIC := '0';
+ wr_cancel : out STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+ wr_accept : in STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+
+ rx_read : in STD_LOGIC;
+ rx_write : in STD_LOGIC;
+ rx_complete : in STD_LOGIC;
+ rx_data : in STD_LOGIC_VECTOR (63 downto 0);
+ rx_address : in STD_LOGIC_VECTOR (63 downto 3);
+ rx_tag : in std_logic_vector(4 downto 0);
+
+ tx_read : out STD_LOGIC := '0';
+ tx_write : out STD_LOGIC := '0';
+ tx_complete : out STD_LOGIC := '0';
+ tx_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ tx_address : out STD_LOGIC_VECTOR (63 downto 3) := (others => '0');
+ tx_length : out STD_LOGIC_VECTOR (8 downto 0) := (others => '0');
+ tx_tag : out std_logic_vector(4 downto 0) := (others => '0');
+ tx_accept : in STD_LOGIC;
+ tx_done : in STD_LOGIC;
+
+ interrupt : out std_logic := '0';
+ interrupt_rdy : in std_logic;
+
+ max_read : in std_logic_vector(2 downto 0);
+ max_write : in std_logic_vector(2 downto 0);
+
+ mdio_command : out std_logic_vector(0 to 27) := (others => '0');
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic := '0';
+ mdio_done : in std_logic
+);
+end engine;
+
+architecture arch of engine is
+
+ constant BUFF_EMPTY : std_logic_vector(1 downto 0) := "00";
+ constant BUFF_ADDR : std_logic_vector(1 downto 0) := "01";
+ constant BUFF_DATA : std_logic_vector(1 downto 0) := "10";
+ constant BUFF_FULL : std_logic_vector(1 downto 0) := "11";
+
+ type buff_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(1 downto 0);
+ type length_t is array (0 to BUFF_COUNT - 1) of unsigned(8 downto 0);
+ type address_t is array (0 to BUFF_COUNT - 1) of unsigned(63 downto 3);
+ type time_t is array (0 to BUFF_COUNT - 1) of unsigned(TIME_BITS - 1 downto 0);
+
+ type rx_state_t is (rx_state_idle, rx_state_write_done, rx_state_mdio);
+ type tx_state_t is (tx_state_idle, tx_state_read, tx_state_write,
+ tx_state_complete, tx_state_interrupt);
+
+ signal rx_state : rx_state_t := rx_state_idle;
+ signal tx_state : tx_state_t := tx_state_idle;
+
+ signal tx_data_i : std_logic_vector(63 downto 0) := (others => '0');
+
+ constant CMD_STATUS : std_logic_vector(1 downto 0) := "00";
+ constant CMD_SEND : std_logic_vector(1 downto 0) := "01";
+ constant CMD_RECV : std_logic_vector(1 downto 0) := "10";
+ constant CMD_MDIO : std_logic_vector(1 downto 0) := "11";
+
+ signal send_buff : buff_t := (others => BUFF_FULL);
+ signal send_length : length_t := (others => (others => '0'));
+ signal send_remain : length_t := (others => (others => '0'));
+ signal send_address : address_t := (others => (others => '0'));
+ signal send_read_time : time_t := (others => (others => '0'));
+
+ signal recv_buff : buff_t := (others => BUFF_EMPTY);
+ signal recv_address0 : unsigned(63 downto 3);
+ signal recv_address1 : unsigned(63 downto 3);
+ signal recv_address2 : unsigned(63 downto 3);
+ signal recv_address3 : unsigned(63 downto 3);
+ signal recv_address4 : unsigned(63 downto 3);
+ signal recv_address5 : unsigned(63 downto 3);
+ signal recv_address6 : unsigned(63 downto 3);
+ signal recv_address7 : unsigned(63 downto 3);
+ signal recv_address8 : unsigned(63 downto 3);
+ signal recv_address9 : unsigned(63 downto 3);
+ signal recv_address10 : unsigned(63 downto 3);
+ signal recv_address11 : unsigned(63 downto 3);
+ signal recv_address12 : unsigned(63 downto 3);
+ signal recv_address13 : unsigned(63 downto 3);
+ signal recv_address14 : unsigned(63 downto 3);
+ signal recv_address15 : unsigned(63 downto 3);
+
+ signal send_int : std_logic := '0';
+ signal send_int_needed : std_logic := '0';
+ signal send_read : std_logic := '0';
+ signal send_read_done : std_logic := '0';
+ signal send_read_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+ signal send_read_length : unsigned(8 downto 0);
+ signal send_read_remain : unsigned(8 downto 0);
+ signal send_read_address : unsigned(63 downto 3);
+ signal send_write : std_logic := '0';
+ signal send_write_new : std_logic := '0';
+ signal send_write_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+ signal send_write_length : unsigned(8 downto 0);
+ signal send_write_address : unsigned(63 downto 3);
+
+ signal debug_address : std_logic_vector(63 downto 3) := (others => '0');
+ signal debug_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal debug_cmd : std_logic_vector(1 downto 0) := (others => '0');
+ signal debug_buff : std_logic_vector(BUFF_BITS - 1 downto 0) := (others => '0');
+ signal debug_length : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(42, 9));
+
+ signal debug_cmpl_count : unsigned(7 downto 0) := (others => '0');
+ signal debug_cmpl_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal debug_cmpl_tag : std_logic_vector(4 downto 0) := (others => '0');
+ signal debug_cmpl_state : std_logic_vector(7 downto 0) := x"FF";
+
+ signal debug_write_count : unsigned(7 downto 0) := (others => '0');
+ signal debug_write_length : std_logic_vector(8 downto 0) := (others => '0');
+ signal debug_write_addr : std_logic_vector(63 downto 3) := (others => '0');
+ signal debug_write_data : std_logic_vector(63 downto 0) := (others => '0');
+
+ signal debug_accept_count : unsigned(7 downto 0) := (others => '0');
+ signal debug_done_count : unsigned(7 downto 0) := (others => '0');
+
+ signal timer : unsigned(TIME_BITS - 1 downto 0) := (others => '0');
+begin
+ rd_en <= tx_accept when tx_state = tx_state_write else '0';
+
+ tx_data <= rd_data when tx_state = tx_state_write else tx_data_i;
+
+ process (clk)
+ variable bar_read : std_logic := '0';
+ variable bar_read_address : std_logic_vector(63 downto 3) := (others => '0');
+
+ variable tmp_cmd : std_logic_vector(1 downto 0);
+ variable tmp_buff : integer range 0 to BUFF_COUNT - 1;
+ variable tmp_length : unsigned(8 downto 0);
+ variable tmp_remain : unsigned(8 downto 0);
+ variable tmp_address : unsigned(63 downto 3);
+ variable tmp_bar : unsigned(BAR_BITS - 1 downto 0);
+
+ -- see 'metered reads' in pcie core manual (xilinx)
+ -- a maximum of 8 openstanding reads is allowed
+ constant READ_MAX : unsigned(3 downto 0) := x"8";
+ variable read_count : unsigned(3 downto 0) := (others => '0');
+ variable read_decr : std_logic;
+ variable read_incr : std_logic;
+ begin
+ if rising_edge(clk) then
+ wr_en <= '0';
+ wr_data <= (others => '0');
+ wr_done <= '0';
+ wr_cancel <= (others => '0');
+ read_decr := '0';
+ read_incr := '0';
+
+ timer <= timer + 1;
+
+ -- ENGINE: RX
+ if rx_state = rx_state_idle then
+ if rx_read = '1' then
+ bar_read := '1';
+ bar_read_address := rx_address;
+
+ elsif rx_write = '1' then
+ tmp_cmd := rx_address(4 downto 3);
+ tmp_buff := to_integer(unsigned(rx_address(5 + BUFF_BITS - 1 downto 5)));
+ tmp_length := unsigned(rx_address(18 downto 10));
+ tmp_address := unsigned(rx_data(63 downto 3));
+
+ debug_address <= rx_address;
+ debug_data <= rx_data;
+ debug_cmd <= tmp_cmd;
+ debug_buff <= std_logic_vector(to_unsigned(tmp_buff, debug_buff'length));
+ debug_length <= std_logic_vector(tmp_length);
+
+ if tmp_cmd = CMD_SEND then
+ if send_buff(tmp_buff) = BUFF_EMPTY then
+ send_buff(tmp_buff) <= BUFF_ADDR;
+ send_address(tmp_buff) <= tmp_address;
+ send_length(tmp_buff) <= tmp_length;
+ end if;
+
+ elsif tmp_cmd = CMD_RECV then
+ if recv_buff(tmp_buff) = BUFF_FULL then
+ recv_buff(tmp_buff) <= BUFF_ADDR;
+
+ if tmp_buff = 0 then
+ recv_address0 <= tmp_address;
+ elsif tmp_buff = 1 then
+ recv_address1 <= tmp_address;
+ elsif tmp_buff = 2 then
+ recv_address2 <= tmp_address;
+ elsif tmp_buff = 3 then
+ recv_address3 <= tmp_address;
+ elsif tmp_buff = 4 then
+ recv_address4 <= tmp_address;
+ elsif tmp_buff = 5 then
+ recv_address5 <= tmp_address;
+ elsif tmp_buff = 6 then
+ recv_address6 <= tmp_address;
+ elsif tmp_buff = 7 then
+ recv_address7 <= tmp_address;
+ elsif tmp_buff = 8 then
+ recv_address8 <= tmp_address;
+ elsif tmp_buff = 9 then
+ recv_address9 <= tmp_address;
+ elsif tmp_buff = 10 then
+ recv_address10 <= tmp_address;
+ elsif tmp_buff = 11 then
+ recv_address11 <= tmp_address;
+ elsif tmp_buff = 12 then
+ recv_address12 <= tmp_address;
+ elsif tmp_buff = 13 then
+ recv_address13 <= tmp_address;
+ elsif tmp_buff = 14 then
+ recv_address14 <= tmp_address;
+ elsif tmp_buff = 15 then
+ recv_address15 <= tmp_address;
+ end if;
+ end if;
+
+ elsif tmp_cmd = CMD_MDIO then
+ rx_state <= rx_state_mdio;
+ mdio_enable <= '1';
+ mdio_command <= rx_data(27 downto 0);
+ end if;
+
+ elsif rx_complete = '1' then
+ tmp_buff := to_integer(unsigned(rx_tag(BUFF_BITS - 1 downto 0)));
+
+ debug_cmpl_count <= debug_cmpl_count + 1;
+ debug_cmpl_data <= rx_data;
+ debug_cmpl_tag <= rx_tag;
+ debug_cmpl_state <= x"00";
+
+ if send_buff(tmp_buff) = BUFF_DATA then
+ wr_en <= '1';
+ wr_data <= rx_data;
+ wr_buff <= std_logic_vector(to_unsigned(tmp_buff, BUFF_BITS));
+ send_remain(tmp_buff) <= send_remain(tmp_buff) - 1;
+ debug_cmpl_state <= x"01";
+
+ if send_remain(tmp_buff) = 1 then
+ read_decr := '1';
+
+ if send_length(tmp_buff) = 0 then
+ rx_state <= rx_state_write_done;
+ debug_cmpl_state <= x"02";
+ else
+ send_buff(tmp_buff) <= BUFF_ADDR;
+ debug_cmpl_state <= x"03";
+ end if;
+ end if;
+ end if;
+ end if;
+
+ elsif rx_state = rx_state_write_done then
+ rx_state <= rx_state_idle;
+ wr_done <= '1';
+
+ elsif rx_state = rx_state_mdio then
+ if mdio_done = '1' then
+ rx_state <= rx_state_idle;
+ mdio_enable <= '0';
+ end if;
+ end if;
+
+ -- ENGINE: TX
+ if send_read_done = '1' then
+ send_read_done <= '0';
+ send_buff(send_read_buff) <= BUFF_DATA;
+ send_length(send_read_buff) <= send_read_length - send_read_remain;
+ send_remain(send_read_buff) <= send_read_remain;
+ send_address(send_read_buff) <= send_read_address + send_read_remain;
+ send_read_time(send_read_buff) <= timer;
+ end if;
+
+ if tx_state = tx_state_idle or
+ (tx_state = tx_state_read and tx_done = '1') or
+ (tx_state = tx_state_write and tx_done = '1') or
+ (tx_state = tx_state_complete and tx_done = '1') or
+ (tx_state = tx_state_interrupt and interrupt_rdy = '1') then
+
+ tx_state <= tx_state_idle;
+ tx_read <= '0';
+ tx_write <= '0';
+ tx_complete <= '0';
+ tx_data_i <= (others => '0');
+ tx_address <= (others => '0');
+ tx_length <= (others => '0');
+ tx_tag <= (others => '0');
+ interrupt <= '0';
+
+ if bar_read = '1' then
+ tx_state <= tx_state_complete;
+ tx_complete <= '1';
+ tx_address <= bar_read_address;
+ tmp_cmd := bar_read_address(4 downto 3);
+ tmp_bar := unsigned(bar_read_address(3 + BAR_BITS - 1 downto 3));
+ bar_read := '0';
+
+ if tmp_bar = 0 then
+ --if tmp_cmd = CMD_STATUS then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tx_data_i(i*4 + 1 downto i*4 + 0) <= send_buff(i);
+ tx_data_i(i*4 + 3 downto i*4 + 2) <= recv_buff(i);
+ end loop;
+ send_int <= '0';
+ send_int_needed <= '1';
+
+ elsif tmp_bar = 1 then
+ tx_data_i(63 downto 3) <= debug_address;
+
+ elsif tmp_bar = 2 then
+ tx_data_i <= debug_data;
+
+ elsif tmp_bar = 3 then
+ tx_data_i(1 downto 0) <= debug_cmd;
+
+ elsif tmp_bar = 4 then
+ tx_data_i(BUFF_BITS - 1 downto 0) <= debug_buff;
+
+ elsif tmp_bar = 5 then
+ tx_data_i(8 downto 0) <= debug_length;
+
+ elsif tmp_bar = 10 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_cmpl_count);
+
+ elsif tmp_bar = 11 then
+ tx_data_i <= debug_cmpl_data;
+
+ elsif tmp_bar = 12 then
+ tx_data_i(4 downto 0) <= debug_cmpl_tag;
+
+ elsif tmp_bar = 13 then
+ tx_data_i(7 downto 0) <= debug_cmpl_state;
+
+ elsif tmp_bar = 20 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_write_count);
+
+ elsif tmp_bar = 21 then
+ tx_data_i(8 downto 0) <= debug_write_length;
+
+ elsif tmp_bar = 22 then
+ tx_data_i(63 downto 3) <= debug_write_addr;
+
+ elsif tmp_bar = 23 then
+ tx_data_i(63 downto 0) <= debug_write_data;
+
+ elsif tmp_bar = 24 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_accept_count);
+
+ elsif tmp_bar = 25 then
+ tx_data_i(7 downto 0) <= std_logic_vector(debug_done_count);
+
+ elsif tmp_bar = 30 then
+ tx_data_i(15 downto 0) <= mdio_data;
+
+ else
+ tx_data_i(63 downto 3) <= bar_read_address;
+ end if;
+
+ elsif send_int = '1' and send_int_needed = '1' then
+ tx_state <= tx_state_interrupt;
+ interrupt <= '1';
+ send_int_needed <= '0';
+
+ elsif send_read = '1' and read_count < READ_MAX then
+ tmp_buff := send_read_buff;
+ tmp_length := send_read_length;
+ tmp_address := send_read_address;
+ tmp_remain := 16 - resize(tmp_address(6 downto 3), tmp_remain'length);
+
+ if max_read = "001" then
+ tmp_remain := 32 - resize(tmp_address(7 downto 3), tmp_remain'length);
+ elsif max_read = "010" then
+ tmp_remain := 64 - resize(tmp_address(8 downto 3), tmp_remain'length);
+ elsif max_read = "011" then
+ tmp_remain := 128 - resize(tmp_address(9 downto 3), tmp_remain'length);
+ elsif max_read = "100" then
+ tmp_remain := 256 - resize(tmp_address(10 downto 3), tmp_remain'length);
+ elsif max_read = "101" then
+ tmp_remain := 512 - resize(tmp_address(11 downto 3), tmp_remain'length);
+ end if;
+
+ if tmp_remain > tmp_length then
+ tmp_remain := tmp_length;
+ end if;
+
+ tx_state <= tx_state_read;
+ tx_read <= '1';
+ tx_address <= std_logic_vector(tmp_address);
+ tx_length <= std_logic_vector(tmp_remain);
+ tx_tag <= std_logic_vector(to_unsigned(tmp_buff, tx_tag'length));
+
+ send_read <= '0';
+ send_read_done <= '1';
+ send_read_remain <= tmp_remain;
+ read_incr := '1';
+
+ elsif send_write = '1' then
+ if send_write_new = '1' then
+ tmp_length := unsigned(rd_length);
+ else
+ tmp_length := send_write_length;
+ end if;
+ tmp_address := send_write_address;
+ tmp_remain := 16 - resize(tmp_address(6 downto 3), tmp_remain'length);
+
+ if max_write = "001" then
+ tmp_remain := 32 - resize(tmp_address(7 downto 3), tmp_remain'length);
+ elsif max_write = "010" then
+ tmp_remain := 64 - resize(tmp_address(8 downto 3), tmp_remain'length);
+ elsif max_write = "011" then
+ tmp_remain := 128 - resize(tmp_address(9 downto 3), tmp_remain'length);
+ elsif max_write = "100" then
+ tmp_remain := 256 - resize(tmp_address(10 downto 3), tmp_remain'length);
+ elsif max_write = "101" then
+ tmp_remain := 512 - resize(tmp_address(11 downto 3), tmp_remain'length);
+ end if;
+
+ if tmp_remain > tmp_length then
+ tmp_remain := tmp_length;
+ end if;
+
+ tx_state <= tx_state_write;
+ tx_write <= '1';
+ tx_address <= std_logic_vector(tmp_address);
+ tx_length <= std_logic_vector(tmp_remain);
+
+ debug_write_count <= debug_write_count + 1;
+ debug_write_length <= std_logic_vector(tmp_remain);
+ debug_write_addr <= std_logic_vector(tmp_address);
+ debug_write_data <= rd_data;
+
+ tmp_length := tmp_length - tmp_remain;
+ tmp_address := tmp_address + tmp_remain;
+
+ send_write_length <= tmp_length;
+ send_write_address <= tmp_address;
+ send_write_new <= '0';
+
+ if tmp_length = 0 then
+ send_write <= '0';
+ end if;
+ end if;
+ end if;
+
+ if read_decr = '1' and read_incr = '0' then
+ read_count := read_count - 1;
+ elsif read_decr = '0' and read_incr = '1' then
+ read_count := read_count + 1;
+ end if;
+
+ if tx_accept = '1' then
+ debug_accept_count <= debug_accept_count + 1;
+ end if;
+ if tx_done = '1' then
+ debug_done_count <= debug_done_count + 1;
+ end if;
+
+ for i in 0 to BUFF_COUNT - 1 loop
+ if send_buff(i) = BUFF_DATA and wr_accept(i) = '0' then
+ send_buff(i) <= BUFF_FULL;
+ -- no send_int here
+ end if;
+ if send_buff(i) = BUFF_FULL and wr_accept(i) = '1' then
+ send_buff(i) <= BUFF_EMPTY;
+ send_int <= '1';
+ end if;
+ if recv_buff(i) = BUFF_EMPTY and rd_valid(i) = '1' then
+ recv_buff(i) <= BUFF_FULL;
+ send_int <= '1';
+ end if;
+ if recv_buff(i) = BUFF_DATA and rd_valid(i) = '0' then
+ recv_buff(i) <= BUFF_EMPTY;
+ send_int <= '1';
+ end if;
+
+ if send_buff(i) = BUFF_DATA and send_read_time(i) = timer then
+ -- read timeout
+ wr_cancel(i) <= '1';
+ end if;
+ end loop;
+
+ if send_read = '0' and send_read_done = '0' then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (send_read_buff + i) mod BUFF_COUNT;
+
+ if send_buff(tmp_buff) = BUFF_ADDR then
+ send_read <= '1';
+ send_read_buff <= tmp_buff;
+ send_read_length <= send_length(tmp_buff);
+ send_read_address <= send_address(tmp_buff);
+ exit;
+ end if;
+ end loop;
+ end if;
+
+ if send_write = '0' and (tx_state /= tx_state_write or tx_done = '1') then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (send_write_buff + i) mod BUFF_COUNT;
+
+ if recv_buff(tmp_buff) = BUFF_ADDR then
+ recv_buff(tmp_buff) <= BUFF_DATA;
+ send_write <= '1';
+ send_write_new <= '1';
+ send_write_buff <= tmp_buff;
+ rd_buff <= std_logic_vector(to_unsigned(tmp_buff, BUFF_BITS));
+
+ if tmp_buff = 0 then
+ send_write_address <= recv_address0;
+ elsif tmp_buff = 1 then
+ send_write_address <= recv_address1;
+ elsif tmp_buff = 2 then
+ send_write_address <= recv_address2;
+ elsif tmp_buff = 3 then
+ send_write_address <= recv_address3;
+ elsif tmp_buff = 4 then
+ send_write_address <= recv_address4;
+ elsif tmp_buff = 5 then
+ send_write_address <= recv_address5;
+ elsif tmp_buff = 6 then
+ send_write_address <= recv_address6;
+ elsif tmp_buff = 7 then
+ send_write_address <= recv_address7;
+ elsif tmp_buff = 8 then
+ send_write_address <= recv_address8;
+ elsif tmp_buff = 9 then
+ send_write_address <= recv_address9;
+ elsif tmp_buff = 10 then
+ send_write_address <= recv_address10;
+ elsif tmp_buff = 11 then
+ send_write_address <= recv_address11;
+ elsif tmp_buff = 12 then
+ send_write_address <= recv_address12;
+ elsif tmp_buff = 13 then
+ send_write_address <= recv_address13;
+ elsif tmp_buff = 14 then
+ send_write_address <= recv_address14;
+ elsif tmp_buff = 15 then
+ send_write_address <= recv_address15;
+ end if;
+ exit;
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/eth.vhd b/netfpga10g/hdl/eth.vhd
new file mode 100644
index 0000000..8034ceb
--- /dev/null
+++ b/netfpga10g/hdl/eth.vhd
@@ -0,0 +1,219 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity eth is
+generic (
+ BITS : integer := 14;
+ REVERSE_LANES : std_logic := '0'
+);
+port (
+ clk : in std_logic;
+ reset : in std_logic;
+ clk156_out : out std_logic;
+
+ read : out std_logic;
+ rd_data : in std_logic_vector(63 downto 0);
+ rd_empty : in std_logic;
+ rd_count : in std_logic_vector(BITS downto 0);
+
+ write : out std_logic;
+ wr_data : out std_logic_vector(63 downto 0);
+ wr_full : in std_logic;
+ wr_count : in std_logic_vector(BITS downto 0);
+
+ xaui_clk_p : in std_logic;
+ xaui_clk_n : in std_logic;
+ xaui_dclk : in std_logic;
+ xaui_tx_l0_p : out std_logic;
+ xaui_tx_l0_n : out std_logic;
+ xaui_tx_l1_p : out std_logic;
+ xaui_tx_l1_n : out std_logic;
+ xaui_tx_l2_p : out std_logic;
+ xaui_tx_l2_n : out std_logic;
+ xaui_tx_l3_p : out std_logic;
+ xaui_tx_l3_n : out std_logic;
+ xaui_rx_l0_p : in std_logic;
+ xaui_rx_l0_n : in std_logic;
+ xaui_rx_l1_p : in std_logic;
+ xaui_rx_l1_n : in std_logic;
+ xaui_rx_l2_p : in std_logic;
+ xaui_rx_l2_n : in std_logic;
+ xaui_rx_l3_p : in std_logic;
+ xaui_rx_l3_n : in std_logic
+);
+end eth;
+
+architecture arch of eth is
+ type state_t is (state_idle, state_length, state_data, state_end);
+
+ signal xgmii_txd : std_logic_vector(63 downto 0);
+ signal xgmii_txc : std_logic_vector(7 downto 0);
+ signal xgmii_rxd : std_logic_vector(63 downto 0);
+ signal xgmii_rxc : std_logic_vector(7 downto 0);
+
+ signal clk156 : std_logic;
+
+ signal rx_data : std_logic_vector(63 downto 0);
+ signal rx_start : std_logic;
+ signal rx_end : std_logic;
+ signal rx_rem : integer range 0 to 7;
+
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_start : std_logic;
+ signal tx_end : std_logic;
+ signal tx_rem : integer range 0 to 7;
+begin
+ clk156_out <= clk156;
+
+ -- sending
+ process (clk, reset)
+ variable state : state_t;
+ variable length : unsigned(BITS downto 0);
+ begin
+ if reset = '1' then
+ state := state_idle;
+ read <= '0';
+ tx_data <= (others => '0');
+ tx_start <= '0';
+ tx_end <= '0';
+ tx_rem <= 0;
+
+ elsif rising_edge(clk) then
+ read <= '0';
+ tx_data <= (others => '0');
+ tx_start <= '0';
+ tx_end <= '0';
+ tx_rem <= 0;
+
+ if state = state_idle then
+ if rd_empty = '0' then
+ length := unsigned(rd_data(BITS downto 0)) + 1;
+
+ if length <= unsigned(rd_count) then
+ state := state_data;
+ read <= '1';
+ tx_start <= '1';
+ end if;
+ end if;
+
+ elsif state = state_data then
+ tx_data <= rd_data;
+ length := length - 1;
+
+ if length > 0 then
+ read <= '1';
+ else
+ state := state_end;
+ end if;
+
+ elsif state = state_end then
+ state := state_idle;
+ tx_end <= '1';
+ tx_rem <= 0;
+ end if;
+ end if;
+ end process;
+
+ -- receiving
+ process (clk, reset)
+ variable state : state_t;
+ variable length : unsigned(BITS downto 0);
+ begin
+ if reset = '1' then
+ state := state_idle;
+ write <= '0';
+ wr_data <= (others => '0');
+
+ elsif rising_edge(clk) then
+ write <= '0';
+ wr_data <= (others => '0');
+
+ if state = state_idle then
+ if rx_start = '1' and rx_end = '0' then
+ state := state_length;
+ end if;
+
+ elsif state = state_length then
+ state := state_idle;
+
+ if rx_end = '0' and
+ unsigned(rx_data) <= 511 and
+ 16384 - unsigned(wr_count) >= 512
+ then
+ state := state_data;
+ length := unsigned(rx_data(BITS downto 0)) + 1;
+ end if;
+ end if;
+
+ if state = state_data then
+ write <= '1';
+ wr_data <= rx_data;
+ length := length - 1;
+
+ if length = 0 then
+ state := state_idle;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ xaui : entity work.xaui_top
+ generic map (
+ REVERSE_LANES => REVERSE_LANES
+ )
+ port map (
+ dclk => xaui_dclk,
+ reset => reset,
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+ clk156_out => clk156,
+ refclk_p => xaui_clk_p,
+ refclk_n => xaui_clk_n,
+ xaui_tx_l0_p => xaui_tx_l0_p,
+ xaui_tx_l0_n => xaui_tx_l0_n,
+ xaui_tx_l1_p => xaui_tx_l1_p,
+ xaui_tx_l1_n => xaui_tx_l1_n,
+ xaui_tx_l2_p => xaui_tx_l2_p,
+ xaui_tx_l2_n => xaui_tx_l2_n,
+ xaui_tx_l3_p => xaui_tx_l3_p,
+ xaui_tx_l3_n => xaui_tx_l3_n,
+ xaui_rx_l0_p => xaui_rx_l0_p,
+ xaui_rx_l0_n => xaui_rx_l0_n,
+ xaui_rx_l1_p => xaui_rx_l1_p,
+ xaui_rx_l1_n => xaui_rx_l1_n,
+ xaui_rx_l2_p => xaui_rx_l2_p,
+ xaui_rx_l2_n => xaui_rx_l2_n,
+ xaui_rx_l3_p => xaui_rx_l3_p,
+ xaui_rx_l3_n => xaui_rx_l3_n
+ );
+
+ rx_eth : entity work.rx_eth port map (
+ clk => clk,
+ reset => reset,
+
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+
+ rx_data => rx_data,
+ rx_start => rx_start,
+ rx_end => rx_end,
+ rx_rem => rx_rem
+ );
+
+ tx_eth : entity work.tx_eth port map (
+ clk => clk,
+ reset => reset,
+
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+
+ tx_data => tx_data,
+ tx_start => tx_start,
+ tx_end => tx_end,
+ tx_rem => tx_rem
+ );
+end arch;
diff --git a/netfpga10g/hdl/eth_rx.vhd b/netfpga10g/hdl/eth_rx.vhd
new file mode 100644
index 0000000..bcd395f
--- /dev/null
+++ b/netfpga10g/hdl/eth_rx.vhd
@@ -0,0 +1,84 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity eth_rx is port (
+ clk : in std_logic;
+
+ wr_en : out std_logic := '0';
+ wr_data : out std_logic_vector (63 downto 0) := (others => '0');
+ wr_done : out std_logic := '0';
+ wr_accept : in std_logic;
+
+ xgmii_rxd : in std_logic_vector(63 downto 0);
+ xgmii_rxc : in std_logic_vector(7 downto 0)
+);
+end eth_rx;
+
+architecture arch of eth_rx is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+ constant ERR : std_logic_vector(7 downto 0) := x"FE";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes_a : lanes_t;
+ signal lanes_b : lanes_t;
+
+ signal control_a : std_logic_vector(7 downto 0);
+ signal control_b : std_logic_vector(7 downto 0);
+
+ type state_t is (state_idle, state_a, state_b);
+ signal state : state_t := state_idle;
+begin
+ gen_a : for i in 0 to 7 generate
+ lanes_a(i) <= xgmii_rxd(7+8*i downto 8*i);
+ control_a(i) <= xgmii_rxc(i);
+ end generate gen_a;
+
+ lanes_b(4 to 7) <= lanes_a(0 to 3);
+ control_b(7 downto 4) <= control_a(3 downto 0);
+
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ wr_en <= '0';
+ wr_data <= (others => '0');
+ wr_done <= '0';
+
+ lanes_b(0 to 3) <= lanes_a(4 to 7);
+ control_b(3 downto 0) <= control_a(7 downto 4);
+
+ if state = state_idle and wr_accept = '1' then
+ if control_a(0) = '1' and lanes_a(0) = START then
+ state <= state_a;
+ elsif control_b(0) = '1' and lanes_b(0) = START then
+ state <= state_b;
+ end if;
+
+ elsif state = state_a then
+ wr_en <= '1';
+ for i in 0 to 7 loop
+ wr_data(63-8*i downto 56-8*i) <= lanes_a(i);
+
+ if control_a(i) = '1' and (lanes_a(i) = TERMINATE or lanes_a(i) = ERR) then
+ state <= state_idle;
+ wr_done <= '1';
+ end if;
+ end loop;
+
+ elsif state = state_b then
+ wr_en <= '1';
+ for i in 0 to 7 loop
+ wr_data(63-8*i downto 56-8*i) <= lanes_b(i);
+
+ if control_b(i) = '1' and (lanes_b(i) = TERMINATE or lanes_b(i) = ERR) then
+ state <= state_idle;
+ wr_done <= '1';
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/eth_tx.vhd b/netfpga10g/hdl/eth_tx.vhd
new file mode 100644
index 0000000..cf0081d
--- /dev/null
+++ b/netfpga10g/hdl/eth_tx.vhd
@@ -0,0 +1,68 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity eth_tx is port (
+ clk : in std_logic;
+
+ rd_en : out std_logic;
+ rd_data : in std_logic_vector (63 downto 0);
+ rd_valid : in std_logic;
+
+ xgmii_txd : out std_logic_vector(63 downto 0);
+ xgmii_txc : out std_logic_vector(7 downto 0)
+);
+end eth_tx;
+
+architecture arch of eth_tx is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+
+ constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes : lanes_t := (others => IDLE);
+ signal control : std_logic_vector(7 downto 0) := (others => '1');
+
+ type state_t is (state_idle, state_data);
+ signal state : state_t := state_idle;
+begin
+ lanes_gen : for i in 0 to 7 generate
+ xgmii_txd(7+8*i downto 8*i) <= lanes(i);
+ xgmii_txc(i) <= control(i);
+ end generate lanes_gen;
+
+ rd_en <= '1' when state = state_data else '0';
+
+ process (clk)
+ begin
+ if rising_edge(clk) then
+ lanes <= (others => IDLE);
+ control <= (others => '1');
+
+ if state = state_idle then
+ if rd_valid = '1' then
+ state <= state_data;
+ lanes(0) <= START;
+ lanes(1 to 6) <= (others => PREAMBLE);
+ lanes(7) <= SFD;
+ control(7 downto 1) <= (others => '0');
+ end if;
+
+ elsif state = state_data then
+ if rd_valid = '1' then
+ for i in 0 to 7 loop
+ lanes(i) <= rd_data(63-8*i downto 56-8*i);
+ control(i) <= '0';
+ end loop;
+ else
+ state <= state_idle;
+ lanes(0) <= TERMINATE;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/mdio.vhd b/netfpga10g/hdl/mdio.vhd
new file mode 100644
index 0000000..1cb34fa
--- /dev/null
+++ b/netfpga10g/hdl/mdio.vhd
@@ -0,0 +1,223 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity mdio is port (
+ clk125 : in std_logic;
+ reset125 : in std_logic;
+
+ command : in std_logic_vector(0 to 27); -- operation(2) & phyaddr(5) & devaddr(5) & data_in(16)
+ data_out : out std_logic_vector(0 to 15);
+ enable : in std_logic;
+ done : out std_logic;
+
+ mdio_in : in std_logic;
+ mdio_out : out std_logic;
+ mdio_Z : out std_logic;
+ mdc : out std_logic;
+ phy_reset_n : out std_logic;
+
+ total_count : out std_logic_vector(31 downto 0);
+ address_count : out std_logic_vector(31 downto 0);
+ write_count : out std_logic_vector(31 downto 0);
+ read_count : out std_logic_vector(31 downto 0);
+ read_incr_count : out std_logic_vector(31 downto 0)
+);
+end mdio;
+
+architecture arch of mdio is
+ type state_t is (state_idle, state_preamble, state_start, state_operation,
+ state_phyaddr, state_devaddr, state_turnaround, state_data);
+
+ signal state : state_t;
+ signal state_count : natural range 0 to 32;
+
+ signal operation : std_logic_vector(0 to 1);
+ signal phyaddr : std_logic_vector(0 to 4);
+ signal devaddr : std_logic_vector(0 to 4);
+ signal data_in : std_logic_vector(0 to 15);
+
+ signal mdc_count : natural range 0 to 25;
+ signal mdc_i : std_logic;
+
+ signal total_count_i : unsigned(31 downto 0);
+ signal address_count_i : unsigned(31 downto 0);
+ signal write_count_i : unsigned(31 downto 0);
+ signal read_count_i : unsigned(31 downto 0);
+ signal read_incr_count_i : unsigned(31 downto 0);
+
+ signal done_i : std_logic;
+begin
+ phy_reset_n <= not reset125;
+ mdc <= mdc_i;
+
+ operation <= command(0 to 1);
+ phyaddr <= command(2 to 6);
+ devaddr <= command(7 to 11);
+ data_in <= command(12 to 27);
+
+ done <= done_i;
+
+ process (clk125, reset125) begin
+ if reset125 = '1' then
+ mdc_i <= '0';
+ mdc_count <= 0;
+ done_i <= '0';
+
+ elsif rising_edge(clk125) then
+ done_i <= '0';
+
+ if mdc_count = 25 - 1 then
+ mdc_count <= 0;
+ mdc_i <= not mdc_i; -- 2.5 MHz
+
+ if mdc_i = '0' then -- rising edge
+ if state = state_data and state_count = 15 then
+ done_i <= '1';
+ end if;
+ end if;
+ else
+ mdc_count <= mdc_count + 1;
+ end if;
+ end if;
+ end process;
+
+ process (mdc_i, reset125) begin
+ if reset125 = '1' then
+ state <= state_idle;
+ state_count <= 0;
+ data_out <= (others => '0');
+
+ elsif rising_edge(mdc_i) then
+ state_count <= state_count + 1;
+
+ if state = state_preamble then
+ if state_count = 31 then
+ state <= state_start;
+ state_count <= 0;
+ end if;
+ elsif state = state_start then
+ if state_count = 1 then
+ state <= state_operation;
+ state_count <= 0;
+ end if;
+ elsif state = state_operation then
+ if state_count = 1 then
+ state <= state_phyaddr;
+ state_count <= 0;
+ end if;
+ elsif state = state_phyaddr then
+ if state_count = 4 then
+ state <= state_devaddr;
+ state_count <= 0;
+ end if;
+ elsif state = state_devaddr then
+ if state_count = 4 then
+ state <= state_turnaround;
+ state_count <= 0;
+ end if;
+ elsif state = state_turnaround then
+ if state_count = 1 then
+ state <= state_data;
+ state_count <= 0;
+ end if;
+ elsif state = state_data then
+ data_out(state_count) <= mdio_in;
+
+ if state_count = 15 then
+ state <= state_idle;
+ state_count <= 0;
+ end if;
+ else -- state = state_idle
+ if enable = '1' then
+ state <= state_preamble;
+ state_count <= 0;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ process (mdc_i, reset125) begin
+ if reset125 = '1' then
+ mdio_out <= '0';
+ mdio_Z <= '1';
+
+ elsif falling_edge(mdc_i) then
+ mdio_out <= '0';
+ mdio_Z <= '1';
+
+ if state = state_preamble then
+ mdio_out <= '1';
+ mdio_Z <= '0';
+
+ elsif state = state_start then
+ mdio_out <= '0';
+ mdio_Z <= '0';
+
+ elsif state = state_operation then
+ mdio_out <= operation(state_count);
+ mdio_Z <= '0';
+
+ elsif state = state_phyaddr then
+ mdio_out <= phyaddr(state_count);
+ mdio_Z <= '0';
+
+ elsif state = state_devaddr then
+ mdio_out <= devaddr(state_count);
+ mdio_Z <= '0';
+
+ elsif state = state_turnaround then
+ if operation(0) = '0' then -- write or address
+ mdio_Z <= '0';
+
+ if state_count = 0 then
+ mdio_out <= '1';
+ else
+ mdio_out <= '0';
+ end if;
+ end if;
+
+ elsif state = state_data then
+ if operation(0) = '0' then -- write or address
+ mdio_Z <= '0';
+ mdio_out <= data_in(state_count);
+ end if;
+ end if;
+ end if;
+ end process;
+
+ total_count <= std_logic_vector(total_count_i);
+ address_count <= std_logic_vector(address_count_i);
+ write_count <= std_logic_vector(write_count_i);
+ read_count <= std_logic_vector(read_count_i);
+ read_incr_count <= std_logic_vector(read_incr_count_i);
+
+ process (clk125, reset125) begin
+ if reset125 = '1' then
+ total_count_i <= (others => '0');
+ address_count_i <= (others => '0');
+ write_count_i <= (others => '0');
+ read_count_i <= (others => '0');
+ read_incr_count_i <= (others => '0');
+
+ elsif rising_edge(clk125) then
+ if done_i = '1' then
+ total_count_i <= total_count_i + 1;
+
+ if operation = "00" then
+ address_count_i <= address_count_i + 1;
+ end if;
+ if operation = "01" then
+ write_count_i <= write_count_i + 1;
+ end if;
+ if operation = "11" then
+ read_count_i <= read_count_i + 1;
+ end if;
+ if operation = "10" then
+ read_incr_count_i <= read_incr_count_i + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
diff --git a/netfpga10g/hdl/pcie.vhd b/netfpga10g/hdl/pcie.vhd
new file mode 100644
index 0000000..6dd99cf
--- /dev/null
+++ b/netfpga10g/hdl/pcie.vhd
@@ -0,0 +1,268 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity pcie is
+generic (
+ BITS : integer := 14
+);
+port (
+ pcie_clk_p : in std_logic;
+ pcie_clk_n : in std_logic;
+ reset25 : in std_logic;
+
+ clk125_out : out std_logic;
+ reset125_out : out std_logic;
+
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ port0_read : out std_logic;
+ port0_rd_data : in std_logic_vector(63 downto 0);
+ port0_rd_empty : in std_logic;
+ port0_rd_count : in std_logic_vector(BITS downto 0);
+
+ port0_write : out std_logic;
+ port0_wr_data : out std_logic_vector(63 downto 0);
+ port0_wr_full : in std_logic;
+ port0_wr_count : in std_logic_vector(BITS downto 0);
+
+ port1_read : out std_logic;
+ port1_rd_data : in std_logic_vector(63 downto 0);
+ port1_rd_empty : in std_logic;
+ port1_rd_count : in std_logic_vector(BITS downto 0);
+
+ port1_write : out std_logic;
+ port1_wr_data : out std_logic_vector(63 downto 0);
+ port1_wr_full : in std_logic;
+ port1_wr_count : in std_logic_vector(BITS downto 0);
+
+ port2_read : out std_logic;
+ port2_rd_data : in std_logic_vector(63 downto 0);
+ port2_rd_empty : in std_logic;
+ port2_rd_count : in std_logic_vector(BITS downto 0);
+
+ port2_write : out std_logic;
+ port2_wr_data : out std_logic_vector(63 downto 0);
+ port2_wr_full : in std_logic;
+ port2_wr_count : in std_logic_vector(BITS downto 0);
+
+ port3_read : out std_logic;
+ port3_rd_data : in std_logic_vector(63 downto 0);
+ port3_rd_empty : in std_logic;
+ port3_rd_count : in std_logic_vector(BITS downto 0);
+
+ port3_write : out std_logic;
+ port3_wr_data : out std_logic_vector(63 downto 0);
+ port3_wr_full : in std_logic;
+ port3_wr_count : in std_logic_vector(BITS downto 0);
+
+ mdio_command : out std_logic_vector(0 to 27);
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic;
+ mdio_done : in std_logic;
+
+ leds : out std_logic_vector(2 downto 0)
+);
+end pcie;
+
+architecture arch of pcie is
+ signal clk125 : std_logic;
+ signal reset125 : std_logic;
+
+ signal rx_frame : std_logic_vector(63 downto 0);
+ signal rx_sof : std_logic;
+ signal rx_eof : std_logic;
+ signal rx_valid : std_logic;
+
+ signal rx_read : std_logic;
+ signal rx_write : std_logic;
+ signal rx_complete : std_logic;
+ signal rx_data : std_logic_vector(63 downto 0);
+ signal rx_address : std_logic_vector(28 downto 0);
+
+ signal tx_frame : std_logic_vector(63 downto 0);
+ signal tx_sof : std_logic;
+ signal tx_eof : std_logic;
+ signal tx_half : std_logic;
+ signal tx_valid : std_logic;
+ signal tx_ready : std_logic;
+
+ signal tx_read : std_logic;
+ signal tx_write : std_logic;
+ signal tx_complete : std_logic;
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_address : std_logic_vector(28 downto 0);
+ signal tx_length : std_logic_vector(8 downto 0);
+ signal tx_accept : std_logic;
+ signal tx_done : std_logic;
+
+ signal bus_dev_func : std_logic_vector(15 downto 0);
+ signal transaction_id : std_logic_vector(23 downto 0);
+
+ signal max_read : std_logic_vector(2 downto 0);
+ signal max_write : std_logic_vector(2 downto 0);
+
+ signal interrupt : std_logic;
+ signal interrupt_rdy : std_logic;
+
+ signal bar0 : std_logic;
+begin
+ clk125_out <= clk125;
+ reset125_out <= reset125;
+
+ pcie_wrapper : entity work.pcie_wrapper port map (
+ pcie_clk_p => pcie_clk_p,
+ pcie_clk_n => pcie_clk_n,
+ reset25 => reset25,
+
+ clk125 => clk125,
+ reset125 => reset125,
+
+ pci_exp_rxn => pci_exp_rxn,
+ pci_exp_rxp => pci_exp_rxp,
+ pci_exp_txn => pci_exp_txn,
+ pci_exp_txp => pci_exp_txp,
+
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+
+ bus_dev_func => bus_dev_func,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ bar0 => bar0
+ );
+
+ pcie_rx : entity work.pcie_rx port map (
+ clk => clk125,
+ reset => reset125,
+
+ frame => rx_frame,
+ sof => rx_sof,
+ eof => rx_eof,
+ valid => rx_valid,
+
+ read => rx_read,
+ write => rx_write,
+ complete => rx_complete,
+ data => rx_data,
+ address => rx_address,
+
+ transaction_id => transaction_id,
+ bar0 => bar0
+ );
+
+ pcie_tx : entity work.pcie_tx port map (
+ clk => clk125,
+ reset => reset125,
+
+ frame => tx_frame,
+ sof => tx_sof,
+ eof => tx_eof,
+ half => tx_half,
+ valid => tx_valid,
+ ready => tx_ready,
+
+ read => tx_read,
+ write => tx_write,
+ complete => tx_complete,
+ data => tx_data,
+ address => tx_address,
+ length => tx_length,
+ accept => tx_accept,
+ done => tx_done,
+
+ transaction_id => transaction_id,
+ bus_dev_func => bus_dev_func
+ );
+
+ dma : entity work.dma port map (
+ clk => clk125,
+ reset => reset125,
+
+ rx_read => rx_read,
+ rx_write => rx_write,
+ rx_complete => rx_complete,
+ rx_data => rx_data,
+ rx_address => rx_address,
+
+ tx_read => tx_read,
+ tx_write => tx_write,
+ tx_complete => tx_complete,
+ tx_data => tx_data,
+ tx_address => tx_address,
+ tx_length => tx_length,
+ tx_accept => tx_accept,
+ tx_done => tx_done,
+
+ port0_read => port0_read,
+ port0_rd_data => port0_rd_data,
+ port0_rd_empty => port0_rd_empty,
+ port0_rd_count => port0_rd_count,
+
+ port0_write => port0_write,
+ port0_wr_data => port0_wr_data,
+ port0_wr_full => port0_wr_full,
+ port0_wr_count => port0_wr_count,
+
+ port1_read => port1_read,
+ port1_rd_data => port1_rd_data,
+ port1_rd_empty => port1_rd_empty,
+ port1_rd_count => port1_rd_count,
+
+ port1_write => port1_write,
+ port1_wr_data => port1_wr_data,
+ port1_wr_full => port1_wr_full,
+ port1_wr_count => port1_wr_count,
+
+ port2_read => port2_read,
+ port2_rd_data => port2_rd_data,
+ port2_rd_empty => port2_rd_empty,
+ port2_rd_count => port2_rd_count,
+
+ port2_write => port2_write,
+ port2_wr_data => port2_wr_data,
+ port2_wr_full => port2_wr_full,
+ port2_wr_count => port2_wr_count,
+
+ port3_read => port3_read,
+ port3_rd_data => port3_rd_data,
+ port3_rd_empty => port3_rd_empty,
+ port3_rd_count => port3_rd_count,
+
+ port3_write => port3_write,
+ port3_wr_data => port3_wr_data,
+ port3_wr_full => port3_wr_full,
+ port3_wr_count => port3_wr_count,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ mdio_command => mdio_command,
+ mdio_data => mdio_data,
+ mdio_enable => mdio_enable,
+ mdio_done => mdio_done,
+
+ leds => leds
+ );
+end arch;
+
diff --git a/netfpga10g/hdl/pcie_rx.vhd b/netfpga10g/hdl/pcie_rx.vhd
new file mode 100644
index 0000000..c4ee177
--- /dev/null
+++ b/netfpga10g/hdl/pcie_rx.vhd
@@ -0,0 +1,98 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity pcie_rx is port (
+ clk : in std_logic;
+
+ frame : in std_logic_vector(63 downto 0);
+ sof : in std_logic;
+ eof : in std_logic;
+ valid : in std_logic;
+
+ read : out std_logic := '0';
+ write : out std_logic := '0';
+ complete : out std_logic := '0';
+ data : out std_logic_vector(63 downto 0) := (others => '0');
+ address : out std_logic_vector(63 downto 3) := (others => '0');
+ tag : out std_logic_vector(4 downto 0) := (others => '0');
+ remote : out std_logic_vector(23 downto 0) := (others => '0');
+
+ bar0 : in std_logic
+);
+end pcie_rx;
+
+architecture arch of pcie_rx is
+ type state_t is (state_idle, state_read, state_write, state_write_head,
+ state_complete, state_complete_head);
+
+ signal fmt : std_logic_vector(1 downto 0);
+ signal typ : std_logic_vector(4 downto 0);
+ signal status : std_logic_vector(2 downto 0);
+begin
+ fmt <= frame(62 downto 61);
+ typ <= frame(60 downto 56);
+ status <= frame(15 downto 13);
+
+ process (clk)
+ variable state : state_t := state_idle;
+ variable extra : std_logic_vector(31 downto 0) := (others => '0');
+ begin
+ if rising_edge(clk) then
+ read <= '0';
+ write <= '0';
+ complete <= '0';
+
+ if valid = '0' then
+ -- nothing
+
+ elsif state = state_idle and sof = '1' then
+ data <= (others => '0');
+ address <= (others => '0');
+ tag <= (others => '0');
+
+ if fmt = "00" and typ = "00000" and bar0 = '1' then
+ state := state_read;
+ remote <= frame(31 downto 8);
+
+ elsif fmt = "10" and typ = "00000" and bar0 = '1' then
+ state := state_write_head;
+
+ elsif fmt = "10" and typ = "01010" and status = "000" then
+ state := state_complete_head;
+ end if;
+
+ elsif state = state_read then
+ state := state_idle;
+ read <= '1';
+ address <= x"00000000" & frame(63 downto 35);
+
+ elsif state = state_write_head then
+ state := state_write;
+ address <= x"00000000" & frame(63 downto 35);
+ extra := frame(31 downto 0);
+
+ elsif state = state_write then
+ state := state_idle;
+ write <= '1';
+ data <= extra & frame(63 downto 32);
+
+ elsif state = state_complete_head then
+ state := state_complete;
+ tag <= frame(44 downto 40);
+ extra := frame(31 downto 0);
+
+ elsif state = state_complete then
+ complete <= '1';
+ data <= extra & frame(63 downto 32);
+ extra := frame(31 downto 0);
+ end if;
+
+ if valid = '1' and eof = '1' then
+ state := state_idle;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/pcie_tx.vhd b/netfpga10g/hdl/pcie_tx.vhd
new file mode 100644
index 0000000..dc892b4
--- /dev/null
+++ b/netfpga10g/hdl/pcie_tx.vhd
@@ -0,0 +1,178 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity pcie_tx is port (
+ clk : in std_logic;
+
+ frame : out std_logic_vector(63 downto 0) := (others => '0');
+ sof : out std_logic := '0';
+ eof : out std_logic := '0';
+ half : out std_logic := '0';
+ valid : out std_logic := '0';
+ ready : in std_logic;
+
+ read : in std_logic;
+ write : in std_logic;
+ complete : in std_logic;
+ data : in std_logic_vector(63 downto 0);
+ address : in std_logic_vector(63 downto 3);
+ length : in std_logic_vector(8 downto 0);
+ tag : in std_logic_vector(4 downto 0);
+ local : in std_logic_vector(15 downto 0);
+ remote : in std_logic_vector(23 downto 0);
+ accept : out std_logic;
+ done : out std_logic
+);
+end pcie_tx;
+
+architecture arch of pcie_tx is
+ type state_t is (state_idle, state_read_32, state_read_64,
+ state_write_32, state_write_64,
+ state_write_end_32, state_write_head_64,
+ state_complete, state_complete_head, state_done);
+ signal state : state_t := state_idle;
+begin
+ accept <= ready when state = state_write_32 or state = state_write_64 else '0';
+ done <= ready when state = state_done else '0';
+
+ process (clk)
+ variable extra : std_logic_vector(31 downto 0) := (others => '0');
+ variable remain : unsigned(8 downto 0) := (others => '0');
+ begin
+ if rising_edge(clk) and (ready = '1' or state = state_idle) then
+ frame <= (others => '0');
+ sof <= '0';
+ eof <= '0';
+ half <= '0';
+ valid <= '0';
+
+ -- read
+ if state = state_idle and read = '1' then
+ if unsigned(length) = 0 then
+ state <= state_done;
+ else
+ if address(63 downto 32) = x"00000000" then
+ state <= state_read_32;
+ frame <= "0" & "00" & "00000" & x"00" &
+ "000000" &
+ length & "0" &
+ local &
+ "000" & tag & x"FF";
+ else
+ state <= state_read_64;
+ frame <= "0" & "01" & "00000" & x"00" &
+ "000000" &
+ length & "0" &
+ local &
+ "000" & tag & x"FF";
+ end if;
+ sof <= '1';
+ valid <= '1';
+ end if;
+
+ elsif state = state_read_32 then
+ state <= state_done;
+ frame <= address(31 downto 3) & "000" & x"00000000";
+ eof <= '1';
+ half <= '1';
+ valid <= '1';
+
+ elsif state = state_read_64 then
+ state <= state_done;
+ frame <= address & "000";
+ eof <= '1';
+ valid <= '1';
+
+ -- write
+ elsif state = state_idle and write = '1' then
+ if unsigned(length) = 0 then
+ state <= state_done;
+ else
+ if address(63 downto 32) = x"00000000" then
+ state <= state_write_32;
+ frame <= "0" & "10" & "00000" & x"00" &
+ "000000" &
+ length & "0" &
+ local &
+ x"00" & x"FF";
+ extra := address(31 downto 3) & "000";
+ else
+ state <= state_write_head_64;
+ frame <= "0" & "11" & "00000" & x"00" &
+ "000000" &
+ length & "0" &
+ local &
+ x"00" & x"FF";
+ end if;
+ sof <= '1';
+ valid <= '1';
+ remain := unsigned(length);
+ end if;
+
+ elsif state = state_write_32 then
+ frame <= extra & data(63 downto 32);
+ extra := data(31 downto 0);
+ valid <= '1';
+
+ remain := remain - 1;
+
+ if remain = 0 then
+ state <= state_write_end_32;
+ end if;
+
+ elsif state = state_write_end_32 then
+ state <= state_done;
+ frame <= extra & x"00000000";
+ eof <= '1';
+ half <= '1';
+ valid <= '1';
+
+ elsif state = state_write_head_64 then
+ state <= state_write_64;
+ frame <= address & "000";
+ valid <= '1';
+
+ elsif state = state_write_64 then
+ frame <= data;
+ valid <= '1';
+
+ remain := remain - 1;
+
+ if remain = 0 then
+ state <= state_done;
+ eof <= '1';
+ end if;
+
+ -- complete
+ elsif state = state_idle and complete = '1' then
+ state <= state_complete_head;
+ frame <= "0" & "10" & "01010" & x"00" &
+ x"0002" &
+ local &
+ x"0008";
+ sof <= '1';
+ valid <= '1';
+
+ elsif state = state_complete_head then
+ state <= state_complete;
+ frame <= remote & "0" & address(6 downto 3) & "000" &
+ data(63 downto 32);
+ valid <= '1';
+
+ elsif state = state_complete then
+ state <= state_done;
+ frame <= data(31 downto 0) & x"00000000";
+ eof <= '1';
+ half <= '1';
+ valid <= '1';
+
+ -- done
+ elsif state = state_done then
+ state <= state_idle;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/pcie_wrapper.vhd b/netfpga10g/hdl/pcie_wrapper.vhd
new file mode 100644
index 0000000..35c6047
--- /dev/null
+++ b/netfpga10g/hdl/pcie_wrapper.vhd
@@ -0,0 +1,358 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity pcie_wrapper is port (
+ pcie_clk_p : in std_logic;
+ pcie_clk_n : in std_logic;
+ reset25 : in std_logic;
+
+ clk125 : out std_logic;
+ reset125 : out std_logic;
+
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ rx_frame : out std_logic_vector(63 downto 0);
+ rx_sof : out std_logic;
+ rx_eof : out std_logic;
+ rx_valid : out std_logic;
+
+ tx_frame : in std_logic_vector(63 downto 0);
+ tx_sof : in std_logic;
+ tx_eof : in std_logic;
+ tx_half : in std_logic;
+ tx_valid : in std_logic;
+ tx_ready : out std_logic;
+
+ bus_dev_func : out std_logic_vector(15 downto 0);
+
+ max_read : out std_logic_vector(2 downto 0);
+ max_write : out std_logic_vector(2 downto 0);
+
+ interrupt : in std_logic;
+ interrupt_rdy : out std_logic;
+
+ bar0 : out std_logic
+);
+end pcie_wrapper;
+
+architecture arch of pcie_wrapper is
+
+ component pcie_core port (
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ sys_clk : in std_logic;
+ sys_reset_n : in std_logic;
+
+ refclkout : out std_logic;
+
+ trn_clk : out std_logic;
+ trn_reset_n : out std_logic;
+ trn_lnk_up_n : out std_logic;
+
+ trn_rd : out std_logic_vector(63 downto 0);
+ trn_rrem_n : out std_logic_vector(7 downto 0);
+ trn_rsof_n : out std_logic;
+ trn_reof_n : out std_logic;
+ trn_rsrc_dsc_n : out std_logic;
+ trn_rsrc_rdy_n : out std_logic;
+ trn_rbar_hit_n : out std_logic_vector(6 downto 0);
+ trn_rdst_rdy_n : in std_logic;
+ trn_rerrfwd_n : out std_logic;
+ trn_rnp_ok_n : in std_logic;
+ trn_rfc_npd_av : out std_logic_vector(11 downto 0);
+ trn_rfc_nph_av : out std_logic_vector(7 downto 0);
+ trn_rfc_pd_av : out std_logic_vector(11 downto 0);
+ trn_rfc_ph_av : out std_logic_vector(7 downto 0);
+ trn_rcpl_streaming_n : in std_logic;
+
+ trn_td : in std_logic_vector(63 downto 0);
+ trn_trem_n : in std_logic_vector(7 downto 0);
+ trn_tsof_n : in std_logic;
+ trn_teof_n : in std_logic;
+ trn_tsrc_dsc_n : in std_logic;
+ trn_tsrc_rdy_n : in std_logic;
+ trn_tdst_dsc_n : out std_logic;
+ trn_tdst_rdy_n : out std_logic;
+ trn_terrfwd_n : in std_logic ;
+ trn_tbuf_av : out std_logic_vector(3 downto 0);
+
+ cfg_do : out std_logic_vector(31 downto 0);
+ cfg_rd_wr_done_n : out std_logic;
+ cfg_di : in std_logic_vector(31 downto 0);
+ cfg_byte_en_n : in std_logic_vector(3 downto 0);
+ cfg_dwaddr : in std_logic_vector(9 downto 0);
+ cfg_wr_en_n : in std_logic;
+ cfg_rd_en_n : in std_logic;
+
+ cfg_err_cor_n : in std_logic;
+ cfg_err_cpl_abort_n : in std_logic;
+ cfg_err_cpl_timeout_n : in std_logic;
+ cfg_err_cpl_unexpect_n : in std_logic;
+ cfg_err_ecrc_n : in std_logic;
+ cfg_err_posted_n : in std_logic;
+ cfg_err_tlp_cpl_header : in std_logic_vector(47 downto 0);
+ cfg_err_ur_n : in std_logic;
+ cfg_err_cpl_rdy_n : out std_logic;
+ cfg_err_locked_n : in std_logic;
+ cfg_interrupt_n : in std_logic;
+ cfg_interrupt_rdy_n : out std_logic;
+ cfg_pm_wake_n : in std_logic;
+ cfg_pcie_link_state_n : out std_logic_vector(2 downto 0);
+ cfg_to_turnoff_n : out std_logic;
+ cfg_interrupt_assert_n : in std_logic;
+ cfg_interrupt_di : in std_logic_vector(7 downto 0);
+ cfg_interrupt_do : out std_logic_vector(7 downto 0);
+ cfg_interrupt_mmenable : out std_logic_vector(2 downto 0);
+ cfg_interrupt_msienable : out std_logic;
+
+ cfg_trn_pending_n : in std_logic;
+ cfg_bus_number : out std_logic_vector(7 downto 0);
+ cfg_device_number : out std_logic_vector(4 downto 0);
+ cfg_function_number : out std_logic_vector(2 downto 0);
+ cfg_status : out std_logic_vector(15 downto 0);
+ cfg_command : out std_logic_vector(15 downto 0);
+ cfg_dstatus : out std_logic_vector(15 downto 0);
+ cfg_dcommand : out std_logic_vector(15 downto 0);
+ cfg_lstatus : out std_logic_vector(15 downto 0);
+ cfg_lcommand : out std_logic_vector(15 downto 0);
+ cfg_dsn : in std_logic_vector(63 downto 0);
+
+ fast_train_simulation_only : in std_logic
+ );
+ end component;
+
+ signal sys_reset_n : std_logic;
+
+ signal trn_clk : std_logic;
+ signal trn_reset_n : std_logic;
+ signal trn_lnk_up_n : std_logic;
+
+ signal trn_rd : std_logic_vector(63 downto 0);
+ signal trn_rrem_n : std_logic_vector(7 downto 0);
+ signal trn_rsof_n : std_logic;
+ signal trn_reof_n : std_logic;
+ signal trn_rsrc_dsc_n : std_logic;
+ signal trn_rsrc_rdy_n : std_logic;
+ signal trn_rbar_hit_n : std_logic_vector(6 downto 0);
+ signal trn_rdst_rdy_n : std_logic;
+ signal trn_rerrfwd_n : std_logic;
+ signal trn_rnp_ok_n : std_logic;
+ signal trn_rfc_npd_av : std_logic_vector(11 downto 0);
+ signal trn_rfc_nph_av : std_logic_vector(7 downto 0);
+ signal trn_rfc_pd_av : std_logic_vector(11 downto 0);
+ signal trn_rfc_ph_av : std_logic_vector(7 downto 0);
+ signal trn_rcpl_streaming_n : std_logic;
+
+ signal trn_td : std_logic_vector(63 downto 0);
+ signal trn_trem_n : std_logic_vector(7 downto 0);
+ signal trn_tsof_n : std_logic;
+ signal trn_teof_n : std_logic;
+ signal trn_tsrc_dsc_n : std_logic;
+ signal trn_tsrc_rdy_n : std_logic;
+ signal trn_tdst_dsc_n : std_logic;
+ signal trn_tdst_rdy_n : std_logic;
+ signal trn_terrfwd_n : std_logic;
+ signal trn_tbuf_av : std_logic_vector(3 downto 0);
+
+ signal cfg_do : std_logic_vector(31 downto 0);
+ signal cfg_rd_wr_done_n : std_logic;
+ signal cfg_di : std_logic_vector(31 downto 0);
+ signal cfg_byte_en_n : std_logic_vector(3 downto 0);
+ signal cfg_dwaddr : std_logic_vector(9 downto 0);
+ signal cfg_wr_en_n : std_logic;
+ signal cfg_rd_en_n : std_logic;
+
+ signal cfg_err_cor_n : std_logic;
+ signal cfg_err_cpl_abort_n : std_logic;
+ signal cfg_err_cpl_timeout_n : std_logic;
+ signal cfg_err_cpl_unexpect_n : std_logic;
+ signal cfg_err_ecrc_n : std_logic;
+ signal cfg_err_posted_n : std_logic;
+ signal cfg_err_tlp_cpl_header : std_logic_vector(47 downto 0);
+ signal cfg_err_ur_n : std_logic;
+ signal cfg_err_cpl_rdy_n : std_logic;
+ signal cfg_err_locked_n : std_logic;
+ signal cfg_interrupt_n : std_logic;
+ signal cfg_interrupt_rdy_n : std_logic;
+ signal cfg_pm_wake_n : std_logic;
+ signal cfg_pcie_link_state_n : std_logic_vector(2 downto 0);
+ signal cfg_to_turnoff_n : std_logic;
+ signal cfg_interrupt_assert_n : std_logic;
+ signal cfg_interrupt_di : std_logic_vector(7 downto 0);
+ signal cfg_interrupt_do : std_logic_vector(7 downto 0);
+ signal cfg_interrupt_mmenable : std_logic_vector(2 downto 0);
+ signal cfg_interrupt_msienable : std_logic;
+
+ signal cfg_trn_pending_n : std_logic;
+ signal cfg_bus_number : std_logic_vector(7 downto 0);
+ signal cfg_device_number : std_logic_vector(4 downto 0);
+ signal cfg_function_number : std_logic_vector(2 downto 0);
+ signal cfg_status : std_logic_vector(15 downto 0);
+ signal cfg_command : std_logic_vector(15 downto 0);
+ signal cfg_dstatus : std_logic_vector(15 downto 0);
+ signal cfg_dcommand : std_logic_vector(15 downto 0);
+ signal cfg_lstatus : std_logic_vector(15 downto 0);
+ signal cfg_lcommand : std_logic_vector(15 downto 0);
+ signal cfg_dsn : std_logic_vector(63 downto 0);
+
+ signal pcie_clk : std_logic;
+begin
+ pcie_clk_ibuf : IBUFDS port map (
+ O => pcie_clk,
+ I => pcie_clk_p,
+ IB => pcie_clk_n
+ );
+
+ sys_reset_n <= not reset25;
+
+ trn_rdst_rdy_n <= '0';
+ trn_rnp_ok_n <= '0';
+ trn_rcpl_streaming_n <= '1';
+
+ trn_tsrc_dsc_n <= '1';
+ trn_terrfwd_n <= '1';
+
+ cfg_di <= (others => '0');
+ cfg_byte_en_n <= (others => '1');
+ cfg_dwaddr <= (others => '0');
+ cfg_wr_en_n <= '1';
+ cfg_rd_en_n <= '1';
+
+ cfg_err_cor_n <= '1';
+ cfg_err_cpl_abort_n <= '1';
+ cfg_err_cpl_timeout_n <= '1';
+ cfg_err_cpl_unexpect_n <= '1';
+ cfg_err_ecrc_n <= '1';
+ cfg_err_posted_n <= '1';
+ cfg_err_tlp_cpl_header <= (others => '0');
+ cfg_err_ur_n <= '1';
+ cfg_err_locked_n <= '1';
+ cfg_interrupt_n <= not interrupt;
+ cfg_pm_wake_n <= '1';
+ cfg_interrupt_assert_n <= '1';
+ cfg_interrupt_di <= (others => '0');
+ interrupt_rdy <= not cfg_interrupt_rdy_n;
+
+ cfg_trn_pending_n <= '1';
+ cfg_dsn <= (others => '0');
+
+ ep : pcie_core port map (
+ pci_exp_rxn => pci_exp_rxn,
+ pci_exp_rxp => pci_exp_rxp,
+ pci_exp_txn => pci_exp_txn,
+ pci_exp_txp => pci_exp_txp,
+
+ sys_clk => pcie_clk,
+ sys_reset_n => sys_reset_n,
+
+ refclkout => open,
+
+ trn_clk => trn_clk,
+ trn_reset_n => trn_reset_n,
+ trn_lnk_up_n => trn_lnk_up_n,
+
+ trn_rd => trn_rd,
+ trn_rrem_n => trn_rrem_n,
+ trn_rsof_n => trn_rsof_n,
+ trn_reof_n => trn_reof_n,
+ trn_rsrc_dsc_n => trn_rsrc_dsc_n,
+ trn_rsrc_rdy_n => trn_rsrc_rdy_n,
+ trn_rbar_hit_n => trn_rbar_hit_n,
+ trn_rdst_rdy_n => trn_rdst_rdy_n,
+ trn_rerrfwd_n => trn_rerrfwd_n,
+ trn_rnp_ok_n => trn_rnp_ok_n,
+ trn_rfc_npd_av => trn_rfc_npd_av,
+ trn_rfc_nph_av => trn_rfc_nph_av,
+ trn_rfc_pd_av => trn_rfc_pd_av,
+ trn_rfc_ph_av => trn_rfc_ph_av,
+ trn_rcpl_streaming_n => trn_rcpl_streaming_n,
+
+ trn_td => trn_td,
+ trn_trem_n => trn_trem_n,
+ trn_tsof_n => trn_tsof_n,
+ trn_teof_n => trn_teof_n,
+ trn_tsrc_dsc_n => trn_tsrc_dsc_n,
+ trn_tsrc_rdy_n => trn_tsrc_rdy_n,
+ trn_tdst_dsc_n => trn_tdst_dsc_n,
+ trn_tdst_rdy_n => trn_tdst_rdy_n,
+ trn_terrfwd_n => trn_terrfwd_n,
+ trn_tbuf_av => trn_tbuf_av,
+
+ cfg_do => cfg_do,
+ cfg_rd_wr_done_n => cfg_rd_wr_done_n,
+ cfg_di => cfg_di,
+ cfg_byte_en_n => cfg_byte_en_n,
+ cfg_dwaddr => cfg_dwaddr,
+ cfg_wr_en_n => cfg_wr_en_n,
+ cfg_rd_en_n => cfg_rd_en_n,
+
+ cfg_err_cor_n => cfg_err_cor_n,
+ cfg_err_cpl_abort_n => cfg_err_cpl_abort_n,
+ cfg_err_cpl_timeout_n => cfg_err_cpl_timeout_n,
+ cfg_err_cpl_unexpect_n => cfg_err_cpl_unexpect_n,
+ cfg_err_ecrc_n => cfg_err_ecrc_n,
+ cfg_err_posted_n => cfg_err_posted_n,
+ cfg_err_tlp_cpl_header => cfg_err_tlp_cpl_header,
+ cfg_err_ur_n => cfg_err_ur_n,
+ cfg_err_cpl_rdy_n => cfg_err_cpl_rdy_n,
+ cfg_err_locked_n => cfg_err_locked_n,
+ cfg_interrupt_n => cfg_interrupt_n,
+ cfg_interrupt_rdy_n => cfg_interrupt_rdy_n,
+ cfg_pm_wake_n => cfg_pm_wake_n,
+ cfg_pcie_link_state_n => cfg_pcie_link_state_n,
+ cfg_to_turnoff_n => cfg_to_turnoff_n,
+ cfg_interrupt_assert_n => cfg_interrupt_assert_n,
+ cfg_interrupt_di => cfg_interrupt_di,
+ cfg_interrupt_do => cfg_interrupt_do,
+ cfg_interrupt_mmenable => cfg_interrupt_mmenable,
+ cfg_interrupt_msienable => cfg_interrupt_msienable,
+
+ cfg_trn_pending_n => cfg_trn_pending_n,
+ cfg_bus_number => cfg_bus_number,
+ cfg_device_number => cfg_device_number,
+ cfg_function_number => cfg_function_number,
+ cfg_status => cfg_status,
+ cfg_command => cfg_command,
+ cfg_dstatus => cfg_dstatus,
+ cfg_dcommand => cfg_dcommand,
+ cfg_lstatus => cfg_lstatus,
+ cfg_lcommand => cfg_lcommand,
+ cfg_dsn => cfg_dsn,
+
+ fast_train_simulation_only => '0'
+ );
+
+ clk125 <= trn_clk;
+ reset125 <= not trn_reset_n;
+
+ rx_frame <= trn_rd;
+ rx_sof <= not trn_rsof_n;
+ rx_eof <= not trn_reof_n;
+ rx_valid <= not trn_rsrc_rdy_n;
+
+ trn_td <= tx_frame;
+ trn_tsof_n <= not tx_sof;
+ trn_teof_n <= not tx_eof;
+ trn_tsrc_rdy_n <= not tx_valid;
+ trn_trem_n <= x"0F" when tx_half = '1' else x"00";
+
+ tx_ready <= not trn_tdst_rdy_n;
+
+ bus_dev_func <= cfg_bus_number & cfg_device_number & cfg_function_number;
+
+ max_read <= cfg_dcommand(14 downto 12);
+ max_write <= cfg_dcommand(7 downto 5);
+
+ bar0 <= not trn_rbar_hit_n(0);
+end arch;
+
diff --git a/netfpga10g/hdl/port_fifo.vhd b/netfpga10g/hdl/port_fifo.vhd
new file mode 100644
index 0000000..ff8c93a
--- /dev/null
+++ b/netfpga10g/hdl/port_fifo.vhd
@@ -0,0 +1,94 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity port_fifo is
+generic (
+ BITS : integer := 14
+);
+port (
+ reset : in std_logic;
+
+ rd_clk : in std_logic;
+ rd_read : in std_logic;
+ rd_data : out std_logic_vector(63 downto 0);
+ rd_empty : out std_logic;
+ rd_count : out std_logic_vector(BITS downto 0);
+
+ wr_clk : in std_logic;
+ wr_write : in std_logic;
+ wr_data : in std_logic_vector(63 downto 0);
+ wr_full : out std_logic;
+ wr_count : out std_logic_vector(BITS downto 0)
+);
+end port_fifo;
+
+architecture arch of port_fifo is
+
+ component data_fifo port (
+ rst : in std_logic;
+ rd_clk : in std_logic;
+ rd_en : in std_logic;
+ dout : out std_logic_vector(63 downto 0);
+ empty : out std_logic;
+ rd_data_count : out std_logic_vector(BITS downto 0);
+ wr_clk : in std_logic;
+ wr_en : in std_logic;
+ din : in std_logic_vector(63 downto 0);
+ full : out std_logic;
+ wr_data_count : out std_logic_vector(BITS downto 0)
+ );
+ end component;
+
+ signal raw_read : std_logic;
+ signal raw_data : std_logic_vector(63 downto 0);
+ signal raw_empty : std_logic;
+ signal raw_count : std_logic_vector(BITS downto 0);
+
+ signal has_extra : std_logic;
+ signal extra : std_logic_vector(63 downto 0);
+begin
+ rd_data <= extra when has_extra = '1' and rd_read = '0' else raw_data;
+ rd_empty <= '0' when has_extra = '1' and rd_read = '0' else '1';
+ rd_count <= std_logic_vector(unsigned(raw_count) + 1) when has_extra = '1' and rd_read = '0' else raw_count;
+
+ raw_read <= '0' when has_extra = '1' and rd_read = '0' else '1';
+
+ process (rd_clk, reset)
+ begin
+ if reset = '1' then
+ has_extra <= '0';
+ extra <= (others => '0');
+
+ elsif rising_edge(rd_clk) then
+ if has_extra = '1' then
+ if rd_read = '1' then
+ has_extra <= not raw_empty;
+ extra <= raw_data;
+ end if;
+ else
+ if rd_read = '0' then
+ has_extra <= not raw_empty;
+ extra <= raw_data;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ fifo : data_fifo port map (
+ rst => reset,
+
+ rd_clk => rd_clk,
+ rd_en => raw_read,
+ dout => raw_data,
+ empty => raw_empty,
+ rd_data_count => raw_count,
+
+ wr_clk => wr_clk,
+ wr_en => wr_write,
+ din => wr_data,
+ full => wr_full,
+ wr_data_count => wr_count
+ );
+end arch;
diff --git a/netfpga10g/hdl/recv_mux.vhd b/netfpga10g/hdl/recv_mux.vhd
new file mode 100644
index 0000000..42932af
--- /dev/null
+++ b/netfpga10g/hdl/recv_mux.vhd
@@ -0,0 +1,86 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+
+entity recv_mux is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4 -- 2^4 = 16
+);
+port (
+ rd_clk : in std_logic;
+ rd_buff : in std_logic_vector (BUFF_BITS - 1 downto 0);
+ rd_en : in std_logic;
+ rd_data : out std_logic_vector (63 downto 0) := (others => '0');
+ rd_length : out std_logic_vector (8 downto 0) := (others => '0');
+ rd_valid : out std_logic_vector (BUFF_COUNT - 1 downto 0) := (others => '0');
+
+ wr_clk : in std_logic;
+ wr_en : in std_logic;
+ wr_data : in std_logic_vector (63 downto 0);
+ wr_done : in std_logic;
+ wr_accept : out std_logic := '0'
+);
+end recv_mux;
+
+architecture arch of recv_mux is
+ type rd_data_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(63 downto 0);
+ type rd_length_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(8 downto 0);
+
+ signal wr_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_done_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_accept_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+
+ signal rd_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal rd_data_i : rd_data_t := (others => (others => '0'));
+ signal rd_length_i : rd_length_t := (others => (others => '0'));
+ signal rd_buff_i : integer range 0 to BUFF_COUNT - 1 := 0;
+begin
+ rd_buff_i <= to_integer(unsigned(rd_buff));
+
+ recv_gen: for i in 0 to BUFF_COUNT - 1 generate
+ recv_buff : entity work.buff port map (
+ wr_clk => wr_clk,
+ wr_en => wr_en_i(i),
+ wr_data => wr_data,
+ wr_done => wr_done_i(i),
+ wr_accept => wr_accept_i(i),
+
+ rd_clk => rd_clk,
+ rd_en => rd_en_i(i),
+ rd_data => rd_data_i(i),
+ rd_length => rd_length_i(i),
+ rd_valid => rd_valid(i)
+ );
+
+ wr_en_i(i) <= wr_en when wr_buff = i else '0';
+ wr_done_i(i) <= wr_done when wr_buff = i else '0';
+
+ rd_en_i(i) <= rd_en when rd_buff_i = i else '0';
+ end generate recv_gen;
+
+ rd_data <= rd_data_i(rd_buff_i);
+ rd_length <= rd_length_i(rd_buff_i);
+
+ wr_accept <= wr_accept_i(wr_buff);
+
+ process (wr_clk)
+ variable tmp_buff : integer range 0 to BUFF_COUNT - 1;
+ begin
+ if rising_edge(wr_clk) then
+ if wr_accept_i(wr_buff) = '0' then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (i + wr_buff) mod BUFF_COUNT;
+
+ if wr_accept_i(tmp_buff) = '1' then
+ wr_buff <= tmp_buff;
+ exit;
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/rx_eth.vhd b/netfpga10g/hdl/rx_eth.vhd
new file mode 100644
index 0000000..fe6e65e
--- /dev/null
+++ b/netfpga10g/hdl/rx_eth.vhd
@@ -0,0 +1,168 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity rx_eth is port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ xgmii_rxd : in std_logic_vector(63 downto 0);
+ xgmii_rxc : in std_logic_vector(7 downto 0);
+
+ rx_data : out std_logic_vector(63 downto 0);
+ rx_start : out std_logic;
+ rx_end : out std_logic;
+ rx_rem : out integer range 0 to 7;
+
+ start_count_out : out std_logic_vector(31 downto 0);
+ end_count_out : out std_logic_vector(31 downto 0)
+);
+end rx_eth;
+
+architecture arch of rx_eth is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+ constant ERR : std_logic_vector(7 downto 0) := x"FE";
+
+ constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes_a : lanes_t;
+ signal lanes_b : lanes_t;
+
+ signal control_a : std_logic_vector(7 downto 0);
+ signal control_b : std_logic_vector(7 downto 0);
+
+ signal use_a : std_logic;
+
+ signal start_count : unsigned(31 downto 0);
+ signal end_count : unsigned(31 downto 0);
+begin
+ start_count_out <= std_logic_vector(start_count);
+ end_count_out <= std_logic_vector(end_count);
+
+ rx_lanes_gen : for i in 0 to 7 generate
+ lanes_a(i) <= xgmii_rxd(7+8*i downto 8*i);
+ end generate rx_lanes_gen;
+
+ control_a <= xgmii_rxc;
+ lanes_b(4) <= lanes_a(0);
+ lanes_b(5) <= lanes_a(1);
+ lanes_b(6) <= lanes_a(2);
+ lanes_b(7) <= lanes_a(3);
+ control_b(4) <= control_a(0);
+ control_b(5) <= control_a(1);
+ control_b(6) <= control_a(2);
+ control_b(7) <= control_a(3);
+
+ rx_logic : process (clk, reset) begin
+ if reset = '1' then
+ rx_data <= (others => '0');
+ rx_start <= '0';
+ rx_end <= '0';
+ rx_rem <= 0;
+ start_count <= (others => '0');
+ end_count <= (others => '0');
+ lanes_b(0) <= (others => '0');
+ lanes_b(1) <= (others => '0');
+ lanes_b(2) <= (others => '0');
+ lanes_b(3) <= (others => '0');
+ control_b(3 downto 0) <= (others => '0');
+ use_a <= '1';
+
+ elsif rising_edge(clk) then
+ rx_start <= '0';
+ rx_end <= '0';
+ rx_rem <= 0;
+
+ lanes_b(0) <= lanes_a(4);
+ lanes_b(1) <= lanes_a(5);
+ lanes_b(2) <= lanes_a(6);
+ lanes_b(3) <= lanes_a(7);
+ control_b(3 downto 0) <= control_a(7 downto 4);
+
+ for i in 0 to 7 loop
+ if use_a = '1' then
+ rx_data(63-8*i downto 56-8*i) <= lanes_a(i);
+ else
+ rx_data(63-8*i downto 56-8*i) <= lanes_b(i);
+ end if;
+ end loop;
+
+ if control_a(0) = '1' and lanes_a(0) = START then
+ rx_start <= '1';
+ use_a <= '1';
+ elsif control_b(0) = '1' and lanes_b(0) = START then
+ rx_start <= '1';
+ use_a <= '0';
+ start_count <= start_count + 1;
+ end if;
+
+ if use_a = '1' then
+ if control_a(0) = '1' and (lanes_a(0) = TERMINATE or lanes_a(0) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 0;
+ elsif control_a(1) = '1' and (lanes_a(1) = TERMINATE or lanes_a(1) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 1;
+ elsif control_a(2) = '1' and (lanes_a(2) = TERMINATE or lanes_a(2) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 2;
+ elsif control_a(3) = '1' and (lanes_a(3) = TERMINATE or lanes_a(3) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 3;
+ elsif control_a(4) = '1' and (lanes_a(4) = TERMINATE or lanes_a(4) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 4;
+ elsif control_a(5) = '1' and (lanes_a(5) = TERMINATE or lanes_a(5) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 5;
+ elsif control_a(6) = '1' and (lanes_a(6) = TERMINATE or lanes_a(6) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 6;
+ elsif control_a(7) = '1' and (lanes_a(7) = TERMINATE or lanes_a(7) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 7;
+ end if;
+ else
+ if control_b(0) = '1' and (lanes_b(0) = TERMINATE or lanes_b(0) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 0;
+ end_count <= end_count + 1;
+ elsif control_b(1) = '1' and (lanes_b(1) = TERMINATE or lanes_b(1) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 1;
+ end_count <= end_count + 1;
+ elsif control_b(2) = '1' and (lanes_b(2) = TERMINATE or lanes_b(2) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 2;
+ end_count <= end_count + 1;
+ elsif control_b(3) = '1' and (lanes_b(3) = TERMINATE or lanes_b(3) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 3;
+ end_count <= end_count + 1;
+ elsif control_b(4) = '1' and (lanes_b(4) = TERMINATE or lanes_b(4) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 4;
+ end_count <= end_count + 1;
+ elsif control_b(5) = '1' and (lanes_b(5) = TERMINATE or lanes_b(5) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 5;
+ end_count <= end_count + 1;
+ elsif control_b(6) = '1' and (lanes_b(6) = TERMINATE or lanes_b(6) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 6;
+ end_count <= end_count + 1;
+ elsif control_b(7) = '1' and (lanes_b(7) = TERMINATE or lanes_b(7) = ERR) then
+ rx_end <= '1';
+ rx_rem <= 7;
+ end_count <= end_count + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/send_mux.vhd b/netfpga10g/hdl/send_mux.vhd
new file mode 100644
index 0000000..8d9f667
--- /dev/null
+++ b/netfpga10g/hdl/send_mux.vhd
@@ -0,0 +1,77 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+
+entity send_mux is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4 -- 2^4 = 16
+);
+ Port ( wr_clk : in STD_LOGIC;
+ wr_buff : in STD_LOGIC_VECTOR (BUFF_BITS - 1 downto 0);
+ wr_en : in STD_LOGIC;
+ wr_data : in STD_LOGIC_VECTOR (63 downto 0);
+ wr_done : in STD_LOGIC;
+ wr_cancel : in STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0);
+ wr_accept : out STD_LOGIC_VECTOR (BUFF_COUNT - 1 downto 0) := (others => '0');
+ rd_clk : in STD_LOGIC;
+ rd_en : in STD_LOGIC;
+ rd_data : out STD_LOGIC_VECTOR (63 downto 0) := (others => '0');
+ rd_valid : out STD_LOGIC := '0');
+end send_mux;
+
+architecture arch of send_mux is
+ type rd_data_t is array (0 to BUFF_COUNT - 1) of std_logic_vector(63 downto 0);
+
+ signal wr_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal wr_done_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+
+ signal rd_en_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal rd_data_i : rd_data_t := (others => (others => '0'));
+ signal rd_valid_i : std_logic_vector(BUFF_COUNT - 1 downto 0) := (others => '0');
+ signal rd_buff : integer range 0 to BUFF_COUNT - 1 := 0;
+begin
+ send_gen: for i in 0 to BUFF_COUNT - 1 generate
+ send_buff : entity work.buff port map (
+ wr_clk => wr_clk,
+ wr_en => wr_en_i(i),
+ wr_data => wr_data,
+ wr_done => wr_done_i(i),
+ wr_cancel => wr_cancel(i),
+ wr_accept => wr_accept(i),
+
+ rd_clk => rd_clk,
+ rd_en => rd_en_i(i),
+ rd_data => rd_data_i(i),
+ rd_length => open,
+ rd_valid => rd_valid_i(i)
+ );
+
+ wr_en_i(i) <= wr_en when to_integer(unsigned(wr_buff)) = i else '0';
+ wr_done_i(i) <= wr_done when to_integer(unsigned(wr_buff)) = i else '0';
+
+ rd_en_i(i) <= rd_en when rd_buff = i else '0';
+ end generate send_gen;
+
+ rd_data <= rd_data_i(rd_buff);
+ rd_valid <= rd_valid_i(rd_buff);
+
+ process (rd_clk)
+ variable tmp_buff : integer range 0 to BUFF_COUNT - 1;
+ begin
+ if rising_edge(rd_clk) then
+ if rd_valid_i(rd_buff) = '0' then
+ for i in 0 to BUFF_COUNT - 1 loop
+ tmp_buff := (i + rd_buff) mod BUFF_COUNT;
+
+ if rd_valid_i(tmp_buff) = '1' then
+ rd_buff <= tmp_buff;
+ exit;
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/hdl/system_loop.vhd b/netfpga10g/hdl/system_loop.vhd
new file mode 100644
index 0000000..79031c3
--- /dev/null
+++ b/netfpga10g/hdl/system_loop.vhd
@@ -0,0 +1,253 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+library unisim;
+use unisim.vcomponents.all;
+
+entity system_loop is
+generic (
+ BUFF_COUNT : integer := 16;
+ BUFF_BITS : integer := 4 -- 2^4 = 16
+);
+port (
+ eth_clk : in std_logic;
+ pcie_clk : in std_logic;
+
+ rx_frame : in std_logic_vector(63 downto 0);
+ rx_sof : in std_logic;
+ rx_eof : in std_logic;
+ rx_valid : in std_logic;
+ rx_bar0 : in std_logic;
+
+ tx_frame : out std_logic_vector(63 downto 0);
+ tx_sof : out std_logic;
+ tx_eof : out std_logic;
+ tx_half : out std_logic;
+ tx_valid : out std_logic;
+ tx_ready : in std_logic;
+
+ interrupt : out std_logic;
+ interrupt_rdy : in std_logic;
+
+ max_read : in std_logic_vector(2 downto 0);
+ max_write : in std_logic_vector(2 downto 0);
+
+ local : in std_logic_vector(15 downto 0);
+
+ xgmii_rxd : in std_logic_vector(63 downto 0);
+ xgmii_rxc : in std_logic_vector(7 downto 0);
+
+ xgmii_txd : out std_logic_vector(63 downto 0);
+ xgmii_txc : out std_logic_vector(7 downto 0);
+
+ mdio_command : out std_logic_vector(0 to 27);
+ mdio_data : in std_logic_vector(0 to 15);
+ mdio_enable : out std_logic;
+ mdio_done : in std_logic
+);
+end system_loop;
+
+architecture arch of system_loop is
+ -- send mux
+ signal send_rd_en : std_logic;
+ signal send_rd_data : std_logic_vector (63 downto 0);
+ signal send_rd_valid : std_logic;
+
+ signal send_wr_buff : std_logic_vector (BUFF_BITS - 1 downto 0) := (others => '0');
+ signal send_wr_en : std_logic := '0';
+ signal send_wr_data : std_logic_vector (63 downto 0) := (others => '0');
+ signal send_wr_done : std_logic := '0';
+ signal send_wr_cancel : std_logic_vector (BUFF_COUNT - 1 downto 0);
+ signal send_wr_accept : std_logic_vector (BUFF_COUNT - 1 downto 0);
+
+ -- recv mux
+ signal recv_wr_en : std_logic;
+ signal recv_wr_data : std_logic_vector (63 downto 0);
+ signal recv_wr_done : std_logic;
+ signal recv_wr_accept : std_logic;
+
+ signal recv_rd_buff : std_logic_vector (BUFF_BITS - 1 downto 0) := (others => '0');
+ signal recv_rd_en : std_logic := '0';
+ signal recv_rd_data : std_logic_vector (63 downto 0);
+ signal recv_rd_length : std_logic_vector (8 downto 0);
+ signal recv_rd_valid : std_logic_vector (BUFF_COUNT - 1 downto 0);
+
+ -- pcie_rx
+ signal rx_read : std_logic;
+ signal rx_write : std_logic;
+ signal rx_complete : std_logic;
+ signal rx_data : std_logic_vector(63 downto 0);
+ signal rx_address : std_logic_vector(63 downto 3);
+ signal rx_tag : std_logic_vector(4 downto 0);
+
+ signal remote : std_logic_vector(23 downto 0);
+
+ -- pcie_tx
+ signal tx_read : std_logic;
+ signal tx_write : std_logic;
+ signal tx_complete : std_logic;
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_address : std_logic_vector(63 downto 3);
+ signal tx_length : std_logic_vector(8 downto 0);
+ signal tx_tag : std_logic_vector(4 downto 0);
+ signal tx_accept : std_logic;
+ signal tx_done : std_logic;
+begin
+ eth_rx : entity work.eth_rx port map (
+ clk => eth_clk,
+
+ wr_en => recv_wr_en,
+ wr_data => recv_wr_data,
+ wr_done => recv_wr_done,
+ wr_accept => recv_wr_accept,
+
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc
+ );
+
+ eth_tx : entity work.eth_tx port map (
+ clk => eth_clk,
+
+ rd_en => send_rd_en,
+ rd_data => send_rd_data,
+ rd_valid => send_rd_valid,
+
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc
+ );
+
+ send_mux : entity work.send_mux
+ generic map (
+ BUFF_COUNT => BUFF_COUNT,
+ BUFF_BITS => BUFF_BITS
+ )
+ port map (
+ wr_clk => pcie_clk,
+ wr_buff => send_wr_buff,
+ wr_en => send_wr_en,
+ wr_data => send_wr_data,
+ wr_done => send_wr_done,
+ wr_cancel => send_wr_cancel,
+ wr_accept => send_wr_accept,
+
+ rd_clk => eth_clk,
+ rd_en => send_rd_en,
+ rd_data => send_rd_data,
+ rd_valid => send_rd_valid
+ );
+
+ recv_mux : entity work.recv_mux
+ generic map (
+ BUFF_COUNT => BUFF_COUNT,
+ BUFF_BITS => BUFF_BITS
+ )
+ port map (
+ rd_clk => pcie_clk,
+ rd_buff => recv_rd_buff,
+ rd_en => recv_rd_en,
+ rd_data => recv_rd_data,
+ rd_length => recv_rd_length,
+ rd_valid => recv_rd_valid,
+
+ wr_clk => eth_clk,
+ wr_en => recv_wr_en,
+ wr_data => recv_wr_data,
+ wr_done => recv_wr_done,
+ wr_accept => recv_wr_accept
+ );
+
+ engine : entity work.engine
+ generic map (
+ BUFF_COUNT => BUFF_COUNT,
+ BUFF_BITS => BUFF_BITS
+ )
+ port map (
+ clk => pcie_clk,
+
+ rd_buff => recv_rd_buff,
+ rd_en => recv_rd_en,
+ rd_data => recv_rd_data,
+ rd_length => recv_rd_length,
+ rd_valid => recv_rd_valid,
+
+ wr_buff => send_wr_buff,
+ wr_en => send_wr_en,
+ wr_data => send_wr_data,
+ wr_done => send_wr_done,
+ wr_cancel => send_wr_cancel,
+ wr_accept => send_wr_accept,
+
+ rx_read => rx_read,
+ rx_write => rx_write,
+ rx_complete => rx_complete,
+ rx_data => rx_data,
+ rx_address => rx_address,
+ rx_tag => rx_tag,
+
+ tx_read => tx_read,
+ tx_write => tx_write,
+ tx_complete => tx_complete,
+ tx_data => tx_data,
+ tx_address => tx_address,
+ tx_length => tx_length,
+ tx_tag => tx_tag,
+ tx_accept => tx_accept,
+ tx_done => tx_done,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ mdio_command => mdio_command,
+ mdio_data => mdio_data,
+ mdio_enable => mdio_enable,
+ mdio_done => mdio_done
+ );
+
+ pcie_rx : entity work.pcie_rx port map (
+ clk => pcie_clk,
+
+ frame => rx_frame,
+ sof => rx_sof,
+ eof => rx_eof,
+ valid => rx_valid,
+
+ read => rx_read,
+ write => rx_write,
+ complete => rx_complete,
+ data => rx_data,
+ address => rx_address,
+ tag => rx_tag,
+ remote => remote,
+
+ bar0 => rx_bar0
+ );
+
+ pcie_tx : entity work.pcie_tx port map (
+ clk => pcie_clk,
+
+ frame => tx_frame,
+ sof => tx_sof,
+ eof => tx_eof,
+ half => tx_half,
+ valid => tx_valid,
+ ready => tx_ready,
+
+ read => tx_read,
+ write => tx_write,
+ complete => tx_complete,
+ data => tx_data,
+ address => tx_address,
+ length => tx_length,
+ tag => tx_tag,
+ local => local,
+ remote => remote,
+ accept => tx_accept,
+ done => tx_done
+ );
+
+end arch;
+
diff --git a/netfpga10g/hdl/top.vhd b/netfpga10g/hdl/top.vhd
new file mode 100644
index 0000000..83a5002
--- /dev/null
+++ b/netfpga10g/hdl/top.vhd
@@ -0,0 +1,243 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+Library UNISIM;
+use UNISIM.vcomponents.all;
+
+entity top is port (
+ led1 : out std_logic;
+ led2 : out std_logic;
+ led3 : out std_logic;
+
+ pcie_clk_p : in std_logic;
+ pcie_clk_n : in std_logic;
+ clk25 : in std_logic;
+ clk100 : in std_logic;
+
+ pci_exp_rxn : in std_logic_vector(7 downto 0);
+ pci_exp_rxp : in std_logic_vector(7 downto 0);
+ pci_exp_txn : out std_logic_vector(7 downto 0);
+ pci_exp_txp : out std_logic_vector(7 downto 0);
+
+ mdio : inout std_logic;
+ mdc : out std_logic;
+ phy_reset_n : out std_logic;
+
+ xaui0_clk_p : in std_logic;
+ xaui0_clk_n : in std_logic;
+ xaui0_tx_l0_p : out std_logic;
+ xaui0_tx_l0_n : out std_logic;
+ xaui0_tx_l1_p : out std_logic;
+ xaui0_tx_l1_n : out std_logic;
+ xaui0_tx_l2_p : out std_logic;
+ xaui0_tx_l2_n : out std_logic;
+ xaui0_tx_l3_p : out std_logic;
+ xaui0_tx_l3_n : out std_logic;
+ xaui0_rx_l0_p : in std_logic;
+ xaui0_rx_l0_n : in std_logic;
+ xaui0_rx_l1_p : in std_logic;
+ xaui0_rx_l1_n : in std_logic;
+ xaui0_rx_l2_p : in std_logic;
+ xaui0_rx_l2_n : in std_logic;
+ xaui0_rx_l3_p : in std_logic;
+ xaui0_rx_l3_n : in std_logic
+);
+end top;
+
+architecture arch of top is
+ signal clk125 : std_logic;
+ signal reset125 : std_logic;
+
+ signal count25 : unsigned(6 downto 0) := (others => '0');
+ signal reset25 : std_logic := '1';
+
+ signal clk50 : std_logic;
+ signal clk156 : std_logic;
+
+ signal rx_frame : std_logic_vector(63 downto 0);
+ signal rx_sof : std_logic;
+ signal rx_eof : std_logic;
+ signal rx_valid : std_logic;
+ signal rx_bar0 : std_logic;
+
+ signal tx_frame : std_logic_vector(63 downto 0);
+ signal tx_sof : std_logic;
+ signal tx_eof : std_logic;
+ signal tx_half : std_logic;
+ signal tx_valid : std_logic;
+ signal tx_ready : std_logic;
+
+ signal interrupt : std_logic;
+ signal interrupt_rdy : std_logic;
+
+ signal max_read : std_logic_vector(2 downto 0);
+ signal max_write : std_logic_vector(2 downto 0);
+
+ signal local : std_logic_vector(15 downto 0);
+
+ signal xgmii_rxd : std_logic_vector(63 downto 0);
+ signal xgmii_rxc : std_logic_vector(7 downto 0);
+ signal xgmii_txd : std_logic_vector(63 downto 0);
+ signal xgmii_txc : std_logic_vector(7 downto 0);
+
+ signal mdio_command : std_logic_vector(0 to 27);
+ signal mdio_data : std_logic_vector(0 to 15);
+ signal mdio_enable : std_logic;
+ signal mdio_done : std_logic;
+
+ signal mdio_in : std_logic;
+ signal mdio_out : std_logic;
+ signal mdio_Z : std_logic;
+begin
+ led1 <= '1';
+ led2 <= '0';
+ led3 <= '1';
+
+ process (clk25) begin
+ if rising_edge(clk25) then
+ if count25 = 100 then
+ reset25 <= '0';
+ else
+ count25 <= count25 + 1;
+ end if;
+ end if;
+ end process;
+
+ process (clk100, reset125) begin
+ if reset125 = '1' then
+ clk50 <= '0';
+ elsif rising_edge(clk100) then
+ clk50 <= not clk50;
+ end if;
+ end process;
+
+ pcie_wrapper : entity work.pcie_wrapper port map (
+ pcie_clk_p => pcie_clk_p,
+ pcie_clk_n => pcie_clk_n,
+ reset25 => reset25,
+
+ clk125 => clk125,
+ reset125 => reset125,
+
+ pci_exp_rxn => pci_exp_rxn,
+ pci_exp_rxp => pci_exp_rxp,
+ pci_exp_txn => pci_exp_txn,
+ pci_exp_txp => pci_exp_txp,
+
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+
+ bus_dev_func => local,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ bar0 => rx_bar0
+ );
+
+ system_loop: entity work.system_loop port map (
+ eth_clk => clk156,
+ pcie_clk => clk125,
+
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+ rx_bar0 => rx_bar0,
+
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+
+ max_read => max_read,
+ max_write => max_write,
+
+ local => local,
+
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+
+ mdio_command => mdio_command,
+ mdio_data => mdio_data,
+ mdio_enable => mdio_enable,
+ mdio_done => mdio_done
+ );
+
+ xaui : entity work.xaui_top
+ generic map (
+ REVERSE_LANES => '1'
+ )
+ port map (
+ dclk => clk50,
+ reset => reset125,
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc,
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc,
+ clk156_out => clk156,
+ refclk_p => xaui0_clk_p,
+ refclk_n => xaui0_clk_n,
+ xaui_tx_l0_p => xaui0_tx_l0_p,
+ xaui_tx_l0_n => xaui0_tx_l0_n,
+ xaui_tx_l1_p => xaui0_tx_l1_p,
+ xaui_tx_l1_n => xaui0_tx_l1_n,
+ xaui_tx_l2_p => xaui0_tx_l2_p,
+ xaui_tx_l2_n => xaui0_tx_l2_n,
+ xaui_tx_l3_p => xaui0_tx_l3_p,
+ xaui_tx_l3_n => xaui0_tx_l3_n,
+ xaui_rx_l0_p => xaui0_rx_l0_p,
+ xaui_rx_l0_n => xaui0_rx_l0_n,
+ xaui_rx_l1_p => xaui0_rx_l1_p,
+ xaui_rx_l1_n => xaui0_rx_l1_n,
+ xaui_rx_l2_p => xaui0_rx_l2_p,
+ xaui_rx_l2_n => xaui0_rx_l2_n,
+ xaui_rx_l3_p => xaui0_rx_l3_p,
+ xaui_rx_l3_n => xaui0_rx_l3_n
+ );
+
+ mdio_iobuf : IOBUF port map (
+ O => mdio_in,
+ IO => mdio,
+ I => mdio_out,
+ T => mdio_Z
+ );
+
+ mdio_module : entity work.mdio port map (
+ clk125 => clk125,
+ reset125 => reset125,
+
+ command => mdio_command,
+ data_out => mdio_data,
+ enable => mdio_enable,
+ done => mdio_done,
+
+ mdio_in => mdio_in,
+ mdio_out => mdio_out,
+ mdio_Z => mdio_Z,
+ mdc => mdc,
+ phy_reset_n => phy_reset_n
+ );
+end arch;
diff --git a/netfpga10g/hdl/tx_eth.vhd b/netfpga10g/hdl/tx_eth.vhd
new file mode 100644
index 0000000..fab9cac
--- /dev/null
+++ b/netfpga10g/hdl/tx_eth.vhd
@@ -0,0 +1,96 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity tx_eth is port (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ xgmii_txd : out std_logic_vector(63 downto 0);
+ xgmii_txc : out std_logic_vector(7 downto 0);
+
+ tx_data : in std_logic_vector(63 downto 0);
+ tx_start : in std_logic;
+ tx_end : in std_logic;
+ tx_rem : in integer range 0 to 7;
+
+ start_count_out : out std_logic_vector(31 downto 0);
+ end_count_out : out std_logic_vector(31 downto 0)
+);
+end tx_eth;
+
+architecture arch of tx_eth is
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERMINATE : std_logic_vector(7 downto 0) := x"FD";
+
+ constant PREAMBLE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ type lanes_t is array (0 to 7) of std_logic_vector(7 downto 0);
+ signal lanes : lanes_t;
+
+ signal in_packet : std_logic;
+
+ signal start_count : unsigned(31 downto 0);
+ signal end_count : unsigned(31 downto 0);
+begin
+ start_count_out <= std_logic_vector(start_count);
+ end_count_out <= std_logic_vector(end_count);
+
+ tx_lanes_gen : for i in 0 to 7 generate
+ xgmii_txd(7+8*i downto 8*i) <= lanes(i);
+ end generate tx_lanes_gen;
+
+ tx_logic : process (clk, reset) begin
+ if reset = '1' then
+ in_packet <= '0';
+ start_count <= (others => '0');
+ end_count <= (others => '0');
+
+ for i in 0 to 7 loop
+ lanes(i) <= IDLE;
+ xgmii_txc(i) <= '1';
+ end loop;
+
+ elsif rising_edge(clk) then
+ for i in 0 to 7 loop
+ lanes(i) <= IDLE;
+ xgmii_txc(i) <= '1';
+ end loop;
+
+ if tx_start = '1' then
+ in_packet <= '1';
+ lanes(0) <= START;
+ xgmii_txc(0) <= '1';
+ lanes(1 to 6) <= (others => PREAMBLE);
+ xgmii_txc(6 downto 1) <= (others => '0');
+ lanes(7) <= SFD;
+ xgmii_txc(7) <= '0';
+ start_count <= start_count + 1;
+
+ elsif tx_end = '1' then
+ in_packet <= '0';
+ end_count <= end_count + 1;
+
+ for i in 0 to 7 loop
+ if i < tx_rem then
+ lanes(i) <= tx_data(63-8*i downto 56-8*i);
+ xgmii_txc(i) <= '0';
+ elsif i = tx_rem then
+ lanes(i) <= TERMINATE;
+ xgmii_txc(i) <= '1';
+ end if;
+ end loop;
+
+ elsif in_packet = '1' then
+ for i in 0 to 7 loop
+ lanes(i) <= tx_data(63-8*i downto 56-8*i);
+ xgmii_txc(i) <= '0';
+ end loop;
+ end if;
+ end if;
+ end process;
+end arch;
+
diff --git a/netfpga10g/tests/buff_test.vhd b/netfpga10g/tests/buff_test.vhd
new file mode 100644
index 0000000..d9f4a0a
--- /dev/null
+++ b/netfpga10g/tests/buff_test.vhd
@@ -0,0 +1,151 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY buff_test IS
+END buff_test;
+
+ARCHITECTURE behavior OF buff_test IS
+
+ -- Component Declaration for the Unit Under Test (UUT)
+
+ COMPONENT buff
+ PORT(
+ wr_clk : IN std_logic;
+ wr_en : IN std_logic;
+ wr_data : IN std_logic_vector(63 downto 0);
+ wr_done : IN std_logic;
+ wr_accept : OUT std_logic;
+ rd_clk : IN std_logic;
+ rd_en : IN std_logic;
+ rd_data : OUT std_logic_vector(63 downto 0);
+ rd_length : OUT std_logic_vector(8 downto 0);
+ rd_valid : OUT std_logic
+ );
+ END COMPONENT;
+
+
+ signal wr_clk : std_logic := '0';
+ signal wr_en : std_logic := '0';
+ signal wr_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal wr_done : std_logic := '0';
+ signal wr_accept : std_logic;
+
+ signal rd_clk : std_logic := '0';
+ signal rd_en : std_logic := '0';
+ signal rd_data : std_logic_vector(63 downto 0);
+ signal rd_length : std_logic_vector(8 downto 0);
+ signal rd_valid : std_logic;
+
+ -- Clock period definitions
+ constant wr_clk_period : time := 10 ns;
+ constant rd_clk_period : time := 7 ns;
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: buff PORT MAP (
+ wr_clk => wr_clk,
+ wr_en => wr_en,
+ wr_data => wr_data,
+ wr_done => wr_done,
+ wr_accept => wr_accept,
+ rd_clk => rd_clk,
+ rd_en => rd_en,
+ rd_data => rd_data,
+ rd_length => rd_length,
+ rd_valid => rd_valid
+ );
+
+ -- Clock process definitions
+ wr_clk_process :process
+ begin
+ wr_clk <= '0';
+ wait for wr_clk_period/2;
+ wr_clk <= '1';
+ wait for wr_clk_period/2;
+ end process;
+
+ rd_clk_process :process
+ begin
+ rd_clk <= '0';
+ wait for rd_clk_period/2;
+ rd_clk <= '1';
+ wait for rd_clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ wait for wr_clk_period;
+
+ wr_en <= '1';
+ wr_data <= x"0123456789ABCDEF";
+
+ wait for wr_clk_period;
+
+ wr_en <= '1';
+ wr_data <= x"FEDCBA9876543210";
+
+ wait for wr_clk_period;
+
+ wr_en <= '0';
+ wr_data <= x"0000000000000000";
+ wr_done <= '1';
+
+ wait for wr_clk_period;
+
+ wr_done <= '0';
+
+ wait until wr_accept = '1';
+ wait for wr_clk_period / 2;
+
+ wr_en <= '1';
+ wr_data <= x"AAAAAAAAAAAAAAAA";
+ wait for wr_clk_period;
+ wr_data <= x"BBBBBBBBBBBBBBBB";
+ wait for wr_clk_period;
+ wr_data <= x"CCCCCCCCCCCCCCCC";
+ wait for wr_clk_period;
+ wr_data <= x"DDDDDDDDDDDDDDDD";
+ wait for wr_clk_period;
+ wr_en <= '0';
+ wr_data <= x"0000000000000000";
+ wr_done <= '1';
+ wait for wr_clk_period;
+ wr_done <= '0';
+
+ wait until wr_accept = '1';
+ wait for wr_clk_period / 2;
+ wait for wr_clk_period;
+
+ wr_en <= '1';
+ wr_data <= x"0123456789ABCDEF";
+ wait for wr_clk_period;
+ wr_data <= x"FEDCBA9876543210";
+ wait for wr_clk_period;
+ wr_data <= x"0123456789ABCDEF";
+ wait for wr_clk_period;
+ wr_data <= x"FEDCBA9876543210";
+ wait for wr_clk_period;
+
+ wr_en <= '0';
+ wr_data <= x"0000000000000000";
+ wr_done <= '1';
+ wait for wr_clk_period;
+ wr_done <= '0';
+
+ wait;
+ end process;
+
+ process
+ begin
+ rd_en <= '0';
+ wait for rd_clk_period;
+ rd_en <= '1';
+ wait for rd_clk_period * 2;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/engine_test.vhd b/netfpga10g/tests/engine_test.vhd
new file mode 100644
index 0000000..bf1b3c3
--- /dev/null
+++ b/netfpga10g/tests/engine_test.vhd
@@ -0,0 +1,1123 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY engine_test IS
+END engine_test;
+
+ARCHITECTURE behavior OF engine_test IS
+
+ COMPONENT engine
+ PORT(
+ clk : IN std_logic;
+ rd_buff : OUT std_logic_vector(3 downto 0);
+ rd_en : OUT std_logic;
+ rd_data : IN std_logic_vector(63 downto 0);
+ rd_length : IN std_logic_vector(8 downto 0);
+ rd_valid : IN std_logic_vector(15 downto 0);
+ wr_buff : OUT std_logic_vector(3 downto 0);
+ wr_en : OUT std_logic;
+ wr_data : OUT std_logic_vector(63 downto 0);
+ wr_done : OUT std_logic;
+ wr_accept : IN std_logic_vector(15 downto 0);
+ rx_read : IN std_logic;
+ rx_write : IN std_logic;
+ rx_complete : IN std_logic;
+ rx_data : IN std_logic_vector(63 downto 0);
+ rx_address : IN std_logic_vector(63 downto 3);
+ rx_tag : IN std_logic_vector(4 downto 0);
+ tx_read : OUT std_logic;
+ tx_write : OUT std_logic;
+ tx_complete : OUT std_logic;
+ tx_data : OUT std_logic_vector(63 downto 0);
+ tx_address : OUT std_logic_vector(63 downto 3);
+ tx_length : OUT std_logic_vector(8 downto 0);
+ tx_tag : OUT std_logic_vector(4 downto 0);
+ tx_accept : IN std_logic;
+ tx_done : IN std_logic;
+ interrupt : OUT std_logic;
+ interrupt_rdy : IN std_logic;
+ max_read : IN std_logic_vector(2 downto 0);
+ max_write : IN std_logic_vector(2 downto 0)
+ );
+ END COMPONENT;
+
+ signal clk : std_logic := '0';
+
+ signal rd_buff : std_logic_vector(3 downto 0);
+ signal rd_en : std_logic;
+ signal rd_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal rd_length : std_logic_vector(8 downto 0) := (others => '0');
+ signal rd_valid : std_logic_vector(15 downto 0) := (others => '0');
+
+ signal wr_buff : std_logic_vector(3 downto 0);
+ signal wr_en : std_logic;
+ signal wr_data : std_logic_vector(63 downto 0);
+ signal wr_done : std_logic;
+ signal wr_accept : std_logic_vector(15 downto 0) := (others => '0');
+
+ signal rx_read : std_logic := '0';
+ signal rx_write : std_logic := '0';
+ signal rx_complete : std_logic := '0';
+ signal rx_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal rx_address : std_logic_vector(63 downto 3) := (others => '0');
+ signal rx_tag : std_logic_vector(4 downto 0) := (others => '0');
+
+ signal tx_read : std_logic;
+ signal tx_write : std_logic;
+ signal tx_complete : std_logic;
+ signal tx_data : std_logic_vector(63 downto 0);
+ signal tx_address : std_logic_vector(63 downto 3);
+ signal tx_length : std_logic_vector(8 downto 0);
+ signal tx_tag : std_logic_vector(4 downto 0);
+ signal tx_accept : std_logic := '0';
+ signal tx_done : std_logic := '0';
+
+ signal interrupt : std_logic;
+ signal interrupt_rdy : std_logic := '0';
+
+ signal max_read : std_logic_vector(2 downto 0) := (others => '0');
+ signal max_write : std_logic_vector(2 downto 0) := (others => '0');
+
+ constant clk_period : time := 10 ns;
+
+ signal test_fail : std_logic := '0';
+
+ constant CMD_STATUS : std_logic_vector(1 downto 0) := "00";
+ constant CMD_SEND : std_logic_vector(1 downto 0) := "01";
+ constant CMD_RECV : std_logic_vector(1 downto 0) := "10";
+ constant CMD_MDIO : std_logic_vector(1 downto 0) := "11";
+
+ constant ADDR_31 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(31, 61));
+ constant ADDR_32 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(32, 61));
+ constant ADDR_4 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(4, 61));
+
+ constant LEN_3 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(3, 9));
+ constant LEN_2 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(2, 9));
+ constant LEN_1 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(1, 9));
+
+ constant BUFF_0 : std_logic_vector(3 downto 0) := std_logic_vector(to_unsigned(0, 4));
+ constant BUFF_2 : std_logic_vector(3 downto 0) := std_logic_vector(to_unsigned(2, 4));
+ constant BUFF_5 : std_logic_vector(3 downto 0) := std_logic_vector(to_unsigned(5, 4));
+
+ constant TAG_2 : std_logic_vector(4 downto 0) := std_logic_vector(to_unsigned(2, 5));
+ constant TAG_5 : std_logic_vector(4 downto 0) := std_logic_vector(to_unsigned(5, 5));
+
+ constant EMPTY : std_logic_vector(1 downto 0) := "00";
+ constant ADDR : std_logic_vector(1 downto 0) := "01";
+ constant DATA : std_logic_vector(1 downto 0) := "10";
+ constant FULL : std_logic_vector(1 downto 0) := "11";
+
+ constant DATA_A : std_logic_vector(63 downto 0) := x"123AAAAAAAAAAAAA";
+ constant DATA_B : std_logic_vector(63 downto 0) := x"123BBBBBBBBBBBBB";
+ constant DATA_C : std_logic_vector(63 downto 0) := x"123CCCCCCCCCCCCC";
+ constant DATA_D : std_logic_vector(63 downto 0) := x"123DDDDDDDDDDDDD";
+ constant DATA_E : std_logic_vector(63 downto 0) := x"123EEEEEEEEEEEEE";
+BEGIN
+
+ uut: engine PORT MAP (
+ clk => clk,
+ rd_buff => rd_buff,
+ rd_en => rd_en,
+ rd_data => rd_data,
+ rd_length => rd_length,
+ rd_valid => rd_valid,
+ wr_buff => wr_buff,
+ wr_en => wr_en,
+ wr_data => wr_data,
+ wr_done => wr_done,
+ wr_accept => wr_accept,
+ rx_read => rx_read,
+ rx_write => rx_write,
+ rx_complete => rx_complete,
+ rx_data => rx_data,
+ rx_address => rx_address,
+ rx_tag => rx_tag,
+ tx_read => tx_read,
+ tx_write => tx_write,
+ tx_complete => tx_complete,
+ tx_data => tx_data,
+ tx_address => tx_address,
+ tx_length => tx_length,
+ tx_tag => tx_tag,
+ tx_accept => tx_accept,
+ tx_done => tx_done,
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+ max_read => max_read,
+ max_write => max_write
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ wr_accept <= (others => '1');
+
+ wait for clk_period;
+
+ -- read status
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- send page: addr = 31, len = 3, data = ABC, buff = 2
+ -- expecting two reads:
+ -- first: addr = 31, len = 1, tag = 2
+ -- second: addr = 32, len = 2, tag = 2
+
+ rx_write <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_SEND;
+ rx_address(8 downto 5) <= BUFF_2;
+ rx_address(18 downto 10) <= LEN_3;
+ rx_data <= ADDR_31 & "000";
+
+ wait for clk_period * 3;
+
+ if tx_read /= '1' or
+ tx_address /= ADDR_31 or
+ tx_length /= LEN_1 or
+ tx_tag /= TAG_2 then
+ test_fail <= '1';
+ end if;
+
+ rx_write <= '0';
+ rx_address <= (others => '0');
+ rx_data <= (others => '0');
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_read /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- read status again
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' or
+ tx_data(2*4 + 1 downto 2*4 + 0) /= DATA or
+ tx_data(2*4 + 3 downto 2*4 + 2) /= EMPTY then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- answer the previous read with completions
+ -- data = A, tag = 2, len = 1
+ rx_complete <= '1';
+ rx_data <= DATA_A;
+ rx_tag <= TAG_2;
+
+ wait for clk_period;
+
+ -- expect wr_en (buff = 2, data = A)
+ if wr_buff /= BUFF_2 or
+ wr_en /= '1' or
+ wr_data /= DATA_A or
+ wr_done /= '0' or
+ tx_read /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_complete <= '0';
+ rx_data <= (others => '0');
+ rx_tag <= (others => '0');
+
+ wait for clk_period * 2;
+
+ -- expect new tx_read (tag 2, len 2, addr 32)
+ if wr_en /= '0' or
+ tx_read /= '1' or
+ tx_tag /= TAG_2 or
+ tx_length /= LEN_2 or
+ tx_address /= ADDR_32 then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_read /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ -- answer read with completions
+ -- data = B and C, tag = 2, len = 2
+ rx_complete <= '1';
+ rx_data <= DATA_B;
+ rx_tag <= TAG_2;
+
+ wait for clk_period;
+
+ -- expect wr_en (buff = 2, data = B) and no tx action
+ if wr_buff /= BUFF_2 or
+ wr_en /= '1' or
+ wr_data /= DATA_B or
+ wr_done /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_complete <= '1';
+ rx_data <= DATA_C;
+ rx_tag <= TAG_2;
+
+ wait for clk_period;
+
+ -- expect wr_en (buff = 2, data = C) and no tx action
+ if wr_buff /= BUFF_2 or
+ wr_en /= '1' or
+ wr_data /= DATA_C or
+ wr_done /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_complete <= '0';
+ rx_data <= (others => '0');
+ rx_tag <= (others => '0');
+
+ wait for clk_period;
+
+ -- expect wr_done and no tx action
+ if wr_done /= '1' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- buff will respond to wr_done with wr_accept = 0
+ wr_accept(2) <= '0';
+
+ wait for clk_period;
+
+ -- read status again
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' or
+ tx_data(2*4 + 1 downto 2*4 + 0) /= FULL or
+ tx_data(2*4 + 3 downto 2*4 + 2) /= EMPTY then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ wr_accept(2) <= '1';
+
+ wait for clk_period;
+
+ -- read status again, but this time buff must be EMPTY
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' or
+ tx_data(2*4 + 1 downto 2*4 + 0) /= EMPTY or
+ tx_data(2*4 + 3 downto 2*4 + 2) /= EMPTY then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ -- EMPTY buff doesn't result in interrupt, because status is just read
+ if tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- RECEIVE PACKET
+ -- the buff will say there is data to read (rd_valid)
+ -- interrupt will be send
+ -- status is read
+ -- addr will be gotten via rx_write
+ -- data will be send via tx_write
+ -- interrupt will be send
+
+ -- no reading and no tx actions
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- buff 5 becomes valid
+ rd_valid(5) <= '1';
+
+ wait for clk_period * 2;
+
+ -- expect interrupt
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '1' then
+ test_fail <= '1';
+ end if;
+
+ -- read status again
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+ interrupt_rdy <= '1';
+
+ wait for clk_period;
+
+ -- expect complete, no interrupt
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '1' or
+ interrupt /= '0' or
+ tx_data(5*4 + 1 downto 5*4 + 0) /= EMPTY or
+ tx_data(5*4 + 3 downto 5*4 + 2) /= FULL then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+ interrupt_rdy <= '0';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- no reading and no tx actions
+ if rd_en /= '0' or
+ rd_buff /= BUFF_0 or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- recv page: addr = 4, buff = 5
+ rx_write <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_RECV;
+ rx_address(8 downto 5) <= BUFF_5;
+ rx_data <= ADDR_4 & "000";
+
+ wait for clk_period;
+
+ -- no reading and no tx actions
+ if rd_en /= '0' or
+ rd_buff /= BUFF_0 or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_write <= '0';
+ rx_address <= (others => '0');
+ rx_data <= (others => '0');
+
+ wait for clk_period;
+
+ -- expect to read buff 5, but no tx actions yet
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- data = D and E, length = 2
+ rd_data <= DATA_D;
+ rd_length <= LEN_2;
+
+ wait for clk_period;
+
+ -- tx_write: data = D, addr = 4, length = 2
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_D or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- same
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_D or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ tx_accept <= '1';
+
+ wait for clk_period;
+
+ -- data D
+ if rd_en /= '1' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_D or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ rd_data <= DATA_E;
+
+ wait for clk_period;
+
+ -- data E
+ if rd_en /= '1' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_E or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ rd_valid(5) <= '0';
+ rd_data <= (others => '0');
+ rd_length <= (others => '0');
+ tx_accept <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- interrupt because writing is done
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '1' then
+ test_fail <= '1';
+ end if;
+
+ interrupt_rdy <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ interrupt_rdy <= '0';
+
+ wait for clk_period * 5;
+
+
+
+ -- ======================
+ -- LETS GO AGAIN !!!!!!!
+ -- ======================
+
+
+
+ -- read status
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- send page: addr = 31, len = 3, data = ABC, buff = 2
+ -- expecting two reads:
+ -- first: addr = 31, len = 1, tag = 2
+ -- second: addr = 32, len = 2, tag = 2
+
+ rx_write <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_SEND;
+ rx_address(8 downto 5) <= BUFF_2;
+ rx_address(18 downto 10) <= LEN_3;
+ rx_data <= ADDR_31 & "000";
+
+ wait for clk_period * 3;
+
+ if tx_read /= '1' or
+ tx_address /= ADDR_31 or
+ tx_length /= LEN_1 or
+ tx_tag /= TAG_2 then
+ test_fail <= '1';
+ end if;
+
+ rx_write <= '0';
+ rx_address <= (others => '0');
+ rx_data <= (others => '0');
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_read /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- read status again
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' or
+ tx_data(2*4 + 1 downto 2*4 + 0) /= DATA or
+ tx_data(2*4 + 3 downto 2*4 + 2) /= EMPTY then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- answer the previous read with completions
+ -- data = A, tag = 2, len = 1
+ rx_complete <= '1';
+ rx_data <= DATA_A;
+ rx_tag <= TAG_2;
+
+ wait for clk_period;
+
+ -- expect wr_en (buff = 2, data = A)
+ if wr_buff /= BUFF_2 or
+ wr_en /= '1' or
+ wr_data /= DATA_A or
+ wr_done /= '0' or
+ tx_read /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_complete <= '0';
+ rx_data <= (others => '0');
+ rx_tag <= (others => '0');
+
+ wait for clk_period * 2;
+
+ -- expect new tx_read (tag 2, len 2, addr 32)
+ if wr_en /= '0' or
+ tx_read /= '1' or
+ tx_tag /= TAG_2 or
+ tx_length /= LEN_2 or
+ tx_address /= ADDR_32 then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_read /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ -- answer read with completions
+ -- data = B and C, tag = 2, len = 2
+ rx_complete <= '1';
+ rx_data <= DATA_B;
+ rx_tag <= TAG_2;
+
+ wait for clk_period;
+
+ -- expect wr_en (buff = 2, data = B) and no tx action
+ if wr_buff /= BUFF_2 or
+ wr_en /= '1' or
+ wr_data /= DATA_B or
+ wr_done /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_complete <= '1';
+ rx_data <= DATA_C;
+ rx_tag <= TAG_2;
+
+ wait for clk_period;
+
+ -- expect wr_en (buff = 2, data = C) and no tx action
+ if wr_buff /= BUFF_2 or
+ wr_en /= '1' or
+ wr_data /= DATA_C or
+ wr_done /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_complete <= '0';
+ rx_data <= (others => '0');
+ rx_tag <= (others => '0');
+
+ wait for clk_period;
+
+ -- expect wr_done and no tx action
+ if wr_done /= '1' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- buff will respond to wr_done with wr_accept = 0
+ wr_accept(2) <= '0';
+
+ wait for clk_period;
+
+ -- read status again
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' or
+ tx_data(2*4 + 1 downto 2*4 + 0) /= FULL or
+ tx_data(2*4 + 3 downto 2*4 + 2) /= EMPTY then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ wr_accept(2) <= '1';
+
+ wait for clk_period;
+
+ -- read status again, but this time buff must be EMPTY
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+
+ wait for clk_period;
+
+ if tx_complete /= '1' or
+ tx_data(2*4 + 1 downto 2*4 + 0) /= EMPTY or
+ tx_data(2*4 + 3 downto 2*4 + 2) /= EMPTY then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ -- EMPTY buff doesn't result in interrupt, because status is just read
+ if tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- RECEIVE PACKET
+ -- the buff will say there is data to read (rd_valid)
+ -- interrupt will be send
+ -- status is read
+ -- addr will be gotten via rx_write
+ -- data will be send via tx_write
+ -- interrupt will be send
+
+ -- no reading and no tx actions
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- buff 5 becomes valid
+ rd_valid(5) <= '1';
+
+ wait for clk_period * 2;
+
+ -- expect interrupt
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '1' then
+ test_fail <= '1';
+ end if;
+
+ -- read status again
+ rx_read <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_STATUS;
+ interrupt_rdy <= '1';
+
+ wait for clk_period;
+
+ -- expect complete, no interrupt
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '1' or
+ interrupt /= '0' or
+ tx_data(5*4 + 1 downto 5*4 + 0) /= EMPTY or
+ tx_data(5*4 + 3 downto 5*4 + 2) /= FULL then
+ test_fail <= '1';
+ end if;
+
+ rx_read <= '0';
+ tx_done <= '1';
+ interrupt_rdy <= '0';
+
+ wait for clk_period;
+
+ if tx_complete /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- no reading and no tx actions
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- recv page: addr = 4, buff = 5
+ rx_write <= '1';
+ rx_address <= (others => '0');
+ rx_address(4 downto 3) <= CMD_RECV;
+ rx_address(8 downto 5) <= BUFF_5;
+ rx_data <= ADDR_4 & "000";
+
+ wait for clk_period;
+
+ -- no reading and no tx actions
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_write <= '0';
+ rx_address <= (others => '0');
+ rx_data <= (others => '0');
+
+ wait for clk_period;
+
+ -- expect to read buff 5, but no tx actions yet
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- data = D and E, length = 2
+ rd_data <= DATA_D;
+ rd_length <= LEN_2;
+
+ wait for clk_period;
+
+ -- tx_write: data = D, addr = 4, length = 2
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_D or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- same
+ if rd_en /= '0' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_D or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ tx_accept <= '1';
+
+ wait for clk_period;
+
+ -- data D
+ if rd_en /= '1' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_D or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ rd_data <= DATA_E;
+
+ wait for clk_period;
+
+ -- data E
+ if rd_en /= '1' or
+ rd_buff /= BUFF_5 or
+ tx_read /= '0' or
+ tx_write /= '1' or
+ tx_complete /= '0' or
+ interrupt /= '0' or
+ tx_data /= DATA_E or
+ tx_address /= ADDR_4 or
+ tx_length /= LEN_2 then
+ test_fail <= '1';
+ end if;
+
+ rd_valid(5) <= '0';
+ rd_data <= (others => '0');
+ rd_length <= (others => '0');
+ tx_accept <= '0';
+ tx_done <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_done <= '0';
+
+ wait for clk_period;
+
+ -- interrupt because writing is done
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '1' then
+ test_fail <= '1';
+ end if;
+
+ interrupt_rdy <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if rd_en /= '0' or
+ tx_read /= '0' or
+ tx_write /= '0' or
+ tx_complete /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ interrupt_rdy <= '0';
+
+ wait for clk_period * 5;
+
+
+
+
+
+
+
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/eth_buff_loop_test.vhd b/netfpga10g/tests/eth_buff_loop_test.vhd
new file mode 100644
index 0000000..b8c5902
--- /dev/null
+++ b/netfpga10g/tests/eth_buff_loop_test.vhd
@@ -0,0 +1,173 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY eth_buff_loop_test IS
+END eth_buff_loop_test;
+
+ARCHITECTURE behavior OF eth_buff_loop_test IS
+
+ signal eth_clk : std_logic := '0';
+ signal pcie_clk: std_logic := '0';
+
+ signal eth_rd_en : std_logic := '0';
+ signal eth_rd_data : std_logic_vector(63 downto 0);
+ signal eth_rd_length : std_logic_vector(8 downto 0);
+ signal eth_rd_valid : std_logic;
+
+ signal eth_wr_en : std_logic := '0';
+ signal eth_wr_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal eth_wr_done : std_logic := '0';
+ signal eth_wr_accept : std_logic;
+
+ signal pcie_rd_en : std_logic := '0';
+ signal pcie_rd_data : std_logic_vector(63 downto 0);
+ signal pcie_rd_length : std_logic_vector(8 downto 0);
+ signal pcie_rd_valid : std_logic;
+
+ signal pcie_wr_en : std_logic := '0';
+ signal pcie_wr_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal pcie_wr_done : std_logic := '0';
+ signal pcie_wr_accept : std_logic;
+
+ constant eth_clk_period : time := 7 ns;
+ constant pcie_clk_period : time := 10 ns;
+
+ signal xgmii_data : std_logic_vector(63 downto 0);
+ signal xgmii_control : std_logic_vector(7 downto 0);
+
+ signal test_fail : std_logic := '0';
+
+BEGIN
+
+ buff_tx : entity work.buff port map (
+ wr_clk => pcie_clk,
+ wr_en => pcie_wr_en,
+ wr_data => pcie_wr_data,
+ wr_done => pcie_wr_done,
+ wr_accept => pcie_wr_accept,
+ rd_clk => eth_clk,
+ rd_en => eth_rd_en,
+ rd_data => eth_rd_data,
+ rd_length => eth_rd_length,
+ rd_valid => eth_rd_valid
+ );
+
+ buff_rx : entity work.buff port map (
+ wr_clk => eth_clk,
+ wr_en => eth_wr_en,
+ wr_data => eth_wr_data,
+ wr_done => eth_wr_done,
+ wr_accept => eth_wr_accept,
+ rd_clk => pcie_clk,
+ rd_en => pcie_rd_en,
+ rd_data => pcie_rd_data,
+ rd_length => pcie_rd_length,
+ rd_valid => pcie_rd_valid
+ );
+
+ eth_rx: entity work.eth_rx port map(
+ clk => eth_clk,
+ wr_en => eth_wr_en,
+ wr_data => eth_wr_data,
+ wr_done => eth_wr_done,
+ wr_accept => eth_wr_accept,
+ xgmii_rxd => xgmii_data,
+ xgmii_rxc => xgmii_control
+ );
+
+ eth_tx: entity work.eth_tx port map (
+ clk => eth_clk,
+ rd_en => eth_rd_en,
+ rd_data => eth_rd_data,
+ rd_valid => eth_rd_valid,
+ xgmii_txd => xgmii_data,
+ xgmii_txc => xgmii_control
+ );
+
+ -- Clock process definitions
+ eth_clk_process : process
+ begin
+ eth_clk <= '0';
+ wait for eth_clk_period/2;
+ eth_clk <= '1';
+ wait for eth_clk_period/2;
+ end process;
+
+ pcie_clk_process :process
+ begin
+ pcie_clk <= '0';
+ wait for pcie_clk_period/2;
+ pcie_clk <= '1';
+ wait for pcie_clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ wait for pcie_clk_period;
+
+ if pcie_wr_accept /= '1' then
+ test_fail <= '1';
+ end if;
+
+ pcie_wr_en <= '1';
+ pcie_wr_data <= x"0123456789ABCDEF";
+
+ wait for pcie_clk_period;
+
+ pcie_wr_en <= '1';
+ pcie_wr_data <= x"AAAAAAAAAAAAAAAA";
+
+ wait for pcie_clk_period;
+
+ pcie_wr_en <= '0';
+ pcie_wr_data <= (others => '0');
+ pcie_wr_done <= '1';
+
+ wait for pcie_clk_period;
+
+ pcie_wr_done <= '0';
+
+ wait until pcie_rd_valid = '1';
+ wait for pcie_clk_period / 2;
+
+ if pcie_rd_data /= x"0123456789ABCDEF" or
+ pcie_rd_length /= "000000010" then
+ test_fail <= '1';
+ end if;
+
+ pcie_rd_en <= '1';
+
+ wait for pcie_clk_period;
+
+ if pcie_rd_data /= x"AAAAAAAAAAAAAAAA" then
+ test_fail <= '1';
+ end if;
+
+ pcie_rd_en <= '1';
+
+ wait for pcie_clk_period;
+
+ if pcie_rd_valid /= '0' or
+ pcie_rd_data /= x"0000000000000000" or
+ pcie_rd_length /= "000000000" then
+ test_fail <= '1';
+ end if;
+
+ pcie_rd_en <= '0';
+
+ wait for pcie_clk_period;
+
+ if pcie_rd_valid /= '0' or
+ pcie_rd_data /= x"0000000000000000" or
+ pcie_rd_length /= "000000000" then
+ test_fail <= '1';
+ end if;
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/eth_rx_test.vhd b/netfpga10g/tests/eth_rx_test.vhd
new file mode 100644
index 0000000..7497a97
--- /dev/null
+++ b/netfpga10g/tests/eth_rx_test.vhd
@@ -0,0 +1,225 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY eth_rx_test IS
+END eth_rx_test;
+
+ARCHITECTURE behavior OF eth_rx_test IS
+
+ COMPONENT eth_rx
+ PORT(
+ clk : IN std_logic;
+ wr_en : OUT std_logic;
+ wr_data : OUT std_logic_vector(63 downto 0);
+ wr_done : OUT std_logic;
+ wr_accept : IN std_logic;
+ xgmii_rxd : IN std_logic_vector(63 downto 0);
+ xgmii_rxc : IN std_logic_vector(7 downto 0)
+ );
+ END COMPONENT;
+
+ signal clk : std_logic := '0';
+
+ signal wr_en : std_logic;
+ signal wr_data : std_logic_vector(63 downto 0);
+ signal wr_done : std_logic;
+ signal wr_accept : std_logic := '0';
+
+ signal xgmii_rxd : std_logic_vector(63 downto 0) := (others => '0');
+ signal xgmii_rxc : std_logic_vector(7 downto 0) := (others => '0');
+
+ constant clk_period : time := 10 ns;
+
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERM : std_logic_vector(7 downto 0) := x"FD";
+ constant ERR : std_logic_vector(7 downto 0) := x"FE";
+
+ constant PRE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+
+ signal test_fail : std_logic := '0';
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: eth_rx PORT MAP (
+ clk => clk,
+ wr_en => wr_en,
+ wr_data => wr_data,
+ wr_done => wr_done,
+ wr_accept => wr_accept,
+ xgmii_rxd => xgmii_rxd,
+ xgmii_rxc => xgmii_rxc
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ xgmii_rxd <= IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE;
+ xgmii_rxc <= "00000000";
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= SFD & PRE & PRE & PRE & PRE & PRE & PRE & START;
+ xgmii_rxc <= "00000001";
+ wr_accept <= '1';
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= x"EFCDAB8967452301";
+ xgmii_rxc <= "00000000";
+
+ wait for clk_period;
+
+ if wr_en /= '1' or
+ wr_data /= x"0123456789ABCDEF" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & TERM;
+ xgmii_rxc <= "11111111";
+
+ wait for clk_period;
+
+ if wr_done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE;
+ xgmii_rxc <= "11111111";
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= SFD & PRE & PRE & PRE & PRE & PRE & PRE & START;
+ xgmii_rxc <= "00000001";
+ wr_accept <= '0';
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= x"EFCDAB8967452301";
+ xgmii_rxc <= "00000000";
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= SFD & PRE & PRE & PRE & PRE & PRE & PRE & START;
+ xgmii_rxc <= "00000001";
+ wr_accept <= '1';
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= x"ABCDABCDABCDABCD";
+ xgmii_rxc <= "00000000";
+
+ wait for clk_period;
+
+ if wr_en /= '1' or
+ wr_data /= x"CDABCDABCDABCDAB" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= IDLE & IDLE & IDLE & ERR & IDLE & IDLE & IDLE & IDLE;
+ xgmii_rxc <= "00010000";
+
+ wait for clk_period;
+
+ if wr_done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= PRE & PRE & PRE & START & IDLE & IDLE & IDLE & IDLE;
+ xgmii_rxc <= "00011111";
+ wr_accept <= '1';
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= x"67452311" & SFD & PRE & PRE & PRE;
+ xgmii_rxc <= "00000000";
+
+ wait for clk_period;
+
+ if wr_en /= '0' or
+ wr_data /= x"0000000000000000" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= IDLE & IDLE & IDLE & TERM & x"EFCDAB89";
+ xgmii_rxc <= "11110000";
+
+ wait for clk_period;
+
+ if wr_en /= '1' or
+ wr_data /= x"1123456789ABCDEF" or
+ wr_done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ xgmii_rxd <= IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE;
+ xgmii_rxc <= "11111111";
+
+ wait for clk_period;
+
+ if wr_done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/eth_tx_test.vhd b/netfpga10g/tests/eth_tx_test.vhd
new file mode 100644
index 0000000..0697b84
--- /dev/null
+++ b/netfpga10g/tests/eth_tx_test.vhd
@@ -0,0 +1,126 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY eth_tx_test IS
+END eth_tx_test;
+
+ARCHITECTURE behavior OF eth_tx_test IS
+
+ -- Component Declaration for the Unit Under Test (UUT)
+
+ COMPONENT eth_tx
+ PORT(
+ clk : IN std_logic;
+ rd_en : OUT std_logic;
+ rd_data : IN std_logic_vector(63 downto 0);
+ rd_valid : IN std_logic;
+ xgmii_txd : OUT std_logic_vector(63 downto 0);
+ xgmii_txc : OUT std_logic_vector(7 downto 0)
+ );
+ END COMPONENT;
+
+ signal clk : std_logic := '0';
+ signal rd_en : std_logic;
+ signal rd_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal rd_valid : std_logic := '0';
+
+ signal xgmii_txd : std_logic_vector(63 downto 0);
+ signal xgmii_txc : std_logic_vector(7 downto 0);
+
+ -- Clock period definitions
+ constant clk_period : time := 10 ns;
+
+ signal test_fail : std_logic := '0';
+
+ constant IDLE : std_logic_vector(7 downto 0) := x"07";
+ constant START : std_logic_vector(7 downto 0) := x"FB";
+ constant TERM : std_logic_vector(7 downto 0) := x"FD";
+
+ constant PRE : std_logic_vector(7 downto 0) := "01010101";
+ constant SFD : std_logic_vector(7 downto 0) := "11010101";
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: eth_tx PORT MAP (
+ clk => clk,
+ rd_en => rd_en,
+ rd_data => rd_data,
+ rd_valid => rd_valid,
+ xgmii_txd => xgmii_txd,
+ xgmii_txc => xgmii_txc
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ for i in 1 to 5 loop
+
+ if i = 1 or i = 2 then
+ wait for clk_period;
+
+ if rd_en /= '0' or
+ xgmii_txd /= IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE or
+ xgmii_txc /= "11111111" then
+ test_fail <= '1';
+ end if;
+ end if;
+
+ rd_valid <= '1';
+ rd_data <= x"0123456789ABCDEF";
+
+ wait for clk_period;
+
+ if rd_en /= '1' or
+ xgmii_txd /= SFD & PRE & PRE & PRE & PRE & PRE & PRE & START or
+ xgmii_txc /= "00000001" then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ if rd_en /= '1' or
+ xgmii_txd /= x"EFCDAB8967452301" or
+ xgmii_txc /= "00000000" then
+ test_fail <= '1';
+ end if;
+
+ rd_valid <= '1';
+ rd_data <= x"BBBBBBBBBBBBBBBB";
+
+ wait for clk_period;
+
+ if rd_en /= '1' or
+ xgmii_txd /= x"BBBBBBBBBBBBBBBB" or
+ xgmii_txc /= "00000000" then
+ test_fail <= '1';
+ end if;
+
+ rd_valid <= '0';
+ rd_data <= x"0000000000000000";
+
+ wait for clk_period;
+
+ if rd_en /= '0' or
+ xgmii_txd /= IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & IDLE & TERM or
+ xgmii_txc /= "11111111" then
+ test_fail <= '1';
+ end if;
+
+ end loop;
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/pcie_rx_test.vhd b/netfpga10g/tests/pcie_rx_test.vhd
new file mode 100644
index 0000000..4180b81
--- /dev/null
+++ b/netfpga10g/tests/pcie_rx_test.vhd
@@ -0,0 +1,322 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY pcie_rx_test IS
+END pcie_rx_test;
+
+ARCHITECTURE behavior OF pcie_rx_test IS
+
+ COMPONENT pcie_rx
+ PORT(
+ clk : IN std_logic;
+ frame : IN std_logic_vector(63 downto 0);
+ sof : IN std_logic;
+ eof : IN std_logic;
+ valid : IN std_logic;
+ read : OUT std_logic;
+ write : OUT std_logic;
+ complete : OUT std_logic;
+ data : OUT std_logic_vector(63 downto 0);
+ address : OUT std_logic_vector(63 downto 3);
+ tag : OUT std_logic_vector(4 downto 0);
+ remote : OUT std_logic_vector(15 downto 0);
+ bar0 : IN std_logic
+ );
+ END COMPONENT;
+
+
+ signal clk : std_logic := '0';
+
+ signal frame : std_logic_vector(63 downto 0) := (others => '0');
+ signal sof : std_logic := '0';
+ signal eof : std_logic := '0';
+ signal valid : std_logic := '0';
+
+ signal read : std_logic;
+ signal write : std_logic;
+ signal complete : std_logic;
+ signal data : std_logic_vector(63 downto 0);
+ signal address : std_logic_vector(63 downto 3);
+ signal tag : std_logic_vector(4 downto 0);
+ signal remote : std_logic_vector(15 downto 0);
+ signal bar0 : std_logic := '0';
+
+ constant clk_period : time := 10 ns;
+
+ constant ADDR_0 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(0, 61));
+ constant ADDR_1 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(1, 61));
+ constant ADDR_2 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(2, 61));
+
+ constant TAG_0 : std_logic_vector(4 downto 0) := "0" & x"0";
+ constant TAG_A : std_logic_vector(4 downto 0) := "0" & x"A";
+ constant TAG_B : std_logic_vector(4 downto 0) := "0" & x"B";
+
+ constant ID_0 : std_logic_vector(15 downto 0) := x"0000";
+ constant ID_A : std_logic_vector(15 downto 0) := x"AAAA";
+ constant ID_B : std_logic_vector(15 downto 0) := x"BBBB";
+
+ constant DATA_0 : std_logic_vector(63 downto 0) := x"0000000000000000";
+ constant DATA_A : std_logic_vector(63 downto 0) := x"AAAAAAAAAAAAAAAA";
+ constant DATA_B : std_logic_vector(63 downto 0) := x"BBBBBBBBBBBBBBBB";
+
+ signal test_fail : std_logic := '0';
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: pcie_rx PORT MAP (
+ clk => clk,
+ frame => frame,
+ sof => sof,
+ eof => eof,
+ valid => valid,
+ read => read,
+ write => write,
+ complete => complete,
+ data => data,
+ address => address,
+ tag => tag,
+ remote => remote,
+ bar0 => bar0
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ bar0 <= '1';
+
+ wait for clk_period;
+
+ -- expect nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_0 then
+ test_fail <= '1';
+ end if;
+
+ -- read: addr = 1, tag = A, remote = A
+ frame <= "0" & "00" & "00000" &
+ x"00" &
+ "000000" & "0000000010" &
+ ID_A & "000" & TAG_A & x"FF";
+ sof <= '1';
+ eof <= '0';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- remote = A
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= ADDR_1(31 downto 3) & "000" & x"00000000";
+ sof <= '0';
+ eof <= '1';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- read: addr = 1, tag = A, remote = A
+ if read /= '1' or
+ write /= '0' or
+ complete /= '0' or
+ data /= DATA_0 or
+ address /= ADDR_1 or
+ tag /= TAG_A or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ -- write: data = A, addr = 2
+ frame <= "0" & "10" & "00000" &
+ x"00" &
+ "000000" & "0000000010" &
+ ID_B & x"00" & x"FF";
+ sof <= '1';
+ eof <= '0';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- remote stays A
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= ADDR_2(31 downto 3) & "000" & DATA_A(63 downto 32);
+ sof <= '0';
+ eof <= '0';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- expect nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= DATA_A(31 downto 0) & x"00000000";
+ sof <= '0';
+ eof <= '1';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- write: data = A, addr = 2
+ if read /= '0' or
+ write /= '1' or
+ complete /= '0' or
+ data /= DATA_A or
+ address /= ADDR_2 or
+ tag /= TAG_0 or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= (others => '0');
+ sof <= '0';
+ eof <= '0';
+ valid <= '0';
+
+ wait for clk_period;
+
+ -- expect nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ -- complete: length = 2x32b, data = A + B, tag = B
+ frame <= "0" & "10" & "01010" &
+ x"00" &
+ "000000" & "0000000100" &
+ ID_B & x"0004";
+ sof <= '1';
+ eof <= '0';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- expect nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= ID_B & "000" & TAG_B & x"00" &
+ DATA_A(63 downto 32);
+ sof <= '0';
+ eof <= '0';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= DATA_A(31 downto 0) & DATA_B(63 downto 32);
+ sof <= '0';
+ eof <= '0';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- completion: data = A, tag = B
+ if read /= '0' or
+ write /= '0' or
+ complete /= '1' or
+ data /= DATA_A or
+ address /= ADDR_0 or
+ tag /= TAG_B or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= (others => '0');
+ sof <= '0';
+ eof <= '0';
+ valid <= '0';
+
+ wait for clk_period;
+
+ -- nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= DATA_B(31 downto 0) & x"01234567";
+ sof <= '0';
+ eof <= '1';
+ valid <= '1';
+
+ wait for clk_period;
+
+ -- completion: data = B, tag = B
+ if read /= '0' or
+ write /= '0' or
+ complete /= '1' or
+ data /= DATA_B or
+ address /= ADDR_0 or
+ tag /= TAG_B or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+ frame <= (others => '0');
+ sof <= '0';
+ eof <= '0';
+ valid <= '0';
+
+ wait for clk_period;
+
+ -- nothing
+ if read /= '0' or
+ write /= '0' or
+ complete /= '0' or
+ remote /= ID_A then
+ test_fail <= '1';
+ end if;
+
+
+
+
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/pcie_tx_test.vhd b/netfpga10g/tests/pcie_tx_test.vhd
new file mode 100644
index 0000000..4f9e091
--- /dev/null
+++ b/netfpga10g/tests/pcie_tx_test.vhd
@@ -0,0 +1,561 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY pcie_tx_test IS
+END pcie_tx_test;
+
+ARCHITECTURE behavior OF pcie_tx_test IS
+
+ COMPONENT pcie_tx
+ PORT(
+ clk : IN std_logic;
+ frame : OUT std_logic_vector(63 downto 0);
+ sof : OUT std_logic;
+ eof : OUT std_logic;
+ half : OUT std_logic;
+ valid : OUT std_logic;
+ ready : IN std_logic;
+ read : IN std_logic;
+ write : IN std_logic;
+ complete : IN std_logic;
+ data : IN std_logic_vector(63 downto 0);
+ address : IN std_logic_vector(63 downto 3);
+ length : IN std_logic_vector(8 downto 0);
+ tag : IN std_logic_vector(4 downto 0);
+ local : IN std_logic_vector(15 downto 0);
+ remote : IN std_logic_vector(15 downto 0);
+ accept : OUT std_logic;
+ done : OUT std_logic
+ );
+ END COMPONENT;
+
+
+ signal clk : std_logic := '0';
+
+ signal read : std_logic := '0';
+ signal write : std_logic := '0';
+ signal complete : std_logic := '0';
+ signal data : std_logic_vector(63 downto 0) := (others => '0');
+ signal address : std_logic_vector(63 downto 3) := (others => '0');
+ signal length : std_logic_vector(8 downto 0) := (others => '0');
+ signal tag : std_logic_vector(4 downto 0) := (others => '0');
+ signal local : std_logic_vector(15 downto 0) := (others => '0');
+ signal remote : std_logic_vector(15 downto 0) := (others => '0');
+ signal accept : std_logic;
+ signal done : std_logic;
+
+ signal frame : std_logic_vector(63 downto 0);
+ signal sof : std_logic;
+ signal eof : std_logic;
+ signal half : std_logic;
+ signal valid : std_logic;
+ signal ready : std_logic := '0';
+
+ constant clk_period : time := 10 ns;
+
+ signal test_fail : std_logic := '0';
+
+ constant FRAME_0 : std_logic_vector(63 downto 0) := (others => '0');
+
+ constant DATA_A : std_logic_vector(63 downto 0) := x"AAAAAAAAAAAAAAAA";
+ constant DATA_B : std_logic_vector(63 downto 0) := x"BBBBBBBBBBBBBBBB";
+ constant DATA_C : std_logic_vector(63 downto 0) := x"CCCCCCCCCCCCCCCC";
+
+ constant ADDR_1 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(1, 61));
+ constant ADDR_2 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(2, 61));
+ constant ADDR_3 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(3, 61));
+ constant ADDR_HIGH : std_logic_vector(63 downto 3) := x"100000000000000" & "0";
+
+ constant LEN_1 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(1, 9));
+ constant LEN_2 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(2, 9));
+ constant LEN_3 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(3, 9));
+
+ constant TAG_A : std_logic_vector(4 downto 0) := "0" & x"A";
+ constant TAG_B : std_logic_vector(4 downto 0) := "0" & x"B";
+ constant TAG_C : std_logic_vector(4 downto 0) := "0" & x"C";
+
+ constant ID_A : std_logic_vector(15 downto 0) := x"AAAA";
+ constant ID_B : std_logic_vector(15 downto 0) := x"BBBB";
+ constant ID_C : std_logic_vector(15 downto 0) := x"CCCC";
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: pcie_tx PORT MAP (
+ clk => clk,
+ frame => frame,
+ sof => sof,
+ eof => eof,
+ half => half,
+ valid => valid,
+ ready => ready,
+ read => read,
+ write => write,
+ complete => complete,
+ data => data,
+ address => address,
+ length => length,
+ tag => tag,
+ local => local,
+ remote => remote,
+ accept => accept,
+ done => done
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ variable expect : std_logic_vector(63 downto 0) := (others => '0');
+ begin
+ wait for clk_period;
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- read: addr = 1, len = 1, tag = A, local = A
+ read <= '1';
+ address <= ADDR_1;
+ length <= LEN_1;
+ tag <= TAG_A;
+ local <= ID_A;
+
+ wait for clk_period;
+
+ -- expect 32 bit read: sof valid
+ expect := "0" & "00" & "00000" & x"00" &
+ "000000" & "0000000010" &
+ ID_A & "000" & TAG_A & x"0F";
+
+ if frame /= expect or
+ sof /= '1' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period * 3 / 4;
+ ready <= '1';
+ wait for clk_period / 4;
+
+ -- same thing, because ready was 0 during clk
+ if frame /= expect or
+ sof /= '1' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period * 3 / 4;
+ ready <= '0';
+ wait for clk_period / 4;
+
+ -- read address: eof half valid
+ expect := ADDR_1(31 downto 3) & "000" & x"00000000";
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '1' or
+ half /= '1' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period * 3 / 4;
+ ready <= '1';
+ wait for clk_period / 4;
+
+ -- same thing, because ready was 0
+ -- but ready now, so done next time
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '1' or
+ half /= '1' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- done, so...
+ read <= '0';
+ write <= '0';
+ complete <= '0';
+ data <= (others => '0');
+ address <= (others => '0');
+ length <= (others => '0');
+ tag <= (others => '0');
+ local <= (others => '0');
+ remote <= (others => '0');
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- write: data = B+C, addr = 2, length = 2, local = B
+ write <= '1';
+ data <= DATA_B;
+ address <= ADDR_2;
+ length <= LEN_2;
+ local <= ID_B;
+
+ wait for clk_period;
+
+ -- write: sof valid
+ expect := "0" & "10" & "00000" & x"00" &
+ x"0004" &
+ ID_B & x"00" & x"FF";
+
+ if frame /= expect or
+ sof /= '1' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '1' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- write 32bit address + data: valid
+ expect := ADDR_2(31 downto 3) & "000" & DATA_B(63 downto 32);
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '1' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ data <= DATA_C;
+
+ wait for clk_period;
+
+ -- write data: valid
+ expect := DATA_B(31 downto 0) & DATA_C(63 downto 32);
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ data <= (others => '0');
+
+ wait for clk_period;
+
+ -- write half data: eof half valid done
+ expect := DATA_C(31 downto 0) & x"00000000";
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '1' or
+ half /= '1' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- done, so...
+ read <= '0';
+ write <= '0';
+ complete <= '0';
+ data <= (others => '0');
+ address <= (others => '0');
+ length <= (others => '0');
+ tag <= (others => '0');
+ local <= (others => '0');
+ remote <= (others => '0');
+
+ -- complete: data = C, addr = 3, tag = C, local = A, remote = B
+ complete <= '1';
+ data <= DATA_C;
+ address <= ADDR_3;
+ tag <= TAG_C;
+ local <= ID_A;
+ remote <= ID_B;
+
+ wait for clk_period;
+
+ -- expect completion 64bit
+ expect := "0" & "10" & "01010" & x"00" &
+ x"0002" & ID_A & x"0008";
+
+ if frame /= expect or
+ sof /= '1' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- compl header + data(higher 32b)
+ expect := ID_B & "000" & TAG_C & "0" & x"3" & "000" &
+ DATA_C(63 downto 32);
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- read of compl data: eof half valid done
+ expect := DATA_C(31 downto 0) & x"00000000";
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '1' or
+ half /= '1' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- done, so...
+ read <= '0';
+ write <= '0';
+ complete <= '0';
+ data <= (others => '0');
+ address <= (others => '0');
+ length <= (others => '0');
+ tag <= (others => '0');
+ local <= (others => '0');
+ remote <= (others => '0');
+
+ -- 64bit read: addr = HIGH, length = 3, tag = C, local = C
+ read <= '1';
+ address <= ADDR_HIGH;
+ length <= LEN_3;
+ tag <= TAG_C;
+ local <= ID_C;
+
+ wait for clk_period;
+
+ -- expect 64bit read
+ expect := "0" & "01" & "00000" & x"00" & x"0006" &
+ ID_C & "000" & TAG_C & x"FF";
+
+ if frame /= expect or
+ sof /= '1' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect 64bit address: eof valid done
+ expect := ADDR_HIGH & "000";
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '1' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- done, so...
+ read <= '0';
+ write <= '0';
+ complete <= '0';
+ data <= (others => '0');
+ address <= (others => '0');
+ length <= (others => '0');
+ tag <= (others => '0');
+ local <= (others => '0');
+ remote <= (others => '0');
+
+ -- 64bit write: addr = HIGH, length = 1, data = A, local = A
+ write <= '1';
+ address <= ADDR_HIGH;
+ length <= LEN_1;
+ data <= DATA_A;
+ local <= ID_A;
+
+ wait for clk_period;
+
+ -- expect 64bit write header; sof valid
+ expect := "0" & "11" & "00000" & x"00" & x"0002" &
+ ID_A & x"00" & x"0F";
+
+ if frame /= expect or
+ sof /= '1' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect addr HIGH: valid accept
+ expect := ADDR_HIGH & "000";
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '1' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect data A: eof valid done
+ expect := DATA_A;
+
+ if frame /= expect or
+ sof /= '0' or
+ eof /= '1' or
+ half /= '0' or
+ valid /= '1' or
+ accept /= '0' or
+ done /= '1' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- expect nothing
+ if frame /= FRAME_0 or
+ sof /= '0' or
+ eof /= '0' or
+ half /= '0' or
+ valid /= '0' or
+ accept /= '0' or
+ done /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- done, so...
+ read <= '0';
+ write <= '0';
+ complete <= '0';
+ data <= (others => '0');
+ address <= (others => '0');
+ length <= (others => '0');
+ tag <= (others => '0');
+ local <= (others => '0');
+ remote <= (others => '0');
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/queue_test.vhd b/netfpga10g/tests/queue_test.vhd
new file mode 100644
index 0000000..dc53ea0
--- /dev/null
+++ b/netfpga10g/tests/queue_test.vhd
@@ -0,0 +1,149 @@
+--------------------------------------------------------------------------------
+-- Company:
+-- Engineer:
+--
+-- Create Date: 17:42:12 02/23/2017
+-- Design Name:
+-- Module Name: /home/alexander/Code/raptor2/hw/tests/queue_test.vhd
+-- Project Name: raptor2
+-- Target Device:
+-- Tool versions:
+-- Description:
+--
+-- VHDL Test Bench Created by ISE for module: queue
+--
+-- Dependencies:
+--
+-- Revision:
+-- Revision 0.01 - File Created
+-- Additional Comments:
+--
+-- Notes:
+-- This testbench has been automatically generated using types std_logic and
+-- std_logic_vector for the ports of the unit under test. Xilinx recommends
+-- that these types always be used for the top-level I/O of a design in order
+-- to guarantee that the testbench will bind correctly to the post-implementation
+-- simulation model.
+--------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+
+-- Uncomment the following library declaration if using
+-- arithmetic functions with Signed or Unsigned values
+--USE ieee.numeric_std.ALL;
+
+ENTITY queue_test IS
+END queue_test;
+
+ARCHITECTURE behavior OF queue_test IS
+
+ -- Component Declaration for the Unit Under Test (UUT)
+
+ COMPONENT queue
+ PORT(
+ clk : IN std_logic;
+ reset : IN std_logic;
+ in_data : IN std_logic_vector(63 downto 0);
+ in_valid : in std_logic;
+ in_end : IN std_logic;
+ in_cancel : IN std_logic;
+ out_data : OUT std_logic_vector(63 downto 0);
+ out_valid : OUT std_logic;
+ out_next : IN std_logic
+ );
+ END COMPONENT;
+
+
+ --Inputs
+ signal clk : std_logic := '0';
+ signal reset : std_logic := '0';
+ signal in_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal in_valid : std_logic := '0';
+ signal in_end : std_logic := '0';
+ signal in_cancel : std_logic := '0';
+ signal out_next : std_logic := '0';
+
+ --Outputs
+ signal out_data : std_logic_vector(63 downto 0);
+ signal out_valid : std_logic;
+
+ -- Clock period definitions
+ constant clk_period : time := 10 ns;
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: queue PORT MAP (
+ clk => clk,
+ reset => reset,
+ in_data => in_data,
+ in_valid => in_valid,
+ in_end => in_end,
+ in_cancel => in_cancel,
+ out_data => out_data,
+ out_valid => out_valid,
+ out_next => out_next
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+ -- TESTS
+ process begin
+ reset <= '1';
+ wait for 5 ns;
+ reset <= '0';
+ wait;
+ end process;
+
+ process begin
+ wait for clk_period * 2;
+ in_data <= x"AAAAAAAAAAAAAAAA";
+ in_valid <= '1';
+ wait for clk_period;
+ in_data <= x"BBBBBBBBBBBBBBBB";
+ in_valid <= '0';
+ wait for clk_period;
+ in_data <= x"CCCCCCCCCCCCCCCC";
+ in_valid <= '1';
+ wait for clk_period;
+ in_data <= x"DDDDDDDDDDDDDDDD";
+ in_valid <= '1';
+ in_end <= '1';
+ wait for clk_period;
+ in_valid <= '0';
+ in_end <= '0';
+
+ wait for clk_period * 2;
+ in_data <= x"AAAAAAAAAAAAAAAA";
+ in_valid <= '1';
+ wait for clk_period;
+ in_data <= x"BBBBBBBBBBBBBBBB";
+ in_valid <= '1';
+ wait for clk_period;
+ in_data <= x"CCCCCCCCCCCCCCCC";
+ in_valid <= '1';
+ wait for clk_period;
+ in_data <= x"DDDDDDDDDDDDDDDD";
+ in_valid <= '1';
+ in_cancel <= '1';
+ wait for clk_period;
+ in_valid <= '0';
+ in_cancel <= '0';
+ end process;
+
+ process begin
+ wait for clk_period * 15;
+ out_next <= '1';
+ wait for clk_period * 2;
+ out_next <= '0';
+ wait for clk_period * 2;
+ out_next <= '1';
+ end process;
+END;
diff --git a/netfpga10g/tests/send_mux_test.vhd b/netfpga10g/tests/send_mux_test.vhd
new file mode 100644
index 0000000..f737ca9
--- /dev/null
+++ b/netfpga10g/tests/send_mux_test.vhd
@@ -0,0 +1,199 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY send_mux_test IS
+END send_mux_test;
+
+ARCHITECTURE behavior OF send_mux_test IS
+
+ COMPONENT send_mux
+ PORT(
+ wr_clk : IN std_logic;
+ wr_buff : IN std_logic_vector(3 downto 0);
+ wr_en : IN std_logic;
+ wr_data : IN std_logic_vector(63 downto 0);
+ wr_done : IN std_logic;
+ wr_accept : OUT std_logic_vector(15 downto 0);
+ rd_clk : IN std_logic;
+ rd_en : IN std_logic;
+ rd_data : OUT std_logic_vector(63 downto 0);
+ rd_valid : OUT std_logic
+ );
+ END COMPONENT;
+
+ signal wr_clk : std_logic := '0';
+ signal wr_buff : std_logic_vector(3 downto 0) := (others => '0');
+ signal wr_en : std_logic := '0';
+ signal wr_data : std_logic_vector(63 downto 0) := (others => '0');
+ signal wr_done : std_logic := '0';
+ signal wr_accept : std_logic_vector(15 downto 0);
+
+ signal rd_clk : std_logic := '0';
+ signal rd_en : std_logic := '0';
+ signal rd_data : std_logic_vector(63 downto 0);
+ signal rd_valid : std_logic;
+
+ constant wr_clk_period : time := 10 ns;
+ constant rd_clk_period : time := 7 ns;
+
+ constant DATA_A : std_logic_vector(63 downto 0) := x"AAAAAAAAAAAAAAAA";
+ constant DATA_B : std_logic_vector(63 downto 0) := x"BBBBBBBBBBBBBBBB";
+ constant DATA_C : std_logic_vector(63 downto 0) := x"CCCCCCCCCCCCCCCC";
+
+ constant BUFF_1 : std_logic_vector (3 downto 0) := x"1";
+ constant BUFF_2 : std_logic_vector (3 downto 0) := x"2";
+ constant BUFF_3 : std_logic_vector (3 downto 0) := x"3";
+
+ signal test_fail : std_logic := '0';
+ signal test_done : std_logic := '0';
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: send_mux PORT MAP (
+ wr_clk => wr_clk,
+ wr_buff => wr_buff,
+ wr_en => wr_en,
+ wr_data => wr_data,
+ wr_done => wr_done,
+ wr_accept => wr_accept,
+ rd_clk => rd_clk,
+ rd_en => rd_en,
+ rd_data => rd_data,
+ rd_valid => rd_valid
+ );
+
+ -- Clock process definitions
+ wr_clk_process :process
+ begin
+ wr_clk <= '0';
+ wait for wr_clk_period/2;
+ wr_clk <= '1';
+ wait for wr_clk_period/2;
+ end process;
+
+ rd_clk_process :process
+ begin
+ rd_clk <= '0';
+ wait for rd_clk_period/2;
+ rd_clk <= '1';
+ wait for rd_clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ begin
+ wait for wr_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFF" then
+ test_fail <= '1';
+ end if;
+
+ wr_buff <= BUFF_1;
+ wr_en <= '1';
+ wr_data <= DATA_A;
+ wr_done <= '0';
+
+ wait for wr_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFF" then
+ test_fail <= '1';
+ end if;
+
+ wr_buff <= BUFF_2;
+ wr_en <= '1';
+ wr_data <= DATA_A;
+ wr_done <= '0';
+
+ wait for wr_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFF" then
+ test_fail <= '1';
+ end if;
+
+ wr_buff <= BUFF_3;
+ wr_en <= '1';
+ wr_data <= DATA_A;
+ wr_done <= '0';
+
+ wait for wr_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFF" then
+ test_fail <= '1';
+ end if;
+
+ wr_buff <= BUFF_1;
+ wr_en <= '1';
+ wr_data <= DATA_B;
+ wr_done <= '0';
+
+ wait for wr_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFF" then
+ test_fail <= '1';
+ end if;
+
+ wr_buff <= BUFF_1;
+ wr_en <= '0';
+ wr_data <= (others => '0');
+ wr_done <= '1';
+
+ wait for wr_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFD" then
+ test_fail <= '1';
+ end if;
+
+ wr_buff <= BUFF_1;
+ wr_en <= '0';
+ wr_data <= (others => '0');
+ wr_done <= '0';
+
+ wait until rd_valid = '1';
+ wait for rd_clk_period / 2;
+
+ if rd_valid /= '1' or
+ rd_data /= DATA_A or
+ wr_accept /= x"FFFD" then
+ test_fail <= '1';
+ end if;
+
+ rd_en <= '1';
+
+ wait for rd_clk_period;
+
+ if rd_valid /= '1' or
+ rd_data /= DATA_B or
+ wr_accept /= x"FFFD" then
+ test_fail <= '1';
+ end if;
+
+ rd_en <= '1';
+
+ wait for rd_clk_period;
+
+ if rd_valid /= '0' or
+ wr_accept /= x"FFFD" then
+ test_fail <= '1';
+ end if;
+
+ rd_en <= '0';
+
+ wait until wr_accept(1) = '1';
+
+ report "done";
+ test_done <= '1';
+
+ wait;
+ end process;
+
+END;
diff --git a/netfpga10g/tests/system_loop_test.vhd b/netfpga10g/tests/system_loop_test.vhd
new file mode 100644
index 0000000..81a4f6e
--- /dev/null
+++ b/netfpga10g/tests/system_loop_test.vhd
@@ -0,0 +1,285 @@
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.numeric_std.ALL;
+
+ENTITY system_loop_test IS
+END system_loop_test;
+
+ARCHITECTURE behavior OF system_loop_test IS
+
+ COMPONENT system_loop
+ PORT(
+ clk : IN std_logic;
+
+ rx_frame : IN std_logic_vector(63 downto 0);
+ rx_sof : IN std_logic;
+ rx_eof : IN std_logic;
+ rx_valid : IN std_logic;
+ rx_bar0 : IN std_logic;
+
+ tx_frame : OUT std_logic_vector(63 downto 0);
+ tx_sof : OUT std_logic;
+ tx_eof : OUT std_logic;
+ tx_half : OUT std_logic;
+ tx_valid : OUT std_logic;
+ tx_ready : IN std_logic;
+
+ interrupt : OUT std_logic;
+ interrupt_rdy : IN std_logic;
+ max_read : IN std_logic_vector(2 downto 0);
+ max_write : IN std_logic_vector(2 downto 0);
+ local : IN std_logic_vector(15 downto 0)
+ );
+ END COMPONENT;
+
+ signal clk : std_logic := '0';
+
+ signal rx_frame : std_logic_vector(63 downto 0) := (others => '0');
+ signal rx_sof : std_logic := '0';
+ signal rx_eof : std_logic := '0';
+ signal rx_valid : std_logic := '0';
+ signal rx_bar0 : std_logic := '0';
+
+ signal tx_frame : std_logic_vector(63 downto 0);
+ signal tx_sof : std_logic;
+ signal tx_eof : std_logic;
+ signal tx_half : std_logic;
+ signal tx_valid : std_logic;
+ signal tx_ready : std_logic := '0';
+
+ signal interrupt : std_logic;
+ signal interrupt_rdy : std_logic := '0';
+
+ signal max_read : std_logic_vector(2 downto 0) := (others => '0');
+ signal max_write : std_logic_vector(2 downto 0) := (others => '0');
+ signal local : std_logic_vector(15 downto 0) := (others => '0');
+
+ constant clk_period : time := 10 ns;
+
+ signal test_fail : std_logic := '0';
+
+ constant LEN_1 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(1, 9));
+ constant LEN_2 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(2, 9));
+ constant LEN_3 : std_logic_vector(8 downto 0) := std_logic_vector(to_unsigned(3, 9));
+
+ constant TAG_1 : std_logic_vector(4 downto 0) := std_logic_vector(to_unsigned(1, 5));
+ constant TAG_2 : std_logic_vector(4 downto 0) := std_logic_vector(to_unsigned(2, 5));
+ constant TAG_3 : std_logic_vector(4 downto 0) := std_logic_vector(to_unsigned(3, 5));
+
+ constant ADDR_1 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(1, 61));
+ constant ADDR_2 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(2, 61));
+ constant ADDR_3 : std_logic_vector(63 downto 3) := std_logic_vector(to_unsigned(3, 61));
+
+ constant DATA_A : std_logic_vector(63 downto 0) := x"AAAAAAAAAAAAAAAA";
+ constant DATA_B : std_logic_vector(63 downto 0) := x"BBBBBBBBBBBBBBBB";
+ constant DATA_C : std_logic_vector(63 downto 0) := x"CCCCCCCCCCCCCCCC";
+
+ constant ID_A : std_logic_vector(15 downto 0) := x"AAAA";
+ constant ID_B : std_logic_vector(15 downto 0) := x"BBBB";
+ constant ID_C : std_logic_vector(15 downto 0) := x"CCCC";
+
+ constant BUFF_1 : std_logic_vector(3 downto 0) := x"1";
+ constant BUFF_2 : std_logic_vector(3 downto 0) := x"2";
+ constant BUFF_3 : std_logic_vector(3 downto 0) := x"3";
+
+ constant CMD_STATUS : std_logic_vector(1 downto 0) := "00";
+ constant CMD_SEND : std_logic_vector(1 downto 0) := "01";
+ constant CMD_RECV : std_logic_vector(1 downto 0) := "10";
+ constant CMD_MDIO : std_logic_vector(1 downto 0) := "11";
+
+ constant FRAME_0 : std_logic_vector(63 downto 0) := (others => '0');
+
+BEGIN
+
+ -- Instantiate the Unit Under Test (UUT)
+ uut: system_loop PORT MAP (
+ clk => clk,
+ rx_frame => rx_frame,
+ rx_sof => rx_sof,
+ rx_eof => rx_eof,
+ rx_valid => rx_valid,
+ rx_bar0 => rx_bar0,
+ tx_frame => tx_frame,
+ tx_sof => tx_sof,
+ tx_eof => tx_eof,
+ tx_half => tx_half,
+ tx_valid => tx_valid,
+ tx_ready => tx_ready,
+ interrupt => interrupt,
+ interrupt_rdy => interrupt_rdy,
+ max_read => max_read,
+ max_write => max_write,
+ local => local
+ );
+
+ -- Clock process definitions
+ clk_process :process
+ begin
+ clk <= '0';
+ wait for clk_period/2;
+ clk <= '1';
+ wait for clk_period/2;
+ end process;
+
+
+ -- Stimulus process
+ stim_proc: process
+ variable bar_addr : std_logic_vector(31 downto 0);
+ variable bar_data : std_logic_vector(63 downto 0);
+ variable expect : std_logic_vector(63 downto 0);
+ variable remote : std_logic_vector(15 downto 0);
+ begin
+ -- local = A
+ -- remote = B
+ local <= ID_A;
+ remote := ID_B;
+
+ -- always bar0
+ rx_bar0 <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if tx_frame /= FRAME_0 or
+ tx_sof /= '0' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- rx_write of 64 bits to bar
+ rx_frame <= "0" & "10" & "00000" & x"00" & x"0002" &
+ remote & x"00" & x"0F";
+ rx_sof <= '1';
+ rx_eof <= '0';
+ rx_valid <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if tx_frame /= FRAME_0 or
+ tx_sof /= '0' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ -- rx_write:
+ -- bar_addr: cmd = SEND, buff = 2, len = 2
+ -- bar_data: addr = 2
+ bar_addr := (others => '0');
+ bar_addr(4 downto 3) := CMD_SEND;
+ bar_addr(8 downto 5) := BUFF_2;
+ bar_addr(18 downto 10) := LEN_2;
+ bar_data := ADDR_2 & "000";
+
+ rx_frame <= bar_addr & bar_data(63 downto 32);
+ rx_sof <= '0';
+ rx_eof <= '0';
+ rx_valid <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if tx_frame /= FRAME_0 or
+ tx_sof /= '0' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_frame <= bar_data(31 downto 0) & x"00000000";
+ rx_sof <= '0';
+ rx_eof <= '1';
+ rx_valid <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if tx_frame /= FRAME_0 or
+ tx_sof /= '0' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ rx_frame <= (others => '0');
+ rx_sof <= '0';
+ rx_eof <= '0';
+ rx_valid <= '0';
+
+ wait for clk_period;
+
+ -- nothing
+ if tx_frame /= FRAME_0 or
+ tx_sof /= '0' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ wait for clk_period;
+
+ -- tx_read: addr = 2, len = 2, tag = 2
+ expect := "0" & "00" & "00000" & x"00" & "000000" & LEN_2 & "0" &
+ local & "000" & TAG_2 & x"FF";
+
+ if tx_frame /= expect or
+ tx_sof /= '1' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '1' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_ready <= '1';
+
+ wait for clk_period;
+
+ expect := ADDR_2(31 downto 3) & "000" & x"00000000";
+
+ if tx_frame /= expect or
+ tx_sof /= '0' or
+ tx_eof /= '1' or
+ tx_half /= '1' or
+ tx_valid /= '1' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_ready <= '1';
+
+ wait for clk_period;
+
+ -- nothing
+ if tx_frame /= FRAME_0 or
+ tx_sof /= '0' or
+ tx_eof /= '0' or
+ tx_half /= '0' or
+ tx_valid /= '0' or
+ interrupt /= '0' then
+ test_fail <= '1';
+ end if;
+
+ tx_ready <= '0';
+
+
+
+
+
+ wait;
+ end process;
+
+END;