0

I'm working on a project in which I need a bidirectional tri-state buffer. I've developed a VHDL code based on my searches in this community and some other websites. But it doesn't work as it should. Below is the VHDL code.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Inter_Con_Mod is
    generic(WL: integer := 8);
    port(In1: in signed(WL-1 downto 0);
          RW: in std_logic;
          Data_IO1: inout signed(WL-1 downto 0);
          Out1: out signed(WL-1 downto 0));

end Inter_Con_Mod;

architecture Behav of Inter_Con_Mod is

begin

Data_IO1 <= In1 when RW = '1' else
                (others => 'Z');

Out1 <= Data_IO1;


end Behav;

This is the testbench code:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

USE ieee.numeric_std.ALL;

ENTITY InterCon_test IS
END InterCon_test;

ARCHITECTURE behavior OF InterCon_test IS 

     -- Component Declaration for the Unit Under Test (UUT)

     COMPONENT Inter_Con_Mod
     PORT(
            In1 : IN  signed(7 downto 0);


            RW : IN  std_logic;
            Data_IO1 : INOUT  signed(7 downto 0);

            Out1 : OUT  signed(7 downto 0)

          );
     END COMPONENT;


    --Inputs
    signal In1 : signed(7 downto 0) := (others => '0');


    signal RW : std_logic := '0';

    --BiDirs
    signal Data_IO1 : signed(7 downto 0);


    --Outputs
    signal Out1 : signed(7 downto 0);

    -- No clocks detected in port list. Replace <clock> below with 
    -- appropriate port name 

    --constant <clock>_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
    uut: Inter_Con_Mod PORT MAP (
             In1 => In1,


             RW => RW,
             Data_IO1 => Data_IO1,

             Out1 => Out1

          );

    -- Clock process definitions
-- Stimulus process
    stim_proc: process
    begin       
        -- hold reset state for 100 ns.
        wait for 5 ns;  
        In1 <= "01111111";
        wait for 5 ns;
        RW <= '1';
        wait for 5 ns;

        RW <= '0';
        wait for 20 ns;
        Data_IO1 <= "00101010";



        wait;
    end process;

END;

But look what happens in the simulation Result:

Simulation_Result

I don't get why it ignores the test bench stimulation I've provided before setting RW to 0.

Thanks in advance.

  • The fact is that when I remove the Data_IO1 <= "00101010"; from the Testbench, the system works at it's expected. But that wouldn't be the case I'm looking for. I want the INOUT port to work both as input and output. – Seyed Mohammad Reza Shahshahni Apr 19 '17 at 06:26
  • If you have two drivers on one wire preventing contention requires only one of them can be driving at a time and the other must be high impedance ('Z'). You need to assign 'Z' when appropriate in the testbench. You can also have contention using a single control line based on different control to 'Z' and control to drive times. –  Apr 21 '17 at 08:21
  • Wow. Thanks! I didn't know that. And unfortunately I couldn't find anything discussing this matter as you did. I got it solved using your comment. – Seyed Mohammad Reza Shahshahni Apr 22 '17 at 07:01
  • It would seem it's common to expect hardware thinking. Post an answer. –  Apr 22 '17 at 07:46
  • Yeah. I will post an answer. Just one more thing. When I want to synthesize such a module, in reality the 'Z' assignment is inferred automatically (as it means high impedance), but in testbench I need to do it manually, yes? – Seyed Mohammad Reza Shahshahni Apr 22 '17 at 09:07

1 Answers1

0

Thanks to @user1155120 the problem was solved. I've changed the whole code to what comes below.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Inter_Con_Mod is
    generic(WL: integer := 8);
    port(PortL,PortR: inout signed(WL-1 downto 0);
          RW: in std_logic);

end Inter_Con_Mod;

architecture Behav of Inter_Con_Mod is

begin


 PortR <= PortL when RW = '0' else
            (others => 'Z');

 PortL <= PortR when RW = '1' else
            (others => 'Z');

end Behav;

So I have 2 inout ports and one select input port. The problem was not in the module's code. It was in the testbench. I had to drive the inout port I needed to act as an output in order not to have interference of data on the line. Below comes the Testbench code:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY Test IS
END Test;

ARCHITECTURE behavior OF Test IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT Inter_Con_Mod
    PORT(
         PortL : INOUT  signed(7 downto 0);
         PortR : INOUT  signed(7 downto 0);
         RW : IN  std_logic
        );
    END COMPONENT;


   --Inputs
   signal RW : std_logic := '0';
    --BiDirs
   signal PortL : signed(7 downto 0);
   signal PortR : signed(7 downto 0);
   -- No clocks detected in port list. Replace <clock> below with 
   -- appropriate port name 



BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: Inter_Con_Mod PORT MAP (
          PortL => PortL,
          PortR => PortR,
          RW => RW
        );




   -- Stimulus process
   stim_proc: process
   begin        

            PortL <= "01111111";
            PortR <= (others => 'Z');

            wait for 5 ns;
            RW <= '1';
            wait for 5 ns;
            PortR <= "01111100";
            PortL <= (others => 'Z');

            wait for 20 ns;



            wait;


      wait;
   end process;

END;

I hope this can help those who are new to hardware as me.