1. 项目背景与核心价值
在工业控制、汽车电子和航空航天等领域,CAN总线作为可靠的现场总线标准已有30余年应用历史。传统方案多采用专用CAN控制器芯片(如SJA1000),但这类芯片存在采购周期长、接口灵活性差的问题。这个开源项目用纯Verilog实现的FPGA版CAN控制器,完美解决了这些痛点。
我曾在汽车ECU开发中遇到过SJA1000芯片全球缺货导致项目延期的困境,这也是我后来深入研究FPGA实现CAN协议栈的原因。与ASIC方案相比,FPGA实现具有三大独特优势:
- 可定制化:能灵活调整波特率、滤波器等参数
- 集成度高:可与其它逻辑模块(如ARM软核)协同工作
- 供应链安全:避免专用芯片的断供风险
2. 架构设计与协议实现
2.1 CAN 2.0B协议核心机制
该设计完整实现了CAN 2.0B协议规范,包括:
- 标准帧(11位标识符)和扩展帧(29位标识符)双模式
- 非破坏性逐位仲裁机制
- 基于CRC的差错检测(15位多项式)
- 自动重传与错误帧处理
协议状态机采用三段式写法实现,以下是关键状态转换逻辑:
verilog复制always @(posedge clk) begin
case(current_state)
IDLE: if(tx_req) next_state = ARBITRATION;
ARBITRATION: if(win_arb) next_state = TRANSMIT;
TRANSMIT: if(ack_received) next_state = IDLE;
default: next_state = IDLE;
endcase
end
2.2 时钟域同步方案
由于CAN总线异步通信特性,设计采用了双时钟域处理:
- 系统时钟域(100MHz):用于寄存器配置
- CAN时钟域(16MHz):由波特率预分频生成
verilog复制// 波特率生成示例(1MHz波特率)
localparam CLK_DIV = 16; // 16MHz/(16*1) = 1MHz
reg [7:0] baud_cnt;
always @(posedge clk) begin
if(baud_cnt == CLK_DIV-1) begin
baud_cnt <= 0;
can_clk <= ~can_clk;
end else begin
baud_cnt <= baud_cnt + 1;
end
end
3. 关键模块实现细节
3.1 位时序处理单元
这是CAN控制器的核心难点,需要精确控制:
- 同步段(Sync Seg)
- 传播段(Prop Seg)
- 相位缓冲段(Phase Seg1/2)
verilog复制// 位时序配置寄存器
reg [3:0] sync_seg = 1;
reg [4:0] prop_seg = 4;
reg [4:0] phase_seg1 = 4;
reg [3:0] phase_seg2 = 3;
// 位时序状态机
always @(posedge can_clk) begin
case(bit_state)
SYNC: if(sample_point) bit_state <= PROP;
PROP: if(bit_cnt == prop_seg) bit_state <= PHASE1;
PHASE1:if(bit_cnt == phase_seg1) bit_state <= PHASE2;
PHASE2:if(bit_cnt == phase_seg2) bit_state <= SYNC;
endcase
end
3.2 验收滤波器设计
支持四种过滤模式:
- 单ID精确匹配
- ID范围匹配
- 掩码模式
- 全局接收(调试用)
verilog复制// 掩码模式匹配示例
function match_mask;
input [28:0] rx_id;
input [28:0] filter_id;
input [28:0] mask;
begin
match_mask = ((rx_id & mask) == (filter_id & mask));
end
endfunction
4. 跨平台移植要点
4.1 Altera器件适配
在Cyclone IV上的特殊处理:
- 使用PLL生成精确时钟
- 注意SignalTap调试时的时钟域交叉
- 推荐使用Quartus 18.1以上版本综合
4.2 Xilinx器件优化
针对Artix-7的优化技巧:
- 使用BUFG处理全局时钟
- 启用-retiming优化选项
- 7系列器件中SRL16E资源的利用
5. 实测性能数据
在DE0-Nano开发板(Cyclone IV)上的测试结果:
| 测试项 | 标准要求 | 实测结果 |
|---|---|---|
| 波特率精度 | ±1% | ±0.8% |
| 帧接收延迟 | <5μs | 3.2μs |
| 错误检测率 | 100% | 100% |
| 资源占用(LEs) | - | 1,823 |
6. 常见问题排查指南
6.1 总线显性电平锁定
症状:CANH/CANL电压持续3V以上
解决方法:
- 检查终端电阻(需60Ω)
- 确认PHY芯片使能信号
- 用示波器捕捉总线波形
6.2 接收丢帧问题
可能原因:
- 验收滤波器配置错误
- 缓冲区溢出
- 时钟偏差过大
调试步骤:
verilog复制// 添加调试计数器
reg [15:0] rx_counter;
always @(posedge can_clk) begin
if(rx_frame_valid && !rx_buffer_full)
rx_counter <= rx_counter + 1;
end
7. 进阶开发建议
7.1 与Nios II软核集成
在Qsys中的连接技巧:
- 将CAN控制器封装为Avalon-MM从设备
- 使用DMA传输接收帧
- 中断优先级设置建议高于UART
7.2 汽车电子应用增强
满足ISO 11898-2规范的改进:
- 添加总线唤醒功能
- 实现TTCAN时间触发机制
- 支持CAN FD扩展(需硬件加速)
我在实际项目中总结的几条经验:
- 综合时设置"keep hierarchy"保留模块边界
- 接收FIFO深度建议不小于32帧
- 关键信号添加时序约束(set_false_path除外)
- 回环测试时注意禁用自动重传
