Forum Discussion

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

I2C bus in vhdl file

hi!

i would like to write a I2C file.vhdl (master) to communicate with several

PCF8574 devices .

I already wrote this library for PIC microntroller , without to use

periperal and successfull running , just to show i know the protocol.

I'm studing vhdl , and i never found hou to set a "pin" input and output .

For example when my master write on bus i have to set

the SDA pin as output , and when i'm waiting to receive i need to set it

as input.

How may i set this pin in vhdl file ?

thanks for helps

ciao

walter

6 Replies

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

    In VHDL, when you declare the entity, you define a port list. In this port list is where you specify what signals are input/output/bidir to the 'function'. You can look at the simple example at the end of my post.

    The following is going to to be quartus specific. To get your signals to actual FPGA pins do the following: Once you complete your entity, you can create a schematic symbol for your entity by loading your VHDL in Quartus, and then going to File -> Create/Update -> Create Symbol Files for Current File. Once you do so, you'll be able to place a symbol of your VHDL entity on a schematic (double click a blank schematic and navigate to your project). and connect it's traces to Input or Output symbols. From there, you can goto Assignments -> Pin Planner and connect at will.

    Let me know if you need any details on any specific step.

    VHDL Example (P.S. This code does not perform any (useful?) function):

    --------------------------------------------------------------------------------
    -- Kevin Wolfe
    -- This is a comment
    --------------------------------------------------------------------------------
    -- Rev.  0 - 08/14/06 - KDW - Inception
    LIBRARY ieee;
    USE ieee.STD_LOGIC_1164.all;
    USE ieee.STD_LOGIC_unsigned.all;
    ---------------------------------------------------
    ENTITY RAM_MANAGER IS
    PORT(
        clk      :    IN  STD_LOGIC;
        mcu_data    :    IN  STD_LOGIC_VECTOR(7  DOWNTO 0);    
        addr_dec    :  OUT  STD_LOGIC);
        
    END RAM_MANAGER;
    ----------------------------------------------------
    ARCHITECTURE behv of RAM_MANAGER IS
        CONSTANT SOME_CONSTANT_NAME      :    integer := 2;
        SIGNAL    some_singal_i  : STD_LOGIC_VECOTR(8 DOWNTO 0)    := (OTHERS => '0');
        
        SIGNAL    count_i      : INTEGER range 0 to READ_PERIOD    := 26;
    BEGIN
        -- Process to respond to read Requests
        PROCESS (clk)
        BEGIN
      CASE (conv_integer(mcu_data)) IS
          WHEN 0 =>
        some_singal_i <= &#39;1&#39;;
          WHEN 1 =>
        some_singal_i <= &#39;0&#39;;
          WHEN 2 =>
        count_i    <= count_i + 1;
          WHEN OTHERS      =>
      END CASE;
        END PROCESS;
        
        addr_dec <= some_singal_;
    END behv;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    very nice .

    I already wrote some custom peripheral and included in my system as vhdl files.

    After that wrote driver device and use them in NIOS II IDE .

    But in my case how i have to set the pin , as input , as output (not good )

    or bidirectional if exist ?

    For PIC mcu i wrote library , and was possible because i can change direction "on flight" using TRIS register .Setting 0 or 1 change the direction

    but how to do in vhdl file ?

    thanks for helps

    ciao

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

    two ways to do this:

    1.

    in your vhdl file

    port (

    ..

    ..

    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

    );

    remark: "this is from opencores i2c master, see opencores.org"

    in Quartus graphic editor, add a "tri" component and BIDIR pin.

    connect sda_padoen_o --> tri.enable

    connect sda_pad_o --> tri.input

    connect tri.output to sda BIDIR IO PIN

    connect sda_pad_i to sda BIDIR IO PIN

    this one is preffered because you normally don&#39;t have tristate signals

    inside your fpga. IP cores are always connected together in this way.

    -- remark sda is open collector

    -- to write &#39;0&#39; to sda

    sda_pad_o <= &#39;0&#39;;

    sda_padoen_o <= &#39;1&#39;;

    -- to write &#39;1&#39; to sda

    sda_pad_o <= &#39;0&#39;; -- &#39;0&#39; or &#39;1&#39; doesn&#39;t matter

    sda_padoen_o <= &#39;0&#39;;

    2.

    however it should also be possible to do the following if you

    directly connect your in/output to a QUARTUS BIDIR pin

    in your vhdl file

    port (

    ..

    ..

    sda_pad_io : inout std_logic; -- i2c data line in/output

    );

    -- in Quartus graphic editor, add a BIDIR pin.

    -- connect sda_pad_io directly to your BIDIR sda pin.

    signal sda_in : std_logic;

    signal sda_out : std_logic;

    -- read input

    sda_in <= sda_pad_io;

    -- write output

    -- sda is open collector or open drain, we never drive a &#39;1&#39;

    sda_pad_io <= &#39;0&#39; when sda_out=&#39;0&#39; else &#39;Z&#39;;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hi

    I would like design simoulation of I2c bus with (vhdl),please help me