1

下面是一个简单的 3 位计数器。

当 reset(rst) 为 0 时,计数器值为“000”,否则在每个时钟的上升沿递增 1。

 LIBRARY ieee;
 USE ieee.std_logic_1164.all;
 use IEEE.std_logic_unsigned.all;
 use IEEE.numeric_std.all;
 ---------------------------------------------
 ENTITY counter IS
 PORT (clk : IN STD_LOGIC;
    rst : in std_logic;
       digit : out std_logic_vector (2 downto 0)
       );
 END counter;
 ---------------------------------------------
 ARCHITECTURE counter OF counter IS
 BEGIN

 count: PROCESS(clk,rst)
 VARIABLE temp : std_logic_vector(2 downto 0);
 BEGIN
 IF (clk'EVENT AND clk='1') THEN
     if (rst = '1') then
        temp := temp + "001";
     else
        temp := "000";
     END IF;
 END IF;
 digit <= temp;
 END PROCESS count;
 END counter;

下面是我得到的模拟结果:

在此处输入图像描述

结果,输出是正确的。但是在时间 rst = 1 和 output='001' 之间有一个时钟延迟。即当rst = '1' 时,计数器不会立即增加。

根据我的理解,只要 clk 或 rst 发生变化,就会执行进程。所以当 rst 从低变高时,就会发生一个事件。进程检查 clk 的上升沿是否为 YES。然后检查rst = 1,是。因此,通常计数器必须在该 clk 本身中增加。但事实并非如此。

问题:

  1. 为什么复位 = 1 和输出 = 001 之间有一个时钟周期延迟?
  2. 我的理解有什么问题?
4

3 回答 3

5

最可能的原因是“rst”是由时钟进程生成的,由相同的“clk”信号时钟。

所以“rst”出现在“clk”之后的一个增量周期。当“rst”改变时,它会唤醒进程,但“clk'event”在前一个增量周期,因此“if”语句将不会执行。

在下一个时钟沿,rst = 1,因此计数器按预期工作。

三个小点:

  • 值得将复位信号命名为 rst_n 以更清楚地表明它是低电平有效复位!
  • rst 真的不需要在敏感列表中
  • 布尔表达式周围不需要括号
于 2012-12-01T17:30:30.870 回答
3

(免责声明:我已经很久没有用 VHDL 编程了,所以这仅适用于通用逻辑设计。)

无论如何,不​​能指望在触发进程时立即准备好加法的结果。关键是,即使是计算 000 + 001 的第一位也会受到相当于一次异或运算的传播延迟的影响。第二位是根据第一位的进位(如果两个位都是 1)和第二位的异或运算来计算的。等等。

如果有人会异步探测“temp”变量,则会看到如下内容:

                        ^ ________________
result_bit_0    __________|
                        0123456789
                _____________
result_bit_1            ^    |____________
                        0123456789
                ____________ _____
result_bit_2            ^  |_|   |________
                        0123456789abcde
                        ________       
clock:          ________|      |______|

该图试图更详细地说明通用加法操作的波形。
在时间 0 开始添加过程。
在一个小的延迟“2”之后,第一位稳定到 1。
在时间“5”第二位稳定到 0,在时间“9”第三位稳定到 0。但也很常见,如 result_bit_2,输出在各种状态之间切换。

它是每个临时变量的总/最大延迟来稳定,这决定了最小时钟周期。在这种情况下,时刻“e”是那个时刻,我们已经确定计数器递增的结果是可用的。

尽管如此,从角度result(这是一个向量)来看,一切都会在下一个时钟周期立即发生。

于 2012-12-01T16:29:32.240 回答
1

“问题”在于您描述“第一个”的方式。你这样做的方式会导致“同步”复位,即复位只会在时钟上升沿后生效。

一般来说,这只是编码风格/偏好的问题。我通常更喜欢异步重置(可能在顶层使用重置同步器以避免释放重置时的亚稳定性),但采用同步重置方法并没有错。

在异步重置的情况下,您需要将代码更改为以下内容:

PROCESS (clk, rst_n) BEGIN
   IF rst_n = '0' THEN
      ...
   ELSIF rising_edge(clk) THEN
    ...
   END IF;
END PROCESS;
于 2018-09-25T13:22:49.557 回答