Implementing CAN Bus Functionality on ZYNQ PL Using CAN IP
Clock Configuration for PL-CAN
The CAN peripheral clock originates from FCLK-CLK0 in the ZYNQ system. After completing the Vivado block design, this clock value should be verified in the configuration table, which typically shows FCLK-CLK0 at 50 MHz. This value serves as the reference for CAN peripheral programming.
CAN CLK External Clock Input
The CAN IP core requires an external clock input on the CAN CLK pins. Failing to constrain these pins results in bitstream generation errors. The PG096 CAN IP documentation specifies that both CAN IP instances require this clock input when using the internal AXI bus clock. This requirement is often overlooked during initial system configuration.
The FCLK-CLK0 signal serves as the primary clock source for PL logic. When configuring additional clock domains for CAN IP, FCLK-CLK1 can be generated and routed directly to the CAN-CLK input without requiring a separate Clock Wizard IP. However, this clock routing must be properly constrained and connected in the wrapper file to avoid synchronization issues.
Mode Configuration and State Machine Issues
Entering Configuration Mode
After device reset, the CAN peripheral should immediately enter Configuration Mode. When the mode check fails, the GetMode function returns a status indicating the current operating mode. The following example demonstrates proper initialization with mode verification:
#define XCAN_MODE_CONFIG 0x00000001
#define XCAN_MODE_NORMAL 0x00000002
#define XCAN_MODE_LOOPBACK 0x00000004
#define XCAN_MODE_SLEEP 0x00000008
int can_initialize(XCan *InstancePtr)
{
u32 mode_status;
XCan_Reset(InstancePtr);
XCan_EnterMode(InstancePtr, XCAN_MODE_CONFIG);
mode_status = XCan_GetMode(InstancePtr);
if (mode_status != XCAN_MODE_CONFIG) {
xil_printf("Mode transition failed, current: %d\r\n", mode_status);
return XST_FAILURE;
}
return XST_SUCCESS;
}
The PL-CAN IP exhibits different reset behavior compared to PS-CAN. After reset, the device enters Loopback Mode rather than Configuration Mode. This behavior requires explicit mode transition commands before configuring baud rate and other parameters.
Status Register Analysis
The Status Register (SR) provides insight into the current operating mode and peripheral state. When all status bits read as zero, the CAN peripheral has likely failed to receive a valid clock signal, causing the core to remain in an abnormal state. The GetMode function implements a priority-based mode detection:
u8 XCan_GetMode(XCan *InstancePtr)
{
u32 reg_value;
reg_value = XCan_GetStatus(InstancePtr);
if (reg_value & XCAN_SR_CONFIG_MASK) {
return XCAN_MODE_CONFIG;
} else if (reg_value & XCAN_SR_SLEEP_MASK) {
return XCAN_MODE_SLEEP;
} else if (reg_value & XCAN_SR_NORMAL_MASK) {
return XCAN_MODE_NORMAL;
} else {
return XCAN_MODE_LOOPBACK;
}
}
Pin Constraint Considerations
ZYNQ device pins have specific capabilities, and not all pins can be arbitrarily assigned to CAN functions. When creating pin constraints, special function pins, bank locations, and memory group configurations must be verified for CAN compatibility.
Verified Pin Assignments for XC7Z020
The following pin assignments have been verified for PL-CAN functionality:
# PL-CAN Channel 0
set_property PACKAGE_PIN M19 [get_ports {plcan0_rx}]
set_property IOSTANDARD LVCMOS33 [get_ports {plcan0_rx}]
set_property PACKAGE_PIN M20 [get_ports {plcan0_tx}]
set_property IOSTANDARD LVCMOS33 [get_ports {plcan0_tx}]
# PL-CAN Channel 1
set_property PACKAGE_PIN H15 [get_ports {plcan1_rx}]
set_property IOSTANDARD LVCMOS33 [get_ports {plcan1_rx}]
set_property PACKAGE_PIN F16 [get_ports {plcan1_tx}]
set_property IOSTANDARD LVCMOS33 [get_ports {plcan1_tx}]
Interface override warnings in the synthesis report often indicate improper signal connections at the wrapper level. These warnings require direct modification of the RTL wrapper file to establish correct signal routing between the ZYNQ processing system and the CAN IP core.
Wrapper File Modifications for Clock Routing
When the block design properly exports the CAN interface clock signal but synchronization failures occur, manual wrapper file modification becomes necessary. The following example shows the correct signal assignment method:
module zynq_system_wrapper (
output wire CAN_INTERFACE_0_clk,
input wire FCLK_CLK1_0,
// ... other signals
);
assign CAN_INTERFACE_0_clk = FCLK_CLK1_0;
can_ip_instance can_ip_inst (
.CAN_INTERFACE_0_clk(CAN_INTERFACE_0_clk),
.CAN_INTERFACE_0_rx(CAN_INTERFACE_0_rx),
.CAN_INTERFACE_0_tx(CAN_INTERFACE_0_tx),
// ... other connections
);
endmodule
Direct module port connection (bypassing the intermediate wire) ensures the clock signal reaches the CAN IP input without potential synchronization issues caused by signal overriding in the hierarchy.
PS-CAN Baseline Configuration
When implementing PL-CAN functionality, establishing a working PS-CAN configuration provides a reference baseline. The following demonstrates CAN frame transmission with proper mode transitions:
int can_send_frame(XCanPs *CanInstance, u32 frame_id, u8 *data, u8 length)
{
u32 tx_buffer[3];
u8 *data_ptr;
u32 fifo_status;
int index;
XCanPs_EnterMode(CanInstance, XCANPS_MODE_CONFIG);
XCanPs_SetBaudRatePrescaler(CanInstance, 3);
XCanPs_SetBitTiming(CanInstance, 3, 2, 15);
XCanPs_EnterMode(CanInstance, XCANPS_MODE_NORMAL);
while (XCanPs_GetMode(CanInstance) != XCANPS_MODE_NORMAL) {
;
}
tx_buffer[0] = XCanPs_CreateIdValue(frame_id, 0, 0, 0, 0);
tx_buffer[1] = XCanPs_CreateDlcValue(length);
data_ptr = (u8 *)&tx_buffer[2];
for (index = 0; index < length; index++) {
*data_ptr++ = data[index];
}
while (XCanPs_IsTxFifoFull(CanInstance) == TRUE) {
;
}
return XCanPs_Send(CanInstance, tx_buffer);
}
Vivado and SDK Synchronization Issues
The Vivado to SDK workflow requires explicit synchronization at multiple stages. When hardware parameters are modified in the block design, the following verification steps ensure proper propagation:
- After modifying block design, regenerate output products
- Update the HDL wrapper file
- Run synthesis before generating output products
- Verify the HDF file and HTML documentation reflect the changes
- In SDK, refresh the hardware description before rebuilding BSP
Wrapper file updates sometimes fail to propagate correctly. The "interface pin is being overridden" warning indicates signal connection problems that prevent proper CAN clock routing. These issues manifest as timing violations in the implementation results, specifically showing WNS (Worst Negative Slack) and WHS (Worst Hold Slack) values outside acceptable ranges.
Platform Version Considerasions
Different Vivado versions exhibit varying synchronization behaviors. Version 2018 shows different clock configuration options in the ZYNQ configuration GUI. The Advanced Clocking page must be used for precise clock adjustments, and synchronization between the GUI display and actual HDF file contents requires explicit verification. When encountering persistent issues, creating a new project with current specifications often resolves underlying platform-specific problems.
Practical Debugging Approach
When CAN peripheral initialization fails despite correct code and configuration, a systematic debugging approach helps isolate the root cause:
- Verify clock signals: Use ILA (Integrated Logic Analyzer) to confirm clock activity on the CAN-CLK input
- Check Status Register values: Monitor the SR register for proper mode indication
- Review pin constraints: Confirm selected pins support CAN functionality in their configured IOSTANDARD
- Test PS-CAN first: Establish a working CAN configuration on the processor side before tackling PL-CAN
- Isolate subsystem: Comment out other PL peripherals to eliminate resource conflicts
Timing Constraints and Resource Management
When adding ILA and Clock Wizard IP to the design for debugging purposes, timing constraint violations may occur. These violasions (WNS, TNS, WHS, THS values outside acceptable ranges) indicate the implementation tools cannot meet timing requirements with the current configuration. Solutions include:
- Reducing design complexity by removing debugging IP after clock verification
- Modifying chip speed grade settings
- Setting false paths for non-critical signals
- Simplifying the block design to minimum required components
The timing analysis methodology for these issues is documented in Xilinx UG906 (Design Analysis and Closure Techniques).