Перейти к содержанию
    

Боролся долго с SIGNED UNSIGNED, пришел к выводу что смысл это все имеет очень сомнительный, и кажущаяся удобность просто на корню убивается, что я делаю не так....

 

вот два примера.

 

 

ibrary IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

--use IEEE.STD_LOGIC_SIGNED.ALL;

use IEEE.NUMERIC_STD.ALL;

 

 

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

 

entity ADCProcess is

Port ( ADC_IN : in SIGNED (13 downto 0);

ADC_DRDY : in std_logic;

SYNC : in std_logic;

ADC_AMPLITUDE : out UNSIGNED(13 downto 0);

ADC_RAW_PHASE : out SIGNED(14 downto 0);

ADC_VALUE : out SIGNED(13 downto 0);

PHASE_DRDY : out std_logic);

end ADCProcess;

 

 

architecture Behavioral of ADCProcess is

 

signal ADC_MIN : SIGNED (13 downto 0) :=CONV_SIGNED(8191,14);

signal ADC_MAX : SIGNED (13 downto 0) :=CONV_SIGNED(-8192,14);

signal StoreClear : UNSIGNED (1 downto 0) := "00";

 

begin

 

process (ADC_DRDY)

begin

if ADC_DRDY='1' and ADC_DRDY'event then

 

ADC_VALUE <= ADC_IN;

 

if StoreClear /= CONV_UNSIGNED(1,2) then --collect min and max value

if ADC_MIN > ADC_IN then

ADC_MIN <= ADC_IN;

end if;

 

if ADC_MAX < ADC_IN then

ADC_MAX <= ADC_IN;

end if;

end if;

 

if StoreClear = CONV_UNSIGNED(0,2) AND SYNC ='1' then -- store phase and amplitude data

StoreClear <= StoreClear+1;

ADC_AMPLITUDE <= CONV_UNSIGNED(ADC_MAX-ADC_MIN,14);

-- add 13'th bit for store true MIN, MAX sign

-- not devide max+min on 2, instead it we mult ADC val on 2

-- and have multed on 2 raw_phase val

-- from out max(sin)/ampletude(sin) = 0.5 we want 1, and

-- already have it, because raw_phase was multiplied

-- from out we need only divide raw_phase on amplitude

-- to take real phase val

ADC_RAW_PHASE <= ADC_IN&'0' - (ADC_MAX(13)&ADC_MAX)+(ADC_MIN(13)&ADC_MIN);

end if;

 

if StoreClear = CONV_UNSIGNED(1,2) then -- clear colect min max data

StoreClear <= StoreClear+1;

ADC_MIN <=CONV_SIGNED(8191,14);

ADC_MAX <=CONV_SIGNED(-8192,14);

PHASE_DRDY <='1'; -- set phase data ready signal

end if;

 

if SYNC= '0' then -- set scheme to sync sygnal wating state

StoreClear <= "00";

PHASE_DRDY <='0';

end if;

 

end if;

 

 

end process;

 

end Behavioral;

 

этот пример синтезируется, но не симулируется как я с ним не бился... ModelSim ругается на конструкцию To_INTEGER, хотя я уже, кажется, перепробовал все библиотеки, а встроенный ругается на невозможность вызова функции write, в той же строке где TO_INTEGER

 

 

Вот реализация той же логике моим способом

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

 

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

 

entity ADCProcessSigned is

Port ( ADC_IN : in std_logic_vector(13 downto 0);

ADC_DRDY : in std_logic;

SYNC : in std_logic;

ADC_AMPLITUDE : out std_logic_vector(13 downto 0);

ADC_RAW_PHASE : out std_logic_vector(14 downto 0);

ADC_VALUE : out std_logic_vector(13 downto 0);

PHASE_DRDY : out std_logic);

end ADCProcessSigned;

 

 

architecture Behavioral of ADCProcessSigned is

 

signal ADC_MIN : std_logic_vector (13 downto 0) :="11111111111111";

signal ADC_MAX : std_logic_vector (13 downto 0) :="00000000000000";

signal StoreClear : std_Logic_Vector (1 downto 0) := "00";

 

begin

 

process (ADC_DRDY, SYNC)

begin

if ADC_DRDY='1' and ADC_DRDY'event then

ADC_VALUE <= ADC_IN;

 

if StoreClear = "01" then --clear min max data

PHASE_DRDY <='1'; --set data ready signal

ADC_MIN <="11111111111111"; --unsigned max possible val

ADC_MAX <="00000000000000"; --unsigned min possible val

StoreClear <= StoreClear+1;

else --if StoreClear /= "01" --if not clear flag, collect data

if ADC_MIN > (ADC_IN + "10000000000000") then -- convert -n..n to 0..2n

ADC_MIN <= ADC_IN + "10000000000000";

end if;

 

if ADC_MAX < (ADC_IN + "10000000000000") then -- convert -n..n to 0..2n

ADC_MAX <= ADC_IN + "10000000000000";

end if;

end if;

 

 

if StoreClear = "00" AND SYNC ='1' then --store phase and amplitude data

ADC_AMPLITUDE <= ADC_MAX-ADC_MIN;

-- add 13 bit to store true sign

-- not divide max+min on 2, instead it we mult ADC val on 2

-- and have mult on 2 phase val

-- to convert unsigned 0..2n to -n to n, 14 bit adc min max

-- widen on '0' and '1' it's equal adding of '100000000000000'

-- in out, we need divide raw_phase on amplitude, and don't need

-- multiply it on 2 , because raw_phase already doubled

-- multiply need because (max(sin)/ampl(sin) = 0.5, we want 1)

ADC_RAW_PHASE <= ADC_IN&'0' - (('1'&ADC_MAX)+('0'&ADC_MIN));

StoreClear <= StoreClear+1;

end if;

 

if SYNC= '0' then -- set sync signal waiting state

StoreClear <= "00";

PHASE_DRDY <='0';

end if;

end if;

end process;

 

end Behavioral;

 

этот пример синтезируется и симулируется, и вроде даже работает как мне хочется...

 

первый дает макс частоту ADC_DRDY 130 МГц, второй 127.

и во втором тратится на одну лук ап таблицу больше. Это все сравнительные характеристики а не абсолютные естественно...

 

 

ВАШ ОТВЕТ МЕНЯ ОЗАДАЧИЛ

я как раз думал что если ввести один общий синхронизирующий сигнал в моем случае ADC_DRDY, то наоборот схема будет наиболее надежной.

 

я хотел чтобы каждый раз как появятся данные на АЦП, чему свидетельствует восходящий фронт ADC_DRDY

у меня это значение защелкивалось на ADC_VALUE, и сохранялось в регистрах MIN, MAX, если меньше минимума или больше максимума...

каждый раз когда генерится сигнал SYNC (этот сигнал генерится когда аналоговый сигнал переходит ноль из минуса в плюс. запускается автомат из 4 состояний. Причем синхронизированный по ADC_DRDY, что гарантирует как я думаю отсуствие гонок сигналов...

 

состояние 0 сбор данных, MIN MAX, ожидание сигнала SYNC, если SYNC -> состояние 1

состояние 1 расчет амплитуды из MIN,MAX, и фазы по последнему ADC_IN... -> состояние 2

состояние 2 обнуление MIN, MAX, выставление наличие данных фазы и амлитуды -> состояние 3

состояние 3 сбор новых данных, MIN MAX, ожидание сброса

 

как SYNC уйдет в 0,

автомат переходит в состояние 0

сбрасывает сигнал наличия данных...

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если вы работаете с числами и операциями над ними, то signed и unsigned имеют для Вас смысл. Если нет, то Вам будет достаточно std_logic_vector.

 

В вашем первом примере Вы ошибочно включили numeric_std, тогда как он не может быть включен вместе с std_logic_*. Т.е. если вы поставите только

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;

то все будет нормально моделироваться.

 

ВАШ ОТВЕТ МЕНЯ ОЗАДАЧИЛ

я как раз думал что если ввести один общий синхронизирующий сигнал в моем случае ADC_DRDY, то наоборот схема будет наиболее надежной.

 

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

 

У Вас точно это единственный сигнал синхронизации в проекте?

 

я хотел чтобы каждый раз как появятся данные на АЦП, чему свидетельствует восходящий фронт ADC_DRDY

у меня это значение защелкивалось на ADC_VALUE, и сохранялось в регистрах MIN, MAX, если меньше минимума или больше максимума...

каждый раз когда генерится сигнал SYNC (этот сигнал генерится когда аналоговый сигнал переходит ноль из минуса в плюс. запускается автомат из 4 состояний. Причем синхронизированный по ADC_DRDY, что гарантирует как я думаю отсуствие гонок сигналов...

 

Проблема может возникнуть в том месте, где будут использоваться полученные на выходе Вашей схемы результаты. Если они будут защелкиваться по иному тактовому сигналу, то это может привести к ошибкам по причине возможной метастабильности триггеров входных регистров.

состояние 0 сбор данных, MIN MAX, ожидание сигнала SYNC, если SYNC -> состояние 1

состояние 1 расчет амплитуды из MIN,MAX, и фазы по последнему ADC_IN... -> состояние 2

состояние 2 обнуление MIN, MAX, выставление наличие данных фазы и амлитуды -> состояние 3

состояние 3 сбор новых данных, MIN MAX, ожидание сброса

 

как SYNC уйдет в 0,

автомат переходит в состояние 0

сбрасывает сигнал наличия данных...

 

Это-то понятно. :)

 

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

 

Только если один тактовый сигнал. Если несколько или есть основной периодический тактовый сигнал, то лучше использовать другую логику работу (по основному тактовому сигналу).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

библиотеку нумерик я добавил уже от отчаяния...

 

этот проект у меня не симулится хоть умри....

 

и как вы говорите тоже не симулится... может надо среду менять.. у меня ксалинский проек навигатор 7.1.04i вроде бы из последних...

 

 

а проблемы наверное правда могут быть. Половину данных я защелкну по специальному сигналу PHASE_DRDY, а вот про ADC_VAL я что-то забыл... но это моно поправить, и для него тоже вывести ADC_DRDY… хотя это уже перебор…

 

Другими словами имеет смысл ввести в схему глобальный сигнал синхронизации...

 

что-то типа

 

process (CLK, ADC_DRDY)

begin

if CLK='1' and CLK'event then

if ADC_DRDY ='1' then

ADC_OUT <=ADC_IN;

end if;

end if;

end process

 

 

кстати хотел узнать, можно ли делать так

 

process (CLK, ADC_DRDY)

begin

if CLK='1' and CLK'event then

if ADC_DRDY'event then -- имея ввиду первый подъем ADC_DRDY после фронта CLK?

ADC_OUT <=ADC_IN;

end if;

end if;

end process;

 

или это надо реализовывать через флаг? чтобы не считывать данные каждый клок, а только один раз..

 

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

Изменено пользователем Golikov A.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а вот я подумал...

 

если я поставлю D триггер, на данные ему подам ADC_DRDY а на клок - основной клок схемы, получится что у меня все заcсинхронизируется на основной клок схемы... или не получится?

 

signal a:std_logic_vector(3 downto 0) :="0000";

signal b:std_logic_vector(3 downto 0) :="0000";

 

process(ADC_DRDY_D_TRIG_OUT)

begin

if ADC_DRDY_D_TRIG_OUT ='1' and ADC_DRDY_D_TRIG_OUT'event then

a<= ADC_IN;

end if;

end process

 

process(GLB_CLK)

begin

if GLB_CLK='1' and GLB_CLK'event then

b<= a;

end if;

end process

 

по идее рассинхрона не будет, так?...

то есть нет шанса что в b защелкнется переходной процесс из a?

 

И кстати вот еще что. Если последовательно соединить несколько D триггеров, с общим клоком, то на каждый фронт будет происходит сдвиг данных как в сдвиговом регистре? А не может так получится, что в какой-то из защелок будет сохранен переходной процесс с прошлой? Как-то раньше этот вопрос у меня не возникал, а теперь я не понимаю как это работает:)...

Изменено пользователем Golikov A.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по идее рассинхрона не будет, так?...

то есть нет шанса что в b защелкнется переходной процесс из a?

Насколько я понял частоты похожы, но немного оличаются?

если да, то b может защелкнутся в переходной процесс a!

и ещё, проще использовать конструкцию:

If rising_edge(CLK) Then

вместо

If CLK = '1' and CLK'event Then

 

а если нужен спад, то falling_edge(CLK)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

не ну не настолько близко...

 

67 и 100 МГц.

 

 

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

 

Единственное волнует переходной процесс открывающейся latch, но можно открывать ее по падающему фронту и тогда к восходящему все будет ок! Или так не делают?

Изменено пользователем Golikov A.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...