If you are wondering about how the <= operator works; it is what is called a 'nonblocking assignment.' What this means is that the left hand side of all of the <= are performed for a particular event (e.g. rising clock edge) and then once those are all evaluated, the result is placed in the output. This allows you to write shift registers without temporary variables. None of the values change until the left hand calculations are completed, then the results are moved over to the right hand side. It is generally not a good idea to use nonblocking assignments for combinatorial logic. Generally they are only used to create latches and registers and you use regular blocking assignments for combinatorial logic. When synchronized with a clock signal, you can generally consider <= operations to be D flip-flops that sample the input and transfer it to the output atomically on a single clock edge.
'Race conditions' where intermediate indeterminate results appear on the outputs of combinatorial functions are hard to avoid and they can depend greatly on how the design is actually implemented on an ASIC or FPGA. However, most designs are synchronous and so as long as the output settles within one clock period this is not a problem. There are tools that can check the timing performance of a design to check all of the path delays to ensure that the results will always be valid for a given clock frequency, but this is highly dependent not on the actual HDL code but on the way the design is placed and routed.
Synthesizers (not compilers!!!!) will generally perform optimization on combinatorial logic. There are limits to how much the synthesizer can do (e.g. it will not re-architect your system) so you have to know more or less how it will end up being implemented. If you're working on an FPGA, generally the synthesis and place and route will pack any logic function that fits onto LUTs. So if you can separate out a single logic function with up to 4 inputs and 1 output, this will end up on a single LUT and the only delay that matters is the propagation delay of the LUT, which is the same for all of its inputs. In the case of your example function, both pieces of code may be implemented identically on one LUT with three inputs and one output.
Bisg is an INPUT signal not an INOUT despite the fact that it has other uses (driving segment G on the top level).
To see this; reflect that NOTHING in your component actually drives BISG.
So your component is regarded as driving it with an undefined initial level; that is, 'U', and the combination of that 'U' with any external driving level is - as ISIM says - 'U'.
You have 2 options to fix it:
(1) make BISG an INPUT since you aren't driving it. This is the simplest and in this case correct.
(2) Drive BISG in your component with 'Z' - that is, remove the 'U' output from the component. 'Z' means "high impedance : i.e. don't fight whatever external source (your testbench) is driving the pin. This is typically done to allow 2-way communication on a signal. The two ends must agree (somehow) which end is allowed to drive the signal and the other end must drive 'Z'.
In your case, adding the line
BISG <= 'Z';
(after the "begin") to your component BCT should resolve the problem. (Yes, you are modifying the file labelled "do not modify", and the modification WILL disappear when you next compile the schematic to VHDL).
Then re-run the simulation and all should be well.
I do not know if there's a way to implement solution 2 in the schematic - and I don't care : these days the schematic approach is an utter waste of time.
Your whole schematic comes down to (the original entity, and)
architecture HDL of BCT is
begin
Bisg <= 'Z';
Bnisc <= not Bisg;
sf <= not Bisg and not A;
saisdise <= Bisg or not A;
sb <= '1';
end HDL;
And simplifies further if Bisg
is an input...
Which do you think is faster to create, and easier to read?
EDIT : if you need an output to drive segment G, there's nothing wrong with a separate port G, driven directly from input B, as G <= B;
or a wire on the schematic.
Best Answer
Throw out the terms blocking and non-blocking assignments altogether, they have no place in VHDL. For which I am glad, they seem to cause enough confusion in Verilog.
The one huge advantage VHDL has over not just Verilog but virtually every other digital simulation/verification language out there is its deterministic timing model. In Verilog, simulations may legitimately deliver different results on different simulators because of the order in which processes (tasks, modules) are executed. Can't happen with VHDL - or if it does, there's a bug in the simulator.
But it's worth understanding how this timing model works - I'd say it's absolutely key to understanding VHDL. Grasp this and VHDL will become a lot easier.
It relies on 2 key points:
"delta cycles"
until nothing is happening, when it can step forward some finite timestep (fs, ps, ns) to the next scheduled event (delay, or clock edge).Variables are local to a process, and variable assignments take place immediately - the next statement sees the new value.
Signal assignments don't happen immediately, but are scheduled to happen after the end of the current
delta cycle
, when all executing processes have happened. More detail here.If it still isn't clear, refine the question.