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
Related
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.
Below code is not compiling. How can I modify it to make it works? Thank you.
case S is
when '0' =>
U1: hi port map (x,y,z);
when others =>
U2: hey port map (x,y,z);
end case;
Without the rest of the code there will be some guessing, but you have probably used case outside a process, thus the "illegal concurrent statement" message, since case is a statement that can only be used in a process. However, component instantiation with port map (x,y,z) is a concurrent statement, thus can only be used outside a process.
VHDL is not a programming language, but a Hardware Description Language (the HDL part of VHDL), thus when writing VHDL code, think of it like describing a electrical circuit, and in this the parts are fixed, but the signal values can vary over time.
So, instantiate the components outside a process with port map (x,y,z) and control the signal values from processes, other components, ports, etc.
As you are instantiating components, you are not within a process, hence you cannot use sequential programming constructs.
You can however use if ... generate which selectively generates hardware, on the value of S as long as S is a generic or constant. (If you could input a signal to if ... generate, that would require hardware to appear or disappear when the signal value changed ... not gonna happen!)
Note that if ... generate has no "elsif" or "else" options, so you have to express your example in a slightly more awkward fashion:
gen_S_0 : if S = '0' generate
U1: hi port map (x,y,z);
end generate;
gen_S_others: if S /= '0' generate
U2: hey port map (x,y,z);
end generate;
A lot of the FSMs I see in VHDL work by setting a variable "next_state" in the FSM logic and then assign this seperately to the state variable outside of the process.
If there anything wrong with simply writing "state <= state_five;" to set the next state instead?
I'm presuming there is a reason that so many people use a separate next state variable instead of directly assigning to the state as I see it all the time, but as far as I can tell there is no difference except that it makes the code longer and more complicated looking.
Have I missed something? Or is it just a question of style? And if so why is that style better, it seems unnecessary to me.
"Is there anything wrong with simply writing state <= state_five;?"
Nothing whatsoever - PROVIDED the state assignment is done in a clocked process.
This leads to the neat simple reliable "single process state machine" style, instead of the unreliable (because it's easy to get the sensitivity lists wrong) two-process style that is taught in WAY too many textbooks and online tutorials.
Search for "single process state machine" and you should be able to find good example material and further discussion.
Historical note : there may have been some synthesis tools in the previous century that had problems with the single-process style; but that's no reason to avoid it now.
The reason why some people always write two-process state machines (that is, one synchronous process and one concurrent process) is probably mostly because they learned to do it that way in school, like others have said.
However, in some cases this coding style can actually be better than having a single synchronous process. In short it allows you to mix synchronous and concurrent assignments in the same context. Consider the following two pieces of code, both accomplishing the same thing:
Two-process state machine:
process (clk)
begin
if rising_edge(clk) then
state <= state_next;
end if;
end process;
process (all)
begin
state_next <= state;
case state is
when s_idle =>
if req_i = '1' then
fifo_read <= '1'; -- Concurrent assignment
state_next <= s_check_data; -- "Synchronous" assignment
end if;
when s_check_data =>
if fifo_out = x"1234" then
(...)
end if;
(...)
end case;
end process;
One-process state machine:
process (clk)
begin
if rising_edge(clk) then
case state is
when s_idle =>
if req_i = '1' then
fifo_read <= '1';
state <= s_wait_for_data;
end if;
when s_wait_for_data =>
state <= s_check_data;
when s_check_data =>
-- Data word from FIFO now available.
if fifo_out = x"1234" then
(...)
end if;
(...)
end case;
end if;
end process;
Notice the extra state in the second example. Because there is no way to make concurrent assignments in synchronous processes in VHDL (I wish there was!), a register will be added to the fifo_read signal, delaying it by one cycle. While this example is simple enough, always sticking to one-process state machines can sometimes cause the code to become quite confusing and hard to follow for this reason. It can also cause your state machine to spend more resources in hardware and even make the code longer. Neither style is always the right choice, but I usually prefer the one-process variant.
Or even use a variable:
state := state_five
Using a variable to store the state means that it remains completely local to the process and doesn't pollute the namespace of the whole architecture.
It also means that if you are in the habit of using printf (sorry report) to track the progress of state machines when debugging (which is sometimes preferable to a waveform viewer), you can report the intended next state at the end of the state machine process, which can be handy.
Added:
As noted in the comments, the variable assignment occurs "instantly" (to be clear - this doesn't cause the case statement to immediately switch to the next state though!)
This effect can be used to advantage (occasionally) if you need an output a cycle early - by assigning to said signal based on the next state at the end of the process. If I end up needing to do that I tend to have an explicit next_state variable which I use for everything except the case statement and the state := next_state; (which is right at the end of the clocked process). It demonstrates to the code reviewers that you intended to do it this way!
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.