Как правильно увеличить частоту подсветки сегментов дисплея при нажатии кнопки - PullRequest
0 голосов
/ 07 февраля 2019

Я программирую плату Xilinx Basys 3 в поведенческом VHDL.Я освещаю отдельные сегменты 4х семисегментного дисплея, чтобы он выглядел так, как будто на дисплее есть два вращающихся «колеса».Мой общий проект состоит из многих компонентов, таких как декодер, мультиплексор, debouncer, счетчик, делитель тактовых импульсов для частоты обновления дисплея и т. Д. Все это было очищено моим проф.В настоящее время я работаю над компонентом, который использует 250 Гц clk и кнопки вверх и вниз.Кнопки «вверх» и «вниз» позволяют увеличивать счетчик, который отображается на 11 различных прескалярных значений.Эти значения затем изменят максимальный шаг делителя тактового сигнала соответственно.

В настоящее время моя кнопка сброса работает.Однако кнопки «вверх» и «вниз» просто приостанавливают вращение сегментов, а не увеличивают скорость их вращения.Я считаю, что этот компонент является проблемой, но я не могу выяснить, где, в рамках трех процессов.

 library IEEE;
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.std_logic_unsigned.all;

entity wheelClkDiv is
    Port ( btnUp, btnDown, clk, reset : in STD_LOGIC;   
           --up/down/rst buttons and 250Hz clk initialized as inputs
           clkout : out STD_LOGIC
           -- newly divided clock initialized as output         
         );
end wheelClkDiv;

architecture Behavioral of wheelClkDiv is

signal count : STD_LOGIC_VECTOR(19 downto 0) := x"00000";   --20 bit count value for clk divider
signal temp : STD_LOGIC := '0';                             --temp store value for clk divider
signal countDiv : STD_LOGIC_VECTOR(19 downto 0) := x"00000"; --value given to choose prescalar 
signal btn_counter : STD_LOGIC_VECTOR(3 downto 0) := "0110";    --button press counter
begin
    buttonChoose : process(btnUp, btnDown, reset)
        begin
            if(btnUp = '1') then
                btn_counter <= btn_counter + 1;     --add one to count if up button pushed
            elsif(btnDown = '1') then
                btn_counter <= btn_counter - 1;     --subtract one from count if down button pushed
            elsif(reset = '1') then
                btn_counter <="0110";           --set back to middle speed if reset is pushed
            end if;
    end process;

    setDivideCase : process(btn_counter)
        begin
            case btn_counter is    --case statement to choose prescalar based on btn_counter value
                when "0000" => 
                    countDiv <= b"00000000000110010000"; --3.2s cycle
                when "0001" => 
                    countDiv <= b"00000000000100101100"; --2.4s cycle
                when "0010" => 
                    countDiv <= b"00000000000011001000"; --1.6s cycle
                when "0011" => 
                    countDiv <= b"00000000000010010110"; --1.2s cycle
                when "0100" => 
                    countDiv <= b"00000000000001100100"; --0.8s cycle
                when "0101" => 
                    countDiv <= b"00000000000001001011"; --0.6s cycle
                when "0110" => 
                    countDiv <= b"00000000000000110010"; --0.4s cycle
                when "0111" => 
                    countDiv <= b"00000000000000100110"; --0.3s cycle
                when "1000" => 
                    countDiv <= b"00000000000000011001"; --0.2s cycle
                when "1001" => 
                    countDiv <= b"00000000000000010011"; --0.15s cycle
                when "1010" => 
                    countDiv <= b"00000000000000001101"; --0.1s cycle     
                when others =>
                    countDiv <= b"00000000000000001101";--not correct
            end case;      
    end process;

    wheelDivider : process(clk, reset)
    begin
        if(reset = '1') then    --reset clock count if reset pushed
            count <= x"00000";
            temp <= '0';
        elsif(rising_edge(clk)) then    
            if(count = countDiv) then    --set clk counter value to prescalar
                count <= x"00000";
                temp <= not temp;            
            else
                count <= count + 1;   --keep incrementing clk count until it matches PS
                temp <= temp;
            end if;
        end if;
   end process;
   clkout <= temp;  --give temp value to output clk 
end Behavioral;

1 Ответ

0 голосов
/ 07 февраля 2019

Первое, что я вижу, это то, что вы игнорируете тот факт, что сигнал count постоянно считается.Когда вы нажимаете reset, ваш count возвращается к `x" 00000 ", это единственная причина, по которой он работает.

Но когда вы нажимаете кнопку вверх / вниз, вы меняете значение countDiv с

countDiv <= b"00000000000000110010"; --0.4s cycle

до

countDiv <= b"00000000000000011001"; --0.2s cycle

но что, если в момент нажатия кнопки count будет b"00000000000000100000"?Условие count = countDiv не было поймано ранее и никогда не будет поймано.Счет начнет отсчитываться бесконечно, и любые дальнейшие изменения countDiv не изменят этот факт (возможно, если вы нажмете другую кнопку достаточно быстро и, конечно, ожидаете кнопку reset).clkout остановится на текущем значении, и дисплей будет зависать, пока, конечно, count не переполнится.

Конечно, самым простым разрешением будет изменение count = countDiv на count >= countDiv, но такое сравнение требует ресурсов, так что это не очень хороший способ дизайна fpgas.Вам следует сбрасывать значение count на ноль каждый раз, когда вы чегеете countDiv, или даже лучше, вести обратный отсчет до нуля, начиная с countDiv.Тогда временное перенапряжение тока countDiv не должно быть проблемой.У вас есть много возможностей.

Например:

wheelDivider : process(clk, reset)
    begin
        if(reset = '1') then    --reset clock count if reset pushed
            count <= b"00000000000001001011";
            temp <= '0';
        elsif(rising_edge(clk)) then    
            if(count = x"00000") then    --set clk counter value to zero
                count <= countDiv;
                temp <= not temp;            
            else
                count <= count - 1;   --keep decrementing count until zero
                temp <= temp;
            end if;
        end if;
end process;

Я не уверен, что это пока единственная проблема.Надеюсь, что это так.

...