From 1946ed619761084da0168b88ffe0f8ce95f31d13 Mon Sep 17 00:00:00 2001 From: Marno van der Maas Date: Tue, 16 Jan 2024 14:58:10 +0000 Subject: [PATCH] Add support for Sonata PCB This commit assumes revision 0.2 of the board. It adds a pin file, a top level module, a clock generator and the appropriate changes to the core file. It also updates the getting started guide to use the Sonata PCB by default. This commit is derived from a PR in the demo system: https://github.com/lowRISC/ibex-demo-system/pull/86 --- data/pins_sonata.xdc | 85 +++++++++++++++++++++++++++++++ doc/guide/getting-started.md | 6 ++- rtl/fpga/clkgen_sonata.sv | 83 ++++++++++++++++++++++++++++++ rtl/fpga/top_sonata.sv | 99 ++++++++++++++++++++++++++++++++++++ sonata.core | 39 ++++++++++++-- 5 files changed, 306 insertions(+), 6 deletions(-) create mode 100644 data/pins_sonata.xdc create mode 100644 rtl/fpga/clkgen_sonata.sv create mode 100644 rtl/fpga/top_sonata.sv diff --git a/data/pins_sonata.xdc b/data/pins_sonata.xdc new file mode 100644 index 000000000..837cedace --- /dev/null +++ b/data/pins_sonata.xdc @@ -0,0 +1,85 @@ +## Copyright lowRISC contributors. +## Licensed under the Apache License, Version 2.0, see LICENSE for details. +## SPDX-License-Identifier: Apache-2.0 + +## Clocks +create_clock -period 40.000 -name mainclk -waveform {0.000 20.000} [get_ports main_clk] +create_clock -period 100.000 -name tck -waveform {0.000 50.000} [get_ports tck_i] + +## Reset +set_property PACKAGE_PIN R11 [get_ports {nrst_btn}] +set_property IOSTANDARD LVCMOS33 [get_ports {nrst_btn}] + +## General purpose LEDs +set_property -dict { PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports {led_user[0]}]; +set_property -dict { PACKAGE_PIN B14 IOSTANDARD LVCMOS33 } [get_ports {led_user[1]}]; +set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports {led_user[2]}]; +set_property -dict { PACKAGE_PIN B12 IOSTANDARD LVCMOS33 } [get_ports {led_user[3]}]; +set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports {led_user[4]}]; +set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports {led_user[5]}]; +set_property -dict { PACKAGE_PIN F13 IOSTANDARD LVCMOS33 } [get_ports {led_user[6]}]; +set_property -dict { PACKAGE_PIN F14 IOSTANDARD LVCMOS33 } [get_ports {led_user[7]}]; + +## JTAG test +set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports tck_i]; +set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports td_i]; +set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports td_o]; +set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports tms_i]; + +## Switch and button input +set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports {user_sw[0]}]; +set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports {user_sw[1]}]; +set_property -dict { PACKAGE_PIN B16 IOSTANDARD LVCMOS33 } [get_ports {user_sw[2]}]; +set_property -dict { PACKAGE_PIN B17 IOSTANDARD LVCMOS33 } [get_ports {user_sw[3]}]; +set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports {user_sw[4]}]; +set_property -dict { PACKAGE_PIN A16 IOSTANDARD LVCMOS33 } [get_ports {user_sw[5]}]; +set_property -dict { PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports {user_sw[6]}]; +set_property -dict { PACKAGE_PIN A14 IOSTANDARD LVCMOS33 } [get_ports {user_sw[7]}]; +set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS18 } [get_ports {nav_sw[0]}]; +set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS18 } [get_ports {nav_sw[1]}]; +set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS18 } [get_ports {nav_sw[2]}]; +set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS18 } [get_ports {nav_sw[3]}]; +set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS18 } [get_ports {nav_sw[4]}]; + +## CHERI error LEDs +set_property -dict { PACKAGE_PIN K6 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[0]}]; +set_property -dict { PACKAGE_PIN L1 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[1]}]; +set_property -dict { PACKAGE_PIN M1 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[2]}]; +set_property -dict { PACKAGE_PIN K3 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[3]}]; +set_property -dict { PACKAGE_PIN L3 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[4]}]; +set_property -dict { PACKAGE_PIN N2 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[5]}]; +set_property -dict { PACKAGE_PIN N1 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[6]}]; +set_property -dict { PACKAGE_PIN M3 IOSTANDARD LVCMOS33 } [get_ports {led_cherierr[7]}]; +set_property -dict { PACKAGE_PIN M2 IOSTANDARD LVCMOS33 } [get_ports {led_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 user_sw[*]] +set_property PULLTYPE PULLUP [get_ports nav_sw[*]] + + +set_output_delay -clock main_clk 0.000 [get_ports led_user] + +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports main_clk]; + +set_property CFGBVS VCCO [current_design] +set_property CONFIG_VOLTAGE 3.3 [current_design] +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] + +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets tck_i] 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..11cd30d3b --- /dev/null +++ b/rtl/fpga/top_sonata.sv @@ -0,0 +1,99 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Ibex demo system top level for the Sonata board +module top_sonata ( + input main_clk, + input nrst_btn, + + output logic [7:0] led_user, + output logic led_bootok, + output logic led_halted, + output logic led_cheri, + output logic led_legacy, + output logic [8:0] led_cherierr, + + input logic [4:0] nav_sw, + input logic [7:0] user_sw, + + 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, + + input logic tck_i, + input logic tms_i, + input logic td_i, + output logic td_o +); + parameter SRAMInitFile = ""; + + logic top_rst_n; + logic mainclk_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 mainclk_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_btn; + + 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 = ~nav_sw; + assign user_sw_n = ~user_sw; + + // 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({led_user, lcd_backlight, lcd_dc, lcd_rst, lcd_cs}), + + .uart_rx_i(ser0_rx), + .uart_tx_o(ser0_tx), + + .pwm_o({led_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 (main_clk), + .IO_CLK_BUF(mainclk_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