2

I'm working on a VHDL project where I need to implement a comparator between two 16-bit std_logic_vector signals, a and b. The goal is to check if a is greater than, less than, or equal to b.

The issue I'm facing is that after synthesis, the comparator uses a significant amount of resources (image below) specifically, it uses 2 CARRY4 blocks and too many LUTs. My professor, who assigned this task, explicitly stated that I must not convert a and b to integer, unsigned, or any other numeric type. They must be compared as std_logic_vector.

Is there a way to implement a more resource-efficient comparator under these constraints? Any ideas or patterns to reduce the number of LUTs or avoid the use of carry chains would be appreciated.

Here is the code :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity comparator is
    Port (
        clk, rst : in std_logic;
        a, b     : in std_logic_vector (15 downto 0);
        max, min : out std_logic_vector (15 downto 0)
    );
end comparator;

architecture Behavioral of comparator is

signal max_int, min_int : std_logic_vector (15 downto 0);
begin

process (clk)
begin   
    if (rst = '1') then
    
        min_int <= (others => '0');
        max_int <= (others => '0');
       
    elsif (rising_edge(clk)) then
    
        if (a <= b) then
            min_int <= a;
            max_int <= b;
        else
            min_int <= b;
            max_int <= a;
        end if;
        
    end if;
    
end process;

max <= max_int;
min <= min_int; 

end behavioral;

https://i.sstatic.net/0b7SOv8C.png

9
  • 1
    How many CARRY4 blocks and LUTs do you expect it to use? Commented Jun 6 at 17:54
  • 1
    This is possible because you are using the Implicit version of "<=", rather than the arithmetic versions from numeric_std or you would get using an integer. Why not try a version using these and see what they implement, which I assume would be the most optimal as they are the most used. You then have a target to aim for and know what an "efficient" solution is. Commented Jun 6 at 18:13
  • 4
    Im saying do it, on your own, to get an idea of what an "ideal" solution is. And then you have an idea of what "a lot" of LUTs actually is. Commented Jun 6 at 18:35
  • 3
    Well what are you expecting? How do you know what a "significant amount of resources" is? Have you been given a target utilisation? Commented Jun 6 at 23:04
  • 1
    You might want to investigate how engineers implemented comparators in real gates to get a feeling, for example 74HC85. However, LUTs are a short cut of n-input gates. Commented Jun 7 at 15:36

2 Answers 2

2

If the comparisons are unsigned and your prof does not know it already, you can try the numeric_std_unsigned package that overloads arithmetic operators for std_logic_vector:

use ieee.numeric_std_unsigned.all;
...
if a < b then
  max_int <= b;
  min_int <= a;
else
  max_int <= a;
  min_int <= b;
end if;

As, after seeing this, they could add a new constraint to prevent the use of ieee.numeric_std_unsigned, you can try the following MSB-to-LSB recursive comparison:

function is_less(a: std_logic_vector; b: std_logic_vector) return boolean is
  constant len: natural := a'length;
  constant va: std_logic_vector(1 to len) := a;
  constant vb: std_logic_vector(1 to len) := b;
begin
  if len = 0 then
    return false;
  elsif va(1) /= vb(1) then
    return va(1) = '0';
  else
    return is_less(va(2 to len), vb(2 to len));
  end if;
end function is_less;

...

if is_less(a, b) then
  max_int <= b;
  min_int <= a;
else
  max_int <= a;
  min_int <= b;
end if;

The 3 constants declared and computed in function is_less are just a trick to re-index the bits of the a and b parameters such that the code is independent from the way a and b have been declared. The function works even if a is a std_logic_vector(1 to 5) and b is a std_logic_vector(7 downto 3). Note that there will be an error at compilation or at simulation time if the two parameters have different lengths.

Sign up to request clarification or add additional context in comments.

2 Comments

Can the is_less function be expected to give different synthesis results than the < operator?
@mkrieger1 Yes, because it does not use arithmetic. So synthesizers that do something special for arithmetic may infer something different with this style. Like synthesizers for FPGAs with dedicated hardware resources (carry chains, DSP blocks...), or for ASICs with dedicated algorithms for high speed arithmetic (carry select, carry look-ahead...) But of course this is highly dependent on the synthesizer. In my opinion, if a synthesizer does something different with my proposal, it could be smaller (not sure) but likely also slower. But as they seem to ask for something non-arithmetic...
1

You could also try simply xoring the two different vectors to see where they differ and then check the highest differing bit from the inputs to determine which one is bigger:

architecture am9417 of comparator is
  signal max_int, min_int : std_logic_vector (15 downto 0);
  signal xorred : std_logic_vector(max_int'range);
begin

xorred <= a xor b;

process (clk, rst)
begin   
    if (rst = '1') then
        min_int <= (others => '0');
        max_int <= (others => '0');
    elsif rising_edge(clk) then

        -- By default, a is larger than b
        max_int <= a;
        min_int <= b;

        for i in xorred'range loop
            -- Differing bit found
            if xorred(i) = '1' then
                -- B is larger
                if b(i) = '1' then
                   max_int <= b;
                   min_int <= a;
                end if;
                exit; -- Stop comparing further
            end if;
            
        end loop;
    end if;
    
 end process;

max <= max_int;
min <= min_int; 

end architecture am9417;

This answers your first question, with no type-conversions or casting.

However, what I've tested, all the alternatives here consume same amount of resources. You still have to compare 16 bits of two values.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.