МАРСОХОД

Open Source Hardware Project

Симуляция SDRAM контроллера в ModelSim


modelsim altera logo

Попробую просимулировать SDRAM контроллер из предыдущей статьи mindango с помощью симулятора ModelSim Altera.
Действительно у ModelSim Altera есть ряд ограничений, очень важное ограничение - это отсутствие mixed language support. То есть, невозможно просто симулировать проекты содержащие модули одновременно и на Verilog HDL и на VHDL. Если я хочу симулировать SDRAM контроллер написаный на VHDL, а модель микросхемы памяти Micron написана на Verilog, то это проблема. Однако, выход есть. В Altera Quartus II можно скомпилировать проект, содержащий код VHDL в формат файла "Verilog Output" и он уже может быть использован в ModelSim совместно c другими модулями на Verilog.

Я думаю, что принципиально важно симулировать разрабатываемый контроллер с моделью памяти созданной производителем. Только в этом случае можно будет надеяться, что действительно все ньюансы взаимодействия контроллера и чипа памяти учтены. А то ведь бывает читаешь многостраничную документацию на микросхему на английском языке, сразу все удержать в памяти довольно трудно, очень легко запутаться или что-то понять не так как оно есть на самом деле...

Приступим.

1. Создадим новый проект sdram_sim в Altera Quartus II.

В среде Quartus II откроем файл контроллера sdram_controller.vhd из предыдущей статьи. И сделаем этот файл модулем самого верхнего уровня проекта с помощью меню Project => Set as Top-Level Entity.

Поскольку у модуля контроллера sdram довольно много входных и выходных сигналов выберу и назначу для проекта какую нибудь FPGA с большим числом пользовательских пинов, например, выберу Cyclone III EP3C16U484C7. Это можно сделать в диалоговом окне Device, вызвав его из меню Assignments => Device... Сразу скажу, что не собираюсь загружать в реальную ПЛИС откомпилированный проект, нет, мне только и нужно скомпилировать, чтобы получить выходные файлы для ModelSim.

2. В настройках проекта дополнительно укажем какие выходные файлы генерировать для симулятора ModelSim.
Для этого заходим в меню Assignments => Settings. В открывшемся диалоговом окне слева в категориях находим EDA Tool Settings, Simulation.

settings

Сверху указываем тип симулятора tool name: ModelSim Altera и ниже указываем тип генерируемых файлов Format for output netlist: Verilog HDL. Тут еще есть ряд важных опций: папка, куда будут сохранены сгенерированные файлы и точность симуляции Time scale..

3. Компилирую проект в Quartus II.
Потом иду в папку simulation/modelsim и вижу,что действительно появились новые файлы:

altera quartus II verilog output files

4. Напишем тестбенч для нашего эксперимента.
Тут есть проблема мультиязычности. Кто-то больше понимает в Verilog, кто-то в VHDL. У меня, например, опыта с VHDL практически нет. Я пишу тестбенч на Verilog. Тем более, что сама модель памяти Micron (мы ее скачали с сайта Micron) так же написана на Verilog. И симулировать в ModelSim я буду в "режиме" Verilog, для этого Quartus II нам скомпилировал выходные *.vo (Verilog Output) файлы из VHDL модуля SDRAM контроллера.

Тестбенч - это довольно простая программа, которая соединяет проводами экземпляр модели чипа SDRAM с экземпляром контроллера sdram_controller. Вот как-то так:

verilog testbench

Еще в тестбенче есть простой блок кода initial, он подает тестовые сигналы записи и чтения на sdram_controller.
Здесь вообще-то нужно предусмотреть ВСЕ возможные варианты использования контроллера, и подавать все возможные комбинации входных сигналов, в том числе одиночные или блочные передачи данных, чтение одновременно с записью (посмотреть что там с приоритетами запросов) и так далее. Этого полного покрытия тестами я сейчас, конечно, делать не буду. Мне важно показать принцип, как сделать тестбенч и как симулировать в ModelSim.

Еще тонкость. Мы сейчас делаем временную симуляцию, а хотелось бы делать функциональную. Это опять из-за ограничений ModelSim Altera по поводу мультиязычности. Вот если бы весь проект был только на Verilog или только на VHDL - тогда функциональная симуляция возможна. У нас же проект использует и Verilog и VHDL, а значит мы используем нетлисты *.VO созданные Quartus II из VHDL и поэтому нам сейчас доступна только временная симуляция.

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

Поэтому, чтобы сигналы на диаграммах выглядели почти как на функциональной симуляции я умышленно значительно понижаю тактовую частоту проекта. У меня в тестбенче сейчас написано always #25 sclk = ~sclk; - это значит я буду симулировать систему с рабочей частотой всего 20МГц - только с единственно целью убедиться правильно ли спроектирован контроллер.

Весь тестбенч вот:


`timescale 1ns / 1ns

module testbench;

wire [15 : 0] dq; // SDRAM I/O
wire [11 : 0] addr; // SDRAM Address
wire [1 : 0] ba; // Bank Address
wire cke; // Synchronous Clock Enable
wire cs_n; // CS#
wire ras_n; // RAS#
wire cas_n; // CAS#
wire we_n; // WE#
wire [1 : 0] dqm; // I/O Mask

//model ext quartz source
reg sclk;
initial sclk = 1;
always #25 sclk = ~sclk;

//instance of SDRAM chip model
mt48lc4m16a2 sdram_inst (
 .Clk (sclk),
 .Cke (cke),
 .Cs_n (cs_n),
 .Dq (dq),
 .Dqm (dqm),
 .Addr (addr),
 .Ba (ba),
 .Ras_n (ras_n),
 .Cas_n (cas_n),
 .We_n (we_n)
 );

wire [15:0]read_data;
wire read_valid;
wire wire_sdram_clk_n;

reg [21:0]raddr=0;
reg [21:0]waddr=0;
reg [15:0]wdata=0;
reg rdreq=0;
reg wrreq=0;

sdram_controller sdram_controller_inst (
 .clk( sclk ),
 .rd_req ( rdreq ),
 .rd_adr ( raddr ),
 .rd_data( read_data ),
 .rd_valid( read_valid ),
 .wr_req ( wrreq ),
 .wr_adr ( waddr ),
 .wr_data( wdata ),

 //SDRAM interface
 .sdram_dq(dq),
 .sdram_dqm(dqm),
 .sdram_a(addr),
 .sdram_ba(ba),
 .sdram_ras_n(ras_n),
 .sdram_cas_n(cas_n),
 .sdram_wren_n(we_n),
 .sdram_clk_n( wire_sdram_clk_n )
 );

assign cke = 1;
assign cs_n = 0;

initial
begin
 #500000;
 @(posedge sclk);
 waddr = 22'h333;
 wdata = 16'hAA55;
 wrreq = 1;

 @(posedge sclk);
 #1;
 waddr = 0;
 wdata = 0;
 wrreq = 0;

 @(posedge sclk);
 @(posedge sclk);
 @(posedge sclk);

 @(posedge sclk);
 waddr = 22'h833;
 wdata = 16'hBB66;
 wrreq = 1;

 @(posedge sclk);
 #1;
 waddr = 0;
 wdata = 0;
 wrreq = 0;

 @(posedge sclk);
 @(posedge sclk);
 @(posedge sclk);
 @(posedge sclk);
 @(posedge sclk);
 @(posedge sclk);
 @(posedge sclk);

 raddr = 22'h333;
 rdreq = 1;

 @(posedge sclk);
 #1;
 raddr = 0;
 rdreq = 0;

 #5000;

 $stop();
end

endmodule


 5. Запускаем ModelSim и создаем новый проект.

Меню File => New => Project...

6. Добавляем в проект нужные файлы.
Я в папку проекта ModelSim скопировал те файлы, которые мне сгенерировал Quartus II: sdram_sim.vo, sdram_sim.sdo, sdram_sim.sft. Может можно не копировать, но так проще. В этой же папке находятся testbench.v и mt48lc4m16a2.v (это Verilog модель памяти).

Использую ModelSim меню Project => Add to Project => Existing File...
Добавляем файлы *.v и *.vo. Три файла получаются в проекте: тестбенч, модель памяти и контроллер.

modelsim project

Чтобы посмотреть какие файлы уже включены в проект откройте окно просмотра файлов проекта: меню View => Project (x)

7. Компилируем файлы включенные в проект с помощью ModelSim
Меню Compile => Compile All.
Можно компилировать файлы по отдельности, меню Compile => Compile Selected.
Все файлы должны быть скомпилированы.

8. Запускаем симуляцию проекта.
Меню Simulate => Start Simulation.
Появляется диалоговое окно:

start simulation modelsim

Здесь выбираю конкретный файл для симуляции, это конечно testbench.v.
Дополнительно поставьте точность симуляции Resolution: ns.

Перейдите во вкладку Libraries
Нужно добавить библиотеки альтеры именно той микросхемы к которой компиловал квартус наш проект:

add libs

Нажимаем ОК и видим вот такую картину (клинкуть на изображение, чтобы увидеть в полном разрешении):

modelsim s

9. Симулируем.

Сперва добавим интересующие нас сигналы в окно Wave.
Выбор сигналов производится в окне Objects, кликаем по сигналу правой кнопркой мыши, в меню выбираем Add to => Wave => Selected Signals.

Выполняем по шагам из меню ModelSim: Simulate => Run => Run 100 (F9) или все сразу Simulate => Run => Run -All.
В тестбенче должна быть системная команда об окончании симуляции: $stop(). Иначе, если выполнить Run -All ModelSIm может надолго зависнуть вычисляя работу системы..

Кликнуть на изображении, чтобы увидеть в полном разрешении:

modelsim2 s

Я делаю Run -All. Симуляция завершается и в окне ModelSim Transcript появляются сообщения выдаваемые моделью памяти SDRAM:


run -all
# testbench.sdram_inst : at time 50.0 ns LMR : Load Mode Register
# testbench.sdram_inst : CAS Latency = Reserved
# testbench.sdram_inst : Burst Length = 1
# testbench.sdram_inst : Burst Type = Sequential
# testbench.sdram_inst : Write Burst Mode = Programmed Burst Length
# testbench.sdram_inst : at time 50.0 ns ERROR: all banks must be Precharge before Load Mode Register
# testbench.sdram_inst : at time 50.0 ns ERROR: tRFC violation during Load Mode Register
# testbench.sdram_inst : at time 50.0 ns ERROR: tMRD violation during Load Mode Register
# testbench.sdram_inst : at time 500050.0 ns ERROR: Bank already activated -- data can be corrupted
# testbench.sdram_inst : at time 500100.0 ns WRITE: Bank = 0 Row = x, Col = 0, Data = 0
# testbench.sdram_inst : at time 500300.0 ns ACT : Bank = 0 Row = 0
# testbench.sdram_inst : at time 500350.0 ns WRITE: Bank = 0 Row = 0, Col = 0, Data = 0
# testbench.sdram_inst : at time 500700.0 ns ACT : Bank = 0 Row = 0


 Вот ради этих сообщений все и затевалось. Модель микросхемы памяти написана производителем микросхемы. Они лучше знают как она будет реагировать на входные воздействия и их чип. Поэтому лучше довериться модели предоставленной производителем, чем своим собственным представлениям о том, как все должно происходить. В данном случае, похоже, модель SDRAM говорит, что не все хорошо с входными сигналами. В данном конкретном случае модель говорит о том, что в самом начале работы системы была загрузка в Mode Register и при этом не выдержаны tRFC, tMRD.. Кроме того, не определен CAS Latency - он остался Reserved.

Я думаю, нужно дальше совершенствовать этот контроллер SDRAM, прежде чем использовать его в работе.

Надеюсь описанная выше методика позволит обнаружить и устранить все имеющиеся проблемы.

Весь проект для Altera Quartus II и ModelSim можно взять здесь: 


 

 PS: Теперь, после некоторых внесенных (by mindango) изменений, контроллер работает гораздо лучше. Прочтите заключительные строки статьи о контроллере SDRAM.

Ну а я покажу, что теперь, после изменений, показывает симулятор ModelSim (кликнуть картинку, чтобы увидеть в полном разрешении):

ok s

Как видите, ошибок в модели памяти больше нет:

run -all
# testbench.sdram_inst : at time 250300.0 ns AREF : Auto Refresh
# testbench.sdram_inst : at time 250650.0 ns AREF : Auto Refresh
# testbench.sdram_inst : at time 251000.0 ns LMR : Load Mode Register
# testbench.sdram_inst : CAS Latency = 2
# testbench.sdram_inst : Burst Length = Full
# testbench.sdram_inst : Burst Type = Sequential
# testbench.sdram_inst : Write Burst Mode = Programmed Burst Length
# testbench.sdram_inst : at time 500100.0 ns ACT : Bank = 0 Row = 3
# testbench.sdram_inst : at time 500150.0 ns WRITE: Bank = 0 Row = 3, Col = 51, Data = 43605
# testbench.sdram_inst : at time 500350.0 ns ACT : Bank = 0 Row = 8
# testbench.sdram_inst : at time 500400.0 ns WRITE: Bank = 0 Row = 8, Col = 51, Data = 47974
# testbench.sdram_inst : at time 500750.0 ns ACT : Bank = 0 Row = 3
# testbench.sdram_inst : at time 500855.0 ns READ : Bank = 0 Row = 3, Col = 51, Data = 43605
# Break in Module testbench at C:/altera/marsohod2/sdram_sim/simulation/tb/testbench.v line 116

Я надеюсь, что я убедил вас, что симуляцию делать можно и нужно. Только симуляция дает некоторую уверенность в том, что все делается правильно.

 Новый контроллер можно взять здесь: 

 

 

Комментарии  

0 #3 willy 27.12.2014 06:49
Что за ошибка :

Unresolved defparam reference to '\Add0~10 ' in \Add0~10 .lut_mask.

День бьюсь с ModelSim но после Start Simulation получаю только кучу таких ошибок
0 #2 mindango 27.11.2014 10:10
To mtkt

Сплошным потоком можно вычитать или записать до 256 слов.

Состояние "011" это NOP, в данной версии контроллера оно не используется – просто автор поленился его убрать из кода. Так что можете смело убрать его, или не обращать внимания.
0 #1 mtkt 27.11.2014 06:44
Объясните пожалуйста, сколько слов можно вычитать сплошным потоком из данной SDRAM, что установлена на плате Марсоход 2?
И еще, смотрел по исправленной версии кода, он не входит в состояние 011 в строчке 108, не нашел где state-у назначают это состояние:

when "011" => sdram_cmd

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



facebook  GitHub  YouTube  Twitter
Вы здесь: Начало Статьи о разном Симуляция SDRAM контроллера в ModelSim