Search code examples
comparisonvhdlsynthesisvivadohardware

How is /= translated to actual hardware in vhdl


I am a beginner in VHDL/FPGA programming. I want to compare two 32-bit std_logic_vectors. I am currently using:

      if ( RX_FRAME(to_integer(s_data_counter)).Data /= REF_FRAME(to_integer(s_data_counter)).Data ) then
        s_bad_frame <= '1';
        state <= DONE;
      end if;

Here RX_FRAME and REF_FRAME are 2 arrays of std_logic_vector(31 downto 0)

I want to know how the synthesis tool translates /= into hardware. Is it advisable to use this? Or should I do an XOR of the concerned vectors and check the resulting vector against zeros? In case I do an XOR and check against zeroes, doesn't it increase the amount of hardware needed? I am using Vivado Design Suite 2015.3.


Solution

  • As Morten already presented, compare operations are implemented in LUTs doing some kind of X(N)OR and AND/(N)OR aggregation.

    But it could be faster ...
    FPGAs have fast carry chains, which can be used to speed up compare operations with wide inputs, but synthesis tools mostly don't utilize this special resources.

    How to do an equality comparation using a carry chain?
    Carry chains can be implemented as kill-propagate chains. This naming comes from ripple carry adders, wherein a carry out can be generated, propagated from carry in or be killed.

    A comparator starts with an active carry in (all is equal). Each step computes in the LUT: An = Bn. If yes, propagate the carry bit else kill it.

    If the carry out is high (the initial value has survived the chain) all bits were equal.

    Appendix for Morten Zilmer

    I don't have an example code for the equal or unequal operation, but I have a similar example for prefix and and prefix or operators using carry chains to speed up computation for wide inputs.

    • prefix_and calculates: y(i) <= '1' when x(i downto 0) = (i downto 0 => '1') else '0'; Explanation:
      The resulting vector is 1 until the first 0 is found, after that it is 0.
      Or in other words: The first zero found at position i while going from 0 to n kills all remaining bits regardless of the input bits.

    • prefix_or calculates: y(i) <= '0' when x(i downto 0) = (i downto 0 => '0') else '1';

      Explanation:
      The resulting vector is 0 until the first 1 is found, after that it is 1.
      Or in other words: The first one found at position i while going from 0 to n generates an one and propagates it to all remaining bits regardless of the input bits.

    The following code is a generic VHDL description of prefix_and. It is vendor independent, but uses special primitives (MUXCY) on Xilinx FPGAs.

    architecture rtl of arith_prefix_and is
    begin
      y(0) <= x(0);
      gen1: if N > 1 generate
        signal  p : unsigned(N-1 downto 1);
      begin
        p(1) <= x(0) and x(1);
        gen2: if N > 2 generate
          p(N-1 downto 2) <= unsigned(x(N-1 downto 2));
    
          -- Generic Carry Chain through Addition
          genGeneric: if VENDOR /= VENDOR_XILINX generate
            signal  s : std_logic_vector(N downto 1);
          begin
            s <= std_logic_vector(('0' & p) + 1);
            y(N-1 downto 2) <= s(N downto 3) xor ('0' & x(N-1 downto 3));
          end generate genGeneric;
    
          -- Direct Carry Chain by MUXCY Instantiation
          genXilinx: if VENDOR = VENDOR_XILINX generate
            component MUXCY
              port (
                S  : in  std_logic;
                DI : in  std_logic;
                CI : in  std_logic;
                O  : out std_logic
              );
            end component;
            signal  c : std_logic_vector(N-1 downto 0);
          begin
            c(0) <= '1';
            genChain: for i in 1 to N-1 generate
              mux : MUXCY
                port map (
                  S  => p(i),
                  DI => '0',
                  CI => c(i-1),
                  O  => c(i)
                );
            end generate genChain;
            y(N-1 downto 2) <= c(N-1 downto 2);
          end generate genXilinx;
    
        end generate gen2;
        y(1) <= p(1);
      end generate gen1;
    end architecture;
    

    Source: PoC.arith.prefix_and