From bad64bcf6dd7bdfd02ffc4b3ba7d45485de7dcd8 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 24 Jun 2024 12:27:17 +0200 Subject: [PATCH 1/3] soc/cores: Add initial CTU-CAN-FD integration from 2021 work with recent updates/tests. --- litex/soc/cores/can/__init__.py | 0 litex/soc/cores/can/ctu_can_fd.py | 184 ++++++++++++++++++++++++++++++ litex/soc/cores/can/rtl_lst.txt | 88 ++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 litex/soc/cores/can/__init__.py create mode 100644 litex/soc/cores/can/ctu_can_fd.py create mode 100644 litex/soc/cores/can/rtl_lst.txt diff --git a/litex/soc/cores/can/__init__.py b/litex/soc/cores/can/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/litex/soc/cores/can/ctu_can_fd.py b/litex/soc/cores/can/ctu_can_fd.py new file mode 100644 index 000000000..5bd91c0b0 --- /dev/null +++ b/litex/soc/cores/can/ctu_can_fd.py @@ -0,0 +1,184 @@ +# +# CTU CAN-FD Core Wrapper for LiteX. +# +# Copyright (c) 2021 Andrew Dennison +# Copyright (c) 2021-2024 Florent Kermarrec +# Copyright (c) 2024 Gwenhael Goavec-Merou +# 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.mr_int_ena_set_int_ena_set_o = Signal(12) + self.mr_int_mask_set_int_mask_set_o = Signal(12) + self.int_status_i = Signal(12) + + 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_irq = self.irq, + + # CAN Bus. + o_can_tx = pads.tx, + i_can_rx = pads.rx, + o_dbg_mr_int_ena_set_int_ena_set_o = self.mr_int_ena_set_int_ena_set_o, + o_dbg_mr_int_mask_set_int_mask_set_o = self.mr_int_mask_set_int_mask_set_o, + o_dbg_int_status_i = self.int_status_i, + + + # Debug. + #o_test_probe = , + ) + + self.comb += pads.irq.eq(self.irq) + + def add_sources(self, platform): + sources = [] + cdir = os.path.dirname(__file__) + sdir = os.path.abspath(os.path.join(cdir, "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) diff --git a/litex/soc/cores/can/rtl_lst.txt b/litex/soc/cores/can/rtl_lst.txt new file mode 100644 index 000000000..19d92a25d --- /dev/null +++ b/litex/soc/cores/can/rtl_lst.txt @@ -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 From 71ff4eaadc89b5d0129eaa6c77c56260f258675a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 24 Jun 2024 12:53:38 +0200 Subject: [PATCH 2/3] soc/cores/can: Switch to our fork of CTU-CAN-FD, remove debug signals and do a git clone if not present in execution directory. --- litex/soc/cores/can/ctu_can_fd.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/litex/soc/cores/can/ctu_can_fd.py b/litex/soc/cores/can/ctu_can_fd.py index 5bd91c0b0..2a952dcf7 100644 --- a/litex/soc/cores/can/ctu_can_fd.py +++ b/litex/soc/cores/can/ctu_can_fd.py @@ -117,10 +117,6 @@ class CTUCANFD(LiteXModule, EventManager): ) # CTU CAN-FD Signals. - self.mr_int_ena_set_int_ena_set_o = Signal(12) - self.mr_int_mask_set_int_mask_set_o = Signal(12) - self.int_status_i = Signal(12) - self.core_params.update( # Clk / Rst. i_clk_sys = ClockSignal("sys"), @@ -143,15 +139,11 @@ class CTUCANFD(LiteXModule, EventManager): o_data_out = mem_data_out, # Interrupt. - o_irq = self.irq, + o_int = self.irq, # CAN Bus. o_can_tx = pads.tx, i_can_rx = pads.rx, - o_dbg_mr_int_ena_set_int_ena_set_o = self.mr_int_ena_set_int_ena_set_o, - o_dbg_mr_int_mask_set_int_mask_set_o = self.mr_int_mask_set_int_mask_set_o, - o_dbg_int_status_i = self.int_status_i, - # Debug. #o_test_probe = , @@ -161,9 +153,10 @@ class CTUCANFD(LiteXModule, EventManager): def add_sources(self, platform): sources = [] + sdir = "CTU-CAN-FD" cdir = os.path.dirname(__file__) - sdir = os.path.abspath(os.path.join(cdir, "CTU-CAN-FD")) - + 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')) From 462016a1d0803566657f0cbc47cab1e4d2f9aec4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 24 Jun 2024 13:01:18 +0200 Subject: [PATCH 3/3] litex/tools/litex_json2dts_linux: Add initial CAN support. --- litex/tools/litex_json2dts_linux.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/litex/tools/litex_json2dts_linux.py b/litex/tools/litex_json2dts_linux.py index 08e9c0e8a..8d5e7f8c1 100755 --- a/litex/tools/litex_json2dts_linux.py +++ b/litex/tools/litex_json2dts_linux.py @@ -633,6 +633,25 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic }}; """.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"]: