Как симулировать проекты Quartus Prime выполненные в схеме?

top level

Если ответить коротко, то "никак". А если все таки подумать, то выход есть: сперва нужно конвертировать имеющуюся схему в Verilog или VHDL программу и уже потом можно симулировать. Сейчас я покажу, как это можно сделать. Это может оказаться не очень просто, но все проблемы, в принципе, решаемы.

Возьмем первый проект для платы Марсоход3, там, где "мигаем светодиодами" и попробуем его просимулировать в ModelSim.
Заодно посмотрим, какие могут быть особенности при симуляции альтеровской мегафункции PLL.

Итак, берем и скачиваем с нашего сайта проект платы Марсоход3: 


Самый главный модуль, top-level, изображен выше. Здесь есть компонент mypll - этот модуль создан с помощью альтеровского визарда мегафункции PLL. Обычно PLL позволяет из одной входной частоты синтезировать несколько других, но здесь в этом проекте он ничего особого не делает: было на входе 100МГц и стало 100МГц на выходе. Но при этом, конечно, выходной сигнал тактовой частоты из PLL разведен по кристаллу ПЛИС по специальным (dedicated) сигнальным линиям.

Тактовая частота с PLL подается на 32-х битный счетчик LPM_COUNTER. Это так же альтеровский библиотечный компонент. Некоторые выходы счетчика выведены на светодиоды платы LED[7..0].

Проект использует еще два входных сигнала от кнопочек key1 и key0. Эти сигналы заведены на асинхронный сброс счетчика aclr и на разрешение счета cnt_en. Сигналы на кнопочках на плате притянуты к напряжению питания pull-up резисторами, так что на них по умолчанию входной сигнал единица, но если нажать на кнопочку, то будет ноль.

Преобразуем схему в файл программы на языке Verilog. Для этого, в среде Altera Intel Quartus Prime используем меню File => Create / Update => Create HDL Design from Current File. Файл схемы назывался max10.bdf, а получим вот такой новый файл max10.v.


// Copyright (C) 2016 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions
// and other software and tools, and its AMPP partner logic
// functions, and any output files from any of the foregoing
// (including device programming or simulation files), and any
// associated documentation or information are expressly subject
// to the terms and conditions of the Intel Program License
// Subscription Agreement, the Intel Quartus Prime License Agreement,
// the Intel MegaCore Function License Agreement, or other
// applicable license agreement, including, without limitation,
// that your use is for the sole purpose of programming logic
// devices manufactured by Intel and sold by Intel or its
// authorized distributors. Please refer to the applicable
// agreement for further details.

// PROGRAM "Quartus Prime"
// VERSION "Version 16.1.0 Build 196 10/24/2016 SJ Lite Edition"
// CREATED "Fri Jan 20 11:00:24 2017"

module max10(
  CLK100MHZ,
  key0,
  key1,
  FTDI_BD2,
  FTDI_BD0,
  ftdi_bd1,
  ftdi_bd3,
  FTC,
  FTD,
  io,
  LED
);

input wire CLK100MHZ;
input wire key0;
input wire key1;
input wire FTDI_BD2;
input wire FTDI_BD0;
output wire ftdi_bd1;
output wire ftdi_bd3;
output wire [7:0] FTC;
output wire [7:0] FTD;
output wire [19:0] io;
output wire [7:0] LED;

wire clk;
wire [31:0] q;
wire SYNTHESIZED_WIRE_0;

assign ftdi_bd1 = 0;
assign ftdi_bd3 = 0;
assign FTC = 8'b00000000;
assign FTD = 8'b00000000;
assign io = 20'b00000000000000000000;

mypll b2v_inst2(
  .inclk0(CLK100MHZ),
  .c0(clk)
  );

assign SYNTHESIZED_WIRE_0 = ~key1;

lpm_counter_0 b2v_inst33(
  .aclr(SYNTHESIZED_WIRE_0),
  .clock(clk),
  .cnt_en(key0),
  .q(q));

assign LED[7:0] = q[31:24];

endmodule


module lpm_counter_0(aclr,clock,cnt_en,q);
/* synthesis black_box */

input aclr;
input clock;
input cnt_en;
output [31:0] q;

endmodule


В получившемся Verilog файле мы видим для модуля mypll его установленный экземпляр b2v_inst2 и для модуля lpm_counter_0 его экземпляр b2v_inst33. При конвертации схемы в Verilog для проводов без имени квартус создает свои имена вида SYNTHESIZED_WIRE_0.

В принципе здесь все хорошо, но почему он здесь же создал "synthesis black_box" для lpm_counter_0? Объявил модуль который ничего не делает. Это не порядок. При этом, квартус тут же создал новый файл для счетчика: lpm_counter_0.v.

Тут придется заниматься немного шаманством: нужно полностью удалить объявление модуля lpm_counter_0 из max10.v - не нужны нам такие пустые "synthesis black_box", нам нужен актуальный счетчик, который описан в новом файле lpm_counter_0.v.

Теперь уже можно пробовать симулировать получившиеся Verilog файлы в ModelSim. Конечно, для этого нам нужно еще написать testbench.
Сделаю самый простой тестбенч, который можно придумать:


`timescale 1ns/1ns

module tb;

reg clk = 1'b0;
always
  clk = #5 ~clk;

wire [7:0]led;
reg k0;
reg k1;

initial
begin
  //$dumpfile("tb.vcd");
  //$dumpvars(0, tb);
  k0 = 1'b1;
  k1 = 1'b1;
  #200;
  k0 = 1'b0;
  #200;
  k0 = 1'b1;
  #200;
  k1 = 1'b0;
  #200;
  k1 = 1'b1;
  #1000000000;
  $stop;
end

max10 max10_inst(
  .CLK100MHZ( clk ),
  .key0( k0 ),
  .key1( k1 ),
  .FTDI_BD2( 1'b0 ),
  .FTDI_BD0( 1'b0 ),
  .ftdi_bd1(),
  .ftdi_bd3(),
  .FTC(),
  .FTD(),
  .io(),
  .LED( led )
  );

endmodule


 

Здесь в тестбенче устанавливаем экземпляр тестируемого проекта max10 max10_inst. Строка always clk = #5 ~clk; создает сигнал тактовой частоты (имитация кварцевого генератора платы) и сигнал clk подается на модуль max10_inst. В блоке initial управляем сигналами кнопочек: через 200нс от начала работы нажимаем k0 и отпускаем ее еще через 200нс. Потом, еще через 200нс нажимаем k1 и отпускаем ее еще через 200нс. Единицы измерения временных интервалов в тестбенче задаются в первой строке с помощью timescale.

Довольно подробно симуляция описана другой статье 11-blog/118-modelsim Не знаю, нужно ли повторяться...
Таким образом, если коротко то вот так:

  1. создаем новый проект в ModelSim через меню File => New => Project... назовем проект "mywork".
  2. добавим в этот новый проект существующие файлы через меню Project => Add to Project => Existing File.. Добавляем файлы max10.v, lpm_counter_0.v, mypll.v и конечно тестбенч tb.vc
  3. скомпилируем проект с помощью ModelSim, меню Compile => Compile All
  4. начнем симуляцию через меню Simulation => Start Simulation... тут появится диалоговое окно и нужно на вкладке Design выбрать наш тестбенч из нашего проекта mywork.

start sim

Это еще не все. Так как наш проект сейчас использует компоненты и PLL мегафункцию альтеры, то нужно подключить соответствующие библиотеки. Это сделаем на вкладке Libraries.

start sim2

В принципе, весь этот пункт 4) можно выполнить из командной строки ModelSim с командой "vsim -gui mywork.tb -L altera_mf_ver -L lpm_ver". Впрочем, очень многое, если не все, можно в ModelSim делать из командной строки и из скриптов TCL.

К сожалению, последний пункт 4) в этом нашем конкретном случае не выполняется гладко. Напротив, я вижу ошибку моделсима:

# Loading lpm_ver.lpm_counter
# ** Error (suppressible): (vsim-10000) C:/altera/MAX10/max10_leds/max10_leds/lpm_counter_0.v(28): Unresolved defparam reference to 'LPM_WIDTH' in lpm_instance.LPM_WIDTH.
# Time: 0 ps Iteration: 0 Instance: /tb/max10_inst/b2v_inst33 File: C:/altera/MAX10/max10_leds/max10_leds/lpm_counter_0.v
# Error loading design

Вот квартус при конвертации схемы в текст верилога сам создал файл lpm_counter_0.v, но сделал он это не правильно. В файле lpm_counter_0.v он передает параметр LPM_WIDTH счетчику, а такого параметра у него нет. Есть параметр lpm_width маленькими буквами и для верилога это важно. Так что придется ручками править созданный квартусом файл: меняю строки

lpm_counter lpm_instance(.aclr(aclr),.clock(clock),.cnt_en(cnt_en),.q(q));
  defparam lpm_instance.LPM_WIDTH = 32;
на
lpm_counter lpm_instance(.aclr(aclr),.clock(clock),.cnt_en(cnt_en),.q(q));
  defparam lpm_instance.lpm_width = 32;

Теперь повторяем вышеизложенные пункты 3 и 4, компилируем проект и заново запускаем симуляцию. Теперь ошибок никаких не выдает и проект готов для симуляции.

Чтобы увидеть временные диаграммы каких-то сигналов их нужно добавить для просмотра. Я добавил сигналы из PLL: входной inclk0, выходной c0 и еще locked - сигнал готовности выходной частоты PLL. Так же мне интересно посмотреть на счетчик lpm_counter. Поэтому я добавил к просмотру его входные сигналы aclr, cnt_en (они подключены к кнопочкам палты), и выходной сигнал q.

modelsim add wave

Симулировать можно через меню Simulate => Run 100 или Simulate => Run All..
А можно из командной строки ModelSim: например, для симуляции одной миллисекунды, run 1ms

counter

После "run 1ms" можно увидеть нашу симуляцию в виде временной диаграммы.

Выводы:

  1. симулировать проекты, которые изначально были выполнены в виде схем можно, но при этом потребуется конвертация этих схем в Verilog или VHDL тексты.
  2. автоматическая конвертация квартусом возможна через пункты меню File => Create / Update => Create HDL Design from Current File, однако, вероятно придется вручную модифицировать файлы (убирать не нужную декларацию дополнительных модулей типа /* synthesis black_box */ или менять имена параметров ).

Еще несколько слов о симуляции PLL.
В описанном выше примере PLL удачно стартует буквально через несколько тактов входной частоты и появляется сигнал locked и выдается выходная частота.
Если во время симуляции вы видите, что PLL не стартует, то на это может быть несколько причин.

  • PLL при симуляции не стартует, если на вход PLL из тестбенча подана частота не такая, как было заявлено при создании экземпляра PLL в визарде мегафункции.

Например, в моем тестбенче имитируется тактовая частота
  always
     clk = #5 ~clk;
При этом в начале файла тестбенча указано разрешение `timescale 1ns/1ns. Timescale определяет единицы измерения в модуле и точность округления при вычислении времени в модуле `timescale <time_unit>/<time_precision>. Значит в моем примере полупериод 5нс и период 10нс, что соответствует частоте 100МГц. И в проекте квартуса, когда создавался mypll в визарде входная частота заявлена 100МГц. Так что все должно получиться и при симуляции. А вот если при написании тестбенча ошибиться и написать, например, always clk = #50 ~clk; То уже PLL в симуляторе запускаться не будет, так как тестбенч подает на PLL не 100МГц, а 10МГц.

  • PLL в симуляторе не стартует если точность симулятора установлена слишком грубой.

Иногда хочется посмотреть на временных диаграммах длительные интервалы времени и симуляция идет долго, десятки минут или даже часы. Есть соблазн понизить точность симуляции, по умолчанию у ModelSim точность стоит 1ps. Сразу скажу, что на длительность симуляции изменение точности скорее всего не влияет.

Тем не менее, вы можете понизить точность симулятора указав в командной строке параметр -t <precision>:
vsim -gui -L altera_mf_ver -L lpm_ver mywork.tb -t ns

При этом, внезапно, увидите, что PLL перестал запускаться. Видимо сама модель PLL написана так, что ей нужны какие-то вычисления времени, которые нужно делать довольно точно. Без этого сигнал locked не выставляется и выходная частота не появляется.

 

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