0

以下代码是 Xilinx ISE 14.7 中的 VDHL 模块,它计算去抖按钮按下 (iXXX),测试它们是否已达到最大值,并将每个累积输入的“值”输出到将显示的 std_logic_vector (oXXX)在 7 段 LED 上(未显示显示多路复用器和逻辑)。复位 (clrXX) 是板上的开关 (Digilent Spartan 3)。

尝试在 XILINX ISE 中合成或检查语法时,我收到以下错误:

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.

我怎样才能解决这个问题?我对 VHDL 相当陌生,不知道从哪里开始。

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;
4

2 回答 2

1

您的问题可能与您从多个进程驱动信号 ( oSTRIKE_s, oBALL_s, ) 的事实有关。oOUT_s将此视为短路(当不同的过程在值上不一致时,您期望什么值?)。

那么为什么它不会在编译和/或模拟时产生错误?

作为大多数不了解多驱问题、VHDL解析函数和解析类型的人(也就是很多VHDL程序员甚至老师),你总是使用STD_LOGIC内置解析函数的类型计算多个驱动过程的结果值。它有效(通常给出很多X值)......仅用于模拟。如果您使用了未解析的类型 ( STD_ULOGIC),您将在编译或仿真时遇到错误,因为这些类型不支持多驱动情况。

为什么它在合成中不起作用?

您的合成器会尝试将您的设计映射到目标(Spartan FPGA)的可用硬件资源上。碰巧您的目标没有配备可用于实现您的虚假设计的三态缓冲器。所以合成器会产生错误。我写这篇文章是偶然的,因为如果它是另一个能够实现这一点的目标,你可以对它进行编程并……融合它,这要归功于你的短路。可能有什么东西会在为时已晚之前阻止你,但你永远不知道......所以你很幸运,毕竟。

那该怎么办?

  1. 永远不要使用STD_LOGIC并且STD_LOGIC_VECTOR当您不设计合理使用多个驱动器的东西时。也就是说,在任何时候所有进程都以'Z'(高阻抗)驱动信号的设计,至多驱动强值('0''1')的信号除外。在大多数情况下,您不想这样做,您必须使用STD_ULOGICand STD_ULOGIC_VECTOR。如果您的老师坚持让您使用STD_LOGICand STD_LOGIC_VECTOR,请将其发送给我。
  2. 从一个处理所有情况(重置、状态...)的单个进程中驱动任何信号。
于 2015-10-31T06:46:58.673 回答
0

终于明白了!问题是多个进程将值分配给同一信号。这就是我纠正错误的方式:

注意标志信号 {Bmax_s、Smax_s 和 Omax_s}。一个进程使用它们向其他进程指示它已达到其最大计数。然后,每个时钟周期,每个进程使用一个或多个标志来决定是否清除,或者在 OUT_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;

下面是来自测试台的模拟输出图像,该测试台重置并增加球和击球,直到发生 3 次击球......

ISim 测试台

对我的第一个 VHDL 项目来说还不错:D

于 2015-10-31T21:43:04.757 回答