POD Tutorial
=Tutorial 1=
Contents
Introduction
In this tutorial, we will learn how to use POD with a simple example project for an apf9328 board. The project is described in figure 1. It is composed of 3 virtual components:
- blink : blink is the instance name of a led (virtual component) that can «blink» by simply writing a value in a register.
- push : push is the instance name of a button (virtual component) that can generate an interrupt when pushed/released. The state of the button can be read in a register.
- i2c : i2c is the instance name of the i2cocore virtual component (from OpenCores.org). This component is an i2c bus controller.
Installation
Before using POD you must verify that Python is installed on your computer.
$ python
Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
If you get a «command not found», install it. [1]
To install POD, simply unpack the archive in the directory of your choice:
tar -zxvf pod-r75.tar.gz
Then open pod/bin/define.py file to modify the binary path :
...
#global
BINARYPATH="path_to_pod/pod"
...
To simulate a project with ghdl you will need ghdl and gtkwave:
sudo apt-get install ghdl gtkwave
To synthesize the project for a Xilinx FPGA, the ISE Webpack is required, see [2].
And to compile the drivers for an ARMadeus platform, you will need the ARMadeus toolchain correctly configured, see [3].
POD
POD can be started by writing "pod" in the pod/bin/ directory. If you are under Windows python has to be written before:
$ python pod/bin/pod
POD>
If you don't want to write the entire path each time, you can set your $PATH variable with the path of POD:
export PATH=$PATH:"path_to_pod/pod/bin"
Playing with POD
POD is a console program composed of several environments described in figure 2.
To enter in an environment, simply write its name from the parent environment.
POD> project
POD.project>
For a complete list of the available commands type help
POD.project> help
Documented commands (type help <topic>):
========================================
EOF create help listplatforms setaddr
addbusclock delcomponent history load setgeneric
addcomponent delconnection info ls shell
autoconnectbus description intercon printxml simulation
check driver listcomponents quit synthesis
closeproject eof listinstances savehistory top
connectbus exit listinterfaces saveproject
connectpin getmapping listmasters selectplatform
POD.project>
A short description is although available for each command.
POD.project> help listcomponents
listcomponents [componenttype]
List components available in the library
POD.project>
Command completion and argument completion can be done by using the <TAB> key :
POD.project> help list<TAB>
listcomponents listinterfaces listplatforms
listinstances listmasters
POD.project> help list
System commands can be used with «!» before:
POD.project> !echo "POD is really useful"
POD is really useful
POD.project>
Project creation
To create a project, enter the create command in the project environment:
POD.project> create i2cledbutton-tutorial
Project i2cledbutton-tutorial created
POD.project:i2cledbutton-tutorial>
The i2cledbutton-tutorial project is now created, you can save it when you want, by typing saveproject.
The target platform has to be selected by means of the selectplatform command :
POD.project:i2cledbutton-tutorial> selectplatform apf9328
Component platform added as apf9328
Component imx9328_wb16_wrapper added as imx9328_wb16_wrapper00
Component rstgen_syscon added as rstgen_syscon00
Component irq_mngr added as irq_mngr00
setting base address 0x0 for irq_mngr00.swb16
Platform apf9328 selected
POD.project:i2cledbutton-tutorial>
By selecting this platform, several components will be automaticaly added by POD:
- imx9328_wb16_wrapper: this component is used to convert the i.MX processor bus to the Wishbone (16bits data) bus.
- rstgen_syscon : this component manages the clock and the reset for the design.
- irq_mngr : this is a Wishbone16 slave which manages the interrupts generated by the other components and which propagates them to the processor.
Adding components
Components are organized by category in the library, to list the categories, use listcomponents:
POD.project:i2cledbutton-tutorial> listcomponents
test components wrappers syscons
POD.project:i2cledbutton-tutorial>
And to list the components under a category use listcomponents again with the category name in parameter:
POD.project:i2cledbutton-tutorial> listcomponents components
i2cocore c38a_control ledsensor led simplegpio uart16550 irq_mngr button
POD.project:i2cledbutton-tutorial>
Three components will be loaded with the command addcomponents:
POD.project:i2cledbutton-tutorial> help addcomponent
addcomponent <componenttype>.<componentname>.[componentversion] [newinstancename]
Add component in project
The second parameter is used to give the instance name of the component in the project.
POD.project:i2cledbutton-tutorial> addcomponent components.button push
Component button added as push
POD.project:i2cledbutton-tutorial> addcomponent components.led.wb16 blink
Component led added as blink
POD.project:i2cledbutton-tutorial> addcomponent components.i2cocore.wb16 i2c
Component i2cocore added as i2c
Note: some components like the led may have several versions depending on the Wishbone bus size for example.
Internal pin connections
push and i2c components have output pins to generate interrupts. These pins have to be connected to the interrupt manager "irq_mngr00".
A complete description of an instance in the project can be displayed with the info command:
POD.project:i2cledbutton-tutorial> info i2c
Component name :i2c
Instance name :i2cocore
description : A simple button ip
->Generics
id : 1
wb_size : 16
->Interfaces
irq :
inta_o s1
candr :
rst_i s1
clk_i s1
i2c :
scl s1
sda s1
swb16 Base address:0x0
adr_i s4
dat_i s16
dat_o s16
we_i s1
stb_i s1
ack_o s1
cyc_i s1
POD.project:i2cledbutton-tutorial>
This command gives the interfaces, the ports and the size of the ports (s1, s16, ...). We want to connect the interrupt port pin number 0, named inta_o and part of the irq interface, to the irq_mngr00.
POD.project:i2cledbutton-tutorial> info irq_mngr00
Component name :irq_mngr00
Instance name :irq_mngr
description : Manage interruptions.
->Generics
id : 1
irq_level : '1'
irq_count : 1
->Interfaces
candr :
gls_clk s1
gls_reset s1
swb16 Base address:0x0
wbs_s1_address s2
wbs_s1_readdata s16
wbs_s1_writedata s16
wbs_s1_ack s1
wbs_s1_strobe s1
wbs_s1_cycle s1
wbs_s1_write s1
irq :
irqport s16
ext_irq :
gls_irq s1
pin 0: -> apf9328.fpga.TIM1.0
The targeted port in the irq_mngr is irqport part of the irq interface. To establish the connection, the connectpin command will be used:
POD.project:i2cledbutton-tutorial> connectpin irq_mngr00.irq.irqport.0 i2c.irq.inta_o.0
pin connected
Same thing for the push button :
POD.project:i2cledbutton-tutorial> connectpin irq_mngr00.irq.irqport.1 push.int_button.irq.0
pin connected
The info command can be used to verify that the connection is correctly performed:
POD.project:i2cledbutton-tutorial> info irq_mngr00
Component name :irq_mngr00
Instance name :irq_mngr
description : Manage interruptions.
->Generics
id : 1
irq_level : '1'
irq_count : 2
->Interfaces
candr :
gls_clk s1
gls_reset s1
swb16 Base address:0x0
wbs_s1_address s2
wbs_s1_readdata s16
wbs_s1_writedata s16
wbs_s1_ack s1
wbs_s1_strobe s1
wbs_s1_cycle s1
wbs_s1_write s1
irq :
irqport s16
pin 0: -> i2c.irq.inta_o.0
pin 1: -> push.int_button.irq.0
ext_irq :
gls_irq s1
pin 0: -> apf9328.fpga.TIM1.0
External pin connections
Connecting an external pin is done the same way as for an internal pin by giving the name of the platform in place of the instance name. In the apf9328 platform, the pin name can be found in FPGA schematic [4] (page 13). The name of the interface is fpga for the apf9328. In this example we will connect the button, the led and the i2c to the APF9328DevFull connector X7 (figure 6).
We just have to connect the pins as following :
POD.project:i2cledbutton-tutorial> connectpin apf9328.fpga.IO_L01N_0 push.int_button.button.0
pin connected
POD.project:i2cledbutton-tutorial> connectpin i2c.i2c.sda apf9328.fpga.IO_L32N_0
pin connected
POD.project:i2cledbutton-tutorial> connectpin i2c.i2c.scl apf9328.fpga.IO_L01P_0
pin connected
POD.project:i2cledbutton-tutorial> connectpin blink.int_led.led.0 apf9328.fpga.IO_L32P_0
pin connected
Bus and clock connections
- Bus
To connect a bus, the master bus interface is used as first argument of the connectbus command, the second argument being the slave bus interface:
POD.project:i2cledbutton-tutorial> connectbus imx9328_wb16_wrapper00.mwb16 blink.swb16
Bus connected
POD.project:i2cledbutton-tutorial> connectbus imx9328_wb16_wrapper00.mwb16 push.swb16
Bus connected
POD.project:i2cledbutton-tutorial> connectbus imx9328_wb16_wrapper00.mwb16 i2c.swb16
Bus connected
- clock
The bus interconection (Intercon) need to be synchronized with a clock and reset generator. This can be done by means of the addbusclock command.
POD.project:i2cledbutton-tutorial> addbusclock rstgen_syscon00.candr imx9328_wb16_wrapper00.mwb16
Connected
- autoconnect
Bus and clock connections can be automaticaly performed with the autoconnect command. This command works only for "classical" architectures and with recognized buses.
POD.project:i2cledbutton-tutorial> autoconnectbus
Intercon generation
Once the connections done, the Intercon component has to be generated. The Intercon is a component responsible for decoding the addresses and for routing the Wishbone bus signals.
POD.project:i2cledbutton-tutorial> intercon imx9328_wb16_wrapper00.mwb16
Top generation
The Top component is the component responsible for connecting the non Wishbone signals in the FPGA. The Top can be generated with the top command
POD.project:i2cledbutton-tutorial> top
Top generated with name : top_i2cledbutton-tutorial.vhd
Synthesis
In the apf9328 platform, the FPGA is a Spartan3 from Xilinx. This means that the synthesis of the project can only be done with ISE. Fortunately, Xilinx provides the ISE Webpack freely on its website [5].
POD has to generate a project that ISE can understand. This can be accomplished from the synthesis environment :
POD.project:i2cledbutton-tutorial> synthesis
POD.project.synthesis>
Then the tool used for the synthesis has to be specified with the selecttoolchain command:
POD.project.synthesis> selecttoolchain ise
After that we can generate an ISE project with the generateproject command.
POD.project:i2cledbutton-tutorial.synthesis> selecttoolchain ise
POD.project:i2cledbutton-tutorial.synthesis> generateproject
Make directory for imx9328_wb16_wrapper
Make directory for rstgen_syscon
Make directory for irq_mngr
Make directory for led
Make directory for button
Make directory for i2cocore
Make directory for imx9328_wb16_wrapper00_mwb16
Constraint file generated with name :~/pod/tests/i2cledbutton-tutorial/synthesis/i2cledbutton-tutorial.ucf
TCL script generated with name : i2cledbutton-tutorial.tcl
As you can see, POD generates although a TCL script that can be executed by ISE. This script eases the synthesis process.
In the Tcl tab (1), change the default directory to the synthesis directory (2), find the tcl script you want to execute (3, under Windows type dir instead of ls) and start it with the source command (4).
The resulting bitstream (binary FPGA synthetized code) top_i2cledbutton.bit can be found in the i2cledbutton_tutorial/objs directory.
Simulation
If a simulation is required, POD can generate a template for the whole project. To do this, enter in the simulation environment :
POD.project:i2cledbutton_tutorial> simulation
POD.project:i2cledbutton_tutorial.simulation>
To generate the testbench and the makefile use the command:
POD.project:i2cledbutton_tutorial.simulation> generatemakefile
Testbench with name : /home/fabien/projectpod/software/pod/tests/i2cledbutton_tutorial/simulation/top_i2cledbutton_tutorial_tb.vhd Done
Makefile generated with name : /home/fabien/projectpod/software/pod/tests/i2cledbutton_tutorial/simulation/Makefile Done
Now, you just have to modify the top_i2cledbutton_tutorial_tb.vhd file to add your own tests under the stimulis process.
stimulis : process
begin
-- write stimulis here
wait for 10 us;
assert false report "End of test" severity error;
end process stimulis;
You can then start the simulation with make ghdl-simu and launch make ghdl-view to view the generated chronograms with gtkwave.
Drivers
Numbers of components have a driver template for different operating systems. POD can fill these templates with the informations contained in the project.
From the driver environment,
POD.project:i2cledbutton_tutorial> driver
POD.project:i2cledbutton_tutorial.driver>
choose the targeted operating system:
POD.project:i2cledbutton_tutorial.driver> selectoperatingsystem linux
And generate the driver project :
POD.project:i2cledbutton_tutorial.driver> generateproject
No driver for imx9328_wb16_wrapper
No driver for rstgen_syscon
Create directory for irq_mngr driver
Create directory for button driver
Create directory for led driver
Create directory for i2cocore driver
No driver for imx9328_wb16_wrapper00_mwb16
Copy and fill template for irq_mngr
Copy and fill template for button
Copy and fill template for led
Copy and fill template for i2cocore
Drivers are generated and can be found in the i2cledbutton_tutorial/drivers/ directory. POD can copy this drivers to the right place in the software development tree. Select the path with selectprojecttree then copy the files with copydrivers:
POD.project:i2cledbutton_tutorial.driver> selectprojecttree ~/armadeus/target/linux/modules/fpga/POD
POD.project:i2cledbutton_tutorial.driver> copydrivers
To compile the drivers, go to your armadeus/ directory then type make linux-menuconfig. The drivers generated by POD are located in Device Drivers - Armadeus specific drivers - FPGA drivers (see figure 11).
$ make linux-menuconfig
$ make