Concurrent signal assignment in VHDL - concurrency

I was thinking about the signal assignment in generally and I got into a dilemma.
If I have some project in which I have the following code:
ARCHITECTURE wait_example of wait_example IS
SIGNAL sendB, sendA : std_logic;
BEGIN
sendA <= ‘0’;
A : PROCESS
BEGIN
-- something
END PROCESS A;
B : PROCESS
BEGIN
-- something
END PROCESS B;
C : PROCESS
BEGIN
-- something
END PROCESS C;
And so on... I was thinking about when will the "sendA <='0';" part occurs? Only once in the beginning? Will it constantly reset sendA to 0? Or something else?
Thanks in advance,
Bojan Matovski

In addition to David Koontz good answer, it may be added that even through the
sendA <= '0' is only executed once, it will continuously drive sendA to
'0'. In test bench design, the final value on sendA is given by the resolution function
over all drives of sendA, where as in synthesizable design there should not be multiple drivers.
If you also try to drive sendA from one of the processes like:
sendA <= '0';
A : PROCESS
BEGIN
wait for 100 ns;
sendA <= '0';
wait for 100 ns;
sendA <= '1';
wait for 100 ns;
sendA <= 'Z';
wait;
END PROCESS A;
Then you will get the final value of sendA as:
0 ns: 'U', as result of resolution by '0' and 'U' from the yet unassigned
signal driven in A process.
100 ns: '0', as result of resolution by '0' and '0'
200 ns: 'X', as result of resolution by '0' and '1'
300 ns: '0', as result of resolution by '0' and 'Z'
Waveform is shown below.

Any concurrent statement has an equivalent process. Without a signal on the right hand side it's equivalent is a process terminated by a WAIT; statement. It'll execute once.

Although VHDL is a hardware description language, what you write down is a little different to the real circuit.
Concurrent assignments generally stand for combination logic. But that doesn't mean that you can't modify sendA's value after you make a concurrent assignment like sendA <= '0';, as MortenZdk mentioned. The value of signals with type std_logic are determined by a function called resolved function because std_logic is a resolved type. For example, if sendA has two drivers associated with it(sendA <= '0'; & sendA <= '1'; in two different processes), it'll get a 'X' eventually.
EDIT:
See also about delta time and multiple drivers.

Related

Verilog "if(test_conditional)" behavior at 'test_conditional' signal transition

Say I have the following:
always # (posedge clk) beign
...
if (~x) begin
y<=1'b0
end
...
end
And x, driven in another block, happens to be transitioning from 0 to 1 at the moment I'm checking it. How does if() evaluate in this case? Does it take the starting value of x (0) or the final value of x (1)?
I have looked over other answers to similar questions, but none discuss the particular case when the signal is transitioning.
Looking at the waves, the time precision does not allow me to discern if the signal x has settled to 0 or 1.
It depends on how x is driven.
If it is synchronous to the clock signal clk, then the value of x just before the clock edge (0) will be used. In a Verilog simulation, this means that x must be driven off the posedge clk and using a nonblocking assignment:
always #(posedge clk)
x <= some_expression;
Otherwise, you will have a race condition, and the value of x that is used will be indeterminate: it may be 0 or 1.

Vhdl if statement won't execute

I'm making a simple clock divider in modelsim.
When testing i notice that one if statement is never being executed. Any idea why?
It's the if count > 3 then statement. Modelsim gives the correct value of the counter integer (4, 5, 6, etc) but will never go into the if statement.
------------------------------------------------
-------- CLOCK DIVIDER
------------------------------------------------
entity clock_divider is
port ( clk,reset: in std_logic;
clock_out: out std_logic);
end clock_divider;
architecture bhv of clock_divider is
signal tmp : std_logic:='0';
begin
process(clk,reset,tmp)
variable count: integer:=1;
begin
if(reset='1') then
count := 0;
tmp <= '0';
elsif rising_edge(clk) then
count := count + 1;
if count > 3 then
tmp <= not(tmp);
count := 0;
end if;
end if;
clock_out <= tmp;
end process;
end bhv;
It's because you're using a variable for count. It should be a signal.
Each time the process is carried out in simulation, count will be set to 1.
Variables sometimes get wrongly seen as 'local signals', sort of like local variables in software, which they're not. A design using variables like this will behave differently in simulation to what is produced by a compiler during synthesis. The compiler will promote the variable to a signal but hidden away, with a warning given amongst any other warnings.
Instead, use a signal for count. The HDL design really must imply the actual circuit to be produced, which is DFFs for count.
Variables are useful in the clocked processes of synthesizable designs for (a) reshaping signal values, such as forming buses, or (b) naming nodes along a combinatorial tree. They're not for implying DFFs.

How statements are executed concurrently in combinational logic using VHDL?

I wonder how signal assignment statements are executed concurrently in combinational logic using VHDL? For the following code for example the three statements are supposed to run concurrently. What I have a doubt in is that how the 'y' output signal is immediately changed when I run the simulation although if the statements ran concurrently 'y' will not see the effect of 'wire1' and 'wire2' (only if the statements are executed more than one time).
entity test1 is port (a, b, c, d : in bit; y : out bit);
end entity test1;
------------------------------------------------------
architecture basic of test1 is
signal wire1, wire2 : bit;
begin
wire1 <= a and b;
wire2 <= c and d;
y <= wire1 and wire2;
end architecture basic;
Since VHDL is used for simulating digital circuits, this must work similarly to the actual circuits, where (after a small delay usually ignored in simulations) circuits continously follow their inputs.
I assume you wonder how the implementation achieves this behaviour:
The simulator will keep track of which signal depends on which other symbol and reevaluates the expression whenever one of the inputs changes.
So when a changes, wire1 will be updated, and in turn trigger an update to y. This will continue as long as combinatorial updates are necessary. So in the simulation the updates are indeed well ordered, although no simulation time has passed. The "time" between such updates is often called a "delta cycle".

concurrent and conditional signal assignment (VHDL)

In VHDL, there are two types for signal assignment:
concurrent ----> when...else
----> select...when...else
sequential ----> if...else
----> case...when
Problem is that some say that when...else conditions are checked line by line (king of sequential) while select...when...else conditionals are checked once. See this reference for example.
I say that when..else is also a sequential assignment because you are checking line by line. In other words, I say that there no need to say if..else within a process is equivalent to when..else. Why they assume when..else is a concurrent assignment?
Where you are hinting at in your problem has nothing to do with concurrent assignments or sequential statements. It has more to do with the difference between if and case. Before we get to that first lets understand a few equivalents. The concurrent conditional assignment:
Y <= A when ASel = '1' else B when BSel = '1' else C ;
Is exactly equivalent to a process with the following code:
process(A, ASel, B, BSel, C)
begin
if ASel = '1' then
Y <= A ;
elsif BSel = '1' then
Y <= B ;
else
Y <= C ;
end if ;
end process ;
Likewise the concurrent selected assignment:
With MuxSel select
Y <= A when "00", B when "01", C when others ;
Is equivalent to a process with the following:
process(MuxSel, A, B , C)
begin
case MuxSel is
when "00" => Y <= A;
when "01" => Y <= B ;
when others => Y <= C ;
end case ;
end process ;
From a coding perspective, the sequential forms above have a little more coding capability than the assignment form because case and if allow blocks of code, where the assignment form only assigns to one signal. However other than that, they have the same language restrictions and produce the same hardware (as much as synthesis tools do that). In addition for many simple hardware problems, the assignment form works well and is a concise capture of the problem.
So where your thoughts are leading really comes down to the difference between if and case. If statements (and their equivalent conditional assignments) that have have multiple "elsif" in (or implied in) them tend to create priority logic or at least cascaded logic. Where as case (and their equivalent selected assignments) tend to be well suited for things like multiplexers and their logic structure tends to be more of a balanced tree structure.
Sometimes tools will refactor an if statement to allow it to be equivalent to a case statement. Also for some targets (particularly LUT based logic like Xilinx and Altera), the difference between them in terms of hardware effiency does not show up until there are enough "elsif" branches though.
With VHDL-2008, the assignment forms are also allowed in sequential code. The transformation is the same except without the process wrapper.
Concurrent vs Sequential is about independence of execution.
A concurrent statement is simply a statement that is evaluated and/or executed independently of the code that surrounds it. Processes are concurrent. Component/Entity Instances are concurrent. Signal assignments and procedure calls that are done in the architecture are concurrent.
Sequential statements (other than wait) run when the code around it also runs.
Interesting note, while a process is concurrent (because it runs independently of other processes and concurrent assignments), it contains sequential statements.
Often when we write RTL code, the processes that we write are simple enough that it is hard to see the sequential nature of them. It really takes a statemachine or a testbench to see the true sequential nature of a process.

Please, clarify the concept of sequential and concurrent execution in VHDL

I got familiar with a little bit of Verilog at school and now, one year later, I bought a Basys 3 FPGA board. My goal is to learn VHDL.
I have been reading a free book called "Free Range VHDL" which assists greatly in understanding the VHDL language. I have also searched through github repos containing VHDL code for reference.
My biggest concern is the difference between sequential and concurrent execution. I understand the meaning of these two words but I still cannot imagine why we can use "process" for combinational logic (i.e. seven segment decoder). I have implemented my seven segment decoder as conditional assignment of concurrent statements. What would be the difference if I implemented the decoder using process and a switch statement? I do not understand the word sequential execution of process when it comes to combinational logic. I would understand it if it was a sequential machine-a state machine.
Can somebody please explain this concept?
Here is my code for a seven-segment decoder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity hex_display_decoder is
Port ( D: in STD_LOGIC_VECTOR (3 downto 0);
SEG_OUT : out STD_LOGIC_VECTOR (6 downto 0));
end hex_display_decoder;
architecture dataflow of hex_display_decoder is
begin
with D select
SEG_OUT <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when "0100",
"0010010" when "0101",
"0000010" when "0110",
"1111000" when "0111",
"0000000" when "1000",
"0010000" when "1001",
"0001000" when "1010",
"0000011" when "1011",
"1000110" when "1100",
"0100001" when "1101",
"0000110" when "1110",
"0001110" when "1111",
"1111111" when others;
end dataflow;
Thank you,
Jake Hladik
My biggest concern is difference between sequential and concurrent
execution. I understand the meaning of these two words but I still
cannot imagine why we can use "process" for combinational logic (ex.
seven segment decoder).
You are confounding two things:
The type of logic, which can be sequential or combinational.
The order of execution of statements, which can be sequential or concurrent.
Types of logic
In logic design:
A combinational circuit is one that implements a pure logic function without any state. There is no need for a clock in a combinational circuit.
A sequential circuit is one that changes every clock cycle and that remembers its state (using flip-flops) between clock cycles.
The following VHDL process is combinational:
process(x, y) begin
z <= x or y;
end process;
We know it is combinational because:
It does not have a clock.
All its inputs are in its sensitivity list (the parenthesis after the process keyword). That means a change to any one of these inputs will cause the process to be re-evaluated.
The following VHDL process is sequential:
process(clk) begin
if rising_edge(clk) then
if rst = '1' then
z <= '0';
else
z <= z xor y;
end if;
end if;
end process;
We know it is sequential because:
It is only sensitive to changes on its clock (clk).
Its output only changes value on a rising edge of the clock.
The output value of z depends on its previous value (z is on both sides of the assignment).
Model of Execution
To make a long story short, processes are executed as follow in VHDL:
Statements within a process are executed sequentially (i.e. one after the
other in order).
Processes run concurrently relative to one another.
Processes in Disguise
So-called concurrent statements, essentially all statements outside a process, are actually processes in disguise. For example, this concurrent signal assignment (i.e. an assignment to a signal outside a process):
z <= x or y;
Is equivalent to this process:
process(x, y) begin
z <= x or y;
end process;
That is, it is equivalent to the same assignment within a process that has all of its inputs in the sensitivity list. And by equivalent, I mean the VHDL standard (IEEE 1076) actually defines the behaviour of concurrent signal assignments by their equivalent process.
What that means is that, even though you didn't know it, this statement of yours in hex_display_decoder:
SEG_OUT <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when "0100",
"0010010" when "0101",
"0000010" when "0110",
"1111000" when "0111",
"0000000" when "1000",
"0010000" when "1001",
"0001000" when "1010",
"0000011" when "1011",
"1000110" when "1100",
"0100001" when "1101",
"0000110" when "1110",
"0001110" when "1111",
"1111111" when others;
is already a process.
Which, in turn, means
What would be the difference if I implemented the decoder using
process and a switch statement?
None at all.