Today, I bring you the design of a CAN bus controller based on FPGA. Due to the lengthy content, it is divided into three parts. Today, I present the third part, followed by the next one, which covers the program simulation and testing, as well as a summary. Without further ado, let’s get started.
I will also provide hyperlinks to the first two parts here:
Design of CAN Bus Controller Based on FPGA (Part 1)
Design of CAN Bus Controller Based on FPGA (Part 2)
Introduction
The CAN bus (Controller Area Network) is a serial data communication protocol developed by the German company BOSCH in the early 1980s to facilitate data exchange among numerous control and testing instruments in modern vehicles. Currently, the CAN bus has been included in the ISO international standard, referred to as ISO11898. The CAN bus has become one of the mainstream technologies for industrial data communication.
As a digital serial communication technology, the CAN bus has unique technical advantages in reliability, real-time performance, and flexibility compared to other similar technologies. Its main features are as follows:
-
The CAN bus is a multi-master bus, allowing any node on the bus to actively send information to other nodes at any time without a master-slave distinction, thus enabling free communication among nodes. -
The CAN bus employs non-destructive bus arbitration technology. When multiple nodes send information to the bus simultaneously, nodes with lower priority will actively withdraw from transmission, while the highest priority node can continue transmitting data without being affected, thus greatly saving arbitration time during bus conflicts. Even under heavy network load, network paralysis does not occur. -
The communication medium for the CAN bus can be twisted pair, coaxial cable, or fiber optic, offering flexibility in selection. -
The communication rate of the CAN bus can reach 1Mbit/s (with a maximum communication distance of 40 meters), and the maximum communication distance can reach 10km (with a rate below 5kbit/s). -
Node information on the CAN bus is divided into different priority levels, meeting various real-time requirements, with high-priority data being transmitted within 134μs. -
The CAN bus can transmit data in point-to-point, one-to-many, and global broadcast modes through message filtering, without the need for dedicated scheduling. -
The CAN bus uses a short frame structure, resulting in short transmission times and low interference probability, providing excellent error detection capabilities. -
The CAN bus employs CRC checks and offers corresponding error handling functions, ensuring the reliability of data communication. -
Devices on the CAN bus can be placed in a sleep mode with no internal activity, effectively reducing system power consumption.
Nodes on the CAN bus have the ability to automatically shut down outputs in the event of severe errors, ensuring that operations of other nodes on the bus are not affected. The outstanding features, high reliability, and unique design of the CAN bus make it particularly suitable for interconnecting monitoring devices in industrial processes. Thus, it is increasingly gaining attention in the industry and is recognized as one of the most promising field buses. Additionally, the CAN bus protocol has been recognized by the International Organization for Standardization, with mature technology and commercially available control chips that are cost-effective, especially suitable for data communication among distributed measurement and control systems.
CAN bus interface cards can be inserted into any PC AT XT compatible machine, conveniently forming a distributed monitoring system. Therefore, implementing a CAN bus communication controller using FPGA has significant application value. This article will explain the implementation method of a CAN bus communication controller using FPGA through an example.
Summary of the third part: This part will introduce the program simulation and testing, as well as summary and related content.

4. Program Simulation and Testing
The simulation program for the CAN bus communication controller needs to simulate data transmission and reception.
Below is part of the code for the testing program:
// Connect can_top module can_top i_can_top( .cs_can_i(cs_can), .clk_i(clk), .rx_i(rx_and_tx), .tx_o(tx), .irq_on(irq), .clkout_o(clkout) );
// Generate 24 MHz clock initial begin clk=0; forever #21 clk = ~clk; end
// Initialize initial begin start_tb = 0; cs_can = 0; rx = 1; extended_mode = 0; tx_bypassed = 0; rst_i = 1'b0; ale_i = 1'b0; rd_i = 1'b0; wr_i = 1'b0; port_0_o = 8'h0; port_0_en = 0; port_free = 1; rst_i = 1; #200 rst_i = 0; #200 start_tb = 1; end
// Generate delayed tx signal (CAN transmitter delay) always begin wait (tx); repeat (4*BRP) @ (posedge clk); // 4 time quants delay #1 delayed_tx = tx; wait (~tx); repeat (4*BRP) @ (posedge clk); // 4 time quants delay #1 delayed_tx = tx; end assign rx_and_tx = rx & (delayed_tx | tx_bypassed); // When this signal is on, tx is not looped back to the rx. // Main program initial begin wait(start_tb);
// Set bus timing register write_register(8'd6, {`CAN_TIMING0_SJW, `CAN_TIMING0_BRP}); write_register(8'd7, {`CAN_TIMING1_SAM, `CAN_TIMING1_TSEG2, `CAN_TIMING1_TSEG1});
// Set clock division register extended_mode = 1'b0; write_register(8'd31, {extended_mode, 3'h0, 1'b0, 3'h0}); // Setting the normal mode (not extended)
// Set receive code and receive register write_register(8'd16, 8'ha6); // acceptance code 0 write_register(8'd17, 8'hb0); // acceptance code 1 write_register(8'd18, 8'h12); // acceptance code 2 write_register(8'd19, 8'h30); // acceptance code 3 write_register(8'd20, 8'h0); // acceptance mask 0 write_register(8'd21, 8'h0); // acceptance mask 1 write_register(8'd22, 8'h00); // acceptance mask 2 write_register(8'd23, 8'h00); // acceptance mask 3 write_register(8'd4, 8'he8); // acceptance code write_register(8'd5, 8'h0f); // acceptance mask #10; repeat (1000) @ (posedge clk); // Switch reset mode write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)}); repeat (BRP) @ (posedge clk); // After reset, set bus idle repeat (11) send_bit(1); test_full_fifo; // test currently switched on send_frame; // test currently switched off bus_off_test; // test currently switched off forced_bus_off; // test currently switched off send_frame_basic; // test currently switched off send_frame_extended; // test currently switched off self_reception_request; // test currently switched off manual_frame_basic; // test currently switched off manual_frame_ext; // test currently switched off $display("CAN Testbench finished !"); $stop; end
During the testing process, multiple tasks are used to verify the various functional modules of the program. The following program is used to verify the forced bus-off task:
// Forced bus-off task
task forced_bus_off; // Forcing bus-off by writing to tx_err_cnt register
begin
// Switch to reset mode
write_register(8'd0, {7'h0, `CAN_MODE_RESET});
// Set clock division register
write_register(8'd31, {1'b1, 7'h0}); // Setting the extended mode (not normal)
// Write data to register
write_register(8'd15, 255);
// Switch to reset mode
write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
#2500000;
// Switch to reset mode
write_register(8'd0, {7'h0, `CAN_MODE_RESET});
// Write data to register
write_register(8'd15, 245);
// Turn off reset mode
write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
#1000000;
end
endtask // forced_bus_off
The following program verifies how to send a basic format frame of data:
// Send a basic format frame
task manual_frame_basic;
begin
// Switch to reset mode write_register(8'd0, {7'h0, (`CAN_MODE_RESET)});
// Set register write_register(8'd4, 8'h28); // acceptance code write_register(8'd5, 8'hff); // acceptance mask repeat (100) @ (posedge clk);
// Switch to reset mode write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
// Set bus idle after module reset repeat (11) send_bit(1); write_register(8'd10, 8'h55); // Writing ID[10:3] = 0x55 write_register(8'd11, 8'h57); // Writing ID[2:0] = 0x2, rtr = 1, length = 7 write_register(8'd12, 8'h00); // data byte 1 write_register(8'd13, 8'h00); // data byte 2 write_register(8'd14, 8'h00); // data byte 3 write_register(8'd15, 8'h00); // data byte 4 write_register(8'd16, 8'h00); // data byte 5 write_register(8'd17, 8'h00); // data byte 6 write_register(8'd18, 8'h00); // data byte 7 write_register(8'd19, 8'h00); // data byte 8 tx_bypassed = 1; // When this signal is on, tx is not looped back to the rx. fork begin self_reception_request_command; end begin #2200; repeat (1) // Start sending data begin send_bit(0); // Frame start send_bit(0); // ID send_bit(1); // ID send_bit(0); // ID send_bit(1); // ID send_bit(0); // ID send_bit(1); // ID send_bit(0); // ID send_bit(1); // ID send_bit(0); // ID send_bit(1); // ID send_bit(0); // ID send_bit(1); // RTR send_bit(0); // IDE send_bit(0); // r0 send_bit(0); // DLC send_bit(1); // DLC send_bit(1); // DLC send_bit(1); // DLC send_bit(1); // CRC send_bit(1); // CRC send_bit(0); // CRC stuff send_bit(0); // CRC 6 send_bit(0); // CRC send_bit(0); // CRC send_bit(0); // CRC send_bit(1); // CRC stuff send_bit(0); // CRC 0 send_bit(0); // CRC send_bit(1); // CRC send_bit(0); // CRC send_bit(1); // CRC 5 send_bit(1); // CRC send_bit(0); // CRC send_bit(1); // CRC send_bit(1); // CRC b send_bit(1); // CRC DELIM send_bit(0); // ACK send_bit(1); // ACK DELIM send_bit(1); // EOF send_bit(1); // EOF send_bit(1); // EOF send_bit(1); // EOF send_bit(1); // EOF send_bit(1); // EOF send_bit(1); // EOF send_bit(1); // INTER send_bit(1); // INTER send_bit(1); // INTER end // repeat end join // Read data from receive buffer read_receive_buffer; release_rx_buffer_command; read_receive_buffer; release_rx_buffer_command; read_receive_buffer; #4000000; end
endtask // manual_frame_basic

5. Summary
This article explains how to implement a CAN bus communication controller using FPGA through an example. It first discusses relevant content about the CAN bus protocol and then introduces the main features of a commonly used CAN communication controller, the SJA1000. Next, it explains the main framework of the program and specific code. Finally, a test program is used to verify the implementation. This example provides readers with a practical case for implementing their own CAN bus communication controller.
This concludes the article. See you next time!
– -THE END- –