0

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;
  • Is there a reason why you do not look at the logfile and post the error message? – Renaud Pacalet Oct 31 '15 at 06:32
  • 1
    OK I found 'Multisource Error' on all the signals with naming convention: o_XXX_s. and it has added "_lut" and "_cy" to some of them... Do I just need more signals? Does it have to do with them being present in different processes? – Boone Angel Oct 31 '15 at 06:49
  • Good to know. If you have time, please edit your question and provide a **minimal** example with the error message. SO questions are read by many visitors and the better they are the more useful they are for others with similar problems. And accept the answer that you agree with. – Renaud Pacalet Oct 31 '15 at 06:54

2 Answers2

1

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?

  1. Never use 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.
  2. Drive any signal from one single process in which you deal with all situations (reset, states...).
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
0

Finally got it! The problem was multiple processes assigning values to the same signal. This was how I corrected the error:

Notice the flag signals {Bmax_s, Smax_s, and Omax_s}. They are used by one process to indicate to other processes that it has reached its max count. Then, each clock cycle, every process uses one or more flags to decide whether to clear, or in the case of OUT_PROCESS increment, its output signal and/or update its own flag.

Now every signal is only assigned by a single process!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity BSO_cnt is
    Port ( inBALL       : in  STD_LOGIC;
           inSTRIKE     : in  STD_LOGIC;
           inOUTS       : in  STD_LOGIC;
           inclrBS      : in  STD_LOGIC;
           inclrOUT     : in  STD_LOGIC;
           CLK          : in  STD_LOGIC;
           outBALL      : out  STD_LOGIC_VECTOR (1 downto 0);
           outSTRIKE    : out  STD_LOGIC_VECTOR (1 downto 0);
           outOUTS      : out  STD_LOGIC_VECTOR (1 downto 0));
end BSO_cnt;

architecture Behavioral of BSO_cnt is
    --inputs
    SIGNAL inBALL_s     :   STD_LOGIC;
    SIGNAL inSTRIKE_s   :   STD_LOGIC;
    SIGNAL inOUTS_s     :   STD_LOGIC;
    --outputs
    SIGNAL outBALL_s    :   STD_LOGIC_VECTOR(1 DOWNTO 0);
    SIGNAL outSTRIKE_s  :   STD_LOGIC_VECTOR(1 DOWNTO 0);
    SIGNAL outOUTS_s    :   STD_LOGIC_VECTOR(1 DOWNTO 0);
    --max count flags
    SIGNAL maxBALL      :   STD_LOGIC;
    SIGNAL maxSTRIKE    :   STD_LOGIC;
    SIGNAL maxOUTS      :   STD_LOGIC;

begin

    --assign signals to module outputs
    outBALL     <=  outBALL_s;
    outSTRIKE   <=  outSTRIKE_s;
    outOUTS     <=  outOUTS_s;

    --count ball pushes & update ball counter
    BALL_PROCESS: PROCESS(CLK)
    BEGIN   
        --wait for postive edge of clock
        IF rising_edge(CLK) THEN
            --check for clear ball/strike switch 
            IF (inclrBS = '1') THEN
                outBALL_s   <=  (OTHERS =>  '0');
            --check for any max count flags 
            ELSIF (maxSTRIKE = '1') OR (maxBALL = '1') OR (maxOUTS = '1') THEN
                --clear ball count
                outBALL_s   <=  (OTHERS =>  '0');
                --clear ball max count flag
                maxBALL     <=  '0';
            --check for change of ball button state
            ELSIF (inBALL_s /= inBALL) THEN
                --if pressed 
                IF inBALL = '1' THEN
                    inBALL_s        <=  inBALL;
                    -- check for walk
                    IF (outBALL_s = "11") THEN
                        --set flag
                        maxBALL <=  '1';
                    ELSE
                        --increment ball counter
                        outBALL_s   <=  STD_LOGIC_VECTOR(UNSIGNED(outBALL_s) + 1);
                    END IF;
                --if released   
                ELSE
                    inBALL_s    <=  inBALL;
                END IF;             
            END IF;         
        END IF;     
    END PROCESS;

    --Count strike pushes, and update strike counter
    STRIKE_PROCESS: PROCESS(CLK)
    BEGIN   
        --wait for positive edge of clock
        IF rising_edge(CLK) THEN
            --check for clr ball/strike switch
            IF inclrBS = '1' THEN
                outSTRIKE_s <=  (OTHERS =>  '0');
            --check for any max counts reached & update strike count
            ELSIF (maxSTRIKE = '1') OR (maxBALL = '1') OR (maxOUTS = '1') THEN
                outSTRIKE_s <=  (OTHERS =>  '0');
                --reset flag
                maxSTRIKE   <=  '0';
            --check for strike button state change
            ELSIF (inSTRIKE_s /= inSTRIKE) THEN
                --if pressed increment strike count
                IF inSTRIKE = '1' THEN
                    inSTRIKE_s      <=  inSTRIKE;
                    --check for strikeout 
                    IF (outSTRIKE_s = "10") THEN
                        --set flag
                        maxSTRIKE   <=  '1';
                    ELSE
                        --increment strike count
                        outSTRIKE_s     <=  STD_LOGIC_VECTOR(UNSIGNED(outSTRIKE_s) + 1);
                    END IF;
                --if released   
                ELSE
                    inSTRIKE_s  <=  inSTRIKE;
                END IF;             
            END IF;
        END IF; 
    END PROCESS;

    --Count out pushes, and update out counter
    OUT_PROCESS: PROCESS(CLK)
    BEGIN
        --wait for positive clock edge
        IF rising_edge(CLK) THEN
            --check for clear out switch
            IF inclrOUT = '1' THEN
                outOUTS_s   <=  (OTHERS =>  '0');
            --check for max out count
            ELSIF maxOUTS = '1' THEN
                outOUTS_s   <=  (OTHERS =>  '0');
                --clear flag
                maxOUTS     <=  '0';
            --check for strikeout
            ELSIF maxSTRIKE = '1' THEN
                --check for max outs
                IF (outOUTS_s = "10") THEN
                    --set max outs flag
                    maxOUTS <=  '1';
                ELSE
                    --increment outs
                    outOUTS_s   <=  STD_LOGIC_VECTOR(UNSIGNED(outOUTS_s) + 1);
                END IF;
            --check if button has changed states
            ELSIF (inOUTS_s /= inOUTS) THEN
                --if pressed
                IF inOUTS = '1' THEN
                    inOUTS_s    <=  inOUTS;
                    --check for change of inning
                    IF (outOUTS_s = "10") THEN
                        maxOUTS <=  '1';
                    ELSE
                        --increment outs
                        outOUTS_s   <=  STD_LOGIC_VECTOR(UNSIGNED(outOUTS_s) + 1);
                    END IF;
                --if released
                ELSE
                    inOUTS_s    <=  inOUTS;
                END IF;
            END IF;
        END IF;
    END PROCESS;

end Behavioral;

Below is an image of the simulation output from a test bench that resets, and increments balls & strikes until 3 strikes occur...

ISim TestBench

not bad for my first VHDL project :D