Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Устройство мигания светодиодов (VHDL)
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
lyzifer
Устройство моргания 4-мя светодиодами.По сути,программа очень простая.Но у меня в итоге светодиоды "бегают" (т.е. загорелся первый,потом сразу же следующий с частотой 1 Гц).А мне нужно чтобы диод загорелся,потух,а только потом,через 1 с, следующий. Заранее благодарен.
вот реализация и временная диаграмма:

Код
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity LED is
port( CLK : in std_logic;
L_D : out std_logic_vector(3 downto 0)); -- поправил у меня 4 светодиода подключены
end LED;

architecture A_LED of LED is
signal counter : std_logic_vector(20 downto 0):= (others => '0');
signal LED_temp : std_logic_vector(3 downto 0) := (0 => '1',others =>'0'); -- поправил на 4 светодиода
signal res : std_logic := '0';
begin
count : process(CLK,res)
begin
if(res = '1') then
counter <= (others => '0');
elsif(rising_edge(CLK)) then
counter <= counter +1;
end if;
end process;

L : process(counter)
begin
if(counter = 2000000) then
res <= '1';
LED_temp <= LED_temp(2 downto 0) & LED_temp(3);
-- вращаю выходной вектор по кругу налево, постоянно смещая на 1 разряд
else
res <= '0';
end if;
end process;

L_D <= led_temp; -- выдаю информацию из регистров в порт

end A_LED;


На выходе получаю



а надо:



iosifk
Цитата(lyzifer @ Jul 13 2017, 14:52) *
Устройство моргания 4-мя светодиодами.По сути,программа очень простая.Но у меня в итоге светодиоды "бегают" (т.е. загорелся первый,потом сразу же следующий с частотой 1 Гц).А мне нужно чтобы диод загорелся,потух,а только потом,через 1 с, следующий. Заранее благодарен.

Это значит, что нужна пауза, когда все светодиоды будут выключены... Ну так и сделайте ее... Например к Вашему коду можно добавить сигнал блокировки, который будет срабатывть по переднему фронту импульсов на светодиоды и будет их выключать на требуемое время...
Ну а можно сделать еще проще. Автомат и таймер. Могу рассказать по скайпу...
Удачи!
lyzifer
Цитата(iosifk @ Jul 13 2017, 14:58) *
Это значит, что нужна пауза, когда все светодиоды будут выключены... Ну так и сделайте ее... Например к Вашему коду можно добавить сигнал блокировки, который будет срабатывть по переднему фронту импульсов на светодиоды и будет их выключать на требуемое время...

хм..это не плохой вариант.но я новичок в VHDL (т.е. тупой). не могли бы написать,как должен выглядеть этот кусок кода??буду очень благодарен
Tausinov
Ввести дополнительный сигнал
signal phase : std_logic;

По каждому превышению счетчиком порога делать
phase <= not(phase);
И соответственно сдвигать регистр LED_temp только при нуле или при единице.

А дальше останется 1 if добавить.

if (phase = '0') then
LD <= (others => '0');
else
LD <= LED_temp;
end if;
lyzifer
Цитата(Tausinov @ Jul 13 2017, 16:51) *
Ввести дополнительный сигнал
signal phase : std_logic;

По каждому превышению счетчиком порога делать
phase <= not(phase);
И соответственно сдвигать регистр LED_temp только при нуле или при единице.

А дальше останется 1 if добавить.

if (phase = '0') then
LD <= (others => '0');
else
LD <= LED_temp;
end if;


Блин,видимо я не оч догоняю,как правильно добавить в код...((ошибку выдаёт на выходе при моделировании...
Покажи,плиииииз, как правильно.заранее благодарен!!
Код
signal counter : std_logic_vector(22 downto 0):= (others => '0');
signal LED_temp : std_logic_vector(3 downto 0) := (0 => '1',others =>'0');
signal res : std_logic := '0';
signal phase : std_logic;
begin
  count : process(CLK,res)
  begin
    if(res = '1') then
      counter <= (others => '0');
    elsif(rising_edge(CLK)) then
      counter <= (counter + 1);
    end if;
  end process;
L : process(counter)
  begin
    if(counter = 5000000) then
      res <= '1';
    LED_temp <= LED_temp(2 downto 0) & LED_temp(3);
    phase <= not(phase);
   else
      res <= '0';
    end if;
  end process;
  
G: process (phase)
begin
if (phase = '0') then
L_D <= (others => '0');
else
L_D <= LED_temp;
end if;
end process;

L_D <= led_temp; --  сигнал из регистров в порт
end A_LED;
Tausinov
Цитата(lyzifer @ Jul 13 2017, 17:32) *
Блин,видимо я не оч догоняю,как правильно добавить в код...((ошибку выдаёт на выходе при моделировании...
Покажи,плиииииз, как правильно.заранее благодарен!!


Код
signal res      : std_logic                     := '0';
signal phase    : std_logic                     := '0';
signal LED_temp : std_logic_vector( 3 downto 0) := (0 => '1', others =>'0');
signal counter  : std_logic_vector(22 downto 0) := (others => '0');

begin
  count : process(CLK, res)
  begin
    if(res = '1') then
      counter <= (others => '0');
    elsif(rising_edge(CLK)) then
      counter <= (counter + 1);
    end if;
  end process;

  L : process(counter)
  begin
    if(counter = 5000000) then
      phase <= not(phase);

      if (phase = '1') then
        res <= '1';
        LED_temp <= LED_temp(2 downto 0) & LED_temp(3);
      else
        res <= '0';
      end if;
    else
      res <= '0';
    end if;
  end process;
  
  G: process(phase)
  begin
    if (phase = '0') then
      L_D <= (others => '0');
    else
      L_D <= LED_temp;
    end if;
  end process;
  
end A_LED;


Ну и по-хорошему, счетчик можно обнулять синхронно по сравнению с верхним порогом, а не делать отдельный сигнал, применяемый асинхронно.
lyzifer
Цитата(Tausinov @ Jul 13 2017, 18:18) *

Всеравно ошибка на выходе.но спосибо за попытку помочь))

Tausinov
Дизайн:
Код
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity test_led is
  generic (
    p_TD      : time    := 1 ns;
    p_CNT_LIM : integer := 32768 - 1
  );
  port (
    clk : in  std_logic;
    led : out std_logic_vector(3 downto 0)
  );
end test_led;

architecture rtl of test_led is
  signal div_cnt_u : unsigned(31 downto 0)        := (others => '0');

  signal phase     : std_logic                    := '1';
  signal led_reg   : std_logic_vector(3 downto 0) := (0 => '1', others => '0');
begin

  counter_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u < p_CNT_LIM) then
        div_cnt_u <= div_cnt_u + 1 after p_TD;
      else
        div_cnt_u <= (others => '0');
      end if;
    else
      NULL;
    end if;
  end process;

  phase_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        phase <= not(phase) after p_TD;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --phase_control_p

  led_reg_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        if (phase = '1') then
          led_reg <= led_reg(2 downto 0) & led_reg(3) after p_TD;
        else
          NULL;
        end if;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --led_reg_control_p

  out_form_logic_p : process(phase)
  begin
    if (phase = '0') then
      led <= (others => '0');
    else
      led <= led_reg;
    end if;
  end process; --out_form_logic_p

end rtl;


Тестбенч:
Код
library ieee;
   use ieee.std_logic_1164.all;

entity test_led_tb is
   generic (
      p_TD    : time := 1 ns;
      p_CLK_T : time := 4 ns
   );
end test_led_tb;

architecture behav of test_led_tb is
   signal clk : std_logic                    := '0';
   signal led : std_logic_vector(3 downto 0);

   component test_led is
     generic (
       p_TD      : time    := 1 ns;
       p_CNT_LIM : integer := 32768 - 1
     );
     port (
       clk : in  std_logic;
       led : out std_logic_vector(3 downto 0)
     );
   end component;
begin
   clk_gen_p : process
   begin
      clk <= not(clk);
      wait for p_CLK_T / 2;
   end process;

   UUT : test_led
      generic map (
         p_TD => p_TD
      )
      port map (
         clk => clk,
         led => led
      );
end behav;


Stewart Little
Цитата(lyzifer @ Jul 13 2017, 14:52) *
А мне нужно чтобы диод загорелся,потух,а только потом,через 1 с, следующий.

Коллеги каких-то сложностей насоветовали...
А нельзя ли просто увеличить разрядность сдвигового регистра в два раза, а светодиоды поджигать только четными (или только нечетными) разрядами?
Tausinov
Цитата(Stewart Little @ Jul 13 2017, 19:17) *
Коллеги каких-то сложностей насоветовали...
А нельзя ли просто увеличить разрядность сдвигового регистра в два раза, а светодиоды поджигать только четными (или только нечетными) разрядами?


Можно, красивый вариант. Просто, если потом захочется чего-то более необычного, то, имхо, проще будет поправить текущий вариант, чем переделывать узко заточенный.
lyzifer
Цитата(Tausinov @ Jul 13 2017, 18:58) *


оу))не ожидал,что вы мне ещё напишите))большое спасибо за интерес к моей проблеме))жаль,что только завтра утром смогу проверить работоспособность проги. rolleyes.gif
Maverick
lyzifer, это не программа, а описание цифровой схемы - посмотреть можно в RTL viewer
AVR
Вопрос автору темы: обязательно ли VHDL? Видя это требование, воздерживался от ответов. Я мог бы на Verilog сделать. Вижу что начинающий, еще не поздно, ссылки у меня в подписи.
lyzifer
Цитата(Tausinov @ Jul 13 2017, 19:26) *

ЕЕЕЕ)))Заработала))ещё раз нереальное спасибо))
AVR
Цитата(lyzifer @ Jul 14 2017, 10:41) *
ЕЕЕЕ)))Заработала))ещё раз нереальное спасибо))

Будет ли Вам интересно увидеть, как я решу эту задачу в разы меньшим по объему текстом на другом HDL-языке? sm.gif
Не буду назойливым, просто меня шокировал объем кода для такой-то простой задачи...
Flip-fl0p
А есть ли особый смысл в этих строчках ?
Код
    else
      NULL;
    end if;

lyzifer
Цитата(AVR @ Jul 14 2017, 11:08) *
Будет ли Вам интересно увидеть, как я решу эту задачу в разы меньшим по объему текстом на другом HDL-языке? sm.gif
Не буду назойливым, просто меня шокировал объем кода для такой-то простой задачи...

дело в том,что я работаю в Vivado и ISE.поэтому,к сожалению, принципиально важно работать на VHDL.
Да,это задание можно выполнить и с меньшим кол-ом програмного кода. но спасибо за интерес)))
Tausinov
Цитата(Flip-fl0p @ Jul 14 2017, 11:44) *
А есть ли особый смысл в этих строчках ?
Код
    else
      NULL;
    end if;



Нет, просто привычка, чтобы задуматься, а не должно ли что-то по else зануляться, например. Несколько раз обжигался на том, что пропускал такие моменты.

Цитата(lyzifer @ Jul 14 2017, 11:57) *
дело в том,что я работаю в Vivado и ISE.поэтому,к сожалению, принципиально важно работать на VHDL.
Да,это задание можно выполнить и с меньшим кол-ом програмного кода. но спасибо за интерес)))


Обе среды же прекрасно Верилог поддерживают.

Цитата(AVR @ Jul 14 2017, 11:08) *
Не буду назойливым, просто меня шокировал объем кода для такой-то простой задачи...


На VHDL тоже можно написать компактнее, а на Верилоге даже длиннее. Суть не в языке описания, а в логике работы. Выше предложили, например, красивый вариант с удвоенным сдвиговым регистром и управлением диодиками каждым вторым битом - его еще компактнее можно сделать. Но у автора цель, как я понимаю, разобраться в логике работы, а не в том, чтобы сэкономить пару килобайт на жестком диске)
lyzifer
Цитата(Tausinov @ Jul 14 2017, 12:16) *
Обе среды же прекрасно Верилог поддерживают.

На VHDL тоже можно написать компактнее, а на Верилоге даже длиннее. Суть не в языке описания, а в логике работы. Выше предложили, например, красивый вариант с удвоенным сдвиговым регистром и управлением диодиками каждым вторым битом - его еще компактнее можно сделать. Но у автора цель, как я понимаю, разобраться в логике работы, а не в том, чтобы сэкономить пару килобайт на жестком диске)

Я И НЕ ЗНАЛ. Ну да.прост надо уметь оптимизировать код (чего я явно не умею)
Tausinov
Цитата(lyzifer @ Jul 14 2017, 12:59) *
Я И НЕ ЗНАЛ. Ну да.прост надо уметь оптимизировать код (чего я явно не умею)


Оптимизация все-таки подразумевает уменьшение не кол-ва кода, а кол-ва ресурсов, в которые выльется в итоге этот самый код, само собой с учетом требуемых частот. А код, имхо, в первую очередь должен быть понятным и удобочитаемым. На том же Си, например, можно сделать смену значений в двух переменных так:
Код
    a ^= b ^= a ^= b;

Но кто-то со стороны, пробегая ваш код глазами, вряд ли сразу поймет, что тут происходит.
iosifk
Цитата(lyzifer @ Jul 14 2017, 12:59) *
Я И НЕ ЗНАЛ. Ну да.прост надо уметь оптимизировать код (чего я явно не умею)

Это неверное суждение. Код не надо оптимизировать. Это сделает компилятор.
Надо учиться формализовать задание и превращать написание кода не в "художественные промыслы" как тут большинство Вам советовало, а в "полуавтоматизированную рутину". Потому что цель разработки - это сделать с первого раза и без ошибок.
Я для ТС шанс предложил, но пока он не хочет им воспользоваться... Увы...
sonycman
Цитата(Tausinov @ Jul 14 2017, 13:16) *
На VHDL тоже можно написать компактнее, а на Верилоге даже длиннее.

Не верю sm.gif

VHDL - это просто жуткое количество совершенно лишнего текста.

Verilog же - компактный и красивый язык.
Ещё бы заменили begin\end чем нибудь кототеньким... sm.gif
AVR
Цитата(sonycman @ Jul 14 2017, 13:45) *
Не верю sm.gif
VHDL - это просто жуткое количество совершенно лишнего текста.
Verilog же - компактный и красивый язык.

Очень прошу, давайте не будем спорить на эту тему. Мои предпочтения очевидны.
Моя вина. Я просто хотел показать новичку альтернативу, он сам и только сам должен решать что лучше для него sm.gif

Лучше просто добавить в тему лаконичную демонстрацию этого факта относительно задачи этой темы.
yoggy
Цитата(sonycman @ Jul 14 2017, 13:45) *
...
Verilog же - компактный и красивый язык.
Ещё бы заменили begin\end чем нибудь кототеньким... sm.gif


Тоже огорчает эта устаревшая форма записи. В SV вроде это осталось так же для совместимости.
Может кто занимается синтаксической переработкой языка verilog, Какие-либо openSource проекты?
(только не превратилось бы это в кучу сахарных языков, как в js)

Из известных мне, только MyHDL - "надстройка" над python.
Огурцов
Цитата(iosifk @ Jul 14 2017, 10:40) *
цель разработки - это сделать с первого раза и без ошибок

цель разработки - сделать, в первую очередь, чтобы без ошибок со второго раза
ибо, тот, кто придёт после вас, не будет разбираться в ваших оптимизациях, а станет переписывать - код в ведро




Цитата(sonycman @ Jul 14 2017, 10:45) *
Ещё бы заменили begin\end чем нибудь кототеньким...

эти люди - извращенцы, сначала в паскаль добавили сей, а затем паскаль убрали, но почему-то не весь
я никак не могу себе это объяснить
или крестик сними, или трусы одень (с)
iosifk
Цитата(Огурцов @ Jul 15 2017, 07:20) *
цель разработки - сделать, в первую очередь, чтобы без ошибок со второго раза
ибо, тот, кто придёт после вас, не будет разбираться в ваших оптимизациях, а станет переписывать - код в ведро


Давайте я объясню.
после меня никто код не переписывает. Для этого есть правила оформления кода.
А по сути я бы сделал так.
Ввел бы параметры:
"Дебаг_релиз"
"Импульс_дебаг", "Импульс_релиз"
"Пауза_дебаг", "Пауза_релиз"
"Число_LED"
"Инверсия_LED"

Далее - сдвиговый регистр на 2 * "Число_LED". Нечетные на LED напрямую или с инверсией в зависимости от "Инверсия_LED".
У этого регистра должно быть 2 входа управления: загрузка и сдвиг. Ну и шина данных для загрузки с кодом "1". Эта единичка и будет сдвигаться по регистру...
Теперь далее. Поскольку есть паузы - добавляем программируемый таймер. Его разрядность считаем по формулам от длительности импульса и паузы и выбираем большую. Для этого делаем функцию... Чтобы ни в коем случае не руками... Таймер обычно часто применяемый "кирпич", поэтому с ним проблем вообще нет... sm.gif
У таймера должно быть 2 входа: загрузка и шина данных, ну и выход готовности.
И последний компонент - автомат. 5 состояний. Исходное, когда грузится сдвиговый регистр и 4 рабочих. Загрузка таймера и ожидание готовности таймера для импульса и 2 таких же для паузы... Вот по этим 4-м состояниям он и бегает...
В состоянии автомата для загрузки таймера активен сигнал "загрузка таймера", не активен сигнал "сдвиг". Код загрузки берется из параметра. В состоянии ожидания конца счета - наоборот. Активен только "сдвиг".
Автомат грузит таймер и ждет окончания счета, потом бежит далее. В состоянии загрузки таймера дается импульс на сдвиг регистра.

Вот и весь проект.
Для симуляции берем например ИМПУЛЬС = 5, ПАУЗА = 3, ЧИСЛО = 4... Симулируется моментально.
Для релиза указываем реальные времена, все разрядности пересчитываются автоматически...
Теперь вопрос: ну и где тут ошибаться? Цель такого подхода в том, что каждый отдельно взятый кусок может быть проверен отдельно от всего остального...
Да, еще добавлю. Я одновременно веду 3 файла. В Ворде и визио - блок-схема, на верилоге и Срр для тестов...
Maverick
Цитата(AVR @ Jul 14 2017, 13:47) *
Я просто хотел показать новичку альтернативу, он сам и только сам должен решать что лучше для него sm.gif

Вы вняли мои слова sm.gif
PS Я просто так говорю, что человек сам должен произвести выбор, без навязывания sm.gif
lyzifer
Цитата(Tausinov @ Jul 14 2017, 13:36) *

Ваша программа прекрасно работает,за что ещё раз спасибо))))но теперь к ней нужно добавить кнопку так, чтобы когда нажал один раз,светодиоды загорались и тухли ,как и в предыдущем проекте, а при повторном нажатии светодиоды должны прекратить светиться до тех пор, пока я опять не нажму кнопку)уже 2 дня не получается это правильно реализовать((( я так понимаю надо добавить в проект ещё один входной сигнал кнопки (например btn) и один цикл if,где будет при btn=1 идти сигнал на светодиод,а при btn=0 .НО НИКАК НЕ ПОЛУЧАЕТСЯ.
Код
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity test_led is
  generic (
    p_TD      : time    := 1 ns;
    p_CNT_LIM : integer := 5000000-1                      
  );
  port (
    clk : in  std_logic;
    btn : in  std_logic; кнопка
    led : out std_logic_vector(7 downto 0)
  );
end test_led;

architecture rtl of test_led is
  signal div_cnt_u : unsigned(22 downto 0)        := (others => '0');
  signal phase     : std_logic                    := '1';
  signal btn_tu    : std_logic                    : ='1'; -сигнал при нажатии кнопки
  signal led_reg   : std_logic_vector(7 downto 0) := (0 => '1', others => '0');
begin

btn_control: process(clk)
begin
  if rising_edge(clk) then
    btn_tu <= btn;
    if btn_tu = '0' and btn = '1' then
      led_reg <= led_reg + 1;
    end if;
  end if;
end process;

counter_control_p: process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u < p_CNT_LIM) then
        div_cnt_u <= div_cnt_u + 1 after p_TD;
      else
        div_cnt_u <= (others => '0');
      end if;
    else
      NULL;
    end if;
  end process;

phase_control_p: process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        phase <= not(phase) after p_TD;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --phase_control_p

led_reg_control_p: process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        if (phase = '1') then
          led_reg <= led_reg(6 downto 0) & led_reg(7) after p_TD;
          NULL;
        end if;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --led_reg_control_p

out_form_logic_p: process(phase)
  begin
    if (phase = '0') then
      led <= (others => '0');
    else
      led <= led_reg;
    end if;
  end process; --out_form_logic_p

end rtl;
Tausinov
Что-то странное вы пытаетесь сделать, если честно. Я имею в виду в коде, а не идею с кнопкой. Все, что нужно - завести дополнительный сигнал, например, signal ce : std_logic := '0'; и по каждому нажатию на кнопку делать ce <= not(ce); А дальше уже много вариантов. Можно, например, phase в нуле "заморозить".

А, ну и для железа по-хорошему нужно делать антидребезг и защиту от метастабильности в виде двух-трех регистров.
lyzifer
Цитата(Tausinov @ Jul 17 2017, 15:42) *
Что-то странное вы пытаетесь сделать, если честно. Я имею в виду в коде, а не идею с кнопкой. Все, что нужно - завести дополнительный сигнал, например, signal ce : std_logic := '0'; и по каждому нажатию на кнопку делать ce <= not(ce); А дальше уже много вариантов. Можно, например, phase в нуле "заморозить".
А, ну и для железа по-хорошему нужно делать антидребезг и защиту от метастабильности в виде двух-трех регистров.

хм...по-моему,это очень хорошая идея))сейчас попробую))позже отпишусь)) rolleyes.gif
lyzifer
Цитата(Tausinov @ Jul 17 2017, 15:42) *
Все, что нужно - завести дополнительный сигнал, например, signal ce : std_logic := '0'; и по каждому нажатию на кнопку делать ce <= not(ce); Можно, например, phase в нуле "заморозить".

Видимо,я пока слишком туп((
Код
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity test_led is
  generic (
    p_TD      : time    := 1 ns;
    p_CNT_LIM : integer := 5000000-1                      
  );
  port (
    clk : in  std_logic;
    --btn : in  std_logic; --кнопка
    led : out std_logic_vector(7 downto 0)
  );
end test_led;

architecture rtl of test_led is
  signal div_cnt_u : unsigned(22 downto 0)        := (others => '0');
  signal phase     : std_logic                    := '1';
  signal btn_ce    : std_logic                    := '0'; --сигнал при нажатии кнопки
  signal led_reg   : std_logic_vector(7 downto 0) := (0 => '1', others => '0');
begin

counter_control_p: process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u < p_CNT_LIM) then
        div_cnt_u <= div_cnt_u + 1 after p_TD;
      else
        div_cnt_u <= (others => '0');
      end if;
    else
      NULL;
    end if;
  end process;

phase_control_p: process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        phase <= not(phase) after p_TD;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --phase_control_p

led_reg_control_p: process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        if (phase = '1') then
          led_reg <= led_reg(6 downto 0) & led_reg(7) after p_TD;
          NULL;
        end if;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --led_reg_control_p
  
btn_control: process(clk) -- нажатия кнопки
  begin
   if (btn_ce = '1') then
       btn_ce <= not(btn_ce)
       phase <= (others => '0');
       else
       phase <= '1';
   end if;
  end process;
  
out_form_logic_p: process(phase)
  begin
    if (phase = '0') then
      led <= (others => '0');
    else
      led <= led_reg;
    end if;
  end process; --out_form_logic_p

end rtl;
Tausinov
Как-то так, например.
Тестбенч :
Код
library ieee;
   use ieee.std_logic_1164.all;

entity test_led_tb is
   generic (
      p_TD    : time := 1 ns;
      p_CLK_T : time := 4 ns
   );
end test_led_tb;

architecture behav of test_led_tb is
   signal clk : std_logic                    := '0';
   signal sw  : std_logic                    := '0';
   signal led : std_logic_vector(3 downto 0);

   component test_led is
     generic (
       p_TD      : time    := 1 ns;
       p_CNT_LIM : integer := 1000 - 1
     );
     port (
       clk : in  std_logic;
       sw  : in  std_logic;
       led : out std_logic_vector(3 downto 0)
     );
   end component;
begin
  clk_gen_p : process
  begin
    clk <= not(clk);
    wait for p_CLK_T / 2;
  end process;

  sw <= '1' after 100 us, '0' after 101 us, '1' after 200 us;

  UUT : test_led
    generic map (
      p_TD => p_TD
    )
    port map (
      clk => clk,
      sw  => sw,
      led => led
    );

end behav;

Дизайн:
Код
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity test_led is
  generic (
    p_TD      : time    := 1 ns;
    p_CNT_LIM : integer := 32768 - 1
  );
  port (
    clk : in  std_logic;
    sw  : in  std_logic;
    led : out std_logic_vector(3 downto 0)
  );
end test_led;

architecture rtl of test_led is
  type on_off_state is (OFF, ONN);
  signal led_state  : on_off_state                 := OFF;

  signal div_cnt_u  : unsigned(31 downto 0)        := (others => '0');

  signal phase      : std_logic                    := '1';
  signal sw_sync_re : std_logic                    := '0';
  signal sw_reg     : std_logic_vector(2 downto 0);
  signal led_reg    : std_logic_vector(3 downto 0) := (0 => '1', others => '0');
begin

  resync_sw_p : process(clk)
  begin
    if (rising_edge(clk)) then
      sw_reg(0)          <= sw                 after p_TD;
      sw_reg(2 downto 1) <= sw_reg(1 downto 0) after p_TD;
    else
      NULL;
    end if;
  end process; --resync_sw_p

  sw_sync_re <= sw_reg(1) and not(sw_reg(2));

  scheme_state_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (sw_sync_re = '1') then
        if (led_state = ONN) then
          led_state <= OFF after p_TD;
        else
          led_state <= ONN after p_TD;
        end if;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --scheme_state_control_p

  counter_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u < p_CNT_LIM) then
        div_cnt_u <= div_cnt_u + 1 after p_TD;
      else
        div_cnt_u <= (others => '0');
      end if;
    else
      NULL;
    end if;
  end process;

  phase_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        if (phase = '0') then
          if (led_state = ONN) then
            phase <= '1' after p_TD;
          else
            phase <= '0' after p_TD;
          end if;
        else
          phase <= '0' after p_TD;
        end if;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --phase_control_p

  led_reg_control_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (div_cnt_u = p_CNT_LIM) then
        if (phase = '1') then
          led_reg <= led_reg(2 downto 0) & led_reg(3) after p_TD;
        else
          NULL;
        end if;
      else
        NULL;
      end if;
    else
      NULL;
    end if;
  end process; --led_reg_control_p

  out_form_logic_p : process(phase)
  begin
    if (phase = '0') then
      led <= (others => '0');
    else
      led <= led_reg;
    end if;
  end process; --out_form_logic_p

end rtl;


Пы.Сы ONN вместо ON, потому что ON - зарезервированное слово.

Пы.Пы.Сы. Научите код под спойлер убирать(
lyzifer
Цитата(Tausinov @ Jul 17 2017, 17:59) *

Блин,я наверное,уже задолбал, (( crying.gif
но походу "замораживать фазу" не лучшая идея,т.к моделирование показывает вообще не тот результат.

ПРИ ТАКИХ ПАРАМЕТРАХ:
Код
sw <= '0' after 0 ms, '1' after 3000  ms, '0' after 6000 ms, '1'after 10000 ms;



а вот так должна выглядеть времянка. т.е. до 3 сек. кнопка не нажата и светодиоды не мигают. на 3 секунде я нажал кнопку и светодиодымигают до 6 сек. потом я опять нажал кнопку и светодиоды потухли. И Т.Д.





iosifk
Цитата(lyzifer @ Jul 18 2017, 16:52) *
Блин,я наверное,уже задолбал, (( crying.gif


И не лень Вам упираться рогом??? Как говорил классик: "Не тем путем идете, товарищ"!
Два раза уже объяснил как делать проще.
Предлагал свою помощь... А Вам видно лень переделывать... Или может цель в том, чтобы троллить? Кто бы другой уже давно бы включил скайп...
lyzifer
Цитата(iosifk @ Jul 18 2017, 16:59) *
Два раза уже объяснил как делать проще.
Предлагал свою помощь... А Вам видно лень переделывать... Или может цель в том, чтобы троллить? Кто бы другой уже давно бы включил скайп...

Я ПОНИМАЮ,ВЫГЛЯДИТ ОЧЕНЬ ТУПО. wacko.gif
прост,я хочу этот проект,так сказать, модифицировать.Я VHDL изучаю всего месяц от силы.
но троллинга тут нет НИКАКОГО.просто я действительно до такой степень тупой (надеюсь это временно)
Tausinov
Один из диодов в начале горит, т.к. регистр инициализирован 1. Это все можно поправить. А по поводу моментов моргания...
Цитата
но теперь к ней нужно добавить кнопку так, чтобы когда нажал один раз,светодиоды загорались и тухли ,как и в предыдущем проекте, а при повторном нажатии светодиоды должны прекратить светиться до тех пор, пока я опять не нажму кнопку

lyzifer
Цитата(Tausinov @ Jul 18 2017, 18:53) *
Один из диодов в начале горит, т.к. регистр инициализирован 1. Это все можно поправить.

т.е если я буду инициализировать регистр в 0, то ,по идее, система должна заработать как надо?
AVR
Я не выдержал, моё решение (сам модуль примерно 25 не пустых строк):
Код
`timescale 1ns / 1ps

//----- top module

module led_blink(
input clock,
input sw,
output reg [3:0] led
);

initial led = 0;
reg [3:0] state;
initial state = 4'b1000;

reg on1off0;
initial on1off0 = 1;

reg [23:0] divider;
initial divider = 0;
always @(posedge clock) begin
    if(divider < 499999) divider <= divider + 1;
    else begin
        divider <= 0;
        if(sw) begin
            on1off0 <= !on1off0;
            if(on1off0) begin
                state <= {state[0], state[3:1]};
                led <= state;
            end else led <= 0;
        end else begin
            on1off0 <= 1;
            led <= 0;
        end
    end
end

endmodule

//----- testbench

module testbench();

    reg clock1m; // 1 MHz
    initial clock1m = 0;
    always clock1m = #500 !clock1m;

    reg sw;
    wire [3:0] leds;

    led_blink uut(
    .clock(clock1m),
    .led(leds),
    .sw(sw));
    
    initial begin
        sw = 0;
        
        #999999000;
        #1000000000;
        #1000000000;
        
        sw = 1;
        
        #1000000000;
        #1000000000;
        #1000000000;
        
        sw = 0;
        
        #1000000000;
        #1000000000;
        #1000000000;
        #1000000000;
        
        sw = 1;
        
        #1000000000;
        #1000000000;
        #1000000000;
        #1000000000;
        #1000000000;
        
        sw = 0;
        
        #1000000000;
        #1000000000;
        #1000000000;
        
        $stop;
    end

endmodule


Нажмите для просмотра прикрепленного файла
lyzifer
Цитата(AVR @ Jul 18 2017, 22:56) *
Я не выдержал, моё решение (сам модуль примерно 25 не пустых строк):

Спасибо,конечно))но принципиально важно реализовать этот проект на VHDL. (так от меня требуют)
Tausinov
Так осталось просто тоже самое переписать на VHDL. Тут каких-то принципиально отличных конструкций нет, переносится без проблем.
lyzifer
Цитата(Tausinov @ Jul 19 2017, 11:39) *
Так осталось просто тоже самое переписать на VHDL. Тут каких-то принципиально отличных конструкций нет, переносится без проблем.

ага, для меня Верилог это вообще набор иероглифов biggrin.gif
Tausinov
Код
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;

entity led_blink is
  port (
    clk : in  std_logic;
    sw  : in  std_logic;
    led : out std_logic_vector(3 downto 0)
  );
end led_blink;

architecture rtl of led_blink is
  signal on1off0 : std_logic                    := '1';
  signal state   : std_logic_vector(3 downto 0) := "0001";
  signal divider : unsigned(23 downto 0)        := (others => '0');
begin
  main_p : process(clk)
  begin
    if (rising_edge(clk)) then
      if (divider < 200) then
        divider <= divider + 1;
      else
        divider <= (others => '0');
        if (sw = '1') then
          on1off0 <= not(on1off0);
          if (on1off0 = '1') then
            state <= state(2 downto 0) & state(3);
            led   <= state;
          else
            led   <= (others => '0');
          end if;
        else
          on1off0 <= '1';
          led     <= (others => '0');
        end if;
      end if;
    end if;
  end process;
end rtl;


Тоже самое на vhdl, больше лишь на пару строк.
Все же, если будет запуск на реальном железе, нужны анти-дребезг и перетактирование сигнала с кнопки.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.