使用VHDL与Quartus II和ModelSim模拟闪烁LED

时间:2014-10-25 20:14:17

标签: vhdl quartus

我是VHDL,Quartus II和ModelSim的新手。现在,我正在建立一个我们正在构建闪烁LED的实验室。当施工处理相对较长的时间段时,应该如何处理模拟。闪烁LED的频率为1 Hz,开发板I(使用(Terasic DE2-115))上的时钟为50 MHz。在代码中,我计算时钟脉冲并相应地打开LED。但是,当我想用​​ModelSim验证我的代码时,我遇到了处理时间长达几秒钟的麻烦。所以我只是通过将代码中的周期更改为几个时钟周期来解决它,以确定波的行为符合预期。对于最终编译,我只需更改对应于1秒的计数值。

但应该有更好的方法。我不想在模拟后触摸VHDL代码。在处理接近1 ms或更高的时间段时,我应该使用两个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;

2 个答案:

答案 0 :(得分:1)

您声明了一个命名常量,然后忽略它......

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;

它使用&#34;魔法&#34; pragmas translate_off(和_on)可能在综合工具之间有所不同,但大多数人都接受。这些直接合成忽略了源的位:在这种情况下,第一个返回只能由模拟器看到。

现在你可以调用这个函数初始化常量

constant CLK_FRQ : integer := Clock_Frequency;

完成工作。

答案 1 :(得分:1)

我不会改变时钟频率,因为这不会改变模拟器必须模拟的事件数(这也是耗时因素)。我认为在更改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是作为一个额外的触发器合成的。