首页 > 解决方案 > 如何在 FPGA (Lattice MachXO3) 中使用内部振荡器?

问题描述

我正在尝试为 Lattice MachXO3L 分线板制作 Blink-LED 程序。我相信我已经设置了内部振荡器,我只是不知道如何连接到它的输出并使用它,当我尝试时会出错。这是在具有 LED 和开关的分线板上。当开关单向翻转时,它应该以 1Hz 的频率振荡,而当开关翻转到另一向时,它会关闭。

我已阅读 PLL 使用指南并在互联网上搜索答案。我相信我已经很接近了,并且由于对 VHDL 和 FPGA 不熟悉而陷入了一些语法问题。基本上,我的主要代码是'进程和它下面的所有代码。上面的任何内容基本上都是来自 PLL 使用指南的内容。

library ieee;
use ieee.std_logic_1164.all;
library machxo3l;
use machxo3l.all;

entity led_blink is
    port (
        i_switch_1  : in std_logic;
        o_led_1     : out std_logic;
        i_clock     : in std_logic;
        osc_int     : out std_logic
    );
end led_blink;

architecture rtl of led_blink is
    COMPONENT OSCH
    -- synthesis translate_off
    GENERIC (NOM_FREQ: string := "12.09");
    -- synthesis translate on
    PORT (  STDBY:IN std_logic;
            OSC:OUT std_logic);
    END COMPONENT;

    attribute NOM_FREQ : string;
    attribute NOM_FREQ of OSCHinst0 : label is "12.09";

    constant C_CNT_1HZ      : natural := 6000000;

    signal R_CNT_1HZ        : natural range 0 to C_CNT_1HZ;

    signal R_1HZ            : std_logic := '0';

begin

OSCHInst0: OSCH
-- synthesis translate_off
    GENERIC MAP(NOM_FREQ => "12.09")
-- synthesis translate on
    PORT MAP (STDBY => '0',
    OSC             => osc_int
    );

p_1HZ : process (i_clock) is
begin
    if rising_edge(i_clock) then
        if R_CNT_1HZ     = C_CNT_100HZ-1 then
            R_1HZ       <= not R_1Hz;
            R_CNT_1HZ       <= 0;
        else
            R_CNT_1HZ   <= R_CNT_1HZ + 1;
        end if;
    end if;
end process;

osc_int <= i_clock;

o_led_1     <= R_1HZ        when (i_switch_1 = '0') else not R_1HZ;
end rtl;

如果我尝试分配osc_int给进程的敏感度列表p_1Hz,我会收到一条错误消息,指出我无法从输出中读取。

只是一个旁注,以防其他观众像我一样感到困惑,开车i_clock似乎osc_int不合逻辑,因为它使用的分配似乎暗示发生相反的情况osc_int <= i_clock。如果我错了,请纠正我,但它是将输入分配给输出,这对非 hdl 程序员来说似乎很困惑,因为方向是由输入/输出类型决定的,而不是由赋值运算符本身决定的。

当我这样做(将 i_clk 链接到 osc_int)时,它会保存而不给我错误,直到我尝试合成它说有多个非三态驱动程序的代码i_clock。我可以想象这是真的唯一方法是,如果名为 的“组件”部分中的“端口”OSC被映射到osc_int,会创建两个驱动信号,这两个驱动信号都链接到i_clock该单个osc_int <= i_clock;语句中。但如果这是真的,你将如何访问时钟的输出呢?

如果我只是删除该osc_int <= i_clock语句,它就可以工作,只是 LED 常亮/常灭,而不是振荡/常灭。

标签: vhdlfpgalattice-diamond

解决方案


生成的时钟来自 OSCH 组件内部。那么你不需要任何 i_clock 来实现你想要的。内部振荡器的输出是 OSCH 组件的 OUT 端口。

你可以试试这个:

entity led_blink is
    port (
        i_switch_1  : in std_logic;    -- from the input switch : OK
        o_led_1     : out std_logic    -- to the blinking led   : OK 
    );
end led_blink;
architecture rtl of led_blink is
    COMPONENT OSCH
      -- synthesis translate_off
      GENERIC (NOM_FREQ: string := "12.09");
      -- synthesis translate on
      PORT (  STDBY:IN std_logic;
              OSC:OUT std_logic);
    END COMPONENT;

    attribute NOM_FREQ : string;
    attribute NOM_FREQ of OSCHinst0 : label is "12.09";

    constant C_CNT_1HZ      : natural := 6000000;

    signal R_CNT_1HZ        : natural range 0 to C_CNT_1HZ := 0;

    signal R_1HZ            : std_logic := '0';

begin

OSCHInst0: OSCH
-- synthesis translate_off
    GENERIC MAP(NOM_FREQ => "12.09")
-- synthesis translate on
    PORT MAP (STDBY => '0',
    OSC             => osc_int -- <= this is the 12.09MHz internal clock from the internal oscillator
    );

p_1HZ : process (osc_int) is
begin
    if rising_edge(osc_int) then
        if R_CNT_1HZ     = C_CNT_100HZ-1 then
            R_1HZ       <= not R_1Hz;
            R_CNT_1HZ       <= 0;
        else
            R_CNT_1HZ   <= R_CNT_1HZ + 1;
        end if;
    end if;
end process;


o_led_1     <= R_1HZ        when (i_switch_1 = '0') else '0';
end rtl;

推荐阅读