diff --git a/data/pins_sonata.xdc b/data/pins_sonata.xdc new file mode 100644 index 000000000..8da3333e5 --- /dev/null +++ b/data/pins_sonata.xdc @@ -0,0 +1,78 @@ +## Copyright lowRISC contributors. +## Licensed under the Apache License, Version 2.0, see LICENSE for details. +## SPDX-License-Identifier: Apache-2.0 + +# Using the names in the PCB design, they should match this file with a case-insensitive search: +# https://github.com/newaetech/sonata-pcb/tree/main + +## Clocks +create_clock -period 40.000 -name mainClk -waveform {0.000 20.000} [get_ports mainClk] + +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports mainClk]; + +## Reset +set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports {nrst}]; + +## General purpose LEDs +set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports {usrLed[0]}]; +set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports {usrLed[1]}]; +set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports {usrLed[2]}]; +set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports {usrLed[3]}]; +set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports {usrLed[4]}]; +set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports {usrLed[5]}]; +set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports {usrLed[6]}]; +set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports {usrLed[7]}]; + +set_output_delay -clock mainClk 0.000 [get_ports usrLed] + +## Switch and button input +set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports {usrSw[0]}]; +set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports {usrSw[1]}]; +set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports {usrSw[2]}]; +set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports {usrSw[3]}]; +set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports {usrSw[4]}]; +set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports {usrSw[5]}]; +set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports {usrSw[6]}]; +set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports {usrSw[7]}]; +set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS18 } [get_ports {navSw[0]}]; +set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS18 } [get_ports {navSw[1]}]; +set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS18 } [get_ports {navSw[2]}]; +set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS18 } [get_ports {navSw[3]}]; +set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS18 } [get_ports {navSw[4]}]; + +## CHERI error LEDs +set_property -dict { PACKAGE_PIN K6 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[0]}]; +set_property -dict { PACKAGE_PIN L1 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[1]}]; +set_property -dict { PACKAGE_PIN M1 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[2]}]; +set_property -dict { PACKAGE_PIN K3 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[3]}]; +set_property -dict { PACKAGE_PIN L3 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[4]}]; +set_property -dict { PACKAGE_PIN N2 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[5]}]; +set_property -dict { PACKAGE_PIN N1 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[6]}]; +set_property -dict { PACKAGE_PIN M3 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[7]}]; +set_property -dict { PACKAGE_PIN M2 IOSTANDARD LVCMOS33 } [get_ports {cheriErr[8]}]; + +## Status LEDs +set_property -dict { PACKAGE_PIN K5 IOSTANDARD LVCMOS33 } [get_ports led_legacy]; +set_property -dict { PACKAGE_PIN L4 IOSTANDARD LVCMOS33 } [get_ports led_cheri]; +set_property -dict { PACKAGE_PIN L6 IOSTANDARD LVCMOS33 } [get_ports led_halted]; +set_property -dict { PACKAGE_PIN L5 IOSTANDARD LVCMOS33 } [get_ports led_bootok]; + +## LCD display +set_property -dict { PACKAGE_PIN R6 IOSTANDARD LVCMOS33 } [get_ports lcd_rst]; +set_property -dict { PACKAGE_PIN U4 IOSTANDARD LVCMOS33 } [get_ports lcd_dc]; +set_property -dict { PACKAGE_PIN R3 IOSTANDARD LVCMOS33 } [get_ports lcd_copi]; +set_property -dict { PACKAGE_PIN R5 IOSTANDARD LVCMOS33 } [get_ports lcd_clk]; +set_property -dict { PACKAGE_PIN P5 IOSTANDARD LVCMOS33 } [get_ports lcd_cs]; + +## UART +set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports ser0_tx]; +set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports ser0_rx]; + +## Switches +set_property PULLTYPE PULLUP [get_ports usrSw[*]] +set_property PULLTYPE PULLUP [get_ports navSw[*]] + +## Voltage +set_property CFGBVS VCCO [current_design] +set_property CONFIG_VOLTAGE 3.3 [current_design] +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] diff --git a/doc/guide/getting-started.md b/doc/guide/getting-started.md index 4f065e189..ae8d96f31 100644 --- a/doc/guide/getting-started.md +++ b/doc/guide/getting-started.md @@ -172,9 +172,13 @@ Then run this command: fusesoc --cores-root=. run --target=synth --setup --build lowrisc:sonata:system ``` +For the Arty A7 use the `synth_artya7` target. + ### Programming Programming the FPGA: ```sh -openFPGALoader -b arty_a7_35t build/lowrisc_sonata_system_0/synth-vivado/lowrisc_sonata_system_0.bit +openFPGALoader -c ft4232 build/lowrisc_sonata_system_0/synth-vivado/lowrisc_sonata_system_0.bit ``` + +For the Arty A7 use `-b arty_a7_35t` instead of `-c ft4232`. diff --git a/rtl/fpga/clkgen_sonata.sv b/rtl/fpga/clkgen_sonata.sv new file mode 100644 index 000000000..d216f67f6 --- /dev/null +++ b/rtl/fpga/clkgen_sonata.sv @@ -0,0 +1,83 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +module clkgen_sonata ( + input IO_CLK, + output IO_CLK_BUF, + input IO_RST_N, + output clk_sys, + output rst_sys_n +); + logic locked_pll; + logic io_clk_buf; + logic clk_50_buf; + logic clk_50_unbuf; + logic clk_fb_buf; + logic clk_fb_unbuf; + + // input buffer + IBUF io_clk_ibuf( + .I (IO_CLK), + .O (io_clk_buf) + ); + + PLLE2_ADV #( + .BANDWIDTH ("OPTIMIZED"), + .COMPENSATION ("ZHOLD"), + .STARTUP_WAIT ("FALSE"), + .DIVCLK_DIVIDE (1), + .CLKFBOUT_MULT (34), + .CLKFBOUT_PHASE (0.000), + .CLKOUT0_DIVIDE (17), + .CLKOUT0_PHASE (0.000), + .CLKOUT0_DUTY_CYCLE (0.500), + .CLKIN1_PERIOD (40.000) + ) pll ( + .CLKFBOUT (clk_fb_unbuf), + .CLKOUT0 (clk_50_unbuf), + .CLKOUT1 (), + .CLKOUT2 (), + .CLKOUT3 (), + .CLKOUT4 (), + .CLKOUT5 (), + // Input clock control + .CLKFBIN (clk_fb_buf), + .CLKIN1 (io_clk_buf), + .CLKIN2 (1'b0), + // Tied to always select the primary input clock + .CLKINSEL (1'b1), + // Ports for dynamic reconfiguration + .DADDR (7'h0), + .DCLK (1'b0), + .DEN (1'b0), + .DI (16'h0), + .DO (), + .DRDY (), + .DWE (1'b0), + // Other control and status signals + .LOCKED (locked_pll), + .PWRDWN (1'b0), + // Do not reset PLL on external reset, otherwise ILA disconnects at a reset + .RST (1'b0)); + + // output buffering + BUFG clk_fb_bufg ( + .I (clk_fb_unbuf), + .O (clk_fb_buf) + ); + + BUFG clk_50_bufg ( + .I (clk_50_unbuf), + .O (clk_50_buf) + ); + + assign IO_CLK_BUF = io_clk_buf; + + // outputs + // clock + assign clk_sys = clk_50_buf; + + // reset + assign rst_sys_n = locked_pll & IO_RST_N; +endmodule diff --git a/rtl/fpga/top_sonata.sv b/rtl/fpga/top_sonata.sv new file mode 100644 index 000000000..0932d7f55 --- /dev/null +++ b/rtl/fpga/top_sonata.sv @@ -0,0 +1,94 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Sonata system top level for the Sonata PCB +module top_sonata ( + input logic mainClk, + input logic nrst, + + output logic [7:0] usrLed, + output logic led_bootok, + output logic led_halted, + output logic led_cheri, + output logic led_legacy, + output logic [8:0] cheriErr, + + input logic [4:0] navSw, + input logic [7:0] usrSw, + + output logic lcd_rst, + output logic lcd_dc, + output logic lcd_copi, + output logic lcd_clk, + output logic lcd_cs, + + output logic ser0_tx, + input logic ser0_rx +); + parameter SRAMInitFile = ""; + + logic top_rst_n; + logic main_clk_buf; + logic clk_sys, rst_sys_n; + logic [7:0] reset_counter; + + logic [4:0] nav_sw_n; + logic [7:0] user_sw_n; + + initial begin + reset_counter = 0; + end + + always_ff @(posedge main_clk_buf) begin + if (reset_counter != 8'hff) begin + reset_counter <= reset_counter + 8'd1; + end + end + + assign top_rst_n = reset_counter < 8'd5 ? 1'b1 : + reset_counter < 8'd200 ? 1'b0 : + nrst ; + + assign led_bootok = 1'b1; + + // Switch inputs have pull-ups and switches pull to ground when on. Invert here so CPU sees 1 for + // on and 0 for off. + assign nav_sw_n = ~navSw; + assign user_sw_n = ~usrSw; + + // No LCD backlight FPGA IO on v0.2 board, so leave this unconnected. + logic lcd_backlight; + + sonata_system #( + .GpiWidth ( 13 ), + .GpoWidth ( 12 ), + .PwmWidth ( 12 ), + .SRAMInitFile( SRAMInitFile ) + ) u_sonata_system ( + .clk_sys_i (clk_sys), + .rst_sys_ni(rst_sys_n), + + .gp_i({user_sw_n, nav_sw_n}), + .gp_o({usrLed, lcd_backlight, lcd_dc, lcd_rst, lcd_cs}), + + .uart_rx_i(ser0_rx), + .uart_tx_o(ser0_tx), + + .pwm_o({CheriErr, led_legacy, led_cheri, led_halted}), + + .spi_rx_i (1'b0), + .spi_tx_o (lcd_copi), + .spi_sck_o(lcd_clk) + ); + + // Produce 50 MHz system clock from 25 MHz Sonata board clock. + clkgen_sonata clkgen( + .IO_CLK (mainClk), + .IO_CLK_BUF(main_clk_buf), + .IO_RST_N (top_rst_n), + .clk_sys, + .rst_sys_n + ); + +endmodule diff --git a/sonata.core b/sonata.core index d02049e2c..cd7761071 100644 --- a/sonata.core +++ b/sonata.core @@ -9,7 +9,16 @@ filesets: depend: - lowrisc:sonata:design - files_xilinx: + files_sonata: + depend: + - lowrisc:ibex:rv_timer + - lowrisc:ibex:fpga_xilinx_shared + files: + - rtl/fpga/top_sonata.sv + - rtl/fpga/clkgen_sonata.sv + file_type: systemVerilogSource + + files_artya7: depend: - lowrisc:ibex:rv_timer - lowrisc:ibex:fpga_xilinx_shared @@ -29,7 +38,12 @@ filesets: - dv/verilator/sonata_system_main.cc: { file_type: cppSource } - dv/verilator/sonata_verilator_lint.vlt: { file_type: vlt } - files_constraints: + files_constraints_sonata: + files: + - data/pins_sonata.xdc + file_type: xdc + + files_constraints_artya7: files: - data/pins_artya7.xdc file_type: xdc @@ -57,16 +71,31 @@ targets: default: &default_target filesets: - files_rtl + synth: <<: *default_target default_tool: vivado filesets_append: - - files_xilinx - - files_constraints + - files_sonata + - files_constraints_sonata + toplevel: top_sonata + tools: + vivado: + part: "xc7a50tcsg324-1" # Artix-7 50T + parameters: + - SRAMInitFile + - PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx + + synth_artya7: + <<: *default_target + default_tool: vivado + filesets_append: + - files_artya7 + - files_constraints_artya7 toplevel: top_artya7 tools: vivado: - part: "xc7a35tcsg324-1" # Default to Arty A7-35 + part: "xc7a35tcsg324-1" # Arty A7-35T parameters: - SRAMInitFile - PRIM_DEFAULT_IMPL=prim_pkg::ImplXilinx