Полная версия этой страницы:
NIOS II
Здравствуйте, пишу программу на Си в ниос2 эклипс. Проект был собран в qsys, там имеется ниос2, DDR2, PIO, on-chip memory2 и т.д. Возник вопрос: как на языке Си обратиться например именно к выводу PIO или к шине адреса DDR2? Вставил несколько строк, но не знаю правильно ли сделал
ALT_MODULE_CLASS_pio_in (PIO_IN_BASE, data_inp);
ALT_MODULE_CLASS_pio_out_on (PIO_OUT_ON_BASE, data_out_on);
ALT_MODULE_CLASS_pio_out (PIO_OUT_BASE, data_out);
ALT_MODULE_CLASS_onchip_memory2_0 (ONCHIP_MEMORY2_0_BASE, on_chip);
doom13
Jan 20 2015, 07:55
Цитата(x66 @ Jan 20 2015, 09:52)

Здравствуйте, пишу программу на Си в ниос2 эклипс. Проект был собран в qsys, там имеется ниос2, DDR2, PIO, on-chip memory2 и т.д. Возник вопрос: как на языке Си обратиться например именно к выводу PIO или к шине адреса DDR2? Вставил несколько строк, но не знаю правильно ли сделал
ALT_MODULE_CLASS_pio_in (PIO_IN_BASE, data_inp);
ALT_MODULE_CLASS_pio_out_on (PIO_OUT_ON_BASE, data_out_on);
ALT_MODULE_CLASS_pio_out (PIO_OUT_BASE, data_out);
ALT_MODULE_CLASS_onchip_memory2_0 (ONCHIP_MEMORY2_0_BASE, on_chip);
Смотрите в BSP папку drivers, там есть всё необходимое.
Цитата(doom13 @ Jan 20 2015, 10:55)

Смотрите в BSP папку drivers, там есть всё необходимое.
Все что есть в папке. Где взять DDR2 и on-chip memory2 ?
doom13
Jan 20 2015, 08:36
Цитата(x66 @ Jan 20 2015, 11:24)

Все что есть в папке. Где взять DDR2 и on-chip memory2 ?
Bsp перегенерили после добавления DDR2? Должны драйвера под контроллер DDR2 появиться, для On-Chip memory и не требуются, ну а для GPIO - altera_avalon_gpio_regs.h.
Golikov A.
Jan 20 2015, 08:38
DDR2 - это не просто статичная память, даже когда вы ее не трогаете там много всего происходит. Потому олопачиванием ее занимается специальный контроллер. Который дергает адреса, производит рефреши, выдбирает столбики и колонки.
Из этого следует что в целом вам не зачем и нельзя обращаться к шине что идет на память, иначе вы этот процесс собьете.
Чтобы просто пошевелить ножками проца - для этого существует модули которые подключаются к шине проца и данные переводят в пины GPIO. Если же есть острая необходимость шевелить ногами памяти (что скорее всего не выйдет), надо писать свой модуль между контроллером и памятью и с шиной к процу. Но скорее всего после внедрения этого модуля ваша память перестанет работать...
Применение контроллера DDR должно встроить память в адресное пространство вашего процессора, во всяком случае это логично и у ксалинкс сделано именно так, потому обращение в память подключенную к процу через контроллер происходит просто по адресам (чтение, запись по указателю в С)
doom13
Jan 20 2015, 08:49
Обманул Вас, для DDR2 как и для On-Chip Memory не будет драйверов в BSP. При условии правильных настроек в Qsys для DDR2-контроллера и соблюдения всех таймингов будет работать как обычная память - создаём указатель на адреса DDR, по нему обращаемся к памяти.
получается, что я могу работать только с адресами ОЗУ? Адресное пространство вроде задал верно, qsys не ругался.
Цитата(doom13 @ Jan 20 2015, 11:36)

Bsp перегенерили после добавления DDR2? Должны драйвера под контроллер DDR2 появиться, для On-Chip memory и не требуются, ну а для GPIO - altera_avalon_gpio_regs.h.
altera_avalon_gpio_regs.h получается общем для нескольких PIO? я в qsys сделал несколько PIO (PIO_IN, PIO_OUT, PIO_OUT_ON)
doom13
Jan 20 2015, 09:09
Цитата(x66 @ Jan 20 2015, 12:07)

altera_avalon_gpio_regs.h получается общем для нескольких PIO? я в qsys сделал несколько PIO (PIO_IN, PIO_OUT, PIO_OUT_ON)
Да, только там есть параметр BASE, а он для всех GPIO разный.
Цитата(doom13 @ Jan 20 2015, 12:09)

Да, только там есть параметр BASE, а он для всех GPIO разный.
Спасибо, начинаю понимать. Везде в примерах даются строки, например IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, leds), но не объясняются.
doom13
Jan 20 2015, 09:16
Цитата(x66 @ Jan 20 2015, 12:07)

получается, что я могу работать только с адресами ОЗУ? Адресное пространство вроде задал верно, qsys не ругался.
Не совсем понял, что Вы этим хотели сказать. Если к Ниосу прикручен DDR2 и On-chip memory, то и тот и тот есть ОЗУ.
Для работы с DDR2 можно использовать что-то типа:
Код
int *ddr2_ptr = (int *) DDR2_START_ADDRESS;
или в BSP Editor определяете секции, которые будут ложится в DDR2 (например .heap - тогда при динамическом выделении памяти, она и будет выделяться в DDR2).
Цитата(doom13 @ Jan 20 2015, 12:09)

Да, только там есть параметр BASE, а он для всех GPIO разный.
В моем случае надо так вводить строки?
IOWR_ALTERA_AVALON_PIO_DATA(pio_in, data)
IOWR_ALTERA_AVALON_PIO_DATA(pio_out, data)
IOWR_ALTERA_AVALON_PIO_DATA(pio_out_on, data)
Вместо data вводится свое имя переменной
Golikov A.
Jan 20 2015, 09:21
С DDR можно работать как с памятью вообще
Для этого надо узнать ее адрес и по адресу читать - писать
А можно как с памятью процессора, для этого надо линкеру про нее рассказать, и тогда все остальное будет происходить само. переменные в ней создадутся, куча там будет и так далее..
Можно комбинировать, часть разметить и отдать процу, а часть использовать самому по указателю.
Неужели альтера не дает примеров с тестом памяти? посмотрите его, там же все очевидно
Цитата(doom13 @ Jan 20 2015, 12:16)

Не совсем понял, что Вы этим хотели сказать. Если к Ниосу прикручен DDR2 и On-chip memory, то и тот и тот есть ОЗУ.
Для работы с DDR2 можно использовать что-то типа:
Код
int *ddr2_ptr = (int *) DDR2_START_ADDRESS;
или в BSP Editor определяете секции, которые будут ложится в DDR2 (например .heap - тогда при динамическом выделении памяти, она и будет выделяться в DDR2).
Имеется внешняя DDR2, также есть On-chip memory, которая необходима для моментов времени, когда происходит чтение из DDR2. В эклипсе для работы с адресами я использую строки, например int addr_on_chip=0x4008000; Правильная ли такая запись?
Golikov A.
Jan 20 2015, 09:24
нет
потому что нужно адрес не
int addr_on_chip=0x4008000
а
int *addr_on_chip = (int *)0x4008000;
записать туда *addr_on_chip = 10;
считать оттуда
int Temp = *addr_on_chip;
при условии что 0x4008000 - это адрес в ДДР
doom13
Jan 20 2015, 09:26
Цитата(x66 @ Jan 20 2015, 12:19)

В моем случае надо так вводить строки?
IOWR_ALTERA_AVALON_PIO_DATA(pio_in, data)
IOWR_ALTERA_AVALON_PIO_DATA(pio_out, data)
IOWR_ALTERA_AVALON_PIO_DATA(pio_out_on, data)
Вместо data вводится свое имя переменной
Да, data - то, что хотите видеть на выходе порта или то, что читаете.
Адреса pio_in, pio_out, pio_out_on берёте из system.h.
Цитата(Golikov A. @ Jan 20 2015, 12:24)

нет
потому что нужно адрес не
int addr_on_chip=0x4008000
а
int *addr_on_chip = (int *)0x4008000;
записать туда *addr_on_chip = 10;
считать оттуда
int Temp = *addr_on_chip;
при условии что 0x4008000 - это адрес в ДДР
Спасибо за разъяснение.
Цитата(doom13 @ Jan 20 2015, 12:26)

Да, data - то, что хотите видеть на выходе порта или то, что читаете.
Адреса pio_in, pio_out, pio_out_on берёте из system.h.
Спасибо, теперь все понятно стало
doom13
Jan 20 2015, 09:42
Цитата(x66 @ Jan 20 2015, 12:22)

Имеется внешняя DDR2, также есть On-chip memory, которая необходима для моментов времени, когда происходит чтение из DDR2. В эклипсе для работы с адресами я использую строки, например int addr_on_chip=0x4008000; Правильная ли такая запись?
Нет, не правильная, все действия через указатель.
Цитата(doom13 @ Jan 20 2015, 12:42)

Нет, не правильная, все действия через указатель.
имеете ввиду надо как запись повыше у Golikov A.
Golikov A.
Jan 20 2015, 09:59
имеет ввиду тоже что и я... просто ответил позже
кстати если копнете макрос
IOWR_ALTERA_AVALON_PIO_DATA
то на конце найдете что это таже самая запись через указатели, в определенный адрес
В процах вообще все делается через обращения в адреса памяти. Потому что в вашем проце вся периферия - это модули которые весят на шине и имеют свой адрес, и все их регистры доступны как данные через этот адрес (группу адресов)
doom13
Jan 20 2015, 10:19
Цитата(Golikov A. @ Jan 20 2015, 12:59)

В процах вообще все делается через обращения в адреса памяти. Потому что в вашем проце вся периферия - это модули которые весят на шине и имеют свой адрес, и все их регистры доступны как данные через этот адрес (группу адресов)
Только вот в случае ниоса обращение к регистрам периферии лучще осуществлять с использованием макросов из BSP, чтобы потом не думать, что же оно не работает.
Цитата(x66 @ Jan 20 2015, 12:57)

имеете ввиду надо как запись повыше у Golikov A.
да, подробный механизм работы с указателем у Golikov A расписан, а пример того, как это делается (указатель на память) приводил выше (сообщение #10), что и было потом расписано с подробностями.0
Цитата
Только вот в случае ниоса обращение к регистрам периферии лучще осуществлять с использованием макросов из BSP, чтобы потом не думать, что же оно не работает.
Присоединяюсь. Есть там такая тонкость: если общаться с переферийным модулем (в т.ч. самописным) посредством макросов типа IOWR/IORD, то все должно работать нормально, если общаться через сишные пойнтеры, то могут возникнуть проблемы. Сам сталкивался с этим и долго думал, что же не работает. Объявил пойнтеры на начало массива по адресу, выделенному переферийному модулю, но при попытке чтения/записи массива стандартным для С способом получалась ошибка. Проблема была в Nios Data Cache. Когда он включен, адекватно работают только макросы IOWR/IORD. Если его вырубить, то можно использовать стандартные методы С, но если в этом нет необходимости, я тоже советую использовать макросы.
Когда смотрел примеры, на сайте альтеры нашел файл где была программа с использованием указателей. натыкался на другие примеры там с использованием макросов было. Это меня и сбивало с толку, как я понял это два способа работы с одним и тем же
doom13
Jan 20 2015, 10:53
Цитата(x66 @ Jan 20 2015, 13:45)

Когда смотрел примеры, на сайте альтеры нашел файл где была программа с использованием указателей. натыкался на другие примеры там с использованием макросов было. Это меня и сбивало с толку, как я понял это два способа работы с одним и тем же
Сомневаюсь, что Вы могли найти примеры от Alter-ы с использованием указателей для обращения к регистрам периферии, тут всё только через макросы (возможно какой-то очень "особенный" пример для ниоса без кэша, но очень маловероятно). Для работы с памятью (On-Chip, SDRAM, DDR и т.д.) указатели и используются.
Golikov A.
Jan 20 2015, 10:59
Ну прекратите сбивать человека
ну возьмите вы свои макросы и поглядите, все в конце сводиться к
volatile записи ну или на худой конец к записи с вызовом слива кеша.
Чудес то не бывает, макрос то тоже написан средствами языка С, просто иногда делает больше чем 1 действие.
У ксалинкса можно еще выбрать не кешируемое пространство, куда периферию пихаешь чтобы проблем не было, уверен у ниоса тоже должно что-то такое быть.
Так что все можно и ручками сделать, если по какой-то причине макросы вредят. А такое бывает
если у вас запись в 10 портов под кешевой областью, то кешь сливать лучше не после каждой записи а сразу после всех. Ну или наоборот, нюансы бывают...
Цитата(doom13 @ Jan 20 2015, 13:53)

Сомневаюсь, что Вы могли найти примеры от Alter-ы с использованием указателей для обращения к регистрам периферии, тут всё только через макросы (возможно какой-то очень "особенный" пример для ниоса без кэша, но очень маловероятно). Для работы с памятью (On-Chip, SDRAM, DDR и т.д.) указатели и используются.
вот код примера
int to_hex(char* pkt)
{
int value[8];
int value1;
int q;
for (q=0; q <= 7; q++)
{
value[q] = (pkt[q] > 0x39) ? (pkt[q] - 0x37) : (pkt[q] - 0x30);
if (q == 0)
value1 = (0 + value[q]);
else
value1 = ((value[q-1] << 4) + value[q]);
}
return value1;
}
int main()
{
unsigned long *DDR_address; //long is 32 bits.
int addr;
int datar;
int ddr_data_out;
char packet[32];
DDR_address = (unsigned long *)0x2000000; //make non-cache
iprintf("DDR test installed \n");
while (1)
{
gets(packet);
switch(packet[0])
{
case 'B': // write operation
addr = to_hex(&packet[1]);
datar = to_hex(&packet[9]);
DDR_address[addr] = datar;
iprintf("Written %08x to address %08x \n", datar, addr);
break;
case 'C': // Read operation
addr = to_hex(&packet[1]);
ddr_data_out = DDR_address[addr];
iprintf("Read %08x from address %08x \n", ddr_data_out, addr);
break;
default:
iprintf("Error: Unexpected command. Switch was - %C \n",packet[0]);
break;
}
}
return 0;
}
http://www.altera.com/literature/hb/nios2/n2sw_nii52007.pdfдля данных есть такой метод как Bit-31 Cache Bypass для Nios II/f
doom13
Jan 20 2015, 11:38
Цитата(Golikov A. @ Jan 20 2015, 13:59)

Ну прекратите сбивать человека
ну возьмите вы свои макросы и поглядите, все в конце сводиться к
volatile записи ну или на худой конец к записи с вызовом слива кеша.
Чудес то не бывает, макрос то тоже написан средствами языка С, просто иногда делает больше чем 1 действие.
У ксалинкса можно еще выбрать не кешируемое пространство, куда периферию пихаешь чтобы проблем не было, уверен у ниоса тоже должно что-то такое быть.
Так что все можно и ручками сделать, если по какой-то причине макросы вредят. А такое бывает
если у вас запись в 10 портов под кешевой областью, то кешь сливать лучше не после каждой записи а сразу после всех. Ну или наоборот, нюансы бывают...
Это Вы прекратите сбивать человека. Если я использую указатель для записи памяти/регистра, то я предполагаю, что после записи значения по данному указателю, необходимое значение попадает по нужному адресу и нет необходимости в выполнении ещё каких-то дополнительных действий. В случае регистров Ниоса этого не происходит, т.е. тут правильно исполтьзовать макросы для работы с регистрами. Макросы не вредят, они и присутствуют в BSP, чтобы их использовать.
Код
// 1
IOWR(BASE, DATA);
Код
// 2
unsigned int *base_ptr = (unsigned int *)BASE;
*base_ptr = DATA;
Первый код будет работать, а второй нет (BASE - адресс какого-либо регистра).
Цитата(x66 @ Jan 20 2015, 14:00)

вот код примера
Но это и есть использование указателя для обращения к памяти (тут всё ок), речь шла про настройку регистров.
Например код для GPIO:
Код
// 1
unsigned int *gpio_data_ptr;
unsigned int *gpio_direction_ptr;
gpio_data_ptr = (unsigned int) GPIO_OUT_BASE;
gpio_direction_ptr = (unsigned int) (GPIO_OUT_BASE + 1);
*gpio_data_ptr = 1;
*gpio_direction_ptr = 1;
может не работать.
А 100% рабочий вариант:
Код
// 2
IOWR_ALTERA_AVALON_PIO_DATA(GPIO_OUT_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DIRECTION(GPIO_OUT_BASE, 1);
Подразумевалось что код и 1 и 2 должен выполнить одно и то же, на на деле - нет. Для других процов первый вариант кода будет работать - для Ниоса НЕТ!
Golikov A.
Jan 20 2015, 11:51
ох...
Цитата
Первый код будет работать, а второй нет (BASE - адресс какого-либо регистра).
а так?
volatile unsigned int *base_ptr = (unsigned int *)BASE;
*base_ptr = DATA;
doom13
Jan 20 2015, 11:55
Цитата(Golikov A. @ Jan 20 2015, 14:51)

а так?
volatile unsigned int *base_ptr = (unsigned int *)BASE;
*base_ptr = DATA;
И каким образом volatile тут будет влиять на то, чтоб запись данных шла мимо кэша? Знающие люди советовали
другое.
Golikov A.
Jan 20 2015, 12:01
раскройте вы макрос и поглядите что в нем, я не спорю что у всех может быть все по своему, но не думаю что альтера себе враг.
вот ксалиновский макрос
Код
XGpio_WriteReg(BASE, XGPIO_DATA_OFFSET, Data);
который на самом деле
Код
#define XGpio_WriteReg(BaseAddress, RegOffset, Data) \
XGpio_Out32((BaseAddress) + (RegOffset), (u32)(Data))
который на самом деле
Код
#define XGpio_Out32 Xil_Out32
который на самом деле
Код
#define Xil_Out32(Addr, Value) \
(*(volatile u32 *)((Addr)) = (Value))
то есть эта обычная запись по адресу, но с принудительным указанием того что он valotile
Цитата
И каким образом volatile тут будет влиять на то, чтоб запись данных шла мимо кэша? Знающие люди советовали другое.
я и не утверждаю что valotile на это повлияет и я видел что пишут другие люди. Нету у меня среды альтеры, потому не могу макрос поглядеть, и прошу вас его показать.
В ксалинксе периферия вешается в не кешируемую область памяти, неужели ниосы до этого не догадались? Так делают на всех процах.
А так как я правды не знаю, то и прошу раскрыть макрос
doom13
Jan 20 2015, 12:24
Цитата(Golikov A. @ Jan 20 2015, 14:58)

С Вашим примером всё понятно, но тут всё немного не так. Альтеровский макрос гарантирует, что запись идёт мимо кэша, т.е. помимо записи по указателю должно быть что-то ещё.
Макрос максимум могу посмотреть до __builtin_stwio(void *, unsigned int), а это ни есть запись по указателю.
Цитата(krux @ Jan 20 2015, 14:00)

http://www.altera.com/literature/hb/nios2/n2sw_nii52007.pdfдля данных есть такой метод как Bit-31 Cache Bypass для Nios II/f
To Golikov A.
вот это правильный документ, можете просмотреть, там есть описание того, что использование макросов из BSP позволяет обойти кэш о чём и шла речь. Т.е. это не равнозначно обращению к регистру через указатель.
Golikov A.
Jan 20 2015, 12:28
ну пипец ваша альтера

....
этож надо было придумать отдельные инструкции записи мимо кеша. Так за этим еще следить надо чтобы кеш был всегда синхронен с памятью под ним...
а вот явно указано
Цитата
Declaring a C pointer volatile does not make pointer accesses bypass the data cache.
The volatile keyword merely prevents the compiler from optimizing out accesses
using the pointer. This volatile behavior is different from the methodology for the
first-generation Nios processor.
что срали они на понятие изменяемый%) и просто оптимизацию отключают и рады)
doom13
Jan 20 2015, 12:30
Цитата(Golikov A. @ Jan 20 2015, 15:27)

ну пипец ваша альтера

....
этож надо было придумать отдельные инструкции записи мимо кеша. Так за этим еще следить надо чтобы кеш был всегда синхронен с памятью под ним...
т.е. вся дискуссия была для того, чтобы Вы сказали, что Альтера == дураки? смелое заявление
Golikov A.
Jan 20 2015, 13:12
Цитата
т.е. вся дискуссия была для того, чтобы Вы сказали, что Альтера == дураки? смелое заявление
я сказал пипец ваша альтера, дураки ли они не знаю...
мне дисскусия была полезна, я теперь знаю что волатаил с альтерой не поможет и что у нее спец команды, и что перифирия в кеше (последние не 100% но косвенно так).
А вам не знаю...
doom13
Jan 20 2015, 13:41
Цитата(Golikov A. @ Jan 20 2015, 16:12)

я сказал пипец ваша альтера, дураки ли они не знаю...
мне дисскусия была полезна, я теперь знаю что волатаил с альтерой не поможет и что у нее спец команды, и что перифирия в кеше (последние не 100% но косвенно так).
А вам не знаю...
Хороший подход. Не зная, как оно устроено, Вы утверждали обратное, советовали не вводить человека в заблуждение,
потом сказали - "узнал много нового"
Golikov A.
Jan 20 2015, 16:28
не надо передергивать
я говорил что никакой магии нет, и что любой макрос может быть заменен конструкциями С языка, потому что в конечном итоге он записан при помощи их.
А также я говорил что иногда есть выгода от прямого обращения без макроса. И даже кешированные регистры можно менять через указатель если хочется, просто в конце задания режима надо дернуть слить кеш!
Ну в целом это не важно хихикайте дальше
Возник еще такой вопрос: во время переключения DDR2 с чтения на запись и наоборот имеются тайминги, и как их учесть программно, т.е. у меня есть постоянно приходящие данные, которые записываются в DDR2, в нужные моменты времени эти данные считываются из DDR2, и хочу узнать можно ли программно отследить данные в этот маленький момент времени между переключениями ОЗУ.
doom13
Jan 23 2015, 08:39
Цитата(x66 @ Jan 23 2015, 10:47)

Возник еще такой вопрос: во время переключения DDR2 с чтения на запись и наоборот имеются тайминги, и как их учесть программно, т.е. у меня есть постоянно приходящие данные, которые записываются в DDR2, в нужные моменты времени эти данные считываются из DDR2, и хочу узнать можно ли программно отследить данные в этот маленький момент времени между переключениями ОЗУ.
Для программы Nios у Вас будет что-то типа memcpy() или цикл, "никаких маленьких моментов времени тут нет". Если хотите разгрузить процессор на время записи/чтения данных - используйте одно из ядер DMA/SgDMA/mSgDMA.
Цитата(doom13 @ Jan 23 2015, 11:39)

Для программы Nios у Вас будет что-то типа memcpy() или цикл, "никаких маленьких моментов времени тут нет". Если хотите разгрузить процессор на время записи/чтения данных - используйте одно из ядер DMA/SgDMA/mSgDMA.
я планировал на время чтения из DDR2 производить запись входных данных в on-chip memory. Как я понял программно отследить данные на время таймингов переключения не получится
doom13
Jan 23 2015, 08:54
Цитата(x66 @ Jan 23 2015, 11:50)

я планировал на время чтения из DDR2 производить запись входных данных в on-chip memory. Как я понял программно отследить данные на время таймингов переключения не получится
Смотрите в направленни описанных ядер, поможет одновременно читать/писать данные и использовать процессор.
Цитата(doom13 @ Jan 23 2015, 11:54)

Смотрите в направленни описанных ядер, поможет одновременно читать/писать данные и использовать процессор.
Проблема DDR2 памяти в том, что она работает либо на чтение либо на запись. Данные приходят постоянно, а чтение происходит по запросу пользователя, т.е. может быть и раз в минуту, час. Объем данных для чтения 1.2 Мбайт. Поэтому сразу если выводить данные, то накопятся входные данные, а их терять нельзя. Решил использовать два on-chip memory и по кусочкам выводить эти 1.2Мбайта данных. Может есть какой то другой способ реализации?
doom13
Jan 23 2015, 11:16
Цитата(x66 @ Jan 23 2015, 12:02)

Проблема DDR2 памяти в том, что она работает либо на чтение либо на запись. Данные приходят постоянно, а чтение происходит по запросу пользователя, т.е. может быть и раз в минуту, час. Объем данных для чтения 1.2 Мбайт. Поэтому сразу если выводить данные, то накопятся входные данные, а их терять нельзя. Решил использовать два on-chip memory и по кусочкам выводить эти 1.2Мбайта данных. Может есть какой то другой способ реализации?
Тут ещё про шину avalon почитайте, если два устройства будут стучаться к DDR, она должна будет разрулить время доступа для каждого из устройств.
Golikov A.
Jan 23 2015, 11:59
Вам FIFO надо.
Данные поступают в FIFO а оттуда в DDR, через какой либо DMA контроллер.
Если данные нужны кому-то еще вы их читаете из ДДР, это приостанавливает DMA контроллер, и данные на время задержек падают в FIFO.
Ничего руками разруливать не надо, потому что проц не долбиться в шину постоянно (хотя может НИОС опять по чудному сделан, но надеюсь что нет). Вот и пока проц делает что-то еще, ДМА сам займет шину и успеет положить еще кусочек. Систему надо строить именно на таком принципе. Кстати ДДР контроллер разьве изначально не 2 портовый?
Вам надо перейти на следующий уровень абстракции, надо забыть про то какая у вас память, это забота контроллера, вы же не собираетесь еще сами следить за тем вовремя ли он подает ревреши, я надеюсь%)... Так же забота контроллера обеспечивать доступ к памяти по нескольким портам, во всяком случае у ксалинкс контроллер точно несколько портовый с арбитражем, наверяка у вас тоже, если это не так, то надо делать свой контроллер - арбитр, но не лезть к памяти напрямую, это дело контроллера памяти.
Обратите внимание что контроллер памяти ДДР - это не что-то собранное из вентилей ПЛИС, а отдельная область, готовый блок, слишком там все по таймингам не просто.
doom13
Jan 23 2015, 12:03
Цитата(Golikov A. @ Jan 23 2015, 14:59)

Обратите внимание что контроллер памяти ДДР - это не что-то собранное из вентилей ПЛИС, а отдельная область, готовый блок, слишком там все по таймингам не просто.
Это уже от ПЛИС зависит, может быть и на логике собран.
Golikov A.
Jan 23 2015, 17:44
Чего то мне говорит что начиная с ддр2, уже не может, но могу и ошибаться...
doom13
Jan 23 2015, 19:27
Цитата(Golikov A. @ Jan 23 2015, 20:44)

Чего то мне говорит что начиная с ддр2, уже не может, но могу и ошибаться...
У Альтеры даже для DDR3 можно ставить контроллер на логике. Лучше конечно хардовый, но это от FPGA будет зависеть. При генерации IP-ядра выбирается, какой контроллер будем ставить.
Golikov A.
Jan 23 2015, 21:48
смело...
doom13
Jan 24 2015, 12:03
Xilinx MPMCИ у Xilinx вроде давно уже есть контроллер памяти на логике, поддержка DDR3 и LPDDR2 в наличие... Про использование хардовых MCB нигде не говорится
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.