The following code is a VDHL module in Xilinx ISE 14.7 that counts debounced button presses (iXXX), tests to see if they have reached a max, and outputs a "value" for each accumulated input to a std_logic_vector (oXXX) that will be displayed on a 7-segment LED (display mux & logic not shown). The resets (clrXX) are switches on the board (Digilent Spartan 3).
When trying to synthesize or checking syntax in XILINX ISE, I get the following errors:
Xst:528 - Multi-source in Unit <BSO_cnt> on signal <Mcount_oOUT_s_cy<0>>;
this signal is connected to multiple drivers.
Xst:528 - Multi-source in Unit <BSO_cnt> on signal <Mcount_oOUT_s_lut<1>>;
this signal is connected to multiple drivers.
Xst:528 - Multi-source in Unit <BSO_cnt> on signal <Mcount_oBALL_s_cy<0>>;
this signal is connected to multiple drivers.
Xst:528 - Multi-source in Unit <BSO_cnt> on signal <Mcount_oBALL_s_lut<1>>;
this signal is connected to multiple drivers.
Xst:528 - Multi-source in Unit <BSO_cnt> on signal <Mcount_oBALL_s_lut<2>>;
this signal is connected to multiple drivers.
Xst:528 - Multi-source in Unit <BSO_cnt> on signal <Mcount_oSTRIKE_s_cy<0>>;
this signal is connected to multiple drivers.
Xst:528 - Multi-source in Unit <BSO_cnt> on signal
<Mcount_oSTRIKE_s_lut<1>>; this signal is connected to multiple drivers.
How can I fix this? I am fairly new to VHDL, and not sure where to start.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity BSO_cnt is
Port ( iBALL : in STD_LOGIC;
iSTRIKE : in STD_LOGIC;
iOUT : in STD_LOGIC;
clrBS : in STD_LOGIC;
clrOUT : in STD_LOGIC;
CLK : in STD_LOGIC;
oBALL : out STD_LOGIC_VECTOR (2 downto 0);
oSTRIKE : out STD_LOGIC_VECTOR (1 downto 0);
oOUT : out STD_LOGIC_VECTOR (1 downto 0));
end BSO_cnt;
architecture Behavioral of BSO_cnt is
SIGNAL iBALL_s : STD_LOGIC;
SIGNAL iSTRIKE_s : STD_LOGIC;
SIGNAL iOUT_s : STD_LOGIC;
SIGNAL oBALL_s : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL oSTRIKE_s : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL oOUT_s : STD_LOGIC_VECTOR(1 DOWNTO 0);
Begin
oBALL <= oBALL_s;
oSTRIKE <= oSTRIKE_s;
oOUT <= oOUT_s;
BALL_PROCESS: PROCESS(CLK)
BEGIN
IF rising_edge(CLK) THEN
IF (clrBS = '1') THEN
oBALL_s <= (OTHERS => '0');
ELSIF (iBALL_s /= iBALL) THEN
IF (iBALL = '1') THEN
iBALL_s <= iBALL;
oBALL_s <= STD_LOGIC_VECTOR(UNSIGNED(oBALL_s) + 1);
IF (oBALL_s = "100") THEN
oBALL_s <= (OTHERS => '0');
oSTRIKE_s <= (OTHERS => '0');
END IF;
END IF;
ELSE
iBALL_s <= iBALL;
END IF;
END IF;
END PROCESS;
STRIKE_PROCESS: PROCESS(CLK)
BEGIN
IF rising_edge(CLK) THEN
IF (clrBS = '1') THEN
oSTRIKE_s <= (OTHERS => '0');
ELSIF (iSTRIKE_s /= iSTRIKE) THEN
IF (iSTRIKE = '1') THEN
iSTRIKE_s <= iSTRIKE;
oSTRIKE_s <= STD_LOGIC_VECTOR(UNSIGNED(oSTRIKE_s) + 1);
IF (oSTRIKE_s = "11") THEN
oSTRIKE_S <= (OTHERS => '0');
oBALL_s <= (OTHERS => '0');
oOUT_s <= (OTHERS => '0');
END IF;
END IF;
ELSE
iSTRIKE_s <= iSTRIKE;
END IF;
END IF;
END PROCESS;
OUT_PROCESS: PROCESS(CLK)
BEGIN
IF rising_edge(CLK) THEN
IF (clrOUT = '1') THEN
oOUT_s <= (OTHERS => '0');
ELSIF (iOUT_s /= iOUT) THEN
IF (iOUT = '1') THEN
iOUT_s <= iOUT;
oOUT_s <= STD_LOGIC_VECTOR(UNSIGNED(oOUT_s) + 1);
IF (oOUT_s = "11") THEN
oOUT_s <= (OTHERS => '0');
oBALL_s <= (OTHERS => '0');
oSTRIKE_s <= (OTHERS => '0');
END IF;
END IF;
ELSE
iOUT_s <= iOUT;
END IF;
END IF;
END PROCESS;
end Behavioral;
Your problem has probably something to do with the fact that you drive signals (oSTRIKE_s
, oBALL_s
, oOUT_s
) from several processes. Think of this as short circuits (what value do you expect when the different processes do not agree on the value?).
Why then doesn't it produce errors at compilation and / or simulation?
As most people who do not know about the multiple drive problem, the resolution functions and the resolved types of VHDL (that is, a lot of VHDL programmers and even teachers), you always use the STD_LOGIC
type that has a built-in resolution function to compute the resulting value of multiple driving processes. And it works (usually giving a lot of X
values)... for simulation only. If you had used an unresolved type (STD_ULOGIC
) instead you would have had an error at compilation or simulation because these types do not support multiple drive situations.
Why does it not work in synthesis?
Your synthesiser tries to map your design on the available hardware resources of your target (Spartan FPGA). By chance your target is not equipped with the three-state buffers that could be used to implement your bogus design. So the synthesiser raises errors. I wrote by chance because, if it had been another target capable of implementing this, you could have programmed it and... fuse it, thanks to your nice short circuits. Something would probably have prevented you before it is to late but you never know... So you are lucky, after all.
What to do then?
STD_LOGIC
and STD_LOGIC_VECTOR
when you do not design something that reasonably makes use of multiple drive. That is, a design where at any time all processes drive the signal with 'Z'
(high impedance) except, at most, one that drives a strong value ('0'
or '1'
). In most cases you do not want to do this and you must use STD_ULOGIC
and STD_ULOGIC_VECTOR
. If your teacher insists that you use STD_LOGIC
and STD_LOGIC_VECTOR
, send it to me.