2015-12-18 21 views
0

我做了一个由2个模块组成的VHDL设计。一个处理通信,并运行在100兆赫(我不能改变这一点)。另一个模块进行计算,并且由于时间原因必须以45 Mhz运行。特定时间的信号为高

第二个模块有一个名为“newPair”的输入引脚,当新数据准备好并且可以由第二个模块处理时,我想将其设置为高电平。现在我的第二个模块只能在时钟的上升沿工作,所以我需要将该引脚设置为45 Mhz时钟周期的高电平,然后将其拉低。这必须从运行在45 Mhz的模块完成。我怎样才能做到这一点?我虽然想为此创建一个DCM,但这似乎有点过分。

谢谢!

更新:

我工作的一个的Spartan-6(xc6slx150)

+0

什么是您的目标平台和设备? – Paebbels

+0

我刚更新了它。对不起 – nablahero

回答

2

你的设计有2个时钟域,所以你需要同步电路,从一个时钟域的信息传输到其他。

第1部分 - 同步器

基本同步器是2链d-FF的构建。这个同步器可以用于标志信号(这些信号不经常变化)。它不能用于选通信号(这些信号是1个周期的高电平信号),因为选通信号可能会在目标时钟域上丢失或重复出现。

2 d-FF同步器:

genLoop : for i in Input'range generate 
    signal Data_async : STD_LOGIC; 
    signal Data_meta  : STD_LOGIC  := '0'); 
    signal Data_sync  : STD_LOGIC  := '0' ; 
begin 
    Data_async <= Input(i); 
    process(Clock) 
    begin 
    if rising_edge(Clock) then 
     Data_meta <= Data_async; 
     Data_sync  <= Data_meta; 
    end if; 
    end process; 
    Output(i) <= Data_sync; 
end generate; 

此代码可以由供应商特定的属性VHDL来改善。查看我的链接源代码,查看通用,Altera和Xilinx变体。

来源: PoC.misc.sync.Bits

参见存储在UCF文件赛灵思ISE这些时序约束设计:
- https://github.com/VLSI-EDA/PoC/blob/master/ucf/MetaStability.ucf
- https://github.com/VLSI-EDA/PoC/blob/master/ucf/misc/sync/sync_Bits_Xilinx.ucf

第2部分 - 构建用于选通脉冲信号的合成器电路

具有频闪功能的跨时钟同步器构建于:

  • 1 T-FF以编码在源时钟域
  • 2 d-FF作为标志同步信号的变化,如在第1部分
  • 一个变化检测器,以恢复在目标时钟的原始值来描述域(1个D-FF和一个XOR)

该同步器可用于将您的newPair信号传输到45 MHz时钟域。您将需要相同的回路:)

以下示例执行busy信号以指示传输过程。断言InputBusy很高导致忽略闪光灯。

entity sync_Strobe IS 
    generic (
    BITS        : POSITIVE  := 1;              -- number of bit to be synchronized 
    GATED_INPUT_BY_BUSY : BOOLEAN   := TRUE             -- use gated input (by busy signal) 
); 
    port (
    Clock1       : in STD_LOGIC;               -- <Clock> input clock domain 
    Clock2       : in STD_LOGIC;               -- <Clock> output clock domain 
    Input        : in STD_LOGIC_VECTOR(BITS - 1 downto 0);  -- @Clock1: input bits 
    Output       : out STD_LOGIC_VECTOR(BITS - 1 downto 0);  -- @Clock2: output bits 
    Busy        : out STD_LOGIC_VECTOR(BITS - 1 downto 0)   -- @Clock1: busy bits 
); 
end entity; 

architecture rtl of sync_Strobe is 
    attribute SHREG_EXTRACT          : STRING; 

    signal syncClk1_In  : STD_LOGIC_VECTOR(BITS - 1 downto 0); 
    signal syncClk1_Out  : STD_LOGIC_VECTOR(BITS - 1 downto 0); 
    signal syncClk2_In  : STD_LOGIC_VECTOR(BITS - 1 downto 0); 
    signal syncClk2_Out  : STD_LOGIC_VECTOR(BITS - 1 downto 0); 
begin 
    gen : for i in 0 to BITS - 1 generate 
    signal D0       : STD_LOGIC   := '0'; 
    signal T1       : STD_LOGIC   := '0'; 
    signal D2       : STD_LOGIC   := '0'; 

    signal Changed_Clk1  : STD_LOGIC; 
    signal Changed_Clk2  : STD_LOGIC; 
    signal Busy_i     : STD_LOGIC; 

    -- Prevent XST from translating two FFs into SRL plus FF 
    attribute SHREG_EXTRACT OF D0 : signal is "NO"; 
    attribute SHREG_EXTRACT OF T1 : signal is "NO"; 
    attribute SHREG_EXTRACT OF D2 : signal is "NO"; 

    begin 

    process(Clock1) 
    begin 
     if rising_edge(Clock1) then 
      -- input delay for rising edge detection 
      D0  <= Input(I); 

      -- T-FF to converts a strobe to a flag signal 
      if (GATED_INPUT_BY_BUSY = TRUE) then 
       T1 <= (Changed_Clk1 and not Busy_i) xor T1; 
      else 
       T1 <= Changed_Clk1 xor T1; 
      end if; 
     end if; 
    end process; 

    -- D-FF for level change detection (both edges) 
    D2 <= syncClk2_Out(I) when rising_edge(Clock2); 

    -- assign syncClk*_In signals 
    syncClk2_In(I) <= T1; 
    syncClk1_In(I) <= syncClk2_Out(I); -- D2 

    Changed_Clk1  <= not D0 and Input(I);    -- rising edge detection 
    Changed_Clk2  <= syncClk2_Out(I) xor D2;  -- level change detection; restore strobe signal from flag 
    Busy_i     <= T1 xor syncClk1_Out(I);  -- calculate busy signal 

    -- output signals 
    Output(I)    <= Changed_Clk2; 
    Busy(I)     <= Busy_i; 
    end generate; 

    syncClk2 : entity PoC.sync_Bits 
    generic map (
     BITS    => BITS      -- number of bit to be synchronized 
    ) 
    port map (
     Clock    => Clock2,    -- <Clock> output clock domain 
     Input    => syncClk2_In,  -- @async: input bits 
     Output   => syncClk2_Out  -- @Clock: output bits 
    ); 

    syncClk1 : entity PoC.sync_Bits 
    generic map (
     BITS    => BITS      -- number of bit to be synchronized 
    ) 
    port map (
     Clock    => Clock1,    -- <Clock> output clock domain 
     Input    => syncClk1_In,  -- @async: input bits 
     Output   => syncClk1_Out  -- @Clock: output bits 
    ); 
end architecture; 

来源:PoC.misc.sync.Strobe

第2部分 - 特殊合成电路

我想你也从一个时钟域传输数据到另一个。所以你需要一个多位同步器(建立在选通同步器之上)或一个支持交叉时钟的FIFO。

我参与的PoC-Library也有多位/矢量同步器。查看链接的源文件夹中的其他模块。还有一个跨时钟/独立时钟(ic)FIFO。

+0

真棒回答。谢谢:) – nablahero

1

您不需要在特定时间内断言某些信号。

如果第一个和第二个模块之间的数据交换发生得很稀疏,您可以使用级别触发让第二个块知道数据已准备就绪。 (您可以阅读this answer以了解电平触发和边沿触发之间的差异)。

如果您需要处理流数据,则需要使用异步FIFO。 (This answer可能会给你更多的信息)。

作为一个建议,我不会使用信号断言的具体数量的循环方法,因为它不是一个好的做法可重用的代码(它适用于这种特定的设计,但您可能需要重新校准周期数如果由于某种原因你的时钟周期发生变化)。

+0

非常感谢你的回答。我选择另一个作为答案,但你的帮助我也谢谢:) – nablahero