Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Контроллер памяти DDR2 для Altera Cyclone
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
Hoodwin
Вот хочу поднять тему о принципах построения контроллера DDR2 памяти для Altera Cyclone. На данный момент делаю его для Cyclone 3. Но суть то как раз в том, что в отличие от альтеровских коров он написан просто на VHDL с использованием только IEEE.numeric_std. И поэтому он в принципе универсален, может применяться для Spartan, например.

Собственно интерес возник вот по какой причине. С самого начала продвижения DDR в FPGA альтеровцы нагородили там какую-то специальную поддержку DDR прямо в IOE. И вот, апофеоз всех их страданий, в Cyclone 3 руководство по применению контроллера - увесистый документ, объясняющий, в частности, что для реализации правильной времянки памяти нужно чуть ли не 5 выходов PLL, причем для простого циклона -С8 можно рассчитывать на тактовую частоту только около 133 МГц (По крайней мере визард больше не дает). И это при том, что максимальная частота самого Cyclone III (и даже Cyclone II) ограничена значением в 402 МГц. А, следовательно, даже лобовое решение, когда DDR эмулируется на удвоенной частоте, должно дать реализацию в 200 МГц даже для speed grade 8. Причем для этого потребуется весьма простая PLL с тремя выходами, и в настройке такое решение весьма неприхотливо. Фазы можно двигать с помощью настроек PLL, а на выводах не нужны никакие DDR опции, что освобождает от мучительного размещения выводов по группам DQ/DQS, как это было раньше.

Ну вот исходя из этих соображений я и сел рисовать такой контроллер, с целью проверить, какова будет в итоге у него предельная частота. Ограничения собственно два.
1) Удастся ли логику всего контроллера реализовать с частотой 200 МГц.
2) Удастся ли реализовать входную и выходную часть шины данных с переходом 32бита*200МГц в 16бит*400МГц.

Еще до конца не доделал, но предварительно удалось. Проект бегает в ModelSim'е с двумя моделями, от Micron и от Samsung, правда данные там пока автосинтезируемые, но в правильных местах. При этом квартус собирает это и дает нормальные частоты даже для C8, 201 МГц для контроллера и 402 для данных (и то, - это программное ограничение, без указания явных проблемных путей).

Уже недолго осталось, чтобы на железке проверить, но все-таки кажется странным, что же это за столбовая дорога у Альтеры такая, что столько возни, столько правил и такой чахлый результат.
"Гора родила мышь!"

У кого какие мысли?

Cordroy
Цитата(Hoodwin @ Jun 24 2011, 20:33) *
[...] но все-таки кажется странным, что же это за столбовая дорога у Альтеры такая, что столько возни, столько правил и такой чахлый результат.
"Гора родила мышь!"

У кого какие мысли?


По-моему, одна из причин пользоваться альтеровскими контурами для DDR2 (DQ/DQS groups, dynamic termination, автокалибрация, DLL's etc.) это гарантированная устойчивость к вариациям по температуре, процессу, погрешностям времянки, и т. п.

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

В любом случае - желаю успеха с проектом, вещь полезная. Сам уже намучался и возненавидел альтеровские IP и их документацию sm.gif
Hoodwin
Немного поторопился я с п.2. 402 МГц не получается, если добавляю опцию Fast Output(enable) Register. Причем возникает довольно странная картина, проблема с частотой связана с разделами Minimum Pulse Width Requirement (High/low).

Код
-0.178 ns    1.428 ns    1.250 ns    ddr2_pll:mem_pll|altpll:altpll_component|ddr2_pll_altpll2:auto_generated|wire_pll1_clk[1]    mem1_data[2]~reg0


Квартус пишет, что он зарубил частотку до 350 МГц по причине минимальной длительности тактового импульса. Смотрел даташит и так и не смог понять, откуда там такое ограничение взялось? Получается, что несмотря на 402 МГц внутри кристалла на триггеры в IOE нельзя подавать частоту выше 350МГц? Что-то я с таким ограничением раньше не встречался, где-нибудь подробнее оно описано?
des00
Цитата(Hoodwin @ Jun 25 2011, 02:13) *
Что-то я с таким ограничением раньше не встречался, где-нибудь подробнее оно описано?

раздел даташита Maximum Input & Output Clock Toggle Rate
BSACPLD
Кстати, а возможно ли описывая контроллер исключительно на HDL (без задействования мегафункций) заставить Quartus укладывать сигналы в DQ/DQS группы?
Shtirlits
Насколько мне известно, ни в VHDL, ни в Verilog*, нет выразительных средств для управления размещением и разводкой. Есть инструменто-зависимые средства работы с атрибутами, позволяющие почти не пользоваться дополнительными файлами констрейнов.
gosu-art
Мне тоже в скором времени понадобиться контроллер ДДР2, но только для Актела! crying.gif
Hoodwin
Цитата
Кстати, а возможно ли описывая контроллер исключительно на HDL (без задействования мегафункций) заставить Quartus укладывать сигналы в DQ/DQS группы?


Так я и начал разговор с того, что это не нужно. Во всяком случае в этом заключается идея альтернативной реализации. Группы DQ/DQS - это наследие от первых циклонов и первой реализации DDR, у которой сигнал DQS был тактовым в обе стороны. В результате возникала привязка группы DQ к DQS, поскольку тактирование входных регистров в IOE от общего DQS было реализовано аппаратно. Это нагородило кучу проблем, о которых написано в свежих руководствах. Например, когда DQS был тактовым сигналом, то нужно было правильно его блокировать, поскольку при переключении с выхода на вход были возможны выбросы, которые приводили к тому, что данные защелкивались лишний раз. В DDR2 ситуация иная. Входной DQS выровнен с данными и служит просто селектором регистра приема. Если явно работать на двойной частоте, то проблема групп вообще уходит, поскольку все линии данных могут работать независимо, по внутреннему клоку.

Мне доводилось делать несколько проектов с современными DSP от TI, где тоже применяется память DDR2. Причем я делал там и схему, и плату, и программирование контроллера DDR2 памяти в самом DSP. И доподлинно известно и проверено на практике, что на частотах до 250 МГц и близком расположении памяти к контроллеру вся эта задачка решается в лоб, не требует никаких согласований длины цепей, не требует ODT, и т.п. Причем TI в итоге в этом честно сознался и просто написал доки, где сказано, что делайте по-простому, и будет хорошо. А альтеровцы нагородили самый сложный вариант, объявили его интеллектуальной собственностью, и в итоге получили какую-то абсолютно жалкую производительность. Таких тормозных чипов DDR2, какие нужны для их контроллеров, сейчас уже и не производится. Даже самый медленный чип уже от 333 МГц, а контроллер только до 133 МГц тянет. Все эти доводы и наводят на мысль попробовать сделать свой вариант.

Цитата
По-моему, одна из причин пользоваться альтеровскими контурами для DDR2 (DQ/DQS groups, dynamic termination, автокалибрация, DLL's etc.) это гарантированная устойчивость к вариациям по температуре, процессу, погрешностям времянки, и т. п.

Вообще, муть это все. Об этом можно начинать задумываться, когда частоты существнно выше 200МГц. Вариации по температуре можно смоделировать, так как квартус умеет аннотировать задержки для разных температур. Для прогнозируемой работы схемы все равно нужно использовать триггеры в IOE.

Единственное серьезное ограничение связано с токовыми способностями банков и вследствие этого шумами, создаваемыми переключающимися выводами адреса и управления. Квартус не дает плотно упаковать в один банк и шину данных, и шину адреса. Поэтому для проверки схемы соединений FPGA с DDR2 SDRAM мне приходилось сначала собирать простую болванку, в которой есть все сигналы, им назначены правильные I/O стандарты и все они как-нибудь шевелятся на предельной частоте. И в итоге часть выводов банка приходится оставлять пустыми.


Цитата
раздел даташита Maximum Input & Output Clock Toggle Rate


Сейчас специально выкачал весь cyclone3_handbook.pdf и не вижу там указанного раздела. Что я делаю не так, и как его искать? Проглядывал раздел по имени Periphery Performance, там, во-первых, нет внятного параметра максимальной частоты для отдельно взятого IOE, а, во-вторых, вообще ни для одного параметра нет предельного значения в 350 МГц, который выдает мне квартус. Чудеса...
Sergey_Bekrenyov
Цитата(Cordroy @ Jun 25 2011, 12:06) *
По-моему, одна из причин пользоваться альтеровскими контурами для DDR2 (DQ/DQS groups, dynamic termination, автокалибрация, DLL's etc.) это гарантированная устойчивость к вариациям по температуре, процессу, погрешностям времянки, и т. п.

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

В любом случае - желаю успеха с проектом, вещь полезная. Сам уже намучался и возненавидел альтеровские IP и их документацию sm.gif


Присоединяюсь к ненавистникам альтеровских IP и их документации sm.gif

Делал интерфейс с DDR на Virtex-4 года 3 назад. Запустил за неделю. С альтерой бился 3 месяца - читал, пробовал, снова читал. В результате перед самой сдачей схемы обнаружил еще одни группы - VREF, которые не могут тянуть более 9 ножек. В итоге все работает, однако на 150 Мгц Cyclone-IV 7
Купил себе отладочную плату на Spartan-6 с железным контроллером памяти. Вот это сказка!
vadimuzzz
Цитата(Hoodwin @ Jun 25 2011, 21:22) *
Сейчас специально выкачал весь cyclone3_handbook.pdf и не вижу там указанного раздела. Что я делаю не так, и как его искать?

это сейчас мода такая у альтеры, даташиты укорачивать. сейчас они пишут, что смотрите сообщения от квартуса, они самые точные. в аттаче хендбук от 2008 года, там этот раздел еще есть (стр. 406).
BSACPLD
to Hoodwin
Я сейчас тоже озаботился написанием собственного контроллера DDR2.
Может, скинете мне на почту (BSA-one(собака)яндекс.ру) HDL код вашего контроллера.
Я хочу попробовать взять его за основу. Правда, писать собираюсь на SV.
Hoodwin
vadimuzzz
Спасибо, посмотрел. Странно, но там частота указана 300 МГц, а квартус дает все 350.

Буду доделывать тогда для C8 под 175 тактовую МГц. Но там еще есть заморочка с предельной частотой входных триггеров в IOE. 175 Всяко больше, чем 133.
Shtirlits
Там еще заморочка с setup/hold и оставшимся окошечком для данных.
Для наглядности в модели стоит приделать нечто превращающее данные в 'U' во время setup и для контроля добавить проверку на hold.

Со скепсисом схрумкал еще попкорна.
des00
Цитата(BSACPLD @ Jun 26 2011, 01:43) *
Я сейчас тоже озаботился написанием собственного контроллера DDR2.

тоже что ли плюнуть на все и потратить недельку на переписку hssdrc в hsd2drc контроллер wacko.gif
warrior-2001
Во многих проектах использую Альтеровские контроллеры DDR & DDR2. Один раз помучался - и теперь просто тиражирую.
Было бы интересно взглянуть на самописные архитектурно независимые контроллеры. Есть возможность проверить на arria GX & arriaII GX в боевых проектах с загрузкой вплоть до 100% ПЛИС.
Пока что я присоединюсь к Shtirlits.

Цитата(Shtirlits @ Jun 26 2011, 13:00) *
Со скепсисом схрумкал еще попкорна.

torik
Тут уже трое берутся написать свой DDR2 контроллер. А в результате ваши труды станут достоянием народа? Документация хоть краткая будет?
des00
Цитата(torik @ Jun 27 2011, 04:52) *
Тут уже трое берутся написать свой DDR2 контроллер. А в результате ваши труды станут достоянием народа? Документация хоть краткая будет?

согласен, как то мало я вижу чужих открытых сорцов %(
Hoodwin
Цитата
Тут уже трое берутся написать свой DDR2 контроллер.


ну, не так. Двое подумывают, а я то его уже практически написал.

Вот времянка памяти из моделсима. Это срез сигналов на выводах памяти. Частота 175 МГц.
Тест пока довольно простой, записываются 4 слова подряд, затем они читаются назад. Это продолжается в цикле по всей памяти.
На диаграмме показан переход от чтения к записи. Модель памяти взята у микрона, а контроллер синтезирован для EP3C16F484C8.
Контроллер занял 575 LCELLs и 352 регистра.

Осталось доделать прием данных с шины памяти.

Несколько комментариев к времянке. Вопреки сомнениям скептиков на ней хорошо видно, что окошки данных там ОГРОМНЫЕ, туда "боинг можно посадить". При этом, DQS вообще всегда стоит посередине данных, потому что они синхронизированы по общему удвоенному клоку, только DQ переключаются по заднему фронту, а DQS - по переднему. Времянка потянула бы и бОльшие частоты, если бы не ограничения самого циклона на скорость IOE. Сравните это, например, со стандартным ALTMEMPHY, где времянка DQS базируется на фазовом сдвиге PLL, а мультиплексор в IOE вносит фиксированную задержку, которая мешает свободно масштабировать частоту, не ковыряя существенно фазы всех клоков. В данном случае используется всего 3 клока: 1) основной клок на 175 Мгц, 2) удвоенный клок на 350 МГц, сфазированный с основным, 3) внешний клок 175 МГц, сдвинутый относительно основного по фазе так, чтобы соответствовать окну данных. Фактически нужно играть только одним этим клоком, и это абсолютно тривиально.
des00
Цитата(Hoodwin @ Jun 27 2011, 06:38) *
ну, не так. Двое подумывают, а я то его уже практически написал.

отлично, ждем сорцов disco.gif . давно я не реверсил контроллеры памяти, даже на свой опенсорсный проект времени нет %(
Hoodwin
Интересно, а кто-нибудь задействовал всякие фичи DDR2? вроде:
1) Burst Length = 8.
2) Additive latency > 0.
3) Read/write with Auto precharge и т.п.

Я пока не делал этого, так как у меня в применениях, в основном, потоковое чтение памяти для генерации видео формата HD.
Может и не делать их вовсе?
torik
Цитата
ну, не так. Двое подумывают, а я то его уже практически написал.

Не вижу ответа на главный вопрос, как там с открытостью проекта?
Hoodwin
Torik
1) Это совсем не главный вопрос, перечитайте начало темы.
2) Мой проект значительно выходит за рамки одного лишь контроллера памяти, и он не является открытым.

des00
Я опубликую исходный текст контроллера DDR2 через некоторе время, если объявятся желающие его протестировать на разных ПЛИС, желательно - разных семействах разных производителей. Причем не просто протестировать, но и отписать сюда о результатах.

Очевидно, что публиковать непроверенный модуль не очень хорошо, а проверка у меня запланирована на конец недели (и возможно следующую неделю), когда я сделаю код для потребителей данных из памяти. До этого момента можно только в симуляторе гонять тестовые времянки.
Hoodwin
Вот еще вопрос какой.
Вот есть такой основной параметр у памяти CAS latency. Имеет ли смысл городить контроллер, поддерживающий динамическую смену этого параметра?

Соображения такие. Частота IO у Cyclone по меркам DDR2 памяти низкая, то есть на этой частоте CAS Latency выйдет от 2 до 4. 2 трудно поддерживать по соображениям ускорения конвейера. 3 или 4 - в самый раз. Смысл делать 5, 6 или 7 практически нулевой. Если же можно явно описать, что синтезируем только для CAS latency = 3, то можно сэкономить память тэгов и еще кое-что по-мелочи.
warrior-2001
ИМХО параметр синтеза для CAS latency - самое то.
Меня вот какой вопрос интересует - а какой локальный интерфейс вы используете в своём ddr2 контроллере?
Если это что-то самописное - то не факт, что я смогу оперативно проверить ваш контроллер. Как то не особо хочется городить переходник между самописным локальным интерфейсом и AMBA или Avalon. Если всё же это так - то нужно хотя бы простейшее описание этого интерфейса. Проще всего - если это будут выводы двухклоковых фифошек. Тогда и переходник писать - дело нехитрое, и доки не надо никакой.
Hoodwin
Интерфейс такой:
Код
  ready     : out std_logic;  -- controller is ready to accept command
  ad        : in  std_logic_vector(CTL_WIDTH_ADDR-1 downto 0);
  wr        : in  std_logic;  -- write strobe
  wr_tag    : in  std_logic_vector(TAG_WIDTH-1 downto 0);
  di        : in  std_logic_vector(MEM_WIDTH_DATA*2-1 downto 0);
  di_ena    : in  std_logic_vector(MEM_WIDTH_DATA/4-1 downto 0);
  di_get    : out std_logic;  -- input data read (e.g. from FIFO)
  di_tag    : out std_logic_vector(TAG_WIDTH-1 downto 0);
  rd        : in  std_logic;  -- read strobe
  rd_tag    : in  std_logic_vector(TAG_WIDTH-1 downto 0);
  do        : out std_logic_vector(MEM_WIDTH_DATA*2-1 downto 0);
  do_put    : out std_logic;  -- output data vaild
  do_tag    : out std_logic_vector(TAG_WIDTH-1 downto 0);


Пояснения
- ready - сигнал готовности интерфейса к приему команды rd или wr. При любый условиях после приема команды ready пропадает как минимум на один такт, что позволяет делать мультиплексор входной команды и адреса, дающий задержку в 1 такт. Такая задержка неизбежно возникнет. если будет потребность в скоростном многопортовом доступе к памяти.
- ad - адрес текущей операции.
- wr - признак команды записи. Не должен выдаваться одновременно с rd.
- rd - признак команды чтения. Не должен выдаваться одновременно с wr.
- wr_tag - метка команды записи. См описание меток ниже.
- rd_tag - метка команды чтения. См описание меток ниже.
- di - данные для записи. Считываются при активном стробе чтения di_get.
- di_ena - признаки разрешения на обновление данных. Управляют маской при записи. значение '1' разрешает запись соответствующего байта.
- di_get - строб чтения. Возникает через некоторое время после того, как контроллер принял команду записи. Длится два такта для BL=4, и 4 такта для BL=8.
- di_tag - метка входных данных. Выдается синхронно с di_get и позволяет установить, от какого источника фактически нужны данные в данный момент.
- do - данные, прочитанные из памяти, активны под стробом do_put.
- do_put - строб готовности данных чтения. Возникает некоторое время после того, как контроллер принял команду чтения. Длится два такта для BL=4, и 4 такта для BL=8.
- do_tag - метка выходных данных. Выдается синхронно с do_put и позволяет установить, кому предназначаются данные в данный момент.

Общий принцип работы такой. Контроллер устанавливает сигнал ready и ожидает команды. Команда считается принятой, если в одном такте либо ready='1' и rd='1', либо ready='1' и wr='1'. В этом такте должны вместе с командой должны быть указаны также адрес ad, метка чтения rd_tag (rd='1') или метка записи (wr='1'). Приняв команду контроллер снимает ready и планирует команду на внешнем интерфейсе, параллельно проверяя всякие внутренние события: необходимость делать precharge, активацию новой строки, ожидание на переключение направления шины, регенерацию и т.п. Как только внутреннее состояние контроллера доберется до выдачи непосредственной команды на шину, контроллер формирует сигнал di_get для команды записи и забирает данные пользователя, которые затем попадают на шину. При команде чтения с некоторой задержкой формируется строб do_put.

Метки
Пролистывал документ от Altera, не видал у них такой фичи. Но себе сделал. потому как удобно. Часто память требует разделения между разными потребителями. Например, у меня видеопамять требует доступа на чтения со стороны подсистемы формирования развертки, полного доступа стороны процессора, а также, в перспективе, доступа на запись со стороны видео-ускорителя. Конвейерный характер доступа к памяти, а также довольно большие задержки конвейера приводят к тому, что команды разных потребителей порождают непредсказуемо задержанные фазы передачи данных и для чередования потребителей в такой ситуации приходится ждать, пока контроллер полностью освободит не только командную шину (rd, wr, ad), но и шины данных (di и do). Проверка этих условий весьма утомительна, так как, вообще говоря, занятость шины данных неизвестна. Можно было бы учитывать, сколько команд выдано. и сколько потом фаз данных состоялось, но это муторно, это не наш метод. Вместо этого контроллер позволяет метить команды с помощью тегов и гарантирует, что система тэговых задержек синхронизирована с шиной самой памяти, так что в итоге разные потребители могут просто свалить в кучу все команды и получат назад пакет данных, в котором выходные данные помечены ровно так же как и входная последовательность команд. например, если читатель выдал команду rd='1', rd_tag=2, то его данные пойдут под стробом do_put and do_tag=2, причем совершенно не важно, с какой задержкой возникнет строб. Это достаточно удобно. Вам просто достаточно сделать автомат, планирующий команды и правильно подключить источники/приемники данных. В особенности это хорошо сочетается с FIFO, поскольку там нет явного адреса, но и с чтением в память тоже сочетается без сложностей.

В заключение привожу времянку, как это выглядит. Обратите внимание на движение rd_tag -> do_tag & do_put и на wr_tag -> di_tag & di_get.
warrior-2001
Цитата(Hoodwin @ Jun 30 2011, 17:27) *
Метки
Пролистывал документ от Altera, не видал у них такой фичи. Но себе сделал. потому как удобно. Часто память требует разделения между разными потребителями.


Вообще-то Альтера гарантирует, что последовательность команд на входе контроллера будет сохранена при обращении к памяти. Вы эту работу перекладываете на пользователя? Тоесть если на локальном интерфейсе я сперва заказал чтение адреса Х, а потом записал по тому же адресу, то возможна ситуация, когда данные сперва запишутся, а потом прочитаются?
В принципе интерфейс понятен и без особых проблем ложится на стандартные локальные интерфейсы. А Метки вообще можно прикрутить к AMBA AXI, что ускорит обмен на интерконнекте.
Timmy
Может быть, имеет смысл разделить на отдельные модули командный блок и блок передачи данных? Иначе этот контроллер будет Cyclone 3 only. Блок передачи данных нельзя нормально сделать архитектурно независимым, зато он достаточно тривиален по логике и его можно спокойно портировать. А командный блок по логике нетривиален, зато архитектурно независим.
Если контроллер не изменяет порядок выполнения команд относительно порядка запросов, то стоит также вынести в отдельный модуль управление тэгами.
Полезно предусмотреть команды с автозакрытием банка - так будет работать быстрее, например, для каналов DMA, делающих запросы не очень часто.
Что касается подключения к шинам типа Avalone, Wishbone и тд, то мосты для них могут написать те, кому это больше всех надоsm.gif, и потом можно добавить к проекту.
Hoodwin
Цитата(warrior-2001 @ Jul 1 2011, 11:53) *
Вообще-то Альтера гарантирует, что последовательность команд на входе контроллера будет сохранена при обращении к памяти. Вы эту работу перекладываете на пользователя?


Нет, не так. Последовательность команд и у меня сохраняется, но только это та последовательность, которая имеется на входе контроллера. Просто если эти команды формируют разные потребители, скажем, процессор, и контроллер DMA, то им трудно отслеживать, например, кто именно в данный момент должен давать данные на шину памяти, там же конвейер. Тэги идут по конвейеру так же как и команда, поэтому они позволяют быстро разобраться, кто должен давать данные или получать их. Если же вопрос был о том, что будет если процессор и контроллер DMA копошатся в одних и тех же адресах, то это действительно проблема пользователя, как там выстроить общий порядок команд к памяти. Но это всеобщая проблема. Имея довольно большой опыт с DMA в DSP от TI, pci bus mastering и т.п. могу сказать, что нигде такое разделение не делается на уровне контроллера доступа к шине. Обычно софт следит за разделением адресных пространств для разных подсистем.

Цитата
Тоесть если на локальном интерфейсе я сперва заказал чтение адреса Х, а потом записал по тому же адресу, то возможна ситуация, когда данные сперва запишутся, а потом прочитаются?

Нет, такого не будет никогда.

Timmy
Можно подробнее, что за блоки? И какие связи между ними, а то я что-то пока у себя не заметил. Если имеется ввиду выделить какой-то интерфейс для IO шины данных, то я думал об этом, но пока не получилось придумать такой его интерфейс, чтобы он легко реализовывался, скажем и на fast output register + double i/o clock rate, и на DDR I/O cell за счет ее внутренних свойств. Там сразу все разъезжается по времени, меняются принципы настройки. Кроме того, я не думаю, что у Cyclone какие-то выдающиеся особенности в соотношении между предельной частотой внутри кристалла и на I/O. Даже, я бы сказал, совсем не выдающиеся. Предельная частота I/O ниже частоты внутри кристалла. Пока что все примерно сбалансировано, и частота контроллера примерно вдвое ниже частоты I/O после разводки. На более продвинутых семействах, скажем, на Stratix, где уже LUT имеет 6 входов, а не 4, и где более сложная комбинаторика будет иметь тенденцию к ускорению, частота контроллера станет больше, чем половина частоты I/O, но производительность упрется в предельную частоту I/O cell. Но мы и сейчас в нее упираемся в Cyclone 3. Если где-то это окажется не так, и контроллер будет тормознее, чем половина частоты I/O, вот тогда и будем думать, как его оптимизировать.

Управление тэгами нельзя вынести в отдельный блок, просто потому что тэги - это тот же самый конвейер команд, только напичканный не командами rd, wr, а пользовательскими битами. нет никакого смысла делать это отдельно. Можно не использовать тэги, если у используется ровно один писатель и ровно один читатель памяти, но тогда они просто вымрут при компиляции.

О командах с автозакрытием банка (а именно write/read with auto precharge) я думал, но при реализации они как-то не востребовались. Они усложняют логику команд, экономят в общей сложности 1% тактов по сравнению с отдельным precharge, но зато рубят частоту контроллера из за усложнения логики блокировки последующей команды, оно надо? Кроме того, что плохого в том, что банк после DMA останется активным? Вдруг в него кто-то еще раз обратится потом, и попадет в тот же ряд? Возможно, это имеет смысл с точки зрения низкого энергопотребления, но хочу заметить, что раз в 3.9-7.8 мкс и так возникает событие регенерации памяти, которое требует закрыть вообще все банки. Если после этого никто в них не лезет, то они и останутся закрытыми с низким потреблением.
BSACPLD
Докладываю о своих результатах.
Сделана инициализация и запись с Auto Precharge.
Тактовая частота 265 МГц (не DDR) в EP3SE50F780C3.
Осталось:
1. Доделать чтение.
2. Написать констрейны.
3. Проверить на железе.
4. Оптимизировать под различные виды записи и чтения (потоковая и побайтная).
Hoodwin
Судя по картинке, это пока чистая модель, откуда частота 265 МГц? Или это проверка на собираемость просто?
Еще не увидел на картинке собственно модели памяти DDR2. Там c реальной моделью много интересного еще может повылезать.
1,2. Чтение, кстати, интересный дало эффект. Оказалось, что аннотация реальных задержек в кристалле приводит к сдвигу приема данных с шины на 1 такт. В итоге, поведение модели до сборки и после сборки отличается. В пятницу проверял на железе, уперся в этот факт. Сижу вот теперь, приделываю обманку для этого.
3. А перед тем как на железе проверять, хорошо бы выдать vho + sdf и посмотреть, что за времянка получается.
4. Побайтная запись не интересна на самом деле, нужно потоковую обеспечивать. Во всяком случае, я бы выбрал потоковую...

P.S. А еще есть рефреш, который тоже не худо бы сделать sm.gif


BSACPLD
Цитата(Hoodwin @ Jul 4 2011, 16:31) *
Судя по картинке, это пока чистая модель, откуда частота 265 МГц? Или это проверка на собираемость просто?
Еще не увидел на картинке собственно модели памяти DDR2. Там c реальной моделью много интересного еще может повылезать.
1,2. Чтение, кстати, интересный дало эффект. Оказалось, что аннотация реальных задержек в кристалле приводит к сдвигу приема данных с шины на 1 такт. В итоге, поведение модели до сборки и после сборки отличается. В пятницу проверял на железе, уперся в этот факт. Сижу вот теперь, приделываю обманку для этого.
3. А перед тем как на железе проверять, хорошо бы выдать vho + sdf и посмотреть, что за времянка получается.
4. Побайтная запись не интересна на самом деле, нужно потоковую обеспечивать. Во всяком случае, я бы выбрал потоковую...

P.S. А еще есть рефреш, который тоже не худо бы сделать sm.gif

Проверка на собираемость. По моему 265 МГц для Stratix III вполне нормальная частота.
Моделирование проводилось с реальной моделью MT47H256M8HG-37IT.
CODE
`define sg37E
`define x8
`define DEBUG

`include "ddr2.v"

`timescale 1 ns / 1 ps

module test ;

parameter NUM8XCHIP = 1 ;
parameter FCLK = 100000000 ;
parameter FCLK_CPU = 50000000 ;

// CPU interface
reg clk_cpu ;
reg reset ;
// address
reg [31:0] address ;
reg load_address ;
// write
reg [NUM8XCHIP*8-1:0] data_in ;
reg wren ;
wire wr_full ;
// read
wire [NUM8XCHIP*8-1:0] data_out ;
reg rden ;
wire rd_empty ;
// DDR2 interface
// reference clock
reg clk ;
// memory interface
wire [15:0] ddr2_a ;
wire [2:0] ddr2_ba ;
wire [NUM8XCHIP*8-1:0] ddr2_dq ;
wire [NUM8XCHIP-1:0] ddr2_dqs_p ;
wire [NUM8XCHIP-1:0] ddr2_dqs_n ;
wire [NUM8XCHIP-1:0] ddr2_dm ;
wire ddr2_we_n ;
wire ddr2_ras_n ;
wire ddr2_cas_n ;
wire [NUM8XCHIP-1:0] ddr2_ck_p ;
wire [NUM8XCHIP-1:0] ddr2_ck_n ;
wire ddr2_cke ;
wire ddr2_cs_n ;
wire ddr2_odt ;

genvar i ;


initial begin
clk <= 1'b0 ;
clk_cpu <= 1'b0 ;
reset <= 1'b0 ;
address <= 0 ;
load_address <= 1'b0 ;
data_in <= 0 ;
wren <= 1'b0 ;
rden <= 1'b0 ;

#250000 ;

@(posedge clk_cpu) ;
address <= #(250000000/FCLK_CPU) 0 ;
load_address <= #(250000000/FCLK_CPU) 1'b1 ;
@(posedge clk_cpu) ;
load_address <= #(250000000/FCLK_CPU) 1'b0 ;

@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'hAA ;
wren <= #(250000000/FCLK_CPU) 1'b1 ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'hBB ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'hCC ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'hDD ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'h00 ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'h11 ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'h22 ;
@(posedge clk_cpu) ;
data_in <= #(250000000/FCLK_CPU) 8'h33 ;
@(posedge clk_cpu) ;
wren <= #(250000000/FCLK_CPU) 1'b0 ;

#10000 $finish ;
end

always begin
#(500000000/FCLK) clk <= ~clk ;
end

always begin
#(500000000/FCLK_CPU) clk_cpu <= ~clk_cpu ;
end


ddr2_ctrl #(
.NUM8XCHIP (NUM8XCHIP)
)

sys_ddr2_ctrl (
// CPU interface
.clk_cpu (clk_cpu),
.reset (reset),
// address
.address (address),
.load_address (load_address),
// write
.data_in (data_in),
.wren (wren),
.wr_full (wr_full),
// read
.data_out (data_out),
.rden (rden),
.rd_empty (rd_empty),
// DDR2 interface
// reference clock
.clk (clk),
// memory interface
.ddr2_a (ddr2_a),
.ddr2_ba (ddr2_ba),
.ddr2_dq (ddr2_dq),
.ddr2_dqs_p (ddr2_dqs_p),
.ddr2_dqs_n (ddr2_dqs_n),
.ddr2_dm (ddr2_dm),
.ddr2_we_n (ddr2_we_n),
.ddr2_ras_n (ddr2_ras_n),
.ddr2_cas_n (ddr2_cas_n),
.ddr2_ck_p (ddr2_ck_p),
.ddr2_ck_n (ddr2_ck_n),
.ddr2_cke (ddr2_cke),
.ddr2_cs_n (ddr2_cs_n),
.ddr2_odt (ddr2_odt)
) ;

generate
for (i=0 ; i<NUM8XCHIP ; i=i+1) begin:loop_8xchip
ddr2 sys_ddr2 (
.ck (ddr2_ck_p[i]),
.ck_n (ddr2_ck_n[i]),
.cke (ddr2_cke),
.cs_n (ddr2_cs_n),
.ras_n (ddr2_ras_n),
.cas_n (ddr2_cas_n),
.we_n (ddr2_we_n),
.dm_rdqs (ddr2_dm[i]),
.ba (ddr2_ba),
.addr (ddr2_a),
.dq (ddr2_dq),
.dqs (ddr2_dqs_p[i]),
.dqs_n (ddr2_dqs_n[i]),
.rdqs_n (),
.odt (ddr2_odt)
) ;
end
endgenerate

endmodule

P.S. Refresh сделан, просто он не показан.
Hoodwin
Выкладываю проект как есть.
Собрал для двух устройств:
1. Altera EP3C16F484C8
* частота - 180/360 МГц
* 750 LCELLs / 516 registers

2. Altera EP3SE50F780C3
* частота 275/550 МГц
* 332 ALUTs / 507 registers

В проекте есть модель памяти для Micron и тестбенч для прогонки простых времянок до и после компиляции.
des00
Цитата(Hoodwin @ Jul 5 2011, 04:35) *
Выкладываю проект как есть.

работа с банками красиво сделана, а вот тестбенч слишком уж дубовый biggrin.gif могу натянуть тест со своего открытого проекта, заодно и перформанс можно померить %)
Hoodwin
Чтобы потом не удивлялись, перечисляю, чего нет:
1. Нет управления сигналом ODT. Мне это пока не интересно, так как на этих частотах при коротких трассах ПЛИС-память можно работать без него на сниженных токах.
2. Нет поддержки AL > 0. Не пытайтесь настраивать EMR.AL > 0, результат будет плохой.
3. Нет поддержки burst length = 8. Для ПЛИС эта опция не имеет никаких преимуществ, по сравнению с BL = 4.
4. Нет управления Auto Precharge внутри записи-чтения.
5. Нет сделаны режимы sleep, power down.
6. Нет динамической реконфигурации памяти по числу банков, строк и столбцов.
7. Не реализован алгоритм калибровки импедансов OCD.
8. Не реализована поддержка RDQS, но и не нужна особо.

В остальном вроде бы все сделано.

Дополнение. Те кто захочет собрать на реальном железе, имейте ввиду, что заявленные частоты - это результат не только исходного текста, но и правильных настроек I/O и фаз PLL.
Пример таких настроек есть в проекте для Cyclone 3, Stratix 3. Наиболее важные настройки - Fast Input Register, Fast Output Register, Fast Output Enable Register. так же в зависимости от семейства могут потребоваться настройки Input Pin to Input register Delay, Delay from output register to Output pin, Output Enabe Pin Delay. В общем все эти настройки лучше подогнать по результатам моделирования.
Hoodwin
Новости:
1. В опубликованном коде ошибочка нашлась. В симуляторе все работало и до, и после компиляции, а на практике наблюдалось неправильное чтение, в каждом пакете был сдвиг на одно слово. Два дня ковырялся с калибровкой, чтобы не шибко зависело от разводки. Вроде победил. Понаблюдаю пока, насколько стабильно будет, если не будет рецидивов, то обновлю архивчик.
2. В процессе возни и отладки обнаружился странный глюк у самсунговской модели памяти. она почему-то не хочет работать на частоте ниже 200 МГц и ругается на tCCD violation. Чтобы обойти это бяку, пришлось оптимизировать частотку и, удалось таки достичь 200 МГц для Cyclone 3 при сборке. Рихтовкой времянок не занимался, и поэтому откатил частоту на 180 МГц.
3. Просматривая в очередной раз datasheet'ы вспомнил, что в списке недоделок не хватает еще одного момента. А именно, для 8-банковых чипов не проверяется скользящее окно tFAW, в течение которого не должно быть более 4 команд активации. У меня пока в проекте этого нет, но для порядка надо сделать.
Timmy
Цитата(Hoodwin @ Jul 6 2011, 18:26) *
1. В опубликованном коде ошибочка нашлась. В симуляторе все работало и до, и после компиляции, а на практике наблюдалось неправильное чтение, в каждом пакете был сдвиг на одно слово. Два дня ковырялся с калибровкой, чтобы не шибко зависело от разводки. Вроде победил. Понаблюдаю пока, насколько стабильно будет, если не будет рецидивов, то обновлю архивчик.

К сожалению, не могу открыть Ваш проект, так в нём стоит абсолютная ссылка на файл, которого нет в архиве. Но, если я правильно понял, там вообще не заданы IO тайминги, только частота опорного генератора. Именно в этом ваша проблема. Сигнал бегает через IO buffers около 5 ns, что и приводит к сдвигу примерно на такт. Но бегает он с переменной скоростью, поэтому статически подогнать фазу не получится. Как правильно определить констейны для подобного случая, хорошо рассказывается в блоге des00. В результате окажется, что при точном статическом подгоне фазы можно разогнаться примерно до 100МГц (на Cyclone 3). И не забываем про джиттер +-300-500ps на чипе памяти и примерно +-200ps от помех на плате.
Чтобы работать на более высоких частотах, используется достаточно хитрая динамическая система, основанная либо на чтении DQS, либо на внешнем фидбэке в PLL. Которая является существенно архитектурно зависимой, и я рекомендовал её оформлять отдельно от контроллера.

Ещё советую сделать враппер для микроновской модели SDRAM, в котором определить три параметра(x16,sg3 и ещё что-то там) и включить оригинальный файл, чтобы эти параметры не болтались в непортабельном проекте Моделсима. А то собирать этот проект в Aldec HDL слегка неудобноsm.gif.

В моём контроллере интерфейс примерно такой:
CODE
entity ddr2sdram is
generic(clk_pdiv:integer:=3; clk_pmul:integer:=20; debug:integer:=0);
port(
clk, rst:std_logic;
cmd_in:std_logic_vector(2 downto 0);
rdy_out:out std_logic;
addr:std_logic_vector(24 downto 0);
bank:std_logic_vector(2 downto 0);
tRP, tRTP, tRC, tRCD, tRAS, tWR, tWTR:integer;
CL:integer;
bank_out:out std_logic_vector(2 downto 0);
cmd_out:out std_logic_vector(4 downto 0);
addr_out:out std_logic_vector(13 downto 0);
odt_en:out std_logic;
dqs_read:out std_logic;
dqs_t_out: out std_logic_vector(1 downto 0)
);
end entity;

entity ddr2sdram_data is
generic(n_dqs:integer:=1; n_dqbits:integer := 4);
port(
clk, xclk, rclk, rst:in std_logic;
dq_en:std_logic_vector(1 downto 0);
data_in:in std_logic_vector(n_dqs*2*n_dqbits-1 downto 0);
data_out:out std_logic_vector(n_dqs*2*n_dqbits-1 downto 0);
dq:inout std_logic_vector(n_dqs*n_dqbits-1 downto 0);
dqs_en: std_logic_vector(1 downto 0);
dqs_read:in std_logic;
dqs:inout std_logic_vector(n_dqs-1 downto 0);
dm_in:in std_logic_vector(1 downto 0);
dm:out std_logic_vector(n_dqs-1 downto 0);
data_valid:out std_logic_vector(n_dqs-1 downto 0);
dqsxfer_o:out std_logic_vector(n_dqs-1 downto 0);
dqs_del:in std_logic
);
end entity;

Два модуля сцеплены всего тремя проводками dqs_t_out и dqs_read.
Hoodwin
Timmy
1. А что за файла не хваает? Моделсим какой-странный, вроде включил ему опцию soft pathnames, а он все равно полные пути лепит, причем даже после того, как я их однажды ручками переделал в относительные. Я думаю, что особого труда не составит поправить пути под себя, а вот если я файл какой-то забыл положить, то скажите, какой.
2. С констрейнами немного не так. В IO есть несколько опций для регулирования задержки сигнала от пина до входного триггера. Проблема не в том, чтобы сделать эту задержку постоянной и предсказуемой, проблема в том, что никакое значение задержки в собранном проекте не может дать прихода данных в том же такте, в каком они приходят в чистой модели. В результате пришлось добавить динамическую калибровку задержки по приходу DQS, реализовав пробное чтение в момент инициализации. Работает пока очень хорошо, и в симуляторе, и в синтезаторе. Частота - 180 МГц, но проект можно собрать и на 200 при желании.
3. А в чем проблемы со сборкой модуля в Aldec HDL? Ему же наверное также в свойствах модуля в проекте можно приписать параметры для сборки и путь к включаемым файлам?

Timmy
Цитата(Hoodwin @ Jul 11 2011, 08:00) *
Timmy
1. А что за файла не хваает? Моделсим какой-странный, вроде включил ему опцию soft pathnames, а он все равно полные пути лепит, причем даже после того, как я их однажды ручками переделал в относительные. Я думаю, что особого труда не составит поправить пути под себя, а вот если я файл какой-то забыл положить, то скажите, какой.
2. С констрейнами немного не так. В IO есть несколько опций для регулирования задержки сигнала от пина до входного триггера. Проблема не в том, чтобы сделать эту задержку постоянной и предсказуемой, проблема в том, что никакое значение задержки в собранном проекте не может дать прихода данных в том же такте, в каком они приходят в чистой модели. В результате пришлось добавить динамическую калибровку задержки по приходу DQS, реализовав пробное чтение в момент инициализации. Работает пока очень хорошо, и в симуляторе, и в синтезаторе. Частота - 180 МГц, но проект можно собрать и на 200 при желании.
3. А в чем проблемы со сборкой модуля в Aldec HDL? Ему же наверное также в свойствах модуля в проекте можно приписать параметры для сборки и путь к включаемым файлам?

1. Это не Моделсим, а Квартус, строчка конфига "set_global_assignment -name MISC_FILE "D:/Libs/VHDL/ddr2/build/build_ep3c16f484c8.dpf"".
Пути должны быть по возможности только относительные, чтобы под себя не подправлять.
2. Все некалиброванные задержки имеют допуск примерно +-30% по температуре и экземплярам кристаллов. Я не сомневаюсь, что на вашей отладочной плате всё будет работать замечательно и без строгого выполнения констрейнов, но вот пустите это в серию - и очень вероятны массовые глюки.
Калибровки только при инициализации может быть недостаточно, так как температура может меняться в ходе работы, это надо по констрейнам проверять.
3. Проблем, собственно, нет, просто лень делать лишние телодвижения, без которых легко можно было бы обойтись.
Кстати, ещё один фокус в том, что библиотека "altera_mf" у меня зовётся "lpm", видимо, мои допотопные библиотеки безнадёжно устарели.
Hoodwin
1. Ок, поправлю. Что-то раньше таких файлов не было - .dpf.
2. Ну, плата не отладочная, а вполне себе боевая. sm.gif Призводители вообще любят стращать сложными требованиями, чтобы у них IP покупали. Мне, например, не надо ставить SODIMM, у меня длина проводников DQ - от 9 до 15 мм, соответственно и задержка от 55 до 90 пс, что НАМНОГО меньше периода тактовой частоты (5500 пс). Адреса и пр. сигналы длиннее, но раза в два максимум. Емкость линий мала, поэтому и температурный уход невелик. Задержки ведь не сами по себе зависят от температуры, а косвенно. Сначала от температуры зависит проводимость каналов у транзисторов, а уже затем, в зависимости от емкости трасс, возникает задержка их перезаряда. При маленькой емкости разница проявляется лишь в наклоне фронта сигнала, но "полка" все равно остается. Так что не все так уж и мрачно. Кроме того, инициализация памяти - вещь программно управляемая, а особенно - калибровка процесса чтения. Можно ее вынести и проводить регулярно, хоть с каждым рефрешем. Кстати, это на самом деле единственное место, которое "плавает". Времянка записи вообще никак не страдает, так как она привязана к общему удвоенному клоку, а всякие там задержки в IOE от температуры зависят одновременно и практически одинаково.
3. Проблемы модели памяти - это к авторам тех моделей sm.gif У самсунга например, все в одном исходнике, но тоже параметры внешние, правда другие. У Hynix - тоже параметры, но тоже другие. Всем не угодишь, в общем.
nckkm
Цитата(Hoodwin @ Jul 5 2011, 14:35) *
Выкладываю проект как есть.
Собрал для двух устройств:
1. Altera EP3C16F484C8
* частота - 180/360 МГц
* 750 LCELLs / 516 registers

2. Altera EP3SE50F780C3
* частота 275/550 МГц
* 332 ALUTs / 507 registers

В проекте есть модель памяти для Micron и тестбенч для прогонки простых времянок до и после компиляции.

А Вы не думали выкладывать проект, скажем, на opencores.org?
Hoodwin
Цитата
А Вы не думали выкладывать проект, скажем, на opencores.org?

А смысл то какой в этом?
cioma
Больше людей смогут ознакомиться
Hoodwin
Поднимем тему еще раз.

Цитата
Было бы интересно взглянуть на самописные архитектурно независимые контроллеры. Есть возможность проверить на arria GX & arriaII GX


Цитата
могу натянуть тест со своего открытого проекта, заодно и перформанс можно померить %)


Еще кто-то хотел тестировать на всяких там стратиксах, спартанах и т.п.

В итоге то как, хоть кто-то смотрел что-нибудь? Вместо этого один флуд про 10000 строк в месяц... sad.gif

У меня работает на 180 МГц, причем стабильно от 25 до 55 градусов в процессе прогрева кристалла.

warrior-2001
Цитата(Hoodwin @ Jul 21 2011, 13:41) *
...
В итоге то как, хоть кто-то смотрел что-нибудь? ...


В теме вы писали про внесение изменений в проект.
Выложите тут последний вариант с описанием всех интерфейсов(где-то тут уже было вроде).

Я от своих слов не отказываюсь. Просто жду информации от создателя о готовности последнего рабочего релиза. wink.gif
des00
у меня времени нет, как появится тогда сделаю. там нужно будет драйверы на классах интерфейсные переписать.
Hoodwin
Выкладываю последний вариант. У меня пока работает без нареканий, уже прошел сборок 15-20 в составе большого проекта. Иногда бывают затыки в анализаторе времянок, фиттер почему-то умудряется так разместить все, что частота падает ниже желаемой, но это редко. Лечится сборкой с другим seed'ом.

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

ИДЕЯ, ОВЛАДЕВШАЯ МАССАМИ, ОБРЕТАЕТ МАТЕРИАЛЬНУЮ СИЛУ!

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

P.S.
des00

Это не времени нет, это мы все чаще существуем где-то вне времени. Раньше вон, и в школу походить, и в футбол после школы погонять, и квасу сходить попить, в игрушку поиграть, какой-нибудь бабах замутить, да даже просто книжку почитать или на всякие глупости с девчонками время было, а теперь вот ну совсем ни капли нет, да? Время, видишь ли, виновато...
tAmega
Спасибо, огромное добрый волшебник Hoodwin.
Действительно, народ у нас суровый, на похвалы скупой... sm.gif
Говорю за всех СПАСИБО!!!
des00
Цитата(Hoodwin @ Jul 22 2011, 04:23) *
P.S.
des00

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

когда количество ваших открытых проектов, приблизится к количеству проектов, которые я выложил на этом форуме, и вы будете одновременно вести 5 коммерческих проектов, тогда и вернемся к разговору о времени и обидах.
Hoodwin
Ай-я-яй, нехорошо. Выпад не по адресу.
1) Я ни кого за язык не тянул, Вы же сами попросили выложить проект и сами брались его проверить.
2) Аналогичные ответы можно увидеть и в других темах, после сделанных заявлений. Я вот привык, что обещания либо не дают, либо дают и выполняют.
3) А с чего вы взяли, что я не веду одновременно 5 коммерческих проектов? sm.gif

PS. Без обид!
BSACPLD
Выкладываю свой вариант контроллера.
Он ещё не до конца написан, но его уже можно использовать.
Ограничения текущей версии контроллера:
1. Минимальное AL + CL = 4.
2. Если меняете количество микросхем памяти нужно перегенерить FIFO под нужную разрядность.
3. Перестройку тактовой частоты нужно производить путем перегенерации PLL.
4. При использовании под другое семейство микросхем (текущий вариант сделан под Stratix III) нужно перегенерить мегафункции реализующие PHY.
5. Тайминги для gate-level моделирования в Modelsim (для Stratix III) отличаются от реальной времянки - настройку фазы нужно производить по отчёту Timing Analyzer или на реальном железе.
6. Объём записываемых/читаемых данных должен быть кратен размеру burst.

Если кто-нибудь опробует данный контроллер на реальном железе просьба отписать сюда о результатах.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.