VHDL 一直让我很感兴趣,刚从 Digilent 收到我的新 Arty S7-25 FPGA 板,我有机会尝试一下!我想为我的第一个项目使用 LED 做一些事情,所以我制作了一些不同的模式,并在代码中将它们绑定在一起,以便它们一个接一个地显示。
作为 VHDL 的新手,代码可能达不到标准,但我会尽力解释,我希望你也能得到这些很酷的模式来点亮你的 FPGA 板!
我们将使用板上的四个标准 LED(不是 RGB LED)
代码的总体思路是让不同的计数器控制具有使能信号的模式的长度。这些使能信号由状态机驱动。另一个process
模块对启用信号进行解码,并确定 LED 上应显示的模式。
可以在此处找到 github 存储库。查看“src”文件夹以找到主要实体。
首先,我有一些信号声明
-- enables for different patterns/counters
signal r_patt1_en : std_logic := '1';
signal r_patt2_en : std_logic := '0';
signal r_patt3_en : std_logic := '0';
signal r_patt4_en : std_logic := '0';
-- pattern counters
signal r_patt1_cntr : integer range 0 to 1e6 := 0;
signal r_patt1_light_LED : integer range 0 to 4 := 0;
signal r_patt2_cntr : integer range 0 to 2e6 := 0;
signal r_patt3_cntr : integer range 0 to 2e6 := 0;
signal r_patt3_alt_cntr : integer range 0 to 5 := 0;
signal r_patt4_duty : integer range 0 to 1e5 := 0;
signal r_patt4_cntr : integer range 0 to 1e5 := 0;
signal r_patt4_incr_duty : std_logic := '0';
上述代码的顶部包含每个模式的启用信号。在任何给定时间,只有一个可以处于活动状态。这些信号有助于确定 LED 应遵循的模式,以及启用特定于该模式的计数器。
这些是其他一些信号
-- indicates if pattern should be changed
signal r_change_pattern : std_logic := '0';
signal r_clk_cntr : integer range 0 to 36e6 := 0;
-- FSM
type t_state is (PATT1, PATT2, PATT3, PATT4);
signal STATE : t_state;
实体需要知道何时改变模式(在这种情况下,每 3 秒一次,或何时r_clk_cntr
翻转),因此r_change_pattern
被创建。此外,状态机的状态在此处声明。
让我们进入其中一种模式。
模式 1 一个接一个地切换每个 LED,就像一个带有单个 1 的移位寄存器,其余的都是零(希望这是有道理的:p)。“on” LED 保持亮起 83.333 ms(1/12 秒很容易使用 12 MHz 系统时钟实现),然后每 83.333 ms 打开一个新 LED。我为这些计数器创建了两个单独的进程。
-- pattern 1 counter keeps each LED on in pattern 1 for 83.333 ms
PATT1_CNTR_PROC : process(i_clk)
begin
if rising_edge(i_clk) then
if r_patt1_en = '0' then
r_patt1_cntr <= 0;
else
if r_patt1_cntr < 1e6 then
r_patt1_cntr <= r_patt1_cntr + 1;
else
r_patt1_cntr <= 0;
end if;
end if;
end if;
end process;
对于 12 MHz 系统时钟,1/12 秒(或 100 万个 clk 周期计数)是使用时间的简单度量。r_patt1_cntr
在翻转到 0 之前计数到这个数字,导致 1/12 秒或 83.333 毫秒。
-- pattern 1 alt counter signals when to switch LEDs every 83.333 ms
PATT1_ALT_CNTR_PROC : process(i_clk)
begin
if rising_edge(i_clk) then
if r_patt1_en = '0' then
r_patt1_light_LED <= 0;
else
if r_patt1_cntr = 1e6 then
if r_patt1_light_LED < 4 then
r_patt1_light_LED <= r_patt1_light_LED + 1;
else
r_patt1_light_LED <= 0;
end if;
end if;
end if;
end if;
end process;
PATT1_ALT_CNTR_PROC
监视r_patt1_cntr
并查找 1e6 的最大值。一旦完成,r_patt1_light_LED
就会增加。这将确定哪个 LED 亮起。
在代码的更下方,我们看到PATT_DECODE_PROC.
这个过程(如下)决定了在模式启用时应该发生什么。
PATT_DECODE_PROC : process(i_clk)
variable r_patt_en : std_logic_vector(3 downto 0);
begin
if rising_edge(i_clk) then
r_patt_en := r_patt1_en & r_patt2_en & r_patt3_en & r_patt4_en; -- cnct into vect
if r_patt_en = "1000" then -- blink LEDS in circle
case r_patt1_light_LED is
when 0 =>
r_LEDs <= "0001";
when 1 =>
r_LEDs <= "0010";
when 2 =>
r_LEDs <= "0100";
when 3 =>
r_LEDs <= "1000";
when 4 =>
r_LEDs <= "0000";
end case;
首先,所有不同的模式使能连接成一个向量 ( r_patt_en
) 以便于阅读。然后,对此进行检查。如果r_patt_en = "1000"
, 意思r_patt1_en
是激活的,模式 1 将显示在 LED 上。但是,在模式 1 期间会发生什么?
还记得PATT1_ALT_CNTR_PROC
吗?该过程增加了一个名为 的信号r_patt1_light_LED
,该信号由PATT_DECODE_PROC
(上面)使用 case 语句读取,并点亮与 的值相对应的每个 LED r_patt1_light_LED
。
其余模式以这种方式编码,带有计数器和使能,然后中的 case 语句PATT_DECODE_PROC
点亮 LED。除了上面的示例模式之外,还有一个切换模式、一个心跳模式和一个使用 PWM 的调光模式。
github repo 上的“sim”文件中有一个测试台。如果您选择运行 sim,只需知道它可能需要大约 8 分钟(取决于您的机器)。每个模式显示 3 秒,因此最短模拟时间应该是 12 秒才能看到所有 4 个模式。
这是几分钟后我的 sim 卡的样子:
您可以清楚地看到第一个模式的类似移位寄存器的行为,以及心跳模式。最后的PWM调光模式只能放大查看。
打开 Vivado 并创建一个项目。出现提示时,从“Boards”菜单中选择“Arty S7-25”。
如果您没有看到这个,请使用此处找到的 Digilent 更新您的电路板文件。
从 github repo 添加源文件、sim 文件和约束文件,并生成比特流。
对您的电路板进行编程,您应该会在 4 个 LED 上看到一些整齐的图案:)
感谢您关注我的第一个 VHDL/Arty S7 项目!请修改代码以创建您自己的模式!在评论中发布任何新模式或问题。我想看看你创造了什么:)
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !