diff options
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; |