Может ли кто-нибудь помочь мне с этим кодом VHDL (в настоящее время работает со сбоями)? - PullRequest
0 голосов
/ 20 февраля 2012

Этот код должен быть (и является) очень простым, и я не знаю, что я делаю неправильно. Вот описание того, что он должен делать:

Он должен отображать число на одном 7-сегментном дисплее. Это число следует увеличивать на единицу каждый раз, когда кто-то нажимает кнопку. Также есть кнопка сброса, которая устанавливает число в 0. Вот и все. Вот код VHDL:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PWM is
    Port ( cp_in : in  STD_LOGIC;
           inc : in  STD_LOGIC;
              rst: in std_logic;
           AN : out  STD_LOGIC_VECTOR (3 downto 0);
           segments : out  STD_LOGIC_VECTOR (6 downto 0));
end PWM;

architecture Behavioral of PWM is
    signal cp: std_logic;

    signal CurrentPWMState: integer range 0 to 10;
    signal inco: std_logic;
    signal temp: std_logic_vector (3 downto 0);
begin
    --cp = 100 Hz
    counter: entity djelitelj generic map (CountTo => 250000) port map (cp_in, cp);
    debounce: entity debounce port map (inc, cp, inco);
    temp <= conv_std_logic_vector(CurrentPWMState, 4);
    ss: entity decoder7seg port map (temp, segments);

    process (inco, rst)
    begin
        if inco = '1' then
            CurrentPWMState <= CurrentPWMState + 1;
        elsif rst='1' then
            CurrentPWMState <= 0;
        end if;
    end process;

    AN <= "1110";
end Behavioral;

Entity djelitelj (счетчик, используемый для деления тактовой частоты 50 МГц):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PWM is
    Port ( cp_in : in  STD_LOGIC;
           inc : in  STD_LOGIC;
              rst: in std_logic;
           AN : out  STD_LOGIC_VECTOR (3 downto 0);
           segments : out  STD_LOGIC_VECTOR (6 downto 0));
end PWM;

architecture Behavioral of PWM is
    signal cp: std_logic;

    signal CurrentPWMState: integer range 0 to 10;
    signal inco: std_logic;
    signal temp: std_logic_vector (3 downto 0);
begin
    --cp = 100 Hz
    counter: entity djelitelj generic map (CountTo => 250000) port map (cp_in, cp);
    debounce: entity debounce port map (inc, cp, inco);
    temp <= conv_std_logic_vector(CurrentPWMState, 4);
    ss: entity decoder7seg port map (temp, segments);

    process (inco, rst)
    begin
        if inco = '1' then
            CurrentPWMState <= CurrentPWMState + 1;
        elsif rst='1' then
            CurrentPWMState <= 0;
        end if;
    end process;

    AN <= "1110";
end Behavioral;

Debouncing сущность:

library IEEE;
use  IEEE.STD_LOGIC_1164.all;
use  IEEE.STD_LOGIC_ARITH.all;
use  IEEE.STD_LOGIC_UNSIGNED.all;
ENTITY debounce IS
    PORT(pb, clock_100Hz : IN    STD_LOGIC;
         pb_debounced     : OUT    STD_LOGIC);
END debounce;

ARCHITECTURE a OF debounce IS
    SIGNAL SHIFT_PB : STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN

-- Debounce Button: Filters out mechanical switch bounce for around 40Ms.
-- Debounce clock should be approximately 10ms
process 
begin
  wait until (clock_100Hz'EVENT) AND (clock_100Hz = '1');
      SHIFT_PB(2 Downto 0) <= SHIFT_PB(3 Downto 1);
      SHIFT_PB(3) <= NOT PB;
      If SHIFT_PB(3 Downto 0)="0000" THEN
        PB_DEBOUNCED <= '1';
      ELSE 
        PB_DEBOUNCED <= '0';
      End if;
end process;
end a;

А вот 7-сегментный декодер BCD:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity decoder7seg is
    port (
        bcd: in std_logic_vector (3 downto 0);
        segm: out std_logic_vector (6 downto 0));
end decoder7seg;

architecture Behavioral of decoder7seg is
begin
    with bcd select
        segm<= "0000001" when "0000", -- 0
        "1001111" when "0001",        -- 1
        "0010010" when "0010",        -- 2
        "0000110" when "0011",        -- 3
        "1001100" when "0100",        -- 4
        "0100100" when "0101",        -- 5
        "0100000" when "0110",        -- 6
        "0001111" when "0111",        -- 7
        "0000000" when "1000",        -- 8
        "0000100" when "1001",        -- 9
        "1111110" when others;        -- just - character

end Behavioral;

Кто-нибудь видит, где я допустил ошибку? Я попробовал этот дизайн на плате Spartan-3 Started, и она не работает ... Каждый раз, когда я нажимаю кнопку, я получаю сумасшедшие (случайные) значения. Кнопка сброса работает правильно. Спасибо !!!!

Ответы [ 2 ]

2 голосов
/ 20 февраля 2012

Я думаю, проблема здесь:

process (inco, rst)
begin
    if inco = '1' then
        CurrentPWMState <= CurrentPWMState + 1;
    elsif rst='1' then
        CurrentPWMState <= 0;
    end if;
end process;

Когда rst='1' вы сбросите CurrentPWMState. Но когда inco='1', вы бесконечно добавляете 1 к CurrentPWMState. Это что-то вроде асинхронной обратной связи через защелку. Вы должны сделать что-то чувствительное к краю здесь. Возможно, вы должны захватить inco, используя ваш тактовый сигнал, обнаружить изменение 0-> 1 и затем добавить 1.

1 голос
/ 08 апреля 2012

Согласен с предыдущим ответом.

Такой код должен сработать:

process (inco, ps, rst)
begin
  if rst='1' then
    CurrentPWMState <= '0';
    prev_inco <= inco; -- This signal captures the previous value of inco
  elsif ps'event and ps='1' then
    if inco='1' and prev_inco='0' then -- Capture the flank rising.
      CurrentPWMState <= CurrentPWMState + 1;
    end if;
    prev_inco <= inco;
  end if;
end process;

Я понимаю, что не пробовал код (только что закодированный здесь), но ядумаю, что все в порядке.

...