VHDL时钟同步器中的综合误差

VHDL时钟同步器中的综合误差,vhdl,Vhdl,我试图在下面的VHDL代码中实现时钟同步和时钟分频器。时钟(时钟rx和时钟tx)应在总线上“rx”信号的上升沿和下降沿同步。我可以模拟以下内容,但在ISE中无法合成,因为我使用的是“RX”事件。有谁能提出一个替代方案吗?(Verilog也将起作用) --------------------------------------------时钟分频器----------------------------------------------------------------------------

我试图在下面的VHDL代码中实现时钟同步和时钟分频器。时钟(时钟rx和时钟tx)应在总线上“rx”信号的上升沿和下降沿同步。我可以模拟以下内容,但在ISE中无法合成,因为我使用的是“RX”事件。有谁能提出一个替代方案吗?(Verilog也将起作用)

--------------------------------------------时钟分频器----------------------------------------------------------------------------------------

PROCESS (CLK_I, RX)
BEGIN
   IF (RX'EVENT) THEN
      clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);  
   ELSIF (CLK_I'EVENT AND CLK_I = '1') THEN
       IF clk_cnt >2499 THEN
         clk_cnt <= to_unsigned(0,clk_cnt'LENGTH); 
      ELSE  
         clk_cnt <= clk_cnt + 1;    
       END IF;
   END IF;
END PROCESS;


clk_rx <= '1' WHEN  clk_cnt = 1250 ELSE '0';  -----clk_rx=1 only at the half of the counter period----------clk enable
clk_tx <= '1' WHEN  clk_cnt = 2499 ELSE '0';
过程(时钟I、RX)
开始
如果(接收事件)那么
clk_cnt 2499然后

clk_cnt问题不仅仅在于您使用的是RX'EVENT,而是在RX'EVENT条件中有一个clk_I'EVENT条件。那是不可合成的


假设CLK_I的频率远高于RX'事件,尝试使用CLK_I采样RX。如果RX的先前值较低,而当前值较高,则在CLK_I'事件上同步重置CLK_cnt。请注意,如果RX与CLK_I真正异步,则需要担心亚稳态问题,在寻找从0到1的更改之前,应添加2个触发器以同步RX。

尝试此代码。正如@Joe Hass所解释的,我的代码中仍然并没有触发器来解决RX的亚稳态问题

但用于同步接收信号

PROCESS (CLK_I, RX)
BEGIN
   IF (CLK_I'EVENT AND CLK_I = '1') THEN
       IF (RX='1') THEN
          clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);  
       ELSE
           IF clk_cnt >2499 THEN
               clk_cnt <= to_unsigned(0,clk_cnt'LENGTH); 
           ELSE  
               clk_cnt <= clk_cnt + 1;    
           END IF;
      END IF;
   END IF;
END PROCESS;
过程(时钟I、RX)
开始
如果(CLK_I’事件和CLK_I='1'),则
如果(RX='1'),则

clk_cnt您可以在下面找到代码的建议。请注意以下属性:

  • clk_rx_o(clk_rx)和clk_rx_o(clk_tx)作为触发器的输出生成,因为为了避免在基于过程外cnt的组合比较生成信号时可能出现的故障
  • rx_i由两个触发器同步,假设它尚未与clk_i同步
  • 时钟除法为2501,因为cnt从0开始。。当(cnt>2499)时,因包裹而产生2500。对于2500除法,使用(cnt>=2499)代替
  • VHDL编码风格:所有信号名称都是小写,VHDL语句也是如此,表达式之间的间距一致,便于阅读
代码:

ieee库;
使用ieee.std_logic_1164.all;
实体mdl是
港口(
clk_i:标准逻辑中;
rx_i:标准_逻辑中;
时钟接收输出:输出标准逻辑;
时钟输出(输出标准逻辑);
终端实体;
图书馆ieee;
使用ieee.numeric_std.all;
mdl的体系结构syn是
信号接收单元:标准逻辑;
信号接收同步:标准逻辑;
信号cnt:std_逻辑_向量(12-1向下至0);
开始
--rx_i同步到时钟_i
过程(clk_i)是
开始
如果上升沿(clk_i),则

非常感谢您的支持

我按照@Joe和@MortenZdk的建议修改了代码。现在我可以合成它了。 我必须检测“RX”的posedge和NEGDEDGE。因此,我将代码更改如下:

PROCESS(CLK_I)  -- Stabilizing the RX signal to avoid meta stable state
begin
  if rising_edge(CLK_I) then    
    rx_meta <= RX; 
    rx_sync <= rx_meta;      
  end if;
END PROCESS;

PROCESS (CLK_I)
BEGIN              
   IF (CLK_I'EVENT AND CLK_I = '1') THEN
     tmp_RX <= rx_sync;
     IF (rx_sync /= tmp_RX) THEN
       clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);  
     ELSE
       IF clk_cnt >2499 THEN
         clk_cnt <= to_unsigned(0,clk_cnt'LENGTH); 
       ELSE  
         clk_cnt <= clk_cnt + 1;    
       END IF;
     END IF;
     -- Clock generate as single cycle pulse    
     clk_rx <= '0';
     IF clk_cnt = 1250 THEN
        clk_rx <= '1';
     END IF;
     clk_tx <= '0';
     IF clk_cnt = 2500 THEN
       clk_tx <= '1';
     END IF;

   END IF;
END PROCESS;
过程(CLK_I)——稳定接收信号以避免亚稳态
开始
如果上升沿(CLK_I),则

rx_meta您必须重新考虑这一点,使其仅对一个信号(时钟)上的事件敏感。改变语言也无济于事。你可以在clk_I的每一个上升沿上观察RX的状态,并从那里得到它。为什么到处都有不必要的类型转换?
PROCESS(CLK_I)  -- Stabilizing the RX signal to avoid meta stable state
begin
  if rising_edge(CLK_I) then    
    rx_meta <= RX; 
    rx_sync <= rx_meta;      
  end if;
END PROCESS;

PROCESS (CLK_I)
BEGIN              
   IF (CLK_I'EVENT AND CLK_I = '1') THEN
     tmp_RX <= rx_sync;
     IF (rx_sync /= tmp_RX) THEN
       clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);  
     ELSE
       IF clk_cnt >2499 THEN
         clk_cnt <= to_unsigned(0,clk_cnt'LENGTH); 
       ELSE  
         clk_cnt <= clk_cnt + 1;    
       END IF;
     END IF;
     -- Clock generate as single cycle pulse    
     clk_rx <= '0';
     IF clk_cnt = 1250 THEN
        clk_rx <= '1';
     END IF;
     clk_tx <= '0';
     IF clk_cnt = 2500 THEN
       clk_tx <= '1';
     END IF;

   END IF;
END PROCESS;