我已经在VHDL项目上工作了几个星期,而且功能一切都很顺利。我可以模拟和编程我的DE0-nano FPGA开发板,检查我正在做的是否正常工作,确实如此。但是,随着项目的迅速扩展,我开始担心源代码的可读性。
就我的经验而言,我是电子工程专业的大学生,并且学过很多关于电子学的课程,但我是一个关于VHDL的完整菜鸟。 (虽然我可以说我在过去几周内对VHDL的了解已经发展得非常快)
问题:
我的问题是我有几个组件,其端口我想单独映射到不同的高级实体。假设你有一个adder.vhd,我想从operandA.vhd提供操作数A,从operandB.vhd提供操作数B,这意味着我想将adder.vhd的端口A映射到operandA.vhd,和adder.vhd的端口B进入operandB.vhd。
我目前使用的解决方案是按照我的实体的层次顺序映射我的信号,如果operandB.vhd完全埋没在另一个级别而不是operandA.vhd,我将信号一直映射到在我认为需要的同时指定端口A和B的单个端口映射中,需要的最高级实体,然后返回到adder.vhd。
然而,我发现这个解决方案非常混乱,因为它在我的高级实体中累积信号,仅用于路由目的。更重要的是,继续adder.vhd类比,我想要几个实体来提供操作数A或B(在不同的时间,我不打算在相同的输入端口上驱动不同的值)所以应用当前的解决方案意味着我也会有很多近乎重复的任命。
还有其他解决方案吗?我找不到任何关于这方面的文档,我担心这是语言的一个严格限制,但我可能不知道嘎嘎,因为我刚刚开始使用VHDL。
这也可能是我身上的设计错误,因为我比VHDL电路描述更习惯于实际的电子设计。将组件的端口连接到一堆其他不同的组件是非常自然的,但可能不是VHDL的工作方式。
探索性框图:
我目前在做什么:http://i.stack.imgur.com/CJVjg.gif
我想做什么:http://i.stack.imgur.com/hrNwF.gif
示例代码:
-- ********************************************
--
-- TOP-LEVEL ENTITY, in a file topLevel.vhd
entity topLevel is
port
(
-- Any ports, not useful for the problem at hand
);
end entity topLevel ;
architecture topLevel_Architecture of topLevel is
-- HERE : I have to accumulate signals just to get my data from the two subEntityA & B to computeFromAB.
--
-- I can't just map subEntityA and subEntityB as low-level entites into computeFromAB, as they provide data
-- that I need elsewhere in the circuit. Well, I could do that but then I'd still have to get the "otherSignalFromX"
-- through the same method.
--
-- I'd rather directly map SEPARATELY (if that's possible)
-- - operandA & operandB into computeFromAB
-- - otherSignalFromA & otherSignalFromB into topLevel
-- The signals I use to get my data from subEntityA and subEntityB to computeFromAB
SIGNAL operandA : std_logic_vector(7 downto 0) := ( others => '0' ) ;
SIGNAL operandB : std_logic_vector(7 downto 0) := ( others => '0' ) ;
-- Other signals that I do not need to get to computeFromAB
SIGNAL otherSignalFromA : std_logic ;
SIGNAL otherSignalFromB : std_logic ;
begin
-- PORT MAP : subEntityA.vhd
subEntityA : entity work.subEntityA
PORT MAP(
-- The first signal I'd like to get through to computeFromAB
operandA => operandA,
-- Other signals
otherSignalFromA => otherSignalFromA
);
-- PORT MAP : subEntityB.vhd
subEntityB : entity work.subEntityB
PORT MAP(
-- The second signal I'd like to get through to computeFromAB
operandB => operandB,
-- Other signals
otherSignalFromB => otherSignalFromB
);
-- PORT MAP : computeFromAB.vhd
computeFromAB : entity work.computeFromAB
PORT MAP(
-- The "useful" signals
operandA => operandA,
operandB => operandB
);
-- PROCESSES, ETC, OF TOPLEVEL ENTITY
end topLevel_Architecture ;
-- ********************************************
--
-- OPERAND A ENTITY, in a file subEntityA.vhd
entity subEntityA is
port
(
-- The first signal I'd like to get through to computeFromAB
operandA : OUT std_logic_vector(7 downto 0)
-- Other signals
otherSignalFromA : OUT std_logic ;
);
end entity subEntityA ;
-- ARCHITECTURE, PROCESSES OF subEntityA
-- ********************************************
--
-- OPERAND B ENTITY, in a file subEntityB.vhd
entity subEntityB is
port
(
-- The second signal I'd like to get through to computeFromAB
operandB : OUT std_logic_vector(7 downto 0)
-- Other signals
otherSignalFromB : OUT std_logic ;
);
end entity subEntityB ;
-- ARCHITECTURE, PROCESSES OF subEntityB
-- ********************************************
--
-- COMPUTATION FROM OPERANDS A & B ENTITY, in a file computationFromAB.vhd
entity computeFromAB is
port
(
operandA : IN std_logic_vector(7 downto 0) ;
operandB : IN std_logic_vector(7 downto 0)
);
-- ARCHITECTURE, PROCESSES OF computeFromAB
感谢阅读,感谢您提供的任何意见。
编辑1:感谢您删除“词典”标签,不知道为什么会这样。
编辑2:添加了一些示例代码,但我不确定它是否有任何帮助
编辑3:添加说明性框图
答案 0 :(得分:1)
为什么不直接将实体 A + B + computeFromAb 包装在一起创建 entityAB 。然后将 otherSignalA 和 otherSignalB 通过顶层路由到 entityC 。这个想法是用cratea整洁的子模块来包装和隐藏其他模块。如果您以后需要复制某些逻辑,这也会有所帮助。
可能是信号和设计变得有点复杂,但这通常是原始想法过于复杂的明确标志。因此,无论何时您对自己的代码感到困惑,那么现在是时候回到笔和纸上并重新实现您实际想要实现的目标;)
此外,在某些时候,您不再确定某些信号即将到来以及应该在哪里发生。那是你诅咒你的信号命名惯例的时候 - 如果你有任何 - 并提出更合理的东西。
向您的顶级实体添加100个模块,您就会开始了解顶级集成商在项目中的感受以及为什么其中一些模块存在严重的心理问题。
答案 1 :(得分:1)
您的问题是组织问题之一,而不是将其视为简单元素的互连。因此,您的后一个框图就是您在代码中实际执行的操作,而不是前者。
以下是您应该做的事情:将每个子模块实体/体系结构对放在自己的文件中。将其编译成图书馆工作。然后在你的顶层代码中简单地连接它,就像这样:
U0 : entity work.subEntityA
PORT MAP(operandA => operandA,
otherSignalFromA => otherSignalFromA);
U1 : entity work.subEntityB
PORT MAP(operandB => operandB,
otherSignalFromB => otherSignalFromB);
U2 : entity work.computeFromAB
PORT MAP(operandA => operandA,
operandB => operandB);
U3 : entity work.C
PORT MAP(otherSignalFromA => otherSignalFromA,
otherSignalFromB => otherSignalFromB );
您使用了构造"实体work.module_name"在您的示例代码中,这是一个很好的做法。让默认绑定执行其作业和AVOID配置文件。
随着代码的增长,您最终将所有这4个代码放入一个实体/ arch对(进行另一层次的层次结构)并继续。我建议您只能接线。将逻辑留给子模块。
是的,随着您的列表和通用列表的增长,它变得越来越复杂,但这就是层次结构的用途,以帮助您组织它。