Ссылка на первую часть Рассматриваемая нами конфигурация состоит из следующих элементов:  Является основным инструментом для общения ядра MIPSfpga с внешним миром. Из нее в модуль доступа к SDRAM поступают команды на чтение и запись информации, по ней же передаются считываемые и записываемые данные. Основная особенность: фаза адреса последующей команды совпадает по времени с фазой данных текущей команды. Лучше всего это видно на следующей диаграмме:

Краткое описание изображенных сигналов: HCLK — тактовый сигнал; HADDR — адрес, данные по которому мы хотим записать или прочитать на следующей фазе, задается мастером; HWRITE — при высоком уровне на следующей фазе должна быть произведена операция записи, выставляется мастером; HRDATA — прочитанные данные; HREADY — флаг завершения текущей операции; HWDATA — записываемые данные, выставляются мастером. Документация на шину, включая описание всех сигналов и их возможных комбинаций входит в состав пакета MIPSfpga. Основные принципы, на которых построена SDRAM, очень хорошо описаны в Главе 5 учебника Харрис-энд-Харрис [1]. Отметим главные моменты: Дальнейшее рассмотрение продолжим на примере микросхемы MT48LC64M8A2 компании Микрон. Помимо очень удобного и детального даташита компания предоставляет Verilog модель для симуляции работы с этим чипом памяти. Что, с одной стороны, значительно упрощает разработку, а с другой, позволяет, не имея отладочной платы, запустить MIPSfpga внутри симулятора и посмотреть, как ядро взаимодействует с SDRAM. Структурная схема чипа памяти представлена на рисунке ниже.  Основные элементы: Для корректной работы ОЗУ нам необходимо выполнить ряд условий. Часть из них рассматривать не будем: обеспечение температурного режим, стабильность частоты и питания, уровни сигналов (статическая дисциплина), правильная разводка на плате. В поле нашего зрения остается: Для того, чтобы предметно понимать о чем идет речь, рассмотрим, что должен сделать модуль доступа к памяти при чтении данных из ОЗУ. В качестве примера выступит случай т.н. READ With Auto Precharge — когда микросхема после операции чтения сама обеспечивает подзарядку ячеек, к которым мы обратились. Инициализация модуля (INIT), операции записи (WRITE) или автоматическая регенерация (AUTO_REFRESH) выполняются аналогичным образом, с разницей в выполняемых командах и накладываемых временных ограничениях. Ниже приведены выкопировки из даташита: таблица истинности для команд и временная диаграмма, на которой показано как производится корректное чтение данных.  Примечание: L — низкий уровень, H — высокий уровень, Х — не имеет значения, High-Z — высокий импеданс. 
Примечание: tCMS — command setup time, tCMH — command hold time, tAS — address setup time, tAH — address hold time, tRCD — active command to read, tRAS — command period (ACT to PRE), tRC — command period (ACT to ACT), tLZ — output Low impedance time, tAC — access time from clock, tOH — output data hold time, tRP — commad period (PRE to ACT). Минимальные значения этих и других параметров для разных условий приведены в документации на чип памяти. T0. Не позднее чем за tCMS до фронта CLK обеспечить наличие установивших сигналов на выводах CS#, RAS#, CAS#, WE#, DQM (далее — команда), соответствующих команде ACTIVE. Указанные сигналы не должны менять свое состояние в течении tCMH с момента фронта CLK. Не позднее чем за tAS до фронта tCLK установить на шине адреса (A[12:0]) адрес строки, на шине адреса банка памяти (BA[1:0]) — адрес банка памяти. Эти сигналы должны быть стабильны в течении tAH после фронта CLK. T1. В течении (tRCD — 1 такт) подавать команду NOP. По истечении этого временного промежутка ранее переданный адрес строки будет гарантированно сохранен в row-address latch & decoder соответствующего банка памяти, произойдет выбор одной из 8192 строк (см.структурную схему чипа). T2. Не позднее чем за tCMS до фронта CLK обеспечить ввод команды READ, не менять команду в течении tCMH с момента фронта CLK. Не позднее чем за tAS до фронта tCLK установить на шине адреса адрес столбца, на шине адреса банка памяти — адрес банка памяти. Десятый бит шины адреса устанавливается в 1 как признак того, что после чтения необходимо выполнить Auto Precharge. T3-T7. Обеспечить подачу команды NOP на все время чтения данных и не менее чем на (tRC — 1 такт) с момента подачи команды ACTIVE. T4. Спустя CL тактов (т.н. CAS Latency, CAS) считанные данные будут гарантированно присутствовать на шине данных DQ. Если более точно, то они появятся на шине спустя (1 такт + tAC) — для случая, когда CAS = 2. И будут стабильны в течении минимум tOH после фронта CLK. За это время данные с шины необходимо считать. Если смотреть на взаимодействие внутри чипа, то за время (1 такт + tAC) адрес столбца будет сохранен в column-address counter/latch, на выходе соответствующего банку памяти column decoder будет установлены сигналы, выбирающие 16 бит необходимого нам столбца, эти данные поступят в data output register и, в итоге, окажутся на шине данных (DQ[15:0]). T5-T7. Рассматриваемый нами пример предполагает, что чип памяти был настроен на выполнение пакетных операций (burst) c размером пакета BL = 4 (burst length, задается в числе других параметров командой LOAD MODE REGISTER, в текущей реализации модуля доступа к памяти он задан как BL = 2, чтобы получить 32 бита данных). По этой причине в течении последующих трех тактов column-address counter/latch будет автоматически увеличиваться на единицу, а на выход шины данных — поступит еще 3х16 бит. Необходимо учесть, что количество тактов не обязательно будет равным 8, как изображено на диаграмме (Т0-Т7) — оно должно быть увеличено в большую сторону с целью удовлетворения требований всех временных ограничений: tRCD, tRC и т.д. Требования временных ограничений выполняются с помощью Есть несколько хороших источников ( и ), которые аргументировано противопоставляют "научный" подход определения смещения фазы тактового сигнала методу "проб и ошибок". В этих документах приведен ряд формул по вычислению границ "безопасных окон", в которые нужно подставить значения задержек. После чего предлагается сместить тактовые сигналы таким образом, чтобы их фронты оказались максимально близки к центрам этих "окон". Соглашаясь с тем, что описанная методика работает, хочу обратить внимание на несколько более "ленивый" вариант этого же подхода (мне кажется, что он изображен на 12 и 20 страницах презентации, но т.к. комментариев к ней нет, то я в этом не уверен): Чтобы обеспечить точное и стабильное смещение фаз в состав системы необходимо включить PLL-модуль. Обычно я добавляю еще 3-й тактовый сигнал с частотой в 4 раза выше, чем другие и небольшим фазовым смещением — для того, чтобы использовать его в качестве тактовой частоты для логического анализатора (SignalTap) при отладке взаимодействия с памятью в железе. В этом разделе приведены диаграмма состояний конечного автомата модуля доступа к памяти, а также отдельные строчки кода модуля, описывающие процедуру чтения данных (с указанием номеров строк кода для упрощения навигации). Исходные коды модуля целиком: mfp_ahb_ram_sdram.v. В случае, если чтение скриншотов с кодом доставляет вам дискомфорт, фрагменты исходников из статьи (включая комментарии к ним) продублированы на github.  Состояния конечного автомата, описывающие процедуру чтения, полностью соответствуют тому, что было описано выше на примере диаграммы READ With Auto Precharge.  Правила перехода между этими состояниями:  Там, где необходима задержка, она заносится в регистр delay_n, нулевое значение регистра соответствует флагу DelayFinished. На статусах S_READ4_RD0 и S_READ4_RD1 производится считывание данных из шины DQ:  Кодирование команд и их вывод в зависимости от текущего состояния: 
 Все задержки являются настраиваемыми и задаются в параметрах модуля, что должно упростить портирование на другие платы, а также модификацию настроек в случае изменения частоты тактового сигнала.  [1] Учебник Дэвида Харриса и Сары Харрис «Цифровая схемотехника и архитектура компьютера»
[2] Документация на микросхему памяти MT48LC64M8A2 компании Микрон;
[3] Документация Quartus. Ядро конроллера SDRAM (перевод)
[4] SDRAM PLL Tuning (презентация)
[5] Ryan Donohue. Synchronization in Digital Logic Circuits (презентация)
[6] Документация на микросхему памяти IS42S16320D Все даташиты, статьи и презентации на которые есть ссылки в статье, доступны на github.