基于Quartus II和ModelSim的VHDL模拟闪烁LED
我不熟悉VHDL、Quartus II和ModelSim。现在我正在做一个实验室,我们正在建造一个闪烁的LED。当施工涉及相对较长的时间段时,应如何处理模拟。闪烁LED的频率为1 Hz,我使用Terasic DE2-115的开发板上的时钟为50 MHz。在代码中,我正在计算时钟脉冲,并相应地打开LED。然而,当我想用ModelSim验证我的代码时,我遇到了处理时间长达秒的麻烦。所以我解决了这个问题,只需将代码中的周期更改为几个时钟周期,以查看波形的行为是否符合预期。对于最终编译,我只需更改对应于1秒的计数值 但应该有更好的办法。我真的不想在模拟之后再接触VHDL代码。当处理接近1ms或更高的时间段时,我是否应该使用两个rtl,一个用于合成,一个用于模拟 VHDL代码基于Quartus II和ModelSim的VHDL模拟闪烁LED,vhdl,quartus,Vhdl,Quartus,我不熟悉VHDL、Quartus II和ModelSim。现在我正在做一个实验室,我们正在建造一个闪烁的LED。当施工涉及相对较长的时间段时,应如何处理模拟。闪烁LED的频率为1 Hz,我使用Terasic DE2-115的开发板上的时钟为50 MHz。在代码中,我正在计算时钟脉冲,并相应地打开LED。然而,当我想用ModelSim验证我的代码时,我遇到了处理时间长达秒的麻烦。所以我解决了这个问题,只需将代码中的周期更改为几个时钟周期,以查看波形的行为是否符合预期。对于最终编译,我只需更改对应于
library ieee;
use ieee.std_logic_1164.all;
entity lab4 is
port( CLOCK_50 : in std_logic; -- DE2-115 internal clock
KEY : in std_logic_vector(0 downto 0); -- Push-buttons, active 0
-- KEY(0) as reset
LEDG : out std_logic_vector(7 downto 0)); -- Green LEDs
end entity lab4;
architecture lab4_rtl of lab4 is
signal RESET_N : std_logic;
begin
-- Parallel VHDL
constant CLK_FRQ : integer := 50000000;
RESET_N <= KEY(0); -- Here we connect reset to a push-button
-- synch process with asynch reset, i.e. reset as soon as reset is active
p1 : process(CLOCK_50, RESET_N)
variable counter : integer := 0;
variable led_num : integer := 0;
begin
-- reset part
if RESET_N = '0' then --KEY is active 0
counter := 0; --reset counter
LEDG(0) <= '0'; --turn OFF leds
-- synch part, updates depending on clock
elsif rising_edge(CLOCK_50) then
counter := counter + 1;
if counter < 50000000 then;
LEDG(0) <= '1';
elsif counter >= 50000000 AND counter < 100000000 then
LEDG(0) <= '0';
else
counter := 0;
end if;
end if;
end process p1;
end architecture lab4_rtl;
您声明了一个命名常量,然后忽略了它
constant CLK_FRQ : integer := 50000000;
首先,您可以用CLK_FRQ和CLK_FRQ*2代替幻数重写计数器
然后,您可以在sim和synth中为CLK_FRQ设置不同的值。有各种各样的方法,但我更喜欢函数
function Clock_Frequency return natural is
begin
-- synthesis translate_off
return 50;
-- synthesis translate_on
return 50000000;
end Clock_Frequency;
它使用了神奇的pragmas translate_off和_on,这在不同的合成工具中可能有所不同,但被大多数工具所接受。这些直接合成忽略了源的位:在这种情况下,第一次返回仅由模拟器看到
现在可以调用此函数来初始化常量
constant CLK_FRQ : integer := Clock_Frequency;
工作完成。我不会更改时钟频率,因为这不会更改必须由模拟器模拟的事件计数。这也是一个耗时的因素。我认为最好改变必须经过的周期数,直到改变LED输出 您可以定义一个VHDL函数,如果您在模拟环境中,该函数将返回TRUE:
function SIMULATION return boolean is
variable ret : boolean;
begin
ret := false;
--synthesis translate_off
if Is_X('X') then ret := true; end if;
--synthesis translate_on
return ret;
end function;
除此之外,您还可以定义if-then-else函数来简化代码:
function ite(cond : BOOLEAN; value1 : INTEGER; value2 : INTEGER) return INTEGER is
begin
if cond then
return value1;
else
return value2;
end if;
end function;
现在可以在一行中选择计数器的最大值,如下所示:
constant COUNTER_MAX : INTEGER := ite(SIMULATION, 500, 50000);
从上面查看代码时,出现了一些错误:
LED以0.5 Hz而不是1 Hz的频率闪烁,这与您的if有关
占空比不是50.00000%,因为您的计数器设置为零,一个周期延迟。
我认为LED不是作为加法触发器合成的。