Difference between process and "vanilla" VHDL - vhdl

I'm practicing VHDL, and I have a fundamental question about "simple" statements which do not require a process.
I would like to know the difference between
c <= a and b;
Where the statement is not inside a process, just written after the architecture begin, and
process(a,b)
begin
c <= a and b;
end process;
Will these results produce the same thing?
Ty :)

Yes, the two descriptions are equivalent.
The concurrent signal assignment c <= a and b is evaluated at each update of any of the argument (a or b), and the process will also evaluate each time any of the arguments in the sensitivity list is updated (a or b).
In the simple example it not required to use a process, but for more complex expressions, the process has the advantage that control structures like if and for can be used, which is not directly possible in a concurrent signal assignment. Also, for sequential logic a process is required.

You can think of any VHDL one liner as an implied process with the arguments on the RHS of <= in the sensitivity list.
This is why both of the code snippets you wrote are practically equivalent.

Related

VHDL block and guarded input - what does this code do?

I have the following from a beginner's VHDL tutorial:
rising_edge: block(clk’event and clk = ‘1’)
begin
result <= guarded input or force after 10ns;
end block rising_edge
The explanatory text is
"Essentially I have a block called rising_edge, and it's a block with a guard condition which does the following, it checks that we have an event on the clock, and that the clock is equal to one, so we're effectively looking for the so called rising_edge. We're looking for the event where the clock goes from 0 to 1, and if it does, then we can conditionally assign the results, so you'll see that the result variable here says that it is a guarded input or force after 10 ns might seem a bit confusing, but consider it without the guarded keyword. All we're doing is we're assigning the result of the evaluation of input or force, and we're doing it in a guarded setup. So, in this case, the assignment of the signal result is only executed if the guard signal is actually true, and in our example it means that the assignment of the expression, which is input or force, will only happen on the rising_edge of the clock because that's on guard condition."
Now I've read this over and over and searched on the net but have come up blanks as to what this is actually doing. Can someone please gently explain its purpose?
A block is essentially a grouping of concurrent statements. In terms of practical usage, it is very similar to a process, only it has a limited scope wich allows component-style signal mapping(with port and port map). It can be used to improve readability(see this question) and really not much else. Blocks are resonably rarely used and frequently not synthesis supported(see here). To my (limited) knowledge, the use of blocks has no other advantage than readability.
Because your block statement contains a guard condition(clk'event and clk='1' is the guard condition here), it is a guarded block. Inside a guarded block, signals that are declared guarded (like in your example) will only be assigned if the guard condition evaluates to true
The entire statement that has been guarded(i.e. in your case input or force after 10ns) will only be executed when the guard condition evaluates to true, i.e. on the rising edge of clk. Thus, for all intents and purposes this block has the same behaviour as
process(clk)
begin
if clk'event and clk = '1' then
result <= input or force after 10ns;
end if;
end process;
I will say though, this is a terrible example. For one thing, as others have stated, the usage of block is very rare and they are generally only used in quite advanced designs. The usage of clk'event and clk = '1' has been discouraged since 1993(see here). It should also be mentioned again that the usage of rising_edge as a label is a terrible idea, as is the use of force for a signal name(in VHDL 2008, force is a reserved keyword that can be used to force a signal to a value).
Working from the idea that this is supposed to be a beginners tutorial, and with the lack of any explanation as to why such an unusual style has been used, a much more conventional implementation would be:
process : (clk)
begin
if (rising_edge(clk)) then
result <= input or force after 10 ns;
end if;
end process;
A couple of points to note:
This assumes that input and force are either signals, or inputs to the entity.
It is unusual to model signal assignment delays if your code is going to be implemented in a real hardware device.
The code in your question uses after 10ns;, which is not valid; you need a space between the value and the units (as in my code).
The code in your question uses rising_edge as an identifier, when this is actually already defined as a function, assuming you are including standard IEEE libraries newer than I believe VHDL93.
The code in your question uses force as a signal name, when this is also a reserved language keyword since VHDL2008.
My advice to you is to find a different tutorial. The quote you posted is not clearly written, and the code you posted appears to be sending you down a strange path. All I can think is that the tutorial is in fact very, very old.

how to approach string/pattern checking in VHDL?

I have a problem - that I think I can solve with regular 'c' like operations
but I was wondering if there is a better way, something like 'regexp' for VHDL
the problem is that I have a string/collection of bits, "101010101010101" and I want to look for the pattern (with no overlapping) "1010" inside
what are my best options for attacking this problem?
edit : I'd like to mention that the input is parralel, all the bits at once and not in serial
it is still possible to implement this as an FSM - but it there a more efficient way?
If all you want to do is find a pattern within a vector, then you can just iterate over it. Assuming "downto" vectors:
process (vec, what_to_find)
begin
found <= 0;
for start in vec'high downto vec'low+what_to_find'length loop
if vec(start downto start - what_to_find'length) = what_to_find then
found <= start;
end if;
end for;
end process;
Depending on the sizes of your input and search vectors compared to the target device, this will be a reasonable or unreasonable amount of logic!
VHDL does not have builtin regex support, however what you are planning to solve is a pattern matching problem. Basically what you do is build a statemachine (which is what happens when evaluating a regular expression) and use it to match the input. The most simple approach is to check whether the first n bit match your pattern, then shift and continue. Longer, or more interesting patterns, e.g., incorporating quantifiers, matching groups etc. require a bit more.
There are numerous approaches to do that (try google vhdl pattern matching, it is used,e.g., for network traffic analysis), I even found one that would automatically generate the vhdl. I would guess, however, that a specialized hand-made version for your problem would be rather more efficient.
The there is no generally applicable VHDL solution for that kind of pattern
matching, but the solution should be driven by the requirements, since size and
speed can vary greatly for that kind of design.
So, if timing allows for ample time to do an all parallel compare and filtering
of overlapping patterns, and there is plenty of hardware to implement that,
then you can do a parallel compare.
For an all parallel implementation without FSM and clock, then you can make a
function that takes the pattern and collection, and returns a match indication
std_logic_vector with '1' for start of each match.
The function can then be used in concurrent assign with:
match <= pattern_search_collection(pattern, collection);
The function can be implemented with something along the lines of:
function pattern_search_collection(pat : std_logic_vector;
col : std_logic_vector) return std_logic_vector is
...
begin
-- Code for matching with overlap using loop over all possible positions
-- Code for filtering out overlaps using loop over all result bits
return result;
end function;

VHDL library for basic elements

I am starting at VHDL and while trying to implement a circuit I found that I need basic elements like leading one/zero detectors or leading one/zero counters. Since I consider these basic I would like to know if there is a library to include.
If I have to put together my own implementations is there a collection where one can copy from or do I need to reinvent the wheel?
(I can google them one by one and find implementations in forums, however some of them seem quite bad/implemented not general enough (i.e. this multiplexer)).
One reason why the approach you suggest (a library of simple re-usable elements) doesn't catch on : you are often better off without them.
The example multiplexer you linked to illustrates the point quite well:
ENTITY multiplexer IS
PORT (
a, b, c, d, e, f, g, h : IN STD_LOGIC;
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
y : OUT STD_LOGIC
);
END ENTITY multiplexer;
given slightly better design, using the type system you could write (perhaps in a re-usable package)
subtype sel_type is natural range 0 to 7;
and then in your design, given the signal declarations
signal sel_inputs : std_logic_vector(sel_type);
signal sel : sel_type;
signal y : std_logic;
you could simply write
sel_inputs <= a & b & c & d & e & f & g & h;
y <= sel_inputs(sel);
with much less fuss than actually instantiating the multiplexer component.
Leading zero detectors look harder at first glance : they are generally implemented as clocked processes, or as part of a larger clocked process.
Recent trends in VHDL are moving towards a semi-behavioural style of synthesisable VHDL, where quite a lot is written in a sequential style within a single clocked process. This is best seen in the "single process state machine"; smaller, easier to understand and definitely more reliable * than the "two process" style still commonly taught.
(* unless your tools support the "process(all)" sensitivity list of VHDL-2008 for the combinational process.)
Within a clocked process (i.e. assume the following is inside if rising_edge(clk) then simple tasks like counting the leading zeroes in an array can be expressed using for loops; for example:
for i in sel_type loop
if sel_inputs(i) = '1' then
zero_count <= sel_type'high - i;
end if;
end loop;
The last assignment will win; if h = '1' the count will be 0, otherwise if g = '1' the count will be 1, and so on.
Now it's not a one-liner unless you write a procedure for it (also synthesisable with most tools!) but compare it with the size of an entity instantiation (and interconnections).
Of course a library of procedures and functions can be useful; and (for less trivial tasks) the same is true for entities also, but in my opinion, making them general enough to be useful to all, without making them heavyweight, would be quite an achievement.
some IDEs come directly with an example library. e.g. Xilinx ISE has the "language Templates" section with basic synthesis constructs, coding examples,...

VHDL Structural vs Behavioral

This is a question for those who have a good understanding of VHDL. I'm a newbie but so far I have been generating VHDL using a behavioral description. For me it is much easier to think about as it is similar to writing software. I am aware that a possible downfall is that behavioral 'executes' sequentially while structural executes concurrently within the design component/process..
So I'm just curious, if I have an architecture that uses a process for say an 8-bit shift register (SISO) and I want to create 4 instances of these (4x8-bit shift registers) would I create a component and 4 instances of the process?
Or would I generate 4 processes (executing in parallel to one another) and just call each process by a different name?
Also, just a general question to get a consensus of what good practices people use out there, which do you prefer: structural vs. behavioral?? When would be a good time to choose one over the other? I'm guessing their could be some benefits with 'faster' execution using components that allow internal concurrency vs. sequential execution in processes.. It sure does seem to me though that one could reduce the design time with behavioral designs..
Thanks!
~doddy
For my money, the role of structural HDL nowadays is restricted to interconnecting tested working behavioral blocks (or connecting untested ones to their testbenches!) - I would agree with you about the superiority of behavioural VHDL in terms of design creation and test time.
I would also agree that writing a behavioural process is in some ways similar to writing software (over the screams of some that it isn't)
HOWEVER
do not fall into the trap of equating behavioural with sequential or slow!
Given your shift register, say
type reg_type is array(7 downto 0) of bit;
signal s_in, s_out : bit;
process(clk) is
variable reg : reg_type;
begin
if rising_edge(clk) then
s_out <= reg(7);
reg := reg(6 downto 0) & s_in;
end if;
end;
I can trivially parallelise it as follows:
signal p_in, p_out : array(1 to 4) of bit;
process(clk) is
variable reg : array(1 to 4) of reg_type;
begin
if rising_edge(clk) then
for i in reg'range loop
p_out(i) <= reg(i)(7);
reg(i) := reg(i)(6 downto 0) & p_in(i);
end loop;
end if;
end;
(And yes there are simpler ways to write this!)
It is important to note that the loop does not take any longer to run : it just generates more hardware (in software terms, it is unrolled completely). Each iteration is completely independent of the others; if they weren't, things would be more complex.
Don't worry about the academic differences between structural and behavioral.
Worry about the difference between signal assignment scheduling and variable assignment scheduling in a process (learn what delta cycles and postponed assignment are - this is one of the key diffs from software, and arises because software only has variables, not VHDL's signals). That will explain why I implemented the pipeline upside down here (output first) - because I used a variable.
Worry about why so many people teach the idiotic 2-process state machine when the 1-process SM is simpler and safer.
Find and understand Mike Treseler's pages about single-process models (I hope they are still online)

how are process'es evaluated in practice

I have two process'es like below.
If say A=1, B=2 and C=3, what happens in simulation is on rising_edge B=1 and C=2, which is the result I want.
But am I guaranteed that this is also true when the design is implemented into an fpga?
What worries me is the delay associated with the extra if-state in process BC.
AB : process(A,clk)
begin
if rising_edge(clk) then
B <= A;
end if;
end process;
BC : process(B,clk)
begin
if rising_edge(clk) then
if (some_statement) then
C <= B;
end if;
end if;
end process;
B will take on the value of A (B=1) and C will take on the value of B (C=2).
However, I guess you are not actually describing what you want to. The problem is that you have A and B in the sensitivity list of the two processes. This means that in process AB, B will change each time A changes as well as when rising_edge(clk) is true. The same holds for process BC. Assuming you want to describe two registers in series, your code should be
AB : process(clk)
begin
if rising_edge(clk) then
B <= A;
end if;
end process;
BC : process(clk)
begin
if rising_edge(clk) then
if (some_statement) then
C <= B;
end if;
end if;
end process;
In this case, if you synthesize this code onto an FPGA, you will infer two registers. The register in process BC will use the registers enable signal which is connected to the boolean output of some_statement. If some_statement is already a single std_logic signal, this will not introduce additional delay but require some routing ressources, so you should still avoid using the enable signal where you don't really need it.
I think Simon answered the question perfectly, just to clarify the issue a bit further:
If initial values of your data is A=1, B=2 and C=3 then you will have the following during the simulation:
During start A=1, B=2 and C=3
After first rising edge of the clock A=1, B=1 and C=2
After second rising edge of the clock A=1, B=1 and C=1
After that, all signals will be 1.
The delay of the if statement must be more than 'clock period' - 'hold time necessary for internal registers' to cause any problem for you. Unless you have an extremely complicated logic with signals from multiple clock domains there, there is a little risk you get into problem with your code (the more accurate code is the one sent by Simon).
But am I guaranteed that this is also true when the design is implemented into an fpga?
The synthesizer ought to produce an FPGA which matches the behaviour of your VHDL in the simulator. If not, it's a bug!
Note that there are some "accepted" deviations - for example, if you miss a right-hand side signal off the sensitivity list, the synthesizer will assume you meant to put it there, but the simulator will assume you know what you're doing, and there will be a mismatch. Personally, I regard that behaviour as a bug, but it is too firmly entrenched by too many tools, I don't see it ever changing.
What worries me is the delay associated with the extra if-state in process BC.
Everything in a clocked process like yours "executes" within a single clock tick. If there is too much logic (for example, each nested if introduces a new layer of logic), you may find that a clock tick has to last longer than you desire.
(Not like software on most modern micros, where everything "takes as long as it takes", and is often unpredictable, depending on the state of caches, TLBs etc.)

Resources