URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 22 to Rev 23
- ↔ Reverse comparison
Rev 22 → Rev 23
/neorv32/trunk/docs/figures/neorv32_processor.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/neorv32/trunk/docs/NEORV32.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/neorv32/trunk/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" |
); |
|
/neorv32/trunk/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 -------------------------------------------------------------------------- |
/neorv32/trunk/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" |
); |
|
/neorv32/trunk/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; |
/neorv32/trunk/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 -- |
/neorv32/trunk/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; |
/neorv32/trunk/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; |
|
/neorv32/trunk/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; |
/neorv32/trunk/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; |
|
/neorv32/trunk/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 -- |
/neorv32/trunk/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; |
/neorv32/trunk/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; |
/neorv32/trunk/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 -- |
/neorv32/trunk/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; |
/neorv32/trunk/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); |
/neorv32/trunk/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; |
/neorv32/trunk/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 -- |
/neorv32/trunk/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 |
/neorv32/trunk/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> |
/neorv32/trunk/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; |
/neorv32/trunk/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 |
/neorv32/trunk/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 |
|
/neorv32/trunk/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)); |
/neorv32/trunk/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 |
/neorv32/trunk/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; |
} |
/neorv32/trunk/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); |
|
/neorv32/trunk/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 |
/neorv32/trunk/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 |
/neorv32/trunk/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 |
/neorv32/trunk/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) */ |
}; |
|
|
/neorv32/trunk/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 |
/neorv32/trunk/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 |
/neorv32/trunk/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 |
/neorv32/trunk/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); |
/neorv32/trunk/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); |
/neorv32/trunk/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; |
} |
|
/neorv32/trunk/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)); |
} |
|
|
/neorv32/trunk/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; |
} |
/neorv32/trunk/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 |
} |
|
/neorv32/trunk/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). |
* |
/neorv32/trunk/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. |
/neorv32/trunk/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. |
/neorv32/trunk/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) |
/neorv32/trunk/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) |
|