New Horizons









Welcome to my blog

My name is Sven Andersson and I
work as a consultant in embedded
system design, implemented in ASIC
and FPGA.
In my spare time I write this blog
and I hope it will inspire others to
learn more about this fantastic field.
I live in Stockholm Sweden and have
my own company

Contact

You are welcome to contact me
and ask questions or make comments
about my blog.



Content

New Horizons
What's new
Starting a blog
Writing a blog
Using an RSS reader

Zynq Design From Scratch
Started February 2014
1 Introduction
Changes and updates
2 Zynq-7000 All Programmable SoC
3 ZedBoard and other boards
4 Computer platform and VirtualBox
5 Installing Ubuntu
6 Fixing Ubuntu
7 Installing Vivado
8 Starting Vivado
9 Using Vivado
10 Lab 1. Create a Zynq project
11 Lab 1. Build a hardware platform
12 Lab 1. Create a software application
13 Lab 1. Connect to ZedBoard
14 Lab 1. Run a software application
15 Lab 1. Benchmarking ARM Cortex-A9
16 Lab 2. Adding a GPIO peripheral
17 Lab 2. Create a custom HDL module
18 Lab 2. Connect package pins and implement
19 Lab 2. Create a software application and configure the PL
20 Lab 2. Debugging a software application
21 Running Linux from SD card
22 Installing PetaLinux
23 Booting PetaLinux
24 Connect to ZedBoad via ethernet
25 Rebuilding the PetaLinux kernel image
26 Running a DHCP server on the host
27 Running a TFTP server on the host
28 PetaLinux boot via U-boot
29 PetaLinux application development
30 Fixing the host computer
31 Running NFS servers
32 VirtualBox seamless mode
33 Mounting guest file system using sshfs
34 PetaLinux. Setting up a web server
35 PetaLinux. Using cgi scripts
36 PetaLinux. Web enabled application
37 Convert from VirtualBox to VMware
38 Running Linaro Ubuntu on ZedBoard
39 Running Android on ZedBoard
40 Lab2. Booting from SD card and SPI flash
41 Lab2. PetaLinux board bringup
42 Lab2. Writing userspace IO device driver
43 Lab2. Hardware debugging
44 MicroZed quick start
45 Installing Vivado 2014.1
46 Lab3. Adding push buttons to our Zynq system
47 Lab3. Adding an interrupt service routine
48 Installing Ubuntu 14.04
49 Installing Vivado and Petalinux 2014.2
50 Using Vivado 2014.2
51 Upgrading to Ubuntu 14.04
52 Using Petalinux 2014.2
53 Booting from SD card and SPI flash
54 Booting Petalinux 2014.2 from SD card
55 Booting Petalinux 2014.2 from SPI flash
56 Installing Vivado 2014.3

Chipotle Verification System
Introduction

EE Times Retrospective Series
It all started more than 40 years ago
My first job as an electrical engineer
The Memory (R)evolution
The Microprocessor (R)evolution

Four soft-core processors
Started January 2012
Introduction
Table of contents
Leon3
MicroBlaze
OpenRISC 1200
Nios II

Using the Spartan-6 LX9 MicroBoard
Started August 2011
Introduction
Table of contents
Problems, fixes and solutions

FPGA Design From Scratch
Started December 2006
Introduction
Table of contents
Index
Acronyms and abbreviations

Actel FPGA design
Designing with an Actel FPGA. Part 1
Designing with an Actel FPGA. Part 2
Designing with an Actel FPGA. Part 3
Designing with an Actel FPGA. Part 4
Designing with an Actel FPGA. Part 5

CAD
A hardware designer's best friend
Zoo Design Platform

Linux
Installing Cobra Command Tool
A processor benchmark

Mac
Porting a Unix program to Mac OS X
Fixing a HyperTerminal in Mac OS X
A dream come true

Bicycling
Stockholm by bike

Running
The New York City Marathon

Skiing/Skating
Kittelfjall 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
Links
Books, photos, films and videos
Weather forecasts

Travel
38000 feet above see level
A trip to Spain
Florida the sunshine state

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

Books
100 Power Tips for FPGA Designers

Favorites
Adventures in ASIC
ChipHit
Computer History Museum
DeepChip
Design & Reuse
Dilbert
d9 Tech Blog
EDA Cafe
EDA DesignLine
Eli's tech Blog
Embedded.com
EmbeddedRelated.com
FPGA Arcade
FPGA Blog
FPGA Central
FPGA CPU News
FPGA developer
FPGA Journal
FPGA World
Lesley Shannon Courses
Mac 2 Ubuntu
Programmable Logic DesignLine
OpenCores
Simplehelp
SOCcentral
World of ASIC



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



rss feed



 
Sunday, August 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 by

 

Leave a Comment:

Name


Homepage (optional)


Comments




Previous Entry Home Next Entry