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;
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:
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.