如何在FPGA中使用内部振荡器(Lattice MachXO3)?



我正在尝试为莱迪思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 <= i_clock的任务。 如果我错了,请纠正我,但它正在将输入分配给输出,这对非 hdl 程序员来说似乎令人困惑,因为方向是由输入/输出类型决定的,而不是赋值运算符本身。

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

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

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

最新更新