Search code examples
vhdlfpga

vhdl input not used


I'm trying to develop an 8-bit binary to BCD VHDL module, but the Xilinx suite is optimizing my Bin_in signal to always be ground. I've found several other threads that mention the similar problems (in different coding contexts) but the answers provided seem to concern algorithms where the complete truth table for the output isn't declared. I've also found examples of an 8-bit to BCD converter with a similar algorithm as mine. If I've developed my code correctly the process should run any time the Bin_in input changes, so I don't understand why the tools would optimize it out. Any info or help is much appreciated.

This is the warning from synthesis:

WARNING:Xst:647 - Input <Bin_in<7:1>> is never used. This port will be
preserved and left unconnected if it belongs to a top-level block or
it belongs to a sub-block and the hierarchy of this sub-block is
preserved.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.numeric_std.ALL;

entity B8_to_4BCD is
port (Bin_in : in std_logic_vector (7 downto 0);
      BCD0, BCD1, BCD2 : out std_logic_vector (3 downto 0)
     );

end entity B8_to_4BCD;

architecture Behavioral of B8_to_4BCD is

begin

--Sequential code follows, runs if Bin_in changes
process (Bin_in)
--Holders for Bin_in and output BCD
variable input : std_logic_vector (7 downto 0);
variable output : std_logic_vector (11 downto 0);

begin
    input  := Bin_in;          --Assign Bin_in to input
    output := (others => '0'); --Set output to all zeroes

    for I in 1 to 8 loop
        --Check ones for greater than or equal to 5
        if output(3 downto 0) >= "0101" then
            output(3 downto 0) := output(3 downto 0) + "0011";

        --Check tens for greater than or equal to 5
        elsif output(7 downto 4) >= "0101" then
            output(7 downto 4) := output(7 downto 4) + "0011";

        --Check hundreds for greater than or equal to 5
        elsif output(11 downto 8) >= "0101" then
            output(11 downto 8) := output(11 downto 8) + "0011";
        else

        end if;

        output := output(11 downto 1) & input(7); --Shift output left one and move input(7) into LSB
        input := input(6 downto 0) & '0';         --Shift input left one and pad with zero

    end loop;

    BCD0 <= output(3 downto 0);
    BCD1 <= output(7 downto 4);
    BCD2 <= output(11 downto 8);

end process;

end Behavioral;

Solution

  • In addition to the issue Paebbels raised, that the if statements should be independent, there's also an issue with the shift left for output.

    The following is the corrected for loop:

        for i in 1 to 8 loop
            if output(3 downto 0) >= "0101" then
                output(3 downto 0) := output(3 downto 0) + "0011";
            end if;
            --check tens for greater than or equal to 5
            if output(7 downto 4) >= "0101" then
                output(7 downto 4) := output(7 downto 4) + "0011";
            end if;
            --check hundreds for greater than or equal to 5
            if output(11 downto 8) >= "0101" then
                output(11 downto 8) := output(11 downto 8) + "0011";            
            end if;
            output := output(10 downto 0) & input(7);       --shift output left one and move input(7) into lsb
            input := input(6 downto 0) & '0' ;              --shift input left one and pad with zero;
         end loop;
    

    And with a testbench:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity bin8bcd_tb is
    end entity;
    
    architecture foo of bin8bcd_tb is
        signal bin: std_logic_vector (7 downto 0) := (others => '0');
        -- (initialized to prevent those annoying metavalue reports)
    
        signal bcd: std_logic_vector (11 downto 0);
    
    begin
    
    DUT:
        entity work.b8_to_4bcd
            port map (
                bin_in => bin,
                bcd0 => bcd(3 downto 0),
                bcd1 => bcd(7 downto 4),
                bcd2 => bcd(11 downto 8)
            );
    
    STIMULUS:
        process
    
        begin
            for i in 0 to 255 loop
                bin <= std_logic_vector(to_unsigned(i,8));
                wait for 1 ns;
            end loop;
            wait for 1 ns;
            wait;
        end process;
    end architecture;
    

    that gives:

    bin8_to_4bcd.png (clickable)

    Matching values for the input binary (radix decimal) and the output BCD (radix hex).

    You'd expect the synthesis output to match the simulation. Note the warning told you Bin_in<7:1> didn't change, and LSB did (which would have matched your simulation, it matched mine).

    Simulation before synthesis is for those of us who are lousy at proof reading.