Kelvin Integration Guide

This document describes integrating Kelvin as an AXI/TileLink peripheral in a bigger system.

AXI

We provide a scalar-only Kelvin configuration that can integrate with an AXI based system. The SystemVerilog can be generated with:

bazel build //hdl/chisel/src/kelvin:core_mini_axi_cc_library_emit_verilog

Module interfaces

Kelvin AXI

The interfaces to Kelvin are defined as follows:

Signal BundleDescription
clkThe clock of the AXI Bus/Kelvin core.
resetThe active-low reset signal for the AXI Bus/Kelvin core.
s_axiAn AXI4 slave interface that can be used to write TCMs or touch Kelvin CSRs.
m_axiAn AXI4 master interface used by Kelvin to read/write to memories/CSRs.
irqnActive-low interrupt to the Kelvin core. Can be triggered by peripherals or other host processor.
wfiActive-high signal from the Kelvin core, indicating that the core is waiting for an interrupt. While this is active, Kelvin is clock-gated.
debugDebug interface to monitor Kelvin instructions execution. This interface is typically only used for simulation.
s_logDebug interface to handle SLOG instruction. This interface is typically only used for simulation.
haltedOutput interface informing if the Core is running or not. Can be ignored.
faultOutput interface to determine if the Core hit a fault. These signals should be connected to a system control CPU interrupt-line or status register for notification when Kelvin faults or is halted.

AXI master signals

AR / AW channel

SignalBehaviour
addrAddress Kelvin wishes to read/write
protAlways 2 (unprivileged, insecure, data)
idAlways 0
len(Count of beats in the burst) - 1
sizeBytes-per-beat (1, 2, or 4)
burstAlways 1 (INCR)
lockAlways 0 (normal access)
cacheAlways 0 (Device non-bufferable)
qosAlways 0
regionAlways 0

R channel

SignalBehaviour
dataResponse data from the slave
idIgnored, but should be 0 as Kelvin only emits txns with an id of 0
respResponse code
lastWhether the beat is the last in the burst

W channel

SignalBehaviour
dataData Kelvin wishes to write
lastWhether the beat is the last in the burst
strbWhich bytes in the data are valid

B channel

SignalBehaviour
idIgnored, but should be 0 as Kelvin only emits txns with an id of 0 (an RTL assertion exists for this)
respResponse code

Note: the USER signal is not supported on any of the channels.

AXI slave signals

AR / AW channel

SignalBehaviour
addrAddress the master wishes to read / write to
protIgnored
idTransaction ID, should be reflected in the response beats
len(Count of beats in the burst) - 1
sizeBytes-per-beat (1,2,4,8,16)
burst0, 1, or 2 (FIXED, INCR, WRAP)
lockIgnored
cacheIgnored
qosIgnored
regionIgnored

R channel

SignalBehaviour
dataResponse data from Kelvin
idTransaction ID, should match with the id field from AR
respResponse code (0/OKAY or 2/SLVERR)
lastWhether the beat is the last in the burst

W channel

SignalBehaviour
dataData the master wishes to write to Kelvin
lastWhether the beat is the last in the burst
strbWhich bytes in data are valid

B channel

SignalBehaviour
idTransaction ID, should match with the id field from AW
respResponse code (0/OKAY or 2/SLVERR)

Note: the USER signal is not supported on any of the channels.

Debug Signals

SignalBehaviour
en4-bit value, indicating which fetch lanes are active
addr32-bit values, containing the PC for each fetch lane
inst32-bit values, containing the instruction for each fetch lane
cyclescycle counter
dbusInformation about internal LSU transactions
-> validWhether the transaction is valid
-> bitsaddr: The 32-bit address for the transaction
write: If the transaction is a write
wdata: 128-bit write data for the transaction
dispatchInformation about instructions which are dispatched for execution
-> fireIf an instruction was dispatched in the slot, this cycle
-> addrThe 32-bit address of the instruction
-> instThe 32-bit value of the instruction
regfileInformation about writes to the integer register file
-> writeAddrRegister addresses to which a future write is expected
->-> validIf an instruction was dispatched in this lane, which will write the regfile
->-> bitsThe 5-bit register address to which the write is expected
-> writeDataFor each port in the register file, information about writes
->-> validIf a write occurred on this port, this cycle
->-> bits_addrThe 5-bit register address to which the write occurred
->-> bits_dataThe 32-bit value which was written to the register
floatInformation about write to the floating point register file
-> writeAddrRegister addresses to which a future write is expected
->-> validIf an instruction was dispatched to floating point on this cycle
->-> bitsThe address of the register to which a write is expected
-> writeDataFor each port in the register file, information about writes
->-> validIf a write occured on this port, this cycle
->-> bits_addrThe 5-bit register address to which the writh occurred
->-> bits_dataThe 32-bit value which was written to the register

Kelvin Memory Map

Memory accesses to Kelvin are defined as follows:

RegionRangeSizeAlignmentDescription
ITCM0x0000 - 0x1FFF8kB4 bytesITCM storage for code executed by Kelvin.
DTCM0x10000 - 0x17FFF32kB1 byteDTCM storage for data used by Kelvin.
CSR0x30000 - TBDTBD4 bytesCSR interface used to query/control Kelvin.

Reset Considerations

Kelvin uses a synchronous reset strategy -- to ensure proper reset behavior, ensure that the clock runs for a cycle with reset active, before enabling either the internal clock gate (via CSR) or gating externally.

Booting Kelvin

A note first -- in these examples, Kelvin is located in the overall system memory map at 0x70000000.

  1. The instruction memory of Kelvin must be initialized.
volatile uint8_t* kelvin_itcm = (uint8_t*)0x00000000L;
for (int i = 0; i < kelvin_binary_len; ++i) {
    kelvin_itcm[i] = kelvin_binary[i];
}

If something like a DMA engine is present in your system, that is probably a better option for initializing the ITCM.

  1. Program the start PC If your program is linked such that the starting address is 0, you may skip this.
volatile uint32_t* kelvin_pc_csr = (uint32_t*)0x00030004L;
*kelvin_pc_csr = start_addr;
  1. Release clock gate
volatile uint32_t* kelvin_reset_csr = (uint32_t*)0x00030000L;
*kelvin_reset_csr = 1;

After this, ensure you wait a cycle to allow Kelvin‘s reset to occur. If you want to configure something like an interrupt that is connected to Kelvin’s fault or halted outputs, this is a good time.

  1. Release reset
volatile uint32_t* kelvin_reset_csr = (uint32_t*)0x00030000L;
*kelvin_reset_csr = 0;

At this point, Kelvin will begin executing at the PC programmed in step 2.

  1. Monitor for io_halted The status of Kelvin's execution can be checked by reading the status CSR:
volatile uint32_t* kelvin_status_csr = (uint32_t*)0x00030008L;
uint32_t status = *kelvin_status_csr;
bool halted = status & 1;
bool fault = status & 2;