LOGI - Wishbone - HW

From ValentFx Wiki
Jump to: navigation, search

Contents

Overview

The LOGI boards were designed with the goal of being able to easily communicate between the FPGA and the host CPU of the Rpi or BBB.  To achieve this goal the wishbone bus was chosen to be used to as the main interface on the FPGA.  The wishbone bus serves as a single master multi slave architecture which allows the wishbone master on the FPGA to easily interconnect any number of peripherals residing on the FPGA to the host CPU.  The host CPU communicates with the wishbone master using it's native communication protocols which are GPMC or SPI on the BBB and SPI on the Raspberry Pi.  

HW/SW Overview and details regarding the project/component

Connecting components to the Wishbone bus

The wishbone bus is a high performance open source bus that support the following topologies:

  • Master -> slaves
  • Multi-master

The LOGI-board currently only supports the Master -> slaves topology to avoid overloading the FPGA logic with bus related logic. The current implementation is based on 16-bit data width and 16 bit address width for the same reason. In its Master -> slaves topology a wishbone topology relies on two main components.

  • The Wishbone master, that generates all the wishbone signals
  • The Wishbone intercon that is in charge of the adressing of all the slaves on the bus

In the case of a unique slave on the wishbone bus, the intercon is not required.

 

 

The LOGI-hard library of the logi projects proposed a simplified generic implementation of the Intercon component and a Wishbone master specific to the LOGI-Pi and the LOGI-Bone.

The LOGI-Bone specific Wishbone master, generates its signals based on the GPMC interface of the beaglebone-black. For this purpose the GPMC is configured in 16 bit synchronous interface with address/data multiplexed. The wishbone master signals are directly inferred from the GPMC signals.

The LOGI-Pi specific Wishbone master, generates its signals from a slave SPI interface. In this case the SPI bus (serial bus) implements a low level protocol that generates the wishbone signals. A SPI transaction to control the wishbone bus is organized as follows.

  1. The SPI master (the raspberry-pi) asserts the slave select signals to indicate start of a transaction. The SPI slave detects the beginning of the transacaction and resets all its internal signals
  2. The SPI master sends a 16-bit data (MSB first) organized as follows:
    1. 14 bits that indicates the start address of the transaction
    2. 1 bit (read/write bit) indicating whether its a read transaction or a write transaction
    3. 1 bit (burst bit) indicating if the address needs to be increased after each usbsequent operation
  3. The SPI slave decodes the 16 bit command word and sets the wishbone address and internal signals to indicate a read or write operation
  4. For a read operation, the SPI master sends 16 clock ticks and the SPI slave sends the data at the address set by the command word. If the burst bit is set, the address is increased after each word access
  5. For write operation, the SPI master sends 16 bits that are written at the configured address. If the burst bit is set, the address is increased after each word access.
  6. When the transaction is complete, the SPI master de-asserts the slave select signal to indicate the transaction is over

Wishbone addressing in the HDL

Each wishbone slave peripheral needs to have an address assigned in the HDL design.  The addreses are assign in the top level wishbone architecture of the ISE project. Below is an example of addressing which is used in the logi-apps wishbone project.  The wishbone project uses three slave peripherals including a Register, PWM, and memory slave periphaerals.  

reg_cs       <= '1' when intercon_wrapper_wbm_address(15 downto 2) = "00000000000000" else  '0' ;         

pwm0_cs  <= '1' when intercon_wrapper_wbm_address(15 downto 3) = "00000000000001"  else  '0' ;

mem0_cs <= '1' when intercon_wrapper_wbm_address(15 downto 11) = "00001"  else '0' ;

The peripherals are addressed as follows based up on the HDL description:

  • Register base address   = 0x0000
  • PWM base address         = 0x0008
  • Memory base address    = 0x0800

Each peripheral is further broken down into registers.  The register layout Register and PWM wishbone peripherals are as follows.

WISHBONE ADDRESSES ********************************************************************************

address       |    name       |    note    |
0x0000         register_0        read :0xDEAD
0x0002         register_1           read : 0xBEEF 
0x0004         register_3           read/write register
0x0006         register_4           write pmod2/read pmod1 and switches
0x0010         pwm_divider       system_clock divider for pwm
0x0012         pwm_period           pwm signal period
0x0014         pwm0_high           high time for pwm0 (unconnected)
0x0016         pwm1_high           high time for pwm1 connected to LED0

0x0018         pwm2_hight           high time for pwm2 connected to LED1

 

These addresses are no longer valid with recent changes.  The factor of 2 seems to no longer apply?  Where the factor of 2 change?

previous version of the library was using byte addressing for the logibone and word addressing for the logipi, now both uses word addressing so the address directly match what is configured in HDL.

Read/Write Wishbone from C Libraries

The c library function calls to read and write to the wishbone peripherals are as follows.

int logipi_write(unsigned int add, unsigned char * data, unsigned int size, unsigned char inc);
int logipi_read(unsigned int add, unsigned char * data, unsigned int size, unsigned char inc);

The parameter descriptions are as follows

  • add: the address of the wishbone peripheral to read or write to
  • * data: pointer to data to read/wirte to wishbone
  • size: number bytes to be written ???????????? Size is expressed in bytes
  • inc: increment value of the address for each write ????????????? This is still a problem because it does not work with logibone ...
unsigned int wishbone_read(unsigned char * buffer, unsigned int length, unsigned int address)
int logipi_read(unsigned int add, unsigned char * data, unsigned int size, unsigned char inc)

What is the differnce between the logipi_write and the wishbone_write????????

they are exactly the same, I thought that it would be best to unify python and c for the functions prototypes.

 

Read/Write Wishbone from Python Libraries

python c wrapper build file:

static PyObject* logiWrite(PyObject* self, PyObject* arg)
static PyObject* logiRead(PyObject* self, PyObject* arg)

python final function calls

logiWrite(0x0008, (0x04, 0x00))
logiWrite(0x0009, (0x00, 0x08))

Can you explain how the tuples work here?  The function is very different from the c function call as there is no "size" and "inc" parameters as is the case in the c function call.

in python the size is extracted form the tuple length. I think I am gonna drop the inc parameter to be consistent between c and python.

It appears that the "size" and "inc" paramters are taken care of in the python to c wrapper?  

 

Where to go from here

  • Limitations of the current state of the project

  • Example application using the same project structure

References

  • Github

  • Videos

  • Logi-apps

  • blog

  • Other referenced resources
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox