МАРСОХОД

Open Source Hardware Project

ARM System-on-Chip

Поключение SDRAM к системе на кристалле Amber

Вообще-то оригинальный проект Amber уже имел встроенный контроллер DDR. Я же его за ненадобностью выбросил, потому, что на нашей плате Марсоход2 стоит не DDR память, а SDRAM. Память SDRAM, конечно, проще, чем DDR. Она не требует отдельного питания и выделения специальных банков выводов с микросхемы ПЛИС. Однако, теперь у нас есть проблема – как подключить SDRAM к системе?

Не будем изобретать велосипед, а возьмем какой-нибудь готовый контроллер с opencores.org. Я выбираю вот этот:

OpenCores sdram controller

Похоже это то, что нужно:

Description

Feature:
• 8/16/32 Configurable SDRAM data width
• Wish Bone compatible
• Application clock and SDRAM clock can be async
• Programmable column address
• Support for industry-standard SDRAM devices and modules
• Supports all standard SDRAM functions
• Fully Synchronous; All signals registered on positive edge of system clock
• One chip-select signals
• Support SDRAM with four bank
• Programmable CAS latency
• Data mask signals for partial write operations
• Bank management architecture, which minimizes latency
• Automatic controlled refresh
• Static synchronous design
• Fully synthesizable

Выкачал исходники с сайта OpenCores (я говорил, что там много полезного можно найти) и положил их в папку нашего проекта Amber hw/vlog/sdram.

Что дальше? Добавил в мой проект системы Amber для Quartus II в файл msystem.qsf ссылки на добавленные файлы:

set_global_assignment -name VERILOG_FILE ../vlog/sdram/sdr_ctrl/trunk/rtl/lib/sync_fifo.v

set_global_assignment -name VERILOG_FILE ../vlog/sdram/sdr_ctrl/trunk/rtl/lib/async_fifo.v
set_global_assignment -name VERILOG_FILE ../vlog/sdram/sdr_ctrl/trunk/rtl/wb2sdrc/wb2sdrc.v
set_global_assignment -name VERILOG_FILE ../vlog/sdram/sdr_ctrl/trunk/rtl/top/sdrc_top.v


Расширил пути поиска для компиляторов Quartus II:

set_global_assignment -name SEARCH_PATH ../vlog/sdram/sdr_ctrl/trunk/rtl/core

Добавил новый макрос для Verilog:

set_global_assignment -name VERILOG_MACRO "SDRAM=1"

Кроме этого, изменил Verilog модуль верхнего уровня msystem.v:

  • Добавил входы и выходы SDRAM.
  • Подключил к шине Wishbone модуль контроллера памяти sdrc_top.
  • Назначил параметры контроллера SDRAM.

Вот такое включение модуля контроллера памяти SDRAM


`ifdef SDRAM
//system with SDRAM
assign s_wb_err[2] = 0;
wire sdr_init_done;
assign phy_init_done = sdr_init_done;
assign sdr_clk = mem_clk;

sdrc_top #(.SDR_DW(16),.SDR_BW(2)) u_sdram(
 .cfg_sdr_width      (2'b01              ), // 16 BIT SDRAM
 .cfg_colbits        (2'b00              ), // 8 Bit Column Address

 /* WISHBONE */
 .wb_rst_i           (sys_rst),
 .wb_clk_i           (sys_clk            ),
 .wb_stb_i           (s_wb_stb[2]        ),
 .wb_ack_o           (s_wb_ack[2]        ),
 .wb_addr_i          (s_wb_adr[2]>>2     ),
 .wb_we_i            (s_wb_we[2]         ),
 .wb_dat_i           (s_wb_dat_w[2]      ),
 .wb_sel_i           (s_wb_sel[2]        ),
 .wb_dat_o           (s_wb_dat_r[2]      ),
 .wb_cyc_i           (s_wb_cyc[2]        ),
 .wb_cti_i           (0),

 /* Interface to SDRAMs */

 .sdram_clk          (sdr_clk            ),
 .sdram_resetn       (~sys_rst           ),
 .sdr_cs_n           ( /*sdr_cs_n*/      ),
 .sdr_cke            ( /*sdr_cke*/       ),
 .sdr_ras_n          (sdr_ras_n          ),
 .sdr_cas_n          (sdr_cas_n          ),
 .sdr_we_n           (sdr_we_n           ),
 .sdr_dqm            (sdr_dqm            ),
 .sdr_ba             (sdr_ba             ),
 .sdr_addr           (sdr_addr           ),
 .sdr_dq             (sdr_dq             ),

 /* Parameters */

 .sdr_init_done      (sdr_init_done      ),
 .cfg_req_depth      (2'h3               ), //how many req. buffer should hold
 .cfg_sdr_en         (sdr_ena            ),
 .cfg_sdr_mode_reg   (12'h023            ),
 .cfg_sdr_tras_d     (4'h4               ), //44-120000ns
 .cfg_sdr_trp_d      (4'h2               ), //min 20ns
 .cfg_sdr_trcd_d     (4'h2               ), //min 20ns
 .cfg_sdr_cas        (3'h3               ), //cas latency in clocks, depends on mode reg
 .cfg_sdr_trcar_d    (4'h7               ), //min 66ns
 .cfg_sdr_twr_d      (4'h1               ), //write recovery time, 1ck+7,5/15ns
 .cfg_sdr_rfsh       (12'h100            ), //16 or 64 ms?
 .cfg_sdr_rfmax      (3'h6               )
 );
`else
 //assume memory always ready if no SDRAM
 assign phy_init_done = 1'd1;
`endif

 

Еще изменил модуль my_clocks_reset.v. В нем теперь синтезируется в PLL две тактовых частоты: 40Мгц для системы и 80Мгц для памяти SDRAM.

В процессе отладки проекта с помощью SignalTap и чтения документации на контроллер SDRAM (она есть в папке hw/vlog/sdram/sdr_ctrl/trunk/doc) выяснилось, что для успешной инициализации памяти необходимо подать на нее тактовую частоту и выждать около 100мкс. Только после этого контроллер может выдавать микросхеме памяти какие-то первые инициализационные команды. Я это не сразу понял. Сигнал cfg_sdr_en  на модуле контроллера как раз для этого. Теперь мой модуль my_clocks_reset сам выжидает како-то время и выдает контроллеру памяти sdrc_top сигнал разрешения работы cfg_sdr_en. Контроллер программирует микросхеаму памяти в некоторый заданный режим и после этого выдает сигнал sdr_init_done. Вот только после этого стартует процессор.

Еще одна проблема, которую я встретил – в настройках контроллера почему-то присутствуют дублирующие друг-друга настройки. Так, на вход cfg_sdr_mode_reg подается константа 12’h023 и вторая тетрада «2» обозначает CAS Latency – задержка готовности данных. Тем не менее есть еще один конфигурирующий сигнал cfg_sdr_cas который обозначает то же самое. Однако странно, чтобы все работало правильно нужно, чтобы cfg_sdr_cas был на единицу больше, чем указанное число в MODE регистре, определяемом сигналами cfg_sdr_mode_reg. Это довольно странно. Довольно много здесь времени потерял, пока понял, как надо сделать. MODE регистр в памяти SDRAM определяет режим работы микросхемы и должен быть проинициализирован в начале работы системы.

В самом процессоре в boot-rom я теперь помещяю не программу hello-world, как раньше, а специальную программу boot-loader. Я не сам ее писал, а взял оригинальную из папки sw/boot-loader. Я создал свою папку boot-loader-8M и скопировал все оригинальные файлы туда. Собственно изменение в этом проекте только одно. Нужно поставить стек программ под вершину нашей памяти в 8Мбайт.

Как и в случае с программой hello-world я компилирую boot-loader и преобразую полученный MEM файл в Altera MIF командами

make
../tools/mem2mif boot-loader.mem >> boot-loader.mif


В проекте Altera Quartus II в визарде для sram_2048_32_byte_en теперь указываю, что bootrom должен при старте инициализирован новым boot-loader.mif

В принципе это в общем и все.

Для дальнейших экспериментов нам понадобится программа терминала для последовательного порта TeraTerm. Я раньше пользовался Putty, но теперь рекомендую эту программу TeraTerm. Чуть позже объясню почему.

Теперь опишу как это работает. После компиляции проекта в Quartus II открываю в TeraTerm последовательный порт COM9 на скорости 921600, 1 стоп бит, без четности. Запускаю программатор Quartus II и загружаю проект в ПЛИС платы Марсоход2.

Boot-loader в плате Марсоход2

В консоли последовательного порта появляется вот такое «меню». Это, в отличии от программы hello-world, уже интерактивное приложение. Набирая команду «w» можно писать в память, а команду «d» читать и отображать блок памяти. На картинке видно, что я записал число 0x55667788 по адресу 0x80004 и потом посмотрел область с адреса 0x80000.

Но и это еще не все! Теперь можно через последовательный порт загрузить программу в память устройства. Для этого и нужен терминал TeraTerm. Он позволяет передавать файлы по протоколу XMODEM w/1k на наше устройство. В boot-loader как раз и реализован этот протокол.

xmodem

Набираем в консоли команду «l» и boot-loader начинает ожидать файл из COM порта. В меню программы TeraTerm выбираем пункты File => Transfer => XMODEM => Send

Далее выбираем файл, который желаете передать и не забудьте поставить флажек w/1k – это видимо разновидность протокола передачи.

Boot-loader в плате Марсоход2

Я выбираю программу, скомпилированную ранее - hello-world.elf - ELF это такой тип исполняемых файлов в Linux. Вот только такая тонкость. Помните, для первого запуска программы hello-world в плате Марсоход2 мне пришлось поменять базовый адрес программы с 0x8000 в 0x0000? Я тогда удивлялся, зачем автор так странно делает такой адрес, ведь там нет boot-rom? Так вот теперь и понятно - адрес 0x8000 как раз нужен, чтобы программу hello-world загрузить с помощью boot-loader в память устройства через последовательный порт протоколом XMODEM! В общем, программу hello-world нужно перекомпилировать установив базовый адрес программы назад в 0x8000 в файле sections.lds.

Выбирая файл не забудьте указать опцию в диалоговом окне терминала TeraTerm - "1K" - это видимо какая-то разновидность протокола передачи.

Все - программа загружена:

Boot-loader в плате Марсоход2

Ее легко запустить на устройстве, набрав команду "j 8000"

Вот так, я подключил память SDRAM к системе. Пока еще не могу с уверенностью сказать, что там все работает превосходно - нужно бы посмотреть на временные диаграммы. Однако уже сейчас видно, что система становится более функциональной.

Весь проект с изменениями есть на нашем GitHub разделе - вот тут можно взять TAG с проектом https://github.com/marsohod4you/Amber-Marsohod2/zipball/sdram-attached

 

 

 

Комментарии  

+1 #13 Yuva 28.10.2014 14:13
Здравствуйте!
Очень интересная статья!
А почему бы Вам не сделать подобную систему с Nios II. Как раз придется рассчитать задержку такта SDRAM по отношению к такту процессора) Это актуально
+1 #12 _андрей 23.09.2014 06:23
на 80 Мгц. В контроллере sdram есть цепь (wire #(1.0) sdram_pad_clk = sdram_clk;) По ней защелкиваются данные на чтение. При синтезе наверно эта конструкция не работает. Поэтому мне и непонятно.
+1 #11 nckm 23.09.2014 05:12
Цитирую _андрей:
Сдвиг фазы тактирования sdram, относительно клока тактирования контроллера. Кстати значение в регистре cfg_sdr_cas учитывает этот сдвиг. Я так понял, что он подбирается. И у меня заработало только со сдвигом -60гр.

Даже не знаю что и сказать. Не знаю зачем бы это было нужно. А на какой частоте у вас память работает?
+1 #10 _андрей 22.09.2014 05:03
Сдвиг фазы тактирования sdram, относительно клока тактирования контроллера. Кстати значение в регистре cfg_sdr_cas учитывает этот сдвиг. Я так понял, что он подбирается. И у меня заработало только со сдвигом -60гр.
+1 #9 nckm 21.09.2014 09:40
Цитирую _андрей:
Скажите, а сдвиг клока вы не делали?

а что такое сдвиг клока? и зачем?
+1 #8 _андрей 16.09.2014 05:09
Скажите, а сдвиг клока вы не делали?
+1 #7 андрей 21.12.2012 06:45
кстати нужно подправить адрес AdrMalloc в libc_asm.S. Сейчас динамическое выделение памяти происходит в несуществуещей области памяти.
+1 #6 андрей 20.12.2012 10:31
Сейчас разбираюсь с функцией elfsplitter, которая распаковывает elf файл в памяти. Она копирует все содержимое секций по адресам которые указаны в таблице секций (Section Headers). А там соответственно стартовый адрес 0x8000, который мы прописали в файле линкера. Что тогда находится по адресу 80000 ?
+1 #5 nckm 20.12.2012 05:34
Цитирую андрей:
в boot-loader8M стартовый адрес для загрузки файла по Xmodem равен 0x00100000, а запуск происходит с адреса 0x8000, т.е начального адреса SDRAM. Немного непонятно.. Я правильно понимаю, что команда запуска - j 100000 ?

Смотря что вы загружаете и как. Если загружаете бинарный файл командой b то образ загружается как раз по этому адресу, там его и запускать. А вот если загружаете командой l, то она используется для ELF файлов, которые похоже как-то разбираются и помещаются сами куда надо.
Их запускать с адреса 80000
+1 #4 андрей 19.12.2012 18:26
в boot-loader8M стартовый адрес для загрузки файла по Xmodem равен 0x00100000, а запуск происходит с адреса 0x8000, т.е начального адреса SDRAM. Немного непонятно.. Я правильно понимаю, что команда запуска - j 100000 ?
+1 #3 afad 12.10.2012 12:42
Осталось вставить в проект видеоконтроллер и Marsohod-компью тер готов.
+1 #2 Vladimir Balash 08.10.2012 11:48
И Марсоход II превращается... ...... В Радио РК (Микроша. Орион. Специалист - нужное выбрать :) ) с мошнейшим процесором и управляющей програмой монитор!!! :)

Припомнило :)
+1 #1 Angel007 08.10.2012 11:25
Вы продолжаете удивлять! Браво и Большой Респект!

Добавить комментарий


Защитный код
Обновить


GitHub YouTube Twitter
Вы здесь: Начало Проекты Проект Марсоход2 Amber ARM SoC Поключение SDRAM к системе на кристалле Amber