我正在尝试在下面的VHDL代码中实现时钟同步和时钟分频器。时钟(clk_rx和clk_tx)应在总线上'RX'信号的上升沿和下降沿同步。我可以模拟以下但是它在ISE中无法合成,因为我正在使用“RX'EVENT”。任何人都可以提出替代方案吗? (Verilog也会工作)
-------------------------------------------- CLOCK DIVIDER- -------------------------------------------------- -------------------------------------
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';
答案 0 :(得分:1)
问题不仅仅是你正在使用RX'EVENT,而是你在RX'EVENT条件下有一个CLK_I'EVENT条件。那只是不可综合的。
假设CLK_I的频率远高于RX'EVENT,请尝试使用CLK_I对RX进行采样。如果RX的先前值为低且当前值为高,则在CLK_I'EVENT上同步复位clk_cnt。请注意,如果RX与CLK_I真正异步,则需要担心亚稳态,您应该在之前添加2个触发器以同步RX ,以查找从0到1的变化。
答案 1 :(得分:0)
试试这段代码。 @Joe Hass解释说,我的代码中仍然没有触发器来解决RX的亚稳态问题。
但there is a scheme用于同步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;
答案 2 :(得分:0)
您可以在下方找到代码建议。请注意以下属性:
代码:
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;
答案 3 :(得分:0)
非常感谢您的支持。
我将代码修改为@Joe和@MortenZdk建议。现在我能够合成它。 我必须检测“RX”的posedge和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;