BCD таймер в VHDL - PullRequest
       120

BCD таймер в VHDL

0 голосов
/ 26 мая 2018

Только что начал в VHDL, из любопытства.

Поэтому я пытался записать BCD таймер на спартанскую плату 3 и

Почему-то я не мог понять, почему этопродолжает отображаться сообщение «неожиданно с ошибкой».

Так что, если я хочу использовать такую ​​функцию, как показано на ссылке рисунка, как я могу изменить код? Любая помощь будет благодарна.

my initial sketch_picture link to imgur
(кликабельно)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity w3 is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           stp : in  STD_LOGIC;
           an : out  STD_LOGIC_VECTOR (3 downto 0);
           c : out  STD_LOGIC_VECTOR (6 downto 0));
end w3;

architecture timer of w3 is
signal div1 : integer range 0 to 499999 :=0; -- 100Hz
signal ck100hz : std_logic; -- 100Hz output
signal div2 : integer range 0 to 249999 :=0; -- 200Hz
signal ck200hz : std_logic; -- 200Hz output
signal div3 : integer range 0 to 124999 :=0; -- 400Hz
signal ck400hz : std_logic; -- 400Hz output
signal index : integer range 0 to 9 :=0;
signal scan : std_logic_vector (3 downto 0);
signal S : std_logic;
signal disp : std_logic_vector (3 downto 0);

begin
process begin
wait until rising_edge(clk);
if div1 < 499999 then
    ck100hz <= '0';
    div1 <= div1+1;
else 
    ck100hz <= '1';
    div1 <= 0;
end if;
if div2 < 249999 then
    ck200hz <= '0';
    div2 <= div2+1;
else
    ck200hz <= '1';
    div2 <= 0;
end if;
if div3 < 124999 then
    ck400hz <= '0';
    div3 <= div3+1;
else
    ck400hz <= '1';
    div3 <= 0;
end if;
end process;

process begin
wait until rising_edge(clk);
if rst = '1' then 
    index <= 0; 
end if;
if stp = '1' then 
    index <= index; 
end if;

if ck100hz = '1' then
    if index < 3 then index <= index+1;
        else index <= 0;
        if index < 4 and index > 7 then index <= index+1;
            else index <= 0;
            if index < 8 and index > 11 then index <= index+1;
                else index <= 0;
                if index < 12 and index > 15 then index <= index+1;
                    else index <= 0;
   end if;
      end if;
          end if;
             end if;
end if;
end process;

process begin
wait until rising_edge(clk);
if ck400hz = '1' then
    With scan select -- error unexpected With
        an <= an(0) when "00",
              an(1) when "01",
              an(2) when "10",
              an(3) when others;
end if;
end process;

process begin
wait until rising_edge(clk);
if ck200hz = '1' then
    With S select   -- error unexpected With
    disp <= index integer range 0 to 3 when "00",
            index integer range 4 to 7 when "01",
            index integer range 8 to 11 when "10",
            index integer range 12 to 15 when others;
end if;
end process;




with index select
    C <= "1000000" when 0, 
          "1111001" when 1, 
          "0100100" when 2, 
          "0110000" when 3, 
          "0011001" when 4, 
          "0010010" when 5, 
          "0000010" when 6,
          "1111000" when 7,       
          "0000000" when 8,
          "0011000" when 9;

end timer;

1 Ответ

0 голосов
/ 27 мая 2018

Для малоактивных:
Вы должны назначить 0111111 на C в случае index = 0.Вы должны включить почти все сегменты.Теперь ваш внутренний расчет будет высокоактивным.Сам дисплей низкоактивен из-за расположения печатной платы, поэтому вы должны инвертировать весь вектор C, прежде чем назначить его порту Cathode_n: Cathode_n <= not C; Обратите внимание, я использовал _n для обозначения низкоактивногоповедение этого порта.

Старый код:

with index select
  C <= "1000000" when 0, 
       "1111001" when 1,
       -- ...
       "0011000" when 9;

Это должно быть целью при написании чисто высокоактивного кода:

with index select
  C <= "0111111" when 0, 
       "0000110" when 1,
       -- ...
       "1100111" when 9;

  Cathode_n <= not C;

Высокоактивный означает:Если бит высокий (1), то вещь активна.В вашем случае светодиод 7-сегментного дисплея активирован.Основываясь на дизайне печатной платы, вы должны ехать на низкой скорости (0), чтобы активировать свет.Это низкий уровень активности, потому что низкое значение что-то активирует.

Оператор выбора должен назначить позицию для 1, которую следует просветить, а не позиции, которую нужно отключить.Более низкоактивные сигналы должны быть отмечены в коде, чтобы обозначить там другое поведение.Только компонент верхнего уровня должен преобразовывать высокоактивные сигналы в малоактивные сигналы и наоборот.Это гарантирует, что внутренние части вашего дизайна являются чисто высокоактивными.


Для без драйверов:
Нет назначения для S и scan.Оба сигнала 'U' или "UUUU" соответственно.

Редактировать:
Каждое назначение сигнала создает драйвер для сигнала.В настоящее время ваш код никогда не присваивает значения S или scan.Таким образом, начальные значения S и scan становятся движущими значениями сигналов.Вы должны запустить симуляцию и увидеть множество U s в вашей форме волны.

Инструменты синтеза могут сообщать: сигнал S читается, но никогда не назначается.


Для использования elsif:

Я переформатировал вам ужасную конструкцию if-then-else:

if ck100hz = '1' then
  if index < 3 then
    index <= index+1;
  else
    index <= 0;
    if index < 4 and index > 7 then
      index <= index+1;
    else
      index <= 0;
      if index < 8 and index > 11 then
        index <= index+1;
      else
        index <= 0;
        if index < 12 and index > 15 then
          index <= index+1;
        else
          index <= 0;
        end if;
      end if;
    end if;
  end if;
end if;

Теперь мы видим, что ваш код не может использовать elsif, поскольку у вас есть назначения в ветке else перед следующим оператором if .С другой стороны, назначение index <= 0; является избыточным и может быть удалено:

if ck100hz = '1' then
  if index < 3 then
    index <= index+1;
  else
    if index < 4 and index > 7 then
      index <= index+1;
    else
      if index < 8 and index > 11 then
        index <= index+1;
      else
        if index < 12 and index > 15 then
          index <= index+1;
        else
          index <= 0;
        end if;
      end if;
    end if;
  end if;
end if;

Теперь мы можем преобразовать его для использования elsif ответвлений:

if ck100hz = '1' then
  if index < 3 then
    index <= index + 1;
  elsif index < 4 and index > 7 then
    index <= index + 1;
  elsif index < 8 and index > 11 then
    index <= index + 1;
  elsif index < 12 and index > 15 then
    index <= index+1;
  else
    index <= 0;
  end if;
end if;

Гораздо более читабельно, верно?

Далее, давайте проверим ваши выражения в этом утверждении:

elsif index < 4 and index > 7 then

index не может быть меньше 4 и больше 7 одновременно.Итак, давайте воспроизведем синтез и оптимизируем удаленные недоступные ветви:

if ck100hz = '1' then
  if index < 3 then
    index <= index + 1;
  else
    index <= 0;
  end if;
end if;

Хорошо, другие проблемы в коде:

if rst = '1' then 
  index <= 0; 
end if;
if stp = '1' then 
  index <= index; 
end if;

if ck100hz = '1' then
  -- ...
end if;

Сброс всегда должен быть максимальнымприоритет.В вашем случае, например, stp имеет более высокий приоритет.В хорошем случае вы тратите только ресурсы FPGA, в плохом случае синтез не может преобразовать ваш код в примитивы в FPGA.Например, триггеры с соответствующим поведением сброса.

Правильная реализация:

if rst = '1' then 
  index <= 0; 
elsif stp = '1' then 
  index <= index; 
elsif ck100hz = '1' then
  -- ...
end if;

Думаю, на данный момент у вас достаточно ввода для исправления кода.

...