【问题标题】:Type mismatch error in VHDL?VHDL中的类型不匹配错误?
【发布时间】:2014-02-03 04:28:11
【问题描述】:

我正在设计一个 1 位 ALU 并使用结构化方法。出于某种原因,即使我只对所有内容都使用 std_logic_vectors,我也会不断收到类型不匹配错误。我看不出有什么问题?

代码如下: 1 位 ALU:

LIBRARY ieee; 
USE ieee.std_logic_1164.ALL; 
USE ieee.std_logic_arith.ALL; 
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;

ENTITY alu1 is

PORT(
    a        : IN STD_LOGIC_VECTOR; 
    b        : IN STD_LOGIC_VECTOR; 
    op       : IN STD_LOGIC_VECTOR(2 DOWNTO 0); 
    result   : OUT STD_LOGIC_VECTOR; 
    cout     : OUT STD_LOGIC; 
    zero     : OUT STD_LOGIC); 
END alu1;

ARCHITECTURE structure OF alu1 IS 

    COMPONENT FourToOneMux 
    PORT(
        andIn   : IN STD_LOGIC_VECTOR;
        orIn    : IN STD_LOGIC_VECTOR;
        addIn   : IN STD_LOGIC_VECTOR;
        bMuxIn  : IN STD_LOGIC_VECTOR;
        sel     : IN STD_LOGIC_VECTOR;
        muxOut  : OUT STD_LOGIC_VECTOR);
    END COMPONENT;

    COMPONENT TwoToOneMux 
    PORT(
        bIn         : IN STD_LOGIC_VECTOR;
        bInvertedIn : IN STD_LOGIC_VECTOR;
        sel         : IN STD_LOGIC_VECTOR;
        muxOut      : OUT STD_LOGIC_VECTOR);
    END COMPONENT;

    COMPONENT FullAdder
    PORT(
        a       :IN STD_LOGIC_VECTOR;
        b       :IN STD_LOGIC_VECTOR;
        cin     :IN STD_LOGIC_VECTOR;
        cout    :OUT STD_LOGIC_VECTOR;
        output  :OUT STD_LOGIC_VECTOR);
    END COMPONENT;

    signal muxOneOut, muxTwoOut, andOut, orOut, addOut, FMuxOut, carryOut : STD_LOGIC_VECTOR := (others => '0');

BEGIN

    M1: TwoToOneMux port map(b, NOT b, op(0), muxOneOut);
    M2: TwoToOneMux port map(a, b, op(0), muxTwoOut);
    andOut <= a AND muxOneOut;
    orOut <= a OR muxOneOut;
    A1: FullAdder port map(a, muxOneOut, cout, carryOut, addOut);
    F1: FourToOneMux port map(andOut, orOut, addOut, muxTwoOut, op(1) & op(2), result); 

END structure;

还有 TwoToOneMux 代码:

LIBRARY ieee; 
USE ieee.std_logic_1164.ALL; 
USE ieee.std_logic_arith.ALL; 
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;

ENTITY TwoToOneMux is

PORT(
    in1     : IN STD_LOGIC_VECTOR;
    in2     : IN STD_LOGIC_VECTOR;
    sel     : IN STD_LOGIC_VECTOR;
    output  : OUT STD_LOGIC_VECTOR);
END TwoToOneMux;

ARCHITECTURE behavioral OF TwoToOneMux IS BEGIN

    WITH sel select
        output <= in1 when "0",
                  in2 when "1",
                  null when others;

END behavioral;

我是 VHDL 的新手,我感到很头疼,因此感谢任何帮助。

【问题讨论】:

  • 作为 VHDL 的新手,您可能会考虑从较小的目标开始,以便体验 VHDL 类型和运算符,否则您会遇到许多问题,例如提供的代码。从一个带有少量端口的简单模块开始,然后逐步了解不同的结构并尝试不同的类型。你可以在网上找到很多例子。
  • 我希望我能哈哈。这是一个课程,但这个课程实际上并不教授 VHDL,他们只是希望我们知道它。
  • @user2929779:为了理解问题,建议添加关于错误或问题的描述。

标签: vhdl alu


【解决方案1】:

首先,您实际上并没有向我们提供类型不匹配适用于哪个信号或实体的线索,因此这将是对您的代码问题的分散枪回答。但是有一个可能的候选人,所以请耐心等待......

有关更多信息,有很多不好的来源,也有一些好的来源。最好的之一是 Peter Ashenden 的“VHDL 设计者指南”。


其次,我很好奇你从哪里“得到”这个 USE 列表:请发表评论并告诉我

USE ieee.std_logic_1164.ALL; 
USE ieee.std_logic_arith.ALL; 
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;

有很多资源教授这种风格或在示例代码中使用它,我想知道哪些资源可以引导初学者远离......

USE ieee.std_logic_1164.ALL; 
USE ieee.numeric_std.all;

是你想要或需要的一切;其他库是非标准的(一家大公司出于商业利益而强制使用 VHDL,并且违背了 VHDL 理念)。它们引入了与ieee.numeric_std.signedunsigned 同名的不同类型的多个定义,这有助于造成混淆。

使用 numeric_std 类型系统的快速教程: - 使用 std_logic_vector 您正在处理的值未键入:例如一个可以有符号、无符号、指令、浮点数或其他任何上下文的词 - 使用signed,其中值为有符号整数 - 使用unsigned,其中值是一个无符号整数 正确选择声明将减少这些类型之间的转换次数。


第三,您的所有STD_LOGIC_VECTOR 端口和信号都不受约束。有些地方适合使用无约束向量,但是……这已经被破坏了。

VHDL 是强类型的,不会推断类型,但它为您提供了有限形式的类型自省的工具。使用它既简单又安全(因为编译器会捕获大多数错误!)但通常被认为是相当先进的,因为它可能会让初学者感到沮丧。

所以

Signal A_BUS : std_logic_vector(31 downto 0);
Signal B_BUS : std_logic_vector(7 downto 0);

声明两种不同类型的信号:std_logic_vector,但分别是 32 位和 8 位。现在给定一个带有端口的组件

PORT(
    a        : IN STD_LOGIC_VECTOR; 
    b        : IN STD_LOGIC_VECTOR );

可以连接成

PORT MAP(
    a => a_bus,
    b => b_bus );

...看到问题了吗? a 和 b 不兼容,因为它们的长度不同。在 Python 中,动态类型可以尝试在运行时清理混乱,或者在 C 中,类型不匹配会默默地导致溢出导致其他东西在很久以后崩溃。但不是在您设计硬件的 VHDL 中,您实际上希望它工作。

最简单(初学者)的解决方案是显式声明所有信号和端口长度

PORT(
    a        : IN STD_LOGIC_VECTOR(31 downto 0); 
    b        : IN STD_LOGIC_VECTOR(31 downto 0));

现在编译器将在端口映射中捕获错误。

这样做的缺点是它会阻止您以多态方式使用相同的模块,例如在 8 位、16 位和 32 位 CPU 中。通常这并不重要,但在它起作用的地方,更先进的技术就会出现......

查看您的内部信号声明之一:

signal muxOneOut : STD_LOGIC_VECTOR;

假设您希望muxOneOut 具有与端口 A 相同的范围...您可以通过声明来做到这一点:

signal muxOneOut : STD_LOGIC_VECTOR(A'range);

它现在可以根据外部连接到端口 A 的任何信号进行自我调整。如果多路复用器将端口 A 或 B 选择到此信号上,则此方法有效 - 假设端口 A 和 B 的宽度相同。所以让我们检查一下这个假设:

assert A'length = B'length report "Port width mismatch" severity FAILURE;

如果外部信号的大小不正确,现在构建设计将会失败。 等等……


但我们仍然没有找到您的类型不匹配的可能罪魁祸首。就是这样:

    COMPONENT TwoToOneMux 
    PORT(
        bIn         : IN STD_LOGIC_VECTOR;
        bInvertedIn : IN STD_LOGIC_VECTOR;
        sel         : IN STD_LOGIC_VECTOR;
        muxOut      : OUT STD_LOGIC_VECTOR);
    END COMPONENT;
...
    M2: TwoToOneMux port map(a, b, op(0), muxTwoOut);

(同上 M1)。事实证明,您使用的类型不止一种:您同时使用std_logic_vectorstd_logic

“sel”显然是一位信号,最清晰的表达方式是std_logic。然而,一位std_logic_vector(如您在此处使用的)是完全合法的,只是令人困惑(尽管std_logic_vector 更有意义,如果您也使用相同的样式,例如 4:1 和 8:1 多路复用器)。

提取 1 位 std_logic_vector 版本所需要做的就是使用正确的语法:op(0 downto 0) 提取在同一元素处开始和结束的向量,而不是提取 std_logic 的 op(0)

【讨论】:

  • 哇,感谢您的回复。我昨晚找到了解决方案,但只是想感谢您花时间尝试和帮助。
最近更新 更多