Weak 'H', Pullup on inout bidirectional signal in simulation - vhdl

Is there a way to tell the simulator (I'm using Modelsim) to pull a signal to weak 'H' when it's not being driven by either bidirectional interface?
For example if I have an I2C signal I2C_SDA that is declared as an inout from 2 modules. One is my actual UUT and the other is a testbench. Both have statements like this:
io_i2c_sda <= r_I2C_DATA when r_I2C_DATA_EN = '1' else 'Z';
So both ends are tri-stated. This works fine in simulation, except that the line is BLUE ('Z') all the time that neither end is transmitting. How can I pull-up this line to a 'H' in the code when neither end is transmitting?

For VHDL, it should be possible to simply add an extra driver to the signal (which has to be of std_logic type), with the constant value 'H'. In Verilog one would use a simple '1' driver and the net type wand for wired and. 'H' specifically means a weak high driver, so it will be overridden by the low drivers.

Related

VHDL buffer variable vs out variable

I work in a VHDL program and I need to do a RAM 256 using the ALTERA DE2-115. The outputs will show in a seven segment display.
The problem is that: I have a dataout output variable. Then the variable has the following values of the temp_ram array:
dataout <= temp_ram(conv_integer(dir));
Then I want to divide the vaules of dataout to put in the seven segment
dataout(7 downto 4)
dataout(3 downto 0)
This shows the following error:
Error (10309): VHDL Interface Declaration error in RAM.vhd(45): interface object "dataout" of mode out cannot be read. Change object mode to buffer.
When I change to buffer and this run prefect, but I can't understand what happen
For cross-platform compatibility and code-reusability, I'd recommend an intermediate signal ( dataout_int can be used by other statements) :
dataout_int <= temp_ram(conv_integer(dir));
and assign the output to this intermediate signal:
dataout <= dataout_int;
You are using conv_integer from a Synopsys package. Please use only official IEEE packages.
dataout is a signal, not a variable, because you use a signal assignment statement. Moreover, the signal is a port of mode out. (Ports are signals as well).
Besides static typing, VHDL is also checking directions of signal in ports. Your signal is of mode out so it can't be read.
Als a solution, you can:
use an intermediate signal,
use mode buffer, which is not supported by all synthesis tools equally
use VHDL-2008, which allows ports of mode out to be read.
Quartus support some VHDL-2008 features.

how does inout parameters be implemented?

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.

VHDL - same bitstream, two boards -> inout issue

I wanted to ask if it is possible to use an inout pin as inout and normal out? The two behaviours should be switched through a MUX. The reason for this weird looking implementation is that I have two boards and I want to use the same bitstream. On one board, the same pin is connected to a LED through GPIO and on the other it goes to my I2C bus connection. The software tries to detect the I2C and if successful it sets a register. If not, it clears it.
LED_or_SDA : inout std_logic; -- port definition
process (register)
begin
if ( register = '1') then -- software sets this register
LED_or_SDA <= I2C_SDA; -- here I want to use it as inout
else
LED_or_SDA <= gpio_reg; -- here I want to use it as normal out
end if;
end process;
This implementation throws the error "bidirect pad net is driving non-buffer primitives" during translate. Is there a solution for this?
No, you can't. A mux is not a switch, it is a logic function. The line
LED_or_SDA <= I2C_SDA;
strongly drives LED_or_SDA from I2C_SDA. It does not connect the two nets in a way that allows bidirectional data flow.
You'll need to separate the two directions:
I2C_SDA_in <= LED_or_SDA;
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
'0' WHEN (I2C_SDA_out = '0') ELSE
'Z';
Most I2C logic blocks have separate data in and out signals anyway, right up until the external interface, where you'll find a tri-state buffer expressed in much the same way as the code I gave you. You'll simply need to make the input and output data separate ports on your I2C block.
Unfortunately, the weak drive state of the internal signal likely isn't accessible to internal logic, so these won't work:
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
I2C_SDA_out;
LED_or_SDA <= gpio_reg WHEN (register = '1') ELSE
'Z' WHEN (I2C_SDA_out = 'Z') ELSE
I2C_SDA_out;
The VHDL compiler actually is keeping track of a tri-state control signal, and propagating that through port statements until it hits the external pin and connects it to the real (hardware) tri-state buffer. But in most compilers you can't access that control signal for your own logic.
Guessing from your error message I assume that we are talking about a Xilinx System, e.g. around a Microblaze - if that's not the case, please update your question and also specify the exact GPIO core you're using.
Often these GPIO blocks already contain the IO-Buffer macro by default. This IOBUF is located next to a physical pin and can not drive any other signals on the FPGA. Hence the GPIO block is intended to be used on the top level of the chip and be directly connected to a pin. However, there usually is a way to also access the signals before the IOBUF: E.g. in Xilinx Platform Studio on the tab "Ports" you should have a choice to use also GPIO_IO (after buffer), GPIO_IO_I (pure input), GPIO_IO_O (pure output), GPIO_IO_T (tristate) or similar.
Yes, the trick is to treat it always as a tristate buffer, and control the output based on the state of register
-- define a tristate pin the usual way.
LED_or_SDA <= LED_or_SDA_out when LED_or_SDA_tristate = '0' else 'Z';
LED_or_SDA_in <= LED_or_SDA
-- then control the data onto it, and the tristate control line
LED_or_SDA_tristate <= '0' when register = '0' else ICD_SDA;
LED_or_SDA_out <= gpio_reg when register = '0' else '0';

VHDL - why do we need to declare signals for processes?

Just revisiting some VHDL and I was wondering inside processes for example, why do we need to declare a signal for a clock for example? Then later on in the code assign it to the port from the entity...
EXAMPLE VHDL:
signal clk_int: std_logic := '1';
BEGIN
clkgen: process(clk_int)
begin
clk_int <= not clk_int after 50ns
end process ckgen
ck_l <= clk_int;
In this example ck_l is a physcial port from the d flip flop yet we create and mess around with clk int then return the value to ck
The reason is that the port ck_l in this case is probably declared with direction out, so It cannot be read from. If you want to read it, like you would need to if you want to have a process that is sensitive to it, you need to use a signal or declare the port as inout or buffer.

Error : Identifier 'q' is not readable in architecture of T Flip Flop

I am trying to model a T Flip Flop using VHDL.
library ieee;
use ieee.std_logic_1164.all;
entity tff is
port (
clk: std_logic;
t: in bit;
q: out bit;
qbar: out bit);
end tff;
architecture tff_arch of tff is
begin
process(clk)
begin
if (clk = '1' and t = '1')
then
q <= not q;
qbar <= not qbar;
end if;
end process;
end tff_arch;
But the error i am getting is
Error: CSVHDL0168: tff.vhdl: (line 17): Identifier 'q' is not readable
Error: CSVHDL0168: tff.vhdl: (line 18): Identifier 'qbar' is not readable
The reason of error i think is, i am using "not q", when q has not been initialized. Correct me here, if i am wrong.
And what to do to get around this problem? I have modeled D Flip flop and its test bench waveform correctly using Symphony EDA free version.
In the old days you couldn't read an output, so you had to either:
make it an inout (which is a bit unpleasant as you are fudging the direction you really mean, just so you can read it) - this works, but is not widely used in industry (as far as I'm aware)
make it a buffer, but that had downsides (prior to VHDL-2002) in that you have to make all the rest of the hierarchy of that signal driven by buffers. Almost never used in my experience.
use and intermediate signal (which you can read) and then use an assignment to set the output to the value of that signal. This is the idiomatic way of doing it amongst practising engineers.
Since VHDL-2008 you can read output ports (although the stated intention of this is for it only to be used for verification purposes). You'll probably need a tool switch to enable VHDL-2008 mode. (And it may be that your particular simulator/synthesiser still doesn't support VHDL-2008, which shows the staggering pace of development in the EDA tools world!)
q is an output of the entity.
You can't read an output. It's that simple.
You need an internal version that you use for the feedback loop, and then q <= local_q;
Can't remember VHDL very well, but this might give you a clue:
The problem is that q is only a signal out of your entity, so there is nothing to access when you try to read it.
So, to not solve your homework, think of it this way:
Either you need to have q as an input in order to access it (probably not what you want) or you need to store q (or at least next value of q) internally. This can be done by specifying q (or q_next) as a signal in the architecture part. For example:
architecture tff_arch of tff is
signal q_next: std_logic;
begin
and so on. The same goes for your qbar signal.

Resources