refactor(fpga): Replace tlgen xbar with Chisel-based KelvinXbar
This commit replaces the legacy `tlgen`-based crossbar with the new,
data-driven Chisel-based `KelvinXbar` in the FPGA design. This change
simplifies the build system, improves maintainability, and provides a
more flexible and robust interconnect.
Key changes:
- Removed the `tlgen` and `post_process_xbar.py` infrastructure from
the FPGA build system.
- Instantiated the new `KelvinXbar` in `kelvin_soc.sv`, replacing the
old crossbar and all associated width-sizers.
- Updated the clocking and reset logic to support the new crossbar's
asynchronous domains, placing the Ibex core on its own clock.
- Removed the now-redundant Verilog implementations of the TileLink-UL
primitives (FIFOs, sockets, width bridges).
- Added integrity generation to the `CoreTlul` module to ensure data
integrity on the TileLink bus.
- Increased the FPGA clock frequency to 80MHz.
Change-Id: I340658419ca5cc93acee481c16334aeb026b2e7e
diff --git a/fpga/BUILD b/fpga/BUILD
index f221189..4d8dc81 100644
--- a/fpga/BUILD
+++ b/fpga/BUILD
@@ -16,57 +16,10 @@
load("@lowrisc_opentitan_gh//rules:fusesoc.bzl", "fusesoc_build")
load("//rules:kelvin_v2.bzl", "kelvin_v2_binary")
load("//rules:utils.bzl", "cc_embed_data")
-load(":rules.bzl", "tlgen_rule")
package(default_visibility = ["//visibility:public"])
-_CLOCK_FREQUENCY_MHZ = "10"
-
-# This is the tlgen.py script itself
-py_binary(
- name = "tlgen_tool",
- srcs = ["@lowrisc_opentitan_gh//util:tlgen.py"],
- main = "@lowrisc_opentitan_gh//util:tlgen.py",
- deps = [
- "@kelvin_pip_deps_hjson//:pkg",
- "@lowrisc_opentitan_gh//util/tlgen",
- ],
-)
-
-tlgen_rule(
- name = "tl_crossbar_generated",
- topcfg = "tl_config.hjson",
-)
-
-py_binary(
- name = "post_process_xbar",
- srcs = ["post_process_xbar.py"],
-)
-
-genrule(
- name = "tl_crossbar_processed",
- srcs = [":tl_crossbar_generated"],
- outs = [
- "tl_crossbar_processed_out",
- ],
- cmd = "$(execpath :post_process_xbar) " +
- "--input-dir $(location :tl_crossbar_generated) " +
- "--output-dir $(location tl_crossbar_processed_out) " +
- "--cores kelvinv2:ip:kelvin_tlul:0.1",
- tools = [":post_process_xbar"],
-)
-
-filegroup(
- name = "tl_crossbar",
- srcs = [
- ":tl_crossbar_processed_out",
- ],
-)
-
-filegroup(
- name = "tl_crossbar_core",
- srcs = [":tl_crossbar"],
-)
+_CLOCK_FREQUENCY_MHZ = "80"
filegroup(
name = "rtl_files",
@@ -75,7 +28,7 @@
"//fpga/ip/rv_core_ibex:rtl_files",
"//fpga/ip/rvv_core_mini_tlul:rtl_files",
"//fpga/ip/sram:rtl_files",
- "//fpga/ip/tlul_width_bridge:rtl_files",
+ "//fpga/ip/xbar_kelvin_soc_chisel:rtl_files",
"//fpga/rtl:rtl_files",
],
)
@@ -144,10 +97,11 @@
KELVIN_SOC_CORES = [
"//fpga/ip/rv_core_ibex:rv_core_ibex.core",
+ "//fpga/ip/rvv_core_mini_tlul:rvv_core_mini_tlul.core",
+ "//fpga/ip/xbar_kelvin_soc_chisel:xbar_kelvin_soc_chisel.core",
":kelvin_soc.core",
":kelvin_soc_pkg.core",
":racl_pkg.core",
- ":tl_crossbar_core",
"@lowrisc_opentitan_gh//hw:check_tool_requirements.core",
]
@@ -202,8 +156,6 @@
_PREFIX = "../../../../../../../../.."
-# "../../../../../../../"bazel-out/k8-fastbuild-ST-be77d280135c/bin/fpga
-# "../../../../../../../"bazel-out/k8-fastbuild-ST-be77d280135c/bin/fpga/wfi.vmem
_IBEX_BOOT_ROM_VMEM = ":ibex_boot_rom.vmem"
IBEX_BOOT_ROM_VMEM_PATH = "{}/$(location {})".format(_PREFIX, _IBEX_BOOT_ROM_VMEM)
@@ -221,15 +173,7 @@
"--ClockFrequencyMhz=" + _CLOCK_FREQUENCY_MHZ,
],
output_groups = {
- # /home/atv/.cache/bazel/_bazel_atv/cb485e413f28624e05d5dee28237de6d/sandbox/
- # linux-sandbox/34/execroot/kelvin_hw/bazel-out/k8-fastbuild/bin/fpga/
- # build.build_chip_nexus_bitstream/
- # com.google.kelvin_fpga_chip_nexus_0.1/synth-vivado/com.google.kelvin_fpga_chip_nexus_0.1.runs/impl_1/chip_nexus.bit
"bitstream": ["com.google.kelvin_fpga_chip_nexus_0.1/synth-vivado/com.google.kelvin_fpga_chip_nexus_0.1.runs/impl_1/chip_nexus.bit"],
- # /home/atv/.cache/bazel/_bazel_atv/cb485e413f28624e05d5dee28237de6d/sandbox/
- # linux-sandbox/34/execroot/kelvin_hw/bazel-out/k8-fastbuild/bin/fpga/
- # build.build_chip_nexus_bitstream/
- # com.google.kelvin_fpga_chip_nexus_0.1/synth-vivado/com.google.kelvin_fpga_chip_nexus_0.1.runs/
"logs": ["com.google.kelvin_fpga_chip_nexus_0.1/synth-vivado/com.google.kelvin_fpga_chip_nexus_0.1.runs/"],
},
systems = ["com.google.kelvin:fpga:chip_nexus:0.1"],
diff --git a/fpga/chip_nexus.core b/fpga/chip_nexus.core
index 912ddaf..4d930dd 100644
--- a/fpga/chip_nexus.core
+++ b/fpga/chip_nexus.core
@@ -25,7 +25,7 @@
ClockFrequencyMhz:
datatype: int
description: "Target clock frequency in MHz."
- default: 10
+ default: 80
paramtype: vlogparam
MemInitFile:
datatype: str
diff --git a/fpga/chip_verilator.core b/fpga/chip_verilator.core
index 0971b5a..343866e 100644
--- a/fpga/chip_verilator.core
+++ b/fpga/chip_verilator.core
@@ -6,7 +6,6 @@
files_rtl:
depend:
- com.google.kelvin:fpga:kelvin_soc:0.2
- - kelvinv2:ip:sram:0.1
- kelvinv2:ip:kelvin_tlul:0.1
- lowrisc:dv_dpi_c:uartdpi:0.1
- lowrisc:dv_dpi_sv:uartdpi:0.1
@@ -25,7 +24,7 @@
ClockFrequencyMhz:
datatype: int
description: "Target clock frequency in MHz."
- default: 10
+ default: 80
paramtype: vlogparam
MemInitFile:
datatype: str
diff --git a/fpga/ip/kelvin_tlul/kelvin_tlul.core b/fpga/ip/kelvin_tlul/kelvin_tlul.core
index 37336d3..f189753 100644
--- a/fpga/ip/kelvin_tlul/kelvin_tlul.core
+++ b/fpga/ip/kelvin_tlul/kelvin_tlul.core
@@ -9,10 +9,6 @@
files:
- kelvin_tlul_pkg_128.sv
- kelvin_tlul_pkg_32.sv
- - tlul_fifo_async_128.sv
- - tlul_fifo_sync_128.sv
- - tlul_socket_1n_128.sv
- - tlul_socket_m1_128.sv
file_type: systemVerilogSource
targets:
diff --git a/fpga/ip/kelvin_tlul/tlul_fifo_async_128.sv b/fpga/ip/kelvin_tlul/tlul_fifo_async_128.sv
deleted file mode 100644
index 22894bb..0000000
--- a/fpga/ip/kelvin_tlul/tlul_fifo_async_128.sv
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright lowRISC contributors (OpenTitan project).
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-//
-// TL-UL fifo, used to add elasticity or an asynchronous clock crossing
-// to an TL-UL bus. This instantiates two FIFOs, one for the request side,
-// and one for the response side.
-
-`include "prim_assert.sv"
-
-module tlul_fifo_async_128
- #(parameter int unsigned ReqDepth = 4,
- parameter int unsigned RspDepth = 4)
- (input clk_h_i,
- input rst_h_ni,
- input clk_d_i,
- input rst_d_ni,
- input kelvin_tlul_pkg_128::tl_h2d_t tl_h_i,
- output kelvin_tlul_pkg_128::tl_d2h_t tl_h_o,
- output kelvin_tlul_pkg_128::tl_h2d_t tl_d_o,
- input kelvin_tlul_pkg_128::tl_d2h_t tl_d_i);
-
- // Put everything on the request side into one FIFO
- localparam int unsigned REQFIFO_WIDTH =
- $bits(kelvin_tlul_pkg_128::tl_h2d_t) - 2;
-
- prim_fifo_async #(.Width(REQFIFO_WIDTH),
- .Depth(ReqDepth),
- .OutputZeroIfInvalid(1))
- reqfifo(.clk_wr_i(clk_h_i),
- .rst_wr_ni(rst_h_ni),
- .clk_rd_i(clk_d_i),
- .rst_rd_ni(rst_d_ni),
- .wvalid_i(tl_h_i.a_valid),
- .wready_o(tl_h_o.a_ready),
- .wdata_i({tl_h_i.a_opcode, tl_h_i.a_param, tl_h_i.a_size,
- tl_h_i.a_source, tl_h_i.a_address, tl_h_i.a_mask,
- tl_h_i.a_data, tl_h_i.a_user}),
- .rvalid_o(tl_d_o.a_valid),
- .rready_i(tl_d_i.a_ready),
- .rdata_o({tl_d_o.a_opcode, tl_d_o.a_param, tl_d_o.a_size,
- tl_d_o.a_source, tl_d_o.a_address, tl_d_o.a_mask,
- tl_d_o.a_data, tl_d_o.a_user}),
- .wdepth_o(),
- .rdepth_o());
-
- // Put everything on the response side into the other FIFO
-
- localparam int unsigned RSPFIFO_WIDTH =
- $bits(kelvin_tlul_pkg_128::tl_d2h_t) - 2;
-
- prim_fifo_async #(.Width(RSPFIFO_WIDTH),
- .Depth(RspDepth),
- .OutputZeroIfInvalid(1))
- rspfifo(.clk_wr_i(clk_d_i),
- .rst_wr_ni(rst_d_ni),
- .clk_rd_i(clk_h_i),
- .rst_rd_ni(rst_h_ni),
- .wvalid_i(tl_d_i.d_valid),
- .wready_o(tl_d_o.d_ready),
- .wdata_i({tl_d_i.d_opcode, tl_d_i.d_param, tl_d_i.d_size,
- tl_d_i.d_source, tl_d_i.d_sink, tl_d_i.d_data,
- tl_d_i.d_user, tl_d_i.d_error}),
- .rvalid_o(tl_h_o.d_valid),
- .rready_i(tl_h_i.d_ready),
- .rdata_o({tl_h_o.d_opcode, tl_h_o.d_param, tl_h_o.d_size,
- tl_h_o.d_source, tl_h_o.d_sink, tl_h_o.d_data,
- tl_h_o.d_user, tl_h_o.d_error}),
- .wdepth_o(),
- .rdepth_o());
-endmodule
diff --git a/fpga/ip/kelvin_tlul/tlul_fifo_sync_128.sv b/fpga/ip/kelvin_tlul/tlul_fifo_sync_128.sv
deleted file mode 100644
index af404f1..0000000
--- a/fpga/ip/kelvin_tlul/tlul_fifo_sync_128.sv
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright lowRISC contributors (OpenTitan project).
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-//
-// TL-UL fifo, used to add elasticity or an asynchronous clock crossing
-// to an TL-UL bus. This instantiates two FIFOs, one for the request side,
-// and one for the response side.
-
-module tlul_fifo_sync_128
- #(parameter bit ReqPass = 1'b1,
- parameter bit RspPass = 1'b1,
- parameter int unsigned ReqDepth = 2,
- parameter int unsigned RspDepth = 2,
- parameter int unsigned SpareReqW = 1,
- parameter int unsigned SpareRspW = 1)
- (input clk_i,
- input rst_ni,
- input kelvin_tlul_pkg_128::tl_h2d_t tl_h_i,
- output kelvin_tlul_pkg_128::tl_d2h_t tl_h_o,
- output kelvin_tlul_pkg_128::tl_h2d_t tl_d_o,
- input kelvin_tlul_pkg_128::tl_d2h_t tl_d_i,
- input [SpareReqW - 1 : 0] spare_req_i,
- output [SpareReqW - 1 : 0] spare_req_o,
- input [SpareRspW - 1 : 0] spare_rsp_i,
- output [SpareRspW - 1 : 0] spare_rsp_o);
- import kelvin_tlul_pkg_128::*;
- // Put everything on the request side into one FIFO
- localparam int unsigned REQFIFO_WIDTH = $bits(kelvin_tlul_pkg_128::tl_h2d_t) -
- 2 + SpareReqW;
-
- prim_fifo_sync #(.Width(REQFIFO_WIDTH),
- .Pass(ReqPass),
- .Depth(ReqDepth))
- reqfifo(.clk_i,
- .rst_ni,
- .clr_i(1'b0),
- .wvalid_i(tl_h_i.a_valid),
- .wready_o(tl_h_o.a_ready),
- .wdata_i({tl_h_i.a_opcode, tl_h_i.a_param, tl_h_i.a_size,
- tl_h_i.a_source, tl_h_i.a_address, tl_h_i.a_mask,
- tl_h_i.a_data, tl_h_i.a_user, spare_req_i}),
- .rvalid_o(tl_d_o.a_valid),
- .rready_i(tl_d_i.a_ready),
- .rdata_o({tl_d_o.a_opcode, tl_d_o.a_param, tl_d_o.a_size,
- tl_d_o.a_source, tl_d_o.a_address, tl_d_o.a_mask,
- tl_d_o.a_data, tl_d_o.a_user, spare_req_o}),
- .full_o(),
- .depth_o(),
- .err_o());
-
- // Put everything on the response side into the other FIFO
-
- localparam int unsigned RSPFIFO_WIDTH = $bits(kelvin_tlul_pkg_128::tl_d2h_t) -
- 2 + SpareRspW;
-
- prim_fifo_sync #(.Width(RSPFIFO_WIDTH),
- .Pass(RspPass),
- .Depth(RspDepth))
- rspfifo(.clk_i,
- .rst_ni,
- .clr_i(1'b0),
- .wvalid_i(tl_d_i.d_valid),
- .wready_o(tl_d_o.d_ready),
- .wdata_i({tl_d_i.d_opcode, tl_d_i.d_param, tl_d_i.d_size,
- tl_d_i.d_source, tl_d_i.d_sink,
- (tl_d_i.d_opcode == tlul_pkg::AccessAckData)
- ? tl_d_i.d_data
- : {kelvin_tlul_pkg_128::TL_DW{1'b0}},
- tl_d_i.d_user, tl_d_i.d_error, spare_rsp_i}),
- .rvalid_o(tl_h_o.d_valid),
- .rready_i(tl_h_i.d_ready),
- .rdata_o({tl_h_o.d_opcode, tl_h_o.d_param, tl_h_o.d_size,
- tl_h_o.d_source, tl_h_o.d_sink, tl_h_o.d_data,
- tl_h_o.d_user, tl_h_o.d_error, spare_rsp_o}),
- .full_o(),
- .depth_o(),
- .err_o());
-endmodule
diff --git a/fpga/ip/kelvin_tlul/tlul_socket_1n_128.sv b/fpga/ip/kelvin_tlul/tlul_socket_1n_128.sv
deleted file mode 100644
index 2b333f0..0000000
--- a/fpga/ip/kelvin_tlul/tlul_socket_1n_128.sv
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright lowRISC contributors (OpenTitan project).
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-//
-// TL-UL socket 1:N module
-//
-// configuration settings
-// device_count: 4
-//
-// Verilog parameters
-// HReqPass: if 1 then host requests can pass through on empty fifo,
-// default 1
-// HRspPass: if 1 then host responses can pass through on empty fifo,
-// default 1
-// DReqPass: (one per device_count) if 1 then device i requests can
-// pass through on empty fifo, default 1
-// DRspPass: (one per device_count) if 1 then device i responses can
-// pass through on empty fifo, default 1
-// HReqDepth: Depth of host request FIFO, default 2
-// HRspDepth: Depth of host response FIFO, default 2
-// DReqDepth: (one per device_count) Depth of device i request FIFO,
-// default 2
-// DRspDepth: (one per device_count) Depth of device i response FIFO,
-// default 2
-// ExplicitErrs: This module always returns a request error if dev_select_i
-// is greater than N-1. If ExplicitErrs is set then the width
-// of the dev_select_i signal will be chosen to make sure that
-// this is possible. This only makes a difference if N is a
-// power of 2.
-//
-// Requests must stall to one device until all responses from other devices
-// have returned. Need to keep a counter of all outstanding requests and
-// wait until that counter is zero before switching devices.
-//
-// This module will return a request error if the input value of 'dev_select_i'
-// is not within the range 0..N-1. Thus the instantiator of the socket
-// can indicate error by any illegal value of dev_select_i. 4'b1111 is
-// recommended for visibility
-//
-// The maximum value of N is 63
-
-`include "prim_assert.sv"
-
-module tlul_socket_1n_128
- #(parameter int unsigned N = 4,
- parameter bit HReqPass = 1'b1,
- parameter bit HRspPass = 1'b1,
- parameter bit [N - 1 : 0] DReqPass = {N{1'b1}},
- parameter bit [N - 1 : 0] DRspPass = {N{1'b1}},
- parameter bit [3 : 0] HReqDepth = 4'h1,
- parameter bit [3 : 0] HRspDepth = 4'h1,
- parameter bit [N * 4 - 1 : 0] DReqDepth = {N{4'h1}},
- parameter bit [N * 4 - 1 : 0] DRspDepth = {N{4'h1}},
- parameter bit ExplicitErrs = 1'b1,
-
- // The width of dev_select_i. We must be able to select any of the N
- // devices (i.e. values 0..N-1). If ExplicitErrs is set, we also need to
- // be able to represent N.
- localparam int unsigned NWD = $clog2(ExplicitErrs ? N + 1 : N))
- (input clk_i,
- input rst_ni,
- input kelvin_tlul_pkg_128::tl_h2d_t tl_h_i,
- output kelvin_tlul_pkg_128::tl_d2h_t tl_h_o,
- output kelvin_tlul_pkg_128::tl_h2d_t tl_d_o[N],
- input kelvin_tlul_pkg_128::tl_d2h_t tl_d_i[N],
- input [NWD - 1 : 0] dev_select_i);
-
- `ASSERT_INIT(maxN, N < 64)
-
- // Since our steering is done after potential FIFOing, we need to
- // shove our device select bits into spare bits of reqfifo
-
- // instantiate the host fifo, create intermediate bus 't'
-
- // FIFO'd version of device select
- logic [NWD - 1 : 0] dev_select_t;
-
- kelvin_tlul_pkg_128::tl_h2d_t tl_t_o;
- kelvin_tlul_pkg_128::tl_d2h_t tl_t_i;
-
- tlul_fifo_sync_128 #(.ReqPass(HReqPass),
- .RspPass(HRspPass),
- .ReqDepth(HReqDepth),
- .RspDepth(HRspDepth),
- .SpareReqW(NWD))
- fifo_h(.clk_i,
- .rst_ni,
- .tl_h_i,
- .tl_h_o,
- .tl_d_o(tl_t_o),
- .tl_d_i(tl_t_i),
- .spare_req_i(dev_select_i),
- .spare_req_o(dev_select_t),
- .spare_rsp_i(1'b0),
- .spare_rsp_o());
-
- // We need to keep track of how many requests are outstanding,
- // and to which device. New requests are compared to this and
- // stall until that number is zero.
- localparam int MaxOutstanding =
- 2 ** top_pkg::TL_AIW; // Up to 256 outstanding
- localparam int OutstandingW = $clog2(MaxOutstanding + 1);
- logic [OutstandingW - 1 : 0] num_req_outstanding;
- logic [NWD - 1 : 0] dev_select_outstanding;
- logic hold_all_requests;
- logic accept_t_req, accept_t_rsp;
-
- assign accept_t_req = tl_t_o.a_valid & tl_t_i.a_ready;
- assign accept_t_rsp = tl_t_i.d_valid & tl_t_o.d_ready;
-
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- num_req_outstanding <= '0;
- dev_select_outstanding <= '0;
- end else if (accept_t_req) begin
- if (!accept_t_rsp) begin
- num_req_outstanding <= num_req_outstanding + 1'b1;
- end
- dev_select_outstanding <= dev_select_t;
- end else if (accept_t_rsp) begin
- num_req_outstanding <= num_req_outstanding - 1'b1;
- end
- end
-
- `ASSERT(NotOverflowed_A, accept_t_req && !accept_t_rsp ->
- num_req_outstanding <= MaxOutstanding)
-
- assign hold_all_requests = (num_req_outstanding != '0) &
- (dev_select_t != dev_select_outstanding);
-
- // Make N copies of 't' request side with modified reqvalid, call
- // them 'u[0]' .. 'u[n-1]'.
-
- kelvin_tlul_pkg_128::tl_h2d_t tl_u_o[N + 1];
- kelvin_tlul_pkg_128::tl_d2h_t tl_u_i[N + 1];
-
- // ensure that when a device is not selected, both command
- // data integrity can never match
- kelvin_tlul_pkg_128::tl_a_user_t blanked_auser;
- assign blanked_auser = '{
- rsvd: tl_t_o.a_user.rsvd,
- instr_type: tl_t_o.a_user.instr_type,
- cmd_intg: kelvin_tlul_pkg_128::get_bad_cmd_intg(tl_t_o),
- data_intg: kelvin_tlul_pkg_128::get_bad_data_intg(
- kelvin_tlul_pkg_128::BlankedAData)
- };
-
- // if a host is not selected, or if requests are held off, blank the bus
- for (genvar i = 0; i < N; i++) begin : gen_u_o
- logic dev_select;
- assign dev_select = dev_select_t == NWD'(i) & ~hold_all_requests;
-
- assign tl_u_o[i].a_valid = tl_t_o.a_valid & dev_select;
- assign tl_u_o[i].a_opcode = tl_t_o.a_opcode;
- assign tl_u_o[i].a_param = tl_t_o.a_param;
- assign tl_u_o[i].a_size = tl_t_o.a_size;
- assign tl_u_o[i].a_source = tl_t_o.a_source;
- assign tl_u_o[i].a_address = tl_t_o.a_address;
- assign tl_u_o[i].a_mask = tl_t_o.a_mask;
- assign tl_u_o[i].a_data =
- dev_select ? tl_t_o.a_data : kelvin_tlul_pkg_128::BlankedAData;
- assign tl_u_o[i].a_user = dev_select ? tl_t_o.a_user : blanked_auser;
-
- assign tl_u_o[i].d_ready = tl_t_o.d_ready;
- end
-
- kelvin_tlul_pkg_128::tl_d2h_t tl_t_p;
-
- // for the returning reqready, only look at the device we're addressing
- logic hfifo_reqready;
- always_comb begin
- hfifo_reqready = tl_u_i[N].a_ready; // default to error
- for (int idx = 0; idx < N; idx++) begin
- // if (dev_select_outstanding == NWD'(idx)) hfifo_reqready =
- // tl_u_i[idx].a_ready;
- if (dev_select_t == NWD'(idx)) hfifo_reqready = tl_u_i[idx].a_ready;
- end
- if (hold_all_requests) hfifo_reqready = 1'b0;
- end
- // Adding a_valid as a qualifier. This prevents the a_ready from having
- // unknown value when the address is unknown and the Host TL-UL FIFO is bypass
- // mode.
- assign tl_t_i.a_ready = tl_t_o.a_valid & hfifo_reqready;
-
- always_comb begin
- tl_t_p = tl_u_i[N];
- for (int idx = 0; idx < N; idx++) begin
- if (dev_select_outstanding == NWD'(idx)) tl_t_p = tl_u_i[idx];
- end
- end
- assign tl_t_i.d_valid = tl_t_p.d_valid;
- assign tl_t_i.d_opcode = tl_t_p.d_opcode;
- assign tl_t_i.d_param = tl_t_p.d_param;
- assign tl_t_i.d_size = tl_t_p.d_size;
- assign tl_t_i.d_source = tl_t_p.d_source;
- assign tl_t_i.d_sink = tl_t_p.d_sink;
- assign tl_t_i.d_data = tl_t_p.d_data;
- assign tl_t_i.d_user = tl_t_p.d_user;
- assign tl_t_i.d_error = tl_t_p.d_error;
-
- // Instantiate all the device FIFOs
- for (genvar i = 0; i < N; i++) begin : gen_dfifo
- tlul_fifo_sync_128 #(.ReqPass(DReqPass[i]),
- .RspPass(DRspPass[i]),
- .ReqDepth(DReqDepth[i * 4 +: 4]),
- .RspDepth(DRspDepth[i * 4 +: 4]))
- fifo_d(.clk_i,
- .rst_ni,
- .tl_h_i(tl_u_o[i]),
- .tl_h_o(tl_u_i[i]),
- .tl_d_o(tl_d_o[i]),
- .tl_d_i(tl_d_i[i]),
- .spare_req_i(1'b0),
- .spare_req_o(),
- .spare_rsp_i(1'b0),
- .spare_rsp_o());
- end
-
- // Instantiate the error responder. It's only needed if a value greater than
- // N-1 is actually representable in NWD bits.
- if ($clog2(N + 1) <= NWD) begin : gen_err_resp
- assign tl_u_o[N].d_ready = tl_t_o.d_ready;
- assign tl_u_o[N].a_valid =
- tl_t_o.a_valid & (dev_select_t >= NWD'(N)) & ~hold_all_requests;
- assign tl_u_o[N].a_opcode = tl_t_o.a_opcode;
- assign tl_u_o[N].a_param = tl_t_o.a_param;
- assign tl_u_o[N].a_size = tl_t_o.a_size;
- assign tl_u_o[N].a_source = tl_t_o.a_source;
- assign tl_u_o[N].a_address = tl_t_o.a_address;
- assign tl_u_o[N].a_mask = tl_t_o.a_mask;
- assign tl_u_o[N].a_data = tl_t_o.a_data;
- assign tl_u_o[N].a_user = tl_t_o.a_user;
- tlul_err_resp err_resp(.clk_i,
- .rst_ni,
- .tl_h_i(tl_u_o[N]),
- .tl_h_o(tl_u_i[N]));
- end else begin : gen_no_err_resp // block: gen_err_resp
- assign tl_u_o[N] = '0;
- assign tl_u_i[N] = '0;
- logic unused_sig;
- assign unused_sig = ^tl_u_o[N];
- end
-endmodule
diff --git a/fpga/ip/kelvin_tlul/tlul_socket_m1_128.sv b/fpga/ip/kelvin_tlul/tlul_socket_m1_128.sv
deleted file mode 100644
index cded907..0000000
--- a/fpga/ip/kelvin_tlul/tlul_socket_m1_128.sv
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright lowRISC contributors (OpenTitan project).
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-//
-// TL-UL socket M:1 module
-//
-// Verilog parameters
-// M: Number of host ports.
-// HReqPass: M bit array to allow requests to pass through the host i
-// FIFO with no clock delay if the request FIFO is empty. If
-// 1'b0, at least one clock cycle of latency is created.
-// Default is 1'b1.
-// HRspPass: Same as HReqPass but for host response FIFO.
-// HReqDepth: Mx4 bit array. bit[i*4+:4] is depth of host i request FIFO.
-// Depth of zero is allowed if ReqPass is true. A maximum value
-// of 16 is allowed, default is 2.
-// HRspDepth: Same as HReqDepth but for host response FIFO.
-// DReqPass: Same as HReqPass but for device request FIFO.
-// DRspPass: Same as HReqPass but for device response FIFO.
-// DReqDepth: Same as HReqDepth but for device request FIFO.
-// DRspDepth: Same as HReqDepth but for device response FIFO.
-
-`include "prim_assert.sv"
-
-module tlul_socket_m1_128
- #(parameter int unsigned M = 4,
- parameter bit [M - 1 : 0] HReqPass = {M{1'b1}},
- parameter bit [M - 1 : 0] HRspPass = {M{1'b1}},
- parameter bit [M * 4 - 1 : 0] HReqDepth = {M{4'h1}},
- parameter bit [M * 4 - 1 : 0] HRspDepth = {M{4'h1}},
- parameter bit DReqPass = 1'b1,
- parameter bit DRspPass = 1'b1,
- parameter bit [3 : 0] DReqDepth = 4'h1,
- parameter bit [3 : 0] DRspDepth = 4'h1)
- (input clk_i,
- input rst_ni,
-
- input kelvin_tlul_pkg_128::tl_h2d_t tl_h_i[M],
- output kelvin_tlul_pkg_128::tl_d2h_t tl_h_o[M],
-
- output kelvin_tlul_pkg_128::tl_h2d_t tl_d_o,
- input kelvin_tlul_pkg_128::tl_d2h_t tl_d_i);
-
- `ASSERT_INIT(maxM, M < 16)
-
- // Signals
- //
- // tl_h_i/o[0] | tl_h_i/o[1] | ... | tl_h_i/o[M-1]
- // | | |
- // u_hostfifo[0] u_hostfifo[1] u_hostfifo[M-1]
- // | | |
- // hreq_fifo_o(i) / hrsp_fifo_i(i)
- // ---------------------------------------
- // | request/grant/req_data |
- // | |
- // | PRIM_ARBITER |
- // | |
- // | arb_valid / arb_ready / arb_data |
- // ---------------------------------------
- // |
- // dreq_fifo_i / drsp_fifo_o
- // |
- // u_devicefifo
- // |
- // tl_d_o/i
- //
- // Required ID width to distinguish between host ports
- // Used in response steering
- localparam int unsigned IDW = top_pkg::TL_AIW;
- localparam int unsigned STIDW = $clog2(M);
-
- kelvin_tlul_pkg_128::tl_h2d_t hreq_fifo_o[M];
- kelvin_tlul_pkg_128::tl_d2h_t hrsp_fifo_i[M];
-
- logic [M - 1 : 0] hrequest;
- logic [M - 1 : 0] hgrant;
-
- kelvin_tlul_pkg_128::tl_h2d_t dreq_fifo_i;
- kelvin_tlul_pkg_128::tl_d2h_t drsp_fifo_o;
-
- logic arb_valid;
- logic arb_ready;
- kelvin_tlul_pkg_128::tl_h2d_t arb_data;
-
- // Host Req/Rsp FIFO
- for (genvar i = 0; i < M; i++) begin : gen_host_fifo
- kelvin_tlul_pkg_128::tl_h2d_t hreq_fifo_i;
-
- // ID Shifting
- logic [STIDW - 1 : 0] reqid_sub;
- logic [IDW - 1 : 0] shifted_id;
- assign reqid_sub = i; // can cause conversion error?
- assign shifted_id = {tl_h_i[i].a_source[0 +: (IDW - STIDW)], reqid_sub};
-
- `ASSERT(idInRange, tl_h_i[i].a_valid |->
- tl_h_i[i].a_source[IDW - 1 -: STIDW] == '0)
-
- // assign not connected bits to nc_* signal to make lint happy
- logic [IDW - 1 : IDW - STIDW] unused_tl_h_source;
- assign unused_tl_h_source = tl_h_i[i].a_source[IDW - 1 -: STIDW];
-
- // Put shifted ID
- assign hreq_fifo_i = '{
- a_valid: tl_h_i[i].a_valid,
- a_opcode: tl_h_i[i].a_opcode,
- a_param: tl_h_i[i].a_param,
- a_size: tl_h_i[i].a_size,
- a_source: shifted_id,
- a_address: tl_h_i[i].a_address,
- a_mask: tl_h_i[i].a_mask,
- a_data: tl_h_i[i].a_data,
- a_user: tl_h_i[i].a_user,
- d_ready: tl_h_i[i].d_ready
- };
-
- tlul_fifo_sync_128 #(.ReqPass(HReqPass[i]),
- .RspPass(HRspPass[i]),
- .ReqDepth(HReqDepth[i * 4 +: 4]),
- .RspDepth(HRspDepth[i * 4 +: 4]),
- .SpareReqW(1))
- u_hostfifo(.clk_i,
- .rst_ni,
- .tl_h_i(hreq_fifo_i),
- .tl_h_o(tl_h_o[i]),
- .tl_d_o(hreq_fifo_o[i]),
- .tl_d_i(hrsp_fifo_i[i]),
- .spare_req_i(1'b0),
- .spare_req_o(),
- .spare_rsp_i(1'b0),
- .spare_rsp_o());
- end
-
- // Device Req/Rsp FIFO
- tlul_fifo_sync_128 #(.ReqPass(DReqPass),
- .RspPass(DRspPass),
- .ReqDepth(DReqDepth),
- .RspDepth(DRspDepth),
- .SpareReqW(1))
- u_devicefifo(.clk_i,
- .rst_ni,
- .tl_h_i(dreq_fifo_i),
- .tl_h_o(drsp_fifo_o),
- .tl_d_o(tl_d_o),
- .tl_d_i(tl_d_i),
- .spare_req_i(1'b0),
- .spare_req_o(),
- .spare_rsp_i(1'b0),
- .spare_rsp_o());
-
- // Request Arbiter
- for (genvar i = 0; i < M; i++) begin : gen_arbreqgnt
- assign hrequest[i] = hreq_fifo_o[i].a_valid;
- end
-
- assign arb_ready = drsp_fifo_o.a_ready;
-
- if (kelvin_tlul_pkg_128::ArbiterImpl == "PPC") begin : gen_arb_ppc
- prim_arbiter_ppc #(.N(M),
- .DW($bits(kelvin_tlul_pkg_128::tl_h2d_t)))
- u_reqarb(.clk_i,
- .rst_ni,
- .req_chk_i(1'b0),
- // TL-UL allows dropping valid without ready. See #3354.
- .req_i(hrequest),
- .data_i(hreq_fifo_o),
- .gnt_o(hgrant),
- .idx_o(),
- .valid_o(arb_valid),
- .data_o(arb_data),
- .ready_i(arb_ready));
- end else if (kelvin_tlul_pkg_128::ArbiterImpl == "BINTREE")
- begin : gen_tree_arb
- prim_arbiter_tree #(.N(M),
- .DW($bits(kelvin_tlul_pkg_128::tl_h2d_t)))
- u_reqarb(.clk_i,
- .rst_ni,
- .req_chk_i(1'b0),
- // TL-UL allows dropping valid without ready. See #3354.
- .req_i(hrequest),
- .data_i(hreq_fifo_o),
- .gnt_o(hgrant),
- .idx_o(),
- .valid_o(arb_valid),
- .data_o(arb_data),
- .ready_i(arb_ready));
- end else begin : gen_unknown
- `ASSERT_INIT(UnknownArbImpl_A, 0)
- end
-
- logic [M - 1 : 0] hfifo_rspvalid;
- logic [M - 1 : 0] dfifo_rspready;
- logic [IDW - 1 : 0] hfifo_rspid;
- logic dfifo_rspready_merged;
-
- // arb_data --> dreq_fifo_i
- // dreq_fifo_i.hd_rspready <= dfifo_rspready
-
- assign dfifo_rspready_merged = |dfifo_rspready;
- assign dreq_fifo_i = '{
- a_valid: arb_valid,
- a_opcode: arb_data.a_opcode,
- a_param: arb_data.a_param,
- a_size: arb_data.a_size,
- a_source: arb_data.a_source,
- a_address: arb_data.a_address,
- a_mask: arb_data.a_mask,
- a_data: arb_data.a_data,
- a_user: arb_data.a_user,
-
- d_ready: dfifo_rspready_merged
- };
-
- // Response ID steering
- // drsp_fifo_o --> hrsp_fifo_i[i]
-
- // Response ID shifting before put into host fifo
- assign hfifo_rspid = {{STIDW{1'b0}}, drsp_fifo_o.d_source[IDW - 1 : STIDW]};
- for (genvar i = 0; i < M; i++) begin : gen_idrouting
- assign hfifo_rspvalid[i] =
- drsp_fifo_o.d_valid & (drsp_fifo_o.d_source[0 +: STIDW] == i);
- assign dfifo_rspready[i] = hreq_fifo_o[i].d_ready &
- (drsp_fifo_o.d_source[0 +: STIDW] == i) &
- drsp_fifo_o.d_valid;
-
- assign hrsp_fifo_i[i] = '{
- d_valid: hfifo_rspvalid[i],
- d_opcode: drsp_fifo_o.d_opcode,
- d_param: drsp_fifo_o.d_param,
- d_size: drsp_fifo_o.d_size,
- d_source: hfifo_rspid,
- d_sink: drsp_fifo_o.d_sink,
- d_data: drsp_fifo_o.d_data,
- d_user: drsp_fifo_o.d_user,
- d_error: drsp_fifo_o.d_error,
- a_ready: hgrant[i]
- };
- end
-
- // this assertion fails when rspid[0+:STIDW] not in [0..M-1]
- `ASSERT(rspIdInRange, drsp_fifo_o.d_valid |->
- drsp_fifo_o.d_source[0 +: STIDW] >= 0 &&
- drsp_fifo_o.d_source[0 +: STIDW] < M)
-endmodule
diff --git a/fpga/ip/tlul_width_bridge/tlul_device_downsizer.core b/fpga/ip/tlul_width_bridge/tlul_device_downsizer.core
deleted file mode 100644
index 5cc6203..0000000
--- a/fpga/ip/tlul_width_bridge/tlul_device_downsizer.core
+++ /dev/null
@@ -1,32 +0,0 @@
-CAPI=2:
-# Copyright 2025 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-name: "kelvinv2:ip:tlul_device_downsizer"
-description: "TL-UL Device Downsizer"
-
-filesets:
- files_rtl:
- depend:
- - "lowrisc:prim:all"
- - "lowrisc:tlul:headers"
- - "kelvinv2:ip:kelvin_tlul:0.1"
- files:
- - tlul_device_downsizer.sv: { file_type: systemVerilogSource }
- file_type: systemVerilogSource
-
-targets:
- default:
- filesets:
- - files_rtl
diff --git a/fpga/ip/tlul_width_bridge/tlul_device_downsizer.sv b/fpga/ip/tlul_width_bridge/tlul_device_downsizer.sv
deleted file mode 100644
index 524fb6b..0000000
--- a/fpga/ip/tlul_width_bridge/tlul_device_downsizer.sv
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-`include "prim_assert.sv"
-
-module tlul_device_downsizer
- #(parameter int AddrWidth = 32)
- (input clk_i,
- input rst_ni,
-
- // Slave (Upsizer-facing) TL-UL Interface
- input kelvin_tlul_pkg_128::tl_h2d_t s_tl_i,
- output kelvin_tlul_pkg_128::tl_d2h_t s_tl_o,
-
- // Master (Crossbar-facing) TL-UL Interface
- output kelvin_tlul_pkg_32::tl_h2d_t m_tl_o,
- input kelvin_tlul_pkg_32::tl_d2h_t m_tl_i);
-
- localparam int SlaveDataWidth = 128;
- localparam int MasterDataWidth = 32;
- localparam int LaneWidth = MasterDataWidth / 8;
- localparam int NumLanes = SlaveDataWidth / MasterDataWidth;
- localparam int LaneIndexWidth = $clog2(NumLanes);
-
- // Response path skid buffer
- kelvin_tlul_pkg_128::tl_d2h_t d_skid_reg;
- logic d_skid_valid_q, d_skid_valid_d;
- logic d_skid_ready;
-
- // Internal signals
- logic [LaneIndexWidth - 1 : 0] lane_idx;
- logic [LaneIndexWidth - 1 : 0] lane_idx_reg;
- logic [MasterDataWidth - 1 : 0] m_a_data;
- logic [MasterDataWidth / 8 - 1 : 0] m_a_mask;
- logic [1 : 0] a_size_from_mask;
-
- // Lane index calculation from mask
- always_comb begin
- // Priority encode the mask to find the active lane
- unique case (1'b1)
- |s_tl_i.a_mask[3 : 0]:
- lane_idx = 2'b00;
- |s_tl_i.a_mask[7 : 4]:
- lane_idx = 2'b01;
- |s_tl_i.a_mask[11 : 8]:
- lane_idx = 2'b10;
- |s_tl_i.a_mask[15 : 12]:
- lane_idx = 2'b11;
- default:
- lane_idx = 2'b00; // Should not happen for valid requests
- endcase
- end
-
- // Master port data and mask generation
- always_comb begin
- m_a_data = s_tl_i.a_data >> (lane_idx * MasterDataWidth);
- m_a_mask = s_tl_i.a_mask >> (lane_idx * LaneWidth);
- end
-
- // Calculate master port a_size from mask
- always_comb begin
- case ($countones(m_a_mask))
- 1:
- a_size_from_mask = 2'h0;
- 2:
- a_size_from_mask = 2'h1;
- 3, 4:
- a_size_from_mask = 2'h2;
- default:
- a_size_from_mask = 2'h0;
- endcase
- end
-
- logic [15 : 0] dbg_s_tl_i_a_size = s_tl_i.a_size;
- // Master port connections
- assign m_tl_o.a_valid = s_tl_i.a_valid;
- assign m_tl_o.a_opcode = s_tl_i.a_opcode;
- assign m_tl_o.a_param = s_tl_i.a_param;
- assign m_tl_o.a_size =
- (s_tl_i.a_opcode == tlul_pkg::Get) ? 2 : a_size_from_mask;
- assign m_tl_o.a_address = {s_tl_i.a_address[AddrWidth - 1 : 4], lane_idx,
- 2'b00};
- assign m_tl_o.a_source = s_tl_i.a_source;
- assign m_tl_o.a_data = m_a_data;
- assign m_tl_o.a_mask = m_a_mask;
- assign m_tl_o.a_user = s_tl_i.a_user;
- assign m_tl_o.d_ready = d_skid_ready;
-
- // Slave port connections
- assign s_tl_o.d_opcode = d_skid_reg.d_opcode;
- assign s_tl_o.d_param = d_skid_reg.d_param;
- assign s_tl_o.d_sink = d_skid_reg.d_sink;
- assign s_tl_o.d_source = d_skid_reg.d_source;
- assign s_tl_o.d_data = d_skid_reg.d_data;
- assign s_tl_o.d_error = d_skid_reg.d_error;
- assign s_tl_o.d_user = d_skid_reg.d_user;
- assign s_tl_o.d_size = d_skid_reg.d_size;
- assign s_tl_o.d_valid = d_skid_valid_q;
- assign s_tl_o.a_ready = m_tl_i.a_ready;
- logic d_skid_reg_size = d_skid_reg.d_size;
-
- // Skid buffer logic
- assign d_skid_ready = !d_skid_valid_q || s_tl_i.d_ready;
-
- always_comb begin
- d_skid_valid_d = d_skid_valid_q;
- if (d_skid_ready) begin
- d_skid_valid_d = m_tl_i.d_valid;
- end
- end
-
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- d_skid_valid_q <= 1'b0;
- d_skid_reg <= '0;
- lane_idx_reg <= '0;
- end else begin
- d_skid_valid_q <= d_skid_valid_d;
- if (d_skid_ready && m_tl_i.d_valid) begin
- d_skid_reg.d_opcode <= m_tl_i.d_opcode;
- d_skid_reg.d_param <= m_tl_i.d_param;
- d_skid_reg.d_sink <= m_tl_i.d_sink;
- d_skid_reg.d_source <= m_tl_i.d_source;
- d_skid_reg.d_data <= m_tl_i.d_data << (lane_idx_reg * MasterDataWidth);
- d_skid_reg.d_error <= m_tl_i.d_error;
- d_skid_reg.d_user <= m_tl_i.d_user;
- d_skid_reg.d_size <= m_tl_i.d_size;
- end
- if (s_tl_i.a_valid && s_tl_o.a_ready) begin
- lane_idx_reg <= lane_idx;
- end
- end
- end
-endmodule
diff --git a/fpga/ip/tlul_width_bridge/tlul_host_upsizer.core b/fpga/ip/tlul_width_bridge/tlul_host_upsizer.core
deleted file mode 100644
index 3c25112..0000000
--- a/fpga/ip/tlul_width_bridge/tlul_host_upsizer.core
+++ /dev/null
@@ -1,32 +0,0 @@
-CAPI=2:
-# Copyright 2025 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-name: "kelvinv2:ip:tlul_host_upsizer"
-description: "TL-UL Host Upsizer"
-
-filesets:
- files_rtl:
- depend:
- - "lowrisc:prim:all"
- - "lowrisc:tlul:headers"
- - "kelvinv2:ip:kelvin_tlul:0.1"
- files:
- - tlul_host_upsizer.sv: { file_type: systemVerilogSource }
- file_type: systemVerilogSource
-
-targets:
- default:
- filesets:
- - files_rtl
diff --git a/fpga/ip/tlul_width_bridge/tlul_host_upsizer.sv b/fpga/ip/tlul_width_bridge/tlul_host_upsizer.sv
deleted file mode 100644
index 6958dfd..0000000
--- a/fpga/ip/tlul_width_bridge/tlul_host_upsizer.sv
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2025 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-`include "prim_assert.sv"
-
-module tlul_host_upsizer
- #(parameter int AddrWidth = 32)
- (input clk_i,
- input rst_ni,
-
- // Slave (Host-facing) TL-UL Interface
- input kelvin_tlul_pkg_32::tl_h2d_t s_tl_i,
- output kelvin_tlul_pkg_32::tl_d2h_t s_tl_o,
-
- // Master (Crossbar-facing) TL-UL Interface
- output kelvin_tlul_pkg_128::tl_h2d_t m_tl_o,
- input kelvin_tlul_pkg_128::tl_d2h_t m_tl_i);
-
- localparam int SlaveDataWidth = 32;
- localparam int MasterDataWidth = 128;
- localparam int LaneWidth = SlaveDataWidth / 8;
- localparam int NumLanes = MasterDataWidth / SlaveDataWidth;
- localparam int LaneIndexWidth = $clog2(NumLanes);
-
- // Response path skid buffer
- kelvin_tlul_pkg_32::tl_d2h_t d_skid_reg;
- logic d_skid_valid_q, d_skid_valid_d;
- logic d_skid_ready;
-
- // Internal signals
- logic [LaneIndexWidth - 1 : 0] lane_idx;
- logic [LaneIndexWidth - 1 : 0] lane_idx_reg;
- logic [MasterDataWidth - 1 : 0] m_a_data;
- logic [MasterDataWidth / 8 - 1 : 0] m_a_mask;
-
- // Lane index calculation
- assign lane_idx = s_tl_i.a_address[LaneIndexWidth + 1 : 2];
-
- // Master port data and mask generation
- always_comb begin
- m_a_data = '0;
- m_a_mask = '0;
- m_a_data[lane_idx * SlaveDataWidth +: SlaveDataWidth] = s_tl_i.a_data;
- m_a_mask[lane_idx * LaneWidth +: LaneWidth] = s_tl_i.a_mask;
- end
-
- // Master port connections
- assign m_tl_o.a_valid = s_tl_i.a_valid;
- assign m_tl_o.a_opcode = s_tl_i.a_opcode;
- assign m_tl_o.a_param = s_tl_i.a_param;
- assign m_tl_o.a_size = s_tl_i.a_size;
- assign m_tl_o.a_address = {
- s_tl_i.a_address[AddrWidth - 1 : LaneIndexWidth + 2],
- {(LaneIndexWidth + 2){1'b0}}};
- assign m_tl_o.a_source = s_tl_i.a_source;
- assign m_tl_o.a_data = m_a_data;
- assign m_tl_o.a_mask = m_a_mask;
- assign m_tl_o.a_user = s_tl_i.a_user;
- assign m_tl_o.d_ready = d_skid_ready;
-
- // Slave port connections
- assign s_tl_o.d_opcode = d_skid_reg.d_opcode;
- assign s_tl_o.d_param = d_skid_reg.d_param;
- assign s_tl_o.d_sink = d_skid_reg.d_sink;
- assign s_tl_o.d_source = d_skid_reg.d_source;
- assign s_tl_o.d_data = d_skid_reg.d_data;
- assign s_tl_o.d_error = d_skid_reg.d_error;
- assign s_tl_o.d_user = d_skid_reg.d_user;
- assign s_tl_o.d_size = d_skid_reg.d_size;
- assign s_tl_o.d_valid = d_skid_valid_q;
- assign s_tl_o.a_ready = m_tl_i.a_ready;
-
- // Skid buffer logic
- assign d_skid_ready = !d_skid_valid_q || s_tl_i.d_ready;
-
- always_comb begin
- d_skid_valid_d = d_skid_valid_q;
- if (d_skid_ready) begin
- d_skid_valid_d = m_tl_i.d_valid;
- end
- end
-
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- d_skid_valid_q <= 1'b0;
- d_skid_reg <= '0;
- lane_idx_reg <= '0;
- end else begin
- d_skid_valid_q <= d_skid_valid_d;
- if (d_skid_ready && m_tl_i.d_valid) begin
- d_skid_reg.d_opcode <= m_tl_i.d_opcode;
- d_skid_reg.d_param <= m_tl_i.d_param;
- d_skid_reg.d_sink <= m_tl_i.d_sink;
- d_skid_reg.d_source <= m_tl_i.d_source;
- d_skid_reg.d_data <= m_tl_i.d_data >> (lane_idx_reg * SlaveDataWidth);
- d_skid_reg.d_error <= m_tl_i.d_error;
- d_skid_reg.d_user <= m_tl_i.d_user;
- d_skid_reg.d_size <= m_tl_i.d_size;
- end
- if (s_tl_i.a_valid && s_tl_o.a_ready) begin
- lane_idx_reg <= lane_idx;
- end
- end
- end
-endmodule
\ No newline at end of file
diff --git a/fpga/ip/tlul_width_bridge/BUILD b/fpga/ip/xbar_kelvin_soc_chisel/BUILD
similarity index 60%
rename from fpga/ip/tlul_width_bridge/BUILD
rename to fpga/ip/xbar_kelvin_soc_chisel/BUILD
index d78f918..fe7f6ab 100644
--- a/fpga/ip/tlul_width_bridge/BUILD
+++ b/fpga/ip/xbar_kelvin_soc_chisel/BUILD
@@ -14,10 +14,29 @@
package(default_visibility = ["//visibility:public"])
+genrule(
+ name = "kelvin_xbar",
+ srcs = ["//hdl/chisel/src/soc:KelvinXbar.sv"],
+ outs = ["KelvinXbar.sv"],
+ cmd = "cp $< $@",
+)
+
+genrule(
+ name = "generate_core_file",
+ srcs = [
+ "xbar_kelvin_soc_chisel.core.tpl",
+ ":kelvin_xbar",
+ ],
+ outs = ["xbar_kelvin_soc_chisel.core"],
+ cmd = "sed 's|__VERILOG_FILE__|KelvinXbar.sv|' $(location xbar_kelvin_soc_chisel.core.tpl) > $@",
+)
+
filegroup(
name = "rtl_files",
srcs = glob([
"*.sv",
"*.core",
- ]),
+ ]) + [
+ ":KelvinXbar.sv",
+ ],
)
diff --git a/fpga/ip/xbar_kelvin_soc_chisel/xbar_kelvin_soc_chisel.core b/fpga/ip/xbar_kelvin_soc_chisel/xbar_kelvin_soc_chisel.core
new file mode 100644
index 0000000..b469a7a
--- /dev/null
+++ b/fpga/ip/xbar_kelvin_soc_chisel/xbar_kelvin_soc_chisel.core
@@ -0,0 +1,14 @@
+CAPI=2:
+name: "kelvinv2:ip:xbar_kelvin_soc_chisel:0.1"
+description: "Kelvin SoC Chisel-Generated Crossbar"
+
+filesets:
+ rtl:
+ files:
+ - KelvinXbar.sv
+ file_type: systemVerilogSource
+
+targets:
+ default:
+ filesets:
+ - rtl
diff --git a/fpga/ip/xbar_kelvin_soc_chisel/xbar_kelvin_soc_chisel.core.tpl b/fpga/ip/xbar_kelvin_soc_chisel/xbar_kelvin_soc_chisel.core.tpl
new file mode 100644
index 0000000..88044d9
--- /dev/null
+++ b/fpga/ip/xbar_kelvin_soc_chisel/xbar_kelvin_soc_chisel.core.tpl
@@ -0,0 +1,14 @@
+CAPI=2:
+name: "kelvinv2:ip:xbar_kelvin_soc_chisel:0.1"
+description: "Kelvin SoC Chisel-Generated Crossbar"
+
+filesets:
+ rtl:
+ files:
+ - __VERILOG_FILE__
+ file_type: systemVerilogSource
+
+targets:
+ default:
+ filesets:
+ - rtl
diff --git a/fpga/kelvin_soc.core b/fpga/kelvin_soc.core
index 3db97b4..7cfb9e2 100644
--- a/fpga/kelvin_soc.core
+++ b/fpga/kelvin_soc.core
@@ -5,7 +5,7 @@
filesets:
rtl:
depend:
- - lowrisc:ip:xbar_kelvin_soc_xbar:0.1
+ - kelvinv2:ip:xbar_kelvin_soc_chisel:0.1
- com.google.kelvin:fpga:kelvin_soc_pkg:0.1
- com.google.kelvin:fpga:racl_pkg:0.1
- lowrisc:ip:uart:0.1
@@ -15,8 +15,6 @@
- lowrisc:ip:spi_device:0.1
- lowrisc:kelvin_ip:rv_core_ibex:0.1
- google:kelvin:rvv_core_mini_tlul
- - kelvinv2:ip:tlul_host_upsizer
- - kelvinv2:ip:tlul_device_downsizer
- lowrisc:ibex:ibex_tracer
- kelvinv2:ip:sram:0.1
- kelvinv2:ip:kelvin_tlul:0.1
diff --git a/fpga/main.cc b/fpga/main.cc
index 3e1d352..bc5fe64 100644
--- a/fpga/main.cc
+++ b/fpga/main.cc
@@ -45,7 +45,7 @@
memutil.RegisterMemoryArea("dtcm", 0x00010000, &dtcm);
simctrl.RegisterExtension(&memutil);
- simctrl.SetInitialResetDelay(20000);
+ simctrl.SetInitialResetDelay(2000);
simctrl.SetResetDuration(10);
std::cout << "Simulation of Kelvin SoC" << std::endl
diff --git a/fpga/post_process_xbar.py b/fpga/post_process_xbar.py
deleted file mode 100644
index 20179ab..0000000
--- a/fpga/post_process_xbar.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2025 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""A script to post-process the output of tlgen.
-
-This script takes an input directory and an output directory. It copies the
-contents of the input directory to the output directory, and then modifies the
-generated SystemVerilog file to use the correct TileLink types.
-"""
-
-import argparse
-import os
-import re
-import shutil
-import stat
-
-
-def main():
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument(
- "--input-dir",
- required=True,
- help="The input directory.",
- )
- parser.add_argument(
- "--output-dir",
- required=True,
- help="The output directory.",
- )
- parser.add_argument(
- "--cores",
- nargs="+",
- required=True,
- help="The cores to add as dependencies.",
- )
- args = parser.parse_args()
-
- # Copy the contents of the input directory to the output directory.
- if os.path.exists(args.output_dir):
- shutil.rmtree(args.output_dir)
- shutil.copytree(args.input_dir, args.output_dir)
-
- # Find the generated SystemVerilog file.
- sv_file = None
- for root, _, files in os.walk(args.output_dir):
- for f in files:
- if f == "xbar_kelvin_soc_xbar.sv":
- sv_file = os.path.join(root, f)
- break
- if sv_file:
- break
-
- if sv_file is None:
- raise RuntimeError("Could not find generated SystemVerilog file.")
-
- # Make the file writable.
- os.chmod(sv_file, stat.S_IWRITE | stat.S_IREAD)
-
- # Read the file and perform the replacements.
- with open(sv_file, "r") as f:
- content = f.read()
- original_content = content
- content = content.replace("tlul_pkg::tl_h2d_t",
- "kelvin_tlul_pkg_128::tl_h2d_t")
- content = content.replace("tlul_pkg::tl_d2h_t",
- "kelvin_tlul_pkg_128::tl_d2h_t")
- content = content.replace("import tlul_pkg::*",
- "import kelvin_tlul_pkg_128::*")
- content = content.replace("tlul_socket_1n #", "tlul_socket_1n_128 #")
- content = content.replace("tlul_socket_m1 #", "tlul_socket_m1_128 #")
- content = content.replace("tlul_fifo_async #", "tlul_fifo_async_128 #")
-
- if original_content == content:
- print("Warning: No replacements made.")
- else:
- print("Success: Replacements made.")
-
- with open(sv_file, "w") as f:
- f.write(content)
-
- core_file = None
- for root, _, files in os.walk(args.output_dir):
- for f in files:
- if f == "xbar_kelvin_soc_xbar.core":
- core_file = os.path.join(root, f)
- break
- if core_file:
- break
- if core_file is None:
- raise RuntimeError("Could not find generated core file.")
- os.chmod(core_file, stat.S_IWRITE | stat.S_IREAD)
- with open(core_file, "r") as f:
- content = f.read()
- original_content = content
- for core in args.cores:
- content = re.sub(r"(\s+)depend:", r"\1depend:\n\1 - " + core, content)
- if original_content == content:
- print("Warning: No replacements made (core).")
- else:
- print("Success: replacesments made (core).")
- with open(core_file, "w") as f:
- f.write(content)
-
-
-if __name__ == "__main__":
- main()
diff --git a/fpga/rtl/chip_nexus.sv b/fpga/rtl/chip_nexus.sv
index 30f8dff..50dd228 100644
--- a/fpga/rtl/chip_nexus.sv
+++ b/fpga/rtl/chip_nexus.sv
@@ -14,7 +14,7 @@
module chip_nexus
#(parameter MemInitFile = "",
- parameter int ClockFrequencyMhz = 10)
+ parameter int ClockFrequencyMhz = 80)
(input clk_p_i,
input clk_n_i,
input rst_ni,
@@ -28,6 +28,8 @@
logic clk;
logic rst_n;
+ logic clk_ibex;
+ logic rst_ibex_n;
logic clk_48MHz;
logic clk_aon;
@@ -50,12 +52,27 @@
.clk_main_o(clk),
.clk_48MHz_o(clk_48MHz),
.clk_aon_o(clk_aon),
+ .clk_ibex_o(clk_ibex),
.rst_no(rst_n));
+ // Reset synchronizer for Ibex reset.
+ logic rst_n_sync;
+ always_ff @(posedge clk_ibex or negedge rst_n) begin
+ if (!rst_n) begin
+ rst_n_sync <= 1'b0;
+ rst_ibex_n <= 1'b0;
+ end else begin
+ rst_n_sync <= 1'b1;
+ rst_ibex_n <= rst_n_sync;
+ end
+ end
+
kelvin_soc #(.MemInitFile(MemInitFile),
.ClockFrequencyMhz(ClockFrequencyMhz))
i_kelvin_soc(.clk_i(clk),
.rst_ni(rst_n),
+ .ibex_clk_i(clk_ibex),
+ .ibex_rst_ni(rst_ibex_n),
.spi_clk_i(spi_clk_i),
.scanmode_i(prim_mubi_pkg::MuBi4False),
.uart_sideband_i(uart_sideband_i),
diff --git a/fpga/rtl/chip_verilator.sv b/fpga/rtl/chip_verilator.sv
index b94ffcb..ce495ed 100644
--- a/fpga/rtl/chip_verilator.sv
+++ b/fpga/rtl/chip_verilator.sv
@@ -14,7 +14,7 @@
module chip_verilator
#(parameter MemInitFile = "",
- parameter int ClockFrequencyMhz = 10)
+ parameter int ClockFrequencyMhz = 80)
(input clk_i,
input rst_ni,
input spi_clk_i,
@@ -52,6 +52,8 @@
.ClockFrequencyMhz(ClockFrequencyMhz))
i_kelvin_soc(.clk_i(clk_i),
.rst_ni(rst_ni),
+ .ibex_clk_i(ibex_clk_i),
+ .ibex_rst_ni(ibex_rst_ni),
.spi_clk_i(spi_clk_i),
.scanmode_i(scanmode_i),
.uart_sideband_i(
@@ -62,4 +64,29 @@
assign uart0_tx = uart_sideband_o[0].cio_tx;
assign uart1_tx = uart_sideband_o[1].cio_tx;
+
+ // Clock divider for Ibex clock.
+ logic [1:0] clk_divider;
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ clk_divider <= 2'b0;
+ end else begin
+ clk_divider <= clk_divider + 1;
+ end
+ end
+ logic ibex_clk_i;
+ assign ibex_clk_i = clk_divider[1];
+
+ // Reset synchronizer for Ibex reset.
+ logic ibex_rst_ni;
+ logic rst_n_sync;
+ always_ff @(posedge ibex_clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ rst_n_sync <= 1'b0;
+ ibex_rst_ni <= 1'b0;
+ end else begin
+ rst_n_sync <= 1'b1;
+ ibex_rst_ni <= rst_n_sync;
+ end
+ end
endmodule
diff --git a/fpga/rtl/clkgen_wrapper.sv b/fpga/rtl/clkgen_wrapper.sv
index 55339ef..bcc8bcc 100644
--- a/fpga/rtl/clkgen_wrapper.sv
+++ b/fpga/rtl/clkgen_wrapper.sv
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
module clkgen_wrapper
- #(parameter int ClockFrequencyMhz = 10)
+ #(parameter int ClockFrequencyMhz = 80)
(input clk_p_i,
input clk_n_i,
input rst_ni,
@@ -11,6 +11,7 @@
output clk_main_o,
output clk_48MHz_o,
output clk_aon_o,
+ output clk_ibex_o,
output rst_no);
clkgen_xilultrascaleplus #(.ClockFrequencyMhz(ClockFrequencyMhz))
@@ -21,5 +22,6 @@
.clk_main_o(clk_main_o),
.clk_48MHz_o(clk_48MHz_o),
.clk_aon_o(clk_aon_o),
+ .clk_ibex_o(clk_ibex_o),
.rst_no(rst_no));
endmodule
\ No newline at end of file
diff --git a/fpga/rtl/clkgen_xilultrascaleplus.sv b/fpga/rtl/clkgen_xilultrascaleplus.sv
index 9817265..bedc4a5 100644
--- a/fpga/rtl/clkgen_xilultrascaleplus.sv
+++ b/fpga/rtl/clkgen_xilultrascaleplus.sv
@@ -14,7 +14,7 @@
// limitations under the License.
module clkgen_xilultrascaleplus
- #(parameter int ClockFrequencyMhz = 10,
+ #(parameter int ClockFrequencyMhz = 80,
// Add BUFG if not done by downstream logic
parameter bit AddClkBuf = 1)
(input clk_i,
@@ -24,6 +24,7 @@
output clk_main_o,
output clk_48MHz_o,
output clk_aon_o,
+ output clk_ibex_o,
output rst_no);
logic locked_pll;
logic io_clk_buf;
@@ -36,6 +37,8 @@
logic clk_48_unbuf;
logic clk_aon_buf;
logic clk_aon_unbuf;
+ logic clk_ibex_buf;
+ logic clk_ibex_unbuf;
logic clk_ibufds_o;
// Input IBUFDS conver diff-pair to single-end
@@ -44,6 +47,7 @@
.O(clk_ibufds_o));
localparam real CLKOUT0_DIVIDE_F_CALC = 1200.0 / ClockFrequencyMhz;
+ localparam int CLKOUT2_DIVIDE_CALC = CLKOUT0_DIVIDE_F_CALC * 4;
MMCME2_ADV #(
.BANDWIDTH("OPTIMIZED"),
@@ -58,6 +62,9 @@
.CLKOUT1_DIVIDE(25),
.CLKOUT1_PHASE(0.000),
.CLKOUT1_DUTY_CYCLE(0.500),
+ .CLKOUT2_DIVIDE(CLKOUT2_DIVIDE_CALC),
+ .CLKOUT2_PHASE(0.000),
+ .CLKOUT2_DUTY_CYCLE(0.500),
// With CLKOUT4_CASCADE, CLKOUT6's divider is an input to CLKOUT4's
// divider. The effective ratio is a multiplication of the two.
.CLKOUT4_DIVIDE(40),
@@ -72,7 +79,7 @@
.CLKOUT0B(),
.CLKOUT1(clk_48_unbuf),
.CLKOUT1B(),
- .CLKOUT2(),
+ .CLKOUT2(clk_ibex_unbuf),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
@@ -120,10 +127,14 @@
BUFGCE clk_48_bufgce(.I(clk_48_unbuf),
.O(clk_48_buf));
+
+ BUFGCE clk_ibex_bufgce(.I(clk_ibex_unbuf),
+ .O(clk_ibex_buf));
end else begin : gen_no_clk_bufs
// BUFGs added by downstream modules, no need to add here
assign clk_10_buf = clk_10_unbuf;
assign clk_48_buf = clk_48_unbuf;
+ assign clk_ibex_buf = clk_ibex_unbuf;
end
// outputs
@@ -131,6 +142,7 @@
assign clk_main_o = clk_10_buf;
assign clk_48MHz_o = clk_48_buf;
assign clk_aon_o = clk_aon_buf;
+ assign clk_ibex_o = clk_ibex_buf;
// reset
assign rst_no = locked_pll & rst_ni & srst_ni;
diff --git a/fpga/rtl/kelvin_soc.sv b/fpga/rtl/kelvin_soc.sv
index 1c23def..479f887 100644
--- a/fpga/rtl/kelvin_soc.sv
+++ b/fpga/rtl/kelvin_soc.sv
@@ -14,9 +14,11 @@
module kelvin_soc
#(parameter MemInitFile = "",
- parameter int ClockFrequencyMhz = 10)
+ parameter int ClockFrequencyMhz = 80)
(input clk_i,
input rst_ni,
+ input ibex_clk_i,
+ input ibex_rst_ni,
input spi_clk_i,
input prim_mubi_pkg::mubi4_t scanmode_i,
input top_pkg::uart_sideband_i_t[1 : 0] uart_sideband_i,
@@ -34,102 +36,257 @@
kelvin_tlul_pkg_32::tl_h2d_t tl_ibex_core_i_o_32;
kelvin_tlul_pkg_32::tl_d2h_t tl_ibex_core_i_i_32;
- kelvin_tlul_pkg_128::tl_h2d_t tl_ibex_core_i_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_ibex_core_i_i_xbar;
-
- tlul_host_upsizer i_ibex_core_i_upsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_ibex_core_i_o_32),
- .s_tl_o(tl_ibex_core_i_i_32),
- .m_tl_o(tl_ibex_core_i_o_xbar),
- .m_tl_i(tl_ibex_core_i_i_xbar));
kelvin_tlul_pkg_32::tl_h2d_t tl_rom_o_32;
kelvin_tlul_pkg_32::tl_d2h_t tl_rom_i_32;
- kelvin_tlul_pkg_128::tl_h2d_t tl_rom_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_rom_i_xbar;
- tlul_device_downsizer i_rom_downsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_rom_o_xbar),
- .s_tl_o(tl_rom_i_xbar),
- .m_tl_o(tl_rom_o_32),
- .m_tl_i(tl_rom_i_32));
kelvin_tlul_pkg_32::tl_h2d_t tl_ibex_core_d_o_32;
kelvin_tlul_pkg_32::tl_d2h_t tl_ibex_core_d_i_32;
- kelvin_tlul_pkg_128::tl_h2d_t tl_ibex_core_d_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_ibex_core_d_i_xbar;
- tlul_host_upsizer i_ibex_core_d_upsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_ibex_core_d_o_32),
- .s_tl_o(tl_ibex_core_d_i_32),
- .m_tl_o(tl_ibex_core_d_o_xbar),
- .m_tl_i(tl_ibex_core_d_i_xbar));
-
- kelvin_tlul_pkg_128::tl_h2d_t tl_sram_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_sram_i_xbar;
tl_h2d_t tl_sram_o;
tl_d2h_t tl_sram_i;
- tlul_device_downsizer i_sram_downsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_sram_o_xbar),
- .s_tl_o(tl_sram_i_xbar),
- .m_tl_o(tl_sram_o),
- .m_tl_i(tl_sram_i));
- kelvin_tlul_pkg_128::tl_h2d_t tl_uart0_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_uart0_i_xbar;
+
tl_h2d_t tl_uart0_o;
tl_d2h_t tl_uart0_i;
- tlul_device_downsizer i_uart0_downsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_uart0_o_xbar),
- .s_tl_o(tl_uart0_i_xbar),
- .m_tl_o(tl_uart0_o),
- .m_tl_i(tl_uart0_i));
- kelvin_tlul_pkg_128::tl_h2d_t tl_uart1_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_uart1_i_xbar;
+
tl_h2d_t tl_uart1_o;
tl_d2h_t tl_uart1_i;
- tlul_device_downsizer i_uart1_downsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_uart1_o_xbar),
- .s_tl_o(tl_uart1_i_xbar),
- .m_tl_o(tl_uart1_o),
- .m_tl_i(tl_uart1_i));
- kelvin_tlul_pkg_128::tl_h2d_t tl_spi0_o_xbar;
- kelvin_tlul_pkg_128::tl_d2h_t tl_spi0_i_xbar;
+
tl_h2d_t tl_spi0_o;
tl_d2h_t tl_spi0_i;
- tlul_device_downsizer i_spi0_downsizer(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .s_tl_i(tl_spi0_o_xbar),
- .s_tl_o(tl_spi0_i_xbar),
- .m_tl_o(tl_spi0_o),
- .m_tl_i(tl_spi0_i));
- xbar_kelvin_soc_xbar i_xbar(.clk_i(clk_i),
- .rst_ni(rst_ni),
- .spi_clk_i(spi_clk_i),
- .scanmode_i(scanmode_i),
- .tl_kelvin_core_i(tl_kelvin_core_i),
- .tl_kelvin_core_o(tl_kelvin_core_o),
- .tl_ibex_core_i_o(tl_ibex_core_i_i_xbar),
- .tl_ibex_core_i_i(tl_ibex_core_i_o_xbar),
- .tl_ibex_core_d_o(tl_ibex_core_d_i_xbar),
- .tl_ibex_core_d_i(tl_ibex_core_d_o_xbar),
- .tl_kelvin_device_o(tl_kelvin_device_o),
- .tl_kelvin_device_i(tl_kelvin_device_i),
- .tl_rom_o(tl_rom_o_xbar),
- .tl_rom_i(tl_rom_i_xbar),
- .tl_sram_o(tl_sram_o_xbar),
- .tl_sram_i(tl_sram_i_xbar),
- .tl_uart0_o(tl_uart0_o_xbar),
- .tl_uart0_i(tl_uart0_i_xbar),
- .tl_uart1_o(tl_uart1_o_xbar),
- .tl_uart1_i(tl_uart1_i_xbar),
- .tl_spi0_o(tl_spi0_o_xbar),
- .tl_spi0_i(tl_spi0_i_xbar));
+ KelvinXbar i_xbar(
+ .io_clk_i(clk_i),
+ .io_rst_ni(rst_ni),
+ .io_async_ports_devices_0_clock(spi_clk_i),
+ .io_async_ports_devices_0_reset(rst_ni),
+ .io_async_ports_hosts_0_clock(ibex_clk_i),
+ .io_async_ports_hosts_0_reset(ibex_rst_ni),
+
+ // Host connections
+ .io_hosts_0_a_valid(tl_kelvin_core_i.a_valid),
+ .io_hosts_0_a_bits_opcode(tl_kelvin_core_i.a_opcode),
+ .io_hosts_0_a_bits_param(tl_kelvin_core_i.a_param),
+ .io_hosts_0_a_bits_size(tl_kelvin_core_i.a_size),
+ .io_hosts_0_a_bits_source(tl_kelvin_core_i.a_source),
+ .io_hosts_0_a_bits_address(tl_kelvin_core_i.a_address),
+ .io_hosts_0_a_bits_mask(tl_kelvin_core_i.a_mask),
+ .io_hosts_0_a_bits_data(tl_kelvin_core_i.a_data),
+ .io_hosts_0_a_bits_user_rsvd(tl_kelvin_core_i.a_user.rsvd),
+ .io_hosts_0_a_bits_user_instr_type(tl_kelvin_core_i.a_user.instr_type),
+ .io_hosts_0_a_bits_user_cmd_intg(tl_kelvin_core_i.a_user.cmd_intg),
+ .io_hosts_0_a_bits_user_data_intg(tl_kelvin_core_i.a_user.data_intg),
+ .io_hosts_0_d_ready(tl_kelvin_core_i.d_ready),
+ .io_hosts_1_a_valid(tl_ibex_core_i_o_32.a_valid),
+ .io_hosts_1_a_bits_opcode(tl_ibex_core_i_o_32.a_opcode),
+ .io_hosts_1_a_bits_param(tl_ibex_core_i_o_32.a_param),
+ .io_hosts_1_a_bits_size(tl_ibex_core_i_o_32.a_size),
+ .io_hosts_1_a_bits_source(tl_ibex_core_i_o_32.a_source),
+ .io_hosts_1_a_bits_address(tl_ibex_core_i_o_32.a_address),
+ .io_hosts_1_a_bits_mask(tl_ibex_core_i_o_32.a_mask),
+ .io_hosts_1_a_bits_data(tl_ibex_core_i_o_32.a_data),
+ .io_hosts_1_a_bits_user_rsvd(tl_ibex_core_i_o_32.a_user.rsvd),
+ .io_hosts_1_a_bits_user_instr_type(tl_ibex_core_i_o_32.a_user.instr_type),
+ .io_hosts_1_a_bits_user_cmd_intg(tl_ibex_core_i_o_32.a_user.cmd_intg),
+ .io_hosts_1_a_bits_user_data_intg(tl_ibex_core_i_o_32.a_user.data_intg),
+ .io_hosts_1_d_ready(tl_ibex_core_i_o_32.d_ready),
+ .io_hosts_2_a_valid(tl_ibex_core_d_o_32.a_valid),
+ .io_hosts_2_a_bits_opcode(tl_ibex_core_d_o_32.a_opcode),
+ .io_hosts_2_a_bits_param(tl_ibex_core_d_o_32.a_param),
+ .io_hosts_2_a_bits_size(tl_ibex_core_d_o_32.a_size),
+ .io_hosts_2_a_bits_source(tl_ibex_core_d_o_32.a_source),
+ .io_hosts_2_a_bits_address(tl_ibex_core_d_o_32.a_address),
+ .io_hosts_2_a_bits_mask(tl_ibex_core_d_o_32.a_mask),
+ .io_hosts_2_a_bits_data(tl_ibex_core_d_o_32.a_data),
+ .io_hosts_2_a_bits_user_rsvd(tl_ibex_core_d_o_32.a_user.rsvd),
+ .io_hosts_2_a_bits_user_instr_type(tl_ibex_core_d_o_32.a_user.instr_type),
+ .io_hosts_2_a_bits_user_cmd_intg(tl_ibex_core_d_o_32.a_user.cmd_intg),
+ .io_hosts_2_a_bits_user_data_intg(tl_ibex_core_d_o_32.a_user.data_intg),
+ .io_hosts_2_d_ready(tl_ibex_core_d_o_32.d_ready),
+
+ // Host response connections
+ .io_hosts_0_a_ready(tl_kelvin_core_o.a_ready),
+ .io_hosts_0_d_valid(tl_kelvin_core_o.d_valid),
+ .io_hosts_0_d_bits_opcode(tl_kelvin_core_o.d_opcode),
+ .io_hosts_0_d_bits_param(tl_kelvin_core_o.d_param),
+ .io_hosts_0_d_bits_size(tl_kelvin_core_o.d_size),
+ .io_hosts_0_d_bits_source(tl_kelvin_core_o.d_source),
+ .io_hosts_0_d_bits_sink(tl_kelvin_core_o.d_sink),
+ .io_hosts_0_d_bits_data(tl_kelvin_core_o.d_data),
+ .io_hosts_0_d_bits_error(tl_kelvin_core_o.d_error),
+ .io_hosts_0_d_bits_user_rsp_intg(tl_kelvin_core_o.d_user.rsp_intg),
+ .io_hosts_0_d_bits_user_data_intg(tl_kelvin_core_o.d_user.data_intg),
+ .io_hosts_1_a_ready(tl_ibex_core_i_i_32.a_ready),
+ .io_hosts_1_d_valid(tl_ibex_core_i_i_32.d_valid),
+ .io_hosts_1_d_bits_opcode(tl_ibex_core_i_i_32.d_opcode),
+ .io_hosts_1_d_bits_param(tl_ibex_core_i_i_32.d_param),
+ .io_hosts_1_d_bits_size(tl_ibex_core_i_i_32.d_size),
+ .io_hosts_1_d_bits_source(tl_ibex_core_i_i_32.d_source),
+ .io_hosts_1_d_bits_sink(tl_ibex_core_i_i_32.d_sink),
+ .io_hosts_1_d_bits_data(tl_ibex_core_i_i_32.d_data),
+ .io_hosts_1_d_bits_error(tl_ibex_core_i_i_32.d_error),
+ .io_hosts_1_d_bits_user_rsp_intg(tl_ibex_core_i_i_32.d_user.rsp_intg),
+ .io_hosts_1_d_bits_user_data_intg(tl_ibex_core_i_i_32.d_user.data_intg),
+ .io_hosts_2_a_ready(tl_ibex_core_d_i_32.a_ready),
+ .io_hosts_2_d_valid(tl_ibex_core_d_i_32.d_valid),
+ .io_hosts_2_d_bits_opcode(tl_ibex_core_d_i_32.d_opcode),
+ .io_hosts_2_d_bits_param(tl_ibex_core_d_i_32.d_param),
+ .io_hosts_2_d_bits_size(tl_ibex_core_d_i_32.d_size),
+ .io_hosts_2_d_bits_source(tl_ibex_core_d_i_32.d_source),
+ .io_hosts_2_d_bits_sink(tl_ibex_core_d_i_32.d_sink),
+ .io_hosts_2_d_bits_data(tl_ibex_core_d_i_32.d_data),
+ .io_hosts_2_d_bits_error(tl_ibex_core_d_i_32.d_error),
+ .io_hosts_2_d_bits_user_rsp_intg(tl_ibex_core_d_i_32.d_user.rsp_intg),
+ .io_hosts_2_d_bits_user_data_intg(tl_ibex_core_d_i_32.d_user.data_intg),
+
+ // Device connections
+ .io_devices_0_a_ready(tl_kelvin_device_i.a_ready),
+ .io_devices_0_d_valid(tl_kelvin_device_i.d_valid),
+ .io_devices_0_d_bits_opcode(tl_kelvin_device_i.d_opcode),
+ .io_devices_0_d_bits_param(tl_kelvin_device_i.d_param),
+ .io_devices_0_d_bits_size(tl_kelvin_device_i.d_size),
+ .io_devices_0_d_bits_source(tl_kelvin_device_i.d_source),
+ .io_devices_0_d_bits_sink(tl_kelvin_device_i.d_sink),
+ .io_devices_0_d_bits_data(tl_kelvin_device_i.d_data),
+ .io_devices_0_d_bits_error(tl_kelvin_device_i.d_error),
+ .io_devices_0_d_bits_user_rsp_intg(tl_kelvin_device_i.d_user.rsp_intg),
+ .io_devices_0_d_bits_user_data_intg(tl_kelvin_device_i.d_user.data_intg),
+ .io_devices_1_a_ready(tl_rom_i_32.a_ready),
+ .io_devices_1_d_valid(tl_rom_i_32.d_valid),
+ .io_devices_1_d_bits_opcode(tl_rom_i_32.d_opcode),
+ .io_devices_1_d_bits_param(tl_rom_i_32.d_param),
+ .io_devices_1_d_bits_size(tl_rom_i_32.d_size),
+ .io_devices_1_d_bits_source(tl_rom_i_32.d_source),
+ .io_devices_1_d_bits_sink(tl_rom_i_32.d_sink),
+ .io_devices_1_d_bits_data(tl_rom_i_32.d_data),
+ .io_devices_1_d_bits_error(tl_rom_i_32.d_error),
+ .io_devices_1_d_bits_user_rsp_intg(tl_rom_i_32.d_user.rsp_intg),
+ .io_devices_1_d_bits_user_data_intg(tl_rom_i_32.d_user.data_intg),
+ .io_devices_2_a_ready(tl_sram_i.a_ready),
+ .io_devices_2_d_valid(tl_sram_i.d_valid),
+ .io_devices_2_d_bits_opcode(tl_sram_i.d_opcode),
+ .io_devices_2_d_bits_param(tl_sram_i.d_param),
+ .io_devices_2_d_bits_size(tl_sram_i.d_size),
+ .io_devices_2_d_bits_source(tl_sram_i.d_source),
+ .io_devices_2_d_bits_sink(tl_sram_i.d_sink),
+ .io_devices_2_d_bits_data(tl_sram_i.d_data),
+ .io_devices_2_d_bits_error(tl_sram_i.d_error),
+ .io_devices_2_d_bits_user_rsp_intg(tl_sram_i.d_user.rsp_intg),
+ .io_devices_2_d_bits_user_data_intg(tl_sram_i.d_user.data_intg),
+ .io_devices_3_a_ready(tl_uart0_i.a_ready),
+ .io_devices_3_d_valid(tl_uart0_i.d_valid),
+ .io_devices_3_d_bits_opcode(tl_uart0_i.d_opcode),
+ .io_devices_3_d_bits_param(tl_uart0_i.d_param),
+ .io_devices_3_d_bits_size(tl_uart0_i.d_size),
+ .io_devices_3_d_bits_source(tl_uart0_i.d_source),
+ .io_devices_3_d_bits_sink(tl_uart0_i.d_sink),
+ .io_devices_3_d_bits_data(tl_uart0_i.d_data),
+ .io_devices_3_d_bits_error(tl_uart0_i.d_error),
+ .io_devices_3_d_bits_user_rsp_intg(tl_uart0_i.d_user.rsp_intg),
+ .io_devices_3_d_bits_user_data_intg(tl_uart0_i.d_user.data_intg),
+ .io_devices_4_a_ready(tl_uart1_i.a_ready),
+ .io_devices_4_d_valid(tl_uart1_i.d_valid),
+ .io_devices_4_d_bits_opcode(tl_uart1_i.d_opcode),
+ .io_devices_4_d_bits_param(tl_uart1_i.d_param),
+ .io_devices_4_d_bits_size(tl_uart1_i.d_size),
+ .io_devices_4_d_bits_source(tl_uart1_i.d_source),
+ .io_devices_4_d_bits_sink(tl_uart1_i.d_sink),
+ .io_devices_4_d_bits_data(tl_uart1_i.d_data),
+ .io_devices_4_d_bits_error(tl_uart1_i.d_error),
+ .io_devices_4_d_bits_user_rsp_intg(tl_uart1_i.d_user.rsp_intg),
+ .io_devices_4_d_bits_user_data_intg(tl_uart1_i.d_user.data_intg),
+ .io_devices_5_a_ready(tl_spi0_i.a_ready),
+ .io_devices_5_d_valid(tl_spi0_i.d_valid),
+ .io_devices_5_d_bits_opcode(tl_spi0_i.d_opcode),
+ .io_devices_5_d_bits_param(tl_spi0_i.d_param),
+ .io_devices_5_d_bits_size(tl_spi0_i.d_size),
+ .io_devices_5_d_bits_source(tl_spi0_i.d_source),
+ .io_devices_5_d_bits_sink(tl_spi0_i.d_sink),
+ .io_devices_5_d_bits_data(tl_spi0_i.d_data),
+ .io_devices_5_d_bits_error(tl_spi0_i.d_error),
+ .io_devices_5_d_bits_user_rsp_intg(tl_spi0_i.d_user.rsp_intg),
+ .io_devices_5_d_bits_user_data_intg(tl_spi0_i.d_user.data_intg),
+
+ // Device response connections
+ .io_devices_0_a_valid(tl_kelvin_device_o.a_valid),
+ .io_devices_0_a_bits_opcode(tl_kelvin_device_o.a_opcode),
+ .io_devices_0_a_bits_param(tl_kelvin_device_o.a_param),
+ .io_devices_0_a_bits_size(tl_kelvin_device_o.a_size),
+ .io_devices_0_a_bits_source(tl_kelvin_device_o.a_source),
+ .io_devices_0_a_bits_address(tl_kelvin_device_o.a_address),
+ .io_devices_0_a_bits_mask(tl_kelvin_device_o.a_mask),
+ .io_devices_0_a_bits_data(tl_kelvin_device_o.a_data),
+ .io_devices_0_a_bits_user_rsvd(tl_kelvin_device_o.a_user.rsvd),
+ .io_devices_0_a_bits_user_instr_type(tl_kelvin_device_o.a_user.instr_type),
+ .io_devices_0_a_bits_user_cmd_intg(tl_kelvin_device_o.a_user.cmd_intg),
+ .io_devices_0_a_bits_user_data_intg(tl_kelvin_device_o.a_user.data_intg),
+ .io_devices_0_d_ready(tl_kelvin_device_o.d_ready),
+ .io_devices_1_a_valid(tl_rom_o_32.a_valid),
+ .io_devices_1_a_bits_opcode(tl_rom_o_32.a_opcode),
+ .io_devices_1_a_bits_param(tl_rom_o_32.a_param),
+ .io_devices_1_a_bits_size(tl_rom_o_32.a_size),
+ .io_devices_1_a_bits_source(tl_rom_o_32.a_source),
+ .io_devices_1_a_bits_address(tl_rom_o_32.a_address),
+ .io_devices_1_a_bits_mask(tl_rom_o_32.a_mask),
+ .io_devices_1_a_bits_data(tl_rom_o_32.a_data),
+ .io_devices_1_a_bits_user_rsvd(tl_rom_o_32.a_user.rsvd),
+ .io_devices_1_a_bits_user_instr_type(tl_rom_o_32.a_user.instr_type),
+ .io_devices_1_a_bits_user_cmd_intg(tl_rom_o_32.a_user.cmd_intg),
+ .io_devices_1_a_bits_user_data_intg(tl_rom_o_32.a_user.data_intg),
+ .io_devices_1_d_ready(tl_rom_o_32.d_ready),
+ .io_devices_2_a_valid(tl_sram_o.a_valid),
+ .io_devices_2_a_bits_opcode(tl_sram_o.a_opcode),
+ .io_devices_2_a_bits_param(tl_sram_o.a_param),
+ .io_devices_2_a_bits_size(tl_sram_o.a_size),
+ .io_devices_2_a_bits_source(tl_sram_o.a_source),
+ .io_devices_2_a_bits_address(tl_sram_o.a_address),
+ .io_devices_2_a_bits_mask(tl_sram_o.a_mask),
+ .io_devices_2_a_bits_data(tl_sram_o.a_data),
+ .io_devices_2_a_bits_user_rsvd(tl_sram_o.a_user.rsvd),
+ .io_devices_2_a_bits_user_instr_type(tl_sram_o.a_user.instr_type),
+ .io_devices_2_a_bits_user_cmd_intg(tl_sram_o.a_user.cmd_intg),
+ .io_devices_2_a_bits_user_data_intg(tl_sram_o.a_user.data_intg),
+ .io_devices_2_d_ready(tl_sram_o.d_ready),
+ .io_devices_3_a_valid(tl_uart0_o.a_valid),
+ .io_devices_3_a_bits_opcode(tl_uart0_o.a_opcode),
+ .io_devices_3_a_bits_param(tl_uart0_o.a_param),
+ .io_devices_3_a_bits_size(tl_uart0_o.a_size),
+ .io_devices_3_a_bits_source(tl_uart0_o.a_source),
+ .io_devices_3_a_bits_address(tl_uart0_o.a_address),
+ .io_devices_3_a_bits_mask(tl_uart0_o.a_mask),
+ .io_devices_3_a_bits_data(tl_uart0_o.a_data),
+ .io_devices_3_a_bits_user_rsvd(tl_uart0_o.a_user.rsvd),
+ .io_devices_3_a_bits_user_instr_type(tl_uart0_o.a_user.instr_type),
+ .io_devices_3_a_bits_user_cmd_intg(tl_uart0_o.a_user.cmd_intg),
+ .io_devices_3_a_bits_user_data_intg(tl_uart0_o.a_user.data_intg),
+ .io_devices_3_d_ready(tl_uart0_o.d_ready),
+ .io_devices_4_a_valid(tl_uart1_o.a_valid),
+ .io_devices_4_a_bits_opcode(tl_uart1_o.a_opcode),
+ .io_devices_4_a_bits_param(tl_uart1_o.a_param),
+ .io_devices_4_a_bits_size(tl_uart1_o.a_size),
+ .io_devices_4_a_bits_source(tl_uart1_o.a_source),
+ .io_devices_4_a_bits_address(tl_uart1_o.a_address),
+ .io_devices_4_a_bits_mask(tl_uart1_o.a_mask),
+ .io_devices_4_a_bits_data(tl_uart1_o.a_data),
+ .io_devices_4_a_bits_user_rsvd(tl_uart1_o.a_user.rsvd),
+ .io_devices_4_a_bits_user_instr_type(tl_uart1_o.a_user.instr_type),
+ .io_devices_4_a_bits_user_cmd_intg(tl_uart1_o.a_user.cmd_intg),
+ .io_devices_4_a_bits_user_data_intg(tl_uart1_o.a_user.data_intg),
+ .io_devices_4_d_ready(tl_uart1_o.d_ready),
+ .io_devices_5_a_valid(tl_spi0_o.a_valid),
+ .io_devices_5_a_bits_opcode(tl_spi0_o.a_opcode),
+ .io_devices_5_a_bits_param(tl_spi0_o.a_param),
+ .io_devices_5_a_bits_size(tl_spi0_o.a_size),
+ .io_devices_5_a_bits_source(tl_spi0_o.a_source),
+ .io_devices_5_a_bits_address(tl_spi0_o.a_address),
+ .io_devices_5_a_bits_mask(tl_spi0_o.a_mask),
+ .io_devices_5_a_bits_data(tl_spi0_o.a_data),
+ .io_devices_5_a_bits_user_rsvd(tl_spi0_o.a_user.rsvd),
+ .io_devices_5_a_bits_user_instr_type(tl_spi0_o.a_user.instr_type),
+ .io_devices_5_a_bits_user_cmd_intg(tl_spi0_o.a_user.cmd_intg),
+ .io_devices_5_a_bits_user_data_intg(tl_spi0_o.a_user.data_intg),
+ .io_devices_5_d_ready(tl_spi0_o.d_ready)
+ );
uart i_uart0(.clk_i(clk_i),
.rst_ni(rst_ni),
@@ -308,226 +465,11 @@
logic rst_cpu_n;
- // Data and Response integrity generation for Kelvin Device Port
- localparam int XbarSourceWidth = kelvin_tlul_pkg_128::TL_AIW;
- localparam int XbarSourceCount = 1 << XbarSourceWidth;
- logic [1 : 0] host_lane_reg[XbarSourceCount - 1 : 0];
-
- logic [38 : 0] dev_ecc_full_0, dev_ecc_full_1, dev_ecc_full_2, dev_ecc_full_3;
- logic [6 : 0] dev_ecc_0, dev_ecc_1, dev_ecc_2, dev_ecc_3;
- logic [6 : 0] dev_selected_ecc;
- tl_d2h_rsp_intg_t dev_rsp_metadata;
- logic [63 : 0] dev_rsp_ecc_full;
- logic [6 : 0] dev_rsp_ecc;
-
- assign dev_ecc_0 = dev_ecc_full_0[38 : 32];
- assign dev_ecc_1 = dev_ecc_full_1[38 : 32];
- assign dev_ecc_2 = dev_ecc_full_2[38 : 32];
- assign dev_ecc_3 = dev_ecc_full_3[38 : 32];
- assign dev_rsp_ecc = dev_rsp_ecc_full[63 : 57];
-
- prim_secded_inv_39_32_enc dev_enc0(.data_i(tl_kelvin_device_i.d_data[31 : 0]),
- .data_o(dev_ecc_full_0));
- prim_secded_inv_39_32_enc dev_enc1(.data_i(
- tl_kelvin_device_i.d_data[63 : 32]),
- .data_o(dev_ecc_full_1));
- prim_secded_inv_39_32_enc dev_enc2(.data_i(
- tl_kelvin_device_i.d_data[95 : 64]),
- .data_o(dev_ecc_full_2));
- prim_secded_inv_39_32_enc dev_enc3(.data_i(
- tl_kelvin_device_i.d_data[127 : 96]),
- .data_o(dev_ecc_full_3));
-
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- for (int i = 0; i < XbarSourceCount; i++) begin
- host_lane_reg[i] <= 2'b0;
- end
- end else begin
- // Capture lane index from Ibex data core requests
- if (tl_ibex_core_d_o_xbar.a_valid && tl_ibex_core_d_i_xbar.a_ready) begin
- unique case (4'hF)
- tl_ibex_core_d_o_xbar.a_mask[3 : 0]:
- host_lane_reg[tl_ibex_core_d_o_xbar.a_source] <= 2'b00;
- tl_ibex_core_d_o_xbar.a_mask[7 : 4]:
- host_lane_reg[tl_ibex_core_d_o_xbar.a_source] <= 2'b01;
- tl_ibex_core_d_o_xbar.a_mask[11 : 8]:
- host_lane_reg[tl_ibex_core_d_o_xbar.a_source] <= 2'b10;
- tl_ibex_core_d_o_xbar.a_mask[15 : 12]:
- host_lane_reg[tl_ibex_core_d_o_xbar.a_source] <= 2'b11;
- endcase
- end
-
- // Capture lane index from Ibex instruction core requests
- if (tl_ibex_core_i_o_xbar.a_valid && tl_ibex_core_i_i_xbar.a_ready) begin
- unique case (4'hF)
- tl_ibex_core_i_o_xbar.a_mask[3 : 0]:
- host_lane_reg[tl_ibex_core_i_o_xbar.a_source] <= 2'b00;
- tl_ibex_core_i_o_xbar.a_mask[7 : 4]:
- host_lane_reg[tl_ibex_core_i_o_xbar.a_source] <= 2'b01;
- tl_ibex_core_i_o_xbar.a_mask[11 : 8]:
- host_lane_reg[tl_ibex_core_i_o_xbar.a_source] <= 2'b10;
- tl_ibex_core_i_o_xbar.a_mask[15 : 12]:
- host_lane_reg[tl_ibex_core_i_o_xbar.a_source] <= 2'b11;
- endcase
- end
-
- // Capture lane index from Kelvin core requests
- if (tl_kelvin_core_i.a_valid && tl_kelvin_core_o.a_ready) begin
- unique case (4'hF)
- tl_kelvin_core_i.a_mask[3 : 0]:
- host_lane_reg[tl_kelvin_core_i.a_source] <= 2'b00;
- tl_kelvin_core_i.a_mask[7 : 4]:
- host_lane_reg[tl_kelvin_core_i.a_source] <= 2'b01;
- tl_kelvin_core_i.a_mask[11 : 8]:
- host_lane_reg[tl_kelvin_core_i.a_source] <= 2'b10;
- tl_kelvin_core_i.a_mask[15 : 12]:
- host_lane_reg[tl_kelvin_core_i.a_source] <= 2'b11;
- endcase
- end
- end
- end
-
- always_comb begin
- logic [1 : 0] lane_idx;
- lane_idx = host_lane_reg[tl_from_kelvin_core.d_source];
- case (lane_idx)
- 2'b00:
- dev_selected_ecc = dev_ecc_0;
- 2'b01:
- dev_selected_ecc = dev_ecc_1;
- 2'b10:
- dev_selected_ecc = dev_ecc_2;
- 2'b11:
- dev_selected_ecc = dev_ecc_3;
- default:
- dev_selected_ecc = dev_ecc_0;
- endcase
- end
-
- assign dev_rsp_metadata = '{
- opcode: tl_from_kelvin_core.d_opcode,
- size: 2'b10,
- error: tl_from_kelvin_core.d_error
- };
-
- prim_secded_inv_64_57_enc dev_enc_rsp(.data_i(
- D2HRspMaxWidth'(dev_rsp_metadata)),
- .data_o(dev_rsp_ecc_full));
-
// Kelvin Core Instantiation
logic kelvin_halted, kelvin_fault, kelvin_wfi;
- kelvin_tlul_pkg_128::tl_d2h_t tl_from_kelvin_core;
-
assign io_halted = kelvin_halted;
assign io_fault = kelvin_fault;
- // Assign all fields for the device D-channel from the Kelvin core's output,
- // except for the user integrity bits, which we override with our generated
- // ECC.
- assign tl_kelvin_device_i.d_valid = tl_from_kelvin_core.d_valid;
- assign tl_kelvin_device_i.d_opcode = tl_from_kelvin_core.d_opcode;
- assign tl_kelvin_device_i.d_param = tl_from_kelvin_core.d_param;
- assign tl_kelvin_device_i.d_size = tl_from_kelvin_core.d_size;
- assign tl_kelvin_device_i.d_source = tl_from_kelvin_core.d_source;
- assign tl_kelvin_device_i.d_sink = tl_from_kelvin_core.d_sink;
- assign tl_kelvin_device_i.d_data = tl_from_kelvin_core.d_data;
- assign tl_kelvin_device_i.d_error = tl_from_kelvin_core.d_error;
- assign tl_kelvin_device_i.a_ready = tl_from_kelvin_core.a_ready;
- assign tl_kelvin_device_i.d_user.rsp_intg = dev_rsp_ecc;
- assign tl_kelvin_device_i.d_user.data_intg = dev_selected_ecc;
-
- // Command and Data integrity generation for Kelvin Host Port
- logic [38 : 0] host_a_data_ecc_full_0, host_a_data_ecc_full_1,
- host_a_data_ecc_full_2, host_a_data_ecc_full_3;
- logic [6 : 0] host_a_data_ecc_0, host_a_data_ecc_1, host_a_data_ecc_2,
- host_a_data_ecc_3;
- logic [6 : 0] host_a_data_selected_ecc;
- tl_h2d_cmd_intg_t host_a_cmd_metadata;
- logic [63 : 0] host_a_cmd_ecc_full;
- logic [6 : 0] host_a_cmd_ecc;
-
- assign host_a_data_ecc_0 = host_a_data_ecc_full_0[38 : 32];
- assign host_a_data_ecc_1 = host_a_data_ecc_full_1[38 : 32];
- assign host_a_data_ecc_2 = host_a_data_ecc_full_2[38 : 32];
- assign host_a_data_ecc_3 = host_a_data_ecc_full_3[38 : 32];
- assign host_a_cmd_ecc = host_a_cmd_ecc_full[63 : 57];
-
- prim_secded_inv_39_32_enc host_a_data_enc0(
- .data_i(tl_kelvin_core_i.a_data[31 : 0]),
- .data_o(host_a_data_ecc_full_0));
- prim_secded_inv_39_32_enc host_a_data_enc1(
- .data_i(tl_kelvin_core_i.a_data[63 : 32]),
- .data_o(host_a_data_ecc_full_1));
- prim_secded_inv_39_32_enc host_a_data_enc2(
- .data_i(tl_kelvin_core_i.a_data[95 : 64]),
- .data_o(host_a_data_ecc_full_2));
- prim_secded_inv_39_32_enc host_a_data_enc3(
- .data_i(tl_kelvin_core_i.a_data[127 : 96]),
- .data_o(host_a_data_ecc_full_3));
-
- logic [top_pkg::TL_DBW - 1 : 0] host_a_cmd_mask;
-
- localparam logic [top_pkg::TL_AW - 1 : 0] Uart1BaseAddr = 32'h40010000;
- logic [15 : 0] computed_mask;
- logic [3 : 0] host_a_cmd_mask_4b;
- logic [1 : 0] host_a_cmd_lane;
- tl_h2d_cmd_intg_t host_a_cmd_payload;
- logic [15 : 0] kelvin_core_i_a_mask;
-
- always_comb begin
- if (tl_kelvin_core_i.a_opcode == tlul_pkg::Get) begin
- computed_mask = ((1 << (1 << tl_kelvin_core_i.a_size)) - 1)
- << (tl_kelvin_core_i.a_address[3 : 0]);
- end else begin
- computed_mask = kelvin_core_i_a_mask;
- end
- host_a_data_selected_ecc = 7'b0;
- host_a_cmd_mask_4b = '0;
- host_a_cmd_lane = '0;
- // This is a priority mux, which is what we want.
- if (|computed_mask[3 : 0]) begin
- host_a_data_selected_ecc = host_a_data_ecc_0;
- host_a_cmd_mask_4b = computed_mask[3 : 0];
- host_a_cmd_lane = 2'b00;
- end else if (|computed_mask[7 : 4]) begin
- host_a_data_selected_ecc = host_a_data_ecc_1;
- host_a_cmd_mask_4b = computed_mask[7 : 4];
- host_a_cmd_lane = 2'b01;
- end else if (|computed_mask[11 : 8]) begin
- host_a_data_selected_ecc = host_a_data_ecc_2;
- host_a_cmd_mask_4b = computed_mask[11 : 8];
- host_a_cmd_lane = 2'b10;
- end else if (|computed_mask[15 : 12]) begin
- host_a_data_selected_ecc = host_a_data_ecc_3;
- host_a_cmd_mask_4b = computed_mask[15 : 12];
- host_a_cmd_lane = 2'b11;
- end
- end
-
- // Manually pack the command integrity payload to match the 32-bit
- // peripheral's view. The packing order is derived from the tl_h2d_cmd_intg_t
- // struct definition.
- assign host_a_cmd_payload = '{
- instr_type: prim_mubi_pkg::MuBi4False, // instr_type (4 bits)
- addr: tl_kelvin_core_i.a_address, // addr (32 bits)
- opcode: tl_kelvin_core_i.a_opcode, // opcode (3 bits)
- mask: host_a_cmd_mask_4b // mask (4 bits)
- };
- logic [31 : 0] dbg_uart1_addr = host_a_cmd_payload.addr;
- logic [2 : 0] dbg_uart1_opcode = host_a_cmd_payload.opcode;
- logic [3 : 0] dbg_uart1_mask = host_a_cmd_payload.mask;
- logic [3 : 0] dbg_uart1_instr_type = host_a_cmd_payload.instr_type;
-
- prim_secded_inv_64_57_enc host_a_cmd_enc(.data_i(H2DCmdMaxWidth'(
- host_a_cmd_payload)),
- .data_o(host_a_cmd_ecc_full));
-
- assign tl_kelvin_core_i.a_user.cmd_intg = host_a_cmd_ecc;
- assign tl_kelvin_core_i.a_user.data_intg = host_a_data_selected_ecc;
- assign tl_kelvin_core_i.a_user.instr_type = prim_mubi_pkg::MuBi4False;
- assign tl_kelvin_core_i.a_mask = computed_mask;
-
RvvCoreMiniTlul
i_kelvin_core(
.io_clk(clk_i),
@@ -539,12 +481,12 @@
.io_tl_host_a_bits_size(tl_kelvin_core_i.a_size),
.io_tl_host_a_bits_source(tl_kelvin_core_i.a_source),
.io_tl_host_a_bits_address(tl_kelvin_core_i.a_address),
- .io_tl_host_a_bits_mask(kelvin_core_i_a_mask),
+ .io_tl_host_a_bits_mask(tl_kelvin_core_i.a_mask),
.io_tl_host_a_bits_data(tl_kelvin_core_i.a_data),
.io_tl_host_a_bits_user_rsvd(tl_kelvin_core_i.a_user.rsvd),
- .io_tl_host_a_bits_user_instr_type(),
- .io_tl_host_a_bits_user_cmd_intg(),
- .io_tl_host_a_bits_user_data_intg(),
+ .io_tl_host_a_bits_user_instr_type(tl_kelvin_core_i.a_user.instr_type),
+ .io_tl_host_a_bits_user_cmd_intg(tl_kelvin_core_i.a_user.cmd_intg),
+ .io_tl_host_a_bits_user_data_intg(tl_kelvin_core_i.a_user.data_intg),
.io_tl_host_d_ready(tl_kelvin_core_i.d_ready),
.io_tl_host_d_valid(tl_kelvin_core_o.d_valid),
.io_tl_host_d_bits_opcode(tl_kelvin_core_o.d_opcode),
@@ -574,17 +516,17 @@
.io_tl_device_a_bits_user_data_intg(
tl_kelvin_device_o.a_user.data_intg),
.io_tl_device_d_ready(tl_kelvin_device_o.d_ready),
- .io_tl_device_a_ready(tl_from_kelvin_core.a_ready),
- .io_tl_device_d_valid(tl_from_kelvin_core.d_valid),
- .io_tl_device_d_bits_opcode(tl_from_kelvin_core.d_opcode),
- .io_tl_device_d_bits_param(tl_from_kelvin_core.d_param),
- .io_tl_device_d_bits_size(tl_from_kelvin_core.d_size),
- .io_tl_device_d_bits_source(tl_from_kelvin_core.d_source),
- .io_tl_device_d_bits_sink(tl_from_kelvin_core.d_sink),
- .io_tl_device_d_bits_data(tl_from_kelvin_core.d_data),
- .io_tl_device_d_bits_error(tl_from_kelvin_core.d_error),
- .io_tl_device_d_bits_user_rsp_intg(),
- .io_tl_device_d_bits_user_data_intg(),
+ .io_tl_device_a_ready(tl_kelvin_device_i.a_ready),
+ .io_tl_device_d_valid(tl_kelvin_device_i.d_valid),
+ .io_tl_device_d_bits_opcode(tl_kelvin_device_i.d_opcode),
+ .io_tl_device_d_bits_param(tl_kelvin_device_i.d_param),
+ .io_tl_device_d_bits_size(tl_kelvin_device_i.d_size),
+ .io_tl_device_d_bits_source(tl_kelvin_device_i.d_source),
+ .io_tl_device_d_bits_sink(tl_kelvin_device_i.d_sink),
+ .io_tl_device_d_bits_data(tl_kelvin_device_i.d_data),
+ .io_tl_device_d_bits_error(tl_kelvin_device_i.d_error),
+ .io_tl_device_d_bits_user_rsp_intg(tl_kelvin_device_i.d_user.rsp_intg),
+ .io_tl_device_d_bits_user_data_intg(tl_kelvin_device_i.d_user.data_intg),
.io_halted(kelvin_halted),
.io_fault(kelvin_fault),
.io_wfi(kelvin_wfi),
@@ -594,8 +536,8 @@
// Ibex Core Instantiation
rv_core_ibex #(.PipeLine(1'b1),
.PMPEnable(1'b0))
- i_ibex_core(.clk_i(clk_i),
- .rst_ni(rst_ni),
+ i_ibex_core(.clk_i(ibex_clk_i),
+ .rst_ni(ibex_rst_ni),
.corei_tl_h_o(tl_ibex_core_i_o_32),
.corei_tl_h_i(tl_ibex_core_i_i_32),
.cored_tl_h_o(tl_ibex_core_d_o_32),
diff --git a/fpga/rules.bzl b/fpga/rules.bzl
deleted file mode 100644
index df307ad..0000000
--- a/fpga/rules.bzl
+++ /dev/null
@@ -1,43 +0,0 @@
-"""Starlark rules for FPGA development."""
-
-def _tlgen_impl(ctx):
- """Implementation of the tlgen_rule."""
- topcfg = ctx.file.topcfg
- out_dir = ctx.actions.declare_directory(ctx.label.name + "_out")
- core_file = ctx.actions.declare_file(ctx.label.name + "_out/" + "xbar_kelvin_soc_xbar.core")
-
- ctx.actions.run(
- outputs = [out_dir, core_file],
- inputs = [topcfg],
- executable = ctx.executable._tool,
- arguments = [
- "--topcfg",
- topcfg.path,
- "--outdir",
- out_dir.path,
- ],
- progress_message = "Running tlgen and extracting core for %s" % topcfg.short_path,
- )
-
- return [
- DefaultInfo(files = depset([out_dir])),
- OutputGroupInfo(
- core_file_output = depset([core_file, out_dir]),
- ),
- ]
-
-tlgen_rule = rule(
- implementation = _tlgen_impl,
- attrs = {
- "topcfg": attr.label(
- allow_single_file = True,
- mandatory = True,
- doc = "HJSON top-level configuration file.",
- ),
- "_tool": attr.label(
- default = Label("//fpga:tlgen_tool"),
- executable = True,
- cfg = "exec",
- ),
- },
-)
diff --git a/fpga/sw/main.cc b/fpga/sw/main.cc
index 3ff561f..f9c7b8e 100644
--- a/fpga/sw/main.cc
+++ b/fpga/sw/main.cc
@@ -6,8 +6,15 @@
extern "C" int main() {
// Copy the embedded binary to Kelvin's ITCM at 0x0.
- void *itcm_base = reinterpret_cast<void *>(static_cast<uintptr_t>(0x0));
- memcpy(itcm_base, add_uint32_m1_bin, add_uint32_m1_bin_len);
+ // NB: Use this copy loop instead of memcpy to get word writes
+ // instead of byte writes.
+ uint32_t* itcm_base =
+ reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(0x0));
+ const uint32_t* add_uint32_m1_bin_u32 =
+ reinterpret_cast<const uint32_t*>(add_uint32_m1_bin);
+ for (unsigned int i = 0; i < add_uint32_m1_bin_len / 4; i++) {
+ *(itcm_base + i) = add_uint32_m1_bin_u32[i];
+ }
// Kelvin run sequence
volatile unsigned int *kelvin_reset_csr =
diff --git a/fpga/tl_config.hjson b/fpga/tl_config.hjson
deleted file mode 100644
index 82f5a83..0000000
--- a/fpga/tl_config.hjson
+++ /dev/null
@@ -1,95 +0,0 @@
-{
- // Top-level configuration for the Kelvin SoC crossbar.
- name: "kelvin_soc_xbar",
- clock: "clk_i",
- reset: "rst_ni",
-
- // Define all the hosts (masters) and devices (slaves) in the system.
- nodes: [
- // Hosts (CPU Cores)
- { name: "kelvin_core", type: "host", clock: "clk_i", reset: "rst_ni", addr_space: "asid0" },
- { name: "ibex_core_i", type: "host", clock: "clk_i", reset: "rst_ni", addr_space: "asid0" },
- { name: "ibex_core_d", type: "host", clock: "clk_i", reset: "rst_ni", addr_space: "asid0" },
-
- // Devices (Peripherals and Memory)
- {
- name: "kelvin_device",
- type: "device",
- clock: "clk_i",
- reset: "rst_ni",
- xbar: false,
- addr_range: [
- { base_addrs: {"asid0": "0x00000000"}, size_byte: "0x2000" }, // 8kB
- { base_addrs: {"asid0": "0x00010000"}, size_byte: "0x8000" }, // 32kB
- { base_addrs: {"asid0": "0x00030000"}, size_byte: "0x1000" } // 4kB
- ]
- },
- {
- name: "rom",
- type: "device",
- clock: "clk_i",
- reset: "rst_ni",
- xbar: false,
- addr_range: [{ base_addrs: {"asid0": "0x10000000"}, size_byte: "0x8000" }] // 32kB
- },
- {
- name: "sram",
- type: "device",
- clock: "clk_i",
- reset: "rst_ni",
- xbar: false,
- addr_range: [{ base_addrs: {"asid0": "0x20000000"}, size_byte: "0x400000" }] // 4MB
- },
- {
- name: "uart0",
- type: "device",
- clock: "clk_i",
- reset: "rst_ni",
- xbar: false,
- addr_range: [{ base_addrs: {"asid0": "0x40000000"}, size_byte: "0x1000" }]
- },
- {
- name: "uart1",
- type: "device",
- clock: "clk_i",
- reset: "rst_ni",
- xbar: false,
- addr_range: [{ base_addrs: {"asid0": "0x40010000"}, size_byte: "0x1000" }]
- },
- {
- name: "spi0",
- type: "device",
- clock: "spi_clk_i", // Using a separate clock for the SPI peripheral
- reset: "rst_ni",
- xbar: false,
- addr_range: [{ base_addrs: {"asid0": "0x40020000"}, size_byte: "0x1000" }]
- }
- ],
-
- // Define which hosts can access which devices.
- connections: {
- kelvin_core: [ "sram", "uart1", "spi0" ],
- ibex_core_i: [ "rom", "sram" ],
- ibex_core_d: [ "rom", "sram", "uart0", "kelvin_device" ]
- },
-
- // Define clock connections for all components.
- clock_connections: {
- clk_i: [
- "kelvin_core",
- "ibex_core_i",
- "ibex_core_d",
- "kelvin_device",
- "rom",
- "sram",
- "uart0",
- "uart1"
- ],
- spi_clk_i: [
- "spi0"
- ]
- },
- reset_connections: {
- rst_ni: "rst_ni"
- }
-}
diff --git a/hdl/chisel/src/kelvin/CoreTlul.scala b/hdl/chisel/src/kelvin/CoreTlul.scala
index 7c41c55..88ba92b 100644
--- a/hdl/chisel/src/kelvin/CoreTlul.scala
+++ b/hdl/chisel/src/kelvin/CoreTlul.scala
@@ -20,6 +20,7 @@
class CoreTlul(p: Parameters, coreModuleName: String) extends RawModule {
override val desiredName = coreModuleName + "Tlul"
val memoryRegions = p.m
+ val tlul_p = new TLULParameters(p)
val io = IO(new Bundle {
val clk = Input(Clock())
val rst_ni = Input(AsyncReset())
@@ -51,9 +52,22 @@
hostBridge.io.axi <> coreAxi.io.axi_master
deviceBridge.io.axi <> coreAxi.io.axi_slave
- io.tl_host.a <> hostBridge.io.tl_a
+ val host_req_intg_gen = withClockAndReset(io.clk, (!io.rst_ni.asBool).asAsyncReset) {
+ Module(new RequestIntegrityGen(tlul_p))
+ }
+ io.tl_host.a.valid := hostBridge.io.tl_a.valid
+ hostBridge.io.tl_a.ready := io.tl_host.a.ready
+ host_req_intg_gen.io.a_i := hostBridge.io.tl_a.bits
+ host_req_intg_gen.io.a_i.user.instr_type := 9.U // MuBi4False
+ io.tl_host.a.bits := host_req_intg_gen.io.a_o
hostBridge.io.tl_d <> io.tl_host.d
+ val device_rsp_intg_gen = withClockAndReset(io.clk, (!io.rst_ni.asBool).asAsyncReset) {
+ Module(new ResponseIntegrityGen(tlul_p))
+ }
deviceBridge.io.tl_a <> io.tl_device.a
- io.tl_device.d <> deviceBridge.io.tl_d
+ io.tl_device.d.valid := deviceBridge.io.tl_d.valid
+ deviceBridge.io.tl_d.ready := io.tl_device.d.ready
+ device_rsp_intg_gen.io.d_i := deviceBridge.io.tl_d.bits
+ io.tl_device.d.bits := device_rsp_intg_gen.io.d_o
}
\ No newline at end of file