-1

我是 VHDL、Quartus II 和 ModelSim 的新手。现在我正在做一个实验室,我们正在构建一个闪烁的 LED。施工时间较长时,应如何处理模拟。闪烁 LED 的频率为 1 Hz,我正在使用的开发板上的时钟(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;
4

2 回答 2

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;

它使用“神奇的”编译指示 translate_off(和 _on),它可能因综合工具而异,但被大多数人接受。这些直接合成忽略了源的位:在这种情况下,第一个 Return 仅由模拟器看到。

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

constant CLK_FRQ : integer := Clock_Frequency;

任务完成。

于 2014-10-25T20:24:51.830 回答
1

我不会改变时钟频率,因为这不会改变必须由模拟器模拟的事件计数(这也是耗时的因素)。我认为最好更改在更改 LED 输出之前必须经过的周期数。

如果您在仿真环境中,您可以定义一个返回 TRUE 的 VHDL 函数:

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 的频率闪烁(如果
  • 占空比不是 50.00000 %,因为您的计数器在一个周期后设置为零。
  • 我认为 LED 不是作为附加触发器合成的。
于 2014-10-26T10:15:31.507 回答