element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
FPGA
  • Technologies
  • More
FPGA
Forum Vivado and Zynq: TRI-STATE help
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join FPGA to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • State Not Answered
  • +1 person also asked this people also asked this
  • Replies 31 replies
  • Subscribers 550 subscribers
  • Views 14616 views
  • Users 0 members are here
  • zynq
  • vivado
Related

Vivado and Zynq: TRI-STATE help

Jan Cumps
Jan Cumps over 3 years ago

I'm trying to write i2c code for Zynq, in VHDL.
I have difficulties creating a TRI-STATE pin.

The output logic should be: the pin is either pulled down to 0, or open-collector.
I have a pull-up resistor between that pin and VCC (3.3 V).
I'm expecting that if I write '0', it is low. When I write 'Z', it's open collector and pulled high by my pullup.
But in my design, the pin stays low. 0.62 V.

I thought, from reading up, that I should be done by:

  • defining the pin as INOUT
  • when you want to drive it low, assign '0'.
  • when you want to drive it open collector, assign 'Z'.
  • put an external pullup between pin and VCC

I created a testbed that puts the pin in "Z' mode, except when reset is asserted (via an external button).
In my testbed I also added a test pin, that I attach to an LED, that is high when the reset is asserted.
I connected a multimeter to the output.

The LED behaves as expected. It lights up when I assert the reset.
But the tri-state pin stays low, whether I write '0' or 'Z' to it. 

entity tristate_test is
    Port ( 
    reset_n: in std_logic;
    reset_out: out std_logic;
    tristate_pin : inout std_logic);
end tristate_test;

architecture Behavioral of tristate_test is

begin

reset_active: process (reset_n) is

begin
  if (reset_n = '0') then
    tristate_pin <= '0';
    reset_out <= '1';
  else
    tristate_pin <= 'Z';
    reset_out <= '0';
  end if;
end process reset_active;

end Behavioral;

Here is how I set the constraint:

image

set_property PACKAGE_PIN Y18 [get_ports tristate_pin_0]
set_property IOSTANDARD LVCMOS33 [get_ports tristate_pin_0]
set_property DRIVE 12 [get_ports tristate_pin_0]

Schema:

image

PMOD A pin 1 is PACKAGE_PIN Y18

What am I doing wrong?

  • Sign in to reply
  • Cancel

Top Replies

  • jc2048
    jc2048 over 3 years ago +4
    It might be a problem with hierarchy with the drag-and-drop stuff. An answer to this support question suggests that you need to set the synthesis to flatten the hierachy so that the tristate-ness can propagate…
  • jc2048
    jc2048 over 3 years ago in reply to bhfletcher +4
    Once you understand that the block-based design is an entity that could be used as part of a larger, more traditional design, the issue with the top-level wrapper becomes clearer. If the user is just using…
  • rachaelp
    rachaelp over 3 years ago +3
    Hi Jan, Just create the tristate in an assignment and not in a process. Not sure why what you have isn't working, have you looked at the schematic for what it's creating in Vivado? I guess maybe it's…
Parents
  • michaelkellett
    0 michaelkellett over 3 years ago

    Hello Jan,

    I'm with Rachael on this, do the tristate with some combinatorial stuff outside any process.

    And remember that once you do that you can't alter the pin (cnf_rdy in my example) from within  the process.

    The example is a bity long winded but illustrates the stuff you need, it's actually a thing for configuring blocks in a big design (but you don't need to worry about what it actually does !)

    It did work OK under Vivado.

    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.NUMERIC_STD.all;
    
    entity conf_interface is
    	 port(
    		 clk_80 : in STD_LOGIC;
    		 lres : in STD_LOGIC;
    		 cnf_dat : in STD_LOGIC;
    		 cnf_frm : in STD_LOGIC;
    		 cnf_sck : in STD_LOGIC;
    		 device_match : in std_logic;
    		 accepted : in STD_LOGIC;
    		 first_word : out STD_LOGIC;
    		 data_ready : out STD_LOGIC;
    		 data : out STD_LOGIC_VECTOR(15 downto 0);
    		 cnf_rdy : inout std_logic
    	     );
    end conf_interface;
    
    --}} End of automatically maintained section
    
    architecture conf_interface of conf_interface is 
    
    signal selected : std_logic;
    signal cnf_frm_d1 : std_logic;	
    signal ready : std_logic;  	
    signal got_first_word : std_logic;
    signal bit : unsigned(3 downto 0);	 
    signal sr : std_logic_vector(15 downto 0);
    
    TYPE t_cnf_state is (CNF_IDLE, CNF_0, CNF_1, CNF_2, CNF_3, CNF_4, CNF_5, CNF_6);
    signal cnf_state : t_cnf_state;
    
    
    begin
    
    	cnf_interface : process(clk_80)
    	begin
    		if rising_edge(clk_80) then
    			if lres = '1' then
    				selected <= '0'; 
    				cnf_frm_d1 <= '0'; 
    				cnf_state <= CNF_IDLE;
    			else 
    				cnf_frm_d1 <= cnf_frm;
    				if cnf_frm = '1' and cnf_frm_d1 = '0' then			-- rising edge always restarts config process
    					cnf_state <= CNF_0;	
    					got_first_word <= '0'; 
    					bit <= "0000";
    					ready <= '0';
    					selected <= '0';
    				end if;
    				if cnf_frm = '0' and cnf_frm_d1 = '0' then	
    					cnf_state <= CNF_IDLE;
    					ready <= '0';
    					selected <= '0';
    				end if;	
    				case cnf_state is 
    					when CNF_IDLE =>	
    					when CNF_0 =>									-- first word is the device code
    						if cnf_sck = '1' then
    							sr <= sr(14 downto 0) & cnf_dat; 
    							bit <= bit + 1;
    							cnf_state <= CNF_1;
    							ready <= '0';
    						end if;	
    					when CNF_1 =>
    						if cnf_sck= '0' then
    							if bit /= 0 then
    								cnf_state <= CNF_0;
    							else 
    								data <= sr;
    								data_ready <= '1';
    								if got_first_word = '0' then
    									first_word <= '1';
    								end if;
    								got_first_word <= '1';
    								cnf_state <= CNF_2;
    							end if;
    						end if;
    					when CNF_2 =>  
    						if device_match = '1'then  
    							selected <= '1';
    							if accepted = '1' then
    								data_ready <= '0';
    								first_word <= '0';
    								ready <= '1';
    								bit <= "0000";
    								cnf_state <= CNF_0;
    							end if;
    						end if;
    					
    					when others =>	 
    				end case;
    			end if;					-- if lres = '1' 
    		end if;						-- f rising_edge(clk_80)
    	end process cnf_interface;
    
    	cnf_rdy <= ready when selected = '1' else 'Z';
    
    end conf_inte

    Hope this helps.

    MK

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
Reply
  • michaelkellett
    0 michaelkellett over 3 years ago

    Hello Jan,

    I'm with Rachael on this, do the tristate with some combinatorial stuff outside any process.

    And remember that once you do that you can't alter the pin (cnf_rdy in my example) from within  the process.

    The example is a bity long winded but illustrates the stuff you need, it's actually a thing for configuring blocks in a big design (but you don't need to worry about what it actually does !)

    It did work OK under Vivado.

    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.NUMERIC_STD.all;
    
    entity conf_interface is
    	 port(
    		 clk_80 : in STD_LOGIC;
    		 lres : in STD_LOGIC;
    		 cnf_dat : in STD_LOGIC;
    		 cnf_frm : in STD_LOGIC;
    		 cnf_sck : in STD_LOGIC;
    		 device_match : in std_logic;
    		 accepted : in STD_LOGIC;
    		 first_word : out STD_LOGIC;
    		 data_ready : out STD_LOGIC;
    		 data : out STD_LOGIC_VECTOR(15 downto 0);
    		 cnf_rdy : inout std_logic
    	     );
    end conf_interface;
    
    --}} End of automatically maintained section
    
    architecture conf_interface of conf_interface is 
    
    signal selected : std_logic;
    signal cnf_frm_d1 : std_logic;	
    signal ready : std_logic;  	
    signal got_first_word : std_logic;
    signal bit : unsigned(3 downto 0);	 
    signal sr : std_logic_vector(15 downto 0);
    
    TYPE t_cnf_state is (CNF_IDLE, CNF_0, CNF_1, CNF_2, CNF_3, CNF_4, CNF_5, CNF_6);
    signal cnf_state : t_cnf_state;
    
    
    begin
    
    	cnf_interface : process(clk_80)
    	begin
    		if rising_edge(clk_80) then
    			if lres = '1' then
    				selected <= '0'; 
    				cnf_frm_d1 <= '0'; 
    				cnf_state <= CNF_IDLE;
    			else 
    				cnf_frm_d1 <= cnf_frm;
    				if cnf_frm = '1' and cnf_frm_d1 = '0' then			-- rising edge always restarts config process
    					cnf_state <= CNF_0;	
    					got_first_word <= '0'; 
    					bit <= "0000";
    					ready <= '0';
    					selected <= '0';
    				end if;
    				if cnf_frm = '0' and cnf_frm_d1 = '0' then	
    					cnf_state <= CNF_IDLE;
    					ready <= '0';
    					selected <= '0';
    				end if;	
    				case cnf_state is 
    					when CNF_IDLE =>	
    					when CNF_0 =>									-- first word is the device code
    						if cnf_sck = '1' then
    							sr <= sr(14 downto 0) & cnf_dat; 
    							bit <= bit + 1;
    							cnf_state <= CNF_1;
    							ready <= '0';
    						end if;	
    					when CNF_1 =>
    						if cnf_sck= '0' then
    							if bit /= 0 then
    								cnf_state <= CNF_0;
    							else 
    								data <= sr;
    								data_ready <= '1';
    								if got_first_word = '0' then
    									first_word <= '1';
    								end if;
    								got_first_word <= '1';
    								cnf_state <= CNF_2;
    							end if;
    						end if;
    					when CNF_2 =>  
    						if device_match = '1'then  
    							selected <= '1';
    							if accepted = '1' then
    								data_ready <= '0';
    								first_word <= '0';
    								ready <= '1';
    								bit <= "0000";
    								cnf_state <= CNF_0;
    							end if;
    						end if;
    					
    					when others =>	 
    				end case;
    			end if;					-- if lres = '1' 
    		end if;						-- f rising_edge(clk_80)
    	end process cnf_interface;
    
    	cnf_rdy <= ready when selected = '1' else 'Z';
    
    end conf_inte

    Hope this helps.

    MK

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
Children
  • Jan Cumps
    0 Jan Cumps over 3 years ago in reply to michaelkellett

    I may need a holiday.

    entity tristate_test is
        port ( 
        reset_n      : in std_logic;
        clock_in     : in std_logic;
        tristate_pin : inout std_logic);
    end tristate_test;
    
    architecture behavioral of tristate_test is
    
    signal tristate_or_low : std_logic;
    
    begin
    
    clocked: process (clock_in, reset_n) is
    begin
      if rising_edge(clock_in) then
        if reset_n = '1' then
          tristate_or_low <= '0';
        else
          tristate_or_low <= '1';
        end if;
        end if;
    
    
    end process clocked;
    
    tristate_pin <= 'Z' when tristate_or_low = '1' else '0';
      
    end behavioral;

    Block design: 

    image

    I tried a different pin too - the PMOD pin Y18 has protection diodes and I wanted to verify that this isn't interfering.
    So I selected T14, the Arduino header signal AR0.

    Same symptoms.

    When I explicitly set the pin to '1' instead of 'Z', it goes to 3.3 V. But 'Z' gives me 0.0x V. The pull-up doesn't seem to be able to pull it away from 0 V.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • wolfgangfriedrich
    0 wolfgangfriedrich over 3 years ago in reply to Jan Cumps

    All working implementations I have seen had the 'Z' in the else case. Maybe try :

    tristate_pin <= '0' when tristate_or_low = '0' else 'Z';

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Jan Cumps
    0 Jan Cumps over 3 years ago in reply to wolfgangfriedrich

    I tried assigning 'Z' in the else clause, it doesn't make a difference.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube