Output an internal fabric clock to LVDS (xilinx zynq device) - vhdl

I am trying to push my fabric clock to an output LVDS pair on a ZedBoard. I am using the solution provided here by scary_jeff.
FCLK_CLK1 is using a DDR PLL set to 150 MHz. I created a testbench for the IP which shows the expeceted output (the lvds pairs following the input clock with the expected inversion between the pairs).
The vhdl used to generate the ip :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library UNISIM;
use UNISIM.Vcomponents.all;
entity clk_to_lvds_v1_0 is
port (
clk_in : in std_logic;
clk_out_p : out std_logic;
clk_out_n : out std_logic
);
end clk_to_lvds_v1_0;
architecture arch_imp of clk_to_lvds_v1_0 is
signal clk_buf : std_logic;
signal clk_inv : std_logic;
begin
-- V1
-- oddr_inst : oddr
-- generic map(
-- DDR_CLK_EDGE => "SAME_EDGE",
-- INIT => '0',
-- SRTYPE => "SYNC"
-- )
-- port map (
-- Q => clk_buf,
-- C => clk_in,
-- CE => '1',
-- D1 => '1',
-- D2 => '0',
-- R => '0',
-- S => '0'
-- );
-- V2
clk_inv <= not clk_in;
ODDR_pxlclk_p : ODDR2
generic map(
DDR_ALIGNMENT => "NONE",
INIT => '0',
SRTYPE => "SYNC")
port map(
Q => clk_buf,
C0 => clk_in,
C1 => clk_inv,
CE => '1',
D0 => '1',
D1 => '0',
R => '0',
S => '0'
);
obufds_inst : obufds
generic map ( IOSTANDARD=>"LVDS_25" )
port map(
O => clk_out_p,
OB => clk_out_n,
I => clk_buf
);
end arch_imp;
The output is being pushed to JC1_P/N pmod ports using LVDS_25 standard.
set_property PACKAGE_PIN AB7 [get_ports {clk_out_p[0]}]
set_property IOSTANDARD LVDS_25 [get_ports {clk_out_p[0]}]
I am measuring the output with a scope (6 GHz, 20 GS/s) and all I'm seeing is noise. I turned on some LEDs in the design to ensure that the bitstream is being loaded properly.
Is this still the preferred method by Xilinx to output a clock on I/O?

The problem was I wasn't initializing the ps7_init on the ARM cores which kicks the clocks off. After doing that I saw the output clock on a scope.

Related

Trouble Instantiating PLL of Lattice iCE40

I have Lattice iCE40 HX8K FPGA in 256 BGA package. I want to use one of the available PLL modules to transform external clock frequency of 37MHz to internal clock for use inside of the FPGA of 74MHz.
I used the "Configure PLL Module" in IceCube2 and used the following configuration:
- PLL Type section:
- GlobalNetworks to be Driven by PLL Output : 1;
- Dedicated Clock Pad;
- PLL Operation Modes:
- No Compensation Mode;
- Additional Delay Settings : No;
- Frequency:
- Input - 37MHz;
- Output - 74MHz;
- Others - nothing selected;
Then I get the two VHDL files - SO_pll.vhd and SO_pll_inst.vhd. I have file Design.vhd where my code is supposed to go.
If I understand correctly Lattice documentation, I need to specify that my Design.vhd (its Entity) is top Level Module, which I did. I need to include
SO_pll.vhd in the list of design files in IceCube2, which I did. And last - I need to use the template provided in SO_pll_inst.vhd to instantiate in my main code the PLL by port mapping the PLL signals to signals in my Design.vhd. Here comes the trouble - how to do it?
---Design.vhd---
library IEEE;
use IEEE.std_logic_1164.all;
entity Design is
port(
I_CLK: in std_logic
);
end entity Design;
architecture RTL of Design is
signal S_CLK : std_logic;
signal S_RESET : std_logic;
begin
SO_pll_inst: SO_pll
port map(
REFERENCECLK => I_CLK,
PLLOUTCORE => open,
PLLOUTGLOBAL => S_CLK,
RESET => S_RESET
);
end RTL;
---SO_pll_inst.vhd---Generated by IceCube2
SO_pll_inst: SO_pll
port map(
REFERENCECLK => ,
PLLOUTCORE => ,
PLLOUTGLOBAL => ,
RESET =>
);
---SO_pll.vhd---Generated by IceCube2
library IEEE;
use IEEE.std_logic_1164.all;
entity SO_pll is
port(
REFERENCECLK: in std_logic;
RESET: in std_logic;
PLLOUTCORE: out std_logic;
PLLOUTGLOBAL: out std_logic
);
end entity SO_pll;
architecture BEHAVIOR of SO_pll is
signal openwire : std_logic;
signal openwirebus : std_logic_vector (7 downto 0);
component SB_PLL40_CORE
generic (
--- Feedback
FEEDBACK_PATH : string := "SIMPLE"; -- String (simple, delay,
phase_and_delay, external)
DELAY_ADJUSTMENT_MODE_FEEDBACK : string := "FIXED";
DELAY_ADJUSTMENT_MODE_RELATIVE : string := "FIXED";
SHIFTREG_DIV_MODE : bit_vector(1 downto 0) := "00";
-- 0-->Divide by 4, 1-->Divide by 7, 3 -->Divide by 5
FDA_FEEDBACK : bit_vector(3 downto 0) := "0000";
-- Integer (0-15).
FDA_RELATIVE : bit_vector(3 downto 0) := "0000";
-- Integer (0-15).
PLLOUT_SELECT : string := "GENCLK";
--- Use the spread sheet to populate the values below
DIVF : bit_vector(6 downto 0);
-- Determine a good default value
DIVR : bit_vector(3 downto 0);
-- Determine a good default value
DIVQ : bit_vector(2 downto 0);
-- Determine a good default value
FILTER_RANGE : bit_vector(2 downto 0);
-- Determine a good default value
--- Additional C-Bits
ENABLE_ICEGATE : bit := '0';
--- Test Mode Parameter
TEST_MODE : bit := '0';
EXTERNAL_DIVIDE_FACTOR : integer := 1
-- Not Used by model, Added for PLL config GUI
);
port (
REFERENCECLK : in std_logic; -- Driven by core logic
PLLOUTCORE : out std_logic; -- PLL output to core logic
PLLOUTGLOBAL : out std_logic; -- PLL output to global network
EXTFEEDBACK : in std_logic; -- Driven by core logic
DYNAMICDELAY : in std_logic_vector (7 downto 0); -- Driven by core
logic
LOCK : out std_logic; -- Output of PLL
BYPASS : in std_logic; -- Driven by core logic
RESETB : in std_logic; -- Driven by core logic
LATCHINPUTVALUE : in std_logic; -- iCEGate Signal
-- Test Pins
SDO : out std_logic; -- Output of PLL
SDI : in std_logic; -- Driven by core logic
SCLK : in std_logic -- Driven by core logic
);
end component;
begin
SO_pll_inst: SB_PLL40_CORE
-- Fin=37, Fout=74
generic map(
DIVR => "0000",
DIVF => "0001111",
DIVQ => "011",
FILTER_RANGE => "011",
FEEDBACK_PATH => "SIMPLE",
DELAY_ADJUSTMENT_MODE_FEEDBACK => "FIXED",
FDA_FEEDBACK => "0000",
DELAY_ADJUSTMENT_MODE_RELATIVE => "FIXED",
FDA_RELATIVE => "0000",
SHIFTREG_DIV_MODE => "00",
PLLOUT_SELECT => "GENCLK",
ENABLE_ICEGATE => '0'
)
port map(
REFERENCECLK => REFERENCECLK,
PLLOUTCORE => PLLOUTCORE,
PLLOUTGLOBAL => PLLOUTGLOBAL,
EXTFEEDBACK => openwire,
DYNAMICDELAY => openwirebus,
RESETB => RESET,
BYPASS => '0',
LATCHINPUTVALUE => openwire,
LOCK => open,
SDI => openwire,
SDO => open,
SCLK => openwire
);
end BEHAVIOR;
I just added Design.vhd and SO_pll.vhd to the list of design files. If I run synthesis with Lattice LSE the synthesis is successful, but the placer report says 0/2 PLLs used. If I run Synthesys with Synplify Pro placer report says 1/2 PLLs used,but I really cannot use it since I have not mapped the signals.
When I get the template from SO_pll_inst.vhd and place it inside of the architecture of Design.vhd I get the error message:
"ERROR - synthesis: design.vhd(19): so_pll is not declared. VHDL-1241"
Well, apparently I am missing something. If it is a template, I would expect just to map my signal and have it running. But no. Either I am doing something wrong, or...I am doing something wrong :) Please help.
Funny - I posted the question and I am posting the answer! :) here it goes:
---Design.vhd---
library IEEE;
use IEEE.std_logic_1164.all;
entity Design is
port(
I_CLK: in std_logic;
I_RESET: in std_logic;
O_PLLOUTGLOBAL : out std_logic
);
end entity Design;
architecture RTL of Design is
begin
SO_pll_inst: entity SO_pll
port map(
REFERENCECLK => I_CLK,
PLLOUTCORE => open,
PLLOUTGLOBAL => O_PLLOUTGLOBAL,
RESET => I_RESET
);
end RTL;
So, as obvious from the file above the key is in the instantiating of the entity of the PLL file. I was missing the keyword "entity" before the name of the entity specified in the PLL file. As expected, I was doing something wrong.

Lattice Fpga Internal clock

I'm trying to configure a lattice MachX03's internal Oscillator. I read the MachXO3 sysCLOCK PLL Design and Usage Guide* and tried using the vhdl code found on page 31 of the documente, but I keep getting this error (VHDL-1261) syntax error near COMPONENT. Can someone tell me how I can get the clock to work using VHDL? here is the code I'm trying to use:
LIBRARY lattice;
library machXO3;
use machXO3.all;
COMPONENT OSCH
GENERIC(
NOM_FREQ: string := "53.20"); --53.20MHz, or can select other supported frequencies
PORT(
STDBY : IN STD_LOGIC; --'0' OSC output is active, '1' OSC output off
OSC : OUT STD_LOGIC; --the oscillator output
SEDSTDBY : OUT STD_LOGIC); --required only for simulation when using standby
END COMPONENT;
OSCInst0: OSCH
GENERIC MAP (NOM_FREQ => "53.20")
PORT MAP (STDBY => '0', OSC => clk, SEDSTDBY => OPEN);
and here is the code found in the manual:
library machXO3;
use machXO3.all;
COMPONENT OSCH
-- synthesis translate_off
GENERIC (NOM_FREQ: string := "2.56");
-- synthesis translate_on
PORT (STDBY:INstd_logic;
OSC:OUTstd_logic;
SEDSTDBY:OUTstd_logic);
END COMPONENT;
attribute NOM_FREQ : string;
attribute NOM_FREQ of OSCinst0 : label is "2.56";
begin
OSCInst0: OSCH
-- synthesis translate_off
GENERIC MAP( NOM_FREQ => "2.56" )
-- synthesis translate_on
PORT MAP (STDBY=> stdby,
OSC => osc_int,
SEDSTDBY => stdby_sed
);
*http://www.latticesemi.com/view_document?document_id=50124
to Use the internal Osc basically use the code in the menu, mentioned above. to get a simple osc working write the following in vhdl. the code sets up a 2.56 Mhz clock, the slowest the internal clock can generate. the highest frequency the interal generator can output is 133 Mhz, refer to pages 30-20 of the document http://www.latticesemi.com/view_document?document_id=50124
library ieee;
use ieee.std_logic_1164.all;
-- For Main Clock --
library machXO3l;
use machXO3l.all;
--------------------
entity Clock is
port (stdby : in std_logic;
osc_int: out std_logic
);
end Clock;
architecture Clock_behav of Clock is
COMPONENT OSCH
-- synthesis translate_off
GENERIC (NOM_FREQ: string := "2.56");
-- synthesis translate_on
PORT (STDBY : IN std_logic;
OSC : OUT std_logic
);
END COMPONENT;
attribute NOM_FREQ : string;
attribute NOM_FREQ of OSCinst0 : label is "2.56";
begin
Clock: OSCH
-- synthesis translate_off
GENERIC MAP( NOM_FREQ => "2.56" )
-- synthesis translate_on
PORT MAP ( STDBY => stdby,
OSC => osc_int
);
end Clock_behav;

Using the SB_RGBA_DRV primitive in VHDL

I'm having trouble using the SB_RGBA_DRV primitive provided for the Lattice ICE40UP fpga.
The Technology Library provides a verilog example which I got to work but when i try using it in VHDL the P&R fails, outputting the following message:
Error: Illegal Connection: Pin 'RGB2' of instance 'myrgb' of type 'SB_RGBA_DRV' should be connected to only one top module port. It is connected to the following terminals :
LED2_obuf/DOUT0
This is my .vhdl file:
library ieee;
use ieee.std_logic_1164.all;
entity led is
port (
LED0 : out std_logic;
LED1 : out std_logic;
LED2 : out std_logic
);
end entity led;
architecture rtl of led is
component SB_HFOSC is
port (
CLKHFEN : in std_logic;
CLKHFPU : in std_logic;
CLKHF : out std_logic
);
end component;
component SB_RGBA_DRV is
generic (
RGB0_CURRENT: string:="0b000000";
RGB1_CURRENT: string:="0b000000";
RGB2_CURRENT: string:="0b000000"
);
port (
RGBPU : in std_logic;
RGBLEDEN : in std_logic;
RGB0PWM : in std_logic;
RGB1PWM : in std_logic;
RGB2PWM : in std_logic;
RGB0 : out std_logic;
RGB1 : out std_logic;
RGB2 : out std_logic
);
end component;
signal int_osc : std_logic;
begin
myosc : SB_HFOSC
PORT MAP (
CLKHFEN => '1',
CLKHFPU => '1',
CLKHF => int_osc
);
myrgb : SB_RGBA_DRV
GENERIC MAP (
RGB0_CURRENT => "0b111111",
RGB1_CURRENT => "0b111111",
RGB2_CURRENT => "0b111111"
)
PORT MAP (
RGBPU => '1',
RGBLEDEN => '1',
RGB0PWM => '1',
RGB1PWM => '1',
RGB2PWM => '1',
RGB0 => LED0,
RGB1 => LED1,
RGB2 => LED2
);
process
begin
wait until int_osc'event;
end process;
end rtl;
The answer to your question is here:
http://we.easyelectronics.ru/teplofizik/podklyuchenie-vstroennogo-modulya-tokovogo-drayvera-fpga-serii-ice5-ice40-ultra.html
(Scroll down.) Yes, it's in Russian. The key is to add the following declaration at the top of your design file:
library sb_ice40_components_syn;
use sb_ice40_components_syn.components.all;
The other things that Teplofizik mentions may be useful to know but aren't entirely necessary.
Your code is almost correct with the above addition. I didn't try to build and run Teplofizik's sample code, but I did modify your code (to actually use the on-chip oscillator) and that code is happily running on an "iCE40UP Breakout" board:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library sb_ice40_components_syn;
use sb_ice40_components_syn.components.all;
entity led is
port (
LED0 : out std_logic;
LED1 : out std_logic;
LED2 : out std_logic
);
end entity led;
architecture rtl of led is
-- not necessary - declared in library
--component SB_HFOSC is
-- port (
-- CLKHFEN : in std_logic;
-- CLKHFPU : in std_logic;
-- CLKHF : out std_logic
-- );
--end component;
--
--component SB_RGBA_DRV is
-- generic (
-- RGB0_CURRENT: string:="0b000000";
-- RGB1_CURRENT: string:="0b000000";
-- RGB2_CURRENT: string:="0b000000"
-- );
-- port (
-- RGBPU : in std_logic;
-- RGBLEDEN : in std_logic;
-- RGB0PWM : in std_logic;
-- RGB1PWM : in std_logic;
-- RGB2PWM : in std_logic;
-- RGB0 : out std_logic;
-- RGB1 : out std_logic;
-- RGB2 : out std_logic
-- );
--end component;
signal int_osc : std_logic;
signal count: unsigned(25 downto 0);
signal led0_en: std_logic;
signal led1_en: std_logic;
signal led2_en: std_logic;
begin
myosc : SB_HFOSC
generic map(
CLKHF_DIV => "0b00" -- 00 = 48 MHz, 01 = 24 MHz, 10 = 12 MHZ, 11 = 6 MHz
)
PORT MAP (
CLKHFEN => '1',
CLKHFPU => '1',
CLKHF => int_osc
);
myrgb : SB_RGBA_DRV
GENERIC MAP (
-- RGB0_CURRENT => "0b111111",
-- RGB1_CURRENT => "0b111111",
-- RGB2_CURRENT => "0b111111"
CURRENT_MODE => "0b0", -- 0 = full current, 1 = halve the current
RGB0_CURRENT => "0b000001", -- 4 mA is more than enough
RGB1_CURRENT => "0b000001",
RGB2_CURRENT => "0b000001"
)
PORT MAP (
-- RGBPU => '1', -- this is an SB_RGB_DRV parameter
CURREN => '1',
RGBLEDEN => '1',
-- RGB0PWM => '1', -- boring
-- RGB1PWM => '1',
-- RGB2PWM => '1',
RGB0PWM => led0_en,
RGB1PWM => led1_en,
RGB2PWM => led2_en,
RGB0 => LED0,
RGB1 => LED1,
RGB2 => LED2
);
-- boring
--process
-- begin
-- wait until int_osc'event;
--end process;
-- cycle through LED's
led0_en <= count(25) and count(24);
led1_en <= count(25) and not count(24);
led2_en <= not count(25) and count(24);
count_proc: process(int_osc)
begin
if rising_edge(int_osc) then
count <= count+1;
end if;
end process;
end rtl;

Either generate a component or drive signal with input

I am trying to create an architecture that has the following behaviour:
entity component1 is
generic (
debounce_ticks : natural range 0 to natural'high
);
port (
rst : in STD_LOGIC;
clk : in STD_LOGIC;
sclk : in STD_LOGIC;
[...]
);
end component1;
architecture Behavioral of component1 is
signal sclk_debounced : STD_LOGIC;
[...]
begin
debouncer:
if debounce_ticks > 0 generate
sclk_debouncer : entity work.static_debouncer
generic map (
debounce_ticks => debounce_ticks
)
port map (
clk => clk,
pulse_in => sclk,
pulse_out => sclk_debounced
);
else --Or something
sclk_debounced <= sclk
end generate debouncer;
[..]
end Behavioral;
So, I have this signal, which I want to either just connect to an input or loop trough a component, based on a generic.
How can I achieve this?
The if generate statement does not support an else clause, so you need to invert the check to simulate an else. Also you need a second label for the other if generate.
begin
debouncer:
if debounce_ticks > 0 generate
sclk_debouncer : entity work.static_debouncer
generic map (
debounce_ticks => debounce_ticks
)
port map (
clk => clk,
pulse_in => sclk,
pulse_out => sclk_debounced
);
end generate debouncer;
no_debouncer:
if debounce_ticks <= 0 generate
sclk_debounced <= sclk
end generate no_debouncer;
[...]
You need two changes:
component is a reserved word and can't be used as an identifier.
the reserved word generate is missing after else
Renamed entity:
entity component1 is
generic (
debounce_ticks : natural range 0 to natural'high
);
port (
rst : in STD_LOGIC;
clk : in STD_LOGIC;
sclk : in STD_LOGIC;
-- [...]
);
end entity component1;
Fixed generate statement:
architecture Behavioral of component1 is
signal sclk_debounced : STD_LOGIC;
-- [...]
begin
debouncer: if debounce_ticks > 0 generate
sclk_debouncer : entity work.static_debouncer
generic map (
debounce_ticks => debounce_ticks
)
port map (
clk => clk,
pulse_in => sclk,
pulse_out => sclk_debounced
);
else generate --Or something
sclk_debounced <= sclk
end generate debouncer;
-- [..]
end architecture Behavioral;

Optional PORTs in VHDL?

I am writing an IP-Core and depending on which generic parameters user chooses not all OUT/IN Ports are needed. Is it possible to have optional Ports? I know something similar should be possible, since when I use Xilinx IP-Cores, depending on parameters not all PORTs are included.
Ports can't be optional, but usage of ports can be, which for the designer is as if they are not there.
Input ports that are not mapped (used) must have a default value in the entity, and output ports can simply be left unmapped.
If an entity is declared like for example:
entity mdl_sub is
generic(
A_C_USE : boolean := FALSE;
B_D_USE : boolean := FALSE);
port(
clk_i : in std_logic;
rst_i : in std_logic;
a_i : in std_logic := 'X';
b_i : in std_logic := 'X';
c_o : out std_logic;
d_o : out std_logic);
end entity;
Then the module can be used in the different configuration like below, where the use of ports can then differ based on the configuration:
-- Using port a_i and c_o
mdl_sub_0 : entity work.mdl_sub
generic map(
A_C_USE => TRUE)
port map(
clk_i => clk_i,
rst_i => rst_i,
a_i => m0_a_i,
c_o => m0_c_o);
-- Using port b_i and d_o
mdl_sub_1 : entity work.mdl_sub
generic map(
B_D_USE => TRUE)
port map(
clk_i => clk_i,
rst_i => rst_i,
b_i => m1_b_i,
d_o => m1_d_o);
All signals and ports are std_logic.

Resources