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


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


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

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
Table of contents
OpenRISC 1200
Nios II

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

FPGA Design From Scratch
Started December 2006
Table of contents
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

A hardware designer's best friend
Zoo Design Platform

Installing Cobra Command Tool
A processor benchmark

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

Stockholm by bike

The New York City Marathon

Kittelfjall Lappland

Tour skating in Sweden and around the world
Wild skating
Tour day
Safety equipment
A look at the equipment you need
Skate maintenance
Books, photos, films and videos
Weather forecasts

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

100 Power Tips for FPGA Designers

Adventures in ASIC
Computer History Museum
Design & Reuse
d9 Tech Blog
EDA Cafe
EDA DesignLine
Eli's tech Blog
FPGA Arcade
FPGA Central
FPGA developer
FPGA Journal
FPGA World
Lesley Shannon Courses
Mac 2 Ubuntu
Programmable Logic DesignLine
World of ASIC

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

rss feed

Sunday, June 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 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

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


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_SPACE lmb_bram_combined COMBINED [0x00000000:0x00001fff]
            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] ;


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

-- File generated by

-- Type: beh

library unisim;
library lmb_bram_elaborate_v1_00_a;

configuration lmb_bram_conf of lmb_bram_wrapper is
    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_MODE_A => WRITE_MODE_A,
            WRITE_MODE_B => WRITE_MODE_B,
            INIT_00 => X"B8BCF930E0B82080B93030310000000000000000000000B8000000B800B800B8",
            INIT_01 => X"F8BC062020F92030B6E98099BC3030B0BCF930E830B6E9F03030BEE8E88099F8",


            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 all : lmb_bram_wrapper use configuration work.lmb_bram_conf;
    end for;
  end for;
end ETC_system_conf;


ETC_system_tb.vhd is the VHDL top testbench file.

-- ETC_system_tb.vhd
library IEEE;

library UNISIM;

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;


  -- Clock generator for fpga_0_DDR_CLK_FB

    fpga_0_DDR_CLK_FB <= '0';
      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

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

  -- Reset Generator for sys_rst_pin

    sys_rst_pin <= '0';
    wait for (sys_rst_pin_LENGTH);
    sys_rst_pin <= not sys_rst_pin;
  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 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.

    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.

// 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 17:56 by svenand


Leave a Comment:


Homepage (optional)


Previous Entry Home Next Entry