New Horizons






<< August 2007 >>
Sun Mon Tue Wed Thu Fri Sat
 01 02 03 04
05 06 07 08 09 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31


Table of content

New Horizons
What's new
Starting a blog
Writing a blog
I got a job

SystemC
SystemC from scratch. Part 1
SystemC from scratch. Part 2
SystemC from scratch. Part 3

ASIC/FPGA Design
Table of content
Index
FPGA design from scratch. Part 1
FPGA design from scratch. Part 2
FPGA design from scratch. Part 3
FPGA design from scratch. Part 4
FPGA design from scratch. Part 5
FPGA design from scratch. Part 6
FPGA design from scratch. Part 7
FPGA design from scratch. Part 8
FPGA design from scratch. Part 9
FPGA design from scratch. Part 10
FPGA design from scratch. Part 11
FPGA design from scratch. Part 12
FPGA design from scratch. Part 13
FPGA design from scratch. Part 14
FPGA design from scratch. Part 15
FPGA design from scratch. Part 16
FPGA design from scratch. Part 17
FPGA design from scratch. Part 18
FPGA design from scratch. Part 19
FPGA design from scratch. Part 20
FPGA design from scratch. Part 21
FPGA design from scratch. Part 22
FPGA design from scratch. Part 23
FPGA design from scratch. Part 24
FPGA design from scratch. Part 25
FPGA design from scratch. Part 26
FPGA design from scratch. Part 27
FPGA design from scratch. Part 28
FPGA design from scratch. Part 29
FPGA design from scratch. Part 30
FPGA design from scratch. Part 31
FPGA design from scratch. Part 32
FPGA design from scratch. Part 33
FPGA design from scratch. Part 34
FPGA design from scratch. Part 35
FPGA design from scratch. Part 36
FPGA design from scratch. Part 37
FPGA design from scratch. Part 38
FPGA design from scratch. Part 39
FPGA design from scratch. Part 40
FPGA design from scratch. Part 41
FPGA design from scratch. Part 42
FPGA design from scratch. Part 43
FPGA design from scratch. Part 44
FPGA design from scratch. Part 45
FPGA design from scratch. Part 46
FPGA design from scratch. Part 47
FPGA design from scratch. Part 48
FPGA design from scratch. Part 49
FPGA design from scratch. Part 50
Links
Acronyms and abbreviations
XCell Journals
CAD
A hardware designer's best friend
Zoo Design Platform
Linux
Installing Ubuntu Linux on a MacBook
Customizing Ubuntu Linux 1
Customizing Ubuntu Linux 2
Upgrading to Ubuntu 7.04
Install Ubuntu 7.04 with VMware
Making the virtual machine run faster
Ubuntu Links
A processor benchmark
Mac
Porting a Unix program to Mac OS X
Fixing a HyperTerminal in Mac OS X
A dream come true
Wireless freedom
Running
The New York City Marathon
Skiing/Skating
Kittelfjäll Lappland
Tour skating in Sweden and around the world
Top
Introduction
SSSK
Wild skating
Tour day
Safety equipment
A look at the equipment you need
Skate maintenance
Calendar
Links
Books, photos, films and videos
Weather forecasts
Travel
38000 feet above see level
A trip to Spain
Florida the sunshine state


Example Files
Verilog Testbench Body
Verilog Testcase
Verilog Setup
Simulation Result File
Simulation Report File




Photo Albums
Seaside Florida
Ronda Spain
Sevilla Spain
Cordoba Spain
Alhambra Spain
Kittelfjäll Lapland
Landsort Art Walk
Skating on thin ice


Favorites
Adventures in ASIC
ChipHit
Computer History Museum
Community of Sweden
DeepChip
Design & Reuse
Dilbert
EDA Cafe
EDA DesignLine
Embedded.com
EmbeddedRelated.com
FPGA Arcade
FPGA Blog
FPGA Central
FPGA Journal
FPGA World
MacApper
Mac geekery
Mac 2 Ubuntu
Get Perpendicular
Programmable Logic DesignLine
History of Linux
OpenCores
ORSoC
Simplehelp
SOCcentral
World of ASIC



New York City Marathon




If you want to be updated on this weblog Enter your email here:



rss feed



 
Aug 12, 2007
FPGA design from scratch. Part 39
Fixing our software device driver

Let's modify our template files and start with the .tcl file.

etc_v2_1_0.tcl

The .tcl script file copies the parameters we specify to the xparameters.h and xextc_g.c files during library generation. It looks like this after modifications.

proc generate {drv_handle} {
  set level [xget_value $drv_handle "PARAMETER" "level"]
  xdefine_include_file $drv_handle "xparameters.h" "XEtc" "NUM_INSTANCES" "MEM_BANK0_BASE_ADDR" "MEM_BANK0_HIGH_ADDR" "MEM_BANK1_BASE_ADDR" "MEM_BANK1_HIGH_ADDR" "REGISTER_BASE_ADDR" "REGISTER_HIGH_ADDR" "DEVICE_ID" "C_INTERRUPT_PRESENT"
  xdefine_config_file $drv_handle "xetc_g.c" "XEtc"  "DEVICE_ID" "MEM_BANK0_BASE_ADDR" "MEM_BANK1_BASE_ADDR" "REGISTER_BASE_ADDR" "C_INTERRUPT_PRESENT"
}

This is the result taken from the xparameters.h file.

/* Definitions for driver ETC */
#define XPAR_XETC_NUM_INSTANCES 1

/* Definitions for peripheral ETC_0 */
#define XPAR_ETC_0_MEM_BANK0_BASE_ADDR 0x42a08000
#define XPAR_ETC_0_MEM_BANK0_HIGH_ADDR 0x42a08fff
#define XPAR_ETC_0_MEM_BANK1_BASE_ADDR 0x42a09000
#define XPAR_ETC_0_MEM_BANK1_HIGH_ADDR 0x42a09fff
#define XPAR_ETC_0_REGISTER_BASE_ADDR 0x71A00000
#define XPAR_ETC_0_REGISTER_HIGH_ADDR 0x71A0001F
#define XPAR_ETC_0_DEVICE_ID 0
#define XPAR_ETC_0_INTERRUPT_PRESENT 0

etc_v2_1_0.tcl.mdd

The .mdd file looks like this.
The "copyfiles" line instructs the EDK tools to copy the source files into the user's project directory and compile them from there.

OPTION psf_version = 2.1;

BEGIN driver etc

  OPTION supported_peripherals = (ETC_0);
  OPTION driver_state = ACTIVE;
  OPTION depends = (common_v1_00_a);
  OPTION copyfiles = all;

 BEGIN INTERFACE linux
 END INTERFACE

 BEGIN ARRAY interrupt_handler
 END ARRAY

END driver



Makefile

In the Makefile we have to add all header file under INCLUDEFILES. This will copy the header files to the directory include during library generation.

COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a

RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}

INCLUDEFILES=xetc.h xetc_l.h xetc_i.h

LIBSOURCES=*.c
OUTS = *.o


xetc_g.c


The xetc_g.c is automatically generated by Libgen. Here is the configuration table taken from the xetc_g.c file.


/*
* The configuration table for devices
*/

XEtc_Config XEtc_ConfigTable[] =
{
    {
        XPAR_ETC_0_DEVICE_ID,
        XPAR_ETC_0_MEM_BANK0_BASE_ADDR,
        XPAR_ETC_0_MEM_BANK1_BASE_ADDR,
        XPAR_ETC_0_REGISTER_BASE_ADDR,
        XPAR_ETC_0_INTERRUPT_PRESENT
    }

xetc.h

The following type definition are modified to match with the configuration table shown above.


/**
 * This typedef contains configuration information for the device.
 */
typedef struct
{
    Xuint16  DeviceId;          /* Unique ID  of device */
    Xuint32  Mem0_BaseAddress;  /* Memory bank0 base address */
    Xuint32  Mem1_BaseAddress;  /* Memory bank1 base address */
    Xuint32  Reg_BaseAddress;   /* Register bank base address */
    Xboolean InterruptPresent;  /* Are interrupts supported in h/w */
} XEtc_Config;

/**
 * The XEtc driver instance data. The user is required to allocate a
 * variable of this type for every ETC device in the system. A pointer
 * to a variable of this type is then passed to the driver API functions.
 */
typedef struct
{
    Xuint32  Mem0_BaseAddress;  /* Memory bank0 base address */
    Xuint32  Mem1_BaseAddress;  /* Memory bank1 base address */
    Xuint32  Reg_BaseAddress;   /* Register bank base address */
    Xuint32  IsReady;           /* Device is initialized and ready */
    XEtc_Config *ConfigPtr;     /* Pointer to the configuration */
} XEtc;

xetc_l.h

For the lowest level we only need to provide register read an write functions. We will use the Xilinx standard routines XIo_Out32 and XIo_in32 to give us these functions.

/****************************************************************************/
#define XEtc_mWriteReg(BaseAddress, RegOffset, Data) XIo_Out32((BaseAddress) + (RegOffset), (Xuint32)(Data))

/****************************************************************************/
#define XEtc_mReadReg(BaseAddress, RegOffset)  XIo_In32((BaseAddress) + (RegOffset))

The XIo_Out32 and XIo_In32 are defined in the header file xio.h found in the include directory.

* Performs an input operation for a 32-bit memory location by reading from the
* specified address and returning the value read from that address.
*
* @param    InputPtr contains the address to perform the input operation at.
*
* @return   The value read from the specified input address.
*

#define XIo_In32(InputPtr)  (*(volatile Xuint32 *)(InputPtr))


* Performs an output operation for a 32-bit memory location by writing the

* specified value to the the specified address.
*
* @param    OutputPtr contains the address to perform the output operation at.
* @param    Value contains the value to be output at the specified address.
*
* @return   None.
*

#define XIo_Out32(OutputPtr, Value) (*(volatile Xuint32 *)((OutputPtr)) = (Value))


Writing an application program

We will start out writing a low level application program only using the read/write functions. Here is an example:

//$$INCLUDE
/*************************************************************************/
/*                                                                       */
/*                     I N C L U D E   H E A D E R   F I L E S           */
/*                                                                       */
/*************************************************************************/

#include "xparameters.h"
#include "xetc.h"
#include "xetc_l.h"
#include "xutil.h"
#include <stdio.h>


//$$DEFINE
/*************************************************************************/
/*                                                                       */
/*                       D E F I N E   C O N S T A N T S                 */
/*                                                                       */
/*************************************************************************/

// The following constant maps to the name of the hardware instances that
// were created in the EDK XPS system.

#define  ETC_REG_BASEADDR      XPAR_ETC_0_REGISTER_BASE_ADDR
 
// The following parameters are used to setup the ETC
#define  ENABLE_INTERRUPT      0X1000
#define  DISABLE_INTERRUPT     0X0
#define  ENABLE_LOOP_MODE      0x800
#define  DISABLE_LOOP_MODE     0x0
#define  SKIP_TDO_SHIFTIR      0x200
#define  SKIP_TDO_SHIFTDR      0x400
#define  DISABLE_SINGLE_STEP   0x0
#define  ENABLE_SINGLE_STEP    0x100
#define  DISABLE_TCK           0x0
#define  ENABLE_TCK            0x80
#define  CLOCK_RATE_DIV_BY_4   0x0
#define  CLOCK_RATE_DIV_BY_8   0x10
#define  CLOCK_RATE_DIV_BY_16  0x20
#define  CLOCK_RATE_DIV_BY_32  0x30
#define  CLOCK_RATE_DIV_BY_64  0x40
#define  EXTERNAL_TEST         0x8

#define  START_ETC             0x1
#define  STOP_ETC              0x0

//$$FUNCTIONS
/*************************************************************************/
/*                                                                       */
/*                       D E F I N E   F U N C T I O N S                 */
/*                                                                       */
/*************************************************************************/

void usleep(unsigned int useconds)
{
  int i,j;
  for (j=0;j<useconds;j++)
    for (i=0;i<26;i++) asm("nop");
}

//$$ETC TEST PROGRAM
/*************************************************************************/
/*                                                                       */
/*                     E T C   T E S T  P R O G R A M                    */
/*                                                                       */
/*************************************************************************/


// Define testprogram

// TestResetKeepingTrstzLow (10);
// LoadInstruction(INSTRUCTION_LENGTH,IDCODE);
// ReadWriteDataRegister(IdentificationRegLen+20,{{IdentificationRegLen{1'b0}},20'b1110011101});
// SetExpectedData(IdentificationRegLen+20,{20'b1110011101,{IdentificationRegLen{1'bx}}});
// EndOfTestProgram;

 Xuint32 TestProgram[] = {

     
  0x800000a1,
  0xc0000043,
  0x00000002,
  0xc0340004,
  0x4000039d,
  0x00000000,
  0x8000000c };
 
  int  ProgramSize =  7;


//$$MAIN
/*************************************************************************/
/*                                                                       */
/*                        M A I N   P R O G R A M                        */
/*                                                                       */
/*************************************************************************/


int main(void) {

    int               i;
    Xuint32  StatusReg;
   
    print("Load test program ");
   
    // Load test program to test program RAM
    for (i = 0; i < ProgramSize; i++) {
           XEtc_mWriteReg(XPAR_ETC_0_MEM_BANK0_BASE_ADDR, i*4, TestProgram[i]);   
    };

    // Write to control register
    XEtc_mWriteReg(ETC_REG_BASEADDR, XETC_CONTROL_REG_OFFSET,
        DISABLE_INTERRUPT +
        DISABLE_LOOP_MODE +
        SKIP_TDO_SHIFTIR +
        DISABLE_SINGLE_STEP +
        ENABLE_TCK +
        CLOCK_RATE_DIV_BY_4 +
        EXTERNAL_TEST);
   
    print("Start test ");
    // Start test
    XEtc_mWriteReg(ETC_REG_BASEADDR, XETC_EXECUTE_REG_OFFSET,
        START_ETC);
 
   // Wait for test to finish
   usleep(4);

    print("Stop test ");
    // Stop test
    XEtc_mWriteReg(ETC_REG_BASEADDR, XETC_EXECUTE_REG_OFFSET,
        STOP_ETC);
       
    // Stop TCK
    XEtc_mWriteReg(ETC_REG_BASEADDR, XETC_CONTROL_REG_OFFSET,
        DISABLE_INTERRUPT +
        DISABLE_LOOP_MODE +
        SKIP_TDO_SHIFTIR +
        DISABLE_SINGLE_STEP +
        DISABLE_TCK +
        CLOCK_RATE_DIV_BY_4 +
        EXTERNAL_TEST);

   // Read status register
   print("Read status register ");  
   StatusReg = XEtc_mReadReg(ETC_REG_BASEADDR, XETC_STATUS_REG_OFFSET);
   xil_printf("Status reg : %x ",StatusReg);


   return 0;
   
    }

Print statements

To save memory space we don't use the standard print routines like printf. Instead we use <xil_printf>and <print>.  


Printout from program

After compiling and linking the program we download it to our design. The program starts and prints out the following text:

Load test program
Start test
Stop test
Read status register
Status reg : 3464


The value in the status register tells us that the testprogram ran successfully. We have written our first application program to drive the ETC. One more milestone reached.


Generate HDL simulation files

We can use the following command from the commandline to generate the HDL simulation files.

==> cd /home/svenand/root/projects/ETC/xps
==> simgen -f simgen.opt

Here is the output:

Simulation Model Generator
Xilinx EDK 9.1.01 EDK_J_SP1.3
Copyright (c) 1995-2007 Xilinx, Inc.  All rights reserved.
Command Line: simgen -p xc4vfx12ff668-10 -lang vhdl -pe microblaze_0
SDK_projects/ETC_system_program/Debug/ETC_system_program.elf -mixed yes -s ncs
-tb -X /home/svenand/root/projects/ETC/verification/database/ncsim/macrolib/ -E
/home/svenand/root/projects/ETC/verification/database/ncsim/edklib/ -m
behavioral ETC_system.mhs

MHS file              : /home/svenand/root/projects/ETC/xps/ETC_system.mhs
Language (-lang)      : VHDL
Simulation Model (-m) : Behavioral
Simulator (-s)        : NcSim (NCS)
Part (-p) [ family ]  : xc4vfx12ff668-10 [ virtex4 ]
Output directory (-od): /home/svenand/root/projects/ETC/xps/

Edklib (-E) :
/home/svenand/root/projects/ETC/verification/database/ncsim/edklib/
Xlib (-X)   :
/home/svenand/root/projects/ETC/verification/database/ncsim/macrolib/

..........

Analyzing file
/home/svenand/root/projects/ETC/xps/SDK_projects/ETC_system_program/Debug/ETC_sy
stem_program.elf...
INFO:MDT - BRAM lmb_bram will be initialized with ELF of processor microblaze_0
Running Data2Mem with the following command:
data2mem -bm ETC_system_sim.bmm  -bd
/home/svenand/root/projects/ETC/xps/SDK_projects/ETC_system_program/Debug/ETC_sy
stem_program.elf tag microblaze_0  -u  -o u tmpucf.ucf

Generating simulator compile script ...

Generating the BRAM initialization file

If we only changed the application program file (.elf) we don't have to generate all the HDL simulation files. We only need the BRAM initialization file:  ETC_system_init.vhd. This file can generated in these two steps:
  1. Use data2mem to convert the .elf file to a .ucf file
  2. Use ucf2vhdl.pl to convert the .ucf file to a .vhdl file
==> cd /home/svenand/root/projects/ETC/xps/simulation/behavioral

==> data2mem -bm ETC_system_sim.bmm  -bd /home/svenand/root/projects/ETC/xps/SDK_projects/ETC_system_program/Debug/ETC_sy
stem_program.elf tag microblaze_0  -u  -o u tmpucf.ucf

==> xilperl /home/svenand/cad/edk91i/bin/lin/ucf2vhdl.pl tmpucf.ucf ETC_system_init.vhd ETC_system ETC_system_conf vhdl

Running a simulation

Here is the same application program running in a simulation.




Top  Next  Previous



Posted at 08:56 am by svenand
Make a comment  

 
Aug 1, 2007
Parallels versus VMware
How good is our virtual machine and is there a difference between Parallels Desktop and VMware Fusion when it comes to execution speed. Let's find out.  We will benchmark the two. Here is what we have.

Hardware

MacBook Intel Core 2 Duo. 2.0 GHz with 1Gb of memory.

Host software

Mac OS X 10.4.10 and the virtual machines Parallels Desktop 3.0 and VMware Fusion 1.0.


Virtual machine software

Ubuntu Linux 7.04 Feisty


Virtual machine setup

512 Mb of memory. One virtual CPU.

Applications


We will use the following Xilinx FPGA tools in our benchmark.
The netlist generation tool runs the Xilinx tool XST to synthesis a complete FPGA design. The bitstream generation tool does the  place and route of the whole design and generates the bitstream to configure the FPGA. Both tools are very compute intensive, using more than 90% of the processor time.


Result

 Task Execution time [s]
Parallels Desktop
Execution time [s]
VMware Fusion
 Netlist generation
 585  556
 Bitstream generation
 255  245


Conclusion


The difference between the two virtual machines is very small and that is what we expected. This benchmark is not very comprehensive and should not be used as a deciding factor.






Posted at 10:41 pm by svenand
Make a comment  

 
Jul 12, 2007
FPGA design from scratch. Part 38

Writing software for our embedded system

I think we are ready to start writing some software to drive our embedded test controller. To make the application software easier to write and understand we will first come up with a software device driver for the ETC.

Writing a software device driver

As it says in the Xilinx Documentation:
Many of you have used embedded microprocessors in your recent FPGA designs. Some of you are experienced embedded processor users, and some of you are beginners to this method of design in FPGAs. Most embedded processor designers will at some stage decide that they need to incorporate a block of custom hardware into the processor system and then control it from software running on the processor. This is often a daunting task, and one that causes much confusion to the designer. This TechXclusive takes a step-by-step approach to designing a custom peripheral for use in an embedded processor system, then looks at some more advanced topics, including writing software device drivers for the created peripheral.


Software development overview

The embedded software platform defines, for each processor, the drivers associated with the peripherals we include in our hardware platform (the board support package), selected libraries, standard input/output devices, interrupt handler routines, and other related software features. Your Xilinx Platform Studio (XPS) project further defines software applications to run on each processor, which are based on the software platform.

Device Driver Programmer Guide

The purpose of this document is to describe the Xilinx device driver environment. This includes the device driver architecture, the
Application Programmer Interface (API) conventions, the scheme for configuring the drivers to work with reconfigurable hardware devices, and the infrastructure that is common to all device drivers.
This document is intended for the software engineer that is using the Xilinx device drivers. It contains design and implementation details necessary for using the drivers. The guide can be found here: EDK_install_dir/doc/usenglish/xilinx_drivers_guide.pdf and in html format :
EDK_install_dir/doc/usenglish/xilinx_drivers.htm

We will use this guide and the TechXclusive to help us write a device driver for the ETC peripheral.

Platform Specification Format Reference Manual

EDK tools are designed to operate in a data-driven manner. There are various meta-data files that capture information, for example, about various IPs, drivers, and software libraries being used in the EDK tools. Files are also used to capture both hardware and software aspects of our design information. These are ASCII files. The set of all these meta-data formats is referred to as the
Platform Specification Format or PSF.

Microprocessor Driver Definition (MDD)

An MDD file contains directives for customizing software drivers. Each device driver has an MDD file and a Tcl (Tool Command Language) file associated with it. The MDD file is used by the Tcl file to customize the driver, depending on different options configured in the MSS file.

Libraries and driver generation

As it says in the Xilinx Documentation:
The MHS and the MSS files define a system. For each processor in the system, Libgen finds the list of addressable peripherals. For each processor, a unique list of drivers and libraries are built. Libgen does the following for each processor:
  • Builds the directory structure as shown here below.
  • Copies the necessary source files for the drivers, OSs, and libraries into the processor instance specific area: OUTPUT_DIR/processor_instance_name/libsrc.
  • Calls the design rule check (defined as an option in the MDD or MLD file) procedure for each of the drivers, OSs, and libraries visible to the processor.
  • Calls the generate Tcl procedure (if defined in the Tcl file associated with an MDD or MLD file) for each of the drivers, OSs, and libraries visible to the processor. This generates the necessary configuration files for each of the drivers, OSs, and libraries in the include directory of the processor.
  • Calls the post_generate Tcl procedure (if defined in the Tcl file associated with an MDD or MLD file) for each of the drivers, OSs, and libraries visible to the processor.
  • Runs make (with targets include and libs) for the OSs, drivers, and libraries specific to the processor. On Unix platforms (Linux and Solaris), the gmake utility is used, while on NT platforms, make is used for compilation.
  • Calls the execs_generate Tcl procedure (if defined in the Tcl file associated with an MDD or MLD file) for each of the drivers, OSs, and libraries visible to the processor.
For more information about library generation read chapter 4 in the  Embedded System Tools Reference Manual.


Device driver architecture

The architecture of the device drivers is designed as a layered architecture as shown in the figure . The layered architecture accommodates the many use cases of device drivers while at the same time providing portability across operating systems, toolsets, and processors. The layered architecture provides seamless integration with an
RTOS (Layer 2), high-level device drivers that are full-featured and portable across operating systems and processors (Layer 1), and low-level drivers for simple use cases (Layer 0).

 Layer 2, RTOS adaptation
 Layer 1, High level drivers
 Layer 0, Low level drivers


xparameters.h


This source file centralizes basic configuration constants for all drivers within the system. Browsing this file gives the user an overall view of the system architecture. The device drivers and Board Support Package (BSP) utilize the information contained here to configure the system at runtime.
The amount of configuration information varies by device, but at a minimum the following items should be defined for each device:
  • Number of device instances
  • Device ID for each instance
  • A Device ID uniquely identifies each hardware device which maps to a device driver. A Device ID is used during initialization to perform the mapping of a device driver to a hardware device.
  • Device IDs are typically assigned either by the user or by a system generation tool. It is currently defined as a 16-bit unsigned integer.
  • Device base address for each instance
  • Device interrupt assignment for each instance if interrupts can be generated.
Here is an example:

/* Definitions for peripheral RS232_UART */

#define XPAR_RS232_UART_BASEADDR 0x40600000
#define XPAR_RS232_UART_HIGHADDR 0x4060FFFF
#define XPAR_RS232_UART_DEVICE_ID 1
#define XPAR_RS232_UART_BAUDRATE 9600
#define XPAR_RS232_UART_USE_PARITY 0
#define XPAR_RS232_UART_ODD_PARITY 0
#define XPAR_RS232_UART_DATA_BITS 8

The xparameters.h file can be found in the include directory.




Software driver source code

During the library generation (
libgen) run, the source code for every driver used, is copied to the SDK project directory libsrc, from the Xilinx source code repository. The old code will be overwritten and therefore we will never make any changes to the code in the libsrc directory. Here is the libgen log file.

Source code repository




Software device drivers used

To find out which software device drivers are used we can open Software Platform Settings and select Drivers. In the Xilinx Platform Studio SDK select Xilinx Tools->Software Platform Settings. The ETC peripheral has a generic driver assigned as default. We will add our own driver.




SDK project directory


The specified version of the driver source code is stored in the libsrc directory.





Let's take the GPIO driver as an example and look at different source files and their usage.

Header source file (xgpio.h and xgpio_l.h)

The
header files contain the interfaces for a component. There will always be external interfaces which is what an application that utilizes the component invokes.
  • The external interfaces for the high level drivers (Layer 1) are contained in a header file with the file name format x<component name>.h.
  • The external interfaces for the low level drivers (Layer 0) are contained in a header file with the file name format x<component name>_l.h.
The xgpio.h file contains the follwing type definitions.

/**************************** Type Definitions ******************************/


/**
 * This typedef contains configuration information for the device.
 */
typedef struct
{
    Xuint16  DeviceId;          /* Unique ID  of device */
    Xuint32  BaseAddress;       /* Device base address */
    Xboolean InterruptPresent;  /* Are interrupts supported in h/w */
    Xboolean IsDual;            /* Are 2 channels supported in h/w */
} XGpio_Config;

/**
 * The XGpio driver instance data. The user is required to allocate a
 * variable of this type for every GPIO device in the system. A pointer
 * to a variable of this type is then passed to the driver API functions.
 */
typedef struct
{
    Xuint32  BaseAddress;       /* Device base address */
    Xuint32  IsReady;           /* Device is initialized and ready */
    Xboolean InterruptPresent;  /* Are interrupts supported in h/w */
    Xboolean IsDual;            /* Are 2 channels supported in h/w */
} XGpio;

It also contains a number of
function prototypes. The functions themselves are defined in the different .c files found in the gpio source directory.

/************************** Function Prototypes *****************************/

/*
 * Initialization functions in xgpio_sinit.c
 */
XStatus XGpio_Initialize(XGpio *InstancePtr, Xuint16 DeviceId);
XGpio_Config *XGpio_LookupConfig(Xuint16 DeviceId);

/*
 * API Basic functions implemented in xgpio.c
 */
XStatus XGpio_CfgInitialize(XGpio *InstancePtr, XGpio_Config *Config,
                            Xuint32 EffectiveAddr);
void    XGpio_SetDataDirection(XGpio *InstancePtr, unsigned Channel,
                               Xuint32 DirectionMask);
Xuint32 XGpio_DiscreteRead(XGpio *InstancePtr, unsigned Channel);
void    XGpio_DiscreteWrite(XGpio *InstancePtr, unsigned Channel, Xuint32 Mask);


Configuration table xgpio_g.c

This file contains configuration tables for all devices that uses the GPIO device driver.

/*
* The configuration table for devices
*/

XGpio_Config XGpio_ConfigTable[] =
{
    {
        XPAR_LEDS_4BIT_DEVICE_ID,
        XPAR_LEDS_4BIT_BASEADDR,
        XPAR_LEDS_4BIT_INTERRUPT_PRESENT,
        XPAR_LEDS_4BIT_IS_DUAL
    },
    {
        XPAR_LEDS_POSITIONS_DEVICE_ID,
        XPAR_LEDS_POSITIONS_BASEADDR,
        XPAR_LEDS_POSITIONS_INTERRUPT_PRESENT,
        XPAR_LEDS_POSITIONS_IS_DUAL
    },
    {
        XPAR_PUSH_BUTTONS_POSITION_DEVICE_ID,
        XPAR_PUSH_BUTTONS_POSITION_BASEADDR,
        XPAR_PUSH_BUTTONS_POSITION_INTERRUPT_PRESENT,
        XPAR_PUSH_BUTTONS_POSITION_IS_DUAL
    },
    {
        XPAR_LCD_16X2_DEVICE_ID,
        XPAR_LCD_16X2_BASEADDR,
        XPAR_LCD_16X2_INTERRUPT_PRESENT,
        XPAR_LCD_16X2_IS_DUAL
    }
};

Adding the ETC software device driver


From the Xilinx documentation it isn't 100% clear how to add a new device driver. Here is how I did it and it seems to work.

1. Edit the ETC_system.mss file and add the etc driver. Like this:

   BEGIN DRIVER
     PARAMETER DRIVER_NAME = etc
     PARAMETER DRIVER_VER = 1.00.a
     PARAMETER HW_INSTANCE = ETC_0
  END

2. Add a new directory called drivers and the subdirectories as shown here:




3. Copy template files to src and data directories. We will use the gpio device driver source code as our template files. It is important to copy the .tcl and .mdd files to the data directory. Libgen will complain if it doesn't find these files.

4. Rename and edit the template files. For the moment we will not bother about writing working code. We will only rename everything called <gpio> to <etc>. Don't forget to make changes to the Makefile. Libgen will use the Makefile during library generation to compile and link the ETC device driver source code.

5. Edit the .mdd and .tcl files. Find out more
here.

6. Run library generation. Select Software->Generate Libraries and BSPs in the Xilinx Platform Studio. Libgen will search inside the drivers or pcores directories for device driver source code.

7. The ETC software device driver source code will be compiled into the library libxil.a together with all other device drivers.


Top  Next  Previous





Posted at 09:34 am by svenand
Comments (5)  

 
Jun 25, 2007
FPGA design from scratch. Part 37
Debugging our design

What to do if our design is not doing what we expected it to do. Then we need a
debugger.

Xilinx Microprocessor Debugger and GNU Software Debugging Tools

Using Xilinx Microprocessor Debugger (XMD) and GNU Debugger (GDB), we can debug our embedded application either on the host development system using an instruction set simulator or virtual platform, or on a board that has the FPGA loaded with our hardware bitstream. For more information on the GNU software debugging tools, refer to the Debug Overview. For more information on XMD, see the "Xilinx Microprocessor Debugger (XMD)" chapter in the Embedded System Tools Reference Manual.

Xilinx Microprocessor Debugger (XMD)

The Xilinx Microprocessor Debugger (XMD) is a tool that facilitates debugging programs and verifying systems using the PowerPC 405GP or MicroBlaze microprocessors. We can use it to debug programs running on a hardware board, Cycle-Accurate Instruction Set Simulator (ISS), or MicroBlaze Cycle-Accurate Virtual Platform (VP) system.

XMD provides a Tool Command Language (Tcl) interface. This interface can be used for command line control and debugging of the target as well as for running complex verification test scripts to test a complete system. XMD supports GNU Debugger (GDB) Remote TCP protocol to control debugging of a target. Some graphical debuggers use this interface for debugging, including PowerPC and MicroBlaze GDB (powerpc-eabi-gdb and mb-gdb) and the Platform Studio Software Development Kit (SDK), EDK's Eclipse-based Software IDE. In either case, the debugger connects to XMD running on the same computer or on a remote computer on the Network.

XMD reads Xilinx Microprocessor Project (XMP), Microprocessor Hardware Specification (MHS), and (Microprocessor Software Specification) (MSS) system files to better understand the hardware system on which the program is debugged. The information is used to perform memory range tests, determine MicroBlaze to Microprocessor Debug Module (MDM) connectivity for faster download speeds, and perform other system actions.

MicroBlaze Processor Target

XMD can connect through JTAG to one or more MicroBlaze processors using the opb_mdm Microprocessor Debug Module (MDM) peripheral. XMD can communicate with a ROM monitor such as XMDStub through JTAG or Serial interface. You can also debug programs using built-in Cycle-accurate MicroBlaze ISS.

MicroBlaze MDM hardware target


                                                                                                                  (Courtesy of Xilinx)

Debug session

This example demonstrates a simple debug session with a MicroBlaze MDM target. Basic XMD-based commands are used after connecting to the MDM target using the connect mb mdm.

==> xmd

XMD% connect mb mdm

connect mb mdm
Info:AutoDetecting cable. Please wait.
Info:Reusing 78010001 key.
Info:Reusing FC010001 key.
Info:Connecting to cable (Parallel Port - parport0).
Info: libusb-driver.so version: 2007-05-27 00:37:02.
Info: parport0: Info:baseAddress=0x0Info:, ecpAddress=0x400Info:
Info: LPT base address = 0000h.
Info: ECP base address = 0400h.
Can't open /dev/parport0: Permission denied
Info:LPT port is already in use. rc = FFFFFFFFh
Info:Cable connection failed.
Info:Reusing 79010001 key.
Info:Reusing FD010001 key.
Info:Connecting to cable (Parallel Port - parport1).
Info: libusb-driver.so version: 2007-05-27 00:37:02.
Info:Cable connection failed.
Info:Reusing 7A010001 key.
Info:Reusing FE010001 key.
Info:Connecting to cable (Parallel Port - parport2).
Info: libusb-driver.so version: 2007-05-27 00:37:02.
Info:Cable connection failed.
Info:Reusing 7B010001 key.
Info:Reusing FF010001 key.
Info:Connecting to cable (Parallel Port - parport3).
Info: libusb-driver.so version: 2007-05-27 00:37:02.
Info:Cable connection failed.
Info:Reusing A0010001 key.
Info:Reusing 24010001 key.
Info:Connecting to cable (Usb Port - USB21).
Info:Checking cable driver.
Info:File version of /home/svenand/cad/xilinx91i/bin/lin/xusbdfwu.hex = 1025(dec), 0x0401.
Info:File version of /usr/share/xusbdfwu.hex = 1025(dec), 0x0401.
Info: libusb-driver.so version: 2007-05-27 00:37:02.
Calling setinterface num=0, alternate=0.
DeviceAttach: received and accepted attach for:
  vendor id 0x3fd, product id 0x8, device handle 0x830b558
Info: Cable PID = 0008.
Info: Max current requested during enumeration is 280 mA.
Info: Cable Type = 3, Revision = 0.
Info: Cable Type = 0x0605.
Info: Setting cable speed to 6 MHz.
Info:Cable connection established.
Info:Firmware version = 1025.
Info:CPLD file version = 0012h.
Info:CPLD version = 0012h.

JTAG chain configuration
--------------------------------------------------
Device   ID Code        IR Length    Part Name
 1       0a001093           8        System_ACE
 2       05059093          16        XCF32P
 3       01e58093          10        XC4VFX12
 4       09608093           8        xc95144xl

MicroBlaze Processor Configuration :
-------------------------------------
Version............................6.00.b
No of PC Breakpoints...............2
No of Read Addr/Data Watchpoints...0
No of Write Addr/Data Watchpoints..0
Instruction Cache Support..........off
Data Cache Support.................off
Exceptions  Support................off
FPU  Support.......................off
Hard Divider Support...............off
Hard Multiplier Support............on - (Mul32)
Barrel Shifter Support.............off
MSR clr/set Instruction Support....on
Compare Instruction Support........on

Connected to MDM UART Target
Connected to "mb" target. id = 0
Starting GDB server for "mb" target (id = 0) at TCP port no 1234

Reading registers in MicroBlaze

XMD% rrd

rrd
    r0: 00000000      r8: 00000001     r16: 00000000     r24: 00000000 
    r1: 00001440      r9: 00000008     r17: 00000000     r25: 00000000 
    r2: 000010f8     r10: 00000000     r18: 00000000     r26: 00000000 
    r3: 00000001     r11: 00000000     r19: 00000000     r27: 00000000 
    r4: 00000000     r12: 00000000     r20: 00000000     r28: 00000000 
    r5: 00000000     r13: 00001158     r21: 00000000     r29: 00000000 
    r6: 0000000d     r14: 00000000     r22: 00000000     r30: 00000000 
    r7: 0000000a     r15: 0000005c     r23: 00000000     r31: 00000000 
    pc: 0000007c     msr: 00000000

Load program

Command: dow elf_file_name

XMD% dow SDK_projects/ETC_system_program/Debug/ETC_system_program.elf

dow SDK_projects/ETC_system_program/Debug/ETC_system_program.elf
    section, .vectors.reset: 0x00000000-0x00000003
    section, .vectors.sw_exception: 0x00000008-0x0000000b
    section, .vectors.interrupt: 0x00000010-0x00000013
    section, .vectors.hw_exception: 0x00000020-0x00000023
    section, .text: 0x00000050-0x00000f0b
    section, .init: 0x00000f0c-0x00000f2f
    section, .fini: 0x00000f30-0x00000f4b
    section, .ctors: 0x00000f4c-0x00000f53
    section, .dtors: 0x00000f54-0x00000f5b
    section, .rodata: 0x00000f5c-0x00000f9d
    section, .data: 0x00000fa0-0x00000ffb
    section, .jcr: 0x00000ffc-0x00000fff
    section, .bss: 0x00001000-0x0000143f
Downloaded Program SDK_projects/ETC_system_program/Debug/ETC_system_program.elf
Setting PC with Program Start Address 0x00000000

Set breakpoint

Command : bps <memory_loc>

XMD% bps 0x50
bps 0x50
Setting breakpoint at 0x00000050

Remove breakpoint

Command : bpr <memory_loc>

XMD% bpr 0x50
bpr 0x50

Display breakpoints

Command : bpl

XMD% bpl
bpl
0: HW BP: Address = 0x00000004
1: SW BP: Address = 0x00000050

Start program execution

Command : con [start_address] or con to continue from breakpoint

XMD% con 0
con
Info:Processor started. Type "stop" to stop processor

RUNNING> XMD% Info:Software Breakpoint 1 Hit, Processor Stopped at 0x00000050


Single step

Command : stp [number_of_instructions]

XMD% stp
stp
      54:   304010F8  addik    r2 , r0 , 4344

XMD% stp
stp
      58:   30201430  addik    r1 , r0 , 5168

XMD% stp
stp
      5C:   B9F40088  brlid    r15, 136

XMD% stp 10
stp 10
     10C:   20C01000  addi     r6 , r0 , 4096


Stop program execution

Command : stop

RUNNING> XMD% stop
stop
XMD% Info:User Interrupt, Processor Stopped at 0x00000068

Display program code

Command : dis <start address, number_of_instructions>

XMD% dis 0x50 20
dis 0x50 20
      50:   31A01158  addik    r13, r0 , 4440
      54:   304010F8  addik    r2 , r0 , 4344
      58:   30201430  addik    r1 , r0 , 5168
      5C:   B9F40088  brlid    r15, 136
      60:   80000000  Or       r0 , r0 , r0
      64:   20210010  addi     r1 , r1 , 16
      68:   B8000000  bri      0
      6C:   E0601000  lbui     r3 , r0 , 4096
      70:   3021FFE4  addik    r1 , r1 , -28
      74:   F9E10000  swi      r15, r1 , 0
      78:   BC030014  beqi     r3 , 20
      7C:   B8000028  bri      40
      80:   F8600FA8  swi      r3 , r0 , 4008
      84:   99FC2000  brald    r15, r4
      88:   80000000  Or       r0 , r0 , r0
      8C:   E8600FA8  lwi      r3 , r0 , 4008
      90:   E8830000  lwi      r4 , r3 , 0
      94:   BE24FFEC  bneid    r4 , -20
      98:   30630004  addik    r3 , r3 , 4
      9C:   30600001  addik    r3 , r0 , 1


Getting help

XMD% help
help

XMD Terminal Commands Types:
init......... Load/Initialize the System Files
connect...... Connect to System Target
files........ Load ELF/Data files
running...... Program Execution
breakpoints.. Setting Breakpoints/Watchpoints
trace........ Tracing and Profiling options
misc......... Miscellaneous Options
help......... Help on help

Type "help" to display XMD command types
Type "help" followed by above "type" for more options
XMD%

XMD% help running
help running

        Program Execution, Reading/Writing Registers and Memory
----- Syntax -----                 ----- Description -----
  run                                   Run program from <Start Address>
  con [address] [-quit]                 Continue
  stp [num_instrns]                     Step
  cstp [num_cycles]                     Cycle Step (Simulator/VP targets)
  rst [-processor]                      Reset the System/Processor
  stop                                  Stop
  rrd [reg num]                         Register Read
  srrd [reg name]                        Special Register Read
  rwr <register> <word>                 Register Write
  mrd <address> [num] [w|h|b]           Memory Read (default: 'w'ord)
  mrd_var <variable name> [ELF file]    Read memory at global variable
  mwr <address> <values> [<num> <w|h|b>]  Memory Write (default: 'w'ord)
XMD%

XMD% help breakpoints
help breakpoints

        Setting Breakpoints and Watchpoints
----- Syntax -----                 ----- Description -----
  bps <address|func name> [sw|hw]  Breakpoint Set. xmd uses last
                                     downloaded ELF file for function name
  watch <r|w> <addr> [data]        Set Read/Write Watchpoints.
  bpr <address|func name|bp id|all> Breakpoint/Watchpoint Remove. xmd uses last
                                    downloaded ELF file for function name
  bpl                              Breakpoints List
XMD%

XMD% help files

help files

        Specify/Download ELF or Data files to System Target
----- Syntax -----                 ----- Description -----
  dow <filename>                Download Elf File
  dow <filename> <addr>         Download PIC Elf File from <addr>
  dow <-data> <filename> <addr> Download Data/Binary File from <addr>
XMD%

XMD% help trace
help trace

        Trace/Statistics/Profile Commands
----- Syntax -----                 ----- Description -----
  tracestart [<filename>]               Start Tracing (For ISS/VP Targets)
  tracestop [done]                      Stop Tracing
  stats [filename]                      Generate Trace Stats (For Simulator Targets)
                                             <filename> Trace file for PPC Sim Only
  profile [-o <Gmon output File>]       Configure or Write Profile Output File
          [-config [sampling_freq_hz <value>]
          [binsize <value>] [profile_mem <Start Address>]
XMD%

XMD% help misc
help misc

        Misc Commands
----- Syntax -----                 ----- Description -----
  debugconfig [-step_mode <value>]      Configure the Debug Session
    [-memory_datawidth_matching <value>]
    [-reset_on_run <system | processor> <enable | disable>]
    [-vpoptions <bus_cycle_accuracy <enable | disable>>]
  state [target id]                     Display the Current State of all targets
                                       or <target id> target.
  dis <address> [num_words]             Disassemble (MicroBlaze Only)
  terminal [-jtag_uart_server [portno]]  Start JTAG-based Hyperterminal to
                                       communicate with MDM UART interface
  read_uart <start|stop> [TCL Channel ID] Read from MDM UART interface
  verbose [<level>]                      Toggle Verbose mode. Verbose Level = 1-3
XMD%



Using XMD in Xilinx Platform Studio

You can run the Xilinx Microprocessor Debugger (XMD) from a command line and use it exclusively for debugging. Alternately, XMD can serve as a link between the GNU debug option and your target board.

To open XMD from Xilinx Platform Studio (XPS), click Debug > Launch XMD.

The first time you open XMD, you are prompted to set the XMD options, and the XMD Debug Options dialog box opens automatically. Select the settings.

If you want to change the debug option setting later, you can do so by clicking Debug > XMD Target Options.

After you have set the debug options, the XMD terminal command-line window opens. On Startup, XMD does the following:

If an XMD Tcl script is specified, XMD executes the script and quits.

Otherwise, XMD is started in an interactive mode. In this case, XMD does the following:

  • Sources the ${HOME}/.xmdrc file. The configuration file can be used to form custom Tcl commands using XMD commands.
  • Opens the XMD Socket server, if the -ipcport option is given.
  • Loads system Xilinx® Microprocessor Project (XMP) file, if the -xmp option is given.
  • Uses Connect option file to connect to processor target, if the -opt option is given.
  • If –nx option is not specified, sources the xmd.ini file, if present in the directory.

The XMD% prompt is displayed. From the Tcl prompt, you can use XMD commands for debugging.

For a list of XMD commands, refer to the "Xilinx Microprocessor Debugger (XMD)" chapter of the Embedded System Tools Reference Manual.


Top  Next  Previous



Posted at 10:18 am by svenand
Comment (1)  

 
Jun 21, 2007
Making the virtual machine run faster
How good is our virtual machine and how can we make it run faster. Let's find out. Here is what we have.

Hardware

MacBook Intel Core 2 Duo. 2.0 GHz with 2Gb of memory.

Host software

Mac OS X 10.4.10 and the virtual machine
VMware Fusion RC1 (build 50460) with the lastest VMware tools installed.


Virtual machine software

Ubuntu Linux 7.04 (i386 32 bit)


Virtual machine setup

512/1024 Mb of memory. One or two virtual CPU(s).


How to speed up execution
  • Paravirtualization
  • Adding more memory
  • Using two CPUs
  • Using a 64 bit OS and 64 bit computer (Intel Core 2 Duo)

Paravirtualization

A hypervisor provides the virtualization abstraction of the underlying computer system. In full virtualization, a guest operating system runs unmodified on a hypervisor. However, improved performance and efficiency is achieved by having the guest operating system communicate with the hypervisor. By allowing the guest operating system to indicate its intent to the hypervisor, each can cooperate to obtain better performance when running in a virtual machine. This type of communication is referred to as paravirtualization.


Enabling paravirtualization

Add the following line vmi.present = TRUE to the file  .vmx found inside the vmware bundle for the virtual machine.



Applications


We will use the following Xilinx FPGA tools in our benchmark.
The netlist generation tool runs the Xilinx tool XST to synthesis a complete FPGA design. The bitstream generation tool does the place and route of the whole design and generates the bitstream to configure the FPGA. Both tools are very compute intensive, using more than 90% of the processor time.


Execution times [s]

Options / Task
Netlist Generation
Bitstream Generation
Paravirtualization : off
Memory  :  512 Mb
582 260
Paravirtualization : on
Memory : 512 Mb
556 245
Paravirtualization : on
Memory : 1024 Mb

540 235 
Paravirtualization : on
Memory :  1024  Mb
CPU  : 2
531  231 

Execution times are mesured with an external clock. Mean values from five runs.


Adding more memory

I have bought two modules with 1Gb each and installed them in my MacBook. I have given 1Gb of memory to the VMware virtual machine. Will it make a difference. We will see.


Using Ubuntu Linux 64 bit version

Will it be possible to use a 64 bit Linux OS. Let's find out. Here are the
memory requirements specified by Xilinx. It seems like they support 64 bit RedHat Linux.


Using two virtual processors







Posted at 12:20 pm by svenand
Comment (1)  

 
Jun 19, 2007
FPGA design from scratch. Part 36
The LCD drivers (once more)

Now it's time to return to the LCD driver application program again. We will start by running a simulation to find out how everything is connected. Let's use a really simple program.

int main(void) {

    XStatus Status;
   
    // Initialize the GPIO component
    Status = XGpio_Initialize(&GpioLCD, GPIO_LCD_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;
 
    // Set the direction for all bits to be outputs
    XGpio_SetDataDirection(&GpioLCD,    LCD_CHANNEL, 0x00);  
 
    // Display one character
    XromWriteData(0x6,0x1);


    return XST_SUCCESS;
   
    }


Here is the simulation waveform plot showing the GPIO bus connected to the LCD.



From this plot we can find out how the GPIO signals should be connected to the LCD driver. It was not the way we thought. Here is what it should look like.

 Signal Name
 Description  GPIO pin
FPGA pin location 
LCD_E Read/Write Enable Pulse
0: Disabled
1: Read/Write operation enabled

0 AE13
LCD_RS Register Select
0:Instruction register during write
1:Data for read or write operation
1
AC17
LCD_RW Read/Write Control
0:Write, LCD accepts data
1:Read, LCD presents data
2 AB17
LCD_DB7 Data Bus bit 7
3 AF12
LDC_DB6  Data Bus bit 6
4 AE12
LCD_DB5 Data Bus bit 5
5 AC10
LCD_DB4 Data Bus bit 4
AB10

Editing the user constraints file

We will change the pin mapping in the ETC_system.ucf file.

#### Module LCD_16x2 constraints

NET LCD_16x2_GPIO_IO_pin<0> LOC="AE13";
NET LCD_16x2_GPIO_IO_pin<0> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<0> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<0> TIG;
NET LCD_16x2_GPIO_IO_pin<1> LOC=AC17;
NET LCD_16x2_GPIO_IO_pin<1> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<1> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<1> TIG;
NET LCD_16x2_GPIO_IO_pin<2> LOC=AB17;
NET LCD_16x2_GPIO_IO_pin<2> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<2> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<2> TIG;
NET LCD_16x2_GPIO_IO_pin<3> LOC=AF12;
NET LCD_16x2_GPIO_IO_pin<3> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<3> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<3> TIG;
NET LCD_16x2_GPIO_IO_pin<4> LOC=AE12;
NET LCD_16x2_GPIO_IO_pin<4> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<4> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<4> TIG;
NET LCD_16x2_GPIO_IO_pin<5> LOC=AC10;
NET LCD_16x2_GPIO_IO_pin<5> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<5> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<5> TIG;
NET LCD_16x2_GPIO_IO_pin<6> LOC=AB10;
NET LCD_16x2_GPIO_IO_pin<6> IOSTANDARD = LVCMOS33;
NET LCD_16x2_GPIO_IO_pin<6> PULLDOWN;
NET LCD_16x2_GPIO_IO_pin<6> TIG;

Generate a new bitstream

We use the menu command Hardware->Generate Bitstream in Xilinx Platform Studio to
generate a new bitstream.

Device configuration

We use the menu command Device Configuration->Download Bitstream to configure the FPGA.

Application program


Here is our "Hello World" program again.

int main(void) {

    XStatus Status;
   
    // Initialize the GPIO component
    Status = XGpio_Initialize(&GpioLCD, GPIO_LCD_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;
 
    // Set the direction for all bits to be outputs
    XGpio_SetDataDirection(&GpioLCD,LCD_CHANNEL, 0x00);  

    //Initialize LCD
    XromLCDInit();
    XromLCDOn();
    XromLCDClear();
    XromLCDPrintString("Hello World");

    return XST_SUCCESS;
   
    }

We compile and link the program in Xilinx Platform Studio SDK and use the command Device Configuration->Program Hardware to load and execute the program. We keep staring at the LCD display and after a few seconds it displays:

                         
Hello World


Top  Next  Previous



Posted at 01:35 pm by svenand
Make a comment  

 
Jun 17, 2007
FPGA design from scratch. Part 35
Generate simulation HDL files

We will take one step back and look at the Xilinx simulation environment and use the program Simgen.

Simgen

Simgen creates and configures various VHDL and Verilog simulation models for a specified hardware. It takes a Microprocessor Hardware Specification (MHS) file as input, which describes the instantiations and connections of hardware components. Simgen is also capable of creating scripts for a specified vendor simulation tool. The scripts compile the generated simulation models. The hardware component is defined by the MHS file. Refer to the "Microprocessor Hardware Specification (MHS)" chapter in the
Platform Specification Format Reference Manual for more information. For more information about Simgen read the Embedded System Tools Reference Manual (chapter 3).

Before we run Simgen let's make sure we have our software project selected in Xilinx Platform Studio. We also make sure we ticked the Marked for BRAM initialization (right-click Project: ETC_system_program).



We invoke Simgen from the Xilinx Platform Studio using the menu command: Simulation->Generate HDL Simulation Files. When the Simgen program has finished we find a new sub directory (simulation) in our xps directory.




Data2MEM Memory Tool

Data2MEM is a command line executable that transforms CPU execution code (in the form of an ELF file), or pure data, into Block RAM initialization records. Simgen will use Data2MEM to convert our ETC_system_program.elf file to a VHDL file that can be used to initialize the BRAM. Here is more information about
Data2Mem.

Here are some of the files that were generated during the Simgen run.

ETC_system_sim.bmm

ETC_system_sim.bmm defines the BRAM size and address space.

// File: /home/svenand/root/projects/ETC/xps/simulation/behavioral/ETC_system_sim.bmm

ADDRESS_MAP microblaze_0 MICROBLAZE 100
    ADDRESS_SPACE lmb_bram_combined COMBINED [0x00000000:0x00001fff]
        ADDRESS_RANGE RAMB16
        BUS_BLOCK
            lmb_bram/lmb_bram/ramb16_0 [31:24] ;
            lmb_bram/lmb_bram/ramb16_1 [23:16] ;
            lmb_bram/lmb_bram/ramb16_2 [15:8] ;
            lmb_bram/lmb_bram/ramb16_3 [7:0] ;
        END_BUS_BLOCK;
        END_ADDRESS_RANGE;
    END_ADDRESS_SPACE;
END_ADDRESS_MAP;


ETC_system_init.vhd

The ETC_system_init.vhd is a VHDL configuration file used to initialize the BRAM.

-- File generated by ucf2vhdl.pl

-- Type: beh

library unisim;
library lmb_bram_elaborate_v1_00_a;

configuration lmb_bram_conf of lmb_bram_wrapper is
  for STRUCTURE
    for lmb_bram : lmb_bram_elaborate
      use entity lmb_bram_elaborate_v1_00_a.lmb_bram_elaborate;
      for STRUCTURE
        for ramb16_0 : ramb16
          use entity unisim.ramb16(ramb16_v)
          generic map(
            READ_WIDTH_A => READ_WIDTH_A,
            READ_WIDTH_B => READ_WIDTH_B,
            WRITE_WIDTH_A => WRITE_WIDTH_A,
            WRITE_WIDTH_B => WRITE_WIDTH_B,
            WRITE_MODE_A => WRITE_MODE_A,
            WRITE_MODE_B => WRITE_MODE_B,
            RAM_EXTENSION_A => RAM_EXTENSION_A,
            RAM_EXTENSION_B => RAM_EXTENSION_B,
            INIT_00 => X"B8BCF930E0B82080B93030310000000000000000000000B8000000B800B800B8",
            INIT_01 => X"F8BC062020F92030B6E98099BC3030B0BCF930E830B6E9F03030BEE8E88099F8",

.........................removed

            INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
            INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000");
        end for;

      end for;
    end for;
  end for;
end lmb_bram_conf;

configuration ETC_system_conf of etc_system is
  for STRUCTURE
    for all : lmb_bram_wrapper use configuration work.lmb_bram_conf;
    end for;
  end for;
end ETC_system_conf;


ETC_system_tb.vhd

ETC_system_tb.vhd is the VHDL top testbench file.

-------------------------------------------------------------------------------
-- ETC_system_tb.vhd
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

library UNISIM;
use UNISIM.VCOMPONENTS.ALL;

entity ETC_system_tb is
end ETC_system_tb;

architecture STRUCTURE of ETC_system_tb is

  constant fpga_0_DDR_CLK_FB_PERIOD : time := 10 ns;
  constant sys_clk_pin_PERIOD : time := 10 ns;
  constant sys_rst_pin_LENGTH : time := 160 ns;

  component ETC_system is
    port (
      fpga_0_RS232_Uart_RX_pin : in std_logic;
      fpga_0_RS232_Uart_TX_pin : out std_logic;
      fpga_0_LEDs_4Bit_GPIO_IO_pin : inout std_logic_vector(0 to 3);
      fpga_0_LEDs_Positions_GPIO_IO_pin : inout std_logic_vector(0 to 4);
      fpga_0_Push_Buttons_Position_GPIO_IO_pin : inout std_logic_vector(0 to 4);
      fpga_0_DDR_SDRAM_64Mx32_DDR_Clk_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_Clkn_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_Addr_pin : out std_logic_vector(0 to 12);
      fpga_0_DDR_SDRAM_64Mx32_DDR_BankAddr_pin : out std_logic_vector(0 to 1);
      fpga_0_DDR_SDRAM_64Mx32_DDR_CASn_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_CKE_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_CSn_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_RASn_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_WEn_pin : out std_logic;
      fpga_0_DDR_SDRAM_64Mx32_DDR_DM_pin : out std_logic_vector(0 to 3);
      fpga_0_DDR_SDRAM_64Mx32_DDR_DQS_pin : inout std_logic_vector(0 to 3);
      fpga_0_DDR_SDRAM_64Mx32_DDR_DQ_pin : inout std_logic_vector(0 to 31);
      fpga_0_DDR_CLK_FB : in std_logic;
      sys_clk_pin : in std_logic;
      sys_rst_pin : in std_logic;
      ETC_0_I_RESETS_pin : in std_logic;
      ETC_0_ETC_TDI_EX_pin : in std_logic;
      ETC_0_ETC_TCKI_pin : in std_logic;
      ETC_0_ETC_TRSTZI_pin : in std_logic;
      ETC_0_ETC_TMSI_pin : in std_logic;
      ETC_0_JTC_TDO_ENB_pin : in std_logic;
      ETC_0_JTC_TDO_pin : in std_logic;
      ETC_0_CE1_pin : in std_logic;
      ETC_0_JTC_TCK_pin : out std_logic;
      ETC_0_JTC_TRSTZ_pin : out std_logic;
      ETC_0_JTC_TMS_pin : out std_logic;
      ETC_0_JTC_TDI_pin : out std_logic;
      ETC_0_ETC_TCKO_pin : out std_logic;
      ETC_0_ETC_TMSO_pin : out std_logic;
      ETC_0_ETC_TDO_pin : out std_logic;
      ETC_0_ETC_TDO_ENB_pin : out std_logic;
      ETC_0_ETC_TRSTZO_pin : out std_logic;
      ETC_0_ETC_ENB_pin : out std_logic;
      ETC_0_ETC_TDI_FX_pin : in std_logic;
      ETC_0_O_INTERRUPT_pin : out std_logic;
      LCD_16x2_GPIO_IO_pin : inout std_logic_vector(0 to 6)
    );
  end component;

.........................removed

  -- Clock generator for fpga_0_DDR_CLK_FB

  process
  begin
    fpga_0_DDR_CLK_FB <= '0';
    loop
      wait for (fpga_0_DDR_CLK_FB_PERIOD/2);
      fpga_0_DDR_CLK_FB <= not fpga_0_DDR_CLK_FB;
    end loop;
  end process;

  -- Clock generator for sys_clk_pin

  process
  begin
    sys_clk_pin <= '0';
    loop
      wait for (sys_clk_pin_PERIOD/2);
      sys_clk_pin <= not sys_clk_pin;
    end loop;
  end process;

  -- Reset Generator for sys_rst_pin

  process
  begin
    sys_rst_pin <= '0';
    wait for (sys_rst_pin_LENGTH);
    sys_rst_pin <= not sys_rst_pin;
    wait;
  end process;

  -- START USER CODE (Do not remove this line)

  -- User: Put your stimulus here. Code in this
  --       section will not be overwritten.

  -- END USER CODE (Do not remove this line)

end architecture STRUCTURE;

configuration ETC_system_tb_conf of ETC_system_tb is
  for STRUCTURE
    for all : ETC_system
      use configuration work.ETC_system_conf;
    end for;
  end for;
end ETC_system_tb_conf;


Modifying the testbench file

We normally run all our simulations in batch mode and we need a simple way to tell how long the simulation will run. Here is one method to run 80000 ns after reset is released.

  process
  begin
    sys_rst_pin <= '0';
    wait for (sys_rst_pin_LENGTH);
    sys_rst_pin <= not sys_rst_pin;
    wait for 800000 ns;
    assert false report "NONE. End of simulation." severity failure;
  end process;


Compiling the BRAM initialization file

We compile the ETC_system_init.vhd together with the wrapper files and store it in the top library.

Compiling the testbench file

We compile the ETC_system_tb.vhd testbench file into the ETC_system_tb library and after elaboration we have the following database structure.



Simulating program execution

Here is the whole sequence to add a new application program to our simulation environment.
  1. Compile and link the program
  2. Convert the ELF file to a BRAM memory image (ETC_system_init.vhd)
  3. Compile the ETC_system_init.vhd using ncvhdl
  4. Elaborate everything using ncelab
  5. Run the simulation using ncsim (ETC_SYSTEM_TB_CONF)
  6. Save the waveforms
  7. When the simulation has finish look at the waveforms in Simvision.
Here is the program.

// The following constant maps to the name of the hardware instances that
// were created in the EDK XPS system.
 
#define GPIO_LCD_DEVICE_ID    XPAR_LCD_16X2_DEVICE_ID
#define GPIO_LED4_DEVICE_ID   XPAR_LEDS_4BIT_DEVICE_ID
#define GPIO_LEDP_DEVICE_ID   XPAR_LEDS_POSITIONS_DEVICE_ID

// The following constant is used to determine which channel of the GPIO is
// used if there are 2 channels supported.

#define LCD_CHANNEL 1
#define LED_CHANNEL 1

// The following are declared globally so they are zeroed and so they are
// easily accessible from a debugger

XGpio GpioLCD;     /* The Instance of the GPIO LCD Driver */
XGpio GpioLED4;    /* The Instance of the GPIO LED4 Driver */
XGpio GpioLEDPOS;  /* The Instance of the GPIO LEDPOS Driver */

int main(void) {  


     XStatus Status;
   
    // Initialize the GPIO component
    Status = XGpio_Initialize(&GpioLCD, GPIO_LCD_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;
    Status = XGpio_Initialize(&GpioLED4, GPIO_LED4_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;
    Status = XGpio_Initialize(&GpioLEDPOS, GPIO_LEDP_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;
  
    // Set the direction for all bits to be outputs
    XGpio_SetDataDirection(&GpioLCD,    LCD_CHANNEL, 0x00);  
    XGpio_SetDataDirection(&GpioLED4,   LED_CHANNEL, 0x00);
    XGpio_SetDataDirection(&GpioLEDPOS, LED_CHANNEL, 0x00);
     
    // Turn on LEDs
    XGpio_DiscreteWrite(&GpioLED4,   LED_CHANNEL, 0xa);  
    XGpio_DiscreteWrite(&GpioLEDPOS, LED_CHANNEL, 0xa);
    // Write to LCD
    XGpio_DiscreteWrite(&GpioLCD,    LCD_CHANNEL, 0xa);
      
    return XST_SUCCESS;

  }

Here is the result.




The simulation runs as expected. One more milestone reached.



Top  Next  Previous


 
Posted at 05:56 pm by svenand
Make a comment  

 
Jun 15, 2007
FPGA design from scratch. Part 34
Program disassembly

What happened to our c program after we compiled and built it. Let's disassemble the ETC_system_program.elf to find out. We will us the command mb-objdump -d ETC_system_program.elf. Here is the printout:

Assembly code

Disassembly of section .vectors.reset:

00000000 <_start>:
   0:    b8080050     brai    80               // 50 <_TEXT_START_ADDR>
Disassembly of section .vectors.sw_exception:

00000008 <_vector_sw_exception>:
   8:    b80801a0     brai    416              // 1a0 <_exception_handler>
Disassembly of section .vectors.interrupt:

00000010 <_vector_interrupt>:
  10:    b80801bc     brai    444              // 1bc <__interrupt_handler>
Disassembly of section .vectors.hw_exception:

00000020 <_vector_hw_exception>:
  20:    b80801b8     brai    440              // 1b8 <_hw_exception_handler>
Disassembly of section .text:

00000050 <_start1>:
  50:    31a003d0     addik    r13, r0, 976    // 3d0 <_SDA_BASE_>
  54:    304003b0     addik    r2, r0, 944     // 3b0 <_SDA2_BASE_>
  58:    30200750     addik    r1, r0, 1872
  5c:    b9f40088     brlid    r15, 136        // e4 <_crtinit>
  60:    80000000     or       r0, r0, r0
  64:    20210010     addi     r1, r1, 16


00000068 <exit>:
  68:    b8000000     bri      0               // 68 <exit>

0000006c <__do_global_dtors_aux>:
  6c:    e0600350     lbui     r3, r0, 848     // 350 <_essro>
  70:    3021ffe4     addik    r1, r1, -28
  74:    f9e10000     swi      r15, r1, 0
  78:    bc030014     beqi     r3, 20          // 8c
  7c:    b8000028     bri      40              // a4
  80:    f8600338     swi      r3, r0, 824     // 338 <p.0>
  84:    99fc2000     brald    r15, r4
  88:    80000000     or       r0, r0, r0
  8c:    e8600338     lwi      r3, r0, 824     // 338 <p.0>
  90:    e8830000     lwi      r4, r3, 0
  94:    be24ffec     bneid    r4, -20         // 80
  98:    30630004     addik    r3, r3, 4
  9c:    30600001     addik    r3, r0, 1
  a0:    f0600350     sbi      r3, r0, 848     // 350 <_essro>
  a4:    e9e10000     lwi      r15, r1, 0
  a8:    b60f0008     rtsd     r15, 8
  ac:    3021001c     addik    r1, r1, 28

000000b0 <frame_dummy>:
  b0:    e860034c     lwi      r3, r0, 844     // 34c <_edata>
  b4:    3021ffe4     addik    r1, r1, -28
  b8:    f9e10000     swi      r15, r1, 0
  bc:    bc03001c     beqi     r3, 28          // d8
  c0:    b0000000     imm      0
  c4:    30600000     addik    r3, r0, 0
  c8:    30a0034c     addik    r5, r0, 844     // 34c <_edata>
  cc:    bc03000c     beqi     r3, 12          // d8
  d0:    99fc1800     brald    r15, r3
  d4:    80000000     or       r0, r0, r0
  d8:    e9e10000     lwi      r15, r1, 0
  dc:    b60f0008     rtsd     r15, 8
  e0:    3021001c     addik    r1, r1, 28

000000e4 <_crtinit>:
  e4:    2021ffec     addi    r1, r1, -20
  e8:    f9e10000     swi     r15, r1, 0
  ec:    20c00350     addi    r6, r0, 848     // 350 <_essro>
  f0:    20e00350     addi    r7, r0, 848     // 350 <_essro>
  f4:    06463800     rsub    r18, r6, r7
  f8:    bc720014     blei    r18, 20         // 10c
  fc:    f8060000     swi     r0, r6, 0
 100:    20c60004     addi    r6, r6, 4
 104:    06463800     rsub    r18, r6, r7
 108:    bc92fff4     bgti    r18, -12        // fc
 10c:    20c00350     addi    r6, r0, 848     // 350 <_essro>
 110:    20e0035c     addi    r7, r0, 860     // 35c <__bss_end>
 114:    06463800     rsub    r18, r6, r7
 118:    bc720014     blei    r18, 20         // 12c
 11c:    f8060000     swi     r0, r6, 0
 120:    20c60004     addi    r6, r6, 4
 124:    06463800     rsub    r18, r6, r7
 128:    bc92fff4     bgti    r18, -12        // 11c
 12c:    b9f40084     brlid   r15, 132        // 1b0 <_program_init>
 130:    80000000     or      r0, r0, r0
 134:    b9f401ac     brlid   r15, 428        // 2e0 <_etext>
 138:    80000000     or      r0, r0, r0
 13c:    20c00000     addi    r6, r0, 0
 140:    20e00000     addi    r7, r0, 0
 144:    b9f40024     brlid   r15, 36         // 168 <main>
 148:    20a00000     addi    r5, r0, 0
 14c:    b9f401b8     brlid   r15, 440        // 304 <__fini>
 150:    80000000     or      r0, r0, r0
 154:    b9f40054     brlid   r15, 84         // 1a8 <_program_clean>
 158:    80000000     or      r0, r0, r0
 15c:    c9e10000     lw      r15, r1, r0
 160:    b60f0008     rtsd    r15, 8
 164:    20210014     addi    r1, r1, 20

00000168 <main>:
 168:    3021ffe8     addik   r1, r1, -24
 16c:    fa610014     swi     r19, r1, 20
 170:    12610000     addk    r19, r1, r0
 174:    b00041f0     imm     16880
 178:    f800c004     swi     r0, r0, -16380
 17c:    3060007f     addik   r3, r0, 127
 180:    b00041f0     imm     16880
 184:    f860c000     swi     r3, r0, -16384
 188:    b00041f0     imm     16880
 18c:    f800c000     swi     r0, r0, -16384
 190:    3060002a     addik   r3, r0, 42
 194:    b00041f0     imm     16880
 198:    f860c000     swi     r3, r0, -16384
 19c:    b8000000     bri     0                // 19c

000001a0 <_exception_handler>:
 1a0:    b6110000     rtsd    r17, 0
 1a4:    80000000     or      r0, r0, r0

000001a8 <_program_clean>:
 1a8:    b60f0008     rtsd   r15, 8
 1ac:    80000000     or     r0, r0, r0

000001b0 <_program_init>:
 1b0:    b60f0008     rtsd   r15, 8
 1b4:    80000000     or     r0, r0, r0

000001b8 <_hw_exception_handler>:
 1b8:    b8000000     bri    0                // 1b8 <_hw_exception_handler>

000001bc <__interrupt_handler>:
 1bc:    3021ffb0     addik  r1, r1, -80
 1c0:    f9e10000     swi    r15, r1, 0
 1c4:    f8610020     swi    r3, r1, 32
 1c8:    f8810024     swi    r4, r1, 36
 1cc:    f8a10028     swi    r5, r1, 40
 1d0:    f8c1002c     swi    r6, r1, 44
 1d4:    f8e10030     swi    r7, r1, 48
 1d8:    f9010034     swi    r8, r1, 52
 1dc:    f9210038     swi    r9, r1, 56
 1e0:    f941003c     swi    r10, r1, 60
 1e4:    f9610040     swi    r11, r1, 64
 1e8:    f9810044     swi    r12, r1, 68
 1ec:    fa210048     swi    r17, r1, 72
 1f0:    95608001     mfs    r11, rmsr
 1f4:    e8a00340     lwi    r5, r0, 832
 1f8:    e860033c     lwi    r3, r0, 828     // 33c <MB_InterruptVectorTable>
 1fc:    fa41004c     swi    r18, r1, 76
 200:    f961001c     swi    r11, r1, 28
 204:    99fc1800     brald  r15, r3
 208:    80000000     or     r0, r0, r0
 20c:    e9e10000     lwi    r15, r1, 0
 210:    e961001c     lwi    r11, r1, 28
 214:    e8610020     lwi    r3, r1, 32
 218:    e8810024     lwi    r4, r1, 36
 21c:    940bc001     mts    rmsr, r11
 220:    e8a10028     lwi    r5, r1, 40
 224:    e8c1002c     lwi    r6, r1, 44
 228:    e8e10030     lwi    r7, r1, 48
 22c:    e9010034     lwi    r8, r1, 52
 230:    e9210038     lwi    r9, r1, 56
 234:    e941003c     lwi    r10, r1, 60
 238:    e9610040     lwi    r11, r1, 64
 23c:    e9810044     lwi    r12, r1, 68
 240:    ea210048     lwi    r17, r1, 72
 244:    ea41004c     lwi    r18, r1, 76
 248:    b62e0000     rtid   r14, 0
 24c:    30210050     addik  r1, r1, 80

00000250 <microblaze_register_handler>:
 250:    f8a0033c     swi    r5, r0, 828     // 33c <MB_InterruptVectorTable>
 254:    f8c00340     swi    r6, r0, 832
 258:    b60f0008     rtsd   r15, 8
 25c:    80000000     or     r0, r0, r0

00000260 <XAssert>:
 260:    e8600354     lwi    r3, r0, 852     // 354 <XAssertCallbackRoutine>
 264:    3021ffe4     addik  r1, r1, -28
 268:    f9e10000     swi    r15, r1, 0
 26c:    bc230018     bnei   r3, 24          // 284
 270:    e8600344     lwi    r3, r0, 836     // 344 <XWaitInAssert>
 274:    bc230000     bnei   r3, 0           // 274
 278:    e9e10000     lwi    r15, r1, 0
 27c:    b60f0008     rtsd   r15, 8
 280:    3021001c     addik  r1, r1, 28
 284:    99fc1800     brald  r15, r3
 288:    80000000     or     r0, r0, r0
 28c:    b800ffe4     bri    -28             // 270

00000290 <XAssertSetCallback>:
 290:    f8a00354     swi    r5, r0, 852     // 354 <XAssertCallbackRoutine>
 294:    b60f0008     rtsd   r15, 8
 298:    80000000     or     r0, r0, r0

0000029c <XNullHandler>:
 29c:    b60f0008     rtsd   r15, 8
 2a0:    80000000     or     r0, r0, r0

000002a4 <__do_global_ctors_aux>:
 2a4:    3021ffe0     addik  r1, r1, -32
 2a8:    fa61001c     swi    r19, r1, 28
 2ac:    e8600320     lwi    r3, r0, 800     // 320 <__CTOR_LIST__>
 2b0:    32600320     addik  r19, r0, 800    // 320 <__CTOR_LIST__>
 2b4:    f9e10000     swi    r15, r1, 0
 2b8:    b8000010     bri    16              // 2c8
 2bc:    99fc1800     brald  r15, r3
 2c0:    3273fffc     addik  r19, r19, -4
 2c4:    e8730000     lwi    r3, r19, 0
 2c8:    aa43ffff     xori   r18, r3, -1
 2cc:    bc32fff0     bnei   r18, -16        // 2bc
 2d0:    e9e10000     lwi    r15, r1, 0
 2d4:    ea61001c     lwi    r19, r1, 28
 2d8:    b60f0008     rtsd   r15, 8
 2dc:    30210020     addik  r1, r1, 32
Disassembly of section .init:

000002e0 <__init>:
 2e0:    3021fff8     addik   r1, r1, -8
 2e4:    d9e00800     sw      r15, r0, r1
 2e8:    b9fc00b0     bralid  r15, 176      // b0 <frame_dummy>
 2ec:    80000000     or      r0, r0, r0
 2f0:    b9fc02a4     bralid  r15, 676      // 2a4 <__do_global_ctors_aux>
 2f4:    80000000     or      r0, r0, r0
 2f8:    c9e00800     lw      r15, r0, r1
 2fc:    b60f0008     rtsd    r15, 8
 300:    30210008     addik   r1, r1, 8
Disassembly of section .fini:

00000304 <__fini>:
 304:    3021fff8     addik   r1, r1, -8
 308:    d9e00800     sw      r15, r0, r1
 30c:    b9fc006c     bralid  r15, 108     // 6c <__do_global_dtors_aux>
 310:    80000000     or      r0, r0, r0
 314:    c9e00800     lw      r15, r0, r1
 318:    b60f0008     rtsd    r15, 8
 31c:    30210008     addik   r1, r1, 8


MicroBlaze Software Reference Guide

The
MicroBlaze Software Reference Guide will tell us all about writing software for the MicroBlaze soft processor.

System memory layout

How is the system memory allocated. Let's try to find out. Address range 0x00000000-0x0000004f is reserved for reset, exceptions, interrupt and break vectors.

Event Vector Address
Register File Return Address
Reset 0x00000000-0x00000004 -
User Vector (Exception)
0x00000008-0x0000000c Rx
Interrrupt 0x00000010-0x00000014  R14
Break
0x00000018-0x0000001c  R16
Hardware Exception
0x00000020-0x00000024 R17 or BTR
Reserved by Xilinx for future use
0x00000028-0x0000004f -

To allow for 64 bit addressing two 32 bit worlds are reserved for each vector.

Reset sequence



When a Reset occurs, MicroBlaze flushes the pipeline and starts fetching instructions from the reset vector (address 0x0). The external reset signal is active high and should be asserted for a minimum of 16 cycles.

The branch instruction <b
rai  _TEXT_START_ADDR> stored in address 0x0 will be executed (see Simvision plot). _TEXT_START_ADDR marks the start of the executable code.


ELF file content

 C routine
 Description
_start1  
exit End of program loop 
_do_global_dtors_aux   
frame_dummy  
_crtinit  
main Our program
_exception_handler
 
_program_clean

_program_init

_hw_exception_handler

__interrupt_handler

microblaze_register_handler

XAssert

XAssertSetCallback

XNullHandler

__do_global_ctors_aux

__init

__fini

 
Here are some more information about the different files used when compiling and linking a typical MicroBlaze executable.
 
Startup files

The compiler includes pre-compiled startup and end files in the final link command when forming an executable. Startup files set up the language and the platform environment before your application code executes. The following actions are typically performed by startup files:
  • Set up any reset, interrupt, and exception vectors as required.
  • Set up stack pointer, small-data anchors, and other registers. Refer to Table 10-9 for details.
  • Clear the BSS memory regions to zero.
  • Invoke language initialization functions, such as C++ constructors.
  • Initialize the hardware sub-system.
  • Set up arguments for the main procedure and invoke it.
Similarly, end files are used to include code that must execute after your program ends. The following actions are typically performed by end files:
  • Invoke language cleanup functions, such as C++ destructors.
  • De-initialize the hardware sub-system. For example, if the program is being profiled, clean up the profiling sub-system.
First stage initialization files

crt0.o

This initialization file is used for programs which are to be executed in standalone mode, without the use of any bootloader or debugging stub such as xmdstub. This CRT populates the reset, interrupt, exception, and hardware exception vectors and invokes the second stage startup routine _crtinit. On returning from _crtinit, it ends the program by infinitely looping in the exit label.

Second stage initialization files

According to the C standard specification, all global and static variables must be initialized to 0. This is a common functionality required by all the CRTs above. Another routine _crtinit is invoked. The _crtinit routine initializes memory in the .bss section of the program. _crtinit is also the wrapper that invokes the main procedure. Before invoking the main procedure, it may invoke other initialization functions. _crtinit is supplied by the following startup files, as described below.

crtinit.o

This is the default second stage C startup file. This startup file performs the following steps:
  1. Clears the .bss section to zero.
  2.  Invokes _program_init.
  3.  Invokes "constructor" functions (__init).
  4. Sets up the arguments for main and invokes main.
  5. Invokes "destructor" functions (__fini).
  6. Invokes _program_clean and returns.

Top
  Next  Previous



Posted at 06:59 pm by svenand
Make a comment  

 
Jun 14, 2007
FPGA design from scratch. Part 33
Simulating the LCD driver

I have been fighting for a few days to the get the LCD driver to display "Hello World" on the LCD without success. Now it's time to setup our simulation environment and run some simulations to try to figure out what is going on. See
part 23 and 24 for more information on how to setup and run a simulation. We can also take a look in EDK System Simulation Tutorial.

C program

Here is the first program we are going to use. We load the code into SDK and compile and link it and then convert the load module to a memory image that we can use in our simulation.

#include "xparameters.h"

#define poke(addr,val)     (*(unsigned char*) (addr) = (val))
#define pokew(addr,val)    (*(unsigned*) (addr) = (val))
#define peek(addr)         (*(unsigned char*) (addr))
#define peekw(addr)        (*(unsigned*) (addr))

int main(void) {  

   unsigned char byte_of_data;
   unsigned      word_of_data;
   int           i,j;
 
   // Define GPIO bus as outputs only
   pokew(XPAR_LCD_16X2_BASEADDR+4,0x00);
  
   // Write data to LCD
   pokew(XPAR_LCD_16X2_BASEADDR,0x7f);
   pokew(XPAR_LCD_16X2_BASEADDR,0x00);
   pokew(XPAR_LCD_16X2_BASEADDR,0x2a);
  
   // Stay in this loop
   while(1);
  
   return 0;
  
  }

Program execution

Here is the result.




Looks perfectly fine to me. So far so good. Let's do the same thing using the Xilinx's software drivers. Like this:

//$$INCLUDE
/*************************************************************************/
/*                                                                       */
/*                I N C L U D E   H E A D E R   F I L E S                */
/*                                                                       */
/*************************************************************************/

#include "xparameters.h"
#include "xgpio.h"

//$$DEFINE
/*************************************************************************/
/*                                                                       */
/*                  D E F I N E   C O N S T A N T S                      */
/*                                                                       */
/*************************************************************************/

// The following constant maps to the name of the hardware instances that
// were created in the EDK XPS system.
 
#define GPIO_LCD_DEVICE_ID    XPAR_LCD_16X2_DEVICE_ID

// The following constant is used to determine which channel of the GPIO is
// used for the LCD if there are 2 channels supported.

#define LCD_CHANNEL 1

// The following are declared globally so they are zeroed and so they are
// easily accessible from a debugger

XGpio GpioLCD;     /* The Instance of the GPIO Driver */

//$$MAIN
/*************************************************************************/
/*                                                                       */
/*                        M A I N   P R O G R A M                        */
/*                                                                       */
/*************************************************************************/

int main(void) {  

    XStatus Status;
   
    // Initialize the GPIO component
    Status = XGpio_Initialize(&GpioLCD, GPIO_LCD_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;
 
    // Set the direction for all bits to be outputs
    XGpio_SetDataDirection(&GpioLCD,    LCD_CHANNEL, 0x00000000);  
 
    // Write data
    XGpio_DiscreteWrite(&GpioLCD,    LCD_CHANNEL, 0x7f);

    XGpio_DiscreteWrite(&GpioLCD,    LCD_CHANNEL, 0x00);
    XGpio_DiscreteWrite(&GpioLCD,    LCD_CHANNEL, 0x2a);
    while(1);
    return XST_SUCCESS;

  }

Before we continue to compile and build a complete application program let's take a look at Xilinx software platform.

Generating the software libraries and BSPs

The Library Generation tool (Libgen) configures libraries, device drivers, file systems, and interrupt handlers for the embedded processor system, creating a software platform.

For more information about Libgen, refer to the "Library Generator (Libgen)" chapter in the Embedded System Tools Reference Manual. For more information on libraries and device drivers, see the OS and Libraries Document Collection.

To generate the software libraries and BSPs (Board Support Packages), right-click on the specific Software Platform project <microblaze_0_sw_platform> and select Generate Libraries and BSPs . This invokes Libgen.

The software library for the project is created in the project area:  .../microblaze_0/lib/libxil.a
The address map of the system is created in the header file:  .../microblaze_0/include/xparameters.h

A status message appears in the Console window at the bottom of the SDK main window.


The following libraries are generated during the libgen run:

 Library  Description Included
Size 
libc.a Standard C functions compiled for MicroBlaze  Yes
382620
libm.a Math functions
Use -lm
414260
libxil.a Xilinx software drivers
Yes
175302

For more information about the libraries read the document <sa_oslib_libxil_stdc.pdf > found in the directory: .../edk_install/doc/usenglish.

GNU Compiler Tools

EDK includes the GNU compiler (GCC) tools for both the PowerPC™ and MicroBlaze processors. The EDK GNU tools support both the C and C++ languages. The MicroBlaze GNU tools include mb-gcc and mb-g++ compilers, mb-as assembler and mb-ld loader/linker.

The GNU compiler is named mb-gcc for MicroBlaze and powerpc-eabi-gcc for PowerPC. The GNU compiler is a wrapper that calls the following executables:

Pre-processor (cpp0) – This is the first pass invoked by the compiler. The pre-processor replaces all macros with definitions as defined in the source and header files.

Machine and language specific compiler – This compiler works on the pre-processed code, which is the output of the first stage. The language-specific compiler is one of the following:
  • C Compiler (cc1) – The compiler is responsible for most of the optimizations done on the input C code and generating assembly code.
  • C++ Compiler (cc1plus) – The compiler is responsible for most of the optimizations done on the input C++ code and generates assembly code.
Assembler (mb-as for MicroBlaze and powerpc-eabi-as for PowerPC) – The assembly code has mnemonics in assembly language. The assembler converts these to machine language. The assembler also resolves some of the labels generated by the compiler. It creates an object file, which is passed on to the linker.

Linker (mb-ld for MicroBlaze and powerpc-eabi-ld for PowerPC) – The linker links all the object files generated by the assembler. If libraries are provided on the command line, the linker resolves some of the undefined references in the code by linking in some of the functions from the assembler.
For more information read
Embedded System Tools Reference Manual chapter 10.

Input files

The compilers take one or more of the following files as input:
  • C source files
  • C++ source files
  • Assembly files
  • Object files
  • Linker scripts
If not specified, the default linker script embedded in the linker (mb-ld or powerpc-eabi-ld) is used.
In addition to the files mentioned above, the compiler implicitly refers to the libraries files libc.a, libgcc.a, libm.a, and libxil.a.

Output files

The compiler generates the following files as output:
  • An ELF file; the default output file name is a.out
  • Assembly file, if -save-temps or -S option is used
  • Object file, if -save-temps or -c option is used
  • Preprocessor output, .i or .ii file, if -save-temps option is used
Output from SDK build process

When we select Project->Build Project in SDK the following process  takes place.

make all
mb-gcc -c -mno-xl-soft-mul -mxl-pattern-compare -mcpu=v6.00.b -I../../microblaze_0_sw_platform/microblaze_0/include -xl-mode-executable -g -O0 -omain.o ../main.c
 
Building target: ETC_system_program.elf
mb-gcc -o ETC_system_program.elf main.o    -mno-xl-soft-mul -mxl-pattern-compare -mcpu=v6.00.b  -L../../microblaze_0_sw_platform/microblaze_0/lib -xl-mode-executable  
Finished building: ETC_system_program.elf

************** Validating ELF File **************

Validating ELF Section Addresses with Hardware Address Map...
elfcheck -mhs /home/svenand/root/projects/ETC/xps/ETC_system.mhs -p xc4vfx12ff668-10 -xmpdir /home/svenand/root/projects/ETC/xps -pe microblaze_0 ETC_system_program.elf
elfcheck
Xilinx EDK 9.1.01 Build EDK_J_SP1.3
Copyright (c) 1995-2007 Xilinx, Inc.  All rights reserved.

Command Line: elfcheck -mhs /home/svenand/root/projects/ETC/xps/ETC_system.mhs
-p xc4vfx12ff668-10 -xmpdir /home/svenand/root/projects/ETC/xps -pe microblaze_0
ETC_system_program.elf

ELF file    : ETC_system_program.elf

Populating list of memories for processor microblaze_0...

Analyzing file ETC_system_program.elf...

Elfcheck on ETC_system_program.elf completed successfully!

************** Determining Size of ELF File **************

mb-size ETC_system_program.elf
   text       data        bss        dec        hex    filename
   1794        112       1088       2994        bb2    ETC_system_program.elf

Build complete for project ETC_system_program

Program size


The mb-size program displays the size of the text, data and bss parts. The total size is displayed in decimal (dec) and hexadecimal (hex) format.

Text


This section of the object file contains executable program instructions. This section has the
x (executable), r (read-only) and i (initialized) flags. This means that this section can be
assigned to an initialized read-only memory (ROM).

Data

This section contains read-write data. This section has the w (read-write) and the i
(initialized) flags. It must be mapped to initialized random access memory (RAM). It
cannot be mapped to a ROM.

BSS

This section contains un-initialized data. The program stack and the heap are also allocated
to this section. This section has the w (read-write) flag and must be mapped to RAM.


Top  Next  Previous




Posted at 09:45 am by svenand
Make a comment  

 
Jun 12, 2007
FPGA design from scratch. Part 32
Writing the "Hello World" program

It is time to write our first application c-program. The purpose of the program is to display "Hello World" on the LCD display. Let's get started. We will use the
Software Development Kit (SDK) from Xilinx to help us accomplish the task. We start SDK from within Xilinx Platform Studio (XPS) using the menu command Software->Launch Platform Studio SDK.




To find out more about how to use SDK we select the Help menu.



When we click the Getting Started book the SDK design checklist is displayed in our web browser.



We are going to use available software drivers in our program. Let's find out how do that by studying the SDK design checklist.

SDK platform settings

Select Xilinx Tools->Software Platform Settings to look at the available software drivers and the current version used.




C program build

Select the menu Project->Properties to display the program build settings.



C header files


We find all header files in the directory .../SDK_projects/microblaze_0_sw_platform/microblaze_0/include.



The file xparameters.h holds information about the LCD_16x2 module. We will include this file in our c-program.

/* Definitions for peripheral LCD_16X2 */
#define XPAR_LCD_16X2_BASEADDR 0x41F0C000
#define XPAR_LCD_16X2_HIGHADDR 0x41F0CFFF
#define XPAR_LCD_16X2_DEVICE_ID 3
#define XPAR_LCD_16X2_INTERRUPT_PRESENT 0
#define XPAR_LCD_16X2_IS_DUAL 0

The GPIO API definitions

The header file xgpio.h contains the software
API definition of the Xilinx General Purpose I/O (XGpio) device driver component. This file will also be included in our c-program.


C program examples


We are not going to re-invent the wheel. Let's look for some good examples to copy. In the directory .../edk91i/sw/XilinxProcessorIPLib/drivers/gpio_v2_01_a there are a few good ones.



More program examples

Looking in the directories of the reference system CD the following example files were found (xrom_lcd.c and xrom_lcd.h).



Let's use the functions declared in xrom_lcd.h.

Main program


//$$DEFINE
/*************************************************************************/
/*                                                                       */
/*                  I N C L U D E  &   D E F I N E                       */
/*                                                                       */
/*************************************************************************/

  #include "xparameters.h"

  #include "xgpio.h"
  #include "xutil.h"
  #include "stdio.h"
  #include "xrom_lcd.h"

  // The following constant maps to the name of the hardware instances that
  // were created in the EDK XPS system.
 
  #define GPIO_LCD_DEVICE_ID    XPAR_LCD_16X2_DEVICE_ID
  #define GPIO_LED4_DEVICE_ID   XPAR_LEDS_4BIT_DEVICE_ID
  #define GPIO_LEDP_DEVICE_ID   XPAR_LEDS_POSITIONS_DEVICE_ID

  // The following constant is used to determine which channel of the GPIO is
  // used for the LCD if there are 2 channels supported.

  #define LCD_CHANNEL 1
  #define LED_CHANNEL 1

  // The following are declared globally so they are zeroed and so they are
  // easily accessible from a debugger

  XGpio GpioLCD;     /* The Instance of the LCD GPIO Driver */
  XGpio GpioLED4;    /* The Instance of the LED4 GPIO Driver */
  XGpio GpioLEDPOS;  /* The Instance of the LED Pos GPIO Driver */
 
/$$MAIN
/*************************************************************************/
/*                                                                       */
/*                        M A I N   P R O G R A M                        */
/*                                                                       */
/*************************************************************************/

int main(void) {

    XStatus Status;
   
    // Initialize the GPIO component
    Status = XGpio_Initialize(&GpioLCD, GPIO_LCD_DEVICE_ID);
    if (Status != XST_SUCCESS) return XST_FAILURE;

    // Set the direction for all bits to be outputs
    XGpio_SetDataDirection(&GpioLCD, LCD_CHANNEL, 0x0000);

    // Initialize the LCD
    XromLCDInit();

    // Send single characters to the LCD
    print("Send Hello World to the LCD ");
    XromLCDPrintChar('H');
   
XromLCDPrintChar("e");
   
XromLCDPrintChar("l");   
   
XromLCDPrintChar("l");   
   
XromLCDPrintChar("o");
   
XromLCDPrintChar(" ");
   
XromLCDPrintChar("W");
   
XromLCDPrintChar("o");   
   
XromLCDPrintChar("r");   
   
XromLCDPrintChar("l");
   
XromLCDPrintChar("d");
           
    print("Hello World is displayed on the LCD display ");           
    while(1);

    return XST_SUCCESS;
   
    }


Device configuration in SDK

After we built our SDK project, we can download an Executable Linked Format (ELF) file for running or debugging on the target processor. To configure our hardware:
  1. Specify the ELF file to be marked for block RAM (BRAM) initialization by selecting Device Configuration > Program Hardware Settings
  2. Select the initialization file (Bootloop, XMDStub, or ELF file) and click Save.


To download the program bit file (download_sdk.bit) use the command: Device Configuration->Program Hardware.




Top   Next  Previous



Posted at 10:36 am by svenand
Comments (4)  

Next Page