Table of Contents
This page explains how to edit the FPGA firmware of the B-Board PRO (equivalently to the B-Box RCP). Imperix offers the possibility to customize that FPGA firmware by instantiating the imperix firmware IP in Xilinx Vivado and editing programmable logic around it. To that end, the provided template provides access to a pre-written framework, designated as the sandbox.
The sandbox enable the user to:
- Exchange data between the application control code running in the CPU (PS) and the logic in the FPGA (PL);
- Drive the PWM output chain, comprised of a dead-time generation system and the hardware protection mechanisms;
- Retrieve ADC conversion results as soon as they are available, directly from within the FPGA;
- Have direct access to physical I/Os pins such as USR, GPI and GPO pins.
C++ drivers and graphical interface blocks (Simulink and PLECS blocksets) are provided in order to exchange data with the FPGA and configure the PWM outputs.
- A custom SPI communication interface for an A/D converter is presented in TN130.
- FPGA-based hysteresis current control is presented in TN120. The same application is also addressed in TN121, which relies on automated HDL code generation using Matlab HDL Coder.
- Automated code generation using Xilinx Vivado HLS is addressed in TN133. This note uses the Direct Torque Control (DTC) of a synchronous motor as the application example.
Information on how to set up the toolchain for the FPGA programming is available in PN120.
The B-Board is based on a Xilinx Zynq XC7Z030 System-on-Chip which consists of a Processing System area (PS) with two CPU cores and a Programmable Logic (PL) area.
- CPU0: Running on Linux, the first core is responsible for loading the application code, supervising the system execution and managing the data logging.
- CPU1: Running on BBOS (lightweight secured proprietary operating system), the second core executes the application-level control code developed by the user.
- FPGA: The PL contains all the application-specific peripherals.
The fixed part of the FPGA firmware containing the pre-implemented peripherals is packaged in the imperix firmware IP.
The step-by-step guidance to instantiate this IP in a Vivado project, generate and load the bitstream into the B-Board is available in PN120.
The imperix firmware IP is designed such that it provides interfaces for implementing special user HDL logic in the so-called sandbox. All interfaces of the firmware IP are accessible and may read or substituted with respect to physical (chip) I/Os
The content of the imperix firmware IP is obfuscated and cannot be either read or edited.
IP port descriptions
This section describes the ports of the imperix firmware IP.
Digital I/Os drivers
These ports drive the physical digital I/Os of the B-Board. The description of the peripherals driving these ports and the physical location of their I/Os are available in the B-Board datasheet.
|output||Pulse-width modulated outputs|
These ports are necessary to communicate with the various components on the B-Board. Modifying these connections could alter the proper behavior of the device.
The user interfaces include data ports and timing signals to exchange data with the CPU, drive PWM outputs, and access ADC value.
|output||ADC 16-bit result in 2’s complement format. If in a B-Box, registers 00 to 15 hold the results the B-Box (external) ADCs. Otherwise, registers 00 to 07 hold the results of the B-Board on-board ADCs and registers 08 to 15 return zero.|
|output||Output to the Sandbox, registers used by the CPU to send data towards the FPGA. The user can write to these registers from C++ drivers or graphical blocksets.|
|input||Input from the Sandbox, registers used by the FPGA to send data to the CPU. The user can read to these registers from C++ drivers or graphical blocksets.|
|output||Indicates the timer period of the CLOCK.|
|output||Indicates the prescaler division value of the CLOCK.|
|output||Clock enable generated by the prescaler, provides the counting rate of |
|output||Timer counting from 0 to |
|output||Asserted for the duration of the READ phase, signaling that |
|output||Asserted for one clock period at each ADC sampling instant.|
|output||Asserted for one clock period at the end of the configuration phase (end of system startup sequence). It may be used as a synchronous reset. In the case where multiple B-Boards (B-Boxes) are connected, this pulse occurs simultaneously in all devices and can be used to synchronize counters.|
|input||User firmware identification number. When a customized firmware is loaded, this number is sent to BB Control and is available from the Configuration tab. It can be used to ensure that the correct firmware has been loaded.|
|output||Asserted when the B-Board is in a B-Box, cleared otherwise.|
Understanding the real-time behavior of the firmware
To correctly develop and integrate custom logic in the B-Board FPGA, a proper understanding of the system behavior during real-time execution is necessary.
The four phases of a control cycle
The next figure is a simplified representation of the elements involved in the real-time execution of the control code and shows the four phases constituting a cycle, which are:
- ACQ: Analog-to-digital conversion (physical chips) and results acquisition (transfer to FPGA);
- READ: Real-time DMA read, FPGA data flagged as real-time are sent to the CPU read buffer;
- PROCESSING: Execution by the CPU of the main control interrupt, processing the user control code. At the beginning of this phase, the CPU read buffer is read. At the end, the CPU write buffer is updated.
- WRITE: Real-time DMA write, data flagged as real-time are transferred from the CPU write buffer to the FPGA peripherals (across the network of multiple B-Boards if needed).
During the READ and WRITE phases, data transfer is handled by the RealSync DMA engines and is independent from the CPU execution.
Four ports of the imperix firmware IP provide timing information, as shown in the next figure.
The ACQ phase starts with the assertion of
sampling_pulse and ends with the assertion of
adc_done_pulse, indicating that new ADC values are available in the
ADC registers. A pulse on
read_pulse signals the start of the READ phase when
SBI registers flagged as real-time are sent toward the CPU. At the end of the WRITE phase
data_valid_pulse is asserted notifying that new data is available in the real-time
Configuring the control cycle timings
The sampling and interrupt frequency are configured using the following C++ functions. In Simulink, the same parameters can be entered in the Configuration block.
Code language: C++ (cpp)
Clock_SetFrequency(CLOCK_0, FREQ); ConfigureMainInterrupt(UserInterrupt, CLOCK_0, PHASE, POSTSCALER);
In this example, a clock generator (
CLOCK_0) is configured to run at a frequency
FREQ and the interrupt to be mapped on this clock generator. The interrupt and sampling are by design linked to the same clock generator, but a POSTSCALER can be specified on the interrupt frequency allowing the sampling to run faster and always in a synchronized fashion.
Exchanging data between the CPU and the FPGA
The Output towards the SandBox (
SBI) and Input from the SandBox (
SBO) registers allow data exchange between the user control code in the CPU and the user logic in the FPGA. The C++ the drivers are available in
Code language: C++ (cpp)
uint16_t Sbi_ReadDirectly(unsigned int address, unsigned int device=0); void Sbi_ConfigureAsRealTime(unsigned int address, unsigned int device=0); uint16_t Sbi_Read(unsigned int address, unsigned int device=0);
Code language: C++ (cpp)
void Sbo_WriteDirectly(unsigned int address, uint16_t data, unsigned int device=0); void Sbo_ConfigureAsRealTime(unsigned int address, unsigned int device=0); void Sbo_Write(unsigned int address, uint16_t data, unsigned int device=0);
Their Simulink counterparts are named SBI and SBO.
The configuration phase occurs only once at the system startup and aims to initiate FPGA-based peripherals and configure the real-time data traffic, possibly across the control network. During this phase, interrupts and PWM operation are not yet active.
SBO registers can be read/written during the configuration phase by using
Sbo_WriteDirectly in the
SBOregisters that are only written once are called configuration registers, opposing to real-time registers.The user selects which registers are set as configuration registers from the “Registers” tab of the SBO block and then set up their values from the “Configuration reg. values” tab.
SBO register as a real-time register indicates that the value of this register is to be transferred at each control interrupt. Configuring a register as real-time is done by using the C++ function
In Simulink, real-time registers are clearly distinguished from configuration registers. They take their run-time values from the block inputs.
Before entering the control interrupt, the data that have previously been configured as real-time are retrieved from the FPGA peripherals and placed into the CPU read buffer (READ phase). As such, they can readily be used from inside the control interrupt using
Reciprocally, using the
Sbo_Write function inside the control interrupt stores data into the write buffer, waiting to be sent back to the FPGA once the interrupt is completed (WRITE phase).
In Simulink real-time data can be easily manipulated using signal wires.
Retrieving ADC conversion results
Inside the FPGA, ADC results are available from the
ADC interface of the firmware IP. The port
sampling_pulse signals the start of an ADC conversion and
adc_done_pulse indicate that the results are available in the
ADC interface. The conversion 16-bit results are in 2’s complement format.
Driving PWM outputs
On the firmware IP, the
sb_pwm[31:0] port provides access to the same PWM output chain as that used by other modulators (CB-PWM, PP-PWM, DO-PWM and SS-PWM). This allows the user to generate complementary signals with dead-time, use the standard activate and deactivate functions and rely on the protection mechanism that blocks PWM outputs when a fault is detected.
The PWM chain can be configured using the C++ function from
Code language: C++ (cpp)
void SbPwm_ConfigureOutputMode(tPwmOutput output, tPwmOutMode outMode, unsigned int device=0); void SbPwm_ConfigureDeadTime(tPwmOutput output, float deadTime, unsigned int device=0); void SbPwm_Activate(tPwmOutput output, unsigned int device=0); void SbPwm_Deactivate(tPwmOutput output, unsigned int device=0);
or using the corresponding Simulink SB-PWM block.
Each bit of the
sb_pwm[31:0] IP port corresponds to a PWM lane.
sb_pwm: lane #0
sb_pwm: lane #1
sb_pwm: lane #2
sb_pwm, etc.). An example of such a configuration is available in TN120.
pwmport as this would bypass the enable/disable mechanism! Instead, the SB-PWM port is meant to provide proper access to PWM outputs, which should be used in all cases.
On B-Box RCP, this is only relatively sensitive as hardware protections exist. However, on B-Board PRO, this is critical since this mechanism also handles the fault management !