VHDL Logical Operators and Signal Assignments for Combinational Logic

In this post, we discuss the VHDL logical operators, when-else statements , with-select statements and instantiation . These basic techniques allow us to model simple digital circuits.

In a previous post in this series, we looked at the way we use the VHDL entity, architecture and library keywords. These are important concepts which provide structure to our code and allow us to define the inputs and outputs of a component.

However, we can't do anything more than define inputs and outputs using this technique. In order to model digital circuits in VHDL, we need to take a closer look at the syntax of the language.

There are two main classes of digital circuit we can model in VHDL – combinational and sequential .

Combinational logic is the simplest of the two, consisting primarily of basic logic gates , such as ANDs, ORs and NOTs. When the circuit input changes, the output changes almost immediately (there is a small delay as signals propagate through the circuit).

Sequential circuits use a clock and require storage elements such as flip flops . As a result, changes in the output are synchronised to the circuit clock and are not immediate. We talk more specifically about modelling combinational logic in this post, whilst sequential logic is discussed in the next post.

Combinational Logic

The simplest elements to model in VHDL are the basic logic gates – AND, OR, NOR, NAND, NOT and XOR.

Each of these type of gates has a corresponding operator which implements their functionality. Collectively, these are known as logical operators in VHDL.

To demonstrate this concept, let us consider a simple two input AND gate such as that shown below.

The VHDL code shown below uses one of the logical operators to implement this basic circuit.

Although this code is simple, there are a couple of important concepts to consider. The first of these is the VHDL assignment operator (<=) which must be used for all signals. This is roughly equivalent to the = operator in most other programming languages.

In addition to signals, we can also define variables which we use inside of processes. In this case, we would have to use a different assignment operator (:=).

It is not important to understand variables in any detail to model combinational logic but we talk about them in the post on the VHDL process block .

The type of signal used is another important consideration. We talked about the most basic and common VHDL data types in a previous post.

As they represent some quantity or number, types such as real, time or integer are known as scalar types. We can't use the VHDL logical operators with these types and we most commonly use them with std_logic or std_logic_vectors.

Despite these considerations, this code example demonstrates how simple it is to model basic logic gates.

We can change the functionality of this circuit by replacing the AND operator with one of the other VHDL logical operators.

As an example, the VHDL code below models a three input XOR gate.

The NOT operator is slightly different to the other VHDL logical operators as it only has one input. The code snippet below shows the basic syntax for a NOT gate.

  • Mixing VHDL Logical Operators

Combinational logic circuits almost always feature more than one type of gate. As a result of this, VHDL allows us to mix logical operators in order to create models of more complex circuits.

To demonstrate this concept, let’s consider a circuit featuring an AND gate and an OR gate. The circuit diagram below shows this circuit.

The code below shows the implementation of this circuit using VHDL.

This code should be easy to understand as it makes use of the logical operators we have already talked about. However, it is important to use brackets when modelling circuits with multiple logic gates, as shown in the above example. Not only does this ensure that the design works as intended, it also makes the intention of the code easier to understand.

  • Reduction Functions

We can also use the logical operators on vector types in order to reduce them to a single bit. This is a useful feature as we can determine when all the bits in a vector are either 1 or 0.

We commonly do this for counters where we may want to know when the count reaches its maximum or minimum value.

The logical reduction functions were only introduced in VHDL-2008. Therefore, we can not use the logical operators to reduce vector types to a single bit when working with earlier standards.

The code snippet below shows the most common use cases for the VHDL reduction functions.

Mulitplexors in VHDL

In addition to logic gates, we often use multiplexors (mux for short) in combinational digital circuits. In VHDL, there are two different concurrent statements which we can use to model a mux.

The VHDL with select statement, also commonly referred to as selected signal assignment, is one of these constructs.

The other method we can use to concurrently model a mux is the VHDL when else statement.

In addition to this, we can also use a case statement to model a mux in VHDL . However, we talk about this in more detail in a later post as this method also requires us to have an understanding of the VHDL process block .

Let's look at the VHDL concurrent statements we can use to model a mux in more detail.

VHDL With Select Statement

When we use the with select statement in a VHDL design, we can assign different values to a signal based on the value of some other signal in our design.

The with select statement is probably the most intuitive way of modelling a mux in VHDL.

The code snippet below shows the basic syntax for the with select statement in VHDL.

When we use the VHDL with select statement, the <mux_out> field is assigned data based on the value of the <address> field.

When the <address> field is equal to <address1> then the <mux_out> signal is assigned to <a>, for example.

We use the the others clause at the end of the statement to capture instance when the address is a value other than those explicitly listed.

We can exclude the others clause if we explicitly list all of the possible input combinations.

  • With Select Mux Example

Let’s consider a simple four to one multiplexer to give a practical example of the with select statement. The output Q is set to one of the four inputs (A,B, C or D) depending on the value of the addr input signal.

The circuit diagram below shows this circuit.

This circuit is simple to implement using the VHDL with select statement, as shown in the code snippet below.

VHDL When Else Statements

We use the when statement in VHDL to assign different values to a signal based on boolean expressions .

In this case, we actually write a different expression for each of the values which could be assigned to a signal. When one of these conditions evaluates as true, the signal is assigned the value associated with this condition.

The code snippet below shows the basic syntax for the VHDL when else statement.

When we use the when else statement in VHDL, the boolean expression is written after the when keyword. If this condition evaluates as true, then the <mux_out> field is assigned to the value stated before the relevant when keyword.

For example, if the <address> field in the above example is equal to <address1> then the value of <a> is assigned to <mux_out>.

When this condition evaluates as false, the next condition in the sequence is evaluated.

We use the else keyword to separate the different conditions and assignments in our code.

The final else statement captures the instances when the address is a value other than those explicitly listed. We only use this if we haven't explicitly listed all possible combinations of the <address> field.

  • When Else Mux Example

Let’s consider the simple four to one multiplexer again in order to give a practical example of the when else statement in VHDL. The output Q is set to one of the four inputs (A,B, C or D) based on the value of the addr signal. This is exactly the same as the previous example we used for the with select statement.

The VHDL code shown below implements this circuit using the when else statement.

  • Comparison of Mux Modelling Techniques in VHDL

When we write VHDL code, the with select and when else statements perform the same function. In addition, we will get the same synthesis results from both statements in almost all cases.

In a purely technical sense, there is no major advantage to using one over the other. The choice of which one to use is often a purely stylistic choice.

When we use the with select statement, we can only use a single signal to determine which data will get assigned.

This is in contrast to the when else statements which can also include logical descriptors.

This means we can often write more succinct VHDL code by using the when else statement. This is especially true when we need to use a logic circuit to drive the address bits.

Let's consider the circuit shown below as an example.

To model this using a using a with select statement in VHDL, we would need to write code which specifically models the AND gate.

We must then include the output of this code in the with select statement which models the multiplexer.

The code snippet below shows this implementation.

Although this code would function as needed, using a when else statement would give us more succinct code. Whilst this will have no impact on the way the device works, it is good practice to write clear code. This help to make the design more maintainable for anyone who has to modify it in the future.

The VHDL code snippet below shows the same circuit implemented with a when else statement.

Instantiating Components in VHDL

Up until this point, we have shown how we can use the VHDL language to describe the behavior of circuits.

However, we can also connect a number of previously defined VHDL entity architecture pairs in order to build a more complex circuit.

This is similar to connecting electronic components in a physical circuit.

There are two methods we can use for this in VHDL – component instantiation and direct entity instantiation .

  • VHDL Component Instantiation

When using component instantiation in VHDL, we must define a component before it is used.

We can either do this before the main code, in the same way we would declare a signal, or in a separate package.

VHDL packages are similar to headers or libraries in other programming languages and we discuss these in a later post.

When writing VHDL, we declare a component using the syntax shown below. The component name and the ports must match the names in the original entity.

After declaring our component, we can instantiate it within an architecture using the syntax shown below. The <instance_name> must be unique for every instantiation within an architecture.

In VHDL, we use a port map to connect the ports of our component to signals in our architecture.

The signals which we use in our VHDL port map, such as <signal_name1> in the example above, must be declared before they can be used.

As VHDL is a strongly typed language, the signals we use in the port map must also match the type of the port they connect to.

When we write VHDL code, we may also wish to leave some ports unconnected.

For example, we may have a component which models the behaviour of a JK flip flop . However, we only need to use the inverted output in our design meaning. Therefore, we do not want to connect the non-inverted output to a signal in our architecture.

We can use the open keyword to indicate that we don't make a connection to one of the ports.

However, we can only use the open VHDL keyword for outputs.

If we attempt to leave inputs to our components open, our VHDL compiler will raise an error.

  • VHDL Direct Entity Instantiation

The second instantiation technique is known as direct entity instantiation.

Using this method we can directly connect the entity in a new design without declaring a component first.

The code snippet below shows how we use direct entity instantiation in VHDL.

As with the component instantiation technique, <instance_name> must be unique for each instantiation in an architecture.

There are two extra requirements for this type of instantiation. We must explicitly state the name of both the library and the architecture which we want to use. This is shown in the example above by the <library_name> and <architecture_name> labels.

Once the component is instantiated within a VHDL architecture, we use a port map to connect signals to the ports. We use the VHDL port map in the same way for both direct entity and component instantiation.

Which types can not be used with the VHDL logical operators?

Scalar types such as integer and real.

Write the code for a 4 input NAND gate

We can use two different types of statement to model multiplexors in VHDL, what are they?

The with select statement and the when else statement

Write the code for an 8 input multiplexor using both types of statement

Write the code to instantiate a two input AND component using both direct entity and component instantiation. Assume that the AND gate is compiled in the work library and the architecture is named rtl.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

Table of Contents

Sign up free for exclusive content.

Don't Miss Out

We are about to launch exclusive video content. Sign up to hear about it first.

assignment not working in vhdl

  • Product Manual
  • Release Notes
  • Screencasts
  • Tech Articles

Signal Assignments in VHDL: with/select, when/else and case

Sometimes, there is more than one way to do something in VHDL. OK, most of the time , you can do things in many ways in VHDL. Let’s look at the situation where you want to assign different values to a signal, based on the value of another signal.

With / Select

The most specific way to do this is with as selected signal assignment. Based on several possible values of a , you assign a value to b . No redundancy in the code here. The official name for this VHDL with/select assignment is the selected signal assignment .

When / Else Assignment

The construct of a conditional signal assignment is a little more general. For each option, you have to give a condition. This means that you could write any boolean expression as a condition, which give you more freedom than equality checking. While this construct would give you more freedom, there is a bit more redundancy too. We had to write the equality check ( a = ) on every line. If you use a signal with a long name, this will make your code bulkier. Also, the separator that’s used in the selected signal assignment was a comma. In the conditional signal assignment, you need the else keyword. More code for the same functionality. Official name for this VHDL when/else assignment is the conditional signal assignment

Combinational Process with Case Statement

The most generally usable construct is a process. Inside this process, you can write a case statement, or a cascade of if statements. There is even more redundancy here. You the skeleton code for a process (begin, end) and the sensitivity list. That’s not a big effort, but while I was drafting this, I had put b in the sensitivity list instead of a . Easy to make a small misstake. You also need to specify what happens in the other cases. Of course, you could do the same thing with a bunch of IF-statements, either consecutive or nested, but a case statement looks so much nicer.

While this last code snippet is the largest and perhaps most error-prone, it is probably also the most common. It uses two familiar and often-used constructs: the process and the case statements.

Hard to remember

The problem with the selected and conditional signal assignments is that there is no logic in their syntax. The meaning is almost identical, but the syntax is just different enough to throw you off. I know many engineers who permanenty have a copy of the Doulos Golden Reference Guide to VHDL lying on their desks. Which is good for Doulos, because their name gets mentioned all the time. But most people just memorize one way of getting the job done and stick with it.

  • VHDL Pragmas (blog post)
  • Records in VHDL: Initialization and Constraining unconstrained fields (blog post)
  • Finite State Machine (FSM) encoding in VHDL: binary, one-hot, and others (blog post)
  • "Use" and "Library" in VHDL (blog post)
  • The scope of VHDL use clauses and VHDL library clauses (blog post)

GitHub

Assignment Symbol in VHDL

VHDL assignments are used to assign values from one object to another. In VHDL there are two assignment symbols:

Either of these assignment statements can be said out loud as the word “gets”. So for example in the assignment: test <= input_1; You could say out loud, “The signal test gets (assigned the value from) input_1.”

Note that there is an additional symbol used for component instantiations (=>) this is separate from an assignment.

Also note that <= is also a relational operator (less than or equal to). This is syntax dependent. If <= is used in any conditional statement (if, when, until) then it is a relational operator , otherwise it’s an assignment.

One other note about signal initialization: Signal initialization is allowed in most FPGA fabrics using the := VHDL assignment operator. It is good practice to assign all signals in an FPGA to a known-value when the FPGA is initialized. You should avoid using a reset signal to initialize your FPGA , instead use the := signal assignment.

Learn Verilog

Leave A Comment Cancel reply

Save my name, email, and website in this browser for the next time I comment.

  • Getting started with vhdl
  • D-Flip-Flops (DFF) and latches
  • Digital hardware design using VHDL in a nutshell
  • Identifiers
  • Protected types
  • Recursivity
  • Resolution functions, unresolved and resolved types
  • Static Timing Analysis - what does it mean when a design fails timing?

vhdl Getting started with vhdl

Fastest entity framework extensions.

VHDL is a compound acronym for VHSIC (Very High Speed Integrated Circuit) HDL (Hardware Description Language). As a Hardware Description Language, it is primarily used to describe or model circuits. VHDL is an ideal language for describing circuits since it offers language constructs that easily describe both concurrent and sequential behavior along with an execution model that removes ambiguity introduced when modeling concurrent behavior.

VHDL is typically interpreted in two different contexts: for simulation and for synthesis. When interpreted for synthesis, code is converted (synthesized) to the equivalent hardware elements that are modeled. Only a subset of the VHDL is typically available for use during synthesis, and supported language constructs are not standardized; it is a function of the synthesis engine used and the target hardware device. When VHDL is interpreted for simulation, all language constructs are available for modeling the behavior of hardware.

A simulation environment for the synchronous counter

Simulation environments.

A simulation environment for a VHDL design (the Design Under Test or DUT) is another VHDL design that, at a minimum:

  • Declares signals corresponding to the input and output ports of the DUT.
  • Instantiates the DUT and connects its ports to the declared signals.
  • Instantiates the processes that drive the signals connected to the input ports of the DUT.

Optionally, a simulation environment can instantiate other designs than the DUT, like, for instance, traffic generators on interfaces, monitors to check communication protocols, automatic verifiers of the DUT outputs...

The simulation environment is analyzed, elaborated and executed. Most simulators offer the possibility to select a set of signals to observe, plot their graphical waveforms, put breakpoints in the source code, step in the source code...

Ideally, a simulation environment should be usable as a robust non-regression test, that is, it should automatically detect violations of the DUT specifications, report useful error messages and guarantee a reasonable coverage of the DUT functionalities. When such simulation environments are available they can be rerun on every change of the DUT to check that it is still functionally correct, without the need of tedious and error prone visual inspections of simulation traces.

In practice, designing ideal or even just good simulation environments is challenging. It is frequently as, or even more, difficult than designing the DUT itself.

In this example we present a simulation environment for the Synchronous counter example. We show how to run it using GHDL and Modelsim and how to observe graphical waveforms using GTKWave with GHDL and the built-in waveform viewer with Modelsim. We then discuss an interesting aspect of simulations: how to stop them?

A first simulation environment for the synchronous counter

The synchronous counter has two input ports and one output ports. A very simple simulation environment could be:

Simulating with GHDL

Let us compile and simulate this with GHDL:

Then error messages tell us two important things:

  • The GHDL analyzer discovered that our design instantiates an entity named counter but this entity was not found in library work . This is because we did not compile counter before counter_sim . When compiling VHDL designs that instantiate entities, the bottom levels must always be compiled before the top levels (hierarchical designs can also be compiled top-down but only if they instantiate component , not entities).
  • The rising_edge function used by our design is not defined. This is due to the fact that this function was introduced in VHDL 2008 and we did not tell GHDL to use this version of the language (by default it uses VHDL 1993 with tolerance of VHDL 1987 syntax).

Let us fix the two errors and launch the simulation:

Note that the --std=08 option is needed for analysis and simulation. Note also that we launched the simulation on entity counter_sim , architecture sim , not on a source file.

As our simulation environment has a never ending process (the process that generates the clock), the simulation does not stop and we must interrupt it manually. Instead, we can specify a stop time with the --stop-time option:

As is, the simulation does not tell us much about the behavior of our DUT. Let's dump the value changes of the signals in a file:

(ignore the error message, this is something that needs to be fixed in GHDL and that has no consequence). A counter_sim.vcd file has been created. It contains in VCD (ASCII) format all signal changes during the simulation. GTKWave can show us the corresponding graphical waveforms:

where we can see that the counter works as expected.

A GTKWave waveform

Simulating with Modelsim

The principle is exactly the same with Modelsim:

enter image description here

Note the -voptargs="+acc" option passed to vsim : it prevents the simulator from optimizing out the data signal and allows us to see it on the waveforms.

Gracefully ending simulations

With both simulators we had to interrupt the never ending simulation or to specify a stop time with a dedicated option. This is not very convenient. In many cases the end time of a simulation is difficult to anticipate. It would be much better to stop the simulation from inside the VHDL code of the simulation environment, when a particular condition is reached, like, for instance, when the current value of the counter reaches 20. This can be achieved with an assertion in the process that handles the reset:

As long as data is different from 20 the simulation continues. When data reaches 20, the simulation crashes with an error message:

Note that we re-compiled only the simulation environment: it is the only design that changed and it is the top level. Had we modified only counter.vhd , we would have had to re-compile both: counter.vhd because it changed and counter_sim.vhd because it depends on counter.vhd .

Crashing the simulation with an error message is not very elegant. It can even be a problem when automatically parsing the simulation messages to decide if an automatic non-regression test passed or not. A better and much more elegant solution is to stop all processes when a condition is reached. This can be done, for instance, by adding a boolean End Of Simulation ( eof ) signal. By default it is initialized to false at the beginning of the simulation. One of our processes will set it to true when the time has come to end the simulation. All the other processes will monitor this signal and stop with an eternal wait when it will become true :

Last but not least, there is an even better solution introduced in VHDL 2008 with the standard package env and the stop and finish procedures it declares:

Hello world

There are many ways to print the classical "Hello world!" message in VHDL. The simplest of all is probably something like:

Installation or Setup

A VHDL program can be simulated or synthesized. Simulation is what resembles most the execution in other programming languages. Synthesis translates a VHDL program into a network of logic gates. Many VHDL simulation and synthesis tools are parts of commercial Electronic Design Automation (EDA) suites. They frequently also handle other Hardware Description Languages (HDL), like Verilog, SystemVerilog or SystemC. Some free and open source applications exist.

VHDL simulation

GHDL is probably the most mature free and open source VHDL simulator. It comes in three different flavours depending on the backend used: gcc , llvm or mcode . The following examples show how to use GHDL ( mcode version) and Modelsim, the commercial HDL simulator by Mentor Graphics, under a GNU/Linux operating system. Things would be very similar with other tools and other operating systems.

Hello World

Create a file hello_world.vhd containing:

A VHDL compilation unit is a complete VHDL program that can be compiled alone. Entities are VHDL compilation units that are used to describe the external interface of a digital circuit, that is, its input and output ports. In our example, the entity is named hello_world and is empty. The circuit we are modeling is a black box, it has no inputs and no outputs. Architectures are another type of compilation unit. They are always associated to an entity and they are used to describe the behaviour of the digital circuit. One entity may have one or more architectures to describe the behavior of the entity. In our example the entity is associated to only one architecture named arc that contains only one VHDL statement:

The statement will be executed at the beginning of the simulation and print the Hello world! message on the standard output. The simulation will then end because there is nothing more to be done. The VHDL source file we wrote contains two compilation units. We could have separated them in two different files but we could not have split any of them in different files: a compilation unit must be entirely contained in one source file. Note that this architecture cannot be synthesized because it does not describe a function which can be directly translated to logic gates.

Analyse and run the program with GHDL:

The gh_work directory is where GHDL stores the files it generates. This is what the --workdir=gh_work option says. The analysis phase checks the syntax correctness and produces a text file describing the compilation units found in the source file. The run phase actually compiles, links and executes the program. Note that, in the mcode version of GHDL, no binary files are generated. The program is recompiled each time we simulate it. The gcc or llvm versions behave differently. Note also that ghdl -r does not take the name of a VHDL source file, like ghdl -a does, but the name of a compilation unit. In our case we pass it the name of the entity . As it has only one architecture associated, there is no need to specify which one to simulate.

With Modelsim:

vlib , vmap , vcom and vsim are four commands that Modelsim provides. vlib creates a directory ( ms_work ) where the generated files will be stored. vmap associates a directory created by vlib with a logical name ( work ). vcom compiles a VHDL source file and, by default, stores the result in the directory associated to the work logical name. Finally, vsim simulates the program and produces the same kind of output as GHDL. Note again that what vsim asks for is not a source file but the name of an already compiled compilation unit. The -c option tells the simulator to run in command line mode instead of the default Graphical User Interface (GUI) mode. The -do option is used to pass a TCL script to execute after loading the design. TCL is a scripting language very frequently used in EDA tools. The value of the -do option can be the name of a file or, like in our example, a string of TCL commands. run -all; quit instruct the simulator to run the simulation until it naturally ends - or forever if it lasts forever - and then to quit.

Signals vs. variables, a brief overview of the simulation semantics of VHDL

This example deals with one of the most fundamental aspects of the VHDL language: the simulation semantics. It is intended for VHDL beginners and presents a simplified view where many details have been omitted (postponed processes, VHDL Procedural Interface, shared variables...) Readers interested in the real complete semantics shall refer to the Language Reference Manual (LRM).

Signals and variables

Most classical imperative programming languages use variables. They are value containers. An assignment operator is used to store a value in a variable:

and the value currently stored in a variable can be read and used in other statements:

VHDL also uses variables and they have exactly the same role as in most imperative languages. But VHDL also offers another kind of value container: the signal. Signals also store values, can also be assigned and read. The type of values that can be stored in signals is (almost) the same as in variables.

So, why having two kinds of value containers? The answer to this question is essential and at the heart of the language. Understanding the difference between variables and signals is the very first thing to do before trying to program anything in VHDL.

Let us illustrate this difference on a concrete example: the swapping.

Note: all the following code snippets are parts of processes. We will see later what processes are.

swaps variables a and b . After executing these 3 instructions, the new content of a is the old content of b and conversely. Like in most programming languages, a third temporary variable ( tmp ) is needed. If, instead of variables, we wanted to swap signals, we would write:

with the same result and without the need of a third temporary signal!

Note: the VHDL signal assignment operator <= is different from the variable assignment operator := .

Let us look at a second example in which we assume that the print subprogram prints the decimal representation of its parameter. If a is an integer variable and its current value is 15, executing:

will print:

If we execute this step by step in a debugger we can see the value of a changing from the initial 15 to 30, 25 and finally 5.

But if s is an integer signal and its current value is 15, executing:

If we execute this step by step in a debugger we will not see any value change of s until after the wait instruction. Moreover, the final value of s will not be 15, 30, 25 or 5 but 3!

This apparently strange behavior is due the fundamentally parallel nature of digital hardware, as we will see in the following sections.

Parallelism

VHDL being a Hardware Description Language (HDL), it is parallel by nature. A VHDL program is a collection of sequential programs that run in parallel. These sequential programs are called processes:

The processes, just like the hardware they are modelling, never end: they are infinite loops. After executing the last instruction, the execution continues with the first.

As with any programming language that supports one form or another of parallelism, a scheduler is responsible for deciding which process to execute (and when) during a VHDL simulation. Moreover, the language offers specific constructs for inter-process communication and synchronization.

The scheduler maintains a list of all processes and, for each of them, records its current state which can be running , run-able or suspended . There is at most one process in running state: the one that is currently executed. As long as the currently running process does not execute a wait instruction, it continues running and prevents any other process from being executed. The VHDL scheduler is not preemptive: it is each process responsibility to suspend itself and let other processes run. This is one of the problems that VHDL beginners frequently encounter: the free running process.

Note: variable a is declared locally while signals s and r are declared elsewhere, at a higher level. VHDL variables are local to the process that declares them and cannot be seen by other processes. Another process could also declare a variable named a , it would not be the same variable as the one of process P3 .

As soon as the scheduler will resume the P3 process, the simulation will get stuck, the simulation current time will not progress anymore and the only way to stop this will be to kill or interrupt the simulation. The reason is that P3 has not wait statement and will thus stay in running state forever, looping over its 3 instructions. No other process will ever be given a chance to run, even if it is run-able .

Even processes containing a wait statement can cause the same problem:

Note: the VHDL equality operator is = .

If process P4 is resumed while the value of signal s is 3, it will run forever because the a = 16 condition will never be true.

Let us assume that our VHDL program does not contain such pathological processes. When the running process executes a wait instruction, it is immediately suspended and the scheduler puts it in the suspended state. The wait instruction also carries the condition for the process to become run-able again. Example:

means suspend me until the value of signal s changes . This condition is recorded by the scheduler. The scheduler then selects another process among the run-able , puts it in running state and executes it. And the same repeats until all run-able processes have been executed and suspended.

Important note: when several processes are run-able , the VHDL standard does not specify how the scheduler shall select which one to run. A consequence is that, depending on the simulator, the simulator's version, the operating system, or anything else, two simulations of the same VHDL model could, at one point, make different choices and select a different process to execute. If this choice had an impact on the simulation results, we could say that VHDL is non-deterministic. As non-determinism is usually undesirable, it would be the responsibility of the programmers to avoid non-deterministic situations. Fortunately, VHDL takes care of this and this is where signals enter the picture.

Signals and inter-process communication

VHDL avoids non determinism using two specific characteristics:

  • Processes can exchange information only through signals
Note: VHDL comments extend from -- to the end of the line.
  • The value of a VHDL signal does not change during the execution of processes

Every time a signal is assigned, the assigned value is recorded by the scheduler but the current value of the signal remains unchanged. This is another major difference with variables that take their new value immediately after being assigned.

Let us look at an execution of process P5 above and assume that a=5 , s=1 and r=0 when it is resumed by the scheduler. After executing instruction a := s + 1; , the value of variable a changes and becomes 2 (1+1). When executing the next instruction r <= a; it is the new value of a (2) that is assigned to r . But r being a signal, the current value of r is still 0. So, when executing a := r + 1; , variable a takes (immediately) value 1 (0+1), not 3 (2+1) as the intuition would say.

When will signal r really take its new value? When the scheduler will have executed all run-able processes and they will all be suspended. This is also referred to as: after one delta cycle . It is only then that the scheduler will look at all the values that have been assigned to signals and actually update the values of the signals. A VHDL simulation is an alternation of execution phases and signal update phases. During execution phases, the value of the signals is frozen. Symbolically, we say that between an execution phase and the following signal update phase a delta of time elapsed. This is not real time. A delta cycle has no physical duration.

Thanks to this delayed signal update mechanism, VHDL is deterministic. Processes can communicate only with signals and signals do not change during the execution of the processes. So, the order of execution of the processes does not matter: their external environment (the signals) does not change during the execution. Let us show this on the previous example with processes P5 and P6 , where the initial state is P5.a=5 , P6.a=10 , s=17 , r=0 and where the scheduler decides to run P5 first and P6 next. The following table shows the value of the two variables, the current and next values of the signals after executing each instruction of each process:

With the same initial conditions, if the scheduler decides to run P6 first and P5 next:

As we can see, after the execution of our two processes, the result is the same whatever the order of execution.

This counter-intuitive signal assignment semantics is the reason of a second type of problems that VHDL beginners frequently encounter: the assignment that apparently does not work because it is delayed by one delta cycle. When running process P5 step-by-step in a debugger, after r has been assigned 18 and a has been assigned r + 1 , one could expect that the value of a is 19 but the debugger obstinately says that r=0 and a=1 ...

Note: the same signal can be assigned several times during the same execution phase. In this case, it is the last assignment that decides the next value of the signal. The other assignments have no effect at all, just like if they never had been executed.

It is time to check our understanding: please go back to our very first swapping example and try to understand why:

actually swaps signals r and s without the need of a third temporary signal and why:

would be strictly equivalent. Try to understand also why, if s is an integer signal and its current value is 15, and we execute:

the two first assignments of signal s have no effect, why s is finally assigned 3 and why the two printed values are 15 and 3.

Physical time

In order to model hardware it is very useful to be able to model the physical time taken by some operation. Here is an example of how this can be done in VHDL. The example models a synchronous counter and it is a full, self-contained, VHDL code that could be compiled and simulated:

In process P1 the wait instruction is not used to wait until the value of a signal changes, like we saw up to now, but to wait for a given duration. This process models a clock generator. Signal clk is the clock of our system, it is periodic with period 20 ns (50 MHz) and has duty cycle.

Process P2 models a register that, if a rising edge of clk just occurred, assigns the value of its input nc to its output c and then waits for the next value change of clk .

Process P3 models an incrementer that assigns the value of its input c , incremented by one, to its output nc ... with a physical delay of 5 ns. It then waits until the value of its input c changes. This is also new. Up to now we always assigned signals with:

which, for the reasons explained in the previous sections, we can implicitly translate into:

This small digital hardware system could be represented by the following figure:

A synchronous counter

With the introduction of the physical time, and knowing that we also have a symbolic time measured in delta , we now have a two dimensional time that we will denote T+D where T is a physical time measured in nano-seconds and D a number of deltas (with no physical duration).

The complete picture

There is one important aspect of the VHDL simulation that we did not discuss yet: after an execution phase all processes are in suspended state. We informally stated that the scheduler then updates the values of the signals that have been assigned. But, in our example of a synchronous counter, shall it update signals clk , c and nc at the same time? What about the physical delays? And what happens next with all processes in suspended state and none in run-able state?

The complete (but simplified) simulation algorithm is the following:

  • Set current time Tc to 0+0 (0 ns, 0 delta-cycle)
  • Initialize all signals.
  • Record the values and delays of signal assignments.
  • Record the conditions for the process to resume (delay or signal change).
  • The resume time of processes suspended by a wait for <delay> .
  • The next time at which a signal value shall change.
  • Update signals that need to be.
  • Put in run-able state all processes that were waiting for a value change of one of the signals that has been updated.
  • Put in run-able state all processes that were suspended by a wait for <delay> statement and for which the resume time is Tc .
  • If Tn is infinity, stop simulation. Else, start a new simulation cycle.

Manual simulation

To conclude, let us now manually exercise the simplified simulation algorithm on the synchronous counter presented above. We arbitrary decide that, when several processes are run-able, the order will be P3 > P2 > P1 . The following tables represent the evolution of the state of the system during the initialization and the first simulation cycles. Each signal has its own column in which the current value is indicated. When a signal assignment is executed, the scheduled value is appended to the current value, e.g. a/b@T+D if the current value is a and the next value will be b at time T+D (physical time plus delta cycles). The 3 last columns indicate the condition to resume the suspended processes (name of signals that must change or time at which the process shall resume).

Initialization phase:

Simulation cycle #1.

Note: during the first simulation cycle there is no execution phase because none of our 3 processes has its resume condition satisfied. P2 is waiting for a value change of clk and there has been a transaction on clk , but as the old and new values are the same, this is not a value change .

Simulation cycle #2

Note: again, there is no execution phase. nc changed but no process is waiting on nc .

Simulation cycle #3

Simulation cycle #4, simulation cycle #5.

Note: one could think that the nc update would be scheduled at 15+2 , while we scheduled it at 15+0 . When adding a non-zero physical delay (here 5 ns ) to a current time ( 10+2 ), the delta cycles vanish. Indeed, delta cycles are useful only to distinguish different simulation times T+0 , T+1 ... with the same physical time T . As soon as the physical time changes, the delta cycles can be reset.

Simulation cycle #6

Simulation cycle #7, simulation cycle #8, simulation cycle #9, simulation cycle #10, simulation cycle #11, synchronous counter, got any vhdl question.

pdf

  • Advertise with us
  • Cookie Policy
  • Privacy Policy

Get monthly updates about new articles, cheatsheets, and tricks.

assignment not working in vhdl

andpas (Member) asked a question.

andpas (Member)

assignment not working in vhdl

drjohnsmith (Member)

assignment not working in vhdl

elzinga (Member)

assignment not working in vhdl

shantesh (Member)

assignment not working in vhdl

bassman59 (Member)

> -------------------------------------------------------------------------------- > > @andpas wrote: > > > Hello. > > I would use the syntax "0000_0000" to assign a value to an STD_LOGIC_VECTOR (7 > downto 0), > > using the underscore as simple bit separator (for viewing purposes). > > However, this syntax is not working... > > How to do it? > > Thanks > > --------------------------------------------------------------------------------

If it's binary, you must use the B prefix on your string literal. Read your fine VHDL textbook for more details.

Related Questions

Community Feedback?

Search code, repositories, users, issues, pull requests...

Provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VHDL2008 conditional variable assignment using when statement not working: cannot handle IIR_KIND_CONDITIONAL_VARIABLE_ASSIGNMENT_STATEMENT #2138

@tristanitschner

tristanitschner commented Jul 22, 2022

@tgingold

tgingold commented Jul 25, 2022 via email

Sorry, something went wrong.

@tgingold

No branches or pull requests

@tgingold

IMAGES

  1. Solved Problem: (a) Write a VHDL signal assignment to

    assignment not working in vhdl

  2. vhdl

    assignment not working in vhdl

  3. Using variables for registers or memory in VHDL

    assignment not working in vhdl

  4. VHDL Tutorial

    assignment not working in vhdl

  5. VHDL types

    assignment not working in vhdl

  6. VHDL Tutorials: 13 Important Concepts

    assignment not working in vhdl

VIDEO

  1. Weight Loss Journal: Ep 8 Bad Comedy Shows and Chicken Wings

  2. Funni Sans Undertale Video

  3. *NEW* ALL WORKING CODES FOR UNTITLED BOXING GAME IN JUNE 2023! ROBLOX UNTITLED BOXING GAME CODES

  4. 15 Best Gadgets 2023 on Amazon #cool gadgets

  5. Hot work in worn Levi's

  6. ONE MONTH ALONE IN GUATEMALA

COMMENTS

  1. vhdl

    In you not working example x_delayed (0) <= x; is aquvalent to. process(x) begin. x_delayed(0) <= x; end process; So the process will assign x_delayed (0) only when x changes. Because this is a signal asignment the x_delayed (0) will not change immediatly, it will change after a delta cycle.

  2. VHDL process assignment does not work

    0. It seems like you are trying to write a clocked process, in which case you should probably write something like this: signal state_last_pushbutton : std_logic; process (clk_clk) begin. if rising_edge(clk_clk) then. state_last_pushbutton <= pushbuttons_external_connection_export(0); end if; end process;

  3. VHDL Logical Operators and Signal Assignments for Combinational Logic

    The VHDL code shown below uses one of the logical operators to implement this basic circuit. and_out <= a and b; Although this code is simple, there are a couple of important concepts to consider. The first of these is the VHDL assignment operator (<=) which must be used for all signals.

  4. Difference between Blocking and Non-Blocking assignment in VHDL

    The one huge advantage VHDL has over not just Verilog but virtually every other digital simulation/verification language out there is its deterministic timing model. ... So perhaps this is a little like Verilog's non-blocking assignment. The delay in VHDL only applies to when the signal is scheduled relative to the current process time and ...

  5. VHDL: value isn't assigned immediately

    VHDL delayed assignment problem. Related. 1. Problem in synthesizing. 3. ... Fairly Simple VHDL SPI bus working in simulation but not on FPGA (Lattice MACHOX3LF-6900C FPGA and Lattice Diamond software) 2. Generation of non overlapping clocks on FPGA using VHDL. 0. VHDL code for ALU and ROM connection. 0.

  6. vhdl Tutorial => Signals vs. variables, a brief overview of the

    As we can see, after the execution of our two processes, the result is the same whatever the order of execution. This counter-intuitive signal assignment semantics is the reason of a second type of problems that VHDL beginners frequently encounter: the assignment that apparently does not work because it is delayed by one delta cycle.

  7. Signal Assignments in VHDL: with/select, when/else and case

    With / Select. The most specific way to do this is with as selected signal assignment. Based on several possible values of a, you assign a value to b. No redundancy in the code here. The official name for this VHDL with/select assignment is the selected signal assignment. with a select b <= "1000" when "00", "0100" when "01", "0010" when "10 ...

  8. vhdl

    1. Assignments in VHDL are neighter specified as registered or combinatorial. In VHDL the actual assignment type (the type of RTL logic generated) is just inferred. Registers in VHDL are created explicitly by assigning a signal on a clock edge, though just because a process has a clock it does not mean all signals in that block will be assigned ...

  9. Assignment Symbol

    In VHDL there are two assignment symbols: <= Assignment of Signals. := Assignment of Variables and Signal Initialization. Either of these assignment statements can be said out loud as the word "gets". So for example in the assignment: test <= input_1; You could say out loud, "The signal test gets (assigned the value from) input_1.".

  10. vhdl Tutorial => Getting started with vhdl

    As we can see, after the execution of our two processes, the result is the same whatever the order of execution. This counter-intuitive signal assignment semantics is the reason of a second type of problems that VHDL beginners frequently encounter: the assignment that apparently does not work because it is delayed by one delta cycle.

  11. underscore in assignment of STD_LOGIC_VECTOR as separator, not working?

    drjohnsmith (Member) 13 years ago. underscore works in vhdl as a seperator, provided you define if the vector is binary, hex or octal. what did not work int he code was the minus "-" as a compare that is not allowed, LikeLikedUnlike. Reply.

  12. assignment of '0' to specific location of arrays of std_logic type do

    Each assignment on the arrays "mult" and "sum" leaves the corresponding location with "U" value, that means the array values do not change after running the corresponding assignment sentence. Does anyone know why the assignments on the arrays "mult" and "sum" do not work? I have a file called test_bench.vhd. Find as follows the code of mult.vhd:

  13. PDF VHDL Syntax Reference

    1 1. Bits, Vectors, Signals, Operators, Types 1.1 Bits and Vectors in Port Bits and vectors declared in port with direction. Example: port ( a : in std_logic; -- signal comes in to port a from outside b : out std_logic; -- signal is sent out to the port b c : inout std_logic; -- bidirectional port x : in std_logic_vector(7 downto 0); -- 8-bit input vector

  14. vhdl

    Until some time passes (ie all the processes triggered during this delta cycle have completed) any assignments made in those processes are merely scheduled to happen at the next time step. You could do: process. begin. wait until input'event; temp <= input; wait for 0 ps; goes_out <= temp after 10ns; end process;

  15. VHDL2008 conditional variable assignment using when statement not

    GHDL does not handle a variable assignment using the conditional when statement without an else clause inside a combinatorial process (haven't checked for sequential process though). Expected behaviour Should be supported according to BNF § 10.5.3 and § 10.6.3 of the VHDL 2008 LRM. How to reproduce?

  16. vhdl

    I tried both versions of the logic in Xilinx ISE 14.6 and both versions work, but there are some caveats. First of all, when I compare the RTL Schematic of the "don't care" version with the explicit version the "don't care" version is much simpler and more optimized.

  17. Why do we assign our outputs to signals first in VHDL?

    4. It's because you couldn't read from ports of type OUT in VHDL. If the value driving an OUT port was to be read within the design, a signal had to used to hold it, then that signal assigned to the OUT port. The capability to do so was added in VHDL-2008.