1. 项目背景与核心价值
在工业自动化和汽车电子领域,控制器局域网(CAN)总线因其出色的抗干扰能力和实时性,成为设备间通信的首选方案。传统CAN方案多采用MCU+独立CAN控制器的架构,而本项目的创新点在于使用FPGA直接驱动SJA1000T CAN控制器芯片,实现了更高灵活性的硬件可编程解决方案。
这套Verilog代码最显著的特点是:
- 完整实现了对SJA1000T芯片的寄存器级控制
- 支持标准帧(11位标识符)和扩展帧(29位标识符)两种格式
- 提供基础版和增强版两套驱动方案
- 包含完整的仿真测试环境和硬件调试接口
提示:SJA1000T是NXP推出的经典独立CAN控制器,采用PeliCAN工作模式时支持CAN 2.0B规范。与市面上常见的SJA1000相比,T版本在ESD防护和温度范围上有明显提升。
2. 硬件架构设计解析
2.1 系统组成框图
整个系统采用分层设计架构,从下至上分为:
- 物理层:FPGA开发板与SJA1000T的电气连接
- 接口层:时序控制模块(rs_port.v)
- 协议层:核心驱动模块(can_port.v/can_port_new.v)
- 应用层:顶层控制模块(can_top.v)
code复制FPGA端:
+-------------------+
| can_top.v | ← 用户控制接口
+-------------------+
| can_port[new].v | ← CAN协议处理
+-------------------+
| rs_port.v | ← 硬件时序控制
+-------------------+
||||||||
vvvvvvvv
SJA1000T芯片:
+-------------------+
| CAN控制器核心 |
+-------------------+
| 总线接口逻辑 |
+-------------------+
2.2 关键硬件接口设计
FPGA与SJA1000T的硬件连接需要特别注意以下信号:
| 信号名称 | FPGA引脚方向 | 功能描述 | 注意事项 |
|---|---|---|---|
| DATA_CAN[7:0] | 双向 | 数据/地址复用总线 | 必须加10K上拉电阻 |
| CAN_ALE | 输出 | 地址锁存使能 | 下降沿锁存地址 |
| CAN_CS | 输出 | 片选信号 | 低电平有效 |
| CAN_RD | 输出 | 读使能 | 低电平有效 |
| CAN_WR | 输出 | 写使能 | 低电平有效 |
| CAN_RST | 输出 | 复位信号 | 至少保持16个时钟周期低电平 |
注意:当FPGA与SJA1000T工作在不同电压等级(如FPGA 3.3V,SJA1000T 5V)时,必须使用电平转换芯片如SN74LVC8T245进行电平匹配,否则会导致通信不稳定甚至器件损坏。
3. 核心驱动模块实现
3.1 寄存器配置详解
SJA1000T的初始化需要配置14个关键寄存器,以下是几个核心寄存器的配置要点:
3.1.1 模式寄存器(MOD - 0x00)
- 复位值:0x01
- 关键位域:
- Bit0(RM):1=复位模式(必须在此模式下配置寄存器)
- Bit3(STM):0=正常模式,1=自测试模式(环回)
- 典型配置:
- 初始化阶段:0x09(RM=1)
- 正常工作阶段:0x08(RM=0)
3.1.2 总线定时寄存器(TIMER0/1 - 0x06/0x07)
波特率计算公式:
code复制tq = 2 × (BRP[5:0] + 1) / fosc
波特率 = 1 / (tq × (1 + TSEG1[3:0] + TSEG2[2:0]))
对于40MHz时钟和800kbps波特率:
- TIMER0 = 0x00 (BRP=0)
- TIMER1 = 0x16 (TSEG1=7, TSEG2=2)
3.1.3 输出控制寄存器(OCR - 0x08)
配置示例:0x1A
- 正常输出模式(Bit6-4=000)
- TX0推挽输出(Bit3=1)
- TX1上拉(Bit7=1)
- 输出极性正常(Bit5=0)
3.2 状态机设计
驱动核心采用五状态独热码状态机,状态转换图如下:
code复制INIT_RESET → INIT → IDLE
↑ ↓
└── DATA_READ
└── DATA_SEND
状态说明:
- INIT_RESET:硬件复位阶段,保持CAN_RST低电平至少30000个时钟周期
- INIT:寄存器配置阶段,依次写入14个初始化值
- IDLE:空闲状态,轮询状态寄存器(SR)
- DATA_READ:接收数据处理状态
- DATA_SEND:发送数据处理状态
关键状态转换条件:
- 接收触发:SR[0]=1(接收缓冲区满)
- 发送触发:SR[2]=1(发送缓冲区空)且CAN_DATA_SEND_EN=1
4. 数据帧处理机制
4.1 标准帧与扩展帧格式
4.1.1 标准帧(11位ID)
code复制| ID10-3 | ID2-0 RTR DLC0 | DATA0-7 | ... | DATA56-63 |
4.1.2 扩展帧(29位ID)
code复制| ID28-21 | ID20-13 | ID12-5 | ID4-0 RTR DLC0 | DATA0-7 | ... | DATA56-63 |
4.2 ID处理特殊问题
SJA1000T在PeliCAN模式下存在3位偏移问题,解决方案:
发送端处理:
verilog复制CAN_ID1_tx = ID_test[28:21];
CAN_ID2_tx = ID_test[20:13];
CAN_ID3_tx = ID_test[12:5];
CAN_ID4_tx = {ID_test[4:0], 3'b000}; // 低5位左移3位
接收端处理:
verilog复制real_recv_id = {3'b000, CAN_ID1_rx, CAN_ID2_rx, CAN_ID3_rx, CAN_ID4_rx[7:3]};
5. 增强版驱动特性
5.1 可变数据长度支持
基础版can_port.v固定处理8字节数据,而增强版can_port_new.v通过DLC(Data Length Code)字段实现0-8字节灵活配置:
| DLC编码 | 数据字节数 |
|---|---|
| 0000 | 0 |
| 0001 | 1 |
| ... | ... |
| 1000 | 8 |
5.2 临时数据缓存设计
增强版新增了双缓冲机制:
- 接收缓冲:正在接收的数据存入tmp_CAN_ID_rx/tmp_CAN_DATA_rx
- 用户缓冲:完整接收的数据复制到CAN_ID_rx/CAN_DATA_rx
这种设计避免了数据覆盖问题,特别适合高速通信场景。
6. 硬件调试实战
6.1 ChipScope配置要点
调试核需要监控的关键信号:
- 状态机信号(state_c)
- 收发完成标志(CAN_DATA_SEND_DONE/CAN_DATA_RECV_DONE)
- 数据总线(DATA_CAN)
- 控制信号(CAN_ALE, CAN_WR, CAN_RD)
建议触发条件设置为状态机异常跳转或错误计数器递增。
6.2 常见故障排查
6.2.1 通信失败检查清单
- 电源检查:测量SJA1000T的VDD电压(4.5-5.5V)
- 时钟检查:用示波器测量XTAL1引脚是否有16MHz正弦波
- 复位检查:上电后CAN_RST应有至少400ns低电平脉冲
- 总线检查:CANH-CANL间应有60Ω左右阻抗(两个120Ω终端电阻并联)
6.2.2 典型波形分析
正常写时序波形特征:
code复制ALE: _|‾|_________
CS: ________|‾|__
WR: _______|‾|___
DATA: <地址>___<数据>
异常波形常见问题:
- ALE脉冲宽度不足(应>30ns)
- WR信号在CS无效期间变化
- 数据建立时间不足(应>10ns)
7. 性能优化建议
7.1 时序优化技巧
- 关键路径约束:
tcl复制set_false_path -from [get_clocks clk] -to [get_clocks CAN_CLK]
set_multicycle_path 2 -setup -from [get_pins can_port/state_c_reg*] -to [get_pins rs_port/*]
- 流水线设计:
对状态机中的寄存器访问操作增加一级流水,可提升最高工作频率约30%。
7.2 资源优化方案
- 共享缓冲区:发送和接收缓冲区可复用同一块RAM,节省约256个LUT
- 状态机编码:改用格雷码编码可减少状态跳转时的毛刺
- 数据位宽:若非必要,可将内部数据处理位宽从32位降至16位
8. 应用场景扩展
8.1 多节点组网方案
通过修改验收滤波寄存器(ACR/AMR)实现多ID识别:
verilog复制// 接收ID 0x123和0x456
ACR0 = 0x12; ACR1 = 0x30; // 0x123的高8位和中间3位
AMR0 = 0xFC; AMR1 = 0xF8; // 屏蔽低4位和中间5位
8.2 汽车电子应用适配
针对汽车环境的特点建议:
- 增加看门狗定时器,超时无响应自动复位
- 错误计数器阈值调整为120(标准为96)
- 重要数据采用双帧发送+校验机制
9. 开发心得与建议
在实际项目部署中,有几个容易忽视但至关重要的细节:
-
ESD防护:SJA1000T的CANH/CANL引脚建议串联22Ω电阻并并联TVS二极管如SM712,可显著提升浪涌抗扰度。
-
时钟抖动:当通信距离超过20米时,建议在FPGA的时钟输入端增加低通滤波器(10Ω+100pF),减少时钟抖动对波特率的影响。
-
热插拔处理:通过监测总线错误计数器,实现热插拔检测:
verilog复制if(RXERR > 96 || TXERR > 96) begin
state_c <= INIT_RESET;
need_reset <= 1'b1;
end
- 调试技巧:在初期调试时,可以先将SJA1000T配置为自测试模式(MOD[3]=1),无需实际连接CAN总线即可验证基本功能。