VHDL DISCUSSION

VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

Started by eddiekadege VHDL multiple driversresolved signalsstd_logic valuesstd_ulogictri-state bus
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

eddiekadege VHDL Forum
#1

I split my counter into two processes: one clears cnt (declared with an initial value of zero) when rst is high, the other increments it on each rising clock edge while rst is low. In simulation cnt is zero during reset, then bit 0 turns to 'X' on the first count, and one clock later all eight bits are 'X'. Synthesis refuses the design with a multiple-driver error. Another signal, which a single process assigns only under a rare condition, sits at 'U' from time zero.

Why can a signal not be assigned from two processes, and what do 'U' and 'X' tell me when I see them in a waveform?

Community replies 5

Re: VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

#2

Each process that contains an assignment to a signal gets its own driver for that signal, and the driver exists for the whole simulation, not only while the assignment is executing. Your reset process drives zeros during reset and keeps driving those zeros afterwards, because nothing in it ever assigns another value. The counting process drives the count.

std_logic is a resolved type, so the simulator combines the drivers with a resolution function: '0' against '1' gives 'X'. On the first count only bit 0 differs, so only bit 0 shows 'X'. On the next edge the counting process computes cnt + 1 from a value that already contains 'X', the arithmetic returns all 'X', and the whole vector is lost.

Re: VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

#3

Reading the nine values: 'U' means uninitialised; no assignment has happened since time zero and the signal had no initial value. 'X' means a conflict between strong drivers, or an unknown that has propagated through logic. 'Z' is high impedance, a driver that has let go. 'W', 'L' and 'H' are weak unknown, low and high, used for pull-ups and pull-downs, and '-' is don't care.

In resolution 'U' overrides everything, so one driver that has never assigned a value makes the whole signal 'U'; then 'X' dominates, a strong '0' or '1' beats the weak values, and 'Z' gives way to anything. Your other signal is the simple case: a single driver that has not yet assigned anything.

Re: VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

#4

The fix is structural: a signal that becomes a register is assigned in exactly one process. Put reset and counting together: process(clk) begin if rising_edge(clk) then if rst = '1' then cnt <= (others => '0'); else cnt <= cnt + 1; end if; end if; end process; with cnt declared as unsigned. One process, one driver, and the priority between reset and count is stated explicitly.

Hardware has the same restriction. Two gate outputs wired together fight each other, and FPGA fabrics have no internal wired connections of that kind, so the synthesiser can only report the error.

Re: VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

#5

You can have the compiler catch this before simulation. std_ulogic and std_ulogic_vector are the unresolved versions of the same types: a second driver on such a signal is an error at compile or elaboration time, instead of an 'X' that you have to notice in a waveform. Using them for internal signals is good practice, and since VHDL-2008 the resolved and unresolved vector types are compatible without conversions.

Several drivers are legitimate only for a real shared bus, where each driver releases the line with 'Z' when inactive: data <= dout when oe = '1' else (others => 'Z');. In an FPGA that is available at the I/O pins; internal tri-state buses have to be written as multiplexers.

Re: VHDL signal shows 'X' or 'U' in simulation when two processes assign it: what is wrong?

#6

When the conflict is not as obvious as two processes, look for the less visible ways of creating a second driver: a concurrent assignment to the same signal elsewhere in the architecture, a signal connected to the output ports of two instances, or a generate loop in which every iteration assigns the whole vector instead of its own slice. Most simulators can list the drivers of a selected signal with their current values, which pinpoints the source directly.

To get rid of a 'U' that is only an initialisation issue, give the register a reset value, or an initial value in the declaration if your target honours it, rather than hiding it in the testbench.

TEP COMMUNITY