1

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.

Stephan Møller
  • 211
  • 1
  • 9
  • 3
    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. – The Photon Apr 27 '20 at 20:32
  • 3
    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. – U.Martinez-Corral Apr 27 '20 at 20:33
  • 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". –  Apr 27 '20 at 20:56
  • `return (2 when val < 0 else 1 when val > 0 else 0); -- vhdl-2008 syntax` but the implementation will likely be identical. –  Apr 27 '20 at 21:06
  • Brian Drummond: I will go test that out right away! Brb – Stephan Møller Apr 27 '20 at 21:16
  • Brian Drummond: What is the non-2008 equivalent for the code? – Stephan Møller Apr 27 '20 at 21:17
  • Your second version or any accurate paraphrase of it. Note, I have amalgamated my comments into a brief answer, they were getting scattered and lost. –  Apr 27 '20 at 21:28

2 Answers2

3

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.

  • 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): https://electronics.stackexchange.com/questions/73387/difference-between-if-else-and-case-statement-in-vhdl – Stephan Møller Apr 27 '20 at 21:29
  • 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. –  Apr 27 '20 at 21:37
  • 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 :) – Stephan Møller Apr 27 '20 at 21:38
  • Absent priority (i.e. with mutually exclusive expressions), IF and CASE are equivalent in your linked example ... and would be, in your question. –  Apr 27 '20 at 21:40
  • But the delay from input to output is shorter in the case-example than in the if/else-example in the link, right? – Stephan Møller Apr 27 '20 at 21:43
  • 2
    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. –  Apr 27 '20 at 21:45
1

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).
DKNguyen
  • 54,733
  • 4
  • 67
  • 153
  • @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. – DKNguyen Apr 27 '20 at 20:56
  • "Everything inside a process runs sequentially" this might be a little misleading as e.g. sequential if statements are also executed in parallel. – po.pe Apr 27 '20 at 20:56
  • @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. – DKNguyen Apr 27 '20 at 20:58
  • 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. – DKNguyen Apr 27 '20 at 20:59
  • 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. –  Apr 27 '20 at 21:00
  • @DKNguyen Yes, I'd just be careful with the word sequential when talking about VHDL because most people might come from an actually sequential programming language having a hard time to understand the boundaries a HDL has. – po.pe Apr 27 '20 at 21:00
  • @BrianDrummond Do either of you have alternative wording that won't make things more confusing for the OP? – DKNguyen Apr 27 '20 at 21:01
  • @po.pe Do either of you have alternative wording that won't make things more confusing for the OP? – DKNguyen Apr 27 '20 at 21:01
  • Some people have apparently found this useful : https://stackoverflow.com/questions/13954193/is-process-in-vhdl-reentrant/13956532#13956532 –  Apr 27 '20 at 21:02
  • @DKNquyen: I am programming VHDL on an FPGA - so no, not everything is sequential. Sorry if I didnt point this out in the original post. – Stephan Møller Apr 27 '20 at 21:05
  • @StephanRyer Sorry, I did not understand that what you are trying to say with that sentence. It was rather incoherent. Please rephrase. – DKNguyen Apr 27 '20 at 21:06
  • Okay I will try :) you wrote: "Everything inside a process runs sequentially" - which is true for things run on a CPU, single threaded. But with FPGAs, not everything runs sequentially. – Stephan Møller Apr 27 '20 at 21:09
  • @StephanRyer Not everything runs sequentially on an FPGA. But many things in a process appear to run sequentially. Your code seems to be using procedures and variables. Variables update instantly with the latest one taking precedence so that is pretty sequential. – DKNguyen Apr 27 '20 at 21:12
  • DKNquyen - yes the if/else going on, even if my edited version without the bug, runs in sequence. But I was qurious to know if anyone could do the same operation more optimized. Thanks for commenting btw. – Stephan Møller Apr 27 '20 at 21:13
  • @StephanRyer Judging from the way you worded the question it sounded like you wanted to have all three value assignments split up, be evaluated simultaneously, and be assigned simultaneously (which technically should only be one assignment occurring since the conditions are mutually exclusive). This would involve sticking each one in its own process which would result in a multi-souce error. Not sure if that's what you meant, but that was my interpretation of your question. – DKNguyen Apr 27 '20 at 21:15