Jump to content
    

LVDS DDR данные из АЦП в ПЛИС

А у вас не с АЦП проблемы? В ветке армов обсуждалось, что если АЦПешене некоторых моделей не хватает времени на выборку оно начинает ступеньки рисовать и выбросы похожие на ваши...

 

 

Share this post


Link to post
Share on other sites

Жаль с ходу не ясно в чём баг.

Баг в том, о чём я писал. На линиях попутан порядок следования бит, вместо D0 принимается D1 и наоборот, это может быть и на других линиях D2-D3, D4-D5, и т.д. На кокой-то из линий данные могут приниматься и правильно. Для устранения этого явления в АЦП и предусмотрена возможность выдачи на выход эталонной последовательности, по которой можно поймать правильный порядок следования бит при старте и продолжать работу с правильными данными. По-хорошему, необходимо устройство, которое будет производить синхронизацию.

Советую запустить простейший SPI, это даст возможность увидеть, где и что перепутано.

 

А у вас не с АЦП проблемы? В ветке армов обсуждалось, что если АЦПешене некоторых моделей не хватает времени на выборку оно начинает ступеньки рисовать и выбросы похожие на ваши...

Позвольте спросить, Вы работали с АЦП с похожим интерфейсом? Если нет, то не вводите в заблуждение.

Share this post


Link to post
Share on other sites

А я посоветую сначала запустить SPI и перевести АЦП в режим SDR CMOS - так захватывать данные будет гораздо проще.

Share this post


Link to post
Share on other sites

Позвольте спросить, Вы работали с АЦП с похожим интерфейсом? Если нет, то не вводите в заблуждение.

 

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

Share this post


Link to post
Share on other sites

Баг в том, о чём я писал. На линиях попутан порядок следования бит

 

Попутан, попутан, да еще как! Половина пар не на своих местах были, половина в воздухе висела.

Прошу прощения, всех ввел в заблуждение своей невнимательностью. Всё исправил.

Завтра буду тестировать.

 

Есть еще вопрос по теме.

Собираю пакет данных и кидаю в двупортовую брам. А со стороны процессора PPC передаю указатель эту на область памяти функции, которая отсылает udp пакеты через lwip.

 

Как правильно расставить флаги заполнения области памяти?

Как оценить, сколько тактов требуется процессору, чтобы получив указатель на эту область памяти, скажем 40 кБайт, прочитать её?

Каким размером лучше разбить эту память по UDP пакетам?

Пока что тренировался с 1 кБайтом, проблем не было, всё влезает в один UDP пакет.

Может лучше на tcp/ip перейти?

Пока что работал с 100 мбитным каналом, хочу попробовать гигабитный. С чего начать?

 

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

Спасибо.

 

 

Share this post


Link to post
Share on other sites

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

Это определено не категорично по виду данных, просто есть опыт работы с подобными АЦП (ADS6445, ADS5263), отличие только в том, что в моём случае у одной 8-бит последовательно передаются по 1-ой линии, у другой - 4 бита, у данного экземпляра 2 бита на одной линии. Я так же не настаиваю, просто из возможных ошибок наиболее вероятна та, которую озвучил.

 

Нормально настраивать АЦП без SPI - никак. Но, возможно, это у Вас отладочная плата от TI? Если так тогда там должны быть джамперы, которые и задают режим работы АЦП (PARALLEL INTERFACE CONTROL), смотрите даташит. Тогда Вы можете попробовать

перевести АЦП в режим SDR CMOS - так захватывать данные будет гораздо проще.

, но интерфейс DDR LVDS более помехоустойчив.

Есть еще вопрос по теме.

Собираю пакет данных и кидаю в двупортовую брам. А со стороны процессора PPC передаю указатель эту на область памяти функции, которая отсылает udp пакеты через lwip.

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

 

А какой пакет планируется и с какой частотой идут синхроимпульсы?

Каким размером лучше разбить эту память по UDP пакетам?

Пока что тренировался с 1 кБайтом, проблем не было, всё влезает в один UDP пакет.

В UDP пакет влезает почти 64 кБ (нужно только размер шапки отнять) - это максимальная длинна пакета, которую можете посылать. LwIP поддерживает фрагментацию на уровне IP, создаёте буфер необходимой длинны, при отправке UDP указываете длинну данных, LwIP сама определит, за сколько фрагментов послать Ваш пакет.

Может лучше на tcp/ip перейти?

Для отправки данных АЦП UDP будет вполне достаточно, всегда используем в этих целях именно UDP.

 

До SPI еще не добрался, и с моими темпами, похоже, не скоро ))

LwIP прикрутили, а SPI - нет? :)

 

Share this post


Link to post
Share on other sites

Но, возможно, это у Вас отладочная плата от TI? Если так тогда там должны быть джамперы, которые и задают режим работы АЦП (PARALLEL INTERFACE CONTROL), смотрите даташит.

Плату сам рисовал, переключение в параллельную шину кмоп есть, еще не пробовал.

 

post-67135-1404286339_thumb.jpg

 

А какой пакет планируется и с какой частотой идут синхроимпульсы?

Буду добиваться максимально возможной частоты синхроимпульсов, хотелось бы чтобы 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-ацп/цап на спартане, но это было давно и как-то я там всё через одно место реализовал, что и вспоминать стыдно, сколько это времени заняло )

 

Исправил пины диф. шины, картинка уже проясняется.

post-67135-1404286346_thumb.jpg

 

Share this post


Link to post
Share on other sites

Плату сам рисовал, переключение в параллельную шину кмоп есть, еще не пробовал.

Тогда пробуйте, проблема должна будет решиться. Меняем один джампер и правим немного приёмник на ПЛИС, под приём параллельного кода.

Буду добиваться максимально возможной частоты синхроимпульсов, хотелось бы чтобы 20-40 МБайт в секунду через UDP пролезало, но пока мучаю 100 Мбит канал.

Для получения максимального потока, нужно было бы реализовывать отправку UDP в железе на ПЛИС.

Очень интересно, спасибо. С LWIP поверхностно пока что разобрался, переделал программу из эхо-демо, подозреваю, что там много лишнего, например, не понимаю, почему без этой строчки программа не работает:

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

Share this post


Link to post
Share on other sites

но интерфейс DDR LVDS более помехоустойчив.

В данном случае главное, что LVDS даёт меньше наводок на АЦП. Но лучше начать с более простого, чтобы не бороться с кучей проблем одновременно. К тому же реализовать захват данных с Tsu/Th 1.5нс/0.5нс - это не так просто для новичка. Хотя можно и схалтурить, почти наверняка будет нормально работать и с более мягкими ограничениями, а не по максимуму:).

Share this post


Link to post
Share on other sites

Исправил пины диф. шины, картинка уже проясняется.

Судя по картинке, АЦП выдаёт данные в формате 2s complement format (т.е. знаковый). На график же данные выводятся как беззнаковые, вот и получается - положительные числа отображаются правильно, отрицательные - НЕТ. Либо поменяйте джампер (возможность такая, как понял, есть), чтоб АЦП выдавало данные в формате Straight binary (беззнаковом), либо правильно отображайте на графике. Но проблема с битами, смотрю, осталась, всё же попутаны они у Вас. Переводите АЦП, как и советовали, в режим SDR CMOS и всё будет гуд.

 

Share this post


Link to post
Share on other sites

Судя по картинке, АЦП выдаёт данные в формате 2s complement format (т.е. знаковый). На график же данные выводятся как беззнаковые, вот и получается - положительные числа отображаются правильно, отрицательные - НЕТ.

 

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

 

Сигнал стал похож на синус, джампер переставил в режим:

Straight binary format and DDR LVDS interface

 

И получил такую картинку.

post-67135-1404301104_thumb.jpg

 

Если джампер переставить в режим:

2s Complement format and DDR LVDS interface

картинка такая же, но больше каких-то ошибок ????

post-67135-1404301537_thumb.jpg

 

Снова что-то я напутал, не пойму почему сигнал режется на 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 В

Интересно, это может влиять на ошибки, которые выглядят как помехи?

 

 

И получил такую картинку.

 

Снова нашел ошибку в порядке пинов. Младшая диф. пара была перепутана со старшей. ))

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Я в двухпортовую память с ацп записываю кусок 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 В

Интересно, это может влиять на ошибки, которые выглядят как помехи?

Используйте то, что должно на 100% работать правильно, выбирайте 2s Complement format, а далее учитывайте это при отрисовке графика.

Share this post


Link to post
Share on other sites

Чтение и запись у Вас по времени не совпадают? Обычно делаю двухбуферную память в таких случаях, когда один буфер пишется - второй читается, потом наоборот.

 

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

Спасибо за идею, то есть нужно две области памяти и два флага заполнения, беру на вооружение.

А как лучше флаги процессору передавать? Не через GPIO же ведь? Так же какой-нибудь регистр этой двухпортовой памяти можно использовать под флаги?

 

Подсунул снова на вход пилу вместо диф приемников, но теперь уже амплитуду в 14 бит, вместо 8-и, и вижу, не правильно данные в память пишутся, упаковываются в регисты... Буду искать баги... )

Share this post


Link to post
Share on other sites

Спасибо за идею, то есть нужно две области памяти и два флага заполнения, беру на вооружение.

А как лучше флаги процессору передавать? Не через GPIO же ведь? Так же какой-нибудь регистр этой двухпортовой памяти можно использовать под флаги?

Да нет, немного не так. Ваш синхроимпульс - сигнал прерывания для процессора, по которому он начинает вычитывать память (длину данных уже сами выбираете), с другой стороны по окончании синхроимпульса поднимается сигнал разрешения записи данных в память и держится необходимое для записи выборки число тактов. По фронту сигнала разрешения записи формируете сигнал выбора буфера памяти, который в данный момент пишется/читается, данный сигнал инвертируется каждый период и тем самым можете выбирать на запись/чтение "верхний" или "нижний" буфер памяти (вход разрешения записи у второго буфера инверсный). Выходы буферов заводите на мультиплексор, который управляется сигналом выбора буфера памяти. Т.о. получаете один буфер в данном периоде доступен для записи, второй для чтения, со стороны процессора адреса остаются одни и те же, но мультиплексором к шине данных процессора подкючается нужный буфер памяти.

Есть готовый кусок кода, можете его взять в качестве примера:

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

 

Не через GPIO же ведь?

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

Share this post


Link to post
Share on other sites

Join the conversation

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

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

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

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...