|
|
  |
LVDS DDR данные из АЦП в ПЛИС |
|
|
|
Jun 30 2014, 18:43
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Что не так делаю? Почему вместо синуса вижу корявый меандр? Не реагирует на изменение амплитуды сигнала. С какой стороны младшие биты? (c D0 или с D6) Тактирую ПЛИС по CLK_OUT от АЦП АЦП ADS6145 http://www.ti.com/lit/ds/symlink/ads6145.pdfСпасибо. Код component IBUFGDS -- -- synopsys translate_off generic( DIFF_TERM : boolean := FALSE); -- -- synopsys translate_on port ( I : in std_logic; IB : in std_logic; O : out std_logic); end component; attribute IOSTANDARD of IBUFGDS : component is "DEFAULT"; attribute DIFF_TERM of IBUFGDS : component is "FALSE"; attribute BOX_TYPE of IBUFGDS : component is "BLACK_BOX"; component IBUFDS -- synopsys translate_off generic( DIFF_TERM : boolean := FALSE); -- synopsys translate_on port ( I : in std_logic; IB : in std_logic; O : out std_logic); end component; attribute IOSTANDARD of IBUFDS : component is "DEFAULT"; attribute DIFF_TERM of IBUFDS : component is "FALSE"; attribute BOX_TYPE of IBUFDS : component is "BLACK_BOX";
begin
data_out <= out13 & out12 & out11 & out10 & out9 & out8 & out7 & out6 & out5 & out4 & out3 & out2 & out1 & out0 ;
clk_out <= USER_CLK;
IBUFGDS_1 : IBUFGDS port map (I=>SMA_DIFF_CLK_IN_P, IB=>SMA_DIFF_CLK_IN_N, O=>USER_CLK);
IBUFDS_1 : IBUFDS port map (I=>HDR2_28_SM_11_P, IB=>HDR2_26_SM_11_N, O=>DDR_1); IBUFDS_2 : IBUFDS port map (I=>HDR2_32_DIFF_3_P, IB=>HDR2_30_DIFF_3_N, O=>DDR_2); ....
process(USER_CLK) begin
if (USER_CLK = '1') then out0 <= DDR_0; out2 <= DDR_1; out4 <= DDR_2; out6 <= DDR_3; out8 <= DDR_4; out10<= DDR_5; out12<= DDR_6;
elsif (USER_CLK = '0') then out1 <= DDR_0; out3 <= DDR_1; out5 <= DDR_2; out7 <= DDR_3; out9 <= DDR_4; out11 <= DDR_5; out13 <= DDR_6;
end if;
end process;
|
|
|
|
|
Jun 30 2014, 19:54
|
Знающий
   
Группа: Свой
Сообщений: 614
Регистрация: 12-06-09
Из: рядом с Москвой
Пользователь №: 50 219

|
Цитата(Ar-han @ Jun 30 2014, 22:43)  Что не так делаю? Почему вместо синуса вижу корявый меандр? Не реагирует на изменение амплитуды сигнала. С какой стороны младшие биты? (c D0 или с D6) Тактирую ПЛИС по CLK_OUT от АЦП
АЦП ADS6145... ПЛИС и инструментарий не указан - ХЗ чем вы там синтезите, но по своему опыту скажу: с такими аппаратными фичами Xilinx как DDR, SERDES, PLL, IODELAY и др. лучше ИМХО обращаться путём наглого вставления примитивов в HDL, иначе ISE будет тупить очень сильно (он конечно тупит и с примитивами - но значительно меньше). Дифференциальные буферы не поленились вставить в ввиде примитивов - вот и IDDR нужно также. Там у IDDR, есть помниться несколько режимов работы, задающихся генериками. А что вам тут ваш синтезатор сделал из вашего кода ХЗ? И вставил ли он вообще IDDR? И если вставил, то с какими настройками? И ещё режет глаз: generic( DIFF_TERM : boolean := FALSE); это так и задумано? место на плате много и снаружи не поленились резюки по 100Ом запаять? P.S. и ещё не ясно, что с клоком из АЦП - на какой тип ноги он заведен (GCLK, MRCC, SRCC или CLOCK_DEDICATED_ROUTE = false) ? P.S.2 констреинты есть какие-нибудь?
|
|
|
|
|
Jul 1 2014, 05:30
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(VladimirB @ Jun 30 2014, 23:54)  ПЛИС и инструментарий не указан - ХЗ чем вы там синтезите,
но по своему опыту скажу: с такими аппаратными фичами Xilinx как DDR, SERDES, PLL, IODELAY и др. лучше ИМХО обращаться путём наглого вставления примитивов в HDL, иначе ISE будет тупить очень сильно (он конечно тупит и с примитивами - но значительно меньше). Дифференциальные буферы не поленились вставить в ввиде примитивов - вот и IDDR нужно также.
Там у IDDR, есть помниться несколько режимов работы, задающихся генериками. А что вам тут ваш синтезатор сделал из вашего кода ХЗ? И вставил ли он вообще IDDR? И если вставил, то с какими настройками?
И ещё режет глаз: generic( DIFF_TERM : boolean := FALSE); это так и задумано? место на плате много и снаружи не поленились резюки по 100Ом запаять?
P.S. и ещё не ясно, что с клоком из АЦП - на какой тип ноги он заведен (GCLK, MRCC, SRCC или CLOCK_DEDICATED_ROUTE = false) ? P.S.2 констреинты есть какие-нибудь? Xilinx ML507, virtex5, ise14. С диф. сигналами работаю впервые, нарисовал диф. приёмники в схематике, сделал view hdl, и исправил расширение файла. CLK_OUT заведен на GCLK: Код SMA_DIFF_CLK_IN_N bank 3 IO_L6P_GC_3 LOC= "H14" SMA_DIFF_CLK_IN_N bank 3 IO_L6N_GC_3 LOC= "H15" Кстати, интересно, можно ли его завести на Clock Capable I/Os?: Предусмотрел возможность на плате, чтобы не тянуть clock через sma разъёмы. Код IO_L9N_CC_SM0N_13 bank13 LOC=AE34 IO_L9P_CC_SM0P_13 bank13 LOC=AF34 Прошу прощения, не совсем понятна фраза: Цитата Дифференциальные буферы вставить в виде примитивов? Про IDDR впервые слышу, спасибо. Если можно в двух словах зачем он? С ходу не разобрался. В ucf файле у меня так: (может нужно что добавить, чтоб было понятно желание использовать ноги, как диф. пары?) Код NET SMA_DIFF_CLK_IN_N LOC="H15"; # Bank 3, Vcco=2.5V, No DCI NET SMA_DIFF_CLK_IN_P LOC="H14"; # Bank 3, Vcco=2.5V, No DCI
////////////////////////////////// //D0_D1 NET HDR2_22_SM_10_N LOC="T34"; # Bank 11, Vcco=2.5V or 3.3V user selectable by J20 (SYSMON External Input: VAUXN[10]) J4-22 NET HDR2_24_SM_10_P LOC="U33"; # Bank 11, Vcco=2.5V or 3.3V user selectable by J20 (SYSMON External Input: VAUXP[10]) J4-24
//D2_D3 NET HDR2_26_SM_11_N LOC="U31"; # Bank 11, Vcco=2.5V or 3.3V user selectable by J20 (SYSMON External Input: VAUXN[9]) J4-26 NET HDR2_28_SM_11_P LOC="U32"; # Bank 11, Vcco=2.5V or 3.3V user selectable by J20 (SYSMON External Input: VAUXP[9]) J4-28
//D4_D5 NET HDR2_30_DIFF_3_N LOC="V33"; # Bank 13, Vcco=2.5V or 3.3V user selectable by J20 (SYSMON External Input: VAUXN[8]) J4-30 NET HDR2_32_DIFF_3_P LOC="V32"; # Bank 13, Vcco=2.5V or 3.3V user selectable by J20 (SYSMON External Input: VAUXP[8]) J4-32 ---------- остальные ноги типа: Код HDR2_22_SM_10_N IO_L18N_SM10N_11 HDR2_24_SM_10_P IO_L18P_SM10P_11 -- Про терминирование большое спасибо, внешних резюков нет, недочитал просто. Думал, что оно жестко привязано внутри к ноге, а что сгенерировал конвертор из схематика не разобрался.
|
|
|
|
|
Jul 1 2014, 10:00
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(Ar-han @ Jul 1 2014, 09:30)  Xilinx ML507, virtex5, ise14. С диф. сигналами работаю впервые, нарисовал диф. приёмники в схематике, сделал view hdl, и исправил расширение файла. CLK_OUT заведен на GCLK: Код NET SMA_DIFF_CLK_IN_N LOC="H15"; NET SMA_DIFF_CLK_IN_P LOC="H14";
//D0_D1 NET HDR2_22_SM_10_N LOC="T34"; NET HDR2_24_SM_10_P LOC="U33"; ... Похоже, я забыл указать в констрейнах что это LVDS сигнал: Код NET SMA_DIFF_CLK_IN_N LOC="H15"|IOSTANDARD = LVDS_25; NET SMA_DIFF_CLK_IN_P LOC="H14"|IOSTANDARD = LVDS_25;
Сообщение отредактировал Ar-han - Jul 1 2014, 10:03
|
|
|
|
|
Jul 1 2014, 13:08
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(Ar-han @ Jun 30 2014, 22:43)  Я, кажется, понял, это тут совсем не нужно: Код process(USER_CLK) begin
if (USER_CLK = '1') then out0 <= DDR_0; out2 <= DDR_1; out4 <= DDR_2; out6 <= DDR_3; out8 <= DDR_4; out10<= DDR_5; out12<= DDR_6;
elsif (USER_CLK = '0') then out1 <= DDR_0; out3 <= DDR_1; out5 <= DDR_2; out7 <= DDR_3; out9 <= DDR_4; out11 <= DDR_5; out13 <= DDR_6;
end if;
end process; , а нужны IDDR модули после диф. приёмников)) Код IDDR_0 : IDDR port map (C=>USER_CLK, CE=>VPP, D=>DDR_0, R=>GRND, S=>GRND, Q1=>out0, Q2=>out1);
|
|
|
|
|
Jul 1 2014, 13:59
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 1 2014, 17:20)  Долго же Вы понимали  И всё же проблема актуальна )) Так выглядит синус f = 1 мгц, амплитудой 0.9 Вольт
|
|
|
|
|
Jul 1 2014, 14:19
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 1 2014, 18:11)  Биты у Вас попутаны. На какой частоте АЦП работает? АЦП на 125 МГц, ломаю голову, где напутал биты. Откуда ярко выраженные ступеньки в сигнале? Вот синус 1 мгц, с амплитудой 100 - 200 мВ.
|
|
|
|
|
Jul 1 2014, 14:21
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(Ar-han @ Jun 30 2014, 22:43)  Что не так делаю? Почему вместо синуса вижу корявый меандр? Не реагирует на изменение амплитуды сигнала. А симулировать проект пробовали? Скажем записать в файл данные от синусоиды и сделать имитатор АЦП. И из файла выдать синусоиду... А уже потом говорить, что данные кривые...
--------------------
www.iosifk.narod.ru
|
|
|
|
|
Jul 1 2014, 14:26
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(iosifk @ Jul 1 2014, 18:21)  А симулировать проект пробовали? Скажем записать в файл данные от синусоиды и сделать имитатор АЦП. И из файла выдать синусоиду...
А уже потом говорить, что данные кривые... Я вместо диф. приёмников пилу подсовывал, вчера вроде бы нормальная пила была.
|
|
|
|
|
Jul 1 2014, 14:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Могу предложить, но для этого Вам понадобиться наладить SPI (если его пока нет), перевести АЦП в режим синхронизации, т.е. для регистра 0x0A записать в TEST PATTERNS режим Custom pattern (101) и в качестве Custom Pattern записать, например, 14'b10101010101010. На приёмной стороне принимаете Вашу тестовую посылку, смотрите, какие биты попутаны. Быстрее всёго они будут приниматься в неправильном порядке, но этот порядок будет сохраняться, тогда меняете местами в соответствии с вашей эталонной последовательностью и можно работать. Если порядок следования бит меняется от запуска к запуску (если тайминги плохо прописаны, то такое и будет), тогда делаете устройство которое при включении будет производить синхронизацию и подключать принимаемые биты в правильном порядке. Цитата(Ar-han @ Jul 1 2014, 17:19)  АЦП на 125 МГц, ломаю голову, где напутал биты. Что делать уже написал, но попробуйте, для начала, и частоту понизить, чтоб хотя бы результат правильный получить, а потом будете поднимать. Цитата(iosifk @ Jul 1 2014, 17:21)  А уже потом говорить, что данные кривые... Данные не кривые, просто принимаются неправильно, нужно поменять порядок следования бит и всё будет в порядке.
|
|
|
|
|
Jul 1 2014, 14:39
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 1 2014, 18:31)  Могу предложить, но для этого Вам понадобиться наладить SPI (если его пока нет), перевести АЦП в режим синхронизации, т.е. для регистра 0x0A записать в TEST PATTERNS режим Custom pattern (101) и в качестве Custom Pattern записать, например, 14'b10101010101010. На приёмной стороне принимаете Вашу тестовую посылку, смотрите, какие биты попутаны. Быстрее всёго они будут приниматься в неправильном порядке, но этот порядок будет сохраняться, тогда меняете местами в соответствии с вашей эталонной последовательностью и можно работать. Если порядок следования бит меняется от запуска к запуску (если тайминги плохо прописаны, то такое и будет), тогда делаете устройство которое при включении будет производить синхронизацию и подключать принимаемые биты в правильном порядке.
Что делать уже написал, но попробуйте, для начала, и частоту понизить, чтоб хотя бы результат правильный получить, а потом будете поднимать. Спасибо! До SPI еще не добрался, и с моими темпами, похоже, не скоро )) Генератор впаян, но есть возможность тактировать из вне. Совет полезный, нужно будет попробовать. Жаль с ходу не ясно в чём баг. Тут-то я правильно описал атрибут IDDR "OPPOSITE_EDGE"? Код component IDDR -- synopsys translate_off generic( INIT_Q1 : bit := '0'; INIT_Q2 : bit := '0'; DDR_CLK_EDGE : string := "OPPOSITE_EDGE"; SRTYPE : string := "SYNC"); -- synopsys translate_on port ( D : in std_logic; CE : in std_logic; C : in std_logic; S : in std_logic; R : in std_logic; Q1 : out std_logic; Q2 : out std_logic); end component; Без входного сигнала:
Сообщение отредактировал Ar-han - Jul 1 2014, 14:45
|
|
|
|
|
Jul 1 2014, 14:53
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 1 2014, 17:39)  Жаль с ходу не ясно в чём баг. Баг в том, о чём я писал. На линиях попутан порядок следования бит, вместо D0 принимается D1 и наоборот, это может быть и на других линиях D2-D3, D4-D5, и т.д. На кокой-то из линий данные могут приниматься и правильно. Для устранения этого явления в АЦП и предусмотрена возможность выдачи на выход эталонной последовательности, по которой можно поймать правильный порядок следования бит при старте и продолжать работу с правильными данными. По-хорошему, необходимо устройство, которое будет производить синхронизацию. Советую запустить простейший SPI, это даст возможность увидеть, где и что перепутано. Цитата(Golikov A. @ Jul 1 2014, 17:47)  А у вас не с АЦП проблемы? В ветке армов обсуждалось, что если АЦПешене некоторых моделей не хватает времени на выборку оно начинает ступеньки рисовать и выбросы похожие на ваши... Позвольте спросить, Вы работали с АЦП с похожим интерфейсом? Если нет, то не вводите в заблуждение.
|
|
|
|
|
Jul 1 2014, 17:53
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 1 2014, 18:53)  Баг в том, о чём я писал. На линиях попутан порядок следования бит Попутан, попутан, да еще как! Половина пар не на своих местах были, половина в воздухе висела. Прошу прощения, всех ввел в заблуждение своей невнимательностью. Всё исправил. Завтра буду тестировать. Есть еще вопрос по теме. Собираю пакет данных и кидаю в двупортовую брам. А со стороны процессора PPC передаю указатель эту на область памяти функции, которая отсылает udp пакеты через lwip. Как правильно расставить флаги заполнения области памяти? Как оценить, сколько тактов требуется процессору, чтобы получив указатель на эту область памяти, скажем 40 кБайт, прочитать её? Каким размером лучше разбить эту память по UDP пакетам? Пока что тренировался с 1 кБайтом, проблем не было, всё влезает в один UDP пакет. Может лучше на tcp/ip перейти? Пока что работал с 100 мбитным каналом, хочу попробовать гигабитный. С чего начать? Весь поток данных мне не нужен, только пакеты заданной длины по синхроимпульсу. Спасибо.
|
|
|
|
|
Jul 1 2014, 20:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 1 2014, 19:22)  Ну я так категорично по виду данных не смог определить ошибку, как вы... но от интерфейса АЦП та ошибка про которую я говорю не зависит, это чисто конструктивные ограничения... но я не настаиваю, просто как версия, которую можно проверить... Это определено не категорично по виду данных, просто есть опыт работы с подобными АЦП (ADS6445, ADS5263), отличие только в том, что в моём случае у одной 8-бит последовательно передаются по 1-ой линии, у другой - 4 бита, у данного экземпляра 2 бита на одной линии. Я так же не настаиваю, просто из возможных ошибок наиболее вероятна та, которую озвучил. Нормально настраивать АЦП без SPI - никак. Но, возможно, это у Вас отладочная плата от TI? Если так тогда там должны быть джамперы, которые и задают режим работы АЦП (PARALLEL INTERFACE CONTROL), смотрите даташит. Тогда Вы можете попробовать Цитата(Timmy @ Jul 1 2014, 19:08)  перевести АЦП в режим SDR CMOS - так захватывать данные будет гораздо проще. , но интерфейс DDR LVDS более помехоустойчив. Цитата(Ar-han @ Jul 1 2014, 20:53)  Есть еще вопрос по теме. Собираю пакет данных и кидаю в двупортовую брам. А со стороны процессора PPC передаю указатель эту на область памяти функции, которая отсылает udp пакеты через lwip. Весь поток данных мне не нужен, только пакеты заданной длины по синхроимпульсу. А какой пакет планируется и с какой частотой идут синхроимпульсы? Цитата(Ar-han @ Jul 1 2014, 20:53)  Каким размером лучше разбить эту память по UDP пакетам? Пока что тренировался с 1 кБайтом, проблем не было, всё влезает в один UDP пакет. В UDP пакет влезает почти 64 кБ (нужно только размер шапки отнять) - это максимальная длинна пакета, которую можете посылать. LwIP поддерживает фрагментацию на уровне IP, создаёте буфер необходимой длинны, при отправке UDP указываете длинну данных, LwIP сама определит, за сколько фрагментов послать Ваш пакет. Цитата(Ar-han @ Jul 1 2014, 20:53)  Может лучше на tcp/ip перейти? Для отправки данных АЦП UDP будет вполне достаточно, всегда используем в этих целях именно UDP. Цитата(Ar-han @ Jul 1 2014, 17:39)  До SPI еще не добрался, и с моими темпами, похоже, не скоро )) LwIP прикрутили, а SPI - нет?
|
|
|
|
|
Jul 2 2014, 07:37
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 2 2014, 00:26)  Но, возможно, это у Вас отладочная плата от TI? Если так тогда там должны быть джамперы, которые и задают режим работы АЦП (PARALLEL INTERFACE CONTROL), смотрите даташит. Плату сам рисовал, переключение в параллельную шину кмоп есть, еще не пробовал.
Цитата А какой пакет планируется и с какой частотой идут синхроимпульсы? Буду добиваться максимально возможной частоты синхроимпульсов, хотелось бы чтобы 20-40 МБайт в секунду через UDP пролезало, но пока мучаю 100 Мбит канал. Цитата LwIP поддерживает фрагментацию на уровне IP Очень интересно, спасибо. С LWIP поверхностно пока что разобрался, переделал программу из эхо-демо, подозреваю, что там много лишнего, например, не понимаю, почему без этой строчки программа не работает: Код xemacif_input(netif); Тут тоже не совсем пока ясно, с выделением памяти, что к чему Код PBUF_RAW или PBUF_TRANSPORT PBUF_RAM или PBUF_POOL остановился на этом: pbuf_to_be_sent = pbuf_alloc( PBUF_RAW, STR_SIZE, PBUF_RAM); Цитата LwIP прикрутили, а SPI - нет?  C spi конечно возился, общался spi-ацп/цап на спартане, но это было давно и как-то я там всё через одно место реализовал, что и вспоминать стыдно, сколько это времени заняло ) Исправил пины диф. шины, картинка уже проясняется.
|
|
|
|
|
Jul 2 2014, 09:44
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 2 2014, 10:37)  Плату сам рисовал, переключение в параллельную шину кмоп есть, еще не пробовал. Тогда пробуйте, проблема должна будет решиться. Меняем один джампер и правим немного приёмник на ПЛИС, под приём параллельного кода. Цитата(Ar-han @ Jul 2 2014, 10:37)  Буду добиваться максимально возможной частоты синхроимпульсов, хотелось бы чтобы 20-40 МБайт в секунду через UDP пролезало, но пока мучаю 100 Мбит канал. Для получения максимального потока, нужно было бы реализовывать отправку UDP в железе на ПЛИС. Цитата(Ar-han @ Jul 2 2014, 10:37)  Очень интересно, спасибо. С LWIP поверхностно пока что разобрался, переделал программу из эхо-демо, подозреваю, что там много лишнего, например, не понимаю, почему без этой строчки программа не работает: Вот я тоже пока поверхностно, пример под отладочную плату переделать удалось и потестить какую-то работоспособность LwIP, а вот под свою плату, пока туговато.
|
|
|
|
|
Jul 2 2014, 10:28
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 2 2014, 10:37)  Исправил пины диф. шины, картинка уже проясняется. Судя по картинке, АЦП выдаёт данные в формате 2s complement format (т.е. знаковый). На график же данные выводятся как беззнаковые, вот и получается - положительные числа отображаются правильно, отрицательные - НЕТ. Либо поменяйте джампер (возможность такая, как понял, есть), чтоб АЦП выдавало данные в формате Straight binary (беззнаковом), либо правильно отображайте на графике. Но проблема с битами, смотрю, осталась, всё же попутаны они у Вас. Переводите АЦП, как и советовали, в режим SDR CMOS и всё будет гуд.
|
|
|
|
|
Jul 2 2014, 12:39
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 2 2014, 14:28)  Судя по картинке, АЦП выдаёт данные в формате 2s complement format (т.е. знаковый). На график же данные выводятся как беззнаковые, вот и получается - положительные числа отображаются правильно, отрицательные - НЕТ. Да, я тоже так решил, искал как конвертировать дополнение до 2 в беззнаковые, и не придумал ничего лучше, как проинвертировать старший бит в данных. Сигнал стал похож на синус, джампер переставил в режим: Straight binary format and DDR LVDS interface И получил такую картинку.
Если джампер переставить в режим: 2s Complement format and DDR LVDS interface картинка такая же, но больше каких-то ошибок ????
Снова что-то я напутал, не пойму почему сигнал режется на 7 кусков в разной фазе. Причём если подобрать частоту сигнала, можно получить целый синус без разрезов. Я в двухпортовую память с ацп записываю кусок 512 точек, каждые 8 ns, получается 4 mks сигнала. Дальше у меня пауза 200 ms, и всё повторяется. Вторым портом память сидит на PLB шине, и процессору передаю указатель на эту память, примерно 10 раз в секунду, и отправляю пакеты на комп. Для режима 2s Complement format and DDR LVDS interface джампер нужно на землю замкнуть, с этим проблем нет. А для режима Straight binary format and DDR LVDS interface джампер нужно замкнуть на (3/8 VDD) = 1.24 В А я замыкаю на (1/3 VDD) = 1.1 В Интересно, это может влиять на ошибки, которые выглядят как помехи? Цитата(Ar-han @ Jul 2 2014, 16:04)  И получил такую картинку. Снова нашел ошибку в порядке пинов. Младшая диф. пара была перепутана со старшей. ))
|
|
|
|
|
Jul 2 2014, 15:55
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 2 2014, 15:39)  Я в двухпортовую память с ацп записываю кусок 512 точек, каждые 8 ns, получается 4 mks сигнала. Дальше у меня пауза 200 ms, и всё повторяется. Вторым портом память сидит на PLB шине, и процессору передаю указатель на эту память, примерно 10 раз в секунду, и отправляю пакеты на комп. Чтение и запись у Вас по времени не совпадают? Обычно делаю двухбуферную память в таких случаях, когда один буфер пишется - второй читается, потом наоборот. Цитата(Ar-han @ Jul 2 2014, 15:39)  Для режима 2s Complement format and DDR LVDS interface джампер нужно на землю замкнуть, с этим проблем нет.
А для режима Straight binary format and DDR LVDS interface джампер нужно замкнуть на (3/8 VDD) = 1.24 В А я замыкаю на (1/3 VDD) = 1.1 В Интересно, это может влиять на ошибки, которые выглядят как помехи? Используйте то, что должно на 100% работать правильно, выбирайте 2s Complement format, а далее учитывайте это при отрисовке графика.
|
|
|
|
|
Jul 2 2014, 18:52
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 2 2014, 19:55)  Чтение и запись у Вас по времени не совпадают? Обычно делаю двухбуферную память в таких случаях, когда один буфер пишется - второй читается, потом наоборот. Да, процессор на своей частоте работает, флагов заполнения памяти пока никаких не успел реализовать. Поэтому сделал большую паузу между циклами записи в эту память. Спасибо за идею, то есть нужно две области памяти и два флага заполнения, беру на вооружение. А как лучше флаги процессору передавать? Не через GPIO же ведь? Так же какой-нибудь регистр этой двухпортовой памяти можно использовать под флаги? Подсунул снова на вход пилу вместо диф приемников, но теперь уже амплитуду в 14 бит, вместо 8-и, и вижу, не правильно данные в память пишутся, упаковываются в регисты... Буду искать баги... )
|
|
|
|
|
Jul 2 2014, 20:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 2 2014, 21:52)  Спасибо за идею, то есть нужно две области памяти и два флага заполнения, беру на вооружение. А как лучше флаги процессору передавать? Не через GPIO же ведь? Так же какой-нибудь регистр этой двухпортовой памяти можно использовать под флаги? Да нет, немного не так. Ваш синхроимпульс - сигнал прерывания для процессора, по которому он начинает вычитывать память (длину данных уже сами выбираете), с другой стороны по окончании синхроимпульса поднимается сигнал разрешения записи данных в память и держится необходимое для записи выборки число тактов. По фронту сигнала разрешения записи формируете сигнал выбора буфера памяти, который в данный момент пишется/читается, данный сигнал инвертируется каждый период и тем самым можете выбирать на запись/чтение "верхний" или "нижний" буфер памяти (вход разрешения записи у второго буфера инверсный). Выходы буферов заводите на мультиплексор, который управляется сигналом выбора буфера памяти. Т.о. получаете один буфер в данном периоде доступен для записи, второй для чтения, со стороны процессора адреса остаются одни и те же, но мультиплексором к шине данных процессора подкючается нужный буфер памяти. Есть готовый кусок кода, можете его взять в качестве примера: CODE module double_buffering_ram ( // Input port input wire wrclock, input wire wren, input wire [31:0] data_in, // Output Port input wire rdclock, input wire rden, input wire rdclocken, input wire [9:0] rdaddress, output wire [31:0] qram );
wire [31:0] qram0, qram1; reg [9:0] wraddr = 10'h0; reg wrclken = 1'b0; always@(posedge wrclock)begin if(wren) wraddr <= wraddr + 10'h1; else wraddr <= 10'h0; end
always@(negedge wren)begin //always@(posedge wren)begin wrclken <= (wrclken ^ 1'b1); end ram1024x32P2 RAM_BUF0 ( .wraddress(wraddr), .wrclock(wrclock), .wrclocken(wrclken), .wren(wren), .data(data_in), .rdaddress(rdaddress), .rden(rden), .rdclock(rdclock), .rdclocken(rdclocken), .q(qram0) ); ram1024x32P2 RAM_BUF1 ( .wraddress(wraddr), .wrclock(wrclock), .wrclocken(~wrclken), .wren(wren), .data(data_in), .rdaddress(rdaddress), .rden(rden), .rdclock(rdclock), .rdclocken(rdclocken), .q(qram1) ); mux2x32 RAM_BUFMUX ( .data0x(qram0), .data1x(qram1), .sel(wrclken), .result(qram) ); endmodule
Цитата(Ar-han @ Jul 2 2014, 21:52)  Не через GPIO же ведь? Именно через GPIO, разрешаете внешнее прерывание от GPIO по фронту (спаду) синхроимпульса или фронту сигнала разрешения записи данных (валидной выборки).
|
|
|
|
|
Jul 3 2014, 04:43
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 2 2014, 16:50)  Если хотите поменять знак, то необходимо каждый бит числа проинвертировать и прибавить к результату 1. Но таким образом Вы поменяете знак и для положительных чисел. Дополнительный код (дополнение до двух) Я посмотрел на эту таблицу, и решил, что для перевода из доп. кода в беззнаковый достаточно проинвертировать старший бит числа, дополнительного кода. Хотя это уже не актуально, вроде бы разобрался со своим джампером, при правильном порядке диф. пар переключение режимов работает.)
Цитата(doom13 @ Jul 3 2014, 00:11)  Ваш синхроимпульс - сигнал прерывания для процессора, по которому он начинает вычитывать память (длину данных уже сами выбираете), с другой стороны по окончании синхроимпульса поднимается сигнал разрешения записи данных в память и держится необходимое для записи выборки число тактов. По фронту сигнала разрешения записи формируете сигнал выбора буфера памяти, который в данный момент пишется/читается, данный сигнал инвертируется каждый период и тем самым можете выбирать на запись/чтение "верхний" или "нижний" буфер памяти (вход разрешения записи у второго буфера инверсный). Выходы буферов заводите на мультиплексор, который управляется сигналом выбора буфера памяти. Т.о. получаете один буфер в данном периоде доступен для записи, второй для чтения, со стороны процессора адреса остаются одни и те же, но мультиплексором к шине данных процессора подкючается нужный буфер памяти. Есть готовый кусок кода, можете его взять в качестве примера: Большое спасибо! Буду разбираться.
|
|
|
|
|
Jul 3 2014, 06:46
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
дополнительный код - старший бит определяет знак. Если он 1, то для получения модуля надо инвертировать число и прибавить 1, если он 0 то ничего делать не надо.
Но это нужно для получения модуля, для вывода синуса это все делать не надо. При выводе графика у вас нет координат -N, Вам надо преобразовать ваш сигнал из диапазона [-(N+1) : N] в диапазон [0 : 2N+1], как не сложно видеть это делается прибавлением (N+1) к каждому значению. Прелесть дополнительного двоичного кода в том что он прекрасно складывается и сам учитывает знак.
Ко всем значениям прибавляете N+1, и на графике в 0 у вас будет минимум -(N+1), в точке (N+1) у вас будет 0, а в точке 2N+1 у вас будет максимум N.
Хотя это и базовые знания программиста...
По передачи данных в память и вычитыванием их из памяти процом. Обращаю ваше внимание что 2 портовая память все же имеет коллизии, и всегда надо следить что вы не пишите и не читаете в одну область памяти. С другой стороны есть железные элементы FIFO, где с одной стороны пишет ваша АЦП, а с другой стороны читает ПРОЦ. Элементы FIFO как раз и созданы для сопряжения и выравнивания частоты чтения и записи. Эти элементы есть как стандартные IP корки на внутренней памяти, но могут быть созданы и ручками на внешней памяти, с них выходит единый сигнал что в FIFO есть данные, при этом можно настроить что сигнал появляется при достаточном пакете, чтобы вас не дергали каждый отсчет. Строго рекомендую обратить внимание на эти элементы прежде чем вы начнете делать свой автомат записи в двойной буфер. Ибо читая что вы имеете трудности с SPI, я представляю что у вас будет при работе с памятью и кучей флагов....
При этом я уверен что самым правильным решением будет АЦП - FIFO - ПРОЦ (если езернет ,будет успевать передавать даныне) или АЦП - FIFO - DMA - DDR - ПРОЦ (если все таки придется данные буфферизировать), Эти цепочки делаются из стандартных компонентов и не изобилуют кучей флагов и прерываний...
если же надо дать максимальную скорость то надо делать АЦП - FIFO - UDP (руками реализованный на железном уровне) При этом надо использовать свойства FIFO что битность входных и выходных данных может быть разная. То есть АЦП может передавать по 16 бит, а UDP забирать и отправлять по 128 или 256 бит, например (там не все сочетания возможны, но их много)
|
|
|
|
|
Jul 3 2014, 07:58
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 3 2014, 09:46)  Можно и fifo конечно, но предложенный вариант не отличается от варианта с fifo ни сложностью ни чемто другим, это уже кому как нравится. Не понял о каких флагах идёт речь, нет там никаких флагов, сигнал синхронизации только формируете, сигнал записи и инвертируемый каждый период сигнал выбора записываемого буфера (плюс мультиплексор выходной переключает). По фронту сигнала записи прерывание на процессор. Далее хотите ДМА подключайте, хотите просто читайте, всё тоже самое. Цитата(Golikov A. @ Jul 3 2014, 09:46)  если же надо дать максимальную скорость то надо делать АЦП - FIFO - UDP (руками реализованный на железном уровне) Максимальная скорость тут уже будет зависеть не от того, исполизуем мы fifo или буферы RAM, а от того сможет ли процессор прокачать необходимый нам поток, ну и, возможно, придётся отказаться от использования процессора и реализовать отправку UDP в железе. Цитата(Golikov A. @ Jul 3 2014, 09:46)  При этом надо использовать свойства FIFO что битность входных и выходных данных может быть разная. То есть АЦП может передавать по 16 бит, а UDP забирать и отправлять по 128 или 256 бит, например (там не все сочетания возможны, но их много) Для RAM битность входных и выходных данных также может быть разная, так что тут тоже кому как удобно. Цитата(Golikov A. @ Jul 3 2014, 09:46)  При этом я уверен что самым правильным решением будет АЦП - FIFO - ПРОЦ (если езернет ,будет успевать передавать даныне) или АЦП - FIFO - DMA - DDR - ПРОЦ (если все таки придется данные буфферизировать), Эти цепочки делаются из стандартных компонентов и не изобилуют кучей флагов и прерываний... Тут могу сказать, что два варианта имеют место быть, одинаковы по сложности реализации и скорость можно и там и там нормальную обеспечить.
|
|
|
|
|
Jul 3 2014, 19:57
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(Golikov A. @ Jul 3 2014, 10:46)  дополнительный код - старший бит определяет знак. Если он 1, то для получения модуля надо инвертировать число и прибавить 1, если он 0 то ничего делать не надо. Это, насколько я понимаю преобразование в прямой код, так же в знаковый формат, а я предложил проинвертировать старший бит числа в дополнительном коде, чтобы получить беззнаковое число из дополнительного кода. Если посмотреть на таблицу, это видно:
Цитата(Golikov A. @ Jul 3 2014, 10:46)  При этом я уверен что самым правильным решением будет АЦП - FIFO - ПРОЦ (если езернет ,будет успевать передавать даныне) или АЦП - FIFO - DMA - DDR - ПРОЦ (если все таки придется данные буфферизировать), Эти цепочки делаются из стандартных компонентов и не изобилуют кучей флагов и прерываний... АЦП - fifo - GPIO_ПРОЦ я пробовал, записывал в fifo по 1 байту, а считывал по 64 бита. Но как fifo c процессором правильно соединить? Я пока пробовал только через GPIO передавать 64 битную шину и флаг заполнения Fifo заводил на внешнее прерывание процессора. Мне показалось, что это не оптимально. Тогда решил попробовать через двухпортовую BRAM на plb шине. Вроде бы получается, но возможно, действительно возникают коллизии, когда я пишу туда и читаю одновременно. Если понизить частоту АЦП, раз в 10, то сигнал приходит нормальный, а при частоте 125 МГц, сигнал приходит порезанный на 7 кусков в разных фазах. С DMA я еще не работал, будет интересно с ним разобраться. Спасибо! Цитата(Golikov A. @ Jul 3 2014, 10:46)  Ибо читая что вы имеете трудности с SPI, я представляю что у вас будет при работе с памятью и кучей флагов.... Это я, конечно, немного утрирую, у меня просто на спартан-3 стартер ките, spi-АЦП и spi-ЦАП были привязаны одним CLK, причем данные в ЦАП нужно было пихать по фронту тактового сигнала, а с АЦП считывать по спаду или наоборот. Еще мне тогда английский труднее давался, проще было сделать методом тыка )) Но, действительно, не спорю, мне еще учиться и учиться. Спасибо за поддержку!
Сообщение отредактировал Ar-han - Jul 3 2014, 20:00
|
|
|
|
|
Jul 4 2014, 05:47
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Это, насколько я понимаю преобразование в прямой код так же в знаковый формат, а я предложил проинвертировать старший бит числа в дополнительном коде, чтобы получить беззнаковое число из дополнительного кода. неправильно понимаете... дополнительный код для положительных чисел совпадает с прямым кодом. Отличие прямого и дополнительного кода только в виде отрицательных чисел. Отрицательные числа сформированные дополнительным кодом при инверсии знакового бита выворачиваются наизнанку -1 становиться максимумом, минимум (-максимум) становиться нулем. Не уверен что это полезное преобразование. Цитата АЦП - fifo - GPIO_ПРОЦ я пробовал, записывал в fifo по 1 байту, а считывал по 64 бита. Но как fifo c процессором правильно соединить? Я пока пробовал только через GPIO передавать 64 битную шину и флаг заполнения Fifo заводил на внешнее прерывание процессора. Принципиальная ошибка! Зачем вы делаете проц в ПЛИС, если используете его как обычный внешний. Лучше тогда сразу к плис пределать снаружи проц, протестированный и не кушающий ресурсы. Прелесть проца ПЛИС в том что у него выведена наружу его шина. Вам надо сделать FIFO не native, а то которое выходом имеет подключение на шину проца. Фифо войдет в адресное пространство проца как доп периферия, как и все другие модули что вы будите делать. В этом случае вам не нужна разная ширина записи-чтения, максимум что писать по 16 а читать по 32 бита. Главное забудьте про GPIO в ПЛИСовом проце, они не очень быстрые, и главное нужны только если вам реально надо пошевелить ножкой ПЛИС. Для всего остального надо использовать ввод-вывод данных через шину проца, а для прерывания есть контроллер. Нет никакого смысла заводить сигнал на ногу, а с ноги прерывание в контроллер, с которого оно пойдет на проц. Даже обработка входных сигналов должна делаться вашим модулем, и через шину отдавать процу значение Иначе это все чесание левого уха через правое плечо...
|
|
|
|
|
Jul 4 2014, 07:50
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 4 2014, 08:47)  Главное забудьте про GPIO в ПЛИСовом проце, они не очень быстрые, и главное нужны только если вам реально надо пошевелить ножкой ПЛИС. Для всего остального надо использовать ввод-вывод данных через шину проца, а для прерывания есть контроллер. Нет никакого смысла заводить сигнал на ногу, а с ноги прерывание в контроллер, с которого оно пойдет на проц. Даже обработка входных сигналов должна делаться вашим модулем, и через шину отдавать процу значение Ну если через GPIO читать данные из FIFO или RAM, то да, решение конечно не верное, но если использовать прерывание от GPIO, как сигнал для считывания этих данных, то почему бы и нет. По прерыванию запускаете DMA, говорите что, сколько, откуда и куда положить. Цитата(Golikov A. @ Jul 4 2014, 08:47)  Принципиальная ошибка! Зачем вы делаете проц в ПЛИС, если используете его как обычный внешний. Лучше тогда сразу к плис пределать снаружи проц, протестированный и не кушающий ресурсы. Ну и кто же использует в процессоре GPIO для чтения внешней памяти (фифо). У любого проца (более-менее функционального) есть в наличии external memory interface, который и используется для этих целей. А для процессора в ПЛИС он и реолизуется возможностью вытянуть шину наружу.
|
|
|
|
|
Jul 4 2014, 08:18
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата но если использовать прерывание от GPIO, как сигнал для считывания этих данных, то почему бы и нет Потому что, как говорит мой знакомый - это долбанная матрешка получается! Сначала ваш модуль через сигнал дергает GPIO, GPIO генерит сигнал для контроллера прерывания, контроллер прерываний генерит сигнал для проца, и тот прерывается. Далее он идет в контроллер узнает что его дернуло GPIO, далее идет в GPIO узнает какая нога, дальше в ваш модуль чтобы узнать что за событие... Не слишком ли сложно? Цитата У любого проца (более-менее функционального) есть в наличии external memory interface, который и используется для этих целей далеко не у всех... и далеко не полная шина выведена в этот интерфейс, и далеко это не внутренняя шина проца, это ее некий рудемент. В случае проца внутри ПЛИС вы имеете полноценную внутреннюю шину, это гораздо более удобно и функционально.
|
|
|
|
|
Jul 4 2014, 09:19
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(Golikov A. @ Jul 4 2014, 09:47)  неправильно понимаете... дополнительный код для положительных чисел совпадает с прямым кодом. Отличие прямого и дополнительного кода только в виде отрицательных чисел. Отрицательные числа сформированные дополнительным кодом при инверсии знакового бита выворачиваются наизнанку -1 становиться максимумом, минимум (-максимум) становиться нулем. Не уверен что это полезное преобразование. Это мне понятно, но я пишу про преобразование не в прямой код, а в беззнаковый формат, в котором самое маленькое число - это 00000000, и дальше оно растет до 11111111. И мне показалось, что удобным из дополнительного кода преобразовать в этот формат путём инвертирования старшего бита. На таблице выше это видно. Прошу прощения, что застрял на этой теме, она этого не стоит. Просто, со стороны компьютера чтение UDP пакетов пока что через LABVIEW, которое читает пакет данных и преобразует его в массив беззнаковых байтов.
|
|
|
|
|
Jul 4 2014, 11:32
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(Golikov A. @ Jul 4 2014, 14:39)  Вы нашли режим ФИФО корки который вешается на шину проца? Нет, еще не нашел. Хочу, всё же, для начала попробовать добить свою двупортовую память, сделал ногу внешнего прерывания на процессоре, и хочу её дергать флагом заполнения памяти. Посмотреть, не будет ли ошибок, и померить скорость, с которой процессор сможет её прочитать. Уже почти доделал, потом попробую с коркой ФИФО. Спасибо.
|
|
|
|
|
Jul 4 2014, 16:37
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 4 2014, 11:18)  Сначала ваш модуль через сигнал дергает GPIO, GPIO генерит сигнал для контроллера прерывания, контроллер прерываний генерит сигнал для проца, и тот прерывается. Далее он идет в контроллер узнает что его дернуло GPIO, далее идет в GPIO узнает какая нога, дальше в ваш модуль чтобы узнать что за событие... Не слишком ли сложно? Это делает не модуль, а это является задачей синхронизации. И совсем не сложно, пришло прерывание - знаем, что данные готовы и забираем их. Ну тогда расскажите, каким способом Вы будете сообщать процессору, что нужно забрать данные, что накопилась нужная пачка в каком-то устройстве хранения. Даже если Вы используете FIFO, то это прерывание от сигнала достаточного уровня заполнения FIFO. Цитата(Golikov A. @ Jul 4 2014, 11:18)  далеко не у всех... и далеко не полная шина выведена в этот интерфейс, и далеко это не внутренняя шина проца, это ее некий рудемент. Я говорил только о том, что именно external memory интерфейс используется для подключения внешней памяти, через GPIO считывать данные с устройства хранения - это тот ещё изврат. Приведите пример подразумеваемого процессора у которого нет external memory периферии, мне кажется это будет что-то способное только на "поморгать лампочкой". Цитата(Golikov A. @ Jul 4 2014, 11:18)  В случае проца внутри ПЛИС вы имеете полноценную внутреннюю шину, это гораздо более удобно и функционально. Да, более удобно, можно свои IP-ядра делать, которые будут для процессора, как его собственная периферия, но вопрос ведь был, каким образом данные забираются с внешнего носителя, и это уж точно не GPIO. Цитата(Ar-han @ Jul 4 2014, 12:19)  Просто, со стороны компьютера чтение UDP пакетов пока что через LABVIEW, которое читает пакет данных и преобразует его в массив беззнаковых байтов. Напишите свой приёмник со стороны ПК или можете воспользоваться Matlab. В Matlab Simulink можно набросать схемку которая принимает UDP с заданного IP и порта, а потом можете любую обработку навесить. Цитата(Ar-han @ Jul 4 2014, 14:32)  Нет, еще не нашел. Хочу, всё же, для начала попробовать добить свою двупортовую память, сделал ногу внешнего прерывания на процессоре, и хочу её дергать флагом заполнения памяти. Посмотреть, не будет ли ошибок, и померить скорость, с которой процессор сможет её прочитать. Не настаиваю, но если используете память, то более удобным и простым в реализации будет вариант с использованием памяти с двумя буферами. Да, и расскажите, как Вы считываете свои данные с памяти, а то что-то дружно тут много всего наговорили.
|
|
|
|
|
Jul 4 2014, 16:45
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Приведите пример подразумеваемого процессора у которого нет external memory периферии, мне кажется это будет что-то способное только на "поморгать лампочкой". LPC1768 в 100 ногом корпусе + Spartan6 Между процом и ПЛИС 2 SSP по 50 МГБит, и с десяток сигнальных ножек GPIO. Не только моргает лампочками, но довольно изощренно рулит сложной системой подвижек. Цитата И совсем не сложно, пришло прерывание - знаем, что данные готовы и забираем их. Ну тогда расскажите, каким способом Вы будете сообщать процессору, что нужно забрать данные, что накопилась нужная пачка в каком-то устройстве хранения Сгенерю прерывание не дернув GPIO, который сгенерит прерывание через модуль обработки, а сразу напрямую подам сигнал на вход модуля обработки прерываний. Двигаясь далее и развивая мысль: FIFO в этой схеме служит для накопления данных пока процессор занят чем то другим. Так что прерывание в этом случае как таковое и не нужно. В основном цикле работы проца (при супер лупе) или в отдельном потоке в случае операционки проверяем флаг наличия пакета данных FIFO, и как оно там есть забираем и отправляем. При этом автомат отслеживания аварийной ситуации как перехлест данных - это просто проверка флага что фифо переполнилось, не надо проверять что один буфер полон, а другой процом не считан и так далее... Но я также не настаиваю, нет абсолютно верных решений, всегда есть компромиссы...
|
|
|
|
|
Jul 4 2014, 17:34
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 4 2014, 19:45)  LPC1768 в 100 ногом корпусе + Spartan6 Между процом и ПЛИС 2 SSP по 50 МГБит, и с десяток сигнальных ножек GPIO. Не только моргает лампочками, но довольно изощренно рулит сложной системой подвижек. Но на него Вы внешний RAM и не вешаете и не пытаетесь вычитывать его через GPIO. Он как бы для этого и не предназначен. Цитата(Golikov A. @ Jul 4 2014, 19:45)  Двигаясь далее и развивая мысль: FIFO в этой схеме служит для накопления данных пока процессор занят чем то другим. Так что прерывание в этом случае как таковое и не нужно. В основном цикле работы проца (при супер лупе) или в отдельном потоке в случае операционки проверяем флаг наличия пакета данных FIFO, и как оно там есть забираем и отправляем. Отправляем мы данные пакетами определённой длинны, т.е. если это FIFO, то читать его будем после того, как необходимое количество данных там накопилось, следовательно необходимо сообщить о наличии данных, прерывание тут и необходимо (вариант его реализации уже будет зависеть от того, кому что нравится). Можно конечно и пулом мониторить наличие данного флага, но в чём преимущество? Два варианта реализации одной и той же задачи. Цитата(Golikov A. @ Jul 4 2014, 19:45)  При этом автомат отслеживания аварийной ситуации как перехлест данных - это просто проверка флага что фифо переполнилось, не надо проверять что один буфер полон, а другой процом не считан и так далее... Тут Вы не разобрались в предложенном варианте решения, там нет никаких проверок на заполнение, всё полностью определено сигналами синхронизации. В моём проекте использовал именно описанный вариант решения, но вариант с FIFO полностью принимаю.
|
|
|
|
|
Jul 4 2014, 18:33
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата Тут Вы не разобрались в предложенном варианте решения, там нет никаких проверок на заполнение, всё полностью определено сигналами синхронизации. Я про то что если захотим сделать защиту. Мало ли что было в сети, наелся кексов стэк, а данные валятся. Я предпочитаю иметь флаг ошибки на этот случай. В случае фифо - это флаг что фифо заполнилось, в случае 2 буферов, это более сложная проверка на заполнение первого и не опустошение второго. При этом ФИФО само следит за этим флагом, а тут придется еще процом симафорить. Это не с целью что это мертвое решение, а так по придираться  Цитата Отправляем мы данные пакетами определённой длинны, т.е. если это FIFO, то читать его будем после того, как необходимое количество данных там накопилось, следовательно необходимо сообщить о наличии данных вот тут я обращаю внимание на то что фифо умеет генерить флаг наличия не только данных вообще, но и конкретного их количества. То есть в этом случае пакет формирует само фифо не занимая процессор. Этот сигнал можно вывести на прерывание, но я бы не стал. Прерывание - это такая штука, что их лучше меньше чем больше. Вы обрабатываете стэк езернета и грузите данные, хорошо бы чтобы один процесс не влезал в другой, значит прерывание не вариант, вот тут я вижу достаточно большую выгоду. Хотя 2 буфера можно так же обрабатывать полингом. Фифо просто как-то экономичнее кажется...
|
|
|
|
|
Jul 4 2014, 19:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 4 2014, 21:33)  Я про то что если захотим сделать защиту. Мало ли что было в сети, наелся кексов стэк, а данные валятся. Я предпочитаю иметь флаг ошибки на этот случай. В случае фифо - это флаг что фифо заполнилось, в случае 2 буферов, это более сложная проверка на заполнение первого и не опустошение второго. При этом ФИФО само следит за этим флагом, а тут придется еще процом симафорить. Ну если "наелся кексов стэк", проц не успевает обработать все накопившиеся данные, то FIFO теряет данные и сигнализирует об ошибке, мой RAM с двумя буферами продолжает щёлкать, перезаписывая поочереди данные в одном буфере, а потом в другом и т.д., т.е. и тут и там потеря данных. При приёме данных с АЦП, думаю, это нестрашно, если конечно это не постоянная ошибка. Цитата(Golikov A. @ Jul 4 2014, 21:33)  вот тут я обращаю внимание на то что фифо умеет генерить флаг наличия не только данных вообще, но и конкретного их количества. То есть в этом случае пакет формирует само фифо не занимая процессор. Этот сигнал можно вывести на прерывание, но я бы не стал. Прерывание - это такая штука, что их лучше меньше чем больше. Аналогично и при использовании RAM, мы сами определяем размер необходимй выборки, всё, что хранится в памяти и есть наша выборка. Сигнал синхронизации сигнализирует, когда буферы чтения/записи меняются местами, когда процессор может начинать вычитывать новые данные. Процессорное время тут также не задействуется. Реализовывалось всё это на Cyclone V и вычитку памяти осуществлял Sg-DMA (думаю, что-то похожее найдётся и у Xilinx), который и запихивал все данные в железный упаковщик UDP. По прерыванию происходит только обновление дескриптора для Sg-DMA, далее процессор выполняет какие-то свои задачи, всю работу по пересылке данных выполняет Sg-DMA. Цитата(Golikov A. @ Jul 4 2014, 21:33)  Это не с целью что это мертвое решение, а так по придираться  Никто и не оспаривал, что какой-то вариант нельзя реализовать, просто изначально в вопросе фигурировала память и было предложено решение, как это всё наладить меньшей кровью. Цитата(druzhin @ Jul 4 2014, 21:42)  У меня есть рабочие проекты на Spartan-6 по приёму данных с АЦП LTC2157. Поделитесь тогда примером, чтоб человеку было от чего оттолкнуться.
|
|
|
|
|
Jul 4 2014, 22:35
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(druzhin @ Jul 4 2014, 22:42)  У меня есть рабочие проекты на Spartan-6 по приёму данных с АЦП LTC2157. Было бы интересно взглянуть, хотя может сначала стоит своих шишек набить. А то у меня сегодня микроблейз на внешние прерывания напрочь отказывался реагировать. Бывает, застряну на какой-то мелочи и сижу по пол дня. Цитата(doom13 @ Jul 4 2014, 20:37)  Да, и расскажите, как Вы считываете свои данные с памяти, а то что-то дружно тут много всего наговорили. В моём варианте двухпортовая память в один порт ацп пишет по два значения (14бит) в один регистр (32бит), а вторым портом она на PLB шине (пока что микроблейза): #define XPAR_XPS_SHARED_BRAM_IF_CNTLR_BASEADDR 0xA0000000 Указатель на эту память: #define pData ((char*)0xA0000000) копирую: memcpy(pbuf_to_be_sent->payload,pData,STR_SIZE); отправляю: err = udp_send(pcb, pbuf_to_be_sent); Хочу научиться понимать и работать со всеми вариантами обмена данными, но пока иду от простого к сложному. Не пинайте сильно, не всегда с новыми понятиями легко разобраться, такими как DMA. Периодически, даю команду читать ацп и писать в память до заполнения, складывая два значения в один регистр. Дергаю ногу прерывания микроблейза флагом, что память заполнена, по этому прерыванию пытаюсь читать данные и отправлять пакет. Пока что заткнулся на прерывании микроблейза. Упорно не хочет работать, хотя раньше с ним проблем не было. (Может я импульс короткий даю на прерывание? он порядка 100 ns) До этого, писал в эту память 4 мкс сигнала, ждал 200 ms и снова писал, а проц выгребал оттуда 10 раз в секунду данные со своей, уж не знаю какой скоростью, и посылал пакеты. В таком варианте сигнал приходил порезанный на несколько кусков в разных фазах. При этом, если снизить частоту тактирования АЦП раз в 10, то сигнал приходил без искажений. Я пока только учусь, хочу попробовать как не правильно делать и как правильно. Всем большое спасибо за поддержку.
|
|
|
|
|
Jul 7 2014, 14:32
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 5 2014, 10:58)  Откуда тогда дискуссия про GPIO и вычитку с его помощью данных  Так и нужно - память как бы внешняя получается. 64-битная шина GPIO была в самом начале, от неё перешёл на двухпортовую BRAM, повешанную на PLB шину. Как мне лучше флаг заполнения памяти передать процессору? Сейчас его завожу на ногу внешнего прерывания. А как правильно? Тоже через корку какую делать обмен флагами? Разделил по времени запись и чтение в двухпортовую память. Теперь сигнал не режется на куски, но какие-то ошибки возникают, снова запутался, порядок ног уже 5 раз проверил. Пила на входе вместо диф. приемников рисуется правильно. синус на входе
без сигнала с замкнутым входом
Может быть какие-то временные ограничения нужно указать сигналу, по которому защелкиваю данные в диф. приемниках? Защелкиваю данные по сигналу clk_out с АЦП. Может нужно подвигать фазу защелкивания DCM блоком, или указать допустимый джиттер на этот сигнал (USER_CLK) ? У меня сейчас так: Код IBUFGDS_1 : IBUFGDS port map (I=>SMA_DIFF_CLK_IN_P, IB=>SMA_DIFF_CLK_IN_N, O=>USER_CLK);
IBUFDS_6 : IBUFDS port map (I=>HDR2_64_SM_9_P, IB=>HDR2_62_SM_9_N, O=>DDR_6); IDDR_6 : IDDR port map (C=>USER_CLK, CE=>VPP, D=>DDR_6, R=>GRND, S=>GRND, Q1=>out12, Q2=>out13); ...
Сообщение отредактировал Ar-han - Jul 7 2014, 14:40
|
|
|
|
|
Jul 7 2014, 20:09
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
А что там с режимом SDR CMOS, можете джампер перебросить, чтобы включить его? По второму рисунку видно, что данные от АЦП приёмник принимает неправильно, шуметь должно несколько разрядов АЦП относительно среднего значения 8192. Путаница с порядком следования бит у Вас осталась. Цитата(Ar-han @ Jul 7 2014, 17:32)  Пила на входе вместо диф. приемников рисуется правильно. Это говорит о том, что запись данных в память и их вычитка из памяти работают нормально. Эту часть можно пока оставить. Цитата(Ar-han @ Jul 7 2014, 17:32)  Разделил по времени запись и чтение в двухпортовую память. Теперь сигнал не режется на куски, но какие-то ошибки возникают, снова запутался, порядок ног уже 5 раз проверил. Тут может влиять не только порядок ног (Вы его уже много раз проверяли), но и выровнены ли линии, какая фаза у клока относительно данных, она может отличаться для разных линий. Т.е. тут решением может быть либо переключение в SDR CMOS режим, где каждая линия будет соответствовать одному биту, либо реализовать SPI и сего помощью управлять АЦП, задать на выход тестовую последовательность 10...10 и тогда можно будет увидеть, какие именно биты перепутаны. Цитата(Ar-han @ Jul 7 2014, 17:32)  Может быть какие-то временные ограничения нужно указать сигналу, по которому защелкиваю данные в диф. приемниках? Защелкиваю данные по сигналу clk_out с АЦП. Может нужно подвигать фазу защелкивания DCM блоком, или указать допустимый джиттер на этот сигнал (USER_CLK) ? Временные ограничения прописать стоит, но основная проблема у Вас не в этом. Подвигать фазу PLL скорее всего не получится, если не ошибаюсь, то клок был заведён на неправильную ногу. Но даже если получится, где гарантия, что поправив для одной линии не испортите для другой. Варианта дальнейших действий для успешного решения проблемы два: 1) Включить режим SDR CMOS. 2) Завести SPI, выдать тестовую последовательность, увидеть причину неправильного приёма данных.
|
|
|
|
|
Jul 7 2014, 21:29
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 7 2014, 23:22)  Ну тогда можно немного задержать данные, чтобы на клок успели. Да, но для каждой линии может быть своя задержка, подбирать каждую, не зная правильно ли подобраны все остальные (только по результату можем определить), будет сложновато. Цитата(Ar-han @ Jul 7 2014, 17:32)  Как мне лучше флаг заполнения памяти передать процессору? Сейчас его завожу на ногу внешнего прерывания. А как правильно? Тоже через корку какую делать обмен флагами? Я так же делал, с приёмом данных сначала разберитесь, потом будете искать более оптимальные пути.
|
|
|
|
|
Jul 8 2014, 07:07
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(Ar-han @ Jul 7 2014, 18:32)  синус на входе Ура, всё заработало! Нашел еще одну дурацкую ошибку, пихал данные в память по совершенно другой частоте, не по той, на которой они защелкивались в диф. приемниках. На входе синус, 2 МГц.
|
|
|
|
|
Jul 9 2014, 05:45
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 12-09-11
Пользователь №: 67 135

|
Цитата(doom13 @ Jul 5 2014, 10:58)  в варианте с двумя буферами памяти, которые переключаются поочереди чтение и запись независимы. Записывающая и вычитывающая стороны работают самостоятельно никак не оказывая влияния друг на друга. Правильно ли я понимаю, что память с двумя буферами, это две одинаковые корки BRAM, с разными адресами, на одной шине (PLB) ? Кстати, интересно, можно ли двухпортовую BRAM повесить на LMB шину? У меня, вроде бы, получалось, но были проблемы, и не удалось её корректно использовать. Цитата(doom13 @ Jul 8 2014, 01:29)  С приёмом данных сначала разберитесь, потом будете искать более оптимальные пути. Приём данных, кажется, удалось победить. Теперь вопрос по флагам, флаг процессору - по внешнему прерыванию. Ок. Это сделал. Измеренная wireshark -ом скорость получилась 2940 пакетов в сек по 1 кБайту. Теперь как мне передать от процессора флаг, что память прочитана? Первое, что приходит в голову - это GPIO, но подозреваю, что это не оптимально. Сейчас использую microblaze на частоте 100 Мгц, интересно, что даст повышение частоты? Хочу перейти на powerPC, только не соображу как на PowerPC запустить UDP пакеты. Под PowerPC тестовое приложение с эхо сервером организовано через TCP протокол. Насколько я понял, если сделать большие UDP пакеты, то lwip сама их разрежет, и отошлет кусками. Но кажется, UDP не поддерживает нумерацию пакетов, значит, рассчитывать, что они склеятся на стороны компа не приходится. Значит самому нужно их резать кусками, нумеровать, и склеивать на компе? Цитата(Golikov A. @ Jul 8 2014, 00:22)  У вас прописаны констрайны, за сколько данные до фронта клока должны стоять и сколько после? Это весьма полезные констрайны! Нет, не прописаны, буду рад подсказке, с констрейнами еще не успел разобраться. Если, можно, ткните где почитать про констрейны. Правильно ли я понимаю, что констрейны пишутся руками в UCF файле, рядом с распиновкой ног? Где-то я слышал, что они удобно прописываются в PlanAhead, только с ходу не нашел. У меня есть пример констрейна для входного сигнала: Код NET "CLOCK_110" TNM_NET = CLOCK_110; TIMESPEC TS_CLOCK_110 = PERIOD "CLOCK_110" 110 MHz HIGH 50% INPUT_JITTER 100 ps; OFFSET = IN 9.09091 ns VALID 9.09091 ns BEFORE "CLOCK_110" RISING; Можно ли таким же образом указать ограничения на тактовый сигнал, который рождается после диф. приёмников - USER_CLK? Из каких соображений выбирается JITTER ? Код IBUFGDS_1 : IBUFGDS port map (I=>SMA_DIFF_CLK_IN_P, IB=>SMA_DIFF_CLK_IN_N, O=>USER_CLK);
IBUFDS_6 : IBUFDS port map (I=>HDR2_64_SM_9_P, IB=>HDR2_62_SM_9_N, O=>DDR_6); IDDR_6 : IDDR port map (C=>USER_CLK, CE=>VPP, D=>DDR_6, R=>GRND, S=>GRND, Q1=>out12, Q2=>out13); Спасибо! Цитата(Ar-han @ Jul 8 2014, 11:07)  Ура, всё заработало! Нашел еще одну дурацкую ошибку, пихал данные в память по совершенно другой частоте, не по той, на которой они защелкивались в диф. приемниках. Только не понятно, откуда брался шум при отсутствии входного сигнала.
Сообщение отредактировал Ar-han - Jul 9 2014, 05:45
|
|
|
|
|
Jul 9 2014, 06:38
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 9 2014, 08:45)  Правильно ли я понимаю, что память с двумя буферами, это две одинаковые корки BRAM, с разными адресами, на одной шине (PLB) ? Да, две одинаковые, но и адреса у них одинаковые, их выходы подключаются к шине поочереди мультиплексором (выше пример кода приводил). Со стороны процессора это как бы одна память. Интервал времени, когда одна собирает данные, вторая - "отдаёт" предыдущую выборку процессору. Ваша задача только синхронизацию сформировать (выше описывал). Цитата(Ar-han @ Jul 9 2014, 08:45)  Приём данных, кажется, удалось победить. Ну да, всё оказалось намного проще, чем я полагал. Цитата(Ar-han @ Jul 9 2014, 08:45)  Теперь как мне передать от процессора флаг, что память прочитана? Первое, что приходит в голову - это GPIO, но подозреваю, что это не оптимально. Сделайте, как я советовал и никакого флага со стороны процессора не нужно, но можно и GPIO - что-то типа сброса запрета записи в память.
|
|
|
|
|
Jul 9 2014, 07:03
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Перейдите уже на FIFO в конце концов... Брать 2 корки памяти, городить к их шине мультиплексор, да еще поддерживающий на одном из концов PLB или AXI шину, городить модуль переключения мультиплексора, ответный сигнал запрета записи в память. Мне одному кажется это мраком? Взяли FIFO, с одного конца АЦП пихает данные, с другого процессор их забирает. Нет никакой надобности следить заполнен первый буфер или второй, запрещать переключения и прочее... Появились данные на выходе, вычитали их и отправили. Пошли свои дела делать, вернулись опять поглядели, есть данные? считали и отправили. Все! Внутри FIFO будут те же блоки BRAM + весьма эффективная обвязка UDP - если вы бирете большой пакет, больше чем лезет через сеть, стэк его порежет и отправить, на другом конце стэк его склеит и вернет. Пакет UDP придет либо целиком, либо не придет вообще. Отсутствие нумерации относится к тому что если вы пошлете 2 пакета UDP никто не знает как они придут и никто не гарантирует что они придут в той же последовательности как вы их отправляли, могут поменяться местами. Более того нет гарантии что один пакет не придет 2 раза (если потеряется что-то в обмене и отправляющий узел продублирует пакет). То есть другими словами если вы хотите слать байтовый поток через UDP - вы обламаетесь, данные должны быть промаркированы внутри, иметь заголовки и прочую фигню. Если же хотите поток с гарантией отсутствия повторений и потерь, то это ТСР. Цитата Сейчас использую microblaze на частоте 100 Мгц, интересно, что даст повышение частоты? трудности с разводкой и очевидно прирост производительности. Доступ микроблайза к данным AXI шины далеко не 1 такт. А доступ к акси-лайт ваще блокирующий. Так что обмен данными по шине - самый тормозящий момент работы микроблайза.
|
|
|
|
|
Jul 9 2014, 07:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 9 2014, 08:45)  Насколько я понял, если сделать большие UDP пакеты, то lwip сама их разрежет, и отошлет кусками. Но кажется, UDP не поддерживает нумерацию пакетов, значит, рассчитывать, что они склеятся на стороны компа не приходится. Значит самому нужно их резать кусками, нумеровать, и склеивать на компе? Да, так и есть, если UDP пакет большой (больше порядка 1500 байт), то LwIP пошлёт его за несколько IP-фрагментов, wireshark-ом Вы увидите эти фрагменты, если написать приёмник в любой среде, то там всё склеится автоматом, указываете только длинну данных, которую передаёте. Правда, для LwIP чтоб заработала фрагментация мне пришлось добавить задержку в цикле, где и происходит разделение на фрагменты, без неё как-то криво работало, часть фрагментов терялось. Пример того, что нужно для отправки UDP: CODE void main() { unsigned char pucMACArray[8]; .... pucMACArray[0] = ((ulUser0 >> 0) & 0xff); pucMACArray[1] = ((ulUser0 >> 8) & 0xff); pucMACArray[2] = ((ulUser0 >> 16) & 0xff); pucMACArray[3] = ((ulUser1 >> 0) & 0xff); pucMACArray[4] = ((ulUser1 >> 8) & 0xff); pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
unsigned long board_ip = 0xC0A80110; unsigned long net_mask = 0xFFFFFF00;
lwIPInit(pucMACArray, board_ip, net_mask, 0, IPADDR_USE_STATIC);
int i; for(i = 0; i < 16384; i++) { buffer[i] = i; }
// UDP
struct udp_pcb *pcb; pcb = udp_new();
unsigned short port_rmt, port_local; struct ip_addr ip_rmt, ip_local;
IP4_ADDR(&ip_rmt, 192, 168, 1, 66); IP4_ADDR(&ip_local, 192, 168, 1, 16); port_rmt = 12000; port_local = 11000;
udp_bind(pcb, &ip_local, port_local); udp_connect(pcb, &ip_rmt, port_rmt);
unsigned short len = 16384; struct pbuf * pb;
int tx_en = 0; err_t error = 55;
while(1) { if(tx_en) { pb = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); //memcpy(pb->payload, buffer, len); pb->payload = buffer; error = udp_send(pcb, pb); pbuf_free(pb); tx_en = 0; } } }
|
|
|
|
|
Jul 9 2014, 07:17
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Цитата У меня есть пример констрейна для входного сигнала: ну вот и правильный констраин Цитата TIMESPEC TS_CLOCK_110 = PERIOD "CLOCK_110" 110 MHz HIGH 50% INPUT_JITTER 100 ps; это говорит что фронты сигнала идут на частоте 110 МГц, 50% скважности и плавают на 100 пикосекунд. Откуда эти параметры? Не знаю, наверное какие то справочные данные. Главное что после разводки схема проверит все ли данные будут успевать вставать к фронтам (которые могут плавать на 100 пикосек). и дополнительно проверит Цитата OFFSET = IN 9.09091 ns VALID 9.09091 ns BEFORE "CLOCK_110" RISING; что за 9.09 наносек до восходящего фронта данные на входах будут готовы, и будут неизменны еще 9.09 наносек... есть такой же OFFSET = OUT для выходных ножек. Так же кроме BEFORE есть AFTER. про констраины надо читать UG625 (не знаю может есть уже более свежие) Смысл в том что вы должны по мануалу вашего АЦП описать когда у вас будут появляться данные на входных ножка относительно сигнала клок. И тогда разводя сигнал внутри ПЛИС синтезатор будет учитывать задержки распространения и понимать все ли данные верно доходят к моменту защелкивания или нет (пути то у всех разные), а также проверять хватает ли времени между фронтами.
|
|
|
|
|
Jul 9 2014, 07:52
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Ar-han @ Jul 9 2014, 08:45)  Только не понятно, откуда брался шум при отсутствии входного сигнала. Вы же сами сказали, что запись в память работала не по тому клоку (возможно в момент каких-то переключений забирались данные), вообще, очень похоже было на ошибку в порядке приёма бит, которая и устраняетсе предложенными способами. Цитата(Golikov A. @ Jul 9 2014, 10:03)  Брать 2 корки памяти, городить к их шине мультиплексор, да еще поддерживающий на одном из концов PLB или AXI шину, городить модуль переключения мультиплексора, ответный сигнал запрета записи в память. Мультиплексор нужен только для шины данных, ничего сложного в этом нет, никакой модуль переключения мультиплексора не нужен. Цитата(Golikov A. @ Jul 9 2014, 10:03)  Мне одному кажется это мраком? Вы так и не разобрались в предложенном варианте, просмотрите, что советовалось, ещё раз и это не будет мраком. Нормальный вариант решения поставленной задачи, единственный недостаток - двойной объём памяти для хранения текущего и предыдущего пакета, но для FIFO, думаю получится примерно также (если делать, чтоб ничего не переполнялось и не перезатиралось). Цитата(Golikov A. @ Jul 9 2014, 10:03)  Взяли FIFO, с одного конца АЦП пихает данные, с другого процессор их забирает. Нет никакой надобности следить заполнен первый буфер или второй, запрещать переключения и прочее... Появились данные на выходе, вычитали их и отправили. Пошли свои дела делать, вернулись опять поглядели, есть данные? считали и отправили. Все! Внутри FIFO будут те же блоки BRAM + весьма эффективная обвязка Ещё раз разберитесь в предлагаемой реализации, а потом утверждайте в необходимости отслеживать заполненность буферов, "запрещать переключения и прочее..." Цитата(Golikov A. @ Jul 9 2014, 10:03)  UDP - если вы бирете большой пакет, больше чем лезет через сеть, стэк его порежет и отправить, на другом конце стэк его склеит и вернет. Пакет UDP придет либо целиком, либо не придет вообще. Отсутствие нумерации относится к тому что если вы пошлете 2 пакета UDP никто не знает как они придут и никто не гарантирует что они придут в той же последовательности как вы их отправляли, могут поменяться местами. Более того нет гарантии что один пакет не придет 2 раза (если потеряется что-то в обмене и отправляющий узел продублирует пакет). Писал уже, если передача данных происходит не между континентами, то всё будет нормально с UDP даже при отправке фрагментированных IP-пакетов, никаких потерь и путаницы пакетов и фрагментов пакета не будет. Цитата(Golikov A. @ Jul 9 2014, 10:03)  То есть другими словами если вы хотите слать байтовый поток через UDP - вы обламаетесь, данные должны быть промаркированы внутри, иметь заголовки и прочую фигню. Если же хотите поток с гарантией отсутствия повторений и потерь, то это ТСР. Не обломаетесь, всё будет работать. Под передачу данных от АЦП (более-менее скоростных) использовать TCP никто не будет. Из собственного опыта - используется UDP, поток данных 655.36 Mbit/s, длина данных в UDP-пакете 32 kB, это всё отправляется с использованием фрагментации IP по 1024 байта в каждом фрагменте. Всё нормально работает без всяких потерь, есть проблемы с приёмом под Windows, но комп с Linux всё нормально принимает и обрабатывает. Да, кстати, при реализации, для сбора данных с АЦП использовалась именно память с двойной буферизацией.
|
|
|
|
|
Jul 9 2014, 09:05
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
У меня нет времени и желания разбираться в предложенном варианте по 2 причинам 1. Вариант понятен и прост, сделать его тяп ляп просто, сделать его правильно с защитой и диагностикой сложно 2. Я не вижу преимуществ этого вариант перед вариантом с FIFO, ни в реализации ни в использовании. Также я хочу заметить что подход Цитата Из собственного опыта ... есть проблемы с приёмом под Windows, но комп с Linux всё нормально принимает и обрабатывает. Весьма детский и непрофессиональный Утверждения вида Цитата Писал уже, если передача данных происходит не между континентами, то всё будет нормально с UDP даже при отправке фрагментированных IP-пакетов, никаких потерь и путаницы пакетов и фрагментов пакета не будет. Допустимы только на студенческих курсовых да и то претендующих на зачет не более... Есть стандарт, в стандарте указано что гарантий нет, значит их нет! Если вы в одних идеальных условиях что-то проверили, и сегодня оно работает - это не дает вам права делать такие утверждения! Откуда вы знаете какие и где будут условия? По передавайте через вайфай на границе сигнала. Понаделают таких поделок, а потом у нас ракеты падают, говорят саботаж... Да я согласен - такой подход САБОТАЖ! Простите, наболело... это на самом деле 0 и главная причина почему я не хочу разбираться в вашем варианте...
|
|
|
|
|
Jul 9 2014, 10:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 9 2014, 12:05)  У меня нет времени и желания разбираться в предложенном варианте по 2 причинам 1. Вариант понятен и прост, сделать его тяп ляп просто, сделать его правильно с защитой и диагностикой сложно 2. Я не вижу преимуществ этого вариант перед вариантом с FIFO, ни в реализации ни в использовании. Так проще всего не разобравшись (стоило только более внимательно прочитать все предыдущие посты, чтобы понять - о чём идёт речь) сказать, что это "мрак". Оба варианта примерно одинаковы и просты в реализации, Вам нравится Ваш, мне - мой. Цитата(Golikov A. @ Jul 9 2014, 12:05)  Также я хочу заметить что подход Цитата(doom13 @ Jul 9 2014, 10:52)  Из собственного опыта .... есть проблемы с приёмом под Windows, но комп с Linux всё нормально принимает и обрабатывает.
Весьма детский и непрофессиональный В чем собственно непрофессионализм - в использовании Linux? Вы сначала попробуйте принять примерный поток на ПК под управлением Windows - потом будете говорить о непрофессионализме. Цитата(Golikov A. @ Jul 9 2014, 12:05)  Утверждения вида Цитата(doom13 @ Jul 9 2014, 10:52)  Писал уже, если передача данных происходит не между континентами, то всё будет нормально с UDP даже при отправке фрагментированных IP-пакетов, никаких потерь и путаницы пакетов и фрагментов пакета не будет.
Допустимы только на студенческих курсовых да и то претендующих на зачет не более... На данный момент никак не связан со студенческими курсовыми, поэтому не могу знать что именно может претендовать на зачёт и т.д., говорил только о том, что знаю и что работает в реальных системах. Это допустимо даже в очень нестуденческих проектах. Нет необходимости использования TCP для передачи данных от АЦП для дальнейшей обработки. Цитата(Golikov A. @ Jul 9 2014, 12:05)  Есть стандарт, в стандарте указано что гарантий нет, значит их нет! Если вы в одних идеальных условиях что-то проверили, и сегодня оно работает - это не дает вам права делать такие утверждения! Откуда вы знаете какие и где будут условия? По передавайте через вайфай на границе сигнала. Понаделают таких поделок, а потом у нас ракеты падают, говорят саботаж... Да я согласен - такой подход САБОТАЖ! Если Вы так опираетесь на стандарт, с которым никто и не спорит, тогда посмотрите ещё и на длины соединений между отдельными узлами сети для которых этот стандарт выполняется, на прохождение данных через всевозможные сетевые устройства. Я точно могу сказать на каком расстоянии друг от друга находятся блоки системы (это не киллометры и даже не сотни метров), через какое количество коммутаторов должны пройти данные, могу проверить работоспособность системы, процент потери пакетов и на основании всего этого сделать заключение - UDP вполне подходит для данных целей.
|
|
|
|
|
Jul 9 2014, 10:15
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
FIFO 1. Размер отправляемого пакета - любой задается через порог фифо не пусто. В любой момент можно изменить, даже на лету. 2. Число буферизуемых пакетов без потерь - ограничен только объемом памяти, число пакетов меняется на лету с их размером 3. Потери памяти (используемая физически, но не используемая для хранения данных) 0. Все пакеты лежат друг за другом байт в байт, выравнивания не требуется 4. Адрес чтения данных - один 5. Автомат управления адресом чтения - отсутствует Вариант с 2 буферами 1. Размер отправляемого пакета - минимум ограничен заполняемостью буфера, если поставите 1 байт то оба буфера будут забиты. Второе ограничение ширина шины адреса, она определяет максимальную длину пакета 2. Число буферизуемых пакетов без потерь - 1. Чтобы их стало больше необходимо ставить еще блоки памяти. Усложнять мультиплексор выбор блока. На лету изменить с изменением размера пакета невозможно. 3. На каждый буфер вы используете один брам 18К, весь хвост 18К - размер пакета у вас не используется. 4. Адрес чтения пакета сменный, и зависит от размера пакета, с изменением размера пакета необходимо менять диапазон адресов 5. Необходим автомат управления адресом при чтении очередью, либо программные циклы с инкрементом Достаточно или есть еще вопросы почему FIFO однозначно лучше? 2 буфера - решение для простоты, но если есть готовое FIFO надо брать его и использовать. Цитата В чем собственно непрофессионализм - в использовании Linux Нет, непрофессионализм - это на основе своего частного мнения и конечного числа экспериментов выдвигать нарушающие стандарт утверждения. Цитата Это допустимо даже в очень нестуденческих проектах. В очень не студенческих, но крайне плохих проектах. Проблема не в использовании UDP, проблема в неправильном его использовании. Кто мешает в UDP пакет вместе с данными положить заголовок с определяющий положение данных? Нет необходимости крутить тяжелый ТСР, но считать что UDP пакеты всегда будут идти друг за другом и никогда не потеряются - преступно! Потому можете сколько угодно трясти готовыми проектами которые так работают. Я не изменю своего мнения. Проект построенный на таких допущениях - барахло!
|
|
|
|
|
Jul 9 2014, 10:52
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 9 2014, 13:15)  Нет, непрофессионализм - это на основе своего частного мнения и конечного числа экспериментов выдвигать нарушающие стандарт утверждения. Вы, как всегда, не так поняли, я не выдвигал нарушающих стандарт утверждений, я всего лишь сказал, что для решения поставленной задачи UDP будет вполне достаточно и качество передачи данных будет достаточно надёжным. Сама система приёма/передачи данных реализовывалась с помощью советов знающих людей с данного форума (за что им и спасибо), которые уже проходили этот путь. Так что утверждать о субъективном мнении и ограниченном числе экспериментов не стоит. Цитата(Golikov A. @ Jul 9 2014, 13:15)  В очень не студенческих, но крайне плохих проектах. Проблема не в использовании UDP, проблема в неправильном его использовании. Кто мешает в UDP пакет вместе с данными положить заголовок с определяющий положение данных? Нет необходимости крутить тяжелый ТСР, но считать что UDP пакеты всегда будут идти друг за другом и никогда не потеряются - преступно! Ваша оценка здесь неуместна, другие люди решают хорошо оно сделано или плохо. Заголовок для данных используется, но он не помогает восстановить данные, просто используется как информация о потере данных и всё. Цитата(Golikov A. @ Jul 9 2014, 13:15)  Потому можете сколько угодно трясти готовыми проектами которые так работают. Я не изменю своего мнения. Проект построенный на таких допущениях - барахло! Про допущения я уже всё пояснил, читайте пожалуйста внимательней. Мне кажется, лучше "трясти" готовым, что работает и проверено, чем голословно без всякой проверки утверждать - всё очень плохо (замечал такое за Вами).
|
|
|
|
|
Jul 9 2014, 11:55
|
Профессионал
    
Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539

|
Цитата(Golikov A. @ Jul 9 2014, 13:15)  FIFO 1. Размер отправляемого пакета - любой задается через порог фифо не пусто. В любой момент можно изменить, даже на лету. Вариант с 2 буферами 1. Размер отправляемого пакета - минимум ограничен заполняемостью буфера, если поставите 1 байт то оба буфера будут забиты. Второе ограничение ширина шины адреса, она определяет максимальную длину пакета Размер отправляемого пакета известен заранее, можно выбрать необходимый размер RAM или FIFO для хранения необходимого количества данных. Менять размер накапливаемых данных в сторону уменьшения возможно в обоих случаях, в сторону увеличения везде столкнёмся с ограничением, которое задали при создании IP-ядра. Но в изменении длины накапливаемых данных и нет необходимости. По поводу того, что два буфера памяти могут заполниться одновременно, объяснять Вам не буду, читайте выше. С шиной адреса тоже проблем не вижу, естественно, закладываем такую, чтоб обеспечить адресацию всех накопленных данных. Цитата(Golikov A. @ Jul 9 2014, 13:15)  FIFO 2. Число буферизуемых пакетов без потерь - ограничен только объемом памяти, число пакетов меняется на лету с их размером Вариант с 2 буферами 2. Число буферизуемых пакетов без потерь - 1. Чтобы их стало больше необходимо ставить еще блоки памяти. Усложнять мультиплексор выбор блока. На лету изменить с изменением размера пакета невозможно. Хранение/передачу данных в обоих случаях можно организовать без потерь, объяснять как Вам не буду, смотрите выше. Цитата(Golikov A. @ Jul 9 2014, 13:15)  FIFO 3. Потери памяти (используемая физически, но не используемая для хранения данных) 0. Все пакеты лежат друг за другом байт в байт, выравнивания не требуется Вариант с 2 буферами 3. На каждый буфер вы используете один брам 18К, весь хвост 18К - размер пакета у вас не используется. Что мешает выбрать оптимальный размер данных, чтобы и работать было удобно и память максимально эффективно использовалась, потери памяти были по нулям. Всё реализуемо. Цитата(Golikov A. @ Jul 9 2014, 13:15)  FIFO 4. Адрес чтения данных - один Вариант с 2 буферами 4. Адрес чтения пакета сменный, и зависит от размера пакета, с изменением размера пакета необходимо менять диапазон адресов Один раз выбирается длина данных с которой хотим работать и больше ничего менять не надо. Цитата(Golikov A. @ Jul 9 2014, 13:15)  FIFO 5. Автомат управления адресом чтения - отсутствует Вариант с 2 буферами 5. Необходим автомат управления адресом при чтении очередью, либо программные циклы с инкрементом Вы опять о чём-то своём. Говорим DMA адрес буфера данных и на этом наше участие в формировании адресов заканчивается, для FIFO DMA не инкреметирует адрес, для RAM - инкремитирует. Всё просто в обеих случаях. Если процессор использовать то цикл чтения будет и для FIFO и для RAM, для вычитки RAM ещё можно memcpy использовать и тогда совсем никаких циклов не видно и адрес инкреметировать не нужно. Цитата(Golikov A. @ Jul 9 2014, 13:15)  Достаточно или есть еще вопросы почему FIFO однозначно лучше? 2 буфера - решение для простоты, но если есть готовое FIFO надо брать его и использовать. Все Ваши доводы неубедительны.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|