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't have tristate signals
inside your fpga. IP cores are always connected together in this way.
-- remark sda is open collector
-- to write '0' to sda
sda_pad_o <= '0';
sda_padoen_o <= '1';
-- to write '1' to sda
sda_pad_o <= '0'; -- '0' or '1' doesn't matter
sda_padoen_o <= '0';
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 '1'
sda_pad_io <= '0' when sda_out='0' else 'Z';