Skip to content

Commit

Permalink
Merge pull request #2007 from enjoy-digital/ctu-can-fd
Browse files Browse the repository at this point in the history
Add initial CTU-CAN-FD core support.
  • Loading branch information
enjoy-digital committed Jul 5, 2024
2 parents d838a9c + 462016a commit 7ec35eb
Show file tree
Hide file tree
Showing 4 changed files with 284 additions and 0 deletions.
Empty file added litex/soc/cores/can/__init__.py
Empty file.
177 changes: 177 additions & 0 deletions litex/soc/cores/can/ctu_can_fd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#
# CTU CAN-FD Core Wrapper for LiteX.
#
# Copyright (c) 2021 Andrew Dennison <andrew@motec.com.au>
# Copyright (c) 2021-2024 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2024 Gwenhael Goavec-Merou <gwenhael@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause

# Documentation at https://canbus.pages.fel.cvut.cz/

import os
import subprocess

from migen import *

from litex.gen import *

from litex.build import tools
from litex.build.vhd2v_converter import VHD2VConverter

from litex.soc.interconnect import wishbone
from litex.soc.interconnect.csr_eventmanager import *

# CTU CAN-FD ---------------------------------------------------------------------------------------

class CTUCANFD(LiteXModule, EventManager):
def __init__(self, platform, pads, timestamp=0, force_convert=False):
# Parameters.
self.platform = platform
self.pads = pads
self._force_convert = force_convert

# Wishbone Bus.
self.bus = wishbone.Interface(data_width=32)

# CSRs.
self.control = CSRStorage(32, fields=[
CSRField("reset", size=1, values=[
("``0b0``", "Normal Operation."),
("``0b1`", "Hold the Core in Reset."),
], reset=0b0),
CSRField("reserved",size=31),
])
self.status = CSRStatus(32, fields=[
CSRField("ready", size=1, values=[
("``0b0``", "Core in Reset."),
("``0b1`", "Core Ready."),
]),
])

# IRQs.
self.irq = Signal()

# CTU CAN-FD Instance ----------------------------------------------------------------------
self.core_params = dict()

# Wishbone to CTU CAN-FD Memory Bus adaptation.
self.mem_scs = mem_scs = Signal()
self.mem_srd = mem_srd = Signal()
self.mem_swr = mem_swr = Signal()
self.mem_sbe = mem_sbe = Signal(4)
self.mem_adress = mem_adress = Signal(16)
self.mem_data_in = mem_data_in = Signal(32)
self.mem_data_out = mem_data_out = Signal(32)

self.comb += [
# On Wishbone Access cycle...
mem_scs.eq(self.bus.cyc & self.bus.stb),
mem_srd.eq(mem_scs & ~self.bus.we & ~self.bus.ack),
mem_swr.eq(mem_scs & self.bus.we),
mem_sbe.eq(self.bus.sel),
# Connect data_in/out.
mem_data_in.eq(self.bus.dat_w),
self.bus.dat_r.eq(mem_data_out),
# Convert 32-bit word addressing to bytes addressing.
mem_adress.eq(Cat(Signal(2), self.bus.adr)),
]
self.sync += [
self.bus.ack.eq(0),
If(mem_scs & ~self.bus.ack, self.bus.ack.eq(1)),
]

# CTU CAN-FD Parameters.
self.core_params.update(
# Target technology (ASIC or FPGA)
#p_target_technology = C_TECH_FPGA

# TX/RX Buffers.
p_txt_buffer_count = 4, # Number of TX Buffers.
p_rx_buffer_size = 32, # RX Buffer size (in 32-bit words).

# Filter A-C.
p_sup_filtA = False,
p_sup_filtB = False,
p_sup_filtC = False,

# Range Filter.
#p_sup_filtV = False,

# Synthesize Range Filter
p_sup_range = False,

# Test registers.
p_sup_test_registers = True, # True to have access to 0x9XX Tests registers

# Traffic counters.
p_sup_traffic_ctrs = False,

# Add parity bit to TXT Buffer and RX Buffer RAMs
p_sup_parity = False,

# Number of active timestamp bits
p_active_timestamp_bits = 63,

# Reset TXT / RX Buffer RAMs
p_reset_buffer_rams = False,
)

# CTU CAN-FD Signals.
self.core_params.update(
# Clk / Rst.
i_clk_sys = ClockSignal("sys"),
i_res_n = ~(ResetSignal("sys") | self.control.fields.reset),
o_res_n_out = self.status.fields.ready,

# DFT support (ASIC only).
i_scan_enable = 0,

# Timestamp (For time based transmission / reception).
i_timestamp = timestamp,

# Memory interface.
i_scs = mem_scs,
i_srd = mem_srd,
i_swr = mem_swr,
i_sbe = mem_sbe,
i_adress = mem_adress,
i_data_in = mem_data_in,
o_data_out = mem_data_out,

# Interrupt.
o_int = self.irq,

# CAN Bus.
o_can_tx = pads.tx,
i_can_rx = pads.rx,

# Debug.
#o_test_probe = ,
)

self.comb += pads.irq.eq(self.irq)

def add_sources(self, platform):
sources = []
sdir = "CTU-CAN-FD"
cdir = os.path.dirname(__file__)
if not os.path.exists(sdir):
os.system(f"git clone https://github.com/enjoy-digital/CTU-CAN-FD")
with open(os.path.join(cdir, 'rtl_lst.txt')) as f:
for line in f:
srcfile = os.path.join(sdir, line.strip().replace('rtl', 'src'))
self.vhd2v_converter.add_source(srcfile)

def do_finalize(self):
# CAN Core instance
self.vhd2v_converter = VHD2VConverter(self.platform,
top_entity = "can_top_level",
build_dir = os.path.abspath(os.path.dirname(__file__)),
work_package = "ctu_can_fd_rtl",
force_convert = self._force_convert,
params = self.core_params,
add_instance = True,
)

# Add Sources.
self.add_sources(self.platform)
88 changes: 88 additions & 0 deletions litex/soc/cores/can/rtl_lst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
rtl/packages/unary_ops_pkg.vhd
rtl/packages/can_fd_register_map.vhd
rtl/packages/can_fd_frame_format.vhd
rtl/packages/id_transfer_pkg.vhd
rtl/packages/can_constants_pkg.vhd
rtl/packages/can_config_pkg.vhd
rtl/packages/can_types_pkg.vhd
rtl/txt_buffer/txt_buffer_fsm.vhd
rtl/tx_arbitrator/tx_arbitrator_fsm.vhd
rtl/tx_arbitrator/priority_decoder.vhd
rtl/tx_arbitrator/tx_arbitrator.vhd
rtl/rx_buffer/rx_buffer_pointers.vhd
rtl/rx_buffer/rx_buffer_fsm.vhd
rtl/prescaler/trigger_generator.vhd
rtl/prescaler/synchronisation_checker.vhd
rtl/prescaler/segment_end_detector.vhd
rtl/prescaler/bit_time_fsm.vhd
rtl/prescaler/bit_time_counters.vhd
rtl/prescaler/bit_time_cfg_capture.vhd
rtl/prescaler/bit_segment_meter.vhd
rtl/prescaler/prescaler.vhd
rtl/memory_registers/generated/memory_reg_rw_lock.vhd
rtl/memory_registers/generated/memory_reg_rw.vhd
rtl/memory_registers/generated/memory_reg_os_lock.vhd
rtl/memory_registers/generated/memory_reg_os.vhd
rtl/memory_registers/generated/memory_bus.vhd
rtl/memory_registers/generated/data_mux.vhd
rtl/memory_registers/generated/cmn_reg_map_pkg.vhd
rtl/memory_registers/generated/can_registers_pkg.vhd
rtl/memory_registers/generated/test_registers_reg_map.vhd
rtl/memory_registers/generated/control_registers_reg_map.vhd
rtl/memory_registers/generated/address_decoder.vhd
rtl/memory_registers/generated/access_signaler.vhd
rtl/interrupt_manager/int_module.vhd
rtl/interface/apb_ifc.vhd
rtl/interface/ahb_ifc.vhd
rtl/frame_filters/range_filter.vhd
rtl/frame_filters/bit_filter.vhd
rtl/frame_filters/frame_filters.vhd
rtl/common_blocks/sig_sync.vhd
rtl/common_blocks/shift_reg_preload.vhd
rtl/common_blocks/shift_reg_byte.vhd
rtl/common_blocks/shift_reg.vhd
rtl/common_blocks/parity_calculator.vhd
rtl/common_blocks/rst_sync.vhd
rtl/common_blocks/rst_reg.vhd
rtl/common_blocks/mux2.vhd
rtl/common_blocks/majority_decoder_3.vhd
rtl/common_blocks/inf_ram_wrapper.vhd
rtl/txt_buffer/txt_buffer_ram.vhd
rtl/rx_buffer/rx_buffer_ram.vhd
rtl/common_blocks/endian_swapper.vhd
rtl/common_blocks/dlc_decoder.vhd
rtl/common_blocks/dff_arst_ce.vhd
rtl/common_blocks/dff_arst.vhd
rtl/interrupt_manager/int_manager.vhd
rtl/common_blocks/clk_gate.vhd
rtl/txt_buffer/txt_buffer.vhd
rtl/rx_buffer/rx_buffer.vhd
rtl/memory_registers/memory_registers.vhd
rtl/can_core/tx_shift_reg.vhd
rtl/can_core/trigger_mux.vhd
rtl/can_core/rx_shift_reg.vhd
rtl/can_core/retransmitt_counter.vhd
rtl/can_core/reintegration_counter.vhd
rtl/can_core/protocol_control_fsm.vhd
rtl/can_core/operation_control.vhd
rtl/can_core/fault_confinement_rules.vhd
rtl/can_core/fault_confinement_fsm.vhd
rtl/can_core/err_detector.vhd
rtl/can_core/err_counters.vhd
rtl/can_core/fault_confinement.vhd
rtl/can_core/crc_calc.vhd
rtl/can_core/control_counter.vhd
rtl/can_core/protocol_control.vhd
rtl/can_core/can_crc.vhd
rtl/can_core/bus_traffic_counters.vhd
rtl/can_core/bit_stuffing.vhd
rtl/can_core/bit_destuffing.vhd
rtl/can_core/can_core.vhd
rtl/bus_sampling/tx_data_cache.vhd
rtl/bus_sampling/trv_delay_meas.vhd
rtl/bus_sampling/ssp_generator.vhd
rtl/bus_sampling/sample_mux.vhd
rtl/bus_sampling/data_edge_detector.vhd
rtl/bus_sampling/bit_err_detector.vhd
rtl/bus_sampling/bus_sampling.vhd
rtl/can_top_level.vhd
19 changes: 19 additions & 0 deletions litex/tools/litex_json2dts_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,25 @@ def get_riscv_cpu_isa_extensions(cpu_isa, cpu_name):
}};
""".format(xadc_csr_base=d["csr_bases"]["xadc"])

# CAN ------------------------------------------------------------------------------------------

for mem in d["memories"]:
if "can" in mem:
dts += """
{name}: can@{can_mem_base:x} {{
compatible = "ctu,ctucanfd";
reg = <0x{can_mem_base:x} 0x{can_mem_size:x}>;
interrupt-parent = <&intc0>;
interrupts = <{can_interrupt}>;
clocks = <&sys_clk>;
status = "okay";
}};
""".format(name=mem,
can_mem_base=d["memories"][mem]["base"],
can_mem_size=d["memories"][mem]["size"],
can_interrupt = int(d["constants"][f"{mem}_interrupt"]),
)

# Framebuffer ----------------------------------------------------------------------------------

if "video_framebuffer" in d["csr_bases"]:
Expand Down

0 comments on commit 7ec35eb

Please sign in to comment.