【问题标题】:How to use the internal oscillator in an FPGA (Lattice MachXO3)?如何在 FPGA (Lattice MachXO3) 中使用内部振荡器?
【发布时间】:2019-12-24 04:45:32
【问题描述】:

我正在尝试为 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 进程的敏感度列表,我会收到一条错误消息,指出我无法从输出中读取数据。

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

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

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

【问题讨论】:

  • 可能在库 machxo3l 中存在一个实体和体系结构对,由 use machxo3l.all; 可见,它与您的组件声明相匹配,这与示例 machxo3 和 machx02 组件声明不同,后者具有额外的输出 SEDSTDBY。还缺少 C_CNT_100HZ 的声明。对于osc_int &lt;= i_clock; 的赋值,osc_int 确实有两个驱动程序,这在综合中是不合法的。进程敏感度列表应包含i_clock 而不是osc_int,这是一种端口模式OUT(Lattice Diamond 似乎不兼容-2008)。
  • 这里不明显的是osc_int如何驱动i_clock(大概是通过osc_int被用作网络名称为i_clock的时钟的输入)。在某些合成系统中,这将需要一个顶级实体。您可能想知道是否可以在此处删除端口i_clock,声明一个本地信号signal i_clock: std_logic; 并将其与OSCHInst 引脚OSC 相关联(OSC =&gt; i_clock 同时离开分配osc_int &lt;= i_clock; 应该osc_int 驱动设备输出销。
  • 去掉i_clock,直接引用OSCH,让它合成,但是,不闪烁LED或似乎表明它已连接到时钟
  • 必须是vhdl吗?在verilog中,以下工作非常好:defparam OSCH_inst.NOM_FREQ = "6.65"; OSCH OSCH_inst( .STDBY(1'b0), // 0=Enabled, 1=Disabled .OSC(osc_clk), .SEDSTDBY() );您是否通过模拟检查您的代码在理论上是否可操作?

标签: vhdl fpga lattice-diamond


【解决方案1】:

生成的时钟来自 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    相关资源
    最近更新 更多