繁体   English   中英

组合逻辑时序

[英]Combinational Logic Timing

我目前正在尝试在一个时钟周期内实现一条数据路径,该路径将计算以下内容。

  • 接受输入A和B并将其相加。
  • 将加法结果右移一位。 (除以2)
  • 从另一个输入C中减去移位后的结果。

实体的行为架构如下所示。

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_outshift_outdata_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)正常工作。

因此,回答这个问题:我如何决定使用unsignedstd_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM