diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_14.png b/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_14.png deleted file mode 100644 index 7818e17..0000000 Binary files a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_14.png and /dev/null differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_16.png b/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_16.png deleted file mode 100644 index f7af81d..0000000 Binary files a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_16.png and /dev/null differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_18.png b/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_18.png deleted file mode 100644 index f65aad1..0000000 Binary files a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_18.png and /dev/null differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_20.png b/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_20.png deleted file mode 100644 index b78e044..0000000 Binary files a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_20.png and /dev/null differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_21.png b/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_21.png deleted file mode 100644 index f7921a2..0000000 Binary files a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_21.png and /dev/null differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_1.png b/.pic/Vivado Basics/Debug manual/fig_01.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_1.png rename to .pic/Vivado Basics/Debug manual/fig_01.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_2.png b/.pic/Vivado Basics/Debug manual/fig_02.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_2.png rename to .pic/Vivado Basics/Debug manual/fig_02.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_3.png b/.pic/Vivado Basics/Debug manual/fig_03.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_3.png rename to .pic/Vivado Basics/Debug manual/fig_03.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_4.png b/.pic/Vivado Basics/Debug manual/fig_04.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_4.png rename to .pic/Vivado Basics/Debug manual/fig_04.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_5.png b/.pic/Vivado Basics/Debug manual/fig_05.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_5.png rename to .pic/Vivado Basics/Debug manual/fig_05.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_6.png b/.pic/Vivado Basics/Debug manual/fig_06.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_6.png rename to .pic/Vivado Basics/Debug manual/fig_06.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_7.png b/.pic/Vivado Basics/Debug manual/fig_07.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_7.png rename to .pic/Vivado Basics/Debug manual/fig_07.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_8.png b/.pic/Vivado Basics/Debug manual/fig_08.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_8.png rename to .pic/Vivado Basics/Debug manual/fig_08.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_9.png b/.pic/Vivado Basics/Debug manual/fig_09.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_9.png rename to .pic/Vivado Basics/Debug manual/fig_09.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_10.png b/.pic/Vivado Basics/Debug manual/fig_10.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_10.png rename to .pic/Vivado Basics/Debug manual/fig_10.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_11.png b/.pic/Vivado Basics/Debug manual/fig_11.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_11.png rename to .pic/Vivado Basics/Debug manual/fig_11.png diff --git a/.pic/Vivado Basics/Debug manual/fig_12.png b/.pic/Vivado Basics/Debug manual/fig_12.png new file mode 100644 index 0000000..2e9ca2e Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_12.png differ diff --git a/.pic/Vivado Basics/Debug manual/fig_13.png b/.pic/Vivado Basics/Debug manual/fig_13.png new file mode 100644 index 0000000..30c94fe Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_13.png differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_12.png b/.pic/Vivado Basics/Debug manual/fig_14.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_12.png rename to .pic/Vivado Basics/Debug manual/fig_14.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_13.png b/.pic/Vivado Basics/Debug manual/fig_15.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_13.png rename to .pic/Vivado Basics/Debug manual/fig_15.png diff --git a/.pic/Vivado Basics/Debug manual/fig_16.png b/.pic/Vivado Basics/Debug manual/fig_16.png new file mode 100644 index 0000000..f832270 Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_16.png differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_15.png b/.pic/Vivado Basics/Debug manual/fig_17.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_15.png rename to .pic/Vivado Basics/Debug manual/fig_17.png diff --git a/.pic/Vivado Basics/Debug manual/fig_18.png b/.pic/Vivado Basics/Debug manual/fig_18.png new file mode 100644 index 0000000..1effb13 Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_18.png differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_17.png b/.pic/Vivado Basics/Debug manual/fig_19.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_17.png rename to .pic/Vivado Basics/Debug manual/fig_19.png diff --git a/.pic/Vivado Basics/Debug manual/fig_20.png b/.pic/Vivado Basics/Debug manual/fig_20.png new file mode 100644 index 0000000..e527314 Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_20.png differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_19.png b/.pic/Vivado Basics/Debug manual/fig_21.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_19.png rename to .pic/Vivado Basics/Debug manual/fig_21.png diff --git a/.pic/Vivado Basics/Debug manual/fig_22.png b/.pic/Vivado Basics/Debug manual/fig_22.png new file mode 100644 index 0000000..3e22ae9 Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_22.png differ diff --git a/.pic/Vivado Basics/Debug manual/fig_23.png b/.pic/Vivado Basics/Debug manual/fig_23.png new file mode 100644 index 0000000..50a2bf3 Binary files /dev/null and b/.pic/Vivado Basics/Debug manual/fig_23.png differ diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_22.png b/.pic/Vivado Basics/Debug manual/fig_24.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_22.png rename to .pic/Vivado Basics/Debug manual/fig_24.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_23.png b/.pic/Vivado Basics/Debug manual/fig_25.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_23.png rename to .pic/Vivado Basics/Debug manual/fig_25.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_24.png b/.pic/Vivado Basics/Debug manual/fig_26.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_24.png rename to .pic/Vivado Basics/Debug manual/fig_26.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_25.png b/.pic/Vivado Basics/Debug manual/fig_27.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_25.png rename to .pic/Vivado Basics/Debug manual/fig_27.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_26.png b/.pic/Vivado Basics/Debug manual/fig_28.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_26.png rename to .pic/Vivado Basics/Debug manual/fig_28.png diff --git a/.pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_27.png b/.pic/Vivado Basics/Debug manual/fig_29.png similarity index 100% rename from .pic/Vivado Basics/Debug manual/bugs_hide_and_seek_tutorial_27.png rename to .pic/Vivado Basics/Debug manual/fig_29.png diff --git a/Other/vector_abs/max_min.sv b/Other/vector_abs/max_min.sv index a04fb07..457e8eb 100644 --- a/Other/vector_abs/max_min.sv +++ b/Other/vector_abs/max_min.sv @@ -5,7 +5,7 @@ module max_min( output logic [ 3:0] min ); - always_comb @(*) begin + always_comb begin if(a > b) begin max = a; min = b; diff --git a/Other/vector_abs/tb_vector_abs.sv b/Other/vector_abs/tb_vector_abs.sv index ebd434b..fcebb01 100644 --- a/Other/vector_abs/tb_vector_abs.sv +++ b/Other/vector_abs/tb_vector_abs.sv @@ -10,8 +10,9 @@ vector_abs dut( .abs(res) ); integer err_count = 0; -task checker(input [31:0]a, b, res); -begin : checker + +task check_result(input logic [31:0]a, b, res); +begin : check_result reg [31:0] ref_res; ref_res = a < b? a/2 + b : a + b/2; if (res !== ref_res) begin @@ -30,22 +31,22 @@ initial begin : test $timeformat(-9,0,"ns"); a = 0; b = 0; #5; - checker(a,b,res); + check_result(a,b,res); a = 1; b = 1; #5; - checker(a,b,res); + check_result(a,b,res); a = 3; b = 4; #5; - checker(a,b,res); + check_result(a,b,res); for(i = 0; i < 100; i=i+1) begin a = $random()&32'hff; b = $random()&32'hff; #5; - checker(a,b,res); + check_result(a,b,res); end $display("Test has been finished with %d errors", err_count); @@ -54,4 +55,4 @@ initial begin : test end $finish(); end -endmodule \ No newline at end of file +endmodule diff --git a/Vivado Basics/Debug manual.md b/Vivado Basics/Debug manual.md index cb7e71e..6446296 100644 --- a/Vivado Basics/Debug manual.md +++ b/Vivado Basics/Debug manual.md @@ -9,6 +9,8 @@ Этот документ посвящен практикуму по поискам подобных ошибок в **SystemVerilog**-коде. +> Обратите внимание на то, как ставится ударение в словосочетании "временна́я диаграмма" (не "вре́менная"). В обиходе это словосочетание заменяется словом "времянка". + - [Руководство по поиску и исправлению ошибок в проекте](#руководство-по-поиску-и-исправлению-ошибок-в-проекте) - [Цель](#цель) - [Алгоритм поиска ошибок](#алгоритм-поиска-ошибок) @@ -27,13 +29,13 @@ 1. Обычно всё начинается с сообщения в логе тестов (никто не проверяет глазами временную диаграмму сложных проектов, состоящую из тысяч сигналов, меняющихся миллионы раз за микросекунду), но на наших простых лабах, этот шаг иногда может быть и пропущен. Сообщение в логе обычно содержит следующую ключевую информацию: имя сигнала, на котором установилось неверное значение, и время когда это произошло. Чем лучше написаны тесты, тем больше ключевой информации будет отражено в сообщении, поэтому написание тестов является своего рода искусством. -1. Получив имя сигнала и время, мы отправляемся на временную диаграмму и проверяем нашу ошибку. Как это сделать? Необходимо определить по коду, какие сигналы и каким образом управляют нашим сигналом. Вариантов может быть несколько: - 1. Управляющие сигналы имеют корректное значение, но логика, по которой они управляют сигналом неверна, из-за этого на нем возникает неверное значение. +2. Получив имя сигнала и время, мы отправляемся на временную диаграмму и проверяем нашу ошибку. Как это сделать? Необходимо определить по коду, какие сигналы и каким образом управляют нашим сигналом. Вариантов может быть несколько: + 1. Управляющие сигналы имеют корректное значение, но логика, по которой они управляют сигналом неверна, из-за этого на нем возникает неверное значение. Это идеальный случай, при возникновении которого мы сразу же находим причину проблемы и исправляем ее. 2. Логика управления верна, а какая-то часть управляющих сигналов имеет неверное значение (пусть для примера, неверное значение будет на управляющем сигнале `X`). Это означает, что обнаруженное несоответствие сигналов является уже следствием какой-то ошибки, и мы должны вернуться к шагу 2, проверяя источники сигналов для сигнала `X`. Так происходит до тех пор, пока мы не попадаем в тип 1. 3. Логика управления и значения управляющих сигналов верны. Это самый сложный тип ошибок, который заключается либо в ошибке в спецификации разрабатываемого устройства, либо в САПРе или компонентах, влияющих на его работу. В рамках данного курса вас не должны заботить данные ошибки, и при их возникновении вам стоит обратиться к преподавателю (предварительно убедившись, что ошибка совершенно точно не подходит под первые два варианта). 4. Любая возможная комбинация всех предыдущих типов. -2. Обнаружив первопричину ошибки, мы исправляем ее (возможно дополняя набор тестов, или внеся правки в спецификацию), и повторно запускаем все тесты, чтобы убедиться в двух вещах: +3. Обнаружив первопричину ошибки, мы исправляем ее (возможно дополняя набор тестов, или внеся правки в спецификацию), и повторно запускаем все тесты, чтобы убедиться в двух вещах: 1. ошибка действительно исправлена 2. исправление ошибки не породило новых ошибок @@ -43,27 +45,41 @@ После запуска симуляции мы видим в логе множество ошибок: -![waveform1](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_1.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_01.png](../.pic/Vivado%20Basics/Debug%20manual/fig_01.png) -В любой ситуации с множеством ошибок, сначала надо разбираться с самой первой из них, поскольку она может быть ключом к появлению всех остальных. Поэтому листаем лог до момента первой ошибки: +_Рисунок 1. Пример сообщения об ошибках в тесте._ -![waveform2](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_2.png) +В любой ситуации с множеством ошибок, сначала надо разбираться с самой первой из них, поскольку она может быть причиной появления всех остальных. Поэтому листаем лог до момента первой ошибки: + +![../.pic/Vivado%20Basics/Debug%20manual/fig_02.png](../.pic/Vivado%20Basics/Debug%20manual/fig_02.png) + +_Рисунок 2. Пример конкретной ошибки в тесте._ В логе сказано, что в момент времени `5ns`, на дизайн подавались координаты вектора, равные `0` и `0`, модель посчитала, что длина вектора равна нулю, в то время как дизайн вернул значение `x`. ## Поиск ошибки на временной диаграмме -Давайте найдем это место на временной диаграмме. Обычно, сразу после запуска симуляции на временной диаграмме отображено место, где симуляция остановилась (возможно с очень неподходящим масштабом). Для начала подгоним масштаб таким образом, чтобы вся временная диаграмма умещалась в окне. Это делается либо нажатием правой кнопкой мыши по в области отображения сигналов, с выбором "Full View" во всплывающем меню, либо нажатием на кнопку Затем найдем приблизительное место рядом с тем временем, что нас интересует, установим там курсор, и приблизим масштаб, периодически уточняя местоположения курсора, пока не найдем интересующее нас место. +Давайте найдем это место на временной диаграмме. Обычно, сразу после запуска симуляции на временной диаграмме отображено место, где симуляция остановилась (возможно с очень неподходящим масштабом). Для начала подгоним масштаб таким образом, чтобы вся временная диаграмма умещалась в окне. Это делается либо нажатием правой кнопкой мыши по в области отображения сигналов, с выбором "Full View" во всплывающем меню, либо нажатием соответствующей кнопки на панели временной диаграммы (см. _рис. 4_), либо нажатием комбинации клавиш `Ctrl+0`. Затем найдем приблизительное место рядом с тем временем, что нас интересует, установим там курсор, и приблизим масштаб (покрутив колесиком мыши при зажатой клавише `Ctrl`), периодически уточняя местоположения курсора, пока не найдем интересующее нас место. -![waveform3](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_3.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_03.png](../.pic/Vivado%20Basics/Debug%20manual/fig_03.png) -![waveform4](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_4.png) +_Рисунок 3. Пример временной диаграммы сразу поле остановки моделирования._ -![waveform4](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_5.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_04.png](../.pic/Vivado%20Basics/Debug%20manual/fig_04.png) -![waveform5](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_6.png) +_Рисунок 4. Пример установки масштаба временной диаграммы таким образом, чтобы та помещалась в текущем окне._ -![waveform6](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_7.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_05.png](../.pic/Vivado%20Basics/Debug%20manual/fig_05.png) + +_Рисунок 5. Пример временной диаграммы после подгонки масштаба._ + +![../.pic/Vivado%20Basics/Debug%20manual/fig_06.png](../.pic/Vivado%20Basics/Debug%20manual/fig_06.png) + +_Рисунок 6. Установка курсора в начало моделирования, чтобы, при увеличении масштаба, временная диаграмма сходилась к началу._ + +![../.pic/Vivado%20Basics/Debug%20manual/fig_07.png](../.pic/Vivado%20Basics/Debug%20manual/fig_07.png) + +_Рисунок 7. Временная диаграмма, отмасштабированная к времени ошибки с рис. 2._ Мы видим ровно ту информацию, которую нам предоставил тестбенч. Теперь надо разобраться в причинах возникновения X-состояния. Такое может произойти в двух ситуациях: какой-то из сигналов, формирующих этот находится в `X` или `Z` состоянии, либо же два каких-то сигнала одновременно пытаются выставить разные значения (подобный вариант встречается куда реже и в цикле ваших лабораторных вряд ли встретится). @@ -71,7 +87,9 @@ В любом случае, первым делом необходимо определить, источник формирования значения сигнала `res`. Для этого, откроем файл с исходным кодом, где определен данный сигнал. Для этого, нажмем правой кнопкой мыши по имени сигнала на временной диаграмме, и выберем `Go To Source Code`: -![waveform7](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_8.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_08.png](../.pic/Vivado%20Basics/Debug%20manual/fig_08.png) + +_Рисунок 8. Переход к месту объявления "проблемного" сигнала._ Открывается следующий код (с курсором на строчке `wire [31:0] res;`): @@ -90,7 +108,8 @@ vector_abs dut( //... ``` -Выделив `res` мы видим, что у нас подсветился `res` в строке `abs(res)`, что означает что мы завели наш провод внутрь объекта `dut` модуля `vector_abs`, и у нас проблема второго типа (X-состояние передалось от выхода `abs` модуля `vector_abs` проводу `res` модуля `tb`). +Выделив `res` мы видим, что у нас подсветился `res` в строке `abs(res)`. Это означает, что мы завели наш провод внутрь объекта `dut` модуля `vector_abs`, и у нас проблема второго типа (X-состояние передалось от выхода `abs` модуля `vector_abs` проводу `res` модуля `tb`). + В этом можно убедиться, если вытащить сигналы модуля `vector_abs` на временную диаграмму. Чтобы это сделать, надо переключиться на окно `Scope`, где размещена иерархия объектов нашего тестбенча ## Добавление сигналов объектов на временную диаграмму @@ -99,16 +118,43 @@ vector_abs dut( Выделим объект `dut`. В окне `Objects` справа отобразятся все внутренние сигналы (входы/выходы, внутренние провода и регистры) объекта `dut`: -![waveform8](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_9.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_09.png](../.pic/Vivado%20Basics/Debug%20manual/fig_09.png) + +_Рисунок 9. Отображение внутренних сигналов проверяемого модуля._ Вообще говоря, мы уже видим, что выход `abs` (к которому подключен наш провод `res`) находится в X-состоянии, но для отработки навыков, разберемся с добавлением на временную диаграмму. Можно поступить двумя способами: 1. Добавить все сигналы (то, что видно в окне `Objects` на временную диаграмму) из окна `Scope` для этого, либо перетаскиваем нужный нам объект, зажав левую кнопку мыши на временную диаграмму, либо жмем правой кнопкой мыши по нужному объекту, и выбираем `Add to Wave Window` 2. Добавить отдельные сигналы из окна `Objects`. Для этого выделяем их (возможно множественное выделение через модификаторы `shift` или `ctrl`), и как и в прошлом случае, либо перетаскиваем сигналы левой кнопкой мыши, либо добавляем их через правую кнопку мыши. -![waveform9](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_10.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_10.png](../.pic/Vivado%20Basics/Debug%20manual/fig_10.png) -![waveform10](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_11.png) +_Рисунок 10. Добавление сигналов модуля на временную диаграмму._ + +![../.pic/Vivado%20Basics/Debug%20manual/fig_11.png](../.pic/Vivado%20Basics/Debug%20manual/fig_11.png) + +_Рисунок 11. Результат добавления сигналов модуля на временную диаграмму._ + +По мере роста сложности проекта, число сигналов на временной диаграмме будет постоянно расти, в связи с чем встает вопрос группировки сигналов. + +Для того чтобы объединить сигналы в группу, необходимо их выделить. Это можно сделать двумя способами: + +1. "прокликав" интересующие сигналы при зажатой клавише `Ctrl`; +2. если речь идет о диапазоне сигналов, можно выбрать сигнал с одного края, после чего, при зажатой клавише `Shift`, выбрать сигнал с другого края этого диапазона. + +После выбора, необходимо нажать правой кнопкой мыши по выделенным сигналам, и в низу выпадающего списка выбрать `New Group`. + +![../.pic/Vivado%20Basics/Debug%20manual/fig_12.png](../.pic/Vivado%20Basics/Debug%20manual/fig_12.png) + +_Рисунок 12. Пример создания группы сигналов (контекстное меню было обрезано для удобства отображения)._ + +После создания группы, ей нужно будет дать имя. В случае, если все сигналы принадлежат одному модулю, удобно называть группу сигналов именем этого модуля. + +![../.pic/Vivado%20Basics/Debug%20manual/fig_13.png](../.pic/Vivado%20Basics/Debug%20manual/fig_13.png) + +_Рисунок 13. Пример созданной группы сигналов._ + +Данну группу можно сворачивать и разворачивать, нажимая на соответствующую стрелку слева от имени группы. > Обратите внимание, что часть сигналов отображают какое-то значение (сигнал `abs` отображает X-состояние), а часть не отображают ничего. Так произошло, потому что провод `abs` **непрерывно связан** с проводом `res`, с точки зрения симулятора это одна сущность, и записывая во время моделирования значения для сигнала `res`, симулятор неявно записывал значения для сигнала `abs`, чего не скажешь про остальные сигналы, которых не было во время моделирования на временной диаграмме. @@ -116,29 +162,36 @@ vector_abs dut( Для того, чтобы получить отсутствующие значения, необходимо повторить моделирование. Для этого, необходимо сбросить время моделирования в 0 и запустить его снова. -Для этого, необходимо на панели симуляции нажать кнопку `Restart` (`|◀`), а затем кнопку `Run all` (`▶`) или `Run for` (`▶t`) +Для этого, необходимо на панели симуляции нажать кнопку `Restart` (`|◀`), а затем кнопку `Run all` (`▶`) или `Run for` (`▶t`). Положение кнопок в окне Vivado иллюстрирует _рис. 14_. + +![../.pic/Vivado%20Basics/Debug%20manual/fig_14.png](../.pic/Vivado%20Basics/Debug%20manual/fig_14.png) + +_Рисунок 14. Расположение кнопок, управляющих моделированием в окне Vivado._ + +Панель управления симуляции с кнопками: + +1. `Restart`, горячие клавиши: `Ctrl+Shift+F5`; +2. `Run all`, горячая клавиша: `F3`; +3. `Run for`, горячие клавиши: `Shift+F2`; +4. `Relaunch Simulation`. + +`Run for` выполняет моделирование указанного количества времени, после чего моделирование приостанавливается. Моделирование может быть остановлено так же и вручную, либо вызовом соответствующей инструкции из кода теста. -`Run for` выполняет моделирование указанного количества времени, после чего моделирование приостанавливается. Моделирование может быть остановлено так же и вручную, либо вызовом соответствующей инструкции из кода теста. `Run all` отличается от `Run for` тем, что в качестве количества моделируемого времени указывается "бесконечность", и моделирование будет остановлено только вручную, либо вызовом соответствующей инструкции. > Обратите внимание, что для добавления недостающих значений добавленных сигналов лучше всего выполнять описанную выше инструкцию. Аналогичного результата можно добиться и нажатием на кнопку `Relaunch Simulation`, однако эта команда запускает повторную компиляцию и запуск симуляции, что для крупных проектов выльется в потерю времени на излишнюю компиляцию. -![waveform11](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_12.png) +Кроме того, чтобы курсор и лог снова не ушли далеко от места первой ошибки, можно сразу указать, необходимое нам время моделирования перед выполнением команды `Run for`: `5ns`. -Панель управления симуляции с кнопками: +![../.pic/Vivado%20Basics/Debug%20manual/fig_15.png](../.pic/Vivado%20Basics/Debug%20manual/fig_15.png) -1. `Restart` -2. `Run all` -3. `Run for` -4. `Relaunch Simulation` +_Рисунок 15. Пример моделирования 5ns._ -Кроме того, чтобы курсор и лог снова не ушли далеко от места первой ошибки, можно сразу указать, необходимое нам время моделирования перед выполнением команды `Run for`: `5ns` +На _рис. 16_ представлен результат моделирования с новыми сигналами. -![waveform12](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_13.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_16.png](../.pic/Vivado%20Basics/Debug%20manual/fig_16.png) -В итоге видим следующую картину на временной диаграмме: - -![waveform13](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_14.png) +_Рисунок 16. Результат повторного моделирования после добавления на временную диаграмму новых сигналов._ Видим два сигнала в Z-состоянии и один сигнал в X-состоянии. Обычно, сигналы с Z-состоянием проще всего исправить, т.к. зачастую это забытое или некорректное подключение провода. Кроме того, сигнал, зависящий от сигнала с Z-состоянием, может оказаться в X-состоянии, так что это может быть решением нашей проблемы, поэтому займемся проводами `min` и `min_half`. Сперва займемся сигналом `min` и перейдем к шагу 2 нашего алгоритма (нажимаем правой кнопкой мыши и выбираем `Go To Source Code`): @@ -163,41 +216,56 @@ vector_abs dut( ## Исправление сигналов с Z-состоянием -Мы видим, что сигнал `min` подключен к выходу `min` объекта `max_min_unit` модуля `max_min`. Добавим сигналы этого модуля на временную диаграмму. Для этого, необходимо раскрыть список объектов, содержащихся в объекте `dut` иерархии объектов `Scope` и выбрать там объект `max_min_unit`: +Мы видим, что сигнал `min` подключен к выходу `min` объекта `max_min_unit` модуля `max_min`. Добавим сигналы этого модуля на временную диаграмму. Для этого, необходимо раскрыть список объектов, содержащихся в объекте `dut` иерархии объектов `Scope` и выбрать там объект `max_min_unit`. -![waveform14](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_15.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_17.png](../.pic/Vivado%20Basics/Debug%20manual/fig_17.png) -Добавляем внутренние сигналы на временную диаграмму, и повторяем моделирование: +_Рисунок 17. Добавление сигналов вложенных модулей на временную диаграмму._ -![waveform15](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_16.png) +Добавляем внутренние сигналы на временную диаграмму, группируем их под именем `max_min`, и повторяем моделирование. + +![../.pic/Vivado%20Basics/Debug%20manual/fig_18.png](../.pic/Vivado%20Basics/Debug%20manual/fig_18.png) + +_Рисунок 18. Результат добавления и группировки сигналов подмодуля `max_min`._ Произошло что-то странное: все внутренние сигналы объекта `max_min_unit` "зеленые" (не имеющие X или Z состояния), однако подключенный к выходу этого модуля сигнал `min` находится в Z-состоянии. Как такое могло произойти? Если присмотреться к сигналу `min`, находящемуся в Z-состоянии, можно заметить, что младшая цифра находится не в Z-состоянии, а в состоянии `0`, такое же значение стоит и на сигнале `min` объекта `max_min_unit`. Это интересно. -Если присмотреться к этим двум сигналам еще пристальней, то можно увидеть, что у сигнала `min` объекта `dut` разрядность 32 бита, в то время как разрядность сигнала `min` объекта `max_min_unit` составляет 4 бита. -Это и является проблемой: мы подключили 4 бита сигнала 4-разрядного сигнала `min` к младшим 4 битам 32-разрядного сигнала `min`, а остальные разряды остались не подключенными. + +Если присмотреться к этим двум сигналам еще пристальней, то можно увидеть, что у сигнала `min` объекта `dut` разрядность 32 бита, в то время как разрядность сигнала `min` объекта `max_min_unit` составляет 4 бита. + +Это и является проблемой: мы подключили 4 бита сигнала 4-разрядного сигнала `min` к младшим 4 битам 32-разрядного сигнала `min`, а остальные разряды остались не подключенными. + По всей видимости, при написании модуля `max_min`, была указана неверная разрядность сигнала `min`, вместо `31` было написано `3`. Исправим это и повторим моделирование. > Обратите внимание, что поскольку мы изменили исходный код, в этот раз необходимо нажать на кнопку `Relaunch Simulation`, поскольку нужна повторная компиляция проекта. -![waveform16](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_17.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_19.png](../.pic/Vivado%20Basics/Debug%20manual/fig_19.png) + +_Рисунок 19. Результат моделирования после исправления разрядности сигнала `min`. + +В логе сообщается о 102 найденных ошибках. Ровно на одну ошибку меньше, чем было ранее. Это не означает, что в проекте осталось 102 ошибки, только то, что, исправив данную ошибку — мы действительно что-то исправили, и один из тестовых сценариев, который ранее завершался ошибкой, теперь завершился без нее. -В логе сообщается о 102 найденных ошибках. Это ровно на одну ошибку меньше, чем было ранее. Это не означает, что в проекте осталось 102 ошибки, только то, что, исправив данную ошибку, мы действительно что-то исправили, и теперь один из тестовых сценариев, который ранее завершался ошибкой, теперь завершился без нее. Помните, что если в проекте много ошибок, то часть ошибок может выправлять поведение других ошибок (хоть и не всегда, но иногда минус на минус может выдать плюс контексте ошибок проекта), поэтому надо осторожно полагаться на число найденных ошибок, если их больше нуля. Посмотрим на нашу временную диаграмму снова, и выберем дальнейшие действия: -![waveform17](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_18.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_20.png](../.pic/Vivado%20Basics/Debug%20manual/fig_20.png) + +_Рисунок 20. Временная диаграмма после исправления разрядности сигнала `min`._ Мы видим, что на временной диаграмме не осталось сигналов в X или Z-состоянии, а значит мы собрали все "низковисящие" улики нашего с вами расследования. Вернемся к месту преступления и попробуем поискать новые улики: -![waveform18](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_19.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_21.png](../.pic/Vivado%20Basics/Debug%20manual/fig_21.png) + +_Рисунок 21. Первая ошибка в новом логе моделирования._ ## Поиск ошибки в сигналах, формирующих проблемный сигнал Мы видим, что первой ошибкой в логе стала не та ошибка, что была прежде. Раньше первый неверный результат мы видели в момент времени `5ns`, когда на дизайн подавались значения `0` и `0`, теперь же первой ошибкой стал момент времени `10ns`, когда на дизайн подаются значения `1` и `1`. Наше устройство считает, что результат должен равняться `3`, в то время как модель считает, что результат должен равняться `1`. Проверим, нет ли ошибки в модели и посчитаем результат самостоятельно: -Для определения приблизительной длины вектора в евклидовом пространстве(вычисления квадратного корня из суммы квадратов / длины гипотенузы прямоугольного треугольника) можно воспользоваться формулой: +Для определения приблизительной длины вектора в евклидовом пространстве(вычисления квадратного корня из суммы квадратов / длины гипотенузы прямоугольного треугольника) можно воспользоваться формулой: + `sqrt(a^2 + b^2) ≈ max + min/2`, где `max` и `min` — большее и меньшее из пары чисел соответственно [**Ричард Лайонс: Цифровая обработка сигналов, Глава 13.2, стр. 475**]. Подставим наши числа в формулу (поскольку оба числа равны, не важно какое из них будет максимумом, а какое минимумом): @@ -206,7 +274,8 @@ vector_abs dut( 1 + 1/2 = 1.5 ``` -Ни модель, ни дизайн не правы? +Ни модель, ни дизайн не правы? + На самом деле, наше устройство поддерживает только целочисленную арифметику, поэтому результат будет: ```text @@ -226,11 +295,15 @@ assign abs = max + min_half; Изучив модуль, мы понимаем, что в логике этого присваивания проблем нет, т.к. оно повторяет логику формулы `max + min/2`, складывая максимум с половиной минимума. Значит проблема в значении какого-то из этих сигналов (или обоих из них). Посчитаем значения этих сигналов самостоятельно (для сложного проекта эти значения бы посчитала модель): `1` и `0`. -Смотрим, какие значения установлены на сигналах `max` и `min_half` в момент времени `10ns`: +Смотрим, какие значения установлены на сигналах `max` и `min_half` в момент времени `10ns`. -![waveform19](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_20.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_22.png](../.pic/Vivado%20Basics/Debug%20manual/fig_22.png) -Мы видим, что в момент времени `10ns` значения `max` и `min_half` изменились ак `1 -> 4` и `2 -> 8` соответственно. Нас интересуют значения `1` и `2`, т.к. в момент времени `10ns` на выходе дизайна в этот момент был установившийся результат для предыдущих значений (еще не успел посчитаться результат для новых значений). +_Рисунок 22. Значения сигналов `max` и `min_half` в момент времени `10 ns` + +> Обратите внимание: вы можете менять и цвета сигналов временной диаграммы через контекстное меню выделенных сигналов. + +Мы видим, что в момент времени `10 ns` значения `max` и `min_half` изменились ак `1 -> 4` и `2 -> 8` соответственно. Нас интересуют значения `1` и `2`, т.к. в момент времени `10ns` на выходе дизайна в этот момент был установившийся результат для предыдущих значений (еще не успел посчитаться результат для новых значений). Значение `max=1` совпадает с ожидаемым, в то время как `min_half=2` явно нет. @@ -251,9 +324,11 @@ endmodule Что делает данный модуль? Он принимает на вход значение и делит его на два. На вход данного модуля будет приходить значение минимума из нашей формулы. -Выход данного модуля зависит от входа `numerator` и логики сдвига влево на 1. Это значит, что проблема либо в логике, либо в значении, подаваемом на вход. Выведем сигнал `numerator` на временную диаграмму и посмотрим на его значение в момент времени `10ns`: +Выход данного модуля зависит от входа `numerator` и логики сдвига влево на 1. Это значит, что проблема либо в логике, либо в значении, подаваемом на вход. Выведем сигнал `numerator` на временную диаграмму и посмотрим на его значение в момент времени `10ns. -![waveform20](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_21.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_23.png](../.pic/Vivado%20Basics/Debug%20manual/fig_23.png) + +_Рисунок 23. Значение сигнала `numerator` в момент времени `10 ns`._ Мы помним, что в момент, когда дизайн начал выдавать неправильный результат, на его входы подавались числа `1` и `1`, это значит, что на вход `numerator` пришло корректное значение: минимум из этих двух чисел и правда равен `1`. Проверим логику данного модуля. @@ -263,18 +338,23 @@ endmodule Именно поэтому, когда мы в первый раз пытались посчитать результат "на бумаге", у нас было расхождение с моделью: когда мы делим 1 на 2, мы получаем 0.5, однако деление путем отбрасывания цифры округляет результат вниз (1/2=0, 15/10=1). -Как "отбросить" цифру средствами цифровой логики? Для этого используется операция сдвига вправо. +Как "отбросить" цифру средствами цифровой логики? Для этого используется операция сдвига вправо. + Операция сдвига вправо в **SystemVerilog** записывается оператором `>>`. Справа от оператора указывается число "отбрасываемых цифр", в нашем случае одна. Но постойте, в логике присваивания стоит оператор `<<`. Это ошибка, исправим ее! Повторяем моделирование. -![waveform21](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_22.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_24.png](../.pic/Vivado%20Basics/Debug%20manual/fig_24.png) + +_Рисунок 24. Результат моделирования после исправления оператора сдвига._ Снова на одну ошибку меньше. Не унываем, вряд ли в проекте число ошибок больше, чем число непустых строк самого проекта. Возвращаемся к начальной ошибке: -![waveform22](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_23.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_25.png](../.pic/Vivado%20Basics/Debug%20manual/fig_25.png) -Мы продвинулись во времени безошибочного моделирования до `15ns`, начинаем наше расследование с начала: +_Рисунок 25. Первая ошибка в повторном моделировании._ + +Мы продвинулись во времени безошибочного моделирования до `15 ns`, начинаем наше расследование с начала: На вход дизайна подаются значения `3` и `4`, дизайн считает, что результатом вычисления `max + min/2` будет `2`, модель считает, что `5`. Посчитаем сами: @@ -288,9 +368,11 @@ max + min/2 = 4 + 3/2 = 4 + 1 = 5 ## Проблема необъявленных сигналов -Поскольку на временной диаграмме стало уже очень много сигналов, уберем лишние, оставив только внутренние сигналы модуля `vector_abs`: +К этому моменту на вашей временной диаграмме скорей всего стало уже очень много сигналов. Уберем лишние, оставив только внутренние сигналы модуля `vector_abs` (для этого выделяем не нужные сигналы, и удаляем их с помощью клавиши `Delete`). -![waveform23](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_24.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_26.png](../.pic/Vivado%20Basics/Debug%20manual/fig_26.png) + +_Рисунок 26. Поведение внутренних сигналов модуля `vector_abs` на временной диаграмме._ В глаза сразу же бросается, что сигнал `max` внешне отличается от всех остальных — он ведет себя как однобитный сигнал. Если все остальные сигналы 32-разрядные, то и сигнал `max` должен быть таким же. Перейдем к объявлению этого сигнала, чтобы это исправить (нажав правой кнопкой мыши, и выбрав `Go To Source Code`): @@ -318,19 +400,26 @@ max + min/2 = 4 + 3/2 = 4 + 1 = 5 Для исправления этой ошибки, объявим сигнал `max` с корректной разрядностью и повторим моделирование. -![waveform24](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_25.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_27.png](../.pic/Vivado%20Basics/Debug%20manual/fig_27.png) + +_Рисунок 27. Результат моделирования после объявления пропущенного сигнала._ ## Самостоятельная работа Число ошибок сократилось до 40! Мы явно на верном пути. Повторяем предыдущие шаги, вернувшись к первой ошибке: -![waveform25](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_26.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_28.png](../.pic/Vivado%20Basics/Debug%20manual/fig_28.png) + +_Рисунок 28. Первая ошибка в повторном моделировании._ В этот раз первая ошибка осталась прежней, только теперь дизайн считает, что результат должен равняться шести (в прошлый раз дизайн выдавал `2`). Мы уже убедились, что в этом случае модель дает правильный результат, поэтому сразу перейдем к формирующим результат сигналам: -![waveform26](../.pic/Vivado%20Basics/Debug%20manual/bugs_hide_and_seek_tutorial_27.png) +![../.pic/Vivado%20Basics/Debug%20manual/fig_29.png](../.pic/Vivado%20Basics/Debug%20manual/fig_29.png) + +_Рисунок 29. Поведение внутренних сигналов модуля `vector_abs` на временной диаграмме._ + +Видим, что значение сигнала `min_half`, формирующего значение выхода `abs` неверно (минимумом из `3` и `4` является `3`, `3/2 = 1`). -Видим, что значение сигнала `min_half`, формирующего значение выхода `abs` неверно (минимумом из `3` и `4` является `3`, `3/2 = 1`). Не отходя далеко от кассы, мы замечаем, что значение `min`, формирующее сигнал `min_half` неверно: его значение `4`, а должно быть `3`. Используя [файлы исходного кода проекта](../Other/vector_abs/), попробуйте разобраться в последней обнаруженной нами ошибке.