1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Add QSPI flash access and IPROG for Alveo

This commit is contained in:
Alex Forencich 2020-09-29 21:12:05 -07:00
parent 9c25a4523e
commit 9dbac6d446
48 changed files with 2048 additions and 76 deletions

View File

@ -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"]

View File

@ -54,6 +54,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

View File

@ -274,6 +274,24 @@ sync_signal_inst (
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
// startupe3 instance
wire cfgmclk;
@ -281,19 +299,19 @@ STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(cfgmclk),
.DI(),
.DO(4'd0),
.DTS(1'b1),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(1'b0),
.FCSBTS(1'b1),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(1'b0),
.USRCCLKTS(1'b1),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
@ -304,6 +322,121 @@ cfgmclk_bufg_inst (
.O(cfgmclk_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)
);
// configure SI5335 clock generators
reg qsfp_refclk_reset_reg = 1'b1;
reg sys_reset_reg = 1'b1;
@ -1391,7 +1524,17 @@ core_inst (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode)
.qsfp1_lpmode(qsfp1_lpmode),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -206,7 +206,17 @@ module fpga_core #
output wire qsfp1_resetl,
input wire qsfp1_modprsl,
input wire qsfp1_intl,
output wire qsfp1_lpmode
output wire qsfp1_lpmode,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -424,6 +434,13 @@ reg qsfp1_lpmode_reg = 1'b0;
reg i2c_scl_o_reg = 1'b1;
reg i2c_sda_o_reg = 1'b1;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -461,6 +478,13 @@ assign i2c_scl_t = i2c_scl_o_reg;
assign i2c_sda_o = i2c_sda_o_reg;
assign i2c_sda_t = i2c_sda_o_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -483,6 +507,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
@ -504,6 +532,20 @@ always @(posedge clk_250mhz) begin
qsfp1_lpmode_reg <= axil_csr_wdata[13];
end
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -566,6 +608,15 @@ always @(posedge clk_250mhz) begin
axil_csr_rdata_reg[12] <= qsfp1_reset_reg;
axil_csr_rdata_reg[13] <= qsfp1_lpmode_reg;
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -611,6 +662,13 @@ always @(posedge clk_250mhz) begin
i2c_scl_o_reg <= 1'b1;
i2c_sda_o_reg <= 1'b1;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -197,6 +197,7 @@ def bench():
qsfp1_rx_axis_tuser = Signal(bool(0))
qsfp1_modprsl = Signal(bool(1))
qsfp1_intl = Signal(bool(1))
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
led = Signal(intbv(0)[3:])
@ -251,6 +252,11 @@ def bench():
qsfp1_modsell = Signal(bool(0))
qsfp1_resetl = Signal(bool(0))
qsfp1_lpmode = Signal(bool(0))
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp0_source = axis_ep.AXIStreamSource()
@ -651,7 +657,13 @@ def bench():
qsfp1_modsell=qsfp1_modsell,
qsfp1_resetl=qsfp1_resetl,
qsfp1_intl=qsfp1_intl,
qsfp1_lpmode=qsfp1_lpmode
qsfp1_lpmode=qsfp1_lpmode,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -120,6 +120,7 @@ reg qsfp1_rx_axis_tlast = 0;
reg qsfp1_rx_axis_tuser = 0;
reg qsfp1_modprsl = 1;
reg qsfp1_intl = 1;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire [2:0] led;
@ -174,6 +175,11 @@ wire qsfp1_tx_axis_tuser;
wire qsfp1_modsell;
wire qsfp1_resetl;
wire qsfp1_lpmode;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -241,7 +247,8 @@ initial begin
qsfp1_rx_axis_tlast,
qsfp1_rx_axis_tuser,
qsfp1_modprsl,
qsfp1_intl
qsfp1_intl,
qspi_dq_i
);
$to_myhdl(
led,
@ -295,7 +302,12 @@ initial begin
qsfp1_tx_axis_tuser,
qsfp1_modsell,
qsfp1_resetl,
qsfp1_lpmode
qsfp1_lpmode,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -430,7 +442,13 @@ UUT (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode_int)
.qsfp1_lpmode(qsfp1_lpmode_int),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -70,6 +70,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

View File

@ -271,6 +271,24 @@ sync_signal_inst (
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
// startupe3 instance
wire cfgmclk;
@ -278,19 +296,19 @@ STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(cfgmclk),
.DI(),
.DO(4'd0),
.DTS(1'b1),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(1'b0),
.FCSBTS(1'b1),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(1'b0),
.USRCCLKTS(1'b1),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
@ -301,6 +319,121 @@ cfgmclk_bufg_inst (
.O(cfgmclk_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)
);
// configure SI5335 clock generators
reg qsfp_refclk_reset_reg = 1'b1;
reg sys_reset_reg = 1'b1;
@ -1443,7 +1576,17 @@ core_inst (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode)
.qsfp1_lpmode(qsfp1_lpmode),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -256,7 +256,17 @@ module fpga_core #
output wire qsfp1_resetl,
input wire qsfp1_modprsl,
input wire qsfp1_intl,
output wire qsfp1_lpmode
output wire qsfp1_lpmode,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -494,6 +504,13 @@ reg qsfp1_lpmode_reg = 1'b0;
reg i2c_scl_o_reg = 1'b1;
reg i2c_sda_o_reg = 1'b1;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -531,6 +548,13 @@ assign i2c_scl_t = i2c_scl_o_reg;
assign i2c_sda_o = i2c_sda_o_reg;
assign i2c_sda_t = i2c_sda_o_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -553,6 +577,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
@ -574,6 +602,20 @@ always @(posedge clk_250mhz) begin
qsfp1_lpmode_reg <= axil_csr_wdata[13];
end
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -636,6 +678,15 @@ always @(posedge clk_250mhz) begin
axil_csr_rdata_reg[12] <= qsfp1_reset_reg;
axil_csr_rdata_reg[13] <= qsfp1_lpmode_reg;
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -681,6 +732,13 @@ always @(posedge clk_250mhz) begin
i2c_scl_o_reg <= 1'b1;
i2c_sda_o_reg <= 1'b1;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -233,6 +233,7 @@ def bench():
qsfp1_rxc_4 = Signal(intbv(0)[8:])
qsfp1_modprsl = Signal(bool(1))
qsfp1_intl = Signal(bool(1))
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
led = Signal(intbv(0)[3:])
@ -293,6 +294,11 @@ def bench():
qsfp1_modsell = Signal(bool(0))
qsfp1_resetl = Signal(bool(0))
qsfp1_lpmode = Signal(bool(0))
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp0_1_source = xgmii_ep.XGMIISource()
@ -713,7 +719,13 @@ def bench():
qsfp1_modsell=qsfp1_modsell,
qsfp1_resetl=qsfp1_resetl,
qsfp1_intl=qsfp1_intl,
qsfp1_lpmode=qsfp1_lpmode
qsfp1_lpmode=qsfp1_lpmode,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -146,6 +146,7 @@ reg [63:0] qsfp1_rxd_4 = 0;
reg [7:0] qsfp1_rxc_4 = 0;
reg qsfp1_modprsl = 1;
reg qsfp1_intl = 1;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire [2:0] led;
@ -206,6 +207,11 @@ wire [7:0] qsfp1_txc_4;
wire qsfp1_modsell;
wire qsfp1_resetl;
wire qsfp1_lpmode;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -301,7 +307,8 @@ initial begin
qsfp1_rxd_4,
qsfp1_rxc_4,
qsfp1_modprsl,
qsfp1_intl
qsfp1_intl,
qspi_dq_i
);
$to_myhdl(
led,
@ -361,7 +368,12 @@ initial begin
qsfp1_txc_4,
qsfp1_modsell,
qsfp1_resetl,
qsfp1_lpmode
qsfp1_lpmode,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -528,7 +540,13 @@ UUT (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode_int)
.qsfp1_lpmode(qsfp1_lpmode_int),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -54,6 +54,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

View File

@ -274,6 +274,24 @@ sync_signal_inst (
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
// startupe3 instance
wire cfgmclk;
@ -281,19 +299,19 @@ STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(cfgmclk),
.DI(),
.DO(4'd0),
.DTS(1'b1),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(1'b0),
.FCSBTS(1'b1),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(1'b0),
.USRCCLKTS(1'b1),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
@ -304,6 +322,121 @@ cfgmclk_bufg_inst (
.O(cfgmclk_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)
);
// configure SI5335 clock generators
reg qsfp_refclk_reset_reg = 1'b1;
reg sys_reset_reg = 1'b1;
@ -1391,7 +1524,17 @@ core_inst (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode)
.qsfp1_lpmode(qsfp1_lpmode),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -206,7 +206,17 @@ module fpga_core #
output wire qsfp1_resetl,
input wire qsfp1_modprsl,
input wire qsfp1_intl,
output wire qsfp1_lpmode
output wire qsfp1_lpmode,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -424,6 +434,13 @@ reg qsfp1_lpmode_reg = 1'b0;
reg i2c_scl_o_reg = 1'b1;
reg i2c_sda_o_reg = 1'b1;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -461,6 +478,13 @@ assign i2c_scl_t = i2c_scl_o_reg;
assign i2c_sda_o = i2c_sda_o_reg;
assign i2c_sda_t = i2c_sda_o_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -483,6 +507,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
@ -504,6 +532,20 @@ always @(posedge clk_250mhz) begin
qsfp1_lpmode_reg <= axil_csr_wdata[13];
end
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -566,6 +608,15 @@ always @(posedge clk_250mhz) begin
axil_csr_rdata_reg[12] <= qsfp1_reset_reg;
axil_csr_rdata_reg[13] <= qsfp1_lpmode_reg;
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -611,6 +662,13 @@ always @(posedge clk_250mhz) begin
i2c_scl_o_reg <= 1'b1;
i2c_sda_o_reg <= 1'b1;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -197,6 +197,7 @@ def bench():
qsfp1_rx_axis_tuser = Signal(bool(0))
qsfp1_modprsl = Signal(bool(1))
qsfp1_intl = Signal(bool(1))
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
led = Signal(intbv(0)[3:])
@ -251,6 +252,11 @@ def bench():
qsfp1_modsell = Signal(bool(0))
qsfp1_resetl = Signal(bool(0))
qsfp1_lpmode = Signal(bool(0))
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp0_source = axis_ep.AXIStreamSource()
@ -651,7 +657,13 @@ def bench():
qsfp1_modsell=qsfp1_modsell,
qsfp1_resetl=qsfp1_resetl,
qsfp1_intl=qsfp1_intl,
qsfp1_lpmode=qsfp1_lpmode
qsfp1_lpmode=qsfp1_lpmode,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -120,6 +120,7 @@ reg qsfp1_rx_axis_tlast = 0;
reg qsfp1_rx_axis_tuser = 0;
reg qsfp1_modprsl = 1;
reg qsfp1_intl = 1;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire [2:0] led;
@ -174,6 +175,11 @@ wire qsfp1_tx_axis_tuser;
wire qsfp1_modsell;
wire qsfp1_resetl;
wire qsfp1_lpmode;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -241,7 +247,8 @@ initial begin
qsfp1_rx_axis_tlast,
qsfp1_rx_axis_tuser,
qsfp1_modprsl,
qsfp1_intl
qsfp1_intl,
qspi_dq_i
);
$to_myhdl(
led,
@ -295,7 +302,12 @@ initial begin
qsfp1_tx_axis_tuser,
qsfp1_modsell,
qsfp1_resetl,
qsfp1_lpmode
qsfp1_lpmode,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -430,7 +442,13 @@ UUT (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode_int)
.qsfp1_lpmode(qsfp1_lpmode_int),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -70,6 +70,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

View File

@ -271,6 +271,24 @@ sync_signal_inst (
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
// startupe3 instance
wire cfgmclk;
@ -278,19 +296,19 @@ STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(cfgmclk),
.DI(),
.DO(4'd0),
.DTS(1'b1),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(1'b0),
.FCSBTS(1'b1),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(1'b0),
.USRCCLKTS(1'b1),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
@ -301,6 +319,121 @@ cfgmclk_bufg_inst (
.O(cfgmclk_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)
);
// configure SI5335 clock generators
reg qsfp_refclk_reset_reg = 1'b1;
reg sys_reset_reg = 1'b1;
@ -1443,7 +1576,17 @@ core_inst (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode)
.qsfp1_lpmode(qsfp1_lpmode),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -256,7 +256,17 @@ module fpga_core #
output wire qsfp1_resetl,
input wire qsfp1_modprsl,
input wire qsfp1_intl,
output wire qsfp1_lpmode
output wire qsfp1_lpmode,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -494,6 +504,13 @@ reg qsfp1_lpmode_reg = 1'b0;
reg i2c_scl_o_reg = 1'b1;
reg i2c_sda_o_reg = 1'b1;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -531,6 +548,13 @@ assign i2c_scl_t = i2c_scl_o_reg;
assign i2c_sda_o = i2c_sda_o_reg;
assign i2c_sda_t = i2c_sda_o_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -553,6 +577,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
@ -574,6 +602,20 @@ always @(posedge clk_250mhz) begin
qsfp1_lpmode_reg <= axil_csr_wdata[13];
end
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -636,6 +678,15 @@ always @(posedge clk_250mhz) begin
axil_csr_rdata_reg[12] <= qsfp1_reset_reg;
axil_csr_rdata_reg[13] <= qsfp1_lpmode_reg;
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -681,6 +732,13 @@ always @(posedge clk_250mhz) begin
i2c_scl_o_reg <= 1'b1;
i2c_sda_o_reg <= 1'b1;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -233,6 +233,7 @@ def bench():
qsfp1_rxc_4 = Signal(intbv(0)[8:])
qsfp1_modprsl = Signal(bool(1))
qsfp1_intl = Signal(bool(1))
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
led = Signal(intbv(0)[3:])
@ -293,6 +294,11 @@ def bench():
qsfp1_modsell = Signal(bool(0))
qsfp1_resetl = Signal(bool(0))
qsfp1_lpmode = Signal(bool(0))
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp0_1_source = xgmii_ep.XGMIISource()
@ -713,7 +719,13 @@ def bench():
qsfp1_modsell=qsfp1_modsell,
qsfp1_resetl=qsfp1_resetl,
qsfp1_intl=qsfp1_intl,
qsfp1_lpmode=qsfp1_lpmode
qsfp1_lpmode=qsfp1_lpmode,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -146,6 +146,7 @@ reg [63:0] qsfp1_rxd_4 = 0;
reg [7:0] qsfp1_rxc_4 = 0;
reg qsfp1_modprsl = 1;
reg qsfp1_intl = 1;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire [2:0] led;
@ -206,6 +207,11 @@ wire [7:0] qsfp1_txc_4;
wire qsfp1_modsell;
wire qsfp1_resetl;
wire qsfp1_lpmode;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -301,7 +307,8 @@ initial begin
qsfp1_rxd_4,
qsfp1_rxc_4,
qsfp1_modprsl,
qsfp1_intl
qsfp1_intl,
qspi_dq_i
);
$to_myhdl(
led,
@ -361,7 +368,12 @@ initial begin
qsfp1_txc_4,
qsfp1_modsell,
qsfp1_resetl,
qsfp1_lpmode
qsfp1_lpmode,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -528,7 +540,13 @@ UUT (
.qsfp1_modsell(qsfp1_modsell),
.qsfp1_resetl(qsfp1_resetl),
.qsfp1_intl(qsfp1_intl_int),
.qsfp1_lpmode(qsfp1_lpmode_int)
.qsfp1_lpmode(qsfp1_lpmode_int),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -54,6 +54,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

View File

@ -209,6 +209,160 @@ sync_reset_125mhz_inst (
// GPIO
assign hbm_cattrip = 1'b0;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
// 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;
@ -1250,7 +1404,17 @@ core_inst (
.qsfp1_rx_axis_tkeep(qsfp1_rx_axis_tkeep_int),
.qsfp1_rx_axis_tvalid(qsfp1_rx_axis_tvalid_int),
.qsfp1_rx_axis_tlast(qsfp1_rx_axis_tlast_int),
.qsfp1_rx_axis_tuser(qsfp1_rx_axis_tuser_int)
.qsfp1_rx_axis_tuser(qsfp1_rx_axis_tuser_int),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -178,7 +178,17 @@ module fpga_core #
input wire [AXIS_ETH_KEEP_WIDTH-1:0] qsfp1_rx_axis_tkeep,
input wire qsfp1_rx_axis_tvalid,
input wire qsfp1_rx_axis_tlast,
input wire qsfp1_rx_axis_tuser
input wire qsfp1_rx_axis_tuser,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -387,6 +397,13 @@ reg axil_csr_arready_reg = 1'b0;
reg [AXIL_DATA_WIDTH-1:0] axil_csr_rdata_reg = {AXIL_DATA_WIDTH{1'b0}};
reg axil_csr_rvalid_reg = 1'b0;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -410,6 +427,13 @@ assign axil_csr_rdata = axil_csr_rdata_reg;
assign axil_csr_rresp = 2'b00;
assign axil_csr_rvalid = axil_csr_rvalid_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -432,10 +456,28 @@ 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'h0100: begin
// GPIO out
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -486,6 +528,15 @@ always @(posedge clk_250mhz) begin
16'h0104: begin
// GPIO in
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -522,6 +573,13 @@ always @(posedge clk_250mhz) begin
axil_csr_arready_reg <= 1'b0;
axil_csr_rvalid_reg <= 1'b0;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -191,6 +191,7 @@ def bench():
qsfp1_rx_axis_tvalid = Signal(bool(0))
qsfp1_rx_axis_tlast = Signal(bool(0))
qsfp1_rx_axis_tuser = Signal(bool(0))
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
@ -234,6 +235,11 @@ def bench():
qsfp1_tx_axis_tvalid = Signal(bool(0))
qsfp1_tx_axis_tlast = Signal(bool(0))
qsfp1_tx_axis_tuser = Signal(bool(0))
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp0_source = axis_ep.AXIStreamSource()
@ -616,7 +622,13 @@ def bench():
qsfp1_rx_axis_tkeep=qsfp1_rx_axis_tkeep,
qsfp1_rx_axis_tvalid=qsfp1_rx_axis_tvalid,
qsfp1_rx_axis_tlast=qsfp1_rx_axis_tlast,
qsfp1_rx_axis_tuser=qsfp1_rx_axis_tuser
qsfp1_rx_axis_tuser=qsfp1_rx_axis_tuser,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -113,6 +113,7 @@ reg [AXIS_ETH_KEEP_WIDTH-1:0] qsfp1_rx_axis_tkeep = 0;
reg qsfp1_rx_axis_tvalid = 0;
reg qsfp1_rx_axis_tlast = 0;
reg qsfp1_rx_axis_tuser = 0;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
@ -156,6 +157,11 @@ wire [AXIS_ETH_KEEP_WIDTH-1:0] qsfp1_tx_axis_tkeep;
wire qsfp1_tx_axis_tvalid;
wire qsfp1_tx_axis_tlast;
wire qsfp1_tx_axis_tuser;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -216,7 +222,8 @@ initial begin
qsfp1_rx_axis_tkeep,
qsfp1_rx_axis_tvalid,
qsfp1_rx_axis_tlast,
qsfp1_rx_axis_tuser
qsfp1_rx_axis_tuser,
qspi_dq_i
);
$to_myhdl(
m_axis_rq_tdata,
@ -259,7 +266,12 @@ initial begin
qsfp1_tx_axis_tkeep,
qsfp1_tx_axis_tvalid,
qsfp1_tx_axis_tlast,
qsfp1_tx_axis_tuser
qsfp1_tx_axis_tuser,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -376,7 +388,13 @@ UUT (
.qsfp1_rx_axis_tkeep(qsfp1_rx_axis_tkeep),
.qsfp1_rx_axis_tvalid(qsfp1_rx_axis_tvalid),
.qsfp1_rx_axis_tlast(qsfp1_rx_axis_tlast),
.qsfp1_rx_axis_tuser(qsfp1_rx_axis_tuser)
.qsfp1_rx_axis_tuser(qsfp1_rx_axis_tuser),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -69,6 +69,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

View File

@ -210,6 +210,160 @@ sync_reset_125mhz_inst (
// GPIO
assign hbm_cattrip = 1'b0;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
// 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;
@ -1312,7 +1466,17 @@ core_inst (
.qsfp1_rxd_4(qsfp1_rxd_4_int),
.qsfp1_rxc_4(qsfp1_rxc_4_int),
.qsfp1_rx_prbs31_enable_4(qsfp1_rx_prbs31_enable_4_int),
.qsfp1_rx_error_count_4(qsfp1_rx_error_count_4_int)
.qsfp1_rx_error_count_4(qsfp1_rx_error_count_4_int),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -228,7 +228,17 @@ module fpga_core #
input wire [63:0] qsfp1_rxd_4,
input wire [7:0] qsfp1_rxc_4,
output wire qsfp1_rx_prbs31_enable_4,
input wire [6:0] qsfp1_rx_error_count_4
input wire [6:0] qsfp1_rx_error_count_4,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -457,6 +467,13 @@ reg axil_csr_arready_reg = 1'b0;
reg [AXIL_DATA_WIDTH-1:0] axil_csr_rdata_reg = {AXIL_DATA_WIDTH{1'b0}};
reg axil_csr_rvalid_reg = 1'b0;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -480,6 +497,13 @@ assign axil_csr_rdata = axil_csr_rdata_reg;
assign axil_csr_rresp = 2'b00;
assign axil_csr_rvalid = axil_csr_rvalid_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -502,10 +526,28 @@ 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'h0100: begin
// GPIO out
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -556,6 +598,15 @@ always @(posedge clk_250mhz) begin
16'h0104: begin
// GPIO in
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -592,6 +643,13 @@ always @(posedge clk_250mhz) begin
axil_csr_arready_reg <= 1'b0;
axil_csr_rvalid_reg <= 1'b0;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -226,6 +226,7 @@ def bench():
qsfp1_rx_rst_4 = Signal(bool(0))
qsfp1_rxd_4 = Signal(intbv(0)[64:])
qsfp1_rxc_4 = Signal(intbv(0)[8:])
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
@ -275,6 +276,11 @@ def bench():
qsfp1_txc_3 = Signal(intbv(0)[8:])
qsfp1_txd_4 = Signal(intbv(0)[64:])
qsfp1_txc_4 = Signal(intbv(0)[8:])
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp0_1_source = xgmii_ep.XGMIISource()
@ -677,7 +683,13 @@ def bench():
qsfp1_rx_clk_4=qsfp1_rx_clk_4,
qsfp1_rx_rst_4=qsfp1_rx_rst_4,
qsfp1_rxd_4=qsfp1_rxd_4,
qsfp1_rxc_4=qsfp1_rxc_4
qsfp1_rxc_4=qsfp1_rxc_4,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -139,6 +139,7 @@ reg qsfp1_rx_clk_4 = 0;
reg qsfp1_rx_rst_4 = 0;
reg [63:0] qsfp1_rxd_4 = 0;
reg [7:0] qsfp1_rxc_4 = 0;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
@ -188,6 +189,11 @@ wire [63:0] qsfp1_txd_3;
wire [7:0] qsfp1_txc_3;
wire [63:0] qsfp1_txd_4;
wire [7:0] qsfp1_txc_4;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -276,7 +282,8 @@ initial begin
qsfp1_rx_clk_4,
qsfp1_rx_rst_4,
qsfp1_rxd_4,
qsfp1_rxc_4
qsfp1_rxc_4,
qspi_dq_i
);
$to_myhdl(
m_axis_rq_tdata,
@ -325,7 +332,12 @@ initial begin
qsfp1_txd_3,
qsfp1_txc_3,
qsfp1_txd_4,
qsfp1_txc_4
qsfp1_txc_4,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -474,7 +486,13 @@ UUT (
.qsfp1_rx_clk_4(qsfp1_rx_clk_4),
.qsfp1_rx_rst_4(qsfp1_rx_rst_4),
.qsfp1_rxd_4(qsfp1_rxd_4),
.qsfp1_rxc_4(qsfp1_rxc_4)
.qsfp1_rxc_4(qsfp1_rxc_4),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -54,6 +54,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

View File

@ -187,6 +187,160 @@ sync_reset_125mhz_inst (
// GPIO
assign hbm_cattrip = 1'b0;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
// 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;
@ -899,7 +1053,17 @@ core_inst (
.qsfp_rx_axis_tkeep(qsfp_rx_axis_tkeep_int),
.qsfp_rx_axis_tvalid(qsfp_rx_axis_tvalid_int),
.qsfp_rx_axis_tlast(qsfp_rx_axis_tlast_int),
.qsfp_rx_axis_tuser(qsfp_rx_axis_tuser_int)
.qsfp_rx_axis_tuser(qsfp_rx_axis_tuser_int),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -166,7 +166,17 @@ module fpga_core #
input wire [AXIS_ETH_KEEP_WIDTH-1:0] qsfp_rx_axis_tkeep,
input wire qsfp_rx_axis_tvalid,
input wire qsfp_rx_axis_tlast,
input wire qsfp_rx_axis_tuser
input wire qsfp_rx_axis_tuser,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -375,6 +385,13 @@ reg axil_csr_arready_reg = 1'b0;
reg [AXIL_DATA_WIDTH-1:0] axil_csr_rdata_reg = {AXIL_DATA_WIDTH{1'b0}};
reg axil_csr_rvalid_reg = 1'b0;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -398,6 +415,13 @@ assign axil_csr_rdata = axil_csr_rdata_reg;
assign axil_csr_rresp = 2'b00;
assign axil_csr_rvalid = axil_csr_rvalid_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -420,10 +444,28 @@ 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'h0100: begin
// GPIO out
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -474,6 +516,15 @@ always @(posedge clk_250mhz) begin
16'h0104: begin
// GPIO in
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -510,6 +561,13 @@ always @(posedge clk_250mhz) begin
axil_csr_arready_reg <= 1'b0;
axil_csr_rvalid_reg <= 1'b0;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -181,6 +181,7 @@ def bench():
qsfp_rx_axis_tvalid = Signal(bool(0))
qsfp_rx_axis_tlast = Signal(bool(0))
qsfp_rx_axis_tuser = Signal(bool(0))
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
qsfp_led_act = Signal(bool(0))
@ -222,6 +223,11 @@ def bench():
qsfp_tx_axis_tvalid = Signal(bool(0))
qsfp_tx_axis_tlast = Signal(bool(0))
qsfp_tx_axis_tuser = Signal(bool(0))
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp_source = axis_ep.AXIStreamSource()
@ -561,7 +567,13 @@ def bench():
qsfp_rx_axis_tkeep=qsfp_rx_axis_tkeep,
qsfp_rx_axis_tvalid=qsfp_rx_axis_tvalid,
qsfp_rx_axis_tlast=qsfp_rx_axis_tlast,
qsfp_rx_axis_tuser=qsfp_rx_axis_tuser
qsfp_rx_axis_tuser=qsfp_rx_axis_tuser,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -103,6 +103,7 @@ reg [AXIS_ETH_KEEP_WIDTH-1:0] qsfp_rx_axis_tkeep = 0;
reg qsfp_rx_axis_tvalid = 0;
reg qsfp_rx_axis_tlast = 0;
reg qsfp_rx_axis_tuser = 0;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire qsfp_led_act;
@ -144,6 +145,11 @@ wire [AXIS_ETH_KEEP_WIDTH-1:0] qsfp_tx_axis_tkeep;
wire qsfp_tx_axis_tvalid;
wire qsfp_tx_axis_tlast;
wire qsfp_tx_axis_tuser;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -194,7 +200,8 @@ initial begin
qsfp_rx_axis_tkeep,
qsfp_rx_axis_tvalid,
qsfp_rx_axis_tlast,
qsfp_rx_axis_tuser
qsfp_rx_axis_tuser,
qspi_dq_i
);
$to_myhdl(
qsfp_led_act,
@ -235,7 +242,12 @@ initial begin
qsfp_tx_axis_tkeep,
qsfp_tx_axis_tvalid,
qsfp_tx_axis_tlast,
qsfp_tx_axis_tuser
qsfp_tx_axis_tuser,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -340,7 +352,13 @@ UUT (
.qsfp_rx_axis_tkeep(qsfp_rx_axis_tkeep),
.qsfp_rx_axis_tvalid(qsfp_rx_axis_tvalid),
.qsfp_rx_axis_tlast(qsfp_rx_axis_tlast),
.qsfp_rx_axis_tuser(qsfp_rx_axis_tuser)
.qsfp_rx_axis_tuser(qsfp_rx_axis_tuser),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule

View File

@ -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"]

View File

@ -69,6 +69,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

View File

@ -188,6 +188,160 @@ sync_reset_125mhz_inst (
// GPIO
assign hbm_cattrip = 1'b0;
// Flash
wire qspi_clk_int;
wire [3:0] qspi_dq_int;
wire [3:0] qspi_dq_i_int;
wire [3:0] qspi_dq_o_int;
wire [3:0] qspi_dq_oe_int;
wire qspi_cs_int;
sync_signal #(
.WIDTH(4),
.N(2)
)
flash_sync_signal_inst (
.clk(pcie_user_clk),
.in({qspi_dq_int}),
.out({qspi_dq_i_int})
);
STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(),
.DI(qspi_dq_int),
.DO(qspi_dq_o_int),
.DTS(~qspi_dq_oe_int),
.EOS(),
.FCSBO(qspi_cs_int),
.FCSBTS(1'b0),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(qspi_clk_int),
.USRCCLKTS(1'b0),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
// 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;
@ -1008,7 +1162,17 @@ core_inst (
.qsfp_rxd_4(qsfp_rxd_4_int),
.qsfp_rxc_4(qsfp_rxc_4_int),
.qsfp_rx_prbs31_enable_4(qsfp_rx_prbs31_enable_4_int),
.qsfp_rx_error_count_4(qsfp_rx_error_count_4_int)
.qsfp_rx_error_count_4(qsfp_rx_error_count_4_int),
/*
* QSPI flash
*/
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk_int),
.qspi_dq_i(qspi_dq_i_int),
.qspi_dq_o(qspi_dq_o_int),
.qspi_dq_oe(qspi_dq_oe_int),
.qspi_cs(qspi_cs_int)
);
endmodule

View File

@ -190,7 +190,17 @@ module fpga_core #
input wire [63:0] qsfp_rxd_4,
input wire [7:0] qsfp_rxc_4,
output wire qsfp_rx_prbs31_enable_4,
input wire [6:0] qsfp_rx_error_count_4
input wire [6:0] qsfp_rx_error_count_4,
/*
* QSPI flash
*/
output wire fpga_boot,
output wire qspi_clk,
input wire [3:0] qspi_dq_i,
output wire [3:0] qspi_dq_o,
output wire [3:0] qspi_dq_oe,
output wire qspi_cs
);
// PHC parameters
@ -419,6 +429,13 @@ reg axil_csr_arready_reg = 1'b0;
reg [AXIL_DATA_WIDTH-1:0] axil_csr_rdata_reg = {AXIL_DATA_WIDTH{1'b0}};
reg axil_csr_rvalid_reg = 1'b0;
reg fpga_boot_reg = 1'b0;
reg qspi_clk_reg = 1'b0;
reg qspi_cs_reg = 1'b1;
reg [3:0] qspi_dq_o_reg = 4'd0;
reg [3:0] qspi_dq_oe_reg = 4'd0;
reg pcie_dma_enable_reg = 0;
reg [95:0] get_ptp_ts_96_reg = 0;
@ -442,6 +459,13 @@ assign axil_csr_rdata = axil_csr_rdata_reg;
assign axil_csr_rresp = 2'b00;
assign axil_csr_rvalid = axil_csr_rvalid_reg;
assign fpga_boot = fpga_boot_reg;
assign qspi_clk = qspi_clk_reg;
assign qspi_cs = qspi_cs_reg;
assign qspi_dq_o = qspi_dq_o_reg;
assign qspi_dq_oe = qspi_dq_oe_reg;
//assign pcie_dma_enable = pcie_dma_enable_reg;
always @(posedge clk_250mhz) begin
@ -464,10 +488,28 @@ 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'h0100: begin
// GPIO out
end
// Flash
16'h0144: begin
// QSPI control
if (axil_csr_wstrb[0]) begin
qspi_dq_o_reg <= axil_csr_wdata[3:0];
end
if (axil_csr_wstrb[1]) begin
qspi_dq_oe_reg <= axil_csr_wdata[11:8];
end
if (axil_csr_wstrb[2]) begin
qspi_clk_reg <= axil_csr_wdata[16];
qspi_cs_reg <= axil_csr_wdata[17];
end
end
// PHC
16'h0230: set_ptp_ts_96_reg[15:0] <= axil_csr_wdata; // PTP set fns
16'h0234: set_ptp_ts_96_reg[45:16] <= axil_csr_wdata; // PTP set ns
@ -518,6 +560,15 @@ always @(posedge clk_250mhz) begin
16'h0104: begin
// GPIO in
end
// Flash
16'h0140: axil_csr_rdata_reg <= {8'd0, 8'd4, 8'd1, 8'd0}; // Flash ID
16'h0144: begin
// QSPI control
axil_csr_rdata_reg[3:0] <= qspi_dq_i;
axil_csr_rdata_reg[11:8] <= qspi_dq_oe;
axil_csr_rdata_reg[16] <= qspi_clk;
axil_csr_rdata_reg[17] <= qspi_cs;
end
// PHC
16'h0200: axil_csr_rdata_reg <= {8'd0, 8'd0, 8'd0, 8'd0}; // PHC features
16'h0210: axil_csr_rdata_reg <= ptp_ts_96[15:0]; // PTP cur fns
@ -554,6 +605,13 @@ always @(posedge clk_250mhz) begin
axil_csr_arready_reg <= 1'b0;
axil_csr_rvalid_reg <= 1'b0;
fpga_boot_reg <= 1'b0;
qspi_clk_reg <= 1'b0;
qspi_cs_reg <= 1'b1;
qspi_dq_o_reg <= 4'd0;
qspi_dq_oe_reg <= 4'd0;
pcie_dma_enable_reg <= 1'b0;
end
end

View File

@ -202,6 +202,7 @@ def bench():
qsfp_rx_rst_4 = Signal(bool(0))
qsfp_rxd_4 = Signal(intbv(0)[64:])
qsfp_rxc_4 = Signal(intbv(0)[8:])
qspi_dq_i = Signal(intbv(0)[4:])
# Outputs
qsfp_led_act = Signal(bool(0))
@ -246,6 +247,11 @@ def bench():
qsfp_txc_3 = Signal(intbv(0)[8:])
qsfp_txd_4 = Signal(intbv(0)[64:])
qsfp_txc_4 = Signal(intbv(0)[8:])
fpga_boot = Signal(bool(0))
qspi_clk = Signal(bool(0))
qspi_dq_o = Signal(intbv(0)[4:])
qspi_dq_oe = Signal(intbv(0)[4:])
qspi_cs = Signal(bool(0))
# sources and sinks
qsfp_1_source = xgmii_ep.XGMIISource()
@ -595,7 +601,13 @@ def bench():
qsfp_rx_clk_4=qsfp_rx_clk_4,
qsfp_rx_rst_4=qsfp_rx_rst_4,
qsfp_rxd_4=qsfp_rxd_4,
qsfp_rxc_4=qsfp_rxc_4
qsfp_rxc_4=qsfp_rxc_4,
fpga_boot=fpga_boot,
qspi_clk=qspi_clk,
qspi_dq_i=qspi_dq_i,
qspi_dq_o=qspi_dq_o,
qspi_dq_oe=qspi_dq_oe,
qspi_cs=qspi_cs
)
@always(delay(5))

View File

@ -115,6 +115,7 @@ reg qsfp_rx_clk_4 = 0;
reg qsfp_rx_rst_4 = 0;
reg [63:0] qsfp_rxd_4 = 0;
reg [7:0] qsfp_rxc_4 = 0;
reg [3:0] qspi_dq_i = 0;
// Outputs
wire qsfp_led_act;
@ -159,6 +160,11 @@ wire [63:0] qsfp_txd_3;
wire [7:0] qsfp_txc_3;
wire [63:0] qsfp_txd_4;
wire [7:0] qsfp_txc_4;
wire fpga_boot;
wire qspi_clk;
wire [3:0] qspi_dq_o;
wire [3:0] qspi_dq_oe;
wire qspi_cs;
initial begin
// myhdl integration
@ -223,7 +229,8 @@ initial begin
qsfp_rx_clk_4,
qsfp_rx_rst_4,
qsfp_rxd_4,
qsfp_rxc_4
qsfp_rxc_4,
qspi_dq_i
);
$to_myhdl(
qsfp_led_act,
@ -267,7 +274,12 @@ initial begin
qsfp_txd_3,
qsfp_txc_3,
qsfp_txd_4,
qsfp_txc_4
qsfp_txc_4,
fpga_boot,
qspi_clk,
qspi_dq_o,
qspi_dq_oe,
qspi_cs
);
// dump file
@ -387,7 +399,13 @@ UUT (
.qsfp_rx_clk_4(qsfp_rx_clk_4),
.qsfp_rx_rst_4(qsfp_rx_rst_4),
.qsfp_rxd_4(qsfp_rxd_4),
.qsfp_rxc_4(qsfp_rxc_4)
.qsfp_rxc_4(qsfp_rxc_4),
.fpga_boot(fpga_boot),
.qspi_clk(qspi_clk),
.qspi_dq_i(qspi_dq_i),
.qspi_dq_o(qspi_dq_o),
.qspi_dq_oe(qspi_dq_oe),
.qspi_cs(qspi_cs)
);
endmodule