diff --git a/Bender.yml b/Bender.yml index fc2ce82e..8b79d0b1 100644 --- a/Bender.yml +++ b/Bender.yml @@ -30,6 +30,7 @@ dependencies: riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git", version: 0.8.1 } serial_link: { git: "https://github.com/pulp-platform/serial_link.git", version: 1.1.1 } unbent: { git: "https://github.com/pulp-platform/unbent.git", version: 0.1.6 } + hyperbus: { git: "https://github.com/pulp-platform/hyperbus.git", rev: bd5688dd1d3ed24e0a6bf2296009d525230c93a0 } export_include_dirs: - hw/include diff --git a/hw/cheshire_pkg.sv b/hw/cheshire_pkg.sv index 691952b0..6eda8438 100644 --- a/hw/cheshire_pkg.sv +++ b/hw/cheshire_pkg.sv @@ -616,7 +616,7 @@ package cheshire_pkg; LlcAmoPostCut : 1, LlcOutConnect : 1, LlcOutRegionStart : 'h8000_0000, - LlcOutRegionEnd : 'h1_0000_0000, + LlcOutRegionEnd : 'h8200_0000, // VGA: RGB332 VgaRedWidth : 3, VgaGreenWidth : 3, diff --git a/target/xilinx/constraints/genesys2.xdc b/target/xilinx/constraints/genesys2.xdc index 18debabc..7c0b098a 100644 --- a/target/xilinx/constraints/genesys2.xdc +++ b/target/xilinx/constraints/genesys2.xdc @@ -19,6 +19,97 @@ create_clock -period $SYS_TCK -name sys_clk [get_ports sys_clk_p] set SOC_TCK 20.0 set soc_clk [get_clocks -of_objects [get_pins i_clkwiz/clk_50]] +############ +# Hyperram # +############ + +set period_hyperbus 40 + +## Create RWDS clock (10MHz) +create_clock -period [expr $period_hyperbus] -name rwds0_clk [get_ports FMC_hyper0_rwds] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets iobuf_rwds0_i/O] + +create_clock -period [expr $period_hyperbus] -name rwds1_clk [get_ports FMC_hyper1_rwds] +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets iobuf_rwds1_i/O] + +## Create the PHY clock +create_generated_clock [get_pins i_hyperbus/clock_generator.ddr_clk/clk0_o] -name clk_phy -source [get_pins i_clkwiz/clk_50] -divide_by 2 +create_generated_clock [get_pins i_hyperbus/clock_generator.ddr_clk/clk90_o] -name clk_phy_90 -source [get_pins i_clkwiz/clk_50] -edges {2 4 6} + +## PHY0 +set clk_rx_shift [expr $period_hyperbus/10] +set rwds_input_delay [expr $period_hyperbus/4] + +create_generated_clock [get_pins i_hyperbus/i_phy/phy_wrap.phy_unroll[0].i_phy/i_trx/i_delay_rx_rwds_90/in_i] \ + -name clk_rwds_0 -edges {1 2 3} -edge_shift "$clk_rx_shift $clk_rx_shift $clk_rx_shift" \ + -source [get_ports FMC_hyper0_rwds] + +create_generated_clock [get_nets i_hyperbus/i_phy/phy_wrap.phy_unroll[0].i_phy/i_trx/i_rx_rwds_cdc_fifo/src_clk_i] \ + -name clk_rwds_sample0 -invert -divide_by 1 \ + -source [get_pins i_hyperbus/i_phy/phy_wrap.phy_unroll[0].i_phy/i_trx/i_delay_rx_rwds_90/in_i] + +## PHY1 +create_generated_clock [get_pins i_hyperbus/i_phy/phy_wrap.phy_unroll[1].i_phy/i_trx/i_delay_rx_rwds_90/in_i] \ + -name clk_rwds_1 -edges {1 2 3} -edge_shift "$clk_rx_shift $clk_rx_shift $clk_rx_shift" \ + -source [get_ports FMC_hyper1_rwds] + +create_generated_clock [get_nets i_hyperbus/i_phy/phy_wrap.phy_unroll[1].i_phy/i_trx/i_rx_rwds_cdc_fifo/src_clk_i] \ + -name clk_rwds_sample1 -invert -divide_by 1 \ + -source [get_pins i_hyperbus/i_phy/phy_wrap.phy_unroll[1].i_phy/i_trx/i_delay_rx_rwds_90/in_i] + +## I/O constraints +set output_ports {{FMC_hyper*_dq*} FMC_hyper*_rwds} +set_output_delay [expr $period_hyperbus/2 ] -clock clk_phy_90 [get_ports $output_ports] -max +set_output_delay [expr $period_hyperbus/-2] -clock clk_phy_90 [get_ports $output_ports] -min -add_delay +set_output_delay [expr $period_hyperbus/2 ] -clock clk_phy_90 [get_ports $output_ports] -max -clock_fall -add_delay +set_output_delay [expr $period_hyperbus/-2] -clock clk_phy_90 [get_ports $output_ports] -min -clock_fall -add_delay + +set input_ports {{FMC_hyper*_dq*} FMC_hyper*_rwds} +set_input_delay -max [expr $period_hyperbus/2] -clock clk_phy [get_ports $input_ports] +set_input_delay -min [expr $period_hyperbus/2] -clock clk_phy [get_ports $input_ports] -add_delay +set_input_delay -max [expr $period_hyperbus/2] -clock clk_phy [get_ports $input_ports] -add_delay -clock_fall +set_input_delay -min [expr $period_hyperbus/2] -clock clk_phy [get_ports $input_ports] -add_delay -clock_fall + +## Async +set_clock_groups -asynchronous -group [get_clocks sys_clk] \ + -group [get_clocks clk_phy] \ + -group [get_clocks clk_phy_90] \ + -group [get_clocks { rwds0_clk clk_rwds_0 clk_rwds_sample0 }] \ + -group [get_clocks { rwds1_clk clk_rwds_1 clk_rwds_sample1 }] + +## FMC +# Hyper 0 +set_property -dict { PACKAGE_PIN D27 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_ck] +set_property -dict { PACKAGE_PIN C27 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_ckn] +set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_csn0] +set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_csn1] +set_property -dict { PACKAGE_PIN F26 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_rwds] +set_property -dict { PACKAGE_PIN D22 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_reset] +set_property -dict { PACKAGE_PIN B29 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio0] +set_property -dict { PACKAGE_PIN C29 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio1] +set_property -dict { PACKAGE_PIN E30 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio2] +set_property -dict { PACKAGE_PIN E29 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio3] +set_property -dict { PACKAGE_PIN E23 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio4] +set_property -dict { PACKAGE_PIN D23 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio5] +set_property -dict { PACKAGE_PIN G22 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio6] +set_property -dict { PACKAGE_PIN F22 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper0_dqio7] + +# Hyper 1 +set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_ck] +set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_ckn] +set_property -dict { PACKAGE_PIN F17 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_csn0] +set_property -dict { PACKAGE_PIN E21 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_csn1] +set_property -dict { PACKAGE_PIN A20 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_rwds] +set_property -dict { PACKAGE_PIN B24 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_reset] +set_property -dict { PACKAGE_PIN B30 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio0] +set_property -dict { PACKAGE_PIN A30 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio1] +set_property -dict { PACKAGE_PIN B28 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio2] +set_property -dict { PACKAGE_PIN A28 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio3] +set_property -dict { PACKAGE_PIN D29 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio4] +set_property -dict { PACKAGE_PIN C30 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio5] +set_property -dict { PACKAGE_PIN B27 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio6] +set_property -dict { PACKAGE_PIN A27 IOSTANDARD LVCMOS12 } [get_ports FMC_hyper1_dqio7] + ############ # Switches # ############ diff --git a/target/xilinx/src/cheshire_top_xilinx.sv b/target/xilinx/src/cheshire_top_xilinx.sv index 4e93b2bc..70c9c6e1 100644 --- a/target/xilinx/src/cheshire_top_xilinx.sv +++ b/target/xilinx/src/cheshire_top_xilinx.sv @@ -76,6 +76,9 @@ module cheshire_top_xilinx ( `ifdef USE_DDR3 `DDR3_INTF `endif +`ifdef USE_HYPERBUS + `HYPERBUS_INTF +`endif output logic uart_tx_o, input logic uart_rx_i @@ -97,6 +100,14 @@ module cheshire_top_xilinx ( ret.VgaRedWidth = 5; ret.VgaGreenWidth = 6; ret.VgaBlueWidth = 5; + ret.LlcNotBypass = 0; + ret.Dma = 0; + ret.Vga = 0; + ret.RegExtNumSlv = 1; + ret.RegExtNumRules = 1; + ret.RegExtRegionIdx [0] = 0; + ret.RegExtRegionStart [0] = 'h4000_0000; + ret.RegExtRegionEnd [0] = 'h4010_0000; return ret; endfunction @@ -390,6 +401,115 @@ module cheshire_top_xilinx ( ); `endif + + ////////////// + // Hyperbus // + ////////////// + + reg_req_t reg_ext_slv_req; + reg_rsp_t reg_ext_slv_rsp; + +`ifdef USE_HYPERBUS + // Signals + logic [1:0] hyper_reset_no; + logic [1:0][1:0] hyper_cs_no; + logic [1:0] hyper_ck_o; + logic [1:0] hyper_ck_no; + logic [1:0] hyper_rwds_o; + logic [1:0] hyper_rwds_i; + logic [1:0] hyper_rwds_oe_o; + logic [1:0][7:0] hyper_dq_o; + logic [1:0][7:0] hyper_dq_i; + logic [1:0] hyper_dq_oe_o; + + // Hyperbus address rules + typedef struct packed { + int unsigned idx; + logic [FPGACfg.AddrWidth-1:0] start_addr; + logic [FPGACfg.AddrWidth-1:0] end_addr; + } hyper_addr_rule_t; + + // Hyperbus + hyperbus #( + .NumChips ( 2 ), + .NumPhys ( 2 ), + .IsClockODelayed ( 0 ), + .AxiAddrWidth ( FPGACfg.AddrWidth ), + .AxiDataWidth ( FPGACfg.AxiDataWidth ), + .AxiIdWidth ( $bits(axi_llc_id_t) ), + .AxiUserWidth ( FPGACfg.AxiUserWidth ), + .axi_req_t ( axi_llc_req_t ), + .axi_rsp_t ( axi_llc_rsp_t ), + .axi_w_chan_t ( axi_llc_w_chan_t ), + .axi_b_chan_t ( axi_llc_b_chan_t ), + .axi_ar_chan_t ( axi_llc_ar_chan_t ), + .axi_r_chan_t ( axi_llc_r_chan_t ), + .axi_aw_chan_t ( axi_llc_aw_chan_t ), + .RegAddrWidth ( FPGACfg.AddrWidth ), + .RegDataWidth ( 32 ), + .reg_req_t ( reg_req_t ), + .reg_rsp_t ( reg_rsp_t ), + .axi_rule_t ( hyper_addr_rule_t ), + .RstChipBase ( 32'(FPGACfg.LlcOutRegionStart) ), + .RstChipSpace ( 32'(8*1024) ) + ) i_hyperbus ( + // WARNING: Keeping system and PHY synchronous works only with careful constraints. + // DO NOT copy-paste this to other projects without consideration; you were warned. + .clk_phy_i ( soc_clk ), + .rst_phy_ni ( rst_n ), + .clk_sys_i ( soc_clk ), + .rst_sys_ni ( rst_n ), + .test_mode_i, + .axi_req_i ( axi_llc_mst_req ), + .axi_rsp_o ( axi_llc_mst_rsp ), + .reg_req_i ( reg_ext_slv_req ), + .reg_rsp_o ( reg_ext_slv_rsp ), + .hyper_cs_no, + .hyper_ck_o, + .hyper_ck_no, + .hyper_rwds_o, + .hyper_rwds_i, + .hyper_rwds_oe_o, + .hyper_dq_i, + .hyper_dq_o, + .hyper_dq_oe_o, + .hyper_reset_no + ); + + // Pads + // PHY0 + (* PULLDOWN = "YES" *) IOBUF iobuf_csn00_i ( .T(1'b0), .I(hyper_cs_no[0][0]), .O(), .IO(FMC_hyper0_csn0) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_csn01_i ( .T(1'b0), .I(hyper_cs_no[0][1]), .O(), .IO(FMC_hyper0_csn1) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_ck0_i ( .T(1'b0), .I(hyper_ck_o[0]), .O(), .IO(FMC_hyper0_ck) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_ckn0_i ( .T(1'b0), .I(hyper_ck_no[0]), .O(), .IO(FMC_hyper0_ckn) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_rwds0_i ( .T(~hyper_rwds_oe_o[0]), .I(hyper_rwds_o[0]), .O(hyper_rwds_i[0]), .IO(FMC_hyper0_rwds) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_rst0_i ( .T(1'b0), .I(hyper_reset_no[0]), .O(), .IO(FMC_hyper0_reset) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq00_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][0]), .O(hyper_dq_i[0][0]), .IO(FMC_hyper0_dqio0) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq01_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][1]), .O(hyper_dq_i[0][1]), .IO(FMC_hyper0_dqio1) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq02_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][2]), .O(hyper_dq_i[0][2]), .IO(FMC_hyper0_dqio2) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq03_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][3]), .O(hyper_dq_i[0][3]), .IO(FMC_hyper0_dqio3) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq04_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][4]), .O(hyper_dq_i[0][4]), .IO(FMC_hyper0_dqio4) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq05_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][5]), .O(hyper_dq_i[0][5]), .IO(FMC_hyper0_dqio5) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq06_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][6]), .O(hyper_dq_i[0][6]), .IO(FMC_hyper0_dqio6) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq07_i ( .T(~hyper_dq_oe_o[0]), .I(hyper_dq_o[0][7]), .O(hyper_dq_i[0][7]), .IO(FMC_hyper0_dqio7) ); + + // PHY1 + (* PULLDOWN = "YES" *) IOBUF iobuf_csn10_i ( .T(1'b0), .I(hyper_cs_no[1][0]), .O(), .IO(FMC_hyper1_csn0) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_csn11_i ( .T(1'b0), .I(hyper_cs_no[1][1]), .O(), .IO(FMC_hyper1_csn1) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_ck1_i ( .T(1'b0), .I(hyper_ck_o[1]), .O(), .IO(FMC_hyper1_ck) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_ckn1_i ( .T(1'b0), .I(hyper_ck_no[1]), .O(), .IO(FMC_hyper1_ckn) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_rwds1_i ( .T(~hyper_rwds_oe_o[1]), .I(hyper_rwds_o[1]), .O(hyper_rwds_i[1]), .IO(FMC_hyper1_rwds) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_rst1_i ( .T(1'b0), .I(hyper_reset_no[1]), .O(), .IO(FMC_hyper1_reset) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq10_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][0]), .O(hyper_dq_i[1][0]), .IO(FMC_hyper1_dqio0) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq11_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][1]), .O(hyper_dq_i[1][1]), .IO(FMC_hyper1_dqio1) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq12_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][2]), .O(hyper_dq_i[1][2]), .IO(FMC_hyper1_dqio2) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq13_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][3]), .O(hyper_dq_i[1][3]), .IO(FMC_hyper1_dqio3) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq14_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][4]), .O(hyper_dq_i[1][4]), .IO(FMC_hyper1_dqio4) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq15_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][5]), .O(hyper_dq_i[1][5]), .IO(FMC_hyper1_dqio5) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq16_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][6]), .O(hyper_dq_i[1][6]), .IO(FMC_hyper1_dqio6) ); + (* PULLDOWN = "YES" *) IOBUF iobuf_dq17_i ( .T(~hyper_dq_oe_o[1]), .I(hyper_dq_o[1][7]), .O(hyper_dq_i[1][7]), .IO(FMC_hyper1_dqio7) ); +`endif + ////////////////// // Cheshire SoC // ////////////////// @@ -417,8 +537,8 @@ module cheshire_top_xilinx ( .axi_ext_mst_rsp_o ( ), .axi_ext_slv_req_o ( ), .axi_ext_slv_rsp_i ( '0 ), - .reg_ext_slv_req_o ( ), - .reg_ext_slv_rsp_i ( '0 ), + .reg_ext_slv_req_o ( reg_ext_slv_req ), + .reg_ext_slv_rsp_i ( reg_ext_slv_rsp ), .intr_ext_i ( '0 ), .intr_ext_o ( ), .xeip_ext_o ( ), diff --git a/target/xilinx/src/phy_definitions.svh b/target/xilinx/src/phy_definitions.svh index a4d7798d..bf266bbc 100644 --- a/target/xilinx/src/phy_definitions.svh +++ b/target/xilinx/src/phy_definitions.svh @@ -20,7 +20,7 @@ `define USE_JTAG_TRSTN `define USE_SD `define USE_SWITCHES - `define USE_DDR3 + `define USE_HYPERRAM `define USE_FAN `define USE_VIO `define USE_I2C @@ -38,6 +38,9 @@ // DRAM INTERFACES // ///////////////////// +`ifdef USE_HYPERRAM +`define USE_HYPERBUS +`endif `ifdef USE_DDR4 `define USE_DDR `endif @@ -78,6 +81,36 @@ output [3:0] ddr3_dm, \ output [0:0] ddr3_odt, +`define HYPERBUS_INTF \ + inout FMC_hyper0_dqio0, \ + inout FMC_hyper0_dqio1, \ + inout FMC_hyper0_dqio2, \ + inout FMC_hyper0_dqio3, \ + inout FMC_hyper0_dqio4, \ + inout FMC_hyper0_dqio5, \ + inout FMC_hyper0_dqio6, \ + inout FMC_hyper0_dqio7, \ + inout FMC_hyper0_ck, \ + inout FMC_hyper0_ckn, \ + inout FMC_hyper0_csn0, \ + inout FMC_hyper0_csn1, \ + inout FMC_hyper0_rwds, \ + inout FMC_hyper0_reset, \ + inout FMC_hyper1_dqio0, \ + inout FMC_hyper1_dqio1, \ + inout FMC_hyper1_dqio2, \ + inout FMC_hyper1_dqio3, \ + inout FMC_hyper1_dqio4, \ + inout FMC_hyper1_dqio5, \ + inout FMC_hyper1_dqio6, \ + inout FMC_hyper1_dqio7, \ + inout FMC_hyper1_ck, \ + inout FMC_hyper1_ckn, \ + inout FMC_hyper1_csn0, \ + inout FMC_hyper1_csn1, \ + inout FMC_hyper1_rwds, \ + inout FMC_hyper1_reset, + `define ila(__name, __signal) \ (* dont_touch = "yes" *) (* mark_debug = "true" *) logic [$bits(__signal)-1:0] __name; \ assign __name = __signal;