UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Observer wen119at
Observer
7,991 Views
Registered: ‎02-16-2010

about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution

Hi everyone,

 

I am trying to add a custom IP which acts as a multiplier to the EDK project. When create the IP template, I selected 3 S/W accessible registers (reg0,reg1,reg2). reg0 acts as datain, reg1 acts as dataout, reg2(0) acts as rst of IP.

The user_logic.vhd is shown below:

*********************************************************************************************************

------------------------------------------------------------------------------
-- user_logic.vhd - entity/architecture pair
------------------------------------------------------------------------------
--
-- ***************************************************************************
-- ** Copyright (c) 1995-2009 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:              Sun Mar 21 02:14: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_v3_00_a;
use proc_common_v3_00_a.proc_common_pkg.all;

-- DO NOT EDIT ABOVE THIS LINE --------------------

--USER libraries added here

------------------------------------------------------------------------------
-- Entity section
------------------------------------------------------------------------------
-- Definition of Generics:
--   C_SLV_DWIDTH                 -- Slave interface data bus width
--   C_NUM_REG                    -- Number of software accessible registers
--
-- Definition of Ports:
--   Bus2IP_Clk                   -- Bus to IP clock
--   Bus2IP_Reset                 -- Bus to IP reset
--   Bus2IP_Data                  -- Bus to IP data bus
--   Bus2IP_BE                    -- Bus to IP byte enables
--   Bus2IP_RdCE                  -- Bus to IP read chip enable
--   Bus2IP_WrCE                  -- Bus to IP write chip enable
--   IP2Bus_Data                  -- IP to Bus data bus
--   IP2Bus_RdAck                 -- IP to Bus read transfer acknowledgement
--   IP2Bus_WrAck                 -- IP to Bus write transfer acknowledgement
--   IP2Bus_Error                 -- IP to Bus error response
------------------------------------------------------------------------------

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_SLV_DWIDTH                   : integer              := 32;
    C_NUM_REG                      : integer              := 3
    -- DO NOT EDIT ABOVE THIS LINE ---------------------
  );
  port
  (
    -- ADD USER PORTS BELOW THIS LINE ------------------
    --USER ports added here
    -- 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_SLV_DWIDTH-1);
    Bus2IP_BE                      : in  std_logic_vector(0 to C_SLV_DWIDTH/8-1);
    Bus2IP_RdCE                    : in  std_logic_vector(0 to C_NUM_REG-1);
    Bus2IP_WrCE                    : in  std_logic_vector(0 to C_NUM_REG-1);
    IP2Bus_Data                    : out std_logic_vector(0 to C_SLV_DWIDTH-1);
    IP2Bus_RdAck                   : out std_logic;
    IP2Bus_WrAck                   : out std_logic;
    IP2Bus_Error                   : out std_logic
    -- DO NOT EDIT ABOVE THIS LINE ---------------------
  );

  attribute SIGIS : string;
  attribute SIGIS of Bus2IP_Clk    : signal is "CLK";
  attribute SIGIS of Bus2IP_Reset  : signal is "RST";

end entity user_logic;

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

architecture IMP of user_logic is

  --USER signal declarations added here, as needed for user logic

  ------------------------------------------
  -- Signals for user logic slave model s/w accessible register example
  ------------------------------------------
  signal slv_reg0                       : std_logic_vector(0 to C_SLV_DWIDTH-1);
  signal slv_reg1                       : std_logic_vector(0 to C_SLV_DWIDTH-1);
  signal slv_reg2                       : std_logic_vector(0 to C_SLV_DWIDTH-1);
  signal slv_reg_write_sel              : std_logic_vector(0 to 2);
  signal slv_reg_read_sel               : std_logic_vector(0 to 2);
  signal slv_ip2bus_data                : std_logic_vector(0 to C_SLV_DWIDTH-1);
  signal slv_read_ack                   : std_logic;
  signal slv_write_ack                  : std_logic;
 
  component multiplier
  Port
  (
  clk : in  STD_LOGIC;
      rst : in  STD_LOGIC;
      datain : in  STD_LOGIC_VECTOR (0 to 7);
      dataout : out  STD_LOGIC_VECTOR (0 to 7)
 );
  end component;
 
begin

  --USER logic implementation added here
 uut_multiplier_0 : component multiplier
 port map
 (
 clk => Bus2IP_Clk,
 rst => slv_reg2(0),
 datain => slv_reg0(0 to 7),
 dataout => slv_reg1(0 to 7));
  ------------------------------------------
  -- 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/Bus2IP_RdCE   Memory Mapped Register
  --                     "1000"   C_BASEADDR + 0x0
  --                     "0100"   C_BASEADDR + 0x4
  --                     "0010"   C_BASEADDR + 0x8
  --                     "0001"   C_BASEADDR + 0xC
  --
  ------------------------------------------
  slv_reg_write_sel <= Bus2IP_WrCE(0 to 2);
  slv_reg_read_sel  <= Bus2IP_RdCE(0 to 2);
  slv_write_ack     <= Bus2IP_WrCE(0) or Bus2IP_WrCE(1) or Bus2IP_WrCE(2);
  slv_read_ack      <= Bus2IP_RdCE(0) or Bus2IP_RdCE(1) or Bus2IP_RdCE(2);

  -- implement slave model software accessible 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');
        slv_reg2 <= (others => '0');
      else
        case slv_reg_write_sel is
          when "100" =>
            slv_reg0 <= Bus2IP_Data; --datain
          when "001" =>
            slv_reg2 <= Bus2IP_Data; --rst
          when others => null;
        end case;
      end if;
    end if;

  end process SLAVE_REG_WRITE_PROC;

  -- implement slave model software accessible register(s) read mux
  SLAVE_REG_READ_PROC : process( slv_reg_read_sel, slv_reg0, slv_reg1, slv_reg2 ) is
  begin

    case slv_reg_read_sel is
      when "100" => slv_ip2bus_data <= slv_reg0;
      when "010" => slv_ip2bus_data <= slv_reg1;
      when "001" => slv_ip2bus_data <= slv_reg2;
      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_WrAck <= slv_write_ack;
  IP2Bus_RdAck <= slv_read_ack;
  IP2Bus_Error <= '0';

end IMP;
***********************************************************************************************

My IP logic multiplier.vhd is:

 

----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date:    02:23:39 03/21/2010
-- Design Name:
-- Module Name:    multiplier - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity multiplier is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           datain : in  STD_LOGIC_VECTOR (0 to 7);
           dataout : out  STD_LOGIC_VECTOR (0 to 7));
end multiplier;

architecture Behavioral of multiplier is

-- define signals for multiplier
signal a : std_logic_vector(0 to 3)  := (others => '0');
signal b : std_logic_vector(0 to 3) := (others => '0');
--signal p : std_logic_vector(0 to 7)  := (others => '0');

begin

 a <= datain(0 to 3);
 b <= datain(4 to 7);
 --dataout <= p;
 
 process(clk)
 begin
 if (clk'event and clk = '1') then
  if (rst = '1') then
   dataout <= (others => '0');
   else
    dataout <= a * b;
  end if;   
 end if;
 end process;
 
end Behavioral;

*************************************************************************

My .c source codes:

 

/*****************************************************************************

* Filename: D:\self_multi_reg/drivers/test_reg_v1_00_a/src/test_reg.c

* Version: 1.00.a

* Description: test_reg Driver Source File

* Date: Sun Mar 21 02:14:21 2010 (by Create and Import Peripheral Wizard)

*****************************************************************************/

 

#include "test_reg.h"

#include "stdlib.h" 

#include "xuartns550_l.h"

#include "xparameters.h"

 

/************************** Function Definitions ***************************/

 int main() { 

 

// base address for IP test_reg

Xuint32 baseaddr;

Xuint32 *baseaddr_p = (Xuint32 *)XPAR_TEST_REG_0_BASEADDR;

baseaddr = (Xuint32) baseaddr_p;

 

 

xil_printf(
"******************************\n\r");

xil_printf("* User Logic Register Test\n\r");xil_printf(

"******************************\n\n\r");

 

//reset

 int i;

 

//start

TEST_REG_mWriteSlaveReg0(XPAR_TEST_REG_0_BASEADDR, 8, 0);//XPAR_TEST_REG_0_BASEADDR

i = TEST_REG_mReadSlaveReg0(XPAR_TEST_REG_0_BASEADDR, 8); // reg2

xil_printf("rst=%d\n\r",i);

 

//send data to reg0

/* Write to user logic slave module register(s) and read back */

 int datain;

xil_printf("User logic slave module test...\n\r");xil_printf(

" - write data to slave reg0...\n\r");

TEST_REG_mWriteSlaveReg0(baseaddr, 0, 99); // reg0, take 99 as input data here

datain = TEST_REG_mReadSlaveReg0(baseaddr, 0);

xil_printf(
"datain=0x%x\n\r",datain);

 

//delay

 int j; for(j = 0; j < 100;)

j++;

 

//read data from reg1

//get the output of multiplier back

 int dataout;xil_printf(" - read output from slave reg1...\n\r");

dataout = TEST_REG_mReadSlaveReg1(baseaddr, 0);

xil_printf(
"dataout=0x%x\n\r",dataout);

 

return 0;

}

 ********************************************************************

What I get from HyperTerminal is:

 

******************************
* User Logic Register Test
******************************

rst=0
User logic slave module test...
   - write data to slave reg0...
datain=0x63
   - read output from slave reg1...
dataout=0x0

 

I am wondering why the output dataout is always 0...

Is there anything that i have missed...

any hint or suggestion is highly appreciated...

thanks in advances...

really puzzled...

 

wen:(

Message Edited by wen119at on 03-22-2010 01:38 PM
0 Kudos
1 Solution

Accepted Solutions
Scholar pumaju1808
Scholar
10,248 Views
Registered: ‎08-14-2007

Re: about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution

hi, i saw two wrong things in your codes:

 

1. Be careful with your registers writing , for example you put

TEST_REG_mWriteSlaveReg0(XPAR_TEST_REG_0_BASEADDR, 8, 0);

in order to write to reg2, right??, but the funciont "TEST_REG_mWriteSlaveReg0" internally has already the offset to register 2, so you are adding 8 more!!, so you in fact are writing to register 5!!, but because all registers starts with 0, then when you read rst register you read 0 too. But you directionally is wrong

You should use just the funcion "TEST_REG_mWriteReg" with your respective offsets, something like this:

 

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 8, 0);  --> if you want to write to reg2

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 4, 0);  --> if you want to write to reg1

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 0, 0);  --> if you want to write to reg0

 

2. When you write value of 15 (0x0000000F) to one register, in fact the 'F' is in bits 28 to 31 of your slave register, NOT in bits 0 to 3!! . So when you have

 

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 0, 15);

 

in your user logic you can catch this value making the assignament:

 

 datain => slv_reg0(28 to 31);

 

So when you write 99 (0x00000063) to your registers , bits 0 to 7 of your slv_reg0 are always 0, if you want to catch '63' hexadecimal you have to assign bits 24 to 31 of your slv_reg0, like this

 

 datain => slv_reg0(24 to 31);

 


3. For your output i recommend put your output in read process:

 

--USER logic implementation added here
 uut_multiplier_0 : component multiplier
 port map
 (
 clk => Bus2IP_Clk,
 rst => slv_reg2(0),
 datain => slv_reg0(0 to 7),
 dataout => out_int );          -- where out_int is:    signal out_int:   std_logic_vector(0 to 7);

 

 

SLAVE_REG_READ_PROC : process( slv_reg_read_sel, slv_reg0, slv_reg1, slv_reg2, out_int ) is
  begin

    case slv_reg_read_sel is
      when "100" => slv_ip2bus_data <= slv_reg0;
      when "010" => slv_ip2bus_data <= "000000000000000000000000" & out_int;    -- 32bit padding

      when "001" => slv_ip2bus_data <= slv_reg2;
      when others => slv_ip2bus_data <= (others => '0');
    end case;

  end process SLAVE_REG_READ_PROC;

 

 So in sofware when you read reg1, you will read your output

 Hope this helps

 

regards

0 Kudos
5 Replies
Scholar pumaju1808
Scholar
10,249 Views
Registered: ‎08-14-2007

Re: about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution

hi, i saw two wrong things in your codes:

 

1. Be careful with your registers writing , for example you put

TEST_REG_mWriteSlaveReg0(XPAR_TEST_REG_0_BASEADDR, 8, 0);

in order to write to reg2, right??, but the funciont "TEST_REG_mWriteSlaveReg0" internally has already the offset to register 2, so you are adding 8 more!!, so you in fact are writing to register 5!!, but because all registers starts with 0, then when you read rst register you read 0 too. But you directionally is wrong

You should use just the funcion "TEST_REG_mWriteReg" with your respective offsets, something like this:

 

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 8, 0);  --> if you want to write to reg2

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 4, 0);  --> if you want to write to reg1

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 0, 0);  --> if you want to write to reg0

 

2. When you write value of 15 (0x0000000F) to one register, in fact the 'F' is in bits 28 to 31 of your slave register, NOT in bits 0 to 3!! . So when you have

 

 TEST_REG_mWriteReg(XPAR_TEST_REG_0_BASEADDR, 0, 15);

 

in your user logic you can catch this value making the assignament:

 

 datain => slv_reg0(28 to 31);

 

So when you write 99 (0x00000063) to your registers , bits 0 to 7 of your slv_reg0 are always 0, if you want to catch '63' hexadecimal you have to assign bits 24 to 31 of your slv_reg0, like this

 

 datain => slv_reg0(24 to 31);

 


3. For your output i recommend put your output in read process:

 

--USER logic implementation added here
 uut_multiplier_0 : component multiplier
 port map
 (
 clk => Bus2IP_Clk,
 rst => slv_reg2(0),
 datain => slv_reg0(0 to 7),
 dataout => out_int );          -- where out_int is:    signal out_int:   std_logic_vector(0 to 7);

 

 

SLAVE_REG_READ_PROC : process( slv_reg_read_sel, slv_reg0, slv_reg1, slv_reg2, out_int ) is
  begin

    case slv_reg_read_sel is
      when "100" => slv_ip2bus_data <= slv_reg0;
      when "010" => slv_ip2bus_data <= "000000000000000000000000" & out_int;    -- 32bit padding

      when "001" => slv_ip2bus_data <= slv_reg2;
      when others => slv_ip2bus_data <= (others => '0');
    end case;

  end process SLAVE_REG_READ_PROC;

 

 So in sofware when you read reg1, you will read your output

 Hope this helps

 

regards

0 Kudos
Scholar pumaju1808
Scholar
7,977 Views
Registered: ‎08-14-2007

Re: about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution

Again the point 3:

 

3. For your output i recommend put your output in read process:

 

--USER logic implementation added here
 uut_multiplier_0 : component multiplier
 port map
 (
 clk => Bus2IP_Clk,
 rst => slv_reg2(31),
 datain => slv_reg0(24 to 31),
 dataout => out_int );          -- where out_int is:    signal out_int:   std_logic_vector(0 to 7);

 

 

SLAVE_REG_READ_PROC : process( slv_reg_read_sel, slv_reg0, slv_reg1, slv_reg2, out_int ) is
  begin

    case slv_reg_read_sel is
      when "100" => slv_ip2bus_data <= slv_reg0;
      when "010" => slv_ip2bus_data <= "000000000000000000000000" & out_int;    -- 32bit padding

      when "001" => slv_ip2bus_data <= slv_reg2;
      when others => slv_ip2bus_data <= (others => '0');
    end case;

  end process SLAVE_REG_READ_PROC;

 

0 Kudos
Observer wen119at
Observer
7,967 Views
Registered: ‎02-16-2010

Re: about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution

yeah~~~~~~~~~~~

that's the problem...

the port map...

thank you so much...

it's working now~~~~~~~~~~~~~~~

0 Kudos
Highlighted
Scholar pumaju1808
Scholar
7,955 Views
Registered: ‎08-14-2007

Re: about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution

 hi,

 

it would be fine if you mark as solution accepted, hence other people can see that this issue is solved and can see the solution

 

regards

0 Kudos
Observer wen119at
Observer
7,953 Views
Registered: ‎02-16-2010

Re: about custom ip with S/W accessible registers, cannot get data from reg

Jump to solution
no problem~~
0 Kudos