跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C算法

FPGA 实现 CAN 总线原理与 Verilog 代码详解

FPGA 通过硬件逻辑模拟 CAN 协议位时序、帧结构及仲裁机制。文章详解物理层差分信号特性、协议层标准数据帧格式,提供基于 50MHz 时钟的 Verilog 核心模块设计,包括位时序生成、CRC 校验、收发状态机及顶层整合。结合 TJA1050 收发器完成硬件连接与回环验证,确保通信可靠性与实时性。

孤勇者发布于 2026/3/23更新于 2026/4/308 浏览
FPGA 实现 CAN 总线原理与 Verilog 代码详解

CAN(Controller Area Network,控制器局域网)是一种差分信号、多主从、异步串行通信总线,核心特点是高可靠性、实时性、抗干扰能力强,广泛应用于汽车电子、工业控制、智能家居等领域。FPGA 实现 CAN 接口的核心是通过硬件逻辑模拟 CAN 协议的位时序、帧结构、仲裁机制、错误处理,再配合 CAN 收发器(如 TJA1050)实现物理层连接。以下从原理、核心模块设计、Verilog 代码实现、硬件验证四方面详细说明:

一、CAN 总线核心原理

1. 物理层特性
  • 总线电平:采用差分信号传输,分为两种状态:
    • 显性电平(Dominant):CAN_H 比 CAN_L 高约 2V(总线电平为 0,优先级高);
    • 隐性电平(Recessive):CAN_H 与 CAN_L 电压差为 0V(总线电平为 1,优先级低);
  • 总线拓扑:多节点挂在 CAN_H 和 CAN_L 总线上,总线两端需接 120Ω 终端电阻;
  • 收发器:FPGA 需通过 CAN 收发器(如 TJA1050)连接总线,FPGA 输出的逻辑电平(TX)转换为差分信号,总线差分信号转换为逻辑电平(RX)给 FPGA。
2. 协议层核心概念
(1)位时序

CAN 的位时间由多个时间量子(TQ)组成,标准位时序划分(以 500kHz 波特率为例):

  • 同步段(SYNC_SEG):1TQ,用于节点同步,检测总线电平跳变;
  • 传播段(PROP_SEG):1~8TQ,补偿总线传输延迟;
  • 相位缓冲段 1(PHASE_SEG1):1~8TQ,用于相位调整;
  • 相位缓冲段 2(PHASE_SEG2):1~8TQ,用于相位调整;
  • 重同步跳转宽度(SJW):1~4TQ,允许节点在同步时调整相位的最大范围;
  • 总位时间 = SYNC_SEG + PROP_SEG + PHASE_SEG1 + PHASE_SEG2(通常为 8~25TQ)。
(2)帧结构(标准数据帧)

CAN 帧分为数据帧、远程帧、错误帧、过载帧,最常用的是标准数据帧,结构如下:

字段长度(位)描述
帧起始(SOF)1显性电平(0),标志帧开始;
仲裁场11+111 位标准 ID(优先级:ID 越小优先级越高)+ RTR 位(0 = 数据帧,1 = 远程帧);
控制场6IDE 位(0 = 标准帧,1 = 扩展帧)+ R0 位(保留)+ 4 位 DLC(数据长度 0~8);
数据场0~64数据长度由 DLC 决定(1 字节 = 8 位);
CRC 场15+115 位 CRC 校验码 + 1 位 CRC 界定符(隐性电平);
ACK 场21 位 ACK 位(接收方拉低为应答)+ 1 位 ACK 界定符(隐性电平);
帧结束(EOF)77 位隐性电平,标志帧结束。
(3)关键机制
  • 仲裁机制:多节点同时发送时,通过 ID 竞争总线,ID 越小优先级越高,发送显性电平的节点获胜,其他节点转为接收;
  • 位填充:为保证同步,连续 5 个相同电平后插入 1 个相反电平(接收时需解除填充);
  • 错误处理:节点检测到错误(位错误、填充错误、CRC 错误等)时,发送错误帧(6 个显性电平),通知其他节点;
  • 应答机制:接收方正确接收数据后,在 ACK 位拉低总线(显性)应答。

二、FPGA 实现 CAN 的核心模块

FPGA 实现 CAN 接口需拆解为物理层接口、位时序模块、发送模块、接收模块、错误处理模块、控制模块,再通过顶层模块整合:

  1. 物理层接口:连接 CAN 收发器(TJA1050),处理 TX/RX 信号;
  2. 位时序模块:生成 CAN 位时间的 TQ 时钟,实现位同步和相位调整;
  3. 发送模块:构建 CAN 帧(标准数据帧),实现位填充、CRC 计算、仲裁逻辑;
  4. 接收模块:解析 CAN 帧,实现位同步、位填充解除、CRC 校验、应答检测;
  5. 错误处理模块:检测总线错误,发送错误帧,管理节点错误状态;
  6. 控制模块:协调各模块工作,提供外部配置接口(如波特率、ID、数据长度等)。

三、Verilog 代码实现(以 50MHz 时钟、500kHz 波特率为例)

1. 全局参数定义
// CAN 参数配置
parameter CLK_FREQ = 50_000_000; // 系统时钟频率(50MHz)
parameter CAN_BAUD = 500_000;    // CAN 目标波特率(500kHz)
parameter TQ_COUNT = 10;         // 每位包含的 TQ 数量(10TQ/位,2μs/位)
parameter SYNC_SEG = 1;          // 同步段(1TQ)
parameter PROP_SEG = 3;          // 传播段(3TQ)
parameter PHASE_SEG1 = 3;        // 相位缓冲段 1(3TQ)
parameter PHASE_SEG2 = 3;        // 相位缓冲段 2(3TQ)
parameter SJW = 2;               // 重同步跳转宽度(2TQ)
// CAN 帧字段参数
parameter STD_ID_LEN = 11;       // 标准 ID 长度(11 位)
parameter DLC_LEN = 4;           // DLC 长度(4 位)
parameter DATA_MAX_LEN = 8;      // 最大数据长度(8 字节)
parameter CRC_LEN = 15;          // CRC 长度(15 位)
// 状态定义
typedef enum {IDLE, SYNC, ARBITRATION, CONTROL, DATA, CRC, ACK, EOF} can_state_t;
2. 位时序模块(CAN Bit Timing Generator)

功能:生成 TQ 时钟(位时间的最小单位),实现位同步和相位调整。

module can_bit_timing(
    input logic clk,              // 系统时钟(50MHz)
    input logic rst_n,            // 复位信号(低电平有效)
    input logic can_rx,           // CAN 接收信号(来自收发器)
    output logic tq_clk,          // TQ 时钟
    output logic sync_seg,        // 同步段标志
    output logic prop_seg,        // 传播段标志
    output logic phase_seg1,      // 相位缓冲段 1 标志
    output logic phase_seg2,      // 相位缓冲段 2 标志
    output logic bit_start,       // 位开始标志
    output logic bit_end          // 位结束标志
);
    parameter DIVISOR = CLK_FREQ / (CAN_BAUD * TQ_COUNT); // 分频系数=10
    logic [3:0] tq_cnt = 4'd0;  // TQ 计数器
    logic [3:0] bit_cnt = 4'd0; // 位计数器
    logic sync_detected = 1'b0; // 同步检测标志
    
    // 生成 TQ 时钟(5MHz)
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            tq_cnt <= 4'd0;
            tq_clk <= 1'b0;
        end else begin
            if (tq_cnt == DIVISOR/2 - 1) begin
                tq_clk <= ~tq_clk;
                tq_cnt <= tq_cnt + 1'b1;
            end else if (tq_cnt == DIVISOR - 1) begin
                tq_clk <= ~tq_clk;
                tq_cnt <= 4'd0;
            end else begin
                tq_cnt <= tq_cnt + 1'b1;
            end
        end
    end
    
    // 位时序分段
    always_ff @(posedge tq_clk or negedge rst_n) begin
        if (!rst_n) begin
            bit_cnt <= 4'd0;
            sync_seg <= 1'b0; prop_seg <= 1'b0; phase_seg1 <= 1'b0; phase_seg2 <= 1'b0;
            bit_start <= 1'b0; bit_end <= 1'b0; sync_detected <= 1'b0;
        end else begin
            // 同步检测(检测 CAN_RX 电平跳变)
            if (can_rx != can_rx_prev) begin
                sync_detected <= 1'b1;
                bit_cnt <= 4'd0;
            end
            // 位计数器递增
            if (bit_cnt == TQ_COUNT - 1) begin
                bit_cnt <= 4'd0;
                bit_end <= 1'b1;
            end else begin
                bit_cnt <= bit_cnt + 1'b1;
                bit_end <= 1'b0;
            end
            // 时序分段标志
            sync_seg <= (bit_cnt < SYNC_SEG) ? 1'b1 : 1'b0;
            prop_seg <= (bit_cnt >= SYNC_SEG && bit_cnt < SYNC_SEG + PROP_SEG) ? 1'b1 : 1'b0;
            phase_seg1 <= (bit_cnt >= SYNC_SEG + PROP_SEG && bit_cnt < SYNC_SEG + PROP_SEG + PHASE_SEG1) ? 1'b1 : 1'b0;
            phase_seg2 <= (bit_cnt >= SYNC_SEG + PROP_SEG + PHASE_SEG1 && bit_cnt < TQ_COUNT) ? 1'b1 : 1'b0;
            // 位开始标志
            bit_start <= (bit_cnt == 4'd0) ? 1'b1 : 1'b0;
            // 同步检测标志清零
            if (sync_seg) begin sync_detected <= 1'b0; end
        end
    end
    
    logic can_rx_prev;
    always_ff @(posedge tq_clk or negedge rst_n) begin
        if (!rst_n) begin can_rx_prev <= 1'b1; end
        else begin can_rx_prev <= can_rx; end
    end
endmodule
3. CRC 计算模块(CAN CRC Generator)

功能:计算 CAN 帧(从 SOF 到数据场)的 15 位 CRC 校验码。

module can_crc(
    input logic clk,
    input logic rst_n,
    input logic crc_en,
    input logic data_bit,
    output logic [CRC_LEN-1:0] crc_out,
    output logic crc_done
);
    logic [CRC_LEN:0] crc_reg = {CRC_LEN+1{1'b1}};
    logic [3:0] bit_cnt = 4'd0;
    logic total_bits;
    
    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            crc_reg <= {CRC_LEN+1{1'b1}};
            bit_cnt <= 4'd0;
            crc_done <= 1'b0;
        end else if (crc_en) begin
            // CAN CRC-15 多项式逻辑
            crc_reg[0] <= data_bit ^ crc_reg[CRC_LEN];
            crc_reg[1] <= crc_reg[0];
            crc_reg[2] <= crc_reg[1];
            crc_reg[3] <= crc_reg[2] ^ data_bit ^ crc_reg[CRC_LEN];
            crc_reg[4] <= crc_reg[3] ^ data_bit ^ crc_reg[CRC_LEN];
            crc_reg[5] <= crc_reg[4];
            crc_reg[6] <= crc_reg[5];
            crc_reg[7] <= crc_reg[6] ^ data_bit ^ crc_reg[CRC_LEN];
            crc_reg[8] <= crc_reg[7] ^ data_bit ^ crc_reg[CRC_LEN];
            crc_reg[9] <= crc_reg[8];
            crc_reg[10] <= crc_reg[9] ^ data_bit ^ crc_reg[CRC_LEN];
            crc_reg[11] <= crc_reg[10];
            crc_reg[12] <= crc_reg[11];
            crc_reg[13] <= crc_reg[12];
            crc_reg[14] <= crc_reg[13] ^ data_bit ^ crc_reg[CRC_LEN];
            crc_reg[15] <= crc_reg[14] ^ data_bit ^ crc_reg[CRC_LEN];
            
            if (bit_cnt == total_bits - 1) begin
                crc_done <= 1'b1;
                bit_cnt <= 4'd0;
            end else begin
                bit_cnt <= bit_cnt + 1'b1;
                crc_done <= 1'b0;
            end
        end else begin
            crc_done <= 1'b0;
        end
    end
    
    always_comb begin
        total_bits = 1 + STD_ID_LEN + 1 + 1 + 1 + DLC_LEN + (8 * dlc);
    end
    input logic [DLC_LEN-1:0] dlc;
endmodule
4. 发送模块(CAN Transmitter)

功能:构建标准数据帧,实现位填充、CRC 计算、仲裁逻辑。

module can_transmitter(
    input logic clk,
    input logic rst_n,
    input logic tq_clk,
    input logic sync_seg,
    input logic phase_seg1,
    input logic phase_seg2,
    input logic bit_end,
    input logic can_rx,
    input logic tx_en,
    input logic [STD_ID_LEN-1:0] std_id,
    input logic rtr,
    input logic [DLC_LEN-1:0] dlc,
    input logic [DATA_MAX_LEN*8-1:0] data,
    output logic can_tx,
    output logic tx_done,
    output logic tx_error
);
    can_state_t state = IDLE;
    logic [3:0] bit_cnt = 4'd0;
    logic [7:0] data_byte = 8'd0;
    logic [CRC_LEN-1:0] crc_val;
    logic crc_en;
    logic crc_done;
    logic [5:0] stuff_cnt = 6'd0;
    logic stuff_bit = 1'b0;
    
    // 实例化 CRC 模块
    can_crc u_crc(.clk(clk), .rst_n(rst_n), .crc_en(crc_en), .data_bit(data_bit), .crc_out(crc_val), .crc_done(crc_done), .dlc(dlc));
    
    // 状态机控制
    always_ff @(posedge tq_clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= IDLE; bit_cnt <= 4'd0; data_byte <= 8'd0; can_tx <= 1'b1;
            tx_done <= 1'b0; tx_error <= 1'b0; stuff_cnt <= 6'd0; stuff_bit <= 1'b0; crc_en <= 1'b0;
        end else begin
            case (state)
                IDLE: begin
                    tx_done <= 1'b0; tx_error <= 1'b0; stuff_cnt <= 6'd0;
                    if (tx_en) begin
                        state <= SYNC; bit_cnt <= 4'd0; can_tx <= 1'b0;
                        crc_en <= 1'b1; data_bit <= 1'b0;
                    end else begin can_tx <= 1'b1; end
                end
                SYNC: begin
                    if (bit_end) begin
                        state <= ARBITRATION; bit_cnt <= 4'd0;
                        can_tx <= std_id[STD_ID_LEN-1 - bit_cnt]; data_bit <= std_id[STD_ID_LEN-1 - bit_cnt];
                        if (can_rx != can_tx) begin state <= IDLE; tx_error <= 1'b1; end
                    end else begin
                        if (can_tx == stuff_bit_prev) begin
                            stuff_cnt <= stuff_cnt + 1'b1;
                            if (stuff_cnt == 5'd5) begin
                                can_tx <= ~can_tx; stuff_cnt <= 6'd0; stuff_bit <= 1'b1; crc_en <= 1'b0;
                            end
                        end else begin
                            stuff_cnt <= 6'd0; stuff_bit <= 1'b0; crc_en <= 1'b1;
                        end
                    end
                end
                // 后续状态(ARBITRATION、CONTROL、DATA、CRC、ACK、EOF)按帧结构发送对应字段
                // 此处省略详细状态跳转,核心逻辑:按帧字段顺序发送,位填充,仲裁检测,CRC 计算
                EOF: begin
                    if (bit_end) begin state <= IDLE; tx_done <= 1'b1; end
                end
                default: state <= IDLE;
            endcase
        end
    end
    
    logic stuff_bit_prev;
    always_ff @(posedge tq_clk or negedge rst_n) begin
        if (!rst_n) begin stuff_bit_prev <= 1'b1; end
        else begin stuff_bit_prev <= can_tx; end
    end
    
    logic data_bit;
    always_comb begin
        case (state)
            SYNC: data_bit <= 1'b0;
            ARBITRATION: data_bit <= std_id[STD_ID_LEN-1 - bit_cnt];
            CONTROL: data_bit <= (bit_cnt == 0) ? 1'b0 : (bit_cnt == 1) ? 1'b0 : (bit_cnt >= 2 && bit_cnt < 2+DLC_LEN) ? dlc[DLC_LEN-1 - (bit_cnt-2)] : 1'b0;
            DATA: data_bit <= data_byte[7 - (bit_cnt % 8)];
            default: data_bit <= 1'b0;
        endcase
    end
endmodule
5. 接收模块(CAN Receiver)

功能:解析 CAN 帧,实现位同步、位填充解除、CRC 校验、应答检测。

module can_receiver(
    input logic clk,
    input logic rst_n,
    input logic tq_clk,
    input logic sync_seg,
    input logic phase_seg1,
    input logic phase_seg2,
    input logic bit_end,
    input logic can_rx,
    output logic rx_done,
    output logic rx_error,
    output logic [STD_ID_LEN-1:0] rx_std_id,
    output logic rx_rtr,
    output logic [DLC_LEN-1:0] rx_dlc,
    output logic [DATA_MAX_LEN*8-1:0] rx_data
);
    can_state_t state = IDLE;
    logic [3:0] bit_cnt = 4'd0;
    logic [7:0] data_byte = 8'd0;
    logic [CRC_LEN-1:0] crc_val;
    logic [CRC_LEN-1:0] calc_crc;
    logic crc_en;
    logic crc_done;
    logic [5:0] stuff_cnt = 6'd0;
    logic stuff_bit = 1'b0;
    
    // 实例化 CRC 模块
    can_crc u_crc(.clk(clk), .rst_n(rst_n), .crc_en(crc_en), .data_bit(can_rx), .crc_out(calc_crc), .crc_done(crc_done), .dlc(rx_dlc));
    
    // 状态机控制
    always_ff @(posedge tq_clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= IDLE; bit_cnt <= 4'd0; data_byte <= 8'd0; rx_done <= 1'b0; rx_error <= 1'b0;
            rx_std_id <= {STD_ID_LEN{1'b0}}; rx_rtr <= 1'b0; rx_dlc <= {DLC_LEN{1'b0}}; rx_data <= {DATA_MAX_LEN*8{1'b0}};
            stuff_cnt <= 6'd0; stuff_bit <= 1'b0; crc_en <= 1'b0;
        end else begin
            case (state)
                IDLE: begin
                    rx_done <= 1'b0; rx_error <= 1'b0; stuff_cnt <= 6'd0;
                    if (can_rx == 1'b0 && sync_seg) begin
                        state <= SYNC; bit_cnt <= 4'd0; crc_en <= 1'b1;
                    end
                end
                SYNC: begin
                    if (bit_end) begin state <= ARBITRATION; bit_cnt <= 4'd0; end
                    if (can_rx == stuff_bit_prev) begin
                        stuff_cnt <= stuff_cnt + 1'b1;
                        if (stuff_cnt == 5'd5) begin stuff_bit <= 1'b1; stuff_cnt <= 6'd0; end
                    end else begin stuff_cnt <= 6'd0; stuff_bit <= 1'b0; end
                end
                ARBITRATION: begin
                    if (bit_end && !stuff_bit) begin
                        if (bit_cnt == STD_ID_LEN - 1) begin
                            rx_std_id[STD_ID_LEN-1 - bit_cnt] <= can_rx; state <= CONTROL; bit_cnt <= 4'd0;
                        end else begin
                            rx_std_id[STD_ID_LEN-1 - bit_cnt] <= can_rx; bit_cnt <= bit_cnt + 1'b1;
                        end
                    end else if (stuff_bit) begin stuff_bit <= 1'b0; end
                    crc_en <= !stuff_bit;
                end
                // 后续状态(CONTROL、DATA、CRC、ACK、EOF)类似,按帧结构接收对应字段,位填充解除,CRC 校验
                EOF: begin
                    if (bit_end) begin
                        state <= IDLE; rx_done <= 1'b1;
                        if (calc_crc != crc_val) begin rx_error <= 1'b1; end
                    end
                end
                default: state <= IDLE;
            endcase
        end
    end
    
    logic stuff_bit_prev;
    always_ff @(posedge tq_clk or negedge rst_n) begin
        if (!rst_n) begin stuff_bit_prev <= 1'b1; end
        else begin stuff_bit_prev <= can_rx; end
    end
endmodule
6. 顶层模块(CAN Top Module)

功能:整合位时序、发送、接收模块,提供与 CAN 收发器的物理接口和外部配置接口。

module can_top(
    input logic clk,
    input logic rst_n,
    input logic tx_en,
    input logic [STD_ID_LEN-1:0] std_id,
    input logic rtr,
    input logic [DLC_LEN-1:0] dlc,
    input logic [DATA_MAX_LEN*8-1:0] data,
    output logic can_tx,
    input logic can_rx,
    output logic tx_done,
    output logic tx_error,
    output logic rx_done,
    output logic rx_error,
    output logic [STD_ID_LEN-1:0] rx_std_id,
    output logic rx_rtr,
    output logic [DLC_LEN-1:0] rx_dlc,
    output logic [DATA_MAX_LEN*8-1:0] rx_data
);
    logic tq_clk; logic sync_seg; logic prop_seg; logic phase_seg1; logic phase_seg2;
    logic bit_start; logic bit_end;
    
    can_bit_timing u_bit_timing(
        .clk(clk), .rst_n(rst_n), .can_rx(can_rx), .tq_clk(tq_clk),
        .sync_seg(sync_seg), .prop_seg(prop_seg), .phase_seg1(phase_seg1),
        .phase_seg2(phase_seg2), .bit_start(bit_start), .bit_end(bit_end)
    );
    
    can_transmitter u_transmitter(
        .clk(clk), .rst_n(rst_n), .tq_clk(tq_clk), .sync_seg(sync_seg),
        .phase_seg1(phase_seg1), .phase_seg2(phase_seg2), .bit_end(bit_end),
        .can_rx(can_rx), .tx_en(tx_en), .std_id(std_id), .rtr(rtr),
        .dlc(dlc), .data(data), .can_tx(can_tx), .tx_done(tx_done), .tx_error(tx_error)
    );
    
    can_receiver u_receiver(
        .clk(clk), .rst_n(rst_n), .tq_clk(tq_clk), .sync_seg(sync_seg),
        .phase_seg1(phase_seg1), .phase_seg2(phase_seg2), .bit_end(bit_end),
        .can_rx(can_rx), .rx_done(rx_done), .rx_error(rx_error),
        .rx_std_id(rx_std_id), .rx_rtr(rx_rtr), .rx_dlc(rx_dlc), .rx_data(rx_data)
    );
endmodule

四、硬件验证

1. 硬件连接
  • FPGA ↔ CAN 收发器(TJA1050):
    • FPGA 的 can_tx → TJA1050 的 TXD;
    • FPGA 的 can_rx → TJA1050 的 RXD;
    • FPGA 的 VCC(3.3V)→ TJA1050 的 VCC;
    • FPGA 的 GND → TJA1050 的 GND;
  • CAN 收发器 ↔ CAN 总线:
    • TJA1050 的 CAN_H → CAN 总线 CAN_H;
    • TJA1050 的 CAN_L → CAN 总线 CAN_L;
    • CAN 总线两端接 120Ω 终端电阻;
  • 其他:FPGA 需提供 50MHz 时钟和复位信号(可通过按键或外部电路实现)。
2. 验证步骤
  1. 参数配置:通过 FPGA 的配置接口(如 JTAG)设置发送参数(ID=0x001,DLC=2,数据 = 0x1234,波特率 = 500kHz);
  2. 发送数据:触发 tx_en 信号,FPGA 生成 CAN 标准数据帧并发送到总线;
  3. 接收验证:
    • 若总线上有其他 CAN 节点(如 CANoe 仿真节点、另一块 FPGA 开发板),可接收并解析该帧,验证 ID、数据、DLC 是否正确;
    • 若只有一块 FPGA,可将 can_tx 直接连接到 can_rx(回环测试),FPGA 接收自己发送的数据,通过 rx_done 和 rx_data 确认接收正确;
  4. 错误测试:故意修改发送数据,验证 rx_error 是否能检测到 CRC 错误。

五、关键注意事项与扩展功能

1. 注意事项
  • 时序精确性:CAN 位时序对传输可靠性至关重要,需严格按照协议规范设计 TQ 时钟和位段划分,避免非整数分频导致的时序误差;
  • 位填充与解除:发送时需正确插入填充位,接收时需准确解除填充,否则会导致帧解析错误;
  • 仲裁机制:多节点通信时,需确保仲裁逻辑正确,避免总线冲突;
  • 收发器匹配:CAN 收发器的电平需与 FPGA 的 IO 电平匹配(通常为 3.3V),否则需添加电平转换电路;
  • 终端电阻:CAN 总线必须接终端电阻,否则信号反射会导致通信失败。
2. 扩展功能
  • 扩展帧支持:在帧结构中添加 29 位扩展 ID,修改仲裁场和控制场的处理逻辑;
  • 多帧发送 / 接收:添加 FIFO 缓冲区,支持连续多帧数据的收发,避免数据丢失;
  • ID 过滤:接收模块添加 ID 过滤逻辑,只接收特定 ID 的帧,减少无效数据处理;
  • 错误管理:完善错误处理模块,支持错误计数器管理和总线关闭恢复;
  • 波特率自适应:设计波特率检测逻辑,支持自动识别总线波特率。

六、总结

FPGA 实现 CAN 接口的核心是严格遵循 CAN 协议的时序和帧结构,通过硬件逻辑实现位时序生成、帧构建与解析、仲裁、错误处理等功能。相比单片机的 CAN 控制器,FPGA 的硬件实现具有实时性强、可定制性高、并行处理能力强的优势,适用于对通信速率和可靠性要求较高的场景。实际应用中,可根据需求扩展扩展帧、ID 过滤、多帧收发等功能,适配复杂的 CAN 总线系统。

目录

  1. 一、CAN 总线核心原理
  2. 1. 物理层特性
  3. 2. 协议层核心概念
  4. (1)位时序
  5. (2)帧结构(标准数据帧)
  6. (3)关键机制
  7. 二、FPGA 实现 CAN 的核心模块
  8. 三、Verilog 代码实现(以 50MHz 时钟、500kHz 波特率为例)
  9. 1. 全局参数定义
  10. 2. 位时序模块(CAN Bit Timing Generator)
  11. 3. CRC 计算模块(CAN CRC Generator)
  12. 4. 发送模块(CAN Transmitter)
  13. 5. 接收模块(CAN Receiver)
  14. 6. 顶层模块(CAN Top Module)
  15. 四、硬件验证
  16. 1. 硬件连接
  17. 2. 验证步骤
  18. 五、关键注意事项与扩展功能
  19. 1. 注意事项
  20. 2. 扩展功能
  21. 六、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Linux 网络编程实战:TCP/IP 协议栈与 UDP 通信
  • Python try-except-else 异常处理详解
  • Python 换行符与代码续行方法详解
  • 金仓 KingbaseES 融合架构实践:从多库并存到一库多能
  • CVE-2026-21962 Oracle WebLogic 代理插件 RCE 漏洞深度解析与防护
  • Flask 框架从入门到实战完整指南
  • 9 篇大模型前沿论文精选
  • 渗透测试概述与标准实施流程
  • SkyWalking 多语言探针现状:.NET、C++ 与 Lua 实践指南
  • ZeroClaw 轻量级 AI Agent 运行时安装与使用指南
  • 2025 至 2026 年前端发展趋势展望
  • AI 提示词工程:原理、策略与实战指南
  • 绿联 NAS 配置 WebDAV 公网访问并使用 RaiDrive 挂载
  • Qwen-Image-2512 V2 模型 ComfyUI 与 WebUI 整合包使用指南
  • Python 合并两个字典的 8 种常用方法
  • C++ 四种类型转换详解:static_cast、reinterpret_cast、const_cast 与 dynamic_cast
  • 大模型实战技术指南:集群、训练、微调与推理加速
  • Docker 本地部署 Dify 开源 LLM 应用平台教程
  • AI 产品经理就业方向与转行指南:核心技能与薪资分析
  • C/C++ 操作 MySQL 核心 API 详解

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online