101 AER Reflex Chip - MCP2515 CAN gateway

101 : AER Reflex Chip - MCP2515 CAN gateway

Design render
  • Author: khu-haeun
  • Description: Robot-arm reflex core: relays joint commands to CAN via an MCP2515, blocks the stream on a danger trigger and injects a reflex pose. Tuning values (recoil/speed/debounce) hardcoded; rules/threshold/flinch programmable.
  • GitHub repository
  • Open in 3D viewer
  • Clock: 20000000 Hz

How it works

This is the decision/relay core of a robot-arm reflex system (AgileX Piper 6-DOF arm). The chip is the only transmitter on the CAN bus: it forwards the host's normal joint commands to the robot via an external MCP2515 (SPI↔CAN controller), and when a danger trigger fires it blocks the normal stream and injects a reflex pose instead. Because the chip is the sole sender, the "gate" is not a cross-module signal — it is a single internal mux.

Two SPI ports:

  • uio[0:3] = SPI slave (the FPGA's PL writes config registers + relays normal CAN frames into the chip).
  • uio[4:6] + ui[3] = SPI master that drives the MCP2515 directly (init, transmit, read-back).

Data path:

  • Normal: PL → SPI-slave mailbox (regs 0x50–0x55) → mux(normal) → MCP2515 → CAN.
  • Reflex: trigger (DIP / soft / XADC-threshold) → reflex_core_c (rule table + priority + debounce) → reflex_pose_gen / reflex_tx_src → mux(reflex, gate closed) → MCP2515 → CAN.
  • RX: MCP2515 RX → mcp_rx_recv (decodes feedback 0x2A5–7 current pose) → used by the "flinch-from-current-pose" reflex.

Reflex actions (action_id):

  1. freeze — block normal commands, hold the current pose (the real arm's e-stop releases torque and droops, so freeze is used instead).
  2. duck/home — drive to the home (0) pose, level-held while the trigger is active.
  3. flinch-home — one-shot: jump toward home for FLINCH_TICKS, then auto-release (re-arm on sensor release).
  4. flinch-current — one-shot: current pose + a J5 delta, then auto-release.

Programmable reflex (rule encoding, register 0x10–0x13): each 16-bit rule is [2:0]=action [3]=enable [5:4]=priority [6]=source(0=digital pin / 1=XADC threshold). The danger source is xadc_val >= threshold (FSR) or a digital pin. Highest-priority active rule wins. A debounce (0x49) rejects noise. MCP2515 read-back (regs 0x21–0x28: CANSTAT/CNF/TEC/REC/…) is exposed so the host can see how the chip configured/drove the CAN controller (black-box-free debugging).

Note: timing constants (MCP oscillator-settle delay, SPI pacing, flinch ticks) are sized for the 20 MHz clock via the module's default parameters. Run the design at ~20 MHz.

How to test

The chip is a clock-synchronous SPI peripheral that also masters an MCP2515. To exercise it:

  1. Clock/reset: drive clk at ~20 MHz, pulse rst_n low then high, keep ena=1, ui[7](arm_enable)=1.
  2. Wait for MCP init: after reset the chip auto-runs the MCP2515 startup (soft-reset 0xC0, oscillator-settle delay, CNF1/2/3=00/C0/80 for 1 Mbps, normal mode). STATUS(0x20) init_done goes high.
  3. Program (via SPI slave on uio[0:2], 24-bit txn = 8-bit cmd {rw,addr[6:0]} + 16-bit data): set a rule (e.g. 0x12=FSR rule), threshold (0x1A), flinch ticks (0x46/0x47), speed (0x48), debounce (0x49).
  4. Relay a normal frame: write 0x50(id) + 0x51–0x54(8 bytes) then 0x55 (send) → appears on CAN.
  5. Fire a reflex: raise ui[0](DIP) or drive the XADC input above threshold → uo[5](reflex_active) goes high, the normal frame is blocked, and the reflex pose (0x150/0x155–7) goes out on CAN instead.
  6. Observe: uo[7]=heartbeat, uo[4:2]=action_id, uo[1]=fire; MCP regs read-back via SPI 0x21–0x28.

A full reference Verilog integration test (chip + an MCP2515 model, exercising pass-through + the current-pose flinch) is in test/tb_reference_full.v (+ mcp2515_model_v2.v). The test/ cocotb harness runs a minimal reset/heartbeat sanity check for the GDS CI.

External hardware

  • MCP2515 SPI↔CAN controller (8 MHz crystal) on uio[4:6] (SCLK/MOSI/CSn) + ui[3] (MISO) + ui[2] (INT).
  • CAN transceiver (e.g. TJA1050/SN65HVD230) from the MCP2515 to the robot's CAN bus (1 Mbps).
  • DIP switch on ui[0] (estop/freeze trigger).
  • FSR (force sensor) into the FPGA XADC analog input; the PL feeds the digitized value to the chip as the threshold-compare source (the reflex trigger).
  • The chip is intended to sit between a Zynq PL (which does the SPI plumbing + XADC) and the robot's CAN bus.

IO

#InputOutputBidirectional
0dip estop triggervalidSPI slave SCLK in
1danger1 soft triggerfireSPI slave MOSI in
2mcp_intaction_id0SPI slave CSn in
3mcp_misoaction_id1SPI slave MISO out
4action_id2SPI master SCLK out
5reflex_active gateSPI master MOSI out
6mcp_rstSPI master CSn out
7arm_enableheartbeat

Chip location

Controller Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux Mux tt_um_chip_rom (Chip ROM) tt_um_factory_test (Tiny Tapeout Factory Test) tt_um_Vincent2405_adder_tree (BSD Convolution Adder Tree) tt_um_BastiBudde_i2c_slave_sensor (I2C Slave Template with Emulated Sensor) tt_um_60hz_load (60 Hz Grid-Forming ASIC with Dump-Load Control) tt_um_spi_config_reg (Simple SPI configuration for analog designs) tt_um_ex_drosen766 (Project) tt_um_spi_cpu_top (SPI-CPU) tt_um_d5smith_mfa (Music for ASICs) tt_um_i2c_master (I2C Master Controller) tt_um_aswarby_mac (Aswarby INT8 MAC) tt_um_arrakeen_spsram_direct (TT-Arrakeen-SPSRAM-direct) tt_um_alu (8-bit Interactive ALU) tt_um_JCT_PoC (ttgf jct PoC) tt_um_jct_lea (LEA-128) tt_um_cwru_cpu (CWRU CPU) tt_um_teapot (100Mbps Ethernet Accelerator Wrapper) tt_um_jte_cordic (CORDIC sin/cos generator) tt_um_aidenkoch4 (Three Channel RGB PWM Controller) tt_um_pschuetz_tremolo (Tremolo guitar pedal ASIC) tt_um_jsabree11_fibonacci_checker (fibbonaci_tt) tt_um_connerdaehler_boop (Procedural ASIC) tt_um_Kieckenwama_Traffic_LIGHT_FSM (Traffic Light FSM) tt_um_KimLuu02_WashingMachine_FSM (WashingMachine_FSM) tt_um_PaulineKreis_PWM_Analyser (PWM-Analyser) tt_um_PWM (PWM Generator) tt_um_wokwi_466666882406199297 (Simple Sprinkler) tt_um_rebeccargb_universal_decoder (Universal Binary to Segment Decoder) tt_um_rebeccargb_hardware_utf8 (Hardware UTF Encoder/Decoder) tt_um_spi_master (SPI Master Slave Communication) tt_um_likitha_trng (Secure TRNG Entropy Generator) tt_um_wnn (8-bit WNN Pattern Recognizer) tt_um_raksha (Raksha) tt_um_uart_soc (UART_SOC) tt_um_ecdsa_verify (ECDSA Verification) tt_um_ecc_processor (ECC Processor) tt_um_fast_auth (Fast Authentication Accelerator) tt_um_karthik_trng (TRNG using Ring Oscillator) tt_um_push (Secure V2X Mini Demonstrator) tt_um_santosh_aes_sbox (AES S-Box Accelerator) tt_um_hardware_anomaly_detection (Hardware Anomaly Detection) tt_um_multi_protocol (Multi-Protocol Communication Controller) tt_um_pqc_ntt_butterfly (PQC NTT Butterfly Core) tt_um_cambridge_nlfsr (Programmable Chaotic NLFSR) tt_um_4b_accumulator_cpu (4 bit Accumulator CPU) tt_um_spi_slave (SPI Slave with 8-Register File) tt_um_geeta_doddamani_lfsr (4-bit Maximum-Length LFSR) tt_um_ecc_accelerator (ECC Scalar Accelerator) tt_um_egurapha_chacha20 (ChaCha20) tt_um_configurable_pwm (Configurable PWM Generator) tt_um_Arctic0 (Arctic0 16-bit CPU) tt_um_comp8 (8-bit Comparator) tt_um_pwm_cit (Configurable 8-bit PWM Generator) tt_um_rameshwar_door_lock (Digital Door Lock) tt_um_sandy_venky (8-bit LFSR Circuit) tt_um_ljhahne_pong (Pong) tt_um_v2x_warning (V2X Collision Warning) tt_um_ecc_scalar_mult (ECC Scalar Multiplication) tt_um_fhw_appel_spiPWMio (spiPWMio) tt_um_arrakeen_spsram_direct_sramrules (TT-Arrakeen-SPSRAM-direct-sramrules) tt_um_arrakeen_spsram_direct_5v (TT-Arrakeen-SPSRAM-direct-5V) tt_um_LukeSilva_cartrip (Car Trip) tt_um_coffeepot (100Mpbs 3 port Ethernet switch) tt_um_emiliopeju_lightscan (Lightscan) tt_um_Alanduan21_triad01_top (triad01) tt_um_lif_snn (4-Neuron LIF Spiking Neural Network) tt_um_smerity_mandelbrot (Smerity-Mandelbrot) tt_um_elvtide01_7SegmentDice (7SegmentDice) tt_um_elemental_harmony (Elemental Harmony Game) tt_um_pattern_gen (Programmable Waveform and PWM Generator) tt_um_antimatter15_pdm_vad (PDM Voice Activity Detector) tt_um_layla_spike_detector (Neural Spike Detector) tt_um_detronyx_arith_lab (Detronyx Arithmetic Lab Tile) tt_um_hasheddan_nni (Nearest Neighbor Interpolation) tt_um_brisq (BRISQ) tt_um_santhosh_spike_codec_gf (Neuromorphic Spike Codec (GF180)) tt_um_santhosh_aer_router_gf (Asynchronous-AER Spike Router (4-phase REQ/ACK, 16-entry routing table, GF180)) tt_um_santhosh_snn_wta_gf (Spiking Neural Network WTA Inference Engine (GF180)) tt_um_santhosh_cim_bist_gf (CIM Controller with BIST and Fault Map (GF180)) tt_um_santhosh_neuro_puf_gf (Neuromorphic PUF (distinct-tap LFSR arbiter + memristor XOR, GF180)) tt_um_detronyx_uart_trace_exerciser (Detronyx UART Trace Exerciser) tt_um_ro_puf (Tiny RIng Oscillator PUF) tt_um_franretfie_top (Quadrature sine generator) tt_um_cherny_xor_8bi (XORing given bits) tt_um_mealycpp_ascon_sdmc_uart (ASCON Integrated Crypto Processor) tt_um_reflex_s4 (AER Reflex Chip - MCP2515 CAN gateway) tt_um_polytrig_core (PolyTrig Digital Waveform Synthesis Core) tt_um_waferspace_vga_screensaver (Wafer.space Logo VGA Screensaver) tt_um_2048_vga_game (2048 sliding tile puzzle game (VGA)) tt_um_urish_simon (Simon Says memory game) Available