Difference between revisions of "A simple design with Wishbone bus"

From ArmadeusWiki
Jump to: navigation, search
m (beautifying)
(beautifying)
Line 68: Line 68:
 
== Wishbone slave application components ==
 
== Wishbone slave application components ==
  
In this example their are 3 wishbone-slave components :
+
In this example there are 3 Wishbone-slave components :
  
 
=== irq manager ===
 
=== irq manager ===
  
Some component (here, just button) generate interrupts, [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/firmware/wishbone_example/src/irq_mngr.vhd?view=markup irq manager] is used to
+
Some components (here, only ''button'') generate interrupts, [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/firmware/wishbone_example/src/irq_mngr.vhd?view=markup irq manager] is used to mux these interrupts for i.MX. The irq_mngr can manage up to 16 internal interrupts.  
group these interrupts for i.MX. The irq_mngr can manage up to 16 internal
+
interrupts.  
+
  
 
IRQ manager component has tree registers, one to enable interrupts, one for flags/acknowledge interrupts and one identification register :
 
IRQ manager component has tree registers, one to enable interrupts, one for flags/acknowledge interrupts and one identification register :
  
{| class="wikitable" align="center" style="text-align:center; width:30%;" border="1"
+
{| align="center" border="1" cellpadding="5" cellspacing="0" summary="irq_mgr registers"
|-
+
|- style="background:#efefef;" align="center"
! bgcolor=lightgray scope=col | register
+
! register !! function
! bgcolor=lightgray scope=col | function
+
 
|-
 
|-
 
| mask
 
| mask
Line 100: Line 97:
 
This component is a simple 16-bit Wishbone slave output port, from [http://www.opencores.org/projects.cgi/web/wishbone/wbspec_b3.pdf wishbone specification example] (p110).
 
This component is a simple 16-bit Wishbone slave output port, from [http://www.opencores.org/projects.cgi/web/wishbone/wbspec_b3.pdf wishbone specification example] (p110).
  
[[image:wbs_led.png|center|frame|'''figure 3''' - ''LED internal structure''|600px]]
+
[[image:wbs_led.png|center|thumb|600px|'''figure 3''' - ''LED internal structure'']]
  
 
It is a simple register, that can be read and write. The LED is controlled with register pin 0.
 
It is a simple register, that can be read and write. The LED is controlled with register pin 0.
Line 106: Line 103:
 
The two registers are :
 
The two registers are :
  
{| class="wikitable" align="center" style="text-align:center; width:30%;" border="1"
+
{| align="center" border="1" cellpadding="5" cellspacing="0" summary="wb_led registers"
 +
|- style="background:#efefef;" align="center"
 +
! register !! function
 
|-
 
|-
! bgcolor=lightgray scope=col | register
+
| LED || Write '1' in LSB to shutdown LED
! bgcolor=lightgray scope=col | function
+
 
|-
 
|-
| LED
+
| id || read identification number
| Write '1' in LSB to shutdown LED
+
|-
+
| id
+
| read identification number
+
 
|}
 
|}
  
Line 122: Line 116:
 
Wb_button component, is like ''led'' but in read only and with an edge detector to rise irq.
 
Wb_button component, is like ''led'' but in read only and with an edge detector to rise irq.
  
[[image:wbs_button.png|center|frame|'''figure 4''' - ''Button internal structure''|500px]]
+
[[image:wbs_button.png|center|thumb|500px|'''figure 4''' - ''Button internal structure'']]
  
 
The two registers are:
 
The two registers are:
  
{| class="wikitable" align="center" style="text-align:center; width:30%;" border="1"
+
{| align="center" border="1" cellpadding="5" cellspacing="0" summary="wb_button registers"
 +
|- style="background:#efefef;" align="center"
 +
! register !! function
 
|-
 
|-
! bgcolor=lightgray scope=col | register
+
| Button || read LSB to know button state
! bgcolor=lightgray scope=col | function
+
 
|-
 
|-
| Button
+
| id || read identification number
| read LSB to know button state
+
|-
+
| id
+
| read identification number
+
 
|}
 
|}
  

Revision as of 19:40, 4 June 2009

This article is intended to explain how to design Wishbone compatible components with simple example. The VHDL source code can be found in sourceforge tree.

Description of the Wishbone structure for ARMadeus can be found here (in french).

General structure

The main functionality of this component is to do the same things that benoît's project : switch on a LED when a button is pressed.

But to learn more about Wishbone component design and Linux driver devt, we have make the thing a little more complicated (!).

When button is pressed, the component button send interrupt signal to irq_mngr. irq_mngr will toggle a flag and send interruption to i.MX processor. A Linux driver on i.MX will read irq_mngr and acknowledge irq by writing '1' on a register. And finally, Linux driver will toggle LED value by writing on led register.

figure 1 - Schematics of wishbone example

imx_wrapper, syscon and irq_mngr are standards ARMadeus-Wishbone IPs that just been instantiated in our design.

button and led are simple slave component we want to integrate in the FPGA.

All these components are connected together with the 'glue logic' component intercon.

Wrapper

The wrapper is used to convert i.MX interface signals into Wishbone signals. Table above show signals from i.MX and signals to wishbone conversion :

i.MX signals function Wishbone signals
imx_address(12) Address vector wbm_address(13)
imx_data(16) Data vector wbm_writedata(16) and wbm_readdata(16)
imx_cs_n Chip select wbm_strobe and wbm_cycle
imx_oe_n Read signal /wbm_write
imx_eb3_n Write signal wbm_write
- Acknowledge wbm_ack

Intercon

The intercon is a component used to manage signals between Wishbone master and slave components. This component decode Wishbone-master addresses and dispatch them to Wishbone-slave components.

figure 2 - Intercon internal structure

Wishbone slave application components

In this example there are 3 Wishbone-slave components :

irq manager

Some components (here, only button) generate interrupts, irq manager is used to mux these interrupts for i.MX. The irq_mngr can manage up to 16 internal interrupts.

IRQ manager component has tree registers, one to enable interrupts, one for flags/acknowledge interrupts and one identification register :

register function
mask write '1' to allow irq
ack/pend read for pending irq, write to acknowledge irq
id identification register


wb_led

Note Note: On apf9328_devfull and on apf27_dev a LED is already soldered on fpga. For apf27_dev the fpga bank1 must be powered with 3.3V (connect pin 39 and pin 1 on J20 header)


This component is a simple 16-bit Wishbone slave output port, from wishbone specification example (p110).

figure 3 - LED internal structure

It is a simple register, that can be read and write. The LED is controlled with register pin 0.

The two registers are :

register function
LED Write '1' in LSB to shutdown LED
id read identification number

wb_button

Wb_button component, is like led but in read only and with an edge detector to rise irq.

figure 4 - Button internal structure

The two registers are:

register function
Button read LSB to know button state
id read identification number

Components drivers

Each component is drove with a Linux driver described above. All driver code is in armadeus directory in target/linux/module/fpga/wishbone_example/.

Each component has an identification register with unique number. This number is used by driver to unsure that device is present when it modproded.

irq manager

The description of IRQ management module is available here. The module code source can be found here.

LED

LED driver is seen in linux like a character driver. Writing in dev file will enable or disable LED.

The driver is composed of two modules :

  • g_led : this module implement generic LED driver mechanisms.
  • board_led : This module describe specific datas for each LED-component available in design. These datas are described in structure plat_led_port and plat_led_device. The module will register each LED with platforme_device_register function. When a plat_led__port device is registered, g_led driver will detect it and will probe it with led_probe function.

button

Button driver is seen in Linux like a character driver. When a process want to read value in button register, the driver will block reading until an interrupt occur.

Structure of button driver is similar to LED driver, it is decomposed in two modules :

  • gbutton : This module implement generic button driver mechanisms.
  • board_button : Like LED module, this module describe specifics datas for each button-component available in design.

Using the design

All code for this design is available in ARMadeus tree, firmware (VHDL) and software (Linux drivers).

Make the FPGA bitstream

ISE Webpack is mandatory to generate the bitstream, then its installation is required. Once bitstream generated, it can be downloaded in FPGA with U-Boot or Linux.

Compile Linux drivers

To compile the drivers for this design select them in Linux menuconfig:

 $ make linux26-menuconfig
    Device Drivers --->
        Armadeus specific drivers --->
            FPGA Drivers --->
                [*] Drivers for wishbone example 
                <M>     Wishbone Button driver
                <M>     Wishbone LED driver
                <M>     IRQ manager with wishbone interface

and compile them:

$ make linux26 && make

Then reflash Linux and rootfs images.

Play with button and LED

Mount modules

Modules must be mounted in right order with modprobe command :

  • IRQ manager :
# modprobe irq_ocore
  • Button generic module must be mounted before board module:
# modprobe gbutton
# modprobe board_buttons
BUTTON0: MAJOR: 251 MINOR: 0
button: irq registered : 193
BUTTON0 insered
  • LED generic module must be mounted before board module:
# modprobe g_led
# modprobe board_leds
LED0: MAJOR: 252 MINOR: 0
LED module LED0 insered

Device access

Devices access are done with special caracters file. These file must be created with major and minor number given when modules are mounted (see Mount modules above in this page) :

  • Make LED access :
# mknod /dev/led0 c 252 0
  • Make button access :
# mknod /dev/button0 c 251 0

Test LED

A test program is available in module directory, simply compile it with arm-linux-gcc compiler :

$ arm-linux-gcc testled.c -o testled

Download it in apf, then test it :

# ./testled /dev/led0 
Testing led driver
Read 1
Write 0
Read 0
Write 1
Read 1
Write 0
Read 0

LED is blinking slowly.

Test Button

A test program is available in module directory, simply compile it with arm-linux-gcc compiler :

$ arm-linux-gcc testbutton.c -o testbutton
# ./testbutton /dev/button0
Testing button driver
Read 1
Read 0
Read 1
Read 0
Read 1
Read 0
Read 0
Read 1
Read 0
Read 1

Each button push or release activate reading register value.

Switching LED with button

A simple program is available in wishbone example directory to switch on the LED when button is pressed.

To compile :

arm-linux-gcc push-led.c -o push-led

To use it, simply type :

# ./push-led /dev/button0 /dev/led0 
Blink a led pushing button

Push the button to switch on the LED.