我正在设计一个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的新手,我感觉很开心,所以感谢任何帮助。
答案 0 :(得分:3)
首先,您实际上并没有告诉我们类型不匹配适用的信号或实体的线索,因此这将是对代码问题的分散解决方案。但是有一个可能的候选人,所以请耐心等待......
有关更多信息,有很多不良消息来源,还有一些好的消息来源。其中最好的是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.signed
和unsigned
相同,这有助于造成混淆。
使用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_vector
和std_logic
。
“sel”显然是一位信号,最明确的表达方式是std_logic
。然而,一位std_logic_vector
(正如你在这里使用的)是完全合法的,只是令人困惑的地狱(尽管std_logic_vector
更有意义,如果你也使用相同的风格,例如4:1和8: 1个多路复用器)。
提取1位std_logic_vector
版本所需要做的就是使用正确的语法:op(0 downto 0)
提取一个以相同元素开头和结尾的向量,而不是{{1}提取std_logic。