OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /neorv32/trunk
    from Rev 22 to Rev 23
    Reverse comparison

Rev 22 → Rev 23

/docs/figures/neorv32_processor.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/docs/NEORV32.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/rtl/core/neorv32_application_image.vhd
6,7 → 6,7
 
package neorv32_application_image is
 
type application_init_image_t is array (0 to 832) of std_ulogic_vector(31 downto 0);
type application_init_image_t is array (0 to 836) of std_ulogic_vector(31 downto 0);
constant application_init_image : application_init_image_t := (
00000000 => x"00000093",
00000001 => x"00000113",
17,100 → 17,100
00000006 => x"00000393",
00000007 => x"00000413",
00000008 => x"00000493",
00000009 => x"00000693",
00000010 => x"00000713",
00000011 => x"00000793",
00000012 => x"ff402583",
00000013 => x"ffc02603",
00000014 => x"00c58133",
00000015 => x"ffc10113",
00000016 => x"00010413",
00000017 => x"80000197",
00000018 => x"7bc18193",
00000019 => x"00000597",
00000020 => x"08058593",
00000021 => x"30559073",
00000022 => x"f8000593",
00000023 => x"0005a023",
00000024 => x"00458593",
00000025 => x"feb01ce3",
00000026 => x"80000597",
00000027 => x"f9858593",
00000028 => x"84018613",
00000029 => x"00c5d863",
00000030 => x"00058023",
00000031 => x"00158593",
00000032 => x"ff5ff06f",
00000033 => x"00001597",
00000034 => x"c7858593",
00000035 => x"80000617",
00000036 => x"f7460613",
00000037 => x"80000697",
00000038 => x"f6c68693",
00000039 => x"00d65c63",
00000040 => x"00058703",
00000041 => x"00e60023",
00000042 => x"00158593",
00000043 => x"00160613",
00000044 => x"fedff06f",
00000045 => x"00000513",
00000046 => x"00000593",
00000047 => x"05c000ef",
00000048 => x"30047073",
00000049 => x"10500073",
00000050 => x"0000006f",
00000051 => x"ff810113",
00000052 => x"00812023",
00000053 => x"00912223",
00000054 => x"34202473",
00000055 => x"02044663",
00000056 => x"34102473",
00000057 => x"00041483",
00000058 => x"0034f493",
00000059 => x"00240413",
00000060 => x"34141073",
00000061 => x"00300413",
00000062 => x"00941863",
00000063 => x"34102473",
00000064 => x"00240413",
00000065 => x"34141073",
00000066 => x"00012483",
00000067 => x"00412403",
00000068 => x"00810113",
00000069 => x"30200073",
00000070 => x"00005537",
00000071 => x"ff010113",
00000072 => x"00000613",
00000073 => x"00000593",
00000074 => x"b0050513",
00000075 => x"00112623",
00000076 => x"00812423",
00000077 => x"508000ef",
00000078 => x"7ec000ef",
00000079 => x"02050c63",
00000080 => x"3ac000ef",
00000081 => x"00001537",
00000082 => x"a3850513",
00000083 => x"58c000ef",
00000084 => x"00000513",
00000085 => x"7e0000ef",
00000086 => x"00000413",
00000087 => x"0ff47513",
00000088 => x"7d4000ef",
00000089 => x"0c800513",
00000090 => x"77c000ef",
00000091 => x"00140413",
00000092 => x"fedff06f",
00000093 => x"00001537",
00000094 => x"a1450513",
00000095 => x"55c000ef",
00000096 => x"00c12083",
00000097 => x"00812403",
00000098 => x"00000513",
00000099 => x"01010113",
00000100 => x"00008067",
00000101 => x"00000000",
00000102 => x"00000000",
00000009 => x"00000713",
00000010 => x"00000793",
00000011 => x"00002537",
00000012 => x"80050513",
00000013 => x"30051073",
00000014 => x"30401073",
00000015 => x"80002117",
00000016 => x"fc010113",
00000017 => x"ffc17113",
00000018 => x"00010413",
00000019 => x"80000197",
00000020 => x"7b418193",
00000021 => x"00000597",
00000022 => x"08058593",
00000023 => x"30559073",
00000024 => x"f8000593",
00000025 => x"0005a023",
00000026 => x"00458593",
00000027 => x"feb01ce3",
00000028 => x"80000597",
00000029 => x"f9058593",
00000030 => x"84018613",
00000031 => x"00c5d863",
00000032 => x"00058023",
00000033 => x"00158593",
00000034 => x"ff5ff06f",
00000035 => x"00001597",
00000036 => x"c8458593",
00000037 => x"80000617",
00000038 => x"f6c60613",
00000039 => x"80000697",
00000040 => x"f6468693",
00000041 => x"00d65c63",
00000042 => x"00058703",
00000043 => x"00e60023",
00000044 => x"00158593",
00000045 => x"00160613",
00000046 => x"fedff06f",
00000047 => x"00000513",
00000048 => x"00000593",
00000049 => x"05c000ef",
00000050 => x"30047073",
00000051 => x"10500073",
00000052 => x"0000006f",
00000053 => x"ff810113",
00000054 => x"00812023",
00000055 => x"00912223",
00000056 => x"34202473",
00000057 => x"02044663",
00000058 => x"34102473",
00000059 => x"00041483",
00000060 => x"0034f493",
00000061 => x"00240413",
00000062 => x"34141073",
00000063 => x"00300413",
00000064 => x"00941863",
00000065 => x"34102473",
00000066 => x"00240413",
00000067 => x"34141073",
00000068 => x"00012483",
00000069 => x"00412403",
00000070 => x"00810113",
00000071 => x"30200073",
00000072 => x"00005537",
00000073 => x"ff010113",
00000074 => x"00000613",
00000075 => x"00000593",
00000076 => x"b0050513",
00000077 => x"00112623",
00000078 => x"00812423",
00000079 => x"500000ef",
00000080 => x"7e4000ef",
00000081 => x"02050c63",
00000082 => x"3a4000ef",
00000083 => x"00001537",
00000084 => x"a3850513",
00000085 => x"584000ef",
00000086 => x"00000513",
00000087 => x"7d8000ef",
00000088 => x"00000413",
00000089 => x"0ff47513",
00000090 => x"7cc000ef",
00000091 => x"0c800513",
00000092 => x"774000ef",
00000093 => x"00140413",
00000094 => x"fedff06f",
00000095 => x"00001537",
00000096 => x"a1450513",
00000097 => x"554000ef",
00000098 => x"00c12083",
00000099 => x"00812403",
00000100 => x"00000513",
00000101 => x"01010113",
00000102 => x"00008067",
00000103 => x"00000000",
00000104 => x"fc010113",
00000105 => x"02112e23",
232,18 → 232,18
00000221 => x"00f77c63",
00000222 => x"00001537",
00000223 => x"00040593",
00000224 => x"c3c50513",
00000224 => x"c5050513",
00000225 => x"3ac000ef",
00000226 => x"0400006f",
00000227 => x"00001737",
00000228 => x"00279793",
00000229 => x"c6870713",
00000229 => x"c7c70713",
00000230 => x"00e787b3",
00000231 => x"0007a783",
00000232 => x"00078067",
00000233 => x"00001737",
00000234 => x"00241793",
00000235 => x"cac70713",
00000235 => x"cc070713",
00000236 => x"00e787b3",
00000237 => x"0007a783",
00000238 => x"00078067",
261,7 → 261,7
00000250 => x"00812403",
00000251 => x"00c12083",
00000252 => x"00001537",
00000253 => x"c4c50513",
00000253 => x"c6050513",
00000254 => x"01010113",
00000255 => x"3340006f",
00000256 => x"00001537",
301,13 → 301,13
00000290 => x"bec50513",
00000291 => x"f39ff06f",
00000292 => x"00001537",
00000293 => x"c0050513",
00000293 => x"c0450513",
00000294 => x"f2dff06f",
00000295 => x"00001537",
00000296 => x"c1450513",
00000296 => x"c1c50513",
00000297 => x"f21ff06f",
00000298 => x"00001537",
00000299 => x"c2850513",
00000299 => x"c3450513",
00000300 => x"f15ff06f",
00000301 => x"ffe58593",
00000302 => x"f2dff06f",
355,7 → 355,7
00000344 => x"00058523",
00000345 => x"00000993",
00000346 => x"00410913",
00000347 => x"cdca0a13",
00000347 => x"cf0a0a13",
00000348 => x"00a00593",
00000349 => x"00048513",
00000350 => x"438000ef",
495,7 → 495,7
00000484 => x"07300913",
00000485 => x"07500b13",
00000486 => x"07800b93",
00000487 => x"ce848493",
00000487 => x"cfc48493",
00000488 => x"00044c03",
00000489 => x"020c0463",
00000490 => x"134c1263",
775,70 → 775,75
00000764 => x"746e6920",
00000765 => x"75727265",
00000766 => x"30207470",
00000767 => x"00000000",
00000768 => x"74736146",
00000769 => x"746e6920",
00000770 => x"75727265",
00000771 => x"31207470",
00000772 => x"00000000",
00000773 => x"74736146",
00000774 => x"746e6920",
00000775 => x"75727265",
00000776 => x"32207470",
00000777 => x"00000000",
00000778 => x"74736146",
00000779 => x"746e6920",
00000780 => x"75727265",
00000781 => x"33207470",
00000782 => x"00000000",
00000783 => x"6e6b6e55",
00000784 => x"206e776f",
00000785 => x"25783028",
00000786 => x"00002978",
00000787 => x"30204020",
00000788 => x"2c782578",
00000789 => x"56544d20",
00000790 => x"303d4c41",
00000791 => x"20782578",
00000792 => x"54522f3c",
00000793 => x"00003e45",
00000794 => x"00000460",
00000795 => x"00000378",
00000796 => x"00000378",
00000797 => x"00000378",
00000798 => x"0000046c",
00000799 => x"00000378",
00000767 => x"44572820",
00000768 => x"00002954",
00000769 => x"74736146",
00000770 => x"746e6920",
00000771 => x"75727265",
00000772 => x"31207470",
00000773 => x"50472820",
00000774 => x"00294f49",
00000775 => x"74736146",
00000776 => x"746e6920",
00000777 => x"75727265",
00000778 => x"32207470",
00000779 => x"41552820",
00000780 => x"00295452",
00000781 => x"74736146",
00000782 => x"746e6920",
00000783 => x"75727265",
00000784 => x"33207470",
00000785 => x"50532820",
00000786 => x"57542f49",
00000787 => x"00002949",
00000788 => x"6e6b6e55",
00000789 => x"206e776f",
00000790 => x"25783028",
00000791 => x"00002978",
00000792 => x"30204020",
00000793 => x"2c782578",
00000794 => x"56544d20",
00000795 => x"303d4c41",
00000796 => x"20782578",
00000797 => x"54522f3c",
00000798 => x"00003e45",
00000799 => x"00000460",
00000800 => x"00000378",
00000801 => x"00000378",
00000802 => x"00000478",
00000803 => x"00000378",
00000802 => x"00000378",
00000803 => x"0000046c",
00000804 => x"00000378",
00000805 => x"00000378",
00000806 => x"00000378",
00000807 => x"00000484",
00000808 => x"00000490",
00000809 => x"0000049c",
00000810 => x"000004a8",
00000811 => x"000003bc",
00000812 => x"00000400",
00000813 => x"0000040c",
00000814 => x"00000418",
00000815 => x"00000424",
00000816 => x"00000430",
00000817 => x"0000043c",
00000818 => x"00000448",
00000819 => x"00000378",
00000820 => x"00000378",
00000821 => x"00000378",
00000822 => x"00000454",
00000823 => x"33323130",
00000824 => x"37363534",
00000825 => x"00003938",
00000826 => x"33323130",
00000827 => x"37363534",
00000828 => x"62613938",
00000829 => x"66656463",
00000830 => x"00000000",
00000807 => x"00000478",
00000808 => x"00000378",
00000809 => x"00000378",
00000810 => x"00000378",
00000811 => x"00000378",
00000812 => x"00000484",
00000813 => x"00000490",
00000814 => x"0000049c",
00000815 => x"000004a8",
00000816 => x"000003bc",
00000817 => x"00000400",
00000818 => x"0000040c",
00000819 => x"00000418",
00000820 => x"00000424",
00000821 => x"00000430",
00000822 => x"0000043c",
00000823 => x"00000448",
00000824 => x"00000378",
00000825 => x"00000378",
00000826 => x"00000378",
00000827 => x"00000454",
00000828 => x"33323130",
00000829 => x"37363534",
00000830 => x"00003938",
00000831 => x"33323130",
00000832 => x"37363534",
00000833 => x"62613938",
00000834 => x"66656463",
00000835 => x"00000000",
others => x"00000000"
);
 
/rtl/core/neorv32_boot_rom.vhd
41,6 → 41,10
use neorv32.neorv32_bootloader_image.all; -- this file is generated by the image generator
 
entity neorv32_boot_rom is
generic (
BOOTROM_BASE : std_ulogic_vector(31 downto 0) := x"FFFF0000"; -- boot ROM base address
BOOTROM_SIZE : natural := 4*1024 -- processor-internal boot ROM memory size in bytes
);
port (
clk_i : in std_ulogic; -- global clock line
rden_i : in std_ulogic; -- read enable
53,7 → 57,7
architecture neorv32_boot_rom_rtl of neorv32_boot_rom is
 
-- local types --
type boot_img_t is array (0 to boot_size_c/4-1) of std_ulogic_vector(31 downto 0);
type boot_img_t is array (0 to BOOTROM_SIZE/4-1) of std_ulogic_vector(31 downto 0);
 
-- init function --
-- impure function: returns NOT the same result every time it is evaluated with the same arguments since the source file might have changed
71,7 → 75,7
signal acc_en : std_ulogic;
signal rden : std_ulogic;
signal rdata : std_ulogic_vector(31 downto 0);
signal addr : std_ulogic_vector(index_size_f(boot_size_c/4)-1 downto 0);
signal addr : std_ulogic_vector(index_size_f(BOOTROM_SIZE/4)-1 downto 0);
 
-- bootloader image --
constant boot_img : boot_img_t := init_boot_rom(bootloader_init_image);
80,8 → 84,8
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i >= boot_base_c) and (addr_i < std_ulogic_vector(unsigned(boot_base_c) + boot_size_c)) else '0';
addr <= addr_i(index_size_f(boot_size_c/4)+1 downto 2); -- word aligned
acc_en <= '1' when (addr_i >= BOOTROM_BASE) and (addr_i < std_ulogic_vector(unsigned(BOOTROM_BASE) + BOOTROM_SIZE)) else '0';
addr <= addr_i(index_size_f(BOOTROM_SIZE/4)+1 downto 2); -- word aligned
 
 
-- Memory Access --------------------------------------------------------------------------
/rtl/core/neorv32_bootloader_image.vhd
6,7 → 6,7
 
package neorv32_bootloader_image is
 
type bootloader_init_image_t is array (0 to 1019) of std_ulogic_vector(31 downto 0);
type bootloader_init_image_t is array (0 to 1015) of std_ulogic_vector(31 downto 0);
constant bootloader_init_image : bootloader_init_image_t := (
00000000 => x"00000093",
00000001 => x"00000113",
17,237 → 17,237
00000006 => x"00000393",
00000007 => x"00000413",
00000008 => x"00000493",
00000009 => x"00000693",
00000010 => x"00000713",
00000011 => x"00000793",
00000012 => x"ff402583",
00000013 => x"ffc02603",
00000014 => x"00c58133",
00000015 => x"ffc10113",
00000016 => x"00010413",
00000017 => x"80010197",
00000018 => x"7bc18193",
00000019 => x"00000597",
00000020 => x"08058593",
00000021 => x"30559073",
00000022 => x"f8000593",
00000023 => x"0005a023",
00000024 => x"00458593",
00000025 => x"feb01ce3",
00000026 => x"80010597",
00000027 => x"f9858593",
00000028 => x"80418613",
00000029 => x"00c5d863",
00000030 => x"00058023",
00000031 => x"00158593",
00000032 => x"ff5ff06f",
00000033 => x"00001597",
00000034 => x"f6458593",
00000035 => x"80010617",
00000036 => x"f7460613",
00000037 => x"80010697",
00000038 => x"f6c68693",
00000039 => x"00d65c63",
00000040 => x"00058703",
00000041 => x"00e60023",
00000042 => x"00158593",
00000043 => x"00160613",
00000044 => x"fedff06f",
00000045 => x"00000513",
00000046 => x"00000593",
00000047 => x"05c000ef",
00000048 => x"30047073",
00000049 => x"10500073",
00000050 => x"0000006f",
00000051 => x"ff810113",
00000052 => x"00812023",
00000053 => x"00912223",
00000054 => x"34202473",
00000055 => x"02044663",
00000056 => x"34102473",
00000057 => x"00041483",
00000058 => x"0034f493",
00000059 => x"00240413",
00000060 => x"34141073",
00000061 => x"00300413",
00000062 => x"00941863",
00000063 => x"34102473",
00000064 => x"00240413",
00000065 => x"34141073",
00000066 => x"00012483",
00000067 => x"00412403",
00000068 => x"00810113",
00000069 => x"30200073",
00000070 => x"fd010113",
00000071 => x"02812423",
00000072 => x"fe002403",
00000073 => x"026267b7",
00000074 => x"02112623",
00000075 => x"02912223",
00000076 => x"03212023",
00000077 => x"01312e23",
00000078 => x"01412c23",
00000079 => x"01512a23",
00000080 => x"01612823",
00000081 => x"01712623",
00000082 => x"01812423",
00000083 => x"9ff78793",
00000084 => x"00000713",
00000085 => x"00000693",
00000086 => x"00000613",
00000087 => x"00000593",
00000088 => x"00200513",
00000089 => x"0087f463",
00000090 => x"00400513",
00000091 => x"399000ef",
00000092 => x"00005537",
00000093 => x"00000613",
00000094 => x"00000593",
00000095 => x"b0050513",
00000096 => x"281000ef",
00000097 => x"239000ef",
00000098 => x"00245793",
00000099 => x"00a78533",
00000100 => x"00f537b3",
00000101 => x"00b785b3",
00000102 => x"251000ef",
00000103 => x"ffff07b7",
00000104 => x"49478793",
00000105 => x"30579073",
00000106 => x"08000793",
00000107 => x"30479073",
00000108 => x"30046073",
00000109 => x"00100513",
00000110 => x"411000ef",
00000111 => x"ffff1537",
00000112 => x"800007b7",
00000113 => x"f0050513",
00000114 => x"0007a023",
00000115 => x"2e1000ef",
00000116 => x"135000ef",
00000117 => x"ffff1537",
00000118 => x"f3850513",
00000119 => x"2d1000ef",
00000120 => x"fe002503",
00000121 => x"240000ef",
00000122 => x"ffff1537",
00000123 => x"f4050513",
00000124 => x"2bd000ef",
00000125 => x"fe402503",
00000126 => x"22c000ef",
00000127 => x"ffff1537",
00000128 => x"f4c50513",
00000129 => x"2a9000ef",
00000130 => x"30102573",
00000131 => x"218000ef",
00000132 => x"ffff1537",
00000133 => x"f5450513",
00000134 => x"295000ef",
00000135 => x"fe802503",
00000136 => x"ffff14b7",
00000137 => x"00341413",
00000138 => x"1fc000ef",
00000139 => x"ffff1537",
00000140 => x"f5c50513",
00000141 => x"279000ef",
00000142 => x"ff802503",
00000143 => x"ffff1937",
00000144 => x"1e4000ef",
00000145 => x"f6448513",
00000146 => x"265000ef",
00000147 => x"ff002503",
00000148 => x"1d4000ef",
00000149 => x"ffff1537",
00000150 => x"f7050513",
00000151 => x"251000ef",
00000152 => x"ffc02503",
00000153 => x"1c0000ef",
00000154 => x"f6448513",
00000155 => x"241000ef",
00000156 => x"ff402503",
00000157 => x"1b0000ef",
00000158 => x"ffff1537",
00000159 => x"f7850513",
00000160 => x"22d000ef",
00000161 => x"139000ef",
00000162 => x"00a404b3",
00000163 => x"0084b433",
00000164 => x"00b40433",
00000165 => x"fa402783",
00000166 => x"0607d263",
00000167 => x"ffff1537",
00000168 => x"fa450513",
00000169 => x"209000ef",
00000170 => x"ffff1937",
00000171 => x"0d4000ef",
00000172 => x"ffff19b7",
00000173 => x"07200a13",
00000174 => x"06800a93",
00000175 => x"07500b13",
00000176 => x"07300b93",
00000177 => x"ffff14b7",
00000178 => x"ffff1c37",
00000179 => x"fb090513",
00000180 => x"1dd000ef",
00000181 => x"1c9000ef",
00000182 => x"00050413",
00000183 => x"1b1000ef",
00000184 => x"fa098513",
00000185 => x"1c9000ef",
00000186 => x"03441e63",
00000187 => x"30047073",
00000188 => x"ffff02b7",
00000189 => x"00028067",
00000190 => x"0000006f",
00000191 => x"0c1000ef",
00000192 => x"f885eae3",
00000193 => x"00b41463",
00000194 => x"f89566e3",
00000195 => x"00100513",
00000196 => x"430000ef",
00000197 => x"fa090513",
00000198 => x"195000ef",
00000199 => x"070000ef",
00000200 => x"f75ff06f",
00000201 => x"01541663",
00000202 => x"058000ef",
00000203 => x"fa1ff06f",
00000204 => x"00000513",
00000205 => x"01640e63",
00000206 => x"01741663",
00000207 => x"64c000ef",
00000208 => x"f8dff06f",
00000209 => x"06c00793",
00000210 => x"00f41863",
00000211 => x"00100513",
00000212 => x"3f0000ef",
00000213 => x"f79ff06f",
00000214 => x"06500793",
00000215 => x"00f41663",
00000216 => x"02c000ef",
00000217 => x"f69ff06f",
00000218 => x"03f00793",
00000219 => x"fb8c0513",
00000220 => x"00f40463",
00000221 => x"fcc48513",
00000222 => x"135000ef",
00000223 => x"f51ff06f",
00000224 => x"ffff1537",
00000225 => x"dd050513",
00000226 => x"1250006f",
00000227 => x"800007b7",
00000228 => x"0007a783",
00000229 => x"00079863",
00000230 => x"ffff1537",
00000231 => x"e3450513",
00000232 => x"10d0006f",
00000233 => x"ff010113",
00000234 => x"00112623",
00000235 => x"30047073",
00000236 => x"00000793",
00000237 => x"30479073",
00000009 => x"00000713",
00000010 => x"00000793",
00000011 => x"00002537",
00000012 => x"80050513",
00000013 => x"30051073",
00000014 => x"30401073",
00000015 => x"80012117",
00000016 => x"fc010113",
00000017 => x"ffc17113",
00000018 => x"00010413",
00000019 => x"80010197",
00000020 => x"7b418193",
00000021 => x"00000597",
00000022 => x"08058593",
00000023 => x"30559073",
00000024 => x"f8000593",
00000025 => x"0005a023",
00000026 => x"00458593",
00000027 => x"feb01ce3",
00000028 => x"80010597",
00000029 => x"f9058593",
00000030 => x"80418613",
00000031 => x"00c5d863",
00000032 => x"00058023",
00000033 => x"00158593",
00000034 => x"ff5ff06f",
00000035 => x"00001597",
00000036 => x"f5058593",
00000037 => x"80010617",
00000038 => x"f6c60613",
00000039 => x"80010697",
00000040 => x"f6468693",
00000041 => x"00d65c63",
00000042 => x"00058703",
00000043 => x"00e60023",
00000044 => x"00158593",
00000045 => x"00160613",
00000046 => x"fedff06f",
00000047 => x"00000513",
00000048 => x"00000593",
00000049 => x"05c000ef",
00000050 => x"30047073",
00000051 => x"10500073",
00000052 => x"0000006f",
00000053 => x"ff810113",
00000054 => x"00812023",
00000055 => x"00912223",
00000056 => x"34202473",
00000057 => x"02044663",
00000058 => x"34102473",
00000059 => x"00041483",
00000060 => x"0034f493",
00000061 => x"00240413",
00000062 => x"34141073",
00000063 => x"00300413",
00000064 => x"00941863",
00000065 => x"34102473",
00000066 => x"00240413",
00000067 => x"34141073",
00000068 => x"00012483",
00000069 => x"00412403",
00000070 => x"00810113",
00000071 => x"30200073",
00000072 => x"fd010113",
00000073 => x"02812423",
00000074 => x"fe002403",
00000075 => x"026267b7",
00000076 => x"02112623",
00000077 => x"02912223",
00000078 => x"03212023",
00000079 => x"01312e23",
00000080 => x"01412c23",
00000081 => x"01512a23",
00000082 => x"01612823",
00000083 => x"01712623",
00000084 => x"01812423",
00000085 => x"9ff78793",
00000086 => x"00000713",
00000087 => x"00000693",
00000088 => x"00000613",
00000089 => x"00000593",
00000090 => x"00200513",
00000091 => x"0087f463",
00000092 => x"00400513",
00000093 => x"391000ef",
00000094 => x"00005537",
00000095 => x"00000613",
00000096 => x"00000593",
00000097 => x"b0050513",
00000098 => x"279000ef",
00000099 => x"231000ef",
00000100 => x"00245793",
00000101 => x"00a78533",
00000102 => x"00f537b3",
00000103 => x"00b785b3",
00000104 => x"249000ef",
00000105 => x"ffff07b7",
00000106 => x"49478793",
00000107 => x"30579073",
00000108 => x"08000793",
00000109 => x"30479073",
00000110 => x"30046073",
00000111 => x"00100513",
00000112 => x"405000ef",
00000113 => x"ffff1537",
00000114 => x"800007b7",
00000115 => x"ef450513",
00000116 => x"0007a023",
00000117 => x"2d9000ef",
00000118 => x"12d000ef",
00000119 => x"ffff1537",
00000120 => x"f2c50513",
00000121 => x"2c9000ef",
00000122 => x"fe002503",
00000123 => x"238000ef",
00000124 => x"ffff1537",
00000125 => x"f3450513",
00000126 => x"2b5000ef",
00000127 => x"fe402503",
00000128 => x"224000ef",
00000129 => x"ffff1537",
00000130 => x"f4050513",
00000131 => x"2a1000ef",
00000132 => x"30102573",
00000133 => x"210000ef",
00000134 => x"ffff1537",
00000135 => x"f4850513",
00000136 => x"28d000ef",
00000137 => x"fe802503",
00000138 => x"ffff14b7",
00000139 => x"00341413",
00000140 => x"1f4000ef",
00000141 => x"ffff1537",
00000142 => x"f5050513",
00000143 => x"271000ef",
00000144 => x"ff802503",
00000145 => x"ffff1937",
00000146 => x"1dc000ef",
00000147 => x"f5848513",
00000148 => x"25d000ef",
00000149 => x"ff002503",
00000150 => x"1cc000ef",
00000151 => x"ffff1537",
00000152 => x"f6450513",
00000153 => x"249000ef",
00000154 => x"ffc02503",
00000155 => x"1b8000ef",
00000156 => x"f5848513",
00000157 => x"239000ef",
00000158 => x"ff402503",
00000159 => x"1a8000ef",
00000160 => x"ffff1537",
00000161 => x"f6c50513",
00000162 => x"225000ef",
00000163 => x"131000ef",
00000164 => x"00a404b3",
00000165 => x"0084b433",
00000166 => x"00b40433",
00000167 => x"fa402783",
00000168 => x"0607d263",
00000169 => x"ffff1537",
00000170 => x"f9850513",
00000171 => x"201000ef",
00000172 => x"ffff1937",
00000173 => x"0d4000ef",
00000174 => x"ffff19b7",
00000175 => x"07200a13",
00000176 => x"06800a93",
00000177 => x"07500b13",
00000178 => x"07300b93",
00000179 => x"ffff14b7",
00000180 => x"ffff1c37",
00000181 => x"fa490513",
00000182 => x"1d5000ef",
00000183 => x"1c1000ef",
00000184 => x"00050413",
00000185 => x"1a9000ef",
00000186 => x"f9498513",
00000187 => x"1c1000ef",
00000188 => x"03441e63",
00000189 => x"30047073",
00000190 => x"ffff02b7",
00000191 => x"00028067",
00000192 => x"0000006f",
00000193 => x"0b9000ef",
00000194 => x"f885eae3",
00000195 => x"00b41463",
00000196 => x"f89566e3",
00000197 => x"00100513",
00000198 => x"434000ef",
00000199 => x"f9490513",
00000200 => x"18d000ef",
00000201 => x"070000ef",
00000202 => x"f75ff06f",
00000203 => x"01541663",
00000204 => x"058000ef",
00000205 => x"fa1ff06f",
00000206 => x"00000513",
00000207 => x"01640e63",
00000208 => x"01741663",
00000209 => x"644000ef",
00000210 => x"f8dff06f",
00000211 => x"06c00793",
00000212 => x"00f41863",
00000213 => x"00100513",
00000214 => x"3f4000ef",
00000215 => x"f79ff06f",
00000216 => x"06500793",
00000217 => x"00f41663",
00000218 => x"02c000ef",
00000219 => x"f69ff06f",
00000220 => x"03f00793",
00000221 => x"facc0513",
00000222 => x"00f40463",
00000223 => x"fc048513",
00000224 => x"12d000ef",
00000225 => x"f51ff06f",
00000226 => x"ffff1537",
00000227 => x"dcc50513",
00000228 => x"11d0006f",
00000229 => x"800007b7",
00000230 => x"0007a783",
00000231 => x"00079863",
00000232 => x"ffff1537",
00000233 => x"e3050513",
00000234 => x"1050006f",
00000235 => x"ff010113",
00000236 => x"00112623",
00000237 => x"30047073",
00000238 => x"ffff1537",
00000239 => x"e5050513",
00000239 => x"e4c50513",
00000240 => x"0ed000ef",
00000241 => x"fa002783",
00000242 => x"fe07cee3",
262,7 → 262,7
00000251 => x"00812423",
00000252 => x"00050413",
00000253 => x"ffff1537",
00000254 => x"e6050513",
00000254 => x"e5c50513",
00000255 => x"00112623",
00000256 => x"0ad000ef",
00000257 => x"03040513",
270,7 → 270,7
00000259 => x"081000ef",
00000260 => x"30047073",
00000261 => x"00100513",
00000262 => x"1b1000ef",
00000262 => x"1ad000ef",
00000263 => x"10500073",
00000264 => x"0000006f",
00000265 => x"fe010113",
278,7 → 278,7
00000267 => x"00050913",
00000268 => x"ffff1537",
00000269 => x"00912a23",
00000270 => x"e8850513",
00000270 => x"e7c50513",
00000271 => x"ffff14b7",
00000272 => x"00812c23",
00000273 => x"01312623",
285,7 → 285,7
00000274 => x"00112e23",
00000275 => x"01c00413",
00000276 => x"05d000ef",
00000277 => x"fd848493",
00000277 => x"fcc48493",
00000278 => x"ffc00993",
00000279 => x"008957b3",
00000280 => x"00f7f793",
322,219 → 322,219
00000311 => x"34202473",
00000312 => x"800007b7",
00000313 => x"00778793",
00000314 => x"02f40a63",
00000315 => x"ffff1537",
00000316 => x"e7450513",
00000317 => x"7b8000ef",
00000318 => x"00040513",
00000319 => x"f29ff0ef",
00000320 => x"ffff1537",
00000321 => x"e8450513",
00000322 => x"7a4000ef",
00000323 => x"34102573",
00000324 => x"f15ff0ef",
00000325 => x"00500513",
00000326 => x"ed1ff0ef",
00000327 => x"00000513",
00000328 => x"089000ef",
00000329 => x"698000ef",
00000330 => x"fe002783",
00000331 => x"0027d793",
00000332 => x"00a78533",
00000333 => x"00f537b3",
00000334 => x"00b785b3",
00000335 => x"6ac000ef",
00000336 => x"03c12403",
00000337 => x"04c12083",
00000338 => x"04812283",
00000339 => x"04412303",
00000340 => x"04012383",
00000341 => x"03812503",
00000342 => x"03412583",
00000343 => x"03012603",
00000344 => x"02c12683",
00000345 => x"02812703",
00000346 => x"02412783",
00000347 => x"02012803",
00000348 => x"01c12883",
00000349 => x"01812e03",
00000350 => x"01412e83",
00000351 => x"01012f03",
00000352 => x"00c12f83",
00000353 => x"05010113",
00000354 => x"30200073",
00000355 => x"ff010113",
00000356 => x"00000513",
00000357 => x"00112623",
00000358 => x"00812423",
00000359 => x"7b4000ef",
00000360 => x"00500513",
00000361 => x"7f0000ef",
00000362 => x"00000513",
00000363 => x"7e8000ef",
00000364 => x"00050413",
00000314 => x"06f41a63",
00000315 => x"00000513",
00000316 => x"0b9000ef",
00000317 => x"6c8000ef",
00000318 => x"fe002783",
00000319 => x"0027d793",
00000320 => x"00a78533",
00000321 => x"00f537b3",
00000322 => x"00b785b3",
00000323 => x"6dc000ef",
00000324 => x"03c12403",
00000325 => x"04c12083",
00000326 => x"04812283",
00000327 => x"04412303",
00000328 => x"04012383",
00000329 => x"03812503",
00000330 => x"03412583",
00000331 => x"03012603",
00000332 => x"02c12683",
00000333 => x"02812703",
00000334 => x"02412783",
00000335 => x"02012803",
00000336 => x"01c12883",
00000337 => x"01812e03",
00000338 => x"01412e83",
00000339 => x"01012f03",
00000340 => x"00c12f83",
00000341 => x"05010113",
00000342 => x"30200073",
00000343 => x"00700793",
00000344 => x"00100513",
00000345 => x"02f40863",
00000346 => x"ffff1537",
00000347 => x"e6850513",
00000348 => x"73c000ef",
00000349 => x"00040513",
00000350 => x"eadff0ef",
00000351 => x"ffff1537",
00000352 => x"e7850513",
00000353 => x"728000ef",
00000354 => x"34102573",
00000355 => x"e99ff0ef",
00000356 => x"00500513",
00000357 => x"e55ff0ef",
00000358 => x"ff010113",
00000359 => x"00000513",
00000360 => x"00112623",
00000361 => x"00812423",
00000362 => x"7a8000ef",
00000363 => x"00500513",
00000364 => x"7e4000ef",
00000365 => x"00000513",
00000366 => x"7b8000ef",
00000367 => x"00c12083",
00000368 => x"0ff47513",
00000369 => x"00812403",
00000370 => x"01010113",
00000371 => x"00008067",
00000372 => x"ff010113",
00000373 => x"00000513",
00000374 => x"00112623",
00000375 => x"00812423",
00000376 => x"770000ef",
00000377 => x"09e00513",
00000378 => x"7ac000ef",
00000379 => x"00000513",
00000380 => x"7a4000ef",
00000381 => x"00050413",
00000366 => x"7dc000ef",
00000367 => x"00050413",
00000368 => x"00000513",
00000369 => x"7ac000ef",
00000370 => x"00c12083",
00000371 => x"0ff47513",
00000372 => x"00812403",
00000373 => x"01010113",
00000374 => x"00008067",
00000375 => x"ff010113",
00000376 => x"00000513",
00000377 => x"00112623",
00000378 => x"00812423",
00000379 => x"764000ef",
00000380 => x"09e00513",
00000381 => x"7a0000ef",
00000382 => x"00000513",
00000383 => x"774000ef",
00000384 => x"00c12083",
00000385 => x"0ff47513",
00000386 => x"00812403",
00000387 => x"01010113",
00000388 => x"00008067",
00000389 => x"ff010113",
00000390 => x"00000513",
00000391 => x"00112623",
00000392 => x"730000ef",
00000393 => x"00600513",
00000394 => x"76c000ef",
00000395 => x"00c12083",
00000396 => x"00000513",
00000397 => x"01010113",
00000398 => x"7380006f",
00000399 => x"ff010113",
00000400 => x"00812423",
00000401 => x"00050413",
00000402 => x"01055513",
00000403 => x"0ff57513",
00000404 => x"00112623",
00000405 => x"740000ef",
00000406 => x"00845513",
00000407 => x"0ff57513",
00000383 => x"798000ef",
00000384 => x"00050413",
00000385 => x"00000513",
00000386 => x"768000ef",
00000387 => x"00c12083",
00000388 => x"0ff47513",
00000389 => x"00812403",
00000390 => x"01010113",
00000391 => x"00008067",
00000392 => x"ff010113",
00000393 => x"00000513",
00000394 => x"00112623",
00000395 => x"724000ef",
00000396 => x"00600513",
00000397 => x"760000ef",
00000398 => x"00c12083",
00000399 => x"00000513",
00000400 => x"01010113",
00000401 => x"72c0006f",
00000402 => x"ff010113",
00000403 => x"00812423",
00000404 => x"00050413",
00000405 => x"01055513",
00000406 => x"0ff57513",
00000407 => x"00112623",
00000408 => x"734000ef",
00000409 => x"0ff47513",
00000410 => x"00812403",
00000411 => x"00c12083",
00000412 => x"01010113",
00000413 => x"7200006f",
00000414 => x"ff010113",
00000415 => x"00812423",
00000416 => x"00050413",
00000417 => x"00000513",
00000418 => x"00112623",
00000419 => x"6c4000ef",
00000420 => x"00300513",
00000421 => x"700000ef",
00000422 => x"00040513",
00000423 => x"fa1ff0ef",
00000424 => x"00000513",
00000425 => x"6f0000ef",
00000426 => x"00050413",
00000409 => x"00845513",
00000410 => x"0ff57513",
00000411 => x"728000ef",
00000412 => x"0ff47513",
00000413 => x"00812403",
00000414 => x"00c12083",
00000415 => x"01010113",
00000416 => x"7140006f",
00000417 => x"ff010113",
00000418 => x"00812423",
00000419 => x"00050413",
00000420 => x"00000513",
00000421 => x"00112623",
00000422 => x"6b8000ef",
00000423 => x"00300513",
00000424 => x"6f4000ef",
00000425 => x"00040513",
00000426 => x"fa1ff0ef",
00000427 => x"00000513",
00000428 => x"6c0000ef",
00000429 => x"00c12083",
00000430 => x"0ff47513",
00000431 => x"00812403",
00000432 => x"01010113",
00000433 => x"00008067",
00000434 => x"fd010113",
00000435 => x"02812423",
00000436 => x"02912223",
00000437 => x"03212023",
00000438 => x"01312e23",
00000439 => x"01412c23",
00000440 => x"02112623",
00000441 => x"00050913",
00000442 => x"00058993",
00000443 => x"00c10493",
00000444 => x"00000413",
00000445 => x"00400a13",
00000446 => x"02091e63",
00000447 => x"5a0000ef",
00000448 => x"00a481a3",
00000449 => x"00140413",
00000450 => x"fff48493",
00000451 => x"ff4416e3",
00000452 => x"02c12083",
00000453 => x"02812403",
00000454 => x"00c12503",
00000455 => x"02412483",
00000456 => x"02012903",
00000457 => x"01c12983",
00000458 => x"01812a03",
00000459 => x"03010113",
00000460 => x"00008067",
00000461 => x"00898533",
00000462 => x"f41ff0ef",
00000463 => x"fc5ff06f",
00000464 => x"fd010113",
00000465 => x"02812423",
00000466 => x"fe802403",
00000467 => x"02112623",
00000468 => x"02912223",
00000469 => x"03212023",
00000470 => x"01312e23",
00000471 => x"01412c23",
00000472 => x"01512a23",
00000473 => x"01612823",
00000474 => x"01712623",
00000475 => x"00847413",
00000476 => x"00040663",
00000477 => x"00400513",
00000478 => x"c71ff0ef",
00000479 => x"00050493",
00000480 => x"02051863",
00000481 => x"ffff1537",
00000482 => x"e8c50513",
00000483 => x"520000ef",
00000484 => x"008005b7",
00000485 => x"00048513",
00000486 => x"f31ff0ef",
00000487 => x"4788d7b7",
00000488 => x"afe78793",
00000489 => x"02f50463",
00000490 => x"00000513",
00000491 => x"fcdff06f",
00000492 => x"ffff1537",
00000493 => x"eac50513",
00000494 => x"4f4000ef",
00000495 => x"e15ff0ef",
00000496 => x"fc0518e3",
00000497 => x"00300513",
00000498 => x"fb1ff06f",
00000499 => x"00800a37",
00000500 => x"004a0593",
00000501 => x"00048513",
00000502 => x"ef1ff0ef",
00000503 => x"00050913",
00000504 => x"008a0593",
00000505 => x"00048513",
00000506 => x"ee1ff0ef",
00000507 => x"ff802783",
00000508 => x"00050a93",
00000509 => x"00100513",
00000510 => x"f927e0e3",
00000511 => x"ff002b83",
00000512 => x"ffc97b13",
00000513 => x"00000993",
00000514 => x"00ca0a13",
00000515 => x"014985b3",
00000516 => x"053b1863",
00000428 => x"6e4000ef",
00000429 => x"00050413",
00000430 => x"00000513",
00000431 => x"6b4000ef",
00000432 => x"00c12083",
00000433 => x"0ff47513",
00000434 => x"00812403",
00000435 => x"01010113",
00000436 => x"00008067",
00000437 => x"fd010113",
00000438 => x"02812423",
00000439 => x"02912223",
00000440 => x"03212023",
00000441 => x"01312e23",
00000442 => x"01412c23",
00000443 => x"02112623",
00000444 => x"00050913",
00000445 => x"00058993",
00000446 => x"00c10493",
00000447 => x"00000413",
00000448 => x"00400a13",
00000449 => x"02091e63",
00000450 => x"594000ef",
00000451 => x"00a481a3",
00000452 => x"00140413",
00000453 => x"fff48493",
00000454 => x"ff4416e3",
00000455 => x"02c12083",
00000456 => x"02812403",
00000457 => x"00c12503",
00000458 => x"02412483",
00000459 => x"02012903",
00000460 => x"01c12983",
00000461 => x"01812a03",
00000462 => x"03010113",
00000463 => x"00008067",
00000464 => x"00898533",
00000465 => x"f41ff0ef",
00000466 => x"fc5ff06f",
00000467 => x"fd010113",
00000468 => x"02812423",
00000469 => x"fe802403",
00000470 => x"02112623",
00000471 => x"02912223",
00000472 => x"03212023",
00000473 => x"01312e23",
00000474 => x"01412c23",
00000475 => x"01512a23",
00000476 => x"01612823",
00000477 => x"01712623",
00000478 => x"00847413",
00000479 => x"00040663",
00000480 => x"00400513",
00000481 => x"c65ff0ef",
00000482 => x"00050493",
00000483 => x"02051863",
00000484 => x"ffff1537",
00000485 => x"e8050513",
00000486 => x"514000ef",
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"ea050513",
00000497 => x"4e8000ef",
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"f4041ee3",
00000519 => x"f60414e3",
00000520 => x"ffff1537",
00000521 => x"eb850513",
00000521 => x"eac50513",
00000522 => x"484000ef",
00000523 => x"02c12083",
00000524 => x"02812403",
00000525 => x"800007b7",
00000526 => x"0127a023",
00000526 => x"0147a023",
00000527 => x"02412483",
00000528 => x"02012903",
00000529 => x"01c12983",
545,11 → 545,11
00000534 => x"03010113",
00000535 => x"00008067",
00000536 => x"00048513",
00000537 => x"e65ff0ef",
00000538 => x"013b87b3",
00000537 => x"e71ff0ef",
00000538 => x"012b87b3",
00000539 => x"00a40433",
00000540 => x"00a7a023",
00000541 => x"00498993",
00000541 => x"00490913",
00000542 => x"f95ff06f",
00000543 => x"ff010113",
00000544 => x"00112623",
557,18 → 557,18
00000546 => x"00912223",
00000547 => x"00058413",
00000548 => x"00050493",
00000549 => x"d81ff0ef",
00000549 => x"d8dff0ef",
00000550 => x"00000513",
00000551 => x"4b4000ef",
00000552 => x"00200513",
00000553 => x"4f0000ef",
00000554 => x"00048513",
00000555 => x"d91ff0ef",
00000555 => x"d9dff0ef",
00000556 => x"00040513",
00000557 => x"4e0000ef",
00000558 => x"00000513",
00000559 => x"4b4000ef",
00000560 => x"ccdff0ef",
00000560 => x"cd9ff0ef",
00000561 => x"00157513",
00000562 => x"fe051ce3",
00000563 => x"00c12083",
602,16 → 602,16
00000591 => x"00112623",
00000592 => x"00812423",
00000593 => x"00050413",
00000594 => x"ccdff0ef",
00000594 => x"cd9ff0ef",
00000595 => x"00000513",
00000596 => x"400000ef",
00000597 => x"0d800513",
00000598 => x"43c000ef",
00000599 => x"00040513",
00000600 => x"cddff0ef",
00000600 => x"ce9ff0ef",
00000601 => x"00000513",
00000602 => x"408000ef",
00000603 => x"c21ff0ef",
00000603 => x"c2dff0ef",
00000604 => x"00157513",
00000605 => x"fe051ce3",
00000606 => x"00c12083",
630,7 → 630,7
00000619 => x"01512223",
00000620 => x"02041863",
00000621 => x"ffff1537",
00000622 => x"e3450513",
00000622 => x"e3050513",
00000623 => x"01812403",
00000624 => x"01c12083",
00000625 => x"01412483",
641,17 → 641,17
00000630 => x"02010113",
00000631 => x"2d00006f",
00000632 => x"ffff1537",
00000633 => x"ebc50513",
00000633 => x"eb050513",
00000634 => x"2c4000ef",
00000635 => x"00040513",
00000636 => x"a35ff0ef",
00000637 => x"ffff1537",
00000638 => x"ec850513",
00000638 => x"ebc50513",
00000639 => x"2b0000ef",
00000640 => x"00800537",
00000641 => x"a21ff0ef",
00000642 => x"ffff1537",
00000643 => x"ee450513",
00000643 => x"ed850513",
00000644 => x"29c000ef",
00000645 => x"288000ef",
00000646 => x"00050493",
658,12 → 658,12
00000647 => x"270000ef",
00000648 => x"07900793",
00000649 => x"0af49e63",
00000650 => x"ba9ff0ef",
00000650 => x"bb5ff0ef",
00000651 => x"00051663",
00000652 => x"00300513",
00000653 => x"9b5ff0ef",
00000654 => x"ffff1537",
00000655 => x"ef050513",
00000655 => x"ee450513",
00000656 => x"01045493",
00000657 => x"268000ef",
00000658 => x"00148493",
693,7 → 693,7
00000682 => x"412005b3",
00000683 => x"e35ff0ef",
00000684 => x"ffff1537",
00000685 => x"eb850513",
00000685 => x"eac50513",
00000686 => x"f05ff06f",
00000687 => x"00090513",
00000688 => x"e79ff0ef",
884,148 → 884,145
00000873 => x"00008067",
00000874 => x"f8400713",
00000875 => x"00072683",
00000876 => x"00f57793",
00000877 => x"00100513",
00000878 => x"00f51533",
00000879 => x"00d54533",
00000880 => x"00a72023",
00000881 => x"00008067",
00000882 => x"f8a02223",
00000883 => x"00008067",
00000884 => x"69617641",
00000885 => x"6c62616c",
00000886 => x"4d432065",
00000887 => x"0a3a7344",
00000888 => x"203a6820",
00000889 => x"706c6548",
00000890 => x"3a72200a",
00000891 => x"73655220",
00000892 => x"74726174",
00000893 => x"3a75200a",
00000894 => x"6c705520",
00000895 => x"0a64616f",
00000896 => x"203a7320",
00000897 => x"726f7453",
00000898 => x"6f742065",
00000899 => x"616c6620",
00000900 => x"200a6873",
00000901 => x"4c203a6c",
00000902 => x"2064616f",
00000903 => x"6d6f7266",
00000904 => x"616c6620",
00000905 => x"200a6873",
00000906 => x"45203a65",
00000907 => x"75636578",
00000908 => x"00006574",
00000909 => x"65206f4e",
00000910 => x"75636578",
00000911 => x"6c626174",
00000912 => x"76612065",
00000913 => x"616c6961",
00000914 => x"2e656c62",
00000915 => x"00000000",
00000916 => x"746f6f42",
00000917 => x"2e676e69",
00000918 => x"0a0a2e2e",
00000919 => x"00000000",
00000920 => x"6f420a07",
00000921 => x"6f6c746f",
00000922 => x"72656461",
00000923 => x"52524520",
00000924 => x"0000005f",
00000925 => x"58450a0a",
00000926 => x"54504543",
00000927 => x"204e4f49",
00000928 => x"00000028",
00000929 => x"20402029",
00000930 => x"00007830",
00000931 => x"69617741",
00000932 => x"676e6974",
00000933 => x"6f656e20",
00000934 => x"32337672",
00000935 => x"6578655f",
00000936 => x"6e69622e",
00000937 => x"202e2e2e",
00000938 => x"00000000",
00000939 => x"64616f4c",
00000940 => x"2e676e69",
00000941 => x"00202e2e",
00000942 => x"00004b4f",
00000943 => x"74697257",
00000944 => x"78302065",
00000945 => x"00000000",
00000946 => x"74796220",
00000947 => x"74207365",
00000948 => x"5053206f",
00000949 => x"6c662049",
00000950 => x"20687361",
00000951 => x"78302040",
00000876 => x"00100793",
00000877 => x"00a797b3",
00000878 => x"00d7c7b3",
00000879 => x"00f72023",
00000880 => x"00008067",
00000881 => x"f8a02223",
00000882 => x"00008067",
00000883 => x"69617641",
00000884 => x"6c62616c",
00000885 => x"4d432065",
00000886 => x"0a3a7344",
00000887 => x"203a6820",
00000888 => x"706c6548",
00000889 => x"3a72200a",
00000890 => x"73655220",
00000891 => x"74726174",
00000892 => x"3a75200a",
00000893 => x"6c705520",
00000894 => x"0a64616f",
00000895 => x"203a7320",
00000896 => x"726f7453",
00000897 => x"6f742065",
00000898 => x"616c6620",
00000899 => x"200a6873",
00000900 => x"4c203a6c",
00000901 => x"2064616f",
00000902 => x"6d6f7266",
00000903 => x"616c6620",
00000904 => x"200a6873",
00000905 => x"45203a65",
00000906 => x"75636578",
00000907 => x"00006574",
00000908 => x"65206f4e",
00000909 => x"75636578",
00000910 => x"6c626174",
00000911 => x"76612065",
00000912 => x"616c6961",
00000913 => x"2e656c62",
00000914 => x"00000000",
00000915 => x"746f6f42",
00000916 => x"2e676e69",
00000917 => x"0a0a2e2e",
00000918 => x"00000000",
00000919 => x"52450a07",
00000920 => x"5f524f52",
00000921 => x"00000000",
00000922 => x"58450a0a",
00000923 => x"54504543",
00000924 => x"204e4f49",
00000925 => x"00000028",
00000926 => x"20402029",
00000927 => x"00007830",
00000928 => x"69617741",
00000929 => x"676e6974",
00000930 => x"6f656e20",
00000931 => x"32337672",
00000932 => x"6578655f",
00000933 => x"6e69622e",
00000934 => x"202e2e2e",
00000935 => x"00000000",
00000936 => x"64616f4c",
00000937 => x"2e676e69",
00000938 => x"00202e2e",
00000939 => x"00004b4f",
00000940 => x"74697257",
00000941 => x"78302065",
00000942 => x"00000000",
00000943 => x"74796220",
00000944 => x"74207365",
00000945 => x"5053206f",
00000946 => x"6c662049",
00000947 => x"20687361",
00000948 => x"78302040",
00000949 => x"00000000",
00000950 => x"7928203f",
00000951 => x"20296e2f",
00000952 => x"00000000",
00000953 => x"7928203f",
00000954 => x"20296e2f",
00000955 => x"00000000",
00000956 => x"616c460a",
00000957 => x"6e696873",
00000958 => x"2e2e2e67",
00000959 => x"00000020",
00000960 => x"0a0a0a0a",
00000961 => x"4e203c3c",
00000962 => x"56524f45",
00000963 => x"42203233",
00000964 => x"6c746f6f",
00000965 => x"6564616f",
00000966 => x"3e3e2072",
00000967 => x"4c420a0a",
00000968 => x"203a5644",
00000969 => x"20677541",
00000970 => x"32203932",
00000971 => x"0a303230",
00000972 => x"3a565748",
00000973 => x"00002020",
00000974 => x"4b4c430a",
00000975 => x"0020203a",
00000976 => x"0a7a4820",
00000977 => x"52455355",
00000978 => x"0000203a",
00000979 => x"53494d0a",
00000980 => x"00203a41",
00000981 => x"4e4f430a",
00000982 => x"00203a46",
00000983 => x"454d490a",
00000984 => x"00203a4d",
00000985 => x"74796220",
00000986 => x"40207365",
00000987 => x"00000020",
00000988 => x"454d440a",
00000989 => x"00203a4d",
00000990 => x"75410a0a",
00000991 => x"6f626f74",
00000992 => x"6920746f",
00000993 => x"7338206e",
00000994 => x"7250202e",
00000995 => x"20737365",
00000996 => x"2079656b",
00000997 => x"61206f74",
00000998 => x"74726f62",
00000999 => x"00000a2e",
00001000 => x"0000000a",
00001001 => x"726f6241",
00001002 => x"2e646574",
00001003 => x"00000a0a",
00001004 => x"444d430a",
00001005 => x"00203e3a",
00001006 => x"53207962",
00001007 => x"68706574",
00001008 => x"4e206e61",
00001009 => x"69746c6f",
00001010 => x"0000676e",
00001011 => x"61766e49",
00001012 => x"2064696c",
00001013 => x"00444d43",
00001014 => x"33323130",
00001015 => x"37363534",
00001016 => x"42413938",
00001017 => x"46454443",
00000953 => x"616c460a",
00000954 => x"6e696873",
00000955 => x"2e2e2e67",
00000956 => x"00000020",
00000957 => x"0a0a0a0a",
00000958 => x"4e203c3c",
00000959 => x"56524f45",
00000960 => x"42203233",
00000961 => x"6c746f6f",
00000962 => x"6564616f",
00000963 => x"3e3e2072",
00000964 => x"4c420a0a",
00000965 => x"203a5644",
00000966 => x"20706553",
00000967 => x"32203631",
00000968 => x"0a303230",
00000969 => x"3a565748",
00000970 => x"00002020",
00000971 => x"4b4c430a",
00000972 => x"0020203a",
00000973 => x"0a7a4820",
00000974 => x"52455355",
00000975 => x"0000203a",
00000976 => x"53494d0a",
00000977 => x"00203a41",
00000978 => x"4e4f430a",
00000979 => x"00203a46",
00000980 => x"454d490a",
00000981 => x"00203a4d",
00000982 => x"74796220",
00000983 => x"40207365",
00000984 => x"00000020",
00000985 => x"454d440a",
00000986 => x"00203a4d",
00000987 => x"75410a0a",
00000988 => x"6f626f74",
00000989 => x"6920746f",
00000990 => x"7338206e",
00000991 => x"7250202e",
00000992 => x"20737365",
00000993 => x"2079656b",
00000994 => x"61206f74",
00000995 => x"74726f62",
00000996 => x"00000a2e",
00000997 => x"0000000a",
00000998 => x"726f6241",
00000999 => x"2e646574",
00001000 => x"00000a0a",
00001001 => x"444d430a",
00001002 => x"00203e3a",
00001003 => x"53207962",
00001004 => x"68706574",
00001005 => x"4e206e61",
00001006 => x"69746c6f",
00001007 => x"0000676e",
00001008 => x"61766e49",
00001009 => x"2064696c",
00001010 => x"00444d43",
00001011 => x"33323130",
00001012 => x"37363534",
00001013 => x"42413938",
00001014 => x"46454443",
others => x"00000000"
);
 
/rtl/core/neorv32_cfu.vhd
0,0 → 1,204
-- #################################################################################################
-- # << NEORV32 - Custom Function Unit (CFU) >> #
-- # ********************************************************************************************* #
-- # For tightly-coupled custom co-processors. Provides four memory mapped interface registers. #
-- # ********************************************************************************************* #
-- # 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_cfu is
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active, use as async
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0); -- "clock" inputs
-- interrupt --
irq_o : out std_ulogic
-- custom io --
-- ...
);
end neorv32_cfu;
 
architecture neorv32_cfu_rtl of neorv32_cfu is
 
-- IO space: module base address --
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(cfu_size_c); -- low address boundary bit
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
signal addr : std_ulogic_vector(31 downto 0); -- access address
signal wr_en : std_ulogic; -- word write enable
signal rd_en : std_ulogic; -- read enable
 
-- default CFU interface registers --
type cfu_regs_t is array (0 to 3) of std_ulogic_vector(31 downto 0);
signal cfu_reg_in : cfu_regs_t; -- interface registers for WRITE
signal cfu_reg_out : cfu_regs_t; -- interface registers for READ
 
begin
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- These assignments are required to check if the CFU is accessed at all.
-- Do NOT modify this for your custom application (unless you really know what you are doing).
 
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = cfu_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= cfu_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wr_en <= acc_en and wren_i;
rd_en <= acc_en and rden_i;
 
 
-- Clock System ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The top unit implements a clock generator providing 8 "derived clocks"
-- Actually, these signals must not be used as direct clock signals, but as clock enable signals.
 
-- The following clock divider rates are available:
-- clkgen_i(clk_div2_c) -> MAIN_CLK/2
-- clkgen_i(clk_div4_c) -> MAIN_CLK/4
-- clkgen_i(clk_div8_c) -> MAIN_CLK/8
-- clkgen_i(clk_div64_c) -> MAIN_CLK/64
-- clkgen_i(clk_div128_c) -> MAIN_CLK/128
-- clkgen_i(clk_div1024_c) -> MAIN_CLK/1024
-- clkgen_i(clk_div2048_c) -> MAIN_CLK/2048
-- clkgen_i(clk_div4096_c) -> MAIN_CLK/4096
 
-- For instance, if you want to drive a system at MAIN_CLK/8, you can use the following construct:
 
-- if (rstn_i = '0') then -- async and low-active reset
-- ...
-- elsif rising_edge(clk_i) then -- Always use the main clock for all clock processes!
-- if (clkgen_i(clk_div8_c) = '1') then -- the div8 "clock" is actually a clock enable
-- ...
-- end if;
-- end if;
 
-- The clkgen_i input clocks are available when at least one IO/peripheral device requires the clocks generated by the
-- clock generator. The CFU can enable the clock generator via the clkgen_en_o signal.
-- Make sure to deactivate clkgen_en_o if no clocks are required to reduce power consumption.
 
clkgen_en_o <= '0'; -- not used for this minimal example
 
 
-- Read/Write Access ----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Here we are reading/writing from/to the interface registers of the module. Please note that the peripheral/IO
-- modules of the NEORV32 can only be written in full word mode (32-bit). Any other write access (half-word or byte)
-- will trigger a store access fault exception.
--
-- All register of every unit are cleared during the processor boot sequence by the default crt0.S code.
-- Make cfu_reg0_addr_c the CFU's control register. This register is cleared first during booting.
-- If the control register is cleared, no actions should be taken when writing to other CFU registers.
--
-- The CFU provides 4 memory-mapped interface register. For instance, these could be used to provide
-- a <status register> for status information, a <data register< for reading/writing from/to a data FIFO, a <command register>
-- for issueing commands and a <control register> for global control of the unit.
--
rw_access: process(clk_i)
begin
if rising_edge(clk_i) then
-- transfer ack --
ack_o <= wr_en or rd_en;
 
-- write access --
if (wr_en = '1') then
if (addr = cfu_reg0_addr_c) then -- this should be the control register
cfu_reg_in(0) <= data_i; -- for example: control register
end if;
if (addr = cfu_reg1_addr_c) then
cfu_reg_in(1) <= data_i; -- for example: data in/out fifo
end if;
if (addr = cfu_reg2_addr_c) then
cfu_reg_in(2) <= data_i; -- for example: command fifo
end if;
if (addr = cfu_reg3_addr_c) then
cfu_reg_in(3) <= data_i; -- for example: status register
end if;
end if;
 
-- read access --
data_o <= (others => '0'); -- make sure the output is zero if there is no actual read access
if (rd_en = '1') then
if (addr = cfu_reg0_addr_c) then
data_o <= cfu_reg_out(0);
elsif (addr = cfu_reg1_addr_c) then
data_o <= cfu_reg_out(1);
elsif (addr = cfu_reg2_addr_c) then
data_o <= cfu_reg_out(2);
else -- addr = cfu_reg3_addr_c
data_o <= cfu_reg_out(3);
end if;
end if;
end if;
end process rw_access;
 
 
-- CFU Interrupt --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- The CFU provides a single interrupt request signal, which is forwarded to the CPU's fast interrupt channel 1.
-- This channel is shared with the GPIO unit - so both unit can trigger the same interrupt.
--
-- An interrupt request is generated when the irq_o signal is high for one cycle. If the signal is high for more than one cycle
-- more than one interrupt request might be generated.
--
-- There is no interrupt acknowledge signal. If required: The interrupt handler can write to a specific control reister bit within the
-- CFU to acknowledge an interrupt.
 
irq_o <= '0'; -- not used for this minimal example
 
 
-- CFU Core -------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- This is where the actual functionality can be implemented. In this example we are just doing some pointless operations.
 
cfu_reg_out(0) <= cfu_reg_in(0) and cfu_reg_in(1);
cfu_reg_out(1) <= cfu_reg_in(2) and cfu_reg_in(3);
cfu_reg_out(2) <= x"00000001";
cfu_reg_out(3) <= (others => '0');
 
 
end neorv32_cfu_rtl;
/rtl/core/neorv32_cpu.vhd
63,7 → 63,6
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
-- Physical Memory Protection (PMP) --
PMP_USE : boolean := false; -- implement PMP?
149,46 → 148,25
 
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
sanity_check: process(clk_i)
begin
if rising_edge(clk_i) then
-- CSR system --
if (CPU_EXTENSION_RISCV_Zicsr = false) then
assert false report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/machine features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning;
end if;
-- U-extension requires Zicsr extension --
if (CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true) then
assert false report "NEORV32 CPU CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
end if;
-- PMP requires Zicsr extension --
if (CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_USE = true) then
assert false report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
end if;
-- performance counters require Zicsr extension --
if (CPU_EXTENSION_RISCV_Zicsr = false) and (CSR_COUNTERS_USE = true) then
assert false report "NEORV32 CPU CONFIG ERROR! Performance counter CSRs require CPU_EXTENSION_RISCV_Zicsr extension." severity error;
end if;
-- PMP regions --
if (PMP_NUM_REGIONS > pmp_max_r_c) and (PMP_USE = true) then
assert false report "NEORV32 CPU CONFIG ERROR! Number of PMP regions out of valid range." severity error;
end if;
-- PMP granulartiy --
if ((PMP_GRANULARITY < 1) or (PMP_GRANULARITY > 32)) and (PMP_USE = true) then
assert false report "NEORV32 CPU CONFIG ERROR! Invalid PMP granulartiy (0 < G < 33)." severity error;
end if;
-- Bus timeout --
if (BUS_TIMEOUT < 1) then
assert false report "NEORV32 CPU CONFIG ERROR! Invalid bus timeout - must be at least 1 cycle." severity error;
end if;
end if;
end process sanity_check;
-- CSR system --
assert not (CPU_EXTENSION_RISCV_Zicsr = false) report "NEORV32 CPU CONFIG WARNING! No exception/interrupt/machine features available when CPU_EXTENSION_RISCV_Zicsr = false." severity warning;
-- U-extension requires Zicsr extension --
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (CPU_EXTENSION_RISCV_U = true)) report "NEORV32 CPU CONFIG ERROR! User mode requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
-- PMP requires Zicsr extension --
assert not ((CPU_EXTENSION_RISCV_Zicsr = false) and (PMP_USE = true)) report "NEORV32 CPU CONFIG ERROR! Physical memory protection (PMP) requires CPU_EXTENSION_RISCV_Zicsr extension." severity error;
-- PMP regions --
assert not ((PMP_NUM_REGIONS > pmp_max_r_c) and (PMP_USE = true)) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions out of valid range." severity error;
-- PMP granulartiy --
assert not (((PMP_GRANULARITY < 1) or (PMP_GRANULARITY > 32)) and (PMP_USE = true)) report "NEORV32 CPU CONFIG ERROR! Invalid PMP granulartiy (0 < G < 33)." severity error;
-- Bus timeout --
assert not (BUS_TIMEOUT < 1) report "NEORV32 CPU CONFIG ERROR! Invalid bus timeout - must be at least 1 cycle." severity error;
 
 
-- Control Unit ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_control_inst: neorv32_cpu_control
generic map (
-- General --
CSR_COUNTERS_USE => CSR_COUNTERS_USE, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
HW_THREAD_ID => HW_THREAD_ID, -- hardware thread id
CPU_BOOT_ADDR => CPU_BOOT_ADDR, -- cpu boot address
-- RISC-V CPU Extensions --
/rtl/core/neorv32_cpu_alu.vhd
113,6 → 113,9
end record;
signal cp_ctrl : cp_ctrl_t;
 
-- bit manipulation --
signal bitm_res : std_ulogic_vector(31 downto 0);
 
begin
 
-- Operand Mux ----------------------------------------------------------------------------
163,6 → 166,19
add_o <= add_res; -- direct output
 
 
-- Bit Manipulation Unit ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
 
-- ------------------ --
-- UNDER CONSTRUCTION --
-- ------------------ --
 
--bitm_minmax <= rs1_i when ((cmp_less xor ???) = '1') else rs2_i; -- min[u] / max[u]
 
-- result of bit manipulation operation --
bitm_res <= opa and (not opb); -- ANDN
 
 
-- Iterative Shifter Unit -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
shifter_unit: process(rstn_i, clk_i)
177,7 → 193,7
shifter.sreg <= opa; -- shift operand
shifter.cnt <= opb(index_size_f(data_width_c)-1 downto 0); -- shift amount
elsif (shifter.run = '1') then -- running shift
-- coarse shift -> multiples of 4 --
-- coarse shift: multiples of 4 --
if (or_all_f(shifter.cnt(shifter.cnt'left downto 2)) = '1') then -- shift amount >= 4
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 4);
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
188,7 → 204,7
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) &
(shifter.sreg(shifter.sreg'left) and ctrl_i(ctrl_alu_shift_ar_c)) & shifter.sreg(shifter.sreg'left downto 4);
end if;
-- fine shift -> 0..3 --
-- fine shift: single shifts, 0..3 times --
else
shifter.cnt <= std_ulogic_vector(unsigned(shifter.cnt) - 1);
if (ctrl_i(ctrl_alu_shift_dir_c) = '0') then -- SLL: shift left logical
230,7 → 246,7
cp_ctrl.busy <= '0';
cp_ctrl.rb_ff0 <= '1';
end if;
else -- no co-processors implemented
else -- no co-processor(s) implemented
cp_ctrl.cmd_ff <= '0';
cp_ctrl.busy <= '0';
cp_ctrl.rb_ff0 <= '0';
241,8 → 257,8
 
-- is co-processor operation? --
cp_ctrl.start <= '1' when (ctrl_i(ctrl_cp_use_c) = '1') and (cp_ctrl.cmd_ff = '0') else '0';
cp0_start_o <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = cp_sel_muldiv_c) else '0'; -- MULDIV CP
cp1_start_o <= '0'; -- not yet implemented
cp0_start_o <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = cp_sel_muldiv_c) else '0'; -- MULDIV CP
cp1_start_o <= '0'; -- not yet implemented
 
-- co-processor operation running? --
cp_ctrl.halt <= cp_ctrl.busy or cp_ctrl.start;
250,12 → 266,12
 
-- ALU Function Select --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
alu_function_mux: process(ctrl_i, opa, opb, add_res, sub_res, cmp_less, shifter)
alu_function_mux: process(ctrl_i, opa, opb, add_res, sub_res, cmp_less, shifter, bitm_res)
begin
case ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) is
when alu_cmd_bitc_c => alu_res <= opa and (not opb); -- bit clear (for CSR modifications only)
when alu_cmd_bitm_c => alu_res <= bitm_res;
when alu_cmd_xor_c => alu_res <= opa xor opb;
when alu_cmd_or_c => alu_res <= opa or opb;
when alu_cmd_or_c => alu_res <= opa or opb;
when alu_cmd_and_c => alu_res <= opa and opb;
when alu_cmd_sub_c => alu_res <= sub_res;
when alu_cmd_add_c => alu_res <= add_res;
/rtl/core/neorv32_cpu_bus.vhd
324,7 → 324,7
i_arbiter.rd_req <= '0';
end if;
elsif (i_bus_ack_i = '1') then -- wait for normal termination
i_arbiter.rd_req <= '0';
i_arbiter.rd_req <= '0';
end if;
end if;
 
/rtl/core/neorv32_cpu_control.vhd
46,7 → 46,6
entity neorv32_cpu_control is
generic (
-- General --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= x"00000000"; -- hardware thread id
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= x"00000000"; -- cpu boot address
-- RISC-V CPU Extensions --
91,9 → 90,9
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0); -- current system time
-- physical memory protection --
pmp_addr_o : out pmp_addr_if_t; -- addresses
pmp_ctrl_o : out pmp_ctrl_if_t; -- configs
priv_mode_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level
pmp_addr_o : out pmp_addr_if_t; -- addresses
pmp_ctrl_o : out pmp_ctrl_if_t; -- configs
priv_mode_o : out std_ulogic_vector(1 downto 0); -- current CPU privilege level
-- bus access exceptions --
mar_i : in std_ulogic_vector(data_width_c-1 downto 0); -- memory address register
ma_instr_i : in std_ulogic; -- misaligned instruction address
239,7 → 238,6
 
signal mcycle_msb : std_ulogic;
signal minstret_msb : std_ulogic;
signal systime : std_ulogic_vector(63 downto 0);
 
-- illegal instruction check --
signal illegal_instruction : std_ulogic;
255,30 → 253,9
-- Instruction Fetch
-- ****************************************************************************************************************************
 
-- Compressed Instructions Recoding -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_decompressor_inst_true:
if (CPU_EXTENSION_RISCV_C = true) generate
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
port map (
-- instruction input --
ci_instr16_i => fetch_engine.ci_input, -- compressed instruction input
-- instruction output --
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
);
end generate;
 
neorv32_cpu_decompressor_inst_false:
if (CPU_EXTENSION_RISCV_C = false) generate
ci_instr32 <= (others => '0');
ci_illegal <= '0';
end generate;
 
 
-- Fetch Engine FSM Sync ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- for registers that require a specific reset state --
-- registers that require a specific reset state --
fetch_engine_fsm_sync_rst: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
293,7 → 270,7
end process fetch_engine_fsm_sync_rst;
 
 
-- for registers that DO NOT require a specific reset state --
-- registers that DO NOT require a specific reset state --
fetch_engine_fsm_sync: process(clk_i)
begin
if rising_edge(clk_i) then
404,6 → 381,27
end process fetch_engine_fsm_comb;
 
 
-- Compressed Instructions Recoding -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cpu_decompressor_inst_true:
if (CPU_EXTENSION_RISCV_C = true) generate
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
port map (
-- instruction input --
ci_instr16_i => fetch_engine.ci_input, -- compressed instruction input
-- instruction output --
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction
);
end generate;
 
neorv32_cpu_decompressor_inst_false:
if (CPU_EXTENSION_RISCV_C = false) generate
ci_instr32 <= (others => '0');
ci_illegal <= '0';
end generate;
 
 
-- ****************************************************************************************************************************
-- Instruction Prefetch Buffer
-- ****************************************************************************************************************************
527,7 → 525,7
execute_engine.last_pc <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
execute_engine.state <= SYS_WAIT;
execute_engine.sleep <= '0';
execute_engine.if_rst <= '1'; -- IF is reset after system reset
execute_engine.if_rst <= '1'; -- instruction fetch is reset after system reset
elsif rising_edge(clk_i) then
execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
if (execute_engine.state = EXECUTE) then
622,11 → 620,11
else -- branches
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU)
end if;
ctrl_nxt(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
ctrl_nxt(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- is arithmetic shift
ctrl_nxt(ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
ctrl_nxt(ctrl_bus_size_msb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
ctrl_nxt(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
ctrl_nxt(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- is arithmetic shift
ctrl_nxt(ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
ctrl_nxt(ctrl_bus_size_msb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
ctrl_nxt(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- only CP0 (MULDIV) implemented yet
 
712,7 → 710,7
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
-- multi cycle alu operation? --
if (alu_operation_v = alu_cmd_shift_c) or -- shift operation?
((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
(execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV?
execute_engine.state_nxt <= ALU_WAIT;
else
720,7 → 718,7
execute_engine.state_nxt <= DISPATCH;
end if;
-- cp access? --
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
(execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV?
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
end if;
728,7 → 726,7
when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0 (only relevant for LUI)
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_auipc_c(5)) then -- AUIPC
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
else -- LUI
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
758,7 → 756,7
when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
-- ------------------------------------------------------------
-- compute target address --
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) then -- JAL
if (execute_engine.i_reg(instr_opcode_lsb_c+3) = opcode_jal_c(3)) then -- JAL
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
else -- JALR
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
773,13 → 771,13
 
when opcode_fence_c => -- fence operations
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
fetch_engine.reset <= '1';
execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
execute_engine.pc_nxt <= execute_engine.next_pc; -- "refetch" next instruction (only relevant for fence.i)
ctrl_nxt(ctrl_bus_fencei_c) <= '1';
end if;
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then -- FENCE
ctrl_nxt(ctrl_bus_fence_c) <= '1';
end if;
execute_engine.state_nxt <= SYS_WAIT;
820,7 → 818,8
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- default
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '0'; -- default
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- default
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- default ALU operation = OR
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- default ALU operation = OR
-- ctrl_nxt(ctrl_alu_bmop2_c downto ctrl_alu_bmop0_c) <= alu_bm_andn_c; -- bit manipulation operation = ANDN
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
-- register operations --
when funct3_csrrw_c => -- CSRRW
837,7 → 836,7
when funct3_csrrc_c => -- CSRRC
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = rs1
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitm_c; -- actual ALU operation = bit manipulation (ANDN)
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
-- immediate operations --
when funct3_csrrwi_c => -- CSRRWI
854,7 → 853,7
when funct3_csrrci_c => -- CSRRCI
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitm_c; -- actual ALU operation = bit manipulation (ANDN)
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if UIMM5 is not zero (bits from rs1 filed) and if valid access
when others => -- undefined
NULL;
910,7 → 909,7
if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
execute_engine.state_nxt <= SYS_WAIT;
elsif (bus_d_wait_i = '0') then -- wait here for bus to finish transaction
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD?
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then -- LOAD
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
end if;
execute_engine.state_nxt <= DISPATCH;
941,7 → 940,6
end if;
 
-- check CSR access --
csr_acc_valid <= '0'; -- default
case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
when x"300" => csr_acc_valid <= is_m_mode_v; -- mstatus
when x"301" => csr_acc_valid <= is_m_mode_v; -- misa
953,29 → 951,29
when x"343" => csr_acc_valid <= is_m_mode_v; -- mtval
when x"344" => csr_acc_valid <= is_m_mode_v; -- mip
--
when x"3a0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpacfg0
when x"3a1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpacfg1
when x"3a0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpacfg0
when x"3a1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpacfg1
--
when x"3b0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpaddr0
when x"3b1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- pmpaddr1
when x"3b2" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- pmpaddr2
when x"3b3" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- pmpaddr3
when x"3b4" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpaddr4
when x"3b5" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- pmpaddr5
when x"3b6" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- pmpaddr6
when x"3b7" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- pmpaddr7
when x"3b0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpaddr0
when x"3b1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- pmpaddr1
when x"3b2" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- pmpaddr2
when x"3b3" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- pmpaddr3
when x"3b4" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpaddr4
when x"3b5" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- pmpaddr5
when x"3b6" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- pmpaddr6
when x"3b7" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- pmpaddr7
--
when x"c00" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- cycle
when x"c01" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- time
when x"c02" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- instret
when x"c80" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- cycleh
when x"c81" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- timeh
when x"c82" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- instreth
when x"c00" => csr_acc_valid <= '1'; -- cycle
when x"c01" => csr_acc_valid <= '1'; -- time
when x"c02" => csr_acc_valid <= '1'; -- instret
when x"c80" => csr_acc_valid <= '1'; -- cycleh
when x"c81" => csr_acc_valid <= '1'; -- timeh
when x"c82" => csr_acc_valid <= '1'; -- instreth
--
when x"b00" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- mcycle
when x"b02" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- minstret
when x"b80" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- mcycleh
when x"b82" => csr_acc_valid <= bool_to_ulogic_f(CSR_COUNTERS_USE) and is_m_mode_v; -- minstreth
when x"b00" => csr_acc_valid <= is_m_mode_v; -- mcycle
when x"b02" => csr_acc_valid <= is_m_mode_v; -- minstret
when x"b80" => csr_acc_valid <= is_m_mode_v; -- mcycleh
when x"b82" => csr_acc_valid <= is_m_mode_v; -- minstreth
--
when x"f11" => csr_acc_valid <= is_m_mode_v; -- mvendorid
when x"f12" => csr_acc_valid <= is_m_mode_v; -- marchid
984,7 → 982,7
--
when x"fc0" => csr_acc_valid <= is_m_mode_v; -- mzext (custom CSR)
--
when others => csr_acc_valid <= '0'; -- undefined
when others => csr_acc_valid <= '0'; -- undefined, invalid access
end case;
end process invalid_csr_access_check;
 
1000,13 → 998,6
illegal_instruction <= '0';
illegal_register <= '0';
 
-- check if using reg >= 16 for E-CPUs --
--if (CPU_EXTENSION_RISCV_E = true) then
-- illegal_register <= ????? FIXME
--else
-- illegal_register <= '0';
--end if;
 
-- check instructions --
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
 
1013,6 → 1004,10
-- OPCODE check sufficient: LUI, UIPC, JAL --
when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
illegal_instruction <= '0';
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
illegal_register <= '1';
end if;
 
when opcode_alui_c => -- check ALUI funct7
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
1024,6 → 1019,10
else
illegal_instruction <= '0';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
illegal_register <= '1';
end if;
when opcode_load_c => -- check LOAD funct3
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
1035,6 → 1034,10
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
illegal_register <= '1';
end if;
when opcode_store_c => -- check STORE funct3
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
1044,6 → 1047,10
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
illegal_register <= '1';
end if;
 
when opcode_branch_c => -- check BRANCH funct3
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
1056,6 → 1063,10
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
illegal_register <= '1';
end if;
 
when opcode_jalr_c => -- check JALR funct3
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
1063,6 → 1074,10
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
illegal_register <= '1';
end if;
 
when opcode_alu_c => -- check ALU funct3 & funct7
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
1077,6 → 1092,11
else
illegal_instruction <= '0';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) and
((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
illegal_register <= '1';
end if;
 
when opcode_fence_c => -- fence instructions --
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
1101,6 → 1121,14
else
illegal_instruction <= '1';
end if;
-- illegal E-CPU register? --
if (CPU_EXTENSION_RISCV_E = true) then
if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
else -- reg-imm CSR
illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
end if;
end if;
 
-- ecall, ebreak, mret, wfi --
elsif (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and
1181,6 → 1209,7
trap_ctrl.exc_ack <= '1'; -- clear execption
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handler
-- assert false report "NEORV32.CPU TRAP: mcause=" & integer'image(to_integer(unsigned(trap_ctrl.cause_nxt))) severity note; -- for debugging
end if;
else -- trap waiting to get started
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
1641,22 → 1670,22
when x"c00" | x"b00" => -- R/(W): cycle/mcycle: Cycle counter LOW
csr_rdata_o <= csr.mcycle(31 downto 0);
when x"c01" => -- R/-: time: System time LOW (from MTIME unit)
csr_rdata_o <= systime(31 downto 0);
csr_rdata_o <= time_i(31 downto 0);
when x"c02" | x"b02" => -- R/(W): instret/minstret: Instructions-retired counter LOW
csr_rdata_o <= csr.minstret(31 downto 0);
when x"c80" | x"b80" => -- R/(W): cycleh/mcycleh: Cycle counter HIGH
csr_rdata_o <= x"000" & csr.mcycleh(19 downto 0); -- only the lowest 20 bit!
when x"c81" => -- R/-: timeh: System time HIGH (from MTIME unit)
csr_rdata_o <= systime(63 downto 32);
csr_rdata_o <= time_i(63 downto 32);
when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
csr_rdata_o <= x"000" & csr.minstreth(19 downto 0); -- only the lowest 20 bit!
 
-- machine information registers --
when x"f11" => -- R/-: mvendorid
csr_rdata_o <= (others => '0'); -- not available for NEORV32
csr_rdata_o <= (others => '0'); -- not assigned
when x"f12" => -- R/-: marchid
csr_rdata_o <= (others => '0'); -- not available for NEORV32
when x"f13" => -- R/-: mimpid - implementation ID / NEORV32: version
csr_rdata_o <= (others => '0'); -- not assigned
when x"f13" => -- R/-: mimpid - implementation ID / NEORV32 version
csr_rdata_o <= hw_version_c;
when x"f14" => -- R/-: mhartid - hardware thread ID
csr_rdata_o <= HW_THREAD_ID;
1665,7 → 1694,6
when x"fc0" => -- R/-: mzext
csr_rdata_o(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr CPU extension
csr_rdata_o(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei CPU extension
csr_rdata_o(2) <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- std (performance) counters enabled
 
-- undefined/unavailable --
when others =>
1678,9 → 1706,6
end if;
end process csr_read_access;
 
-- time[h] CSR --
systime <= time_i when (CSR_COUNTERS_USE = true) else (others => '0');
 
-- CPU's current privilege level --
priv_mode_o <= csr.privilege;
 
1710,47 → 1735,37
mcycle_msb <= '0';
minstret_msb <= '0';
elsif rising_edge(clk_i) then
if (CSR_COUNTERS_USE = true) then
 
-- mcycle (cycle) --
mcycle_msb <= csr.mcycle(csr.mcycle'left);
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b00") then -- write access
csr.mcycle(31 downto 0) <= csr_wdata_i;
csr.mcycle(32) <= '0';
elsif (execute_engine.sleep = '0') then -- automatic update
csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
end if;
-- mcycle (cycle) --
mcycle_msb <= csr.mcycle(csr.mcycle'left);
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b00") then -- write access
csr.mcycle(31 downto 0) <= csr_wdata_i;
csr.mcycle(32) <= '0';
elsif (execute_engine.sleep = '0') then -- automatic update (if CPU is not in sleep mode)
csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
end if;
 
-- mcycleh (cycleh) --
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b80") then -- write access
csr.mcycleh <= csr_wdata_i(19 downto 0);
elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
end if;
-- mcycleh (cycleh) --
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b80") then -- write access
csr.mcycleh <= csr_wdata_i(csr.mcycleh'left downto 0);
elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
end if;
 
-- minstret (instret) --
minstret_msb <= csr.minstret(csr.minstret'left);
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
csr.minstret(31 downto 0) <= csr_wdata_i;
csr.minstret(32) <= '0';
elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
end if;
-- minstret (instret) --
minstret_msb <= csr.minstret(csr.minstret'left);
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
csr.minstret(31 downto 0) <= csr_wdata_i;
csr.minstret(32) <= '0';
elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
end if;
 
-- minstreth (instreth) --
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access
csr.minstreth <= csr_wdata_i(19 downto 0);
elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
end if;
 
else -- if not implemented
csr.mcycle <= (others => '0');
csr.minstret <= (others => '0');
csr.mcycleh <= (others => '0');
csr.minstreth <= (others => '0');
mcycle_msb <= '0';
minstret_msb <= '0';
-- minstreth (instreth) --
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access
csr.minstreth <= csr_wdata_i(csr.minstreth'left downto 0);
elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
end if;
end if;
end process csr_counters;
/rtl/core/neorv32_gpio.vhd
70,8 → 70,9
signal addr : std_ulogic_vector(31 downto 0); -- access address
 
-- accessible regs --
signal din : std_ulogic_vector(31 downto 0); -- r/w
signal dout : std_ulogic_vector(31 downto 0); -- r/w
signal din : std_ulogic_vector(31 downto 0); -- r/-
signal dout : std_ulogic_vector(31 downto 0); -- r/w
signal irq_en : std_ulogic_vector(31 downto 0); -- -/w, uses the same address as data_in
 
-- misc --
signal in_buf : std_ulogic_vector(31 downto 0);
92,8 → 93,10
ack_o <= acc_en and (rden_i or wren_i);
-- write access --
if ((acc_en and wren_i) = '1') then
if (addr = gpio_out_addr_c) then
dout <= data_i;
if (addr = gpio_in_addr_c) then
irq_en <= data_i; -- pin change IRQ enable
else -- gpio_out_addr_c
dout <= data_i; -- data output port
end if;
end if;
-- read access --
100,9 → 103,9
data_o <= (others => '0');
if ((acc_en and rden_i) = '1') then
if (addr = gpio_in_addr_c) then
data_o <= din;
data_o <= din; -- data input port
else -- gpio_out_addr_c
data_o <= dout;
data_o <= dout; -- data output port
end if;
end if;
end if;
121,7 → 124,7
in_buf <= gpio_i;
din <= in_buf;
-- IRQ --
irq_o <= or_all_f(in_buf xor din); -- any transition triggers an interrupt
irq_o <= or_all_f((in_buf xor din) and irq_en); -- any enabled pin transition triggers an interrupt
end if;
end process irq_detector;
 
/rtl/core/neorv32_package.vhd
38,11 → 38,11
 
package neorv32_package is
 
-- Architecture Constants -----------------------------------------------------------------
-- Architecture Constants/Configuration ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - FIXED!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040000"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040300"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED!
constant ipb_entries_c : natural := 2; -- entries in instruction prefetch buffer, must be a power of 2, default=2
 
-- Helper Functions -----------------------------------------------------------------------
62,16 → 62,26
type pmp_ctrl_if_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(7 downto 0);
type pmp_addr_if_t is array (0 to pmp_max_r_c-1) of std_ulogic_vector(33 downto 0);
 
-- Processor-internal Address Space Layout ------------------------------------------------
-- General Address Space Layout -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Instruction Memory & Data Memory --
-- => configured via top's generics
constant ispace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"00000000"; -- instruction memory space base address
constant dspace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"80000000"; -- data memory space base address
 
-- Bootloader ROM --
constant boot_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFF0000"; -- bootloader base address, fixed!
constant boot_size_c : natural := 4*1024; -- bytes
constant boot_max_size_c : natural := 32*1024; -- bytes, fixed!
-- Processor-Internal Address Space Layout ------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- Internal Instruction Memory (IMEM) --
constant imem_base_c : std_ulogic_vector(data_width_c-1 downto 0) := ispace_base_c; -- internal instruction memory base address
--> size is configured via top's generic
 
-- Internal Data Memory (DMEM) --
constant dmem_base_c : std_ulogic_vector(data_width_c-1 downto 0) := dspace_base_c; -- internal data memory base address
--> size is configured via top's generic
 
-- Internal Bootloader ROM --
constant boot_rom_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFF0000"; -- bootloader base address, fixed!
constant boot_rom_size_c : natural := 4*1024; -- bytes
constant boot_rom_max_size_c : natural := 32*1024; -- bytes, fixed!
 
-- IO: Peripheral Devices ("IO") Area --
-- Control register(s) (including the device-enable) should be located at the base address of each device
constant io_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF80";
79,65 → 89,72
 
-- General Purpose Input/Output Unit (GPIO) --
constant gpio_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF80"; -- base address, fixed!
constant gpio_size_c : natural := 2*4; -- bytes, fixed!
constant gpio_in_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(gpio_base_c) + x"00000000");
constant gpio_out_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(gpio_base_c) + x"00000004");
constant gpio_size_c : natural := 2*4; -- bytes
constant gpio_in_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF80";
constant gpio_out_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF84";
 
-- Dummy Device (with SIMULATION output) (DEVNULL) --
constant devnull_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; -- base address, fixed!
constant devnull_size_c : natural := 1*4; -- bytes, fixed!
constant devnull_data_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(devnull_base_c) + x"00000000");
constant devnull_size_c : natural := 1*4; -- bytes
constant devnull_data_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88";
 
-- Watch Dog Timer (WDT) --
constant wdt_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF8C"; -- base address, fixed!
constant wdt_size_c : natural := 1*4; -- bytes, fixed!
constant wdt_ctrl_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(wdt_base_c) + x"00000000");
constant wdt_size_c : natural := 1*4; -- bytes
constant wdt_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF8C";
 
-- Machine System Timer (MTIME) --
constant mtime_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF90"; -- base address, fixed!
constant mtime_size_c : natural := 4*4; -- bytes, fixed!
constant mtime_time_lo_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(mtime_base_c) + x"00000000");
constant mtime_time_hi_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(mtime_base_c) + x"00000004");
constant mtime_cmp_lo_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(mtime_base_c) + x"00000008");
constant mtime_cmp_hi_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(mtime_base_c) + x"0000000C");
constant mtime_size_c : natural := 4*4; -- bytes
constant mtime_time_lo_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF90";
constant mtime_time_hi_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF94";
constant mtime_cmp_lo_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF98";
constant mtime_cmp_hi_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF9C";
 
-- Universal Asynchronous Receiver/Transmitter (UART) --
constant uart_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA0"; -- base address, fixed!
constant uart_size_c : natural := 2*4; -- bytes, fixed!
constant uart_ctrl_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(uart_base_c) + x"00000000");
constant uart_rtx_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(uart_base_c) + x"00000004");
constant uart_size_c : natural := 2*4; -- bytes
constant uart_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA0";
constant uart_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA4";
 
-- Serial Peripheral Interface (SPI) --
constant spi_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA8"; -- base address, fixed!
constant spi_size_c : natural := 2*4; -- bytes, fixed!
constant spi_ctrl_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(spi_base_c) + x"00000000");
constant spi_rtx_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(spi_base_c) + x"00000004");
constant spi_size_c : natural := 2*4; -- bytes
constant spi_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFA8";
constant spi_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFAC";
 
-- Two Wire Interface (TWI) --
constant twi_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB0"; -- base address, fixed!
constant twi_size_c : natural := 2*4; -- bytes, fixed!
constant twi_ctrl_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(twi_base_c) + x"00000000");
constant twi_rtx_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(twi_base_c) + x"00000004");
constant twi_size_c : natural := 2*4; -- bytes
constant twi_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB0";
constant twi_rtx_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB4";
 
-- Pulse-Width Modulation Controller (PWM) --
constant pwm_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB8"; -- base address, fixed!
constant pwm_size_c : natural := 2*4; -- bytes, fixed!
constant pwm_ctrl_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(pwm_base_c) + x"00000000");
constant pwm_duty_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(pwm_base_c) + x"00000004");
constant pwm_size_c : natural := 2*4; -- bytes
constant pwm_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB8";
constant pwm_duty_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFBC";
 
-- True Random Number generator (TRNG) --
-- True Random Number Generator (TRNG) --
constant trng_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0"; -- base address, fixed!
constant trng_size_c : natural := 2*4; -- bytes, fixed!
constant trng_ctrl_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(trng_base_c) + x"00000000");
constant trng_data_addr_c : std_ulogic_vector(31 downto 0) := std_ulogic_vector(unsigned(trng_base_c) + x"00000004");
constant trng_size_c : natural := 1*4; -- bytes
constant trng_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0";
 
-- RESERVED --
--constant ???_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC8"; -- base address, fixed!
--constant ???_size_c : natural := 6*4; -- bytes, fixed!
--constant ???_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC4"; -- base address, fixed!
--constant ???_size_c : natural := 3*4; -- bytes
 
-- System Information Memory (with SIMULATION output) (SYSINFO) --
-- Custom Functions Unit (CFU) --
constant cfu_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0"; -- base address, fixed!
constant cfu_size_c : natural := 4*4; -- bytes
constant cfu_reg0_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0";
constant cfu_reg1_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD4";
constant cfu_reg2_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD8";
constant cfu_reg3_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFDC";
 
-- System Information Memory (SYSINFO) --
constant sysinfo_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFE0"; -- base address, fixed!
constant sysinfo_size_c : natural := 8*4; -- bytes, fixed!
constant sysinfo_size_c : natural := 8*4; -- bytes
 
-- Main Control Bus -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
315,7 → 332,7
constant alu_cmd_xor_c : std_ulogic_vector(2 downto 0) := "100"; -- r <= A xor B
constant alu_cmd_or_c : std_ulogic_vector(2 downto 0) := "101"; -- r <= A or B
constant alu_cmd_and_c : std_ulogic_vector(2 downto 0) := "110"; -- r <= A and B
constant alu_cmd_bitc_c : std_ulogic_vector(2 downto 0) := "111"; -- r <= A and (not B)
constant alu_cmd_bitm_c : std_ulogic_vector(2 downto 0) := "111"; -- r <= bit manipulation
 
-- Trap ID Codes --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
396,24 → 413,19
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
-- 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
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 16*1024; -- total size of instruction memory space in byte
-- 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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 8*1024; -- total size of data memory space in byte
-- 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
-- Memory configuration: External memory interface --
-- 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)
MEM_EXT_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout (>=1)
426,7 → 438,8
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_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)?
IO_CFU_USE : boolean := false -- implement custom functions unit (CFU)?
);
port (
-- Global control --
482,7 → 495,6
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
-- Physical Memory Protection (PMP) --
PMP_USE : boolean := false; -- implement PMP?
533,7 → 545,6
component neorv32_cpu_control
generic (
-- General --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= x"00000000"; -- hardware thread id
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= x"00000000"; -- cpu boot address
-- RISC-V CPU Extensions --
830,6 → 841,10
-- Component: Processor-internal bootloader ROM (BOOTROM) ---------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_boot_rom
generic (
BOOTROM_BASE : std_ulogic_vector(31 downto 0) := x"FFFF0000"; -- boot ROM base address
BOOTROM_SIZE : natural := 4*1024 -- processor-internal boot ROM memory size in bytes
);
port (
clk_i : in std_ulogic; -- global clock line
rden_i : in std_ulogic; -- read enable
1012,14 → 1027,10
component neorv32_wishbone
generic (
INTERFACE_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2)
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 8*1024; -- total size of instruction memory space in byte
-- 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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 4*1024; -- total size of data memory space in byte
-- 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
);
1050,8 → 1061,8
);
end component;
 
---- Component: Dummy Device with SIM Output (DEVNULL) -------------------------------------
---- -------------------------------------------------------------------------------------------
-- Component: Dummy Device with SIM Output (DEVNULL) --------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_devnull
port (
-- host access --
1065,8 → 1076,31
);
end component;
 
---- Component: System Configuration Information Memory (SYSINFO) ---------------------------
---- -------------------------------------------------------------------------------------------
-- Component: Custom Functions Unit (CFU) -------------------------------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_cfu
port (
-- host access --
clk_i : in std_ulogic; -- global clock line
rstn_i : in std_ulogic; -- global reset line, low-active, use as async
addr_i : in std_ulogic_vector(31 downto 0); -- address
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
ack_o : out std_ulogic; -- transfer acknowledge
-- clock generator --
clkgen_en_o : out std_ulogic; -- enable clock generator
clkgen_i : in std_ulogic_vector(07 downto 0); -- "clock" inputs
-- interrupt --
irq_o : out std_ulogic
-- custom io --
-- ...
);
end component;
 
-- Component: System Configuration Information Memory (SYSINFO) ---------------------------
-- -------------------------------------------------------------------------------------------
component neorv32_sysinfo
generic (
-- General --
1073,18 → 1107,14
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
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 8*1024; -- total size of instruction memory space in byte
-- 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_ROM : boolean := false; -- implement processor-internal instruction memory as ROM
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 4*1024; -- total size of data memory space in byte
-- 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
-- Memory configuration: External memory interface --
-- External memory interface --
MEM_EXT_USE : boolean := false; -- implement external memory bus interface?
-- Processor peripherals --
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)?
1095,7 → 1125,8
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 := true; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)?
IO_CFU_USE : boolean := true -- implement custom functions unit (CFU)?
);
port (
-- host access --
/rtl/core/neorv32_pwm.vhd
90,9 → 90,8
-- prescaler clock generator --
signal prsc_tick : std_ulogic;
 
-- pwm counter --
-- pwm core counter --
signal pwm_cnt : std_ulogic_vector(7 downto 0);
signal pwm_out : std_ulogic_vector(3 downto 0);
 
begin
 
157,19 → 156,13
-- channels --
for i in 0 to num_pwm_channels_c-1 loop
if (unsigned(pwm_cnt) >= unsigned(pwm_ch(i))) or (enable = '0') then
pwm_out(i) <= '0';
pwm_o(i) <= '0';
else
pwm_out(i) <= '1';
pwm_o(i) <= '1';
end if;
end loop; -- i, pwm channel
end if;
end process pwm_core;
 
-- output --
pwm_o(0) <= pwm_out(0);
pwm_o(1) <= pwm_out(1);
pwm_o(2) <= pwm_out(2);
pwm_o(3) <= pwm_out(3);
 
 
end neorv32_pwm_rtl;
/rtl/core/neorv32_sysinfo.vhd
48,18 → 48,14
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
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 8*1024; -- total size of instruction memory space in byte
-- 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_ROM : boolean := false; -- implement processor-internal instruction memory as ROM
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 4*1024; -- total size of data memory space in byte
-- 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
-- Memory configuration: External memory interface --
-- External memory interface --
MEM_EXT_USE : boolean := false; -- implement external memory bus interface?
-- Processor peripherals --
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)?
70,7 → 66,8
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 := true; -- implement true random number generator (TRNG)?
IO_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)?
IO_CFU_USE : boolean := true -- implement custom functions unit (CFU)?
);
port (
-- host access --
114,44 → 111,46
-- SYSINFO(0): Processor (primary) clock frequency --
sysinfo_mem(0) <= std_ulogic_vector(to_unsigned(CLOCK_FREQUENCY, 32));
 
-- SYSINFO(1): Custom user code --
-- SYSINFO(1): Custom user code/ID --
sysinfo_mem(1) <= USER_CODE;
 
-- SYSINFO(2): Implemented processor devices/features --
-- Memory
sysinfo_mem(2)(00) <= bool_to_ulogic_f(BOOTLOADER_USE); -- implement processor-internal bootloader?
sysinfo_mem(2)(01) <= bool_to_ulogic_f(MEM_EXT_USE); -- implement external memory bus interface?
sysinfo_mem(2)(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory?
sysinfo_mem(2)(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM?
sysinfo_mem(2)(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory?
-- Memory --
sysinfo_mem(2)(00) <= bool_to_ulogic_f(BOOTLOADER_USE); -- processor-internal bootloader implemented?
sysinfo_mem(2)(01) <= bool_to_ulogic_f(MEM_EXT_USE); -- external memory bus interface implemented?
sysinfo_mem(2)(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- processor-internal instruction memory implemented?
sysinfo_mem(2)(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- processor-internal instruction memory implemented as ROM?
sysinfo_mem(2)(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- processor-internal data memory implemented?
--
sysinfo_mem(2)(15 downto 05) <= (others => '0'); -- reserved
-- IO
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_USE); -- implement general purpose input/output port unit (GPIO)?
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_USE); -- implement machine system timer (MTIME)?
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART_USE); -- implement universal asynchronous receiver/transmitter (UART)?
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_USE); -- implement serial peripheral interface (SPI)?
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_USE); -- implement two-wire interface (TWI)?
sysinfo_mem(2)(21) <= bool_to_ulogic_f(IO_PWM_USE); -- implement pulse-width modulation unit (PWM)?
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_USE); -- implement watch dog timer (WDT)?
sysinfo_mem(2)(23) <= '0';
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_USE); -- implement true random number generator (TRNG)?
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_DEVNULL_USE); -- implement dummy device (DEVNULL)?
-- IO --
sysinfo_mem(2)(16) <= bool_to_ulogic_f(IO_GPIO_USE); -- general purpose input/output port unit (GPIO) implemented?
sysinfo_mem(2)(17) <= bool_to_ulogic_f(IO_MTIME_USE); -- machine system timer (MTIME) implemented?
sysinfo_mem(2)(18) <= bool_to_ulogic_f(IO_UART_USE); -- universal asynchronous receiver/transmitter (UART) implemented?
sysinfo_mem(2)(19) <= bool_to_ulogic_f(IO_SPI_USE); -- serial peripheral interface (SPI) implemented?
sysinfo_mem(2)(20) <= bool_to_ulogic_f(IO_TWI_USE); -- two-wire interface (TWI) implemented?
sysinfo_mem(2)(21) <= bool_to_ulogic_f(IO_PWM_USE); -- pulse-width modulation unit (PWM) implemented?
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_USE); -- watch dog timer (WDT) implemented?
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFU_USE); -- custom functions unit (CFU) implemented?
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_USE); -- true random number generator (TRNG) implemented?
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_DEVNULL_USE); -- dummy device (DEVNULL) implemented?
--
sysinfo_mem(2)(31 downto 26) <= (others => '0'); -- reserved
 
-- SYSINFO(3): reserved --
sysinfo_mem(3) <= (others => '0'); -- reserved - maybe for technology-specific configuration options?
sysinfo_mem(3) <= (others => '0'); -- reserved
 
-- SYSINFO(4): Base address of instruction memory space --
sysinfo_mem(4) <= MEM_ISPACE_BASE;
sysinfo_mem(4) <= ispace_base_c; -- defined in neorv32_package.vhd file
 
-- SYSINFO(5): Base address of data memory space --
sysinfo_mem(5) <= MEM_DSPACE_BASE;
sysinfo_mem(5) <= dspace_base_c; -- defined in neorv32_package.vhd file
 
-- SYSINFO(6): Total size of instruction memory space in bytes --
sysinfo_mem(6) <= std_ulogic_vector(to_unsigned(MEM_ISPACE_SIZE, 32));
-- SYSINFO(6): Size of IMEM in bytes --
sysinfo_mem(6) <= std_ulogic_vector(to_unsigned(MEM_INT_IMEM_SIZE, 32)) when (MEM_INT_IMEM_USE = true) else (others => '0');
 
-- SYSINFO(7): Total size of data memory space in bytes --
sysinfo_mem(7) <= std_ulogic_vector(to_unsigned(MEM_DSPACE_SIZE, 32));
-- SYSINFO(7): Size of DMEM in bytes --
sysinfo_mem(7) <= std_ulogic_vector(to_unsigned(MEM_INT_DMEM_SIZE, 32)) when (MEM_INT_DMEM_USE = true) else (others => '0');
 
 
-- Read Access ----------------------------------------------------------------------------
159,11 → 158,10
read_access: process(clk_i)
begin
if rising_edge(clk_i) then
ack_o <= rden;
ack_o <= rden;
data_o <= (others => '0');
if (rden = '1') then
data_o <= sysinfo_mem(to_integer(unsigned(info_addr)));
else
data_o <= (others => '0');
end if;
end if;
end process read_access;
/rtl/core/neorv32_top.vhd
5,7 → 5,7
-- # and define all the configuration generics according to your needs. Alternatively, you can use #
-- # one of the alternative top entities provided in the "rtl/top_templates" folder. #
-- # #
-- # Check the processor's documentary for more information: docs/NEORV32.pdf #
-- # Check the processor's data sheet for more information: docs/NEORV32.pdf #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
59,24 → 59,19
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
-- 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
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 16*1024; -- total size of instruction memory space in byte
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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 8*1024; -- total size of data memory space in byte
-- 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
-- Memory configuration: External memory interface --
-- 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)
MEM_EXT_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout
89,7 → 84,8
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_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)?
IO_CFU_USE : boolean := false -- implement custom functions unit (CFU)?
);
port (
-- Global control --
133,7 → 129,7
architecture neorv32_top_rtl of neorv32_top is
 
-- CPU boot address --
constant boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(BOOTLOADER_USE, boot_base_c, MEM_ISPACE_BASE);
constant cpu_boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(BOOTLOADER_USE, boot_rom_base_c, ispace_base_c);
 
-- reset generator --
signal rstn_i_sync0 : std_ulogic;
153,6 → 149,7
signal spi_cg_en : std_ulogic;
signal twi_cg_en : std_ulogic;
signal pwm_cg_en : std_ulogic;
signal cfu_cg_en : std_ulogic;
 
-- bus interface --
type bus_interface_t is record
202,6 → 199,8
signal trng_ack : std_ulogic;
signal devnull_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal devnull_ack : std_ulogic;
signal cfu_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal cfu_ack : std_ulogic;
signal sysinfo_rdata : std_ulogic_vector(data_width_c-1 downto 0);
signal sysinfo_ack : std_ulogic;
 
213,6 → 212,7
signal uart_irq : std_ulogic;
signal spi_irq : std_ulogic;
signal twi_irq : std_ulogic;
signal cfu_irq : std_ulogic;
 
-- misc --
signal mtime_time : std_ulogic_vector(63 downto 0); -- current system time from MTIME
221,60 → 221,23
 
-- Sanity Checks --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
sanity_check: process(clk_i)
begin
if rising_edge(clk_i) then
-- internal bootloader memory --
if (BOOTLOADER_USE = true) and (boot_size_c > boot_max_size_c) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Boot ROM size out of range." severity error;
end if;
if (BOOTLOADER_USE = true) and (MEM_INT_IMEM_ROM = true) then
assert false report "NEORV32 PROCESSOR CONFIG WARNING! IMEM is configured as read-only. Bootloader will not be able to load new executables." severity warning;
end if;
-- internal bootloader ROM --
assert not ((BOOTLOADER_USE = true) and (boot_rom_size_c > boot_rom_max_size_c)) report "NEORV32 PROCESSOR CONFIG ERROR! Boot ROM size out of range." severity error;
assert not ((BOOTLOADER_USE = true) and (MEM_INT_IMEM_ROM = true)) report "NEORV32 PROCESSOR CONFIG WARNING! IMEM is configured as read-only. Bootloader will not be able to load new executables." severity warning;
-- memory system - data/instruction fetch --
assert not ((MEM_EXT_USE = false) and (MEM_INT_DMEM_USE = false)) report "NEORV32 PROCESSOR CONFIG ERROR! Core cannot fetch data without external memory interface and internal data memory." severity error;
assert not ((MEM_EXT_USE = false) and (MEM_INT_IMEM_USE = false) and (BOOTLOADER_USE = false)) report "NEORV32 PROCESSOR CONFIG ERROR! Core cannot fetch instructions without external memory interface, internal data memory and bootloader." severity error;
-- memory system --
assert not (imem_base_c(1 downto 0) /= "00") report "NEORV32 PROCESSOR CONFIG ERROR! Instruction memory space base address must be 4-byte-aligned." severity error;
assert not (dmem_base_c(1 downto 0) /= "00") report "NEORV32 PROCESSOR CONFIG ERROR! Data memory space base address must be 4-byte-aligned." severity error;
assert not (MEM_EXT_TIMEOUT < 1) report "NEORV32 PROCESSOR CONFIG ERROR! Invalid bus timeout. Processor-internal components have 1 cycle latency." severity error;
-- clock --
assert not (CLOCK_FREQUENCY = 0) report "NEORV32 PROCESSOR CONFIG ERROR! Core clock frequency (CLOCK_FREQUENCY) not specified." severity error;
-- memory layout notifier --
assert not (imem_base_c /= x"00000000") report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for instruction address space. Make sure this is sync with the software framework." severity warning;
assert not (dmem_base_c /= x"80000000") report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for data address space. Make sure this is sync with the software framework." severity warning;
 
-- memory system - data/instruction fetch --
if (MEM_EXT_USE = false) then
if (MEM_INT_DMEM_USE = false) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Core cannot fetch data without external memory interface and internal data memory." severity error;
end if;
if (MEM_INT_IMEM_USE = false) and (BOOTLOADER_USE = false) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Core cannot fetch instructions without external memory interface, internal data memory and bootloader." severity error;
end if;
end if;
 
-- memory system --
if (MEM_ISPACE_BASE(1 downto 0) /= "00") then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Instruction memory space base address must be 4-byte-aligned." severity error;
end if;
if (MEM_DSPACE_BASE(1 downto 0) /= "00") then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Data memory space base address must be 4-byte-aligned." severity error;
end if;
if (MEM_INT_IMEM_USE = true) and (MEM_INT_IMEM_SIZE > MEM_ISPACE_SIZE) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Internal instruction memory (IMEM) cannot be greater than total instruction address space." severity error;
end if;
if (MEM_INT_DMEM_USE = true) and (MEM_INT_DMEM_SIZE > MEM_DSPACE_SIZE) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Internal data memory (DMEM) cannot be greater than total data address space." severity error;
end if;
if (MEM_EXT_TIMEOUT < 1) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Invalid bus timeout. Processor-internal components have 1 cycle delay." severity error;
end if;
 
-- clock --
if (CLOCK_FREQUENCY = 0) then
assert false report "NEORV32 PROCESSOR CONFIG ERROR! Core clock frequency (CLOCK_FREQUENCY) not specified." severity error;
end if;
 
-- memory layout notifier --
if (MEM_ISPACE_BASE /= x"00000000") then
assert false report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for instruction address space. Make sure this is sync with the software framwork." severity warning;
end if;
if (MEM_DSPACE_BASE /= x"80000000") then
assert false report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for data address space. Make sure this is sync with the software framwork." severity warning;
end if;
end if;
end process sanity_check;
 
 
-- Reset Generator ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
reset_generator_sync: process(clk_i)
290,7 → 253,7
-- keep internal reset active for at least 4 clock cycles
reset_generator: process(rstn_i_sync1, rstn_i_sync2, clk_i)
begin
if ((rstn_i_sync1 or rstn_i_sync2) = '0') then -- signal stable somehow?
if ((rstn_i_sync1 and rstn_i_sync2) = '0') then -- signal stable?
rstn_gen <= (others => '0');
elsif rising_edge(clk_i) then
rstn_gen <= rstn_gen(rstn_gen'left-1 downto 0) & '1';
298,7 → 261,7
end process reset_generator;
 
ext_rstn <= rstn_gen(rstn_gen'left); -- the beautified external reset signal
sys_rstn <= ext_rstn and wdt_rstn; -- system reset - can also be triggered by watchdog
sys_rstn <= ext_rstn and wdt_rstn; -- system reset - can also be triggered by watchdog
 
 
-- Clock Generator ------------------------------------------------------------------------
309,23 → 272,28
clk_div <= (others => '0');
clk_div_ff <= (others => '0');
elsif rising_edge(clk_i) then
-- anybody wanting some fresh clocks? --
if ((wdt_cg_en or uart_cg_en or spi_cg_en or twi_cg_en or pwm_cg_en) = '1') then
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1);
clk_div_ff <= clk_div;
-- fresh clocks anyone? --
if ((wdt_cg_en or uart_cg_en or spi_cg_en or twi_cg_en or pwm_cg_en or cfu_cg_en) = '1') then
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1);
end if;
clk_div_ff <= clk_div;
end if;
end process clock_generator;
 
-- clock enable select: rising edge detectors --
clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2
clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- CLK/4
clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- CLK/8
clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- CLK/64
clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- CLK/128
clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- CLK/1024
clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048
clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096
-- clock enables: rising edge detectors --
clock_generator_edge: process(clk_i)
begin
if rising_edge(clk_i) then
clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2
clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- CLK/4
clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- CLK/8
clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- CLK/64
clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- CLK/128
clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- CLK/1024
clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048
clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096
end if;
end process clock_generator_edge;
 
 
-- CPU ------------------------------------------------------------------------------------
334,7 → 302,7
generic map (
-- General --
HW_THREAD_ID => (others => '0'), -- hardware thread id
CPU_BOOT_ADDR => boot_addr_c, -- cpu boot address
CPU_BOOT_ADDR => cpu_boot_addr_c, -- cpu boot address
-- 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?
343,7 → 311,6
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 --
CSR_COUNTERS_USE => CSR_COUNTERS_USE, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN => FAST_MUL_EN, -- use DSPs for M extension's multiplier
-- Physical Memory Protection (PMP) --
PMP_USE => PMP_USE, -- implement PMP?
394,7 → 361,7
 
-- fast interrupts --
fast_irq(0) <= wdt_irq; -- highest priority
fast_irq(1) <= gpio_irq;
fast_irq(1) <= gpio_irq or cfu_irq; -- can be triggered by GPIO pin-change or CFU
fast_irq(2) <= uart_irq;
fast_irq(3) <= spi_irq or twi_irq; -- lowest priority, can be triggered by SPI or TWI
 
444,11 → 411,11
 
-- processor bus: CPU data input --
p_bus.rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or uart_rdata or
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or devnull_rdata or sysinfo_rdata);
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or devnull_rdata or cfu_rdata or sysinfo_rdata);
 
-- processor bus: CPU data ACK input --
p_bus.ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or uart_ack or
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or devnull_ack or sysinfo_ack);
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or devnull_ack or cfu_ack or sysinfo_ack);
 
-- processor bus: CPU data bus error input --
p_bus.err <= wishbone_err;
460,7 → 427,7
if (MEM_INT_IMEM_USE = true) generate
neorv32_int_imem_inst: neorv32_imem
generic map (
IMEM_BASE => MEM_ISPACE_BASE, -- memory base address
IMEM_BASE => imem_base_c, -- memory base address
IMEM_SIZE => MEM_INT_IMEM_SIZE, -- processor-internal instruction memory size in bytes
IMEM_AS_ROM => MEM_INT_IMEM_ROM, -- implement IMEM as read-only memory?
BOOTLOADER_USE => BOOTLOADER_USE -- implement and use bootloader?
491,7 → 458,7
if (MEM_INT_DMEM_USE = true) generate
neorv32_int_dmem_inst: neorv32_dmem
generic map (
DMEM_BASE => MEM_DSPACE_BASE, -- memory base address
DMEM_BASE => dmem_base_c, -- memory base address
DMEM_SIZE => MEM_INT_DMEM_SIZE -- processor-internal data memory size in bytes
)
port map (
518,6 → 485,10
neorv32_boot_rom_inst_true:
if (BOOTLOADER_USE = true) generate
neorv32_boot_rom_inst: neorv32_boot_rom
generic map (
BOOTROM_BASE => boot_rom_base_c, -- boot ROM base address
BOOTROM_SIZE => boot_rom_size_c -- processor-internal boot TOM memory size in bytes
)
port map (
clk_i => clk_i, -- global clock line
rden_i => p_bus.re, -- read enable
541,14 → 512,10
neorv32_wishbone_inst: neorv32_wishbone
generic map (
INTERFACE_REG_STAGES => MEM_EXT_REG_STAGES, -- number of interface register stages (0,1,2)
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE => MEM_ISPACE_BASE, -- base address of instruction memory space
MEM_ISPACE_SIZE => MEM_ISPACE_SIZE, -- total size of instruction memory space in byte
-- 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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE => MEM_DSPACE_BASE, -- base address of data memory space
MEM_DSPACE_SIZE => MEM_DSPACE_SIZE, -- total size of data memory space in byte
-- 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
)
887,6 → 854,40
end generate;
 
 
-- Custom Functions Unit (CFU) ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_cfu_inst_true:
if (IO_CFU_USE = true) generate
neorv32_cfu_inst: neorv32_cfu
port map (
-- host access --
clk_i => clk_i, -- global clock line
rstn_i => sys_rstn, -- global reset line, low-active, use as async
addr_i => p_bus.addr, -- address
rden_i => io_rden, -- read enable
wren_i => io_wren, -- write enable
data_i => p_bus.wdata, -- data in
data_o => cfu_rdata, -- data out
ack_o => cfu_ack, -- transfer acknowledge
-- clock generator --
clkgen_en_o => cfu_cg_en, -- enable clock generator
clkgen_i => clk_gen, -- "clock" inputs
-- interrupt --
irq_o => cfu_irq
-- custom io --
-- ...
);
end generate;
 
neorv32_cfu_inst_false:
if (IO_CFU_USE = false) generate
cfu_rdata <= (others => '0');
cfu_ack <= '0';
cfu_cg_en <= '0';
cfu_irq <= '0';
end generate;
 
 
-- System Configuration Information Memory (SYSINFO) --------------------------------------
-- -------------------------------------------------------------------------------------------
neorv32_sysinfo_inst: neorv32_sysinfo
895,18 → 896,14
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader?
USER_CODE => USER_CODE, -- custom user code
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE => MEM_ISPACE_BASE, -- base address of instruction memory space
MEM_ISPACE_SIZE => MEM_ISPACE_SIZE, -- total size of instruction memory space in byte
-- 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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE => MEM_DSPACE_BASE, -- base address of data memory space
MEM_DSPACE_SIZE => MEM_DSPACE_SIZE, -- total size of data memory space in byte
-- 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
-- Memory configuration: External memory interface --
-- External memory interface --
MEM_EXT_USE => MEM_EXT_USE, -- implement external memory bus interface?
-- Processor peripherals --
IO_GPIO_USE => IO_GPIO_USE, -- implement general purpose input/output port unit (GPIO)?
917,7 → 914,8
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_DEVNULL_USE => IO_DEVNULL_USE -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE => IO_DEVNULL_USE, -- implement dummy device (DEVNULL)?
IO_CFU_USE => IO_CFU_USE -- implement custom functions unit (CFU)?
)
port map (
-- host access --
/rtl/core/neorv32_trng.vhd
1,21 → 1,11
-- #################################################################################################
-- # << NEORV32 - True Random Number Generator (TRNG) >> #
-- # ********************************************************************************************* #
-- # This unit implements a true random number generator which uses an inverter chain as entropy #
-- # source. The inverter chain is constructed as GARO (Galois Ring Oscillator) TRNG. The single #
-- # inverters are connected via simple latches that are used to enbale/disable the TRNG. Also, #
-- # these latches are used as additional delay element. By using unique enable signals for each #
-- # latch, the synthesis tool cannot "optimize" one of the inverters out of the design. Further- #
-- # more, the latches prevent the synthesis tool from detecting combinatorial loops. #
-- # The output of the GARO is de-biased by a simple von Neuman random extractor and is further #
-- # post-processed by a 16-bit LFSR for improved whitening. #
-- # This unit implements a true random number generator which uses several GARO chain as entropy #
-- # source. The outputs of all chains are XORed and de-biased using a John von Neumann randomness #
-- # extractor. The de-biased signal is further processed by a simple LFSR for improved whitening. #
-- # #
-- # Sources: #
-- # - GARO: "Experimental Assessment of FIRO- and GARO-based Noise Sources for Digital TRNG #
-- # Designs on FPGAs" by Martin Schramm, Reiner Dojen and Michael Heigly, 2017 #
-- # - Latches for platform independence: "Extended Abstract: The Butterfly PUF Protecting IP #
-- # on every FPGA" by Sandeep S. Kumar, Jorge Guajardo, Roel Maesyz, Geert-Jan Schrijen and #
-- # Pim Tuyls, Philips Research Europe, 2008 #
-- # - Von Neumann De-Biasing: "Iterating Von Neumann's Post-Processing under Hardware #
-- # Constraints" by Vladimir Rozic, Bohan Yang, Wim Dehaene and Ingrid Verbauwhede, 2016 #
-- # ********************************************************************************************* #
73,24 → 63,45
architecture neorv32_trng_rtl of neorv32_trng is
 
-- advanced configuration --------------------------------------------------------------------------------
constant num_inv_c : natural := 16; -- length of GARO inverter chain (default=16, max=16)
constant lfsr_taps_c : std_ulogic_vector(15 downto 0) := "1101000000001000"; -- Fibonacci LFSR feedback taps
constant num_inv_c : natural := 15; -- length of GARO inverter chain (default=15, has to be odd)
constant num_garos_c : natural := 2; -- number of GARO elements (default=2)
constant lfsr_taps_c : std_ulogic_vector(7 downto 0) := "10111000"; -- Fibonacci post-processing LFSR feedback taps
constant lfsr_en_c : boolean := true; -- use LFSR-based post-processing
type tap_mask_t is array (0 to num_garos_c-1) of std_ulogic_vector(num_inv_c-2 downto 0);
constant tap_mask : tap_mask_t := ( -- GARO tap masks, sum of set bits has to be even
"11110000000000",
"00000011000000"
);
-- -------------------------------------------------------------------------------------------------------
 
-- control register bits --
constant ctrl_taps_lsb_c : natural := 0; -- -/w: TAP 0 enable
constant ctrl_taps_msb_c : natural := 15; -- -/w: TAP 15 enable
constant ctrl_en_c : natural := 31; -- r/w: TRNG enable
constant ctrl_data_lsb_c : natural := 0; -- r/-: Random data bit LSB
constant ctrl_data_msb_c : natural := 7; -- r/-: Random data bit MSB
constant ctrl_data_valid_c : natural := 15; -- r/-: Output data valid
constant ctrl_err_zero_c : natural := 16; -- r/-: stuck at 0 error
constant ctrl_err_one_c : natural := 17; -- r/-: stuck at 1 error
constant ctrl_en_c : natural := 31; -- r/w: TRNG enable
 
-- data register bits --
constant ctrl_data_lsb_c : natural := 0; -- r/-: Random data bit 0
constant ctrl_data_msb_c : natural := 15; -- r/-: Random data bit 15
constant ctrl_rnd_valid_c : natural := 31; -- r/-: Output byte valid
 
-- IO space: module base address --
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(trng_size_c); -- low address boundary bit
 
-- Component: GARO Element --
component neorv32_trng_garo_element
generic (
NUM_INV : natural := 16 -- number of inverters in chain
);
port (
clk_i : in std_ulogic;
enable_i : in std_ulogic;
enable_o : out std_ulogic;
mask_i : in std_ulogic_vector(NUM_INV-2 downto 0);
data_o : out std_ulogic;
error0_o : out std_ulogic;
error1_o : out std_ulogic
);
end component;
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
signal addr : std_ulogic_vector(31 downto 0); -- access address
97,23 → 108,33
signal wren : std_ulogic; -- full word write enable
signal rden : std_ulogic; -- read enable
 
-- random number generator --
signal rnd_inv : std_ulogic_vector(num_inv_c-1 downto 0); -- inverter chain
signal rnd_enable_sreg : std_ulogic_vector(num_inv_c-1 downto 0); -- enable shift register
signal rnd_enable : std_ulogic;
signal tap_config : std_ulogic_vector(15 downto 0);
signal rnd_sync : std_ulogic_vector(02 downto 0); -- metastability filter & de-biasing
signal ready_ff : std_ulogic; -- new random data available
signal rnd_sreg : std_ulogic_vector(15 downto 0); -- sample shift reg
signal rnd_cnt : std_ulogic_vector(04 downto 0);
signal new_sample : std_ulogic; -- new output byte ready
signal rnd_data : std_ulogic_vector(15 downto 0); -- random data register (read-only)
-- garo array --
signal garo_en_in : std_ulogic_vector(num_garos_c-1 downto 0);
signal garo_en_out : std_ulogic_vector(num_garos_c-1 downto 0);
signal garo_data : std_ulogic_vector(num_garos_c-1 downto 0);
signal garo_err_zero : std_ulogic_vector(num_garos_c-1 downto 0);
signal garo_err_one : std_ulogic_vector(num_garos_c-1 downto 0);
signal garo_res : std_ulogic;
signal garo_err0 : std_ulogic;
signal garo_err1 : std_ulogic;
 
-- Randomness extractor (von Neumann De-Biasing) --
signal db_state : std_ulogic;
signal db_enable : std_ulogic; -- valid data from de-biasing
signal db_data : std_ulogic; -- actual data from de-biasing
-- de-biasing --
signal db_data : std_ulogic_vector(2 downto 0);
signal db_state : std_ulogic; -- process de-biasing every second cycle
signal rnd_valid : std_ulogic;
signal rnd_data : std_ulogic;
 
-- processing core --
signal rnd_enable : std_ulogic;
signal rnd_cnt : std_ulogic_vector(3 downto 0);
signal rnd_sreg : std_ulogic_vector(7 downto 0);
signal rnd_output : std_ulogic_vector(7 downto 0);
signal rnd_ready : std_ulogic;
 
-- health check --
signal rnd_error_zero : std_ulogic; -- stuck at zero
signal rnd_error_one : std_ulogic; -- stuck at one
 
begin
 
-- Access Control -------------------------------------------------------------------------
132,119 → 153,320
ack_o <= acc_en and (rden_i or wren_i);
-- write access --
if (wren = '1') then
if (addr = trng_ctrl_addr_c) then
tap_config <= data_i(tap_config'left downto 0);
rnd_enable <= data_i(ctrl_en_c);
end if;
rnd_enable <= data_i(ctrl_en_c);
end if;
-- read access --
data_o <= (others => '0');
if (rden = '1') then
if (addr = trng_ctrl_addr_c) then
data_o(ctrl_taps_msb_c downto ctrl_taps_lsb_c) <= tap_config;
data_o(ctrl_en_c) <= rnd_enable;
else -- trng_data_addr_c
data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= rnd_data;
data_o(ctrl_rnd_valid_c) <= ready_ff;
end if;
data_o(ctrl_data_msb_c downto ctrl_data_lsb_c) <= rnd_output;
data_o(ctrl_data_valid_c) <= rnd_ready;
data_o(ctrl_err_zero_c) <= rnd_error_zero;
data_o(ctrl_err_one_c) <= rnd_error_one;
data_o(ctrl_en_c) <= rnd_enable;
end if;
end if;
end process rw_access;
 
 
-- True Random Generator ------------------------------------------------------------------
-- Entropy Source -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
entropy_source: process(rnd_enable_sreg, rnd_enable, rnd_inv, tap_config)
neorv32_trng_garo_element_inst:
for i in 0 to num_garos_c-1 generate
neorv32_trng_garo_element_inst_i: neorv32_trng_garo_element
generic map (
NUM_INV => num_inv_c -- number of inverters in chain
)
port map (
clk_i => clk_i,
enable_i => garo_en_in(i),
enable_o => garo_en_out(i),
mask_i => tap_mask(i),
data_o => garo_data(i),
error0_o => garo_err_zero(i),
error1_o => garo_err_one(i)
);
end generate;
 
-- GARO element connection --
garo_intercon: process(rnd_enable, garo_en_out, garo_data, garo_err_zero, garo_err_one)
variable data_v : std_ulogic;
variable err0_v : std_ulogic;
variable err1_v : std_ulogic;
begin
for i in 0 to num_inv_c-1 loop
if (rnd_enable = '0') then -- start with a defined state (latch reset)
rnd_inv(i) <= '0';
-- uniquely enable latches to prevent synthesis from removing chain elements
elsif (rnd_enable_sreg(i) = '1') then -- latch enable
-- here we have the inverter chain --
if (i = num_inv_c-1) then -- left most inverter?
if (tap_config(i) = '1') then
rnd_inv(i) <= not rnd_inv(0); -- direct input of right most inverter (= output signal)
else
rnd_inv(i) <= '0';
end if;
else
if (tap_config(i) = '1') then
rnd_inv(i) <= not (rnd_inv(i+1) xor rnd_inv(0)); -- use final output as feedback
else
rnd_inv(i) <= not rnd_inv(i+1); -- normal chain: use previous inverter's output as input
end if;
end if;
-- enable chain --
for i in 0 to num_garos_c-1 loop
if (i = 0) then
garo_en_in(i) <= rnd_enable;
else
garo_en_in(i) <= garo_en_out(i-1);
end if;
end loop; -- i
end process entropy_source;
-- data & status --
data_v := garo_data(0);
err0_v := garo_err_zero(0);
err1_v := garo_err_one(0);
for i in 1 to num_garos_c-1 loop
data_v := data_v xor garo_data(i);
err0_v := err0_v or garo_err_zero(i);
err1_v := err1_v or garo_err_one(i);
end loop; -- i
garo_res <= data_v;
garo_err0 <= err0_v;
garo_err1 <= err1_v;
end process garo_intercon;
 
-- unique enable signals for each inverter latch --
inv_enable: process(clk_i)
 
-- De-Biasing -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
jvn_debiasing_sync: process(clk_i)
begin
if rising_edge(clk_i) then
-- using individual enable signals for each inverter - derived from a shift register - to prevent the synthesis tool
-- from removing all but one inverter (since they implement "logical identical functions")
-- this also allows to make the trng platform independent
rnd_enable_sreg <= rnd_enable_sreg(num_inv_c-2 downto 0) & rnd_enable; -- activate right most inverter first
db_data <= db_data(db_data'left-1 downto 0) & garo_res;
db_state <= (not db_state) and rnd_enable; -- just toggle when enabled -> process in every second cycle
end if;
end process inv_enable;
end process jvn_debiasing_sync;
 
 
-- John von Neumann De-Biasing --
jvn_debiasing: process(db_state, db_data)
variable tmp_v : std_ulogic_vector(2 downto 0);
begin
-- check groups of two non-overlapping bits from the input stream
tmp_v := db_state & db_data(db_data'left downto db_data'left-1);
case tmp_v is
when "101" => rnd_valid <= '1'; rnd_data <= '1'; -- rising edge -> '1'
when "110" => rnd_valid <= '1'; rnd_data <= '0'; -- falling edge -> '0'
when others => rnd_valid <= '0'; rnd_data <= '-'; -- invalid
end case;
end process jvn_debiasing;
 
 
-- Processing Core ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
processing_core: process(clk_i)
begin
if rising_edge(clk_i) then
-- synchronize output of GARO --
rnd_sync <= rnd_sync(1 downto 0) & rnd_inv(0); -- no more metastability
 
-- von Neumann De-Biasing state --
db_state <= (not db_state) and rnd_enable; -- just toggle -> process in every second cycle
 
-- sample random data & post-processing --
-- sample random data and apply post-processing --
if (rnd_enable = '0') then
rnd_cnt <= (others => '0');
rnd_sreg <= (others => '0');
elsif (db_enable = '1') then -- valid de-biased output?
if (rnd_cnt = "10000") then
elsif (rnd_valid = '1') and (garo_en_out(garo_en_out'left) = '1') then -- valid random sample and GAROs ready?
if (rnd_cnt = "1000") then
rnd_cnt <= (others => '0');
else
rnd_cnt <= std_ulogic_vector(unsigned(rnd_cnt) + 1);
end if;
rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & (xnor_all_f(rnd_sreg and lfsr_taps_c) xor db_data); -- LFSR post-processing
-- rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & db_data; -- LFSR post-processing
if (lfsr_en_c = true) then -- LFSR post-processing
rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & (xnor_all_f(rnd_sreg and lfsr_taps_c) xnor rnd_data);
else -- NO post-processing
rnd_sreg <= rnd_sreg(rnd_sreg'left-1 downto 0) & rnd_data;
end if;
end if;
 
-- data output register --
if (new_sample = '1') then
rnd_data <= rnd_sreg;
if (rnd_cnt = "1000") then
rnd_output <= rnd_sreg;
end if;
 
-- health check error --
if (rnd_enable = '0') then
rnd_error_zero <= '0';
rnd_error_one <= '0';
else
rnd_error_zero <= rnd_error_zero or garo_err0;
rnd_error_one <= rnd_error_one or garo_err1;
end if;
 
-- data ready flag --
if (rnd_enable = '0') or (rden = '1') then -- clear when deactivated or on data read
ready_ff <= '0';
elsif (new_sample = '1') then
ready_ff <= '1';
if (rnd_cnt = "1000") then -- new sample ready?
rnd_ready <= '1';
elsif (rnd_enable = '0') or (rden = '1') then -- clear when deactivated or on data read
rnd_ready <= '0';
end if;
end if;
end process processing_core;
 
-- John von Neumann De-Biasing --
debiasing: process(db_state, rnd_sync)
variable tmp_v : std_ulogic_vector(2 downto 0);
 
end neorv32_trng_rtl;
 
 
-- ############################################################################################################################
-- ############################################################################################################################
 
 
-- #################################################################################################
-- # << NEORV32 - True Random Number Generator (TRNG) - GARO Chain-Based Entropy Source >> #
-- # ********************************************************************************************* #
-- # An inverter chain (ring oscillator) is used as entropy source. The inverter chain is #
-- # constructed as GARO (Galois Ring Oscillator) TRNG, which is an "asynchronous" LFSR. The #
-- # single inverters are connected via latches that are used to enbale/disable the TRNG. Also, #
-- # these latches are used as additional delay element. By using unique enable signals for each #
-- # latch, the synthesis tool cannot "optimize" (=remove) any of the inverters out of the design. #
-- # Furthermore, the latches prevent the synthesis tool from detecting combinatorial loops. #
-- # #
-- # Sources: #
-- # - GARO: "Experimental Assessment of FIRO- and GARO-based Noise Sources for Digital TRNG #
-- # Designs on FPGAs" by Martin Schramm, Reiner Dojen and Michael Heigly, 2017 #
-- # - Latches for platform independence: "Extended Abstract: The Butterfly PUF Protecting IP #
-- # on every FPGA" by Sandeep S. Kumar, Jorge Guajardo, Roel Maesyz, Geert-Jan Schrijen and #
-- # Pim Tuyls, Philips Research Europe, 2008 #
-- # ********************************************************************************************* #
-- # 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_trng_garo_element is
generic (
NUM_INV : natural := 15 -- number of inverters in chain
);
port (
clk_i : in std_ulogic;
enable_i : in std_ulogic;
enable_o : out std_ulogic;
mask_i : in std_ulogic_vector(NUM_INV-2 downto 0);
data_o : out std_ulogic;
error0_o : out std_ulogic;
error1_o : out std_ulogic
);
end neorv32_trng_garo_element;
 
architecture neorv32_trng_garo_element_rtl of neorv32_trng_garo_element is
 
-- debugging --
constant is_sim_c : boolean := false;
 
signal inv_chain : std_ulogic_vector(NUM_INV-1 downto 0); -- oscillator chain
signal enable_sreg : std_ulogic_vector(NUM_INV-1 downto 0); -- enable shift register
signal sync_ff : std_ulogic_vector(2 downto 0); -- synchronizer
 
signal cnt_zero, cnt_one : std_ulogic_vector(5 downto 0); -- stuck-at-0/1 counters
 
begin
 
-- Sanity Check ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
assert ((NUM_INV mod 2) /= 0) report "NEORV32 TRNG.GARO_element: NUM_INV has to be odd." severity error;
 
 
-- Entropy Source -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
garo_chain: process(clk_i, enable_i, enable_sreg, mask_i, inv_chain)
begin
-- check groups of two non-overlapping bits from the input stream
tmp_v := db_state & rnd_sync(2 downto 1);
case tmp_v is
when "101" => db_enable <= '1'; db_data <= '1'; -- rising edge -> '1'
when "110" => db_enable <= '1'; db_data <= '0'; -- falling edge -> '0'
when others => db_enable <= '0'; db_data <= '0'; -- invalid
end case;
end process debiasing;
if (is_sim_c = false) then
for i in 0 to NUM_INV-1 loop -- inverters in chain
if (enable_i = '0') then -- start with a defined state (latch reset)
inv_chain(i) <= '0';
-- Using individual enable signals for each inverter - derived from a shift register - to prevent the synthesis tool
-- from removing all but one inverter (since they implement "logical identical functions").
-- This also allows to make the TRNG platform independent.
elsif (enable_sreg(i) = '1') then
-- here we have the inverter chain --
if (i = NUM_INV-1) then -- left-most inverter?
inv_chain(i) <= not inv_chain(0); -- direct input of right most inverter (= output signal)
else
-- if tap switch is ON: use final output XORed with previous inverter's output
-- if tap switch is OFF: just use previous inverter's output
inv_chain(i) <= not (inv_chain(i+1) xor (inv_chain(0) and mask_i(i)));
end if;
end if;
end loop; -- i
else -- simulate as simple LFSR
if rising_edge(clk_i) then
if (enable_i = '0') then
inv_chain <= (others => '0');
else
inv_chain(NUM_INV-1 downto 0) <= inv_chain(inv_chain'left-1 downto 0) & xnor_all_f(inv_chain(NUM_INV-2 downto 0) and mask_i);
end if;
end if;
end if;
end process garo_chain;
 
-- new valid byte available? --
new_sample <= '1' when (rnd_cnt = "10000") and (rnd_enable = '1') and (db_enable = '1') else '0';
 
-- Control --------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_unit: process(clk_i)
begin
if rising_edge(clk_i) then
enable_sreg <= enable_sreg(enable_sreg'left-1 downto 0) & enable_i; -- activate right-most inverter first
sync_ff <= sync_ff(sync_ff'left-1 downto 0) & inv_chain(0); -- synchronize to prevent metastability
end if;
end process ctrl_unit;
 
end neorv32_trng_rtl;
-- output for "enable chain" --
enable_o <= enable_sreg(enable_sreg'left);
 
-- rnd output --
data_o <= sync_ff(sync_ff'left);
 
 
-- Health Check ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
health_check: process(clk_i)
begin
if rising_edge(clk_i) then
if (enable_sreg(enable_sreg'left) = '0') then
cnt_zero <= (others => '0');
cnt_one <= (others => '0');
else
-- stuck-at-zero --
if (and_all_f(cnt_zero) = '0') then -- max not reached yet
error0_o <= '0';
if (sync_ff(sync_ff'left) = '0') then
cnt_zero <= std_ulogic_vector(unsigned(cnt_zero) + 1);
else
cnt_zero <= (others => '0');
end if;
else
error0_o <= '1';
end if;
-- stuck-at-one --
if (and_all_f(cnt_one) = '0') then -- max not reached yet
error1_o <= '0';
if (sync_ff(sync_ff'left) = '1') then
cnt_one <= std_ulogic_vector(unsigned(cnt_one) + 1);
else
cnt_one <= (others => '0');
end if;
else
error1_o <= '1';
end if;
end if;
end if;
end process health_check;
 
 
end neorv32_trng_garo_element_rtl;
/rtl/core/neorv32_uart.vhd
152,27 → 152,8
data_o <= (others => '0');
if (rd_en = '1') then
if (addr = uart_ctrl_addr_c) then
data_o(ctrl_uart_baud00_c) <= ctrl(ctrl_uart_baud00_c);
data_o(ctrl_uart_baud01_c) <= ctrl(ctrl_uart_baud01_c);
data_o(ctrl_uart_baud02_c) <= ctrl(ctrl_uart_baud02_c);
data_o(ctrl_uart_baud03_c) <= ctrl(ctrl_uart_baud03_c);
data_o(ctrl_uart_baud04_c) <= ctrl(ctrl_uart_baud04_c);
data_o(ctrl_uart_baud05_c) <= ctrl(ctrl_uart_baud05_c);
data_o(ctrl_uart_baud06_c) <= ctrl(ctrl_uart_baud06_c);
data_o(ctrl_uart_baud07_c) <= ctrl(ctrl_uart_baud07_c);
--
data_o(ctrl_uart_baud08_c) <= ctrl(ctrl_uart_baud08_c);
data_o(ctrl_uart_baud09_c) <= ctrl(ctrl_uart_baud09_c);
data_o(ctrl_uart_baud10_c) <= ctrl(ctrl_uart_baud10_c);
data_o(ctrl_uart_baud11_c) <= ctrl(ctrl_uart_baud11_c);
--
data_o(ctrl_uart_prsc0_c) <= ctrl(ctrl_uart_prsc0_c);
data_o(ctrl_uart_prsc1_c) <= ctrl(ctrl_uart_prsc1_c);
data_o(ctrl_uart_prsc2_c) <= ctrl(ctrl_uart_prsc2_c);
data_o <= ctrl; -- default
data_o(ctrl_uart_rxovr_c) <= uart_rx_avail(0) and uart_rx_avail(1);
data_o(ctrl_uart_en_c) <= ctrl(ctrl_uart_en_c);
data_o(ctrl_uart_rx_irq_c) <= ctrl(ctrl_uart_rx_irq_c);
data_o(ctrl_uart_tx_irq_c) <= ctrl(ctrl_uart_tx_irq_c);
data_o(ctrl_uart_tx_busy_c) <= uart_tx_busy;
else -- uart_rtx_addr_c
data_o(data_rx_avail_c) <= uart_rx_avail(0);
/rtl/core/neorv32_wishbone.vhd
4,9 → 4,9
-- # 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). #
-- # #
-- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
-- # All bus accesses from the CPU, which do not target the internal IO region, the internal boot- #
-- # loader or the internal instruction & data memories (if implemented), are delegated via this #
-- # loader or the internal instruction or data memories (if implemented), are delegated via this #
-- # Wishbone gateway to the external bus interface. #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
50,14 → 50,10
entity neorv32_wishbone is
generic (
INTERFACE_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2)
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 8*1024; -- total size of instruction memory space in byte
-- 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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 4*1024; -- total size of data memory space in byte
-- 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
);
93,8 → 89,10
-- 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, int_io_acc : 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_stb_ff0 : std_ulogic;
103,32 → 101,29
signal wb_ack_ff : std_ulogic;
signal wb_err_ff : std_ulogic;
 
-- data read-back --
signal wb_rdata : std_ulogic_vector(31 downto 0);
 
begin
 
-- Sanity Check ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
sanity_check: process(clk_i)
begin
if rising_edge(clk_i) then
if (INTERFACE_REG_STAGES > 2) then
assert false report "NEORV32 CONFIG ERROR! Number of external memory interface buffer stages must be 0, 1 or 2." severity error;
end if;
end if;
end process sanity_check;
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;
 
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- access to internal IMEM or DMEM? --
int_imem_acc <= '1' when (addr_i >= MEM_ISPACE_BASE) and (addr_i < std_ulogic_vector(unsigned(MEM_ISPACE_BASE) + MEM_INT_IMEM_SIZE)) else '0';
int_dmem_acc <= '1' when (addr_i >= MEM_DSPACE_BASE) and (addr_i < std_ulogic_vector(unsigned(MEM_DSPACE_BASE) + MEM_INT_DMEM_SIZE)) else '0';
int_imem_acc <= '1' when (addr_i >= imem_base_c) and (addr_i < std_ulogic_vector(unsigned(imem_base_c) + MEM_INT_IMEM_SIZE)) else '0';
int_dmem_acc <= '1' when (addr_i >= dmem_base_c) and (addr_i < std_ulogic_vector(unsigned(dmem_base_c) + MEM_INT_DMEM_SIZE)) else '0';
int_imem_acc_real <= int_imem_acc when (MEM_INT_IMEM_USE = true) else '0';
int_dmem_acc_real <= int_dmem_acc when (MEM_INT_DMEM_USE = true) else '0';
int_boot_acc <= '1' when (addr_i >= boot_base_c) else '0';
int_io_acc <= '1' when (addr_i >= io_base_c) else '0';
int_boot_acc <= '1' when (addr_i >= boot_rom_base_c) else '0'; -- this also covers access to the IO space
--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 (not int_io_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) and (wren_i or rden_i);
 
 
-- Bus Arbiter -----------------------------------------------------------------------------
136,17 → 131,19
bus_arbiter: process(rstn_i, clk_i)
begin
if (rstn_i = '0') then
wb_cyc_ff <= '0';
wb_stb_ff1 <= '0';
wb_stb_ff0 <= '0';
wb_ack_ff <= '0';
wb_err_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';
elsif rising_edge(clk_i) then
-- 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) or (not wb_err_i)) and (not cancel_i);
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;
155,6 → 152,13
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;
 
170,12 → 174,16
-- cpu err --
err_o <= wb_err_ff when (INTERFACE_REG_STAGES = 2) else wb_err_i;
 
-- 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');
 
 
-- Bus Buffer -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
interface_reg_level_zero:
if (INTERFACE_REG_STAGES = 0) generate -- 0 register levels: direct connection
data_o <= wb_dat_i;
wb_rdata <= wb_dat_i;
wb_adr_o <= addr_i;
wb_dat_o <= data_i;
wb_sel_o <= ben_i;
195,7 → 203,7
end if;
end if;
end process buffer_stages_one;
data_o <= wb_dat_i;
wb_rdata <= wb_dat_i;
end generate;
 
interface_reg_level_two:
208,8 → 216,10
wb_dat_o <= data_i;
wb_sel_o <= ben_i;
wb_we_o <= wren_i;
data_o <= wb_dat_i;
end if;
if (wb_ack_i = '1') then
wb_rdata <= wb_dat_i;
end if;
end if;
end process buffer_stages_two;
end generate;
/rtl/top_templates/neorv32_test_setup.vhd
80,24 → 80,19
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => true, -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE => true, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN => false, -- use DSPs for M extension's multiplier
-- Physical Memory Protection (PMP) --
PMP_USE => false, -- implement PMP?
PMP_NUM_REGIONS => 4, -- number of regions (max 16)
PMP_GRANULARITY => 14, -- region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE => x"00000000", -- base address of instruction memory space
MEM_ISPACE_SIZE => 16*1024, -- total size of instruction memory space in byte
-- Internal Instruction memory --
MEM_INT_IMEM_USE => true, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => 16*1024, -- size of processor-internal instruction memory in bytes
MEM_INT_IMEM_ROM => false, -- implement processor-internal instruction memory as ROM
-- Memory configuration: Data memory --
MEM_DSPACE_BASE => x"80000000", -- base address of data memory space
MEM_DSPACE_SIZE => 8*1024, -- total size of data memory space in byte
-- Internal Data memory --
MEM_INT_DMEM_USE => true, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => 8*1024, -- size of processor-internal data memory in bytes
-- Memory configuration: External memory interface --
-- 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)
MEM_EXT_TIMEOUT => 15, -- cycles after which a valid bus access will timeout
110,7 → 105,8
IO_PWM_USE => false, -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE => true, -- implement watch dog timer (WDT)?
IO_TRNG_USE => false, -- implement true random number generator (TRNG)?
IO_DEVNULL_USE => true -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE => true, -- implement dummy device (DEVNULL)?
IO_CFU_USE => false -- implement custom functions unit (CFU)?
)
port map (
-- Global control --
/sim/ghdl/ghdl_sim.sh
24,12 → 24,12
 
# List files
echo "Simulation source files:"
ls -al $srcdir_core
ls -al $srcdir_sim
ls -l $srcdir_core
ls -l $srcdir_sim
 
# Just a hint
echo ""
echo "Tip: Compile application with USER_FLAGS+=-DDEVNULL_UART_OVERRIDE to have faster UART/console output."
echo "Tip: Compile application with USER_FLAGS+=-DDEVNULL_UART_OVERRIDE to have faster UART/console output via NEORV32.DEVNULL."
echo ""
 
# Analyse sources; libs and images at first!
39,6 → 39,7
#
ghdl -a --work=neorv32 $srcdir_core/neorv32_boot_rom.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_busswitch.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cfu.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_alu.vhd
ghdl -a --work=neorv32 $srcdir_core/neorv32_cpu_bus.vhd
/sim/vivado/neorv32_tb_behav.wcfg
12,15 → 12,15
</db_ref>
</db_ref_list>
<zoom_setting>
<ZoomStartTime time="244577083fs"></ZoomStartTime>
<ZoomEndTime time="245084584fs"></ZoomEndTime>
<Cursor1Time time="244825000fs"></Cursor1Time>
<ZoomStartTime time="820966fs"></ZoomStartTime>
<ZoomEndTime time="923467fs"></ZoomEndTime>
<Cursor1Time time="866866fs"></Cursor1Time>
</zoom_setting>
<column_width_setting>
<NameColumnWidth column_width="203"></NameColumnWidth>
<ValueColumnWidth column_width="102"></ValueColumnWidth>
<ValueColumnWidth column_width="94"></ValueColumnWidth>
</column_width_setting>
<WVObjectSize size="95" />
<WVObjectSize size="112" />
<wvobject type="divider" fp_name="divider273">
<obj_property name="label">CPU: Control.FETCH</obj_property>
<obj_property name="DisplayName">label</obj_property>
127,80 → 127,6
<obj_property name="ElementShortName">execute_engine</obj_property>
<obj_property name="ObjectShortName">execute_engine</obj_property>
<obj_property name="isExpanded"></obj_property>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state" type="other">
<obj_property name="ElementShortName">.state</obj_property>
<obj_property name="ObjectShortName">.state</obj_property>
<obj_property name="CustomSignalColor">#FF00FF</obj_property>
<obj_property name="UseCustomSignalColor">true</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state_prev" type="other">
<obj_property name="ElementShortName">.state_prev</obj_property>
<obj_property name="ObjectShortName">.state_prev</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.state_nxt" type="other">
<obj_property name="ElementShortName">.state_nxt</obj_property>
<obj_property name="ObjectShortName">.state_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.i_reg" type="array">
<obj_property name="ElementShortName">.i_reg[31:0]</obj_property>
<obj_property name="ObjectShortName">.i_reg[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.i_reg_nxt" type="array">
<obj_property name="ElementShortName">.i_reg_nxt[31:0]</obj_property>
<obj_property name="ObjectShortName">.i_reg_nxt[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_ci" type="logic">
<obj_property name="ElementShortName">.is_ci</obj_property>
<obj_property name="ObjectShortName">.is_ci</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_ci_nxt" type="logic">
<obj_property name="ElementShortName">.is_ci_nxt</obj_property>
<obj_property name="ObjectShortName">.is_ci_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_jump" type="logic">
<obj_property name="ElementShortName">.is_jump</obj_property>
<obj_property name="ObjectShortName">.is_jump</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.is_jump_nxt" type="logic">
<obj_property name="ElementShortName">.is_jump_nxt</obj_property>
<obj_property name="ObjectShortName">.is_jump_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.branch_taken" type="logic">
<obj_property name="ElementShortName">.branch_taken</obj_property>
<obj_property name="ObjectShortName">.branch_taken</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc" type="array">
<obj_property name="ElementShortName">.pc[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.pc_nxt" type="array">
<obj_property name="ElementShortName">.pc_nxt[31:0]</obj_property>
<obj_property name="ObjectShortName">.pc_nxt[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.next_pc" type="array">
<obj_property name="ElementShortName">.next_pc[31:0]</obj_property>
<obj_property name="ObjectShortName">.next_pc[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.last_pc" type="array">
<obj_property name="ElementShortName">.last_pc[31:0]</obj_property>
<obj_property name="ObjectShortName">.last_pc[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.sleep" type="logic">
<obj_property name="ElementShortName">.sleep</obj_property>
<obj_property name="ObjectShortName">.sleep</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.sleep_nxt" type="logic">
<obj_property name="ElementShortName">.sleep_nxt</obj_property>
<obj_property name="ObjectShortName">.sleep_nxt</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.if_rst" type="logic">
<obj_property name="ElementShortName">.if_rst</obj_property>
<obj_property name="ObjectShortName">.if_rst</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_control_inst/execute_engine.if_rst_nxt" type="logic">
<obj_property name="ElementShortName">.if_rst_nxt</obj_property>
<obj_property name="ObjectShortName">.if_rst_nxt</obj_property>
</wvobject>
</wvobject>
<wvobject type="divider" fp_name="divider139">
<obj_property name="label">CPU: Control.TRAP</obj_property>
355,12 → 281,10
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/cpu_i" type="array">
<obj_property name="ElementShortName">cpu_i</obj_property>
<obj_property name="ObjectShortName">cpu_i</obj_property>
<obj_property name="isExpanded"></obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/cpu_d" type="array">
<obj_property name="ElementShortName">cpu_d</obj_property>
<obj_property name="ObjectShortName">cpu_d</obj_property>
<obj_property name="isExpanded"></obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cpu_inst/neorv32_cpu_bus_inst/PMP_USE" type="other">
<obj_property name="ElementShortName">PMP_USE</obj_property>
482,4 → 406,72
<obj_property name="ElementShortName">acc_en</obj_property>
<obj_property name="ObjectShortName">acc_en</obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider238">
<obj_property name="label">EXT_MEM Interface</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_adr_o" type="array">
<obj_property name="ElementShortName">wb_adr_o[31:0]</obj_property>
<obj_property name="ObjectShortName">wb_adr_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_dat_i" type="array">
<obj_property name="ElementShortName">wb_dat_i[31:0]</obj_property>
<obj_property name="ObjectShortName">wb_dat_i[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_dat_o" type="array">
<obj_property name="ElementShortName">wb_dat_o[31:0]</obj_property>
<obj_property name="ObjectShortName">wb_dat_o[31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_we_o" type="logic">
<obj_property name="ElementShortName">wb_we_o</obj_property>
<obj_property name="ObjectShortName">wb_we_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_sel_o" type="array">
<obj_property name="ElementShortName">wb_sel_o[3:0]</obj_property>
<obj_property name="ObjectShortName">wb_sel_o[3:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_stb_o" type="logic">
<obj_property name="ElementShortName">wb_stb_o</obj_property>
<obj_property name="ObjectShortName">wb_stb_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_cyc_o" type="logic">
<obj_property name="ElementShortName">wb_cyc_o</obj_property>
<obj_property name="ObjectShortName">wb_cyc_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_ack_i" type="logic">
<obj_property name="ElementShortName">wb_ack_i</obj_property>
<obj_property name="ObjectShortName">wb_ack_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/wb_err_i" type="logic">
<obj_property name="ElementShortName">wb_err_i</obj_property>
<obj_property name="ObjectShortName">wb_err_i</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/fence_o" type="logic">
<obj_property name="ElementShortName">fence_o</obj_property>
<obj_property name="ObjectShortName">fence_o</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/fencei_o" type="logic">
<obj_property name="ElementShortName">fencei_o</obj_property>
<obj_property name="ObjectShortName">fencei_o</obj_property>
</wvobject>
<wvobject type="divider" fp_name="divider238">
<obj_property name="label">IO: CFU</obj_property>
<obj_property name="DisplayName">label</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cfu_inst_true/neorv32_cfu_inst/wr_en" type="logic">
<obj_property name="ElementShortName">wr_en</obj_property>
<obj_property name="ObjectShortName">wr_en</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cfu_inst_true/neorv32_cfu_inst/rd_en" type="logic">
<obj_property name="ElementShortName">rd_en</obj_property>
<obj_property name="ObjectShortName">rd_en</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cfu_inst_true/neorv32_cfu_inst/cfu_reg_in" type="array">
<obj_property name="ElementShortName">cfu_reg_in[0:3][31:0]</obj_property>
<obj_property name="ObjectShortName">cfu_reg_in[0:3][31:0]</obj_property>
</wvobject>
<wvobject fp_name="/neorv32_tb/neorv32_top_inst/neorv32_cfu_inst_true/neorv32_cfu_inst/cfu_reg_out" type="array">
<obj_property name="ElementShortName">cfu_reg_out[0:3][31:0]</obj_property>
<obj_property name="ObjectShortName">cfu_reg_out[0:3][31:0]</obj_property>
</wvobject>
</wave_config>
/sim/neorv32_tb.vhd
60,6 → 60,7
constant baud_rate_c : real := 19200.0; -- standard UART baudrate
constant wb_mem_base_addr_c : std_ulogic_vector(31 downto 0) := x"F0000000"; -- wishbone memory base address
constant wb_mem_size_c : natural := 256; -- wishbone memory size in bytes
constant wb_mem_latency_c : natural := 8; -- latency in clock cycles (min 1)
-- -------------------------------------------------------------------------------------------
 
-- text.io --
103,16 → 104,18
end record;
signal wb_cpu : wishbone_t;
 
-- Wishbone memory --
type wb_mem_ram_t is array (0 to wb_mem_size_c/4-1) of std_ulogic_vector(31 downto 0);
type wb_mem_read_latency_t is array (0 to wb_mem_latency_c-1) of std_ulogic_vector(31 downto 0);
type wb_mem_t is record
ram : wb_mem_ram_t;
rdata : wb_mem_read_latency_t;
acc_en : std_ulogic;
ack : std_ulogic_vector(wb_mem_latency_c-1 downto 0);
rb_en : std_ulogic_vector(wb_mem_latency_c-1 downto 0);
end record;
signal wb_mem : wb_mem_t;
 
-- Wishbone memory, SimCom --
type wb_mem_file_t is array (0 to wb_mem_size_c/4-1) of std_ulogic_vector(31 downto 0);
signal wb_mem_file : wb_mem_file_t := (others => (others => '0'));
signal rb_en : std_ulogic;
signal r_data : std_ulogic_vector(31 downto 0);
signal wb_acc_en : std_ulogic;
signal wb_mem_rdata : std_ulogic_vector(31 downto 0);
signal wb_mem_ack : std_ulogic;
 
begin
 
-- Clock/Reset Generator ------------------------------------------------------------------
137,24 → 140,19
CPU_EXTENSION_RISCV_Zicsr => true, -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei => true, -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE => true, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN => false, -- use DSPs for M extension's multiplier
-- Physical Memory Protection (PMP) --
PMP_USE => true, -- implement PMP?
PMP_NUM_REGIONS => 4, -- number of regions (max 16)
PMP_GRANULARITY => 14, -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE => x"00000000", -- base address of instruction memory space
MEM_ISPACE_SIZE => 16*1024, -- total size of instruction memory space in byte
-- Internal Instruction memory --
MEM_INT_IMEM_USE => true, -- implement processor-internal instruction memory
MEM_INT_IMEM_SIZE => 16*1024, -- size of processor-internal instruction memory in bytes
MEM_INT_IMEM_ROM => false, -- implement processor-internal instruction memory as ROM
-- Memory configuration: Data memory --
MEM_DSPACE_BASE => x"80000000", -- base address of data memory space
MEM_DSPACE_SIZE => 8*1024, -- total size of data memory space in byte
-- Internal Data memory --
MEM_INT_DMEM_USE => true, -- implement processor-internal data memory
MEM_INT_DMEM_SIZE => 8*1024, -- size of processor-internal data memory in bytes
-- Memory configuration: External memory interface --
-- 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)
MEM_EXT_TIMEOUT => 15, -- cycles after which a valid bus access will timeout
166,8 → 164,9
IO_TWI_USE => true, -- implement two-wire interface (TWI)?
IO_PWM_USE => true, -- implement pulse-width modulation unit (PWM)?
IO_WDT_USE => true, -- implement watch dog timer (WDT)?
IO_TRNG_USE => false, -- CANNOT BE SIMULATED!
IO_DEVNULL_USE => true -- implement dummy device (DEVNULL)?
IO_TRNG_USE => false, -- DEFAULT TRNG CONFIG CANNOT BE SIMULATED!
IO_DEVNULL_USE => true, -- implement dummy device (DEVNULL)?
IO_CFU_USE => true -- implement custom functions unit (CFU)?
)
port map (
-- Global control --
210,12 → 209,7
twi_scl <= 'H';
twi_sda <= 'H';
 
-- Wishbone read-back --
wb_cpu.rdata <= wb_mem_rdata;
wb_cpu.ack <= wb_mem_ack;
wb_cpu.err <= '0';
 
 
-- Console UART Receiver ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
uart_rx_console: process(clk_gen)
270,27 → 264,40
 
-- Wishbone Memory ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
wb_mem_file_access: process(clk_gen)
begin
if rising_edge(clk_gen) then
rb_en <= wb_cpu.cyc and wb_cpu.stb and wb_acc_en and (not wb_cpu.we); -- read-back control
wb_mem_ack <= wb_cpu.cyc and wb_cpu.stb and wb_acc_en; -- wishbone acknowledge
if ((wb_cpu.cyc and wb_cpu.stb and wb_acc_en and wb_cpu.we) = '1') then -- valid write access
for i in 0 to 3 loop
if (wb_cpu.sel(i) = '1') then
wb_mem_file(to_integer(unsigned(wb_cpu.addr(index_size_f(wb_mem_size_c/4)+1 downto 2))))(7+i*8 downto 0+i*8) <= wb_cpu.wdata(7+i*8 downto 0+i*8);
end if;
end loop; -- i
end if;
r_data <= wb_mem_file(to_integer(unsigned(wb_cpu.addr(index_size_f(wb_mem_size_c/4)+1 downto 2)))); -- word aligned
wb_mem_ram_access: process(clk_gen)
begin
if rising_edge(clk_gen) then
-- control --
wb_mem.rb_en(0) <= wb_cpu.cyc and wb_cpu.stb and wb_mem.acc_en and (not wb_cpu.we); -- read-back control
wb_mem.ack(0) <= wb_cpu.cyc and wb_cpu.stb and wb_mem.acc_en; -- wishbone acknowledge
-- write access --
if ((wb_cpu.cyc and wb_cpu.stb and wb_mem.acc_en and wb_cpu.we) = '1') then -- valid write access
for i in 0 to 3 loop
if (wb_cpu.sel(i) = '1') then
wb_mem.ram(to_integer(unsigned(wb_cpu.addr(index_size_f(wb_mem_size_c/4)+1 downto 2))))(7+i*8 downto 0+i*8) <= wb_cpu.wdata(7+i*8 downto 0+i*8);
end if;
end loop; -- i
end if;
end process wb_mem_file_access;
-- read access --
wb_mem.rdata(0) <= wb_mem.ram(to_integer(unsigned(wb_cpu.addr(index_size_f(wb_mem_size_c/4)+1 downto 2)))); -- word aligned
-- virtual read and ack latency --
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.ack(i) <= wb_mem.ack(i-1);
end loop;
end if;
end if;
end process wb_mem_ram_access;
 
-- wb mem access --
wb_acc_en <= '1' when (wb_cpu.addr >= wb_mem_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(wb_mem_base_addr_c) + wb_mem_size_c)) else '0';
-- wishbone memory access? --
wb_mem.acc_en <= '1' when (wb_cpu.addr >= wb_mem_base_addr_c) and (wb_cpu.addr < std_ulogic_vector(unsigned(wb_mem_base_addr_c) + wb_mem_size_c)) else '0';
 
-- output gate --
wb_mem_rdata <= r_data when (rb_en = '1') else (others=> '0');
-- 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);
wb_cpu.err <= '0';
 
 
end neorv32_tb_rtl;
/sw/bootloader/bootloader.c
227,11 → 227,11
neorv32_uart_print("\nCONF: ");
print_hex_word(SYSINFO_FEATURES);
neorv32_uart_print("\nIMEM: ");
print_hex_word(SYSINFO_ISPACE_SIZE);
print_hex_word(SYSINFO_IMEM_SIZE);
neorv32_uart_print(" bytes @ ");
print_hex_word(SYSINFO_ISPACE_BASE);
neorv32_uart_print("\nDMEM: ");
print_hex_word(SYSINFO_DSPACE_SIZE);
print_hex_word(SYSINFO_DMEM_SIZE);
neorv32_uart_print(" bytes @ ");
print_hex_word(SYSINFO_DSPACE_BASE);
 
323,12 → 323,12
return;
}
 
// no need to shutdown or reset the used peripherals
// no need to shut down or reset the used peripherals
// no need to disable interrupt sources
// -> this will be done by application's crt0
 
// deactivate IRQs and IRQ sources
// deactivate global IRQs
neorv32_cpu_dint();
neorv32_cpu_csr_write(CSR_MIE, 0);
 
neorv32_uart_print("Booting...\n\n");
 
336,10 → 336,10
while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
 
// reset performance counters (to benchmark actual application)
asm volatile ("csrw mcycle, zero"); // will also clear 'cycle'
asm volatile ("csrw mcycleh, zero"); // will also clear 'cycleh'
asm volatile ("csrw minstret, zero"); // will also clear 'instret'
asm volatile ("csrw minstreth, zero"); // will also clear 'instreth'
asm volatile ("csrw mcycle, zero"); // also clears 'cycle'
asm volatile ("csrw mcycleh, zero"); // also clears 'cycleh'
asm volatile ("csrw minstret, zero"); // also clears 'instret'
asm volatile ("csrw minstreth, zero"); // also clears 'instreth'
 
// start app at instruction space base address
register uint32_t app_base = SYSINFO_ISPACE_BASE;
349,8 → 349,7
 
 
/**********************************************************************//**
* Bootloader trap handler.
* Primarily used for the MTIME tick.
* Bootloader trap handler. Used for the MTIME tick and to capture any other traps.
* @warning Since we have no runtime environment, we have to use the interrupt attribute here. Here, and only here!
**************************************************************************/
void __attribute__((__interrupt__)) bootloader_trap_handler(void) {
357,15 → 356,7
 
// make sure this was caused by MTIME IRQ
uint32_t cause = neorv32_cpu_csr_read(CSR_MCAUSE);
if (cause != TRAP_CODE_MTI) { // raw exception code for MTI
neorv32_uart_print("\n\nEXCEPTION (");
print_hex_word(cause);
neorv32_uart_print(") @ 0x");
print_hex_word(neorv32_cpu_csr_read(CSR_MEPC));
system_error(ERROR_SYSTEM);
while(1); // freeze
}
else {
if (cause == TRAP_CODE_MTI) { // raw exception code for MTI
if (STATUS_LED_EN == 1) {
// toggle status LED
neorv32_gpio_pin_toggle(STATUS_LED);
373,6 → 364,18
// set time for next IRQ
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + (SYSINFO_CLK/4));
}
 
else if (cause == TRAP_CODE_S_ACCESS) { // seems like executable is too large
system_error(ERROR_SIZE);
}
 
else {
neorv32_uart_print("\n\nEXCEPTION (");
print_hex_word(cause);
neorv32_uart_print(") @ 0x");
print_hex_word(neorv32_cpu_csr_read(CSR_MEPC));
system_error(ERROR_SYSTEM);
}
}
 
 
414,12 → 417,6
uint32_t size = get_exe_word(src, addr + EXE_OFFSET_SIZE); // size in bytes
uint32_t check = get_exe_word(src, addr + EXE_OFFSET_CHECKSUM); // complement sum checksum
 
// executable too large?
uint32_t imem_size = SYSINFO_ISPACE_SIZE;
if (size > imem_size) {
system_error(ERROR_SIZE);
}
 
// transfer program data
uint32_t *pnt = (uint32_t*)SYSINFO_ISPACE_BASE;
uint32_t checksum = 0;
548,7 → 545,7
**************************************************************************/
void system_error(uint8_t err_code) {
 
neorv32_uart_print("\a\nBootloader ERR_"); // output error code with annoying bell sound
neorv32_uart_print("\a\nERROR_"); // output error code with annoying bell sound
neorv32_uart_putc('0' + ((char)err_code)); // FIXME err_code should/must be below 10
 
neorv32_cpu_dint(); // deactivate IRQs
/sw/common/crt0.S
41,11 → 41,7
// IO region
.equ IO_BEGIN, 0xFFFFFF80 // start of processor-internal IO region
 
// SYSINFO
.equ SYSINFO_DSPACE_BASE, 0xFFFFFFF4
.equ SYSINFO_DSPACE_SIZE, 0xFFFFFFFC
 
 
_start:
.cfi_startproc
.cfi_undefined ra
68,29 → 64,30
//addi x10, x0, 0
//addi x11, x0, 0
//addi x12, x0, 0
addi x13, x0, 0
//addi x13, x0, 0
addi x14, x0, 0
addi x15, x0, 0
 
 
// *********************************************************
// Setup stack pointer
// No interrupts, thanks
// *********************************************************
__crt0_stack_pointer_init:
lw x11, SYSINFO_DSPACE_BASE(zero) // data memory space base address
lw x12, SYSINFO_DSPACE_SIZE(zero) // data memory space size
add sp, x11, x12
addi sp, sp, -4 // stack pointer = last entry
addi fp, sp, 0 // frame pointer = stack pointer
__crt0_status_init:
li x10, 0x00001800 // clear mstatus and set mpp(1:0)
csrrw zero, mstatus, x10
csrrw zero, mie, zero // clear mie
 
 
// *********************************************************
// Setup global pointer
// Setup pointers using linker script symbol
// *********************************************************
__crt0_global_pointer_init:
__crt0_pointer_init:
.option push
.option norelax
la gp, __global_pointer$
la sp, __crt0_stack_begin
andi sp, sp, 0xfffffffc // make sure this is aligned
addi fp, sp, 0 // frame pointer = stack pointer
la gp, __global_pointer$ // global pointer
.option pop
 
 
117,7 → 114,7
 
 
// *********************************************************
// Clear .bss section (byte-wise)
// Clear .bss section (byte-wise) using linker script symbols
// *********************************************************
__crt0_clear_bss:
la x11, __crt0_bss_start
133,7 → 130,7
 
 
// *********************************************************
// Copy initialized .data section from ROM to RAM (byte-wise)
// Copy initialized .data section from ROM to RAM (byte-wise) using linker script symbols
// *********************************************************
__crt0_copy_data:
la x11, __crt0_copy_data_src_begin // start of data area (copy source)
189,6 → 186,7
csrr x8, mepc
 
// is compressed instruction?
__crt0_dummy_trap_handler_exc_c_check:
lh x9, 0(x8) // get compressed instruction or lower 16 bits of uncompressed instruction that caused exception
andi x9, x9, 3 // mask: isolate lowest 2 opcode bits (= 11 for uncompressed instructions)
 
199,6 → 197,7
bne x8, x9, __crt0_dummy_trap_handler_irq // jump if compressed instruction
// is uncompressed instruction
__crt0_dummy_trap_handler_exc_uncrompressed:
csrr x8, mepc
addi x8, x8, +2 // add another 2 (making +4) for uncompressed instructions
csrw mepc, x8
205,9 → 204,9
 
__crt0_dummy_trap_handler_irq:
 
lw x9, 0(sp)
lw x8, 4(sp)
addi sp, sp, +8
lw x9, 0(sp)
lw x8, 4(sp)
addi sp, sp, +8
 
mret
 
/sw/common/neorv32.ld
46,21 → 46,23
ENTRY(_start)
SEARCH_DIR("=/opt/riscv/riscv64-unknown-linux-gnu/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
 
/* ************************************************* */
/* NEORV32 memory configuration. */
/* Make sure this is sync with your processor/ */
/* memory hardware configuration. */
/* ************************************************* */
/* ************************************************************************* */
/* NEORV32 memory configuration. */
/* Make sure this is sync with your processor/memory hardware configuration. */
/* ************************************************************************* */
MEMORY
{
/* rom section: first value of ORIGIN/LENGHT: bootloader ROM; second value of ORIGIN/LENGHT: IMEM */
/* "rom" section: first value of ORIGIN/LENGHT => bootloader ROM; second value of ORIGIN/LENGHT => instruction memory */
 
rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 4*1024 : 16*1024
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 8*1024
}
/* ************************************************* */
/* ************************************************************************* */
 
SECTIONS
{
/* stack pointer init: last 32-bit entry in data memory */
__crt0_stack_begin = (ORIGIN(ram) + LENGTH(ram)) - 4;
 
/* start section on WORD boundary */
. = ALIGN(4);
284,8 → 286,8
 
 
/* Provide further symbols for neorv32 crt0.elf */
PROVIDE(__crt0_bss_start = __bss_start);
PROVIDE(__crt0_bss_end = __BSS_END__);
PROVIDE(__crt0_bss_start = __bss_start);
PROVIDE(__crt0_bss_end = __BSS_END__);
PROVIDE(__crt0_copy_data_src_begin = __etext + SIZEOF(.rodata));
PROVIDE(__crt0_copy_data_dst_begin = __DATA_BEGIN__);
PROVIDE(__crt0_copy_data_dst_end = __DATA_BEGIN__ + SIZEOF(.data));
/sw/example/blink_led/blink_led_in_asm.S
0,0 → 1,37
.file "blink_led_in_asm.S"
.section .text
.balign 4
.global blink_led_asm
 
blink_led_asm:
 
/* base address of GPIO controller's output port is passed as argument (in a0)*/
sw zero, 0(a0) /* clear output port */
 
li t1, 0 /* initialize counter */
 
 
blink_loop:
andi t1, t1, 255 /* apply 8-bit mask */
sw t1, 0(a0) /* output current counter value */
addi t1, t1, 1 /* increment counter */
 
jal ra, blink_delay /* call delay function */
 
j blink_loop
 
 
blink_delay:
li t2, 0xfffff /* delay time */
 
blink_delay_loop:
beq t2, zero, blink_delay_end
addi t2, t2, -1
nop
nop
j blink_delay_loop
 
blink_delay_end:
ret
 
.end
/sw/example/blink_led/main.c
48,10 → 48,18
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
/** Use the custom ASM version for blinking the LEDs if != 0 */
#define USE_ASM_VERSION 0
/**@}*/
 
 
/**********************************************************************//**
* ASM function to blink LEDs (if enabled)
**************************************************************************/
extern void blink_led_asm(uint32_t gpio_out_addr);
 
 
/**********************************************************************//**
* Main function; shows an incrementing 8-bit counter on GPIO.output(7:0).
*
* @note This program requires the GPIO controller to be synthesized (the UART is optional).
76,6 → 84,10
// say hello
neorv32_uart_print("Blinking LED demo program\n");
 
 
// use C version of LED blinking
#if (USE_ASM_VERSION == 0)
 
neorv32_gpio_port_set(0); // clear gpio output put
 
int cnt = 0;
85,5 → 97,11
neorv32_cpu_delay_ms(200); // wait 200ms using busy wait
}
 
// use ASM version of LED blinking (file: blink_led_in_asm.S)
#else
 
blink_led_asm((uint32_t)(&GPIO_OUTPUT));
 
#endif
return 0;
}
/sw/example/cpu_test/main.c
604,7 → 604,7
 
 
// ----------------------------------------------------------
// Fast interrupt
// Fast interrupt channel 0 (WDT)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("FIRQ0 (WDT): ");
631,7 → 631,7
test_fail();
}
#endif
// no more mtime interrupts
// no more WDT interrupts
neorv32_wdt_disable();
}
else {
640,6 → 640,128
 
 
// ----------------------------------------------------------
// Fast interrupt channel 2 (UART)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("FIRQ2 (UART): ");
 
if (neorv32_uart_available()) {
cnt_test++;
 
// wait for UART to finish transmitting
while(neorv32_uart_tx_busy());
 
// enable UART TX done IRQ
UART_CT |= (1 << UART_CT_TX_IRQ);
 
// trigger UART TX IRQ
UART_DATA = 0; // we need to access the raw HW here, since >DEVNULL_UART_OVERRIDE< might be active
 
// wait for UART to finish transmitting
while(neorv32_uart_tx_busy());
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == TRAP_CODE_FIRQ_2) {
test_ok();
}
else {
test_fail();
}
#endif
// wait for UART to finish transmitting
while(neorv32_uart_tx_busy());
 
// disable UART TX done IRQ
UART_CT &= ~(1 << UART_CT_TX_IRQ);
}
else {
neorv32_uart_printf("skipped (UART not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 3 (SPI)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("FIRQ3 (SPI): ");
 
if (neorv32_spi_available()) {
cnt_test++;
 
// configure SPI, enable transfer-done IRQ
neorv32_spi_setup(CLK_PRSC_2, 0, 0, 0, 1);
 
// trigger SPI IRQ
neorv32_spi_trans(0);
while(neorv32_spi_busy()); // wait for current transfer to finish
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == TRAP_CODE_FIRQ_3) {
test_ok();
}
else {
test_fail();
}
#endif
// disable SPI
neorv32_spi_disable();
}
else {
neorv32_uart_printf("skipped (SPI not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Fast interrupt channel 3 (TWI)
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
neorv32_uart_printf("FIRQ3 (TWI): ");
 
if (neorv32_twi_available()) {
cnt_test++;
 
// configure TWI, fastest clock, transfer-done IRQ enable
neorv32_twi_setup(CLK_PRSC_2, 1);
 
// trigger TWI IRQ
neorv32_twi_trans(0);
neorv32_twi_generate_stop();
 
// wait some time for the IRQ to arrive the CPU
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
 
#if (DETAILED_EXCEPTION_DEBUG==0)
if (exception_handler_answer == TRAP_CODE_FIRQ_3) {
test_ok();
}
else {
test_fail();
}
#endif
// disable TWI
neorv32_twi_disable();
}
else {
neorv32_uart_printf("skipped (TWI not implemented)\n");
}
 
 
// ----------------------------------------------------------
// Test WFI ("sleep") instructions, wakeup via MTIME
// ----------------------------------------------------------
exception_handler_answer = 0xFFFFFFFF;
886,8 → 1008,8
exe_cycles.uint64 = neorv32_cpu_get_cycle();
exe_instr.uint64 = neorv32_cpu_get_instret();
 
neorv32_uart_printf("\n\nExecuted instructions: 0x%x_%x\n", exe_instr.uint32[1], exe_instr.uint32[0]);
neorv32_uart_printf( "Clock cycles: 0x%x_%x\n", exe_cycles.uint32[1], exe_cycles.uint32[0]);
neorv32_uart_printf("\n\nExecuted instructions: %u\n", exe_instr.uint32[0]);
neorv32_uart_printf( "Required clock cycles: %u\n", exe_cycles.uint32[0]);
 
neorv32_uart_printf("\nTests: %i\nOK: %i\nFAIL: %i\n\n", cnt_test, cnt_ok, cnt_fail);
 
/sw/example/demo_trng/main.c
64,8 → 64,9
uint8_t lucky_numbers_5of50[5];
uint8_t lucky_numbers_2of10[2];
 
uint8_t i, j, tmp;
uint16_t trng_data;
int err;
uint8_t i, j, probe;
uint8_t trng_data;
unsigned int num_samples;
 
// check if UART unit is implemented at all
73,7 → 74,6
return 0;
}
 
 
// capture all exceptions and give debug info via UART
// this is not required, but keeps us safe
neorv32_rte_setup();
91,11 → 91,8
return 0;
}
 
// configure TRNG with defaul GARO tap mask
neorv32_uart_printf("Configuring TRNG...\n");
uint16_t trng_tap_config = neorv32_trng_find_tap_mask();
neorv32_uart_printf("TRNG: Using tap mask: 0x%x ", (uint32_t)trng_tap_config);
neorv32_trng_setup(trng_tap_config);
// enable TRNG
neorv32_trng_enable();
 
while(1) {
 
113,11 → 110,12
if (cmd == 'n') {
num_samples = 0;
while(1) {
if (neorv32_trng_get(&trng_data)) {
neorv32_uart_printf("\nTRNG error!\n");
err = neorv32_trng_get(&trng_data);
if (err) {
neorv32_uart_printf("\nTRNG error (%i)!\n", err);
break;
}
neorv32_uart_printf("%u ", (uint32_t)(trng_data & 0xFF));
neorv32_uart_printf("%u ", (uint32_t)(trng_data));
num_samples++;
if (neorv32_uart_char_received()) { // abort when key pressed
neorv32_uart_printf("\nPrinted samples: %u", num_samples);
128,7 → 126,7
 
// print lucky numbers
if (cmd == 'l') {
// reset array
// reset arrays
for (i=0; i<5; i++) {
lucky_numbers_5of50[i] = 0;
}
138,45 → 136,57
// get numbers
i = 0;
while (i<5) {
if (neorv32_trng_get(&trng_data)) {
neorv32_uart_printf("\nTRNG error!\n");
err = neorv32_trng_get(&trng_data);
if (err) {
neorv32_uart_printf("\nTRNG error (%i)!\n", err);
break;
}
// valid range?
tmp = (uint8_t)(trng_data & 0xff);
if ((tmp == 0) || (tmp > 50)) {
if ((trng_data == 0) || (trng_data > 50)) {
continue;
}
// already sampled?
probe = 0;
for (j=0; j<5; j++) {
if (lucky_numbers_5of50[j] == tmp) {
continue;
if (lucky_numbers_5of50[j] == trng_data) {
probe++;
}
}
lucky_numbers_5of50[i] = tmp;
i++;
if (probe) {
continue;
}
else {
lucky_numbers_5of50[i] = trng_data;
i++;
}
}
 
// get numbers part 2
i = 0;
while (i<2) {
if (neorv32_trng_get(&trng_data)) {
neorv32_uart_printf("\nTRNG error!\n");
err = neorv32_trng_get(&trng_data);
if (err) {
neorv32_uart_printf("\nTRNG error (%i)!\n", err);
break;
}
// valid range?
tmp = (uint8_t)(trng_data & 0xff);
if ((tmp == 0) || (tmp > 10)) {
if ((trng_data == 0) || (trng_data > 10)) {
continue;
}
// already sampled?
probe = 0;
for (j=0; j<2; j++) {
if (lucky_numbers_2of10[j] == tmp) {
continue;
if (lucky_numbers_2of10[j] == trng_data) {
probe++;
}
}
lucky_numbers_2of10[i] = tmp;
i++;
if (probe) {
continue;
}
else {
lucky_numbers_2of10[i] = trng_data;
i++;
}
}
 
// output
/sw/example/game_of_life/main.c
106,7 → 106,7
int u = 0, cell = 0, n = 0;
int x, y;
int trng_available = 0;
uint16_t trng_data;
uint8_t trng_data;
 
 
// initialize universe
123,9 → 123,8
 
// check if TRNG was synthesized
if (neorv32_trng_available()) {
uint16_t trng_tap_config = neorv32_trng_find_tap_mask();
neorv32_trng_setup(trng_tap_config);
neorv32_uart_printf("\nTRNG detected (tap mask 0x%x). Using TRNG for universe initialization.\n", (uint32_t)trng_tap_config);
neorv32_uart_printf("\nTRNG detected. Using TRNG for universe initialization.\n");
neorv32_trng_enable();
trng_available = 1;
}
 
140,11 → 139,17
for (x=0; x<NUM_CELLS_X/8; x++) {
for (y=0; y<NUM_CELLS_Y; y++) {
if (trng_available) {
if (neorv32_trng_get(&trng_data)) {
neorv32_uart_printf("TRNG error!\n");
return 1;
while (1) {
int err = neorv32_trng_get(&trng_data);
if (err) {
neorv32_uart_printf("TRNG error (%i)! Restarting TRNG...\n", err);
continue;
}
else {
break;
}
}
universe[0][x][y] = (uint8_t)trng_data; // use data from TRNG
universe[0][x][y] = trng_data; // use data from TRNG
}
else {
universe[0][x][y] = (uint8_t)xorshift32(); // use data from PRNG
/sw/image_gen/image_gen.cpp
181,7 → 181,7
"package neorv32_application_image is\n"
"\n"
" type application_init_image_t is array (0 to %lu) of std_ulogic_vector(31 downto 0);\n"
" constant application_init_image : application_init_image_t := (\n", argv[4], argv[2], (raw_exe_size/4)+1);
" constant application_init_image : application_init_image_t := (\n", argv[4], argv[2], raw_exe_size/4);
fputs(tmp_string, output);
 
// data
230,7 → 230,7
"package neorv32_bootloader_image is\n"
"\n"
" type bootloader_init_image_t is array (0 to %lu) of std_ulogic_vector(31 downto 0);\n"
" constant bootloader_init_image : bootloader_init_image_t := (\n", argv[4], argv[2], (raw_exe_size/4)+1);
" constant bootloader_init_image : bootloader_init_image_t := (\n", argv[4], argv[2], raw_exe_size/4);
fputs(tmp_string, output);
 
// data
/sw/lib/include/neorv32.h
220,9 → 220,9
**************************************************************************/
/**@{*/
/** instruction memory base address (r/w/x) */
// -> use value from MEM_ISPACE_BASE generic
// -> configured via ispace_base_c constant in neorv32_package.vhd and available to SW via SYSCONFIG entry
/** data memory base address (r/w/x) */
// -> use value from MEM_DSPACE_BASE generic
// -> configured via dspace_base_c constant in neorv32_package.vhd and available to SW via SYSCONFIG entry
/** bootloader memory base address (r/-/x) */
#define BOOTLOADER_BASE_ADDRESS (0xFFFF0000UL)
/** peripheral/IO devices memory base address (r/w/x) */
234,8 → 234,8
* @name IO Device: General Purpose Input/Output Port Unit (GPIO)
**************************************************************************/
/**@{*/
/** GPIO parallel input port 32-bit (r/-) */
#define GPIO_INPUT (*(IO_ROM32 0xFFFFFF80UL))
/** read access: GPIO parallel input port 32-bit (r/-), write_access: pin-change IRQ for each input pin (-/w) */
#define GPIO_INPUT (*(IO_REG32 0xFFFFFF80UL))
/** GPIO parallel output port 32-bit (r/w) */
#define GPIO_OUTPUT (*(IO_REG32 0xFFFFFF84UL))
/**@}*/
442,24 → 442,34
* @name IO Device: True Random Number Generator (TRNG)
**************************************************************************/
/**@{*/
/** TRNG control register (r/w) */
/** TRNG control/data register (r/w) */
#define TRNG_CT (*(IO_REG32 0xFFFFFFC0UL))
/** TRNG data register (r/-) */
#define TRNG_DATA (*(IO_ROM32 0xFFFFFFC4UL))
 
/** TRNG control register bits */
/** TRNG control/data register bits */
enum NEORV32_TRNG_CT_enum {
TRNG_CT_TAP_LSB = 0, /**< TRNG control register(0) (r/w): TAP mask (16-bit) LSB */
TRNG_CT_TAP_MSB = 15, /**< TRNG control register(15) (r/w): TAP mask (16-bit) MSB */
TRNG_CT_EN = 31 /**< TRNG control register(31) (r/w): TRNG enable */
TRNG_CT_DATA_LSB = 0, /**< TRNG data/control register(0) (r/-): Random data (8-bit) LSB */
TRNG_CT_DATA_MSB = 7, /**< TRNG data/control register(7) (r/-): Random data (8-bit) MSB */
TRNG_CT_VALID = 15, /**< TRNG data/control register(15) (r/-): Random data output valid */
TRNG_CT_ERROR_0 = 16, /**< TRNG data/control register(16) (r/-): Stuck-at-zero error */
TRNG_CT_ERROR_1 = 17, /**< TRNG data/control register(17) (r/-): Stuck-at-one error */
TRNG_CT_EN = 31 /**< TRNG data/control register(31) (r/w): TRNG enable */
};
/**@}*/
/**@}*/
 
/** WTD data register bits */
enum NEORV32_TRNG_DUTY_enum {
TRNG_DATA_LSB = 0, /**< TRNG data register(0) (r/-): Random data (16-bit) LSB */
TRNG_DATA_MSB = 15, /**< TRNG data register(15) (r/-): Random data (16-bit) MSB */
TRNG_DATA_VALID = 31 /**< TRNG data register(31) (r/-): Random data output valid */
};
 
/**********************************************************************//**
* @name IO Device: Custom Functions Unit (CFU)
**************************************************************************/
/**@{*/
/** CFU register 0 ((r)/(w)) */
#define CFU_REG_0 (*(IO_REG32 0xFFFFFFD0UL)) // (r)/(w): CFU register 0, user-defined
/** CFU register 1 ((r)/(w)) */
#define CFU_REG_1 (*(IO_REG32 0xFFFFFFD4UL)) // (r)/(w): CFU register 1, user-defined
/** CFU register 2 ((r)/(w)) */
#define CFU_REG_2 (*(IO_REG32 0xFFFFFFD8UL)) // (r)/(w): CFU register 2, user-defined
/** CFU register 3 ((r)/(w)) */
#define CFU_REG_3 (*(IO_REG32 0xFFFFFFDCUL)) // (r)/(w): CFU register 3, user-defined
/**@}*/
 
 
474,15 → 484,15
/** SYSINFO(2): Clock speed */
#define SYSINFO_FEATURES (*(IO_ROM32 0xFFFFFFE8UL))
/** SYSINFO(3): reserved */
#define SYSINFO_reserved1 (*(IO_ROM32 0xFFFFFFECUL))
#define SYSINFO_reserved (*(IO_ROM32 0xFFFFFFECUL))
/** SYSINFO(4): Instruction memory address space base */
#define SYSINFO_ISPACE_BASE (*(IO_ROM32 0xFFFFFFF0UL))
/** SYSINFO(5): Data memory address space base */
#define SYSINFO_DSPACE_BASE (*(IO_ROM32 0xFFFFFFF4UL))
/** SYSINFO(6): Instruction memory address space size in bytes */
#define SYSINFO_ISPACE_SIZE (*(IO_ROM32 0xFFFFFFF8UL))
/** SYSINFO(7): Data memory address space size in bytes */
#define SYSINFO_DSPACE_SIZE (*(IO_ROM32 0xFFFFFFFCUL))
/** SYSINFO(6): Internal instruction memory (IMEM) size in bytes */
#define SYSINFO_IMEM_SIZE (*(IO_ROM32 0xFFFFFFF8UL))
/** SYSINFO(7): Internal data memory (DMEM) size in bytes */
#define SYSINFO_DMEM_SIZE (*(IO_ROM32 0xFFFFFFFCUL))
/**@}*/
 
 
503,9 → 513,9
SYSINFO_FEATURES_IO_TWI = 20, /**< SYSINFO_FEATURES (20) (r/-): Two-wire interface implemented when 1 (via IO_TWI_USE generic) */
SYSINFO_FEATURES_IO_PWM = 21, /**< SYSINFO_FEATURES (21) (r/-): Pulse-width modulation unit implemented when 1 (via IO_PWM_USE generic) */
SYSINFO_FEATURES_IO_WDT = 22, /**< SYSINFO_FEATURES (22) (r/-): Watchdog timer implemented when 1 (via IO_WDT_USE generic) */
 
SYSINFO_FEATURES_IO_CFU = 23, /**< SYSINFO_FEATURES (23) (r/-): Custom functions unit implemented when 1 (via IO_CFU_USE generic) */
SYSINFO_FEATURES_IO_TRNG = 24, /**< SYSINFO_FEATURES (24) (r/-): True random number generator implemented when 1 (via IO_TRNG_USE generic) */
SYSINFO_FEATURES_IO_DEVNULL = 25 /**< SYSINFO_FEATURES (24) (r/-): Dummy device implemented when 1 (via IO_DEVNULL_USE generic) */
SYSINFO_FEATURES_IO_DEVNULL = 25 /**< SYSINFO_FEATURES (25) (r/-): Dummy device implemented when 1 (via IO_DEVNULL_USE generic) */
};
 
 
/sw/lib/include/neorv32_gpio.h
49,8 → 49,9
void neorv32_gpio_pin_set(uint8_t p);
void neorv32_gpio_pin_clr(uint8_t p);
void neorv32_gpio_pin_toggle(uint8_t p);
uint16_t neorv32_gpio_pin_get(uint8_t p);
void neorv32_gpio_port_set(uint16_t d);
uint16_t neorv32_gpio_port_get(void);
uint32_t neorv32_gpio_pin_get(uint8_t p);
void neorv32_gpio_port_set(uint32_t d);
uint32_t neorv32_gpio_port_get(void);
void neorv32_gpio_pin_change_config(uint32_t pin_sel);
 
#endif // neorv32_gpio_h
/sw/lib/include/neorv32_spi.h
51,5 → 51,6
void neorv32_spi_cs_en(uint8_t cs);
void neorv32_spi_cs_dis(uint8_t cs);
uint32_t neorv32_spi_trans(uint32_t tx_data);
int neorv32_spi_busy(void);
 
#endif // neorv32_spi_h
/sw/lib/include/neorv32_trng.h
46,9 → 46,8
 
// prototypes
int neorv32_trng_available(void);
int neorv32_trng_setup(uint16_t tap_mask);
uint16_t neorv32_trng_find_tap_mask(void);
void neorv32_trng_enable(void);
void neorv32_trng_disable(void);
int neorv32_trng_get(uint16_t *data);
int neorv32_trng_get(uint8_t *data);
 
#endif // neorv32_trng_h
/sw/lib/include/neorv32_twi.h
49,6 → 49,7
void neorv32_twi_setup(uint8_t prsc, uint8_t irq_en);
void neorv32_twi_disable(void);
void neorv32_twi_mack_enable(void);
int neorv32_twi_busy(void);
int neorv32_twi_start_trans(uint8_t a);
int neorv32_twi_trans(uint8_t d);
uint8_t neorv32_twi_get_data(void);
/sw/lib/include/neorv32_uart.h
52,6 → 52,7
void neorv32_uart_setup(uint32_t baudrate, uint8_t rx_irq, uint8_t tx_irq);
void neorv32_uart_disable(void);
void neorv32_uart_putc(char c);
int neorv32_uart_tx_busy(void);
char neorv32_uart_getc(void);
int neorv32_uart_char_received(void);
char neorv32_uart_char_received_get(void);
/sw/lib/source/neorv32_gpio.c
64,12 → 64,12
/**********************************************************************//**
* Set single pin of GPIO's output port.
*
* @param[in] pin Pin number to be set (0..15).
* @param[in] pin Output pin number to be set (0..31).
**************************************************************************/
void neorv32_gpio_pin_set(uint8_t pin) {
 
pin &= 0x0f;
GPIO_OUTPUT = GPIO_OUTPUT | (uint16_t)(1 << pin);
pin &= 0x1f;
GPIO_OUTPUT = GPIO_OUTPUT | (uint32_t)(1 << pin);
}
 
 
76,12 → 76,12
/**********************************************************************//**
* Clear single pin of GPIO's output port.
*
* @param[in] pin Pin number to be cleared (0..15).
* @param[in] pin Output pin number to be cleared (0..31).
**************************************************************************/
void neorv32_gpio_pin_clr(uint8_t pin) {
 
pin &= 0x0f;
GPIO_OUTPUT = GPIO_OUTPUT & ~((uint16_t)(1 << pin));
pin &= 0x1f;
GPIO_OUTPUT = GPIO_OUTPUT & ~((uint32_t)(1 << pin));
}
 
 
88,12 → 88,12
/**********************************************************************//**
* Toggle single pin of GPIO's output port.
*
* @param[in] pin Pin number to be toggled (0..15).
* @param[in] pin Output pin number to be toggled (0..31).
**************************************************************************/
void neorv32_gpio_pin_toggle(uint8_t pin) {
 
pin &= 0x0f;
GPIO_OUTPUT = GPIO_OUTPUT ^ (uint16_t)(1 << pin);
pin &= 0x1f;
GPIO_OUTPUT = GPIO_OUTPUT ^ (uint32_t)(1 << pin);
}
 
 
100,13 → 100,13
/**********************************************************************//**
* Get single pin of GPIO's input port.
*
* @param[in] pin Pin to be read (0..15).
* @return uint16_t: =0 if pin is low, !=0 if pin is high.
* @param[in] pin Input pin to be read (0..31).
* @return uint32_t: =0 if pin is low, !=0 if pin is high.
**************************************************************************/
uint16_t neorv32_gpio_pin_get(uint8_t pin) {
uint32_t neorv32_gpio_pin_get(uint8_t pin) {
 
pin &= 0x0f;
return GPIO_INPUT & (uint16_t)(1 << pin);
pin &= 0x1f;
return GPIO_INPUT & (uint32_t)(1 << pin);
}
 
 
113,9 → 113,9
/**********************************************************************//**
* Set complete GPIO output port.
*
* @param[in] port_data New port value.
* @param[in] port_data New output port value (32-bit).
**************************************************************************/
void neorv32_gpio_port_set(uint16_t port_data) {
void neorv32_gpio_port_set(uint32_t port_data) {
 
GPIO_OUTPUT = port_data;
}
124,9 → 124,23
/**********************************************************************//**
* Get complete GPIO input port.
*
* @return Current input port state.
* @return Current input port state (32-bit).
**************************************************************************/
uint16_t neorv32_gpio_port_get(void) {
uint32_t neorv32_gpio_port_get(void) {
 
return GPIO_INPUT;
}
 
 
/**********************************************************************//**
* Configure pin-change IRQ mask for input pins.
*
* @note The pin-change IRQ will trigger on any transition (rising and falling edge) for any enabled input pin.
*
* @param[in] pin_en Mask to select which input pins can cause a pin-change IRQ (32-bit), 1 = pin enabled.
**************************************************************************/
void neorv32_gpio_pin_change_config(uint32_t pin_sel) {
 
GPIO_INPUT = pin_sel;
}
 
/sw/lib/source/neorv32_rte.c
210,10 → 210,10
case TRAP_CODE_MSI: neorv32_uart_printf("Machine software interrupt"); break;
case TRAP_CODE_MTI: neorv32_uart_printf("Machine timer interrupt"); break;
case TRAP_CODE_MEI: neorv32_uart_printf("Machine external interrupt"); break;
case TRAP_CODE_FIRQ_0: neorv32_uart_printf("Fast interrupt 0"); break;
case TRAP_CODE_FIRQ_1: neorv32_uart_printf("Fast interrupt 1"); break;
case TRAP_CODE_FIRQ_2: neorv32_uart_printf("Fast interrupt 2"); break;
case TRAP_CODE_FIRQ_3: neorv32_uart_printf("Fast interrupt 3"); break;
case TRAP_CODE_FIRQ_0: neorv32_uart_printf("Fast interrupt 0 (WDT)"); break;
case TRAP_CODE_FIRQ_1: neorv32_uart_printf("Fast interrupt 1 (GPIO)"); break;
case TRAP_CODE_FIRQ_2: neorv32_uart_printf("Fast interrupt 2 (UART)"); break;
case TRAP_CODE_FIRQ_3: neorv32_uart_printf("Fast interrupt 3 (SPI/TWI)"); break;
default: neorv32_uart_printf("Unknown (0x%x)", trap_cause); break;
}
 
249,19 → 249,23
// CPU configuration
neorv32_uart_printf("\n-- Central Processing Unit --\n");
 
// Hart ID
// ID
neorv32_uart_printf("Hart ID: %u\n", neorv32_cpu_csr_read(CSR_MHARTID));
 
// Custom user code
neorv32_uart_printf("User code: 0x%x\n", SYSINFO_USER_CODE);
neorv32_uart_printf("Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MVENDORID));
 
tmp = neorv32_cpu_csr_read(CSR_MARCHID);
neorv32_uart_printf("Architecture ID: 0x%x", tmp);
 
// Custom user code/ID
neorv32_uart_printf("\nUser ID: 0x%x\n", SYSINFO_USER_CODE);
 
// HW version
neorv32_uart_printf("Hardware version: ");
neorv32_rte_print_hw_version();
neorv32_uart_printf(" (0x%x)\n", neorv32_cpu_csr_read(CSR_MIMPID));
 
// CPU architecture
neorv32_uart_printf("Architecture: ");
neorv32_uart_printf("\nArchitecture: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
tmp = (tmp >> 30) & 0x03;
if (tmp == 0) {
278,7 → 282,7
}
// CPU extensions
neorv32_uart_printf(" + ");
neorv32_uart_printf("\nExtensions: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
for (i=0; i<26; i++) {
if (tmp & (1 << i)) {
287,10 → 291,8
neorv32_uart_putc(' ');
}
}
neorv32_uart_printf("(0x%x)\n", tmp);
// Z* CPU extensions (from custom CSR)
neorv32_uart_printf("Z* extensions: ");
// Z* CPU extensions (from custom CSR "mzext")
tmp = neorv32_cpu_csr_read(CSR_MZEXT);
if (tmp & (1<<0)) {
neorv32_uart_printf("Zicsr ");
298,9 → 300,6
if (tmp & (1<<1)) {
neorv32_uart_printf("Zifencei ");
}
if (tmp & (1<<2)) {
neorv32_uart_printf("cpu_counters ");
}
 
 
// Misc
311,19 → 310,17
// Memory configuration
neorv32_uart_printf("\n-- Processor Memory Configuration --\n");
 
uint32_t size = SYSINFO_ISPACE_SIZE;
uint32_t base = SYSINFO_ISPACE_BASE;
neorv32_uart_printf("Instruction memory: %u bytes @ 0x%x\n", size, base);
neorv32_uart_printf("Instr. base address: 0x%x\n", SYSINFO_ISPACE_BASE);
neorv32_uart_printf("Internal IMEM: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM));
neorv32_uart_printf("IMEM size: %u bytes\n", SYSINFO_IMEM_SIZE);
neorv32_uart_printf("Internal IMEM as ROM: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM));
 
size = SYSINFO_DSPACE_SIZE;
base = SYSINFO_DSPACE_BASE;
neorv32_uart_printf("Data memory: %u bytes @ 0x%x\n", size, base);
neorv32_uart_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE);
neorv32_uart_printf("Internal DMEM: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM));
neorv32_uart_printf("DMEM size: %u bytes\n", SYSINFO_DMEM_SIZE);
 
neorv32_uart_printf("Bootloader: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER));
362,6 → 359,9
 
neorv32_uart_printf("DEVNULL: ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_DEVNULL));
 
neorv32_uart_printf("CFU: ");
__neorv32_rte_print_true_false(tmp & (1 << SYSINFO_FEATURES_IO_CFU));
}
 
 
/sw/lib/source/neorv32_spi.c
150,3 → 150,19
 
return SPI_DATA;
}
 
 
/**********************************************************************//**
* Check if SPI transceiver is busy.
*
* @note This function is blocking.
*
* @return 0 if idle, 1 if busy
**************************************************************************/
int neorv32_spi_busy(void) {
 
if ((SPI_CT & (1<<SPI_CT_BUSY)) != 0) {
return 1;
}
return 0;
}
/sw/lib/source/neorv32_trng.c
62,30 → 62,23
 
 
/**********************************************************************//**
* Enable and configure true random number generator. The TRNG control register bits are listed in #NEORV32_TRNG_CT_enum.
*
* @param[in] tap_mask 16-bit tap mask for GARO array.
* @return Returns 0 if the provided tap_mask works correctly (GARO-array is oscillating), returns 1 otherwise.
* Enable true random number generator. The TRNG control register bits are listed in #NEORV32_TRNG_CT_enum.
**************************************************************************/
int neorv32_trng_setup(uint16_t tap_mask) {
void neorv32_trng_enable(void) {
 
int i;
 
TRNG_CT = 0; // reset
 
// configure
uint32_t tap_config = (uint32_t)(tap_mask);
tap_config = tap_config << TRNG_CT_TAP_LSB;
TRNG_CT = (1 << TRNG_CT_EN) | tap_config;
for (i=0; i<1000; i++) {
asm volatile ("nop");
}
 
neorv32_cpu_delay_ms(1);
TRNG_CT = 1 << TRNG_CT_EN; // activate
 
// check if TRNG is oscillating
uint16_t trng_data;
if (neorv32_trng_get(&trng_data) == 0) {
return 0;
for (i=0; i<1000; i++) {
asm volatile ("nop");
}
else {
return 1;
}
}
 
 
101,71 → 94,30
/**********************************************************************//**
* Get random data from TRNG.
*
* @param[in,out] data uint16_t pointer for storing random data word
* @return Valid data when 0, invalid data when 1
* @note The TRNG is automatically reset if a stuck-at-one/stuck-at-zero error is detected.
*
* @param[in,out] data uint8_t pointer for storing random data word
* @return Data is valid when 0, stuck-at-zero error when 1, stuck-at-one error when 2, data not (yet) valid when 3
**************************************************************************/
int neorv32_trng_get(uint16_t *data) {
int neorv32_trng_get(uint8_t *data) {
 
int i;
const int max_try = 16;
uint32_t trng_data;
uint32_t rnd_data;
uint32_t trng_ct_reg = TRNG_CT;
 
for(i=0; i<max_try; i++) {
if (trng_ct_reg & (1<<TRNG_CT_ERROR_0)) { // stuck at zero error
neorv32_trng_enable(); // reset TRNG
return 1;
}
 
trng_data = TRNG_DATA;
rnd_data = trng_data >> TRNG_DATA_LSB;
*data = (uint16_t)rnd_data;
 
if (trng_data & (1<<TRNG_DATA_VALID)) { // output data valid?
return 0; // valid
}
 
if (trng_ct_reg & (1<<TRNG_CT_ERROR_1)) { // stuck at one error
neorv32_trng_enable(); // reset TRNG
return 2;
}
 
return 1; // invalid
}
 
 
/**********************************************************************//**
* Try to find a valid TRNG tap configuration mask.
*
* @return Tap mask for configuring the TRNG. If return is zero, no valid tap mask was found.
**************************************************************************/
uint16_t neorv32_trng_find_tap_mask(void) {
 
int j;
uint16_t tap_config16 = 0xfff0; // keep the lowest inverters without feedback
uint16_t trng_data;
int success = 0;
 
// tap mask is zero, try to find a nice one
while (1) {
 
// good mask found?
if ((success) || (tap_config16 <= 0x0008)) {
break;
}
 
// generate a new tap
tap_config16 -= 0x0008;
 
// install it
if (neorv32_trng_setup(tap_config16)) {
continue;
}
 
// does it work?
success = 1;
for (j=0; j < 100; j++) {
neorv32_cpu_delay_ms(1);
if (neorv32_trng_get(&trng_data)) { // stop testing on fail
success = 0;
break;
}
}
if ((trng_ct_reg & (1<<TRNG_CT_VALID)) == 0) { // output data valid (yet)?
return 3;
}
 
return (uint16_t)tap_config16;
*data = (uint8_t)(trng_ct_reg >> TRNG_CT_DATA_LSB);
return 0; // valid data
}
 
/sw/lib/source/neorv32_twi.c
111,6 → 111,22
}
 
 
/**********************************************************************//**
* Check if TWI is busy.
*
* @note This function is blocking.
*
* @return 0 if idle, 1 if busy
**************************************************************************/
int neorv32_twi_busy(void) {
 
if (TWI_CT & (1 << TWI_CT_BUSY)) {
return 1;
}
return 0;
}
 
 
/**********************************************************************//**
* Generate START condition and send first byte (address including R/W bit).
*
/sw/lib/source/neorv32_uart.c
125,7 → 125,6
}
 
 
 
/**********************************************************************//**
* Send single char via UART.
*
149,6 → 148,22
 
 
/**********************************************************************//**
* Check if UART TX is busy.
*
* @note This function is blocking.
*
* @return 0 if idle, 1 if busy
**************************************************************************/
int neorv32_uart_tx_busy(void) {
 
if ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0) {
return 1;
}
return 0;
}
 
 
/**********************************************************************//**
* Get char from UART.
*
* @note This function is blocking.
/sw/README.md
0,0 → 1,27
## NEORV32 Software Framework
 
This folder provides the core of the NEORV32 software framework. This is a short description of the main folders.
 
### `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`
 
NEORV32-specific common files for all bootloader and application programs: linker script for executable generation and
processor start-up code.
 
### `example`
 
Several example programs for testing and for getting started.
 
### `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`
 
Core libraries (sources and header files) and helper functions for using the processor peripherals and the CPU itself.
/CONTRIBUTING.md
0,0 → 1,14
# Contributing
 
When contributing to this repository, please first discuss the change you wish to make via issue,
email, or any other method with the owners of this repository before making a change.
 
Please note we have a [Code of Conduct](https://github.com/stnolting/neorv32/tree/master/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
 
## Contributing Process
 
1. [Fork](https://github.com/stnolting/neorv32/fork) this repository
2. Create a feature branch in your fork: `git checkout -b cool_new_feature`
3. Commit your modifications: `git commit -am 'This is awesome because ...'`
4. Push to the branch: `git push origin cool_new_feature`
5. Create a new [pull request](https://github.com/stnolting/neorv32/pulls)
/README.md
20,7 → 20,7
 
## Introduction
 
The NEORV321 Processor is a customizable microcontroller-like system on chip (SoC) that is based
The NEORV32 Processor is a customizable microcontroller-like system on chip (SoC) that is based
on the RISC-V-compliant NEORV32 CPU. The project consists of two main parts:
 
 
61,7 → 61,7
with the NEORV32. If you do not want to [compile the GCC toolchains](https://github.com/riscv/riscv-gnu-toolchain) by yourself, you can also
download [pre-compiled toolchains](https://github.com/stnolting/riscv_gcc_prebuilt) for Linux.
 
For more information take a look a the [![NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/PDF_32.png) NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf).
For more information take a look at the [![NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/PDF_32.png) NEORV32 datasheet](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf).
 
This project is hosted on [GitHub](https://github.com/stnolting/neorv32) and [opencores.org](https://opencores.org/projects/neorv32).
A not-so-complete project log can be found on [hackaday.io](https://hackaday.io/project/174167-the-neorv32-risc-v-processor).
69,7 → 69,7
 
### Key Features
 
- RISC-V-compliant `rv32i` CPU with optional `C`, `E`, `M`, `U`, `Zicsr`, `Zifencei` and PMP (physical memory protection) extensions
- RISC-V-compliant `rv32i` CPU with optional `C`, `E`, `M`, `U`, `Zicsr`, `Zifencei` and `PMP` (physical memory protection) extensions
- GCC-based toolchain ([pre-compiled rv32i and rv32e toolchains available](https://github.com/stnolting/riscv_gcc_prebuilt))
- Application compilation based on [GNU makefiles](https://github.com/stnolting/neorv32/blob/master/sw/example/blink_led/makefile)
- [Doxygen-based](https://github.com/stnolting/neorv32/blob/master/docs/doxygen_makefile_sw) documentation of the software framework: available on [GitHub pages](https://stnolting.github.io/neorv32/files.html)
87,7 → 87,7
* Plain VHDL without technology-specific parts like attributes, macros or primitives.
* Easy to use – working out of the box.
* Clean synchronous design, no wacky combinatorial interfaces.
* Be as small as possible – but with a reasonable size-speed tradeoff.
* Be as small as possible – but with a reasonable size-performance tradeoff.
* The processor has to fit in a Lattice iCE40 UltraPlus 5k FPGA running at 20+ MHz.
 
 
105,23 → 105,6
| [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) | |
 
 
### Non RISC-V-Compliant Issues
 
* No exception is triggered for the `E` CPU extension when using registers above `x15` (*needs fixing*)
* `misa` CSR is read-only - no dynamic enabling/disabling of implemented CPU extensions during runtime
* `mcause` CSR is read-only
* The `[m]cycleh` and `[m]instreth` CSR counters are only 20-bit wide (in contrast to original 32-bit)
* The physical memory protection (**PMP**) only supports `NAPOT` mode, a minimal granularity of 8 bytes and only up to 8 regions
 
 
### NEORV32-Specific CPU Extensions
 
The NEORV32-specific extensions are always enabled and are indicated via the `X` bit in the `misa` CSR.
 
* Four *fast interrupt* request channels with according control/status bits in `mie` and `mip` and custom exception codes in `mcause`
* `mzext` CSR to check for implemented `Z*` CPU extensions (like `Zifencei`)
 
 
### To-Do / Wish List
 
- Add AXI(-Lite) bridges
129,6 → 112,7
- Maybe port additional RTOSs (like [Zephyr](https://github.com/zephyrproject-rtos/zephyr) or [RIOT](https://www.riot-os.org))
- Implement further CPU extensions:
- Atomic operations (`A`)
- Bitmanipulation operations (`B`), when they are "official"
- Floating-point instructions (`F`)
- ...
 
139,21 → 123,24
 
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_processor.png)
 
Highly customizable processor configuration:
- Optional processor-internal data and instruction memories (DMEM/IMEM)
- Optional internal bootloader with UART console and automatic SPI flash boot option
- Optional machine system timer (MTIME), RISC-V-compliant
- Optional universal asynchronous receiver and transmitter (UART)
- 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 general purpose parallel IO port (GPIO), 16xOut & 16xIn, with pin-change interrupt
- Optional 32-bit external bus interface, Wishbone b4 compliant (WISHBONE)
- 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)
- Optional dummy device (DEVNULL) (can be used for *fast* simulation console output)
- System configuration information memory to check hardware configuration by software (SYSINFO)
The NEORV32 Processor provides a full-scale microcontroller-like SoC based on the NEORV32 CPU. The setup
is highly customizable via the processor top's generics.
 
- Optional processor-internal data and instruction memories (**DMEM** / **IMEM**)
- Optional internal **Bootloader** with UART console and automatic SPI flash boot option
- Optional machine system timer (**MTIME**), RISC-V-compliant
- Optional universal asynchronous receiver and transmitter (**UART**)
- 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 general purpose parallel IO port (**GPIO**), 16xOut & 16xIn, with pin-change interrupt
- Optional 32-bit external bus interface, Wishbone b4 compliant (**WISHBONE**)
- 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**)
- Optional dummy device (**DEVNULL**); used for debugging; can also be used for *fast* simulation console output
- Optional custom functions unit (**CFU**) for tightly-coupled custom co-processors
- System configuration information memory to check hardware configuration by software (**SYSINFO**)
 
### CPU Features
 
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_cpu.png)
167,9 → 154,11
 
 
**General**:
* Modified Harvard architecture (separate CPU interfaces for data and instructions; single processor-bus via bus switch)
* Modified Harvard architecture (separate CPU interfaces for data and instructions; NEORV32 processor: Single processor-internal bus via bus I/D mux)
* Two stages in-order pipeline (FETCH, EXECUTE); each stage uses a multi-cycle processing scheme
* No hardware support of unaligned accesses - they will trigger an exception
* Little-endian byte order
* All reserved or unimplemented instructions will raise an illegal instruction exception
* Privilege levels: `machine` mode, `user` mode (if enabled via `U` extension)
 
 
199,7 → 188,7
* CSR access instructions: `CSRRW` `CSRRS` `CSRRC` `CSRRWI` `CSRRSI` `CSRRCI`
* System instructions: `MRET` `WFI`
* Counter CSRs: `[m]cycle[h]` `[m]instret[h]` `time[h]`
* Machine CSRs: `mstatus` `misa`(read-only!) `mie` `mtvec` `mscratch` `mepc` `mcause`(read-only!) `mtval` `mip` `mvendorid` `marchid` `mimpid` `mhartid` `mzext`(custom)
* Machine CSRs: `mstatus` `misa`(read-only!) `mie` `mtvec` `mscratch` `mepc` `mcause`(read-only!) `mtval` `mip` `mvendorid` [`marchid`](https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md) `mimpid` `mhartid` `mzext`(custom)
* Supported exceptions and interrupts:
* Misaligned instruction address
* Instruction access fault
222,18 → 211,36
* System instructions: `FENCE.I`
 
**Privileged architecture / Physical memory protection** (`PMP`, requires `Zicsr` extension):
* Additional machine CSRs: `pmpcfgx` `pmpaddrx`
* Additional machine CSRs: `pmpcfg0` `pmpcfg1` `pmpaddr0` `pmpaddr1` `pmpaddr2` `pmpaddr3` `pmpaddr4` `pmpaddr5` `pmpaddr6` `pmpaddr7`
 
 
### Non-RISC-V-Compliant Issues
 
* `misa` CSR is read-only - no dynamic enabling/disabling of synthesized CPU extensions during runtime
* `mcause` CSR is read-only
* The `[m]cycleh` and `[m]instreth` CSR counters are only 20-bit wide (in contrast to original 32-bit)
* The physical memory protection (**PMP**) only supports `NAPOT` mode, a minimal granularity of 8 bytes and only up to 8 regions
* All invalid, unimplemented, unspecified or disabled instructions will trigger an illegal instruction exception
 
 
### NEORV32-Specific CPU Extensions
 
The NEORV32-specific extensions are always enabled and are indicated via the `X` bit in the `misa` CSR.
 
* Four *fast interrupt* request channels with according control/status bits in `mie` and `mip` and custom exception codes in `mcause`
* `mzext` CSR to check for implemented `Z*` CPU extensions (like `Zifencei`)
 
 
 
## FPGA Implementation Results
 
This chapter shows exemplary implementation results of the NEORV32 processor for an **Intel Cyclone IV EP4CE22F17C6N FPGA** on
### NEORV32 CPU
 
This chapter shows exemplary implementation results of the NEORV32 CPU for an **Intel Cyclone IV EP4CE22F17C6N FPGA** on
a DE0-nano board. The design was synthesized using **Intel Quartus Prime Lite 19.1** ("balanced implementation"). The timing
information is derived from the Timing Analyzer / Slow 1200mV 0C Model. If not otherwise specified, the default configuration
of the CPU's generics is assumed (e.g., no PMP). No constraints were used at all.
 
### CPU
 
Results generated for hardware version: `1.3.6.5`
 
| CPU Configuration | LEs | FFs | Memory bits | DSPs | f_max |
244,8 → 251,9
| `rv32imc` + `Zicsr` + `Zifencei` | 2714 | 1064 | 2048 | 0 | 100 MHz |
| `rv32emc` + `Zicsr` + `Zifencei` | 2717 | 1064 | 1024 | 0 | 100 MHz |
 
### Processor-Internal Peripherals and Memories
 
### NEORV32 Processor-Internal Peripherals and Memories
 
Results generated for hardware version: `1.3.6.5`
 
| Module | Description | LEs | FFs | Memory bits | DSPs |
252,6 → 260,7
|:----------|:------------------------------------------------|:---:|:---:|:-----------:|:----:|
| BOOT ROM | Bootloader ROM (4kB) | 4 | 1 | 32 768 | 0 |
| BUSSWITCH | Mux for CPU I & D interfaces | 62 | 8 | 0 | 0 |
| CFU | Custom functions unit | - | - | - | - |
| DEVNULL | Dummy device | 3 | 1 | 0 | 0 |
| DMEM | Processor-internal data memory (8kB) | 12 | 2 | 65 536 | 0 |
| GPIO | General purpose input/output ports | 40 | 33 | 0 | 0 |
266,10 → 275,10
| WDT | Watchdog timer | 59 | 45 | 0 | 0 |
 
 
### Exemplary FPGA Setups
### NEORV32 Processor - Exemplary FPGA Setups
 
Exemplary implementation results for different FPGA platforms. The processor setup uses *all provided peripherals*,
no external memory interface, no PMP and only internal instruction and data memories. IMEM uses 16kB and DMEM uses 8kB memory space. The setup's top entity connects most of the
Exemplary processor implementation results for different FPGA platforms. The processor setup uses *all provided peripherals* (but not the _CFU_),
no external memory interface and only internal instruction and data memories. IMEM uses 16kB and DMEM uses 8kB memory space. The setup's top entity connects most of the
processor's [top entity](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) signals
to FPGA pins - except for the Wishbone bus and the interrupt signals.
 
281,7 → 290,7
| Lattice | iCE40 UltraPlus `iCE40UP5K-SG48I` | Upduino v2.0 | Radiant 2.1 (Synplify Pro) | default | `rv32icu` + `Zicsr` + `Zifencei` | 4249 (80%) | 1617 (31%) | 0 (0%) | - | 12 (40%) | 4 (100%) | *c* 20.25 MHz |
| Xilinx | Artix-7 `XC7A35TICSG324-1L` | Arty A7-35T | Vivado 2019.2 | default | `rv32imcu` + `Zicsr` + `Zifencei` + `PMP` | 2447 (12%) | 1803 (4%) | 0 (0%) | - | 8 (16%) | - | *c* 100 MHz |
 
**Notes**
**_Notes_**
* The Lattice iCE40 UltraPlus setup uses the FPGA's SPRAM memory primitives for the internal IMEM and DMEM (each 64kb).
The FPGA-specific memory components can be found in [`rtl/fpga_specific`](https://github.com/stnolting/neorv32/blob/master/rtl/fpga_specific/lattice_ice40up).
* The clock frequencies marked with a "c" are constrained clocks. The remaining ones are _f_max_ results from the place and route timing reports.
349,19 → 358,84
 
## Top Entities
 
The top entity of the **processor** is [**neorv32_top.vhd**](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) (from the `rtl/core` folder).
The top entity of the **NEORV32 Processor** is [**neorv32_top.vhd**](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) (from the `rtl/core` folder).
Just instantiate this file in your project and you are ready to go! All signals of this top entity are of type *std_ulogic* or *std_ulogic_vector*, respectively
(except for the TWI signals, which are of type *std_logic*).
 
The top entity of the **CPU** is [**neorv32_cpu.vhd**](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_cpu.vhd) (from the `rtl/core` folder).
The top entity of the **NEORV32 CPU** is [**neorv32_cpu.vhd**](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_cpu.vhd) (from the `rtl/core` folder).
All signals of this top entity are of type *std_ulogic* or *std_ulogic_vector*, respectively.
 
Use the generics to configure the processor/CPU according to your needs. Each generic is initilized with the default configuration.
Detailed information regarding the signals and configuration generics can be found in the [NEORV32 documentary](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf).
Detailed information regarding the signals and configuration generics can be found in
the [NEORV32 documentary](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/NEORV32.pdf).
 
Alternative top entities can be found in [`rtl/top_templates`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates) folder.
Alternative top entities, like the simplified ["hello world" test setup](#Create-a-new-Hardware-Project), can be found
in [`rtl/top_templates`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates) folder.
 
 
### CPU
 
```vhdl
entity neorv32_cpu is
generic (
-- General --
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= (others => '0'); -- hardware thread id
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= (others => '0'); -- cpu boot address
-- 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
-- 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
-- Bus Interface --
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
port (
-- global control --
clk_i : in std_ulogic := '0'; -- global clock, rising edge
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
-- instruction bus interface --
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data
i_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
i_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
i_bus_we_o : out std_ulogic; -- write enable
i_bus_re_o : out std_ulogic; -- read enable
i_bus_cancel_o : out std_ulogic; -- cancel current bus transaction
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
-- 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
d_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
d_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
d_bus_we_o : out std_ulogic; -- write enable
d_bus_re_o : out std_ulogic; -- read enable
d_bus_cancel_o : out std_ulogic; -- cancel current bus transaction
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
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time
-- interrupts (risc-v compliant) --
msw_irq_i : in std_ulogic := '0'; -- machine software interrupt
mext_irq_i : in std_ulogic := '0'; -- machine external interrupt
mtime_irq_i : in std_ulogic := '0'; -- machine timer interrupt
-- fast interrupts (custom) --
firq_i : in std_ulogic_vector(3 downto 0) := (others => '0')
);
end neorv32_cpu;
```
 
 
### Processor
 
```vhdl
379,24 → 453,19
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
CPU_EXTENSION_RISCV_Zifencei : boolean := true; -- implement instruction stream sync.?
-- Extension Options --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
-- 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
-- Memory configuration: Instruction memory --
MEM_ISPACE_BASE : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
MEM_ISPACE_SIZE : natural := 16*1024; -- total size of instruction memory space in byte
PMP_GRANULARITY : natural := 14; -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64kB
-- 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
-- Memory configuration: Data memory --
MEM_DSPACE_BASE : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
MEM_DSPACE_SIZE : natural := 8*1024; -- total size of data memory space in byte
-- 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
-- Memory configuration: External memory interface --
-- 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)
MEM_EXT_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout
409,7 → 478,8
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_DEVNULL_USE : boolean := true -- implement dummy device (DEVNULL)?
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)?
IO_CFU_USE : boolean := false -- implement custom functions unit (CFU)?
);
port (
-- Global control --
452,71 → 522,7
```
 
 
### CPU
 
```vhdl
entity neorv32_cpu is
generic (
-- General --
HW_THREAD_ID : std_ulogic_vector(31 downto 0):= (others => '0'); -- hardware thread id
CPU_BOOT_ADDR : std_ulogic_vector(31 downto 0):= (others => '0'); -- cpu boot address
-- 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 --
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier
-- 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
-- Bus Interface --
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout
);
port (
-- global control --
clk_i : in std_ulogic := '0'; -- global clock, rising edge
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
-- instruction bus interface --
i_bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
i_bus_rdata_i : in std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); -- bus read data
i_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
i_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
i_bus_we_o : out std_ulogic; -- write enable
i_bus_re_o : out std_ulogic; -- read enable
i_bus_cancel_o : out std_ulogic; -- cancel current bus transaction
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
-- 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
d_bus_wdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
d_bus_ben_o : out std_ulogic_vector(03 downto 0); -- byte enable
d_bus_we_o : out std_ulogic; -- write enable
d_bus_re_o : out std_ulogic; -- read enable
d_bus_cancel_o : out std_ulogic; -- cancel current bus transaction
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
-- system time input from MTIME --
time_i : in std_ulogic_vector(63 downto 0) := (others => '0'); -- current system time
-- interrupts (risc-v compliant) --
msw_irq_i : in std_ulogic := '0'; -- machine software interrupt
mext_irq_i : in std_ulogic := '0'; -- machine external interrupt
mtime_irq_i : in std_ulogic := '0'; -- machine timer interrupt
-- fast interrupts (custom) --
firq_i : in std_ulogic_vector(3 downto 0) := (others => '0')
);
end neorv32_cpu;
```
 
 
 
## Getting Started
 
This overview is just a short excerpt from the *Let's Get It Started* section of the NEORV32 documentary:
532,7 → 538,7
:warning: Keep in mind that – for instance – a `rv32imc` toolchain only provides library code compiled with compressed and
`mul`/`div` instructions! Hence, this code cannot be executed (without emulation) on an architecture without these extensions!
 
To build the toolchain by yourself, follow the official [build instructions](https://github.com/riscv/riscv-gnu-toolchain.
To build the toolchain by yourself, follow the official [build instructions](https://github.com/riscv/riscv-gnu-toolchain).
Make sure to use the `ilp32` or `ilp32e` ABI.
 
**Alternatively**, you can download a prebuilt toolchain. I have uploaded the toolchains I am using to GitHub. These toolchains
543,23 → 549,26
 
### Dowload the NEORV32 Project
 
Get the sources of the NEORV32 Processor project. You can either download a [release](https://github.com/stnolting/neorv32/releases)
or get the most recent version of this project as [`*.zip` file](https://github.com/stnolting/neorv32/archive/master.zip) or using `git clone` (suggested for easy project updates via `git pull`):
Get the sources of the NEORV32 Processor project. The simplest way is using `git clone` (suggested for easy project updates via `git pull`):
 
$ git clone https://github.com/stnolting/neorv32.git
 
Create a new project with your FPGA design tool of choice and add all the `*.vhd` files from the [`rtl/core`](https://github.com/stnolting/neorv32/blob/master/rtl)
folder to this project. Make sure to add them to a **new library** called `neorv32`.
Alternatively, you can either download a specific [release](https://github.com/stnolting/neorv32/releases) or get the most recent version
of this project as [`*.zip` file](https://github.com/stnolting/neorv32/archive/master.zip).
 
 
### Create a new Hardware Project
 
Create a new project with your FPGA design tool of choice. Add all the `*.vhd` files from the [`rtl/core`](https://github.com/stnolting/neorv32/blob/master/rtl)
folder to this project. Make sure to add these files to a **new design library** called `neorv32`.
 
You can either instantiate the [processor's top entity](https://github.com/stnolting/neorv32#top-entity) in your own project or you
can use a simple [test setup](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates/neorv32_test_setup.vhd) (from the project's
[`rtl/top_templates`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates) folder) as top entity.
This test setup instantiates the processor and implements most of the peripherals and some ISA extensions. Only the UART, clock, reset and some GPIO output sginals are
propagated (basically, its a FPGA "hello world" example):
 
This test setup instantiates the processor and implements most of the peripherals and some ISA extensions. Only the UART lines, clock, reset and some GPIO output sginals are
propagated as actual entity signals. Basically, its a FPGA "hello world" example:
 
```vhdl
entity neorv32_test_setup is
port (
576,7 → 585,7
```
 
 
### Compiling and Uploading One of the Example Projects
### Check the Toolchain
 
Make sure `GNU Make` and a native `GCC` compiler are installed. To test the installation of the RISC-V toolchain navigate to an example project like
`sw/example/blink_led` and run:
583,13 → 592,19
 
neorv32/sw/example/blink_led$ make check
 
 
### Compiling an Example Program
 
The NEORV32 project includes some [example programs](https://github.com/stnolting/neorv32/tree/master/sw/example) from
which you can start your own application. Simply compile one of these projects. This will create a NEORV32
executable `neorv32_exe.bin` in the same folder.
*executable* `neorv32_exe.bin` in the same folder:
 
neorv32/sw/example/blink_led$ make clean_all compile
neorv32/sw/example/blink_led$ make clean_all exe
 
Connect your FPGA board via UART to you computer and open the according port to interface with the NEORV32 bootloader. The bootloader
 
### Upload the Executable via the Bootloader
 
Connect your FPGA board via UART to your computer and open the according port to interface with the NEORV32 bootloader. The bootloader
uses the following default UART configuration:
 
- 19200 Baud
597,9 → 612,9
- 1 stop bit
- No parity bits
- No transmission / flow control protocol (raw bytes only)
- Newline on `\r\n` (carriage return & newline)
- Newline on `\r\n` (carriage return & newline) - also for sent data
 
Use the bootloader console to upload the `neorv32_exe.bin` file and run your application image.
Use the bootloader console to upload the `neorv32_exe.bin` executable and run your application image.
 
```
<< NEORV32 Bootloader >>
638,14 → 653,15
## Contribute
 
I'm always thankful for help! So if you have any questions, bug reports, ideas or if you want to give some kind of feedback, feel free
to open a [new issue](https://github.com/stnolting/neorv32/issues) or directly drop me a line (mailto:stnolting@gmail.com).
to [open a new issue](https://github.com/stnolting/neorv32/issues) or directly [drop me a line](mailto:stnolting@gmail.com).
 
If you'd like to contribute:
 
1. [Fork](https://github.com/stnolting/neorv32/fork) this repository
2. Create a feature branch in your fork: `git checkout -b cool_new_feature`
3. Commit your modifications: `git commit -am 'This is awesome because ...'`
4. Push to the branch: `git push origin cool_new_feature`
1. [Fork](https://github.com/stnolting/neorv32/fork) this repository and clone the fork
2. Create a feature branch in your fork: `git checkout -b awesome_new_feature_branch`
3. Create a new remote for the upstream repo: `git remote add https://github.com/stnolting/neorv32`
3. Commit your modifications: `git commit -m "Awesome new feature!"`
4. Push to the branch: `git push origin awesome_new_feature_branch`
5. Create a new [pull request](https://github.com/stnolting/neorv32/pulls)
 
Please also check out the project's [code of conduct](https://github.com/stnolting/neorv32/tree/master/CODE_OF_CONDUCT.md).
703,8 → 719,6
 
#### Proprietary Notice
 
"Windows" is a trademark of Microsoft Corporation.
 
"Artix" and "Vivado" are trademarks of Xilinx Inc.
 
"Cyclone", "Quartus Prime", "Quartus Prime Lite" and "Avalon Bus" are trademarks of Intel Corporation.
721,7 → 735,7
 
[![RISC-V](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/riscv_logo.png)](https://riscv.org/)
 
[RISC-V](https://riscv.org/) - Instruction Sets Want To Be Free :heart:
[RISC-V](https://riscv.org/) - Instruction Sets Want To Be Free!
 
[![Continous Integration provided by Travis CI](https://travis-ci.com/images/logos/TravisCI-Full-Color.png)](https://travis-ci.com/stnolting/neorv32)
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.