Jump to content

    
Sign in to follow this  
vpd

Контроллер памяти DDR2 для Altera Cyclone

Recommended Posts

Судя по картинке, это пока чистая модель, откуда частота 265 МГц? Или это проверка на собираемость просто?

Еще не увидел на картинке собственно модели памяти DDR2. Там c реальной моделью много интересного еще может повылезать.

1,2. Чтение, кстати, интересный дало эффект. Оказалось, что аннотация реальных задержек в кристалле приводит к сдвигу приема данных с шины на 1 такт. В итоге, поведение модели до сборки и после сборки отличается. В пятницу проверял на железе, уперся в этот факт. Сижу вот теперь, приделываю обманку для этого.

3. А перед тем как на железе проверять, хорошо бы выдать vho + sdf и посмотреть, что за времянка получается.

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

 

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

Проверка на собираемость. По моему 265 МГц для Stratix III вполне нормальная частота.

Моделирование проводилось с реальной моделью MT47H256M8HG-37IT.

`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 сделан, просто он не показан.

Share this post


Link to post
Share on other sites

Выкладываю проект как есть.

Собрал для двух устройств:

1. Altera EP3C16F484C8

* частота - 180/360 МГц

* 750 LCELLs / 516 registers

 

2. Altera EP3SE50F780C3

* частота 275/550 МГц

* 332 ALUTs / 507 registers

 

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

ddr2_core.rar

Share this post


Link to post
Share on other sites
Выкладываю проект как есть.

работа с банками красиво сделана, а вот тестбенч слишком уж дубовый :biggrin: могу натянуть тест со своего открытого проекта, заодно и перформанс можно померить %)

Share this post


Link to post
Share on other sites

Чтобы потом не удивлялись, перечисляю, чего нет:

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. В общем все эти настройки лучше подогнать по результатам моделирования.

 

Edited by Hoodwin

Share this post


Link to post
Share on other sites

Новости:

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

2. В процессе возни и отладки обнаружился странный глюк у самсунговской модели памяти. она почему-то не хочет работать на частоте ниже 200 МГц и ругается на tCCD violation. Чтобы обойти это бяку, пришлось оптимизировать частотку и, удалось таки достичь 200 МГц для Cyclone 3 при сборке. Рихтовкой времянок не занимался, и поэтому откатил частоту на 180 МГц.

3. Просматривая в очередной раз datasheet'ы вспомнил, что в списке недоделок не хватает еще одного момента. А именно, для 8-банковых чипов не проверяется скользящее окно tFAW, в течение которого не должно быть более 4 команд активации. У меня пока в проекте этого нет, но для порядка надо сделать.

Share this post


Link to post
Share on other sites
1. В опубликованном коде ошибочка нашлась. В симуляторе все работало и до, и после компиляции, а на практике наблюдалось неправильное чтение, в каждом пакете был сдвиг на одно слово. Два дня ковырялся с калибровкой, чтобы не шибко зависело от разводки. Вроде победил. Понаблюдаю пока, насколько стабильно будет, если не будет рецидивов, то обновлю архивчик.

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

Чтобы работать на более высоких частотах, используется достаточно хитрая динамическая система, основанная либо на чтении DQS, либо на внешнем фидбэке в PLL. Которая является существенно архитектурно зависимой, и я рекомендовал её оформлять отдельно от контроллера.

 

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

 

В моём контроллере интерфейс примерно такой:

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.

Share this post


Link to post
Share on other sites

Timmy

1. А что за файла не хваает? Моделсим какой-странный, вроде включил ему опцию soft pathnames, а он все равно полные пути лепит, причем даже после того, как я их однажды ручками переделал в относительные. Я думаю, что особого труда не составит поправить пути под себя, а вот если я файл какой-то забыл положить, то скажите, какой.

2. С констрейнами немного не так. В IO есть несколько опций для регулирования задержки сигнала от пина до входного триггера. Проблема не в том, чтобы сделать эту задержку постоянной и предсказуемой, проблема в том, что никакое значение задержки в собранном проекте не может дать прихода данных в том же такте, в каком они приходят в чистой модели. В результате пришлось добавить динамическую калибровку задержки по приходу DQS, реализовав пробное чтение в момент инициализации. Работает пока очень хорошо, и в симуляторе, и в синтезаторе. Частота - 180 МГц, но проект можно собрать и на 200 при желании.

3. А в чем проблемы со сборкой модуля в Aldec HDL? Ему же наверное также в свойствах модуля в проекте можно приписать параметры для сборки и путь к включаемым файлам?

 

 

Share this post


Link to post
Share on other sites
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", видимо, мои допотопные библиотеки безнадёжно устарели.

 

Share this post


Link to post
Share on other sites

1. Ок, поправлю. Что-то раньше таких файлов не было - .dpf.

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

3. Проблемы модели памяти - это к авторам тех моделей :) У самсунга например, все в одном исходнике, но тоже параметры внешние, правда другие. У Hynix - тоже параметры, но тоже другие. Всем не угодишь, в общем.

Share this post


Link to post
Share on other sites
Выкладываю проект как есть.

Собрал для двух устройств:

1. Altera EP3C16F484C8

* частота - 180/360 МГц

* 750 LCELLs / 516 registers

 

2. Altera EP3SE50F780C3

* частота 275/550 МГц

* 332 ALUTs / 507 registers

 

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

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

Share this post


Link to post
Share on other sites

Поднимем тему еще раз.

 

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

 

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

 

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

 

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

 

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

 

 

Share this post


Link to post
Share on other sites
...

В итоге то как, хоть кто-то смотрел что-нибудь? ...

 

В теме вы писали про внесение изменений в проект.

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

 

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this