1. 项目概述:FPGA CAN控制器设计的意义
在嵌入式系统和工业控制领域,CAN总线因其高可靠性和实时性被广泛应用。传统方案需要外挂独立的CAN控制器芯片(如MCP2515、SJA1000等),这不仅占用宝贵的PCB面积,还增加了BOM成本和布线复杂度。而采用FPGA实现CAN控制器IP核,能够将通信功能直接集成到主控芯片内部,实现真正的单芯片解决方案。
这个项目展示了一个完全用Verilog实现的CAN控制器核心,支持标准CAN 2.0B协议,已在Altera(现Intel)和Xilinx两大主流FPGA平台上验证通过。实测表明,该设计在Artix-7器件上仅占用约1200个LUT,相当于不到10%的中低端FPGA资源,却可以替代一个完整的独立CAN控制器芯片。
2. 核心架构设计解析
2.1 CAN协议层硬件化分解
CAN控制器的核心是将协议栈的各个层次映射为硬件模块:
- 位时序处理单元:负责实现CAN总线特有的位填充机制(每5个相同位后插入一个反相位)
- CRC校验模块:采用15位多项式计算(CRC-15-CAN),硬件实现比软件查表法快10倍以上
- 验收滤波单元:支持多达32个可编程ID过滤器,通过比较器阵列实现纳秒级过滤
- 错误检测逻辑:实时监测格式错误、ACK缺失、位错误等6种标准错误类型
关键设计技巧:位时序生成采用相位累加器方案而非简单分频,这样在动态调整波特率时能避免毛刺。例如当需要从500kbps切换到1Mbps时,只需修改相位增量值而无需重置计数器。
2.2 总线接口优化方案
为降低FPGA引脚占用,设计采用以下优化:
verilog复制// 精简的三线制接口示例
module can_phy_interface (
input can_rx, // 总线差分输入
output can_tx, // 总线差分输出
output can_enable // 收发器使能(节省一路GPIO)
);
实测表明,这种设计相比传统SPI接口的CAN控制器可节省4个IO口。对于引脚受限的封装(如QFN32),这种节省尤为关键。
2.3 跨平台实现策略
针对Altera和Xilinx器件差异,采用宏定义隔离平台相关代码:
verilog复制`ifdef XILINX
// 7系列FPGA专用的IDDR原语
IDDR #(.DDR_CLK_EDGE("SAME_EDGE")) rx_iddr (
.Q1(rx_sample1), .Q2(rx_sample2),
.C(sys_clk), .CE(1'b1), .D(can_rx), .R(1'b0));
`else
// Altera的ALTDDIO实现
altddio_in rx_input (
.datain(can_rx), .inclock(sys_clk),
.dataout_h(rx_sample1), .dataout_l(rx_sample2));
`endif
3. 关键模块实现细节
3.1 位时序同步状态机
CAN总线要求严格的时钟同步,我们设计的三级状态机实现方案:
- 硬同步:在帧起始(SOF)的下降沿强制调整时钟相位
- 重同步:根据后续位跳变沿微调采样点位置
- 相位缓冲段:动态调整TSEG1/TSEG2参数以适应不同总线长度
状态转移图的核心逻辑:
verilog复制always @(posedge clk) begin
case(state)
IDLE: if(sof_detected) state <= HARD_SYNC;
HARD_SYNC: state <= RESYNC;
RESYNC: if(bit_edge) adjust_phase();
endcase
end
3.2 高效FIFO设计
为处理突发报文,采用双时钟域FIFO设计要点:
- 写端口使用CAN总线时钟(典型1MHz)
- 读端口使用系统时钟(如100MHz)
- 格雷码计数器实现跨时钟域指针同步
- 深度可配置(默认16帧),每帧存储:
- 29位标识符(支持扩展帧)
- 8字节数据
- 4位DLC(数据长度代码)
- 3位状态标志(RTR/IDE/ERR)
3.3 动态波特率配置
传统CAN控制器修改波特率需要复位整个模块,本设计通过以下方式实现热切换:
- 配置寄存器写入新波特率分频值
- 等待当前报文传输完成(检测到11个连续隐性位)
- 原子性地更新波特率生成器的相位增量寄存器
- 自动重新同步到总线
实测切换过程仅需50us(在1Mbps下),远快于独立芯片的毫秒级复位时间。
4. 平台适配与实测数据
4.1 Xilinx平台优化
在Artix-7上的实现关键点:
- 使用STARTUPE2原语直接访问配置引脚,省去外部电平转换
- 利用SRL16E实现紧凑的移位寄存器
- 通过MMCM生成精确的时钟(误差<0.1%)
资源占用报告:
| 资源类型 | 使用量 | 占比 |
|---|---|---|
| LUT | 1,243 | 9% |
| FF | 897 | 7% |
| BRAM | 2 | 3% |
| BUFG | 1 | 6% |
4.2 Intel/Altera平台差异
Cyclone IV E的特殊处理:
- 需要手动实例化IOBUF实现三态总线
- 使用PLL而非MMCM生成时钟
- 验收滤波器改用ROM查表法(节省逻辑资源)
实测波特率稳定性对比:
| 平台 | 100kbps误差 | 1Mbps误差 |
|---|---|---|
| Artix-7 | ±0.08% | ±0.12% |
| Cyclone IV | ±0.15% | ±0.25% |
5. 常见问题与调试技巧
5.1 总线冲突处理
当检测到连续6个显性位时(错误标志),控制器会自动:
- 记录错误计数器(TEC/REC)
- 根据错误状态进入被动错误模式或总线关闭状态
- 触发中断并保存错误代码到状态寄存器
调试建议:在测试模式强制发送错误帧,验证错误恢复机制是否正常。
5.2 时序收敛问题
在高速(1Mbps)下可能遇到的建立/保持时间违例,解决方法:
- 对CAN_RX信号添加IOB约束(如set_input_delay)
- 在综合属性中设置MAX_FANOUT(建议≤16)
- 关键路径手动布局(RLOC约束)
5.3 验收滤波器配置
典型配置示例(只接收ID 0x123的标准帧):
c复制// 设置滤波掩码(所有位都必须匹配)
write_reg(MASK_REG0, 0x0000);
write_reg(MASK_REG1, 0x07FF);
// 设置期望ID
write_reg(FILTER_REG0, 0x0123);
write_reg(FILTER_REG1, 0x0000);
6. 实际应用案例
6.1 工业PLC集成
在某型号PLC中替换传统方案后的对比:
| 指标 | 独立芯片方案 | FPGA集成方案 |
|---|---|---|
| PCB面积 | 320mm² | 0mm² |
| 物料成本 | $4.2 | $0 |
| 最大帧率 | 8,000帧/秒 | 12,000帧/秒 |
| 延迟抖动 | ±50us | ±10us |
6.2 车载网关设计
通过FPGA实现4路CAN FD网关的关键优化:
- 共享一个CRC计算模块(时分复用)
- 使用Block RAM实现4K深度报文缓冲
- 动态优先级仲裁算法(基于ID和时效性)
实测在Xilinx Zynq MPSoC上可同时处理:
- 2路CAN FD(5Mbps)
- 2路经典CAN(1Mbps)
总吞吐量达到1.2MB/s,延迟低于100us。