fpgasynthesislattice-diamond

Lattice ICE5LP4K FPGA: How to add HFOSC to user vhdl


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?


Solution

  • 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