|
| 1 | +// Copyright lowRISC contributors. |
| 2 | +// Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | +// SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +// Sonata Trace Port functionality. |
| 6 | +module strace_top |
| 7 | +#( |
| 8 | + // Number of I2C buses to trace. |
| 9 | + parameter int unsigned I2C_NUM = 1, |
| 10 | + // Number of SPI buses to trace. |
| 11 | + parameter int unsigned SPI_NUM = 1 |
| 12 | +) ( |
| 13 | + input logic clk_i, |
| 14 | + input logic rst_ni, |
| 15 | + |
| 16 | + // Configuration interface. |
| 17 | + input logic cfg_re, |
| 18 | + input logic cfg_we, |
| 19 | + input logic [3:0] cfg_addr, |
| 20 | + input logic [31:0] cfg_wdata, |
| 21 | + output logic [31:0] cfg_rdata, |
| 22 | + |
| 23 | + // I2C bus(es). |
| 24 | + input logic [I2C_NUM-1:0] i2c_scl, |
| 25 | + input logic [I2C_NUM-1:0] i2c_sda, |
| 26 | + |
| 27 | + // SPI bus(es). |
| 28 | + input logic [SPI_NUM-1:0] spi_cs, |
| 29 | + input logic [SPI_NUM-1:0] spi_sck, |
| 30 | + input logic [SPI_NUM-1:0] spi_copi, |
| 31 | + input logic [SPI_NUM-1:0] spi_cipo, |
| 32 | + |
| 33 | + // TL-UL activity. |
| 34 | + input logic [3:0] tlul_trace, |
| 35 | + |
| 36 | + // Trace output. |
| 37 | + output logic [3:0] strace_o |
| 38 | +); |
| 39 | + |
| 40 | +// TODO: We probably want to use structured data types to prevent awkward reordering of signals. |
| 41 | + |
| 42 | +// Re-time all of the inputs by running them through synchronizers. |
| 43 | +// TODO: Simplify this by padding to 4 here? |
| 44 | +localparam int unsigned TraceInW = 4 + SPI_NUM*4 + I2C_NUM*2; |
| 45 | +logic [TraceInW-1:0] trace_in; |
| 46 | +prim_flop_2sync #( |
| 47 | + .Width (TraceInW) |
| 48 | +) u_cdc ( |
| 49 | + .clk_i (clk_i), |
| 50 | + .rst_ni (rst_ni), |
| 51 | + .d_i ({tlul_trace, |
| 52 | + spi_cipo, spi_copi, spi_sck, spi_cs, |
| 53 | + i2c_sda, i2c_scl}), |
| 54 | + .q_o (trace_in) |
| 55 | +); |
| 56 | + |
| 57 | +// Instantiate the execution trace logic. |
| 58 | + |
| 59 | +// The configuration interface presently consists of nothing more than a control register. |
| 60 | +reg [31:0] control; |
| 61 | +wire enable = control[31]; // Enabling trace output? |
| 62 | +wire [3:0] src_sel = control[3:0]; // Source selection. |
| 63 | +always_ff @(posedge clk_i or negedge rst_ni) begin |
| 64 | + if (!rst_ni) begin |
| 65 | +// TODO: For now we want the strace to be on the microSD card output. |
| 66 | +// control <= 32'b0; |
| 67 | + control <= 32'h8000_0000 | 32'(I2C_NUM); |
| 68 | + end else if (cfg_we) begin |
| 69 | + case (cfg_addr) |
| 70 | + default: control <= cfg_wdata; |
| 71 | + endcase |
| 72 | + end |
| 73 | +end |
| 74 | +assign cfg_rdata = control; // There's only a single register at present. |
| 75 | + |
| 76 | +// We may now choose the appropriate source. |
| 77 | +localparam int unsigned SPI_OFST = I2C_NUM * 2; |
| 78 | +logic [4:0] spi_idx = 5'(32'(src_sel) - I2C_NUM); |
| 79 | +logic [3:0] sel_strace; |
| 80 | +always_comb begin |
| 81 | + if (32'(src_sel) < I2C_NUM) begin |
| 82 | + sel_strace = {2'b00, trace_in[I2C_NUM + 32'(src_sel)], trace_in[{1'b0,src_sel}]}; |
| 83 | + end else if (32'(src_sel) < I2C_NUM + SPI_NUM) begin : sel_spi |
| 84 | + sel_strace = {trace_in[SPI_NUM*3 + SPI_OFST + 32'(spi_idx)], |
| 85 | + trace_in[SPI_NUM*2 + SPI_OFST + 32'(spi_idx)], |
| 86 | + trace_in[SPI_NUM + SPI_OFST + 32'(spi_idx)], |
| 87 | + trace_in[ SPI_OFST + 32'(spi_idx)]}; |
| 88 | + end else begin |
| 89 | + sel_strace = trace_in[SPI_NUM*4 + I2C_NUM*2+3 -: 4]; |
| 90 | + end |
| 91 | +end |
| 92 | + |
| 93 | +// Output the trace signals. |
| 94 | +always_ff @(posedge clk_i or negedge rst_ni) begin |
| 95 | + if (!rst_ni) begin |
| 96 | + strace_o <= 4'b0; |
| 97 | + end else if (enable) begin |
| 98 | + strace_o <= sel_strace; |
| 99 | + end |
| 100 | +end |
| 101 | + |
| 102 | +logic unused_; |
| 103 | +assign unused_ = cfg_re; |
| 104 | + |
| 105 | +endmodule : strace_top |
0 commit comments