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.
Related
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.
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.
I know what the inout parameters is and how to use them. Assume that we have an inout parameter io and want to create a bidirectional static RAM such as the following code :
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY sram IS
port(
clk : IN std_logic;
wr : IN std_logic;
io : INOUT std_logic;
addr : IN INTEGER RANGE 0 TO 7
);
END sram;
ARCHITECTURE behavioral OF sram IS
TYPE matrix IS ARRAY (0 TO 7) OF std_logic;
SIGNAL mem : matrix;
BEGIN
PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN
IF wr = '1' THEN
mem(addr) <= io;
END IF;
END IF;
END PROCESS;
io <= mem(addr) WHEN wr = '0' ELSE 'Z';
END behavioral;
We can create an instance of sram and write on it such as the following code :
io <= '1' WHEN wr = '1' ELSE 'Z';
Question : How can synthesis tool control the multiple assignments and judge between multiple drivers ? What hardware is implemented to do it ?
Thanks for comments and answers ...
For typical FPGA and ASIC devices, implementation of tristate capabilities are only available on the IO, like for example in an Altera Arria 10 FPGA:
So for such devices, the internal RAMs are always implemented with dedicated input and output ports, thus not using any internal tristate capabilities.
Even if a RAM is connected to external IOs that support tristate, then the internal RAM block is still typically created with dedicated input and output ports, so the connection to a tristate capable pin on the device is handled through an in-out buffer with the output enable and tristate capability.
If internal design tries to use tristate capabilities or multiple drivers when this is not supported by the device, then the synthesis tool will generate and error, typically saying that multiple drivers are not supported for the same net.
On Xilinx devices, the schematics are similar.
This is an image of primitive IOBUF:
The green part is the output driver with tristate control; the blue part is the input driver. The complete IOB (Input/Output Block) consists of several primitives:
IOB registers (input, output, tristate control)
delay chains
wires to combine two IOBs to a differential IOB (**BUFDS)
capability to drive clock networks (CC-IOB - clock capable IOB)
pullup, pulldown, ...
driver (IOBUF)
pin/ball (IPAD, OPAD, IOPAD) - this includes ESD protection
How does synthesis work?
Xilinx synthesis tools (XST / Synth) add IPAD or OPAD primitives for every wire in your top-level component's port description. A pad is just the primitive to represent a physical pin or ball under the FPGA package.
If you enabled to automatically add I/O buffers, the tool will add IBUF, OBUF, IOBUF, IBUFDS, ... primitives between every PAD and top-level port. It uses the port direction (in, out, inout) to infer the correct buffer type. If this option is disabled (default = on) you have to manually add buffers for every I/O pin. In some cases XST gets offended: I added some IOBUFs with tristate control by hand so XST declined to infer the missing buffers. So I had to add all buffers by hand ...
While using Xilinx XST it's possible to use tristate buses (port direction = inout) beneath the top-level. XST will report that it added (virtual) tristate buffers. These buffers get trimmed if the direction of each bit of the bus has an obvious direction and no multiple driver problem.
This does not work in iSim.
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.
I got WebPack up and running on my machine again and after synthesizing a simple design and uploading it to my FPGA, I encountered quite a problem with my understanding.
When there is a line like this in the user constraint file:
NET "W1A<0>" LOC = "P18" ;
How exactly does the synthesis software determine how this pin gets assigned to by the VHDL code?
For instance, take this example code I've been provided with:
entity Webpack_Quickstart is
Port (
W1A : out STD_LOGIC_VECTOR(15 downto 0);
rx : in STD_LOGIC;
tx : inout STD_LOGIC;
clk : in STD_LOGIC
);
end Webpack_Quickstart;
architecture Behavioral of Webpack_Quickstart is
signal counter : STD_LOGIC_VECTOR(47 downto 0) := (others => '0');
begin
W1A(0) <= '1';
end;
How exactly does this code make the WIA0 pin on my FPGA turn on? What is the link? Is it just the name of the port in the entity declaration is there more magic involved?
Your .ucf constraints are applied in the implementation phase. At this point your design has been synthesized, and the available top-level nets are thus "known". So yes, it is only a matter of matching equally named nets to equally named constraints.
The syntax is slightly different though (using <> instead of () for indexing vectors for instance), but otherwise it's just a simple string match.
The easiest way to initially configure your pin constraints, especially for large designs, is to just use one of the graphical tools (PlanAhead, if it's included in the WebPack) to assign the pins, and generate an initial .ucf file.
I find that making small changes later on is easiest to do by hand using the standard ISE text editor directly though.