Hi !
In this post we will create basic low level software to handle our custom IP.
There are several goals here :
- Will we see how to test this low level software using HDL simulation of a MicroBlaze subsystem. This is a great tool to start building the software developement task without any board !
- This low level software can then be packaged in different ways to make a standalone driver, a Linux device driver, or a test application. They will all be based on simple routines to achieve simple tasks with the custom IP.
This post will be based on the MicroBlaze subsystem defined in the following post:
2.3 - How to create a Microblaze design to simulate low level Software Functions
As this post is quite long, here are the main sections of this post for a quick jump :
Step 1 : Exporting the hardware platform for the software project
There are here a few things to understand.
Good to know :
The software developement will be done in the provided tool, the Xilinx SDK environment.
As the software uses the hardware, its has to know what is the provided hardware for the current project. This is really easy, the VIVADO tool will export the HDF file (Hardware Definition File) which is an encrypted container file that embedds everything needed !
Each time you make changes to your VIVADO project, you have to regenerate the HDF file, which will be automatically detected by SDK to recompile the whole software environment.
The software developement will be done in the provided tool, the Xilinx SDK environment.
As the software uses the hardware, its has to know what is the provided hardware for the current project. This is really easy, the VIVADO tool will export the HDF file (Hardware Definition File) which is an encrypted container file that embedds everything needed !
Each time you make changes to your VIVADO project, you have to regenerate the HDF file, which will be automatically detected by SDK to recompile the whole software environment.
Stage 1
First thing to do is to export the VIVADO hardware project.
But as our source files are only based on a Block Design file we have to convert it to an HDL file.
Easy !
In the Block Design window select the Sources tab.
Then right click on the BD file and click Create HDL wrapper.
Then a pop up will ask you if you want to handle the file or if you want VIVADO to do it for you.
As this is an exemple project, we will let VIVADO do it for us.
So click Next.
Stage 2
So, the wrapper has been generated, added to the source files and the source section has been updated.
To see if everything is fine with our Design let's generate the output from the Block Design content.
Select the Block Design source file and right click to Generate Output Products.
To check the validity of the Block Design content you could also click the Validate Design button or press F6.
Then the generate output function will provide the Configuration pop up.
Just use the global option and click Generate.
You can follow the generation steps in the Tcl Console Window.
Terminate the generation step by clicking Ok on the last pop up.
Stage 3
Now let's generate the hdf file.
Once again it's easy !
Go to File, then Export and Export Hardware.
Once again the tool asks you if you want to handle the repository of the hdf file or if you want him to handle it for you. Let it do the job !
Select Ok.
It's done !
Step 2 : Creating the software project
Stage 1
Now let's create the SDK Software project.
Go to File, then Launch SDK.
And again the tool asks you if you want to handle the repository of the software project or if you want him to handle it for you. Let it do the job !
Select Ok.
Depending on your system, it will take some time to open the project in SDK.
Stage 2
Now we are in the SDK project automatically created for us.
You have to know that for a basic standalone SDK project you must have the following items :
- The hardware platform (Created By VIVADO)
- A BSP (Created by SDK)
- An Application (Created by SDK)
For now the SDK tool created for us the hardware platform from the exported hdf file.
So if you look in the project explorer, the first section is the Hardware Platform, where you find the system.hdf file.
In the right window there is an overview of the hdf file with various information.
The first important information is the mapping of the system, where you can find our IP mapping in the system.
The second important information is the list of the IPs in the system, and hopefully our IP is in the list !!!
Another important point that you migth have noticed, is that our custom IP has its associated software driver automatically included in the drivers section !!!
This is very nice because when your driver is finalized, you don't have to care about providing it to the software project, it is automatically included whn you use the IP.
For now this is the template generated by the Custom IP generation wizzard and it contains nothing very interesting, we'll come back to it in the following posts.
Stage 3
We still have to generate the BSP and the application.
You can either create both manually, or BSP can be automatically created for us on application creation ! This is what we're going to do.
So, in the File menu, select New, then select Application Project.
Then the Application Project configuration window pops up.
Provide the name of our project.
Verify that Create New is selected for the BSP auto creation.
Click on Next.
Here you can use a template for several application use cases.
We'll use the Empty Application one.
Click Finish.
So the tool populated the BSP (2) and the application (3) sections.
The tool also opened the BSP overview in the system.mss file. We can check that our IP's driver is available in the BSP.
In the application section we can check that there is no source file excepted the auto generated linker script file lscript.ld.
Ok, the tool helped us a lot in generating all the resources needed for the SDK software project.
Now we have to write some C !
Step 3 : Writing the test application
Stage 1
First thing to do, create our source file. Here we only create a basic main.c file.
So on the src repository of the application section, right click for New, then Source File.
So give it the main.c name and click Finish.
Now the file appears in the src repository and is opened by the tool, ready for edition.
Stage 2
Let's write the C code.
Good to know :
For software developement there is a very important practice to understand and apply.
The low level functions we are going to write are intended to be used in drivers or application, for standalone or Linux. To have them portable among all these contexts, writing and reading in IPs shall be done using pointers.
As these low level functions will access hardware resources inside the IPs, software has to know the hardware properties (address, configuration parameters......). For standalone application, everything is available in the xparameters.h file located in the led_test_bsp > microblaze_0 > include.
For software developement there is a very important practice to understand and apply.
The low level functions we are going to write are intended to be used in drivers or application, for standalone or Linux. To have them portable among all these contexts, writing and reading in IPs shall be done using pointers.
As these low level functions will access hardware resources inside the IPs, software has to know the hardware properties (address, configuration parameters......). For standalone application, everything is available in the xparameters.h file located in the led_test_bsp > microblaze_0 > include.
First section : the includes files
Here only one thing will interest us, the hardware parameters. So let's include the xparameters file.
#include "xparameters.h"
Second section : the variable declaration
The first variable needed is the pointer to the IP's hardware registers, let's call it ptr_ip.
The second variable needed, is a counter for temporization creation, let's call it tempo.
int main()
{
unsigned int *ptr_ip; // To access IP's registers
unsigned int tempo; // To wait some time between actions
Third section : initialize the pointer
To access the physical registers of the IP, first initialize the pointer to the IP's registers base address.
The base address (XPAR_LED_TEST_IP_0_S00_AXI_IN_BASEADDR) is provided in the xparameters.h file.
// Initialize pointer to IP's base address
// This provided by the xparameters.h file
ptr_ip = (unsigned int *)XPAR_LED_TEST_IP_0_S00_AXI_IN_BASEADDR;
Fourth section : sequence definition
For example we will define the following test sequence :
- Generate a temporization
- Set the mode ON, the LED should be set
// Tempo for(tempo=0; tempo<100; tempo++); // Set mode ON // Activate bit 0 of register at offset 0x00 *(ptr_ip + 0x00) = 0x00000001; // Apply configuration by generating rising edge on bit 24 at offset Ox0C *(ptr_ip + 0x03) = 0x01000000; *(ptr_ip + 0x03) = 0x00000000;- Generate a temporization
- Set the mode OFF, the LED should be unset
// Tempo for(tempo=0; tempo<100; tempo++); // Set mode OFF // De activate bit 0 of register at offset 0x00 *(ptr_ip + 0x00) = 0x00000000; // Activate bit 8 of register at offset 0x04 *(ptr_ip + 0x01) = 0x00000100; // Apply configuration by generating rising edge on bit 24 at offset Ox0C *(ptr_ip + 0x03) = 0x01000000; *(ptr_ip + 0x03) = 0x00000000;- Generate a temporization
- Set the mode BLINK, the LED should blink using the value set in the IP's GUI in the Block Design editor.
// Tempo for(tempo=0; tempo<100; tempo++); // Set mode BLINK // De activate bit 8 of register at offset 0x04 *(ptr_ip + 0x01) = 0x00000000; // Activate bit 16 of register at offset 0x08 *(ptr_ip + 0x02) = 0x00010000; // Apply configuration by generating rising edge on bit 24 at offset Ox0C *(ptr_ip + 0x03) = 0x01000000; *(ptr_ip + 0x03) = 0x00000000;
Stage 3
Once the C source code is written it has to be compiled.
SDK is configured to launch automatically source compilation on source file save.
Otherwise you can use Project > Built all, or Ctrl + B
Building results are available in the Console.
There was no error and the output led_test.elf file is generated.
Step 4 : Simulating the software running on the hardware
Stage 1
The system RTL behavioral simulation is launched from VIVADO, so go back to the VIVADO tool.
The first thing to do is to tell the VIVADO tool to initialize the MicroBlaze's BRAM instruction memory with the generated led_test.elf file.
Go for Tools then Associate ELF Files...
This will open the ELF File Association window.
This is where you will specify which elf file will initialize the MicroBlaze's BRAM instruction memory for implementation and for simulation.
elf files can be different for implementation and for simulation.
The default file is the one called mb_bootloop_le.elf, it is provided by Xilinx and mostly, it will put the Microblaze in a inactive infinite loop after its initialization.
So, click on the file section of the simulation.
Then provide the path to the led_test.elf file we've just generated.
Click Ok, then Ok.
Stage 2
Now that software has been added to the simulation, let's launch the simulation.
This is done in VIVADO, on the left side, in the SIMULATION section.
Click on Run Simulation.
This will pop up the list of available simulation runs.
Click on the Run Behavioral Simulation.
This will launch the internal simulator of VIVADO called XSIM.
The main advantage of this simulator is that it handles everything for you !
Everything that has to be generated or compiled is done automatically by the tool !!
If you want to use Modelsim, no problem, VIVADO will generate for you all the needed scripts.
For my personal projects, I don't use anymore Modelsim, because XSIM is really enougth for my needs and it's FREE !!!
Stage 3
So after some time (depending on the content of your design and the efficiency of your computer) the simulator will open its window in the VIVADO layout.
Add the signals you want to see, set the simulation duration time and then Run the simulation !
And here you are :
You can see that :
- The clock is running,
- The reset is activated and released,
- The sequence of the 3 modes is there with the temporizations.
And so that's it !
The test software application can access the IP's registers and can be simulated to achieve the expected behavior.
Post Conclusion
Now we have :
- Created a VIVADO Project,
- Created the MicroBlaze Subsystem,
- Set the memory mapping of the MicroBlaze Subsystem,
- Written low level software to access the IP's registers,
- Simulated the software to achieve the expected behavior of the software.
The written software is very low level, now it has to be written in a more structured way to be used in drivers !
This will be done in next posts.
- Created a VIVADO Project,
- Created the MicroBlaze Subsystem,
- Set the memory mapping of the MicroBlaze Subsystem,
- Written low level software to access the IP's registers,
- Simulated the software to achieve the expected behavior of the software.
The written software is very low level, now it has to be written in a more structured way to be used in drivers !
This will be done in next posts.




















No comments:
Post a Comment