0

我正在尝试在以下 VHDL 代码中实现时钟同步和时钟分频器。时钟(clk_rx 和 clk_tx)应在总线上“RX”信号的上升沿和下降沿同步。我可以模拟以下内容,但由于我使用的是“RX'EVENT”,因此无法在 ISE 中合成。有人可以为此提出替代方案吗?(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';
4

4 回答 4

1

问题不仅在于您使用的是 RX'EVENT,还在于您在 RX'EVENT 条件内有一个 CLK_I'EVENT 条件。那只是无法合成。

假设 CLK_I 的频率远高于 RX'EVENT,尝试使用 CLK_I 对 RX 进行采样。如果 RX 之前的值为低,而当前值为高,则在 CLK_I'EVENT 上同步复位 clk_cnt。请注意,如果 RX 与 CLK_I 真正异步,您需要担心亚稳态,并且您应该在寻找从 0 到 1 的变化之前添加 2 个触发器来同步 RX 。

于 2013-07-14T12:52:42.730 回答
1

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

  • clk_rx_o (clk_rx) 和 clk_rx_o (clk_tx) 是作为触发器的输出生成的,这是为了避免在基于进程外 cnt 的组合比较生成信号时可能发生的毛刺
  • rx_i 由两个触发器同步,假设它尚未与 clk_i 同步
  • 时钟分频为 2501,因为 cnt 由于在 (cnt > 2499) 时换行而从 0 .. 2500 开始。除以 2500 时,请改用 (cnt >= 2499)。
  • VHDL 编码风格:所有信号名称都是小写,VHDL 语句也是如此,表达式周围的间距一致以提高可读性

代码:

library ieee;
use ieee.std_logic_1164.all;

entity mdl is
  port(
    clk_i    : in  std_logic;
    rx_i     : in  std_logic;
    clk_rx_o : out std_logic;
    clk_tx_o : out std_logic);
end entity;

library ieee;
use ieee.numeric_std.all;

architecture syn of mdl is

  signal rx_meta : std_logic;
  signal rx_sync : std_logic;
  signal cnt     : std_logic_vector(12 - 1 downto 0);

begin

  -- rx_i sync to clk_i
  process (clk_i) is
  begin
    if rising_edge(clk_i) then
      rx_meta <= rx_i;
      rx_sync <= rx_meta;
    end if;
  end process;

  process (clk_i) is
  begin
    if rising_edge(clk_i) then
      -- Clock align and divide
      if rx_sync = '1' then
        cnt <= std_logic_vector(to_unsigned(0, cnt'length));
      else
        if unsigned(cnt) > 2499 then
          cnt <= std_logic_vector(to_unsigned(0, cnt'length));
        else
          cnt <= std_logic_vector(unsigned(cnt) + 1);
        end if;
      end if;
      -- Clock generate as single cycle pulse
      clk_rx_o <= '0';
      if unsigned(cnt) = 1250 then
        clk_rx_o <= '1';
      end if;
      clk_tx_o <= '0';
      if unsigned(cnt) = 2499 then
        clk_tx_o <= '1';
      end if;
    end if;
  end process;

end architecture;
于 2013-07-14T21:32:43.970 回答
0

试试这个代码。正如@Joe Hass 解释的那样,我的代码中仍然没有触发器来解决 RX 的亚稳态。

但是有一个同步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;
于 2013-07-14T14:58:31.670 回答
0

非常感谢您的支持。

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

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;
于 2013-07-21T13:46:09.907 回答