Forum Discussion

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

How to connect an FPGA input port to QSYS pio inout port

Hi,

I have a QSYS/NIOS system, exporting bidirectional PIO port.

Now I'd like to connect input port of top level to the bidir PIO port, with no success so far.

I have tried with an helper signal:

signal helper: std_ulogic;

and connected the top level input port to helper by:

helper <= 'H' when top_input = '1' else 'L';

and the QSYS inout port is connected to helper by:

port map(
   inout_port => helper

Quartus (13.1) gives an error 13076 ("...has multiple drivers...").

Any ideas if this is even possible?

BR, -Topi

2 Replies

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

    Hi,

    I'm not an Altera guru, but I think what you're trying does not work in general.

    The mode "inout" means that this signal connects to a pin through an input driver, and an output driver with tri-state control. Now you're connecting this inout to an input instead, through the net "helper". Now this means that there is a possibility that the FPGA pin is driven from the outside, which drives helper, but at the same time the PIO also wants to drive helper. This is forbidden.

    Another way of looking at it: the inout of the entity implies that there is a way to drive the signal connected to it, but you cannot drive an input pin from that direction. The synthesis tool does not know how to handle this. The "multiple drivers" here refers to the tri-state-enable signal (an input has a permanently enabled tri-state-enable, but inout implies that the tri-state can be switched on and off).

    The synthesis tool only seems to allow this when the top-level pin is also of mode inout. Of course, this could result in the FPGA driving a wire that is driven by another chip at the same time, but that's not the synthesis tool's concern. The synthesis tool expects all external drivers to be put into tri-state when the inout pin is driving.

    Another thing you could to is to change the PIO to input-only mode. If you need bidirectional functionality on some, but not all pins of the PIO, you can do the following instead:

    • create three PIOs, one of mode in, two of mode out

    • the first PIO is your input

    • the second is your output

    • the third is the tri-state enable

    • for each in-only pin, connect it to the corresponding pin of the first PIO, while leaving the corresponding pins of the other two PIOs open

    • for each output-only pin, connect it to the corresponding pin of the second PIO, while leaving the corresponding pins of the other two PIOs open (actually, assignal a default value to the first PIO's input)

    • for each inout-only pin, connect it to the corresponding pin of the first and second PIOs, while using the corresponding pin of the third PIO as a tri-state enable

    The corresponding code in the top-level would look something like this:

    fpga_pin: inout std_logic;
    ...
    begin
    ...
    pio_1_signal <= fpga_pin;
    fpga_pin <= pio_2_signal when (pio_3_signal = '1') else 'Z';

    (in fact, I believe that is exactly what the PIO does internally, as a inout PIO has three registers)

    Best regards,

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

    Hi,

    Sure, that is the way to do it if stripping of the inout functionality doesn't work.

    But std_logic type is designed to be resolved. The problem might be that Altera (as a U.S. company) is putting all efforts to verilog, and supports vhdl only because they have to -with a minimum effort. I don't speak verilog, so don't know if there is similar functionality available.

    At least the following code works in simulator (the behaviour of port 2) as intended. The synthesis tool has all the information needed to make the internal unidirectional (no tri-state buffers) netlist work with equivalent behaviour.

    BR, -Topi

    library ieee;
    use ieee.std_logic_1164.all;
    entity gpio is
    	port(
    		gio_inout: inout std_logic_vector(3 downto 1)
    	);
    end;
    architecture test of gpio is
    begin
    	process
    	begin
    		gio_inout <= "000";
    		wait for 1 ms;
    		gio_inout <= "111";
    		wait for 1 ms;
    		gio_inout <= "ZZZ";
    		wait for 1 ms;
    	end process;
    end;
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity top is
    	port(
    		p1_inout: inout std_logic;
    		p2_in: in std_logic;
    		p3_out: out std_logic
    	);
    end;
    architecture test of top is	   
    	signal p2: std_logic;
    begin
    	gp: entity work.gpio
    	port map(
    		gio_inout(1) => p1_inout,
    		gio_inout(2) => p2,
    		gio_inout(3) => p3_out
    	);
    	
    	p2 <= 'H' when to_01(p2_in) = '1' else 'L';
    end;
    library ieee;
    use ieee.std_logic_1164.all;
    entity tb is
    end;
    architecture test of tb  is
    	signal p1: std_logic;
    	signal p2: std_logic;
    	signal p3: std_logic;
    begin
    	t: entity work.top
    	port map(
    		p1_inout => p1,
    		p2_in => p2,
    		p3_out => p3
    	);
    	
    	process
    	begin		
    		p1 <= '0';
    		p2 <= '0';
    		wait for 3 ms;
    		p1 <= '1';
    		p2 <= '1';
    		wait for 3 ms;
    		p1 <= 'Z';
    		p2 <= 'Z';
    		wait for 3 ms;
    	end process;
    end;