2

我正在尝试在 spartan 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).

我真的不知道如何在不违反 spartan 6 规则的情况下使计时器加载得足够快。

4

2 回答 2

3

Xilinx WP309 Targeting and Retargeting Guide for Spartan-6 FPGA [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 时 ,不推荐使用以下类型的寄存器/锁存器:

      ______|______  
      |    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

于 2013-09-19T00:29:33.243 回答
2

从第一种(同步)方法转移到第二种(异步集)很少是解决问题的正确方法。无论 Spartan-6 经济体的复位逻辑如何。事实上,我会以......“不要那样做”为由证明他们是正当的。

相反,请查看语句“问题是我的状态机在同一个时钟上计时,并且对于一些短持续时间的状态,它就像计时器没有及时设置一样爆炸。”

首先,I2C 信号的持续时间不短,除非这可能是它的数百兆赫兹导数......

其次,VHDL 做得很好的一件事是同步设计,因此“爆破”而不用在其他地方重置计数器点:可能是这里提到的信号分配规则。

我怀疑这会导致状态机设置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;

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

于 2013-09-19T08:58:32.280 回答