From 3253164fec7d70892a00a3e54963dc1cfc88f730 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 3 Oct 2020 15:37:37 -0700 Subject: [PATCH] Add IPROG for ExaNIC X25 --- fpga/mqnic/ExaNIC_X25/fpga_10g/boot.xdc | 4 + fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/Makefile | 1 + fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v | 116 ++++++++++++++++++ .../mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v | 11 ++ .../ExaNIC_X25/fpga_10g/tb/test_fpga_core.py | 2 + .../ExaNIC_X25/fpga_10g/tb/test_fpga_core.v | 3 + 6 files changed, 137 insertions(+) create mode 100644 fpga/mqnic/ExaNIC_X25/fpga_10g/boot.xdc diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/boot.xdc b/fpga/mqnic/ExaNIC_X25/fpga_10g/boot.xdc new file mode 100644 index 000000000..5fb323e94 --- /dev/null +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/boot.xdc @@ -0,0 +1,4 @@ +# Timing constraints for FPGA boot logic + +set_property ASYNC_REG TRUE [get_cells "fpga_boot_sync_reg_0_reg fpga_boot_sync_reg_1_reg"] +set_false_path -to [get_pins "fpga_boot_sync_reg_0_reg/D"] diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/Makefile b/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/Makefile index a791ed99c..9f874db8a 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/Makefile +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/Makefile @@ -72,6 +72,7 @@ SYN_FILES += lib/pcie/rtl/pulse_merge.v # XDC files XDC_FILES = fpga.xdc +XDC_FILES += boot.xdc XDC_FILES += lib/axis/syn/axis_async_fifo.tcl XDC_FILES += lib/axis/syn/sync_reset.tcl XDC_FILES += lib/eth/syn/ptp_clock_cdc.tcl diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v index 2357ceed2..8a70edab6 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v @@ -276,6 +276,121 @@ flash_sync_signal_inst ( .out(flash_dq_i_int) ); +// FPGA boot +wire fpga_boot; + +reg fpga_boot_sync_reg_0 = 1'b0; +reg fpga_boot_sync_reg_1 = 1'b0; +reg fpga_boot_sync_reg_2 = 1'b0; + +wire icap_avail; +reg [2:0] icap_state = 0; +reg icap_csib_reg = 1'b1; +reg icap_rdwrb_reg = 1'b0; +reg [31:0] icap_di_reg = 32'hffffffff; + +wire [31:0] icap_di_rev; + +assign icap_di_rev[ 7] = icap_di_reg[ 0]; +assign icap_di_rev[ 6] = icap_di_reg[ 1]; +assign icap_di_rev[ 5] = icap_di_reg[ 2]; +assign icap_di_rev[ 4] = icap_di_reg[ 3]; +assign icap_di_rev[ 3] = icap_di_reg[ 4]; +assign icap_di_rev[ 2] = icap_di_reg[ 5]; +assign icap_di_rev[ 1] = icap_di_reg[ 6]; +assign icap_di_rev[ 0] = icap_di_reg[ 7]; + +assign icap_di_rev[15] = icap_di_reg[ 8]; +assign icap_di_rev[14] = icap_di_reg[ 9]; +assign icap_di_rev[13] = icap_di_reg[10]; +assign icap_di_rev[12] = icap_di_reg[11]; +assign icap_di_rev[11] = icap_di_reg[12]; +assign icap_di_rev[10] = icap_di_reg[13]; +assign icap_di_rev[ 9] = icap_di_reg[14]; +assign icap_di_rev[ 8] = icap_di_reg[15]; + +assign icap_di_rev[23] = icap_di_reg[16]; +assign icap_di_rev[22] = icap_di_reg[17]; +assign icap_di_rev[21] = icap_di_reg[18]; +assign icap_di_rev[20] = icap_di_reg[19]; +assign icap_di_rev[19] = icap_di_reg[20]; +assign icap_di_rev[18] = icap_di_reg[21]; +assign icap_di_rev[17] = icap_di_reg[22]; +assign icap_di_rev[16] = icap_di_reg[23]; + +assign icap_di_rev[31] = icap_di_reg[24]; +assign icap_di_rev[30] = icap_di_reg[25]; +assign icap_di_rev[29] = icap_di_reg[26]; +assign icap_di_rev[28] = icap_di_reg[27]; +assign icap_di_rev[27] = icap_di_reg[28]; +assign icap_di_rev[26] = icap_di_reg[29]; +assign icap_di_rev[25] = icap_di_reg[30]; +assign icap_di_rev[24] = icap_di_reg[31]; + +always @(posedge clk_125mhz_int) begin + case (icap_state) + 0: begin + icap_state <= 0; + icap_csib_reg <= 1'b1; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hffffffff; // dummy word + + if (fpga_boot_sync_reg_2 && icap_avail) begin + icap_state <= 1; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hffffffff; // dummy word + end + end + 1: begin + icap_state <= 2; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'hAA995566; // sync word + end + 2: begin + icap_state <= 3; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h20000000; // type 1 noop + end + 3: begin + icap_state <= 4; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h30008001; // write 1 word to CMD + end + 4: begin + icap_state <= 5; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h0000000F; // IPROG + end + 5: begin + icap_state <= 0; + icap_csib_reg <= 1'b0; + icap_rdwrb_reg <= 1'b0; + icap_di_reg <= 32'h20000000; // type 1 noop + end + endcase + + fpga_boot_sync_reg_0 <= fpga_boot; + fpga_boot_sync_reg_1 <= fpga_boot_sync_reg_0; + fpga_boot_sync_reg_2 <= fpga_boot_sync_reg_1; +end + +ICAPE3 +icape3_inst ( + .AVAIL(icap_avail), + .CLK(clk_125mhz_int), + .CSIB(icap_csib_reg), + .I(icap_di_rev), + .O(), + .PRDONE(), + .PRERROR(), + .RDWRB(icap_rdwrb_reg) +); + // PCIe wire pcie_sys_clk; wire pcie_sys_clk_gt; @@ -1003,6 +1118,7 @@ core_inst ( /* * BPI flash */ + .fpga_boot(fpga_boot), .flash_dq_i(flash_dq_i_int), .flash_dq_o(flash_dq_o_int), .flash_dq_oe(flash_dq_oe_int), diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v index 46f4be4d4..d9762efea 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v @@ -198,6 +198,7 @@ module fpga_core # /* * BPI Flash */ + output wire fpga_boot, input wire [15:0] flash_dq_i, output wire [15:0] flash_dq_o, output wire flash_dq_oe, @@ -435,6 +436,8 @@ reg sfp_i2c_sda_o_reg = 1'b1; reg eeprom_i2c_scl_o_reg = 1'b1; reg eeprom_i2c_sda_o_reg = 1'b1; +reg fpga_boot_reg = 1'b0; + reg [15:0] flash_dq_o_reg = 16'd0; reg flash_dq_oe_reg = 1'b0; reg [22:0] flash_addr_reg = 23'd0; @@ -493,6 +496,8 @@ assign eeprom_i2c_scl_t = eeprom_i2c_scl_o_reg; assign eeprom_i2c_sda_o = eeprom_i2c_sda_o_reg; assign eeprom_i2c_sda_t = eeprom_i2c_sda_o_reg; +assign fpga_boot = fpga_boot_reg; + assign flash_dq_o = flash_dq_o_reg; assign flash_dq_oe = flash_dq_oe_reg; assign flash_addr = flash_addr_reg; @@ -529,6 +534,10 @@ always @(posedge clk_250mhz) begin axil_csr_bvalid_reg <= 1'b1; case ({axil_csr_awaddr[15:2], 2'b00}) + 16'h0040: begin + // FPGA ID + fpga_boot_reg <= axil_csr_wdata == 32'hFEE1DEAD; + end // GPIO 16'h0110: begin // GPIO I2C 0 @@ -772,6 +781,8 @@ always @(posedge clk_250mhz) begin eeprom_i2c_scl_o_reg <= 1'b1; eeprom_i2c_sda_o_reg <= 1'b1; + fpga_boot_reg <= 1'b0; + flash_dq_o_reg <= 16'd0; flash_dq_oe_reg <= 1'b0; flash_addr_reg <= 23'd0; diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py b/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py index 952afb17a..9e19e10d8 100755 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.py @@ -253,6 +253,7 @@ def bench(): eeprom_i2c_scl_t = Signal(bool(1)) eeprom_i2c_sda_o = Signal(bool(1)) eeprom_i2c_sda_t = Signal(bool(1)) + fpga_boot = Signal(bool(0)) flash_dq_o = Signal(intbv(0)[16:]) flash_dq_oe = Signal(bool(0)) flash_addr = Signal(intbv(0)[23:]) @@ -601,6 +602,7 @@ def bench(): eeprom_i2c_sda_i=eeprom_i2c_sda_i, eeprom_i2c_sda_o=eeprom_i2c_sda_o, eeprom_i2c_sda_t=eeprom_i2c_sda_t, + fpga_boot=fpga_boot, flash_dq_i=flash_dq_i, flash_dq_o=flash_dq_o, flash_dq_oe=flash_dq_oe, diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v b/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v index 7854734a8..cc1d56e2f 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/test_fpga_core.v @@ -167,6 +167,7 @@ wire eeprom_i2c_scl_o; wire eeprom_i2c_scl_t; wire eeprom_i2c_sda_o; wire eeprom_i2c_sda_t; +wire fpga_boot; wire [15:0] flash_dq_o; wire flash_dq_oe; wire [22:0] flash_addr; @@ -292,6 +293,7 @@ initial begin eeprom_i2c_scl_t, eeprom_i2c_sda_o, eeprom_i2c_sda_t, + fpga_boot, flash_dq_o, flash_dq_oe, flash_addr, @@ -428,6 +430,7 @@ UUT ( .eeprom_i2c_sda_i(eeprom_i2c_sda_i), .eeprom_i2c_sda_o(eeprom_i2c_sda_o), .eeprom_i2c_sda_t(eeprom_i2c_sda_t), + .fpga_boot(fpga_boot), .flash_dq_i(flash_dq_i), .flash_dq_o(flash_dq_o), .flash_dq_oe(flash_dq_oe),