为什么我的输出断断续续?

时间:2015-03-11 04:15:46

标签: vhdl fpga

我最近购买了Altera DE0 nano板,并成功实现了计数器和状态机等基本功能。我现在正试图在电路板的内置LED上实现一维生命游戏,它可以正常工作,但有问题。

我希望游戏状态以1Hz(或任意快速)更新,这个程序可以做到,除了它还以相同的频率闪烁LED,因此LED在显示下一个状态之前会空白半秒。我没有看到代码有什么问题,但我怀疑我是如何处理造成这个问题的1Hz时钟边缘。

以下是当前版本的代码:

----------------------------------
--      Library Declaration     --
----------------------------------
-- Like any other programming language, we should declare libraries

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

----------------------------------
--      Entity Declaration      --
----------------------------------
-- Here we specify all input/output ports

entity blinking_led is
    port(
        clk_50mhz : in std_logic ;
        reset_btn : in std_logic;
        green_leds : out unsigned(7 downto 0) := "11111111"
    );
end entity;

----------------------------------
--  Architecture Declaration    --
----------------------------------
--  here we put the description code of the design

architecture behave of blinking_led is

-- signal declaration

constant CLK_SPD : integer := 50000000;
constant N : integer := 8;

signal LED_init : unsigned(7 downto 0) := "00100100"; 
signal clk_1hz : std_logic ;
signal scaler : integer range 0 to 25000000 ;
signal out_register : unsigned(7 downto 0) := LED_init;
signal out_register_old : unsigned(7 downto 0) := "00000000";

begin

-- this process is used to scale down the 50mhz frequency
-- In reality, clk_1hz is not periodic but i used it to get 2 clock cycle by second ( 2 rising edge ).
-- 50 mhz means 50 000 000 cycle in one second : 
-- by using the scaler , i will have 2 cycle by second so that led will be on 1/2 s and off 1/2 s

    clk_1hz_process : process( clk_50mhz , reset_btn )
    begin
        if (reset_btn = '0') then 
            clk_1hz <= '0';
            scaler <= 0;
        elsif(rising_edge(clk_50mhz)) then 
            if (scaler < CLK_SPD/2) then 
                scaler <= scaler + 1 ;
                clk_1hz <= '0';
            else
                scaler <= 0;
                clk_1hz <= '1';
            end if;
        end if;
    end process clk_1hz_process;

    next_gen : process (clk_1hz,reset_btn, out_register, out_register_old)
    variable neighbours : std_logic_vector(1 downto 0);
    variable rand_temp : std_logic_vector(N-1 downto 0) := (N-1 => '1',others => '0');
    variable temp : std_logic := '0'; --(others => '0');

    begin
        --green_leds <= LED_init;
        if (reset_btn = '0') then 
            --green_leds <= LED_init;
            elsif clk_1hz'event and clk_1hz = '1' then

                out_register_old <= out_register;

                --Game rules:
                --Cells are connected on a N-entry long ring, so the first entry has its last as a neighbor and v/v
                --0 neighbors: no action
                --1 neighbor:  cell is born/stays alive
                --2 neighbors: cell dies

                for I in 0 to (N-1) loop
                    if(I = 0) then
                        neighbours := out_register_old(N-1) & out_register_old(I+1);
                    elsif(I > 0 and I < (N-1)) then
                        neighbours := out_register_old(I-1) & out_register_old(I+1);
                    elsif(I = N-1) then
                        neighbours := out_register_old(I-1) & out_register_old(0);
                    end if;

                    case neighbours is 
                        when "00" => out_register(I) <= out_register_old(I);
                        when "01" => out_register(I) <= '1';
                        when "10" => out_register(I) <= '1';
                        when "11" => out_register(I) <= '0';
                        when others => report "unreachable" severity failure;
                    end case;
                end loop;

                --PRNG for game reset logic 
                temp := rand_temp(N-1) xor rand_temp(N-2);
                rand_temp(N-1 downto 1) := rand_temp(N-2 downto 0);
                rand_temp(0) := temp;
--                  
--              if(out_register = 0) then
--                  --reset to random vector
--                  --out_register <= unsigned(rand_temp);
--                  out_register <= LED_init;
--              end if; 
--              
--              if(out_register = out_register_old) then 
--                  --stalemate, prepare to reset
--                  out_register <= "00000000"; 
--              end if;
--              
            end if;     
            green_leds <= out_register;
    end process next_gen;

    end behave;

我的VHDL生锈了所以任何帮助都表示赞赏。

2 个答案:

答案 0 :(得分:0)

据我了解代码,clk_1hz实际上在一秒内有两个高脉冲(缩放器

   green_leds <= out_register;

似乎是在一个错误的地方。

答案 1 :(得分:0)

虽然它可能有用,但你不应该使用派生信号作为时钟,而是使用clk_50mhz直到使用clk_1hz作为门控信号。您也可以异步使用reset_btn(在clk_1hz_process中)和同步(在next_gen中),这也可能会产生一些有趣的效果。

next_gen : process 
-- ...
begin
    if(rising_edge(clk_50mhz)) then 
        if (reset_btn = '0') or (out_register = 0) then 
            -- synchronous reset and check for empty state in one
            out_register <= ...;
        elsif (clk_1hz = '1') then
             -- the main logic here
            out_register <= ...;
        else
            -- nothing happens here
        end if;
    end if;
end process;

-- output assignment
green_leds  <= out_register;

但最重要的是,您尝试在同一个周期中使用out_register_old,同时也指定它(out_register_old <= out_register),因此它应该是一个变量(out_register_old := out_register);或者它可以只用out_register本身替换,因为这将保持其旧值直到过程结束。