[英]Combinational Logic Timing
我目前正在尝试在一个时钟周期内实现一条数据路径,该路径将计算以下内容。
实体的行为架构如下所示。
signal sum_out : std_logic_vector (7 downto 0);
signal shift_out : std_logic_vector (7 downto 0);
process (clock, data_in_a, data_in_b, data_in_c)
begin
if clock'event and clock = '1' then
sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b));
shift_out <= '0' & sum_out(7 downto 1);
data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out));
end if;
end process;
当我模拟上面的代码时,确实得到了期望得到的结果。 但是,我在3个时钟周期后得到了结果,而不是我希望的1个结果。 仿真波形如下所示。
我还不熟悉实现具有时序问题的设计。 我想知道,是否有办法在一个时钟周期内完成上述计算。 如果有,我如何实施它们?
当您为流程内部的信号分配新值时,此新值仅在流程完成执行后才可用。 因此,无论何时读取信号的值,都将使用过程开始执行时的原始值。
另一方面,对变量的赋值会立即发生,并且您可以根据需要在后续语句中使用新值。
因此,要解决您的问题,只需使用变量而不是信号来实现sum_out
, shift_out
和data_out
。 然后,只需将data_out
的值复制到实体的输出端口即可。
不使用变量:
sum <= in_a + in_b;
process (clock)
begin
if rising_edge(clock) then
data_out <= in_c - ('0' & sum(7 downto 1));
end if;
end process;
除时钟外的所有声明都是unsigned(7 downto 0);
为什么要使它更复杂?
原始的流水线化为3个周期,可能会以更高的时钟速率工作。
编辑以下评论:
我想证明VHDL不必那么冗长。
但是,似乎有很多人在“教” VHDL,他们只专注于琐碎的元素,而完全忽略了全局,因此我将对此稍作说明。
VHDL是一种强类型化的语言,可以防止在类型彼此混淆时(例如,您将两个大数相加并得到否定的结果)引起的错误蔓延。
这并不意味着您需要在各处进行类型转换。 确实,如果您需要大量的类型转换,则表明您的设计可能是错误的,现在该重新考虑一下,而不是沿着错误的方向前进。
任何语言的代码应尽可能简洁明了。
否则,将很难阅读,并且其中可能包含错误。
类似于C的语言和VHDL之间的最大区别是:
在C语言中,使用正确的数据类型,您可以编写sum = in_a + in_b;
它会工作。 使用错误的数据类型,您还可以编写sum = in_a + in_b;
它会编译就好了; 实际上,这是另一回事! 这些错误是隐藏的:确定正确的类型取决于您,如果您弄错了,除了继续测试之外,您几乎无能为力。
在VHDL中,使用正确的类型,您可以编写sum <= in_a + in_b;
并使用错误的类型,编译器将迫使您编写诸如sum <= std_logic_vector(unsigned(in_a) + unsigned(in_b));
该死的丑陋,但仍然可以(可能:请参见注释1)正常工作。
因此,回答这个问题:我如何决定使用unsigned
或std_logic_vector
?
我看到我需要三个输入和一个输出。 我可以将它们设置为std_logic_vector
但我停下来问:它们代表什么?
数字。
他们可以否定吗? 不按照我对规范的阅读(您的问题)。
因此,无符号数字...(注1)
我是否需要非算术运算? 是的,有一个转变。(注2)
因此,与std_logic_vector
相关的numeric_std.unsigned
而不是仅是整数的natural
。
现在,您无法完全避免类型转换。 编码标准可能会施加限制,例如“所有顶级端口都必须为std_logic_vector
”,并且您必须实现要求的外部实体规范;例如, 用于类型转换的中间信号有时比替代方法更干净,例如in_a <= unsigned(data_in_a);
或者,如果你正在从以上相同内存的说明,文字和数字,例如,你可能决定存储器中的内容必须是std_logic_vector
因为它不只是包含数字。 但是选择正确的类型转换位置,您可能会发现90%的类型转换消失了。 以此为设计准则。
(注1:但是,如果C <(A + B)/ 2会发生什么?应该对data_out进行签名吗?即使沿着这些思路思考,也可能发现了一个可能隐藏了std_logic_vector的错误...
正确的答案取决于未知因素,包括data_out的用途:如果确实要对它进行未签名(例如,内存地址),则可能要标记一个错误而不是对其进行签名)
(注2:没有一个尚不存在的综合工具无法将signal a : natural; ... x <= a/2
转换signal a : natural; ... x <= a/2
转换为右移,因此natural
也将起作用,除非有其他选择的理由很多人似乎仍然被教导整数是不可综合的,这是错误的 。
使用信号执行此操作,只需仅注册链中的最后一个元素(data_out)。 经过分析,我没有编写测试平台来验证仿真。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity signal_single_clock is
port (
signal clock: in std_logic;
signal data_in_a: in std_logic_vector(7 downto 0);
signal data_in_b: in std_logic_vector(7 downto 0);
signal data_in_c: in std_logic_vector(7 downto 0);
signal data_out: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of signal_single_clock is
signal sum_out : std_logic_vector (7 downto 0);
signal shift_out : std_logic_vector (7 downto 0);
begin
sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b));
shift_out <= '0' & sum_out(7 downto 1);
single_reg:
process (clock)
begin
if clock'event and clock = '1' then
data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out));
end if;
end process;
end architecture;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.