March 23

Building Digital Circuits with VHDL – Part 3

0  comments

This is the third video in our series of VHDL video tutorials, where I’ll be discussing how to design combinational circuits using the conditional signal assignment construct.

If you haven’t watched the first two videos in this series yet, I recommend pausing this video here and checking out those tutorials first.

More...

Recap of Previous Videos

In the previous videos, I explained how you can describe combinational circuits in the concurrent section of VHDL using two types of signal assignment constructs: the selected signal assignment and the conditional signal assignment.  

In those tutorials, I focused on using the selected signal assignment to describe combinational circuits. In this video, I’ll cover the conditional signal assignment.

If you recall from the previous video, we used a 4-to-1 multiplexer as an example to explain the selected signal assignment.

I’ll use the same example here so you can better understand the differences between the selected and conditional signal assignment. 

As you may remember from your digital logic courses—or if not, from the previous video—a multiplexer is a widely used combinational circuit. It has several inputs, a control input, and an output. 

4-to-1-Multiplexer

4-to-1 Multiplexer

Based on the value of the control input, one of the input signals is connected to the output.

Multiplexer-truth-table

The truth table for a 4-to-1 multiplexer.

Implementing a 4-to-1 Multiplexer Using Conditional Signal Assignment

Now, let’s see how we can implement this circuit in VHDL using the conditional signal assignment construct.

The code you see here describes a 4-to-1 multiplexer using the conditional signal assignment.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity MUX4to1 is

  port (
        w0      :  in      std_logic;
        w1      :  in      std_logic;
        w2      :  in      std_logic;
        w3      :  in      std_logic;
        S       :  in      std_logic_vector(1 downto 0);
        F       :  out     std_logic
      );

end MUX4to1;

architecture Behavioral of MUX4to1 is

begin

    F    <=    w0   when      s="00" else
               w1   when      s="01" else
               w2   when      s="10" else
               w3;

end Behavioral; 

The Entity for this circuit shouldn’t be any different from the one we used to describe the 4-to-1 multiplexer with the selected signal assignment.

So here, as you can see, we have four single-bit inputs, labeled W0 to W3, a single-bit output F, and a two-bit control input S, which is defined using the STD_LOGIC_VECTOR type.

As we explained in the previous video, for signals with more than one bit, we use the STD_LOGIC_VECTOR type instead of STD_LOGIC, and we specify the length of the signal in parentheses. Here, 1 downto 0 indicates that this signal is 2 bits wide, with indices ranging from 1 to 0.

Now, let’s see how the conditional signal assignment can describe this multiplexer for us.

In the above code, you can see the implementation of the 4-to-1 multiplexer using the conditional signal assignment.  

The logic of this assignment is as follows: it assigns input W0 to the output F when the control input S equals 0. If not, it assigns W1 to F when S equals 1. If not, it assigns W2 to F when S equals 2, and finally, if none of these conditions are met, it assigns W3 to F.  

In the last case, it’s clear that we’re referring to the scenario where the control input S equals 3.  

Comparing Conditional and Selected Signal Assignment for Multiplexers

Personally, I prefer using this conditional signal assignment over the selected signal assignment because it is clearer and, due to its flexibility, can be more useful in certain situations.  

Pro Tip!

Personally, I prefer using this conditional signal assignment over the selected signal assignment because it is clearer and, due to its flexibility, can be more useful in certain situations.

For example, in the selected signal assignment construct, we use the control signal S only once and reference its values in the conditions.

However, in the conditional signal assignment construct, the condition is written explicitly each time, improving readability. This is particularly helpful when you need to review or debug your code later.

Now, let’s continue exploring the use of the conditional signal assignment construct with another example to deepen your understanding of how it works and when to use it.

Designing a Priority Encoder with Conditional Signal Assignment

In this example, we’ll design a priority encoder. If you remember from your digital logic courses, an encoder is a widely used combinational circuit.

It has several inputs and outputs, where the number of inputs equals 2 raised to the power of the number of outputs.

4-to-2-Encoder

4-to-2 Encoder

Here, we’re looking at a 4-to-2 encoder with inputs W0 to W3 and outputs Y0 and Y1.

From the truth table we’ve written for this encoder, we can determine its functionality. 

encoder-truth-table

The truth table for a 4-to-2 encoder.

In a standard encoder, at any given moment, one of the inputs is high (1), while the rest are low (0). Depending on which input is high, the output produces a binary number corresponding to that input.

For instance, in this encoder, if W0 is 1, the output is 0. If W1 is 1, the output is 1. Finally, if W3 is 1, the output is 3. This is the normal behavior of an encoder. 

But here’s the question: what happens if more than one input is high? For example, what if both W1 and W3 are high, as shown in the figure below? 

Priority-Encoder

What would be the encoder output if both W1 and W3 are high?

What would be the encoder output in this case? Since a standard encoder assumes only one input is high, this creates an ambiguity. 

To resolve this issue, the concept of a priority encoder is introduced. A priority encoder assigns priority to one side of the inputs—either the most significant bit (MSB) or the least significant bit (LSB). 

For example, let’s say we want a priority encoder where W3 has the highest priority.

In this case, when both W1 and W3 are high, the priority encoder starts evaluating inputs from the MSB side, which here is W3. It checks whether W3 equals 1. If so, the output is determined based on W3, which means the output will be 3.  

It doesn’t matter if other inputs, like W1, are also high—the encoder ignores them.  

The truth table for such a priority encoder can be represented as follows.

priority-encoder-truth-table

The truth table for a 4-to-2 priority encoder.

In this table, for instance, when W3 equals 1, the remaining inputs are marked as “don’t care,” meaning their values are irrelevant.  

This is reflected in the truth table of this priority encoder. For instance, when W3 is high, the lower-priority inputs are treated as "don’t care" because the output is determined solely by W3.

If W3 equals 1, the output is 3, regardless of the other inputs. Similarly, for W2, if W3 is 0 and W2 equals 1, the output is determined based on W2, and the lower-priority inputs are ignored.  

Now, let’s see how we can implement this priority encoder using the conditional signal assignment construct in VHDL.

Implementing the Priority Encoder in VHDL

In this code, you can see the priority encoder implemented in VHDL.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Encoder is

  port (
        w      :  in    std_logic_vector(3 downto 0);
        y      :  out   std_logic_vector(1 downto 0)
       );

end Encoder;

architecture Behavioral of Encoder is

begin

    y    <=    "11"   when   w(3) = '1' else
               "10"   when   w(2) = '1' else
               "01"   when   w(1) = '1' else
               "00";

end Behavioral;

In the Entity section, we’ve defined the input W and the output Y. Since W consists of 4 bits, we’ve used the STD_LOGIC_VECTOR type and specified its range as 3 downto 0, which means it has indices from 3 to 0, making it 4 bits wide.

Similarly, for the output, which is 2 bits wide, we’ve used the same type and defined its range as 1 downto 0.

To implement the circuit, we’re using the conditional signal assignment construct. Here, we assign the value 11 (representing 3 in binary) to the output Y when W3 equals 1.

W3, being the most significant bit of the input, has the highest priority. If W3 equals 1, we assign 3 to the output, and no further conditions are evaluated. 

If not, we check W2, the next most significant bit. If W2 equals 1, we assign 2 to the output.

Similarly, if W1 is high, the output is set to 1. Finally, if none of the higher-priority inputs are high, the output is set to 0 when W0 is high.

Why does this implementation behave as a priority encoder? It’s because we evaluate the inputs in order of their priority, starting with W3. If W3 is high, the output is set to 3, and the remaining conditions are ignored.

Even if other inputs like W2 or W1 are high, W3 takes precedence. This ensures that the encoder functions as a priority encoder, prioritizing the most significant bit.

We can also implement a priority encoder that prioritizes the least significant bit instead.

In that case, you can probably guess that we’d simply reverse the indices in the code.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Encoder is

  port (
        	w      :  in    std_logic_vector(3 downto 0);
        	y      :  out   std_logic_vector(1 downto 0)
       );

end Encoder;

architecture Behavioral of Encoder is

begin

    y    <=    "00"    when   w(0) = '1' else
            	 "01"    when   w(1) = '1' else
               "10"    when   w(2) = '1' else
               "11";

end Behavioral;

For instance, we’d assign 00 to the output when W0 equals 1, 01 when W1 equals 1, and so on.

In this scenario, the encoder would evaluate the inputs starting with W0, and if W0 is high, the rest of the inputs would be ignored.

This alternate implementation would give us a priority encoder based on the least significant bit.

Did you find the tutorial "Building Digital Circuits with VHDL – Part 3" helpful?

If you have any questions about this post, please feel free to ask in the comments section below. And if you enjoyed the content, don't forget to share it with your friends!

About the author 

Ahmad Saghafi

Hi, I’m Ahmad, founder of FPGATEK and creator of the FPGA Design Blueprint training. With over 15 years of hands-on experience and a wealth of knowledge from successfully implementing numerous industrial projects, I am thrilled to share my insights and expertise with you on this website.

Enjoyed this article?


You may also like:

Leave a Comment

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Get Started With FPGA In 20 Minutes

>