Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: помогите в написании кода
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Схемотехника
xamsid
изучаю плис в течении 1 недели, пытаюсь изучить путем решения не сложных задач , научился делать один строго один импульс по нажатию кнопки вот пример кода
Код
entity sig is
    Port ( CLK : in  STD_LOGIC;
           btn : in  STD_LOGIC;
           vix : out  STD_LOGIC);
end sig;

architecture Behavioral of sig is
signal a: std_logic_vector(1 DOWNTO 0):="00" ;
begin
    process (CLK)
        begin
        if rising_edge(CLK) then    
           a<= a(0) & btn;
            if (a = "01") then                
                       vix <= '1';
            else    vix <= '0';
        end if;    
        end if;
    end process;
end Behavioral;

не получается разобратся как сделать 2 импульса разной длинны по нажатию кнопки, причем если кнопку удерживать сигнал должен все равно прикратится. crying.gif
за ранее спасибо.
sazh
Цитата(xamsid @ Jul 31 2009, 12:20) *
не получается разобратся как сделать 2 импульса разной длинны по нажатию кнопки, причем если кнопку удерживать сигнал должен все равно прикратится. crying.gif


Увеличить разрядность сдвигающего регистра
Maverick
Цитата(xamsid @ Jul 31 2009, 11:20) *
изучаю плис в течении 1 недели, пытаюсь изучить путем решения не сложных задач , научился делать один строго один импульс по нажатию кнопки вот пример кода

не получается разобратся как сделать 2 импульса разной длинны по нажатию кнопки, причем если кнопку удерживать сигнал должен все равно прикратится. crying.gif
за ранее спасибо.

Желательно вначале поставить схемку из двух триггеров которая б убирала дребезг контакта кнопки, затем поставить схемку которая фиксировала бы нажатие кнопки, т.е. выдавала бы одиночный импульс (так называемый детектор переднего/заднего форнта импульса), после поставить схемку которая по приходу одиночного импульса заускала счетчик тактовой частоты и как только счетчик набрал необходимое количество импульсов тактовой частоты переставал работать.
Таким оразом можно формировать импульсы различной длительности с помощью дешифратора и JK-тригера.
Примерно таким я вижу ход разработки схемы для Вашего ответа.
ЗЫ под "поставить схемку" = схема описанная на VHDL = схема в нарисованная в схематикедитре
ЗЫ ЗЫ это в том случае если подойти к задаче так как надо. Если упрощенный вариант, тогда схемкой из двух триггеров которая б убирала дребезг контакта кнопки можно пренебречь
Shtirlits
Стараюсь писать как можно понятнее. И самому легче и ошибок меньше.
Мне понятнее так:

CODE
entity sig is
Port ( CLK : in STD_LOGIC;
reset : in std_logic; -- sync reset
btn : in STD_LOGIC;
vix : out STD_LOGIC);
end sig;

architecture Behavioral of sig is

type state_t is (st_idle, st_button_pressed, st_wait_depress);
signal state_reg : state_t;

begin
process (CLK, reset)
if rising_edge(CLK) then
if reset='1' then
button_reg1 <= '0';
button_reg <= '0';
else
button_reg1 <= btn;
button_reg <= button_reg1;
end if;
end process;


process (CLK, reset)
begin
if rising_edge(CLK) then
viz <= '0'; -- by default
if reset='1' then
state_reg <= st_idle;
else
case state_reg is

when st_idle =>
if button_reg='1' then
state_reg <= st_button_pressed;
end if; -- else keep state_reg

when st_button_pressed =>
viz <= '1'; -- 1 cycle pulse
if button_reg='1' then
state_reg <= st_wait_depress;
else
state_reg <= st_idle;
end if;

when st_wait_depress =>
if button_reg='0' then
state_reg <= st_idle;
end if;

end case;
end if;
end if;
end process;

end Behavioral;



Сразить метастабильность можно еще так (версия для xilinx):
CODE
-- reduce probability of metastable effect

library IEEE;
use IEEE.std_logic_1164.all;

library unisim;
use unisim.vcomponents.all;

entity sync is
generic (
LENGTH : natural := 2;
PATH_COUNT : natural := 3
);
port (
clk : in std_logic;
d : in std_logic;
q : out std_logic
);
end sync;

architecture v2p of sync is

function majority(a : std_logic_vector) return std_logic is
variable c0, c1 : natural;
begin
c0 := 0; c1 := 0;
for i in a'range loop
if a(i)='1' then c1:=c1+1; end if;
if a(i)='0' then c0:=c0+1; end if;
end loop;
if c0>c1 then return '0'; else return '1'; end if;
end;

subtype path_t is std_logic_vector(0 to PATH_COUNT-1);
type path_vector is array (natural range <>) of path_t;

signal x : path_vector(0 to LENGTH);

attribute syn_keep : boolean;
attribute syn_keep of x : signal is true;

begin

-- generate chains of ff, prevent shift register instantiation

path_gen : for path in 0 to PATH_COUNT-1 generate
x(0)(path) <= d;
chain_gen : for stage in 0 to LENGTH-1 generate
fd_inst : FD port map(C=>clk, D=>x(stage)(path), Q=>x(stage+1)(path));
end generate;
end generate;

-- registered majority output

process(clk)
begin
if rising_edge(clk) then
q <= majority(x(LENGTH));
end if;
end process;

end v2p;
xamsid
Цитата(Maverick @ Jul 31 2009, 12:42) *
Желательно вначале поставить схемку из двух триггеров которая б убирала дребезг контакта кнопки, затем поставить схемку которая фиксировала бы нажатие кнопки, т.е. выдавала бы одиночный импульс (так называемый детектор переднего/заднего форнта импульса), после поставить схемку которая по приходу одиночного импульса заускала счетчик тактовой частоты и как только счетчик набрал необходимое количество импульсов тактовой частоты переставал работать.

Спасибо за ответ, но мне все же не понятно ( 1 неделя как вижу код )
Если ли очень простой вариант написания кода для двух одинаковых импульсов?
Просто хочу посмотреть логику реализации.
С длительностью я уже позаморачиваюсь.
Позалуста unsure.gif
xamsid
спасибо, поздно посмотрел на ваш код, вроде справился сам.
написал следующие и все заработоло
CODE
entity sig is
Port ( CLK : in STD_LOGIC;
btn : in STD_LOGIC;
vix : out STD_LOGIC);
end sig;

architecture Behavioral of sig is
signal a: std_logic_vector(1 DOWNTO 0):="00" ;

begin
process (CLK)
variable CNT:integer range 0 to 10000 :=100;
begin
if rising_edge(CLK) then
CNT:=CNT+1;
a<= a(0) & btn;
if CNT<20 then
vix <='1';
end if;
if CNT>19 and CNT<30 then
vix <='0';
end if;
if CNT>29 and CNT<150 then
vix <='1';
end if;
if CNT>149 then
vix <='0';
CNT:=1000;
end if;

if (a = "01") then
CNT:=0;
end if;

end if;
end process;
end Behavioral;
=AK=
Цитата(xamsid @ Jul 31 2009, 19:54) *
Если ли очень простой вариант написания кода для двух одинаковых импульсов?


Я не очень хорошо понял, что вы хотите. Попробую ответить в боее-менее общем виде.

Самое простое и бронебойно-правильное решение состоит в том, чтобы передать неизвестно-какие сигналы (от кнопок и т.п.) во временное пространство вашего основного клока CLK, а дальше работать в нем. Передача сигнала производится при помощи 2-х или 3-х каскадного "синхронизатора", ктороый представляет собой по сути просто сдвиговый регистр. В примере внизу я обрабатываю 2 входных сигнала Button1_i и Button2_i совершенно одинаково по сути, но по-разному в написании, получая сигналы button1 и button2

Два замечания к представленному коду:
- Я сознательно предпочитаю где можно пользоваться переменными (variable), а не сигналами (signal), посколку переменные более локальны и за пределами процесса не видны
- Отступы надо "беречь" и пользоваться ими экономно. Основная цель состоит в том, чтобы повысить читаемость текста, а не в том, чтобы долбить по клавишам
Код
resync_pro : process(CLK)
variable b0,b1: std_logic;
variable bb : std_logic_vector(1 downto 0);
begin
if rising_edge(CLK) then
  button1<=b1; b1:=b0; b0:= Button1_i; --  сдвиговый регистр "собран из кусочков", так удобно писАть, когда он короткий
  button2<=bb(1); bb:=bb(0) & Button2_i; -- сдвиговый регистр в основном сделан вторым выражением, его можно было сделать любой длины
end if; -- CLK
end process resync_pro;


Предположим, что входы Button1_i и Button2_i приходят от одной кнопки с контактом "на переключение", которая замыкает Button1_i на землю при нажатиии кнопки, или замыкает Button2_i на землю при отпускании кнопки (конечно, на входы навешены подтягивающие резисторы). Тогда подавление дребезга элементарно обеспечивается простым RS-триггером. Результирующий сигнал назовем button
Код
debounce_pro : process(CLK)
begin
if rising_edge(CLK) then
  if ( button1='0') then
    button<='1'; -- кнопка нажата
  elsif ( button2='0') then
    button<='0'; -- кнопка отжата
  end if;
end if; -- CLK
end process debounce_pro;


Теперь создадим короткие импульсы длительностью 1 клок по нажатию кнопки (назовем его button_re, где re означает "rising edge") и по отпусканию кнопки (назовем его button_fe, где fe означает "falling edge")
Код
edges_pro : process(CLK)
variable b :std_logic;
begin
if rising_edge(CLK) then
  ------------------------
  -- rising edge
  ------------------------
  if (button='1') and (b='0') then
    button_re<='1';
  else
    button_re<='0';
  end if;
  ------------------------
  -- falling edge
  ------------------------
  if (button='0') and (b='1') then
    button_fe<='1';
  else
    button_fe<='0';
  end if;
  ------------------------
  -- 1-битный сдвиговый регистр
  ------------------------
  b:=button; -- это должно быть в конце процесса, а не в начале
end if; -- CLK
end process edges_pro;


Напоследок сделаем простенький одновибратор, запускаемый по одному из фронтов. Второй такой же, запускается по другому фронту.
Выходной сигнал назовем Pulse1_o

Код
pulse1_pro : process(CLK)
variable cnt : unsigned(7 downto 0);
begin
if rising_edge(CLK) then
  -------------------------
  -- по фронту
  -------------------------
  if (button_re='1') then
    cnt := (others => '0'); -- обнулили счетчик
    Pulse1_o <= '1'; -- запустили вых. импульс
  -------------------------
  -- считаем до тех пор, пока старший разряд счетчика равен 0
  -------------------------
  elsif (cnt(7)='0') then
    if (to_integer(cnt)=55) then -- когда счетчик отсчитал нужное нам число клоков
      Pulse1_o <= '0'; -- закончили вых. импульс
    end if;
    cnt := cnt+1; -- считаем клоки
  end if;
end if; -- CLK
end process pulse1_pro;
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.