diff --git a/data/pins_sonata.xdc b/data/pins_sonata.xdc
index 5cea66eec..2f1202f8d 100644
--- a/data/pins_sonata.xdc
+++ b/data/pins_sonata.xdc
@@ -239,6 +239,12 @@ set_property PULLTYPE PULLUP [get_ports rph_g1]
set_property PULLTYPE PULLUP [get_ports rph_g0]
## Arduino Shield
+## ICSP - hijacked for Sonata Trace port.
+set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports ah_tmpio14]
+set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports ah_tmpio15]
+set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports ah_tmpio17]
+## GPIO
+set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports ah_tmpio16]
## SPI SCLK
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 IO_BUFFER_TYPE NONE } [get_ports ah_tmpio13]
## SPI CIPO
diff --git a/doc/img/sonata-development-system.svg b/doc/img/sonata-development-system.svg
index 897bf89ba..cb4926103 100644
--- a/doc/img/sonata-development-system.svg
+++ b/doc/img/sonata-development-system.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/dv/verilator/top_verilator.sv b/dv/verilator/top_verilator.sv
index d0ec78daf..7821adfa5 100644
--- a/dv/verilator/top_verilator.sv
+++ b/dv/verilator/top_verilator.sv
@@ -297,6 +297,10 @@ module top_verilator (input logic clk_i, rst_ni);
wire [7:0] user_sw_n = '0;
wire [2:0] sel_sw_n = '0;
+ // Sonata Trace Port functionality.
+ logic [3:0] strace;
+ wire strace_unused_ = ^strace;
+
// Instantiating the Sonata System.
sonata_system #(
.CheriErrWidth ( CheriErrWidth ),
@@ -399,7 +403,9 @@ module top_verilator (input logic clk_i, rst_ni);
.out_to_pins_o (out_to_pins ),
.inout_from_pins_i (inout_from_pins ),
.inout_to_pins_o (inout_to_pins ),
- .inout_to_pins_en_o (inout_to_pins_en)
+ .inout_to_pins_en_o (inout_to_pins_en),
+
+ .strace_o (strace)
);
// I2C HAT ID DPI - this I2C bus is to the ID EEPROM of a Raspberry Pi HAT.
diff --git a/rtl/fpga/top_sonata.sv b/rtl/fpga/top_sonata.sv
index 0697b3399..1063a9a05 100644
--- a/rtl/fpga/top_sonata.sv
+++ b/rtl/fpga/top_sonata.sv
@@ -111,6 +111,12 @@ module top_sonata
inout logic ah_tmpio8,
inout logic ah_tmpio9,
+ // Sonata Trace port.
+ inout logic ah_tmpio14,
+ inout logic ah_tmpio15,
+ inout logic ah_tmpio16,
+ inout logic ah_tmpio17,
+
// Arduino shield SPI bus
inout logic ah_tmpio10, // Chip select
inout logic ah_tmpio11, // COPI
@@ -266,6 +272,12 @@ module top_sonata
logic rs485_rx, rs485_tx;
logic rs485_rx_enable, rs485_tx_enable;
+ // Sonata Trace port
+ // - the signal ordering here ensures that when tracing an SPI bus the signals match the pin
+ // names and PCB legend since we're hijacking the ICSP connector which carries an SPI bus.
+ logic [3:0] strace;
+ assign {ah_tmpio14, ah_tmpio17, ah_tmpio15, ah_tmpio16} = strace;
+
sonata_system #(
.CheriErrWidth ( 9 ),
.SRAMInitFile ( SRAMInitFile ),
@@ -366,7 +378,9 @@ module top_sonata
.out_to_pins_o (out_to_pins ),
.inout_from_pins_i (inout_from_pins ),
.inout_to_pins_o (inout_to_pins ),
- .inout_to_pins_en_o (inout_to_pins_en)
+ .inout_to_pins_en_o (inout_to_pins_en),
+
+ .strace_o (strace)
);
assign rgbled0 = ~rgbled_dout;
diff --git a/rtl/ip/strace/rtl/strace_top.sv b/rtl/ip/strace/rtl/strace_top.sv
new file mode 100644
index 000000000..4570caa8b
--- /dev/null
+++ b/rtl/ip/strace/rtl/strace_top.sv
@@ -0,0 +1,105 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// Sonata Trace Port functionality.
+module strace_top
+#(
+ // Number of I2C buses to trace.
+ parameter int unsigned I2C_NUM = 1,
+ // Number of SPI buses to trace.
+ parameter int unsigned SPI_NUM = 1
+) (
+ input logic clk_i,
+ input logic rst_ni,
+
+ // Configuration interface.
+ input logic cfg_re,
+ input logic cfg_we,
+ input logic [3:0] cfg_addr,
+ input logic [31:0] cfg_wdata,
+ output logic [31:0] cfg_rdata,
+
+ // I2C bus(es).
+ input logic [I2C_NUM-1:0] i2c_scl,
+ input logic [I2C_NUM-1:0] i2c_sda,
+
+ // SPI bus(es).
+ input logic [SPI_NUM-1:0] spi_cs,
+ input logic [SPI_NUM-1:0] spi_sck,
+ input logic [SPI_NUM-1:0] spi_copi,
+ input logic [SPI_NUM-1:0] spi_cipo,
+
+ // TL-UL activity.
+ input logic [3:0] tlul_trace,
+
+ // Trace output.
+ output logic [3:0] strace_o
+);
+
+// TODO: We probably want to use structured data types to prevent awkward reordering of signals.
+
+// Re-time all of the inputs by running them through synchronizers.
+// TODO: Simplify this by padding to 4 here?
+localparam int unsigned TraceInW = 4 + SPI_NUM*4 + I2C_NUM*2;
+logic [TraceInW-1:0] trace_in;
+prim_flop_2sync #(
+ .Width (TraceInW)
+) u_cdc (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+ .d_i ({tlul_trace,
+ spi_cipo, spi_copi, spi_sck, spi_cs,
+ i2c_sda, i2c_scl}),
+ .q_o (trace_in)
+);
+
+// Instantiate the execution trace logic.
+
+// The configuration interface presently consists of nothing more than a control register.
+reg [31:0] control;
+wire enable = control[31]; // Enabling trace output?
+wire [3:0] src_sel = control[3:0]; // Source selection.
+always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+// TODO: For now we want the strace to be on the microSD card output.
+// control <= 32'b0;
+ control <= 32'h8000_0000 | 32'(I2C_NUM);
+ end else if (cfg_we) begin
+ case (cfg_addr)
+ default: control <= cfg_wdata;
+ endcase
+ end
+end
+assign cfg_rdata = control; // There's only a single register at present.
+
+// We may now choose the appropriate source.
+localparam int unsigned SPI_OFST = I2C_NUM * 2;
+logic [4:0] spi_idx = 5'(32'(src_sel) - I2C_NUM);
+logic [3:0] sel_strace;
+always_comb begin
+ if (32'(src_sel) < I2C_NUM) begin
+ sel_strace = {2'b00, trace_in[I2C_NUM + 32'(src_sel)], trace_in[{1'b0,src_sel}]};
+ end else if (32'(src_sel) < I2C_NUM + SPI_NUM) begin : sel_spi
+ sel_strace = {trace_in[SPI_NUM*3 + SPI_OFST + 32'(spi_idx)],
+ trace_in[SPI_NUM*2 + SPI_OFST + 32'(spi_idx)],
+ trace_in[SPI_NUM + SPI_OFST + 32'(spi_idx)],
+ trace_in[ SPI_OFST + 32'(spi_idx)]};
+ end else begin
+ sel_strace = trace_in[SPI_NUM*4 + I2C_NUM*2+3 -: 4];
+ end
+end
+
+// Output the trace signals.
+always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ strace_o <= 4'b0;
+ end else if (enable) begin
+ strace_o <= sel_strace;
+ end
+end
+
+logic unused_;
+assign unused_ = cfg_re;
+
+endmodule : strace_top
diff --git a/rtl/system/sonata_system.sv b/rtl/system/sonata_system.sv
index 148c3df22..d7cf2561f 100644
--- a/rtl/system/sonata_system.sv
+++ b/rtl/system/sonata_system.sv
@@ -101,7 +101,9 @@ module sonata_system
output sonata_out_pins_t out_to_pins_o,
input sonata_inout_pins_t inout_from_pins_i,
output sonata_inout_pins_t inout_to_pins_o,
- output sonata_inout_pins_t inout_to_pins_en_o
+ output sonata_inout_pins_t inout_to_pins_en_o,
+
+ output logic [3:0] strace_o
);
///////////////////////////////////////////////
// Signals, types and parameters for system. //
@@ -1208,6 +1210,64 @@ module sonata_system
.rgbled_dout_o
);
+ // TODO: Tap onto the PWM device port for now.
+ wire strace_cfg_re = device_req[Pwm] & !device_we[Pwm] & device_addr[Pwm][7];
+ wire strace_cfg_we = device_req[Pwm] & device_we[Pwm] & device_addr[Pwm][7];
+ wire [3:0] strace_cfg_addr = device_addr[Pwm][3:0];
+ wire [31:0] strace_cfg_wdata = device_wdata[Pwm];
+
+ // Collect the I2C buses and SPI buses.
+ logic [I2C_NUM-1:0] strace_i2c_scl;
+ logic [I2C_NUM-1:0] strace_i2c_sda;
+ logic [SPI_NUM-1:0] strace_spi_sck;
+ logic [SPI_NUM-1:0] strace_spi_cs; // TODO: require multi-CS support.
+ logic [SPI_NUM-1:0] strace_spi_copi;
+ logic [SPI_NUM-1:0] strace_spi_cipo;
+ always_comb begin
+ for (integer i = 0; i < I2C_NUM; i++) begin
+ strace_i2c_scl[i] = i2c_scl_d2h[i];
+ strace_i2c_sda[i] = i2c_sda_d2h[i];
+ end
+ for (integer i = 0; i < SPI_NUM; i++) begin
+ strace_spi_sck[i] = spi_sclk[i];
+ strace_spi_cs[i] = spi_cs[i][1]; // TODO: Only interested in microSD presently!
+ strace_spi_copi[i] = spi_copi[i];
+ strace_spi_cipo[i] = spi_cipo[i];
+ end
+ end
+
+ // Sonata Trace port.
+ strace_top #(
+ .I2C_NUM (I2C_NUM),
+ .SPI_NUM (SPI_NUM)
+ ) u_strace(
+ .clk_i (clk_sys_i),
+ .rst_ni (rst_sys_ni),
+
+ // Configuration interface.
+ .cfg_re (strace_cfg_re),
+ .cfg_we (strace_cfg_we),
+ .cfg_addr (strace_cfg_addr),
+ .cfg_wdata (strace_cfg_wdata),
+ // TODO: make read data available; presently not done because of GPIO tap.
+ .cfg_rdata (),
+
+ // I2C bus(es).
+ .i2c_scl (strace_i2c_scl),
+ .i2c_sda (strace_i2c_sda),
+
+ // SPI bus(es).
+ .spi_cs (strace_spi_cs),
+ .spi_sck (strace_spi_sck),
+ .spi_copi (strace_spi_copi),
+ .spi_cipo (strace_spi_cipo),
+
+ // TL-UL activity.
+ .tlul_trace (4'h0),
+
+ .strace_o (strace_o)
+ );
+
// Debug module top.
dm_top #(
.NrHarts ( 1 ),
diff --git a/sonata_system.core b/sonata_system.core
index 7fffb3f9b..4e61f5488 100644
--- a/sonata_system.core
+++ b/sonata_system.core
@@ -28,6 +28,7 @@ filesets:
files:
- rtl/system/sonata_pkg.sv
- rtl/bus/sonata_xbar_main.sv
+ - rtl/ip/strace/rtl/strace_top.sv
- rtl/system/jtag_id_pkg.sv
- rtl/system/sonata_system.sv
- rtl/system/dm_top.sv