|
|
  |
Контроллер памяти DDR2 для Altera Cyclone, размышления на тему о предельной частоте |
|
|
|
Jul 4 2011, 14:23
|
Местный
  
Группа: Свой
Сообщений: 371
Регистрация: 24-07-05
Из: Москва
Пользователь №: 7 056

|
Цитата(Hoodwin @ Jul 4 2011, 16:31)  Судя по картинке, это пока чистая модель, откуда частота 265 МГц? Или это проверка на собираемость просто? Еще не увидел на картинке собственно модели памяти DDR2. Там c реальной моделью много интересного еще может повылезать. 1,2. Чтение, кстати, интересный дало эффект. Оказалось, что аннотация реальных задержек в кристалле приводит к сдвигу приема данных с шины на 1 такт. В итоге, поведение модели до сборки и после сборки отличается. В пятницу проверял на железе, уперся в этот факт. Сижу вот теперь, приделываю обманку для этого. 3. А перед тем как на железе проверять, хорошо бы выдать vho + sdf и посмотреть, что за времянка получается. 4. Побайтная запись не интересна на самом деле, нужно потоковую обеспечивать. Во всяком случае, я бы выбрал потоковую... P.S. А еще есть рефреш, который тоже не худо бы сделать  Проверка на собираемость. По моему 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 сделан, просто он не показан.
|
|
|
|
|
Jul 5 2011, 10:35
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Выкладываю проект как есть. Собрал для двух устройств: 1. Altera EP3C16F484C8 * частота - 180/360 МГц * 750 LCELLs / 516 registers 2. Altera EP3SE50F780C3 * частота 275/550 МГц * 332 ALUTs / 507 registers В проекте есть модель памяти для Micron и тестбенч для прогонки простых времянок до и после компиляции.
|
|
|
|
|
Jul 5 2011, 11:49
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Чтобы потом не удивлялись, перечисляю, чего нет: 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 - Jul 5 2011, 11:56
|
|
|
|
|
Jul 6 2011, 14:26
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Новости: 1. В опубликованном коде ошибочка нашлась. В симуляторе все работало и до, и после компиляции, а на практике наблюдалось неправильное чтение, в каждом пакете был сдвиг на одно слово. Два дня ковырялся с калибровкой, чтобы не шибко зависело от разводки. Вроде победил. Понаблюдаю пока, насколько стабильно будет, если не будет рецидивов, то обновлю архивчик. 2. В процессе возни и отладки обнаружился странный глюк у самсунговской модели памяти. она почему-то не хочет работать на частоте ниже 200 МГц и ругается на tCCD violation. Чтобы обойти это бяку, пришлось оптимизировать частотку и, удалось таки достичь 200 МГц для Cyclone 3 при сборке. Рихтовкой времянок не занимался, и поэтому откатил частоту на 180 МГц. 3. Просматривая в очередной раз datasheet'ы вспомнил, что в списке недоделок не хватает еще одного момента. А именно, для 8-банковых чипов не проверяется скользящее окно tFAW, в течение которого не должно быть более 4 команд активации. У меня пока в проекте этого нет, но для порядка надо сделать.
|
|
|
|
|
Jul 10 2011, 17:57
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(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 слегка неудобно  . В моём контроллере интерфейс примерно такой: 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.
|
|
|
|
|
Jul 11 2011, 04:00
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Timmy 1. А что за файла не хваает? Моделсим какой-странный, вроде включил ему опцию soft pathnames, а он все равно полные пути лепит, причем даже после того, как я их однажды ручками переделал в относительные. Я думаю, что особого труда не составит поправить пути под себя, а вот если я файл какой-то забыл положить, то скажите, какой. 2. С констрейнами немного не так. В IO есть несколько опций для регулирования задержки сигнала от пина до входного триггера. Проблема не в том, чтобы сделать эту задержку постоянной и предсказуемой, проблема в том, что никакое значение задержки в собранном проекте не может дать прихода данных в том же такте, в каком они приходят в чистой модели. В результате пришлось добавить динамическую калибровку задержки по приходу DQS, реализовав пробное чтение в момент инициализации. Работает пока очень хорошо, и в симуляторе, и в синтезаторе. Частота - 180 МГц, но проект можно собрать и на 200 при желании. 3. А в чем проблемы со сборкой модуля в Aldec HDL? Ему же наверное также в свойствах модуля в проекте можно приписать параметры для сборки и путь к включаемым файлам?
|
|
|
|
|
Jul 11 2011, 07:09
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(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", видимо, мои допотопные библиотеки безнадёжно устарели.
|
|
|
|
|
Jul 11 2011, 08:16
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
1. Ок, поправлю. Что-то раньше таких файлов не было - .dpf. 2. Ну, плата не отладочная, а вполне себе боевая.  Призводители вообще любят стращать сложными требованиями, чтобы у них IP покупали. Мне, например, не надо ставить SODIMM, у меня длина проводников DQ - от 9 до 15 мм, соответственно и задержка от 55 до 90 пс, что НАМНОГО меньше периода тактовой частоты (5500 пс). Адреса и пр. сигналы длиннее, но раза в два максимум. Емкость линий мала, поэтому и температурный уход невелик. Задержки ведь не сами по себе зависят от температуры, а косвенно. Сначала от температуры зависит проводимость каналов у транзисторов, а уже затем, в зависимости от емкости трасс, возникает задержка их перезаряда. При маленькой емкости разница проявляется лишь в наклоне фронта сигнала, но "полка" все равно остается. Так что не все так уж и мрачно. Кроме того, инициализация памяти - вещь программно управляемая, а особенно - калибровка процесса чтения. Можно ее вынести и проводить регулярно, хоть с каждым рефрешем. Кстати, это на самом деле единственное место, которое "плавает". Времянка записи вообще никак не страдает, так как она привязана к общему удвоенному клоку, а всякие там задержки в IOE от температуры зависят одновременно и практически одинаково. 3. Проблемы модели памяти - это к авторам тех моделей  У самсунга например, все в одном исходнике, но тоже параметры внешние, правда другие. У Hynix - тоже параметры, но тоже другие. Всем не угодишь, в общем.
|
|
|
|
|
Jul 11 2011, 17:14
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 13-04-10
Пользователь №: 56 623

|
Цитата(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?
|
|
|
|
|
Jul 11 2011, 19:56
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Цитата А Вы не думали выкладывать проект, скажем, на opencores.org? А смысл то какой в этом?
|
|
|
|
|
Jul 21 2011, 09:41
|
Знающий
   
Группа: Участник
Сообщений: 881
Регистрация: 21-03-10
Из: _// \\_
Пользователь №: 56 107

|
Поднимем тему еще раз. Цитата Было бы интересно взглянуть на самописные архитектурно независимые контроллеры. Есть возможность проверить на arria GX & arriaII GX Цитата могу натянуть тест со своего открытого проекта, заодно и перформанс можно померить %) Еще кто-то хотел тестировать на всяких там стратиксах, спартанах и т.п. В итоге то как, хоть кто-то смотрел что-нибудь? Вместо этого один флуд про 10000 строк в месяц...  У меня работает на 180 МГц, причем стабильно от 25 до 55 градусов в процессе прогрева кристалла.
|
|
|
|
|
Jul 22 2011, 05:21
|
Местный
  
Группа: Свой
Сообщений: 375
Регистрация: 9-10-08
Из: Таганрог, Ростовская обл.
Пользователь №: 40 792

|
Цитата(Hoodwin @ Jul 21 2011, 13:41)  ... В итоге то как, хоть кто-то смотрел что-нибудь? ... В теме вы писали про внесение изменений в проект. Выложите тут последний вариант с описанием всех интерфейсов(где-то тут уже было вроде). Я от своих слов не отказываюсь. Просто жду информации от создателя о готовности последнего рабочего релиза.
--------------------
Глупцы игнорируют сложность. Прагматики терпят ее. Некоторые могут избегать ее. Гении ее устраняют.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|