Кодировщик клавиатуры, почему с 8 состояниями?

Мне нужно закодировать в vhdl кодировщик клавиатуры. Я думал сделать это с 4 состояниями. когда в столбце n1 сканируйте строку 1, строку 2, строку 2, строку 4. По моему мнению, 4 таких состояний должно быть достаточно, но пример, который я нашел в Интернете, делает это с 8 состояниями:

key_scanner_sm : process (clk)
  begin  -- process key_scanner
    if clk'event and clk = '1' then

      if state_inc = '1' then

        -- reset scan_complete
        scan_complete <= '0';

        case key_state is

          when pulse_row_1 =>
            key_read  <= (others => '0');
            key_row   <= "0001";
            key_state <= read_row_1;

          when read_row_1 =>
            case key_col is
              when "0001" => key_read <= X"31";  -- 1
              when "0010" => key_read <= X"32";  -- 2
              when "0100" => key_read <= X"33";  -- 3
              when "1000" => key_read <= X"41";  -- A
              when others => null;
            end case;
            key_state <= pulse_row_2;

          when pulse_row_2 =>
            key_row   <= "0010";
            key_state <= read_row_2;

          when read_row_2 =>
            case key_col is
              when "0001" => key_read <= X"34";  -- 4
              when "0010" => key_read <= X"35";  -- 5
              when "0100" => key_read <= X"36";  -- 6
              when "1000" => key_read <= X"42";  -- B
              when others => null;
            end case;
            key_state <= pulse_row_3;

          when pulse_row_3 =>
            key_row   <= "0100";
            key_state <= read_row_3;

          when read_row_3 =>
            case key_col is
              when "0001" => key_read <= X"37";  -- 7
              when "0010" => key_read <= X"38";  -- 8
              when "0100" => key_read <= X"39";  -- 9
              when "1000" => key_read <= X"43";  -- C
              when others => null;
            end case;
            key_state <= pulse_row_4;

          when pulse_row_4 =>
            key_row   <= "1000";
            key_state <= read_row_4;

          when read_row_4 =>
            case key_col is
              when "0001" => key_read <= X"2A";  -- *
              when "0010" => key_read <= X"30";  -- 0
              when "0100" => key_read <= X"23";  -- #
              when "1000" => key_read <= X"44";  -- D
              when others => null;
            end case;
            key_state     <= pulse_row_1;
            scan_complete <= '1';

          when others => null;
        end case;

      end if;
    end if;
  end process key_scanner_sm;

Есть ли веская причина для этого, кто-нибудь знает?


person Anarkie    schedule 06.05.2014    source источник


Ответы (1)


Приведенный вами пример нуждается в дополнительных состояниях, потому что он реализован как один оператор case. Присвоение key_row требует дополнительного цикла, прежде чем можно будет считать key_col. Поскольку это простое циклическое сканирование, состояния pulse_row_n можно исключить, назначив следующее значение key_row из предыдущего состояния read_row_n.

person Kevin Thibedeau    schedule 06.05.2014
comment
Итак, мы можем просто написать это в 4 состояниях, я просто не понимаю, почему кодер сделал это в 8 состояниях? Зачем усложнять? Я ищу вескую причину для этого, не так ли? Для защиты например от ситуации типа 2 кнопки нажаты и т.д.? - person Anarkie; 06.05.2014
comment
Они не реализовали возможность подрезать некоторые штаты. Большая часть VHDL-кода, который вы видите в Интернете, имеет низкое или среднее качество. Он не всегда представляет лучшие практики. В этом случае не имеет значения, что циклы тратятся впустую, так как это небольшая часть логики и достаточно быстрая для взаимодействия с человеком. О чем вам нужно помнить, так это о внедрении фильтров для устранения дребезга матричных входов, чтобы избежать записи нескольких нажатий от прыгучей кнопки. Вам также необходимо синхронизировать входы key_col с вашим часовым доменом, прежде чем подавать внешние сигналы непосредственно в фильтр подавления дребезга. - person Kevin Thibedeau; 07.05.2014
comment
Одним из примеров того, чего следует избегать, является шаблонное событие clock'event и clock = '1' в стиле VHDL-87 для синхронных процессов. Вы должны использовать функцию Rising_Edge VHDL-93, так как она имеет внутренний вызов to_X01 для уменьшения уровня тактового сигнала перед его тестированием. Это более удобочитаемо и важно для правильного поведения в ситуациях моделирования, где часы могут быть «H» или «L». Многие современные VHDL все еще закодированы по-старому из-за плохо написанных, устаревших учебных материалов. Когда я вижу VHDL-87 в коде, которому меньше 15 лет, я с подозрением отношусь к его качеству. - person Kevin Thibedeau; 07.05.2014
comment
Правильное устранение дребезга очень важно, и я уже спрашивал об этом здесь с щедростью, я был бы рад, если бы вы могли мне помочь: stackoverflow.com/questions/23434772/ - person Anarkie; 07.05.2014
comment
Нужно сохранить сброс в дизайне. См. мои комментарии по этому поводу для более подробного объяснения, почему. Если вы не производите производственное оборудование, можно использовать внешний переключатель для управления сбросом, в противном случае рассмотрите возможность использования совета по созданию внутреннего сброса. - person Kevin Thibedeau; 07.05.2014