This shows you the differences between two versions of the page.
cn1:resurse:debug [2020/02/29 13:50] bogdan.firuti |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | * Tutorialul își propune depanarea unui modul folosind uneltele de debugging puse la dispoziție de simulatorul integrat în Xilinx ISE. Scopul modului este să implementeze un sumator cu propagare a transportului (ripple carry). O implementare Verilog a acestuia, care conține 2 greșeli, este prezentată în figura următoare. | ||
- | {{ cn1:tutoriale:debug-ise:00.jpg?direct&400 |}} | ||
- | |||
- | * Modulul de test folosit pentru simulare este următorul. | ||
- | {{ cn1:tutoriale:debug-ise:01.jpg?direct&400 |}} | ||
- | * Simularea inițială a modului poate fi observată în figura următoare. Se observă că semnalul //sum// conține valori nedefinite (//X//) pe toată durata de simulare a modulului. | ||
- | {{ cn1:tutoriale:debug-ise:02.jpg?direct&400 |}} | ||
- | * Pentru a ne ușura analiza semnalelor vom schimba modul în care aceastea sunt afișate. Apăsând click-dreapta pe un semnal vom alege ca acesta să fie afișat ca un număr în baza 10, fără semn. | ||
- | {{ cn1::tutoriale:debug-ise:03.jpg?direct&400 |}} | ||
- | * După ce schimbăm toate semnalele, diagrama va arăta în felul următor. | ||
- | {{ cn1:tutoriale:debug-ise:04.jpg?direct&400 |}} | ||
- | * Putem expanda un semnal pe mai multi biți pentru a inspecta toți biții acestuia. | ||
- | {{ cn1:tutoriale:debug-ise:05.jpg?direct&400 |}} | ||
- | * Se poate observa că doar bitul 7 din ''//sum//'' este nedefinit. | ||
- | {{ cn1:tutoriale:debug-ise:06.jpg?direct&400 |}} | ||
- | * Putem vedea variabilele interne unui modul dacă selectăm selectăm instanța acestuia din lista de instanțe. În cadrul ierarhiei, modulul nostru se află imediat sub modulul ''//test_adder//'', iar instanța acestuia se numește ''//uut//'' (//unit under test//). | ||
- | {{ cn1:tutoriale:debug-ise:07.jpg?direct&400 |}} | ||
- | * Putem deschide codul sursă al unei instanțe în simulator făcând dublu-click pe aceasta. | ||
- | {{ cn1:tutoriale:debug-ise:08.jpg?direct&400 |}} | ||
- | * În cadrul editorului de cod putem activa un breakpoint la linia curentă folosind tasta ''//F9//'' sau făcând click pe porțiunea gri din dreapta numărului liniei. | ||
- | {{ cn1:tutoriale:debug-ise:09.jpg?direct&400 |}} | ||
- | * În continuare vom activa 2 breakpoint-uri, la liniile 35 și 37, pentru a putea inspecta starea variabilelor în fiecare iterație și la sfârșitul ciclului. | ||
- | {{ cn1:tutoriale:debug-ise:10.jpg?direct&400 |}} | ||
- | * Repornim simularea folosind butonul //Restart//. | ||
- | {{ cn1:tutoriale:debug-ise:11.jpg?direct&400 |}} | ||
- | * Se poate observa că la începutul simulării toate variabilele modulului ''//uut//'' sunt nedefinite(''x'' inseamna nedefinit), lucru normal deoarece simularea nu a început încă . | ||
- | {{ cn1:tutoriale:debug-ise:12.jpg?direct&400 |}} | ||
- | * Folosim butonul ''//Run All//'' pentru a porni simularea. | ||
- | {{ cn1:tutoriale:debug-ise:13.jpg?direct&400 |}} | ||
- | * Simularea se va opri la orice breakpoint întâlnit. În cazul nostrul, primul breakpoint întâlnit este cel de la linia 35, iar simularea se va opri **înainte** de a executa instrucțiunea de la linia 35. În acest moment al simulării putem vedea că ambele intrări ale modului au valoarea 0, contorul ciclului are valoarea 0 (ne aflăm în prima iterație), iar ieșirile sunt încă nedefinite, deoarece încă nu le-am atribuit nici o valoare. | ||
- | {{ cn1:tutoriale:debug-ise:14.jpg?direct&400 |}} | ||
- | * Vom rula simularea în continuare folosind butonul ''//Run All//''. Simularea se va opri din nou la breakpoint-ul de la linia 35, însa în momentul acesta ne aflăm în a doua iterație a ciclului. Putem vedea lucrul acesta inspectând valoarea contorului, care este 1 (prima valoare a contorului a fost 0). În această iterație vedem că primul bit al lui ''//sum//'' a fost setat la valoarea 0. | ||
- | {{ cn1:tutoriale:debug-ise:15.jpg?direct&400 |}} | ||
- | * Rulăm în continuare simularea, folosind butonul ''//Run All//'', până când execuția ciclului se termină și ajungem la breakpoint-ul de la linia 37. În acest moment, pentru o implementare corectă, suma celor două intrări ar trebui să fie calculată complet. Observăm însă că cel mai semnificativ bit al lui //sum// a rămas nedefinit. Înseamnă că ciclul nostru s-a terminat prea repede. Inspectând condiția de oprire, vedem că ieșirea din ciclu se face când ''//i//'' devine 7. Iterația corespunzătoare lui ''//i == 7//'' nu se execută, ceea ce explică de ce bitul 7 din ''//sum//'' este nedefinit. | ||
- | {{ cn1:tutoriale:debug-ise:16.jpg?direct&400 |}} | ||
- | * Modificăm codul corectând cu condiția corectă: ''//i < **8**//''. | ||
- | {{ cn1:tutoriale:debug-ise:17.jpg?direct&400 |}} | ||
- | * După ce am modificat codul modulului este necesar să recompilăm simularea pentru a vedeam efectele schimbării. Folosim butonul ''//Re-launch//'' pentru a recompila și rerula simularea. | ||
- | {{ cn1:tutoriale:debug-ise:18.jpg?direct&400 |}} | ||
- | * __Eliminăm breakpoint-urile făcând click pe ele sau folosind tasta //F9// pentru a putea rula ușor simularea până la capăt cu butonul ''//Run All//''__. La o primă vedere, din fereastra de variabile, rezultatul pare a fi corect, semnalele nedefinite au dispărut, iar suma pare a fi calculată corect. | ||
- | {{ cn1:tutoriale:debug-ise:19.jpg?direct&400 |}} | ||
- | * Inspectarea digramei de semnale, însă, arată că suma dintre 10 și 40 este 39. | ||
- | {{ cn1:tutoriale:debug-ise:20.jpg?direct&400 |}} | ||
- | * Adăugăm din nou breakpoint-urile anterioare și reluăm simularea de la început cu butonul ''//Restart//''. | ||
- | {{ cn1:tutoriale:debug-ise:21.jpg?direct&400 |}} | ||
- | * Rulăm simularea până ajungem în prima iterație a celei de-a doua pereche de numere adunate. Recunoaștem această stare după valorile ''//00101000//'' și'' //00001010//'' prezente la intrarile ''//a//'' și ''//b//'' și valoarea 0 a controului ''//i//''. Valoarea sumei, ''//00000000//'', este rămasă de la adunarea anterioară. | ||
- | {{ cn1:tutoriale:debug-ise:22.jpg?direct&400 |}} | ||
- | * În a doua iterație vedem că suma calculată în prima iterație pentru cel mai puțin semnificativ bit al lui ''//sum//'' este **1**. Din datele de intrare: ''//a[0] == 0//'', ''//b[0] == 0//'' și ''//c_in == 0//'' am deduce că această sumă ar trebui să fie 0. Inspectând expresia pentru calcul sumei, observăm că rezultatul pentru toți biții lui //sum// se calculează cu ''//b[**1**]//''. | ||
- | {{ cn1:tutoriale:debug-ise:23.jpg?direct&400 |}} | ||
- | * Modificăm codul, corectând cu expresia corectă a sumei în funcție de //b[**i**]//. | ||
- | {{ cn1:tutoriale:debug-ise:24.jpg?direct&400 |}} | ||
- | * Dezactivăm breakpoint-urile, recompilăm simularea și inspectăm din nou diagrama de semnale. Cu modificările făcute, circuitul pare să funcționeze corect (cel puțin pentru cele 4 cazuri testate). | ||
- | {{ cn1:tutoriale:debug-ise:25.jpg?direct&400 |}} | ||
- | * În continuare, pentru a ne asigura de funcționarea corectă a modului, acesta trebuie testat folosind mai multe combinații pentru variabilele de intrare (în special cazuri limită). La descoperirea unei erori în output, vom relua procesul de debugging, pentru a găsi și corecta bug-ul. |