cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Newbie
Newbie
11,198 Views
Registered: ‎02-10-2009

How to write software for custom IP?

Jump to solution

Hello,

 

I'm working on a project which will be implemented by EDK 10.1. I have built the system and added a custom peripheral into the system successfully. Next I would like to add software application for the custom IP, but I couldn't find any helpful documents concerning how to write source code and header file for a custom IP. (I can only find examples of existing peripherals.) Could you post some useful link where I can find some application notes or something which I can refer to?(I have included PLB v46, UART 16550 and PowerPC 405 into my application, and I'm using XUPV2P board.)  

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Scholar
Scholar
13,295 Views
Registered: ‎08-14-2007

Hi,

 

When you add a custom IP, generally you uses the "Create/Import Peripheral" wizard of XPS, then you add some "services" to your custom IP (software reset, software registers, interrupts, FIFOs, etc), at the end of this wizard, software drivers (C functions) are created depends of the services that you selected, these drivers are C functions that control your custom IP peripheral, then in your application you only add the library "mycustomip.h"  and then you can use the drivers in your application

 

The drivers of your custom ip are in the directory  ($EDK_project\drivers ) where $EDK_project is the root directory of your project, in this directory you can take a look of how drivers are implemented to control you peripheral. you can add new functions to your customip.h library

Again this drivers depends of what your custom ip do

 

Hope this helps

Regards

View solution in original post

18 Replies
Highlighted
Scholar
Scholar
13,296 Views
Registered: ‎08-14-2007

Hi,

 

When you add a custom IP, generally you uses the "Create/Import Peripheral" wizard of XPS, then you add some "services" to your custom IP (software reset, software registers, interrupts, FIFOs, etc), at the end of this wizard, software drivers (C functions) are created depends of the services that you selected, these drivers are C functions that control your custom IP peripheral, then in your application you only add the library "mycustomip.h"  and then you can use the drivers in your application

 

The drivers of your custom ip are in the directory  ($EDK_project\drivers ) where $EDK_project is the root directory of your project, in this directory you can take a look of how drivers are implemented to control you peripheral. you can add new functions to your customip.h library

Again this drivers depends of what your custom ip do

 

Hope this helps

Regards

View solution in original post

Highlighted
Newbie
Newbie
11,154 Views
Registered: ‎02-10-2009

Thanx a lot!

I've got it clearly!

LEakey

 

0 Kudos
Highlighted
Historian
Historian
11,143 Views
Registered: ‎02-25-2008

lsqleakey wrote:

Hello,

 

I'm working on a project which will be implemented by EDK 10.1. I have built the system and added a custom peripheral into the system successfully. Next I would like to add software application for the custom IP, but I couldn't find any helpful documents concerning how to write source code and header file for a custom IP. (I can only find examples of existing peripherals.) Could you post some useful link where I can find some application notes or something which I can refer to?(I have included PLB v46, UART 16550 and PowerPC 405 into my application, and I'm using XUPV2P board.)  


We have found that the whole Xilinx notion of "drivers" is waaay overcomplicated and fraught with danger.

 

It's a simple matter to understand that, at the base of things, your IP core amounts to a bunch of hardware addresses that you peek and poke. So it's easy to create a source file and a header that encapsulate everything necessary to handle your hardware, and then simply add those files to your application project, rather than dealing with it all as a "driver."

 

-a

----------------------------Yes, I do this for a living.
0 Kudos
Highlighted
Observer
Observer
10,142 Views
Registered: ‎03-30-2009

I have followed the steps provided above in all their detail, but for some reason there is no "drivers" folder created for me in the root directory after I have "successfully" added my custom IP. I have gone through the wizard a few times now, and see no options at the end for adding in C-files for my IP. Since EDK can't "find" or "create" a driver for my IP, it goes ahead and assigns my IP a "generic" driver file out of the EDK driver library. I obviously do not want this.

 

Any advice from someone who has done this successfully?

Message Edited by skimura_lynx on 04-23-2009 10:23 AM
0 Kudos
Highlighted
Scholar
Scholar
10,143 Views
Registered: ‎08-14-2007

hi,

 

you must have selected the option "Generate template drivers file ..." in the create custom ip wizard , see figure below, then in the root folder of your project you will have the "drivers" directory

 

best regards

imagcustom.JPG
Highlighted
Observer
Observer
10,102 Views
Registered: ‎09-13-2007

Thanks a lot pumaju 1808

I had the same problem drives directory not generated!!

Now i know the cause. It is mentioned in the EDK CTT pdf "use default"

and the default is unchecked box for " Generate template drivers file ...".

 

take care others...

0 Kudos
Highlighted
Observer
Observer
10,024 Views
Registered: ‎03-30-2009

Thanks for the help so far. Unfortunately, this only works if you CREATE a new peripheral. In my case, I am trying to IMPORT a peripheral from an existing ISE project. What I've found after talking with some Xilinx people, is that you must first "Create" a peripheral so that all of your driver directories/files are created, then you have to manually copy over all of your Verilog/VHDL IP source files as well as modify your .mpd/.pao file a bit to get it work correctly. I can give more details after I try to do it myself right now! :smileyhappy:

0 Kudos
Highlighted
Scholar
Scholar
9,980 Views
Registered: ‎08-14-2007

that right skimura,

 

does not matter if you are trying to import, in any case you must first create your peripheral, then you import

0 Kudos
Highlighted
Contributor
Contributor
8,081 Views
Registered: ‎03-31-2010

i create an ip and i link it to microblaze. it has to in put and one output ; the first is the clock and i link it to bus2ip_clk the second is a 8bit value witch i like to put it myself to control the ip . i tried to write it to slv_reg0 and link or copy it to input but it wrote successefuly in register but variable dont take the value. if i fix input as a signal and write the value in it work and i have an output in led but i like to change it from hyperterminal not to change it in vhdl file and re import the ip and download the bit everyttime. here the user_logic :

0 Kudos
Highlighted
Contributor
Contributor
7,241 Views
Registered: ‎03-31-2010

sorry something gone wrong with the navigator

 

------------------------------------------------------------------------------
-- user_logic.vhd - entity/architecture pair
------------------------------------------------------------------------------
--
-- ***************************************************************************
-- ** Copyright (c) 1995-2006 Xilinx, Inc.  All rights reserved.            **
-- **                                                                       **
-- ** Xilinx, Inc.                                                          **
-- ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"         **
-- ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND       **
-- ** SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,        **
-- ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,        **
-- ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION           **
-- ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,     **
-- ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE      **
-- ** FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY              **
-- ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE               **
-- ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR        **
-- ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF       **
-- ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS       **
-- ** FOR A PARTICULAR PURPOSE.                                             **
-- **                                                                       **
-- ***************************************************************************
--
------------------------------------------------------------------------------
-- Filename:          user_logic.vhd
-- Version:           1.00.a
-- Description:       User logic.
-- Date:              Thu Jun 10 19:15:14 2010 (by Create and Import Peripheral Wizard)
-- VHDL Standard:     VHDL'93
------------------------------------------------------------------------------
-- Naming Conventions:
--   active low signals:                    "*_n"
--   clock signals:                         "clk", "clk_div#", "clk_#x"
--   reset signals:                         "rst", "rst_n"
--   generics:                              "C_*"
--   user defined types:                    "*_TYPE"
--   state machine next state:              "*_ns"
--   state machine current state:           "*_cs"
--   combinatorial signals:                 "*_com"
--   pipelined or register delay signals:   "*_d#"
--   counter signals:                       "*cnt*"
--   clock enable signals:                  "*_ce"
--   internal version of output port:       "*_i"
--   device pins:                           "*_pin"
--   ports:                                 "- Names begin with Uppercase"
--   processes:                             "*_PROCESS"
--   component instantiations:              "<ENTITY_>I_<#|FUNC>"
------------------------------------------------------------------------------

-- DO NOT EDIT BELOW THIS LINE --------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

library proc_common_v2_00_a;
use proc_common_v2_00_a.proc_common_pkg.all;
-- DO NOT EDIT ABOVE THIS LINE --------------------

--USER libraries added here

------------------------------------------------------------------------------
-- Entity section
------------------------------------------------------------------------------
-- Definition of Generics:
--   C_DWIDTH                     -- User logic data bus width
--   C_NUM_CE                     -- User logic chip enable bus width
--
-- Definition of Ports:
--   Bus2IP_Clk                   -- Bus to IP clock
--   Bus2IP_Reset                 -- Bus to IP reset
--   Bus2IP_Data                  -- Bus to IP data bus for user logic
--   Bus2IP_BE                    -- Bus to IP byte enables for user logic
--   Bus2IP_RdCE                  -- Bus to IP read chip enable for user logic
--   Bus2IP_WrCE                  -- Bus to IP write chip enable for user logic
--   IP2Bus_Data                  -- IP to Bus data bus for user logic
--   IP2Bus_Ack                   -- IP to Bus acknowledgement
--   IP2Bus_Retry                 -- IP to Bus retry response
--   IP2Bus_Error                 -- IP to Bus error response
--   IP2Bus_ToutSup               -- IP to Bus timeout suppress
------------------------------------------------------------------------------

entity user_logic is
  generic
  (
    -- ADD USER GENERICS BELOW THIS LINE ---------------
    --USER generics added here
    -- ADD USER GENERICS ABOVE THIS LINE ---------------

    -- DO NOT EDIT BELOW THIS LINE ---------------------
    -- Bus protocol parameters, do not add to or delete
    C_DWIDTH                       : integer              := 32;
    C_NUM_CE                       : integer              := 1
    -- DO NOT EDIT ABOVE THIS LINE ---------------------
  );
  port
  (
    -- ADD USER PORTS BELOW THIS LINE ------------------
    --USER ports added here
    o_pwm                                        : out std_logic ;
     -- ADD USER PORTS ABOVE THIS LINE ------------------

    -- DO NOT EDIT BELOW THIS LINE ---------------------
    -- Bus protocol ports, do not add to or delete
    Bus2IP_Clk                     : in  std_logic;
    Bus2IP_Reset                   : in  std_logic;
    Bus2IP_Data                    : in  std_logic_vector(0 to C_DWIDTH-1);
    Bus2IP_BE                      : in  std_logic_vector(0 to C_DWIDTH/8-1);
    Bus2IP_RdCE                    : in  std_logic_vector(0 to C_NUM_CE-1);
    Bus2IP_WrCE                    : in  std_logic_vector(0 to C_NUM_CE-1);
    IP2Bus_Data                    : out std_logic_vector(0 to C_DWIDTH-1);
    IP2Bus_Ack                     : out std_logic;
    IP2Bus_Retry                   : out std_logic;
    IP2Bus_Error                   : out std_logic;
    IP2Bus_ToutSup                 : out std_logic
    -- DO NOT EDIT ABOVE THIS LINE ---------------------
  );
end entity user_logic;

------------------------------------------------------------------------------
-- Architecture section
------------------------------------------------------------------------------

architecture IMP of user_logic is

  --USER signal declarations added here, as needed for user logic
    signal N            :std_logic_vector(0 to C_DWIDTH-1)                  ;
    signal Q         :std_logic_vector(7 downto 0):= "00000000" ;
    signal pre_pwm :std_logic                                              ;
    signal clk         :std_logic                                              ;
    signal pre_clk    :std_logic                                              ;
    signal cmp         :std_logic_vector(15 downto 0):="0000000000000000";
  ------------------------------------------
  -- Signals for user logic slave model s/w accessible register example
  ------------------------------------------
  signal slv_reg0                       : std_logic_vector(0 to C_DWIDTH-1);
  signal slv_reg_write_select           : std_logic_vector(0 to 0);
  signal slv_reg_read_select            : std_logic_vector(0 to 0);
  signal slv_ip2bus_data                : std_logic_vector(0 to C_DWIDTH-1);
  signal slv_read_ack                   : std_logic;
  signal slv_write_ack                  : std_logic;

begin

  --USER logic implementation added here
  N <= slvreg0 ; \\ i like to control this variable with software i mean i like to write the value using uart
    p1: process( Bus2IP_Clk )
    begin
        if (Bus2IP_Clk'event and Bus2IP_Clk='1') then
             cmp<= cmp + 1 ;
            if cmp=1953    then
               pre_clk<= not(pre_clk);
                cmp<= cmp-cmp ;
            end if;
        end if ;
    end process p1;
    clk <= pre_clk  ;            

    
    p2: process( clk )
    begin
        if (clk'event and clk='1')
            then Q <= Q + 1 ;
        end if;
            
        if Q < N  
            then pre_pwm <= '1' ;
            else pre_pwm <= '0' ;
        end if;        
    end process p2 ;
    o_pwm <= pre_pwm ;
  ------------------------------------------
  -- Example code to read/write user logic slave model s/w accessible registers
  --
  -- Note:
  -- The example code presented here is to show you one way of reading/writing
  -- software accessible registers implemented in the user logic slave model.
  -- Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond
  -- to one software accessible register by the top level template. For example,
  -- if you have four 32 bit software accessible registers in the user logic, you
  -- are basically operating on the following memory mapped registers:
  --
  --    Bus2IP_WrCE or   Memory Mapped
  --       Bus2IP_RdCE   Register
  --            "1000"   C_BASEADDR + 0x0
  --            "0100"   C_BASEADDR + 0x4
  --            "0010"   C_BASEADDR + 0x8
  --            "0001"   C_BASEADDR + 0xC
  --
  ------------------------------------------
  slv_reg_write_select <= Bus2IP_WrCE(0 to 0);
  slv_reg_read_select  <= Bus2IP_RdCE(0 to 0);
  slv_write_ack        <= Bus2IP_WrCE(0);
  slv_read_ack         <= Bus2IP_RdCE(0);

  -- implement slave model register(s)
  SLAVE_REG_WRITE_PROC : process( Bus2IP_Clk ) is
  begin

    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
      if Bus2IP_Reset = '1' then
        slv_reg0 <= (others => '0');
      else
        case slv_reg_write_select is
          when "1" =>
            for byte_index in 0 to (C_DWIDTH/8)-1 loop
              if ( Bus2IP_BE(byte_index) = '1' ) then
                slv_reg0(byte_index*8 to byte_index*8+7) <= Bus2IP_Data(byte_index*8 to byte_index*8+7);
              end if;
            end loop;
          when others => null;
        end case;
      end if;
    
     end if;
--    N <= slv_reg0 ;
  end process SLAVE_REG_WRITE_PROC;

  -- implement slave model register read mux
  SLAVE_REG_READ_PROC : process( slv_reg_read_select, slv_reg0 ) is
  begin

    case slv_reg_read_select is
      when "1" => slv_ip2bus_data <= slv_reg0;
      when others => slv_ip2bus_data <= (others => '0');
    end case;

  end process SLAVE_REG_READ_PROC;

  ------------------------------------------
  -- Example code to drive IP to Bus signals
  ------------------------------------------
  IP2Bus_Data        <= slv_ip2bus_data;

  IP2Bus_Ack         <= slv_write_ack or slv_read_ack;
  IP2Bus_Error       <= '0';
  IP2Bus_Retry       <= '0';
  IP2Bus_ToutSup     <= '0';

end IMP;

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
7,186 Views
Registered: ‎08-07-2007

Hello Everyone,

 

Just want to clarify one thing - the driver that the CIP Wizard created is just a template. It only works with the pcore HDL template that you created with the Wizard. 

 

If you make any modifications or import an totally new pcore, the driver created by the Wizard might not work.

 

-Felix

0 Kudos
Highlighted
Contributor
Contributor
7,173 Views
Registered: ‎03-31-2010

if the template does not work what we can do to fix it or to use the ip with register or fifo functions???

0 Kudos
Highlighted
Observer
Observer
7,169 Views
Registered: ‎03-30-2009

Thanks felix for the info. Not that you have any influence over the way things are, but I might just say that in general, doing anything even moderately complex using Xilinx tools (or maybe any FPGA tools for that matter), can turn into pure chaos very quickly. There are usually a million little kinks that could've been avoided if the tools weren't so buggy, or designed with more of the end-user in mind (I can give you a bunch of examples if you want). That's why it's no surprise to me when I hear from local "contacts" that Xilinx has been buying up small startups that write more intuitive software tools for FPGAs than Xilinx can.

 

I can't wait for a company to actually come out with FPGA development tools that are user-friendly that has a clean interface. So much of my time is spent figuring out "work-arounds" to bugs that are already within the tools.

 

This is meant to be more of a constructive criticism, sorry if it comes off as an attack.

0 Kudos
Highlighted
Contributor
Contributor
7,160 Views
Registered: ‎03-31-2010

Any solution??

0 Kudos
Highlighted
Explorer
Explorer
7,147 Views
Registered: ‎11-26-2008

If what you need to do is only to write a single value to a register, you don't actually need a driver. All registers get mapped into the memory space of the MicroBlaze, so you can just access it directly.

 

For instance:

 

 

volatile unsigned int *slv_reg;

slv_reg = <CUSTOM_IP_CORE_REGISTER_BASE_ADDRESS>; //Have a look in your xparameters.h to find the name of the constant specifying this

slv_reg[0] = <some_value>;

 

 

Also, you might want to have a look at this thread:

http://forums.xilinx.com/t5/EDK-and-Platform-Studio/Custom-IP-Generated-drivers-not-working/td-p/74247

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
7,094 Views
Registered: ‎08-06-2007

Hi,

 

Have you tried to simulate this?

 

Göran

0 Kudos
Highlighted
Contributor
Contributor
7,081 Views
Registered: ‎03-31-2010

NO I dont simulate i juste built the project and download it to spartan 3 my board. what i have to simulate ???

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
7,062 Views
Registered: ‎08-06-2007

Hi,

 

With simulation you can see anything and can control anything.

 

Have you tried to using XMD and read/write to your custom IP?

 

Göran

0 Kudos