§ Виды памяти

Существует огромное количество разных видов памяти, которые подразделяются на категории, отделы, классы и так далее. Например, есть память SRAM (Synchronous Random Access Memory — память произвольного доступа, синхронная), она очень дорогая и выполнена обычно, на транзисторах. Транзисторная память находится в кешах, регистрах, в разного рода защелках. Это очень быстрая память, ее объем исчисляется от байт до мегабайт, а не гигабайтами, но работает такая память на скорости самого ядра процессора.
А есть более дешевая память, DRAM (Dynamic RAM), и выполнена она с использованием микроконденсаторов, которые располагаются специальным образом рядом с управляющим транзистором. Такая память менее надежна и ей требуется постоянное обновление приблизительно раз в 20 мс (миллисекунд, то есть 0.02 секунду), или, так сказать, 50 раз в секунду, но можно и чаще, и чем чаще, тем, на самом деле, лучше. Почему ей нужно обновление, понятно потому, что конденсаторы не могут долго удерживать заряд и разряжаются не только по истечении времени из-за саморазряда, но и при каждом считывании данных с них, поскольку для того, чтобы данные прочитать, приходится "слить" с конденсатора значительную часть заряда, который нужно тут же восстановить.
Поскольку у меня есть SDRAM, а не DRAM (они отличаются временем доступа к данным), то я буду рассказывать именно о том, как работает SDRAM (Synchronous DRAM). Такая память отличается от DRAM тем, что она дает гарантированный ответ через опеределенные промежутки времени и заранее заданное фиксированное количество тактов, в отличии от DRAM, которая может профурычиваться столько, сколько ей потребуется.

§ Порты памяти

Далеко не секрет, что управлять SDRAM памятью очень сложно. Для того, чтобы получить доступ к определенному слову в памяти, сначала надо выбрать банк, строку памяти, а потом уже выбрать столбец, то есть, память устроена в виде трехмерной сетки, на узлах которой находятся требуемые данные.
Теперь перечислю порты памяти SDRAM.
1output         clk,       // Генератор тактовой частоты
2output         cke,       // Chip Enabled (если здесь 1)
3output         csn,       // Chip Select  (если здесь 0)
4output [ x:0]  bank,      // Текущий банк памяти
5output [ x:0]  address,   // Адрес строки или столбца
6inout  [15:0]  dq,        // Данные (вход и выход)
7output         cas,       // Column Address Select, если 0, выбран столбец
8output         ras,       // Row Address Select, если 0, выбрана строка
9output         we,        // Write Enabled, если 0, то запись на следующем такте
10output         ldqm,      // Нижняя маска для записи или чтения
11output         udqm       // Верхняя маска
Здесь много чего непонятного, но если разобраться, то все придет на свои места. С генератором тактовой частоты все ясно, он подает такты на чип памяти, который работает например, частотой 100 мгц. Провод CKE, если 1, активирует память, то есть, просто включает ее в работу. CSN, если 0, разрешает работать с памятью, он ее как бы, активирует, но мягко, не сбрасывает, а временно приостанавливает прием и передачу данных в память и из нее.
У памяти обычно 4 банка, которые могут располагаться, например, в разных "отсеках" физически, и потому, чтобы что-то прочитать, надо обязательно выбрать банк памяти для этого.
Шина address указывает либо на строку (если RAS=0), либо на столбец (если CAS=0), поэтому сначала делается выбор строки, потом столбца. Одновременно и сразу невозможно никак указать на нужный адрес, на выборку тратится время.
С we тут все ясно, если WE=0, то DQ считается за вход и оттуда записывается в память, причем, записывается в некотором порядке. В случае если ldqm=0 и udqm=0, то тогда данные с DQ записываются в младший и старший байт 16 битного слова. Если например, ldqm=0 а udqm=1, то тогда записывается только в младший, а в старший записи не производится, там значение не меняется. Это удобно для проведения операции с байтами. При чтении, ldqm и udqm (или, в общем, DQM), работает аналогично. Здесь активный уровень равен 0.

§ Коды команд

Для того, чтобы работать с памятью, ей необходимо отсылать команды. Всего команд 8 и они представлены в таблице ниже. Там где R — это RAS, C — CAS, W — WE, соотвественно.
R C W   Код         Описане
0 0 0 | LOADMODE  | Загрузка регистра режима
0 0 1 | REFRESH   | Обновление очередной строки
0 1 0 | PRECHARGE | Перезарядка
0 1 1 | ACTIVATE  | Активация строки
1 0 0 | WRITE     | Запись в память
1 0 1 | READ      | Чтение из памяти
1 1 0 | BURSTTERM | Остановка пакетного режима
1 1 1 | NOP       | Ничего не делать
Некоторые команды тут понятны сразу, некоторые придется разобрать.
  • Команда LOADMODE загружает во внутренний статусный регистр настройки для памяти. Что именно туда загружается и как, можно проверить в даташите. Кстати, в даташите все очень понятно и хорошо описано, так что то что я тут пишу, бессмысленно и не нужно.
  • Команда REFRESH перезаряжает очередную строку автоматически. Можно сделать перезарядку иначе, открыв строку, и закрыв ее сразу же, но эта команда позволяет сделать все без дополнительной логики со стороны контроллера и это удобно.
  • ACTIVATE включает строку. После этой команды требуется некоторое время подождать, примерно 2 такта, прежде чем информация со строки будет загружена в промежуточный буфер в памяти и будет готово к работе.
  • Команды WRITE и READ пишут в память и читают оттуда соответственно
  • Инструкция BURSTTERM необходима для того, чтобы досрочно остановить пакетную запись или чтение в память. Особенно важно это при записи, иначе, если этого не сделать, то туда будет записан всякий мусор.
  • Соответственно, инструкция NOP не делает ничего. Это самая ленивая инструкция из всех.
На этом я пока что закончу статью.