Main Content

Generate Custom HDL IP Core for Blinking LED on FPGA Board

This example shows how to use the MATLAB® HDL Workflow Advisor to generate a custom HDL IP core that blinks LEDs on an FPGA board. You can use the generated IP on the Xilinx® Zynq® platform or on any Xilinx FPGA with the MicroBlaze processor.

Introduction

You can use MATLAB to design, simulate, and verify your application, perform what-if scenarios with algorithms, and optimize parameters. You can then prepare your application design for hardware and software implementation on the Zynq-7000 AP SoC by deciding which system elements are performed by the programmable logic and which system elements run on the ARM® Cortex-A9.

Using the guided workflow shown in this example, you can: * Automatically generate VHDL® code for the programmable logic using HDL Coder™. * Export hardware information from the automatically generated EDK project to an SDK project for integration of handwritten C code for the ARM processor. I * Implement the design on the Xilinx Zynq Platform.

This example is a step-by-step guide that introduces you to the hardware and software co-design workflow. In this workflow, you perform these tasks:

  1. Set up your Zynq hardware and tools.

  2. Partition your design for hardware and software implementation.

  3. Generate an HDL IP core by using the MATLAB HDL Workflow Advisor.

  4. Integrate the IP core into a Xilinx EDK project and program the Zynq hardware.

Requirements

  • Xilinx ISE 14.4

  • Xilinx Zynq-7000 SoC ZC702 Evaluation Kit running the Linux® image in the Base Targeted Reference Design 14.4

  • HDL Coder Support Package for Xilinx Zynq Platform

Set Up Zynq Hardware and Tools

1. Set up the Xilinx Zynq ZC702 evaluation kit. Follow the hardware setup steps in HDL Coder example "Getting Started with HW/SW Co-Design Workflow for Xilinx Zynq Platform".

2. Set up the Xilinx ISE synthesis tool path. In the MATLAB Command Window use this command. Use your own ISE installation path when you run the command.

hdlsetuptoolpath('ToolName', 'Xilinx ISE', 'ToolPath', 'C:\Xilinx\14.4\ISE_DS\ISE\bin\nt64\ise.exe');

Partition Design for Hardware and Software Implementation

You must decide which parts of your design to implement on the programmable logic and which parts to run on the ARM processor.

Group the parts of your algorithm that you want to implement on programmable logic into a MATLAB function. This function is the boundary of your hardware/software partition. All the MATLAB code within this function is implemented on programmable logic. You must provide C code that implements the MATLAB code outside this function to run on the ARM processor.

In this example, the function mlhdlc_ip_core_led_blinking is implemented on hardware. It models a counter that blinks the LEDs on an FPGA board. Two input ports, Blink_frequency and Blink_direction, are control ports that determine the LED blink frequency and direction. You can adjust the input values of the hardware subsystem through prompt options in the included embedded software, mlhdlc_ip_core_led_blinking_driver.c and mlhdlc_ip_core_led_blinking_driver.h. The embedded software, which runs on the ARM processor, controls the generated IP core by writing to the AXI interface accessible registers. The output port of the hardware subsystem, LED, connects to the LED hardware. You can use the output port, Read_Back, to read data back to the processor.

design_name = 'mlhdlc_ip_core_led_blinking';
testbench_name = 'mlhdlc_ip_core_led_blinking_tb';
sw_driver_name = 'mlhdlc_ip_core_led_blinking_driver.c';
sw_driver_header_name = 'mlhdlc_ip_core_led_blinking_driver.h';

Review the MATLAB design.

type(design_name);
function [LED, Read_back] = mlhdlc_ip_core_led_blinking(Blink_frequency, Blink_direction)
%

%   Copyright 2013-2015 The MathWorks, Inc.

persistent freqCounter LEDCounter

if isempty(freqCounter)
    freqCounter = 0;
    LEDCounter = 255;
end

if Blink_frequency <= 0
    Blink_frequency = 0;
elseif Blink_frequency >= 15
    Blink_frequency = 15;
end

blinkFrequencyOut = LookupTable(Blink_frequency);
if blinkFrequencyOut == freqCounter
    freqMatch = 1;
else
    freqMatch = 0;
end

freqCounter = freqCounter + 1;

if freqMatch
    freqCounter = 0;
end

if Blink_direction
    LED = 255 - LEDCounter;
else
    LED = LEDCounter;
end

if LEDCounter == 255
    LEDCounter = 0;
elseif freqMatch
    LEDCounter = LEDCounter + 1;
end

Read_back = LED;
end


function y = LookupTable(idx)
s =  2.^(23:-1:8)';
y = s(idx+1);
end
type(testbench_name);

%

%   Copyright 2013-2015 The MathWorks, Inc.

for i=1:16
    [yout, ~] = mlhdlc_ip_core_led_blinking(i-1, 0);
    [yout2, ~] = mlhdlc_ip_core_led_blinking(i-1, 1);
end

Set Up Directory and Files

Copy the example files into a temporary folder.

mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
mlhdlc_temp_dir = [tempdir 'mlhdlc_ip_core_led_blinking'];

% Create a temporary folder and copy the MATLAB files.
cd(tempdir);
[~, ~, ~] = rmdir(mlhdlc_temp_dir, 's');
mkdir(mlhdlc_temp_dir);
cd(mlhdlc_temp_dir);

% Copy the design files to the temporary directory
copyfile(fullfile(mlhdlc_demo_dir, [design_name,'.m*']), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, [testbench_name,'.m*']), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, sw_driver_name), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, sw_driver_header_name), mlhdlc_temp_dir);

Create HDL Coder Project

coder -hdlcoder -new mlhdlc_ip_core_led_blinking_prj

Add the file mlhdlc_ip_core_led_blinking.m to the project as the MATLAB Function and mlhdlc_ip_core_led_blinking_tb.m as the MATLAB Test Bench.

For a more complete tutorial on creating and populating MATLAB HDL Coder projects, see Get Started with MATLAB to HDL Workflow.

Select Code Generation Target

Using the IP Core Generation workflow in the HDL Workflow Advisor enables you to automatically generate a sharable and reusable IP core module from a MATLAB function. The generated IP core is designed to be connected to an embedded processor on an FPGA device. HDL Coder generates HDL code from the MATLAB design function and generates HDL code for the AXI interface logic connecting the IP core to the embedded processor. HDL Coder packages call the generated files into an IP core folder. You can then integrate the generated IP core with a larger FPGA embedded design in the Xilinx EDK environment.

To choose the IP Core Generation workflow:

1. Open the HDL Workflow Advisor and right-click Select Code Generation Target.

2. For Workflow, select IP Core Generation.

Select Platform

There is a generic option called Generic Xilinx Platform in the platform selection. This option is board-independent and generates a generic Xilinx IP core, which has to be manually integrated into your EDK environment.

The remaining options are board-specific and provide the additional capability of integrating the generated IP core into a Xilinx PlanAhead project, synthesize the project, and download the bitstream to FPGA within the HDL Workflow Advisor.

For Platform, select Xilinx Zynq ZC702 evaluation kit. If you do not have this option, select Get more to open the Support Package Installer. In the Support Package Installer, select Xilinx Zynq Platform and follow the instructions to complete the installation.

Convert Design to Fixed-Point Design

1. Right-click the Define Input Types task and select Run This Task.

2. In the Fixed-Point Conversion task, click Advanced and set the Safety margin for sim min/max (%) to 0.

3. In the Proposed Type column in the Variables tab, set the proposed type of the freqCounter variable to unsigned 24-bit integer by entering numerictype(0, 24, 0).

4. Right-click the Fixed-Point Conversion task and select Run This Task.

Configure Target Interface

Map each port in your MATLAB design function to one of the IP core target interfaces in the Set Target Interface subtask.

In this example, input ports Blink_frequency and Blink_direction are mapped to the AXI4-Lite interface and HDL Coder™ generates AXI interface accessible registers for them. The LED output port is mapped to an external interface, LEDs General Purpose [0:7], which connects to the LED hardware on the Zynq board.

To generate the IP Core and IP Core report, right-click the HDL Code Generation step and select Run this task.

Integrate IP Core into with the Xilinx EDK Environment

Insert your generated IP core into a embedded system reference design, generate an FPGA bitstream, and download the bitstream to the Zynq hardware.

The reference design is a predefined Xilinx EDK project. It contains the elements the Xilinx software needs to deploy your design to the Zynq platform, except for the custom IP core and embedded software.

1. Under Embedded System Integration, right-click the Create Project step , and choose Run This Task. A Xilinx PlanAhead project with an EDK embedded design is generated. A link to the project is in the dialog box.

2. Build the FPGA bitstream in the Build Embedded System step. Make sure the Run build process externally option is selected. The Xilinx synthesis tool runs in a separate process from MATLAB. Wait for the synthesis tool process to finish running in the external command window.

3. After the bitstream is generated, right-click the Program Target Device step and choose the option Run This Task to program the Zynq hardware.

After you program the FPGA hardware, the LED starts blinking on your Zynq board.

Next, you integrate the included handwritten C code to run on the ARM processor to control the LED blink frequency and direction.

Run Software on Zynq ZC702 Hardware

The included C code files, mlhdlc_ip_core_led_blinking_driver.c and mlhdlc_ip_core_led_blinking_driver.h, implement a simple menu that enables you to set the LED blink frequency and direction. You can use them for your Linux-based SDK project.

For instructions on how to integrate the included C code into an SDK project and run it on Zynq ZC702 hardware, refer to the Xilinx documentation.

Clean Up Generated Files

To clean up the temporary project folder, run these commands:

mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
mlhdlc_temp_dir = [tempdir 'mlhdlc_ip_core_led_blinking'];
clear mex;
cd (mlhdlc_demo_dir);
rmdir(mlhdlc_temp_dir, 's');