Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
21 years ago

Integrate the Opencores's I2C ip into SOPC

Hello:

I gathered 2 messages about how to integrate Opencores's I2C IP into SOPC.

And I just have got it work by following these instructions below. But one note

is that you can not just include the header file "oc_i2c_master.h" directly.

Please refer to Altera's application note "AN333" to wirte your own header file.

=================================================

you can easily connect the I2C Wishbone core to the NIOS processor

1. Within SOPC builder, generate interface to user logic.

2. Select bus interface type: avalon register slave.

3. Add "i2c_master_top.v" design file.

4. Read port list from file.

5. Connect the signals as follow:

wb_adr_i <=> address

wb_dat_i <=> writedata

wb_dat_o <=> readdata

wb_we_i <=> write

wb_stb_i <=> chipselect

wb_cyc_i <=> chipselect

wb_inta_o <=> irq

wb_clk_i <=> clk

wb_ack_o <=> waitrequest_n

wb_rst_i <=> always0

arst_i <=> reset_n

scl_pad_i <=> export

scl_pad_o <=> export

scl_padoen_o <=> export

sda_pad_i <=> export

sda_pad_o <=> export

sda_padoen_o <=> export

6. Under timing tab, leave the setup, wait and hold settings at 0 cycles.

You can now access the I2C core via included "oc_i2c_master.h".

========================================================

Original message is written by "Guido Kuhlmann" from the Opencores forum.

reference from: (http://www.opencores.org/forums.cgi/cores/2004/04/000609)

========================================================

If you have integrated the I2C IP from Opencores into your system correctly there are only some more steps to bring it to work.

1. Insert -> Symbol ...

2. 2x primitives -> buffer -> tri

3. 2x primitives -> logic -> not

4. 2x primitives -> pin -> bidir

5. connect "scl_padoen_o" and "sda_padoen_o" to the input of the "not"-logics

6. connect "scl_pad_o" and "sda_pad_o" to the input of the "tri"-buffers

7. connect the output of the "not"-logics to the corresponding output-enables of the "tri"-buffers

8. name the output of the "tri"-buffers "i2c_scl" and "i2c_sda"

9. connect "i2c_scl" and "i2c_sda" to the corresponding inputs of the I2C IP

10. connect "i2c_scl" and "i2c_sda" to "bidir"-pins

That&#39;s it!

========================================================

Original message is written by "niosIIuser" from the Nios forum.

reference from : (here (http://www.niosforum.com/forum/index.php?act=st&f=2&t=590&hl=opencore))

========================================================

16 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I have done the process as the trout writes, and generated a symbol named I2cCore. The I2cCore occupys 32 8-bit address. But in the 32 addresses, I find that I can only write 4 of them, why? I am confused that which are the registers? Is there anything I omitted? By the way, in the nios2 core, I have integrated cup, onchip_memory, timer, pio, epcs_controller, jtag and I2cCore. Does anyone can help me?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi:

    I have designed a IPcore which is belown:

    library ieee;

    use ieee.std_logic_1164.all;

    entity ad574 is

    port(D :IN STD_LOGIC_VECTOR(15 DOWNTO 0);

    address: in std_logic_vector(1 downto 0);

    CLK ,STATUS,read: IN STD_LOGIC;--״̬»úʱÖÓCLK£¬AD574״̬ÐźÅSTATUS

    byteenable: in std_logic_vector(3 downto 0);

    chipselect: in std_logic;

    CE,CS,A0,RC,K12X8: OUT STD_LOGIC; --AD574¿ØÖÆÐźÅ

    Q : out STD_LOGIC_VECTOR(31 DOWNTO 0));

    end ad574;

    architecture behav of ad574 is

    type state is (st0, st1, st2, st3,st4);

    signal current_state,next_state :state:=st0;

    signal data_reg_select: std_logic;

    signal control_reg_select: std_logic;

    SIGNAL data_reg : STD_LOGIC_VECTOR(31 DOWNTO 0);

    SIGNAL lock: STD_LOGIC;

    begin

    K12X8 <= &#39;1&#39;;

    process(address,chipselect)

    begin

    data_reg_select<=&#39;0&#39;;

    control_reg_select<=&#39;0&#39;;

    if chipselect=&#39;1&#39; then

    case address is

    when "00" => data_reg_select<=&#39;1&#39;;

    when "01" => control_reg_select<=&#39;1&#39;;

    when others => null;

    end case;

    end if;

    end process;

    process(current_state,status) --»ù±¾ÈÎÎñÉè¼Æ(״̬ÄÚÐźű仯)

    begin

    case current_state is

    when st0 =>CE<=&#39;0&#39;;CS<=&#39;1&#39;; A0<=&#39;1&#39;;RC<=&#39;1&#39;;LOCK<=&#39;0&#39;;next_state <= st1;

    when st1 =>CE<=&#39;1&#39;;CS<=&#39;0&#39;; A0<=&#39;0&#39;;RC<=&#39;0&#39;;LOCK<=&#39;0&#39;; next_state <= st2;

    when st2 =>CE<=&#39;1&#39;;CS<=&#39;0&#39;; A0<=&#39;0&#39;;RC<=&#39;0&#39;;LOCK<=&#39;0&#39;;

    IF (STATUS=&#39;1&#39;) THEN next_state <= st2;

    ELSE next_state <= st3;

    END IF ;

    when st3 =>CE<=&#39;1&#39;;CS<=&#39;0&#39;; A0<=&#39;0&#39;;RC<=&#39;1&#39;;LOCK<=&#39;0&#39;; next_state <= st4;

    when st4 =>CE<=&#39;1&#39;;CS<=&#39;0&#39;; A0<=&#39;0&#39;;RC<=&#39;1&#39;;LOCK<=&#39;1&#39;; next_state <= st0;

    when others =>CE<=&#39;0&#39;;CS<=&#39;1&#39;; A0<=&#39;1&#39;;RC<=&#39;1&#39;;LOCK<=&#39;0&#39;;next_state <= st0;

    end case;

    end process;

    PROCESS (clk,control_reg_select,chipselect) --¿ØÖƼĴæÆ÷¿ØÖÆ×ª»»¹ý³Ì

    BEGIN

    IF ( clk&#39;EVENT AND clk=&#39;1&#39;) THEN

    if (control_reg_select and chipselect)=&#39;1&#39; then

    current_state <= next_state;

    end if;

    END IF;

    END PROCESS ;

    process(lock) --Êý¾Ý¿ØÖƼĴæÆ÷²Ù×÷

    BEGIN

    IF LOCK=&#39;1&#39; AND LOCK&#39;EVENT THEN

    if byteenable(0)=&#39;1&#39; then data_reg(7 downto 0)<=d(7 downto 0);end if;data_reg<=d;

    if byteenable(1)=&#39;1&#39; then data_reg(15 downto 8)<=d(15 downto 8);end if;

    if byteenable(2)=&#39;1&#39; then data_reg(23 downto 16)<="00000000";end if;

    if byteenable(3)=&#39;1&#39; then data_reg(31 downto 24)<="00000000";end if;

    END IF;

    END PROCESS ;

    process(read,clk,data_reg_select,chipselect) --NIOS×ÜÏßͨѶ

    begin

    if clk&#39;event and clk=&#39;1&#39; then

    if (read and data_reg_select and chipselect)=&#39;1&#39; then

    Q <=data_reg;

    else

    Q<=(others=>&#39;Z&#39;);

    end if;

    end if ;

    end process;

    END behav;

    now I integerate the IP to sopc , and the base address of the IP is :0x02000008 and the end address is 0x0200000f , the generation of the system is successful . but when I built the software about the system above on the NiosII IDE , but there is error and display that the range of the IP ---ad16bit is out of the range of the address , what is it? while I change the "Q : out STD_LOGIC_VECTOR(31 DOWNTO 0));" to " Q : out STD_LOGIC_VECTOR(15 DOWNTO 0)); " the error is disappeared. why?

    and how can I write the drivers of the IP core ? who can help me?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    originally posted by tek66tim@Jun 2 2005, 04:08 PM

    hi,

    i looked for the an 333 and it&#39;s no longer available, does anyone have a modified oc_i2c_master.h file or some hints on how to modify the .h file to work with sopc builder?

    thanks

    --- Quote End ---

    There is a new document present on Altera web site who describe how to create a NIOS II / SOPC Builder component:

    Quartus II Development Software Handbook v5.0 Volume 4: SOPC Builder.

    It is available here (http://www.altera.com/literature/hb/qts/qts_qii5v4.pdf)

    or go to quartus literature page (http://www.altera.com/literature/lit-qts.jsp).

    I add opencores I2C master component to SOPC Builder, but to do that I have created an additionnal VHDL file because SOPC Builder seems to have problem with the STD_LOGIC GENERIC parameters.

    --------------------------------------------
    -- Description VHDL d&#39;une interface I2C maître
    -- FM 28/06/2005
    --------------------------------------------
    -- Déclaration des bibliothèques
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_arith.all;
    --------------------------------------------
    -- Déclaration de l&#39;entité
    entity oc_i2c_master_top is
        port(
            -- Signaux du bus Avalon
            address:       in unsigned(2 downto 0);
            readdata:      out std_logic_vector(7 downto 0);
            writedata:     in std_logic_vector(7 downto 0);
            write:         in std_logic;
            chipselect:    in std_logic;
            clk:           in std_logic;                     -- Entrée horloge
            reset_n:       in std_logic;                     -- Entrée de RESET (actif à l&#39;état bas)
            irq:           out std_logic;
            waitrequest_n: out std_logic;
            
            -- Sortie I2C
            scl: inout std_logic;                -- i2c clock line output
            sda: inout std_logic                 -- i2c data line output
         );
    end oc_i2c_master_top;
    --------------------------------------------
    -- Déclaration de l&#39;architecture comportementale "algorithmique" de l&#39;entité
    architecture bhv of oc_i2c_master_top is
    component i2c_master_top is
        generic(
      ARST_LVL : std_logic                          -- asynchronous reset level
        );
        port (
      -- wishbone signals
      wb_clk_i  : in  std_logic;                    -- master clock input
      wb_rst_i  : in  std_logic;                    -- synchronous active high reset
      arst_i    : in  std_logic;                    -- asynchronous reset
      wb_adr_i  : in  unsigned(2 downto 0);         -- lower address bits
      wb_dat_i  : in  std_logic_vector(7 downto 0); -- Databus input
      wb_dat_o  : out std_logic_vector(7 downto 0); -- Databus output
      wb_we_i   : in  std_logic;               -- Write enable input
      wb_stb_i  : in  std_logic;                    -- Strobe signals / core select signal
      wb_cyc_i  : in  std_logic;               -- Valid bus cycle input
      wb_ack_o  : out std_logic;                    -- Bus cycle acknowledge output
      wb_inta_o : out std_logic;                    -- interrupt request output signal
      -- i2c lines
      scl_pad_i     : in  std_logic;                -- i2c clock line input
      scl_pad_o     : out std_logic;                -- i2c clock line output
      scl_padoen_o  : out std_logic;                -- i2c clock line output enable, active low
      sda_pad_i     : in  std_logic;                -- i2c data line input
      sda_pad_o     : out std_logic;                -- i2c data line output
      sda_padoen_o  : out std_logic                 -- i2c data line output enable, active low
        );
    end component;
    signal scl_pad_i     : std_logic;
    signal scl_pad_o     : std_logic;
    signal scl_padoen_o  : std_logic;
    signal sda_pad_i     : std_logic;
    signal sda_pad_o     : std_logic;
    signal sda_padoen_o  : std_logic;
    begin
        i2c_top : i2c_master_top
            generic map ( ARST_LVL => &#39;0&#39;)
            port map (
                wb_adr_i  => address,
                wb_dat_i  => writedata,
                wb_dat_o  => readdata,
                wb_we_i   => write,
                wb_stb_i  => chipselect,
                wb_cyc_i  => chipselect,
                wb_inta_o => irq,
                wb_clk_i  => clk,
                wb_ack_o  => waitrequest_n,
                wb_rst_i  => &#39;0&#39;,
                arst_i    => reset_n,
                
                scl_pad_i    => scl_pad_i,
                scl_pad_o    => scl_pad_o,
                scl_padoen_o => scl_padoen_o,
                sda_pad_i    => sda_pad_i,
                sda_pad_o    => sda_pad_o,
                sda_padoen_o => sda_padoen_o
            );
        scl <= scl_pad_o when (scl_padoen_o = &#39;0&#39;) else &#39;Z&#39;;
        sda <= sda_pad_o when (sda_padoen_o = &#39;0&#39;) else &#39;Z&#39;;
        scl_pad_i <= scl;
        sda_pad_i <= sda;
    end architecture bhv;

    Now I am working on I2C software driver, the basic functions are working. I can read and write I2C devices, now I have to clean up my code.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    I looked for the AN 333 and it&#39;s no longer available, does anyone have a modified oc_i2c_master.h file or some hints on how to modify the .h file to work with SOPC builder?

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The I2C slave model of OC is not synthesizable, but the master seems to work.