VHDL定时器同步/异步加载速度问题

时间:2013-09-18 20:29:48

标签: simulation vhdl synthesis

我正在尝试在斯巴达6上编写类似i2c的总线。我有一堆状态,我在使用下面的计数器。

  -- Timer --
  TimesUp <=  true when TmrCnt = 0 else
             false when TmrCnt /= 0 else
             false;
  tmrProc: process(ClkxC, SetTmr, TmrInit)
  begin
    if (rising_edge(ClkxC)) then
      if (SetTmr = '1') then
        TmrCnt <= TmrInit;
      elsif (TmrCnt > 0) then
        TmrCnt <= TmrCnt - 1;
      end if;
    end if;
  end process;

问题是我的状态机是在同一个时钟上运行的,并且对于一些短时间的状态,它只会爆炸,好像定时器没有及时设置。

所以我尝试了这个:

  -- Timer --
  TimesUp <=  true when TmrCnt = 0 else
             false when TmrCnt /= 0 else
             false;
  tmrProc: process(ClkxC, SetTmr, TmrInit)
  begin
    if (SetTmr = '1') then
      TmrCnt <= TmrInit;
    elsif (rising_edge(ClkxC)) then 
      if (TmrCnt > 0) then
        TmrCnt <= TmrCnt - 1;
      end if;
    end if;
  end process;

现在它模拟得很好,但是当我尝试实现时,我收到一条错误消息:

   This design contains one or more registers/latches that are directly
   incompatible with the Spartan6 architecture. The two primary causes of this is
   either a register or latch described with both an asynchronous set and
   asynchronous reset, or a register or latch described with an asynchronous
   set or reset which however has an initialization value of the opposite 
   polarity (i.e. asynchronous reset with an initialization value of 1).

我真的不知道如何在不制动斯巴达规则6的情况下让定时器加载足够快。

2 个答案:

答案 0 :(得分:2)

警告已在Xilinx WP309 Targeting and Retargeting Guide for Spartan-6 FPGAs [P9-11]中明确说明。

To reduce cost of the overall architecture, slices in Spartan-6 FPGAs do not have a REV 
pin. As a result, flip-flops no longer implement both a set signal and a reset signal. In 
addition, a register with a set or reset signal can only have an initialization value of  
the same polarity. For example, a flip-flop with an asynchronous reset can only have an 
initialization value of 0.  

也就是说,使用Xilinx Spartan-6 FPGA时,以下类型的寄存器/锁存器 NOT RECOMMENDED

      ______|______  
      |    Set    |  
      |           |
   ---| D       Q |---      -- 1. a register/latch with both ASYNCHRONOUS
      |         _ |               set and reset signals
   ---|>Clk     Q |o--      -- NOT RECOMMENDED
      |           |               
      |   Reset   |
      |___________|
            |



    -- 2. a register/latch described with an ASYNCHRONOUS set/reset which
          however has an initialization value of the opposite polarity 

    -- The default value of reg is 0 which is the left
    -- bound value of the integer type definition.
    signal reg: integer range 0 to 7;   <-----
                                              |
    process (clk, reset)                      |___  opposite
    begin                                     |     NOT RECOMMENDED
       if (reset = '0') then                  |
          reg <= 7;                     <-----
       elsif ( rising_edge(clk) ) then
          reg <= val; 
       end if;
    end process;

Xilinx推荐的解决方案:

 1. Remove either the set or reset from all registers and latches
    if not needed for required functionality
 2. Modify the code in order to produce a synchronous set and/or 
    reset (both is preferred)
 3. Ensure all registers have the same initialization value as the 
    described asynchronous set or reset polarity
 4. Use the -async_to_sync option to transform the asynchronous
    set/reset to synchronous operation
    (timing simulation highly recommended when using this option)

在您的设计中,您可以将TmrCnt初始化为TmrInit或向上计数TmrCnt

答案 1 :(得分:2)

从第一种(同步)方法转向第二种(异步集)很少是解决问题的正确方法;无论Spartan-6经济体的重置逻辑如何。事实上,我会以......“不要那样做”为理由来证明这一点。

相反,请查看语句“问题是我的状态机是在同一个时钟上运行的,并且对于一些短时间的状态它只会爆炸,好像定时器没有及时设置。”

首先,I2C信号没有短暂的持续时间,除非这可能是它的数百MHz导数......

其次,VHDL做的事情非常好是同步设计,因此“爆破”而不将计数器点重置为其他东西:可能信号分配规则引用here。 / p>

我怀疑这会导致状态机设置SetTmr以在单独的进程中与计数器通信的问题;所以计数器在一个循环后看到SetTmr,并且该循环延迟导致观察到的错误行为,因为在该循环期间TimesUp具有错误的值。

一个答案 - 我经常使用的模式 - 只是将计时器滚动到SM过程本身;然后你直接设置并保存握手逻辑和一个单独的过程...

StateMch : process(Clock)
  begin
    if rising_edge(Clock) then
      -- default actions
      if Timer > 0 then 
        Timer <= Timer - 1;
      end if;

      -- state machine
      case State is
      when Start_Wait =>
        Timer <= My_Delay;
        State <= Waiting;
      when Waiting =>
        if Timer = 0 then
          State <= Done;
        end if;
      when others => 
        State <= Start_Wait;
      end case;

    end if;
  end process;

除了比大量微小进程更简单和(我发现)更容易理解之外,这允许几个州使用相同的计时器来产生不同的延迟。