基于Xilinx FPGA的CAN总线通信实现:清晰注释的Verilog源码及Vivado工程...

张开发
2026/4/14 19:59:17 15 分钟阅读

分享文章

基于Xilinx FPGA的CAN总线通信实现:清晰注释的Verilog源码及Vivado工程...
xilinx FPGA利用can IP实现can总线通信verilog源码直接可用注释清晰。 vivado实现代码7系列以上都兼容最近在项目里折腾CAN总线通信发现Xilinx官方给的文档虽然全但真找起能直接跑的代码还真费劲。今天就带大家手搓一个基于7系列FPGA的CAN通信模块实测在Kintex-7和Artix-7上都跑通了代码里关键位置都打了注释直接扔工程里就能用。先说硬件配置直接上Xilinx的CAN IP核AXI4-Lite接口版本。注意在IP Integrator里要把时钟域配置成和FPGA主时钟同步不然后面时序约束能折腾死人。这里有个小技巧把IP核的寄存器配置映射到0x43C00000起始地址实测兼容性最好。上核心代码片段// CAN控制器寄存器配置 reg [31:0] can_ctrl_regs [0:15]; always (posedge clk) begin if(axi_awvalid (axi_awaddr[15:0] 16h0000)) begin can_ctrl_regs[axi_awaddr[7:2]] axi_wdata; end end // 发送数据缓冲区 wire [63:0] tx_packet { 8h02, // 数据长度 24h0123, // 标准帧ID 8hAA,8hBB,8hCC,8hDD,8hEE,8hFF,8h00,8h55 // 数据域 }; // 报文发送触发 always (posedge can_clk) begin if(can_ctrl_regs[3][0] !tx_busy) begin can_tx_data tx_packet; tx_busy 1b1; end if(tx_done) tx_busy 1b0; end这段实现了最基本的寄存器配置和报文发送逻辑。注意第7行的数据打包方式——把CAN报文各个字段按位拼接成64位总线实测比用结构体效率更高。发送触发逻辑里用了状态标志位避免连续发送导致数据覆盖。xilinx FPGA利用can IP实现can总线通信verilog源码直接可用注释清晰。 vivado实现代码7系列以上都兼容接收处理有个坑要注意当同时收到标准帧和扩展帧时IP核的接收FIFO可能会溢出。这里我加了硬件过滤// 硬件过滤器配置 can_filter_config #( .FILTER_MODE(2b01), // 标识符掩码模式 .FILTER_ID(28h1234567), .FILTER_MASK(28h1FFFFFFF) ) filter_inst ( .can_clk(can_clk), .filter_en(1b1) );这个配置只接收ID在0x1234567范围内的标准帧实测过滤效果比软件处理靠谱多了。注意掩码值最后四位要留空不然可能会误过滤。时序约束是关键分享我的约束文件片段create_clock -period 20.000 [get_ports can_clk] set_clock_groups -asynchronous -group [get_clocks can_clk] -group [get_clocks clk]这里把CAN时钟和系统时钟设为异步关系实测在100MHz系统时钟20MHz CAN时钟下稳定运行。如果遇到CRC校验失败八成是这里没设对。最后来个调试小技巧在ILA里同时抓取cantx和canrx信号时建议把触发条件设在tx_en的上升沿这样能精准捕捉到报文发送瞬间的波形变化。遇到总线错误时重点看ACK槽位的电平状态——正常应该是发送节点输出隐性位接收节点回显显性位。完整工程已打包上传GitHub地址见评论区包含Vivado 2022.1工程文件和测试脚本。下期预告如何用这个CAN控制器实现Bootloader功能直接通过CAN总线更新FPGA固件。

更多文章