Comparator in Vhdl

Comparator using boolean, when..else and with..select

I carried out this task according to the given comparator truth table below, the simplicity of the table could be made understandable by some 3 simple logic: i.e. eq is 1 when a=b, gr is 1 when a > b and ls is 1 when a < b. The purpose of this task is to show how to implement comparator table with Vivado 2018.2 as well as the synthesis comparison and view each of its output on LED from FPGA board.

Table 1: Comparator Truth Table 

a
  b     
eq
gr
ls
00
 00
1
0
0
00
 01
0
0
1
00
10
0
0
1
00
11
0
0
1
01
00
0
1
0
01
01
1
0
0
01
10
0
0
1
01
11
0
0
1
10
00
0
1
0
10
01
0
1
0
10
10
1
0
0
10
11
0
0
1
11
00
0
1
0
11
01
0
1
0
11
10
0
1
0
11
11
1
0
0
 Note
  a = input a1 down to a0
 b = input  b1 down to b0
 eq =  Output representing equal to  values after a and b   comparison.
 gr = Output representing greater than values after a and b   comparison.
 ls =  Output representing less than values after and b
 comparison.

WORKFLOW
For better clarification, I separated each logical comparator into its actual files e.g.
o   Boolean Comparator.
o   Select  Comparator.
o   When… else Comparator.

1 IMPLEMENTATION OF BOOLEAN COMPARATOR

I commence the implementation by setting up the wizard for each step I took; 

1.1. I created the project name as “booleanComp” and after that I created a new source file for the project; The source file has 3 phases which I set the file type to “VHDL”, file name to “BooleanComp_source_beh” and the last phase which is the file location was a default local location where my source file is saved.
1.2. The next step was I defined a module for the input and output of the source file by given names to my ports and specified each direction the names belong to.
Finally, the environment to set up the behavior of my entity which is the collection of my  inputs and outputs opened up, and  right there I begin the implementation of architecture behavioral of BooleanComp_Source_beh right under the reserved “begin” keyword such as: 
     architecture Behavioral of BooleanComp_Source_beh is
             begin
          --BOOLEAN EQUATION WHEN eq is 1

eq <= (not a0 and not a1 and not b0 and not b1) or (not a0 and a1 and not b0 and b1) or (a0 and not a1 and b0 and not b1) or (a0 and b0 and a1 and b1);  

 -- BOOLEAN EQUATION WHEN gr is 1 
gr <=  (not a0 and a1 and not b0 and not b1) or (a0 and not a1 and not b0 and not b1) or (a0 and not a1 and not b0 and b1) or(a0 and a1 and not b0 and not b1) or (a0 and a1 and not b0 and b1)or (a0 and a1 and b0 and not b1); 
 
  -- BOOLEAN EQUATION WHEN ls is 1   
ls <= (not a0 and not a1 and not b0 and b1) or (not a0 and not a1 and b0 and not b1) or (not a0 and not a1 and b0 and b1) or (not a0 and a1 and b0 and not b1) or
(not a0 and a1 and b0 and b1) or (a0 and not a1 and  b0 and b1); 
I arrived at these equations above by considering these three logical steps below:
          If the values in a are greater than b then  greater is 1 
          if the values in a = b  then equal to is 1
          and, if the values in a are lesser than b then lesser than is 1
It should be noted that the use of “not” with the inputs does not represent a logical not gate. It only considers the values belong to those inputs as 0 which is in contrast with those inputs without “not” which then represent 1.

For synthesis, implementation and the generation of bit stream, I added a constraint file of  .XDC extension that permits the logical activation of the FPGA board to work with the implementation through “open hardware manager”  located in vivado flow navigator.          
Figure1: RTL ANALYSIS SCHEMATIC FOR BOOLEAN COMPARATOR
maxybyte.com
Figure 1















Figure 2: SYNTHESIS SCHEMATICS FOR BOOLEAN COMPARATOR

maxybyte.com
Figure 2












These two schematics design above (Figure 1 and Figure 2) look totally different from each other, the reason is that RTL schematic refers to the total implemented logic, in this case, it has all the gates and components within the project in contrast to the synthesis schematic which show design image within the FPGA. Meanwhile, the schematic result from synthesis and implementation are both the same, Figure 2 and Figure 3 show how they both look:

Figure 3: IMPLEMENTATION SCHEMATIC FOR BOOLEAN COMPARATOR

maxybyte.com
Figure 3












Figure 4 below shows the waveform result through the help of a test bench code after simulation that is included in this article:
The functionality of this test bench stimulus process shows the logical behavior of how my code operate without been tested on FPGA board.

 It should be noted that the test bench entity doesn’t have defined inputs and outputs for its port rather it encapsulates the behavioral port of our source file as component it needs to interact with, which is where the initial inputs and outputs were declared meanwhile the test bench gives room for signal declaration.

It also makes mapping its declared signal with the encapsulated component of the behavioral source file values for input and output possible right within its unit under test. Right under the keyword “begin” situated within the stimulus, the assignment of digit values to signals begins. On the other hand the keyword “wait” stop the test indefinitely whereas the “wait for” is used to wait for a specific period of time before the continuation of the next stimulus process.

Figure 4 : WAVEFORM SIMULATION RESULT FOR BOOLEAN COMPARATOR

maxybyte.com
waveform















Moreover, this waveform correctness is verified by checking each logical step within the stimulus and compare with their output. This was exactly what I did to see how my inputs interact to generate their outputs. The output of this verification could also be compared to what we have on the truth table and tested on the FPGA Board.

2. IMPLEMENTATION OF COMPARATOR USING SELECT

I begin the implementation with setting up the wizard for each step I took; 
2.1. I created the project name as “Comparator_select” and after that I created a new source file for the project; The source file has 3 phases which I set the file type to “VHDL”, file name to “Comparator_select_beh” and the last phase which is the file location was a default local location where my source file is saved.
2.2. The next step was I defined a module for the input and output of the source file by given names to my ports and specified each direction the names belong to.
Finally the environment to set up the behaviour of my entity which is the collection of my inputs and outputs opened up, and right there I begin the implementation of architecture behavioural of Comparator_select_beh right under the reserved “begin” statement such as:
architecture Selected of Comparator_select_beh is begin with a & b select eq_0 <= '1' when "0000" | "0101" |"1010" |"1111" , '0' when others; with a & b select gr_0 <= '1' when "0100" | "1000" |"1001" | "1100"|"1101" | "1110" , '0' when others;  with a & b select ls_0 <= '1' when "0001" | "0010" | "0011"|"0110" |"0111" | "1011" ,  '0'  when others;  end Selected;



Figure 2.1: RTL Schematic for Select Comparator

maxybyte.com
Figure 2.1










Figure 2.2: Synthesis Schematic for Select Comparator

maxybyte.com
Figure 2.2










Figure 2.3: Implementation Schematic for Select Comparator

maxybyte.com
Figure 2.3












Figure 2.4 Waveform result for Select Comparator


maxybyte.com
Figure 2.4











I got decimal number for the value column from the above waveform because I  used a vector to manipulate my inputs a_tb = 3 means 11 and b_tb = 3 also means 11 which are both equal to each other and the output eq is 1 while others are 0’s.
3. IMPLEMENTATION OF COMPARATOR USING WHEN… ELSE

I started the implementation with setting up the wizard for each step I took; 
3.1. I created the project name as “when_source” and after that I created a new source file for the project; The source file has 3 phases which I set the file type to “VHDL”, file name to “when_source _beh” and the last phase which is the file location was a default local location where my source file is saved.
3.2. The next step was I defined a module for the input and output of the source file by given names to my ports and specified each direction the names belong to.Finally, the environment to set up the behavior of my entity -is the collection of my  inputs and outputs opened up, and  right there I begin the implementation of architecture behavioral of when_source _beh right under the reserved “begin” statement such as:  architecture Behavioral of when_source_beh is begin eq <='1' when ((a0='0'and  a1='0')and(b0='0'and b1='0'))or
              ((a0='0'and a1='1')and(b0='0'and b1='1'))or
              ((a0='1'and a1='0')and(b0='1'and b1='0'))or
              ((a0='1'and a1='1')and(b0='1'and b1='1'))
              else '0';
gr <='1' when ((a0='0'and a1='1')and(b0='0'and b1='0'))or
              ((a0='1'and a1='0')and(b0='0'and b1='0'))or
              ((a0='1'and a1='0')and(b0='0'and b1='1'))or
              ((a0='1'and a1='1')and(b0='0'and b1='0'))or
              ((a0='1'and a1='1')and(b0='0'and b1='1'))or
              ((a0='1'and a1='1')and(b0='1'and b1='0'))
              else'0';
ls <='1' when ((a0='0'and a1='0')and(b0='0'and b1='1'))or
              ((a0='0'and a1='0')and(b0='1'and b1='0'))or
              ((a0='0'and a1='0')and(b0='1'and b1='1'))or
              ((a0='0'and a1='1')and(b0='1'and b1='0'))or
              ((a0='0'and a1='1')and(b0='1'and b1='1'))or
              ((a0='1'and a1='0')and(b0='1'and b1='1'))
              else '0';
end Behavioral;

Figure 3.1: RTL Schematic design for When...else Comparator

maxybyte.com
Figure 3.1











Figure 3.2: Synthesis Schematic design for When...else Comparator

Figure 3.2











Figure 3.3: Waveform result for When...else Comparator

Figure 3.3











Boolean Comparator Complete VHDL Code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity BooleanComp_Source_beh is
    Port ( a0 : in STD_LOGIC;
           a1 : in STD_LOGIC;
           b0 : in STD_LOGIC;
           b1 : in STD_LOGIC;
           eq : out STD_LOGIC;
           gr : out STD_LOGIC;
           ls : out STD_LOGIC);
end BooleanComp_Source_beh;
architecture Behavioral of BooleanComp_Source_beh is
begin
--eq_0 is 1 if a0=b0 and a1 =0 and b1 =0.
  eq <= (not a0 and  not a1 and not b0 and not b1) or (not a0 and a1 and not b0 and b1) or (a0 and not a1 and b0 and not b1) or (a0 and b0 and a1 and b1);
  -- gr_0 is 1 if a0>b0 or if a0=b0 and a1 =1.
  gr <=  (not a0 and a1 and not b0 and not b1) or (a0 and not a1 and not b0 and not b1) or (a0 and not a1 and not b0 and b1) or(a0 and a1 and not b0 and not b1) or (a0 and a1 and not b0 and b1)or (a0 and a1 and b0 and not b1);
  -- ls_0 is 1 if a0<b0 or if a0=b0 and b1 =1.
  ls <= (not a0 and not a1 and not b0 and b1) or (not a0 and not a1 and b0 and not b1) or (not a0 and not a1 and b0 and b1) or (not a0 and a1 and b0 and not b1) or (not a0 and a1 and b0 and b1) or (a0 and not a1 and  b0 and b1);
end Behavioral;

Boolean Comparator Complete Testbench code

   library IEEE;
   use IEEE.STD_LOGIC_1164.ALL;
   entity BooleanComp_Source_tb is
--  Port ( );
   end BooleanComp_Source_tb;
   architecture Behavioral of BooleanComp_Source_tb is
   component BooleanComp_Source_beh
   Port (   a0 : in STD_LOGIC;
          a1 : in STD_LOGIC;
          b0 : in STD_LOGIC;
          b1 : in STD_LOGIC;
          eq : out STD_LOGIC;
          gr : out STD_LOGIC;
          ls : out STD_LOGIC);
   end component;
   signal a0_tb: STD_LOGIC;
   signal a1_tb: STD_LOGIC;
   signal b0_tb: STD_LOGIC;
   signal b1_tb: STD_LOGIC;
   signal eq_tb: STD_LOGIC;
   signal gr_tb: STD_LOGIC;
   signal ls_tb: STD_LOGIC;
   begin
    uut: BooleanComp_Source_beh port map 
(   a0=>a0_tb,
    a1=>a1_tb,
    b0=>b0_tb,
    b1=>b1_tb,
    eq=>eq_tb,
    gr=>gr_tb,
    ls=>ls_tb);
    stimulus: process
    begin
    a0_tb <='0';
    a1_tb <='0';
    b0_tb <='0';
    b1_tb <='0';
    wait for 20ns;
    a0_tb<='0';
    a1_tb<='0';
    b0_tb<='0';
    b1_tb<='1';
    wait for 20 ns;
    a0_tb<='0';
    a1_tb<='0';
    b0_tb<='1';
    b1_tb<='0';
    wait for 20 ns;
    a0_tb<='0';
    a1_tb<='0';
    b0_tb<='1';
    b1_tb<='1';
    wait for 20 ns;
    a0_tb<='0';
    a1_tb<='1';
    b0_tb<='0';
   b1_tb<='0';
    wait for 20 ns;
   a0_tb<='0';
    a1_tb<='1';
    b0_tb<='0';
    b1_tb<='1';
    wait for 20 ns;
    a0_tb<='0';
    a1_tb<='1';
    b0_tb<='1';
    b1_tb<='0';
    wait for 20 ns;
    a0_tb<='0';
    a1_tb<='1';
    b0_tb<='1';
    b1_tb<='1';
   wait for 20 ns;
   a0_tb<='1';
   a1_tb<='0';
   b0_tb<='0';
   b1_tb<='0';
   wait for 20 ns;
   a0_tb<='1';
   a1_tb<='0';
   b0_tb<='0';
   b1_tb<='1';
    wait for 20 ns;
    a0_tb<='1';
    a1_tb<='0';
    b0_tb<='1';
    b1_tb<='0';
    wait for 20 ns;
    a0_tb<='1';
    a1_tb<='0';
     b0_tb<='1';
     b1_tb<='1';
     wait for 20 ns;
     a0_tb<='1';
     a1_tb<='1';
     b0_tb<='0';
     b1_tb<='0';
     wait for 20 ns;
      a0_tb<='1';
     a1_tb<='1';
     b0_tb<='0';
     b1_tb<='1';
     wait for 20 ns;
     a0_tb<='1';
    a1_tb<='1';
     b0_tb<='1';
     b1_tb<='0';
     wait for 20 ns;
     a0_tb<='1';
    a1_tb<='1';
    b0_tb<='1';
    b1_tb<='1';
     wait for 20 ns;
     wait;
     end process;
end Behavioral;


o   Select  Comparator VHDL Complete code
library IEEE; use IEEE.STD_LOGIC_1164.ALL;
entity Comparator_select is
Port ( a : in STD_LOGIC_VECTOR(1 downto 0);
b : in STD_LOGIC_VECTOR(1 downto 0);
           eq_0 : out STD_LOGIC;
           gr_0 : out STD_LOGIC;
           ls_0 : out STD_LOGIC);
end Comparator_select;
architecture Selected of Comparator_select is
begin
with a & b
select
eq_0 <= '1' when "0000" | "0101" |"1010" |"1111" , '0' when others;
with a & b
select
gr_0 <= '1' when "0100" | "1000" |"1001" | "1100"|"1101" | "1110" , '0' when others; 
with a & b
select
ls_0 <= '1' when "0001" | "0010" | "0011"|"0110" |"0111" | "1011" ,  '0'  when others; 
end Selected;
o   Select  Comparator VHDL Complete Testbench code
library IEEE; use IEEE.STD_LOGIC_1164.ALL;

entity comparator_select_tb is

 --Port ( );

end comparator_select_tb;

architecture Behavioral of comparator_select_tb is

component Comparator_select
Port ( a : in STD_LOGIC_VECTOR(1 downto 0);
 b : in STD_LOGIC_VECTOR(1 downto 0);
            eq_0: out STD_LOGIC;
             gr_0 : out STD_LOGIC;
             ls_0 : out STD_LOGIC);
  end component;
  signal a_tb: STD_LOGIC_VECTOR(1 downto 0);
  signal b_tb: STD_LOGIC_VECTOR(1 downto 0);
  signal eq_0: STD_LOGIC;
  signal gr_0: STD_LOGIC;
  signal ls_0: STD_LOGIC;
begin
  uut: Comparator_select port map ( a   => a_tb,  b    => b_tb,    eq_0 => eq_0,    gr_0 => gr_0,     ls_0  => ls_0);                                   
stimulus: process
begin
a_tb <= "00" ;
b_tb <= "00";
wait for 20 ns;
a_tb <= "00" ;
b_tb <= "01" ;
wait for 20 ns;
a_tb <= "00" ;
b_tb <= "10" ;
wait for 20 ns;
a_tb <= "00" ;
b_tb <= "11" ;
wait for 20 ns;
a_tb <= "01" ;
b_tb <= "00";
wait for 20 ns;
a_tb <= "01" ;
b_tb <= "01" ;
wait for 20 ns;
a_tb <= "01" ;
b_tb <= "10" ;
wait for 20 ns;
a_tb <= "01" ;
b_tb <= "11" ;
wait for 20 ns;
a_tb <= "10" ;
b_tb <= "00";
wait for 20 ns;
a_tb <= "10" ;
b_tb <= "01" ;
wait for 20 ns;
a_tb <= "10" ;
b_tb <= "10" ;
wait for 20 ns;
a_tb <= "10" ;
b_tb <= "11" ;
wait for 20 ns;
a_tb <= "11" ;
b_tb <= "00";
wait for 20 ns;
a_tb <= "11" ;
b_tb <= "01" ;
wait for 20 ns;
a_tb <= "11" ;
b_tb <= "10" ;
wait for 20 ns;
a_tb <= "11" ;
b_tb <= "11" ;
wait for 20 ns;
wait;
    end process;
end Behavioral;

When else Comparator Complete Vhdl code.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity when_source_beh is
    Port ( a0 : in STD_LOGIC;
           a1 : in STD_LOGIC;
           b0 : in STD_LOGIC;
           b1 : in STD_LOGIC;
           eq : out STD_LOGIC;
           gr : out STD_LOGIC;
           ls : out STD_LOGIC);
end when_source_beh;
architecture Behavioral of when_source_beh is
begin
eq <='1' when ((a0='0'and a1='0')and(b0='0'and b1='0'))or
              ((a0='0'and a1='1')and(b0='0'and b1='1'))or
              ((a0='1'and a1='0')and(b0='1'and b1='0'))or
              ((a0='1'and a1='1')and(b0='1'and b1='1'))
              else '0';
gr <='1' when ((a0='0'and a1='1')and(b0='0'and b1='0'))or
              ((a0='1'and a1='0')and(b0='0'and b1='0'))or
              ((a0='1'and a1='0')and(b0='0'and b1='1'))or
              ((a0='1'and a1='1')and(b0='0'and b1='0'))or
              ((a0='1'and a1='1')and(b0='0'and b1='1'))or
              ((a0='1'and a1='1')and(b0='1'and b1='0'))
              else'0';
ls <='1' when ((a0='0'and a1='0')and(b0='0'and b1='1'))or
              ((a0='0'and a1='0')and(b0='1'and b1='0'))or
              ((a0='0'and a1='0')and(b0='1'and b1='1'))or
              ((a0='0'and a1='1')and(b0='1'and b1='0'))or
              ((a0='0'and a1='1')and(b0='1'and b1='1'))or
              ((a0='1'and a1='0')and(b0='1'and b1='1'))
              else '0';
end Behavioral;


    When else Comparator Complete Vhdl Testbench code.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity when_source_tb is
--  Port ( );
end when_source_tb;
architecture Behavioral of when_source_tb is
component when_source_beh
 Port ( a0 : in STD_LOGIC;
          a1 : in STD_LOGIC;
          b0 : in STD_LOGIC;
          b1 : in STD_LOGIC;
          eq : out STD_LOGIC;
          gr : out STD_LOGIC;
          ls : out STD_LOGIC);
          end component;
signal a0_tb: STD_LOGIC;
signal a1_tb: STD_LOGIC;
signal b0_tb: STD_LOGIC;
signal b1_tb: STD_LOGIC;
signal eq_tb: STD_LOGIC;
signal gr_tb: STD_LOGIC;
signal ls_tb: STD_LOGIC;
begin
uut: when_source_beh port map 
( a0=>a0_tb,
  a1=>a1_tb,
  b0=>b0_tb,
  b1=>b1_tb,
  eq=>eq_tb,
  gr=>gr_tb,
  ls=>ls_tb);
stimulus: process
begin
a0_tb <='0';
a1_tb <='0';
b0_tb <='0';
b1_tb <='0';
wait for 15ns;
a0_tb<='0';
a1_tb<='0';
b0_tb<='0';
b1_tb<='1';
wait for 15 ns;
a0_tb<='0';
a1_tb<='0';
b0_tb<='1';
b1_tb<='0';
wait for 15 ns;
a0_tb<='0';
a1_tb<='0';
b0_tb<='1';
b1_tb<='1';
wait for 15 ns;
a0_tb<='0';
a1_tb<='1';
b0_tb<='0';
b1_tb<='0';
wait for 15 ns;
a0_tb<='0';
a1_tb<='1';
b0_tb<='0';
b1_tb<='1';
wait for 15 ns;
a0_tb<='0';
a1_tb<='1';
b0_tb<='1';
b1_tb<='0';
wait for 15 ns;
a0_tb<='0';
a1_tb<='1';
b0_tb<='1';
b1_tb<='1';
wait for 15 ns;
a0_tb<='1';
a1_tb<='0';
b0_tb<='0';
b1_tb<='0';
wait for 15 ns;
a0_tb<='1';
a1_tb<='0';
b0_tb<='0';
b1_tb<='1';
wait for 15 ns;
a0_tb<='1';
a1_tb<='0';
b0_tb<='1';
b1_tb<='0';
wait for 15 ns;
a0_tb<='1';
a1_tb<='0';
b0_tb<='1';
b1_tb<='1';
wait for 15 ns;
a0_tb<='1';
a1_tb<='1';
b0_tb<='0';
b1_tb<='0';
wait for 15 ns;
a0_tb<='1';
a1_tb<='1';
b0_tb<='0';
b1_tb<='1';
wait for 15 ns;
a0_tb<='1';
a1_tb<='1';
b0_tb<='1';
b1_tb<='0';
wait for 15 ns;
a0_tb<='1';
a1_tb<='1';
b0_tb<='1';
b1_tb<='1';
wait for 15 ns;
wait;
end process;
end Behavioral;

Conclusion

The Comparator operation is performed using Vivado 2018.2 version. The ideal about comparator is that it takes “N” number of input thus providing 3 output thus the GR,LS,EQ. In addition, the source code was compiled and simulated to verify the correctness of the program instruction.


1 comment:

  1. Thanks for sharing this man. You save me.

    ReplyDelete

Note: only a member of this blog may post a comment.

New Post

New style string formatting in Python

In this section, you will learn the usage of the new style formatting. Learn more here . Python 3 introduced a new way to do string formatti...