The VHDL code is:
next_x(7 downto 0) <= rec_data;
What does this line do? What is the equivalent statement? This line is within a process and is executed when condition_1 is true.
My guess is that this statement will update next_x?
Can someone please explain the statement and find the equivalent, if any?
Thanks.
Since this is a signal assignment, it schedules next_x to have the value of rec_data after the process completes. The biggest caveat to be aware of is that a subsequent read of signal next_x in the process where this change is scheduled will return the old value of this signal -- the change has not taken effect yet. You can think of it as being executed concurrently with all other signal assignments in the process, but multiple assignments of the same signal are allowed and only the last will take effect.
On the other hand, variable assignments take effect immediately, so changes are visible by all subsequent statements in the process, much like imperative programming languages.
The equivalent variable assignment would be next_x(7 downto 0) := rec_data;, but next_x must then be a variable, not a signal.
Here is a good summary of signal versus variable assignment.
Related
I am doing a project in VHDL and I am stuck at this point. Any help is appreciated.
The problem is described as follows:
I have a 2D array with N (in number) std_logic_vector signals. The number N is defined in generics, so we do not know the specific length of the array (we use N instead).
This array is used as sensitivity list of a process in order to trigger it. Like so: process(arrayOfSignals)
My question is: Is there any way to know which specific signal of the array triggered the process? (Like for example the signal: arrayOfSignals(2))
I have seen this post: Which signal in the sensitivity list triggers the process but it is not the case here. It would be the case if all the signals of their sensitivity list where inside an array, and this array was triggering the process.
To become clear, below is the VHDL code of what I am trying to do.
process(arrayOfSignals)
begin
for i in 0 to N-1 loop
if arrayOfSignals(i)'transaction'event then --I want to determine which signal of arrayOfSignals (position in the array) triggerd the process.
case arrayOfSignals(i) is
when "01" =>
AD(i)(30 downto 23) <= AD(i)(7 downto 0);
exit;
when others => null; exit;
end case;
exit;
end if;
end loop;
end process;
I don't know how to do exactly what you are asking. But let me suggest a way to do what I think you are trying to do.
Typically if you want to detect a change in a signal, you would have a clocked process and make a registered copy of the signal. You can then compare the state of your input signal with your registered copy (for each element) and if they are not equal, the input has changed and you can trigger your logic.
let's say I have two processes in my code:
prc 1 : process( CLK , RESETN ) {with some code}
Q <= outd
prc2 : process(outd,RESETN)
Note that we change outd in prc1..
A process is executed in parallel with other processes, right? how can it be executed in parallel if we dont change it's sensitivity list? in my code.. how can prc2 be executed in parallel with process 1 If I didnt change the sensitivity list of it?
And another question.. is the line Q <= outd placement has importance? doest it change anything If I put it in the last line?
The description has taken from http://www.vhdl.renerta.com:
The sensitivity list is a compact way of specifying the set of signals, events on which may resume a process. A sensitivity list is specified right after the keyword process
The sensitivity list is equivalent to the wait on statement, which is the last statement of the process statement section
So your prc2 process will wait for changing of outd or RESETN and then will start to work as many times as signals in sensitivity list will changed.
Parallelism means that all process executed in parallel. One process doesn't wait for the end of another process, but works in parallel with it. In your case: the process prc1 will work each CLK or RESETN changing and the process prc2 will work when outd or RESETN changing.
To see the picture how it works you can write (or take any example) some module and testbench for it and look at waveform how processes work.
In addition to Roman's answer, I thought I'd answer your second question:
Is the placement of the line Q <= outd important? Does it change anything if I put it in the last line?
No and no.
As long as the line Q <= outd is not inside of a process, it is purely combinational. Thus, it doesn't matter where you put it in the code - it will be synthesized into the same hardware.
I came across two styles of process statements in VHDL.
process(clk)
begin
if rising_edge(clk)
...do something...
The other one is
process
begin
wait until rising_edge(clk)
...do something...
What are the pros and cons of each method?
Assuming the ... part of the second example does not have any wait statement, the two forms are semantically equivalent.
They will behave identically in simulation.
However, the first form is the recommended style for synthesis and will be deemed more readable by many.
Both forms are equivalent for synthesis in Vivado. The second wait form can be considered more compact as it "saves" an indentation level.
I generally agree with wap26's answer, with one addition.
I sometimes like to write a top-level architecture which acts as both the synthesisable top-level design and as the simulation test bench - typically for smaller designs.
Within such designs, you often drive the clock yourself during simulation, using wait statements, like:
if IS_SIMULATION then
wait for SIM_CLK_PERIOD / 2;
clk <= '0';
wait for SIM_CLK_PERIOD / 2;
clk <= '1';
else
clk <= external_clk;
end if;
The issue now is that you still need to handle the initial/reset state for the synthesisable section. This requires an assertion that the entity's signals have been initialised before the first (or some) rising edge of the external clock.
But we can't use if rising_edge(external_clk), because this process cannot have a sensitivity list (it uses wait statements in the simulation section). Therefore, in this case, using wait until rising_edge(external_clk) is required.
A if [conditions].... :
continuously execute the acts. The process will go on regardless of whether the conditions is met or not, only skipping the statement in the "if" when not meeting the conditions, and will execute the afterwards statements, in all weather!
B wait until [conditions]... :
only execute the acts at the conditions met! If the conditions are not met, the process will hang (or be blocked/suspended) here, and can't go on, even there have many statements afterwards.
In most cases, expecially in simulations, B is better than A. In some cases, only B can be done, rather than A.
Here's an example:
A
for i in 0 to 10 loop;
if rising_edge(clk) then
..acts..
end if;
end loop;
B
for i in 0 to 10 loop;
wait until rising_edge(clk);
...acts....
end loop;
A can't work, but B can!
Essentially, the second type is only useful in simulation. The wait statement requires time to flow between separate statements within a process, which is unlike the hardware synthesis process. It will typically appear within a simulation stimulus or diagnostic process.
In the first form, the process is triggered by the clock event and runs in a single step, representing synchronous logic.
If I have variables in my VHDL, will it be synthesizable (using softwares like RTL compiler)?
I doubt it because it changes its values instantly. I am using std_logic now.
As Brian Drummond writes, you can synthesize processes with variables and the
netlist result depends on whether the variable is read before or after assign.
If the variable is read before assign, then the variable transfers a value
from a previous time to the current time, and storage (typically flip-flop
or latch) is required to keep the state over time. Example code, where both
sig and var will result in flip-flops, since the variable var is read
before assign:
process (clk_i) is
variable var : std_logic;
begin
if rising_edge(clk_i) then
sig <= var;
var := arg;
end if;
end process;
If the variable is read after assign, then any previous variable value is
unused, so no storage is implemented in the netlist. The variable is thereby
only used to make an intermediate value, for example to ease code writing.
Example code, where only sig will result in flip-flop, since the variable
var is read after assign:
process (clk_i) is
variable var : std_logic;
begin
if rising_edge(clk_i) then
var := arg;
sig <= var;
end if;
end process;
In more complex (realistic) code, it may be difficult to ensure that variables
are only read after assign, thus without inferring unintended storage
(flip-flop or latch). A useful coding style is to assign all variables with
unknown ('X') at the start of the code. If a variable is then read before
assign, the bug is typically revealed early on in simulation and debugging.
Example code:
process (clk_i) is
variable var : std_logic;
begin
if rising_edge(clk_i) then
var := `X`; -- Ensure variable assign before any use to avoid storage
var := arg;
sig <= var;
end if;
end process;
Note that in simulation it typically requires additional effort to include
variables in waveforms; ModelSim for example shows process variables in a
separate "Locals" view. If variables that hold state are left out of the
waveform then debugging is much more difficult, since the waveform then
shows only half the story.
A practical coding style is therefore to use variables only for intermediate
values in a process, thus always doing read after assign.
Yes, variables used inside a VHDL process are synthesisable.
Considering this code:
architecture synth of my_entity is
signal a : std_logic;
begin
a <= c and d;
b <= a and c;
end synth;
Is the second line going to respect that a changed in the other process or are all signals only at the end of architecture assigned?
Careful with your terminology. When you say a changed in the other "process", that has a specific meaning in VHDL (process is a keyword in VHDL), and your code does not have any processes.
Synthesizers will treat your code as:
a <= c and d;
b <= (c and d) and c;
Simulators will typically assign a in a first pass, then assign b on a second pass one 'delta' later. A delta is an infinitesimal time delay that takes place at the same simulation time as the initial assignment.
Note this is a gross generalization of what really happens...if you want full details, read up on the documentation provided with your tool chain.
Is the second line going to respect that a changed in the other
process or are all signals only at the end of architecture assigned?
It sounds like you are thinking of signal behaviour within a single process when you say this. In that context, the signals are not updated until the end of the process, so the b update will use the "old" value of a
However, signal assignments not inside a process statement are executed continuously, there is nothing to "trigger" an architecture to "run". Or alternatively, they are all individual separate implied processes (as you have commented), with a sensitivity list implied by everything on the "right-hand-side".
In your particular case, the b assignment will use the new value of a, and the assignment will happen one delta-cycle after the a assignment.
For a readable description of how simulation time works in VHDL, see Jan Decaluwe's page here:
http://www.sigasi.com/content/vhdls-crown-jewel
And also this thread might be instructive:
https://groups.google.com/group/comp.lang.vhdl/browse_thread/thread/e47295730b0c3de4/d5bd4532349aadf0?hl=en&ie=UTF-8&q=vhdl+concurrent+assignment#d5bd4532349aadf0