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

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



 
Wednesday, May 02, 2007
FPGA design from scratch. Part 24
System simulations

System simulation is an effective method for verifying that software drivers are compatible with the hardware. Using a simulator for that purpose offers several advantages over
GDB. For example, no physical link to the hardware is required and internal system signals may be easily monitored. In addition, the hardware does not need to be run through the implementation tools to run a system simulation, allowing the quick analysis of the effects of changes to the code or the generics. The flow presented here can easily be modified to support structural and timing simulation.

The
EDK System Simulation guide presents Xilinx idea about system simulations. They use Modelsim and the setup is to complicated for my taste. We will stay with NCSIM and the simulation strategy we formulated in part 23. We will specify testcases to verify all interfaces in our system. Each testcase will include a c-program to access the peripheral and it's registers. Here is our system.




DDR SDRAM controller


The DDR SDRAM controller (
opb_ddr) connects the DDR SDRAM to the OPB. The DDR SDRAM is a Micron  MT46V16M16P-6T.

Features
  • OPB interface
  • Performs device initialization sequence upon power-up and reset conditions for ~200uS. Provides a parameter to adjust this time for simulation purposes only.
  • Performs auto-refresh cycles
  • Supports CAS latencies of 2 or 3 set by a design parameter
  • Supports 16, 32 and 64 bits DDR data widths set by a designparameter
  • Supports indeterminate burst length
  • Provides big-endian connections to memory devices
  • Supports multiple (up to 4) DDR memory banks.

DDR SDRAM Initialization

Prior to normal operation, DDR SDRAMs must be powered up and initialized in a predefined manner. Operational procedures, other than those specified, may result in undefined operation. To ensure device operation, the DRAM must be initialized as described in the following steps:
  1. Simultaneously apply power to VDD and VDDQ
  2. Apply VREF and then VTT power. VTT must be applied after VDDQ to avoid device latchup, which may cause permanent damage to the device. Exept for CKE, inputs are not recognized as valid until after VREF is applied.
  3. Assert and hold CKE at a LVCMOS logic LOW. Maintaining an LVCMOS LOW level on CKE during power-up is required to ensure that the DQ and DQS outputs will be in the High-Z state, where they will remain until driven in normal operation (by a read access).
  4. Provide stable clock signals.
  5. Wait at least 200μs.
  6. Bring CKE HIGH, and provide at least one NOP or DESELECT command. At this point, the CKE input changes from a LVCMOS input to a SSTL_2 input only and will remain a SSTL_2 input unless a power cycle occurs.
  7. For more information about the initialization see the DDR SDRAM data sheet.
Setting the initialization time

The OPB DDR block will insert a 200us delay before it asserts DDR_init_done (see waveform plot) to allow time for DDR SDRAM initialization to happen.



For simulation purpose only we can change that time by editing the wrapper file ddr_sdram_64mx32_wrapper.vhd.
Look for the line: C_SIM_INIT_TIME_PS => 200000000 and change it to
C_SIM_INIT_TIME_PS => 20000 (20ns).




C program

This program will write and read three addresses in the DDR SDRAM.

int main()

#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))
 

{   

   unsigned char byte_of_data;
   unsigned      word_of_data;
  
   pokew(0x44000000,0xffffffff);
   pokew(0x46000004,0xaaaaaaaa);
   pokew(0x47fffffc,0x55555555);
  
   word_of_data = peekw(0x44000000);
   word_of_data = peekw(0x46000004);
   word_of_data = peekw(0x47fffffc);
   
    return 0;
}
 
Assembly code

 
  0:    3021fff0     addik   r1, r1, -16
   4:    fa61000c     swi     r19, r1, 12
   8:    12610000     addk    r19, r1, r0
   c:    3060ffff     addik   r3, r0, -1
  10:    b0004400     imm     17408
  14:    f8600000     swi     r3, r0, 0
  18:    b000aaaa     imm     -21846
  1c:    3060aaaa     addik   r3, r0, -21846
  20:    b0004600     imm     17920
  24:    f8600004     swi     r3, r0, 4
  28:    b0005555     imm     21845
  2c:    30605555     addik   r3, r0, 21845
  30:    b00047ff     imm     18431
  34:    f860fffc     swi     r3, r0, -4
  38:    b0004400     imm     17408
  3c:    e8600000     lwi     r3, r0, 0
  40:    f8730008     swi     r3, r19, 8
  44:    b0004600     imm     17920
  48:    e8600004     lwi     r3, r0, 4
  4c:    f8730008     swi     r3, r19, 8
  50:    b00047ff     imm     18431
  54:    e860fffc     lwi     r3, r0, -4
  58:    f8730008     swi     r3, r19, 8
  5c:    10600000     addk    r3, r0, r0
  60:    10330000     addk    r1, r19, r0
  64:    ea61000c     lwi     r19, r1, 12
  68:    30210010     addik   r1, r1, 16
  6c:    b60f0008     rtsd    r15, 8
  70:    80000000     or      r0, r0, r0

Simulation result




LED displays and push buttons

The LED displays (LED_Positions and LEDs_4Bit) and the push buttons are connected to the general purpose input/outputs and through the OPB General Purpose Input/Output (
GPIO) controller to the OPB bus.

Features
  • OPB v2.0 bus interface with byte-enable support
  • Configurable as single or dual GPIO channel(s)
  • Number of GPIO bits configurable from 1 to 32 bits
  • Each GPIO bit dynamically programmable as input or output
  • Can be configured as inputs-only on a per channel basis to reduce resource utilization
  • Ports for both 3-state and non 3-state connections
  • Independent reset values for each bit of all registers
  • Optional interrupt request generation
Address ranges

0x40020000-0x4002ffff LEDs_Positions
0x40040000-0x4004ffff LEDs_4Bit
0x40000000-0x4000ffff Push_Buttons_Position

OPB GPIO Registers

There are four internal registers in the OPB GPIO design as shown in the table. These registers are implemented in the GPIO_CORE interface module. The memory map of the OPB GPIO design is determined by setting the C_BASEADDR parameter. The internal registers of the OPB GPIO are at a fixed offset from the base address.

 Register Name
 Description  OPB Address
 Access
 GPIO_DATA  Channel 1 OPB GPIO Data Register  C_BASEADDR + 0x00  Read/Write
 GPIO_TRI  Channel 1 OPB GPIO 3-state Register  C_BASEADDR + 0x04  Read/Write
 GPIO2_DATA  
 Channel 2 OPB GPIO Data register 
 C_BASEADDR + 0x08  Read/Write
 GPIO2_TRI  Channel 2 OPB GPIO 3-state Register
 C_BASEADDR + 0x0C
 Read/Write

C program

int main()

#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))
 

{   

   unsigned char byte_of_data;
   unsigned      word_of_data;
  
// Write to LEDs
   pokew(0x40020000,0xffffffff);

   pokew(0x40020004,0x00000000);
   pokew(0x40020008,0x33333333);
   pokew(0x4002000c,0x00000000);
   pokew(0x40040000,0x55555555);
   pokew(0x40040004,0x00000000);
   pokew(0x40040008,0x11111111);
   pokew(0x4004000c,0x00000000);
// Read push buttons

   pokew(0x40000004,0xffffffff);
  
word_of_data  = peek(0x40000000);
   pokew(0x4000000c,0xffffffff);
 
 
  word_of_data  = peek(0x40000008);
 
   return 0;

Assembly code

   0:    3021fff0     addik  r1, r1, -16
   4:    fa61000c     swi    r19, r1, 12
   8:    12610000     addk   r19, r1, r0
   c:    3060ffff     addik  r3, r0, -1
  10:    b0004002     imm    16386
  14:    f8600000     swi    r3, r0, 0
  18:    b0004002     imm    16386
  1c:    f8000004     swi    r0, r0, 4
  20:    b0003333     imm    13107
  24:    30603333     addik  r3, r0, 13107
  28:    b0004002     imm    16386
  2c:    f8600008     swi    r3, r0, 8
  30:    b0004002     imm    16386
  34:    f800000c     swi    r0, r0, 12
  38:    b0005555     imm    21845
  3c:    30605555     addik  r3, r0, 21845
  40:    b0004004     imm    16388
  44:    f8600000     swi    r3, r0, 0
  48:    b0004004     imm    16388
  4c:    f8000004     swi    r0, r0, 4
  50:    b0001111     imm    4369
  54:    30601111     addik  r3, r0, 4369
  58:    b0004004     imm    16388
  5c:    f8600008     swi    r3, r0, 8
  60:    b0004004     imm    16388
  64:    f800000c     swi    r0, r0, 12
  68:    3060ffff     addik  r3, r0, -1
  6c:    b0004000     imm    16384
  70:    f8600004     swi    r3, r0, 4
  74:    b0004000     imm    16384
  78:    e8600000     lwi    r3, r0, 0
  7c:    f8730008     swi    r3, r19, 8
  80:    3060ffff     addik  r3, r0, -1
  84:    b0004000     imm    16384
  88:    f860000c     swi    r3, r0, 12
  8c:    b0004000     imm    16384
  90:    e8600008     lwi    r3, r0, 8
  94:    f8730008     swi    r3, r19, 8
  98:    10600000     addk   r3, r0, r0
  9c:    10330000     addk   r1, r19, r0
  a0:    ea61000c     lwi    r19, r1, 12
  a4:    30210010     addik  r1, r1, 16
  a8:    b60f0008     rtsd   r15, 8
  ac:    80000000     or     r0, r0, r0


Simulation result





Embedded Test Controller

The Embedded Test Controller (ETC) is a custom IP that implements a 1149.1 complient JTAG tester. It can run JTAG test sequences on the board and/or the complete system during startup and normal operation.

ETC address map


Register/ Memory Name
Size Access Address
Control 32 Write 0x42a10000
Status
32 Read 0x42a10004
Execute 32 Write 0x42a10008 
Debug  32 Read 0x42a1000c
Test program RAM
1Kx32 Write 0x42a08000 
Test result RAM
1Kx32  Read 0x42a09000 

C program

int main()

#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))

{   

   unsigned char byte_of_data;
   unsigned      word_of_data;
  
// Write testprogram
   pokew(0x42a08000,0x800000f1);
   pokew(0x42a08004,0x80000000);
   pokew(0x42a08008,0x800000f2);
   pokew(0x42a0800c,0x8000000c);
    
// Write control register in ETC
// Enable TCK clock
   pokew(0x42a10000,0x000000a0);
   
// Read status register in ETC 
   word_of_data = peekw(0x42a10004); 
// Read debug register in ETC
   word_of_data = peekw(0x42a1000c);
  
// Start test program
   pokew(0x42a10008,0x00000001);


Simulation result
 




Debugging the On-chip Peripheral Bus

When I started to debug the ETC IP I quickly found out that my implementation and the Xilinx implementations of the OPB interface differed.

Specifications

Here is the IBM
On-Chip Peripheral Bus Architecture Specification and here is the Xilinx implementation

MicroBlaze write cycle.

Let's take a closer look at the OPB. Here are two plots showing all signals in the Xilinx implemantation of the OPB interface.

Here are all the input signals to the mb_opb block.





Here are all the output signals from the mb_opb block.




OPB signal description

Signal Description Width
 Used in ETC
OPB_ABus Address bus
32
Yes
OPB_BE Data byte enable
4
Yes
OPB_beAck  OPB byte enable acknowledge
1
No 
OPB_beXfer OPB byte enable transfer
1
No
OPB_busLock
OPB bus arbitration lock  1
No 
OPB_Dbus OPB Ddata bus
32
Yes
OPB_dwAck OPB doubleword acknowledge  1
No
OPB_dwXfer OPB doubleword transfer
1
No
OPB_errAck OPB error acknowledge  1
Yes, always = 0
OPB_fwAck
OPB fullword acknowledge
1
Yes, always = 0
OPB_fwXfer
OPB fullword transfer
1
No
OPB_hwAck
OPB halfword acknowledge
1
No
OPB_hwXfer
OPB halfword transfer
1
No
OPB_MGrant
OPB master bus grant
2
No
OPB_MRequest
OPB Master bus request
2
No
OPB_pendReq
OPB pending master request
2
No
OPB_rdDbus
OPB read data bus
32
No
OPB_retry
OPB bus cycle retry
1
Yes, always = 0
OPB_RNW
OPB read not write (write=L)
1
Yes
OPB_Rst
OPB reset
1
Yes
OPB_select
OPB select
1
Yes
OP_seqAddr
OPB sequential address
1
No
OPB_timeout
OPB timeout error
1
No
OPB_toutSup
OPB timeout suppress
1
Yes, always = 0
OPB_wrDbus
OPB write data bus
32
No
OPB_xferAck
OPB transfer acknowledge
1
Yes


Final result

It took me a couple of days to sort out all issues around the ETC OPB interface. Here is what I found out. Right or wrong?
  • The read and write cycles can be two or more clock cycles long. The OPB interface can decide how long the read and write cycles will be by asserting the OPB_xferAck in the last clock cycle. I am using 3 clock cycles in the ETC OPB interface.
  • The fullword and halfword control signals are not implemented in the Xilinx version of OPB. Use the signal OPB_BE instead. OPB_BE = 4'b1111 enable all four bytes when reading and writing 32 bit words.
  • Always keep the read data bus low when no valid read cycle is taking place. Read data busses from all peripherals are or'ed together in the mb_opb block and only one peripheral at a time can drive the bus high. Important !!!
  • You don't have to implement the signals OPB_errAck, OPB_toutSup and OPB_retry. I have set them all low.
Here is my OPB interface to the ETC block. Comments and improvements are welcomed.


Top  Next  Previous



Posted at 20:55 by svenand

Eldon
November 20, 2007   09:11 AM PST
 
Excellent work man, I will recommend this page to my students
 

Leave a Comment:

Name


Homepage (optional)


Comments




Previous Entry Home Next Entry