VHDL - 比较当前和过去的输入

时间:2014-11-05 12:50:27

标签: vhdl

我的系统有一个3输入D_in,在每个正clk边缘读取。 如果说我想查看当前输入D_in是否比先前的D_in大至少2,则计数将递增。我如何用VHDL写这个?

if clk'event and clk = '1' then  --read at positive edge
if D_in > (D_in + 010) then  <---I am sure this is wrong. How to write the proper code?   

Entity ABC is
Port(D_in: in std_logic_vector(2 downto 0);
     Count: out std_logic_vector(2 downto 0));
Architecture ABC_1 of ABC is
    signal D_last: std_logic_vector(2 downto 0); 
Begin
     Process(D_in)   
         D_last <= D_in;
         if clk'event and clk = '1' then
         if D_last > (D_in + 2) then
         count <= count + 1;
end if;
end process; 
end ABC_1;

2 个答案:

答案 0 :(得分:1)

编写此过程的“好”方法如下:

process (clk)
begin
  if (rising_edge(clk)) then
    -- store the value for the next time the process will be activated
    -- Note that D_last value will be changed after the whole process is completed
    D_last <= D_in;   

    -- compare the actual D_in value with the previous one stored in D_last. 
    -- D_last value is its value at the very beginning of the process activation
    if (D_in > D_last + 2) then   
      -- increment the counter
      count <= count + 1;
    end if;
  end if;
end process;

请注意,D_in,D_last和count必须声明为unsigned而不是std_logic_vector。

我建议你阅读this post,它解释了一个过程是如何工作的:信号何时更新以及哪个信号值用于过程。

干杯

[编辑]这个答案对你的问题应该没问题。但是您显示的代码还有其他错误:

  • 信号clk必须是您实体的输入。
  • 无法在架构中读取信号计数,因为它在实体中定义为输出。然后无法解析“count&lt; = count + 1”这一行。您必须使用内部信号,然后将其值分配给进程外的“count”:

    count&lt; = count_in;

答案 1 :(得分:0)

您的设计规范中还有其他一些错误。这个答案试图在一个地方回答所有问题。

通过在模拟周期中执行过程来模拟VHDL。一切 并发语句可以表示为等效进程 语句或过程语句和块语句的组合。

信号分配是指定的预计输出波形队列 时间。如果没有指定时间,则表示当前时间,并且将更新该值 在下一个模拟周期中执行过程之前,进行增量循环,模拟 当没有安排剩余事件时,时间会提前 当前的模拟时间。

为避免混淆信号分配何时发生,请将其视为 单独的过程(无论你是否以这种方式表达)。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity abc is
    port (
        clk:    in  std_logic;       -- Note 1
        d_in:   in  std_logic_vector(2 downto 0);
        count:  out std_logic_vector(2 downto 0)
    );
end entity;   -- Note 2

architecture foo of abc is
    signal d_last: std_logic_vector(2 downto 0); 
begin

DLAST:                        -- Note 3
     process (clk)   
     begin
         if rising_edge(clk) then   -- Note 4
             d_last <= d_in;
         end if;
     end process; 

INC_COUNT:
    process (clk)
        variable cnt: unsigned(2 downto 0) := "000";  -- Note 5
    begin
        if rising_edge(clk) and 
                unsigned(d_last) >  unsigned(d_in) + 2 then  -- Mote 6,7
            cnt := cnt + 1;
        end if;
        count <= std_logic_vector(cnt);
    end process;

end architecture;

备注

  1. 从端口接口缺少clk
  2. 缺少实体ABC的结束语句。
  3. 从概念上查看D_last     与clk敏感的Count计数器分开注册。 (可     合并为一个过程)
  4. rising_edge函数表示clk&#39;事件和clk =&#39; 1&#39; (&#39;事件 和&#34; =&#34;都是功能)
  5. 计数器必须代表&#34; +&#34;的二进制值。生产一个 二进制结果
  6. &#34; +&#34;优先级高于&#34;&gt;&#34;,优先级高于&#34;&#34;&#34; (你不需要括号)
  7. 包numeric_std为
    提供关系和添加运算符 键入符号并键入无符号,需要D_last的类型转换 和D_in。

    或者使用Synopsys软件包std_logic_unsigned 依赖于Synopsys软件包std_logic_arith并对待 std_logic_vector为无符号。这避免了类型转换,并且 允许将数组类型声明为std_logic_vector类型。

  8. 如果要将端口cnt声明为模式count并提供默认值,则可以取消变量buffer

            count:  buffer std_logic_vector(2 downto 0) :="000" -- Note 5
    

    INC_COUNT:
        process (clk)
        begin
            if rising_edge(clk) and
                    unsigned(d_last) >  unsigned(d_in) + 2 then  -- Note 6,7
                count <= std_logic_vector(unsigned(count) + 1);
            end if;
        end process;
    

    您无法使用Count作为模式out来对其自身的值进行算法修改。访问模式输出端口值的能力用于验证,并且是IEEE Std 1076-2008功能。

    现在你可以看到Synopsys的std_logic_unsigned包的价值,至少可以避免类型转换。

    此外,我还有另一个问题。如果连续3个clk周期d_in为0,我想将count重置为0.如何编写代表3 clk周期的代码?

    为D_in添加另一个管道信号:

        signal d_last:  std_logic_vector(2 downto 0) := "000";
        signal d_last1: std_logic_vector(2 downto 0) := "000";
    

    注意这些也有默认值,FPGA合成通常会尊重它,它由用于编程FPGA的bistream图像中的触发器状态表示。

    修改计数器的操作方式:

    INC_COUNT:
        process (clk)
        begin
            if rising_edge(clk)  then
                if d_in = "000" and d_last = "000" and d_last1 = "000" then
                    count <= "000";
                elsif unsigned(d_last) >  unsigned(d_in) + 2 then  -- Note 6,7
                    count <= std_logic_vector(unsigned(count) + 1);
                end if;
            end if;
        end process;
    

    该示例的三个版本都进行了分析,它们尚未进行模拟,并且应该是合成资格。