diff --git a/Bender.yml b/Bender.yml index b33e3ea18..8abe29448 100644 --- a/Bender.yml +++ b/Bender.yml @@ -50,9 +50,9 @@ sources: - target/sim/src/fixture_cheshire_soc.sv - target/sim/src/tb_cheshire_soc.sv - - target: any(fpga, xilinx) + - target: all(fpga, xilinx) files: - target/xilinx/src/fan_ctrl.sv - - target/xilinx/src/dram_wrapper.sv + - target/xilinx/src/dram_wrapper_xilinx.sv - target/xilinx/src/phy_definitions.svh - target/xilinx/src/cheshire_top_xilinx.sv diff --git a/README.md b/README.md index 9d7df4101..90b1215ac 100644 --- a/README.md +++ b/README.md @@ -21,47 +21,6 @@ run -all If you have access to our internal servers, you can run `make nonfree-init` to fetch additional resources we cannot make publically accessible. Note that these are *not required* to use anything provided in this repository. -## Linux image - -To build the Linux image for FPGA: -```bash -# Clone and build GCC, OpenSBI, U-Boot and Linux -git clone git@github.com:pulp-platform/cva6-sdk.git --branch fix/cheshire -cd cva6-sdk -git submodule update --init --recursive -make images -# Link the output in the sw dir -ln -s cva6-sdk/install64 sw/boot/install64 -# Build the image at sw/boot/linux-[genesys2,vcu128].gpt.bin -make BOARD=[genesys2,vcu128] chs-linux-img - -``` - -On Genesys2, you can now flash this image to your sd card (require sudo). - -```bash -# Replace sdX by your SD card device -dd if=sw/boot/cheshire-linux-genesys2.gpt.bin of=/dev/sdX -``` - -On VCU128, you can now flash this image to the SPI using Vivado: - -```bash -# Define XILINX_PORT, XILINX_HOST, FPGA_PATH to let Vivado find your FPGA -# See defaults in xilinx.mk -make chs-xil-flash BOARD=vcu128 MODE=batch -``` - -## FPGA - -To build the bitstream for FPGA, initialize the repository with `make all` then run `make chs-xil-all` followed by desired arguments: - -* `BOARD=[genesys2,vcu128]`: select supported evaluation board (note `zcu102` is also supported but do not boot Linux as access to an SPI flash or an SD card is not implemented). -* `INT-JTAG=[1,0]`: (only on vcu128) connect the debugger to the intenal JTAG chain (see BSCANE2 primitive) or to an external JTAG dongle (if 0). -* `MODE=[batch,gui]`: open Vivado GUI or execute in shell. - -You can flash the bitstream from the GUI with `make chs-xil-gui` or directly in shell using `make chs-xil-program MODE=batch BOARD=[genesys2,vcu128]`. Here again you will need to define `XILINX_PORT`, `XILINX_HOST`, `FPGA_PATH` for your setup. At IIS, find default values in `carfield.mk`. - ## License Unless specified otherwise in the respective file headers, all code checked into this repository is made available under a permissive license. All hardware sources and tool scripts are licensed under the Solderpad Hardware License 0.51 (see `LICENSE`) with the exception of generated register file code (e.g. `hw/regs/*.sv`), which is generated by a fork of lowRISC's [`regtool`](https://github.com/lowRISC/opentitan/blob/master/util/regtool.py) and licensed under Apache 2.0. All software sources are licensed under Apache 2.0. diff --git a/cheshire.mk b/cheshire.mk index c1be81c0b..a0dba24a6 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -56,7 +56,7 @@ chs-clean-deps: ###################### CHS_NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:pulp-restricted/cheshire-nonfree.git -CHS_NONFREE_COMMIT ?= f70c019 +CHS_NONFREE_COMMIT ?= 1ee2e87 chs-nonfree-init: git clone $(CHS_NONFREE_REMOTE) $(CHS_ROOT)/nonfree @@ -162,7 +162,7 @@ CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl ############# include $(CHS_ROOT)/target/xilinx/xilinx.mk -include $(CHS_XIL_DIR)/sim/simulate.mk +include $(CHS_XIL_DIR)/sim/sim.mk CHS_XILINX_ALL += $(CHS_XIL_DIR)/scripts/add_sources.tcl CHS_LINUX_IMG += $(CHS_SW_DIR)/boot/linux-${BOARD}.gpt.bin diff --git a/docs/tg/xilinx.md b/docs/tg/xilinx.md index e6664988a..95b6625bf 100644 --- a/docs/tg/xilinx.md +++ b/docs/tg/xilinx.md @@ -7,6 +7,7 @@ This page describes how to map Cheshire on Xilinx FPGAs to *execute baremetal pr We currently provide working setups for: - Digilent Genesys 2 with Vivado `>= 2020.2` +- Xilinx VCU128 with Vivado `>= 2020.2` We are working on support for more boards in the future. @@ -19,9 +20,14 @@ Since the implementation steps and available features vary between boards, we pr Generate the bitstream `target/xilinx/out/cheshire_top_xilinx.bit` by running: ``` -make -C target/xilinx +make chs-xil-all BOARD=genesys2 MODE=[batch,gui] ``` +See the argument list below: + +* `VIVADO`: The Vivado version to use (see default in `target/xilinx/xilinx.mk`) +* `MODE`: If 'batch', compile in shell, if 'gui', Open Vivado GUI. + Before flashing the bitstream to your device, take note of the position of onboard switches, which control important functionality: @@ -33,6 +39,37 @@ Before flashing the bitstream to your device, take note of the position of onboa The reset, JTAG TAP, UART, I2C, and VGA are all connected to their onboard logic or ports. The UART has *no flow control*. The microSD slot is connected to chip select 0 of the SPI host peripheral. Serial link and GPIOs are currently not available. +### Xilinx VCU128 + +Generate the bitstream `target/xilinx/out/cheshire_top_xilinx.bit` by running: + +``` +make chs-xil-all BOARD=vcu128 MODE=[batch,gui] INT-JTAG=[0,1] +``` + +See the argument list below: + +* `INT-JTAG`: If 1, use an external JTAG chain (we use a Digilent JTAG-HS2 cable connected to the Xilinx XM105 FMC debug card). See the connections in `vcu128.xdc`. + + +As there are no switches on this board, the bootmode is selected by VIO (see next section). + +## Using the Vivado GUI + +Even after implementing your system in batch mode, you can open the Vivado GUI with: + +``` +make chs-xil-gui +``` + +In particular, it will give you access the to Virtual Inputs Outputs (VIOs) after flashing/refreshing the FPGA: + + | VIO | Function | + | ----------------- | ----------------------------------------------------------------| + | vio_reset | Positive edge-sensitive reset for the whole system | + | vio_boot_mode | Override the boot-mode switches described above | + | vio_boot_mode_sel | Select between 0: using boot mode switches 1: use boot mode VIO | + ## Debugging with OpenOCD To establish a debug bridge over JTAG, ensure the target is in a debuggable state (for example by resetting into the idle boot mode 0) and launch OpenOCD with: @@ -86,7 +123,7 @@ First, build an up-to-date a disk image for your desired binary. For `helloworld make sw/tests/helloworld.gpt.bin ``` -Then flash this image to an SD card (*note that this requires root privileges*): +Then flash this image to an SD card (for Genesys2) (*note that this requires root privileges*): ``` sudo dd if=sw/tests/helloworld.gpt.bin of=/dev/ @@ -115,9 +152,12 @@ In this case, OpenSBI is loaded by a regular baremetal program called the [Zero- To create a full Linux disk image from the ZSL, device tree, firmware, and Linux, run: ``` -make sw/boot/linux.gpt.bin +# Note that the device tree depends from the board's peripherals +make chs-linux-img BOARD=[genesys2, vcu128] ``` +### Digilent Genesys 2 + Flash this image to an SD card as you did in the previous section, then insert the SD card and reset into boot mode 1. You should first see the ZSL print on the UART: ``` @@ -131,3 +171,19 @@ Flash this image to an SD card as you did in the previous section, then insert t ( )))))))))) ``` You should then boot through OpenSBI, U-Boot, and Linux until you are dropped into a shell. + +### Xilinx VCU128 + +This board does not offer a SD card reader. We use the integrated flash: + +``` +make chs-xil-flash MODE=batch BOARD=vcu128 +``` + +Use the following parameters (defaults are in `target/xilinx/xilinx.mk`) to select your board: + +* XILINX_PART : The FPGA part (leave to default) +* XILINX_BOARD : The FPGA board (leave to default) +* XILINX_HOST : The server where your board is connected (or localhost) +* XILINX_PORT : The port opened by Vivado for your board (Vivado usually sets it to 3121) +* VIVADO_PATH : The path to your board as seen in the Vivado Hardware Manager (usually xilinx_tcf/Xilinx/`SerialID`) diff --git a/sw/lib/hal/uart_debug.c b/sw/lib/hal/uart_debug.c index 258777345..a03acaeb4 100644 --- a/sw/lib/hal/uart_debug.c +++ b/sw/lib/hal/uart_debug.c @@ -24,7 +24,7 @@ int uart_debug_init(void *uart_base, uint64_t core_freq) { CHECK_ASSERT(0x11, uart_base != 0); CHECK_ASSERT(0x12, core_freq != 0); // The UART debug mode uses the sane default 115.2kBaud - uart_init(uart_base, core_freq, 115200); + uart_init(uart_base, core_freq, __BAUDRATE); fence(); // Nothing went wrong return 0; diff --git a/sw/sw.mk b/sw/sw.mk index 2a57c9614..c416f1848 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -140,7 +140,7 @@ $(foreach link,$(patsubst $(CHS_SW_LD_DIR)/%.ld,%,$(wildcard $(CHS_SW_LD_DIR)/*. CHS_CVA6_SDK_IMGS ?= $(addprefix $(CHS_SW_DIR)/deps/cva6-sdk/install64/,fw_payload.bin uImage) # Create full Linux disk image -$(CHS_SW_DIR)/boot/linux-${BOARD}.gpt.bin: $(CHS_SW_DIR)/boot/zsl.rom.bin $(CHS_SW_DIR)/boot/cheshire_$(BOARD).dtb $(CHS_SW_DIR)/boot/install64/fw_payload.bin $(CHS_SW_DIR)/boot/install64/uImage +$(CHS_SW_DIR)/boot/linux-${BOARD}.gpt.bin: $(CHS_SW_DIR)/boot/zsl.rom.bin $(CHS_SW_DIR)/boot/cheshire_$(BOARD).dtb $(CHS_CVA6_SDK_IMGS) truncate -s $(CHS_SW_DISK_SIZE) $@ sgdisk --clear -g --set-alignment=1 \ --new=1:64:96 --typecode=1:$(CHS_SW_ZSL_TGUID) \ diff --git a/sw/tests/helloworld.c b/sw/tests/helloworld.c index df250626a..12f39c3bf 100644 --- a/sw/tests/helloworld.c +++ b/sw/tests/helloworld.c @@ -17,7 +17,7 @@ int main(void) { char str[] = "Hello World!\r\n"; uint32_t rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); uint64_t reset_freq = clint_get_core_freq(rtc_freq, 2500); - uart_init(&__base_uart, reset_freq, 115200); + uart_init(&__base_uart, reset_freq, __BAUDRATE); uart_write_str(&__base_uart, str, sizeof(str)); uart_write_flush(&__base_uart); return 0; diff --git a/target/xilinx/constraints/genesys2.xdc b/target/xilinx/constraints/genesys2.xdc index ecfb43f57..ef635363c 100644 --- a/target/xilinx/constraints/genesys2.xdc +++ b/target/xilinx/constraints/genesys2.xdc @@ -63,8 +63,8 @@ set_max_delay -datapath \ # VGA # ####### -# set_output_delay -min -clock $soc_clk [expr $SOC_TCK * 0.10] [get_ports vga*] -# set_output_delay -max -clock $soc_clk [expr $SOC_TCK * 0.35] [get_ports vga*] +set_output_delay -min -clock $soc_clk [expr $SOC_TCK * 0.10] [get_ports vga*] +set_output_delay -max -clock $soc_clk [expr $SOC_TCK * 0.35] [get_ports vga*] ############ # Switches # @@ -95,11 +95,11 @@ set_output_delay -max -clock $soc_clk [expr 0.20 * $SOC_TCK] [get_ports {sd_d_* # I2C # ####### -# set_max_delay [expr $I2C_IO_SPEED * 0.35] -from [get_ports {i2c_scl_io i2c_sda_io}] -# set_false_path -hold -from [get_ports {i2c_scl_io i2c_sda_io}] +set_max_delay [expr $I2C_IO_SPEED * 0.35] -from [get_ports {i2c_scl_io i2c_sda_io}] +set_false_path -hold -from [get_ports {i2c_scl_io i2c_sda_io}] -# set_max_delay [expr $I2C_IO_SPEED * 0.35] -to [get_ports {i2c_scl_io i2c_sda_io}] -# set_false_path -hold -to [get_ports {i2c_scl_io i2c_sda_io}] +set_max_delay [expr $I2C_IO_SPEED * 0.35] -to [get_ports {i2c_scl_io i2c_sda_io}] +set_false_path -hold -to [get_ports {i2c_scl_io i2c_sda_io}] ################################################################################# @@ -188,27 +188,27 @@ set_property -dict { PACKAGE_PIN R28 IOSTANDARD LVCMOS33 } [get_ports { sd_scl #set_property -dict { PACKAGE_PIN AK14 IOSTANDARD LVCMOS15 } [get_ports { ETH_TX_EN }]; #IO_L20P_T3_33 Sch=eth_tx_en ## VGA Connector -# set_property -dict { PACKAGE_PIN AH20 IOSTANDARD LVCMOS33 } [get_ports { vga_b[0] }]; #IO_L22N_T3_12 Sch=vga_b[3] -# set_property -dict { PACKAGE_PIN AG20 IOSTANDARD LVCMOS33 } [get_ports { vga_b[1] }]; #IO_L22P_T3_12 Sch=vga_b[4] -# set_property -dict { PACKAGE_PIN AF21 IOSTANDARD LVCMOS33 } [get_ports { vga_b[2] }]; #IO_L19N_T3_VREF_12 Sch=vga_b[5] -# set_property -dict { PACKAGE_PIN AK20 IOSTANDARD LVCMOS33 } [get_ports { vga_b[3] }]; #IO_L24P_T3_12 Sch=vga_b[6] -# set_property -dict { PACKAGE_PIN AG22 IOSTANDARD LVCMOS33 } [get_ports { vga_b[4] }]; #IO_L20P_T3_12 Sch=vga_b[7] - -# set_property -dict { PACKAGE_PIN AJ23 IOSTANDARD LVCMOS33 } [get_ports { vga_g[0] }]; #IO_L21N_T3_DQS_12 Sch=vga_g[2] -# set_property -dict { PACKAGE_PIN AJ22 IOSTANDARD LVCMOS33 } [get_ports { vga_g[1] }]; #IO_L21P_T3_DQS_12 Sch=vga_g[3] -# set_property -dict { PACKAGE_PIN AH22 IOSTANDARD LVCMOS33 } [get_ports { vga_g[2] }]; #IO_L20N_T3_12 Sch=vga_g[4] -# set_property -dict { PACKAGE_PIN AK21 IOSTANDARD LVCMOS33 } [get_ports { vga_g[3] }]; #IO_L24N_T3_12 Sch=vga_g[5] -# set_property -dict { PACKAGE_PIN AJ21 IOSTANDARD LVCMOS33 } [get_ports { vga_g[4] }]; #IO_L23N_T3_12 Sch=vga_g[6] -# set_property -dict { PACKAGE_PIN AK23 IOSTANDARD LVCMOS33 } [get_ports { vga_g[5] }]; #IO_L17P_T2_12 Sch=vga_g[7] - -# set_property -dict { PACKAGE_PIN AK25 IOSTANDARD LVCMOS33 } [get_ports { vga_r[0] }]; #IO_L15N_T2_DQS_12 Sch=vga_r[3] -# set_property -dict { PACKAGE_PIN AG25 IOSTANDARD LVCMOS33 } [get_ports { vga_r[1] }]; #IO_L18P_T2_12 Sch=vga_r[4] -# set_property -dict { PACKAGE_PIN AH25 IOSTANDARD LVCMOS33 } [get_ports { vga_r[2] }]; #IO_L18N_T2_12 Sch=vga_r[5] -# set_property -dict { PACKAGE_PIN AK24 IOSTANDARD LVCMOS33 } [get_ports { vga_r[3] }]; #IO_L17N_T2_12 Sch=vga_r[6] -# set_property -dict { PACKAGE_PIN AJ24 IOSTANDARD LVCMOS33 } [get_ports { vga_r[4] }]; #IO_L15P_T2_DQS_12 Sch=vga_r[7] - -# set_property -dict { PACKAGE_PIN AF20 IOSTANDARD LVCMOS33 } [get_ports { vga_hs }]; #IO_L19P_T3_12 Sch=vga_hs -# set_property -dict { PACKAGE_PIN AG23 IOSTANDARD LVCMOS33 } [get_ports { vga_vs }]; #IO_L13N_T2_MRCC_12 Sch=vga_vs +set_property -dict { PACKAGE_PIN AH20 IOSTANDARD LVCMOS33 } [get_ports { vga_b[0] }]; #IO_L22N_T3_12 Sch=vga_b[3] +set_property -dict { PACKAGE_PIN AG20 IOSTANDARD LVCMOS33 } [get_ports { vga_b[1] }]; #IO_L22P_T3_12 Sch=vga_b[4] +set_property -dict { PACKAGE_PIN AF21 IOSTANDARD LVCMOS33 } [get_ports { vga_b[2] }]; #IO_L19N_T3_VREF_12 Sch=vga_b[5] +set_property -dict { PACKAGE_PIN AK20 IOSTANDARD LVCMOS33 } [get_ports { vga_b[3] }]; #IO_L24P_T3_12 Sch=vga_b[6] +set_property -dict { PACKAGE_PIN AG22 IOSTANDARD LVCMOS33 } [get_ports { vga_b[4] }]; #IO_L20P_T3_12 Sch=vga_b[7] + +set_property -dict { PACKAGE_PIN AJ23 IOSTANDARD LVCMOS33 } [get_ports { vga_g[0] }]; #IO_L21N_T3_DQS_12 Sch=vga_g[2] +set_property -dict { PACKAGE_PIN AJ22 IOSTANDARD LVCMOS33 } [get_ports { vga_g[1] }]; #IO_L21P_T3_DQS_12 Sch=vga_g[3] +set_property -dict { PACKAGE_PIN AH22 IOSTANDARD LVCMOS33 } [get_ports { vga_g[2] }]; #IO_L20N_T3_12 Sch=vga_g[4] +set_property -dict { PACKAGE_PIN AK21 IOSTANDARD LVCMOS33 } [get_ports { vga_g[3] }]; #IO_L24N_T3_12 Sch=vga_g[5] +set_property -dict { PACKAGE_PIN AJ21 IOSTANDARD LVCMOS33 } [get_ports { vga_g[4] }]; #IO_L23N_T3_12 Sch=vga_g[6] +set_property -dict { PACKAGE_PIN AK23 IOSTANDARD LVCMOS33 } [get_ports { vga_g[5] }]; #IO_L17P_T2_12 Sch=vga_g[7] + +set_property -dict { PACKAGE_PIN AK25 IOSTANDARD LVCMOS33 } [get_ports { vga_r[0] }]; #IO_L15N_T2_DQS_12 Sch=vga_r[3] +set_property -dict { PACKAGE_PIN AG25 IOSTANDARD LVCMOS33 } [get_ports { vga_r[1] }]; #IO_L18P_T2_12 Sch=vga_r[4] +set_property -dict { PACKAGE_PIN AH25 IOSTANDARD LVCMOS33 } [get_ports { vga_r[2] }]; #IO_L18N_T2_12 Sch=vga_r[5] +set_property -dict { PACKAGE_PIN AK24 IOSTANDARD LVCMOS33 } [get_ports { vga_r[3] }]; #IO_L17N_T2_12 Sch=vga_r[6] +set_property -dict { PACKAGE_PIN AJ24 IOSTANDARD LVCMOS33 } [get_ports { vga_r[4] }]; #IO_L15P_T2_DQS_12 Sch=vga_r[7] + +set_property -dict { PACKAGE_PIN AF20 IOSTANDARD LVCMOS33 } [get_ports { vga_hs }]; #IO_L19P_T3_12 Sch=vga_hs +set_property -dict { PACKAGE_PIN AG23 IOSTANDARD LVCMOS33 } [get_ports { vga_vs }]; #IO_L13N_T2_MRCC_12 Sch=vga_vs ## HDMI in #set_property -dict { PACKAGE_PIN Y21 IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_cec }]; #IO_L2P_T0_12 Sch=hdmi_rx_cec @@ -506,8 +506,8 @@ set_property -dict { PACKAGE_PIN Y29 IOSTANDARD LVCMOS33 } [get_ports { jtag_t #set_property -dict { PACKAGE_PIN R21 IOSTANDARD LVCMOS33 } [get_ports { QSPI_D[3] }]; #IO_L2N_T0_D03_14 Sch=qspi_d[3] ## IIC Bus -# set_property -dict { PACKAGE_PIN AE30 IOSTANDARD LVCMOS33 } [get_ports { i2c_scl_io }]; #IO_L16P_T2_13 Sch=sys_scl -# set_property -dict { PACKAGE_PIN AF30 IOSTANDARD LVCMOS33 } [get_ports { i2c_sda_io }]; #IO_L16N_T2_13 Sch=sys_sda +set_property -dict { PACKAGE_PIN AE30 IOSTANDARD LVCMOS33 } [get_ports { i2c_scl_io }]; #IO_L16P_T2_13 Sch=sys_scl +set_property -dict { PACKAGE_PIN AF30 IOSTANDARD LVCMOS33 } [get_ports { i2c_sda_io }]; #IO_L16N_T2_13 Sch=sys_sda ## Display Port IN #set_property -dict { PACKAGE_PIN AC19 IOSTANDARD LVCMOS18 } [get_ports { RX_AUX_IN_CH_N }]; #IO_L17N_T2_32 Sch=rx_aux_ch_n diff --git a/target/xilinx/sim/simulate.mk b/target/xilinx/sim/sim.mk similarity index 100% rename from target/xilinx/sim/simulate.mk rename to target/xilinx/sim/sim.mk diff --git a/target/xilinx/src/cheshire_top_xilinx.sv b/target/xilinx/src/cheshire_top_xilinx.sv index 63072e784..265df78f1 100644 --- a/target/xilinx/src/cheshire_top_xilinx.sv +++ b/target/xilinx/src/cheshire_top_xilinx.sv @@ -297,7 +297,7 @@ module cheshire_top_xilinx ////////////// `ifdef USE_DDR - dram_wrapper #( + dram_wrapper_xilinx #( .axi_soc_aw_chan_t ( axi_llc_aw_chan_t ), .axi_soc_w_chan_t ( axi_llc_w_chan_t ), .axi_soc_b_chan_t ( axi_llc_b_chan_t ), diff --git a/target/xilinx/src/dram_wrapper.sv b/target/xilinx/src/dram_wrapper_xilinx.sv similarity index 99% rename from target/xilinx/src/dram_wrapper.sv rename to target/xilinx/src/dram_wrapper_xilinx.sv index 4c7de91e9..106986164 100644 --- a/target/xilinx/src/dram_wrapper.sv +++ b/target/xilinx/src/dram_wrapper_xilinx.sv @@ -9,7 +9,7 @@ `include "phy_definitions.svh" `include "common_cells/registers.svh" -module dram_wrapper #( +module dram_wrapper_xilinx #( parameter type axi_soc_aw_chan_t = logic, parameter type axi_soc_w_chan_t = logic, parameter type axi_soc_b_chan_t = logic, diff --git a/target/xilinx/src/phy_definitions.svh b/target/xilinx/src/phy_definitions.svh index faae81bb1..41e33536d 100644 --- a/target/xilinx/src/phy_definitions.svh +++ b/target/xilinx/src/phy_definitions.svh @@ -23,6 +23,8 @@ `define USE_DDR3 `define USE_FAN `define USE_VIO + `define USE_I2C + `define USE_VGA `endif `ifdef TARGET_ZCU102