新的 DCM CLK 实例化错误?

New DCM CLK instantiation error?

这是从我的主 vhdl 文件分支出来的 .xco 文件中的代码:

-- The following code must appear in the VHDL architecture header:
------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG
component DCM_18
port
 (-- Clock in ports
  CLK_IN1           : in     std_logic;
  -- Clock out ports
  CLK_OUT1          : out    std_logic
 );
end component;

-- COMP_TAG_END ------ End COMPONENT Declaration ------------
-- The following code must appear in the VHDL architecture
-- body. Substitute your own instance name and net names.
------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
your_instance_name : DCM_18
  port map
   (-- Clock in ports
    CLK_IN1 => CLK_IN1,
    -- Clock out ports
    CLK_OUT1 => CLK_OUT1);
-- INST_TAG_END ------ End INSTANTIATION Template ------------

目标是从 50 MHz 时钟产生 18.432 MHz 时钟。这是我添加到主 vhdl 文件中的代码:

clk: in std_logic;                         -- 50 MHz clock

signal test_clk: std_logic; -- new 18.432 MHz clock
-----------------------------------------------------


component DCM_18
port
(-- Clock in ports
    CLK_IN1           : in     std_logic;
    -- Clock out ports
    CLK_OUT1          : out    std_logic
);
end component;

-------------------------------------------------

new_CLK : DCM_18
 port map
 (-- Clock in ports                      
 CLK_IN1 => clk,
   -- Clock out ports
 CLK_OUT1 => test_clk
 );

但是,我收到了这个错误:

ERROR:Xst:2035 - Port has illegal connections. This port is connected to an input buffer and other components.

有什么想法吗?

编辑:完整代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.math_real.all;

entity basic_uart is
  generic (
    DIVISOR: natural := 120 -- DIVISOR = 50,000,000 / (16 x BAUD_RATE)
    -- 9600 -> 120
     -- 19200 -> 60
  );
  port (
    clk: in std_logic;                         -- clock
    reset: in std_logic;                       -- reset

    -- Client interface
    rx_data: out std_logic_vector(7 downto 0); -- received byte
    rx_enable: out std_logic;                  -- validates received byte (1 system clock spike)
    tx_data: in std_logic_vector(7 downto 0);  -- byte to send
    tx_enable: in std_logic;                   -- validates byte to send if tx_ready is '1'
    tx_ready: out std_logic;                   -- if '1', we can send a new byte, otherwise we won't take it

    -- Physical interface
    rx: in std_logic;
    tx: out std_logic
  );
end basic_uart;

architecture Behavioral of basic_uart is

    component DCM_18
    port
    (-- Clock in ports
        CLK_IN1           : in     std_logic;
        -- Clock out ports
        CLK_OUT1          : out    std_logic
    );
    end component;

  constant COUNTER_BITS : natural := integer(ceil(log2(real(DIVISOR))));

  type fsm_state_t is (idle, active); -- common to both RX and TX FSM

  type rx_state_t is
  record
    fsm_state: fsm_state_t;                -- FSM state
    counter: std_logic_vector(3 downto 0); -- tick count
    bits: std_logic_vector(7 downto 0);    -- received bits
    nbits: std_logic_vector(3 downto 0);   -- number of received bits (includes start bit)
    enable: std_logic;                     -- signal we received a new byte
  end record;

  type tx_state_t is
  record
    fsm_state: fsm_state_t; -- FSM state
    counter: std_logic_vector(3 downto 0); -- tick count
    bits: std_logic_vector(8 downto 0); -- bits to emit, includes start bit
    nbits: std_logic_vector(3 downto 0); -- number of bits left to send
    ready: std_logic; -- signal we are accepting a new byte
  end record;

  signal rx_state,rx_state_next: rx_state_t;
  signal tx_state,tx_state_next: tx_state_t;

  signal sample, test_clk: std_logic; -- 1 clk spike at 16x baud rate
  signal sample_counter: std_logic_vector(COUNTER_BITS - 1 downto 0); -- should fit values in 0..DIVISOR-1

begin

new_CLK : DCM_18
  port map
   (-- Clock in ports
    --CLK_IN1 => clk,
     CLK_IN1 => clk,
    -- Clock out ports
    CLK_OUT1 => test_clk
    );

  -- sample signal at 16x baud rate, 1 CLK spikes
  sample_process: process (clk,reset) is
  begin
    if reset = '1' then
      sample_counter <= (others => '0');
      sample <= '0';
    elsif rising_edge(clk) then
      if sample_counter = DIVISOR - 1 then
        sample <= '1';
        sample_counter <= (others => '0');
      else
        sample <= '0';
        sample_counter <= sample_counter + 1;
      end if;
    end if;
  end process;

  -- RX, TX state registers update at each CLK, and RESET
  reg_process: process (clk,reset) is
  begin
    if reset = '1' then
      rx_state.fsm_state <= idle;
      rx_state.bits <= (others => '0');
      rx_state.nbits <= (others => '0');
      rx_state.enable <= '0';

      tx_state.fsm_state <= idle;
      tx_state.bits <= (others => '1');
      tx_state.nbits <= (others => '0');
      tx_state.ready <= '1';

    elsif rising_edge(clk) then
      rx_state <= rx_state_next;
      tx_state <= tx_state_next;

    end if;
  end process;

  -- RX FSM
  rx_process: process (rx_state,sample,rx) is
  begin
    case rx_state.fsm_state is

    when idle =>
      rx_state_next.counter <= (others => '0');
      rx_state_next.bits <= (others => '0');
      rx_state_next.nbits <= (others => '0');
      rx_state_next.enable <= '0';
      if rx = '0' then
        -- start a new byte
        rx_state_next.fsm_state <= active;
      else
        -- keep idle
        rx_state_next.fsm_state <= idle;
      end if;

    when active =>
      rx_state_next <= rx_state;
      if sample = '1' then
        if rx_state.counter = 8 then
          -- sample next RX bit (at the middle of the counter cycle)
          if rx_state.nbits = 9 then
            rx_state_next.fsm_state <= idle; -- back to idle state to wait for next start bit
            rx_state_next.enable <= rx; -- OK if stop bit is '1'
          else
            rx_state_next.bits <= rx & rx_state.bits(7 downto 1);
            rx_state_next.nbits <= rx_state.nbits + 1;
          end if;
        end if;

        rx_state_next.counter <= rx_state.counter + 1;
      end if;

    end case;
  end process;

  -- RX output
  rx_output: process (rx_state) is
  begin
    rx_enable <= rx_state.enable;
    rx_data <= rx_state.bits;
  end process;

  -- TX FSM
  tx_process: process (tx_state,sample,tx_enable,tx_data) is
  begin
    case tx_state.fsm_state is

    when idle =>
      if tx_enable = '1' then
        -- start a new bit
        tx_state_next.bits <= tx_data & '0';  -- data & start
        tx_state_next.nbits <= "0000" + 10; -- send 10 bits (includes '1' stop bit)
        tx_state_next.counter <= (others => '0');
        tx_state_next.fsm_state <= active;
        tx_state_next.ready <= '0';
      else
        -- keep idle
        tx_state_next.bits <= (others => '1');
        tx_state_next.nbits <= (others => '0');
        tx_state_next.counter <= (others => '0');
        tx_state_next.fsm_state <= idle;
        tx_state_next.ready <= '1';
      end if;

    when active =>
      tx_state_next <= tx_state;
      if sample = '1' then
        if tx_state.counter = 15 then
          -- send next bit
          if tx_state.nbits = 0 then
            -- turn idle
            tx_state_next.bits <= (others => '1');
            tx_state_next.nbits <= (others => '0');
            tx_state_next.counter <= (others => '0');
            tx_state_next.fsm_state <= idle;
            tx_state_next.ready <= '1';
          else
            tx_state_next.bits <= '1' & tx_state.bits(8 downto 1);
            tx_state_next.nbits <= tx_state.nbits - 1;
          end if;
        end if;
        tx_state_next.counter <= tx_state.counter + 1;
      end if;

    end case;
  end process;

  -- TX output
  tx_output: process (tx_state) is
  begin
    tx_ready <= tx_state.ready;
    tx <= tx_state.bits(0);
  end process;

end Behavioral;

编辑:.XCO 文件代码

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;

library unisim;
use unisim.vcomponents.all;

entity DCM_18 is
port
 (-- Clock in ports
  CLK_IN1           : in     std_logic;
  -- Clock out ports
  CLK_OUT1          : out    std_logic
 );
end DCM_18;

architecture xilinx of DCM_18 is
  attribute CORE_GENERATION_INFO : string;
  attribute CORE_GENERATION_INFO of xilinx : architecture is "DCM_18,clk_wiz_v3_6,{component_name=DCM_18,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,feedback_source=FDBK_AUTO,primtype_sel=PLL_BASE,num_out_clk=1,clkin1_period=20.000,clkin2_period=20.000,use_power_down=false,use_reset=false,use_locked=false,use_inclk_stopped=false,use_status=false,use_freeze=false,use_clk_valid=false,feedback_type=SINGLE,clock_mgr_type=AUTO,manual_override=false}";
  -- Input clock buffering / unused connectors
  signal clkin1      : std_logic;
  -- Output clock buffering / unused connectors
  signal clkfbout         : std_logic;
  signal clkfbout_buf     : std_logic;
  signal clkout0          : std_logic;
  signal clkout1_unused   : std_logic;
  signal clkout2_unused   : std_logic;
  signal clkout3_unused   : std_logic;
  signal clkout4_unused   : std_logic;
  signal clkout5_unused   : std_logic;
  -- Unused status signals
  signal locked_unused    : std_logic;

begin


  -- Input buffering
  --------------------------------------
  clkin1_buf : IBUFG
  port map
   (O => clkin1,
    I => CLK_IN1);


  -- Clocking primitive
  --------------------------------------
  -- Instantiation of the PLL primitive
  --    * Unused inputs are tied off
  --    * Unused outputs are labeled unused

  pll_base_inst : PLL_BASE
  generic map
   (BANDWIDTH            => "OPTIMIZED",
    CLK_FEEDBACK         => "CLKFBOUT",
    COMPENSATION         => "SYSTEM_SYNCHRONOUS",
    DIVCLK_DIVIDE        => 1,
    CLKFBOUT_MULT        => 14,
    CLKFBOUT_PHASE       => 0.000,
    CLKOUT0_DIVIDE       => 38,
    CLKOUT0_PHASE        => 0.000,
    CLKOUT0_DUTY_CYCLE   => 0.500,
    CLKIN_PERIOD         => 20.000,
    REF_JITTER           => 0.010)
  port map
    -- Output clocks
   (CLKFBOUT            => clkfbout,
    CLKOUT0             => clkout0,
    CLKOUT1             => clkout1_unused,
    CLKOUT2             => clkout2_unused,
    CLKOUT3             => clkout3_unused,
    CLKOUT4             => clkout4_unused,
    CLKOUT5             => clkout5_unused,
    LOCKED              => locked_unused,
    RST                 => '0',
    -- Input clock control
    CLKFBIN             => clkfbout_buf,
    CLKIN               => clkin1);

  -- Output buffering
  -------------------------------------
  clkf_buf : BUFG
  port map
   (O => clkfbout_buf,
    I => clkfbout);


  clkout1_buf : BUFG
  port map
   (O   => CLK_OUT1,
    I   => clkout0);



end xilinx;

编辑(新 CLK 实例化):从 50 MHz CLK

创建 18.4 MHz CLK
-- <-----Cut code below this line and paste into the architecture body---->

   -- DCM_CLKGEN: Frequency Aligned Digital Clock Manager
   --             Spartan-6
   -- Xilinx HDL Language Template, version 14.7

   DCM_CLKGEN_inst : DCM_CLKGEN
   generic map (
      CLKFXDV_DIVIDE => 2,       -- CLKFXDV divide value (2, 4, 8, 16, 32)
      CLKFX_DIVIDE => 38,         -- Divide value - D - (1-256)
      CLKFX_MD_MAX => 0.0,       -- Specify maximum M/D ratio for timing anlysis
      CLKFX_MULTIPLY => 14,       -- Multiply value - M - (2-256)
      CLKIN_PERIOD => 20.0,       -- Input clock period specified in nS
      SPREAD_SPECTRUM => "NONE", -- Spread Spectrum mode "NONE", "CENTER_LOW_SPREAD", "CENTER_HIGH_SPREAD",
                                 -- "VIDEO_LINK_M0", "VIDEO_LINK_M1" or "VIDEO_LINK_M2" 
      STARTUP_WAIT => FALSE      -- Delay config DONE until DCM_CLKGEN LOCKED (TRUE/FALSE)
   )
   port map (
      CLKFX => new_CLK,         -- 1-bit output: Generated clock output
      CLKFX180 => OPEN,   -- 1-bit output: Generated clock output 180 degree out of phase from CLKFX.
      CLKFXDV => OPEN,     -- 1-bit output: Divided clock output
      LOCKED => OPEN,       -- 1-bit output: Locked output
      PROGDONE => OPEN,   -- 1-bit output: Active high output to indicate the successful re-programming
      STATUS => OPEN,       -- 2-bit output: DCM_CLKGEN status
      CLKIN => CLK,         -- 1-bit input: Input clock
      FREEZEDCM => OPEN, -- 1-bit input: Prevents frequency adjustments to input clock
      PROGCLK => OPEN,     -- 1-bit input: Clock input for M/D reconfiguration
      PROGDATA => OPEN,   -- 1-bit input: Serial data input for M/D reconfiguration
      PROGEN => OPEN,       -- 1-bit input: Active high program enable
      RST => OPEN              -- 1-bit input: Reset input pin
   );

   -- End of DCM_CLKGEN_inst instantiation

出现此错误:

ERROR:Pack:198 - NCD was not produced. All logic was removed from the design. This is usually due to having no input or output PAD connections in the design and no nets or symbols marked as 'SAVE'. You can either add PADs or 'SAVE' attributes to the design, or run 'map -u' to disable logic trimming in the mapper.

问题是coregen会为source clock实例化一个global clock buffer,如果这个pin路由到一个global clock buffer,就不能也直接路由到其他地方了。

我的建议是不要将 coregen 用于一些简单的事情,例如实例化 DCM 块。如果您只是简单地实例化 DCM,您可以将源时钟连接到它 并将 连接到其他逻辑,工具将自动在正确的位置插入一个全局时钟缓冲区以允许它工作。

你似乎在使用ISE,所以去Edit > Language Templates,然后select VHDL > Device Primitive Instantiation,展开相关设备,然后select Clock Components,并为您的 DCM 找到一个模板。您可以将源时钟直接连接到此实例。

我认为这种方法的优点是:

  • 阅读您代码的任何人都可以直接看到各种参数(乘法器、除法器等),而不是必须打开 coregen。
  • 您可以根据泛型或常量指定参数,这样更容易改变输出频率。
  • 您不必担心在何处插入了哪些时钟缓冲区;在大多数情况下,没有必要手动实例化它们。

如果您在为 DCM 实例化设置各种泛型时遇到困难,请查看文档,它通常非常好。例如,此处的 Spartan 6 文档:http://www.xilinx.com/support/documentation/user_guides/ug382.pdf 第 98 页起。或者,您可以从 .xco 文件复制实例并将其用作起点。

您的输入引脚被命名为 clk 并路由到 DCM_18 组件,通过 CoreGen 创建。 DCM_18 模块使用 PLL_ADV 生成时钟。

如您所见,DCM_18 模块实例化了一个 IBUFG,通过一个特殊的(支持时钟的)输入缓冲器将您的时钟信号从外部引脚 clk 路由到一个时钟网络,这就是直接到 PLL_ADV.

PLL_ADV 输出 clkout0 通过 BUFG 路由,以将新时钟信号馈送到时钟网络,您设计中的每个触发器都可以使用它。

所以回到你的顶层模块,新时钟是通过 test_clk 提供的。你应该用这个时钟做你的人字拖。

使用clk是错误的,因为你无法在引脚(IPAD)和输入缓冲区(IBUF(G))之间获取信号。