I'm having trouble using the internal oscillator for the Lattice ICE5LP4K. Per the iCE40 Oscillator Usage Guide Appendix, the code in verilog should look like this:
SB_HFOSC OSCInst0 (
.CLKHF_EN(ENCLKHF),
.CLKHF_PU(CLKHF_POWERUP),
.CLKHF(CLKHF)
) /* synthesis ROUTE_THROUGH_FABRIC= [0|1] */;
Defparam OSCInst0.CLKHF_DIV = 2’b00;
The code base I'm working from is in VHDL, so I've added the component to my architecture as follows:
SB_HFOSC : OscInst0
port map(
CLKHF_EN => RST_SYS_N;
CLKHF_PU => RST_SYS_N;
CLKHF => HFOSC_CLK_48MHZ
);
When I tried this, I received errors related to the component SB_HFOSC not being defined. Then I found this article: lattice FPGA internal oscillator simulation issues which mentions adding lattice components to your project file.
I added a new file in my project which contains the following code from sb_ice_syn_vital.vhd:
-----------------------------------------------------
--- SB_HFOSC -------
------------------------------------------------
library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use IEEE.Vital_Primitives.all;
use IEEE.VITAL_Timing.all;
entity SB_HFOSC is
generic( CLKHF_DIV: string:="0b00";
Xon : boolean := true;
MsgOn : boolean := true;
tipd_CLKHFEN: VitalDelayType01 := (0.000 ns, 0.000 ns);
tipd_CLKHFPU: VitalDelayType01 := (0.000 ns, 0.000 ns);
tpd_CLKHFEN_CLKHF : VitalDelayType01 := (0.000 ns, 0.000 ns);
tpd_CLKHFPU_CLKHF : VitalDelayType01 := (0.000 ns, 0.000 ns)
);
port(
CLKHF : out std_logic;
CLKHFEN :in std_logic;
CLKHFPU : in std_logic
);
attribute VITAL_LEVEL0 of
SB_HFOSC : entity is true;
end SB_HFOSC ;
architecture SB_HFOSC_V of SB_HFOSC is
attribute VITAL_LEVEL0 of
SB_HFOSC_V : architecture is true;
signal CLKHFEN_ipd: std_ulogic := 'X';
signal CLKHFPU_ipd: std_ulogic := 'X';
signal CLKHF_sig : std_ulogic :='X';
component SB_HFOSC_CORE
generic( CLKHF_DIV: string:="0b00");
port (
CLKHF_PU : IN std_logic;
CLKHF_EN : IN std_logic;
CLKHF : OUT std_logic
);
end component;
begin
WireDelay : block
begin
VitalWireDelay (CLKHFEN_ipd, CLKHFEN, tipd_CLKHFEN);
VitalWireDelay (CLKHFPU_ipd, CLKHFPU, tipd_CLKHFPU);
end block;
LS: SB_HFOSC_CORE
GENERIC MAP (CLKHF_DIV => CLKHF_DIV)
port map(
CLKHF_PU=> CLKHFPU_ipd,
CLKHF_EN=> CLKHFEN,
CLKHF=> CLKHF_sig
);
VITALPathDelay :process (CLKHFEN_ipd,CLKHF_sig,CLKHFPU_ipd)
variable CLKHF_GlitchData : VitalGlitchDataType;
variable CLKHF_zd : std_ulogic :='X';
begin
CLKHF_zd:=CLKHF_sig;
VitalPathDelay01 (
OutSignal => CLKHF,
GlitchData => CLKHF_GlitchData,
OutSignalName => "CLKHF",
OutTemp => CLKHF_zd,
Paths => (--0 =>(CLKHFEN_ipd'last_event, tpd_CLKHFEN_CLKHF, true),
0 =>(CLKHFPU_ipd'last_event, tpd_CLKHFPU_CLKHF, true)),
Mode => VitalTransport,
Xon => Xon,
MsgOn => MsgOn,
MsgSeverity => warning);
end process;
end SB_HFOSC_V;
I also added the component definition (to my top architecture) from vcomponent_vital.vhd:
component SB_HFOSC is
generic(
CLKHF_DIV: string:="0b00";
Xon : boolean := true;
MsgOn : boolean := true;
tipd_CLKHFEN: VitalDelayType01 := (0.000 ns, 0.000 ns);
tipd_CLKHFPU: VitalDelayType01 := (0.000 ns, 0.000 ns);
tpd_CLKHFEN_CLKHF : VitalDelayType01 := (0.000 ns, 0.000 ns);
tpd_CLKHFPU_CLKHF : VitalDelayType01 := (0.000 ns, 0.000 ns)
);
port(
CLKHF : out std_logic;
CLKHFEN :in std_logic;
CLKHFPU : in std_logic
);
end component;
When I try to synthesize the code, I receive a slew of errors, all of which appear to be related to "vitaldelaytype01" and "vital_level0" not being defined. As you can see in the code above, I have included the IEEE Vital libraries. I tried compiling using the built-in ICECube2 compiler as well as Synplify Pro but receive similar errors in each case.
Am I following the correct process to implement the HFOSC in my code? Do I need to download additional libraries that aren't automatically provided in the ICECube2 suite?
I was able to resolve this issue through Lattice's customer support portal. The proper process for instantiating a lattice HFOSC IP block is as follows:
In your library includes:
library ice;
In your component definitions:
component SB_HFOSC
GENERIC( CLKHF_DIV :string :="0b00");
PORT(
CLKHFEN: IN STD_LOGIC ;
CLKHFPU: IN STD_LOGIC;
CLKHF:OUT STD_LOGIC
);
END COMPONENT;
In your instance instantiations:
u_osc : SB_HFOSC
GENERIC MAP(CLKHF_DIV =>"0b00")
port map(
CLKHFEN => RST_SYS_N,
CLKHFPU => RST_SYS_N,
CLKHF => HFOSC_CLK_48MHZ
);
Take note of the pin names - they are different from the Lattice guides which is why I was having issues instantiating the component.
One other interesting thing I learned in the process was that the HFOSC block uses a global buffer, but the Lattice tool doesn't recognize that up front so it can run into issues during post-synthesis P&R. To reserve one of the 8 buffers for the HFOSC component, limit the total global buffers to 7 as follows (insert into your top level architecture definition):
attribute syn_global_buffers : integer;
attribute syn_global_buffers of struct : architecture is 7;
Hope this helps others!
Rob