Write an inout Port in a testbench - vhdl

I am currently working on a project where I want to implement a bidirectional bus. For this project I was given an entity that I should not edit.
This entity has two inout ports (sda and scl).
I now want to write from the TestBench to the entity through the inout port sda. To do this I assign a value to to the signal that is connected to sda.
When I do this, I get the error that I have multiple sources for the unresolved signal sda. One is the assigned value and one is the entity itself.
I do not understand how I can assign a value to this inout port without triggering this error.
Is there a quick explanation for this problem ? Otherwise what buzzwords are useful for searching a solution to this problem ?
My code for this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2c_slave_tb is
end i2c_slave_tb;
architecture arch of i2c_slave_tb is
-- signal declaration
-- sim signals
-- uut signals
signal sda: std_ulogic;
signal scl: std_ulogic;
begin -- arch
uut : entity work.i2c_slave
port map (
sda=>sda,
scl=>scl
);
stim_gen :process
begin
wait for 10 ns;
sda<='1';
wait;
end process stim_gen;
end arch;

The sda and scl signals are std_ulogic where the "u" stands for unresolved, meaning that there can be only one driver for the signal, since there is no resolution function attached to the type to determine the signal value in case of multiple drivers.
Change the type to std_logic for a type with standard resolution function, like:
signal sda: std_logic;
signal scl: std_logic;
You can look here for some description of "VHDL resolution function", or search it.

Related

Difference between declaring signal in architecture and in entity

Assuming that I have the following piece of code:
entity MyEntity is
port (
i_clock : in std_logic; -- these are the signals inside entity
Clk_100HZ : inout std_logic;
Data : inout std_logic;
);
end MyEntity;
architecture rtl of MyEntity is
signal D_zeroin : std_logic; -- these are the signals inside architecture
signal D_onein : std_logic;
signal D_twoin : std_logic;
signal D_threein : std_logic;
begin
...
What is the difference between signals declared in port's entity and signals declared directly into architecture?
Declarations in the entity can be of ports or generics. Generics are constants fixed at compilation time. Ports input and/or output signals from the architecture to the instantiating architecture i.e. the 'next level up'.
Signals are nodes/registers/memory within the architecture itself that cannot be seen by any architectures outside.
The parallel often given is that of a logic chip IC on a circuit board:
The entity specifies the pins on the IC that signals flow through, in and out of the chip to the board.
The architecture is the chip circuit inside the IC package. Its internals cannot be accessed.
Instantiating a component is plugging one of that IC into a circuit board.
The publicly-known entity will be visible to the architecture above that instantiated that component.
But the architecture is hidden away with its contents not visible to any other part of the design and not necessarily visible to the people using the component. Different architectures can be designed and associated with the entity for compilation.

Can't handle registered multi driver

I am getting this messege from compiler for all the "busreg" bits:
topld: busshift.vhd: (E463) 'busreg(7)' -- Can't handle registered multi driver.
topld: busshift.vhd: (E446) Can't handle multiple drivers for 'busreg(7)' in selected device.
I was asked to do shift rigister that I can put in put from both side as I choose depends on DIR.
My code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.all;
ENTITY shiftbus IS
PORT
(
busreg : inout std_logic_vector(7 downto 0);
dir,clk : IN std_logic;
pinL,pinR : inout std_logic
);
END shiftbus;
ARCHITECTURE behavioral OF shiftbus IS
BEGIN
busreg<="00000000";
process(clk,dir)
begin
if (rising_edge(clk)) then
if(dir='1') then --1 we input from right
busreg<=busreg(6 downto 0)&pinR;
else-- else is 0 and we input from left
busreg<=pinL & busreg(7 downto 1);
end if;
end if;
end process;
END behavioral;
You have the following line:
busreg <= "00000000";
If you're going to drive this signal low all the time, what's the point of the other logic?
You are driving the signal busreg from two processes: the explicit process and the implicit process busreg <= "00000000";. In other words, you have a short circuit.
A process is a little bit of software that models a little bit of hardware.
So, when you drive a signal from more than one process, you are modelling a signal that is driven from more than one lump of hardware. Normally, if you want to drive a signal from two or more lumps of hardware, you need to be using tristate logic. I think the error message is telling you that the FPGA device you have chosen is not able to implement tristate logic and so it is an error for you to drive a signal from more that one place.
So, why have you written the line busreg <= "00000000";? If you were hoping to reset your shift register, you haven't; you've created a short circuit.
BTW: your process is a sequential process. The sensitivity list of a sequential process should either contain just the clock or, if there is an asynchronous reset, just the clock and the asynchronous reset. dir should not be in your sensitivity list.

Test Bench Waveform no longer on Xilinx....Need VHDL guidance

MAJOR UPDATE. NEVERMIND. I FOUND AN OLDER VERSION OF XILINX ISE SUITE IN THE FORM OF A TORRENT. THE OLDER VERSION HAS TEST BENCH WAVEFORM. I REALLY DISLIKE THEIR BUSINESS MODEL OF DISCONTINUING CERTAIN APPLICATIONS WHICH MAKE THE PROCESS EASIER.
My issue is that I am working a Simple Machine Schematic Circuit which and trying to display is waveform under certain conditions. However Im using the latest Xilinx ISE which does not have Test Bench Waveform ( i cant seem to download old version on Windows 8.1).
I have been struggling to learn the correct VHDL. This is the generated VHDL that I have.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
LIBRARY UNISIM;
USE UNISIM.Vcomponents.ALL;
ENTITY top_top_sch_tb IS
END top_top_sch_tb;
ARCHITECTURE behavioral OF top_top_sch_tb IS
COMPONENT top
PORT( Q1 : OUT STD_LOGIC;
RCO : OUT STD_LOGIC;
INPUT : IN STD_LOGIC;
PRE : IN STD_LOGIC;
CLK : IN STD_LOGIC;
Q0 : OUT STD_LOGIC);
END COMPONENT;
SIGNAL Q1 : STD_LOGIC;
SIGNAL RCO : STD_LOGIC;
SIGNAL INPUT : STD_LOGIC;
SIGNAL PRE : STD_LOGIC;
SIGNAL CLK : STD_LOGIC;
SIGNAL Q0 : STD_LOGIC;
BEGIN
UUT: top PORT MAP(
Q1 => Q1,
RCO => RCO,
INPUT => INPUT,
PRE => PRE,
CLK => CLK,
Q0 => Q0
);
-- *** Test Bench - User Defined Section ***
tb : PROCESS
BEGIN
WAIT; -- will wait forever
END PROCESS;
-- *** End Test Bench - User Defined Section ***
END;
These were the conditions that I was going to use test bench for...but need a VHDL equivalent.
Open the HDL Bencher window. In the Initialize Timing window, select
the option Single Clock. Set Clock High Time and Clock Low Time to 50
ns, Input Setup Time and Output Valid Delay to 10 ns, and Initial
Length of Test Bench to 2500 ns. After checking the values, click on
Finish.
I have found different VHDL language sites... but I cant really clarify anything. IF more detail is needed I will try to supply it.

VHDL: Concat inout std_logic into std_logic_vector signal

I have several tri-stateable (inout) std_logic port pins defined in my top-level port declaration. I have a dedicated internal component that is needing to utilize these, but its port is defined as having an inout std_logic_vector (not my code and I can't change), which I need to concatenate my std_logic into a std_logic_vector to make it happy.
The problem is: I'm not sure how to do this.
I thought that ALIAS would be the correct route, but apparently the concatenation operator can't be used when defining an alias.
Then I thought I'd just use a std_logic_vector internal signal:
mySignal <= inOutBit2 & inOutBit1 & inOutBit0; --Input route
componentPort => mySignal, --Component use
inOutBit2 <= mySignal(2);
inOutBit1 <= mySignal(1);
inOutBit0 <= mySignal(0); --Output route
but this would not synthesize as it viewed inOutBitn as having multiple drivers.
Is there anything I can do to get this to synthesize? I know I can just declare my top-level inout port to be a std_logic_vector, but that is sub-optimal as we have a a well defined port-labeling convention.
Based on your description, I understand that both the top-level ports and the component ports are mode inout.
If this is so, then it may help if you connect the component ports directly to the external inout ports at std_logic level, like:
componentPort(0) => inOutBit0, --Component use
componentPort(1) => inOutBit1, --Component use
componentPort(2) => inOutBit2, --Component use
The intermediate mySignal is then not required.
However, the description says that synthesis reports multiple drivers for inOutBitn, but I would expect that it reported multiple drivers for mySignal in the original code.

VHDL inout ports

I am having trouble creating an entity using inout ports. I tried writing the following code where A is an input and B is an output and it works fine. But as soon as I change A to an inout port, it implements but it won't simulate. Can anyone tell me what the problem is?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Problem2 is
Port ( A : inout integer;
B : out integer
);
end Problem2;
architecture Behavioral of Problem2 is
procedure change (signal A: inout integer; signal B: out integer) is
begin
B<=A after 20 ns;
end change;
begin
change(A=>A, B=>B);
end Behavioral;
The procedure "change" is a driver on A, but doesn't explicitly drive anything, so A will be driven to 'U'. Try this change which should do what you seem to expect:
procedure change (signal A: inout integer; signal B: out integer) is
begin
A <= 'Z';
B <= A after 20 ns;
end change;
Usually, you don't need inout ports. Especially if you are just starting to use VHDL, stick with in or out. Inout is used for modeling tri-state busses. As #wjl points out, you need to assign 'Z' to the signal if you want to be able to read what the other side is writing.
Also, if you are writing procedures for your later reuse, you should not wrap them in an entity and then test the entity. This just causes extra problems (as you are experiencing right now). Instead, call the procedure directly from your test bench, like you would test a procedure (or function) in software.
Are you using Synopsys VCS ?
There is a known limitation in VCS that inout(s) in the entity do not simulate (show up as red)

Resources