Difference between revisions of "POD Tutorial"
(→Drivers) |
(→Drivers) |
||
(31 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | |||
− | |||
− | |||
== Introduction == | == Introduction == | ||
− | In this tutorial, we will learn how to use POD with a simple example project for an | + | In this first tutorial, we will learn how to use POD with a simple example project for an [[APF27]] board. |
− | + | ||
The project is described in figure 1. It is composed of 3 virtual components: | 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. | * '''blink''' : blink is the instance name of a led (virtual component) that can «blink» by simply writing a value in a register. | ||
Line 16: | Line 12: | ||
See [[POD installation guide]] to learn how to install it. | See [[POD installation guide]] to learn how to install it. | ||
+ | |||
+ | {{Note| This tutorial is written for apf27_dev a LED is already soldered on fpga. The fpga bank1 must be powered with 3.3V (connect pin 39 and pin 1 on J20 header)}} | ||
== POD == | == POD == | ||
− | POD | + | If POD is [[POD_installation_guide | correctly installed]], simply type : |
− | < | + | <pre class="host"> |
− | $ | + | $ pod |
POD> | POD> | ||
− | </ | + | </pre> |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
=== Playing with POD === | === Playing with POD === | ||
Line 38: | Line 31: | ||
To enter in an environment, simply write its name from the parent environment. | To enter in an environment, simply write its name from the parent environment. | ||
− | < | + | <pre class="host"> |
− | POD> | + | POD> synthesis |
− | POD. | + | POD.synthesis> |
− | </ | + | </pre> |
For a complete list of the available commands type ''help'' | For a complete list of the available commands type ''help'' | ||
− | < | + | <pre class="pod"> |
− | POD | + | POD> help |
Documented commands (type help <topic>): | Documented commands (type help <topic>): | ||
======================================== | ======================================== | ||
− | EOF | + | EOF create history ls shell |
− | + | addbusclock delbusconnection info printxml simulation | |
− | + | addinstance delinstance generateintercon quit source | |
− | + | autoconnectbus delpinconnection listcomponents report synthesis | |
− | + | check description listforce savehistory generatetop | |
− | + | closeproject driver listinstances saveproject version | |
− | + | connectbus eof listinterfaces selectplatform | |
− | + | connectinterface exit listmasters setaddr | |
+ | connectpin getmapping listplatforms setforce | ||
+ | connectport help load setgeneric | ||
− | + | </pre> | |
− | </ | + | |
− | A short description is although available for each command. | + | A short help description is although available for each command. |
− | < | + | <pre class="pod"> |
− | POD | + | POD> help listcomponents |
listcomponents [componenttype] | listcomponents [componenttype] | ||
List components available in the library | List components available in the library | ||
− | POD | + | POD> |
− | </ | + | </pre> |
Command completion and argument completion can be done by using the <TAB> key : | Command completion and argument completion can be done by using the <TAB> key : | ||
− | < | + | <pre class="host"> |
− | POD | + | POD> help list<TAB> |
listcomponents listinterfaces listplatforms | listcomponents listinterfaces listplatforms | ||
listinstances listmasters | listinstances listmasters | ||
− | POD | + | POD> help list |
− | </ | + | </pre> |
System commands can be used with «!» before: | System commands can be used with «!» before: | ||
− | < | + | <pre class="host"> |
− | POD | + | POD> !echo "POD is really useful" |
POD is really useful | POD is really useful | ||
− | POD | + | POD> |
− | </ | + | </pre> |
=== Project creation === | === Project creation === | ||
− | [[image:exemple-empty.png|center|frame|400px|'''figure 3''' - ''Empty i2cledbutton | + | [[image:exemple-empty.png|center|frame|400px|'''figure 3''' - ''Empty i2cledbutton project'']] |
To create a project, enter the ''create'' command in the ''project'' environment: | To create a project, enter the ''create'' command in the ''project'' environment: | ||
− | < | + | <pre style="host"> |
− | POD | + | POD> create i2cledbutton |
− | Project i2cledbutton | + | Project i2cledbutton created |
− | POD | + | POD:i2cledbutton> |
− | </ | + | </pre> |
− | The ''i2cledbutton | + | The ''i2cledbutton'' project is now created and saved. |
− | + | ||
The target platform has to be selected by means of the ''selectplatform'' command : | The target platform has to be selected by means of the ''selectplatform'' command : | ||
− | < | + | <pre style="host"> |
− | + | project:i2cledbutton> selectplatform standard.apf27 | |
− | Component platform added as | + | [INFO] : No platform in project |
− | Component | + | Component platform added as apf27 |
+ | Component imx27_wb16_wrapper added as imx27_wb16_wrapper00 | ||
Component rstgen_syscon added as rstgen_syscon00 | Component rstgen_syscon added as rstgen_syscon00 | ||
Component irq_mngr added as irq_mngr00 | Component irq_mngr added as irq_mngr00 | ||
− | |||
− | + | project:i2cledbutton> | |
− | + | </pre> | |
− | </ | + | |
By selecting this platform, several components will be automaticaly added by POD: | By selecting this platform, several components will be automaticaly added by POD: | ||
− | * ''' | + | * '''imx27_wb16_wrapper''': this component is used to convert the i.MX27 processor bus to the wishbone (16bits data) bus. |
* '''rstgen_syscon''' : this component manages the clock and the reset for the design. | * '''rstgen_syscon''' : this component manages the clock and the reset for the design. | ||
− | * '''irq_mngr''' : this is a | + | * '''irq_mngr''' : this is a wishbone16 slave which manages the interrupts generated by the other components and which propagates them to the processor. |
[[image:exemple-platform.png|center|frame|400px|'''figure 4''' - ''Platform loaded with their default components'']] | [[image:exemple-platform.png|center|frame|400px|'''figure 4''' - ''Platform loaded with their default components'']] | ||
Line 125: | Line 117: | ||
Components are organized by category in the library, to list the categories, use ''listcomponents'': | Components are organized by category in the library, to list the categories, use ''listcomponents'': | ||
− | < | + | |
− | + | <pre style="host"> | |
− | + | project:i2cledbutton> listcomponents | |
− | + | components logics syscons test wrappers | |
− | </ | + | </pre> |
And to list the components under a category use ''listcomponents'' again with the category name in parameter: | And to list the components under a category use ''listcomponents'' again with the category name in parameter: | ||
− | < | + | <pre style="host"> |
− | + | project:i2cledbutton> listcomponents components | |
− | + | sp_vision_configure bram uart16750 spartan_selectmap | |
− | + | industrial_output anybus_interface simplegpio button | |
− | </ | + | industrial_serial_input led uart16550 sja1000 |
+ | i2cocore pod_gpio irq_mngr | ||
+ | </pre> | ||
− | + | The components will be loaded with the command ''addinstances'': | |
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> help addinstance |
− | + | addinstance <componenttype>.<componentname>.[componentversion] [newinstancename] | |
Add component in project | Add component in project | ||
− | </ | + | </pre> |
The second parameter is used to give the instance name of the component in the project. | The second parameter is used to give the instance name of the component in the project. | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> addinstance components.button push |
Component button added as push | Component button added as push | ||
− | POD | + | POD:i2cledbutton> addinstance components.led.wb16 blink |
Component led added as blink | Component led added as blink | ||
− | POD | + | POD:i2cledbutton> addinstance components.i2cocore.wb16 i2c |
Component i2cocore added as i2c | Component i2cocore added as i2c | ||
− | </ | + | </pre> |
Note: some components like the led may have several versions depending on the Wishbone bus size for example. | Note: some components like the led may have several versions depending on the Wishbone bus size for example. | ||
Line 173: | Line 167: | ||
A complete description of an instance in the project can be displayed with the ''info'' command: | A complete description of an instance in the project can be displayed with the ''info'' command: | ||
− | < | + | <pre style="host"> |
− | + | project:i2cledbutton> info i2c | |
− | + | Instance name :i2c | |
− | + | Component name :i2cocore | |
description : A simple button ip | description : A simple button ip | ||
->Generics | ->Generics | ||
Line 184: | Line 178: | ||
irq : | irq : | ||
inta_o s1 | inta_o s1 | ||
− | |||
− | |||
− | |||
i2c : | i2c : | ||
scl s1 | scl s1 | ||
sda s1 | sda s1 | ||
swb16 Base address:0x0 | swb16 Base address:0x0 | ||
+ | rst_i s1 | ||
+ | clk_i s1 | ||
adr_i s4 | adr_i s4 | ||
dat_i s16 | dat_i s16 | ||
Line 198: | Line 191: | ||
ack_o s1 | ack_o s1 | ||
cyc_i s1 | cyc_i s1 | ||
− | + | project:i2cledbutton> | |
− | </ | + | </pre> |
This command gives the interfaces, the ports and the size of the ports (s1, s16, ...). We want to | This command gives the interfaces, the ports and the size of the ports (s1, s16, ...). We want to | ||
Line 205: | Line 198: | ||
interface, to the ''irq_mngr00''. | interface, to the ''irq_mngr00''. | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> info irq_mngr00 |
Component name :irq_mngr00 | Component name :irq_mngr00 | ||
Instance name :irq_mngr | Instance name :irq_mngr | ||
Line 230: | Line 223: | ||
ext_irq : | ext_irq : | ||
gls_irq s1 | gls_irq s1 | ||
− | pin 0: -> | + | pin 0: -> apf27.fpga.TIM1.0 |
− | </ | + | </pre> |
The targeted port in the irq_mngr is '''irqport''' part of the '''irq''' interface. To establish the connection, the ''connectpin'' command will be used: | The targeted port in the irq_mngr is '''irqport''' part of the '''irq''' interface. To establish the connection, the ''connectpin'' command will be used: | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> connectpin irq_mngr00.irq.irqport.0 i2c.irq.inta_o.0 |
− | + | ||
− | </ | + | </pre> |
Same thing for the push button : | Same thing for the push button : | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> connectpin irq_mngr00.irq.irqport.1 push.int_button.irq.0 |
pin connected | pin connected | ||
− | </ | + | </pre> |
The ''info'' command can be used to verify that the connection is correctly performed: | The ''info'' command can be used to verify that the connection is correctly performed: | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> info irq_mngr00 |
Component name :irq_mngr00 | Component name :irq_mngr00 | ||
Instance name :irq_mngr | Instance name :irq_mngr | ||
Line 276: | Line 269: | ||
ext_irq : | ext_irq : | ||
gls_irq s1 | gls_irq s1 | ||
− | pin 0: -> | + | pin 0: -> apf27.fpga.TIM1.0 |
− | </ | + | </pre> |
=== External pin connections === | === 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 ''' | + | 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 '''apf27''' platform, the pin name |
− | can be found in FPGA schematic [http://www.armadeus.com/_downloads/ | + | can be found in FPGA schematic [http://www.armadeus.com/_downloads/apf27Dev/hardware/apf27_devfull_12.pdf]. |
− | The name of the interface is '''fpga''' for the | + | The name of the interface is '''fpga''' for the apf27. In this example we will connect the button, the led and the i2c to the apf27DevFull connector X7 (figure 6). |
− | [[image: | + | [[image:led_apf27_dev.png|center|frame|400px|'''figure 5''' - ''FPGA led connection on apf27Devfull'']] |
We just have to connect the pins as following : | We just have to connect the pins as following : | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> connectpin blink.int_led.led.0 apf27.fpga.IO_L24P_1 |
− | + | POD:i2cledbutton> connectpin push.int_button.button.0 apf27.fpga.IO_L24N_1 | |
− | POD | + | POD:i2cledbutton> connectpin i2c.i2c.sda apf27.fpga.IO_L20N_1 |
− | + | POD:i2cledbutton> connectpin i2c.i2c.scl apf27.fpga.IO_L20P_1 | |
− | POD | + | </pre> |
− | + | ||
− | POD | + | |
− | + | ||
− | </ | + | |
[[image:exemple-extconnection.png|center|frame|400px|'''figure 6''' - ''external connections'']] | [[image:exemple-extconnection.png|center|frame|400px|'''figure 6''' - ''external connections'']] | ||
Line 311: | Line 300: | ||
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: | 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: | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 blink.swb16 |
− | + | setting base address 0x0 for blink.swb16 | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 push.swb16 | |
+ | setting base address 0x4 for push.swb16 | ||
− | + | POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 i2c.swb16 | |
+ | setting base address 0x20 for i2c.swb16 | ||
+ | POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 irq_mngr00.swb16 | ||
+ | setting base address 0x40 for irq_mngr00.swb16 | ||
+ | </pre> | ||
− | + | * '''clock & reset''' | |
− | < | + | [[image:exemple-clockconnection.png|center|frame|400px|'''figure 8''' - ''Syscon connection'']] |
− | + | ||
− | + | Clock and reset are seen like a standard bus, to connect it, simply use connectbus: | |
− | </ | + | |
+ | <pre style="host"> | ||
+ | project:i2cledbutton> connectbus rstgen_syscon00.candroutput imx27_wb16_wrapper00.candrinput | ||
+ | No addressing value in this type of bus | ||
+ | </pre> | ||
* '''autoconnect''' | * '''autoconnect''' | ||
− | Bus and clock connections can be | + | Bus and clock connections can be automatically performed with the ''autoconnect'' command. This command works only for "classical" architectures and with recognized busses. |
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton> autoconnectbus |
− | </ | + | </pre> |
=== Intercon generation === | === Intercon generation === | ||
− | Once the connections done, the | + | Once the connections done, the Intercons components has to be generated. Intercons are components |
− | responsible for decoding the addresses and for routing | + | responsible for decoding the addresses and for routing bus signals. Intercons must be generated for each master bus. |
− | < | + | * for wrapper master wishbone bus |
− | POD. | + | <pre style="host"> |
− | </ | + | POD> generateintercon imx27_wb16_wrapper00.mwb16 |
+ | Intercon with name : imx27_wb16_wrapper00_mwb16_intercon Done | ||
+ | Component imx27_wb16_wrapper00_mwb16 added as imx27_wb16_wrapper00_mwb16_intercon | ||
+ | </pre> | ||
+ | |||
+ | * for syscon master candr bus | ||
+ | <pre style="host"> | ||
+ | POD> generateintercon rstgen_syscon00.candroutput | ||
+ | Intercon with name : rstgen_syscon00_candroutput_intercon Done | ||
+ | Component rstgen_syscon00_candroutput added as rstgen_syscon00_candroutput_intercon | ||
+ | </pre> | ||
[[image:exemple-intercon.png|center|frame|400px|'''figure 8''' - ''Intercon'']] | [[image:exemple-intercon.png|center|frame|400px|'''figure 8''' - ''Intercon'']] | ||
Line 355: | Line 358: | ||
[[image:exemple-top.png|center|frame|400px|'''figure 9''' - ''Top'']] | [[image:exemple-top.png|center|frame|400px|'''figure 9''' - ''Top'']] | ||
− | The Top component is the component responsible for connecting | + | The Top component is the component responsible for connecting all instances in the FPGA. The Top can be generated with the ''generatetop'' command |
+ | |||
+ | <pre style="host"> | ||
+ | POD:i2cledbutton> generatetop | ||
− | + | Mapping for interface mwb16: | |
− | + | Address | instance.interface | size | |
+ | --------------------------------------------------------- | ||
+ | 0x0 | blink.swb16 | 4 | ||
+ | 0x4 | push.swb16 | 4 | ||
+ | 0x08 | --void-- | 24 | ||
+ | 0x20 | i2c.swb16 | 32 | ||
+ | 0x40 | irq_mngr00.swb16 | 8 | ||
+ | --------------------------------------------------------- | ||
− | Top generated with name : top_i2cledbutton | + | Top generated with name : top_i2cledbutton.vhd |
− | </ | + | </pre> |
== Synthesis == | == Synthesis == | ||
− | In the ''' | + | In the '''apf27''' platform, the FPGA is a Spartan3A 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 [http://www.xilinx.com/ise/logic_design_prod/webpack.htm]. | Webpack freely on its website [http://www.xilinx.com/ise/logic_design_prod/webpack.htm]. | ||
POD has to generate a project that ISE can understand. This can be accomplished from the synthesis environment : | POD has to generate a project that ISE can understand. This can be accomplished from the synthesis environment : | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton-tutorial> synthesis |
− | POD | + | POD.synthesis> |
− | </ | + | </pre> |
Then the tool used for the synthesis has to be specified with the ''selecttoolchain'' command: | Then the tool used for the synthesis has to be specified with the ''selecttoolchain'' command: | ||
− | < | + | <pre style="host"> |
− | POD | + | POD.synthesis> selecttoolchain ise |
− | </ | + | </pre> |
After that we can generate an ISE project with the ''generateproject'' command. | After that we can generate an ISE project with the ''generateproject'' command. | ||
− | < | + | <pre style="host"> |
− | POD | + | POD> synthesis |
− | POD | + | POD.synthesis> selecttoolchain ise |
− | Make directory for | + | POD.synthesis> generateproject |
+ | Make directory for imx27_wb16_wrapper | ||
Make directory for rstgen_syscon | Make directory for rstgen_syscon | ||
Make directory for irq_mngr | Make directory for irq_mngr | ||
− | |||
Make directory for button | Make directory for button | ||
+ | Make directory for led | ||
Make directory for i2cocore | Make directory for i2cocore | ||
− | Make directory for | + | Make directory for rstgen_syscon00_candroutput |
+ | Make directory for imx27_wb16_wrapper00_mwb16 | ||
− | Constraint file generated with name : | + | Constraint file generated with name : /home/fabien/tmp/i2cledbutton/synthesis/i2cledbutton.ucf |
− | TCL script generated with name : i2cledbutton | + | TCL script generated with name : i2cledbutton.tcl |
− | </ | + | </pre> |
As you can see, POD generates although a TCL script that can be executed by ISE. This script eases the synthesis process. | As you can see, POD generates although a TCL script that can be executed by ISE. This script eases the synthesis process. | ||
Line 404: | Line 419: | ||
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'''). | 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'''). | ||
+ | |||
+ | {{ Note | To use this tutorial with APF51, generate binary file '''.bin''' instead of bitstream '''.bit''' file. }} | ||
The resulting bitstream (binary FPGA synthetized code) ''top_i2cledbutton.bit'' can be found in the ''i2cledbutton_tutorial/objs'' directory. | The resulting bitstream (binary FPGA synthetized code) ''top_i2cledbutton.bit'' can be found in the ''i2cledbutton_tutorial/objs'' directory. | ||
+ | |||
+ | {{Warning | There is a bug with ISE-13.x and upper, when tcl script is launched, the constraints file (ucf) is not read and ISE choose FPGA pinout randomly. To avoid this problem, once the script is sourced, re-launch the entire process by clicking right on «Generate Programming File» en selecting «re-run all» }} | ||
== Simulation == | == Simulation == | ||
Line 411: | Line 430: | ||
If a simulation is required, POD can generate a template for the whole project. To do this, enter in the simulation environment : | If a simulation is required, POD can generate a template for the whole project. To do this, enter in the simulation environment : | ||
− | < | + | <pre style="host"> |
POD.project:i2cledbutton_tutorial> simulation | POD.project:i2cledbutton_tutorial> simulation | ||
POD.project:i2cledbutton_tutorial.simulation> | POD.project:i2cledbutton_tutorial.simulation> | ||
− | </ | + | </pre> |
+ | |||
+ | First select your toolchain (here it's ghdl): | ||
+ | <pre style="host"> | ||
+ | POD.project:i2cledbutton_tutorial.simulation> selecttoolchain ghdl | ||
+ | </pre> | ||
To generate the testbench and the makefile use the command: | To generate the testbench and the makefile use the command: | ||
− | < | + | <pre style="host"> |
− | POD.project:i2cledbutton_tutorial.simulation> | + | POD.project:i2cledbutton_tutorial.simulation> generateproject |
Testbench with name : /home/fabien/projectpod/software/pod/tests/i2cledbutton_tutorial/simulation/top_i2cledbutton_tutorial_tb.vhd Done | 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 | Makefile generated with name : /home/fabien/projectpod/software/pod/tests/i2cledbutton_tutorial/simulation/Makefile Done | ||
− | </ | + | </pre> |
Now, you just have to modify the ''top_i2cledbutton_tutorial_tb.vhd'' file to add your own tests | Now, you just have to modify the ''top_i2cledbutton_tutorial_tb.vhd'' file to add your own tests | ||
under the ''stimulis'' process. | under the ''stimulis'' process. | ||
− | < | + | <pre style="host"> |
stimulis : process | stimulis : process | ||
begin | begin | ||
Line 436: | Line 460: | ||
assert false report "End of test" severity error; | assert false report "End of test" severity error; | ||
end process stimulis; | end process stimulis; | ||
− | </ | + | </pre> |
You can then start the simulation with ''make ghdl-simu'' and launch ''make ghdl-view'' to | You can then start the simulation with ''make ghdl-simu'' and launch ''make ghdl-view'' to | ||
Line 448: | Line 472: | ||
From the driver environment, | From the driver environment, | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton_tutorial> driver |
− | POD | + | POD:i2cledbutton_tutorial.driver> |
− | </ | + | </pre> |
choose the targeted platform: | choose the targeted platform: | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton_tutorial.driver> selecttoolchain armadeus |
− | </ | + | </pre> |
And generate the driver project : | And generate the driver project : | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton_tutorial.driver> generateproject |
No driver for imx9328_wb16_wrapper | No driver for imx9328_wb16_wrapper | ||
No driver for rstgen_syscon | No driver for rstgen_syscon | ||
Line 474: | Line 498: | ||
Copy and fill template for led | Copy and fill template for led | ||
Copy and fill template for i2cocore | Copy and fill template for i2cocore | ||
− | </ | + | </pre> |
Drivers are generated and can be found in the ''i2cledbutton_tutorial/drivers/'' directory. | 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 can copy this drivers to the right place in the software development tree. Select the path with ''selectprojecttree'' then copy the files with ''copydrivers'': | ||
− | < | + | <pre style="host"> |
− | POD | + | POD:i2cledbutton_tutorial.driver> selectprojecttree ~/armadeus/target/linux/modules/fpga/POD |
− | POD | + | POD:i2cledbutton_tutorial.driver> copydrivers |
+ | </pre> | ||
− | </ | + | To compile the drivers, go to your ''armadeus/'' directory, then: |
+ | <pre style="host"> | ||
+ | $ make linux-menuconfig | ||
+ | </pre> | ||
− | + | <pre class="config"> | |
+ | Device Drivers ---> | ||
+ | ... | ||
+ | [*] Support for specific Armadeus drivers ---> | ||
+ | ... | ||
+ | *** FPGA related *** | ||
+ | [*] FPGA specific drivers and tools ---> | ||
+ | ... | ||
+ | [*] Board drivers generated by POD | ||
+ | </pre> | ||
− | + | <pre style="host"> | |
− | + | ||
− | < | + | |
− | + | ||
$ make | $ make | ||
− | </ | + | </pre> |
+ | |||
+ | == Test == | ||
+ | |||
+ | Once [[Target_Software_Installation#FPGA_firmware_installation | bitstream is loaded]], run linux and modprobe pod linux module : | ||
+ | <pre class="apf"> | ||
+ | # modprobe irq_ocore | ||
+ | # modprobe pod_irq_mng | ||
+ | # modprobe led_ocore | ||
+ | # modprobe pod_leds | ||
+ | BLINK: MAJOR: 249 MINOR: 0 | ||
+ | LED module BLINK inserted | ||
+ | # modprobe i2c-ocores-pod | ||
+ | # modprobe pod_board_i2c | ||
+ | PM: Adding info for platform:ocores-i2c-pod.0 | ||
+ | PM: Adding info for No Bus:i2c-2 | ||
+ | PM: Adding info for No Bus:i2c-2 | ||
+ | # modprobe button_ocore | ||
+ | # modprobe pod_buttons | ||
+ | probing button | ||
+ | button button.0: PUSH: MAJOR: 248 MINOR: 0 | ||
+ | PUSH loaded | ||
+ | </pre> | ||
+ | |||
+ | Read [[A_simple_design_with_Wishbone_bus]] to know how to use led and button. | ||
+ | |||
+ | |||
[[Category:POD]] | [[Category:POD]] |
Latest revision as of 16:11, 26 August 2013
Contents
Introduction
In this first tutorial, we will learn how to use POD with a simple example project for an APF27 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
See POD installation guide to learn how to install it.
Note: This tutorial is written for apf27_dev a LED is already soldered on fpga. The fpga bank1 must be powered with 3.3V (connect pin 39 and pin 1 on J20 header) |
POD
If POD is correctly installed, simply type :
$ pod POD>
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> synthesis POD.synthesis>
For a complete list of the available commands type help
POD> help Documented commands (type help <topic>): ======================================== EOF create history ls shell addbusclock delbusconnection info printxml simulation addinstance delinstance generateintercon quit source autoconnectbus delpinconnection listcomponents report synthesis check description listforce savehistory generatetop closeproject driver listinstances saveproject version connectbus eof listinterfaces selectplatform connectinterface exit listmasters setaddr connectpin getmapping listplatforms setforce connectport help load setgeneric
A short help description is although available for each command.
POD> help listcomponents listcomponents [componenttype] List components available in the library POD>
Command completion and argument completion can be done by using the <TAB> key :
POD> help list<TAB> listcomponents listinterfaces listplatforms listinstances listmasters POD> help list
System commands can be used with «!» before:
POD> !echo "POD is really useful" POD is really useful POD>
Project creation
To create a project, enter the create command in the project environment:
POD> create i2cledbutton Project i2cledbutton created POD:i2cledbutton>
The i2cledbutton project is now created and saved.
The target platform has to be selected by means of the selectplatform command :
project:i2cledbutton> selectplatform standard.apf27 [INFO] : No platform in project Component platform added as apf27 Component imx27_wb16_wrapper added as imx27_wb16_wrapper00 Component rstgen_syscon added as rstgen_syscon00 Component irq_mngr added as irq_mngr00 project:i2cledbutton>
By selecting this platform, several components will be automaticaly added by POD:
- imx27_wb16_wrapper: this component is used to convert the i.MX27 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:
project:i2cledbutton> listcomponents components logics syscons test wrappers
And to list the components under a category use listcomponents again with the category name in parameter:
project:i2cledbutton> listcomponents components sp_vision_configure bram uart16750 spartan_selectmap industrial_output anybus_interface simplegpio button industrial_serial_input led uart16550 sja1000 i2cocore pod_gpio irq_mngr
The components will be loaded with the command addinstances:
POD:i2cledbutton> help addinstance addinstance <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:i2cledbutton> addinstance components.button push Component button added as push POD:i2cledbutton> addinstance components.led.wb16 blink Component led added as blink POD:i2cledbutton> addinstance 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:
project:i2cledbutton> info i2c Instance name :i2c Component name :i2cocore description : A simple button ip ->Generics id : 1 wb_size : 16 ->Interfaces irq : inta_o s1 i2c : scl s1 sda s1 swb16 Base address:0x0 rst_i s1 clk_i s1 adr_i s4 dat_i s16 dat_o s16 we_i s1 stb_i s1 ack_o s1 cyc_i s1 project:i2cledbutton>
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:i2cledbutton> 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: -> apf27.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:i2cledbutton> connectpin irq_mngr00.irq.irqport.0 i2c.irq.inta_o.0
Same thing for the push button :
POD:i2cledbutton> 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:i2cledbutton> 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: -> apf27.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 apf27 platform, the pin name can be found in FPGA schematic [1]. The name of the interface is fpga for the apf27. In this example we will connect the button, the led and the i2c to the apf27DevFull connector X7 (figure 6).
We just have to connect the pins as following :
POD:i2cledbutton> connectpin blink.int_led.led.0 apf27.fpga.IO_L24P_1 POD:i2cledbutton> connectpin push.int_button.button.0 apf27.fpga.IO_L24N_1 POD:i2cledbutton> connectpin i2c.i2c.sda apf27.fpga.IO_L20N_1 POD:i2cledbutton> connectpin i2c.i2c.scl apf27.fpga.IO_L20P_1
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:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 blink.swb16 setting base address 0x0 for blink.swb16 POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 push.swb16 setting base address 0x4 for push.swb16 POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 i2c.swb16 setting base address 0x20 for i2c.swb16 POD:i2cledbutton> connectbus imx27_wb16_wrapper00.mwb16 irq_mngr00.swb16 setting base address 0x40 for irq_mngr00.swb16
- clock & reset
Clock and reset are seen like a standard bus, to connect it, simply use connectbus:
project:i2cledbutton> connectbus rstgen_syscon00.candroutput imx27_wb16_wrapper00.candrinput No addressing value in this type of bus
- autoconnect
Bus and clock connections can be automatically performed with the autoconnect command. This command works only for "classical" architectures and with recognized busses.
POD:i2cledbutton> autoconnectbus
Intercon generation
Once the connections done, the Intercons components has to be generated. Intercons are components responsible for decoding the addresses and for routing bus signals. Intercons must be generated for each master bus.
- for wrapper master wishbone bus
POD> generateintercon imx27_wb16_wrapper00.mwb16 Intercon with name : imx27_wb16_wrapper00_mwb16_intercon Done Component imx27_wb16_wrapper00_mwb16 added as imx27_wb16_wrapper00_mwb16_intercon
- for syscon master candr bus
POD> generateintercon rstgen_syscon00.candroutput Intercon with name : rstgen_syscon00_candroutput_intercon Done Component rstgen_syscon00_candroutput added as rstgen_syscon00_candroutput_intercon
Top generation
The Top component is the component responsible for connecting all instances in the FPGA. The Top can be generated with the generatetop command
POD:i2cledbutton> generatetop Mapping for interface mwb16: Address | instance.interface | size --------------------------------------------------------- 0x0 | blink.swb16 | 4 0x4 | push.swb16 | 4 0x08 | --void-- | 24 0x20 | i2c.swb16 | 32 0x40 | irq_mngr00.swb16 | 8 --------------------------------------------------------- Top generated with name : top_i2cledbutton.vhd
Synthesis
In the apf27 platform, the FPGA is a Spartan3A 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 [2].
POD has to generate a project that ISE can understand. This can be accomplished from the synthesis environment :
POD:i2cledbutton-tutorial> synthesis POD.synthesis>
Then the tool used for the synthesis has to be specified with the selecttoolchain command:
POD.synthesis> selecttoolchain ise
After that we can generate an ISE project with the generateproject command.
POD> synthesis POD.synthesis> selecttoolchain ise POD.synthesis> generateproject Make directory for imx27_wb16_wrapper Make directory for rstgen_syscon Make directory for irq_mngr Make directory for button Make directory for led Make directory for i2cocore Make directory for rstgen_syscon00_candroutput Make directory for imx27_wb16_wrapper00_mwb16 Constraint file generated with name : /home/fabien/tmp/i2cledbutton/synthesis/i2cledbutton.ucf TCL script generated with name : i2cledbutton.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>
First select your toolchain (here it's ghdl):
POD.project:i2cledbutton_tutorial.simulation> selecttoolchain ghdl
To generate the testbench and the makefile use the command:
POD.project:i2cledbutton_tutorial.simulation> generateproject 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:i2cledbutton_tutorial> driver POD:i2cledbutton_tutorial.driver>
choose the targeted platform:
POD:i2cledbutton_tutorial.driver> selecttoolchain armadeus
And generate the driver project :
POD: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:i2cledbutton_tutorial.driver> selectprojecttree ~/armadeus/target/linux/modules/fpga/POD POD:i2cledbutton_tutorial.driver> copydrivers
To compile the drivers, go to your armadeus/ directory, then:
$ make linux-menuconfig
Device Drivers ---> ... [*] Support for specific Armadeus drivers ---> ... *** FPGA related *** [*] FPGA specific drivers and tools ---> ... [*] Board drivers generated by POD
$ make
Test
Once bitstream is loaded, run linux and modprobe pod linux module :
# modprobe irq_ocore # modprobe pod_irq_mng # modprobe led_ocore # modprobe pod_leds BLINK: MAJOR: 249 MINOR: 0 LED module BLINK inserted # modprobe i2c-ocores-pod # modprobe pod_board_i2c PM: Adding info for platform:ocores-i2c-pod.0 PM: Adding info for No Bus:i2c-2 PM: Adding info for No Bus:i2c-2 # modprobe button_ocore # modprobe pod_buttons probing button button button.0: PUSH: MAJOR: 248 MINOR: 0 PUSH loaded
Read A_simple_design_with_Wishbone_bus to know how to use led and button.