基于Quartus II和ModelSim的VHDL模拟闪烁LED

基于Quartus II和ModelSim的VHDL模拟闪烁LED,vhdl,quartus,Vhdl,Quartus,我不熟悉VHDL、Quartus II和ModelSim。现在我正在做一个实验室,我们正在建造一个闪烁的LED。当施工涉及相对较长的时间段时,应如何处理模拟。闪烁LED的频率为1 Hz,我使用Terasic DE2-115的开发板上的时钟为50 MHz。在代码中,我正在计算时钟脉冲,并相应地打开LED。然而,当我想用ModelSim验证我的代码时,我遇到了处理时间长达秒的麻烦。所以我解决了这个问题,只需将代码中的周期更改为几个时钟周期,以查看波形的行为是否符合预期。对于最终编译,我只需更改对应于

我不熟悉VHDL、Quartus II和ModelSim。现在我正在做一个实验室,我们正在建造一个闪烁的LED。当施工涉及相对较长的时间段时,应如何处理模拟。闪烁LED的频率为1 Hz,我使用Terasic DE2-115的开发板上的时钟为50 MHz。在代码中,我正在计算时钟脉冲,并相应地打开LED。然而,当我想用ModelSim验证我的代码时,我遇到了处理时间长达秒的麻烦。所以我解决了这个问题,只需将代码中的周期更改为几个时钟周期,以查看波形的行为是否符合预期。对于最终编译,我只需更改对应于1秒的计数值

但应该有更好的办法。我真的不想在模拟之后再接触VHDL代码。当处理接近1ms或更高的时间段时,我是否应该使用两个rtl,一个用于合成,一个用于模拟

VHDL代码

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不是作为加法触发器合成的。