URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 34 to Rev 35
- ↔ Reverse comparison
Rev 34 → Rev 35
/neorv32/trunk/docs/figures/neorv32_axi_soc.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
neorv32/trunk/docs/figures/neorv32_axi_soc.png
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: neorv32/trunk/docs/figures/neorv32_processor.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: neorv32/trunk/docs/NEORV32.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: neorv32/trunk/rtl/core/neorv32_application_image.vhd
===================================================================
--- neorv32/trunk/rtl/core/neorv32_application_image.vhd (revision 34)
+++ neorv32/trunk/rtl/core/neorv32_application_image.vhd (revision 35)
@@ -6,7 +6,7 @@
package neorv32_application_image is
- type application_init_image_t is array (0 to 668) of std_ulogic_vector(31 downto 0);
+ type application_init_image_t is array (0 to 669) of std_ulogic_vector(31 downto 0);
constant application_init_image : application_init_image_t := (
00000000 => x"00000093",
00000001 => x"00000113",
@@ -60,7 +60,7 @@
00000049 => x"00158593",
00000050 => x"ff5ff06f",
00000051 => x"00001597",
- 00000052 => x"9a458593",
+ 00000052 => x"9a858593",
00000053 => x"80000617",
00000054 => x"f2c60613",
00000055 => x"80000697",
@@ -104,18 +104,18 @@
00000093 => x"00112623",
00000094 => x"00812423",
00000095 => x"478000ef",
- 00000096 => x"5a8000ef",
+ 00000096 => x"568000ef",
00000097 => x"02050a63",
00000098 => x"410000ef",
00000099 => x"78800513",
00000100 => x"500000ef",
00000101 => x"00000513",
- 00000102 => x"5a0000ef",
+ 00000102 => x"560000ef",
00000103 => x"00000413",
00000104 => x"0ff47513",
- 00000105 => x"594000ef",
+ 00000105 => x"554000ef",
00000106 => x"0c800513",
- 00000107 => x"53c000ef",
+ 00000107 => x"554000ef",
00000108 => x"00140413",
00000109 => x"fedff06f",
00000110 => x"76400513",
@@ -242,7 +242,7 @@
00000231 => x"00112e23",
00000232 => x"01c00413",
00000233 => x"2ec000ef",
- 00000234 => x"a6048493",
+ 00000234 => x"a6448493",
00000235 => x"ffc00993",
00000236 => x"008957b3",
00000237 => x"00f7f793",
@@ -280,13 +280,13 @@
00000269 => x"0400006f",
00000270 => x"00001737",
00000271 => x"00279793",
- 00000272 => x"9b870713",
+ 00000272 => x"9bc70713",
00000273 => x"00e787b3",
00000274 => x"0007a783",
00000275 => x"00078067",
00000276 => x"00001737",
00000277 => x"00241793",
- 00000278 => x"9fc70713",
+ 00000278 => x"a0070713",
00000279 => x"00e787b3",
00000280 => x"0007a783",
00000281 => x"00078067",
@@ -299,7 +299,7 @@
00000288 => x"34002573",
00000289 => x"ef5ff0ef",
00000290 => x"00001537",
- 00000291 => x"9ac50513",
+ 00000291 => x"9b050513",
00000292 => x"200000ef",
00000293 => x"34302573",
00000294 => x"ee1ff0ef",
@@ -306,7 +306,7 @@
00000295 => x"00812403",
00000296 => x"00c12083",
00000297 => x"00001537",
- 00000298 => x"a5850513",
+ 00000298 => x"a5c50513",
00000299 => x"01010113",
00000300 => x"1e00006f",
00000301 => x"00001537",
@@ -373,7 +373,7 @@
00000362 => x"301027f3",
00000363 => x"00079863",
00000364 => x"00001537",
- 00000365 => x"a2c50513",
+ 00000365 => x"a3050513",
00000366 => x"0d8000ef",
00000367 => x"1e000793",
00000368 => x"30579073",
@@ -450,28 +450,28 @@
00000439 => x"00048513",
00000440 => x"fa1ff0ef",
00000441 => x"fc9ff06f",
- 00000442 => x"00050593",
- 00000443 => x"fe002503",
- 00000444 => x"ff010113",
- 00000445 => x"00112623",
- 00000446 => x"00f55513",
- 00000447 => x"044000ef",
- 00000448 => x"00051863",
- 00000449 => x"00c12083",
- 00000450 => x"01010113",
- 00000451 => x"00008067",
- 00000452 => x"00000013",
- 00000453 => x"00000013",
- 00000454 => x"00000013",
- 00000455 => x"00000013",
- 00000456 => x"fff50513",
- 00000457 => x"fddff06f",
- 00000458 => x"fe802503",
- 00000459 => x"01055513",
- 00000460 => x"00157513",
- 00000461 => x"00008067",
- 00000462 => x"f8a02223",
- 00000463 => x"00008067",
+ 00000442 => x"fe802503",
+ 00000443 => x"01055513",
+ 00000444 => x"00157513",
+ 00000445 => x"00008067",
+ 00000446 => x"f8a02223",
+ 00000447 => x"00008067",
+ 00000448 => x"00050593",
+ 00000449 => x"fe002503",
+ 00000450 => x"ff010113",
+ 00000451 => x"00112623",
+ 00000452 => x"00f55513",
+ 00000453 => x"02c000ef",
+ 00000454 => x"00051863",
+ 00000455 => x"00c12083",
+ 00000456 => x"01010113",
+ 00000457 => x"00008067",
+ 00000458 => x"00000013",
+ 00000459 => x"00000013",
+ 00000460 => x"00000013",
+ 00000461 => x"00000013",
+ 00000462 => x"fff50513",
+ 00000463 => x"fddff06f",
00000464 => x"00050613",
00000465 => x"00000513",
00000466 => x"0015f693",
@@ -626,56 +626,57 @@
00000615 => x"75616320",
00000616 => x"203a6573",
00000617 => x"00000000",
- 00000618 => x"00204020",
- 00000619 => x"544d202c",
- 00000620 => x"3d4c4156",
- 00000621 => x"00000000",
- 00000622 => x"00000514",
- 00000623 => x"00000420",
+ 00000618 => x"50204020",
+ 00000619 => x"00003d43",
+ 00000620 => x"544d202c",
+ 00000621 => x"3d4c4156",
+ 00000622 => x"00000000",
+ 00000623 => x"00000514",
00000624 => x"00000420",
00000625 => x"00000420",
- 00000626 => x"00000520",
- 00000627 => x"00000420",
+ 00000626 => x"00000420",
+ 00000627 => x"00000520",
00000628 => x"00000420",
00000629 => x"00000420",
- 00000630 => x"0000052c",
- 00000631 => x"00000420",
+ 00000630 => x"00000420",
+ 00000631 => x"0000052c",
00000632 => x"00000420",
00000633 => x"00000420",
00000634 => x"00000420",
- 00000635 => x"00000538",
- 00000636 => x"00000544",
- 00000637 => x"00000550",
- 00000638 => x"0000055c",
- 00000639 => x"00000468",
- 00000640 => x"000004b4",
- 00000641 => x"000004c0",
- 00000642 => x"000004cc",
- 00000643 => x"000004d8",
- 00000644 => x"000004e4",
- 00000645 => x"000004f0",
- 00000646 => x"000004fc",
- 00000647 => x"00000420",
+ 00000635 => x"00000420",
+ 00000636 => x"00000538",
+ 00000637 => x"00000544",
+ 00000638 => x"00000550",
+ 00000639 => x"0000055c",
+ 00000640 => x"00000468",
+ 00000641 => x"000004b4",
+ 00000642 => x"000004c0",
+ 00000643 => x"000004cc",
+ 00000644 => x"000004d8",
+ 00000645 => x"000004e4",
+ 00000646 => x"000004f0",
+ 00000647 => x"000004fc",
00000648 => x"00000420",
00000649 => x"00000420",
- 00000650 => x"00000508",
- 00000651 => x"4554523c",
- 00000652 => x"4157203e",
- 00000653 => x"4e494e52",
- 00000654 => x"43202147",
- 00000655 => x"43205550",
- 00000656 => x"73205253",
- 00000657 => x"65747379",
- 00000658 => x"6f6e206d",
- 00000659 => x"76612074",
- 00000660 => x"616c6961",
- 00000661 => x"21656c62",
- 00000662 => x"522f3c20",
- 00000663 => x"003e4554",
- 00000664 => x"33323130",
- 00000665 => x"37363534",
- 00000666 => x"42413938",
- 00000667 => x"46454443",
+ 00000650 => x"00000420",
+ 00000651 => x"00000508",
+ 00000652 => x"4554523c",
+ 00000653 => x"4157203e",
+ 00000654 => x"4e494e52",
+ 00000655 => x"43202147",
+ 00000656 => x"43205550",
+ 00000657 => x"73205253",
+ 00000658 => x"65747379",
+ 00000659 => x"6f6e206d",
+ 00000660 => x"76612074",
+ 00000661 => x"616c6961",
+ 00000662 => x"21656c62",
+ 00000663 => x"522f3c20",
+ 00000664 => x"003e4554",
+ 00000665 => x"33323130",
+ 00000666 => x"37363534",
+ 00000667 => x"42413938",
+ 00000668 => x"46454443",
others => x"00000000"
);
/neorv32/trunk/rtl/core/neorv32_bootloader_image.vhd
126,7 → 126,7
00000115 => x"f1450513", |
00000116 => x"0007a023", |
00000117 => x"2fd000ef", |
00000118 => x"14d000ef", |
00000118 => x"159000ef", |
00000119 => x"ffff1537", |
00000120 => x"f4c50513", |
00000121 => x"2ed000ef", |
189,7 → 189,7
00000178 => x"00b41463", |
00000179 => x"fc9566e3", |
00000180 => x"00100513", |
00000181 => x"5a8000ef", |
00000181 => x"5b4000ef", |
00000182 => x"0b4000ef", |
00000183 => x"ffff1937", |
00000184 => x"ffff19b7", |
218,7 → 218,7
00000207 => x"03740063", |
00000208 => x"07300793", |
00000209 => x"00f41663", |
00000210 => x"660000ef", |
00000210 => x"66c000ef", |
00000211 => x"fb1ff06f", |
00000212 => x"06c00793", |
00000213 => x"00f41863", |
475,9 → 475,9
00000464 => x"00898533", |
00000465 => x"f41ff0ef", |
00000466 => x"fc5ff06f", |
00000467 => x"fd010113", |
00000468 => x"02812423", |
00000469 => x"fe802403", |
00000467 => x"fe802783", |
00000468 => x"fd010113", |
00000469 => x"02812423", |
00000470 => x"02112623", |
00000471 => x"02912223", |
00000472 => x"03212023", |
486,285 → 486,285
00000475 => x"01512a23", |
00000476 => x"01612823", |
00000477 => x"01712623", |
00000478 => x"00847413", |
00000479 => x"00040663", |
00000480 => x"00400513", |
00000481 => x"c69ff0ef", |
00000482 => x"00050493", |
00000483 => x"02051863", |
00000484 => x"ffff1537", |
00000485 => x"e9c50513", |
00000486 => x"538000ef", |
00000487 => x"008005b7", |
00000488 => x"00048513", |
00000489 => x"f31ff0ef", |
00000490 => x"4788d7b7", |
00000491 => x"afe78793", |
00000492 => x"02f50463", |
00000493 => x"00000513", |
00000494 => x"fcdff06f", |
00000495 => x"ffff1537", |
00000496 => x"ebc50513", |
00000497 => x"50c000ef", |
00000498 => x"e15ff0ef", |
00000499 => x"fc0518e3", |
00000500 => x"00300513", |
00000501 => x"fb1ff06f", |
00000502 => x"008009b7", |
00000503 => x"00498593", |
00000504 => x"00048513", |
00000505 => x"ef1ff0ef", |
00000506 => x"00050a13", |
00000507 => x"00898593", |
00000508 => x"00048513", |
00000509 => x"ee1ff0ef", |
00000510 => x"ff002b83", |
00000511 => x"00050a93", |
00000512 => x"ffca7b13", |
00000513 => x"00000913", |
00000514 => x"00c98993", |
00000515 => x"013905b3", |
00000516 => x"052b1863", |
00000517 => x"01540433", |
00000518 => x"00200513", |
00000519 => x"f60414e3", |
00000520 => x"ffff1537", |
00000521 => x"ec850513", |
00000522 => x"4a8000ef", |
00000523 => x"02c12083", |
00000524 => x"02812403", |
00000525 => x"800007b7", |
00000526 => x"0147a023", |
00000527 => x"02412483", |
00000528 => x"02012903", |
00000529 => x"01c12983", |
00000530 => x"01812a03", |
00000531 => x"01412a83", |
00000532 => x"01012b03", |
00000533 => x"00c12b83", |
00000534 => x"03010113", |
00000535 => x"00008067", |
00000536 => x"00048513", |
00000537 => x"e71ff0ef", |
00000538 => x"012b87b3", |
00000539 => x"00a40433", |
00000540 => x"00a7a023", |
00000541 => x"00490913", |
00000542 => x"f95ff06f", |
00000543 => x"ff010113", |
00000544 => x"00112623", |
00000545 => x"ec9ff0ef", |
00000546 => x"ffff1537", |
00000547 => x"ecc50513", |
00000548 => x"440000ef", |
00000549 => x"b05ff0ef", |
00000550 => x"0000006f", |
00000551 => x"ff010113", |
00000552 => x"00112623", |
00000553 => x"00812423", |
00000554 => x"00912223", |
00000555 => x"00058413", |
00000556 => x"00050493", |
00000557 => x"d6dff0ef", |
00000558 => x"00000513", |
00000559 => x"4b8000ef", |
00000560 => x"00200513", |
00000561 => x"4f4000ef", |
00000562 => x"00048513", |
00000563 => x"d7dff0ef", |
00000564 => x"00040513", |
00000565 => x"4e4000ef", |
00000566 => x"00000513", |
00000567 => x"4b8000ef", |
00000568 => x"cb9ff0ef", |
00000569 => x"00157513", |
00000570 => x"fe051ce3", |
00000571 => x"00c12083", |
00000572 => x"00812403", |
00000573 => x"00412483", |
00000574 => x"01010113", |
00000575 => x"00008067", |
00000576 => x"fe010113", |
00000577 => x"00812c23", |
00000578 => x"00912a23", |
00000579 => x"01212823", |
00000580 => x"00112e23", |
00000581 => x"00b12623", |
00000582 => x"00300413", |
00000583 => x"00350493", |
00000584 => x"fff00913", |
00000585 => x"00c10793", |
00000586 => x"008787b3", |
00000587 => x"0007c583", |
00000588 => x"40848533", |
00000589 => x"fff40413", |
00000590 => x"f65ff0ef", |
00000591 => x"ff2414e3", |
00000592 => x"01c12083", |
00000593 => x"01812403", |
00000594 => x"01412483", |
00000595 => x"01012903", |
00000596 => x"02010113", |
00000597 => x"00008067", |
00000598 => x"ff010113", |
00000599 => x"00112623", |
00000600 => x"00812423", |
00000601 => x"00050413", |
00000602 => x"cb9ff0ef", |
00000603 => x"00000513", |
00000604 => x"404000ef", |
00000605 => x"0d800513", |
00000606 => x"440000ef", |
00000607 => x"00040513", |
00000608 => x"cc9ff0ef", |
00000609 => x"00000513", |
00000610 => x"40c000ef", |
00000611 => x"c0dff0ef", |
00000612 => x"00157513", |
00000613 => x"fe051ce3", |
00000614 => x"00c12083", |
00000615 => x"00812403", |
00000616 => x"01010113", |
00000617 => x"00008067", |
00000618 => x"fe010113", |
00000619 => x"800007b7", |
00000620 => x"00812c23", |
00000621 => x"0007a403", |
00000622 => x"00112e23", |
00000623 => x"00912a23", |
00000624 => x"01212823", |
00000625 => x"01312623", |
00000626 => x"01412423", |
00000627 => x"01512223", |
00000628 => x"02041863", |
00000629 => x"ffff1537", |
00000630 => x"e5450513", |
00000631 => x"01812403", |
00000632 => x"01c12083", |
00000633 => x"01412483", |
00000634 => x"01012903", |
00000635 => x"00c12983", |
00000636 => x"00812a03", |
00000637 => x"00412a83", |
00000638 => x"02010113", |
00000639 => x"2d40006f", |
00000640 => x"ffff1537", |
00000641 => x"ed050513", |
00000642 => x"2c8000ef", |
00000643 => x"00040513", |
00000644 => x"a15ff0ef", |
00000645 => x"ffff1537", |
00000646 => x"edc50513", |
00000647 => x"2b4000ef", |
00000648 => x"00800537", |
00000649 => x"a01ff0ef", |
00000650 => x"ffff1537", |
00000651 => x"ef850513", |
00000652 => x"2a0000ef", |
00000653 => x"280000ef", |
00000654 => x"00050493", |
00000655 => x"268000ef", |
00000656 => x"07900793", |
00000657 => x"0af49e63", |
00000658 => x"b95ff0ef", |
00000659 => x"00051663", |
00000660 => x"00300513", |
00000661 => x"999ff0ef", |
00000662 => x"ffff1537", |
00000663 => x"f0450513", |
00000664 => x"01045493", |
00000665 => x"26c000ef", |
00000666 => x"00148493", |
00000667 => x"00800937", |
00000668 => x"fff00993", |
00000669 => x"00010a37", |
00000670 => x"fff48493", |
00000671 => x"07349063", |
00000672 => x"4788d5b7", |
00000673 => x"afe58593", |
00000674 => x"00800537", |
00000675 => x"e75ff0ef", |
00000676 => x"00800537", |
00000677 => x"00040593", |
00000678 => x"00450513", |
00000679 => x"e65ff0ef", |
00000680 => x"ff002a03", |
00000681 => x"008009b7", |
00000682 => x"ffc47413", |
00000683 => x"00000493", |
00000684 => x"00000913", |
00000685 => x"00c98a93", |
00000686 => x"01548533", |
00000687 => x"009a07b3", |
00000688 => x"02849663", |
00000689 => x"00898513", |
00000690 => x"412005b3", |
00000691 => x"e35ff0ef", |
00000692 => x"ffff1537", |
00000693 => x"ec850513", |
00000694 => x"f05ff06f", |
00000695 => x"00090513", |
00000696 => x"e79ff0ef", |
00000697 => x"01490933", |
00000698 => x"f91ff06f", |
00000699 => x"0007a583", |
00000700 => x"00448493", |
00000701 => x"00b90933", |
00000702 => x"e09ff0ef", |
00000703 => x"fbdff06f", |
00000704 => x"01c12083", |
00000705 => x"01812403", |
00000706 => x"01412483", |
00000707 => x"01012903", |
00000708 => x"00c12983", |
00000709 => x"00812a03", |
00000710 => x"00412a83", |
00000711 => x"02010113", |
00000712 => x"00008067", |
00000713 => x"fe010113", |
00000714 => x"00912a23", |
00000715 => x"01212823", |
00000716 => x"01312623", |
00000717 => x"01412423", |
00000718 => x"00112e23", |
00000719 => x"00812c23", |
00000720 => x"00000493", |
00000721 => x"00900993", |
00000722 => x"00300a13", |
00000723 => x"00400913", |
00000724 => x"f1302473", |
00000725 => x"40900533", |
00000726 => x"00351513", |
00000727 => x"01850513", |
00000728 => x"00a45433", |
00000729 => x"0ff47413", |
00000730 => x"00000513", |
00000731 => x"0489ea63", |
00000732 => x"00050863", |
00000733 => x"03050513", |
00000734 => x"0ff57513", |
00000735 => x"128000ef", |
00000736 => x"03040513", |
00000737 => x"0ff57513", |
00000738 => x"11c000ef", |
00000739 => x"01448663", |
00000740 => x"02e00513", |
00000741 => x"110000ef", |
00000742 => x"00148493", |
00000743 => x"fb249ae3", |
00000744 => x"01c12083", |
00000745 => x"01812403", |
00000746 => x"01412483", |
00000747 => x"01012903", |
00000748 => x"00c12983", |
00000749 => x"00812a03", |
00000750 => x"02010113", |
00000751 => x"00008067", |
00000752 => x"ff640413", |
00000753 => x"00150513", |
00000754 => x"0ff47413", |
00000755 => x"0ff57513", |
00000756 => x"f9dff06f", |
00000478 => x"0087f793", |
00000479 => x"00050413", |
00000480 => x"00078a63", |
00000481 => x"fe802783", |
00000482 => x"00400513", |
00000483 => x"0047f793", |
00000484 => x"04079663", |
00000485 => x"02041863", |
00000486 => x"ffff1537", |
00000487 => x"e9c50513", |
00000488 => x"530000ef", |
00000489 => x"008005b7", |
00000490 => x"00040513", |
00000491 => x"f29ff0ef", |
00000492 => x"4788d7b7", |
00000493 => x"afe78793", |
00000494 => x"02f50463", |
00000495 => x"00000513", |
00000496 => x"01c0006f", |
00000497 => x"ffff1537", |
00000498 => x"ebc50513", |
00000499 => x"504000ef", |
00000500 => x"e0dff0ef", |
00000501 => x"fc0518e3", |
00000502 => x"00300513", |
00000503 => x"c11ff0ef", |
00000504 => x"008009b7", |
00000505 => x"00498593", |
00000506 => x"00040513", |
00000507 => x"ee9ff0ef", |
00000508 => x"00050a13", |
00000509 => x"00898593", |
00000510 => x"00040513", |
00000511 => x"ed9ff0ef", |
00000512 => x"ff002b83", |
00000513 => x"00050a93", |
00000514 => x"ffca7b13", |
00000515 => x"00000913", |
00000516 => x"00000493", |
00000517 => x"00c98993", |
00000518 => x"013905b3", |
00000519 => x"052b1863", |
00000520 => x"015484b3", |
00000521 => x"00200513", |
00000522 => x"fa049ae3", |
00000523 => x"ffff1537", |
00000524 => x"ec850513", |
00000525 => x"49c000ef", |
00000526 => x"02c12083", |
00000527 => x"02812403", |
00000528 => x"800007b7", |
00000529 => x"0147a023", |
00000530 => x"02412483", |
00000531 => x"02012903", |
00000532 => x"01c12983", |
00000533 => x"01812a03", |
00000534 => x"01412a83", |
00000535 => x"01012b03", |
00000536 => x"00c12b83", |
00000537 => x"03010113", |
00000538 => x"00008067", |
00000539 => x"00040513", |
00000540 => x"e65ff0ef", |
00000541 => x"012b87b3", |
00000542 => x"00a484b3", |
00000543 => x"00a7a023", |
00000544 => x"00490913", |
00000545 => x"f95ff06f", |
00000546 => x"ff010113", |
00000547 => x"00112623", |
00000548 => x"ebdff0ef", |
00000549 => x"ffff1537", |
00000550 => x"ecc50513", |
00000551 => x"434000ef", |
00000552 => x"af9ff0ef", |
00000553 => x"0000006f", |
00000554 => x"ff010113", |
00000555 => x"00112623", |
00000556 => x"00812423", |
00000557 => x"00912223", |
00000558 => x"00058413", |
00000559 => x"00050493", |
00000560 => x"d61ff0ef", |
00000561 => x"00000513", |
00000562 => x"4ac000ef", |
00000563 => x"00200513", |
00000564 => x"4e8000ef", |
00000565 => x"00048513", |
00000566 => x"d71ff0ef", |
00000567 => x"00040513", |
00000568 => x"4d8000ef", |
00000569 => x"00000513", |
00000570 => x"4ac000ef", |
00000571 => x"cadff0ef", |
00000572 => x"00157513", |
00000573 => x"fe051ce3", |
00000574 => x"00c12083", |
00000575 => x"00812403", |
00000576 => x"00412483", |
00000577 => x"01010113", |
00000578 => x"00008067", |
00000579 => x"fe010113", |
00000580 => x"00812c23", |
00000581 => x"00912a23", |
00000582 => x"01212823", |
00000583 => x"00112e23", |
00000584 => x"00b12623", |
00000585 => x"00300413", |
00000586 => x"00350493", |
00000587 => x"fff00913", |
00000588 => x"00c10793", |
00000589 => x"008787b3", |
00000590 => x"0007c583", |
00000591 => x"40848533", |
00000592 => x"fff40413", |
00000593 => x"f65ff0ef", |
00000594 => x"ff2414e3", |
00000595 => x"01c12083", |
00000596 => x"01812403", |
00000597 => x"01412483", |
00000598 => x"01012903", |
00000599 => x"02010113", |
00000600 => x"00008067", |
00000601 => x"ff010113", |
00000602 => x"00112623", |
00000603 => x"00812423", |
00000604 => x"00050413", |
00000605 => x"cadff0ef", |
00000606 => x"00000513", |
00000607 => x"3f8000ef", |
00000608 => x"0d800513", |
00000609 => x"434000ef", |
00000610 => x"00040513", |
00000611 => x"cbdff0ef", |
00000612 => x"00000513", |
00000613 => x"400000ef", |
00000614 => x"c01ff0ef", |
00000615 => x"00157513", |
00000616 => x"fe051ce3", |
00000617 => x"00c12083", |
00000618 => x"00812403", |
00000619 => x"01010113", |
00000620 => x"00008067", |
00000621 => x"fe010113", |
00000622 => x"800007b7", |
00000623 => x"00812c23", |
00000624 => x"0007a403", |
00000625 => x"00112e23", |
00000626 => x"00912a23", |
00000627 => x"01212823", |
00000628 => x"01312623", |
00000629 => x"01412423", |
00000630 => x"01512223", |
00000631 => x"02041863", |
00000632 => x"ffff1537", |
00000633 => x"e5450513", |
00000634 => x"01812403", |
00000635 => x"01c12083", |
00000636 => x"01412483", |
00000637 => x"01012903", |
00000638 => x"00c12983", |
00000639 => x"00812a03", |
00000640 => x"00412a83", |
00000641 => x"02010113", |
00000642 => x"2c80006f", |
00000643 => x"ffff1537", |
00000644 => x"ed050513", |
00000645 => x"2bc000ef", |
00000646 => x"00040513", |
00000647 => x"a09ff0ef", |
00000648 => x"ffff1537", |
00000649 => x"edc50513", |
00000650 => x"2a8000ef", |
00000651 => x"00800537", |
00000652 => x"9f5ff0ef", |
00000653 => x"ffff1537", |
00000654 => x"ef850513", |
00000655 => x"294000ef", |
00000656 => x"274000ef", |
00000657 => x"00050493", |
00000658 => x"25c000ef", |
00000659 => x"07900793", |
00000660 => x"0af49e63", |
00000661 => x"b89ff0ef", |
00000662 => x"00051663", |
00000663 => x"00300513", |
00000664 => x"98dff0ef", |
00000665 => x"ffff1537", |
00000666 => x"f0450513", |
00000667 => x"01045493", |
00000668 => x"260000ef", |
00000669 => x"00148493", |
00000670 => x"00800937", |
00000671 => x"fff00993", |
00000672 => x"00010a37", |
00000673 => x"fff48493", |
00000674 => x"07349063", |
00000675 => x"4788d5b7", |
00000676 => x"afe58593", |
00000677 => x"00800537", |
00000678 => x"e75ff0ef", |
00000679 => x"00800537", |
00000680 => x"00040593", |
00000681 => x"00450513", |
00000682 => x"e65ff0ef", |
00000683 => x"ff002a03", |
00000684 => x"008009b7", |
00000685 => x"ffc47413", |
00000686 => x"00000493", |
00000687 => x"00000913", |
00000688 => x"00c98a93", |
00000689 => x"01548533", |
00000690 => x"009a07b3", |
00000691 => x"02849663", |
00000692 => x"00898513", |
00000693 => x"412005b3", |
00000694 => x"e35ff0ef", |
00000695 => x"ffff1537", |
00000696 => x"ec850513", |
00000697 => x"f05ff06f", |
00000698 => x"00090513", |
00000699 => x"e79ff0ef", |
00000700 => x"01490933", |
00000701 => x"f91ff06f", |
00000702 => x"0007a583", |
00000703 => x"00448493", |
00000704 => x"00b90933", |
00000705 => x"e09ff0ef", |
00000706 => x"fbdff06f", |
00000707 => x"01c12083", |
00000708 => x"01812403", |
00000709 => x"01412483", |
00000710 => x"01012903", |
00000711 => x"00c12983", |
00000712 => x"00812a03", |
00000713 => x"00412a83", |
00000714 => x"02010113", |
00000715 => x"00008067", |
00000716 => x"fe010113", |
00000717 => x"00912a23", |
00000718 => x"01312623", |
00000719 => x"01412423", |
00000720 => x"00112e23", |
00000721 => x"00812c23", |
00000722 => x"01212823", |
00000723 => x"00000493", |
00000724 => x"00300a13", |
00000725 => x"00400993", |
00000726 => x"f13027f3", |
00000727 => x"40900733", |
00000728 => x"00371713", |
00000729 => x"01870713", |
00000730 => x"00e7d7b3", |
00000731 => x"0ff7f793", |
00000732 => x"0047d513", |
00000733 => x"40a00933", |
00000734 => x"00491913", |
00000735 => x"03078793", |
00000736 => x"0ff97913", |
00000737 => x"0ff7f413", |
00000738 => x"00050663", |
00000739 => x"03050513", |
00000740 => x"114000ef", |
00000741 => x"01240533", |
00000742 => x"0ff57513", |
00000743 => x"108000ef", |
00000744 => x"01448663", |
00000745 => x"02e00513", |
00000746 => x"0fc000ef", |
00000747 => x"00148493", |
00000748 => x"fb3494e3", |
00000749 => x"01c12083", |
00000750 => x"01812403", |
00000751 => x"01412483", |
00000752 => x"01012903", |
00000753 => x"00c12983", |
00000754 => x"00812a03", |
00000755 => x"02010113", |
00000756 => x"00008067", |
00000757 => x"ff010113", |
00000758 => x"f9402783", |
00000759 => x"f9002703", |
983,7 → 983,7
00000972 => x"4c420a0a", |
00000973 => x"203a5644", |
00000974 => x"2074634f", |
00000975 => x"32203731", |
00000975 => x"32203232", |
00000976 => x"0a303230", |
00000977 => x"3a565748", |
00000978 => x"00002020", |
/neorv32/trunk/rtl/core/neorv32_cpu.vhd
85,6 → 85,7
i_bus_ack_i : in std_ulogic := '0'; -- bus transfer acknowledge |
i_bus_err_i : in std_ulogic := '0'; -- bus transfer error |
i_bus_fence_o : out std_ulogic; -- executed FENCEI operation |
i_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level |
-- data bus interface -- |
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address |
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data |
96,6 → 97,7
d_bus_ack_i : in std_ulogic := '0'; -- bus transfer acknowledge |
d_bus_err_i : in std_ulogic := '0'; -- bus transfer error |
d_bus_fence_o : out std_ulogic; -- executed FENCE operation |
d_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level |
-- system time input from MTIME -- |
time_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time |
-- interrupts (risc-v compliant) -- |
369,5 → 371,9
d_bus_fence_o => d_bus_fence_o -- fence operation |
); |
|
-- current privilege level -- |
i_bus_priv_o <= priv_mode; |
d_bus_priv_o <= priv_mode; |
|
|
end neorv32_cpu_rtl; |
/neorv32/trunk/rtl/core/neorv32_cpu_control.vhd
551,7 → 551,7
instruction_buffer_data: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (i_buf.we = '1') and (i_buf.clear = '0') then |
if (i_buf.we = '1') then |
i_buf.rdata <= i_buf.wdata; |
end if; |
end if; |
1535,14 → 1535,14
for j in 0 to 3 loop -- bytes in pmpcfg CSR |
if ((j+1) <= PMP_NUM_REGIONS) then |
if (csr.pmpcfg(0+j)(7) = '0') then -- unlocked pmpcfg access |
csr.pmpcfg(0+j)(0) <= csr.wdata(j*8+0); -- R |
csr.pmpcfg(0+j)(1) <= csr.wdata(j*8+1); -- W |
csr.pmpcfg(0+j)(2) <= csr.wdata(j*8+2); -- X |
csr.pmpcfg(0+j)(0) <= csr.wdata(j*8+0); -- R (rights.read) |
csr.pmpcfg(0+j)(1) <= csr.wdata(j*8+1); -- W (rights.write) |
csr.pmpcfg(0+j)(2) <= csr.wdata(j*8+2); -- X (rights.execute) |
csr.pmpcfg(0+j)(3) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_L |
csr.pmpcfg(0+j)(4) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_H - NAPOT/OFF only |
csr.pmpcfg(0+j)(5) <= '0'; -- reserved |
csr.pmpcfg(0+j)(6) <= '0'; -- reserved |
csr.pmpcfg(0+j)(7) <= csr.wdata(j*8+7); -- L |
csr.pmpcfg(0+j)(7) <= csr.wdata(j*8+7); -- L (locked / rights also enforced in m-mode) |
end if; |
end if; |
end loop; -- j (bytes in CSR) |
1553,14 → 1553,14
for j in 0 to 3 loop -- bytes in pmpcfg CSR |
if ((j+1+4) <= PMP_NUM_REGIONS) then |
if (csr.pmpcfg(4+j)(7) = '0') then -- unlocked pmpcfg access |
csr.pmpcfg(4+j)(0) <= csr.wdata(j*8+0); -- R |
csr.pmpcfg(4+j)(1) <= csr.wdata(j*8+1); -- W |
csr.pmpcfg(4+j)(2) <= csr.wdata(j*8+2); -- X |
csr.pmpcfg(4+j)(0) <= csr.wdata(j*8+0); -- R (rights.read) |
csr.pmpcfg(4+j)(1) <= csr.wdata(j*8+1); -- W (rights.write) |
csr.pmpcfg(4+j)(2) <= csr.wdata(j*8+2); -- X (rights.execute) |
csr.pmpcfg(4+j)(3) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_L |
csr.pmpcfg(4+j)(4) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_H - NAPOT/OFF only |
csr.pmpcfg(4+j)(5) <= '0'; -- reserved |
csr.pmpcfg(4+j)(6) <= '0'; -- reserved |
csr.pmpcfg(4+j)(7) <= csr.wdata(j*8+7); -- L |
csr.pmpcfg(4+j)(7) <= csr.wdata(j*8+7); -- L (locked / rights also enforced in m-mode) |
end if; |
end if; |
end loop; -- j (bytes in CSR) |
1731,8 → 1731,8
csr_read_access: process(clk_i) |
begin |
if rising_edge(clk_i) then |
csr.rdata <= (others => '0'); -- default |
csr.re <= csr.re_nxt; -- read access? |
csr.rdata <= (others => '0'); -- default output |
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then |
case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is |
|
1768,7 → 1768,7
csr.rdata <= csr.mscratch; |
when csr_mepc_c => -- R/W: mepc - machine exception program counter |
csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0'; |
when csr_mcause_c => -- R/-: mcause - machine trap cause |
when csr_mcause_c => -- R/W: mcause - machine trap cause |
csr.rdata <= csr.mcause; |
when csr_mtval_c => -- R/W: mtval - machine bad address or instruction |
csr.rdata <= csr.mtval; |
/neorv32/trunk/rtl/core/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- data width - do not change! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040509"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040600"; -- no touchy! |
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED! |
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off! |
|
471,7 → 471,6
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE : boolean := false; -- implement external memory bus interface? |
MEM_EXT_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
499,6 → 498,7
wb_ack_i : in std_ulogic := '0'; -- transfer acknowledge |
wb_err_i : in std_ulogic := '0'; -- transfer error |
-- Advanced memory control signals (available if MEM_EXT_USE = true) -- |
priv_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level |
fence_o : out std_ulogic; -- indicates an executed FENCE operation |
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation |
-- GPIO -- |
513,8 → 513,8
spi_sdi_i : in std_ulogic := '0'; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- TWI -- |
twi_sda_io : inout std_logic := 'H'; -- twi serial data line |
twi_scl_io : inout std_logic := 'H'; -- twi serial clock line |
twi_sda_io : inout std_logic; -- twi serial data line |
twi_scl_io : inout std_logic; -- twi serial clock line |
-- PWM -- |
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
-- Interrupts -- |
561,6 → 561,7
i_bus_ack_i : in std_ulogic := '0'; -- bus transfer acknowledge |
i_bus_err_i : in std_ulogic := '0'; -- bus transfer error |
i_bus_fence_o : out std_ulogic; -- executed FENCEI operation |
i_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level |
-- data bus interface -- |
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address |
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data |
572,6 → 573,7
d_bus_ack_i : in std_ulogic := '0'; -- bus transfer acknowledge |
d_bus_err_i : in std_ulogic := '0'; -- bus transfer error |
d_bus_fence_o : out std_ulogic; -- executed FENCE operation |
d_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level |
-- system time input from MTIME -- |
time_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time |
-- interrupts (risc-v compliant) -- |
1065,14 → 1067,13
-- ------------------------------------------------------------------------------------------- |
component neorv32_wishbone |
generic ( |
INTERFACE_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
WB_PIPELINED_MODE : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode |
WB_PIPELINED_MODE : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode |
-- Internal instruction memory -- |
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes |
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes |
-- Internal data memory -- |
MEM_INT_DMEM_USE : boolean := true; -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE : natural := 4*1024 -- size of processor-internal data memory in bytes |
MEM_INT_DMEM_USE : boolean := true; -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE : natural := 4*1024 -- size of processor-internal data memory in bytes |
); |
port ( |
-- global control -- |
/neorv32/trunk/rtl/core/neorv32_top.vhd
74,7 → 74,6
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE : boolean := false; -- implement external memory bus interface? |
MEM_EXT_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
102,6 → 101,7
wb_ack_i : in std_ulogic := '0'; -- transfer acknowledge |
wb_err_i : in std_ulogic := '0'; -- transfer error |
-- Advanced memory control signals (available if MEM_EXT_USE = true) -- |
priv_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level |
fence_o : out std_ulogic; -- indicates an executed FENCE operation |
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation |
-- GPIO (available if IO_GPIO_USE = true) -- |
116,8 → 116,8
spi_sdi_i : in std_ulogic := '0'; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- TWI (available if IO_TWI_USE = true) -- |
twi_sda_io : inout std_logic := 'H'; -- twi serial data line |
twi_scl_io : inout std_logic := 'H'; -- twi serial clock line |
twi_sda_io : inout std_logic; -- twi serial data line |
twi_scl_io : inout std_logic; -- twi serial clock line |
-- PWM (available if IO_PWM_USE = true) -- |
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
-- Interrupts -- |
169,6 → 169,7
ack : std_ulogic; -- bus transfer acknowledge |
err : std_ulogic; -- bus transfer error |
fence : std_ulogic; -- fence(i) instruction executed |
priv : std_ulogic_vector(1 downto 0); -- current privilege level |
end record; |
signal cpu_i, cpu_d, p_bus : bus_interface_t; |
|
344,6 → 345,7
i_bus_ack_i => cpu_i.ack, -- bus transfer acknowledge |
i_bus_err_i => cpu_i.err, -- bus transfer error |
i_bus_fence_o => cpu_i.fence, -- executed FENCEI operation |
i_bus_priv_o => cpu_i.priv, -- privilege level |
-- data bus interface -- |
d_bus_addr_o => cpu_d.addr, -- bus access address |
d_bus_rdata_i => cpu_d.rdata, -- bus read data |
355,6 → 357,7
d_bus_ack_i => cpu_d.ack, -- bus transfer acknowledge |
d_bus_err_i => cpu_d.err, -- bus transfer error |
d_bus_fence_o => cpu_d.fence, -- executed FENCE operation |
d_bus_priv_o => cpu_d.priv, -- privilege level |
-- system time input from MTIME -- |
time_i => mtime_time, -- current system time |
-- interrupts (risc-v compliant) -- |
366,6 → 369,7
); |
|
-- advanced memory control -- |
priv_o <= cpu_i.priv; -- is the same as "cpu_d.priv" |
fence_o <= cpu_d.fence; -- indicates an executed FENCE operation |
fencei_o <= cpu_i.fence; -- indicates an executed FENCEI operation |
|
521,14 → 525,13
if (MEM_EXT_USE = true) generate |
neorv32_wishbone_inst: neorv32_wishbone |
generic map ( |
INTERFACE_REG_STAGES => MEM_EXT_REG_STAGES, -- number of interface register stages (0,1,2) |
WB_PIPELINED_MODE => wb_pipe_mode_c, -- false: classic/standard wishbone mode, true: pipelined wishbone mode |
WB_PIPELINED_MODE => wb_pipe_mode_c, -- false: classic/standard wishbone mode, true: pipelined wishbone mode |
-- Internal instruction memory -- |
MEM_INT_IMEM_USE => MEM_INT_IMEM_USE, -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes |
MEM_INT_IMEM_USE => MEM_INT_IMEM_USE, -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes |
-- Internal data memory -- |
MEM_INT_DMEM_USE => MEM_INT_DMEM_USE, -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE -- size of processor-internal data memory in bytes |
MEM_INT_DMEM_USE => MEM_INT_DMEM_USE, -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE -- size of processor-internal data memory in bytes |
) |
port map ( |
-- global control -- |
779,8 → 782,8
if (IO_TWI_USE = false) generate |
twi_rdata <= (others => '0'); |
twi_ack <= '0'; |
-- twi_sda_io <= 'H'; |
-- twi_scl_io <= 'H'; |
-- twi_sda_io <= 'Z'; |
-- twi_scl_io <= 'Z'; |
twi_cg_en <= '0'; |
twi_irq <= '0'; |
end generate; |
/neorv32/trunk/rtl/core/neorv32_twi.vhd
74,11 → 74,12
constant ctrl_twi_en_c : natural := 0; -- r/w: TWI enable |
constant ctrl_twi_start_c : natural := 1; -- -/w: Generate START condition |
constant ctrl_twi_stop_c : natural := 2; -- -/w: Generate STOP condition |
constant ctrl_twi_irq_en_c : natural := 3; -- r/w: transmission done interrupt |
constant ctrl_twi_irq_en_c : natural := 3; -- r/w: Enable transmission done interrupt |
constant ctrl_twi_prsc0_c : natural := 4; -- r/w: CLK prsc bit 0 |
constant ctrl_twi_prsc1_c : natural := 5; -- r/w: CLK prsc bit 1 |
constant ctrl_twi_prsc2_c : natural := 6; -- r/w: CLK prsc bit 2 |
constant ctrl_twi_mack_c : natural := 7; -- r/w: generate ACK by controller for transmission |
constant ctrl_twi_cksten_c : natural := 8; -- r/w: enable clock stretching by peripheral |
-- |
constant ctrl_twi_ack_c : natural := 30; -- r/-: Set if ACK received |
constant ctrl_twi_busy_c : natural := 31; -- r/-: Set if TWI unit is busy |
98,7 → 99,7
signal twi_clk_halt : std_ulogic; |
|
-- twi transceiver core -- |
signal ctrl : std_ulogic_vector(7 downto 0); -- unit's control register |
signal ctrl : std_ulogic_vector(8 downto 0); -- unit's control register |
signal arbiter : std_ulogic_vector(2 downto 0); |
signal twi_bitcnt : std_ulogic_vector(3 downto 0); |
signal twi_rtx_sreg : std_ulogic_vector(8 downto 0); -- main rx/tx shift reg |
141,6 → 142,7
data_o(ctrl_twi_prsc1_c) <= ctrl(ctrl_twi_prsc1_c); |
data_o(ctrl_twi_prsc2_c) <= ctrl(ctrl_twi_prsc2_c); |
data_o(ctrl_twi_mack_c) <= ctrl(ctrl_twi_mack_c); |
data_o(ctrl_twi_cksten_c) <= ctrl(ctrl_twi_cksten_c); |
-- |
data_o(ctrl_twi_ack_c) <= not twi_rtx_sreg(0); |
data_o(ctrl_twi_busy_c) <= arbiter(1) or arbiter(0); |
272,12 → 274,13
|
-- Clock Stretching Detector -------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
clock_stretching: process(arbiter, twi_scl_o, twi_scl_i_ff1) |
clock_stretching: process(ctrl, arbiter, twi_scl_o, twi_scl_i_ff1) |
begin |
-- clock stretching by the peripheral can happen at "any time" |
if (arbiter(2) = '1') and -- module enabled |
(twi_scl_o = '1') and -- controller wants to pull scl high |
(twi_scl_i_ff1 = '0') then -- but scl is pulled low by peripheral |
if (arbiter(2) = '1') and -- module enabled |
(ctrl(ctrl_twi_cksten_c) = '1') and -- clock stretching enabled |
(twi_scl_o = '1') and -- controller wants to pull scl high |
(twi_scl_i_ff1 = '0') then -- but scl is pulled low by peripheral |
twi_clk_halt <= '1'; |
else |
twi_clk_halt <= '0'; |
/neorv32/trunk/rtl/core/neorv32_wishbone.vhd
1,15 → 1,15
-- ################################################################################################# |
-- # << NEORV32 - External Bus Interface (WISHBONE) >> # |
-- # ********************************************************************************************* # |
-- # The interface is either unregistered (INTERFACE_REG_STAGES = 0), only outgoing signals are # |
-- # registered (INTERFACE_REG_STAGES = 1) or incoming and outgoing signals are registered # |
-- # (INTERFACE_REG_STAGES = 2). This interface supports classic/standard Wishbone transactions # |
-- # (WB_PIPELINED_MODE = false) and also pipelined transactions for improved timing # |
-- # (WB_PIPELINED_MODE = true). # |
-- # The interface provides registers for all outgoing signals. If the host cancels a running # |
-- # transfer, the Wishbone arbiter still waits some time for the bus system to ACK to transfer. # |
-- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # |
-- # All bus accesses from the CPU, which do not target the internal IO region, the internal boot- # |
-- # loader or the internal instruction or data memories (if implemented), are delegated via this # |
-- # Wishbone gateway to the external bus interface. # |
-- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # |
-- # This interface supports classic/standard Wishbone transactions (WB_PIPELINED_MODE = false) # |
-- # and also pipelined transactions (WB_PIPELINED_MODE = true). # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
51,14 → 51,13
|
entity neorv32_wishbone is |
generic ( |
INTERFACE_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
WB_PIPELINED_MODE : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode |
WB_PIPELINED_MODE : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode |
-- Internal instruction memory -- |
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes |
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 8*1024; -- size of processor-internal instruction memory in bytes |
-- Internal data memory -- |
MEM_INT_DMEM_USE : boolean := true; -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE : natural := 4*1024 -- size of processor-internal data memory in bytes |
MEM_INT_DMEM_USE : boolean := true; -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE : natural := 4*1024 -- size of processor-internal data memory in bytes |
); |
port ( |
-- global control -- |
89,35 → 88,40
|
architecture neorv32_wishbone_rtl of neorv32_wishbone is |
|
-- constants -- |
constant wb_timeout_c : natural := bus_timeout_c/2; |
|
-- access control -- |
signal int_imem_acc, int_imem_acc_real : std_ulogic; |
signal int_dmem_acc, int_dmem_acc_real : std_ulogic; |
signal int_boot_acc : std_ulogic; |
signal wb_access : std_ulogic; |
signal wb_access_ff, wb_access_ff_ff : std_ulogic; |
signal rb_en : std_ulogic; |
|
-- bus arbiter -- |
signal wb_we_ff : std_ulogic; |
signal wb_stb_ff0 : std_ulogic; |
signal wb_stb_ff1 : std_ulogic; |
signal wb_cyc_ff : std_ulogic; |
signal wb_ack_ff : std_ulogic; |
signal wb_err_ff : std_ulogic; |
-- bus arbiter |
type ctrl_state_t is (IDLE, BUSY, CANCELED); |
type ctrl_t is record |
state : ctrl_state_t; |
state_prev : ctrl_state_t; |
we : std_ulogic; |
rd_req : std_ulogic; |
wr_req : std_ulogic; |
adr : std_ulogic_vector(31 downto 0); |
wdat : std_ulogic_vector(31 downto 0); |
rdat : std_ulogic_vector(31 downto 0); |
sel : std_ulogic_vector(3 downto 0); |
ack : std_ulogic; |
err : std_ulogic; |
timeout : std_ulogic_vector(index_size_f(wb_timeout_c)-1 downto 0); |
end record; |
signal ctrl : ctrl_t; |
|
-- wishbone mode: standard / pipelined -- |
signal stb_int_std : std_ulogic; |
signal stb_int_pipe : std_ulogic; |
signal stb_int, cyc_int : std_ulogic; |
|
-- data read-back -- |
signal wb_rdata : std_ulogic_vector(31 downto 0); |
|
begin |
|
-- Sanity Check --------------------------------------------------------------------------- |
-- Sanity Checks -------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
assert (INTERFACE_REG_STAGES <= 2) report "NEORV32 CONFIG ERROR! Number of external memory interface buffer stages must be 0, 1 or 2." severity error; |
assert (INTERFACE_REG_STAGES /= 0) report "NEORV32 CONFIG WARNING! External memory interface without register stages is still experimental for peripherals with more than 1 cycle latency." severity warning; |
assert not (bus_timeout_c <= 15) report "NEORV32 PROCESSOR CONFIG ERROR: Bus timeout (bus_timeout_c) should be >16 for interfacing external modules." severity error; |
|
|
-- Access Control ------------------------------------------------------------------------- |
134,112 → 138,98
--int_io_acc <= '1' when (addr_i >= io_base_c) else '0'; |
|
-- actual external bus access? -- |
wb_access <= (not int_imem_acc_real) and (not int_dmem_acc_real) and (not int_boot_acc) and (wren_i or rden_i); |
wb_access <= (not int_imem_acc_real) and (not int_dmem_acc_real) and (not int_boot_acc); |
|
|
-- Bus Arbiter ----------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
bus_arbiter: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
wb_we_ff <= '0'; |
wb_cyc_ff <= '0'; |
wb_stb_ff1 <= '0'; |
wb_stb_ff0 <= '0'; |
wb_ack_ff <= '0'; |
wb_err_ff <= '0'; |
wb_access_ff <= '0'; |
wb_access_ff_ff <= '0'; |
ctrl.state <= IDLE; |
ctrl.state_prev <= IDLE; |
ctrl.we <= '0'; |
ctrl.rd_req <= '0'; |
ctrl.wr_req <= '0'; |
ctrl.adr <= (others => '0'); |
ctrl.wdat <= (others => '0'); |
ctrl.rdat <= (others => '0'); |
ctrl.sel <= (others => '0'); |
ctrl.timeout <= (others => '0'); |
ctrl.ack <= '0'; |
ctrl.err <= '0'; |
elsif rising_edge(clk_i) then |
-- read/write -- |
wb_we_ff <= (wb_we_ff or wren_i) and wb_access and (not wb_ack_i) and (not wb_err_i) and (not cancel_i); |
-- bus cycle -- |
if (INTERFACE_REG_STAGES = 0) then |
wb_cyc_ff <= '0'; -- unused |
else |
wb_cyc_ff <= (wb_cyc_ff or wb_access) and (not wb_ack_i) and (not wb_err_i) and (not cancel_i); |
end if; |
-- bus strobe -- |
wb_stb_ff1 <= wb_stb_ff0; |
wb_stb_ff0 <= wb_access; |
-- bus ack -- |
wb_ack_ff <= wb_ack_i; |
-- bus err -- |
wb_err_ff <= wb_err_i; |
-- access still active? -- |
wb_access_ff_ff <= wb_access_ff; |
if (wb_access = '1') then |
wb_access_ff <= '1'; |
elsif ((wb_ack_i or wb_err_i or cancel_i) = '1') then |
wb_access_ff <= '0'; |
end if; |
end if; |
end process bus_arbiter; |
-- defaults -- |
ctrl.state_prev <= ctrl.state; |
ctrl.rdat <= (others => '0'); |
ctrl.ack <= '0'; |
ctrl.err <= '0'; |
ctrl.timeout <= std_ulogic_vector(to_unsigned(wb_timeout_c, index_size_f(wb_timeout_c))); |
|
-- valid bus cycle -- |
wb_cyc_o <= wb_access when (INTERFACE_REG_STAGES = 0) else wb_cyc_ff; |
-- state machine -- |
case ctrl.state is |
|
-- bus strobe -- |
stb_int_std <= wb_access when (INTERFACE_REG_STAGES = 0) else wb_cyc_ff; -- same as wb_cyc |
stb_int_pipe <= (wb_access and (not wb_stb_ff0)) when (INTERFACE_REG_STAGES = 0) else (wb_stb_ff0 and (not wb_stb_ff1)); -- wb_access rising edge detector |
-- |
wb_stb_o <= stb_int_std when (WB_PIPELINED_MODE = false) else stb_int_pipe; -- standard or pipelined mode |
when IDLE => -- waiting for host request |
-- ------------------------------------------------------------ |
ctrl.rd_req <= '0'; |
ctrl.wr_req <= '0'; |
-- buffer all outgoing signals -- |
ctrl.we <= wren_i; |
ctrl.adr <= addr_i; |
ctrl.wdat <= data_i; |
ctrl.sel <= ben_i; |
-- valid read/write access -- |
if ((wb_access and (wren_i or ctrl.wr_req or rden_i or ctrl.rd_req)) = '1') then |
ctrl.state <= BUSY; |
end if; |
|
-- cpu ack -- |
ack_o <= wb_ack_ff when (INTERFACE_REG_STAGES = 2) else wb_ack_i; |
when BUSY => -- transfer in progress |
-- ------------------------------------------------------------ |
ctrl.rdat <= wb_dat_i; |
if (cancel_i = '1') then -- transfer canceled by host |
ctrl.state <= CANCELED; |
elsif (wb_err_i = '1') then -- abnormal bus termination |
ctrl.err <= '1'; |
ctrl.state <= CANCELED; |
elsif (wb_ack_i = '1') then -- normal bus termination |
ctrl.ack <= '1'; |
ctrl.state <= IDLE; |
end if; |
|
-- cpu err -- |
err_o <= wb_err_ff when (INTERFACE_REG_STAGES = 2) else wb_err_i; |
when CANCELED => -- |
-- ------------------------------------------------------------ |
ctrl.wr_req <= ctrl.wr_req or wren_i; -- buffer new request |
ctrl.rd_req <= ctrl.rd_req or rden_i; -- buffer new request |
-- wait for bus.peripheral to ACK transfer (as "aborted" but still somehow "completed") |
-- or wait for a timeout and force termination |
ctrl.timeout <= std_ulogic_vector(unsigned(ctrl.timeout) - 1); -- timeout counter |
if (wb_ack_i = '1') or (or_all_f(ctrl.timeout) = '0') then |
ctrl.state <= IDLE; |
end if; |
|
-- cpu read-data -- |
rb_en <= wb_access_ff_ff when (INTERFACE_REG_STAGES = 2) else wb_access_ff; |
data_o <= wb_rdata when (rb_en = '1') else (others => '0'); |
when others => -- undefined |
-- ------------------------------------------------------------ |
ctrl.state <= IDLE; |
|
end case; |
end if; |
end process bus_arbiter; |
|
-- Bus Buffer ----------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
interface_reg_level_zero: |
if (INTERFACE_REG_STAGES = 0) generate -- 0 register levels: direct connection |
wb_rdata <= wb_dat_i; |
wb_adr_o <= addr_i; |
wb_dat_o <= data_i; |
wb_sel_o <= ben_i; |
wb_we_o <= wren_i or wb_we_ff; |
end generate; |
|
interface_reg_level_one: |
if (INTERFACE_REG_STAGES = 1) generate -- 1 register levels: buffer outgoing signals |
buffer_stages_one: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (wb_cyc_ff = '0') then |
wb_adr_o <= addr_i; |
wb_dat_o <= data_i; |
wb_sel_o <= ben_i; |
wb_we_o <= wren_i or wb_we_ff; |
end if; |
end if; |
end process buffer_stages_one; |
wb_rdata <= wb_dat_i; |
end generate; |
-- host access -- |
data_o <= ctrl.rdat; |
ack_o <= ctrl.ack; |
err_o <= ctrl.err; |
|
interface_reg_level_two: |
if (INTERFACE_REG_STAGES = 2) generate -- 2 register levels: buffer incoming and outgoing signals |
buffer_stages_two: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (wb_cyc_ff = '0') then |
wb_adr_o <= addr_i; |
wb_dat_o <= data_i; |
wb_sel_o <= ben_i; |
wb_we_o <= wren_i or wb_we_ff; |
end if; |
if (wb_ack_i = '1') then |
wb_rdata <= wb_dat_i; |
end if; |
end if; |
end process buffer_stages_two; |
end generate; |
-- wishbone interface -- |
wb_adr_o <= ctrl.adr; |
wb_dat_o <= ctrl.wdat; |
wb_we_o <= ctrl.we; |
wb_sel_o <= ctrl.sel; |
wb_stb_o <= stb_int when (WB_PIPELINED_MODE = true) else cyc_int; |
wb_cyc_o <= cyc_int; |
|
stb_int <= '1' when ((ctrl.state = BUSY) and (ctrl.state_prev = IDLE)) else '0'; |
cyc_int <= '0' when (ctrl.state = IDLE) else '1'; |
|
|
end neorv32_wishbone_rtl; |
/neorv32/trunk/rtl/top_templates/README.md
3,21 → 3,31
The top entity of the NEORV32 processor is `rtl/core/neorv32_top.vhd`. This folder provides additional |
top entities/wrappers that instantiate the processor's top entity to provide a different interface. |
|
If you want to use one of the provides top entities from this folder, *also* add the according file to the project's |
HDL file list and select the according top_template file as top entity or instatiate the top_template file in your design. |
|
### `neorv32_test_setup.vhd` |
|
### [`neorv32_test_setup.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) |
|
This entity is intended as "FPGA hello world" example for playing with the NEORV32. It uses only some of the |
provided peripherals and provides a very simple and basic interface - only the clock, reset, UART and a subset |
of the GPIO output port are propagated to the outer world. |
|
|
### `neorv32_cpu_stdlogic.vhd` |
### [`neorv32_cpu_stdlogic.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_cpu_stdlogic.vhd) |
|
Same entity (generics and interface ports) as the default NEORV32 CPU top entity (`rtl/core/neorv32_cpu.vhd`), |
but with _resolved_ port signals: All ports are of type `std_logic` or `std_logic_vector`, respectively. |
|
|
### `neorv32_top_stdlogic.vhd` |
### [`neorv32_top_axi4lite.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_top_axi4lite) |
|
This setup provides all the peripheal/IO signals of the default processor top entity, but features an **AXI4-Lite**-compatible bus interface |
instead of the default Wishbone b4 interface. The AXI signal naming corresponds to the Xilinx user guide. The Xilinx Vivado IP packer |
is able to automatically detect the AXI interface ports. All ports signals of this top entity are of type `std_logic` or `std_logic_vector`, respectively. |
|
|
### [`neorv32_top_stdlogic.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_top_stdlogic.vhd) |
|
Same entity (generics and interface ports) as the default NEORV32 Processor top entity (`rtl/core/neorv32_top.vhd`), |
but with _resolved_ port signals: All ports are of type `std_logic` or `std_logic_vector`, respectively. |
/neorv32/trunk/rtl/top_templates/neorv32_cpu_stdlogic.vhd
74,6 → 74,7
i_bus_ack_i : in std_logic := '0'; -- bus transfer acknowledge |
i_bus_err_i : in std_logic := '0'; -- bus transfer error |
i_bus_fence_o : out std_logic; -- executed FENCEI operation |
i_bus_priv_o : out std_logic_vector(1 downto 0); -- privilege level |
-- data bus interface -- |
d_bus_addr_o : out std_logic_vector(data_width_c-1 downto 0); -- bus access address |
d_bus_rdata_i : in std_logic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data |
85,6 → 86,7
d_bus_ack_i : in std_logic := '0'; -- bus transfer acknowledge |
d_bus_err_i : in std_logic := '0'; -- bus transfer error |
d_bus_fence_o : out std_logic; -- executed FENCE operation |
d_bus_priv_o : out std_logic_vector(1 downto 0); -- privilege level |
-- system time input from MTIME -- |
time_i : in std_logic_vector(63 downto 0) := (others => '0'); -- current system time |
-- interrupts (risc-v compliant) -- |
114,6 → 116,7
signal i_bus_ack_i_int, d_bus_ack_i_int : std_ulogic; |
signal i_bus_err_i_int, d_bus_err_i_int : std_ulogic; |
signal i_bus_fence_o_int, d_bus_fence_o_int : std_ulogic; |
signal i_bus_priv_o_int, d_bus_priv_o_int : std_ulogic_vector(1 downto 0); |
-- |
signal time_i_int : std_ulogic_vector(63 downto 0); |
-- |
160,6 → 163,7
i_bus_ack_i => i_bus_ack_i_int, -- bus transfer acknowledge |
i_bus_err_i => i_bus_err_i_int, -- bus transfer error |
i_bus_fence_o => i_bus_fence_o_int, -- executed FENCEI operation |
i_bus_priv_o => i_bus_priv_o_int, -- privilege level |
-- data bus interface -- |
d_bus_addr_o => d_bus_addr_o_int, -- bus access address |
d_bus_rdata_i => d_bus_rdata_i_int, -- bus read data |
171,6 → 175,7
d_bus_ack_i => d_bus_ack_i_int, -- bus transfer acknowledge |
d_bus_err_i => d_bus_err_i_int, -- bus transfer error |
d_bus_fence_o => d_bus_fence_o_int, -- executed FENCEI operation |
d_bus_priv_o => d_bus_priv_o_int, -- privilege level |
-- system time input from MTIME -- |
time_i => time_i_int, -- current system time |
-- interrupts (risc-v compliant) -- |
195,6 → 200,7
i_bus_ack_i_int <= std_ulogic(i_bus_ack_i); |
i_bus_err_i_int <= std_ulogic(i_bus_err_i); |
i_bus_fence_o <= std_logic(i_bus_fence_o_int); |
i_bus_priv_o <= std_logic_vector(i_bus_priv_o_int); |
|
d_bus_addr_o <= std_logic_vector(d_bus_addr_o_int); |
d_bus_rdata_i_int <= std_ulogic_vector(d_bus_rdata_i); |
206,6 → 212,7
d_bus_ack_i_int <= std_ulogic(d_bus_ack_i); |
d_bus_err_i_int <= std_ulogic(d_bus_err_i); |
d_bus_fence_o <= std_logic(d_bus_fence_o_int); |
d_bus_priv_o <= std_logic_vector(d_bus_priv_o_int); |
|
time_i_int <= std_ulogic_vector(time_i); |
|
/neorv32/trunk/rtl/top_templates/neorv32_test_setup.vhd
95,7 → 95,6
MEM_INT_DMEM_SIZE => 8*1024, -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE => false, -- implement external memory bus interface? |
MEM_EXT_REG_STAGES => 2, -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE => true, -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE => true, -- implement machine system timer (MTIME)? |
123,6 → 122,7
wb_ack_i => '0', -- transfer acknowledge |
wb_err_i => '0', -- transfer error |
-- Advanced memory control signals -- |
priv_o => open, -- current CPU privilege level |
fence_o => open, -- indicates an executed FENCE operation |
fencei_o => open, -- indicates an executed FENCEI operation |
-- GPIO -- |
/neorv32/trunk/rtl/top_templates/neorv32_top_axi4lite.vhd
0,0 → 1,373
-- ################################################################################################# |
-- # << NEORV32 - Processor Top Entity with AXI4-Lite Compatible Master Interface >> # |
-- # ********************************************************************************************* # |
-- # "AXI", "AXI4" and "AXI4-Lite" are trademarks of Arm Holdings plc. # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
-- # # |
-- # Redistribution and use in source and binary forms, with or without modification, are # |
-- # permitted provided that the following conditions are met: # |
-- # # |
-- # 1. Redistributions of source code must retain the above copyright notice, this list of # |
-- # conditions and the following disclaimer. # |
-- # # |
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
-- # conditions and the following disclaimer in the documentation and/or other materials # |
-- # provided with the distribution. # |
-- # # |
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
-- # endorse or promote products derived from this software without specific prior written # |
-- # permission. # |
-- # # |
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
-- # OF THE POSSIBILITY OF SUCH DAMAGE. # |
-- # ********************************************************************************************* # |
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
-- ################################################################################################# |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
|
library neorv32; |
use neorv32.neorv32_package.all; |
|
entity neorv32_top_axi4lite is |
generic ( |
-- General -- |
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
USER_CODE : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom user code |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.? |
-- Extension Options -- |
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations |
-- Physical Memory Protection (PMP) -- |
PMP_USE : boolean := false; -- implement PMP? |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Internal Instruction memory -- |
MEM_INT_IMEM_USE : boolean := true; -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes |
MEM_INT_IMEM_ROM : boolean := false; -- implement processor-internal instruction memory as ROM |
-- Internal Data memory -- |
MEM_INT_DMEM_USE : boolean := true; -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
IO_UART_USE : boolean := true; -- implement universal asynchronous receiver/transmitter (UART)? |
IO_SPI_USE : boolean := true; -- implement serial peripheral interface (SPI)? |
IO_TWI_USE : boolean := true; -- implement two-wire interface (TWI)? |
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_USE : boolean := false; -- implement true random number generator (TRNG)? |
IO_CFU0_USE : boolean := false; -- implement custom functions unit 0 (CFU0)? |
IO_CFU1_USE : boolean := false -- implement custom functions unit 1 (CFU1)? |
); |
port ( |
-- AXI Lite-Compatible Master Interface -- |
-- Clock and Reset -- |
m_axi_aclk : in std_logic; |
m_axi_aresetn : in std_logic; |
-- Write Address Channel -- |
m_axi_awaddr : out std_logic_vector(31 downto 0); |
m_axi_awprot : out std_logic_vector(2 downto 0); |
m_axi_awvalid : out std_logic; |
m_axi_awready : in std_logic; |
-- Write Data Channel -- |
m_axi_wdata : out std_logic_vector(31 downto 0); |
m_axi_wstrb : out std_logic_vector(3 downto 0); |
m_axi_wvalid : out std_logic; |
m_axi_wready : in std_logic; |
-- Read Address Channel -- |
m_axi_araddr : out std_logic_vector(31 downto 0); |
m_axi_arprot : out std_logic_vector(2 downto 0); |
m_axi_arvalid : out std_logic; |
m_axi_arready : in std_logic; |
-- Read Data Channel -- |
m_axi_rdata : in std_logic_vector(31 downto 0); |
m_axi_rresp : in std_logic_vector(1 downto 0); |
m_axi_rvalid : in std_logic; |
m_axi_rready : out std_logic; |
-- Write Response Channel -- |
m_axi_bresp : in std_logic_vector(1 downto 0); |
m_axi_bvalid : in std_logic; |
m_axi_bready : out std_logic; |
-- ------------------------------------------------------------ |
-- GPIO -- |
gpio_o : out std_logic_vector(31 downto 0); -- parallel output |
gpio_i : in std_logic_vector(31 downto 0) := (others => '0'); -- parallel input |
-- UART -- |
uart_txd_o : out std_logic; -- UART send data |
uart_rxd_i : in std_logic := '0'; -- UART receive data |
-- SPI -- |
spi_sck_o : out std_logic; -- SPI serial clock |
spi_sdo_o : out std_logic; -- controller data out, peripheral data in |
spi_sdi_i : in std_logic := '0'; -- controller data in, peripheral data out |
spi_csn_o : out std_logic_vector(07 downto 0); -- SPI CS |
-- TWI -- |
twi_sda_io : inout std_logic; -- twi serial data line |
twi_scl_io : inout std_logic; -- twi serial clock line |
-- PWM -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- Interrupts -- |
mtime_irq_i : in std_logic := '0'; -- machine timer interrupt, available if IO_MTIME_USE = false |
msw_irq_i : in std_logic := '0'; -- machine software interrupt |
mext_irq_i : in std_logic := '0' -- machine external interrupt |
); |
end neorv32_top_axi4lite; |
|
architecture neorv32_top_axi4lite_rtl of neorv32_top_axi4lite is |
|
-- type conversion -- |
constant USER_CODE_INT : std_ulogic_vector(31 downto 0) := std_ulogic_vector(USER_CODE); |
-- |
signal clk_i_int : std_ulogic; |
signal rstn_i_int : std_ulogic; |
-- |
signal gpio_o_int : std_ulogic_vector(31 downto 0); |
signal gpio_i_int : std_ulogic_vector(31 downto 0); |
-- |
signal priv_level : std_ulogic_vector(1 downto 0); |
-- |
signal uart_txd_o_int : std_ulogic; |
signal uart_rxd_i_int : std_ulogic; |
-- |
signal spi_sck_o_int : std_ulogic; |
signal spi_sdo_o_int : std_ulogic; |
signal spi_sdi_i_int : std_ulogic; |
signal spi_csn_o_int : std_ulogic_vector(07 downto 0); |
-- |
signal pwm_o_int : std_ulogic_vector(03 downto 0); |
-- |
signal mtime_irq_i_int : std_ulogic; |
signal msw_irq_i_int : std_ulogic; |
signal mext_irq_i_int : std_ulogic; |
|
-- internal wishbone bus -- |
type wb_bus_t is record |
adr : std_ulogic_vector(31 downto 0); -- address |
di : std_ulogic_vector(31 downto 0); -- processor input data |
do : std_ulogic_vector(31 downto 0); -- processor output data |
we : std_ulogic; -- write enable |
sel : std_ulogic_vector(03 downto 0); -- byte enable |
stb : std_ulogic; -- strobe |
cyc : std_ulogic; -- valid cycle |
ack : std_ulogic; -- transfer acknowledge |
err : std_ulogic; -- transfer error |
end record; |
signal wb_core : wb_bus_t; |
|
-- AXI bridge control -- |
type ctrl_t is record |
radr_received : std_ulogic; |
wadr_received : std_ulogic; |
wdat_received : std_ulogic; |
end record; |
signal ctrl : ctrl_t; |
|
signal ack_read, ack_write : std_ulogic; -- normal transfer termination |
signal err_read, err_write : std_ulogic; -- error transfer termination |
|
begin |
|
-- Sanity Checks -------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
assert not (wb_pipe_mode_c = true) report "NEORV32 PROCESSOR CONFIG ERROR: AXI4-Lite bridge requires STANDARD Wishbone mode (package.wb_pipe_mode_c = false)!" severity error; |
|
|
-- The Core Of The Problem ---------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
neorv32_top_inst: neorv32_top |
generic map ( |
-- General -- |
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz |
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader? |
USER_CODE => USER_CODE_INT, -- custom user code |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension? |
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension? |
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension? |
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension? |
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system? |
CPU_EXTENSION_RISCV_Zifencei => CPU_EXTENSION_RISCV_Zifencei, -- implement instruction stream sync.? |
-- Extension Options -- |
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier |
FAST_SHIFT_EN => FAST_SHIFT_EN, -- use barrel shifter for shift operations |
-- Physical Memory Protection (PMP) -- |
PMP_USE => PMP_USE, -- implement PMP? |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (max 16) |
PMP_GRANULARITY => PMP_GRANULARITY, -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Internal Instruction memory -- |
MEM_INT_IMEM_USE => MEM_INT_IMEM_USE, -- implement processor-internal instruction memory |
MEM_INT_IMEM_SIZE => MEM_INT_IMEM_SIZE, -- size of processor-internal instruction memory in bytes |
MEM_INT_IMEM_ROM => MEM_INT_IMEM_ROM, -- implement processor-internal instruction memory as ROM |
-- Internal Data memory -- |
MEM_INT_DMEM_USE => MEM_INT_DMEM_USE, -- implement processor-internal data memory |
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE => true, -- implement external memory bus interface? |
-- Processor peripherals -- |
IO_GPIO_USE => IO_GPIO_USE, -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE => IO_MTIME_USE, -- implement machine system timer (MTIME)? |
IO_UART_USE => IO_UART_USE, -- implement universal asynchronous receiver/transmitter (UART)? |
IO_SPI_USE => IO_SPI_USE, -- implement serial peripheral interface (SPI)? |
IO_TWI_USE => IO_TWI_USE, -- implement two-wire interface (TWI)? |
IO_PWM_USE => IO_PWM_USE, -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE => IO_WDT_USE, -- implement watch dog timer (WDT)? |
IO_TRNG_USE => IO_TRNG_USE, -- implement true random number generator (TRNG)? |
IO_CFU0_USE => IO_CFU0_USE, -- implement custom functions unit 0 (CFU0)? |
IO_CFU1_USE => IO_CFU1_USE -- implement custom functions unit 1 (CFU1)? |
) |
port map ( |
-- Global control -- |
clk_i => clk_i_int, -- global clock, rising edge |
rstn_i => rstn_i_int, -- global reset, low-active, async |
-- Wishbone bus interface -- |
wb_adr_o => wb_core.adr, -- address |
wb_dat_i => wb_core.di, -- read data |
wb_dat_o => wb_core.do, -- write data |
wb_we_o => wb_core.we, -- read/write |
wb_sel_o => wb_core.sel, -- byte enable |
wb_stb_o => wb_core.stb, -- strobe |
wb_cyc_o => wb_core.cyc, -- valid cycle |
wb_ack_i => wb_core.ack, -- transfer acknowledge |
wb_err_i => wb_core.err, -- transfer error |
-- Advanced memory control signals -- |
priv_o => priv_level, -- current CPU privilege level |
fence_o => open, -- indicates an executed FENCE operation |
fencei_o => open, -- indicates an executed FENCEI operation |
-- GPIO -- |
gpio_o => gpio_o_int, -- parallel output |
gpio_i => gpio_i_int, -- parallel input |
-- UART -- |
uart_txd_o => uart_txd_o_int, -- UART send data |
uart_rxd_i => uart_rxd_i_int, -- UART receive data |
-- SPI -- |
spi_sck_o => spi_sck_o_int, -- SPI serial clock |
spi_sdo_o => spi_sdo_o_int, -- controller data out, peripheral data in |
spi_sdi_i => spi_sdi_i_int, -- controller data in, peripheral data out |
spi_csn_o => spi_csn_o_int, -- SPI CS |
-- TWI -- |
twi_sda_io => twi_sda_io, -- twi serial data line |
twi_scl_io => twi_scl_io, -- twi serial clock line |
-- PWM -- |
pwm_o => pwm_o_int, -- pwm channels |
-- Interrupts -- |
mtime_irq_i => mtime_irq_i_int, -- machine timer interrupt, available if IO_MTIME_USE = false |
msw_irq_i => msw_irq_i_int, -- machine software interrupt |
mext_irq_i => mext_irq_i_int -- machine external interrupt |
); |
|
-- type conversion -- |
gpio_o <= std_logic_vector(gpio_o_int); |
gpio_i_int <= std_ulogic_vector(gpio_i); |
|
uart_txd_o <= std_logic(uart_txd_o_int); |
uart_rxd_i_int <= std_ulogic(uart_rxd_i); |
|
spi_sck_o <= std_logic(spi_sck_o_int); |
spi_sdo_o <= std_logic(spi_sdo_o_int); |
spi_sdi_i_int <= std_ulogic(spi_sdi_i); |
spi_csn_o <= std_logic_vector(spi_csn_o_int); |
|
pwm_o <= std_logic_vector(pwm_o_int); |
|
msw_irq_i_int <= std_ulogic(msw_irq_i); |
mext_irq_i_int <= std_ulogic(mext_irq_i); |
|
|
-- Wishbone to AXI4-Lite Bridge ----------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
|
-- access arbiter -- |
axi_access_arbiter: process(rstn_i_int, clk_i_int) |
begin |
if (rstn_i_int = '0') then |
ctrl.radr_received <= '0'; |
ctrl.wadr_received <= '0'; |
ctrl.wdat_received <= '0'; |
elsif rising_edge(clk_i_int) then |
if (wb_core.cyc = '0') then -- idle |
ctrl.radr_received <= '0'; |
ctrl.wadr_received <= '0'; |
ctrl.wdat_received <= '0'; |
else -- busy |
-- "read address received" flag -- |
if (wb_core.we = '0') then -- pending READ |
if (m_axi_arready = '1') then -- read address received? |
ctrl.radr_received <= '1'; |
end if; |
end if; |
-- "write address received" flag -- |
if (wb_core.we = '1') then -- pending WRITE |
if (m_axi_awready = '1') then -- write address received? |
ctrl.wadr_received <= '1'; |
end if; |
end if; |
-- "write data received" flag -- |
if (wb_core.we = '1') then -- pending WRITE |
if (m_axi_wready = '1') then |
ctrl.wdat_received <= '1'; |
end if; |
end if; |
end if; |
end if; |
end process axi_access_arbiter; |
|
|
-- AXI4-Lite Global Signals -- |
clk_i_int <= std_ulogic(m_axi_aclk); |
rstn_i_int <= std_ulogic(m_axi_aresetn); |
|
|
-- AXI4-Lite Read Address Channel -- |
m_axi_araddr <= std_logic_vector(wb_core.adr); |
m_axi_arvalid <= std_logic((wb_core.cyc and (not wb_core.we)) and (not ctrl.radr_received)); |
m_axi_arprot <= "000"; -- recommended by Xilinx -- "001" when (priv_level = priv_mode_m_c) else "000"; -- always: data-access, secure; privileged only when CPU is in machine mode |
|
-- AXI4-Lite Read Data Channel -- |
m_axi_rready <= std_logic(wb_core.cyc and (not wb_core.we)); |
wb_core.di <= std_ulogic_vector(m_axi_rdata); |
ack_read <= std_ulogic(m_axi_rvalid); |
err_read <= '0' when (m_axi_rresp = "00") else '1'; -- read response = ok? check this signal only when m_axi_rvalid = '1' |
|
|
-- AXI4-Lite Write Address Channel -- |
m_axi_awaddr <= std_logic_vector(wb_core.adr); |
m_axi_awvalid <= std_logic((wb_core.cyc and wb_core.we) and (not ctrl.wadr_received)); |
m_axi_awprot <= "000"; -- recommended by Xilinx -- "001" when (priv_level = priv_mode_m_c) else "000"; -- always: data-access, secure; privileged only when CPU is in machine mode |
|
-- AXI4-Lite Write Data Channel -- |
m_axi_wdata <= std_logic_vector(wb_core.do); |
m_axi_wvalid <= std_logic((wb_core.cyc and wb_core.we) and (not ctrl.wdat_received)); |
m_axi_wstrb <= std_logic_vector(wb_core.sel); -- byte-enable |
|
-- AXI4-Lite Write Response Channel -- |
m_axi_bready <= std_logic(wb_core.cyc and wb_core.we); |
ack_write <= std_ulogic(m_axi_bvalid); |
err_write <= '0' when (m_axi_bresp = "00") else '1'; -- write response = ok? check this signal only when m_axi_bvalid = '1' |
|
|
-- Wishbone transfer termination -- |
wb_core.ack <= ack_read or ack_write; |
wb_core.err <= (ack_read and err_read) or (ack_write and err_write); |
|
|
end neorv32_top_axi4lite_rtl; |
/neorv32/trunk/rtl/top_templates/neorv32_top_stdlogic.vhd
68,7 → 68,6
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE : boolean := false; -- implement external memory bus interface? |
MEM_EXT_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
96,6 → 95,7
wb_ack_i : in std_logic := '0'; -- transfer acknowledge |
wb_err_i : in std_logic := '0'; -- transfer error |
-- Advanced memory control signals (available if MEM_EXT_USE = true) -- |
priv_o : out std_logic_vector(1 downto 0); -- current CPU privilege level |
fence_o : out std_logic; -- indicates an executed FENCE operation |
fencei_o : out std_logic; -- indicates an executed FENCEI operation |
-- GPIO (available if IO_GPIO_USE = true) -- |
110,8 → 110,8
spi_sdi_i : in std_logic := '0'; -- controller data in, peripheral data out |
spi_csn_o : out std_logic_vector(07 downto 0); -- SPI CS |
-- TWI (available if IO_TWI_USE = true) -- |
twi_sda_io : inout std_logic := 'H'; -- twi serial data line |
twi_scl_io : inout std_logic := 'H'; -- twi serial clock line |
twi_sda_io : inout std_logic; -- twi serial data line |
twi_scl_io : inout std_logic; -- twi serial clock line |
-- PWM (available if IO_PWM_USE = true) -- |
pwm_o : out std_logic_vector(03 downto 0); -- pwm channels |
-- Interrupts -- |
139,6 → 139,7
signal wb_ack_i_int : std_ulogic; |
signal wb_err_i_int : std_ulogic; |
-- |
signal priv_o_int : std_ulogic_vector(1 downto 0); |
signal fence_o_int : std_ulogic; |
signal fencei_o_int : std_ulogic; |
-- |
192,7 → 193,6
MEM_INT_DMEM_SIZE => MEM_INT_DMEM_SIZE, -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE => MEM_EXT_USE, -- implement external memory bus interface? |
MEM_EXT_REG_STAGES => MEM_EXT_REG_STAGES, -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE => IO_GPIO_USE, -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE => IO_MTIME_USE, -- implement machine system timer (MTIME)? |
220,6 → 220,7
wb_ack_i => wb_ack_i_int, -- transfer acknowledge |
wb_err_i => wb_err_i_int, -- transfer error |
-- Advanced memory control signals -- |
priv_o => priv_o_int, -- current CPU privilege level |
fence_o => fence_o_int, -- indicates an executed FENCE operation |
fencei_o => fencei_o_int, -- indicates an executed FENCEI operation |
-- GPIO -- |
258,6 → 259,7
wb_ack_i_int <= std_ulogic(wb_ack_i); |
wb_err_i_int <= std_ulogic(wb_err_i); |
|
priv_o <= std_logic_vector(priv_o_int); |
fence_o <= std_logic(fence_o_int); |
fencei_o <= std_logic(fencei_o_int); |
|
276,6 → 278,6
|
msw_irq_i_int <= std_ulogic(msw_irq_i); |
mext_irq_i_int <= std_ulogic(mext_irq_i); |
|
|
|
end neorv32_top_stdlogic_rtl; |
/neorv32/trunk/rtl/README.md
1,16 → 1,16
## VHDL Source File Folders |
|
### `core` |
### [`core`](https://github.com/stnolting/neorv32/tree/master/rtl/core) |
|
This folder contains the the core VHDL files for the NEORV32 CPU and the NEORV32 Processor. When creating a new synthesis/simulation project make |
sure that all `*.vhd` files from this folder are added to a **new** design library called `neorv32`. |
|
### `fpga_specifc` |
### [`fpga_specifc`](https://github.com/stnolting/neorv32/tree/master/rtl/fpga_specific) |
|
This folder provides FPGA- or technology-specific *alternatives* for certain CPU and/or processor modules (for example optimized memory modules using |
FPGA-specific primitves). |
|
### `top_templates` |
### [`top_templates`](https://github.com/stnolting/neorv32/tree/master/rtl/top_templates) |
|
Alternative top entities for the CPU and/or the processor. Actually, these *alternative* top entities are wrappers, which instantiate the *real* top entity of |
processor/CPU and provide a different interface. |
/neorv32/trunk/sim/ghdl/ghdl_sim.sh
66,6 → 66,7
# |
ghdl -a --work=neorv32 $srcdir_top_templates/neorv32_cpu_stdlogic.vhd |
ghdl -a --work=neorv32 $srcdir_top_templates/neorv32_test_setup.vhd |
ghdl -a --work=neorv32 $srcdir_top_templates/neorv32_top_axi4lite.vhd |
ghdl -a --work=neorv32 $srcdir_top_templates/neorv32_top_stdlogic.vhd |
# |
ghdl -a --work=neorv32 $srcdir_sim/*.vhd |
/neorv32/trunk/sim/neorv32_tb.vhd
181,7 → 181,6
MEM_INT_DMEM_SIZE => 8*1024, -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE => true, -- implement external memory bus interface? |
MEM_EXT_REG_STAGES => 2, -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE => true, -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE => true, -- implement machine system timer (MTIME)? |
312,7 → 311,7
if (wb_mem_latency_c > 1) then |
for i in 1 to wb_mem_latency_c-1 loop |
wb_mem.rdata(i) <= wb_mem.rdata(i-1); |
wb_mem.rb_en(i) <= wb_mem.rb_en(i-1); |
wb_mem.rb_en(i) <= wb_mem.rb_en(i-1) and wb_cpu.cyc; |
wb_mem.ack(i) <= wb_mem.ack(i-1) and wb_cpu.cyc; |
end loop; |
end if; |
324,7 → 323,7
|
-- output to cpu -- |
wb_cpu.rdata <= wb_mem.rdata(wb_mem_latency_c-1) when (wb_mem.rb_en(wb_mem_latency_c-1) = '1') else (others=> '0'); -- data output gate |
wb_cpu.ack <= wb_mem.ack(wb_mem_latency_c-1) and wb_cpu.cyc; -- another AND for classic/standard wishbone transactions |
wb_cpu.ack <= wb_mem.ack(wb_mem_latency_c-1); |
wb_cpu.err <= '0'; |
|
|
/neorv32/trunk/sw/bootloader/bootloader.c
415,8 → 415,9
**************************************************************************/ |
void get_exe(int src) { |
|
// is instruction memory (IMEM) read-only? |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) { |
// is MEM implemented and read-only? |
if ((SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) && |
(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM))) { |
system_error(ERROR_ROM); |
} |
|
/neorv32/trunk/sw/example/cpu_test/main.c
49,8 → 49,6
/**@{*/ |
/** UART BAUD rate */ |
#define BAUD_RATE 19200 |
//** Set 1 to run external memory test */ |
#define EXT_MEM_TEST 1 |
//** Reachable unaligned address */ |
#define ADDR_UNALIGNED 0x00000002 |
//** Unreachable aligned address */ |
60,15 → 58,6
/**@}*/ |
|
|
/**********************************************************************//** |
* @name Exception handler acknowledges |
**************************************************************************/ |
/**@{*/ |
/** Global volatile variable to store exception handler answer */ |
volatile uint32_t exception_handler_answer; |
/**@}*/ |
|
|
// Prototypes |
void global_trap_handler(void); |
void test_ok(void); |
97,8 → 86,8
**************************************************************************/ |
int main() { |
|
register uint32_t tmp_a; |
uint32_t i; |
register uint32_t tmp_a, tmp_b, tmp_c; |
uint32_t i, j; |
volatile uint32_t dummy_dst __attribute__((unused)); |
|
union { |
115,7 → 104,7
|
neorv32_mtime_set_time(0); |
// set CMP of machine system timer MTIME to max to prevent an IRQ |
uint64_t mtime_cmp_max = 0xFFFFFFFFFFFFFFFFL; |
uint64_t mtime_cmp_max = 0xFFFFFFFFFFFFFFFFUL; |
neorv32_mtime_set_timecmp(mtime_cmp_max); |
|
// intro |
176,84 → 165,13
// intro2 |
neorv32_uart_printf("\n\nStarting tests...\n\n"); |
|
|
// enable global interrupts |
neorv32_cpu_eint(); |
|
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
|
// ---------------------------------------------------------- |
// Instruction memory test |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("[%i] Processor-internal IMEM test: ", cnt_test); |
|
if ((UART_CT & (1 << UART_CT_SIM_MODE)) == 0) { // check if this is a simulation |
cnt_test++; |
|
register uint32_t dmem_probe_addr = SYSINFO_ISPACE_BASE; |
uint32_t dmem_probe_cnt = 0; |
|
while(1) { |
asm volatile ("lb zero, 0(%[input_j])" : : [input_j] "r" (dmem_probe_addr)); |
if (exception_handler_answer == TRAP_CODE_L_ACCESS) { |
break; |
} |
dmem_probe_addr++; |
dmem_probe_cnt++; |
} |
|
neorv32_uart_printf("%u bytes (should be %u bytes) ", dmem_probe_cnt, SYSINFO_IMEM_SIZE); |
neorv32_uart_printf("@ 0x%x ", SYSINFO_ISPACE_BASE); |
if (dmem_probe_cnt == SYSINFO_IMEM_SIZE) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (disabled for simulation)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Data memory test |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("[%i] Processor-internal DMEM test: ", cnt_test); |
|
if ((UART_CT & (1 << UART_CT_SIM_MODE)) == 0) { // check if this is a simulation |
cnt_test++; |
|
register uint32_t imem_probe_addr = SYSINFO_DSPACE_BASE; |
uint32_t imem_probe_cnt = 0; |
|
while(1) { |
asm volatile ("lb zero, 0(%[input_j])" : : [input_j] "r" (imem_probe_addr)); |
if (exception_handler_answer == TRAP_CODE_L_ACCESS) { |
break; |
} |
imem_probe_addr++; |
imem_probe_cnt++; |
} |
|
neorv32_uart_printf("%u bytes (should be %u bytes) ", imem_probe_cnt, SYSINFO_DMEM_SIZE); |
neorv32_uart_printf("@ 0x%x ", SYSINFO_DSPACE_BASE); |
if (imem_probe_cnt == SYSINFO_DMEM_SIZE) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (disabled for simulation)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// List all accessible CSRs |
// ---------------------------------------------------------- |
neorv32_uart_printf("[%i] List all accessible CSRs: ", cnt_test); |
279,7 → 197,7
|
// iterate through full 12-bit CSR address space |
for (csr_addr_cnt=0x000; csr_addr_cnt<=0xfff; csr_addr_cnt++) { |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
// construct and store new CSR access instruction |
// 0x00006073 = csrrsi, 0x000, 0 |
292,8 → 210,8
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); |
|
// check for access exception |
if (exception_handler_answer == 0xFFFFFFFF) { // no exception -> access ok -> CSR exists |
neorv32_uart_printf(" + 0x%x\n", csr_addr_cnt); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { // no exception -> access ok -> CSR exists |
neorv32_uart_printf(" + 0x%x\n", csr_addr_cnt); |
i++; |
} |
} |
312,7 → 230,7
// ---------------------------------------------------------- |
// CFU0 test (default HW) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Default CFU0 access test: ", cnt_test); |
|
// cfu0 implemented? |
327,7 → 245,7
|
if ((CFU0_REG_0 == 0x01234567) && (CFU0_REG_1 == 0x76543210) && |
(CFU0_REG_2 == 0xABCDABCD) && (CFU0_REG_3 == 0xFFAAFFAA) && // correct read-back |
(exception_handler_answer == 0xFFFFFFFF)) { // no exception |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception |
test_ok(); |
} |
else { |
335,7 → 253,7
} |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
neorv32_uart_printf("skipped (CFU0 not implemented)\n"); |
} |
|
|
342,7 → 260,7
// ---------------------------------------------------------- |
// CFU1 test (default HW) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Default CFU1 access test: ", cnt_test); |
|
// cfu0 implemented? |
357,7 → 275,7
|
if ((CFU1_REG_0 == 0x22334455) && (CFU1_REG_1 == 0x44782931) && |
(CFU1_REG_2 == 0xDDAABBFF) && (CFU1_REG_3 == 0xA0B0D0C0) && // correct read-back |
(exception_handler_answer == 0xFFFFFFFF)) { // no exception |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception |
test_ok(); |
} |
else { |
365,7 → 283,7
} |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
neorv32_uart_printf("skipped (CFU1 not implemented)\n"); |
} |
|
|
372,7 → 290,7
// ---------------------------------------------------------- |
// Bus timeout latency estimation |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Estimate bus time-out latency: ", cnt_test); |
|
// start timing |
380,11 → 298,11
|
// this will timeout |
MMR_UNREACHABLE = 0; |
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_a; |
|
// wait for timeout |
while (exception_handler_answer == 0xFFFFFFFF); |
while (neorv32_cpu_csr_read(CSR_MCAUSE) == 0); |
|
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_a; |
tmp_a = tmp_a / 4; // divide by average CPI |
neorv32_uart_printf("~%u cycles\n", tmp_a); |
|
392,42 → 310,49
// ---------------------------------------------------------- |
// External memory interface test |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("[%i] External memory access test: ", cnt_test); |
#if (EXT_MEM_TEST == 1) |
cnt_test++; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] External memory access (@ 0x%x) test: ", cnt_test, (uint32_t)EXT_MEM_BASE); |
|
// create test program in RAM |
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = { |
0x3407D073, // csrwi mscratch, 15 |
0x00008067 // ret (32-bit) |
}; |
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)) { |
cnt_test++; |
|
// copy to external memory |
if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) { |
test_fail(); |
} |
else { |
// create test program in RAM |
static const uint32_t dummy_ext_program[2] __attribute__((aligned(8))) = { |
0x3407D073, // csrwi mscratch, 15 |
0x00008067 // ret (32-bit) |
}; |
|
// execute program |
tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program |
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); |
|
if (exception_handler_answer == 0xFFFFFFFF) { // make sure there was no exception |
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15) { // make sure the program was executed in the right way |
test_ok(); |
// copy to external memory |
if (memcpy((void*)EXT_MEM_BASE, (void*)&dummy_ext_program, (size_t)sizeof(dummy_ext_program)) == NULL) { |
test_fail(); |
} |
else { |
test_fail(); |
|
// execute program |
tmp_a = (uint32_t)EXT_MEM_BASE; // call the dummy sub program |
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { // make sure there was no exception |
if (neorv32_cpu_csr_read(CSR_MSCRATCH) == 15) { // make sure the program was executed in the right way |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
test_fail(); |
} |
} |
} |
else { |
test_fail(); |
neorv32_uart_printf("skipped (external memory interface not implemented)\n"); |
} |
} |
#else |
neorv32_uart_printf("skipped (disabled)\n"); |
#endif |
else { |
neorv32_uart_printf("skipped (on real hardware)\n"); |
} |
|
|
// ---------------------------------------------------------- |
453,12 → 378,12
// ---------------------------------------------------------- |
// Test fence instructions - make sure CPU does not crash here and throws no exception |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FENCE instruction test: ", cnt_test); |
cnt_test++; |
asm volatile ("fence"); |
|
if (exception_handler_answer != 0xFFFFFFFF) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != 0) { |
test_fail(); |
} |
else { |
470,18 → 395,18
// Test fencei instructions - make sure CPU does not crash here and throws no exception |
// a more complex test is provided by the RISC-V compliance test |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FENCE.I instruction test: ", cnt_test); |
asm volatile ("fence.i"); |
|
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
else { |
cnt_test++; |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
asm volatile ("fence.i"); |
if (exception_handler_answer == 0xFFFFFFFF) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
test_ok(); |
} |
else { |
493,7 → 418,7
// ---------------------------------------------------------- |
// Illegal CSR access (CSR not implemented) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Illegal CSR (0xfff) access test: ", cnt_test); |
|
cnt_test++; |
500,7 → 425,7
|
neorv32_cpu_csr_read(0xfff); // CSR 0xfff not implemented |
|
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
511,7 → 436,7
// ---------------------------------------------------------- |
// Write-access to read-only CSR |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Read-only CSR (time) write access test: ", cnt_test); |
|
cnt_test++; |
518,7 → 443,7
|
neorv32_cpu_csr_write(CSR_TIME, 0); // time CSR is read-only |
|
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
529,7 → 454,7
// ---------------------------------------------------------- |
// No "real" CSR write access (because rs1 = r0) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Read-only CSR (time) no-write (rs1=0) access test: ", cnt_test); |
|
cnt_test++; |
538,7 → 463,7
// -> should cause no exception |
asm volatile("csrrs zero, time, zero"); |
|
if (exception_handler_answer == 0xFFFFFFFF) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
test_ok(); |
} |
else { |
549,7 → 474,7
// ---------------------------------------------------------- |
// Unaligned instruction address |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] I_ALIGN (instruction alignment) exception test: ", cnt_test); |
|
// skip if C-mode is implemented |
560,7 → 485,7
// call unaligned address |
((void (*)(void))ADDR_UNALIGNED)(); |
|
if (exception_handler_answer == TRAP_CODE_I_MISALIGNED) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_MISALIGNED) { |
neorv32_uart_printf("ok\n"); |
cnt_ok++; |
} |
577,7 → 502,7
// ---------------------------------------------------------- |
// Instruction access fault |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] I_ACC (instruction bus access) exception test: ", cnt_test); |
cnt_test++; |
|
584,7 → 509,7
// call unreachable aligned address |
((void (*)(void))ADDR_UNREACHABLE)(); |
|
if (exception_handler_answer == TRAP_CODE_I_ACCESS) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ACCESS) { |
test_ok(); |
} |
else { |
595,7 → 520,7
// ---------------------------------------------------------- |
// Illegal instruction |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] I_ILLEG (illegal instruction) exception test: ", cnt_test); |
|
cnt_test++; |
603,7 → 528,7
asm volatile ("csrrw zero, 0xfff, zero"); // = 0xfff01073 : CSR 0xfff not implemented -> illegal instruction |
|
// make sure this has cause an illegal exception |
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
// make sure this is really the instruction that caused the exception |
// for illegal instructions mtval contains the actual instruction word |
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0xfff01073) { |
621,7 → 546,7
// ---------------------------------------------------------- |
// Illegal compressed instruction |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] CI_ILLEG (illegal compressed instruction) exception test: ", cnt_test); |
|
// skip if C-mode is not implemented |
638,7 → 563,7
tmp_a = (uint32_t)&dummy_sub_program_ci; // call the dummy sub program |
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); |
|
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
653,13 → 578,13
// ---------------------------------------------------------- |
// Breakpoint instruction |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] BREAK (break instruction) exception test: ", cnt_test); |
cnt_test++; |
|
asm volatile("EBREAK"); |
|
if (exception_handler_answer == TRAP_CODE_BREAKPOINT) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_BREAKPOINT) { |
test_ok(); |
} |
else { |
670,7 → 595,7
// ---------------------------------------------------------- |
// Unaligned load address |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] L_ALIGN (load address alignment) exception test: ", cnt_test); |
cnt_test++; |
|
677,7 → 602,7
// load from unaligned address |
asm volatile ("lw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED)); |
|
if (exception_handler_answer == TRAP_CODE_L_MISALIGNED) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) { |
test_ok(); |
} |
else { |
688,7 → 613,7
// ---------------------------------------------------------- |
// Load access fault |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] L_ACC (load bus access) exception test: ", cnt_test); |
cnt_test++; |
|
695,7 → 620,7
// load from unreachable aligned address |
dummy_dst = MMR_UNREACHABLE; |
|
if (exception_handler_answer == TRAP_CODE_L_ACCESS) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) { |
test_ok(); |
} |
else { |
706,7 → 631,7
// ---------------------------------------------------------- |
// Unaligned store address |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] S_ALIGN (store address alignment) exception test: ", cnt_test); |
cnt_test++; |
|
713,7 → 638,7
// store to unaligned address |
asm volatile ("sw zero, %[input_i](zero)" : : [input_i] "i" (ADDR_UNALIGNED)); |
|
if (exception_handler_answer == TRAP_CODE_S_MISALIGNED) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) { |
test_ok(); |
} |
else { |
724,7 → 649,7
// ---------------------------------------------------------- |
// Store access fault |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] S_ACC (store bus access) exception test: ", cnt_test); |
cnt_test++; |
|
731,7 → 656,7
// store to unreachable aligned address |
MMR_UNREACHABLE = 0; |
|
if (exception_handler_answer == TRAP_CODE_S_ACCESS) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) { |
test_ok(); |
} |
else { |
742,13 → 667,13
// ---------------------------------------------------------- |
// Environment call |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] ENVCALL (ecall instruction) exception test: ", cnt_test); |
cnt_test++; |
|
asm volatile("ECALL"); |
|
if (exception_handler_answer == TRAP_CODE_MENV_CALL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MENV_CALL) { |
test_ok(); |
} |
else { |
759,7 → 684,7
// ---------------------------------------------------------- |
// Machine timer interrupt (MTIME) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] MTI (machine timer) interrupt test: ", cnt_test); |
|
if (neorv32_mtime_available()) { |
776,7 → 701,7
asm volatile("nop"); |
asm volatile("nop"); |
|
if (exception_handler_answer == TRAP_CODE_MTI) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) { |
test_ok(); |
} |
else { |
794,7 → 719,7
// ---------------------------------------------------------- |
// Fast interrupt channel 0 (WDT) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ0 (fast IRQ0) interrupt test (via WDT): ", cnt_test); |
|
if (neorv32_wdt_available()) { |
813,7 → 738,7
asm volatile("nop"); |
asm volatile("nop"); |
|
if (exception_handler_answer == TRAP_CODE_FIRQ_0) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_0) { |
test_ok(); |
} |
else { |
831,53 → 756,57
// ---------------------------------------------------------- |
// Fast interrupt channel 1 (GPIO) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ1 (fast IRQ1) interrupt test (via GPIO): ", cnt_test); |
|
if (neorv32_gpio_available()) { |
cnt_test++; |
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation |
if (neorv32_gpio_available()) { |
cnt_test++; |
|
// clear output port |
neorv32_gpio_port_set(0); |
// clear output port |
neorv32_gpio_port_set(0); |
|
// configure GPIO.in(31) for pin-change IRQ |
neorv32_gpio_pin_change_config(0x80000000); |
// configure GPIO.in(31) for pin-change IRQ |
neorv32_gpio_pin_change_config(0x80000000); |
|
// trigger pin-change IRQ by setting GPIO.out(31) |
// the testbench connects GPIO.out => GPIO.in |
neorv32_gpio_pin_set(31); |
// trigger pin-change IRQ by setting GPIO.out(31) |
// the testbench connects GPIO.out => GPIO.in |
neorv32_gpio_pin_set(31); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
if (exception_handler_answer == TRAP_CODE_FIRQ_1) { |
test_ok(); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_1) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
// disable GPIO pin-change IRQ |
neorv32_gpio_pin_change_config(0); |
|
// clear output port |
neorv32_gpio_port_set(0); |
} |
else { |
test_fail(); |
neorv32_uart_printf("skipped (GPIO not implemented)\n"); |
} |
|
// disable GPIO pin-change IRQ |
neorv32_gpio_pin_change_config(0); |
|
// clear output port |
neorv32_gpio_port_set(0); |
} |
else { |
neorv32_uart_printf("skipped (GPIO not implemented)\n"); |
neorv32_uart_printf("skipped (on real hardware)\n"); |
} |
|
|
|
// ---------------------------------------------------------- |
// Fast interrupt channel 2 (UART) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ2 (fast IRQ2) interrupt test (via UART): ", cnt_test); |
|
if (neorv32_uart_available()) { |
915,7 → 844,7
// re-enable UART sim_mode if it was enabled and disable UART TX done IRQ |
UART_CT = uart_ct_backup; |
|
if (exception_handler_answer == TRAP_CODE_FIRQ_2) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_2) { |
test_ok(); |
} |
else { |
931,7 → 860,7
// ---------------------------------------------------------- |
// Fast interrupt channel 3 (SPI) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ3 (fast IRQ3) interrupt test (via SPI): ", cnt_test); |
|
if (neorv32_spi_available()) { |
952,7 → 881,7
asm volatile("nop"); |
asm volatile("nop"); |
|
if (exception_handler_answer == TRAP_CODE_FIRQ_3) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) { |
test_ok(); |
} |
else { |
970,16 → 899,17
// ---------------------------------------------------------- |
// Fast interrupt channel 3 (TWI) |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ3 (fast IRQ3) interrupt test (via TWI): ", cnt_test); |
|
if (neorv32_twi_available()) { |
cnt_test++; |
|
// configure TWI, fastest clock, transfer-done IRQ enable |
neorv32_twi_setup(CLK_PRSC_2, 1); |
// configure TWI, fastest clock, transfer-done IRQ enable, disable peripheral clock stretching |
neorv32_twi_setup(CLK_PRSC_2, 1, 0); |
|
// trigger TWI IRQ |
neorv32_twi_generate_start(); |
neorv32_twi_trans(0); |
neorv32_twi_generate_stop(); |
|
991,7 → 921,7
asm volatile("nop"); |
asm volatile("nop"); |
|
if (exception_handler_answer == TRAP_CODE_FIRQ_3) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_3) { |
test_ok(); |
} |
else { |
1009,7 → 939,7
// ---------------------------------------------------------- |
// Test WFI ("sleep") instructions, wakeup via MTIME |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] WFI (wait for interrupt / sleep instruction) test (wake-up via MTIME): ", cnt_test); |
|
if (neorv32_mtime_available()) { |
1021,7 → 951,7
// put CPU into sleep mode |
asm volatile ("wfi"); |
|
if (exception_handler_answer != TRAP_CODE_MTI) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_MTI) { |
test_fail(); |
} |
else { |
1039,7 → 969,7
// ---------------------------------------------------------- |
// Test invalid CSR access in user mode |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Invalid CSR access (mstatus) from user mode test: ", cnt_test); |
|
// skip if U-mode is not implemented |
1054,7 → 984,7
neorv32_cpu_csr_read(CSR_MSTATUS); |
} |
|
if (exception_handler_answer == TRAP_CODE_I_ILLEGAL) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
1070,7 → 1000,7
// ---------------------------------------------------------- |
// Test RTE debug handler |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] RTE (runtime environment) debug trap handler test: ", cnt_test); |
|
cnt_test++; |
1082,12 → 1012,12
neorv32_cpu_csr_read(0xfff); // CSR not available |
|
neorv32_uart_printf(" "); |
if (exception_handler_answer == 0xFFFFFFFF) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) != 0) { |
test_ok(); |
} |
else { |
test_fail(); |
neorv32_uart_printf("answer: 0x%x", exception_handler_answer); |
neorv32_uart_printf("answer: 0x%x", neorv32_cpu_csr_read(CSR_MCAUSE)); |
} |
|
// restore original handler |
1097,7 → 1027,6
// ---------------------------------------------------------- |
// Test physical memory protection |
// ---------------------------------------------------------- |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_uart_printf("[%i] Physical memory protection (PMP): ", cnt_test); |
|
// check if PMP is implemented |
1105,13 → 1034,37
|
// Test access to protected region |
// --------------------------------------------- |
neorv32_uart_printf("Creating protected page (NAPOT, 64kB) @ 0xFFFFA000, [!x, !w, r]... "); |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
cnt_test++; |
|
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffdfff); // 64k area @ 0xFFFFA000 |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions |
// check min granulartiy |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0); |
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff); |
tmp_a = neorv32_cpu_csr_read(0x3b0); |
|
if ((neorv32_cpu_csr_read(CSR_PMPADDR0) == 0xffffdfff) && (neorv32_cpu_csr_read(CSR_PMPCFG0) == 0b00011001)) { |
// find least-significat set bit |
for (i=31; i!=0; i--) { |
if (((tmp_a >> i) & 1) == 0) { |
break; |
} |
} |
|
tmp_a = SYSINFO_DSPACE_BASE; // base address of protected region |
|
tmp_b = 0; |
for (j=i; j!=0; j--) { |
tmp_b = tmp_b << 1; |
tmp_b = tmp_b | 1; |
} |
tmp_c = tmp_a & (~tmp_b); // clear LSBs in base address |
tmp_c = tmp_c | tmp_b; // set region size config |
|
neorv32_uart_printf("Creating protected page (NAPOT, [!X,!W,R], %u bytes) @ 0x%x (PMPADDR = 0x%x): ", (uint32_t)(1 << (i+1+2)), tmp_a, tmp_c); |
|
neorv32_cpu_csr_write(CSR_PMPADDR0, tmp_c); // 64k area @ 0xFFFFA000 |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions |
|
if ((neorv32_cpu_csr_read(CSR_PMPADDR0) == tmp_c) && (neorv32_cpu_csr_read(CSR_PMPCFG0) == 0b00011001) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
} |
else { |
1119,18 → 1072,43
} |
|
|
// ------ EXECUTE: should fail ------ |
neorv32_uart_printf("[%i] - PMP: U-mode [!X,!W,R] execute test: ", cnt_test); |
cnt_test++; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); // call address to execute -> should fail |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
// switch back to machine mode (if not allready) |
asm volatile ("ecall"); |
|
test_fail(); |
} |
else { |
// switch back to machine mode (if not allready) |
asm volatile ("ecall"); |
|
test_ok(); |
} |
|
|
// ------ LOAD: should work ------ |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] load test: ", cnt_test); |
neorv32_uart_printf("[%i] - PMP: U-mode [!X,!W,R] read test: ", cnt_test); |
cnt_test++; |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile ("lw zero, 0xFFFFFF90(zero)"); // MTIME load access, should work |
asm volatile ("lw zero, 0(%[input_i])" : : [input_i] "r" (tmp_a)); // load access -> should work |
} |
|
if (exception_handler_answer == 0xFFFFFFFF) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
// switch back to machine mode (if not allready) |
asm volatile ("ecall"); |
|
1145,17 → 1123,17
|
|
// ------ STORE: should fail ------ |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] store test: ", cnt_test); |
neorv32_uart_printf("[%i] - PMP: U-mode [!X,!W,R] write test: ", cnt_test); |
cnt_test++; |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
asm volatile ("sw zero, 0xFFFFFF90(zero)"); // MTIME store access, should fail |
asm volatile ("sw zero, 0(%[input_i])" : : [input_i] "r" (tmp_a)); // store access -> should fail |
} |
|
if (exception_handler_answer == TRAP_CODE_S_ACCESS) { |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) { |
// switch back to machine mode (if not allready) |
asm volatile ("ecall"); |
|
1169,18 → 1147,18
} |
|
|
// ------ Lock test ------ |
neorv32_uart_printf("[%i] PMP: Locking pmpcfg0 [mode=off]: ", cnt_test); |
// ------ Lock test - pmpcfg0.0 ------ |
neorv32_uart_printf("[%i] - PMP: pmpcfg0.0 [mode=off] lock test: ", cnt_test); |
cnt_test++; |
exception_handler_answer = 0xFFFFFFFF; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked but entry is deactivated (mode = off) |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked, but entry is deactivated (mode = off) |
|
// make sure a locked cfg cannot be written |
tmp_a = neorv32_cpu_csr_read(CSR_PMPCFG0); |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // try to re-write CFG content |
|
if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPCFG0)) || (exception_handler_answer != 0xFFFFFFFF)) { |
if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPCFG0)) || (neorv32_cpu_csr_read(CSR_MCAUSE) != 0)) { |
test_fail(); |
} |
else { |
1187,6 → 1165,25
test_ok(); |
} |
|
|
// ------ Lock test - pmpaddr0 ------ |
neorv32_uart_printf("[%i] - PMP: pmpaddr0 [mode=off] lock test: ", cnt_test); |
cnt_test++; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b10000001); // locked, but entry is deactivated (mode = off) |
|
// make sure a locked cfg cannot be written |
tmp_a = neorv32_cpu_csr_read(CSR_PMPADDR0); |
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xABABCDCD); // try to re-write ADDR content |
|
if ((tmp_a != neorv32_cpu_csr_read(CSR_PMPADDR0)) || (neorv32_cpu_csr_read(CSR_MCAUSE) != 0)) { |
test_fail(); |
} |
else { |
test_ok(); |
} |
|
} |
else { |
neorv32_uart_printf("not implemented\n"); |
1196,17 → 1193,17
// ---------------------------------------------------------- |
// Final test reports |
// ---------------------------------------------------------- |
neorv32_uart_printf("\n\nExecuted instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); |
neorv32_uart_printf( "Required clock cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE)); |
neorv32_uart_printf("\nExecuted instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); |
neorv32_uart_printf( "Required clock cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE)); |
|
neorv32_uart_printf("\nTest results:\nOK: %i/%i\nFAILED: %i/%i\n\n", cnt_ok, cnt_test, cnt_fail, cnt_test); |
|
// final result |
if (cnt_fail == 0) { |
neorv32_uart_printf("%c[1mTEST OK!%c[0m\n", 27, 27); |
neorv32_uart_printf("%c[1m[TEST OK!]%c[0m\n", 27, 27); |
} |
else { |
neorv32_uart_printf("%c[1mTEST FAILED!%c[0m\n", 27, 27); |
neorv32_uart_printf("%c[1m[TEST FAILED!]%c[0m\n", 27, 27); |
} |
|
return 0; |
1218,8 → 1215,6
**************************************************************************/ |
void global_trap_handler(void) { |
|
exception_handler_answer = neorv32_cpu_csr_read(CSR_MCAUSE); |
|
// hack: always come back in MACHINE MODE |
register uint32_t mask = (1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L); |
asm volatile ("csrrs zero, mstatus, %[input_j]" : : [input_j] "r" (mask)); |
/neorv32/trunk/sw/example/demo_twi/main.c
60,9 → 60,9
|
|
/**********************************************************************//** |
* This program generates a simple dimming sequence for PWM channel 0,1,2. |
* This program provides an interactive console to communicate with TWI devices. |
* |
* @note This program requires the UART and the TWI to be synthesized. |
* @note This program requires the UART and the PWM to be synthesized. |
* |
* @return Irrelevant. |
**************************************************************************/ |
101,8 → 101,8
neorv32_uart_printf("This program allows to create TWI transfers by hand.\n" |
"Type 'help' to see the help menu.\n\n"); |
|
// configure TWI, second slowest clock, no IRQ |
neorv32_twi_setup(CLK_PRSC_2048, 0); |
// configure TWI, second slowest clock, no IRQ, no clock-stretching |
neorv32_twi_setup(CLK_PRSC_2048, 0, 0); |
|
// no active bus session yet |
bus_claimed = 0; |
/neorv32/trunk/sw/example/hex_viewer/main.c
0,0 → 1,271
// ################################################################################################# |
// # << NEORV32 - Hex Viewer - Memory Inspector >> # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
// # # |
// # Redistribution and use in source and binary forms, with or without modification, are # |
// # permitted provided that the following conditions are met: # |
// # # |
// # 1. Redistributions of source code must retain the above copyright notice, this list of # |
// # conditions and the following disclaimer. # |
// # # |
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
// # conditions and the following disclaimer in the documentation and/or other materials # |
// # provided with the distribution. # |
// # # |
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
// # endorse or promote products derived from this software without specific prior written # |
// # permission. # |
// # # |
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
// # OF THE POSSIBILITY OF SUCH DAMAGE. # |
// # ********************************************************************************************* # |
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
// ################################################################################################# |
|
|
/**********************************************************************//** |
* @file hex_viewer/main.c |
* @author Stephan Nolting |
* @brief Interactive memory inspector. |
**************************************************************************/ |
|
#include <neorv32.h> |
#include <string.h> |
|
|
/**********************************************************************//** |
* @name User configuration |
**************************************************************************/ |
/**@{*/ |
/** UART BAUD rate */ |
#define BAUD_RATE 19200 |
/**@}*/ |
|
|
// Prototypes |
void read_memory(void); |
void write_memory(void); |
void dump_memory(void); |
uint32_t hexstr_to_uint(char *buffer, uint8_t length); |
|
|
/**********************************************************************//** |
* This program provides an interactive console to read/write memory. |
* |
* @note This program requires the UART to be synthesized. |
* |
* @return Irrelevant. |
**************************************************************************/ |
int main() { |
|
char buffer[8]; |
int length = 0; |
|
// check if UART unit is implemented at all |
if (neorv32_uart_available() == 0) { |
return 0; |
} |
|
|
// capture all exceptions and give debug info via UART |
neorv32_rte_setup(); |
|
|
// init UART at default baud rate, no rx interrupt, no tx interrupt |
neorv32_uart_setup(BAUD_RATE, 0, 0); |
|
// intro |
neorv32_uart_printf("\n--- Hex Viewer ---\n\n"); |
|
// info |
neorv32_uart_printf("This program allows to read/write/dump memory locations by hand.\n" |
"Type 'help' to see the help menu.\n\n"); |
|
// Main menu |
for (;;) { |
neorv32_uart_printf("HEX_VIEWER:> "); |
length = neorv32_uart_scan(buffer, 8, 1); |
neorv32_uart_printf("\n"); |
|
if (!length) // nothing to be done |
continue; |
|
// decode input and execute command |
if (!strcmp(buffer, "help")) { |
neorv32_uart_printf("Available commands:\n" |
" help - show this text\n" |
" read - read single word from address\n" |
" write - write single word to address\n" |
" dump - dumpe several words from base address\n\n"); |
} |
|
else if (!strcmp(buffer, "read")) { |
read_memory(); |
} |
|
else if (!strcmp(buffer, "write")) { |
write_memory(); |
} |
|
else if (!strcmp(buffer, "dump")) { |
dump_memory(); |
} |
|
else { |
neorv32_uart_printf("Invalid command. Type 'help' to see all commands.\n"); |
} |
} |
|
return 0; |
} |
|
|
/**********************************************************************//** |
* Read word from memory address |
**************************************************************************/ |
void read_memory(void) { |
|
char terminal_buffer[16]; |
|
// enter address |
neorv32_uart_printf("Enter address (8 hex chars): "); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary |
|
// perform read access |
neorv32_uart_printf("\n[0x%x] = ", mem_address); |
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
register uint32_t mem_data = 0; |
|
asm volatile ("lw %[rdata], 0(%[raddr])" : [rdata] "=r" (mem_data) : [raddr] "r" (mem_address)); |
|
// show memory content if there was no exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
neorv32_uart_printf("0x%x", mem_data); |
} |
|
neorv32_uart_printf("\n"); |
} |
|
|
/**********************************************************************//** |
* Write word tp memory address |
**************************************************************************/ |
void write_memory(void) { |
|
char terminal_buffer[16]; |
|
// enter address |
neorv32_uart_printf("Enter address (8 hex chars): "); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary |
|
// enter data |
neorv32_uart_printf("\nEnter data (8 hex chars): "); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
// perform write access |
neorv32_uart_printf("\n[0x%x] = ", mem_address); |
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
asm volatile ("sw %[wdata], 0(%[waddr])" : : [wdata] "r" (mem_data), [waddr] "r" (mem_address)); |
asm volatile ("nop"); |
|
// show memory content if there was no exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
neorv32_uart_printf("0x%x", mem_data); |
} |
|
neorv32_uart_printf("\n"); |
} |
|
|
/**********************************************************************//** |
* Read several words from memory base address |
**************************************************************************/ |
void dump_memory(void) { |
|
char terminal_buffer[16]; |
|
// enter base address |
neorv32_uart_printf("Enter base address (8 hex chars): "); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary |
|
neorv32_uart_printf("\nPress key to start dumping. Press any key to abort.\n"); |
|
neorv32_uart_getc(); // wait for key |
|
// perform read accesses |
register uint32_t mem_data = 0; |
while(neorv32_uart_char_received() == 0) { |
|
neorv32_uart_printf("[0x%x] = ", mem_address); |
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
asm volatile ("lw %[rdata], 0(%[raddr])" : [rdata] "=r" (mem_data) : [raddr] "r" (mem_address)); |
asm volatile ("nop"); |
|
// show memory content if there was no exception |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
neorv32_uart_printf("0x%x\n", mem_data); |
} |
else { |
break; |
} |
|
mem_address = mem_address + 4; |
|
} |
neorv32_uart_char_received_get(); // clear UART rx buffer |
neorv32_uart_printf("\n"); |
} |
|
|
/**********************************************************************//** |
* Helper function to convert N hex chars string into uint32_T |
* |
* @param[in,out] buffer Pointer to array of chars to convert into number. |
* @param[in,out] length Length of the conversion string. |
* @return Converted number. |
**************************************************************************/ |
uint32_t hexstr_to_uint(char *buffer, uint8_t length) { |
|
uint32_t res = 0, d = 0; |
char c = 0; |
|
while (length--) { |
c = *buffer++; |
|
if ((c >= '0') && (c <= '9')) |
d = (uint32_t)(c - '0'); |
else if ((c >= 'a') && (c <= 'f')) |
d = (uint32_t)((c - 'a') + 10); |
else if ((c >= 'A') && (c <= 'F')) |
d = (uint32_t)((c - 'A') + 10); |
else |
d = 0; |
|
res = res + (d << (length*4)); |
} |
|
return res; |
} |
/neorv32/trunk/sw/example/hex_viewer/makefile
0,0 → 1,338
################################################################################################# |
# << NEORV32 - Application Makefile >> # |
# ********************************************************************************************* # |
# Make sure to add the riscv GCC compiler's bin folder to your PATH environment variable. # |
# ********************************************************************************************* # |
# BSD 3-Clause License # |
# # |
# Copyright (c) 2020, Stephan Nolting. All rights reserved. # |
# # |
# Redistribution and use in source and binary forms, with or without modification, are # |
# permitted provided that the following conditions are met: # |
# # |
# 1. Redistributions of source code must retain the above copyright notice, this list of # |
# conditions and the following disclaimer. # |
# # |
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of # |
# conditions and the following disclaimer in the documentation and/or other materials # |
# provided with the distribution. # |
# # |
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to # |
# endorse or promote products derived from this software without specific prior written # |
# permission. # |
# # |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # |
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # |
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # |
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # |
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # |
# OF THE POSSIBILITY OF SUCH DAMAGE. # |
# ********************************************************************************************* # |
# The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # |
################################################################################################# |
|
|
# ***************************************************************************** |
# USER CONFIGURATION |
# ***************************************************************************** |
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here |
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S) |
|
# User's application include folders (don't forget the '-I' before each entry) |
APP_INC ?= -I . |
# User's application include folders - for assembly files only (don't forget the '-I' before each entry) |
ASM_INC ?= -I . |
|
# Optimization |
EFFORT ?= -Os |
|
# Compiler toolchain |
RISCV_TOOLCHAIN ?= riscv32-unknown-elf |
|
# CPU architecture and ABI |
MARCH ?= -march=rv32i |
MABI ?= -mabi=ilp32 |
|
# User flags for additional configuration (will be added to compiler flags) |
USER_FLAGS ?= |
|
# Serial port for executable upload via bootloer |
COM_PORT ?= /dev/ttyUSB0 |
|
# Relative or absolute path to the NEORV32 home folder |
NEORV32_HOME ?= ../../.. |
# ***************************************************************************** |
|
|
|
# ----------------------------------------------------------------------------- |
# NEORV32 framework |
# ----------------------------------------------------------------------------- |
# Path to NEORV32 linker script and startup file |
NEORV32_COM_PATH = $(NEORV32_HOME)/sw/common |
# Path to main NEORV32 library include files |
NEORV32_INC_PATH = $(NEORV32_HOME)/sw/lib/include |
# Path to main NEORV32 library source files |
NEORV32_SRC_PATH = $(NEORV32_HOME)/sw/lib/source |
# Path to NEORV32 executable generator |
NEORV32_EXG_PATH = $(NEORV32_HOME)/sw/image_gen |
# Path to NEORV32 core rtl folder |
NEORV32_RTL_PATH = $(NEORV32_HOME)/rtl/core |
# Marker file to check for NEORV32 home folder |
NEORV32_HOME_MARKER = $(NEORV32_INC_PATH)/neorv32.h |
|
# Core libraries (peripheral and CPU drivers) |
CORE_SRC = $(wildcard $(NEORV32_SRC_PATH)/*.c) |
# Application start-up code |
CORE_SRC += $(NEORV32_COM_PATH)/crt0.S |
|
# Linker script |
LD_SCRIPT = $(NEORV32_COM_PATH)/neorv32.ld |
|
# Main output files |
APP_EXE = neorv32_exe.bin |
APP_ASM = main.asm |
APP_IMG = neorv32_application_image.vhd |
BOOT_IMG = neorv32_bootloader_image.vhd |
|
|
# ----------------------------------------------------------------------------- |
# Sources and objects |
# ----------------------------------------------------------------------------- |
# Define all sources |
SRC = $(APP_SRC) |
SRC += $(CORE_SRC) |
|
# Define all object files |
OBJ = $(SRC:%=%.o) |
|
|
# ----------------------------------------------------------------------------- |
# Tools and flags |
# ----------------------------------------------------------------------------- |
# Compiler tools |
CC = $(RISCV_TOOLCHAIN)-gcc |
OBJDUMP = $(RISCV_TOOLCHAIN)-objdump |
OBJCOPY = $(RISCV_TOOLCHAIN)-objcopy |
SIZE = $(RISCV_TOOLCHAIN)-size |
|
# Host native compiler |
CC_X86 = gcc -Wall -O -g |
|
# NEORV32 executable image generator |
IMAGE_GEN = $(NEORV32_EXG_PATH)/image_gen |
|
# Compiler & linker flags |
CC_OPTS = $(MARCH) $(MABI) $(EFFORT) -Wall -ffunction-sections -fdata-sections -nostartfiles |
CC_OPTS += -Wl,--gc-sections -lm -lc -lgcc -lc |
# This accelerates instruction fetch after branches when C extension is enabled (irrelevant when C extension is disabled) |
CC_OPTS += -falign-functions=4 -falign-labels=4 -falign-loops=4 -falign-jumps=4 |
CC_OPTS += $(USER_FLAGS) |
|
|
# ----------------------------------------------------------------------------- |
# Application output definitions |
# ----------------------------------------------------------------------------- |
.PHONY: check info help elf_info clean clean_all bootloader |
.DEFAULT_GOAL := help |
|
# 'compile' is still here for compatibility |
exe: $(APP_ASM) $(APP_EXE) |
compile: $(APP_ASM) $(APP_EXE) |
install: $(APP_ASM) $(APP_IMG) |
all: $(APP_ASM) $(APP_EXE) $(APP_IMG) |
|
# Check if making bootloader |
# Use different base address and legth for instruction memory/"rom" (BOOTMEM instead of IMEM) |
# Also define "make_bootloader" for crt0.S |
target bootloader: CC_OPTS += -Wl,--defsym=make_bootloader=1 -Dmake_bootloader |
|
|
# ----------------------------------------------------------------------------- |
# Image generator targets |
# ----------------------------------------------------------------------------- |
# install/compile tools |
$(IMAGE_GEN): $(NEORV32_EXG_PATH)/image_gen.cpp |
@echo Compiling $(IMAGE_GEN) |
@$(CC_X86) $< -o $(IMAGE_GEN) |
|
|
# ----------------------------------------------------------------------------- |
# General targets: Assemble, compile, link, dump |
# ----------------------------------------------------------------------------- |
# Compile app *.s sources (assembly) |
%.s.o: %.s |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@ |
|
# Compile app *.S sources (assembly + C pre-processor) |
%.S.o: %.S |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(ASM_INC) $< -o $@ |
|
# Compile app *.c sources |
%.c.o: %.c |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@ |
|
# Compile app *.cpp sources |
%.cpp.o: %.cpp |
@$(CC) -c $(CC_OPTS) -I $(NEORV32_INC_PATH) $(APP_INC) $< -o $@ |
|
# Link object files and show memory utilization |
main.elf: $(OBJ) |
@$(CC) $(CC_OPTS) -T $(LD_SCRIPT) $(OBJ) -o $@ |
@echo "Memory utilization:" |
@$(SIZE) main.elf |
|
# Assembly listing file (for debugging) |
$(APP_ASM): main.elf |
@$(OBJDUMP) -D -S -z $< > $@ |
|
# Generate final executable from .text + .rodata + .data (in THIS order!) |
main.bin: main.elf $(APP_ASM) |
@$(OBJCOPY) -I elf32-little $< -j .text -O binary text.bin |
@$(OBJCOPY) -I elf32-little $< -j .rodata -O binary rodata.bin |
@$(OBJCOPY) -I elf32-little $< -j .data -O binary data.bin |
@cat text.bin rodata.bin data.bin > $@ |
@rm -f text.bin rodata.bin data.bin |
|
|
# ----------------------------------------------------------------------------- |
# Application targets: Generate binary executable, install (as VHDL file) |
# ----------------------------------------------------------------------------- |
# Generate NEORV32 executable image for upload via bootloader |
$(APP_EXE): main.bin $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -app_bin $< $@ $(shell basename $(CURDIR)) |
@echo "Executable ($(APP_EXE)) size in bytes:" |
@wc -c < $(APP_EXE) |
|
# Generate NEORV32 executable VHDL boot image |
$(APP_IMG): main.bin $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -app_img $< $@ $(shell basename $(CURDIR)) |
@echo "Installing application image to $(NEORV32_RTL_PATH)/$(APP_IMG)" |
@cp $(APP_IMG) $(NEORV32_RTL_PATH)/. |
|
|
# ----------------------------------------------------------------------------- |
# Bootloader targets |
# ----------------------------------------------------------------------------- |
# Create and install bootloader VHDL init image |
$(BOOT_IMG): main.bin $(IMAGE_GEN) |
@set -e |
@$(IMAGE_GEN) -bld_img $< $(BOOT_IMG) $(shell basename $(CURDIR)) |
@echo "Installing bootloader image to $(NEORV32_RTL_PATH)/$(BOOT_IMG)" |
@cp $(BOOT_IMG) $(NEORV32_RTL_PATH)/. |
|
# Just an alias that |
bootloader: $(BOOT_IMG) |
|
|
# ----------------------------------------------------------------------------- |
# Check toolchain |
# ----------------------------------------------------------------------------- |
check: $(IMAGE_GEN) |
@echo "---------------- Check: NEORV32_HOME folder ----------------" |
ifneq ($(shell [ -e $(NEORV32_HOME_MARKER) ] && echo 1 || echo 0 ), 1) |
$(error NEORV32_HOME folder not found!) |
endif |
@echo "NEORV32_HOME: $(NEORV32_HOME)" |
@echo "---------------- Check: $(CC) ----------------" |
@$(CC) -v |
@echo "---------------- Check: $(OBJDUMP) ----------------" |
@$(OBJDUMP) -V |
@echo "---------------- Check: $(OBJCOPY) ----------------" |
@$(OBJCOPY) -V |
@echo "---------------- Check: $(SIZE) ----------------" |
@$(SIZE) -V |
@echo "---------------- Check: NEORV32 image_gen ----------------" |
@$(IMAGE_GEN) -help |
@echo "---------------- Check: Native GCC ----------------" |
@$(CC_X86) -v |
@echo |
@echo "Toolchain check OK" |
|
|
# ----------------------------------------------------------------------------- |
# Upload executable via serial port to bootloader |
# ----------------------------------------------------------------------------- |
upload: $(APP_EXE) |
@sh $(NEORV32_EXG_PATH)/uart_upload.sh $(COM_PORT) $(APP_EXE) |
|
|
# ----------------------------------------------------------------------------- |
# Show configuration |
# ----------------------------------------------------------------------------- |
info: |
@echo "---------------- Info: Project ----------------" |
@echo "Project folder: $(shell basename $(CURDIR))" |
@echo "Source files: $(APP_SRC)" |
@echo "Include folder(s): $(APP_INC)" |
@echo "ASM include folder(s): $(ASM_INC)" |
@echo "---------------- Info: NEORV32 ----------------" |
@echo "NEORV32 home folder (NEORV32_HOME): $(NEORV32_HOME)" |
@echo "IMAGE_GEN: $(IMAGE_GEN)" |
@echo "Core source files:" |
@echo "$(CORE_SRC)" |
@echo "Core include folder:" |
@echo "$(NEORV32_INC_PATH)" |
@echo "---------------- Info: Objects ----------------" |
@echo "Project object files:" |
@echo "$(OBJ)" |
@echo "---------------- Info: RISC-V CPU ----------------" |
@echo "MARCH: $(MARCH)" |
@echo "MABI: $(MABI)" |
@echo "---------------- Info: Toolchain ----------------" |
@echo "Toolchain: $(RISCV_TOLLCHAIN)" |
@echo "CC: $(CC)" |
@echo "OBJDUMP: $(OBJDUMP)" |
@echo "OBJCOPY: $(OBJCOPY)" |
@echo "SIZE: $(SIZE)" |
@echo "---------------- Info: Compiler Libraries ----------------" |
@echo "LIBGCC:" |
@$(CC) -print-libgcc-file-name |
@echo "SEARCH-DIRS:" |
@$(CC) -print-search-dirs |
@echo "---------------- Info: Flags ----------------" |
@echo "USER_FLAGS: $(USER_FLAGS)" |
@echo "CC_OPTS: $(CC_OPTS)" |
@echo "---------------- Info: Host Native GCC Flags ----------------" |
@echo "CC_X86: $(CC_X86)" |
|
|
# ----------------------------------------------------------------------------- |
# Show final ELF details (just for debugging) |
# ----------------------------------------------------------------------------- |
elf_info: main.elf |
@$(OBJDUMP) -x main.elf |
|
|
# ----------------------------------------------------------------------------- |
# Help |
# ----------------------------------------------------------------------------- |
help: |
@echo "<<< NEORV32 Application Makefile >>>" |
@echo "Make sure to add the bin folder of RISC-V GCC to your PATH variable." |
@echo "Targets:" |
@echo " help - show this text" |
@echo " check - check toolchain" |
@echo " info - show makefile/toolchain configuration" |
@echo " exe - compile and generate <neorv32_exe.bin> executable for upload via bootloader" |
@echo " install - compile, generate and install VHDL IMEM boot image (for application)" |
@echo " all - compile and generate <neorv32_exe.bin> executable for upload via bootloader and generate and install VHDL IMEM boot image (for application)" |
@echo " clean - clean up project" |
@echo " clean_all - clean up project, core libraries and image generator" |
@echo " bootloader - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)" |
@echo " upload - upload <neorv32_exe.bin> executable via serial port <COM_PORT> to bootloader" |
|
|
# ----------------------------------------------------------------------------- |
# Clean up |
# ----------------------------------------------------------------------------- |
clean: |
@rm -f *.elf *.o *.bin *.out *.asm *.vhd |
|
clean_all: clean |
@rm -f $(OBJ) $(IMAGE_GEN) |
/neorv32/trunk/sw/lib/include/neorv32.h
423,6 → 423,7
TWI_CT_PRSC1 = 5, /**< TWI control register(5) (r/w): Clock prescaler select bit 1 */ |
TWI_CT_PRSC2 = 6, /**< TWI control register(6) (r/w): Clock prescaler select bit 2 */ |
TWI_CT_MACK = 7, /**< TWI control register(7) (r/w): Generate controller ACK for each transmission */ |
TWI_CT_CKSTEN = 8, /**< TWI control register(8) (r/w): Enable clock stretching (by peripheral) */ |
|
TWI_CT_ACK = 30, /**< TWI control register(30) (r/-): ACK received when set */ |
TWI_CT_BUSY = 31 /**< TWI control register(31) (r/-): Transfer in progress, busy flag */ |
/neorv32/trunk/sw/lib/include/neorv32_twi.h
46,7 → 46,7
|
// prototypes |
int neorv32_twi_available(void); |
void neorv32_twi_setup(uint8_t prsc, uint8_t irq_en); |
void neorv32_twi_setup(uint8_t prsc, uint8_t irq_en, uint8_t ckst_en); |
void neorv32_twi_disable(void); |
void neorv32_twi_mack_enable(void); |
int neorv32_twi_busy(void); |
/neorv32/trunk/sw/lib/source/neorv32_cpu.c
246,11 → 246,11
**************************************************************************/ |
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) { |
|
register uint32_t mask = (1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L); |
asm volatile ("csrrc zero, mstatus, %[input_j]" : : [input_j] "r" (mask)); |
// make sure to use NO registers in here! -> naked |
|
// return switching to user mode |
asm volatile ("csrw mepc, ra"); |
asm volatile ("mret"); |
asm volatile ("csrw mepc, ra \n\t" // move return address to mepc so we can return using "mret". also, we can use ra as general purpose register in here |
"li ra, %[input_imm] \n\t" // bit mask to clear the two MPP bits |
"csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode |
"mret \n\t" // return and switch to user mode |
: : [input_imm] "i" ((1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L))); |
} |
|
/neorv32/trunk/sw/lib/source/neorv32_pwm.c
105,6 → 105,10
duty_mask = duty_mask << (channel * 8); |
duty_new = duty_new << (channel * 8); |
|
PWM_DUTY &= ~duty_mask; // clear previous duty cycle |
PWM_DUTY |= duty_new; // set new duty cycle |
uint32_t duty_cycle = PWM_DUTY; |
|
duty_cycle &= ~duty_mask; // clear previous duty cycle |
duty_cycle |= duty_new; // set new duty cycle |
|
PWM_DUTY = duty_cycle; |
} |
/neorv32/trunk/sw/lib/source/neorv32_rte.c
227,7 → 227,7
} |
|
// instruction address |
neorv32_uart_print(" @ "); |
neorv32_uart_print(" @ PC="); |
__neorv32_rte_print_hex_word(neorv32_cpu_csr_read(CSR_MSCRATCH)); // rte core stores actual mepc to mscratch |
|
// additional info |
326,7 → 326,7
|
neorv32_uart_printf("\n- Min granularity: "); |
if (i < 29) { |
neorv32_uart_printf("%u bytes per region (0x%x)\n", (uint32_t)(1 << (i+1+2)), pmp_test_g); |
neorv32_uart_printf("%u bytes per region\n", (uint32_t)(1 << (i+1+2))); |
} |
else { |
neorv32_uart_printf("2^%u bytes per region\n", i+1+2); |
485,8 → 485,8
|
// serial division |
cnt = 0; |
while (tmp >= 10) { |
tmp = tmp - 10; |
while (tmp >= 16) { |
tmp = tmp - 16; |
cnt++; |
} |
|
/neorv32/trunk/sw/lib/source/neorv32_twi.c
66,8 → 66,9
* |
* @param[in] prsc Clock prescaler select (0..7). See #NEORV32_CLOCK_PRSC_enum. |
* @param[in] irq_en Enable transfer-done interrupt when 1. |
* @param[in] ckst_en Enable clock-stretching by peripherals when 1. |
**************************************************************************/ |
void neorv32_twi_setup(uint8_t prsc, uint8_t irq_en) { |
void neorv32_twi_setup(uint8_t prsc, uint8_t irq_en, uint8_t ckst_en) { |
|
TWI_CT = 0; // reset |
|
80,7 → 81,10
uint32_t ct_irq = (uint32_t)(irq_en & 0x01); |
ct_irq = ct_irq << TWI_CT_IRQ_EN; |
|
TWI_CT = ct_enable | ct_prsc | ct_irq; |
uint32_t ct_cksten = (uint32_t)(ckst_en & 0x01); |
ct_cksten = ct_cksten << TWI_CT_CKSTEN; |
|
TWI_CT = ct_enable | ct_prsc | ct_irq | ct_cksten; |
} |
|
|
/neorv32/trunk/sw/lib/source/neorv32_uart.c
118,7 → 118,7
/* Enable the UART for SIM mode. */ |
/* Only use this for simulation! */ |
#ifdef UART_SIM_MODE |
#warning UART_SIM_MODE enabled! Sending all UART.TX to text.io simulation output instead of real UART transmitter. Use this for simulations only! |
#warning UART_SIM_MODE enabled! Sending all UART.TX data to text.io simulation output instead of real UART transmitter. Use this for simulations only! |
uint32_t sim_mode = 1 << UART_CT_SIM_MODE; |
#else |
uint32_t sim_mode = 0; |
/neorv32/trunk/sw/README.md
2,26 → 2,26
|
This folder provides the core of the NEORV32 software framework. This is a short description of the main folders. |
|
### `bootloader` |
### [`bootloader`](https://github.com/stnolting/neorv32/tree/master/sw/bootloader) |
|
Source(s) of the default NEORV32 bootloader. A pre-built image is already installed into the rtl design via the |
`rtl/core/neorv32_bootloader_image.vhd` file. |
|
### `common` |
### [`common`](https://github.com/stnolting/neorv32/tree/master/sw/common) |
|
NEORV32-specific common files for all bootloader and application programs: linker script for executable generation and |
processor start-up code. |
|
### `example` |
### [`example`](https://github.com/stnolting/neorv32/tree/master/sw/example) |
|
Several example programs for testing and for getting started. |
|
### `image_gen` |
### [`image_gen`](https://github.com/stnolting/neorv32/tree/master/sw/image_gen) |
|
This folder contains a simple program that is used to create NEORV32 executables (for upload via bootloader) and VHDL memory |
initializiation files (for memory-persistent applications and for the bootloader). This program is automatically compiled using |
the native GCC when invoking one of the application compilation makefiles. |
|
### `lib` |
### [`lib`](https://github.com/stnolting/neorv32/tree/master/sw/lib) |
|
Core libraries (sources and header files) and helper functions for using the processor peripherals and the CPU itself. |
/neorv32/trunk/CHANGELOG.md
6,8 → 6,8
A list of all releases can be found [here](https://github.com/stnolting/neorv32/releases). The most recent version of the *NEORV32 data sheet* |
can be found [here](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf) (pdf). |
|
The processor can determine its version from the `mimpid` CSR (at CSR address 0xf13). A 2x4-bit decimal-coded representation is used. |
Example: `CSR(mimpid) = 0x01040312 -> 01.04.03.12 -> Version 1.4.3.12 = v1.4.3.12` |
The processor can determine its version from the `mimpid` CSR (at CSR address 0xf13). A 2x4-bit decimal-coded representation is used. Leading |
zeros are optional. Example: `CSR(mimpid) = 0x01040312 -> 01.04.03.12 -> Version 1.4.3.12 = v1.4.3.12 = v01.04.03.12` |
|
For the HDL sources the version number is globally defined by the `hw_version_c` constant in the main VHDL package file |
[`rtl/core/neorv32_package.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_package.vhd). |
14,7 → 14,10
|
| Date (*dd.mm.yyyy*) | Version | Comment | |
|:----------:|:-------:|:--------| |
| 20.10.2020 | 1.4.5.9 | Fixed bug in CPU "sleep" instruction (`WFI` - wait for interrupt) | |
| 24.10.2020 | [**:rocket:1.4.6.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.6.0) | Completely reworked external memory interface (WISHBONE), removed now-obsolete processor generic `MEM_EXT_REG_STAGES`; added processor wrapper with **AXI4-Lite master interface** | |
| 22.10.2020 | 1.4.5.11 | TWI: Added new control register flag to enable/disable SCL clock stretching by peripheral devices | |
| 22.10.2020 | 1.4.5.10 | Added `i_bus_priv_o` and `d_bus_priv_o` signals to CPU_top and `priv_o` to Processor_top to show privilege level of bus access (from `mstatus` MPP); :warning: Fixed bug in external memory interface [WISHBONE] (non-standard Wishbone components were able to corrupt processor-internal ACK/ERR signal logic) | |
| 20.10.2020 | 1.4.5.9 | :warning: Fixed bug in CPU "sleep" instruction (`WFI` - wait for interrupt) | |
| 20.10.2020 | 1.4.5.8 | *Machine timer interrupt* is available as processor input pin (`mtime_irq_i`) if internal `MTIME` is not implemented (`IO_MTIME_USE` = false) | |
| 18.10.2020 | 1.4.5.7 | Added new IO peripheral/Device: Second CFU (CFU1); renamed old CFU to CFU0; CFU VHDL files: `neorv32_cfu0.vhd` & `neorv32_cfu1.vhd`; removed CFU interrupt | |
| 17.10.2020 | 1.4.5.5 | New makefile target `upload` allows to directly upload an executable to the bootloader from the console | |
28,16 → 31,16
| 08.10.2020 | 1.4.4.5 | Removed CPU's `BUS_TIMEOUT` and processor's `MEM_EXT_TIMEOUT` generics; instead, a global configuration `bus_timeout_c` in the VHDL package file is used now | |
| 08.10.2020 | 1.4.4.4 | Removed `DEVNULL` device; all simulation output options from this device are now available as `SIM_MODE` in the `UART`; `mcause` CSR can now also be written; FIXED: trying to write a read-only CSR will cause an illegal instruction exception; for compatibility reasons any write access to the misa CSR will be ignored and will NOT cause an exception | |
| 07.10.2020 | 1.4.4.2 | Simplified ALU's set of core operations; removed co-processor data mux right after ALU -> shorter critical path; CPU control VHDL code clean-up and CSR write logic optimization; optimized IMEM/DMEM access logic; added note regarding alignment of IMEM/DMEM | |
| 05.10.2020 | [**:rocket:1.4.4.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.4.0) | Fixed bug in external memory interface: Executing code from external memory was causing an instruction fetch stall | |
| 05.10.2020 | [**:rocket:1.4.4.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.4.0) | :warning: Fixed bug in external memory interface: Executing code from external memory was causing an instruction fetch stall | |
| 02.10.2020 | 1.4.3.9 | `[m]cycleh` and `[m]instreth` CSRs are now 32-bit wide (-> fully RISC-V-compliant) | |
| 01.10.2020 | 1.4.3.8 | Added CPU top entity wrapper with resolved port signals `rtl/top_templetes/neorv32_cpu_stdlogic.vhd`; optimized ALU core functions – shorter critical path, less control overhead, reduced HW footprint | |
| 27.09.2020 | 1.4.3.3 | Further improved ALU and control logic; CSR access instruction require one additional cycle now (to let side effects kick in); updated synthesis results; added CFU hardware driver dummy | |
| 26.09.2020 | 1.4.3.2 | Fixed bug in `CSRRWI` instruction (introduced with version 1.4.3.1); further ALU operand logic optimizations; updated CPU data path figure | |
| 26.09.2020 | 1.4.3.2 | :warning: Fixed bug in `CSRRWI` instruction (introduced with version 1.4.3.1); further ALU operand logic optimizations; updated CPU data path figure | |
| 25.09.2020 | 1.4.3.1 | Register file's `x0` is now a physical register; this register is initialized by the hardware and locked afterwards; removed "set to zero" stage -> smaller hardware footprint and shorter critical path; added processor top entity wrapper with resolved signals `rtl/top_templetes/neorv32_top_stdlogic.vhd` | |
| 16.09.2020 | [**:rocket:1.4.3.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.3.0) | Simplified memory configuration: removed processor top's memory space configuration generics (`MEM_ISPACE_BASE`, `MEM_ISPACE_SIZE`, `MEM_DSPACE_BASE`, `MEM_DSPACE_SIZE`); data/instruction space sizes are irrelevant for hardware; instruction/data space base addresses are fixed (but can be modified in NEORV32 VHDL package file); modified SYSINFO registers; adapted bootloader, crt0 start-up code and linker script; stack configuration is now done via linker script; reworked chapter "address space"; added CFU interrupt -> fast interrupt channel 1 (shared with GPIO) | |
| 14.09.2020 | 1.4.2.0 | Removed option to disable CSR counters (via `CSR_COUNTERS_USE` generic) since these counters are mandatory according to the RISC-V specs; added new IO/peripheral device: custom functions unit (`CFU`) for tightly-coupled custom co-processors; improved timing of processor-internal clock generator; fixed wrong labels in address space figure and removed dedicated exception vectors box; added mask register to GPIO unit to specify which input pins can trigger a pin-change interrupt | |
| 11.09.2020 | 1.4.0.4 | Reworked `TRNG` architecture and interface; added text regarding fast interrupt channels usage for the NEORV32 processor | |
| 02.09.2020 | 1.4.0.2 | Fixed bugs in external memory interface; added option to define latency of simulated external memory in testbench; hardware configuration sanity checks will now only appear once in console; added more details to data sheet section 3.3. Address Space; fixed typos in MEM_*_BASE and MEM_*_SIZE generic names | |
| 02.09.2020 | 1.4.0.2 | :warning: Fixed bugs in external memory interface; added option to define latency of simulated external memory in testbench; hardware configuration sanity checks will now only appear once in console; added more details to data sheet section 3.3. Address Space; fixed typos in MEM_*_BASE and MEM_*_SIZE generic names | |
| 01.09.2020 | 1.4.0.1 | Using registers above `x15` when the `E` extensions is enabled will now correctly cause an illegal instruction exception | |
| 29.08.2020 | [**:rocket:1.4.0.0**](https://github.com/stnolting/neorv32/releases/tag/v1.4.0.0) | Rearranged and reworked this document; added FreeRTOS port, demo & short referencing chapter; removed booloader-specific linker scripts – main linker script is used for both, applications and bootloader; bootloader can now have `.data` and `.bss` sections; improved IMEM and BOOTROM memory initialization – faster synthesis; image generator now constrains init array size to actual executable size; peripheral/IO devices can only be written in full word mode (= 32-bit); GPIO ports are now 32-bit wide | |
| 23.08.2020 | 1.3.7.3 | Added custom `mzext` CSR to check for available Z* CPU extensions; multiplier's FAST_MUL mode is one cycle faster now; updated performance data | |
46,8 → 49,8
| 06.08.2020 | 1.3.6.5 | Added `FAST_MUL_EN` generic to enable mapping of the multiplier core to DSP blocks; ALU.shifter is no more triggered when executing MULDIV operations; added benchmark results for DSP-based multiplier configurations; updated implementation and performance results; simplified makefiles – using implicit libc definition; crt0 only initializes lowest 16 registers | |
| 03.08.2020 | [**:rocket:1.3.6.0**](https://github.com/stnolting/neorv32/releases/tag/v1.3.6.0) | Relocated `DEVNULL` (changed base address); minor edits, optimization and clean-ups | |
| 30.07.2020 | 1.3.5.2 | Added register stage to PMP mask generation to shorten critical path; removed automatic IRQ enable/disable from RTE install/uninstall functions | |
| 30.07.2020 | 1.3.5.1 | Fixed bug(s) in PMP mask generation; `misa.Z` flag is not yet defined by the RISC-V specs., hence it is read-only and read as zero | |
| 29.07.2020 | 1.3.5.0 | Added user privilege level, enabled via new `CPU_EXTENSION_RISCV_U` generic; fixed error in `mstatus(mpie)` logic; implemented RISC-V spec.-compliant Physical Memory Protection (PMP); allows up to 8 regions but only NAPOT mode is supported yet | |
| 30.07.2020 | 1.3.5.1 | :warning: Fixed bug(s) in PMP mask generation; `misa.Z` flag is not yet defined by the RISC-V specs., hence it is read-only and read as zero | |
| 29.07.2020 | 1.3.5.0 | Added user privilege level, enabled via new `CPU_EXTENSION_RISCV_U` generic; :warning: fixed error in `mstatus(mpie)` logic; implemented RISC-V spec.-compliant Physical Memory Protection (PMP); allows up to 8 regions but only NAPOT mode is supported yet | |
| 25.07.2020 | 1.3.0.0 | `mcause` CSR is read-only now!; removed `CLIC`, added 4 fast IRQ channels to CPU with according flags in `mie` and `mip` and trap IDs; updated core libraries; updated NEORV32 RTE; highly reworked data sheet; updated synthesis and performance results | |
| 21.07.2020 | 1.2.0.6 | Added doc section regarding the CPU's data and instruction interfaces; optimized CPU fetch engine; updated iCE40 synthesis results | |
| 20.07.2020 | 1.2.0.5 | Less penalty for taken branches and jumps (2 cycles faster) | |
56,6 → 59,6
| 10.07.2020 | 1.0.6.0 | Non-taken branches are now 1 cycle faster; the `time[h]` CSR now correctly reflects the system time from the MTIME unit; fixed WFI instruction permanently stalling the CPU; `[m]cycle[h]` counters now stop counting when CPU is in sleep mode; `minstret[h]` and `mcycle[h]` now also allow write-access | |
| 09.07.2020 | 1.0.5.0 | `X` flag of `misa` CSR is zero now; the default SPI flash boot address of the bootloader is now `0x0080000`; new exemplary FPGA utilization results for Intel, Lattice and Xilinx; `misa` CSR is read-only again, switching compressed extension on/off is pretty bad for the fetch engine; `mtval` and `mcause` CSRs now allow write accesses and are finally RISC-V-compliant; time low and high registers of `MTIME` peripheral can now also be written by user; `MTIME` registers only allow full-word write accesses | |
| 06.07.2020 | 1.0.1.0 | Added missing `fence` instruction; added new generic to enable optional Zifencei CPU extension for instruction stream synchronization | |
| 05.07.2020 | 1.0.0.0 | New CPU architecture: Fetch and execute engines; increased CPI; timer and counter CSRs are now all 64-bit wide; fixed CSR access errors; fixed `C.LW` decompression logic; `misa` flags `C` and `M` are now r/w – compressed mode and multiplier/divider support can be switched on/off during runtime; PC(0) is now always zero; fixed bug in multiplier/divider co-processor; renamed SPI signals; added RISC-V compliance check information – processor now passes the official RISC-V compliance tests | |
| 05.07.2020 | 1.0.0.0 | New CPU architecture: Fetch and execute engines; increased CPI; timer and counter CSRs are now all 64-bit wide; :warning: fixed CSR access errors; fixed `C.LW` decompression logic; `misa` flags `C` and `M` are now r/w – compressed mode and multiplier/divider support can be switched on/off during runtime; PC(0) is now always zero; :warning: fixed bug in multiplier/divider co-processor; renamed SPI signals; added RISC-V compliance check information – processor now passes the official RISC-V compliance tests | |
| 25.06.2020 | 0.0.2.5 | Added `DEVNULL` device; added chapter regarding processor simulation; fixed/added links; fixed typos; added FPGA implementation results for iCE40 UP | |
| 23.06.2020 | [**:rocket:0.0.2.3**](https://github.com/stnolting/neorv32/releases/tag/v1.2.0.5) | Publication | |
/neorv32/trunk/README.md
4,9 → 4,6
[![license](https://img.shields.io/github/license/stnolting/neorv32)](https://github.com/stnolting/neorv32/blob/master/LICENSE) |
[![release](https://img.shields.io/github/v/release/stnolting/neorv32)](https://github.com/stnolting/neorv32/releases) |
|
|
## Table of Content |
|
* [Overview](#Overview) |
* [Project Status](#Status) |
* [Features](#Features) |
75,6 → 72,7
* Fully synchronous design, no latches, no gated clocks |
* Small hardware footprint and high operating frequency |
* Highly configurable CPU and processor setup |
* [AXI4-Lite connectivity](#AXI4-Connectivity) - compatible with Xilinx Vivado IP Packer |
* [FreeRTOS port](https://github.com/stnolting/neorv32/blob/master/sw/example/demo_freeRTOS) available |
|
|
102,13 → 100,13
| [RISC-V compliance test](https://github.com/stnolting/neorv32_riscv_compliance) | [![Build Status](https://travis-ci.com/stnolting/neorv32_riscv_compliance.svg?branch=master)](https://travis-ci.com/stnolting/neorv32_riscv_compliance) | | |
|
|
### To-Do / Wish List |
### To-Do / Wish List / [Help Wanted](#Contribute) |
|
* Add a cache for the external memory interface |
* Use LaTeX for data sheet |
* Further size and performance optimization |
* Add AXI(-Lite) bridges |
* Synthesis results (+ wrappers?) for more platforms |
* Maybe port additional RTOSs (like [Zephyr](https://github.com/zephyrproject-rtos/zephyr) or [RIOT](https://www.riot-os.org)) |
* Use LaTeX for data sheet |
* Implement further CPU extensions: |
* Atomic operations (`A`) |
* Bitmanipulation operations (`B`), when they are "official" |
121,7 → 119,7
The full-blown data sheet of the NEORV32 Processor and CPU is available as pdf file: |
[![NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/PDF_32.png) NEORV32 data sheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf). |
|
### Processor Features |
### NEORV32 Processor (SoC) |
|
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_processor.png) |
|
133,9 → 131,10
* Optional machine system timer (**MTIME**), RISC-V-compliant |
* Optional universal asynchronous receiver and transmitter (**UART**) with simulation output option via text.io |
* Optional 8/16/24/32-bit serial peripheral interface controller (**SPI**) with 8 dedicated chip select lines |
* Optional two wire serial interface controller (**TWI**), compatible to the I²C standard |
* Optional two wire serial interface controller (**TWI**), with optional clock-stretching, compatible to the I²C standard |
* Optional general purpose parallel IO port (**GPIO**), 32xOut & 32xIn, with pin-change interrupt |
* Optional 32-bit external bus interface, Wishbone b4 compliant (**WISHBONE**), *standard* or *pipelined* handshake/transactions mode |
* Optional wrapper for **AXI4-Lite Master Interface** (see [AXI Connectivity](#AXI4-Connectivity)), compatibility verified with Xilinx Vivado Block Desginer |
* Optional watchdog timer (**WDT**) |
* Optional PWM controller with 4 channels and 8-bit duty cycle resolution (**PWM**) |
* Optional GARO-based true random number generator (**TRNG**) |
142,7 → 141,7
* Optional custom functions units (**CFU0** and **CFU1**) for tightly-coupled custom co-processors |
* System configuration information memory to check hardware configuration by software (**SYSINFO**) |
|
### CPU Features |
### NEORV32 CPU |
|
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_cpu.png) |
|
272,7 → 271,7
| TWI | Two-wire interface | 74 | 44 | 0 | 0 | |
| UART | Universal asynchronous receiver/transmitter | 175 | 132 | 0 | 0 | |
| WDT | Watchdog timer | 58 | 45 | 0 | 0 | |
| WISHBONE | External memory interface (`MEM_EXT_REG_STAGES` = 2) | 106 | 104 | 0 | 0 | |
| WISHBONE | External memory interface | 106 | 104 | 0 | 0 | |
|
|
### NEORV32 Processor - Exemplary FPGA Setups |
421,6 → 420,7
i_bus_ack_i : in std_ulogic := '0'; -- bus transfer acknowledge |
i_bus_err_i : in std_ulogic := '0'; -- bus transfer error |
i_bus_fence_o : out std_ulogic; -- executed FENCEI operation |
i_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level |
-- data bus interface -- |
d_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address |
d_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data |
432,6 → 432,7
d_bus_ack_i : in std_ulogic := '0'; -- bus transfer acknowledge |
d_bus_err_i : in std_ulogic := '0'; -- bus transfer error |
d_bus_fence_o : out std_ulogic; -- executed FENCE operation |
d_bus_priv_o : out std_ulogic_vector(1 downto 0); -- privilege level |
-- system time input from MTIME -- |
time_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time |
-- interrupts (risc-v compliant) -- |
444,7 → 445,6
end neorv32_cpu; |
``` |
|
|
### NEORV32 Processor |
|
```vhdl |
477,7 → 477,6
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes |
-- External memory interface -- |
MEM_EXT_USE : boolean := false; -- implement external memory bus interface? |
MEM_EXT_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
505,6 → 504,7
wb_ack_i : in std_ulogic := '0'; -- transfer acknowledge |
wb_err_i : in std_ulogic := '0'; -- transfer error |
-- Advanced memory control signals (available if MEM_EXT_USE = true) -- |
priv_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level |
fence_o : out std_ulogic; -- indicates an executed FENCE operation |
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation |
-- GPIO (available if IO_GPIO_USE = true) -- |
519,8 → 519,8
spi_sdi_i : in std_ulogic := '0'; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- TWI (available if IO_TWI_USE = true) -- |
twi_sda_io : inout std_logic := 'H'; -- twi serial data line |
twi_scl_io : inout std_logic := 'H'; -- twi serial clock line |
twi_sda_io : inout std_logic; -- twi serial data line |
twi_scl_io : inout std_logic; -- twi serial clock line |
-- PWM (available if IO_PWM_USE = true) -- |
pwm_o : out std_ulogic_vector(03 downto 0); -- pwm channels |
-- Interrupts -- |
531,8 → 531,27
end neorv32_top; |
``` |
|
### AXI4 Connectivity |
|
Via the [`rtl/top_templates/neorv32_top_axi4lite.vhd`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_top_axi4lite.vhd) |
wrapper the NEORV32 provides an **AXI4-Lite** compatible master interface. This wrapper instantiates the default |
[NEORV32 processor top entitiy](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) and implements a Wishbone to AXI4-Lite bridge. |
|
The AXI4-Lite interface has been tested using Xilinx Vivado 19.2 block designer: |
|
![AXI-SoC](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_axi_soc.png) |
|
The processor was packed as custom IP using `neorv32_top_axi4lite.vhd` as top entity. The AXI interface is automatically detected by the packager. |
All remaining IO interfaces are available as custom signals. The configuration generics are available via the "customize IP" dialog. |
In the figure above the resulting IP block is named "neorv32_top_axi4lite_v1_0". |
*(Note: Use Syntheiss option "global" when generating the block design to maintain the internal TWI tri-state drivers.)* |
|
The setup uses an AXI interconnect to attach two block RAMs to the processor. Since the processor in this example is configured *without* IMEM and DMEM, |
the attached block RAMs are used for storing instructions and data: the first RAM is used as instruction memory |
and is mapped to address `0x00000000 - 0x00003fff` (16kB), the second RAM is used as data memory and is mapped to address `0x80000000 - 0x80001fff` (8kB). |
|
|
|
## Getting Started |
|
This overview is just a short excerpt from the *Let's Get It Started* section of the NEORV32 documentary: |
737,16 → 756,14
|
"Artix" and "Vivado" are trademarks of Xilinx Inc. |
|
"Cyclone", "Quartus Prime", "Quartus Prime Lite" and "Avalon Bus" are trademarks of Intel Corporation. |
"Cyclone", "Quartus Prime Lite" and "Avalon Bus" are trademarks of Intel Corporation. |
|
"Artix" and "Vivado" are trademarks of Xilinx, Inc. |
"iCE40", "UltraPlus" and "Radiant" are trademarks of Lattice Semiconductor Corporation. |
|
"iCE40", "UltraPlus" and "Lattice Radiant" are trademarks of Lattice Semiconductor Corporation. |
"AXI", "AXI4" and "AXI4-Lite" are trademarks of Arm Holdings plc. |
|
"AXI" and "AXI-Lite" are trademarks of Arm Holdings plc. |
|
|
|
## Acknowledgements |
|
[![RISC-V](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/riscv_logo.png)](https://riscv.org/) |