1
\$\begingroup\$

I am new to VHDL and I try to find all places where I can replace if/else statements with cases of inlined OR/AND operations to get more things executed in parallel instead of sequence.

Now I have the following statement:

if (val = 0) then 
 returnVal := 0;
end if;
if (val > 0)
then
 returnVal := 1;
end if;
returnVal := 2;
return returnVal;

As I can see, this will be executed sequentially with a depth of 3.

Is this exact statement possible to do in a more efficient manner?

NOTE: The values 0, 1 and 2 are not important - they must just be different, e.g. could be -123, 234 and 432 if that makes it easier for optimizing

Thanks

UPDATE: As pointed out, this logic was broken. The intended logic is:

if (val = 0) then 
 return 0;
end if;
if (val > 0)
then
 return 1:
end if;
return 2;

UPDATE 2: I am programming VHDL and deploying to an FPGA which is important as it differs from microcontrollers in the terms of parallelism.

UPDATE 3: I realise, that I may not have been explicit about my exact question, so my apoligies. What I mean is: The three statements are mutually exclusive: Than value is either < 0, = 0 or> 0. And even though a case switch cant be used here, I was wondering if anyone had another input to how to improve performance of this.

asked Apr 27, 2020 at 20:19
\$\endgroup\$
7
  • 3
    \$\begingroup\$ I'm not VHDL expert, but it appears as if the example code always returns 2. Therefore there is probably no hardware associated with the if statements and nothing to optimize. \$\endgroup\$ Commented Apr 27, 2020 at 20:32
  • 3
    \$\begingroup\$ Since VHDL is a hardware description language, no instructions are executed sequentially (unless you mean compilation and simulation, instead of synthesis). Hence, the coding style is not as relevant as the synthesis result you get. That will probably be equivalent, regardless of the style. It seems that you want to describe a comparator and a mux. I suggest to focus on that. \$\endgroup\$ Commented Apr 27, 2020 at 20:33
  • \$\begingroup\$ No need. Write sequential code - even loops in a process - and synth will unroll it all to execute in parallel anyway (but preserving the same semantics as your sequential version). (And as Photon points out, if you don't move the default assignment to the top, this optimises to "return 2". \$\endgroup\$ Commented Apr 27, 2020 at 20:56
  • \$\begingroup\$ return (2 when val < 0 else 1 when val > 0 else 0); -- vhdl-2008 syntax but the implementation will likely be identical. \$\endgroup\$ Commented Apr 27, 2020 at 21:06
  • \$\begingroup\$ Brian Drummond: I will go test that out right away! Brb \$\endgroup\$ Commented Apr 27, 2020 at 21:16

2 Answers 2

3
\$\begingroup\$

No need.

Write sequential code - and synth will unroll it all to execute in parallel anyway (but preserving the same semantics as your sequential version).

Some more detail here: https://stackoverflow.com/questions/13954193/is-process-in-vhdl-reentrant/13956532#13956532

What you are defining with your sequential code is the semantics not the implementation.

That is : focus on the semantics of the problem - the highest level abstraction that accurately encapsulates your meaning. That's difficult enough to get right as the question demonstrates! In that context, functions and procedures are good practice, raising the level of abstraction.

Now consider what happens to something even more sequential like a FOR loop in a process. Synthesis will unroll it so that each loop iteration runs in parallel anyway. Same happens here.

For completeness, in VHDL-2008, conditional and case expressions (when/else and with/select) are available within processes, so a shorter expression of your example is possible:

return (2 when val < 0 else 1 when val > 0 else 0); -- vhdl-2008 syntax 

but the implementation will likely be identical.

As would a CASE statement based implementation of the identical algorithm (at least, where the expressions are mutually exclusive as here. An IF statement prioritises when expressions overlap : that would be a compile error in a CASE).

Both the implementation and the speed are likely to be identical. It's a different expression of exactly the same algorithm, and synth tools are brutal at reorganising and optimising; brutally honest in preserving semantics accurately, and brutally ruthless in exploiting mistakes to optimise away redundant hardware ( cough return 2;)

Which boils down to : TEST it first in simulation; THEN synthesise.

Given big enough, complex enough examples, unrolling a whole sequential algorithm and attempting to execute it in a single clock cycle is undesirable and consumes too much FPGA. But that's a story for another day; learn about pipelining and state machines before tackling that.

answered Apr 27, 2020 at 21:23
\$\endgroup\$
6
  • \$\begingroup\$ According to this article, it does matter if you use a case over an if/else construct, for instance. So I dont understand the suqestion to "just write thing sequentially as if it was for a CPU and the compiler will sort everything out for you): electronics.stackexchange.com/questions/73387/… \$\endgroup\$ Commented Apr 27, 2020 at 21:29
  • \$\begingroup\$ Good question. Same situation here as in software. Look at that example. What happens if both bool_expr_1 and _2 are true? the IF prioritises the first one - same as would happen in software. CASE (in VHDL) will report errors at compile time if the case arms aren't mutually exclusive. \$\endgroup\$ Commented Apr 27, 2020 at 21:37
  • \$\begingroup\$ Well maybe I was not cleary in my post. The three cases ar emutually exclusive. Eith val is 0, it is above or it is below. So the priority may be left out, if possible that is. And that is my question :) \$\endgroup\$ Commented Apr 27, 2020 at 21:38
  • \$\begingroup\$ Absent priority (i.e. with mutually exclusive expressions), IF and CASE are equivalent in your linked example ... and would be, in your question. \$\endgroup\$ Commented Apr 27, 2020 at 21:40
  • 2
    \$\begingroup\$ No; it's likely to be identical. It's a different expression of exactly the same algorithm, and synth tools are brutal at reorganising and optimising; brutally honest in preserving semantics accurately, and brutally ruthless in exploiting mistakes to optimise away redundant hardware ( cough return 2;) Which boils down to : TEST it first in simulation; THEN synthesise. \$\endgroup\$ Commented Apr 27, 2020 at 21:45
1
\$\begingroup\$

If what you had in mind was something like dedicating a process to each condition evaluation and its associated value assignment then no, you get multi-source errors if you try and do that here.

Unlike software where one thing happens at a time, in a VHDL everything you put it exists all the time and is running all the time. If you have multiple parallel circuits existing all the time all trying to assign a different value to the same thing it doesn't know which one to pick. This is what a multi-source or multi-driver error is.


You also look like you are using procedures with variables which is a little too closely tied to software programming which runs sequentially. Variables and procedures have their place but generally you should be using processes with signals instead (variables can also be used inside a process too but use them sparingly. You should generally use signals).


You said you are new so I will throw in some background.

  • Everything inside a process appears to execute sequentially. That means you can use sequential statements like if/else statements in a process, but not outside of one.
  • Processes run in parallel with each other
  • Note that in addition to if/else, there are also case statements which also run in a process.

  • Outside of a process there are when/else and with/select statements. Note they all have their limitations (i.e. can't do comparisons other than direct matches, can't assign different variables under different conditions, can only assign a single variable and not take other
    actions or a group of actions for a condition, etc).

  • Variables are assigned with := and can only be used in a process. That is, they can only be used seqwuentially. Variables update instantly and behave the way you would expect them to if you are coming from software programming.
  • Signals are assigned with <= and can be used both inside a process and outside a process. That is, they can be used both sequentially and parallel. The biggest thing about signals is that THEY DO NOT UPDATE INSTANTLY IN A PROCESS like a variable does. They update at the end of the process and their new value appears the next time the process runs.

    This means if you assign a signal in a process, and then read from the signal in a process the read will still return the value it had when the process was entered. Only after the process ends and the next time the process is run will the signal read the value you assigned to it. The signal's value only updates at the end of the clock cycle when the process finishes.

  • If a signal that is not synchronous to the FPGA clock is entering the FPGA, it cannot be guaranteed to properly match the clock edges and metastability can result. You deal with this by passing the signal through a chain of two flip-flops before using it with anything that has a clock in the FPGA (i.e. a process that triggers off the clock).
answered Apr 27, 2020 at 20:28
\$\endgroup\$
15
  • \$\begingroup\$ @BrianDrummond Unless I misunderstood, the OP is asking how he can split up his three conditional, sequential assignments so that all three can run in parallel with each other. That means breaking each one out into its own separate process which creates a multi-source error since each process is trying to assign a value to the same thing. \$\endgroup\$ Commented Apr 27, 2020 at 20:56
  • \$\begingroup\$ "Everything inside a process runs sequentially" this might be a little misleading as e.g. sequential if statements are also executed in parallel. \$\endgroup\$ Commented Apr 27, 2020 at 20:56
  • \$\begingroup\$ @po.pe Hmmmmm. Yes I sort of see what you mean due to the way signals update, but I'm not sure if trying to clarify that will just muddy the waters for the OP at this point. \$\endgroup\$ Commented Apr 27, 2020 at 20:58
  • \$\begingroup\$ Also, I don't think the OP understands that there is nothing he can just replace is if/else statements with to make things run in parallel without changing the fact that its under a function or procedure. \$\endgroup\$ Commented Apr 27, 2020 at 20:59
  • \$\begingroup\$ Consider what happens to ... something even more sequential like a FOR loop in a process. Synth will unroll it so that each loop iteration runs in parallel anyway. Same happens here. What you are defining with your sequential code is the semantics not the implementation. \$\endgroup\$ Commented Apr 27, 2020 at 21:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.