Jump to content
    

нужна помощь VHDL

Хочу сделать приемник последовательного кода. Есть две линии, если по одной приходит фронт (IN-1), то в выходной параллельный код записываем 1, если по IN_0, то записываем 0.

Раньше рисовал все в MAX_PLUS !! c использованием примитивов и насколько помню, что для того чтоб дизайндоктор не ругался все должно быть синхронно, тоесть все это должно синхронизироваться CLK.

 

Quartus 2 пишет ошибки multiply clock edge. Тоесть ему не нравиться IN_1'event и IN_0'event, я и сам чувствую что что-то здесь не то, подскажите как решить поставленную задачу и объясните в чем ошибка.

 

Спасибо.

 

library IEEE;

use IEEE.std_Logic_1164.all;

entity tg is

port(

CLK,IN_1,IN_0 : in std_logic;

PO : out std_logic_vector(7 downto 0));

end tg;

architecture archi of tg is

 

signal tmp : std_logic_vector(7 downto 0);

begin

 

shift: process(clk)

begin

 

if (IN_1'event and IN_1='1')

then

tmp <=tmp(6 downto 0)&'1';

end if;

 

if (IN_0'event and IN_0='1')

then

tmp <=tmp(6 downto 0)&'0';

end if;

 

end process;

 

PO <= tmp;

end archi;

Share this post


Link to post
Share on other sites

Так в этом и ошибка, на что ругался Квартус. Атрибут сигнала Event означает, что условие истинно только в момент изменения сигнала, то есть это детектор фронта и этот атрибут может синтезироваться только в клоковый вход триггера. В Вашем процессе три таких атрибута - еще один используется неявно в конструкции process(clk). Так как в FPGA нет триггеров с тремя клоками, синтезатор не может синтезировать ваш код.

 

Кроме того, Вы в коде требуете чтобы некоторые действия происходили когда два клока приходят одновременно - клока и одного из входов. С физической точки зрения это бессмыссленно, хоть и допустимо в VHDL.

 

Думаю, Ваши сложности связаны с тем, что Вы хотите использовать атрибут Event для диагностирования фронта в дискретном времени в процессе, а этот атрибут предназначен только для сигналов в непрерывном времени. Чтобы получить предыдущее состояние сигнала в дискретном времни в процессе в VHDL есть только один путь - по фронту clk запоминать предыдущее значение сигнала и в условиях явно сравнивать текущее значение с предыдущим, заменив члены IN_x'event на IN_x_prev = '0'. И обеспечить синхронность сигналов IN_x по отношению к clk поставив на входы синхронизаторы, если их еще нет где-нибудь в другом месте.

Share this post


Link to post
Share on other sites

Quartus 2 пишет ошибки multiply clock edge. Тоесть ему не нравиться IN_1'event и IN_0'event, я и сам чувствую что что-то здесь не то, подскажите как решить поставленную задачу и объясните в чем ошибка.

 

Не так здесь на мой вкус подход к проектированию. Надо делать синхронно, if rising_edge(clk) then и дальше case на четыре варианта линий IN_1 и IN_0.

Share this post


Link to post
Share on other sites

Хочу сделать приемник последовательного кода. Есть две линии, если по одной приходит фронт (IN-1), то в выходной параллельный код записываем 1, если по IN_0, то записываем 0.

Раньше рисовал все в MAX_PLUS !! c использованием примитивов и насколько помню, что для того чтоб дизайндоктор не ругался все должно быть синхронно, тоесть все это должно синхронизироваться CLK.

а это вам зачем так подходить к вопросам последовательной передачи - по фронту. что за ТЗ такое и в соответствии с каким стандартом? если уж таким макаром организовывать передачу - то рассматривайте проблему лучше не с точки зрения фронтов а изменения уровней (некоторые скажут что это одно и то же - но это не так) и ещё одна подсказка подумайте в сторону увеличения опорного синхросигнала относительно скорости передачи в несколько раз

Share this post


Link to post
Share on other sites

а это вам зачем так подходить к вопросам последовательной передачи - по фронту. что за ТЗ такое и в соответствии с каким стандартом? если уж таким макаром организовывать передачу - то рассматривайте проблему лучше не с точки зрения фронтов а изменения уровней (некоторые скажут что это одно и то же - но это не так) и ещё одна подсказка подумайте в сторону увеличения опорного синхросигнала относительно скорости передачи в несколько раз

 

Задачка для самообучения. Цель - данные из кода Arinc перевести в любой параллельный код.

Можно работать и по уровню, но по фронту кажется проще. Из вышепрочитанного пришел к выводу что оптимальный вариант - засинхронизироваться от CLK и ловить перепады сигналов.

 

А кстати, можно ли так писать process( rising_edge(CLK)) ?

Share this post


Link to post
Share on other sites

Можно работать и по уровню, но по фронту кажется проще. Из вышепрочитанного пришел к выводу что оптимальный вариант - засинхронизироваться от CLK и ловить перепады сигналов.

 

А кстати, можно ли так писать process( rising_edge(CLK)) ?

ага верно уловили идею - проблема ловли фронтов в дополнительных схемах по отлавливанию ложных фронтов при шуме и неудобству синтеза в ФПГА элементов чувствительных к фронту информационных(нетактирующих) сигналов - поэтому сажайте регистровую логику на тактирующий сигнал повышенный частоты (х8 или х16) и ловите уровни (повышенная частота нужна для отсеивания ложных перепадов)

 

process( rising_edge(CLK)):

нет по ИМХу нельзя rising_edge(CLK)- функция, возвращает булево значение = (clk'event AND clk = '1'), а process (clk) возвращает событие, заносимое в список ассоциированных с процессом инициирующих событий

Share this post


Link to post
Share on other sites

Чтобы получить предыдущее состояние сигнала в дискретном времни в процессе в VHDL есть только один путь - по фронту clk запоминать предыдущее значение сигнала и в условиях явно сравнивать текущее значение с предыдущим, заменив члены IN_x'event на IN_x_prev = '0'. И обеспечить синхронность сигналов IN_x по отношению к clk поставив на входы синхронизаторы, если их еще нет где-нибудь в другом месте.

 

А как мне взять предыдущее значение сигнала? Насколько я понимаю в процессе все операции выполняются одновременно.

Share this post


Link to post
Share on other sites

А как мне взять предыдущее значение сигнала? Насколько я понимаю в процессе все операции выполняются одновременно.

 

Заведите еще один процесс, в котором по фронту клока защелкивайте значение сигнала.

И в вашем рабочем процессе по фронту клока сравнивайте текущее значение сигнала с этим защелкнутым на предыдущем такте.

Share this post


Link to post
Share on other sites

Чтобы получить предыдущее состояние сигнала в дискретном времни в процессе в VHDL есть только один путь - по фронту clk запоминать предыдущее значение сигнала и в условиях явно сравнивать текущее значение с предыдущим, заменив члены IN_x'event на IN_x_prev = '0'. И обеспечить синхронность сигналов IN_x по отношению к clk поставив на входы синхронизаторы, если их еще нет где-нибудь в другом месте.

 

А как мне взять предыдущее значение сигнала? Насколько я понимаю в процессе все операции выполняются одновременно.

 

Запомнить можно так например:

...
signal IN_x_prev : std_logic;

process (clk, rst)
begin
  if rst = '1' then
     IN_x_prev <= '0';
  elsif rising_edge(clk) then
     IN_x_prev <= IN_x; -- запоминаем
  end if;
end process;
....
....

process (clk, rst)
begin
  if rst = '1' then
     tmp <= (others=>'0');
  elsif rising_edge(clk) then
    if IN_x_prev = '1' then
       tmp <=tmp(6 downto 0)&'1';
    elsif ...........  then
       tmp <=tmp(6 downto 0)&'0';
    end if;
  end if;
end process;

 

В Вашем коде нету сигнала сброса, а он должен быть :) В вышенаписанном коде будет задержка на 1 такт из-за конвейера.

 

На форуме гдето был топик по использованию двух клоков, думаю Вам стоит там посмотреть, какие подводные камни могут встретится. Почитайте, например, вот это http://electronix.ru/forum/index.php?showtopic=15633 , там есть ссылки

 

Удачи!

Share this post


Link to post
Share on other sites

To maximka

Скачайте с сайта xilinx документ xst.pdf (синтезабельное hdl описание счетчиков. триггеров, дешифраторов и т.д.

И переведите в лоб свою графику на текст.

Share this post


Link to post
Share on other sites

Ну эту задачу я решил.

Теперь пытаюсь ее усложнить.

Данный код самосинхронезирующийся. По протоколу передаются 32 бита и как бы признаком конца слова является пауза после 32 бита длительностью 4 такта (пусть 0,5 мкс).

Вопрос, как мне сделать анализатор паузы в 4 такта.

Пример:

library IEEE;

use IEEE.std_Logic_1164.all;

entity tg is

port(

RST,CLK,IN_1,IN_0 : in std_logic;

PAUSE: out std_logic;

PO : out std_logic_vector(7 downto 0));

end tg;

 

architecture archi of tg is

 

shared variable a,b:integer;

signal tmp,time : std_logic_vector(7 downto 0);

signal pr,IN_1_prev,IN_0_prev :std_logic;

 

begin

 

prev: process(CLK) -- в данном процессе сохраняем предыдущие значения

begin

if(rising_edge(CLK))

then

IN_1_prev<=IN_1;

IN_0_prev<=IN_0;

a:=a+1; --тут я пытаюсь сделать счетчик клоков

end if;

end process prev;

 

 

shift:process(CLK,RST)

begin

if (RST='1') then --обнулятор

tmp<="00000000";--&"00000000"&"00000000"&"00000000";

elsif(rising_edge(CLK))

then

if(IN_1='1' and IN_1_prev='0') --если есть перепад по IN_1, то

then

tmp <=tmp(6 downto 0)&'1'; --в результирующем слове сдвигаем 1.

b:=a; --длительность b= одному такту

a:=0; --сбрасываем счетчик клоков

end if;

if(IN_0='1' and IN_0_prev='0')then

tmp <=tmp(6 downto 0)&'0'; --аналогично, только сдвигаем не 1, а 0

b:=a;

a:=0;

end if;

 

end if;

--if(a>2)then pr<='1';end if;

end process shift;

 

 

PO <= tmp;-- after 40 ns;--(std_logic_vector)a;

PAUSE<=pr;

end archi;

 

В принципе так все вроде работает.

Теперь надо сделать счетчик паузы

по идее надо условие

IF(4*b>a)then pr<='1';end if;

но куда его не поставлю все время ошибки. подскажите как сделать анализатор паузы и в чем ошибки?

 

И еще вопрос: чем переменная отличается от сигнала?

Спасибо.

Share this post


Link to post
Share on other sites

Ну эту задачу я решил.

Теперь пытаюсь ее усложнить.

Данный код самосинхронезирующийся. По протоколу передаются 32 бита и как бы признаком конца слова является пауза после 32 бита длительностью 4 такта (пусть 0,5 мкс).

Вопрос, как мне сделать анализатор паузы в 4 такта.

Пример:

library IEEE;

use IEEE.std_Logic_1164.all;

entity tg is

port(

RST,CLK,IN_1,IN_0 : in std_logic;

PAUSE: out std_logic;

PO : out std_logic_vector(7 downto 0));

end tg;

 

architecture archi of tg is

 

shared variable a,b:integer;

signal tmp,time : std_logic_vector(7 downto 0);

signal pr,IN_1_prev,IN_0_prev :std_logic;

 

begin

 

prev: process(CLK) -- в данном процессе сохраняем предыдущие значения

begin

if(rising_edge(CLK))

then

IN_1_prev<=IN_1;

IN_0_prev<=IN_0;

a:=a+1; --тут я пытаюсь сделать счетчик клоков

end if;

end process prev;

 

 

shift:process(CLK,RST)

begin

if (RST='1') then --обнулятор

tmp<="00000000";--&"00000000"&"00000000"&"00000000";

elsif(rising_edge(CLK))

then

if(IN_1='1' and IN_1_prev='0') --если есть перепад по IN_1, то

then

tmp <=tmp(6 downto 0)&'1'; --в результирующем слове сдвигаем 1.

b:=a; --длительность b= одному такту

a:=0; --сбрасываем счетчик клоков

end if;

if(IN_0='1' and IN_0_prev='0')then

tmp <=tmp(6 downto 0)&'0'; --аналогично, только сдвигаем не 1, а 0

b:=a;

a:=0;

end if;

 

end if;

--if(a>2)then pr<='1';end if;

end process shift;

 

 

PO <= tmp;-- after 40 ns;--(std_logic_vector)a;

PAUSE<=pr;

end archi;

 

В принципе так все вроде работает.

Теперь надо сделать счетчик паузы

по идее надо условие

IF(4*b>a)then pr<='1';end if;

но куда его не поставлю все время ошибки. подскажите как сделать анализатор паузы и в чем ошибки?

 

И еще вопрос: чем переменная отличается от сигнала?

Спасибо.

 

А зачем Вам пауза, если и так известно скоко бит передается? Задержку легко можно реализовать на конечном автомате.

У Вас несинтезируемый код: не надо использовать shared variable. Используйте сигналы, причем не надо присваивать ему одновременно значения в разных процесах, иначе получите сообщение об ошибке (Вы сейчас так делаете для переменной a ). Что касается отличия переменной от сигнала - то посмотрите в любой литературе по VHDL :)

Share this post


Link to post
Share on other sites

IMHO: Главным различием переменной и сигнала является то, что значение переменной изменяется непосредственно в момент присвоения ей нового занченя a:=b, теперь при дальнейшем выполнении прцесса, значение a будет b. Значение сигнала изменяется только по окончанию выполнения процесса. Запись вида a<=b только намечает транзакцию, которая выполнится после того как выполнится весь процесс. После этой строки в процессе значение a будет a до конца процесса. По крайней мере я так это понял и вроде как работает :)

 

По эжтому принцыпу можно описать сдвиговый регистр

 

signal a, b0, b1, b2, b3, b4, b5, b6, b7: std_logic;

begin

shiftreg: process(CLK) is
begin
if rising_edge(CLK) then
b0<=a;
b1<=b0;
b2<=b1;
b3<=b2;
b4<=b3;
b5<=b4;
b6<=b5;
b7<=b6;
end if;
end process; -- Вроде должен получиться 8 битный сдвиговый регистр :)

end;

Edited by Murr Von Kater

Share this post


Link to post
Share on other sites

IMHO: Главным различием переменной и сигнала является то, что значение переменной изменяется непосредственно в момент присвоения ей нового занченя a:=b, теперь при дальнейшем выполнении прцесса, значение a будет b. Значение сигнала изменяется только по окончанию выполнения процесса. Запись вида a<=b только намечает транзакцию, которая выполнится после того как выполнится весь процесс. После этой строки в процессе значение a будет a до конца процесса. По крайней мере я так это понял и вроде как работает :)

 

По эжтому принцыпу можно описать сдвиговый регистр

 

signal a, b0, b1, b2, b3, b4, b5, b6, b7: std_logic;

begin

shiftreg: process(CLK) is
begin
if rising_edge(CLK) then
b0<=a;
b1<=b0;
b2<=b1;
b3<=b2;
b4<=b3;
b5<=b4;
b6<=b5;
b7<=b6;
end if;
end process; -- Вроде должен получиться 8 битный сдвиговый регистр :)

end;

 

Сдвиг на произвольное количество бит :) http://tams-www.informatik.uni-hamburg.de/...l/shifter8.html -- ссылка приводилась недавно в соседних топиках.

Share this post


Link to post
Share on other sites

А зачем Вам пауза, если и так известно скоко бит передается? Задержку легко можно реализовать на конечном автомате.

У Вас несинтезируемый код: не надо использовать shared variable. Используйте сигналы, причем не надо присваивать ему одновременно значения в разных процесах, иначе получите сообщение об ошибке (Вы сейчас так делаете для переменной a ). Что касается отличия переменной от сигнала - то посмотрите в любой литературе по VHDL :)

 

Что значит несинтезируемый код и почему не надо использовать Shared value? Мне кажется что это очень удобно использовать для какого-нибудь служебного счетчика например.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...