diff --git a/target/xilinx/constraints/genesys2.xdc b/target/xilinx/constraints/genesys2.xdc index 25f63c46a..9feb8fe20 100644 --- a/target/xilinx/constraints/genesys2.xdc +++ b/target/xilinx/constraints/genesys2.xdc @@ -77,11 +77,11 @@ set_output_delay -max -clock $soc_clk [expr { $SOC_TCK * 0.35 }] [get_ports vga* # SPIM # ######## -set_input_delay -min -clock $soc_clk [expr { 0.10 * $SOC_TCK }] [get_ports {sd_d_* sd_cd_i}] -set_input_delay -max -clock $soc_clk [expr { 0.35 * $SOC_TCK }] [get_ports {sd_d_* sd_cd_i}] +set_input_delay -min -clock $soc_clk [expr { 0.10 * $SOC_TCK }] [get_ports {sd_d_* sd_cd_i spih_sd_*}] +set_input_delay -max -clock $soc_clk [expr { 0.35 * $SOC_TCK }] [get_ports {sd_d_* sd_cd_i spih_sd_*}] # TODO: fix this by raising it back up... -set_output_delay -min -clock $soc_clk [expr { 0.020 * $SOC_TCK }] [get_ports {sd_d_* sd_*_o}] -set_output_delay -max -clock $soc_clk [expr { 0.063 * $SOC_TCK }] [get_ports {sd_d_* sd_*_o}] +set_output_delay -min -clock $soc_clk [expr { 0.020 * $SOC_TCK }] [get_ports {sd_d_* sd_*_o spih_sd_* spih_csb_o}] +set_output_delay -max -clock $soc_clk [expr { 0.063 * $SOC_TCK }] [get_ports {sd_d_* sd_*_o spih_sd_* spih_csb_o}] ####### # I2C # @@ -150,6 +150,13 @@ set_property -dict { PACKAGE_PIN T30 IOSTANDARD LVCMOS33 } [get_ports { sd_d_i set_property -dict { PACKAGE_PIN AE24 IOSTANDARD LVCMOS33 } [get_ports { sd_reset_o }]; #IO_L12N_T1_MRCC_12 Sch=sd_reset set_property -dict { PACKAGE_PIN R28 IOSTANDARD LVCMOS33 } [get_ports { sd_sclk_o }]; #IO_L11P_T1_SRCC_14 Sch=sd_sclk +# QSPI +set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { spih_csb_o }]; #IO_L6P_T0_FCS_B_14 Sch=qspi_csn +set_property -dict { PACKAGE_PIN P24 IOSTANDARD LVCMOS33 } [get_ports { spih_sd_io[0] }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_d[0] +set_property -dict { PACKAGE_PIN R25 IOSTANDARD LVCMOS33 } [get_ports { spih_sd_io[1] }]; #IO_L1N_T0_D01_DIN_14 Sch=qspi_d[1] +set_property -dict { PACKAGE_PIN R20 IOSTANDARD LVCMOS33 } [get_ports { spih_sd_io[2] }]; #IO_L2P_T0_D02_14 Sch=qspi_d[2] +set_property -dict { PACKAGE_PIN R21 IOSTANDARD LVCMOS33 } [get_ports { spih_sd_io[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_d[3] + # VGA Connector set_property -dict { PACKAGE_PIN AH20 IOSTANDARD LVCMOS33 } [get_ports { vga_blue_o[0] }]; #IO_L22N_T3_12 Sch=vga_b[3] set_property -dict { PACKAGE_PIN AG20 IOSTANDARD LVCMOS33 } [get_ports { vga_blue_o[1] }]; #IO_L22P_T3_12 Sch=vga_b[4] diff --git a/target/xilinx/src/cheshire_top_xilinx.sv b/target/xilinx/src/cheshire_top_xilinx.sv index b04940522..ab152210a 100644 --- a/target/xilinx/src/cheshire_top_xilinx.sv +++ b/target/xilinx/src/cheshire_top_xilinx.sv @@ -70,6 +70,17 @@ module cheshire_top_xilinx import cheshire_pkg::*; ( output logic [4:0] vga_blue_o, `endif +`ifdef USE_QSPI +`ifndef USE_STARTUPE3 +`ifndef USE_STARTUPE2 + // If a STARTUPE2 is present, this is wired there. + output wire spih_sck_o, +`endif + output wire spih_csb_o, + inout wire [3:0] spih_sd_io, +`endif +`endif + `ifdef USE_DDR4 `DDR4_INTF `endif @@ -248,6 +259,12 @@ module cheshire_top_xilinx import cheshire_pkg::*; ( logic [1:0] spi_cs_soc; logic [3:0] spi_sd_soc_out; logic [3:0] spi_sd_soc_in; + // Multiplex between SPI SD mode and QSPI proper + logic [3:0] spi_sd_sd_in, spi_sd_spih_in; + + // Choose SoC input based on chip select + assign spi_sd_soc_in = + ({4{~spi_cs_soc[0]}} & spi_sd_sd_in) | ({4{~spi_cs_soc[1]}} & spi_sd_spih_in); logic spi_sck_en; logic [1:0] spi_cs_en; @@ -263,13 +280,13 @@ module cheshire_top_xilinx import cheshire_pkg::*; ( // MOSI - SD CMD signal assign sd_cmd_o = spi_sd_en[0] ? spi_sd_soc_out[0] : 1'b1; // MISO - SD DAT0 signal - assign spi_sd_soc_in[1] = sd_d_io[0]; + assign spi_sd_sd_in[1] = sd_d_io[0]; // SD DAT1 and DAT2 signal tie-off - Not used for SPI mode assign sd_d_io[2:1] = 2'b11; // Bind input side of SoC low for output signals - assign spi_sd_soc_in[0] = 1'b0; - assign spi_sd_soc_in[2] = 1'b0; - assign spi_sd_soc_in[3] = 1'b0; + assign spi_sd_sd_in[0] = 1'b0; + assign spi_sd_sd_in[2] = 1'b0; + assign spi_sd_sd_in[3] = 1'b0; `endif //////////// @@ -288,7 +305,7 @@ module cheshire_top_xilinx import cheshire_pkg::*; ( assign qspi_clk = spi_sck_soc; assign qspi_cs_b = spi_cs_soc; assign qspi_dqo = spi_sd_soc_out; - assign spi_sd_soc_in = qspi_dqi; + assign spi_sd_spih_in = qspi_dqi; // Tristate enables assign qspi_clk_ts = ~spi_sck_en; @@ -320,7 +337,66 @@ module cheshire_top_xilinx import cheshire_pkg::*; ( .USRDONETS ( 1'b1 ) ); `else - // TODO: off-chip QSPI interface +`ifdef USE_STARTUPE2 + // define output SPI clock locally here in this case + wire spih_sck_o; + (*keep="TRUE"*) + STARTUPE2 #( + .PROG_USR("FALSE"), + .SIM_CCLK_FREQ(0.0) + ) i_startupe2 ( + .CFGCLK ( ), + .CFGMCLK ( ), + .EOS ( ), + .PREQ ( ), + .CLK ( 1'b0 ), + .GSR ( 1'b0 ), + .GTS ( 1'b0 ), + .KEYCLEARB ( 1'b0 ), + .PACK ( 1'b0 ), + .USRCCLKO ( spih_sck_o ), + .USRCCLKTS ( 1'b0 ), + .USRDONEO ( 1'b0 ), + .USRDONETS ( 1'b0 ) + ); +`endif + IOBUF #( + .DRIVE ( 12 ), + .IBUF_LOW_PWR ( "FALSE" ), + .IOSTANDARD ( "DEFAULT" ), + .SLEW ( "FAST" ) + ) i_spih_sck_iobuf ( + .O ( ), + .IO ( spih_sck_o ), + .I ( spi_sck_soc ), + .T ( ~spi_sck_en ) + ); + + IOBUF #( + .DRIVE ( 12 ), + .IBUF_LOW_PWR ( "FALSE" ), + .IOSTANDARD ( "DEFAULT" ), + .SLEW ( "FAST" ) + ) i_spih_csb_iobuf ( + .O ( ), + .IO ( spih_csb_o ), + .I ( spi_cs_soc [1] ), + .T ( ~spi_cs_en [1] ) + ); + + for (genvar i = 0; i < 4; ++i) begin : gen_qspi_iobufs + IOBUF #( + .DRIVE ( 12 ), + .IBUF_LOW_PWR ( "FALSE" ), + .IOSTANDARD ( "DEFAULT" ), + .SLEW ( "FAST" ) + ) i_spih_sd_iobuf ( + .O ( spi_sd_spih_in [i] ), + .IO ( spih_sd_io [i] ), + .I ( spi_sd_soc_out [i] ), + .T ( ~spi_sd_en [i] ) + ); + end `endif `endif diff --git a/target/xilinx/src/phy_definitions.svh b/target/xilinx/src/phy_definitions.svh index db651854b..eb2861659 100644 --- a/target/xilinx/src/phy_definitions.svh +++ b/target/xilinx/src/phy_definitions.svh @@ -26,6 +26,8 @@ `define USE_I2C `define USE_VGA `define USE_USB + `define USE_STARTUPE2 + `define USE_QSPI `endif `ifdef TARGET_ZCU102