Reputation: 159
here's the code within the .xco file which was branched off my main vhdl file:
-- 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 ------------
the goal was to produce a 18.432 MHz clk from a 50 MHz clock. Here's the code I added to my main vhdl file:
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
);
However, I am recieving this error:
ERROR:Xst:2035 - Port has illegal connections. This port is connected to an input buffer and other components.
Any ideas?
EDIT: COMPLETE CODE
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;
EDIT: .XCO file code
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;
EDIT (NEW CLK instantiation): creating a 18.4 MHz CLK from a 50 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
Got this error:
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.
Upvotes: 0
Views: 2694
Reputation: 16231
Your input pin is named clk
and routed to the DCM_18
component, created via CoreGen. The DCM_18 module uses a PLL_ADV to generate your clock.
As you can see, the DCM_18 module instantiates a IBUFG to route your clock signal from extern pin clk
through a special (clock capable) input buffer and into a clock net, that goes straight to the PLL_ADV.
The PLL_ADV output clkout0 is routed through a BUFG, to feed the new clock signal into a clock network, that can be used by every flip flop in your design.
So back in your top-level module, the new clock is provided via test_clk
. You should use this clock for your flip flops.
Using clk
is a fault, because you can't grab a signal between the pin (IPAD) and the input buffer (IBUF(G)).
Upvotes: 1
Reputation: 4374
The problem is that coregen will instantiate a global clock buffer for the source clock, and if this pin is routed to a global clock buffer, it cannot also be directly routed to other places.
My advice is not to use coregen for something simple like instantiating a DCM block. If you simply instantiate the DCM, you can connect your source clock to it and to other logic, and the tools will automatically insert a global clock buffer in the right place to allow this to work.
You seem to be using ISE, so go to Edit > Language Templates
, then select VHDL > Device Primitive Instantiation
, expand the relevant device, then select Clock Components
, and find a template for your DCM. You can connect your source clock directly to this instantiation.
The advantages of this approach as I see it are:
If you have trouble setting the various generics for the DCM instantiation, take a look at the documentation, which is usually pretty good. For example, the Spartan 6 documentation here: http://www.xilinx.com/support/documentation/user_guides/ug382.pdf page 98 onwards. Alternatively, you can copy the instantiation from the .xco
file and use this as a starting point.
Upvotes: 1