Skocz do zawartości

PicoBlaze z jaką maksymalną częstotliwością zegara działa na Elbercie?


FlyingDutch

Pomocna odpowiedź

Ok, więc wycofuję pytanie.

A jeszcze raz zmieniając temat - jakby ktoś chciał uruchomić quartus-a na Linuxie to mogę opisać, bo dzisiaj drugi raz to robiłem i znowu mi pół dnia zeszło żeby bez praw root-a biednego maximatora zaprogramować 🙂

Link do komentarza
Share on other sites

Najpierw to powiedz która wersja - bo wersja wersji nierówna (tylko podaj też obok numeru czy Lite czy Standard czy inna). A po co? A po to, że co nowa wersja to możliwe ukryte kruczki, które nie będą miały przełożenia na starsze wersje, gdzie takowych np: nie ma (śmieszne, ale np: przy Vivado jak się ściągnęło najnowszą wersję to nagle wyszło, że wszystko jest wywrócone do góry nogami - a tylko chciałem zmienić wersję 😃). Poza tym tak to zrobisz nadzieję komuś, kto ma np: starszą wersję i będzie się motał, bo nie pomyśli, że działasz na najnowszej 😃

Link do komentarza
Share on other sites

Wersja 17.0.0 Lite, ale problem jest inny - proces jtagd działą pięknie jeśli jest uruchamiany z prawami root-a. Ale domyślnie nie jest, więc trzeba się trochę namęczyć z konfiguracją. To dotyczy pewnie wszystkich wersji środowiska, bo odnosi się do programatora, a nie IDE jako takiego.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Hej,

zwiększyłem zegar dla PicoBlaze na Elbercie (ostatnio opisany projet z mruganiem LED)do 240 MHz i program zaczął się zachowywać niestabilnie. Nadal mruga diodą LED ale z mocno losowym okresem (raz dioda świeci kilka sekund bez przerwy następnie seria szybkich mrugnięć bez jekiegoś stałego okresu). Być może można by zrobić optymalizację rozmieszczenia zasobów w płytce FPGA, ale podejrzewam, że bez jakichś bardziej zaawansowanych optymalizacji częstotliwość zegara 240 MHz jest już za duża dla PicoBlaze dla Elberta.

Pozdrawiam

Link do komentarza
Share on other sites

Zapnij generator z zewnątrz i zrób to samo (pętle PLL wnoszą dodatkowe opóźnienia na poziomie układu, podczas gdy w przypadku takiego generatora jest szansa na mniejsze, zwłaszcza jeśli opóźnienia modułów do wyprowadzeń I/O mają ich mniejsze wartości - wtedy też nieco większą częstotliwość uzyskasz teoretycznie - a nawet jeśli nie to będziesz miał zatem odpowiedź, że bloki pamięciowe nie wyrabiają się i już).

Link do komentarza
Share on other sites

Cześć,

metodą prób i błędów ustaliłem, że maksymalna częstotliwość zegara dla Soft_CPU PicoBlaze na zestawie Elbert V2 to 180 MHz (bez żadnych dodatkowych zaawansowanych optymalizacji układu).

Czyli wydajność 90 MIPS to naprawdę nieźle porównując np. do 16 MIPS (zegar 16 MHz) dla także 8-mio bitowejATmegi328 z Arduino UNO. No tylko, że wewnętrzna pamięć RAM 2K i pamięć programu 32K słów dla Atmegi to duża różnica (no i jeszcze architektura "Harvard" w Przypadku ATmegi , czyli osobna pamięć programu i danych co także jest na plus dla ATmegi). Jestem bardzo ciekaw jak przedstawia się porównanie obydwu CPU dla programu rozwiązującego ten sam problem (taki sam algorytm).

Pozdrawiam

Mały Update: w dokumentacji do PicoBlaze (wersja na Spartan3) pisze, że PicoBlaze na Spartanie3 może działać z max. częstotliwością 88Mhz (44MIPS), co stoi w sprzeczności z dokonanymi eksperymentami 😉

Link do komentarza
Share on other sites

Not bad ^^ Dałeś mi w każdym razie też temat do roboty w wolnym czasie na uczelni 😃 Ale to jak będzie czas poza projektami i studiami doktoranckimi ^^ A kto wie - może ktoś taką pracę dyplomową dostanie i pobada MicroBlaze'y i PicoBlaze'y i porówna to z NIOS II (jako doktor dałbym z chęcią taki temat ^^)

Link do komentarza
Share on other sites

Not bad ^^ Dałeś mi w każdym razie też temat do roboty w wolnym czasie na uczelni 😃 Ale to jak będzie czas poza projektami i studiami doktoranckimi ^^ A kto wie - może ktoś taką pracę dyplomową dostanie i pobada MicroBlaze'y i PicoBlaze'y i porówna to z NIOS II (jako doktor dałbym z chęcią taki temat ^^)

No temat całkiem ciekawy, jeśli się go odpowiednio rozwinie 🙂 Teraz zająłem się pomysłem na "framebuffer" dla VGA - najpierw spróbuję temat pobadać na Spartanie6 (tam jest dużo więcej zasobów szczególnie dostępnej RAM), terazz dysponuję też płytką Mimas V2 Numato. Jakby coś z tego wyszło to razem z PicoBlaze jest baza aby spróbować portu jakiejś bardzo prostej gry (to był pomysł Elvisa z jego artykułu dot VGA, ale bardzo przypadł mi do gustu).

Drugi temat to przesyłanie instrukcji programu w assemblerze dla PicoBlaze przez UART (i wykonywanie tego programu na FPGA), jest fajny filmik na Youtube z takim pomysłem. Tylko, że niedługo skończy się wolne i będzie trzeba powrócić do nudnej codzienności pisania jakichś programów finansowych w C# 🙁

Pozdrawiam

Link do komentarza
Share on other sites

Więcej RAM-u? Masz na myśli DDR? Bo pamięć blockRAM jest niewiele większa niż w Elbercie... Ciekaw jestem czy uda Ci się wykorzystać DDR do framebuffera. Dostęp jest chyba zbyt wolny, ale może się mylę.

[ Dodano: 29-12-2017, 17:59 ]

Ok, źle przeczytałem w nocie katalogowej - jednak jest większa.

Link do komentarza
Share on other sites

Więcej RAM-u? Masz na myśli DDR? Bo pamięć blockRAM jest niewiele większa niż w Elbercie... Ciekaw jestem czy uda Ci się wykorzystać DDR do framebuffera. Dostęp jest chyba zbyt wolny, ale może się mylę.

[ Dodano: 29-12-2017, 17:59 ]

Ok, źle przeczytałem w nocie katalogowej - jednak jest większa.

Myślę o Block RAM w Spartanie3 z Elberta jest jej 73 Kb a w Spartanie6 z Mimasa jest 576 Kb.

Link do komentarza
Share on other sites

Cześć,

jak było to opisane wiemy, że max. częstotliwość zegara dla PicoBlaze (ElbertV2) została ustalona na 180 MHz. Jednak do testów używaliśmy bardzo prostego programu w assemblerze PicoBlaze migającego diodą LED.

Przyszedł czas, aby przeprowadzić bardziej zaawansowane próby. Może się okazać, że testując PicoBlaze z programem, który używa operacji arytmetyczno-logicznych z CPU (w pętli) będą występowały przekłamania obliczeń przy niższej częstotliwości zegara.

Mój wybór algorytmu padł na funkcję kontroli błędów CRC-8 ponieważ ma ona stosunkowo prostą realizacje, którą da się "przeportować" z języka C na assembler PicBlaze.

Znalazłem fajną stronę WWW opisującą (na przykładach) jak liczyć algorytm CRC-8 dla danych wejściowych będących jednym bajtem. Strona ta zawiera także krótkie wprowadzenie teoretyczne do sposobów obliczania funkcji CRC ogólnie. Oto ta strona:

http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch1

W podpunkcie 4.2 tej strony podana jest prosta implementacja funkcji CRC-8 w języku C, oraz "ręczny" przykład obliczeń tej funkcji dla danej wejściowej (jeden bajt) o wartości 0xC2 heksdecymalnie. Oto kod w języku C;

public static byte Compute_CRC8_Simple_OneByte(byte byteVal)
{
   const byte generator = 0x1D;
   byte crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */

   for (int i = 0; i < 8; i++)
   {
       if ((crc & 0x80) != 0)
       { /* most significant bit set, shift crc register and perform XOR operation, taking not-saved 9th set bit into account */
           crc = (byte)((crc << 1) ^ generator);
       }
       else
       { /* most significant bit not set, go to next bit */
           crc <<= 1;
       }
   }

   return crc;
} 

A tutaj przykład "ręcznego liczenia tej funkcji dla danej wejściowej 0xC2:

Step-by-step visualization of simple CRC-8 algorithmus:
1100001000000000	crc = 0xC2
100011101	i = 0: 0xC2 = b11000010 -> MSB set:
---------	
010011001 	i = 0: crc = (crc << 1) ^ generator = (0xC2 << 1) ^ 0x1D = 0x184 ^ 0x1D = 0x99.
100011101 	i = 1: 0x99 = b10011001 -> MSB set:
---------	
0000101111 	i = 1: crc = (0x99 << 1) ^ 0x1D = 0x132 ^ 0x1D = 0x2F
  100011101 	i = 2: 0x2F = b00101111 -> MSB not set: crc = (0x2F << 1) = 0x5E
   100011101 	i = 3: 0x5E = b01011110 -> MSB not set: crc = (0x5E << 1) = 0xBC
    100011101 	i = 4: 0xBC = b10111100 -> MSB set:
    ---------	
    001100101 	i = 4: crc = (0xBC << 1) ^ 0x1D = 0x178 ^ 0x1D = 0x65
     100011101 	i = 5: 0x65 = b01100101 -> MSB not set: crc = (0x65 << 1) = 0xCA
      100011101 	i = 6: 0xCA = b11001010 -> MSB set:
      ---------	
      010001001 	i = 6: crc = (0xCA << 1) ^ 0x1D = 0x194 ^ 0x1D = 0x89
       100011101 	i = 7: 0x89 = b10001001 -> MSB set:
       ---------	
       000001111 	i = 7: crc = (0x89 << 1) ^ 0x1D = 0x112 ^ 0x1D = 0x0F

Jak widać z kodu są w nim intensywnie używane przesunięcia bitowe oraz funkcja XOR.

Trzeba zauważyć, że w tej wersji algorytmu CRC-8 został użyty inny wielomian niż w standardowej wersji tego algortmu: 0x1D heksadecymalnie, dlatego jeśli skorzystamy z jakiejś wersji generatora on-line (CRC-8) to uzyskamy inne wyniki. Jako przykład wykorzystania funkcji CRC można podać CRC-7, który jest używany jako suma kontrolna służąca do sprawdzania poprawności danych zapisywanych na kartach pamięci SD.

Aby przetestować kod funkcji napisałem na jego podstawie krótki program dla "Arduino IDE" oczywiście można użyć innego kompilatora C/C++ (gcc z mingw32, C++ builder, Visual Studio itp.) Oto kod programu dla Arduino IDE:

/* CRC-8 algorithm implementation */

byte CalcCRC8 = 0x00;//Obliczona wartosc CRC-8

byte Compute_CRC8_Simple_OneByte(byte byteVal)
{
   const byte generator = 0x1D;//Uzyty wielomian (custom)
   byte crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */

   for (int i = 0; i < 8; i++)
   {
       if ((crc & 0x80) != 0)
       { /* most significant bit set, shift crc register and perform XOR operation, taking not-saved 9th set bit into account */
           crc = (byte)((crc << 1) ^ generator);
       }
       else
       { /* most significant bit not set, go to next bit */
           crc <<= 1;
       }
   }
   return crc;
} 

// the setup routine runs once when you press reset:
void setup() {
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
 CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);
 Serial.println(CalcCRC8, HEX);
 delay(3000);        // delay 3s
}

A oto wynik działania tego programu:

Jak widać obliczona wartość F (0x0F) zgadza się z podanymi wyżej obliczeniami. Nie jest dla nas istotne jakiego wielomianu używa podana implementacja CRC-8 - ważne jest, że wiemy jaka powinna być obliczona suma CRC-8 dla danej danej wejściowej.

Teraz trzeba przenieść ten algorytm z języka C na assembler dla PicoBlaze i wgrać do naszego CPU na FPGA i zobaczyć, przy jakiej częstotliwości zegara zaczną występować przekłamania w liczeniu.

To zajmie mi trochę czasu, dlatego ciąg dalszy tego postu za jakiś czas 😉

W międzyczasie znalazłem kompilator języka C dla PicoBlaze. Oto link:

http://www.fit.vutbr.cz/~meduna/work/doku.php?id=projects:vlam:pbcc:pbcc

Pobieramy pakiet:

Binary package: pbccv2-bin-win32-cygwin-2011-09-01.zip (5.1 MB)

i rozpakowujemy. Otwieramy okno "command" w Windowsie i przechodzimy do katalogu gdzie rozpakowaliśmy pakiet (podkatalog: tests\pblaze):

C:\_PicBlazeCompiler\pbccv2-bin-win32-cygwin\tests\pblaze

i w oknie wywołujemy komendę build (z parametrem którym jest nazwa pliku z programem C):

C:\_PicBlazeCompiler\pbccv2-bin-win32-cygwin\tests\pblaze>build funlit.c

w tym samym katalogu powsatnie plik o nazwie programu C z rozszerzeniem psm - jest to program w assemblerze PicoBlaze.

w programie C - algorytm CRC-8 musiałem trochę zmodyfikować kod (nie ma typu danych byte trzeba go zamienić na unsigned char i trochę zmodyfikować kod pętli for).

Oto zmodyfikowany kod programu do kompilacji:

/* CRC-8 algorithm implementation */

unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8

unsigned char Compute_CRC8_Simple_OneByte(unsigned char byteVal)
{
   const unsigned char generator = 0x1D;//Uzyty wielomian (custom)
   unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
   int i = 0;
   for (i; i < 8; i++)
   {
       if ((crc & 0x80) != 0)
       { /* most significant bit set, shift crc register and perform XOR operation, taking not-saved 9th set bit into account */
           crc = (unsigned char)((crc << 1) ^ generator);
       }
       else
       { /* most significant bit not set, go to next bit */
           crc <<= 1;
       }
   }
   return crc;
} 

void main()
{
  CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);
}

Po kompilacji ten program w assemblerze PicoBlaze wygląda tak:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 3.0.1 #6227 (Oct 24 2011) (CYGWIN)
; This file was generated Mon Jan  1 19:24:51 2018
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
CONSTANT	_CalcCRC8, 00

;	TstFunc1.c:3: unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8
LOAD	s0, 00
STORE	s0, _CalcCRC8
LOAD	sF, 3f
JUMP	__sdcc_program_startup
;--------------------------------------------------------
; Home
;--------------------------------------------------------
__sdcc_program_startup:
CALL	_main
;	return from main will lock up
__sdcc_loop:
JUMP	__sdcc_loop
;--------------------------------------------------------
; code
;--------------------------------------------------------
;	TstFunc1.c:5: unsigned char Compute_CRC8_Simple_OneByte(unsigned char byteVal)
_Compute_CRC8_Simple_OneByte:
LOAD	s0, sB
;	TstFunc1.c:8: unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
;	TstFunc1.c:10: for (i; i < 8; i++)
LOAD	s1, 00
LOAD	s2, 00
_L00104:
TEST	s2, 80
JUMP	C, _LC00116
COMPARE	s2, 00
JUMP	C, _LC00116
COMPARE	s1, 08
JUMP	C, _LC00116
JUMP	_L00113
_LC00116:
;	TstFunc1.c:12: if ((crc & 0x80) != 0)
LOAD	s3, s0
AND	s3, 80
COMPARE	s3, 00
JUMP	NZ, _LC00117
JUMP	_L00102
_LC00117:
;	TstFunc1.c:14: crc = (unsigned char)((crc << 1) ^ generator);
LOAD	s3, s0
SL0	s3
LOAD	s4, s3
XOR	s4, 1d
LOAD	s0, s4
JUMP	_L00106
_L00102:
;	TstFunc1.c:18: crc <<= 1;
LOAD	s3, s0
SL0	s3
LOAD	s0, s3
_L00106:
;	TstFunc1.c:10: for (i; i < 8; i++)
ADD	s1, 01
ADDCY	s2, 00
JUMP	_L00104
_L00113:
;	TstFunc1.c:21: return crc;
LOAD	sB, s0
RETURN
;	TstFunc1.c:24: void main()
_main:
;	TstFunc1.c:26: CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);
LOAD	sB, c2
CALL	_Compute_CRC8_Simple_OneByte
LOAD	s0, sB
STORE	s0, _CalcCRC8
RETURN
;--------------------------------------------------------
; interrupt vector 
;--------------------------------------------------------

Niestety po załadowaniu do symulatora "pBlazeIDE" mam sygnalizowanych sporo błędów - patrz obrazek:

Nawet tak prosty kod C jak ten:

char sum(char nnn1, char n2, char n3)
{
return nnn1 + n2 + n3;
}

void main()
{
char c = 29;
char d = 57;
char e = 113;
sum (c, d, e);	
}

Po kompilacji do ASM:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 3.0.1 #6227 (Oct 24 2011) (CYGWIN)
; This file was generated Mon Jan  1 18:52:51 2018
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------

LOAD	sF, 3f
JUMP	__sdcc_program_startup
;--------------------------------------------------------
; Home
;--------------------------------------------------------
__sdcc_program_startup:
CALL	_main
;	return from main will lock up
__sdcc_loop:
JUMP	__sdcc_loop
;--------------------------------------------------------
; code
;--------------------------------------------------------
;	funlit.c:1: char sum(char nnn1, char n2, char n3)
_sum:
LOAD	s0, sB
LOAD	s1, sC
LOAD	s2, sD
;	funlit.c:3: return nnn1 + n2 + n3;
ADD	s0, s1
ADD	s0, s2
LOAD	sB, s0
RETURN
;	funlit.c:7: void main()
_main:
;	funlit.c:12: sum (c, d, e);
LOAD	sB, 1d
LOAD	sC, 39
LOAD	sD, 71
CALL	_sum
RETURN
;--------------------------------------------------------
; interrupt vector 
;--------------------------------------------------------

Powoduje kilka błędów po załadowaniu do "pBlazeIDE". Na dzisiaj już muszę kończyć, może ktoś z Was ma pomysł jak zmodyfikować program w assemblerze, aby można go przesymulować w "pBlazeIDE" i wykonać w PicoBlaze?

Będę wdzięczny za wszystkie uwagi 😅

------------------------------------------------------------------------------------------------------

Update: dzięki analizie przyczyn błędów wygenerowanego programu obliczania CRC-8 w assemblerze dokonanej przez Jakuba, byłem w stanie poprawić ten program, tak, aby dało go się przesymulować w "pBlazeIDE". Oto ten poprawiony kod programu:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 3.0.1 #6227 (Oct 24 2011) (CYGWIN)
; This file was generated Tue Jan  2 11:22:17 2018
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
;CONSTANT	_CalcCRC8, 00 - nie jest obslgiwane w pBlazeIDE
_CalcCRC8 	   EQU   sF ; przypisujemy rejestr: sF

   LOAD _CalcCRC8, 00
;	TstFunc1.c:3: volatile unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8
LOAD	s0, 00
STORE	s0, _CalcCRC8
LOAD	sF, 63 ;3f
JUMP	__sdcc_program_startup
;--------------------------------------------------------
; Home
;--------------------------------------------------------
__sdcc_program_startup:
CALL	_main
;	return from main will lock up
__sdcc_loop:
JUMP	__sdcc_loop
;--------------------------------------------------------
; code
;--------------------------------------------------------
;	TstFunc1.c:5: unsigned char Compute_CRC8_Simple_OneByte(volatile unsigned char byteVal)
_Compute_CRC8_Simple_OneByte:
LOAD	s0, sB
;	TstFunc1.c:7: volatile const unsigned char generator = 0x1D;//Uzyty wielomian (custom)
LOAD	s1, 29 ;1d
;	TstFunc1.c:8: volatile unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
LOAD	s2, s0
LOAD	s3, s2
;	TstFunc1.c:10: for (i; i < 8; i++)
LOAD	s2, 00
LOAD	s4, 00
_L00104:
TEST	s4, 128 ;80
JUMP	C, _LC00116
COMP	s4, 00
JUMP	C, _LC00116
COMP	s2, 08
JUMP	C, _LC00116
JUMP	_L00113
_LC00116:
;	TstFunc1.c:12: if ((crc & 0x80) != 0)
LOAD	s5, s3
LOAD	s6, s5
AND	    s6, 128 ;80
COMP	s6, 00
JUMP	NZ, _LC00117
JUMP	_L00102
_LC00117:
;	TstFunc1.c:14: crc = (unsigned char)((crc << 1) ^ generator);
LOAD	s5, s3
SL0	    s5
LOAD	s6, s1
LOAD	s7, s5
XOR	    s7, s6
LOAD	s3, s7
JUMP	_L00106
_L00102:
;	TstFunc1.c:18: crc <<= 1;
LOAD	s5, s3
SL0	    s5
LOAD	s3, s5
_L00106:
;	TstFunc1.c:10: for (i; i < 8; i++)
ADD	    s2, 01
ADDC	s4, 00
JUMP	_L00104
_L00113:
;	TstFunc1.c:21: return crc;
LOAD	s2, s3
LOAD	sB, s2
RET
;	TstFunc1.c:24: void main()
_main:
;	TstFunc1.c:26: CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);
LOAD	sB, 194 ;c2
CALL	_Compute_CRC8_Simple_OneByte
LOAD	s0, sB
STORE	s0, _CalcCRC8
RET
;--------------------------------------------------------
; interrupt vector 
;--------------------------------------------------------

A tutaj wynik symulacji programu:

Jak widać po zakończeniu programu w rejestrze s0 do którego jest składowana obliczona wartość funkcji CRC-8 jest wartość: 0F, co jest prawidłowe dla danej wejściowej 0xC2 (194 dziesiętnie).

Byłbym zapomniał - trochę zmodyfikowałem kod programu w C liczenia CRC-8 z którego został wygenerowany program assemblerowy (część zmiennych została oznaczona jako volatile zgodnie z zaleceniami dokumentacji kompilatora). Oto ten kod:

/* CRC-8 algorithm implementation */

volatile unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8

unsigned char Compute_CRC8_Simple_OneByte(volatile unsigned char byteVal)
{
   volatile const unsigned char generator = 0x1D;//Uzyty wielomian (custom)
   volatile unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
   int i = 0;
   for (i; i < 8; i++)
   {
       if ((crc & 0x80) != 0)
       { /* most significant bit set, shift crc register and perform XOR operation, taking not-saved 9th set bit into account */
           crc = (unsigned char)((crc << 1) ^ generator);
       }
       else
       { /* most significant bit not set, go to next bit */
           crc <<= 1;
       }
   }
   return crc;
} 

void main()
{
  CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);
}

Teraz wystarczy tylko w programie assemblerowym zapętlić obliczanie CRC-8 i wykonać sprawdzenie, czy obliczona wartość funkcji jest poprawna, a gdy nie dać informację o błędzie obliczeń - np. zapalić diodę LED.

Potem trzeba program przepuścić przez program "kcpsm3.exe" i wygenerować zawartość pamięci ROM dla PicoBlaze i zmodyfikować projekt w VHDL z CPU PicoBlaze.

No a gdy będzie to gotowe testować projekt PicoBlaze, aby ustalić dla jakiego zegara pojawią się błędy obliczeń :->

Mam już gotowy działający i sprawdzony program w assemblerze PicoBlaze sprawdzony w symulatorze pBlazeIDE (liczy w pętli CRC-8 a gdy wynik porównania obliczonej funkcji z oczekiwaną wartością (0x0F) jest błędny zapala diodę LED). Oto kod:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 3.0.1 #6227 (Oct 24 2011) (CYGWIN)
; This file was generated Tue Jan  2 13:30:45 2018
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
   LED_OUT    DSOUT $00

   ;CONSTANT led_port_nr      , 00    ; numer portu, do ktorego przylaczony jest LED

   led_port_nr    EQU   sD ; przypisujemy rejestr: sD   
   LOAD led_port_nr, $00

;CONSTANT	_CalcCRC8, 00 ;konstrukcja nie obsługiwana

   _CalcCRC8 	   EQU   sF ; przypisujemy rejestr: sF

   LOAD _CalcCRC8, 00

;	CRC8_Pico.c:3: volatile unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8
LOAD	s0, 00
STORE	s0, _CalcCRC8
LOAD	sF, 63 ;3f
JUMP	__sdcc_program_startup
;--------------------------------------------------------
; Home
;--------------------------------------------------------
__sdcc_program_startup:
CALL	_main
;	return from main will lock up
__sdcc_loop:
JUMP	__sdcc_loop
;--------------------------------------------------------
; code
;--------------------------------------------------------
;	CRC8_Pico.c:6: unsigned char Compute_CRC8_Simple_OneByte(volatile unsigned char byteVal)
_Compute_CRC8_Simple_OneByte:
LOAD	s0, sB
;	CRC8_Pico.c:8: volatile const unsigned char generator = 0x1D;//Uzyty wielomian (custom)
LOAD	s1, 29 ;1d
;	CRC8_Pico.c:9: volatile unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
LOAD	s2, s0
LOAD	s3, s2
;	CRC8_Pico.c:11: for (i; i < 8; i++)
LOAD	s2, 00
LOAD	s4, 00
_L00104:
TEST	s4, 128 ;80
JUMP	C, _LC00125
COMP	s4, 00
JUMP	C, _LC00125
COMP	s2, 08
JUMP	C, _LC00125
JUMP	_L00113
_LC00125:
;	CRC8_Pico.c:13: if ((crc & 0x80) != 0)
LOAD	s5, s3
LOAD	s6, s5
AND	    s6, 128 ;80
COMP	s6, 00
JUMP	NZ, _LC00126
JUMP	_L00102
_LC00126:
;	CRC8_Pico.c:15: crc = (unsigned char)((crc << 1) ^ generator);
LOAD	s5, s3
SL0	    s5
LOAD	s6, s1
LOAD	s7, s5
XOR	    s7, s6
LOAD	s3, s7
JUMP	_L00106
_L00102:
;	CRC8_Pico.c:19: crc <<= 1;
LOAD	s5, s3
SL0	    s5
LOAD	s3, s5
_L00106:
;	CRC8_Pico.c:11: for (i; i < 8; i++)
ADD	    s2, 01
ADDC	s4, 00
JUMP	_L00104
_L00113:
;	CRC8_Pico.c:22: return crc;
LOAD	s2, s3
LOAD	sB, s2
RET
;	CRC8_Pico.c:26: void Zapal_LED_Blad() {} 
_Zapal_LED_Blad:
   LOAD led_port_nr, 01
   OUT led_port_nr, LED_OUT ;Zaswiec diode LED Blad
RET
;	CRC8_Pico.c:28: void main()
_main:
   LOAD led_port_nr, 00
   OUT led_port_nr, LED_OUT  ;zgas diodę LED Blad   
_L00119:
;	CRC8_Pico.c:33: CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);//Poprawny wynik 0x0F
LOAD	sB, 194 ;c2 - dana wejsciowa 1 bajt
CALL	_Compute_CRC8_Simple_OneByte
LOAD	s0, sB
STORE	s0, _CalcCRC8
;	CRC8_Pico.c:34: if (CalcCRC8 != 0x0F) Zapal_LED_Blad();
FETCH	s0, _CalcCRC8
COMP	s0, 15 ;0f
JUMP	NZ, _LC00127
JUMP	_L00119
_LC00127:
CALL	_Zapal_LED_Blad
JUMP	_L00119
RET
;--------------------------------------------------------
; interrupt vector 
;--------------------------------------------------------

A tutaj kod programu w C z którego został wygenerowany program assemblerowy (a następnie ręcznie zmodyfikowany aby działał w symulatorze):

/* CRC-8 algorithm based PicoBlaze ALU check  */

volatile unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8

//Funkcja obliczajaca CRC-8
unsigned char Compute_CRC8_Simple_OneByte(volatile unsigned char byteVal)
{
   volatile const unsigned char generator = 0x1D;//Uzyty wielomian (custom)
   volatile unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
   int i = 0;
   for (i; i < 8; i++)
   {
       if ((crc & 0x80) != 0)
       { /* most significant bit set, shift crc register and perform XOR operation, taking not-saved 9th set bit into account */
           crc = (unsigned char)((crc << 1) ^ generator);
       }
       else
       { /* most significant bit not set, go to next bit */
           crc <<= 1;
       }
   }
   return crc;
}

//Funkcja obslugi bledu obliczen
void Zapal_LED_Blad() {} 

void main()
{
  //Infinite loop 
  for (;;) 
  {
     CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);//Poprawny wynik 0x0F
     if (CalcCRC8 != 0x0F) Zapal_LED_Blad();
  }
}

A tam wyglądają wyniki symulacji w pBlazeIDE:

Jak widać port LED_OUT (górny prawy róg obrazka) żadna dioda się nie świeci. Gdy zmieniłem wartość w porównaniu - instrukcja:

COMP s0, 15 ;0f

na np.

COMP s0, 14 ;0f

w symulatorze świeciła się dioda z tego portu o numerze 1.

Teraz wystarczy tylko ten program dać na wejście assemblera "kpcsm3.exe" wygenerować zawartość ROM dla PIcoBlaze w VHDLu i zmodyfikować projekt "ISE" naszego CPU.

Tutaj kod assemblera programu z powrotem przekonwertowany, aby był zgodny z assemblerem "KCPSM3.EXE" dołączonym do kodu procesora PicoBlaze prez Xilinxa:

;--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 3.0.1 #6227 (Oct 24 2011) (CYGWIN)
; This file was generated Tue Jan  2 13:30:45 2018
;--------------------------------------------------------
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
   CONSTANT    led_port_nr , 00    ; numer portu, do ktorego przylaczony jest LED
CONSTANT	_CalcCRC8, 00       ; Wynik obliczenia funkcji CRC-8

;	CRC8_Pico.c:3: volatile unsigned char CalcCRC8 = 0x00;//Obliczona wartosc CRC-8
LOAD	s0, 00
STORE	s0, _CalcCRC8
LOAD	sF, 3f
JUMP	__sdcc_program_startup
;--------------------------------------------------------
; Home
;--------------------------------------------------------
__sdcc_program_startup:
CALL	_main
;	return from main will lock up
__sdcc_loop:
JUMP	__sdcc_loop
;--------------------------------------------------------
; code
;--------------------------------------------------------
;	CRC8_Pico.c:6: unsigned char Compute_CRC8_Simple_OneByte(volatile unsigned char byteVal)
_Compute_CRC8_Simple_OneByte:
LOAD	s0, sB
;	CRC8_Pico.c:8: volatile const unsigned char generator = 0x1D;//Uzyty wielomian (custom)
LOAD	s1, 1d
;	CRC8_Pico.c:9: volatile unsigned char crc = byteVal; /* init crc directly with input byte instead of 0, avoid useless 8 bitshifts until input byte is in crc register */
LOAD	s2, s0
LOAD	s3, s2
;	CRC8_Pico.c:11: for (i; i < 8; i++)
LOAD	s2, 00
LOAD	s4, 00
_L00104:
TEST	s4, 80
JUMP	C, _LC00125
COMPARE	s4, 00
JUMP	C, _LC00125
COMPARE	s2, 08
JUMP	C, _LC00125
JUMP	_L00113
_LC00125:
;	CRC8_Pico.c:13: if ((crc & 0x80) != 0)
LOAD	s5, s3
LOAD	s6, s5
AND	    s6, 80
COMPARE	s6, 00
JUMP	NZ, _LC00126
JUMP	_L00102
_LC00126:
;	CRC8_Pico.c:15: crc = (unsigned char)((crc << 1) ^ generator);
LOAD	s5, s3
SL0	    s5
LOAD	s6, s1
LOAD	s7, s5
XOR	    s7, s6
LOAD	s3, s7
JUMP	_L00106
_L00102:
;	CRC8_Pico.c:19: crc <<= 1;
LOAD	s5, s3
SL0	    s5
LOAD	s3, s5
_L00106:
;	CRC8_Pico.c:11: for (i; i < 8; i++)
ADD	    s2, 01
ADDCY	s4, 00
JUMP	_L00104
_L00113:
;	CRC8_Pico.c:22: return crc;
LOAD	s2, s3
LOAD	sB, s2
RETURN
;	CRC8_Pico.c:26: void Zapal_LED_Blad() {} 
_Zapal_LED_Blad:
   LOAD   sD, 01                 ; sD <= 1
   OUTPUT sD, led_port_nr        ;Zaswiec diode LED Blad
RETURN
;	CRC8_Pico.c:28: void main()
_main:
   LOAD   sD, 00                 ; sD <= 0
   OUTPUT sD, led_port_nr        ;Zgas diodę LED Blad   
_L00119:
;	CRC8_Pico.c:33: CalcCRC8 = Compute_CRC8_Simple_OneByte(0xC2);//Poprawny wynik 0x0F
LOAD	sB, c2                ;Dana wejsciowa dla CRC-8 (1 bajt)
CALL	_Compute_CRC8_Simple_OneByte
LOAD	s0, sB
STORE	s0, _CalcCRC8
;	CRC8_Pico.c:34: if (CalcCRC8 != 0x0F) Zapal_LED_Blad();
FETCH	s0, _CalcCRC8
COMPARE	s0, 0f
JUMP	NZ, _LC00127
JUMP	_L00119
_LC00127:
CALL	_Zapal_LED_Blad
JUMP	_L00119
RETURN
;--------------------------------------------------------
; interrupt vector 
;--------------------------------------------------------

Program skompilował się tym assemblerem poprawnie i powstał plik VHDL, który należy dołączyć do projektu PicoBlaze03 (opis pamięci ROM CPU PicoBlaze):

--
-- Definition of a single port ROM for KCPSM3 program defined by crc8.psm
--
-- Generated by KCPSM3 Assembler 02Jan2018-18:20:06. 
--
-- Standard IEEE libraries
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
--
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--  
library unisim;
use unisim.vcomponents.all;
--
--
entity crc8 is
   Port (      address : in std_logic_vector(9 downto 0);
           instruction : out std_logic_vector(17 downto 0);
                   clk : in std_logic);
   end crc8;
--
architecture low_level_definition of crc8 is
--
-- Attributes to define ROM contents during implementation synthesis. 
-- The information is repeated in the generic map for functional simulation
--
attribute INIT_00 : string; 
attribute INIT_01 : string; 
attribute INIT_02 : string; 
attribute INIT_03 : string; 
attribute INIT_04 : string; 
attribute INIT_05 : string; 
attribute INIT_06 : string; 
attribute INIT_07 : string; 
attribute INIT_08 : string; 
attribute INIT_09 : string; 
attribute INIT_0A : string; 
attribute INIT_0B : string; 
attribute INIT_0C : string; 
attribute INIT_0D : string; 
attribute INIT_0E : string; 
attribute INIT_0F : string; 
attribute INIT_10 : string; 
attribute INIT_11 : string; 
attribute INIT_12 : string; 
attribute INIT_13 : string; 
attribute INIT_14 : string; 
attribute INIT_15 : string; 
attribute INIT_16 : string; 
attribute INIT_17 : string; 
attribute INIT_18 : string; 
attribute INIT_19 : string; 
attribute INIT_1A : string; 
attribute INIT_1B : string; 
attribute INIT_1C : string; 
attribute INIT_1D : string; 
attribute INIT_1E : string; 
attribute INIT_1F : string; 
attribute INIT_20 : string; 
attribute INIT_21 : string; 
attribute INIT_22 : string; 
attribute INIT_23 : string; 
attribute INIT_24 : string; 
attribute INIT_25 : string; 
attribute INIT_26 : string; 
attribute INIT_27 : string; 
attribute INIT_28 : string; 
attribute INIT_29 : string; 
attribute INIT_2A : string; 
attribute INIT_2B : string; 
attribute INIT_2C : string; 
attribute INIT_2D : string; 
attribute INIT_2E : string; 
attribute INIT_2F : string; 
attribute INIT_30 : string; 
attribute INIT_31 : string; 
attribute INIT_32 : string; 
attribute INIT_33 : string; 
attribute INIT_34 : string; 
attribute INIT_35 : string; 
attribute INIT_36 : string; 
attribute INIT_37 : string; 
attribute INIT_38 : string; 
attribute INIT_39 : string; 
attribute INIT_3A : string; 
attribute INIT_3B : string; 
attribute INIT_3C : string; 
attribute INIT_3D : string; 
attribute INIT_3E : string; 
attribute INIT_3F : string; 
attribute INITP_00 : string;
attribute INITP_01 : string;
attribute INITP_02 : string;
attribute INITP_03 : string;
attribute INITP_04 : string;
attribute INITP_05 : string;
attribute INITP_06 : string;
attribute INITP_07 : string;
--
-- Attributes to define ROM contents during implementation synthesis.
--
attribute INIT_00 of ram_1024_x_18  : label is "58134400581324800400020013201200011D10B04005002C40040F3FE0000000";
attribute INIT_01 of ram_1024_x_18  : label is "40231370F7601750161005061530402054194600A68016501530402658134208";
attribute INIT_02 of ram_1024_x_18  : label is "00060BC2CD000D00A000CD000D01A0001B201230400CA4008201135005061530";
attribute INIT_03 of ram_1024_x_18  : label is "0000000000000000000000000000A000402E0029402E5436400F6000E00010B0";
attribute INIT_04 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_05 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_06 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_07 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_08 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_09 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0A of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0B of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0C of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0D of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0E of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_0F of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_10 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_11 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_12 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_13 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_14 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_15 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_16 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_17 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_18 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_19 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1A of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1B of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1C of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1D of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1E of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_1F of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_20 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_21 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_22 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_23 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_24 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_25 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_26 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_27 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_28 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_29 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2A of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2B of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2C of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2D of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2E of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_2F of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_30 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_31 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_32 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_33 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_34 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_35 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_36 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_37 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_38 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_39 of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3A of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3B of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3C of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3D of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3E of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INIT_3F of ram_1024_x_18  : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_00 of ram_1024_x_18 : label is "000000000000000000000000000000000002FF48C8A20D48C023D03DDD000FC8";
attribute INITP_01 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_02 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_03 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_04 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_05 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_06 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
attribute INITP_07 of ram_1024_x_18 : label is "0000000000000000000000000000000000000000000000000000000000000000";
--
begin
--
 --Instantiate the Xilinx primitive for a block RAM
 ram_1024_x_18: RAMB16_S18
 --synthesis translate_off
 --INIT values repeated to define contents for functional simulation
 generic map ( INIT_00 => X"58134400581324800400020013201200011D10B04005002C40040F3FE0000000",
               INIT_01 => X"40231370F7601750161005061530402054194600A68016501530402658134208",
               INIT_02 => X"00060BC2CD000D00A000CD000D01A0001B201230400CA4008201135005061530",
               INIT_03 => X"0000000000000000000000000000A000402E0029402E5436400F6000E00010B0",
               INIT_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_07 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_08 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_09 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_0A => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_0B => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
               INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",    
              INITP_00 => X"000000000000000000000000000000000002FF48C8A20D48C023D03DDD000FC8",
              INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
              INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
              INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
              INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
              INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
              INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
              INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
 --synthesis translate_on
 port map(    DI => "0000000000000000",
             DIP => "00",
              EN => '1',
              WE => '0',
             SSR => '0',
             CLK => clk,
            ADDR => address,
              DO => instruction(15 downto 0),
             DOP => instruction(17 downto 16)); 
--
end low_level_definition;
--
------------------------------------------------------------------------------------
--
-- END OF FILE crc8.vhd
--
------------------------------------------------------------------------------------

Teraz wystarczy delikatnie zmodyfikować nasz projekt "ISE" i zsyntetyzować procesor;

W załączniku pełen plik projektu "ISE Webpack" procesora PicoBlaze z programem liczącym funkcję CRC-8 jako test CPU (ALU - operacje arytmetyczno-logiczne).

PicoBlaze06.zip

  • Lubię! 1
Link do komentarza
Share on other sites

Otóż jak się okazuje ten symulator akceptuje wyłącznie składnie taką jaką używa się w środowisku OpenPIC. Jak do tego doszedłem? Metodą prób i eksperymentów, odkrywając, że:

1. zamiast RETURN jest RET,
2. zamiast COMPARE jest COMP,
3. zamiast ADDCY jest ADDC.

Potem zauważyłem, że odpowiada to składni dla tego środowiska tak jak tutaj: http://ece.gmu.edu/coursewebpages/ECE/ECE448/S14/viewgraphs/ECE448_lecture16_PicoBlaze_instruction_set.pdf

i na bazie tego jeszcze wstawiłem deklaracje dla stałych tak jak w tym linku (np: kkk EQU 80) i zadziałało! Poza tym odkryłem, że tutaj nie są w ogóle akceptowane wartości szesnastkowe (nie łyka ani np: 0xFF, ani FF'h) , a tylko dziesiętne (np: bezpośrednio: 10, 20, 150 i lub 10'd, 20'd, 150'd itd.) i binarne (np: 0001'b, 0100'b itd). Jak już to co najwyżej jako namiastkę szesnatkowych zapisów można wstawić np 28'h czy 30'h, ale np: już nie AB'h czy FF'h (innymi słowy - najpierw jest liczba dziesiętna, a potem atrybut, że niby chcę skonwertować to do szesnatkowej liczby - podobnie z binarnymi). I tyle ^^ Zauważ też, że poprawne instrukcje są pogrubiane (np: ADDCY nie jest poprawne, ale ADDC już jest pogrubiane, czyli jest poprawne)

  • Lubię! 1
Link do komentarza
Share on other sites

Otóż jak się okazuje ten symulator akceptuje wyłącznie składnie taką jaką używa się w środowisku OpenPIC. Jak do tego doszedłem? Metodą prób i eksperymentów, odkrywając, że:

1. zamiast RETURN jest RET,
2. zamiast COMPARE jest COMP,
3. zamiast ADDCY jest ADDC.

Potem zauważyłem, że odpowiada to składni dla tego środowiska tak jak tutaj: http://ece.gmu.edu/coursewebpages/ECE/ECE448/S14/viewgraphs/ECE448_lecture16_PicoBlaze_instruction_set.pdf

i na bazie tego jeszcze wstawiłem deklaracje dla stałych tak jak w tym linku (np: kkk EQU 80) i zadziałało! Poza tym odkryłem, że tutaj nie są w ogóle akceptowane wartości szesnastkowe (nie łyka ani np: 0xFF, ani FF'h) , a tylko dziesiętne (np: bezpośrednio: 10, 20, 150 i lub 10'd, 20'd, 150'd itd.) i binarne (np: 0001'b, 0100'b itd). Jak już to co najwyżej jako namiastkę szesnatkowych zapisów można wstawić np 28'h czy 30'h, ale np: już nie AB'h czy FF'h (innymi słowy - najpierw jest liczba dziesiętna, a potem atrybut, że niby chcę skonwertować to do szesnatkowej liczby - podobnie z binarnymi). I tyle ^^ Zauważ też, że poprawne instrukcje są pogrubiane (np: ADDCY nie jest poprawne, ale ADDC już jest pogrubiane, czyli jest poprawne)

Jakub,

bardzo dziękuję , za tą analizę. dzisiaj wieczorem miałem zajęty czas, ale jutro dokonam modyfikacji i prób zgodnie z twoim opisem, a teraz stawiam piwo 😉

Pozdrawiam

Link do komentarza
Share on other sites

Drobiazg ^^ W końcu jako naukowy człowiek jestem właśnie od analiz 🙂 Niemnie wracając do tematu - oczywiście testowałem tylko pod względem błędów (nie sprawdzałem dalej jak idzie symulacja - stąd spodziewam się, że pewnie na tym się nie skończy i zauważysz jakieś dalsze błędy - a jeśli tak no to dalej się będziemy martwić 🙂)

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.