Блог

Симуляция проекта с помощью Icarus-Verilog.

После некоторых раздумий я решил написать статью о симуляции Verilog проектов с помощью пакета программ icarus-verilog. Мне кажется, что это лучший способ «быстро попробовать» возможности симуляции. Конечно, среда симуляции ModelSim компании Mentor Graphics (или ModelSim-Altera Edition) - это мощное средство, но освоить ее несколько труднее.

Сейчас мы быстренько скачаем из интернета icarus-verilog, установим его и попробуем что нибудь просимулировать...

Первое, что нужно сделать – это посетить сайт http://www.icarus.com/eda/verilog/ - отправная точка для изучения Icarus Verilog. Это свободный проект, то есть при желании можно даже посмотреть исходные тексты всех программ, и компилятора и симулятора Verilog. Здесь есть ссылки на документацию и откуда скачивать файлы для установки. Конечно, есть пакеты программ и для Linux и для Windows.

Оттуда я перехожу по ссылке Pablo Bleyer Kocik's Icarus Verilog Windows packages (off-site), которая ведет меня на станицу скачивания программы для операционной системы Windows. Вы будете приятно удивлены – размер файла для скачивания составляет около 17 мегабайт! Для ModelSim, например, размер будет более 500Мб!

Cкачиваем и устанавливаем, по умолчанию программа устанавливается в папку c:\iverilog и установщик сам прописывает пути к исполняемым файлам. Но можно использовать любую удобную директорию, у нас это d:\dev\iverilog.

pic1

В этой же папке есть несколько коротких но понятных инструкций, как пользоваться компилятором и симулятором (правда на английском языке). Перед началом симуляции, изменим код нашего проекта Логический анализатор SignalTap на примере счетчика Грея, а именно добавим вход wr для установки начального состояния счетчика со входа d:

Verilog Code:
  1. `timescale 1ns /100ps
  2.  
  3. module gray_cnt(
  4. input wire clk,
  5. input wire nreset,
  6. input wire wr,
  7. input wire [SIZE-1:0]d,
  8. output wire [SIZE-1:0]q
  9. );
  10. parameter SIZE = 4;
  11.  
  12. integer i;
  13. reg [SIZE-1:0]gray_cnt;
  14. reg [SIZE-1:0]bin;
  15. reg [SIZE-1:0]next_gray_cnt;
  16.  
  17. always @*
  18. begin
  19. //convert gray-to-bin
  20. for (i=0; i<SIZE; i=i+1)
  21. bin[i] = ^(gray_cnt>>i);
  22. //increment binary
  23. bin=bin+1;
  24. //convert bin-to-gray
  25. next_gray_cnt = (bin>>1)^bin;
  26. end
  27.  
  28. always @(posedge clk or negedge nreset)
  29. if(~nreset)
  30. gray_cnt <= 0;
  31. else
  32. if(~wr)
  33. begin
  34. gray_cnt <= d;
  35. $display("written %h",d);
  36. end
  37. else
  38. gray_cnt <= next_gray_cnt;
  39.  
  40. assign q=gray_cnt;
  41.  
  42. endmodule

С помощью SignalTap посмотрим, как наш счетчик работает в реальном железе:

pic2

Теперь напишем специальный модуля на языке Verilog, который называется testbench:

Verilog Code:
  1. `timescale 1ns /100ps
  2.  
  3. module gray_tb;
  4.  
  5. reg clk, nreset, wr;
  6. reg [SIZE-1:0]d;
  7. wire [SIZE-1:0]q;
  8.  
  9. parameter SIZE = 4;
  10.  
  11. //устанавливаем экземпляр тестируемого модуля
  12. gray_cnt gray_cnt_inst(clk, nreset, wr, d, q);
  13.  
  14. //моделируем сигнал тактовой частоты
  15. always
  16. #10 clk = ~clk;
  17.  
  18. //от начала времени...
  19.  
  20. initial
  21. begin
  22. clk = 0;
  23. nreset = 0;
  24. d = 4'h0;
  25. wr = 1'b1;
  26.  
  27. //через временной интервал "50" подаем сигнал сброса
  28. #50 nreset = 0;
  29.  
  30. //еще через время "4" снимаем сигнал сброса
  31.  
  32. #4 nreset = 1;
  33.  
  34. //пауза длительностью "50"
  35. #50;
  36.  
  37. //ждем фронта тактовой частоты и сразу после нее подаем сигнал записи
  38. @(posedge clk)
  39. #0
  40. begin
  41. d = 4'h5;
  42. wr = 1'b0;
  43. end
  44.  
  45. //по следующему фронту снимаем сигнал записи
  46. @(posedge clk)
  47. #0
  48. begin
  49. d = 4'h0;
  50. wr = 1'b1;
  51. end
  52. end
  53.  
  54. //заканчиваем симуляцию в момент времени "400"
  55. initial
  56. begin
  57. #400 $finish;
  58. end
  59.  
  60. //создаем файл VCD для последующего анализа сигналов
  61. initial
  62. begin
  63. $dumpfile("out.vcd");
  64. $dumpvars(0,gray_tb);
  65. end
  66.  
  67. //наблюдаем на некоторыми сигналами системы
  68. initial
  69. $monitor($stime,, clk,, nreset,, d,, wr,, q);
  70.  
  71. endmodule

Чтобы он был более понятным пожалуйста прочитайте предыдущую статью про System Tasks.

Для чего применяется такая методика из раздельных модулей – тестируемого и тестирующего? Первый модуль – это тот, который мы в будущем хотим компилировать для чипа. Для него важно быть простым и компактным. А второй модуль, тестирующий (их называют testbench) моделирует внешние сигналы, которые подаются на тестируемый модуль и проверяет выходные сигналы из него.

Тут надо заметить, что написание тестбенчей – это в каком-то смысле искуство. Получается мы пишем программу, модуль. Для тестирования этой программы мы пишем вторую программу – модуль тестбенч. Мы можем ошибиться как в первой программе, так и во второй или в обеих сразу! Ведь в любой программе возможны баги. Разработчик может думать, что он все сделал правильно и просимулировал и увидел результат какой хотел, но на самом деле проект может остаться неработоспособным. Но не нужно пугаться.

Icarus-verilog может скомпилировать их в свой «исполняемый» формат. Для этого в командной строке набираем команду:

>iverilog -o qqq gray_cnt.v gray_tb.v

Iverilog – это компилятор, который транслирует исходный код Verilog в файл специального формата для симуляции проекта, или в файлы других форматов netlist для последующей обработки другими программами.

После выполнения этой команды у нас появился новый файл «qqq». Мы будем использовать его для симуляции. Запускаем в командной строке симулятор из комплекта icarus-verilog:

>vvp qqq

Вот мы и видим весь вывод симулятора на консоль:

pic3

Здесь видно, как значение счетчика увеличивается с каждым фронтом сигнала clk.

Видно, что в момент времени "110" устанавливается сигнал wr, а в момент времени "130" происходить запись нового значения в счетчик.

Если вы теперь захотите увидеть сигналы в графическом виде, то это тоже возможно. В результате симуляции у нас появился новый файл "out.vcd" - это Value Change Dump File. Для его просмотра есть инструмент gtkwave. Он есть здесь же в комплекте установленного нами icarus-verilog.

Набираем в командной строке:

>gtkwave out.vcd

И появляется вот такое окно (кликните на картинку, чтобы увеличить ее):

pic4

Слева есть окошко со списком сигналов проекта. Нужно выбрать необходимые сигналы и добавить их к просмотру кнопкой "Append".

Справа – окно графического представления сигналов. Можно менять масштаб просмотра и скролировать вдоль шкалы времени.

Вот так можно проводить  функциональную симуляцию проектов написаных на языке Verilog.

Проект Icarus-Verilog для платы VE-EP4CE10E: signaltap_grey_icarus.zip