URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/rtl/core
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/neorv32_bootloader_image.vhd
51,13 → 51,13
00000040 => x"01612823", |
00000041 => x"01712623", |
00000042 => x"01812423", |
00000043 => x"4e9000ef", |
00000044 => x"4ad000ef", |
00000045 => x"415000ef", |
00000046 => x"285000ef", |
00000047 => x"4c5000ef", |
00000048 => x"26d000ef", |
00000049 => x"fc101473", |
00000043 => x"4fd000ef", |
00000044 => x"4c1000ef", |
00000045 => x"429000ef", |
00000046 => x"299000ef", |
00000047 => x"4d9000ef", |
00000048 => x"281000ef", |
00000049 => x"fc102473", |
00000050 => x"026267b7", |
00000051 => x"9ff78793", |
00000052 => x"00000713", |
67,954 → 67,961
00000056 => x"00200513", |
00000057 => x"0087f463", |
00000058 => x"00400513", |
00000059 => x"391000ef", |
00000059 => x"3a5000ef", |
00000060 => x"00005537", |
00000061 => x"00000613", |
00000062 => x"00000593", |
00000063 => x"b0050513", |
00000064 => x"279000ef", |
00000065 => x"251000ef", |
00000064 => x"28d000ef", |
00000065 => x"265000ef", |
00000066 => x"00245793", |
00000067 => x"00a78533", |
00000068 => x"00f537b3", |
00000069 => x"00b785b3", |
00000070 => x"249000ef", |
00000070 => x"25d000ef", |
00000071 => x"ffff07b7", |
00000072 => x"41478793", |
00000072 => x"42878793", |
00000073 => x"30579073", |
00000074 => x"08000793", |
00000075 => x"30479073", |
00000076 => x"441000ef", |
00000076 => x"455000ef", |
00000077 => x"00100513", |
00000078 => x"41d000ef", |
00000078 => x"431000ef", |
00000079 => x"00000793", |
00000080 => x"34079073", |
00000081 => x"ffff1537", |
00000082 => x"ed850513", |
00000083 => x"2d9000ef", |
00000084 => x"3bc000ef", |
00000082 => x"eec50513", |
00000083 => x"2ed000ef", |
00000084 => x"3d0000ef", |
00000085 => x"ffff1537", |
00000086 => x"f1050513", |
00000087 => x"2c9000ef", |
00000088 => x"fc101573", |
00000089 => x"240000ef", |
00000086 => x"f2450513", |
00000087 => x"2dd000ef", |
00000088 => x"fc102573", |
00000089 => x"254000ef", |
00000090 => x"ffff1537", |
00000091 => x"f1850513", |
00000092 => x"2b5000ef", |
00000093 => x"30101573", |
00000094 => x"22c000ef", |
00000091 => x"f2c50513", |
00000092 => x"2c9000ef", |
00000093 => x"f1402573", |
00000094 => x"240000ef", |
00000095 => x"ffff1537", |
00000096 => x"f2450513", |
00000097 => x"2a1000ef", |
00000098 => x"fc001573", |
00000099 => x"218000ef", |
00000096 => x"f3850513", |
00000097 => x"2b5000ef", |
00000098 => x"30102573", |
00000099 => x"22c000ef", |
00000100 => x"ffff1537", |
00000101 => x"f2c50513", |
00000102 => x"28d000ef", |
00000103 => x"fc601573", |
00000104 => x"ffff14b7", |
00000105 => x"200000ef", |
00000106 => x"f3448513", |
00000107 => x"279000ef", |
00000108 => x"fc401573", |
00000109 => x"1f0000ef", |
00000110 => x"ffff1537", |
00000111 => x"f4050513", |
00000112 => x"265000ef", |
00000113 => x"fc701573", |
00000114 => x"1dc000ef", |
00000115 => x"f3448513", |
00000116 => x"255000ef", |
00000117 => x"fc501573", |
00000118 => x"1cc000ef", |
00000119 => x"ffff1537", |
00000120 => x"f4850513", |
00000121 => x"241000ef", |
00000122 => x"00341413", |
00000123 => x"00000493", |
00000124 => x"ffff1937", |
00000125 => x"fa402783", |
00000126 => x"0607d063", |
00000127 => x"ffff1537", |
00000128 => x"f7850513", |
00000129 => x"221000ef", |
00000130 => x"ffff1937", |
00000131 => x"0f4000ef", |
00000132 => x"ffff19b7", |
00000133 => x"07200a13", |
00000134 => x"06800a93", |
00000135 => x"07500b13", |
00000136 => x"07300b93", |
00000137 => x"ffff14b7", |
00000138 => x"ffff1c37", |
00000139 => x"f8490513", |
00000140 => x"1f5000ef", |
00000141 => x"1e1000ef", |
00000142 => x"00050413", |
00000143 => x"1c9000ef", |
00000144 => x"f7498513", |
00000145 => x"1e1000ef", |
00000146 => x"09440263", |
00000147 => x"03541863", |
00000148 => x"0b0000ef", |
00000149 => x"fd9ff06f", |
00000150 => x"0fd000ef", |
00000151 => x"00b49463", |
00000152 => x"f8856ae3", |
00000153 => x"00100513", |
00000154 => x"508000ef", |
00000155 => x"f7490513", |
00000156 => x"1b5000ef", |
00000157 => x"098000ef", |
00000158 => x"f7dff06f", |
00000159 => x"00000513", |
00000160 => x"01640e63", |
00000161 => x"01741663", |
00000162 => x"72c000ef", |
00000163 => x"fa1ff06f", |
00000164 => x"06c00793", |
00000165 => x"00f41863", |
00000166 => x"00100513", |
00000167 => x"4d4000ef", |
00000168 => x"f8dff06f", |
00000169 => x"06500793", |
00000170 => x"00f41663", |
00000171 => x"060000ef", |
00000172 => x"f7dff06f", |
00000173 => x"03f00793", |
00000174 => x"f8cc0513", |
00000175 => x"00f40463", |
00000176 => x"fa048513", |
00000177 => x"161000ef", |
00000178 => x"f65ff06f", |
00000179 => x"02c12083", |
00000180 => x"02812403", |
00000181 => x"02412483", |
00000182 => x"02012903", |
00000183 => x"01c12983", |
00000184 => x"01812a03", |
00000185 => x"01412a83", |
00000186 => x"01012b03", |
00000187 => x"00c12b83", |
00000188 => x"00812c03", |
00000189 => x"00000513", |
00000190 => x"03010113", |
00000191 => x"00008067", |
00000192 => x"ffff1537", |
00000193 => x"da850513", |
00000194 => x"11d0006f", |
00000195 => x"340017f3", |
00000196 => x"00079863", |
00000101 => x"f4050513", |
00000102 => x"2a1000ef", |
00000103 => x"fc002573", |
00000104 => x"218000ef", |
00000105 => x"ffff1537", |
00000106 => x"f4850513", |
00000107 => x"28d000ef", |
00000108 => x"fc602573", |
00000109 => x"ffff14b7", |
00000110 => x"200000ef", |
00000111 => x"f5048513", |
00000112 => x"279000ef", |
00000113 => x"fc402573", |
00000114 => x"1f0000ef", |
00000115 => x"ffff1537", |
00000116 => x"f5c50513", |
00000117 => x"265000ef", |
00000118 => x"fc702573", |
00000119 => x"1dc000ef", |
00000120 => x"f5048513", |
00000121 => x"255000ef", |
00000122 => x"fc502573", |
00000123 => x"1cc000ef", |
00000124 => x"ffff1537", |
00000125 => x"f6450513", |
00000126 => x"241000ef", |
00000127 => x"00341413", |
00000128 => x"00000493", |
00000129 => x"ffff1937", |
00000130 => x"fa402783", |
00000131 => x"0607d063", |
00000132 => x"ffff1537", |
00000133 => x"f9450513", |
00000134 => x"221000ef", |
00000135 => x"ffff1937", |
00000136 => x"0f4000ef", |
00000137 => x"ffff19b7", |
00000138 => x"07200a13", |
00000139 => x"06800a93", |
00000140 => x"07500b13", |
00000141 => x"07300b93", |
00000142 => x"ffff14b7", |
00000143 => x"ffff1c37", |
00000144 => x"fa090513", |
00000145 => x"1f5000ef", |
00000146 => x"1e1000ef", |
00000147 => x"00050413", |
00000148 => x"1c9000ef", |
00000149 => x"f9098513", |
00000150 => x"1e1000ef", |
00000151 => x"09440263", |
00000152 => x"03541863", |
00000153 => x"0b0000ef", |
00000154 => x"fd9ff06f", |
00000155 => x"0fd000ef", |
00000156 => x"00b49463", |
00000157 => x"f8856ae3", |
00000158 => x"00100513", |
00000159 => x"508000ef", |
00000160 => x"f9090513", |
00000161 => x"1b5000ef", |
00000162 => x"098000ef", |
00000163 => x"f7dff06f", |
00000164 => x"00000513", |
00000165 => x"01640e63", |
00000166 => x"01741663", |
00000167 => x"72c000ef", |
00000168 => x"fa1ff06f", |
00000169 => x"06c00793", |
00000170 => x"00f41863", |
00000171 => x"00100513", |
00000172 => x"4d4000ef", |
00000173 => x"f8dff06f", |
00000174 => x"06500793", |
00000175 => x"00f41663", |
00000176 => x"060000ef", |
00000177 => x"f7dff06f", |
00000178 => x"03f00793", |
00000179 => x"fa8c0513", |
00000180 => x"00f40463", |
00000181 => x"fbc48513", |
00000182 => x"161000ef", |
00000183 => x"f65ff06f", |
00000184 => x"02c12083", |
00000185 => x"02812403", |
00000186 => x"02412483", |
00000187 => x"02012903", |
00000188 => x"01c12983", |
00000189 => x"01812a03", |
00000190 => x"01412a83", |
00000191 => x"01012b03", |
00000192 => x"00c12b83", |
00000193 => x"00812c03", |
00000194 => x"00000513", |
00000195 => x"03010113", |
00000196 => x"00008067", |
00000197 => x"ffff1537", |
00000198 => x"e0c50513", |
00000199 => x"1090006f", |
00000200 => x"ff010113", |
00000201 => x"00112623", |
00000202 => x"251000ef", |
00000203 => x"00000793", |
00000204 => x"30479073", |
00000205 => x"ffff1537", |
00000206 => x"e2850513", |
00000207 => x"0e9000ef", |
00000208 => x"fa002783", |
00000209 => x"fe07cee3", |
00000210 => x"fc4017f3", |
00000211 => x"00078067", |
00000212 => x"ff9ff06f", |
00000213 => x"ff010113", |
00000214 => x"00812423", |
00000215 => x"00050413", |
00000216 => x"ffff1537", |
00000217 => x"e3850513", |
00000218 => x"00112623", |
00000219 => x"0b9000ef", |
00000220 => x"00500793", |
00000221 => x"0287e063", |
00000222 => x"03040513", |
00000223 => x"0ff57513", |
00000224 => x"085000ef", |
00000225 => x"1f5000ef", |
00000226 => x"00100513", |
00000227 => x"1c9000ef", |
00000228 => x"0000006f", |
00000229 => x"ffff1537", |
00000230 => x"e4050513", |
00000231 => x"089000ef", |
00000232 => x"fe5ff06f", |
00000233 => x"fe010113", |
00000234 => x"01212823", |
00000235 => x"00050913", |
00000236 => x"ffff1537", |
00000237 => x"00912a23", |
00000238 => x"e4850513", |
00000239 => x"ffff14b7", |
00000240 => x"00812c23", |
00000241 => x"01312623", |
00000242 => x"00112e23", |
00000243 => x"01c00413", |
00000244 => x"055000ef", |
00000245 => x"fac48493", |
00000246 => x"ffc00993", |
00000247 => x"008957b3", |
00000248 => x"00f7f793", |
00000249 => x"00f487b3", |
00000250 => x"0007c503", |
00000251 => x"ffc40413", |
00000252 => x"015000ef", |
00000253 => x"ff3414e3", |
00000254 => x"01c12083", |
00000255 => x"01812403", |
00000256 => x"01412483", |
00000257 => x"01012903", |
00000258 => x"00c12983", |
00000259 => x"02010113", |
00000260 => x"00008067", |
00000261 => x"fb010113", |
00000262 => x"04112623", |
00000263 => x"04512423", |
00000264 => x"04612223", |
00000265 => x"04712023", |
00000266 => x"02812e23", |
00000267 => x"02a12c23", |
00000268 => x"02b12a23", |
00000269 => x"02c12823", |
00000270 => x"02d12623", |
00000271 => x"02e12423", |
00000272 => x"02f12223", |
00000273 => x"03012023", |
00000274 => x"01112e23", |
00000275 => x"01c12c23", |
00000276 => x"01d12a23", |
00000277 => x"01e12823", |
00000278 => x"01f12623", |
00000279 => x"34201473", |
00000280 => x"800007b7", |
00000281 => x"00778793", |
00000282 => x"02f40a63", |
00000283 => x"ffff1537", |
00000284 => x"e4c50513", |
00000285 => x"7b0000ef", |
00000286 => x"00040513", |
00000287 => x"f29ff0ef", |
00000198 => x"dbc50513", |
00000199 => x"11d0006f", |
00000200 => x"340027f3", |
00000201 => x"00079863", |
00000202 => x"ffff1537", |
00000203 => x"e2050513", |
00000204 => x"1090006f", |
00000205 => x"ff010113", |
00000206 => x"00112623", |
00000207 => x"251000ef", |
00000208 => x"00000793", |
00000209 => x"30479073", |
00000210 => x"ffff1537", |
00000211 => x"e3c50513", |
00000212 => x"0e9000ef", |
00000213 => x"fa002783", |
00000214 => x"fe07cee3", |
00000215 => x"fc4027f3", |
00000216 => x"00078067", |
00000217 => x"ff9ff06f", |
00000218 => x"ff010113", |
00000219 => x"00812423", |
00000220 => x"00050413", |
00000221 => x"ffff1537", |
00000222 => x"e4c50513", |
00000223 => x"00112623", |
00000224 => x"0b9000ef", |
00000225 => x"00500793", |
00000226 => x"0287e063", |
00000227 => x"03040513", |
00000228 => x"0ff57513", |
00000229 => x"085000ef", |
00000230 => x"1f5000ef", |
00000231 => x"00100513", |
00000232 => x"1c9000ef", |
00000233 => x"0000006f", |
00000234 => x"ffff1537", |
00000235 => x"e5450513", |
00000236 => x"089000ef", |
00000237 => x"fe5ff06f", |
00000238 => x"fe010113", |
00000239 => x"01212823", |
00000240 => x"00050913", |
00000241 => x"ffff1537", |
00000242 => x"00912a23", |
00000243 => x"e5c50513", |
00000244 => x"ffff14b7", |
00000245 => x"00812c23", |
00000246 => x"01312623", |
00000247 => x"00112e23", |
00000248 => x"01c00413", |
00000249 => x"055000ef", |
00000250 => x"fc848493", |
00000251 => x"ffc00993", |
00000252 => x"008957b3", |
00000253 => x"00f7f793", |
00000254 => x"00f487b3", |
00000255 => x"0007c503", |
00000256 => x"ffc40413", |
00000257 => x"015000ef", |
00000258 => x"ff3414e3", |
00000259 => x"01c12083", |
00000260 => x"01812403", |
00000261 => x"01412483", |
00000262 => x"01012903", |
00000263 => x"00c12983", |
00000264 => x"02010113", |
00000265 => x"00008067", |
00000266 => x"fb010113", |
00000267 => x"04112623", |
00000268 => x"04512423", |
00000269 => x"04612223", |
00000270 => x"04712023", |
00000271 => x"02812e23", |
00000272 => x"02a12c23", |
00000273 => x"02b12a23", |
00000274 => x"02c12823", |
00000275 => x"02d12623", |
00000276 => x"02e12423", |
00000277 => x"02f12223", |
00000278 => x"03012023", |
00000279 => x"01112e23", |
00000280 => x"01c12c23", |
00000281 => x"01d12a23", |
00000282 => x"01e12823", |
00000283 => x"01f12623", |
00000284 => x"34202473", |
00000285 => x"800007b7", |
00000286 => x"00778793", |
00000287 => x"02f40a63", |
00000288 => x"ffff1537", |
00000289 => x"e5c50513", |
00000290 => x"79c000ef", |
00000291 => x"34101573", |
00000292 => x"f15ff0ef", |
00000293 => x"00500513", |
00000294 => x"ebdff0ef", |
00000295 => x"00000513", |
00000296 => x"095000ef", |
00000297 => x"6b0000ef", |
00000298 => x"fc1017f3", |
00000299 => x"0027d793", |
00000300 => x"00a78533", |
00000301 => x"00f537b3", |
00000302 => x"00b785b3", |
00000303 => x"6a4000ef", |
00000304 => x"03c12403", |
00000305 => x"04c12083", |
00000306 => x"04812283", |
00000307 => x"04412303", |
00000308 => x"04012383", |
00000309 => x"03812503", |
00000310 => x"03412583", |
00000311 => x"03012603", |
00000312 => x"02c12683", |
00000313 => x"02812703", |
00000314 => x"02412783", |
00000315 => x"02012803", |
00000316 => x"01c12883", |
00000317 => x"01812e03", |
00000318 => x"01412e83", |
00000319 => x"01012f03", |
00000320 => x"00c12f83", |
00000321 => x"05010113", |
00000322 => x"30200073", |
00000323 => x"fe010113", |
00000324 => x"00112e23", |
00000325 => x"00812c23", |
00000326 => x"00912a23", |
00000327 => x"01212823", |
00000328 => x"01312623", |
00000329 => x"01412423", |
00000330 => x"01512223", |
00000331 => x"f1301973", |
00000332 => x"00000a93", |
00000333 => x"00900993", |
00000334 => x"00300a13", |
00000335 => x"00400493", |
00000336 => x"41500433", |
00000337 => x"00341413", |
00000338 => x"01840413", |
00000339 => x"00895433", |
00000340 => x"0ff47413", |
00000341 => x"00000513", |
00000342 => x"0489ec63", |
00000343 => x"00050863", |
00000344 => x"03050513", |
00000345 => x"0ff57513", |
00000346 => x"69c000ef", |
00000347 => x"03040513", |
00000348 => x"0ff57513", |
00000349 => x"690000ef", |
00000350 => x"014a8663", |
00000351 => x"02e00513", |
00000352 => x"684000ef", |
00000353 => x"001a8a93", |
00000354 => x"fa9a9ce3", |
00000355 => x"01c12083", |
00000356 => x"01812403", |
00000357 => x"01412483", |
00000358 => x"01012903", |
00000359 => x"00c12983", |
00000360 => x"00812a03", |
00000361 => x"00412a83", |
00000362 => x"02010113", |
00000363 => x"00008067", |
00000364 => x"ff640413", |
00000365 => x"00150513", |
00000366 => x"0ff47413", |
00000367 => x"0ff57513", |
00000368 => x"f99ff06f", |
00000369 => x"ff010113", |
00000370 => x"00000513", |
00000371 => x"00112623", |
00000372 => x"00812423", |
00000373 => x"708000ef", |
00000374 => x"00500513", |
00000375 => x"744000ef", |
00000376 => x"00000513", |
00000377 => x"73c000ef", |
00000378 => x"00050413", |
00000379 => x"00000513", |
00000380 => x"70c000ef", |
00000381 => x"00c12083", |
00000382 => x"0ff47513", |
00000383 => x"00812403", |
00000384 => x"01010113", |
00000385 => x"00008067", |
00000386 => x"ff010113", |
00000387 => x"00000513", |
00000388 => x"00112623", |
00000389 => x"00812423", |
00000390 => x"6c4000ef", |
00000391 => x"09e00513", |
00000392 => x"700000ef", |
00000393 => x"00000513", |
00000394 => x"6f8000ef", |
00000395 => x"00050413", |
00000396 => x"00000513", |
00000397 => x"6c8000ef", |
00000398 => x"00c12083", |
00000399 => x"0ff47513", |
00000400 => x"00812403", |
00000401 => x"01010113", |
00000402 => x"00008067", |
00000403 => x"ff010113", |
00000404 => x"00000513", |
00000405 => x"00112623", |
00000406 => x"684000ef", |
00000407 => x"00600513", |
00000408 => x"6c0000ef", |
00000409 => x"00c12083", |
00000410 => x"00000513", |
00000411 => x"01010113", |
00000412 => x"68c0006f", |
00000413 => x"ff010113", |
00000414 => x"00812423", |
00000415 => x"00050413", |
00000416 => x"01055513", |
00000417 => x"0ff57513", |
00000418 => x"00112623", |
00000419 => x"694000ef", |
00000420 => x"00845513", |
00000421 => x"0ff57513", |
00000422 => x"688000ef", |
00000423 => x"0ff47513", |
00000424 => x"00812403", |
00000425 => x"00c12083", |
00000426 => x"01010113", |
00000427 => x"6740006f", |
00000428 => x"ff010113", |
00000429 => x"00812423", |
00000430 => x"00050413", |
00000431 => x"00000513", |
00000432 => x"00112623", |
00000433 => x"618000ef", |
00000434 => x"00300513", |
00000435 => x"654000ef", |
00000436 => x"00040513", |
00000437 => x"fa1ff0ef", |
00000438 => x"00000513", |
00000439 => x"644000ef", |
00000440 => x"00050413", |
00000441 => x"00000513", |
00000442 => x"614000ef", |
00000443 => x"00c12083", |
00000444 => x"0ff47513", |
00000445 => x"00812403", |
00000446 => x"01010113", |
00000447 => x"00008067", |
00000448 => x"fd010113", |
00000449 => x"02812423", |
00000450 => x"02912223", |
00000451 => x"03212023", |
00000452 => x"01312e23", |
00000453 => x"02112623", |
00000454 => x"00050493", |
00000455 => x"00300413", |
00000456 => x"00358913", |
00000457 => x"fff00993", |
00000458 => x"02049e63", |
00000459 => x"4e8000ef", |
00000460 => x"00c10793", |
00000461 => x"008787b3", |
00000462 => x"00a78023", |
00000463 => x"fff40413", |
00000464 => x"ff3414e3", |
00000465 => x"02c12083", |
00000466 => x"02812403", |
00000467 => x"00c12503", |
00000468 => x"02412483", |
00000469 => x"02012903", |
00000470 => x"01c12983", |
00000471 => x"03010113", |
00000472 => x"00008067", |
00000473 => x"40890533", |
00000474 => x"f49ff0ef", |
00000475 => x"fc5ff06f", |
00000476 => x"fd010113", |
00000477 => x"02112623", |
00000478 => x"02812423", |
00000479 => x"02912223", |
00000480 => x"03212023", |
00000481 => x"01312e23", |
00000482 => x"01412c23", |
00000483 => x"01512a23", |
00000484 => x"01612823", |
00000485 => x"01712623", |
00000486 => x"fc001473", |
00000487 => x"00847413", |
00000488 => x"00040663", |
00000489 => x"00400513", |
00000490 => x"badff0ef", |
00000491 => x"00050493", |
00000492 => x"02051863", |
00000493 => x"ffff1537", |
00000494 => x"e6450513", |
00000495 => x"468000ef", |
00000496 => x"000405b7", |
00000497 => x"00048513", |
00000498 => x"f39ff0ef", |
00000499 => x"4788d7b7", |
00000500 => x"afe78793", |
00000501 => x"02f50463", |
00000502 => x"00000513", |
00000503 => x"fcdff06f", |
00000504 => x"ffff1537", |
00000505 => x"e8450513", |
00000506 => x"43c000ef", |
00000507 => x"e1dff0ef", |
00000508 => x"fc0518e3", |
00000509 => x"00300513", |
00000510 => x"fb1ff06f", |
00000511 => x"00040a37", |
00000512 => x"004a0593", |
00000513 => x"00048513", |
00000514 => x"ef9ff0ef", |
00000515 => x"00050913", |
00000516 => x"008a0593", |
00000517 => x"00048513", |
00000518 => x"ee9ff0ef", |
00000519 => x"00050a93", |
00000520 => x"fc6017f3", |
00000521 => x"00100513", |
00000522 => x"f927e0e3", |
00000523 => x"fc401bf3", |
00000524 => x"00000993", |
00000525 => x"ffc97b13", |
00000526 => x"00ca0a13", |
00000527 => x"014985b3", |
00000528 => x"053b1663", |
00000529 => x"01540433", |
00000530 => x"00200513", |
00000531 => x"f4041ee3", |
00000532 => x"ffff1537", |
00000533 => x"e9050513", |
00000534 => x"3cc000ef", |
00000535 => x"34091073", |
00000536 => x"02c12083", |
00000537 => x"02812403", |
00000538 => x"02412483", |
00000539 => x"02012903", |
00000540 => x"01c12983", |
00000541 => x"01812a03", |
00000542 => x"01412a83", |
00000543 => x"01012b03", |
00000544 => x"00c12b83", |
00000545 => x"03010113", |
00000546 => x"00008067", |
00000547 => x"00048513", |
00000548 => x"e71ff0ef", |
00000549 => x"017987b3", |
00000550 => x"00a40433", |
00000551 => x"00a7a023", |
00000552 => x"00498993", |
00000553 => x"f99ff06f", |
00000554 => x"ff010113", |
00000555 => x"00112623", |
00000556 => x"00812423", |
00000557 => x"00912223", |
00000558 => x"00058413", |
00000559 => x"00050493", |
00000560 => x"d8dff0ef", |
00000561 => x"00000513", |
00000562 => x"414000ef", |
00000563 => x"00200513", |
00000564 => x"450000ef", |
00000565 => x"00048513", |
00000566 => x"d9dff0ef", |
00000567 => x"00040513", |
00000568 => x"440000ef", |
00000569 => x"00000513", |
00000570 => x"414000ef", |
00000571 => x"cd9ff0ef", |
00000572 => x"00157513", |
00000573 => x"fe051ce3", |
00000574 => x"00c12083", |
00000575 => x"00812403", |
00000576 => x"00412483", |
00000577 => x"01010113", |
00000578 => x"00008067", |
00000579 => x"fe010113", |
00000580 => x"00812c23", |
00000581 => x"00912a23", |
00000582 => x"01212823", |
00000583 => x"00112e23", |
00000584 => x"00b12623", |
00000585 => x"00300413", |
00000586 => x"00350493", |
00000587 => x"fff00913", |
00000588 => x"00c10793", |
00000589 => x"008787b3", |
00000590 => x"0007c583", |
00000591 => x"40848533", |
00000592 => x"fff40413", |
00000593 => x"f65ff0ef", |
00000594 => x"ff2414e3", |
00000595 => x"01c12083", |
00000596 => x"01812403", |
00000597 => x"01412483", |
00000598 => x"01012903", |
00000599 => x"02010113", |
00000600 => x"00008067", |
00000601 => x"ff010113", |
00000602 => x"00112623", |
00000603 => x"00812423", |
00000604 => x"00050413", |
00000605 => x"cd9ff0ef", |
00000606 => x"00000513", |
00000607 => x"360000ef", |
00000608 => x"0d800513", |
00000609 => x"39c000ef", |
00000610 => x"00040513", |
00000611 => x"ce9ff0ef", |
00000612 => x"00000513", |
00000613 => x"368000ef", |
00000614 => x"c2dff0ef", |
00000615 => x"00157513", |
00000616 => x"fe051ce3", |
00000617 => x"00c12083", |
00000618 => x"00812403", |
00000619 => x"01010113", |
00000620 => x"00008067", |
00000621 => x"fe010113", |
00000622 => x"00112e23", |
00000623 => x"00812c23", |
00000624 => x"00912a23", |
00000625 => x"01212823", |
00000626 => x"01312623", |
00000627 => x"01412423", |
00000628 => x"01512223", |
00000629 => x"34001473", |
00000630 => x"02041863", |
00000631 => x"ffff1537", |
00000632 => x"e0c50513", |
00000633 => x"01812403", |
00000634 => x"01c12083", |
00000635 => x"01412483", |
00000636 => x"01012903", |
00000637 => x"00c12983", |
00000638 => x"00812a03", |
00000639 => x"00412a83", |
00000640 => x"02010113", |
00000641 => x"2200006f", |
00000642 => x"ffff1537", |
00000643 => x"e9450513", |
00000644 => x"214000ef", |
00000645 => x"00040513", |
00000646 => x"98dff0ef", |
00000289 => x"e6050513", |
00000290 => x"7b0000ef", |
00000291 => x"00040513", |
00000292 => x"f29ff0ef", |
00000293 => x"ffff1537", |
00000294 => x"e7050513", |
00000295 => x"79c000ef", |
00000296 => x"34102573", |
00000297 => x"f15ff0ef", |
00000298 => x"00500513", |
00000299 => x"ebdff0ef", |
00000300 => x"00000513", |
00000301 => x"095000ef", |
00000302 => x"6b0000ef", |
00000303 => x"fc1027f3", |
00000304 => x"0027d793", |
00000305 => x"00a78533", |
00000306 => x"00f537b3", |
00000307 => x"00b785b3", |
00000308 => x"6a4000ef", |
00000309 => x"03c12403", |
00000310 => x"04c12083", |
00000311 => x"04812283", |
00000312 => x"04412303", |
00000313 => x"04012383", |
00000314 => x"03812503", |
00000315 => x"03412583", |
00000316 => x"03012603", |
00000317 => x"02c12683", |
00000318 => x"02812703", |
00000319 => x"02412783", |
00000320 => x"02012803", |
00000321 => x"01c12883", |
00000322 => x"01812e03", |
00000323 => x"01412e83", |
00000324 => x"01012f03", |
00000325 => x"00c12f83", |
00000326 => x"05010113", |
00000327 => x"30200073", |
00000328 => x"fe010113", |
00000329 => x"00112e23", |
00000330 => x"00812c23", |
00000331 => x"00912a23", |
00000332 => x"01212823", |
00000333 => x"01312623", |
00000334 => x"01412423", |
00000335 => x"01512223", |
00000336 => x"f1302973", |
00000337 => x"00000a93", |
00000338 => x"00900993", |
00000339 => x"00300a13", |
00000340 => x"00400493", |
00000341 => x"41500433", |
00000342 => x"00341413", |
00000343 => x"01840413", |
00000344 => x"00895433", |
00000345 => x"0ff47413", |
00000346 => x"00000513", |
00000347 => x"0489ec63", |
00000348 => x"00050863", |
00000349 => x"03050513", |
00000350 => x"0ff57513", |
00000351 => x"69c000ef", |
00000352 => x"03040513", |
00000353 => x"0ff57513", |
00000354 => x"690000ef", |
00000355 => x"014a8663", |
00000356 => x"02e00513", |
00000357 => x"684000ef", |
00000358 => x"001a8a93", |
00000359 => x"fa9a9ce3", |
00000360 => x"01c12083", |
00000361 => x"01812403", |
00000362 => x"01412483", |
00000363 => x"01012903", |
00000364 => x"00c12983", |
00000365 => x"00812a03", |
00000366 => x"00412a83", |
00000367 => x"02010113", |
00000368 => x"00008067", |
00000369 => x"ff640413", |
00000370 => x"00150513", |
00000371 => x"0ff47413", |
00000372 => x"0ff57513", |
00000373 => x"f99ff06f", |
00000374 => x"ff010113", |
00000375 => x"00000513", |
00000376 => x"00112623", |
00000377 => x"00812423", |
00000378 => x"708000ef", |
00000379 => x"00500513", |
00000380 => x"744000ef", |
00000381 => x"00000513", |
00000382 => x"73c000ef", |
00000383 => x"00050413", |
00000384 => x"00000513", |
00000385 => x"70c000ef", |
00000386 => x"00c12083", |
00000387 => x"0ff47513", |
00000388 => x"00812403", |
00000389 => x"01010113", |
00000390 => x"00008067", |
00000391 => x"ff010113", |
00000392 => x"00000513", |
00000393 => x"00112623", |
00000394 => x"00812423", |
00000395 => x"6c4000ef", |
00000396 => x"09e00513", |
00000397 => x"700000ef", |
00000398 => x"00000513", |
00000399 => x"6f8000ef", |
00000400 => x"00050413", |
00000401 => x"00000513", |
00000402 => x"6c8000ef", |
00000403 => x"00c12083", |
00000404 => x"0ff47513", |
00000405 => x"00812403", |
00000406 => x"01010113", |
00000407 => x"00008067", |
00000408 => x"ff010113", |
00000409 => x"00000513", |
00000410 => x"00112623", |
00000411 => x"684000ef", |
00000412 => x"00600513", |
00000413 => x"6c0000ef", |
00000414 => x"00c12083", |
00000415 => x"00000513", |
00000416 => x"01010113", |
00000417 => x"68c0006f", |
00000418 => x"ff010113", |
00000419 => x"00812423", |
00000420 => x"00050413", |
00000421 => x"01055513", |
00000422 => x"0ff57513", |
00000423 => x"00112623", |
00000424 => x"694000ef", |
00000425 => x"00845513", |
00000426 => x"0ff57513", |
00000427 => x"688000ef", |
00000428 => x"0ff47513", |
00000429 => x"00812403", |
00000430 => x"00c12083", |
00000431 => x"01010113", |
00000432 => x"6740006f", |
00000433 => x"ff010113", |
00000434 => x"00812423", |
00000435 => x"00050413", |
00000436 => x"00000513", |
00000437 => x"00112623", |
00000438 => x"618000ef", |
00000439 => x"00300513", |
00000440 => x"654000ef", |
00000441 => x"00040513", |
00000442 => x"fa1ff0ef", |
00000443 => x"00000513", |
00000444 => x"644000ef", |
00000445 => x"00050413", |
00000446 => x"00000513", |
00000447 => x"614000ef", |
00000448 => x"00c12083", |
00000449 => x"0ff47513", |
00000450 => x"00812403", |
00000451 => x"01010113", |
00000452 => x"00008067", |
00000453 => x"fd010113", |
00000454 => x"02812423", |
00000455 => x"02912223", |
00000456 => x"03212023", |
00000457 => x"01312e23", |
00000458 => x"02112623", |
00000459 => x"00050493", |
00000460 => x"00300413", |
00000461 => x"00358913", |
00000462 => x"fff00993", |
00000463 => x"02049e63", |
00000464 => x"4e8000ef", |
00000465 => x"00c10793", |
00000466 => x"008787b3", |
00000467 => x"00a78023", |
00000468 => x"fff40413", |
00000469 => x"ff3414e3", |
00000470 => x"02c12083", |
00000471 => x"02812403", |
00000472 => x"00c12503", |
00000473 => x"02412483", |
00000474 => x"02012903", |
00000475 => x"01c12983", |
00000476 => x"03010113", |
00000477 => x"00008067", |
00000478 => x"40890533", |
00000479 => x"f49ff0ef", |
00000480 => x"fc5ff06f", |
00000481 => x"fd010113", |
00000482 => x"02112623", |
00000483 => x"02812423", |
00000484 => x"02912223", |
00000485 => x"03212023", |
00000486 => x"01312e23", |
00000487 => x"01412c23", |
00000488 => x"01512a23", |
00000489 => x"01612823", |
00000490 => x"01712623", |
00000491 => x"fc002473", |
00000492 => x"00847413", |
00000493 => x"00040663", |
00000494 => x"00400513", |
00000495 => x"badff0ef", |
00000496 => x"00050493", |
00000497 => x"02051863", |
00000498 => x"ffff1537", |
00000499 => x"e7850513", |
00000500 => x"468000ef", |
00000501 => x"000405b7", |
00000502 => x"00048513", |
00000503 => x"f39ff0ef", |
00000504 => x"4788d7b7", |
00000505 => x"afe78793", |
00000506 => x"02f50463", |
00000507 => x"00000513", |
00000508 => x"fcdff06f", |
00000509 => x"ffff1537", |
00000510 => x"e9850513", |
00000511 => x"43c000ef", |
00000512 => x"e1dff0ef", |
00000513 => x"fc0518e3", |
00000514 => x"00300513", |
00000515 => x"fb1ff06f", |
00000516 => x"00040a37", |
00000517 => x"004a0593", |
00000518 => x"00048513", |
00000519 => x"ef9ff0ef", |
00000520 => x"00050913", |
00000521 => x"008a0593", |
00000522 => x"00048513", |
00000523 => x"ee9ff0ef", |
00000524 => x"00050a93", |
00000525 => x"fc6027f3", |
00000526 => x"00100513", |
00000527 => x"f927e0e3", |
00000528 => x"fc402bf3", |
00000529 => x"00000993", |
00000530 => x"ffc97b13", |
00000531 => x"00ca0a13", |
00000532 => x"014985b3", |
00000533 => x"053b1663", |
00000534 => x"01540433", |
00000535 => x"00200513", |
00000536 => x"f4041ee3", |
00000537 => x"ffff1537", |
00000538 => x"ea450513", |
00000539 => x"3cc000ef", |
00000540 => x"34091073", |
00000541 => x"02c12083", |
00000542 => x"02812403", |
00000543 => x"02412483", |
00000544 => x"02012903", |
00000545 => x"01c12983", |
00000546 => x"01812a03", |
00000547 => x"01412a83", |
00000548 => x"01012b03", |
00000549 => x"00c12b83", |
00000550 => x"03010113", |
00000551 => x"00008067", |
00000552 => x"00048513", |
00000553 => x"e71ff0ef", |
00000554 => x"017987b3", |
00000555 => x"00a40433", |
00000556 => x"00a7a023", |
00000557 => x"00498993", |
00000558 => x"f99ff06f", |
00000559 => x"ff010113", |
00000560 => x"00112623", |
00000561 => x"00812423", |
00000562 => x"00912223", |
00000563 => x"00058413", |
00000564 => x"00050493", |
00000565 => x"d8dff0ef", |
00000566 => x"00000513", |
00000567 => x"414000ef", |
00000568 => x"00200513", |
00000569 => x"450000ef", |
00000570 => x"00048513", |
00000571 => x"d9dff0ef", |
00000572 => x"00040513", |
00000573 => x"440000ef", |
00000574 => x"00000513", |
00000575 => x"414000ef", |
00000576 => x"cd9ff0ef", |
00000577 => x"00157513", |
00000578 => x"fe051ce3", |
00000579 => x"00c12083", |
00000580 => x"00812403", |
00000581 => x"00412483", |
00000582 => x"01010113", |
00000583 => x"00008067", |
00000584 => x"fe010113", |
00000585 => x"00812c23", |
00000586 => x"00912a23", |
00000587 => x"01212823", |
00000588 => x"00112e23", |
00000589 => x"00b12623", |
00000590 => x"00300413", |
00000591 => x"00350493", |
00000592 => x"fff00913", |
00000593 => x"00c10793", |
00000594 => x"008787b3", |
00000595 => x"0007c583", |
00000596 => x"40848533", |
00000597 => x"fff40413", |
00000598 => x"f65ff0ef", |
00000599 => x"ff2414e3", |
00000600 => x"01c12083", |
00000601 => x"01812403", |
00000602 => x"01412483", |
00000603 => x"01012903", |
00000604 => x"02010113", |
00000605 => x"00008067", |
00000606 => x"ff010113", |
00000607 => x"00112623", |
00000608 => x"00812423", |
00000609 => x"00050413", |
00000610 => x"cd9ff0ef", |
00000611 => x"00000513", |
00000612 => x"360000ef", |
00000613 => x"0d800513", |
00000614 => x"39c000ef", |
00000615 => x"00040513", |
00000616 => x"ce9ff0ef", |
00000617 => x"00000513", |
00000618 => x"368000ef", |
00000619 => x"c2dff0ef", |
00000620 => x"00157513", |
00000621 => x"fe051ce3", |
00000622 => x"00c12083", |
00000623 => x"00812403", |
00000624 => x"01010113", |
00000625 => x"00008067", |
00000626 => x"fe010113", |
00000627 => x"00112e23", |
00000628 => x"00812c23", |
00000629 => x"00912a23", |
00000630 => x"01212823", |
00000631 => x"01312623", |
00000632 => x"01412423", |
00000633 => x"01512223", |
00000634 => x"34002473", |
00000635 => x"02041863", |
00000636 => x"ffff1537", |
00000637 => x"e2050513", |
00000638 => x"01812403", |
00000639 => x"01c12083", |
00000640 => x"01412483", |
00000641 => x"01012903", |
00000642 => x"00c12983", |
00000643 => x"00812a03", |
00000644 => x"00412a83", |
00000645 => x"02010113", |
00000646 => x"2200006f", |
00000647 => x"ffff1537", |
00000648 => x"ea050513", |
00000649 => x"200000ef", |
00000650 => x"00040537", |
00000651 => x"979ff0ef", |
00000648 => x"ea850513", |
00000649 => x"214000ef", |
00000650 => x"00040513", |
00000651 => x"98dff0ef", |
00000652 => x"ffff1537", |
00000653 => x"ebc50513", |
00000654 => x"1ec000ef", |
00000655 => x"1d8000ef", |
00000656 => x"00050493", |
00000657 => x"1c0000ef", |
00000658 => x"07900793", |
00000659 => x"0af49e63", |
00000660 => x"bb9ff0ef", |
00000661 => x"00051663", |
00000662 => x"00300513", |
00000663 => x"8f9ff0ef", |
00000664 => x"ffff1537", |
00000665 => x"ec850513", |
00000666 => x"01045493", |
00000667 => x"1b8000ef", |
00000668 => x"00148493", |
00000669 => x"00040937", |
00000670 => x"fff00993", |
00000671 => x"00010a37", |
00000672 => x"fff48493", |
00000673 => x"07349063", |
00000674 => x"4788d5b7", |
00000675 => x"afe58593", |
00000676 => x"00040537", |
00000677 => x"e79ff0ef", |
00000678 => x"00040537", |
00000679 => x"00040593", |
00000680 => x"00450513", |
00000681 => x"e69ff0ef", |
00000682 => x"fc401a73", |
00000683 => x"000409b7", |
00000684 => x"ffc47413", |
00000685 => x"00000493", |
00000686 => x"00000913", |
00000687 => x"00c98a93", |
00000688 => x"01548533", |
00000689 => x"014487b3", |
00000690 => x"02849663", |
00000691 => x"00898513", |
00000692 => x"412005b3", |
00000693 => x"e39ff0ef", |
00000694 => x"ffff1537", |
00000695 => x"e9050513", |
00000696 => x"f05ff06f", |
00000697 => x"00090513", |
00000698 => x"e7dff0ef", |
00000699 => x"01490933", |
00000700 => x"f91ff06f", |
00000701 => x"0007a583", |
00000702 => x"00448493", |
00000703 => x"00b90933", |
00000704 => x"e0dff0ef", |
00000705 => x"fbdff06f", |
00000706 => x"01c12083", |
00000707 => x"01812403", |
00000708 => x"01412483", |
00000709 => x"01012903", |
00000710 => x"00c12983", |
00000711 => x"00812a03", |
00000712 => x"00412a83", |
00000713 => x"02010113", |
00000714 => x"00008067", |
00000715 => x"000047b7", |
00000716 => x"70078793", |
00000717 => x"f8f02623", |
00000718 => x"00008067", |
00000719 => x"fc000713", |
00000720 => x"00072783", |
00000721 => x"00179793", |
00000722 => x"0017d793", |
00000723 => x"00f72023", |
00000724 => x"00008067", |
00000725 => x"f9002503", |
00000726 => x"f9402583", |
00000727 => x"00008067", |
00000728 => x"f9800693", |
00000729 => x"fff00613", |
00000730 => x"00c6a023", |
00000731 => x"00a6a023", |
00000732 => x"00b6a223", |
00000733 => x"00008067", |
00000734 => x"fa002023", |
00000735 => x"fc1016f3", |
00000736 => x"00000713", |
00000737 => x"00151513", |
00000738 => x"04a6f263", |
00000739 => x"000016b7", |
00000740 => x"00000793", |
00000741 => x"ffe68693", |
00000742 => x"04e6e463", |
00000743 => x"00167613", |
00000744 => x"0015f593", |
00000745 => x"01879793", |
00000746 => x"01e61613", |
00000747 => x"00c7e7b3", |
00000748 => x"01d59593", |
00000749 => x"00b7e7b3", |
00000750 => x"00e7e7b3", |
00000751 => x"10000737", |
00000752 => x"00e7e7b3", |
00000753 => x"faf02023", |
00000754 => x"00008067", |
00000755 => x"00170793", |
00000756 => x"01079713", |
00000757 => x"40a686b3", |
00000758 => x"01075713", |
00000759 => x"fadff06f", |
00000760 => x"ffe78513", |
00000761 => x"0fd57513", |
00000762 => x"00051a63", |
00000763 => x"00375713", |
00000764 => x"00178793", |
00000765 => x"0ff7f793", |
00000766 => x"fa1ff06f", |
00000767 => x"00175713", |
00000768 => x"ff1ff06f", |
00000769 => x"fa002783", |
00000770 => x"fe07cee3", |
00000771 => x"faa02223", |
00000772 => x"00008067", |
00000773 => x"fa402503", |
00000774 => x"fe055ee3", |
00000775 => x"0ff57513", |
00000776 => x"00008067", |
00000777 => x"ff010113", |
00000778 => x"00812423", |
00000779 => x"01212023", |
00000780 => x"00112623", |
00000781 => x"00912223", |
00000782 => x"00050413", |
00000783 => x"00a00913", |
00000784 => x"00044483", |
00000785 => x"00140413", |
00000786 => x"00049e63", |
00000787 => x"00c12083", |
00000788 => x"00812403", |
00000789 => x"00412483", |
00000790 => x"00012903", |
00000791 => x"01010113", |
00000792 => x"00008067", |
00000793 => x"01249663", |
00000794 => x"00d00513", |
00000795 => x"f99ff0ef", |
00000796 => x"00048513", |
00000797 => x"f91ff0ef", |
00000798 => x"fc9ff06f", |
00000799 => x"00757513", |
00000800 => x"00177793", |
00000801 => x"01079793", |
00000802 => x"0036f693", |
00000803 => x"00a51513", |
00000804 => x"00f56533", |
00000805 => x"00167613", |
00000806 => x"00e69793", |
00000807 => x"0015f593", |
00000808 => x"00f567b3", |
00000809 => x"00d61613", |
00000810 => x"00c7e7b3", |
00000811 => x"00959593", |
00000812 => x"fa800813", |
00000813 => x"00b7e7b3", |
00000814 => x"00082023", |
00000815 => x"1007e793", |
00000816 => x"00f82023", |
00000817 => x"00008067", |
00000818 => x"fa800713", |
00000819 => x"00072783", |
00000820 => x"eff7f793", |
00000821 => x"00f72023", |
00000653 => x"eb450513", |
00000654 => x"200000ef", |
00000655 => x"00040537", |
00000656 => x"979ff0ef", |
00000657 => x"ffff1537", |
00000658 => x"ed050513", |
00000659 => x"1ec000ef", |
00000660 => x"1d8000ef", |
00000661 => x"00050493", |
00000662 => x"1c0000ef", |
00000663 => x"07900793", |
00000664 => x"0af49e63", |
00000665 => x"bb9ff0ef", |
00000666 => x"00051663", |
00000667 => x"00300513", |
00000668 => x"8f9ff0ef", |
00000669 => x"ffff1537", |
00000670 => x"edc50513", |
00000671 => x"01045493", |
00000672 => x"1b8000ef", |
00000673 => x"00148493", |
00000674 => x"00040937", |
00000675 => x"fff00993", |
00000676 => x"00010a37", |
00000677 => x"fff48493", |
00000678 => x"07349063", |
00000679 => x"4788d5b7", |
00000680 => x"afe58593", |
00000681 => x"00040537", |
00000682 => x"e79ff0ef", |
00000683 => x"00040537", |
00000684 => x"00040593", |
00000685 => x"00450513", |
00000686 => x"e69ff0ef", |
00000687 => x"fc402a73", |
00000688 => x"000409b7", |
00000689 => x"ffc47413", |
00000690 => x"00000493", |
00000691 => x"00000913", |
00000692 => x"00c98a93", |
00000693 => x"01548533", |
00000694 => x"014487b3", |
00000695 => x"02849663", |
00000696 => x"00898513", |
00000697 => x"412005b3", |
00000698 => x"e39ff0ef", |
00000699 => x"ffff1537", |
00000700 => x"ea450513", |
00000701 => x"f05ff06f", |
00000702 => x"00090513", |
00000703 => x"e7dff0ef", |
00000704 => x"01490933", |
00000705 => x"f91ff06f", |
00000706 => x"0007a583", |
00000707 => x"00448493", |
00000708 => x"00b90933", |
00000709 => x"e0dff0ef", |
00000710 => x"fbdff06f", |
00000711 => x"01c12083", |
00000712 => x"01812403", |
00000713 => x"01412483", |
00000714 => x"01012903", |
00000715 => x"00c12983", |
00000716 => x"00812a03", |
00000717 => x"00412a83", |
00000718 => x"02010113", |
00000719 => x"00008067", |
00000720 => x"000047b7", |
00000721 => x"70078793", |
00000722 => x"f8f02623", |
00000723 => x"00008067", |
00000724 => x"fc000713", |
00000725 => x"00072783", |
00000726 => x"00179793", |
00000727 => x"0017d793", |
00000728 => x"00f72023", |
00000729 => x"00008067", |
00000730 => x"f9002503", |
00000731 => x"f9402583", |
00000732 => x"00008067", |
00000733 => x"f9800693", |
00000734 => x"fff00613", |
00000735 => x"00c6a023", |
00000736 => x"00a6a023", |
00000737 => x"00b6a223", |
00000738 => x"00008067", |
00000739 => x"fa002023", |
00000740 => x"fc1026f3", |
00000741 => x"00000713", |
00000742 => x"00151513", |
00000743 => x"04a6f263", |
00000744 => x"000016b7", |
00000745 => x"00000793", |
00000746 => x"ffe68693", |
00000747 => x"04e6e463", |
00000748 => x"00167613", |
00000749 => x"0015f593", |
00000750 => x"01879793", |
00000751 => x"01e61613", |
00000752 => x"00c7e7b3", |
00000753 => x"01d59593", |
00000754 => x"00b7e7b3", |
00000755 => x"00e7e7b3", |
00000756 => x"10000737", |
00000757 => x"00e7e7b3", |
00000758 => x"faf02023", |
00000759 => x"00008067", |
00000760 => x"00170793", |
00000761 => x"01079713", |
00000762 => x"40a686b3", |
00000763 => x"01075713", |
00000764 => x"fadff06f", |
00000765 => x"ffe78513", |
00000766 => x"0fd57513", |
00000767 => x"00051a63", |
00000768 => x"00375713", |
00000769 => x"00178793", |
00000770 => x"0ff7f793", |
00000771 => x"fa1ff06f", |
00000772 => x"00175713", |
00000773 => x"ff1ff06f", |
00000774 => x"fa002783", |
00000775 => x"fe07cee3", |
00000776 => x"faa02223", |
00000777 => x"00008067", |
00000778 => x"fa402503", |
00000779 => x"fe055ee3", |
00000780 => x"0ff57513", |
00000781 => x"00008067", |
00000782 => x"ff010113", |
00000783 => x"00812423", |
00000784 => x"01212023", |
00000785 => x"00112623", |
00000786 => x"00912223", |
00000787 => x"00050413", |
00000788 => x"00a00913", |
00000789 => x"00044483", |
00000790 => x"00140413", |
00000791 => x"00049e63", |
00000792 => x"00c12083", |
00000793 => x"00812403", |
00000794 => x"00412483", |
00000795 => x"00012903", |
00000796 => x"01010113", |
00000797 => x"00008067", |
00000798 => x"01249663", |
00000799 => x"00d00513", |
00000800 => x"f99ff0ef", |
00000801 => x"00048513", |
00000802 => x"f91ff0ef", |
00000803 => x"fc9ff06f", |
00000804 => x"00757513", |
00000805 => x"00177793", |
00000806 => x"01079793", |
00000807 => x"0036f693", |
00000808 => x"00a51513", |
00000809 => x"00f56533", |
00000810 => x"00167613", |
00000811 => x"00e69793", |
00000812 => x"0015f593", |
00000813 => x"00f567b3", |
00000814 => x"00d61613", |
00000815 => x"00c7e7b3", |
00000816 => x"00959593", |
00000817 => x"fa800813", |
00000818 => x"00b7e7b3", |
00000819 => x"00082023", |
00000820 => x"1007e793", |
00000821 => x"00f82023", |
00000822 => x"00008067", |
00000823 => x"fa800713", |
00000824 => x"00072683", |
00000825 => x"00757793", |
00000826 => x"00100513", |
00000827 => x"00f51533", |
00000828 => x"00d56533", |
00000829 => x"00a72023", |
00000830 => x"00008067", |
00000831 => x"fa800713", |
00000832 => x"00072683", |
00000833 => x"00757513", |
00000834 => x"00100793", |
00000835 => x"00a797b3", |
00000836 => x"fff7c793", |
00000837 => x"00d7f7b3", |
00000838 => x"00f72023", |
00000839 => x"00008067", |
00000840 => x"faa02623", |
00000841 => x"fa802783", |
00000842 => x"fe07cee3", |
00000843 => x"fac02503", |
00000824 => x"00072783", |
00000825 => x"eff7f793", |
00000826 => x"00f72023", |
00000827 => x"00008067", |
00000828 => x"fa800713", |
00000829 => x"00072683", |
00000830 => x"00757793", |
00000831 => x"00100513", |
00000832 => x"00f51533", |
00000833 => x"00d56533", |
00000834 => x"00a72023", |
00000835 => x"00008067", |
00000836 => x"fa800713", |
00000837 => x"00072683", |
00000838 => x"00757513", |
00000839 => x"00100793", |
00000840 => x"00a797b3", |
00000841 => x"fff7c793", |
00000842 => x"00d7f7b3", |
00000843 => x"00f72023", |
00000844 => x"00008067", |
00000845 => x"f8400713", |
00000846 => x"00072683", |
00000847 => x"00f57793", |
00000848 => x"00100513", |
00000849 => x"00f51533", |
00000850 => x"00d54533", |
00000851 => x"00a72023", |
00000852 => x"00008067", |
00000853 => x"f8a02223", |
00000854 => x"00008067", |
00000855 => x"fb800713", |
00000856 => x"00072783", |
00000857 => x"ffe7f793", |
00000858 => x"00f72023", |
00000845 => x"faa02623", |
00000846 => x"fa802783", |
00000847 => x"fe07cee3", |
00000848 => x"fac02503", |
00000849 => x"00008067", |
00000850 => x"f8400713", |
00000851 => x"00072683", |
00000852 => x"00f57793", |
00000853 => x"00100513", |
00000854 => x"00f51533", |
00000855 => x"00d54533", |
00000856 => x"00a72023", |
00000857 => x"00008067", |
00000858 => x"f8a02223", |
00000859 => x"00008067", |
00000860 => x"30046073", |
00000861 => x"00008067", |
00000862 => x"30047073", |
00000863 => x"00008067", |
00000864 => x"fb000713", |
00000865 => x"00072783", |
00000866 => x"ff77f793", |
00000867 => x"00f72023", |
00000860 => x"fb800713", |
00000861 => x"00072783", |
00000862 => x"ffe7f793", |
00000863 => x"00f72023", |
00000864 => x"00008067", |
00000865 => x"30046073", |
00000866 => x"00008067", |
00000867 => x"30047073", |
00000868 => x"00008067", |
00000869 => x"f8800713", |
00000869 => x"fb000713", |
00000870 => x"00072783", |
00000871 => x"fef7f793", |
00000871 => x"ff77f793", |
00000872 => x"00f72023", |
00000873 => x"00008067", |
00000874 => x"69617641", |
00000875 => x"6c62616c", |
00000876 => x"4d432065", |
00000877 => x"0a3a7344", |
00000878 => x"203a6820", |
00000879 => x"706c6548", |
00000880 => x"3a72200a", |
00000881 => x"73655220", |
00000882 => x"74726174", |
00000883 => x"3a75200a", |
00000884 => x"6c705520", |
00000885 => x"0a64616f", |
00000886 => x"203a7320", |
00000887 => x"726f7453", |
00000888 => x"6f742065", |
00000889 => x"616c6620", |
00000890 => x"200a6873", |
00000891 => x"4c203a6c", |
00000892 => x"2064616f", |
00000893 => x"6d6f7266", |
00000874 => x"f8800713", |
00000875 => x"00072783", |
00000876 => x"fef7f793", |
00000877 => x"00f72023", |
00000878 => x"00008067", |
00000879 => x"69617641", |
00000880 => x"6c62616c", |
00000881 => x"4d432065", |
00000882 => x"0a3a7344", |
00000883 => x"203a6820", |
00000884 => x"706c6548", |
00000885 => x"3a72200a", |
00000886 => x"73655220", |
00000887 => x"74726174", |
00000888 => x"3a75200a", |
00000889 => x"6c705520", |
00000890 => x"0a64616f", |
00000891 => x"203a7320", |
00000892 => x"726f7453", |
00000893 => x"6f742065", |
00000894 => x"616c6620", |
00000895 => x"200a6873", |
00000896 => x"45203a65", |
00000897 => x"75636578", |
00000898 => x"00006574", |
00000899 => x"65206f4e", |
00000900 => x"75636578", |
00000901 => x"6c626174", |
00000902 => x"76612065", |
00000903 => x"616c6961", |
00000904 => x"2e656c62", |
00000905 => x"00000000", |
00000906 => x"746f6f42", |
00000907 => x"2e676e69", |
00000908 => x"0a0a2e2e", |
00000909 => x"00000000", |
00000910 => x"52450a07", |
00000911 => x"00005f52", |
00000912 => x"6e6b6e75", |
00000913 => x"006e776f", |
00000914 => x"00007830", |
00000915 => x"58450a0a", |
00000916 => x"54504543", |
00000917 => x"3a4e4f49", |
00000918 => x"00000020", |
00000919 => x"30204020", |
00000920 => x"00000078", |
00000921 => x"69617741", |
00000922 => x"676e6974", |
00000923 => x"6f656e20", |
00000924 => x"32337672", |
00000925 => x"6578655f", |
00000926 => x"6e69622e", |
00000927 => x"202e2e2e", |
00000928 => x"00000000", |
00000929 => x"64616f4c", |
00000930 => x"2e676e69", |
00000931 => x"00202e2e", |
00000932 => x"00004b4f", |
00000933 => x"74697257", |
00000934 => x"78302065", |
00000935 => x"00000000", |
00000936 => x"74796220", |
00000937 => x"74207365", |
00000938 => x"5053206f", |
00000939 => x"6c662049", |
00000940 => x"20687361", |
00000941 => x"78302040", |
00000942 => x"00000000", |
00000943 => x"7928203f", |
00000944 => x"20296e2f", |
00000945 => x"00000000", |
00000946 => x"616c460a", |
00000947 => x"6e696873", |
00000948 => x"2e2e2e67", |
00000949 => x"00000020", |
00000950 => x"0a0a0a0a", |
00000951 => x"4e203c3c", |
00000952 => x"56524f45", |
00000953 => x"42203233", |
00000954 => x"6c746f6f", |
00000955 => x"6564616f", |
00000956 => x"3e3e2072", |
00000957 => x"4c420a0a", |
00000958 => x"203a5644", |
00000959 => x"206e754a", |
00000960 => x"32203732", |
00000961 => x"0a303230", |
00000962 => x"3a565748", |
00000963 => x"00002020", |
00000964 => x"4b4c430a", |
00000965 => x"0020203a", |
00000966 => x"0a7a4820", |
00000967 => x"4153494d", |
00000968 => x"0000203a", |
00000969 => x"4e4f430a", |
00000970 => x"00203a46", |
00000971 => x"454d490a", |
00000972 => x"00203a4d", |
00000973 => x"74796220", |
00000974 => x"40207365", |
00000975 => x"00000020", |
00000976 => x"454d440a", |
00000977 => x"00203a4d", |
00000978 => x"75410a0a", |
00000979 => x"6f626f74", |
00000980 => x"6920746f", |
00000981 => x"3828206e", |
00000982 => x"202e7329", |
00000983 => x"73657250", |
00000984 => x"656b2073", |
00000985 => x"6f742079", |
00000986 => x"6f626120", |
00000987 => x"0a2e7472", |
00000988 => x"00000000", |
00000989 => x"0000000a", |
00000990 => x"726f6241", |
00000991 => x"2e646574", |
00000992 => x"00000a0a", |
00000993 => x"444d430a", |
00000994 => x"00203e3a", |
00000995 => x"53207962", |
00000996 => x"68706574", |
00000997 => x"4e206e61", |
00000998 => x"69746c6f", |
00000999 => x"0000676e", |
00001000 => x"61766e49", |
00001001 => x"2064696c", |
00001002 => x"00444d43", |
00001003 => x"33323130", |
00001004 => x"37363534", |
00001005 => x"42413938", |
00001006 => x"46454443", |
00000896 => x"4c203a6c", |
00000897 => x"2064616f", |
00000898 => x"6d6f7266", |
00000899 => x"616c6620", |
00000900 => x"200a6873", |
00000901 => x"45203a65", |
00000902 => x"75636578", |
00000903 => x"00006574", |
00000904 => x"65206f4e", |
00000905 => x"75636578", |
00000906 => x"6c626174", |
00000907 => x"76612065", |
00000908 => x"616c6961", |
00000909 => x"2e656c62", |
00000910 => x"00000000", |
00000911 => x"746f6f42", |
00000912 => x"2e676e69", |
00000913 => x"0a0a2e2e", |
00000914 => x"00000000", |
00000915 => x"52450a07", |
00000916 => x"00005f52", |
00000917 => x"6e6b6e75", |
00000918 => x"006e776f", |
00000919 => x"00007830", |
00000920 => x"58450a0a", |
00000921 => x"54504543", |
00000922 => x"3a4e4f49", |
00000923 => x"00000020", |
00000924 => x"30204020", |
00000925 => x"00000078", |
00000926 => x"69617741", |
00000927 => x"676e6974", |
00000928 => x"6f656e20", |
00000929 => x"32337672", |
00000930 => x"6578655f", |
00000931 => x"6e69622e", |
00000932 => x"202e2e2e", |
00000933 => x"00000000", |
00000934 => x"64616f4c", |
00000935 => x"2e676e69", |
00000936 => x"00202e2e", |
00000937 => x"00004b4f", |
00000938 => x"74697257", |
00000939 => x"78302065", |
00000940 => x"00000000", |
00000941 => x"74796220", |
00000942 => x"74207365", |
00000943 => x"5053206f", |
00000944 => x"6c662049", |
00000945 => x"20687361", |
00000946 => x"78302040", |
00000947 => x"00000000", |
00000948 => x"7928203f", |
00000949 => x"20296e2f", |
00000950 => x"00000000", |
00000951 => x"616c460a", |
00000952 => x"6e696873", |
00000953 => x"2e2e2e67", |
00000954 => x"00000020", |
00000955 => x"0a0a0a0a", |
00000956 => x"4e203c3c", |
00000957 => x"56524f45", |
00000958 => x"42203233", |
00000959 => x"6c746f6f", |
00000960 => x"6564616f", |
00000961 => x"3e3e2072", |
00000962 => x"4c420a0a", |
00000963 => x"203a5644", |
00000964 => x"206c754a", |
00000965 => x"32203520", |
00000966 => x"0a303230", |
00000967 => x"3a565748", |
00000968 => x"00002020", |
00000969 => x"4b4c430a", |
00000970 => x"0020203a", |
00000971 => x"0a7a4820", |
00000972 => x"4449484d", |
00000973 => x"0000203a", |
00000974 => x"53494d0a", |
00000975 => x"00203a41", |
00000976 => x"4e4f430a", |
00000977 => x"00203a46", |
00000978 => x"454d490a", |
00000979 => x"00203a4d", |
00000980 => x"74796220", |
00000981 => x"40207365", |
00000982 => x"00000020", |
00000983 => x"454d440a", |
00000984 => x"00203a4d", |
00000985 => x"75410a0a", |
00000986 => x"6f626f74", |
00000987 => x"6920746f", |
00000988 => x"3828206e", |
00000989 => x"202e7329", |
00000990 => x"73657250", |
00000991 => x"656b2073", |
00000992 => x"6f742079", |
00000993 => x"6f626120", |
00000994 => x"0a2e7472", |
00000995 => x"00000000", |
00000996 => x"0000000a", |
00000997 => x"726f6241", |
00000998 => x"2e646574", |
00000999 => x"00000a0a", |
00001000 => x"444d430a", |
00001001 => x"00203e3a", |
00001002 => x"53207962", |
00001003 => x"68706574", |
00001004 => x"4e206e61", |
00001005 => x"69746c6f", |
00001006 => x"0000676e", |
00001007 => x"61766e49", |
00001008 => x"2064696c", |
00001009 => x"00444d43", |
00001010 => x"33323130", |
00001011 => x"37363534", |
00001012 => x"42413938", |
00001013 => x"46454443", |
others => x"00000000" |
); |
|
/neorv32_cpu.vhd
53,6 → 53,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
109,8 → 110,6
signal ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus |
signal alu_cmp : std_ulogic_vector(1 downto 0); -- alu comparator result |
signal imm : std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
signal pc : std_ulogic_vector(data_width_c-1 downto 0); -- current program counter |
signal pc_delayed : std_ulogic_vector(data_width_c-1 downto 0); -- delayed program counter |
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction |
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers |
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result |
127,6 → 126,10
signal be_load : std_ulogic; -- bus error on load data access |
signal be_store : std_ulogic; -- bus error on store data access |
signal bus_exc_ack : std_ulogic; -- bus exception error acknowledge |
signal bus_busy : std_ulogic; -- bus unit is busy |
signal fetch_pc : std_ulogic_vector(data_width_c-1 downto 0); -- pc for instruction fetch |
signal curr_pc : std_ulogic_vector(data_width_c-1 downto 0); -- current pc (for current executed instruction) |
signal next_pc : std_ulogic_vector(data_width_c-1 downto 0); -- next pc (for current executed instruction) |
|
-- co-processor interface -- |
signal cp0_data, cp1_data : std_ulogic_vector(data_width_c-1 downto 0); |
139,9 → 142,10
neorv32_cpu_control_inst: neorv32_cpu_control |
generic map ( |
-- General -- |
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz |
HART_ID => HART_ID, -- custom hardware thread ID |
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader? |
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz |
HART_ID => HART_ID, -- custom hardware thread ID |
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader? |
CSR_COUNTERS_USE => CSR_COUNTERS_USE, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- 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? |
186,8 → 190,9
alu_add_i => alu_add, -- ALU.add result |
-- data output -- |
imm_o => imm, -- immediate |
pc_o => pc, -- current PC |
alu_pc_o => pc_delayed, -- delayed PC for ALU |
fetch_pc_o => fetch_pc, -- PC for instruction fetch |
curr_pc_o => curr_pc, -- current PC (corresponding to current instruction) |
next_pc_o => next_pc, -- next PC (corresponding to current instruction) |
-- csr interface -- |
csr_wdata_i => alu_res, -- CSR write data |
csr_rdata_o => csr_rdata, -- CSR read data |
202,7 → 207,8
be_instr_i => be_instr, -- bus error on instruction access |
be_load_i => be_load, -- bus error on load data access |
be_store_i => be_store, -- bus error on store data access |
bus_exc_ack_o => bus_exc_ack -- bus exception error acknowledge |
bus_exc_ack_o => bus_exc_ack, -- bus exception error acknowledge |
bus_busy_i => bus_busy -- bus unit is busy |
); |
|
|
220,7 → 226,7
mem_i => rdata, -- memory read data |
alu_i => alu_res, -- ALU result |
csr_i => csr_rdata, -- CSR read data |
pc_i => pc, -- current pc |
pc_i => next_pc, -- next pc |
-- data output -- |
rs1_o => rs1, -- operand 1 |
rs2_o => rs2 -- operand 2 |
230,10 → 236,6
-- ALU ------------------------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
neorv32_cpu_alu_inst: neorv32_cpu_alu |
generic map ( |
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension? |
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M -- implement mul/div extension? |
) |
port map ( |
-- global control -- |
clk_i => clk_i, -- global clock, rising edge |
242,8 → 244,7
-- data input -- |
rs1_i => rs1, -- rf source 1 |
rs2_i => rs2, -- rf source 2 |
pc_i => pc, -- current PC |
pc2_i => pc_delayed, -- delayed PC |
pc2_i => curr_pc, -- delayed PC |
imm_i => imm, -- immediate |
csr_i => csr_rdata, -- csr read data |
-- data output -- |
296,8 → 297,7
-- ------------------------------------------------------------------------------------------- |
neorv32_cpu_bus_inst: neorv32_cpu_bus |
generic map ( |
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension? |
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout |
MEM_EXT_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout |
) |
port map ( |
-- global control -- |
306,7 → 306,7
ctrl_i => ctrl, -- main control bus |
-- data input -- |
wdata_i => rs2, -- write data |
pc_i => pc, -- current PC |
pc_i => fetch_pc, -- current PC for instruction fetch |
alu_i => alu_res, -- ALU result |
-- data output -- |
instr_o => instr, -- instruction |
320,6 → 320,7
be_load_o => be_load, -- bus error on load data access |
be_store_o => be_store, -- bus error on store data access |
bus_wait_o => bus_wait, -- wait for bus operation to finish |
bus_busy_o => bus_busy, -- bus unit is busy |
exc_ack_i => bus_exc_ack, -- exception controller ACK |
-- bus system -- |
bus_addr_o => bus_addr_o, -- bus access address |
/neorv32_cpu_alu.vhd
42,10 → 42,6
use neorv32.neorv32_package.all; |
|
entity neorv32_cpu_alu is |
generic ( |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_M : boolean := false -- implement mul/div extension? |
); |
port ( |
-- global control -- |
clk_i : in std_ulogic; -- global clock, rising edge |
54,7 → 50,6
-- data input -- |
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1 |
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2 |
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC |
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC |
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- csr read data |
75,7 → 70,7
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is |
|
-- operands -- |
signal opa, opb, opc, pc_inc : std_ulogic_vector(data_width_c-1 downto 0); |
signal opa, opb, opc : std_ulogic_vector(data_width_c-1 downto 0); |
|
-- results -- |
signal add_res : std_ulogic_vector(data_width_c-1 downto 0); |
109,22 → 104,28
|
-- Operand Mux ---------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
input_op_mux: process(ctrl_i, csr_i, pc2_i, pc_i, rs1_i, rs2_i, imm_i, pc_inc) |
input_op_mux: process(ctrl_i, csr_i, pc2_i, rs1_i, rs2_i, imm_i) |
begin |
-- opa (first ALU input operand) -- |
case ctrl_i(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) is |
when "00" => opa <= rs1_i; |
when "01" => opa <= pc2_i; |
when "10" => opa <= csr_i; |
when others => opa <= pc_i; |
end case; |
if (ctrl_i(ctrl_alu_opa_mux_msb_c) = '0') then |
if (ctrl_i(ctrl_alu_opa_mux_lsb_c) = '0') then |
opa <= rs1_i; |
else |
opa <= pc2_i; |
end if; |
else |
opa <= csr_i; |
end if; |
-- opb (second ALU input operand) -- |
case ctrl_i(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) is |
when "00" => opb <= rs2_i; |
when "01" => opb <= imm_i; |
when "10" => opb <= rs1_i; |
when others => opb <= pc_inc; |
end case; |
if (ctrl_i(ctrl_alu_opb_mux_msb_c) = '0') then |
if (ctrl_i(ctrl_alu_opb_mux_lsb_c) = '0') then |
opb <= rs2_i; |
else |
opb <= imm_i; |
end if; |
else |
opb <= rs1_i; |
end if; |
-- opc (second operand for comparison (and SUB)) -- |
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then |
opc <= imm_i; |
133,10 → 134,7
end if; |
end process input_op_mux; |
|
-- PC increment -- |
pc_inc <= x"00000002" when (CPU_EXTENSION_RISCV_C = true) else x"00000004"; |
|
|
-- Comparator Unit ------------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
-- less than (x < y) -- |
202,7 → 200,7
cp_rb_ff0 <= '0'; |
cp_rb_ff1 <= '0'; |
elsif rising_edge(clk_i) then |
if (CPU_EXTENSION_RISCV_M = true) then |
if (ctrl_i(ctrl_sys_m_ext_en_c) = '1') then |
cp_cmd_ff <= ctrl_i(ctrl_cp_use_c); |
cp_rb_ff0 <= '0'; |
cp_rb_ff1 <= cp_rb_ff0; |
/neorv32_cpu_bus.vhd
43,8 → 43,7
|
entity neorv32_cpu_bus is |
generic ( |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout |
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout |
); |
port ( |
-- global control -- |
67,6 → 66,7
be_load_o : out std_ulogic; -- bus error on load data access |
be_store_o : out std_ulogic; -- bus error on store data access |
bus_wait_o : out std_ulogic; -- wait for bus operation to finish |
bus_busy_o : out std_ulogic; -- bus unit is busy |
exc_ack_i : in std_ulogic; -- exception controller ACK |
-- bus system -- |
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address |
113,7 → 113,7
end process mem_adr_reg; |
|
-- address output -- |
bus_addr_o <= pc_i when (ctrl_i(ctrl_bus_if_c) = '1') else mar; -- is instruction fetch? |
bus_addr_o <= pc_i when ((bus_if_req or ctrl_i(ctrl_bus_if_c)) = '1') else mar; -- is instruction fetch? |
mar_o <= mar; |
|
-- write request output -- |
120,7 → 120,7
bus_we_o <= ctrl_i(ctrl_bus_wr_c) and (not misaligned_data); |
|
-- read request output (also used for instruction fetch) -- |
bus_re_o <= (ctrl_i(ctrl_bus_rd_c) and (not misaligned_data)) or (ctrl_i(ctrl_bus_if_c) and (not misaligned_instr)); |
bus_re_o <= (ctrl_i(ctrl_bus_rd_c) and (not misaligned_data)) or ((bus_if_req or ctrl_i(ctrl_bus_if_c)) and (not misaligned_instr)); |
|
|
-- Write Data ----------------------------------------------------------------------------- |
263,6 → 263,7
ma_store_o <= bus_wr_req and align_err; |
|
-- wait for bus -- |
bus_busy_o <= bus_busy; |
bus_wait_o <= bus_busy and (not bus_ack_i); -- FIXME: 'async' ack |
|
|
290,11 → 291,9
begin |
-- check instruction access -- |
misaligned_instr <= '0'; -- default |
if (CPU_EXTENSION_RISCV_C = true) then -- 16-bit instruction access only |
if (pc_i(0) /= '0') then |
misaligned_instr <= '1'; |
end if; |
else -- 32-bit instruction access only |
if (ctrl_i(ctrl_sys_c_ext_en_c) = '1') then -- 16-bit and 32-bit instruction accesses |
misaligned_instr <= '0'; |
else -- 32-bit instruction accesses only |
if (pc_i(1 downto 0) /= "00") then |
misaligned_instr <= '1'; |
end if; |
/neorv32_cpu_control.vhd
1,8 → 1,9
-- ################################################################################################# |
-- # << NEORV32 - CPU Control >> # |
-- # ********************************************************************************************* # |
-- # FSM to control CPU operations. This unit also includes the control and status registers (CSR) # |
-- # and the interrupt and exception controller. # |
-- # CPU operation is split into a fetch engine (responsible for fetching an decompressing instr- # |
-- # uctions), an execute engine (responsible for actually executing the instructions), an inter- # |
-- # rupt and exception handling controller and the RISC-V status and control registers (CSRs). # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
48,6 → 49,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
92,8 → 94,9
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result |
-- data output -- |
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC |
alu_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC for ALU |
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch |
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction) |
next_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction) |
-- csr data interface -- |
csr_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data |
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data |
108,90 → 111,151
be_instr_i : in std_ulogic; -- bus error on instruction access |
be_load_i : in std_ulogic; -- bus error on load data access |
be_store_i : in std_ulogic; -- bus error on store data access |
bus_exc_ack_o : out std_ulogic -- bus exception error acknowledge |
bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge |
bus_busy_i : in std_ulogic -- bus unit is busy |
); |
end neorv32_cpu_control; |
|
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is |
|
-- state machine -- |
type state_t is (IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3, IFETCH_4, IFETCH_5, IFETCH_6, EXECUTE, |
ALU_WAIT, STORE_0, LOAD_0, LOADSTORE_0, LOADSTORE_1, CSR_ACCESS, SLEEP); |
signal state, state_nxt : state_t; |
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); |
signal hw_control : std_ulogic_vector(data_width_c-1 downto 0); |
-- instruction fetch enginge -- |
type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3); |
type fetch_engine_t is record |
state : fetch_engine_state_t; |
state_nxt : fetch_engine_state_t; |
i_buf : std_ulogic_vector(33 downto 0); |
i_buf_nxt : std_ulogic_vector(33 downto 0); |
i_buf2 : std_ulogic_vector(33 downto 0); |
i_buf2_nxt : std_ulogic_vector(33 downto 0); |
ci_reg : std_ulogic_vector(17 downto 0); |
ci_reg_nxt : std_ulogic_vector(17 downto 0); |
i_buf_state : std_ulogic_vector(01 downto 0); |
i_buf_state_nxt : std_ulogic_vector(01 downto 0); |
pc_real : std_ulogic_vector(data_width_c-1 downto 0); |
pc_real_add : std_ulogic_vector(data_width_c-1 downto 0); |
pc_fetch : std_ulogic_vector(data_width_c-1 downto 0); |
pc_fetch_add : std_ulogic_vector(data_width_c-1 downto 0); |
ci_return : std_ulogic; |
ci_return_nxt : std_ulogic; |
reset : std_ulogic; |
bus_err_ack : std_ulogic; |
end record; |
signal fetch_engine : fetch_engine_t; |
|
-- pre-decoder -- |
signal ci_instr32 : std_ulogic_vector(31 downto 0); |
signal ci_valid : std_ulogic; |
signal ci_illegal : std_ulogic; |
|
-- instruction register -- |
signal i_reg, i_reg_nxt : std_ulogic_vector(31 downto 0); |
signal i_buf, i_buf_nxt : std_ulogic_vector(15 downto 0); |
signal ci_reg, ci_reg_nxt : std_ulogic_vector(15 downto 0); |
signal iavail, iavail_nxt : std_ulogic; |
signal is_ci, is_ci_nxt : std_ulogic; -- current instruction is COMPRESSED instruction flag |
-- instrucion prefetch buffer (IPB) -- |
type ipb_t is record |
wdata : std_ulogic_vector(34 downto 0); |
rdata : std_ulogic_vector(34 downto 0); |
waddr : std_ulogic_vector(31 downto 0); |
raddr : std_ulogic_vector(31 downto 0); |
status : std_ulogic; |
free : std_ulogic; |
avail : std_ulogic; |
we : std_ulogic; |
re : std_ulogic; |
clear : std_ulogic; |
end record; |
signal ipb : ipb_t; |
|
-- immediates -- |
signal imm_reg : std_ulogic_vector(data_width_c-1 downto 0); |
-- instruction execution engine -- |
type execute_engine_state_t is (IDLE, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, STORE, LOAD, LOADSTORE_0, LOADSTORE_1, CSR_ACCESS); |
type execute_engine_t is record |
state : execute_engine_state_t; |
state_nxt : execute_engine_state_t; |
state_prev : execute_engine_state_t; |
i_reg : std_ulogic_vector(31 downto 0); |
i_reg_nxt : std_ulogic_vector(31 downto 0); |
is_ci : std_ulogic; -- current instruction is de-compressed instruction |
is_ci_nxt : std_ulogic; |
is_jump : std_ulogic; -- current instruction is jump instruction |
is_jump_nxt : std_ulogic; |
branch_taken : std_ulogic; -- branch condition fullfilled |
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction |
pc_nxt : std_ulogic_vector(data_width_c-1 downto 0); |
next_pc : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed |
last_pc : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction |
end record; |
signal execute_engine : execute_engine_t; |
|
-- branch system -- |
signal is_branch : std_ulogic; |
signal is_branch_nxt : std_ulogic; |
signal branch_taken : std_ulogic; |
-- trap controller -- |
type trap_ctrl_t is record |
exc_buf : std_ulogic_vector(exception_width_c-1 downto 0); |
exc_fire : std_ulogic; -- set if there is a valid source in the exception buffer |
irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0); |
irq_fire : std_ulogic; -- set if there is a valid source in the interrupt buffer |
exc_ack : std_ulogic; -- acknowledge all exceptions |
irq_ack : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt |
irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0); |
cause : std_ulogic_vector(data_width_c-1 downto 0); -- trap ID (for "mcause") |
cause_nxt : std_ulogic_vector(data_width_c-1 downto 0); |
instr : std_ulogic_vector(31 downto 0); -- faulting instruction |
exc_src : std_ulogic_vector(exception_width_c-1 downto 0); |
-- |
env_start : std_ulogic; -- start trap handler env |
env_start_ack : std_ulogic; -- start of trap handler acknowledged |
env_end : std_ulogic; -- end trap handler env |
-- |
instr_be : std_ulogic; -- instruction fetch bus error |
instr_ma : std_ulogic; -- instruction fetch misaligned address |
instr_il : std_ulogic; -- illegal instruction |
env_call : std_ulogic; |
break_point : std_ulogic; |
end record; |
signal trap_ctrl : trap_ctrl_t; |
|
-- CPU control signals -- |
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0); |
|
-- program counter -- |
signal pc_reg : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC |
signal pc_backup_reg : std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC (for ALU operations) |
signal pc_backup2_reg : std_ulogic_vector(data_width_c-1 downto 0); -- delayed delayed PC (for exception handling) |
signal mepc : std_ulogic_vector(data_width_c-1 downto 0); -- exception PC |
-- fast bus access -- |
signal bus_fast_ir : std_ulogic; |
signal bus_fast_rd : std_ulogic; |
signal bus_fast_wr : std_ulogic; |
|
-- irq controller -- |
signal exc_buf : std_ulogic_vector(exception_width_c-1 downto 0); |
signal exc_ack : std_ulogic; |
signal exc_src : std_ulogic_vector(exception_width_c-1 downto 0); |
signal exc_fire : std_ulogic; |
signal irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0); |
signal irq_ack : std_ulogic_vector(interrupt_width_c-1 downto 0); |
signal irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0); |
signal irq_fire : std_ulogic; |
signal exc_cpu_start : std_ulogic; -- starting exception env |
signal exc_cpu_ack : std_ulogic; -- starting of exception env acknowledge |
signal exc_cpu_end : std_ulogic; -- exiting eception env |
signal exc_cause : std_ulogic_vector(data_width_c-1 downto 0); |
signal exc_cause_nxt : std_ulogic_vector(data_width_c-1 downto 0); |
-- RISC-V control and status registers (CSRs) -- |
type csr_t is record |
we : std_ulogic; -- write enable |
we_nxt : std_ulogic; |
re : std_ulogic; -- read enable |
re_nxt : std_ulogic; |
mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W) |
mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-) |
mip_msip : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W) |
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W) |
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W) |
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W) |
mepc : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W) |
mcause : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-) |
mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W) |
mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-) |
mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W) |
mtinst : std_ulogic_vector(data_width_c-1 downto 0); -- mtinst: machine trap instruction (transformed) (R/-) |
cycle : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-), plus carry bit |
instret : std_ulogic_vector(32 downto 0); -- instret (R/-), plus carry bit |
cycleh : std_ulogic_vector(31 downto 0); -- cycleh, mtimeh (R/-) |
instreth : std_ulogic_vector(31 downto 0); -- instreth (R/-) |
misa_c_en : std_ulogic; -- misa: C extension enable bit (R/W) |
misa_m_en : std_ulogic; -- misa: M extension enable bit (R/W) |
end record; |
signal csr : csr_t; |
|
-- RISC-V CSRs -- |
signal mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W) |
signal mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-) |
signal mip_msip : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W) |
signal mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W) |
signal mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W) |
signal mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W) |
signal mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W) |
signal mtval : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-) |
signal mscratch : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W) |
signal mtinst : std_ulogic_vector(data_width_c-1 downto 0); -- mtinst: machine trap instruction (transformed) (R/-) |
signal cycle_lo : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-) |
signal instret_lo : std_ulogic_vector(32 downto 0); -- instret (R/-) |
signal cycle_hi : std_ulogic_vector(15 downto 0); -- cycleh, mtimeh (R/-) - only 16-bit wide |
signal instret_hi : std_ulogic_vector(15 downto 0); -- instreth (R/-) - only 16-bit wide |
signal cycle_lo_msb : std_ulogic; |
signal instret_lo_msb : std_ulogic; |
signal cycle_msb : std_ulogic; |
signal instret_msb : std_ulogic; |
|
-- illegal instruction check .. |
-- illegal instruction check -- |
signal illegal_instruction : std_ulogic; |
signal illegal_register : std_ulogic; -- only for E-extension |
signal illegal_compressed : std_ulogic; -- only fir C-extension |
|
-- synchronous exceptions trigger -- |
signal illegal_instr_exc : std_ulogic; |
signal env_call : std_ulogic; |
signal break_point : std_ulogic; |
|
begin |
|
-- **************************************************************************************************************************** |
-- Instruction Fetch |
-- **************************************************************************************************************************** |
|
-- Compressed Instructions Recoding ------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
neorv32_cpu_decompressor_inst_true: |
199,9 → 263,8
neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor |
port map ( |
-- instruction input -- |
ci_instr16_i => ci_reg, -- compressed instruction input |
ci_instr16_i => fetch_engine.ci_reg(15 downto 0), -- compressed instruction input |
-- instruction output -- |
ci_valid_o => ci_valid, -- is a compressed instruction |
ci_illegal_o => ci_illegal, -- is an illegal compressed instruction |
ci_instr32_o => ci_instr32 -- 32-bit decompressed instruction |
); |
209,290 → 272,460
|
neorv32_cpu_decompressor_inst_false: |
if (CPU_EXTENSION_RISCV_C = false) generate |
ci_instr32 <= instr_i; |
ci_valid <= '0'; |
ci_instr32 <= (others => '0'); |
ci_illegal <= '0'; |
end generate; |
|
|
-- Fetch Engine FSM Sync ------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
-- for registers that require a specific reset state -- |
fetch_engine_fsm_sync_rst: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
fetch_engine.state <= IFETCH_RESET; |
elsif rising_edge(clk_i) then |
if (fetch_engine.reset = '1') then |
fetch_engine.state <= IFETCH_RESET; |
else |
fetch_engine.state <= fetch_engine.state_nxt; |
end if; |
end if; |
end process fetch_engine_fsm_sync_rst; |
|
|
-- for registers that DO NOT require a specific reset state -- |
fetch_engine_fsm_sync: process(clk_i) |
begin |
if rising_edge(clk_i) then |
if (fetch_engine.state = IFETCH_RESET) then |
fetch_engine.pc_fetch <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC |
fetch_engine.pc_real <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC |
else |
fetch_engine.pc_real <= std_ulogic_vector(unsigned(fetch_engine.pc_real(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_real_add(data_width_c-1 downto 1) & '0')); |
fetch_engine.pc_fetch <= std_ulogic_vector(unsigned(fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_fetch_add(data_width_c-1 downto 1) & '0')); |
end if; |
-- |
fetch_engine.i_buf <= fetch_engine.i_buf_nxt; |
fetch_engine.i_buf2 <= fetch_engine.i_buf2_nxt; |
fetch_engine.i_buf_state <= fetch_engine.i_buf_state_nxt; |
-- |
fetch_engine.ci_reg <= fetch_engine.ci_reg_nxt; |
fetch_engine.ci_return <= fetch_engine.ci_return_nxt; |
end if; |
end process fetch_engine_fsm_sync; |
|
|
-- Fetch Engine FSM Comb ------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
fetch_engine_fsm_comb: process(fetch_engine, execute_engine, csr, ipb, instr_i, bus_wait_i, bus_busy_i, ci_instr32, be_instr_i, ma_instr_i) |
begin |
-- arbiter defaults -- |
fetch_engine.state_nxt <= fetch_engine.state; |
fetch_engine.pc_fetch_add <= (others => '0'); |
fetch_engine.pc_real_add <= (others => '0'); |
bus_fast_ir <= '0'; |
fetch_engine.i_buf_nxt <= fetch_engine.i_buf; |
fetch_engine.i_buf2_nxt <= fetch_engine.i_buf2; |
fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state; |
fetch_engine.ci_reg_nxt <= fetch_engine.ci_reg; |
fetch_engine.ci_return_nxt <= fetch_engine.ci_return; |
fetch_engine.bus_err_ack <= '0'; |
|
-- instruction prefetch buffer interface -- |
ipb.we <= '0'; |
ipb.clear <= '0'; |
ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0); |
ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0'; |
|
-- state machine -- |
case fetch_engine.state is |
|
when IFETCH_RESET => -- reset engine, prefetch buffer, get PC |
-- ------------------------------------------------------------ |
fetch_engine.i_buf_state_nxt <= (others => '0'); |
fetch_engine.ci_return_nxt <= '0'; |
ipb.clear <= '1'; -- clear instruction prefetch buffer |
fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them |
fetch_engine.state_nxt <= IFETCH_0; |
|
when IFETCH_0 => -- output current PC to bus system, request 32-bit word |
-- ------------------------------------------------------------ |
if (bus_busy_i = '0') and (execute_engine.state /= LOAD) and (execute_engine.state /= STORE) and |
(execute_engine.state /= LOADSTORE_0) and (execute_engine.state /= LOADSTORE_1) then -- wait if execute engine is using bus unit |
bus_fast_ir <= '1'; -- fast instruction fetch request (output PC to bus.address) |
fetch_engine.state_nxt <= IFETCH_1; |
end if; |
|
when IFETCH_1 => -- store data from memory to buffer(s) |
-- ------------------------------------------------------------ |
fetch_engine.i_buf_nxt <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store data word and exception info |
if (bus_wait_i = '0') then -- wait for bus response |
fetch_engine.i_buf2_nxt <= fetch_engine.i_buf; |
fetch_engine.i_buf_state_nxt(1) <= fetch_engine.i_buf_state(0); |
fetch_engine.state_nxt <= IFETCH_2; |
end if; |
|
fetch_engine.i_buf_state_nxt(0) <= '1'; |
if (be_instr_i = '1') or (ma_instr_i = '1') then -- any fetch exception? |
fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them |
end if; |
|
when IFETCH_2 => -- construct instruction and issue |
-- ------------------------------------------------------------ |
if (fetch_engine.i_buf_state(1) = '1') then |
if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- 32-bit aligned |
fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00); |
ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0); |
|
if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- uncompressed |
if (ipb.free = '1') then -- free entry in buffer? |
ipb.we <= '1'; |
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(4, data_width_c)); |
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c)); |
fetch_engine.state_nxt <= IFETCH_0; |
end if; |
|
else -- compressed |
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c)); |
fetch_engine.ci_return_nxt <= '1'; -- come back here after issueing |
fetch_engine.state_nxt <= IFETCH_3; |
end if; |
|
else -- 16-bit aligned |
fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(31 downto 16); |
ipb.wdata <= fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16); |
|
if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed |
if (ipb.free = '1') then -- free entry in buffer? |
ipb.we <= '1'; |
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(4, data_width_c)); |
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c)); |
fetch_engine.state_nxt <= IFETCH_0; |
end if; |
|
else -- compressed |
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c)); |
fetch_engine.ci_return_nxt <= '0'; -- start next fetch after issueing |
fetch_engine.state_nxt <= IFETCH_3; |
end if; |
end if; |
else |
fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c)); |
fetch_engine.state_nxt <= IFETCH_0; |
end if; |
|
when IFETCH_3 => -- additional cycle for issueing decompressed instructions |
-- ------------------------------------------------------------ |
if (ipb.free = '1') then -- free entry in buffer? |
ipb.we <= '1'; |
ipb.wdata <= fetch_engine.ci_reg(17 downto 16) & '1' & ci_instr32; |
fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(2, data_width_c)); |
if (fetch_engine.ci_return = '0') then |
fetch_engine.state_nxt <= IFETCH_0; |
else |
fetch_engine.state_nxt <= IFETCH_2; |
end if; |
end if; |
|
when others => -- undefined |
-- ------------------------------------------------------------ |
fetch_engine.state_nxt <= IFETCH_RESET; |
|
end case; |
end process fetch_engine_fsm_comb; |
|
|
-- **************************************************************************************************************************** |
-- Instruction Prefetch Buffer |
-- **************************************************************************************************************************** |
|
|
-- Instruction Prefetch Buffer Stage ------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
instr_prefetch_buffer: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
ipb.status <= '0'; |
ipb.rdata <= (others => '0'); |
ipb.raddr <= (others => '0'); |
elsif rising_edge(clk_i) then |
if (ipb.clear = '1') then |
ipb.status <= '0'; |
elsif (ipb.we = '1') then |
ipb.status <= '1'; |
elsif (ipb.re = '1') then |
ipb.status <= '0'; |
end if; |
if (ipb.we = '1') then |
ipb.rdata <= ipb.wdata; |
ipb.raddr <= ipb.waddr; |
end if; |
end if; |
end process instr_prefetch_buffer; |
|
-- status -- |
ipb.free <= not ipb.status; |
ipb.avail <= ipb.status; |
|
|
-- **************************************************************************************************************************** |
-- Instruction Execution |
-- **************************************************************************************************************************** |
|
|
-- Immediate Generator -------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
imm_gen: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- default: I-immediate -- |
imm_reg(31 downto 11) <= (others => i_reg(31)); -- sign extension |
imm_reg(10 downto 05) <= i_reg(30 downto 25); |
imm_reg(04 downto 01) <= i_reg(24 downto 21); |
imm_reg(00) <= i_reg(20); |
case i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is |
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is |
when opcode_store_c => -- S-immediate |
imm_reg(31 downto 11) <= (others => i_reg(31)); -- sign extension |
imm_reg(10 downto 05) <= i_reg(30 downto 25); |
imm_reg(04 downto 01) <= i_reg(11 downto 08); |
imm_reg(00) <= i_reg(07); |
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension |
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25); |
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08); |
imm_o(00) <= execute_engine.i_reg(07); |
when opcode_branch_c => -- B-immediate |
imm_reg(31 downto 12) <= (others => i_reg(31)); -- sign extension |
imm_reg(11) <= i_reg(07); |
imm_reg(10 downto 05) <= i_reg(30 downto 25); |
imm_reg(04 downto 01) <= i_reg(11 downto 08); |
imm_reg(00) <= '0'; |
imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension |
imm_o(11) <= execute_engine.i_reg(07); |
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25); |
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08); |
imm_o(00) <= '0'; |
when opcode_lui_c | opcode_auipc_c => -- U-immediate |
imm_reg(31 downto 20) <= i_reg(31 downto 20); |
imm_reg(19 downto 12) <= i_reg(19 downto 12); |
imm_reg(11 downto 00) <= (others => '0'); |
imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20); |
imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12); |
imm_o(11 downto 00) <= (others => '0'); |
when opcode_jal_c => -- J-immediate |
imm_reg(31 downto 20) <= (others => i_reg(31)); -- sign extension |
imm_reg(19 downto 12) <= i_reg(19 downto 12); |
imm_reg(11) <= i_reg(20); |
imm_reg(10 downto 05) <= i_reg(30 downto 25); |
imm_reg(04 downto 01) <= i_reg(24 downto 21); |
imm_reg(00) <= '0'; |
imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension |
imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12); |
imm_o(11) <= execute_engine.i_reg(20); |
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25); |
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21); |
imm_o(00) <= '0'; |
when opcode_syscsr_c => -- CSR-immediate |
imm_reg(31 downto 05) <= (others => '0'); |
imm_reg(04 downto 00) <= i_reg(19 downto 15); |
imm_o(31 downto 05) <= (others => '0'); |
imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15); |
when others => -- I-immediate |
imm_reg(31 downto 11) <= (others => i_reg(31)); -- sign extension |
imm_reg(10 downto 05) <= i_reg(30 downto 25); |
imm_reg(04 downto 01) <= i_reg(24 downto 21); |
imm_reg(00) <= i_reg(20); |
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension |
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25); |
imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21); |
imm_o(00) <= execute_engine.i_reg(20); |
end case; |
end if; |
end process imm_gen; |
|
-- output -- |
imm_o <= imm_reg; |
|
|
-- Branch Condition Check ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
branch_check: process(i_reg, cmp_i) |
branch_check: process(execute_engine.i_reg, cmp_i) |
begin |
case i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is |
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is |
when funct3_beq_c => -- branch if equal |
branch_taken <= cmp_i(alu_cmp_equal_c); |
execute_engine.branch_taken <= cmp_i(alu_cmp_equal_c); |
when funct3_bne_c => -- branch if not equal |
branch_taken <= not cmp_i(alu_cmp_equal_c); |
execute_engine.branch_taken <= not cmp_i(alu_cmp_equal_c); |
when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned) |
branch_taken <= cmp_i(alu_cmp_less_c); |
execute_engine.branch_taken <= cmp_i(alu_cmp_less_c); |
when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned) |
branch_taken <= not cmp_i(alu_cmp_less_c); |
execute_engine.branch_taken <= not cmp_i(alu_cmp_less_c); |
when others => -- undefined |
branch_taken <= '0'; |
execute_engine.branch_taken <= '0'; |
end case; |
end process branch_check; |
|
|
-- Arbiter State Machine Sync ------------------------------------------------------------- |
-- Execute Engine FSM Sync ---------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
arbiter_sync_rst: process(rstn_i, clk_i) |
-- for registers that require a specific reset state -- |
execute_engine_fsm_sync_rst: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
-- these registers REQUIRE a specific reset state |
state <= IFETCH_0; |
if (BOOTLOADER_USE = true) then -- boot from bootloader ROM |
execute_engine.pc <= boot_base_c(data_width_c-1 downto 1) & '0'; |
execute_engine.last_pc <= boot_base_c(data_width_c-1 downto 1) & '0'; |
else -- boot from IMEM |
execute_engine.pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0'; |
execute_engine.last_pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0'; |
end if; |
execute_engine.state <= IDLE; |
execute_engine.state_prev <= IDLE; |
elsif rising_edge(clk_i) then |
state <= state_nxt; |
execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0'; |
if (execute_engine.state = EXECUTE) then |
execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; |
end if; |
execute_engine.state <= execute_engine.state_nxt; |
execute_engine.state_prev <= execute_engine.state; |
end if; |
end process arbiter_sync_rst; |
end process execute_engine_fsm_sync_rst; |
|
arbiter_sync: process(clk_i) |
|
-- for registers that DO NOT require a specific reset state -- |
execute_engine_fsm_sync: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- these registers do not need a specific reset state |
ctrl <= ctrl_nxt; |
i_reg <= i_reg_nxt; |
i_buf <= i_buf_nxt; |
ci_reg <= ci_reg_nxt; |
iavail <= iavail_nxt; |
is_ci <= is_ci_nxt; |
is_branch <= is_branch_nxt; |
execute_engine.i_reg <= execute_engine.i_reg_nxt; |
execute_engine.is_ci <= execute_engine.is_ci_nxt; |
execute_engine.is_jump <= execute_engine.is_jump_nxt; |
-- control signals -- |
ctrl <= ctrl_nxt; |
end if; |
end process arbiter_sync; |
end process execute_engine_fsm_sync; |
|
-- control bus output -- |
ctrl_outpu: process(ctrl, i_reg) |
|
-- PC output -- |
execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 2) when (execute_engine.is_ci = '1') else |
std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 4); |
fetch_pc_o <= fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0'; |
curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; |
next_pc_o <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; |
|
|
-- CPU Control Bus Output ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
ctrl_output: process(ctrl, execute_engine, csr, bus_fast_ir, bus_fast_rd, bus_fast_wr) |
begin |
ctrl_o <= ctrl; |
-- direct output of register addresses -- |
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= i_reg(instr_rd_msb_c downto instr_rd_lsb_c); |
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c); |
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c); |
end process ctrl_outpu; |
ctrl_o(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c); |
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c); |
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c); |
-- bus access requests -- |
ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir; |
ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) or bus_fast_rd; |
ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) or bus_fast_wr; |
-- cpu extension control -- |
ctrl_o(ctrl_sys_c_ext_en_c) <= csr.misa_c_en; -- C extension enabled |
ctrl_o(ctrl_sys_m_ext_en_c) <= csr.misa_m_en; -- M extension enabled |
end process ctrl_output; |
|
|
-- Arbiter State Machine Comb ----------------------------------------------- |
-- ----------------------------------------------------------------------------- |
arbiter_comb: process(state, ctrl, i_reg, alu_wait_i, bus_wait_i, exc_cpu_start, ma_load_i, be_load_i, ma_store_i, be_store_i, |
ci_reg, i_buf, instr_i, is_ci, iavail, pc_backup_reg, ci_valid, ci_instr32) |
-- Execute Engine FSM Comb ---------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl, |
alu_add_i, alu_wait_i, bus_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i) |
variable alu_immediate_v : std_ulogic; |
variable alu_operation_v : std_ulogic_vector(2 downto 0); |
variable rd_is_r0_v : std_ulogic; |
variable rs1_is_r0_v : std_ulogic; |
begin |
-- arbiter defaults -- |
state_nxt <= state; |
is_branch_nxt <= '0'; |
exc_cpu_ack <= '0'; |
exc_cpu_end <= '0'; |
execute_engine.state_nxt <= execute_engine.state; |
execute_engine.i_reg_nxt <= execute_engine.i_reg; |
execute_engine.is_jump_nxt <= '0'; |
execute_engine.is_ci_nxt <= execute_engine.is_ci; |
execute_engine.pc_nxt <= execute_engine.pc(data_width_c-1 downto 1) & '0'; |
|
i_reg_nxt <= i_reg; |
i_buf_nxt <= i_buf; |
ci_reg_nxt <= ci_reg; |
iavail_nxt <= iavail; |
is_ci_nxt <= is_ci; |
-- instruction dispatch -- |
fetch_engine.reset <= '0'; |
ipb.re <= '0'; |
|
-- trap environment control -- |
trap_ctrl.env_start_ack <= '0'; |
trap_ctrl.env_end <= '0'; |
|
-- bus access (fast) -- |
bus_fast_rd <= '0'; |
bus_fast_wr <= '0'; |
|
-- exception trigger -- |
env_call <= '0'; |
break_point <= '0'; |
trap_ctrl.instr_be <= '0'; |
trap_ctrl.instr_ma <= '0'; |
trap_ctrl.env_call <= '0'; |
trap_ctrl.break_point <= '0'; |
|
-- CSR access -- |
csr.we_nxt <= '0'; |
csr.re_nxt <= '0'; |
|
-- control defaults -- |
ctrl_nxt <= (others => '0'); -- all off at first |
ctrl_nxt(ctrl_bus_unsigned_c) <= i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU) |
if (i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops |
ctrl_nxt(ctrl_alu_unsigned_c) <= i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation (SLTIU, SLTU) |
ctrl_nxt(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU) |
if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops |
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation (SLTIU, SLTU) |
else -- branches |
ctrl_nxt(ctrl_alu_unsigned_c) <= i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU) |
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU) |
end if; |
ctrl_nxt(ctrl_alu_shift_dir_c) <= i_reg(instr_funct3_msb_c); -- shift direction |
ctrl_nxt(ctrl_alu_shift_ar_c) <= i_reg(30); -- arithmetic shift |
ctrl_nxt(ctrl_bus_size_lsb_c) <= i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word) |
ctrl_nxt(ctrl_bus_size_msb_c) <= i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?) |
ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction |
ctrl_nxt(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- 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_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = add |
ctrl_nxt(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation |
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 implemented yet |
|
-- is immediate operation? -- |
alu_immediate_v := '0'; |
if (i_reg(instr_opcode_msb_c-1) = '0') then |
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then |
alu_immediate_v := '1'; |
end if; |
|
-- hardware branch operation control -- |
hw_control(31 downto 24) <= ('0' & funct3_bne_c) & ('1' & funct3_bne_c); |
hw_control(23 downto 16) <= funct3_xor_c & funct3_slt_c & "00"; |
hw_control(15 downto 08) <= funct3_beq_c & funct3_bne_c & "11"; |
hw_control(07 downto 00) <= funct3_beq_c & funct3_bne_c & "00"; |
|
-- alu operation -- |
case i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is |
-- alu operation re-coding -- |
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is |
when funct3_subadd_c => -- SUB / ADD(I) |
if (alu_immediate_v = '0') and (i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 = SUB |
if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 = SUB |
alu_operation_v := alu_cmd_sub_c; |
else |
alu_operation_v := alu_cmd_add_c; |
end if; |
when funct3_sll_c => alu_operation_v := alu_cmd_shift_c; -- SLL(I) |
when funct3_slt_c => alu_operation_v := alu_cmd_slt_c; -- SLT(I) |
when funct3_sltu_c => alu_operation_v := alu_cmd_slt_c; -- SLTU(I) |
when funct3_xor_c => alu_operation_v := alu_cmd_xor_c; -- XOR(I) |
when funct3_slt_c => alu_operation_v := alu_cmd_slt_c; -- SLT(I) |
when funct3_sltu_c => alu_operation_v := alu_cmd_slt_c; -- SLTU(I) |
when funct3_xor_c => alu_operation_v := alu_cmd_xor_c; -- XOR(I) |
when funct3_sr_c => alu_operation_v := alu_cmd_shift_c; -- SRL(I) / SRA(I) |
when funct3_or_c => alu_operation_v := alu_cmd_or_c; -- OR(I) |
when funct3_and_c => alu_operation_v := alu_cmd_and_c; -- AND(I) |
when funct3_or_c => alu_operation_v := alu_cmd_or_c; -- OR(I) |
when funct3_and_c => alu_operation_v := alu_cmd_and_c; -- AND(I) |
when others => alu_operation_v := (others => '0'); -- undefined |
end case; |
|
-- is rd = r0? -- |
rd_is_r0_v := '0'; |
if (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") then |
rd_is_r0_v := '1'; |
end if; |
|
-- is rs1 = r0? -- |
rs1_is_r0_v := '0'; |
if (i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then |
if (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then |
rs1_is_r0_v := '1'; |
end if; |
|
-- state machine -- |
case execute_engine.state is |
|
-- state machine: instruction fetch and execution -- |
case state is |
|
when IFETCH_0 => -- output current PC to bus system |
when IDLE => -- Delay cycle (used to wait for side effects to kick in) |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_if_c) <= '1'; -- instruction fetch request (output PC to bus address) |
iavail_nxt <= '0'; -- absolutely no instruction available yet |
state_nxt <= IFETCH_1; |
execute_engine.state_nxt <= DISPATCH; |
|
when IFETCH_1 => -- memory latency, update PC |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "11"; -- opa = current PC |
ctrl_nxt(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) <= "11"; -- opb = PC_increment |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD |
ctrl_nxt(ctrl_csr_pc_we_c) <= '1'; -- update PC |
state_nxt <= IFETCH_2; |
when DISPATCH => -- Get new command from instruction prefetch buffer (IPB) |
-- ------------------------------------------------------------ |
if (ipb.avail = '1') then -- instruction available? |
ipb.re <= '1'; |
trap_ctrl.instr_ma <= ipb.rdata(33); |
trap_ctrl.instr_be <= ipb.rdata(34); |
if (trap_ctrl.env_start = '1') or (ipb.rdata(33) = '1') or (ipb.rdata(34) = '1') then -- exception/interrupt? |
execute_engine.state_nxt <= TRAP; |
else |
execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed |
execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0); |
execute_engine.pc_nxt <= ipb.raddr(data_width_c-1 downto 1) & '0'; -- the PC according to the current instruction |
execute_engine.state_nxt <= EXECUTE; |
end if; |
end if; |
|
when IFETCH_2 => -- update instruction buffers |
when TRAP => -- Start trap environment (also used as sleep state) |
-- ------------------------------------------------------------ |
if (exc_cpu_start = '1') then -- exception detected! |
exc_cpu_ack <= '1'; |
state_nxt <= IFETCH_0; -- start new instruction fetch |
else -- normal operation |
-- instruction register update -- |
if (CPU_EXTENSION_RISCV_C = true) then -- compressed AND uncompressed instructions possible |
if (pc_backup_reg(1) = '0') then |
i_buf_nxt <= instr_i(31 downto 16); |
ci_reg_nxt <= instr_i(15 downto 00); |
else |
i_buf_nxt <= instr_i(15 downto 00); |
ci_reg_nxt <= instr_i(31 downto 16); |
end if; |
else -- only uncompressed instructions |
i_reg_nxt <= instr_i(31 downto 0); |
end if; |
-- next state -- |
if (bus_wait_i = '0') then -- wait for bus response |
if (CPU_EXTENSION_RISCV_C = true) then -- compressed AND uncompressed instructions possible |
state_nxt <= IFETCH_3; |
else -- only uncompressed instructions |
state_nxt <= EXECUTE; |
end if; |
end if; |
if (trap_ctrl.env_start = '1') then |
trap_ctrl.env_start_ack <= '1'; |
execute_engine.pc_nxt <= csr.mtvec(data_width_c-1 downto 1) & '0'; |
fetch_engine.reset <= '1'; |
execute_engine.state_nxt <= IDLE; |
end if; |
|
|
when IFETCH_3 => -- check for exception, start instruction execution (only available for C-extension) |
when EXECUTE => -- Decode and execute instruction |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "11"; -- opa = current PC |
ctrl_nxt(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) <= "11"; -- opb = PC_increment |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD |
-- |
if (exc_cpu_start = '1') then -- exception detected! |
exc_cpu_ack <= '1'; |
state_nxt <= IFETCH_0; -- start new instruction fetch |
else -- normal operation |
if (ci_valid = '1') then -- directly execute decoded compressed instruction |
i_reg_nxt <= ci_instr32; |
state_nxt <= EXECUTE; |
elsif (pc_backup_reg(1) = '0') or (iavail = '1') then -- 32-bit aligned uncompressed instruction |
i_reg_nxt <= i_buf & ci_reg; |
state_nxt <= EXECUTE; |
ctrl_nxt(ctrl_csr_pc_we_c) <= not pc_backup_reg(1); -- update PC again when on 32b-aligned address |
else |
i_reg_nxt <= i_buf & ci_reg; |
state_nxt <= IFETCH_4; |
end if; |
end if; |
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is |
|
when IFETCH_4 => -- get missing instruction parts: output current PC to bus system (only available for C-extension) |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_if_c) <= '1'; -- instruction fetch request (output PC to bus address) |
state_nxt <= IFETCH_5; |
|
when IFETCH_5 => -- memory latency, update PC (only available for C-extension) |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "11"; -- opa = current PC |
ctrl_nxt(ctrl_alu_opb_mux_msb_c downto ctrl_alu_opb_mux_lsb_c) <= "11"; -- opb = PC_increment |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD |
ctrl_nxt(ctrl_csr_pc_we_c) <= '1'; -- update PC |
state_nxt <= IFETCH_6; |
|
when IFETCH_6 => -- update missing instruction buffer parts (only available for C-extension) |
-- ------------------------------------------------------------ |
if (bus_wait_i = '0') then -- wait for bus response |
i_buf_nxt <= instr_i(15 downto 00); |
iavail_nxt <= '1'; |
state_nxt <= IFETCH_3; |
end if; |
|
|
when EXECUTE => -- decode and execute instruction |
-- ------------------------------------------------------------ |
is_ci_nxt <= ci_valid; -- flag to indicate this is a compressed instruction beeing executed (ci_valid is zero if not C-ext is not implemented) |
case i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is |
|
when opcode_alu_c | opcode_alui_c => -- ALU operation |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA |
500,31 → 733,31
ctrl_nxt(ctrl_alu_opc_mux_c) <= not alu_immediate_v; |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result |
if (CPU_EXTENSION_RISCV_M = true) and (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and |
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV? |
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and |
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV? |
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP |
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP |
state_nxt <= ALU_WAIT; |
execute_engine.state_nxt <= ALU_WAIT; |
elsif (alu_operation_v = alu_cmd_shift_c) then -- multi-cycle shift operation? |
state_nxt <= ALU_WAIT; |
execute_engine.state_nxt <= ALU_WAIT; |
else |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
state_nxt <= IFETCH_0; |
execute_engine.state_nxt <= DISPATCH; |
end if; |
|
when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC) |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0 |
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC |
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) 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 |
end if; |
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB |
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
state_nxt <= IFETCH_0; |
execute_engine.state_nxt <= DISPATCH; |
|
when opcode_load_c | opcode_store_c => -- load/store |
-- ------------------------------------------------------------ |
531,12 → 764,14
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA |
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation |
ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR |
ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores) |
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD |
state_nxt <= LOAD_0; |
else -- STORE |
state_nxt <= STORE_0; |
ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR |
ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores) |
if (fetch_engine.state /= IFETCH_0) then |
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD |
execute_engine.state_nxt <= LOAD; |
else -- STORE |
execute_engine.state_nxt <= STORE; |
end if; |
end if; |
|
when opcode_branch_c => -- branch instruction |
543,14 → 778,13
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA |
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB |
ctrl_nxt(ctrl_alu_opc_mux_c) <= '1'; -- use RS2 as ALU.OPC |
is_branch_nxt <= '1'; |
state_nxt <= IFETCH_0; |
ctrl_nxt(ctrl_alu_opc_mux_c) <= '1'; -- use RS2 as ALU.OPC |
execute_engine.state_nxt <= BRANCH; |
|
when opcode_jal_c | opcode_jalr_c => -- jump and link (with register) |
-- ------------------------------------------------------------ |
-- compute target address -- |
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) then -- JAL |
if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) 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 |
559,70 → 793,49
-- save return address -- |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = current PC |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
-- update PC -- |
ctrl_nxt(ctrl_csr_pc_we_c) <= '1'; -- update PC |
state_nxt <= IFETCH_0; |
-- |
execute_engine.is_jump_nxt <= '1'; -- this is a jump operation |
execute_engine.state_nxt <= BRANCH; |
|
when opcode_syscsr_c => -- system/csr access |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_csr_re_c) <= '1'; -- ALWAYS READ CSR!!! (OLD: valid CSR read if rd is not r0) |
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system |
case i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is |
when x"000" => env_call <= '1'; state_nxt <= IFETCH_0; -- ECALL |
when x"001" => break_point <= '1'; state_nxt <= IFETCH_0; -- EBREAK |
when x"302" => exc_cpu_end <= '1'; state_nxt <= IFETCH_0; -- MRET |
when x"105" => state_nxt <= SLEEP; -- WFI |
when others => NULL; -- undefined |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then |
csr.re_nxt <= not rd_is_r0_v; -- only read CSR if not writing to zero_reg |
else |
csr.re_nxt <= '1'; -- always read CSR |
end if; |
-- |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system |
case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is |
when x"000" => -- ECALL |
trap_ctrl.env_call <= '1'; |
execute_engine.state_nxt <= IDLE; |
when x"001" => -- EBREAK |
trap_ctrl.break_point <= '1'; |
execute_engine.state_nxt <= IDLE; |
when x"302" => -- MRET |
trap_ctrl.env_end <= '1'; |
execute_engine.pc_nxt <= csr.mepc(data_width_c-1 downto 1) & '0'; |
fetch_engine.reset <= '1'; |
execute_engine.state_nxt <= IDLE; |
when x"105" => -- WFI |
execute_engine.state_nxt <= TRAP; |
when others => -- undefined |
NULL; |
end case; |
elsif (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access |
state_nxt <= CSR_ACCESS; |
execute_engine.state_nxt <= CSR_ACCESS; |
else |
state_nxt <= IFETCH_0; |
execute_engine.state_nxt <= DISPATCH; |
end if; |
|
when others => -- undefined |
-- ------------------------------------------------------------ |
state_nxt <= IFETCH_0; |
execute_engine.state_nxt <= DISPATCH; |
|
end case; |
|
when ALU_WAIT => -- wait for multi-cycle ALU operation to finish |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (write back all the time) |
if (alu_wait_i = '0') then |
state_nxt <= IFETCH_0; |
end if; |
|
when LOAD_0 => -- trigger memory read request |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request |
state_nxt <= LOADSTORE_0; |
|
when STORE_0 => -- trigger memory write request |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request |
state_nxt <= LOADSTORE_0; |
|
when LOADSTORE_0 => -- memory latency |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD) |
state_nxt <= LOADSTORE_1; |
|
when LOADSTORE_1 => -- wait for bus transaction to finish |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD) |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD) |
if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception |
state_nxt <= IFETCH_0; |
elsif (bus_wait_i = '0') then -- wait here for bus to finish transaction |
if (i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD? |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
end if; |
state_nxt <= IFETCH_0; |
end if; |
|
when CSR_ACCESS => -- write CSR data to RF, write ALU.res to CSR |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '0'; -- default |
629,34 → 842,39
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_csr_we_c) <= not rs1_is_r0_v; -- valid CSR write if rs1 is not r0 (or not imm5 = 0) |
case i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is |
when funct3_csrrw_c => -- CSSRW |
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is |
when funct3_csrrw_c => -- CSRRW |
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1 |
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- OPB = rs2 |
ctrl_nxt(ctrl_rf_clear_rs2_c) <= '1'; -- rs2 = 0 |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD |
when funct3_csrrs_c => -- CSSRS |
csr.we_nxt <= '1'; -- always write CSR |
when funct3_csrrs_c => -- CSRRS |
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr |
ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = crs1 |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR |
when funct3_csrrc_c => -- CSSRC |
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg |
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 |
when funct3_csrrwi_c => -- CSSRWI |
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg |
when funct3_csrrwi_c => -- CSRRWI |
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1 |
ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- rs1 = 0 |
ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD |
when funct3_csrrsi_c => -- CSSRSI |
csr.we_nxt <= '1'; -- always write CSR |
when funct3_csrrsi_c => -- CSRRSI |
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_or_c; -- actual ALU operation = OR |
when funct3_csrrci_c => -- CSSRCI |
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed) |
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 |
csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed) |
when others => -- undefined |
NULL; |
end case; |
663,28 → 881,66
-- RF write back -- |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output register |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
state_nxt <= IFETCH_0; |
execute_engine.state_nxt <= DISPATCH; |
|
when SLEEP => -- stall and wait for interrupt (WFI) |
when ALU_WAIT => -- wait for multi-cycle ALU operation to finish |
-- ------------------------------------------------------------ |
if (exc_cpu_start = '1') then -- exception detected! |
exc_cpu_ack <= '1'; |
state_nxt <= IFETCH_0; -- start new instruction fetch |
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (write back all the time) |
if (alu_wait_i = '0') then |
execute_engine.state_nxt <= DISPATCH; |
end if; |
|
when BRANCH => -- update PC for taken branches and jumps |
-- ------------------------------------------------------------ |
if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then |
execute_engine.pc_nxt <= alu_add_i(data_width_c-1 downto 1) & '0'; |
fetch_engine.reset <= '1'; |
end if; |
execute_engine.state_nxt <= IDLE; |
|
when LOAD => -- trigger memory read request |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_rd_c) <= '1';--bus_fast_rd <= '1'; -- fast read request |
execute_engine.state_nxt <= LOADSTORE_0; |
|
when STORE => -- trigger memory write request |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_wr_c) <= '1';--bus_fast_wr <= '1'; -- fast write request |
execute_engine.state_nxt <= LOADSTORE_0; |
|
when LOADSTORE_0 => -- memory latency |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD) |
execute_engine.state_nxt <= LOADSTORE_1; |
|
when LOADSTORE_1 => -- wait for bus transaction to finish |
-- ------------------------------------------------------------ |
ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD) |
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD) |
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 <= IDLE; |
elsif (bus_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? |
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back |
end if; |
execute_engine.state_nxt <= DISPATCH; |
end if; |
|
when others => -- undefined |
-- ------------------------------------------------------------ |
state_nxt <= IFETCH_0; |
execute_engine.state_nxt <= IDLE; |
|
end case; |
end process arbiter_comb; |
end process execute_engine_fsm_comb; |
|
|
-- Illegal Instruction Check -------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
illegal_instruction_check: process(i_reg, state, ctrl_nxt, ci_valid, ci_illegal) |
illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal) |
begin |
if (state = EXECUTE) then |
if (execute_engine.state = EXECUTE) then |
-- defaults -- |
illegal_instruction <= '0'; |
illegal_register <= '0'; |
691,14 → 947,14
illegal_compressed <= '0'; |
|
-- check if using reg >= 16 for E-CPUs -- |
if (CPU_EXTENSION_RISCV_E = true) then |
illegal_register <= ctrl_nxt(ctrl_rf_rd_adr4_c) or ctrl_nxt(ctrl_rf_rs2_adr4_c) or ctrl_nxt(ctrl_rf_rs1_adr4_c); |
else |
illegal_register <= '0'; |
end if; |
--if (CPU_EXTENSION_RISCV_E = true) then |
-- illegal_register <= ctrl_nxt(ctrl_rf_rd_adr4_c) or ctrl_nxt(ctrl_rf_rs2_adr4_c) or ctrl_nxt(ctrl_rf_rs1_adr4_c); |
--else |
-- illegal_register <= '0'; |
--end if; |
|
-- check instructions -- |
case i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is |
case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is |
|
-- OPCODE check sufficient: LUI, UIPC, JAL -- |
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => |
705,11 → 961,11
illegal_instruction <= '0'; |
|
when opcode_alui_c => -- check ALUI funct7 |
if ((i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and |
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left |
((i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and |
((i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and |
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right |
if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and |
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left |
((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and |
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right |
illegal_instruction <= '1'; |
else |
illegal_instruction <= '0'; |
716,11 → 972,11
end if; |
|
when opcode_load_c => -- check LOAD funct3 |
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
727,9 → 983,9
end if; |
|
when opcode_store_c => -- check STORE funct3 |
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
736,12 → 992,12
end if; |
|
when opcode_branch_c => -- check BRANCH funct3 |
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
748,7 → 1004,7
end if; |
|
when opcode_jalr_c => -- check JALR funct3 |
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
755,14 → 1011,14
end if; |
|
when opcode_alu_c => -- check ALU funct3 & funct7 |
if (i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV |
if (CPU_EXTENSION_RISCV_M = false) then |
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV |
if (CPU_EXTENSION_RISCV_M = false) or (csr.misa_m_en = '0') then -- not implemented or disabled |
illegal_instruction <= '1'; |
end if; |
elsif ((i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check |
((i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and |
(i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select |
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and |
(execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select |
illegal_instruction <= '1'; |
else |
illegal_instruction <= '0'; |
770,46 → 1026,45
|
when opcode_syscsr_c => -- check system instructions -- |
-- CSR access -- |
if (i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or |
(i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then |
-- valid CSR? -- |
if (i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"34a") or -- mtinst |
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"34a") or -- mtinst |
-- |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false)) or -- cycle |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false)) or -- time |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false)) or -- instret |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false)) or -- cycleh |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CPU_EXTENSION_RISCV_E = false)) or -- timeh |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false)) or -- instreth |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycle |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- time |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instret |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycleh |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- timeh |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instreth |
-- |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false)) or -- mcycle |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false)) or -- minstret |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false)) or -- mcycleh |
((i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b82") and (CPU_EXTENSION_RISCV_E = false)) or -- minstreth |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycle |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstret |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycleh |
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstreth |
-- |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") or -- mhartid |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fff") or -- mhwctrl |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") or -- mhartid |
-- |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc0") or -- mfeatures |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc1") or -- mclock |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc4") or -- mispacebase |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc5") or -- mispacesize |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc6") or -- mdspacebase |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc7") then -- mdspacesize |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc0") or -- mfeatures |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc1") or -- mclock |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc4") or -- mispacebase |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc5") or -- mispacesize |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc6") or -- mdspacebase |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc7") then -- mdspacesize |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
816,12 → 1071,12
end if; |
|
-- ecall, ebreak, mret, wfi -- |
elsif (i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and |
(i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then |
if (i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000000") or -- ECALL |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000001") or -- EBREAK |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "001100000010") or -- MRET |
(i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000100000101") then -- WFI |
elsif (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") and |
(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then |
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000000") or -- ECALL |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000000000001") or -- EBREAK |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "001100000010") or -- MRET |
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = "000100000101") then -- WFI |
illegal_instruction <= '0'; |
else |
illegal_instruction <= '1'; |
831,10 → 1086,10
end if; |
|
when others => -- compressed instruction or undefined instruction |
if (i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode |
if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode |
illegal_instruction <= '1'; |
else -- compressed instruction |
illegal_compressed <= ci_valid and ci_illegal; |
else -- compressed instruction: illegal or disabled / not implemented |
illegal_compressed <= ci_illegal or (not csr.misa_c_en); |
end if; |
|
end case; |
846,142 → 1101,106
end process illegal_instruction_check; |
|
-- any illegal condition? -- |
illegal_instr_exc <= illegal_instruction or illegal_register or illegal_compressed; |
trap_ctrl.instr_il <= illegal_instruction or illegal_register or illegal_compressed; |
|
|
-- Program Counter ------------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
program_counter: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
if (BOOTLOADER_USE = true) then -- boot from bootloader ROM |
pc_reg <= boot_base_c; |
pc_backup_reg <= boot_base_c; |
pc_backup2_reg <= boot_base_c; |
else -- boot from IMEM |
pc_reg <= MEM_ISPACE_BASE; |
pc_backup_reg <= MEM_ISPACE_BASE; |
pc_backup2_reg <= MEM_ISPACE_BASE; |
end if; |
elsif rising_edge(clk_i) then |
-- actual PC -- |
if (exc_cpu_ack = '1') then -- exception start? |
pc_reg <= mtvec; |
elsif (exc_cpu_end = '1') then -- return from exception |
pc_reg <= mepc; |
elsif (ctrl(ctrl_csr_pc_we_c) = '1') or ((is_branch and branch_taken) = '1') then -- manual update or taken branch |
pc_reg <= alu_add_i; |
end if; |
-- delayed PC -- |
if (state = IFETCH_1) then |
pc_backup_reg <= pc_reg; -- PC for ALU address computations |
end if; |
if (state = EXECUTE) then |
pc_backup2_reg <= pc_backup_reg; -- PC backup for exceptions |
end if; |
end if; |
end process program_counter; |
-- **************************************************************************************************************************** |
-- Exception and Interrupt Control |
-- **************************************************************************************************************************** |
|
-- output -- |
pc_o <= pc_reg; |
alu_pc_o <= pc_backup_reg; |
|
|
-- Exception Controller ------------------------------------------------------------------- |
-- Trap Controller ------------------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
exception_controller: process(rstn_i, clk_i) |
trap_controller: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
exc_buf <= (others => '0'); |
irq_buf <= (others => '0'); |
exc_ack <= '0'; |
irq_ack <= (others => '0'); |
exc_src <= (others => '0'); |
exc_cpu_start <= '0'; |
exc_cause <= (others => '0'); |
mtinst <= (others => '0'); |
trap_ctrl.exc_buf <= (others => '0'); |
trap_ctrl.irq_buf <= (others => '0'); |
trap_ctrl.exc_ack <= '0'; |
trap_ctrl.irq_ack <= (others => '0'); |
trap_ctrl.cause <= (others => '0'); |
trap_ctrl.instr <= (others => '0'); |
trap_ctrl.exc_src <= (others => '0'); |
trap_ctrl.env_start <= '0'; |
elsif rising_edge(clk_i) then |
if (CPU_EXTENSION_RISCV_Zicsr = true) then |
-- exception buffer: misaligned load/store/instruction address |
exc_buf(exception_lalign_c) <= (exc_buf(exception_lalign_c) or ma_load_i) and (not exc_ack); |
exc_buf(exception_salign_c) <= (exc_buf(exception_salign_c) or ma_store_i) and (not exc_ack); |
exc_buf(exception_ialign_c) <= (exc_buf(exception_ialign_c) or ma_instr_i) and (not exc_ack); |
trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i) and (not trap_ctrl.exc_ack); |
trap_ctrl.exc_buf(exception_salign_c) <= (trap_ctrl.exc_buf(exception_salign_c) or ma_store_i) and (not trap_ctrl.exc_ack); |
trap_ctrl.exc_buf(exception_ialign_c) <= (trap_ctrl.exc_buf(exception_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.exc_ack); |
-- exception buffer: load/store/instruction bus access error |
exc_buf(exception_laccess_c) <= (exc_buf(exception_laccess_c) or be_load_i) and (not exc_ack); |
exc_buf(exception_saccess_c) <= (exc_buf(exception_saccess_c) or be_store_i) and (not exc_ack); |
exc_buf(exception_iaccess_c) <= (exc_buf(exception_iaccess_c) or be_instr_i) and (not exc_ack); |
trap_ctrl.exc_buf(exception_laccess_c) <= (trap_ctrl.exc_buf(exception_laccess_c) or be_load_i) and (not trap_ctrl.exc_ack); |
trap_ctrl.exc_buf(exception_saccess_c) <= (trap_ctrl.exc_buf(exception_saccess_c) or be_store_i) and (not trap_ctrl.exc_ack); |
trap_ctrl.exc_buf(exception_iaccess_c) <= (trap_ctrl.exc_buf(exception_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.exc_ack); |
-- exception buffer: illegal instruction / env call / break point |
exc_buf(exception_iillegal_c) <= (exc_buf(exception_iillegal_c) or illegal_instr_exc) and (not exc_ack); |
exc_buf(exception_m_envcall_c) <= (exc_buf(exception_m_envcall_c) or env_call) and (not exc_ack); |
exc_buf(exception_break_c) <= (exc_buf(exception_break_c) or break_point) and (not exc_ack); |
trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or trap_ctrl.env_call) and (not trap_ctrl.exc_ack); |
trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_ack); |
trap_ctrl.exc_buf(exception_iillegal_c) <= (trap_ctrl.exc_buf(exception_iillegal_c) or trap_ctrl.instr_il) and (not trap_ctrl.exc_ack); |
-- interrupt buffer: machine software/external/timer interrupt |
irq_buf(interrupt_msw_irq_c) <= mie_msie and (irq_buf(interrupt_msw_irq_c) or mip_msip) and (not irq_ack(interrupt_msw_irq_c)); |
irq_buf(interrupt_mext_irq_c) <= mie_meie and (irq_buf(interrupt_mext_irq_c) or clic_irq_i) and (not irq_ack(interrupt_mext_irq_c)); |
irq_buf(interrupt_mtime_irq_c) <= mie_mtie and (irq_buf(interrupt_mtime_irq_c) or mtime_irq_i) and (not irq_ack(interrupt_mtime_irq_c)); |
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and (trap_ctrl.irq_buf(interrupt_msw_irq_c) or csr.mip_msip) and (not trap_ctrl.irq_ack(interrupt_msw_irq_c)); |
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c) or clic_irq_i) and (not trap_ctrl.irq_ack(interrupt_mext_irq_c)); |
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i) and (not trap_ctrl.irq_ack(interrupt_mtime_irq_c)); |
|
-- exception control -- |
if (exc_cpu_start = '0') then -- |
-- exception/interrupt triggered, waiting for IRQ in EXECUTE (make sure at least 1 instr. is executed even for a continous IRQ) |
if (exc_fire = '1') or ((irq_fire = '1') and ((state = EXECUTE) or (state = SLEEP))) then |
exc_cause <= exc_cause_nxt; -- capture source for program |
mtinst <= i_reg; -- MTINST NOT FOULLY IMPLEMENTED YET! FIXME |
mtinst(1) <= not is_ci; -- bit is set for uncompressed instruction |
exc_src <= exc_buf; -- capture source for hardware |
exc_ack <= '1'; -- clear execption |
irq_ack <= irq_ack_nxt; -- capture and clear with interrupt ACK mask |
exc_cpu_start <= '1'; |
-- trap control -- |
if (trap_ctrl.env_start = '0') then -- no started trap handler |
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and |
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- exception/IRQ detected! |
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program |
trap_ctrl.instr <= execute_engine.i_reg; -- FIXME mtinst transformation not fully implemented yet! |
trap_ctrl.instr(1) <= not execute_engine.is_ci; -- bit is set for uncompressed instruction |
trap_ctrl.exc_src <= trap_ctrl.exc_buf; -- capture exception source for hardware |
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 we want to start the trap handler |
end if; |
else -- waiting for exception handler to get started |
if (exc_cpu_ack = '1') then -- handler started? |
exc_ack <= '0'; |
irq_ack <= (others => '0'); |
exc_cpu_start <= '0'; |
else -- trap waiting to get started |
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine |
trap_ctrl.exc_ack <= '0'; |
trap_ctrl.irq_ack <= (others => '0'); |
trap_ctrl.env_start <= '0'; |
end if; |
end if; |
else -- (CPU_EXTENSION_RISCV_Zicsr = false) |
exc_buf <= (others => '0'); |
irq_buf <= (others => '0'); |
exc_ack <= '0'; |
irq_ack <= (others => '0'); |
exc_src <= (others => '0'); |
exc_cpu_start <= '0'; |
exc_cause <= (others => '0'); |
mtinst <= (others => '0'); |
end if; |
end if; |
end process exception_controller; |
end process trap_controller; |
|
-- any exception/interrupt? -- |
exc_fire <= or_all_f(exc_buf); -- classic exceptions (faults/traps) cannot be masked |
irq_fire <= or_all_f(irq_buf) and mstatus_mie; -- classic interrupts can be enabled/disabled |
trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked |
trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled |
|
-- exception acknowledge for bus unit -- |
bus_exc_ack_o <= exc_cpu_ack; |
bus_exc_ack_o <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack; |
|
-- exception priority encoder -- |
exc_priority: process(exc_buf, irq_buf) |
-- exception/interrupt/status ID visible for program -- |
csr.mcause <= trap_ctrl.cause; |
csr.mtinst <= trap_ctrl.instr; |
|
|
-- Trap Priority Detector ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
trap_priority: process(trap_ctrl) |
begin |
-- defaults -- |
exc_cause_nxt <= (others => '0'); |
irq_ack_nxt <= (others => '0'); |
trap_ctrl.cause_nxt <= (others => '0'); |
trap_ctrl.irq_ack_nxt <= (others => '0'); |
|
-- interrupt: 1.11 machine external interrupt -- |
if (irq_buf(interrupt_mext_irq_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '1'; |
exc_cause_nxt(3 downto 0) <= "1011"; |
irq_ack_nxt(interrupt_mext_irq_c) <= '1'; |
if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '1'; |
trap_ctrl.cause_nxt(3 downto 0) <= "1011"; |
trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1'; |
|
-- interrupt: 1.7 machine timer interrupt -- |
elsif (irq_buf(interrupt_mtime_irq_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '1'; |
exc_cause_nxt(3 downto 0) <= "0111"; |
irq_ack_nxt(interrupt_mtime_irq_c) <= '1'; |
elsif (trap_ctrl.irq_buf(interrupt_mtime_irq_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '1'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0111"; |
trap_ctrl.irq_ack_nxt(interrupt_mtime_irq_c) <= '1'; |
|
-- interrupt: 1.3 machine SW interrupt -- |
elsif (irq_buf(interrupt_msw_irq_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '1'; |
exc_cause_nxt(3 downto 0) <= "0011"; |
irq_ack_nxt(interrupt_msw_irq_c) <= '1'; |
elsif (trap_ctrl.irq_buf(interrupt_msw_irq_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '1'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0011"; |
trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1'; |
|
|
-- the following traps are caused by synchronous exceptions |
988,150 → 1207,161
-- here we do not need an acknowledge mask since only one exception can trigger at the same time |
|
-- trap/fault: 0.0 instruction address misaligned -- |
elsif (exc_buf(exception_ialign_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0000"; |
elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0000"; |
|
-- trap/fault: 0.1 instruction access fault -- |
elsif (exc_buf(exception_iaccess_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0001"; |
elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0001"; |
|
-- trap/fault: 0.2 illegal instruction -- |
elsif (exc_buf(exception_iillegal_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0010"; |
elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0010"; |
|
|
-- trap/fault: 0.11 environment call from M-mode -- |
elsif (exc_buf(exception_m_envcall_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "1011"; |
elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "1011"; |
|
-- trap/fault: 0.3 breakpoint -- |
elsif (exc_buf(exception_break_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0011"; |
elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0011"; |
|
|
-- trap/fault: 0.6 store address misaligned - |
elsif (exc_buf(exception_salign_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0110"; |
elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0110"; |
|
-- trap/fault: 0.4 load address misaligned -- |
elsif (exc_buf(exception_lalign_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0100"; |
elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0100"; |
|
-- trap/fault: 0.7 store access fault -- |
elsif (exc_buf(exception_saccess_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0111"; |
elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0111"; |
|
-- trap/fault: 0.5 load access fault -- |
elsif (exc_buf(exception_laccess_c) = '1') then |
exc_cause_nxt(exc_cause_nxt'left) <= '0'; |
exc_cause_nxt(3 downto 0) <= "0101"; |
elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then |
trap_ctrl.cause_nxt(data_width_c-1) <= '0'; |
trap_ctrl.cause_nxt(3 downto 0) <= "0101"; |
|
-- undefined / not implemented -- |
else |
exc_cause_nxt <= (others => '0'); |
irq_ack_nxt <= (others => '0'); |
trap_ctrl.cause_nxt <= (others => '0'); |
trap_ctrl.irq_ack_nxt <= (others => '0'); |
end if; |
end process exc_priority; |
end process trap_priority; |
|
|
-- **************************************************************************************************************************** |
-- Control and Status Registers (CSRs) |
-- **************************************************************************************************************************** |
|
-- CSR CPU Access ------------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
csr_cpu_acc: process(clk_i) |
begin |
if rising_edge(clk_i) then |
csr.we <= csr.we_nxt; |
csr.re <= csr.re_nxt; |
end if; |
end process csr_cpu_acc; |
|
|
-- Control and Status Registers Write Access ---------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
csr_write_access: process(rstn_i, clk_i) |
begin |
if (rstn_i = '0') then |
mstatus_mie <= '0'; |
mstatus_mpie <= '0'; |
mie_msie <= '0'; |
mie_meie <= '0'; |
mie_mtie <= '0'; |
mtvec <= (others => '0'); |
mtval <= (others => '0'); |
mepc <= (others => '0'); |
mip_msip <= '0'; |
csr.mstatus_mie <= '0'; |
csr.mstatus_mpie <= '0'; |
csr.mie_msie <= '0'; |
csr.mie_meie <= '0'; |
csr.mie_mtie <= '0'; |
csr.mtvec <= (others => '0'); |
csr.mtval <= (others => '0'); |
csr.mepc <= (others => '0'); |
csr.mip_msip <= '0'; |
csr.misa_c_en <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension |
csr.misa_m_en <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension |
elsif rising_edge(clk_i) then |
if (CPU_EXTENSION_RISCV_Zicsr = true) then |
mip_msip <= '0'; |
csr.mip_msip <= '0'; |
|
-- register that can be modified by user -- |
if (ctrl(ctrl_csr_we_c) = '1') then -- manual update |
if (csr.we = '1') then -- manual update |
|
-- machine trap setup -- |
if (i_reg(31 downto 24) = x"30") then |
if (i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register |
mstatus_mie <= csr_wdata_i(03); |
mstatus_mpie <= csr_wdata_i(07); |
if (execute_engine.i_reg(31 downto 24) = x"30") then |
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register |
csr.mstatus_mie <= csr_wdata_i(03); |
csr.mstatus_mpie <= csr_wdata_i(07); |
end if; |
if (i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register |
mie_msie <= csr_wdata_i(03); -- SW IRQ enable |
mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable |
mie_meie <= csr_wdata_i(11); -- EXT IRQ enable |
if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions |
csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable |
csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable |
end if; |
if (i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions) |
mtvec <= csr_wdata_i; |
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register |
csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable |
csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable |
csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable |
end if; |
if (execute_engine.i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions) |
csr.mtvec <= csr_wdata_i; |
end if; |
end if; |
|
-- machine trap handling -- |
if (i_reg(31 downto 24) = x"34") then |
if (i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register |
mscratch <= csr_wdata_i; |
if (execute_engine.i_reg(31 downto 24) = x"34") then |
if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register |
csr.mscratch <= csr_wdata_i; |
end if; |
if (i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter |
mepc <= csr_wdata_i; |
if (execute_engine.i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter |
csr.mepc <= csr_wdata_i; |
end if; |
if (i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending |
mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger |
if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending |
csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger |
end if; |
end if; |
|
else -- automatic update by hardware |
-- machine exception PC & exception value register -- |
if (exc_cpu_ack = '1') then -- exception start? |
if (exc_cause(exc_cause_nxt'left) = '1') then -- for INTERRUPTs: mepc = address of next (unclompeted) instruction |
mepc <= pc_reg; |
mtval <= (others => '0'); -- not specified |
else -- for EXCEPTIONs: mepc = address of next (unclompeted) instruction |
mepc <= pc_backup2_reg; |
if ((exc_src(exception_iaccess_c) or exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction |
mtval <= pc_backup_reg; |
elsif (exc_src(exception_iillegal_c) = '1') then -- illegal instruction |
mtval <= i_reg; |
elsif ((exc_src(exception_lalign_c) or exc_src(exception_salign_c) or |
exc_src(exception_laccess_c) or exc_src(exception_saccess_c)) = '1') then -- load/store misaligned / access error |
mtval <= mar_i; |
if (trap_ctrl.env_start_ack = '1') then -- trap handler started? |
if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts) |
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction |
csr.mtval <= (others => '0'); |
else -- for EXCEPTIONs |
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction |
if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction |
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; |
elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction |
csr.mtval <= execute_engine.i_reg; |
else -- everything else |
--elsif ((trap_ctrl.exc_src(exception_lalign_c) or trap_ctrl.exc_src(exception_salign_c) or |
-- trap_ctrl.exc_src(exception_laccess_c) or trap_ctrl.exc_src(exception_saccess_c)) = '1') then -- load/store misaligned / access error |
csr.mtval <= mar_i; |
end if; |
end if; |
end if; |
|
-- context switch in mstatus -- |
if (exc_cpu_ack = '1') then -- actually entering trap |
mstatus_mie <= '0'; |
if (mstatus_mpie = '0') then -- FIXME: prevent loosing the prev MIE state after several traps |
mstatus_mpie <= mstatus_mie; |
if (trap_ctrl.env_start_ack = '1') then -- actually entering trap |
csr.mstatus_mie <= '0'; |
if (csr.mstatus_mpie = '0') then -- FIXME: prevent loosing the prev MIE state after several traps |
csr.mstatus_mpie <= csr.mstatus_mie; |
end if; |
elsif (exc_cpu_end = '1') then -- return from exception |
mstatus_mie <= mstatus_mpie; |
elsif (trap_ctrl.env_end = '1') then -- return from exception |
csr.mstatus_mie <= csr.mstatus_mpie; |
end if; |
end if; |
|
else -- CPU_EXTENSION_RISCV_Zicsr = false |
mstatus_mie <= '0'; |
mstatus_mpie <= '0'; |
mie_msie <= '0'; |
mie_meie <= '0'; |
mie_mtie <= '0'; |
mtvec <= (others => '0'); |
mtval <= (others => '0'); |
mepc <= (others => '0'); |
mip_msip <= '0'; |
end if; |
end if; |
end process csr_write_access; |
1144,67 → 1374,66
if rising_edge(clk_i) then |
csr_rdata_o <= (others => '0'); -- default |
if (CPU_EXTENSION_RISCV_Zicsr = true) then -- implement CSR access at all? |
if (ctrl(ctrl_csr_re_c) = '1') then |
case i_reg(31 downto 20) is |
if (csr.re = '1') then |
case execute_engine.i_reg(31 downto 20) is |
-- machine trap setup -- |
when x"300" => -- R/W: mstatus - machine status register |
csr_rdata_o(03) <= mstatus_mie; -- MIE |
csr_rdata_o(07) <= mstatus_mpie; -- MPIE |
csr_rdata_o(03) <= csr.mstatus_mie; -- MIE |
csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE |
csr_rdata_o(11) <= '1'; -- MPP low |
csr_rdata_o(12) <= '1'; -- MPP high |
when x"301" => -- R/-: misa - ISA and extensions |
csr_rdata_o(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension |
when x"301" => -- R/W: misa - ISA and extensions |
csr_rdata_o(02) <= csr.misa_c_en; -- C CPU extension |
csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension |
csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E) |
csr_rdata_o(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension |
csr_rdata_o(12) <= csr.misa_m_en; -- M CPU extension |
csr_rdata_o(23) <= '1'; -- X CPU extension: non-standard extensions |
csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Z CPU extension |
csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo) |
csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi) |
when x"304" => -- R/W: mie - machine interrupt-enable register |
csr_rdata_o(03) <= mie_msie; -- software IRQ enable |
csr_rdata_o(07) <= mie_mtie; -- timer IRQ enable |
csr_rdata_o(11) <= mie_meie; -- external IRQ enable |
csr_rdata_o(03) <= csr.mie_msie; -- software IRQ enable |
csr_rdata_o(07) <= csr.mie_mtie; -- timer IRQ enable |
csr_rdata_o(11) <= csr.mie_meie; -- external IRQ enable |
when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions) |
csr_rdata_o <= mtvec; |
csr_rdata_o <= csr.mtvec; |
-- machine trap handling -- |
when x"340" => -- R/W: mscratch - machine scratch register |
csr_rdata_o <= mscratch; |
csr_rdata_o <= csr.mscratch; |
when x"341" => -- R/W: mepc - machine exception program counter |
csr_rdata_o <= mepc; |
csr_rdata_o <= csr.mepc; |
when x"342" => -- R/-: mcause - machine trap cause |
csr_rdata_o <= exc_cause; |
csr_rdata_o <= csr.mcause; |
when x"343" => -- R/-: mtval - machine bad address or instruction |
csr_rdata_o <= mtval; |
csr_rdata_o <= csr.mtval; |
when x"344" => -- R/W: mip - machine interrupt pending |
csr_rdata_o(03) <= irq_buf(interrupt_msw_irq_c); |
csr_rdata_o(07) <= irq_buf(interrupt_mtime_irq_c); |
csr_rdata_o(11) <= irq_buf(interrupt_mext_irq_c); |
csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c); |
csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c); |
csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c); |
when x"34a" => -- R/-: mtinst - machine trap instruction (transformed) |
csr_rdata_o <= mtinst; |
csr_rdata_o <= csr.mtinst; |
-- counter and timers -- |
when x"c00" | x"c01" | x"b00" => -- R/-: cycle/time/mcycle: Cycle counter LOW / Timer LOW |
csr_rdata_o <= cycle_lo(31 downto 0); |
csr_rdata_o <= csr.cycle(31 downto 0); |
when x"c02" | x"b02" => -- R/-: instret/minstret: Instructions-retired counter LOW |
csr_rdata_o <= instret_lo(31 downto 0); |
csr_rdata_o <= csr.instret(31 downto 0); |
when x"c80" | x"c81" | x"b80" => -- R/-: cycleh/timeh/mcycleh: Cycle counter HIGH / Timer HIGH |
csr_rdata_o(15 downto 0) <= cycle_hi; -- counter is only 16-bit wide! |
csr_rdata_o <= csr.cycleh; |
when x"c82" | x"b82" => -- R/-: instreth/minstreth: Instructions-retired counter HIGH |
csr_rdata_o(15 downto 0) <= instret_hi; -- counter is only 16-bit wide! |
csr_rdata_o <= csr.instreth; |
-- machine information registers -- |
when x"f13" => -- R/-: mimpid - implementation ID / version |
csr_rdata_o <= hw_version_c; |
when x"f14" => -- R/-: mhartid - hardware thread ID |
csr_rdata_o <= HART_ID; |
when x"fff" => -- R/-: mhwctrl - hardware controller |
csr_rdata_o <= hw_control; |
-- CUSTOM read-only machine CSRs -- |
when x"fc0" => -- R/-: mfeatures - implemented processor devices/features |
csr_rdata_o(00) <= bool_to_ulogic_f(BOOTLOADER_USE); -- implement processor-internal bootloader? |
csr_rdata_o(01) <= bool_to_ulogic_f(MEM_EXT_USE); -- implement external memory bus interface? |
csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory |
csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM |
csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory |
csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory? |
csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM? |
csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory? |
csr_rdata_o(05) <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- implement RISC-V (performance) counter? |
-- |
csr_rdata_o(16) <= bool_to_ulogic_f(IO_GPIO_USE); -- implement general purpose input/output port unit (GPIO)? |
csr_rdata_o(17) <= bool_to_ulogic_f(IO_MTIME_USE); -- implement machine system timer (MTIME)? |
1236,41 → 1465,34
end process csr_read_access; |
|
|
-- Optional RISC-V CSRs: Counters --------------------------------------------------------- |
-- RISC-V Counter CSRs -------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
csr_counters: process(rstn_i, clk_i) |
begin |
if rising_edge(clk_i) then |
if (rstn_i = '0') then |
cycle_lo <= (others => '0'); |
instret_lo <= (others => '0'); |
cycle_hi <= (others => '0'); |
instret_hi <= (others => '0'); |
cycle_lo_msb <= '0'; |
instret_lo_msb <= '0'; |
elsif (CPU_EXTENSION_RISCV_E = false) then |
if (rstn_i = '0') then |
csr.cycle <= (others => '0'); |
csr.instret <= (others => '0'); |
csr.cycleh <= (others => '0'); |
csr.instreth <= (others => '0'); |
cycle_msb <= '0'; |
instret_msb <= '0'; |
elsif rising_edge(clk_i) then |
if (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true) then |
-- low word overflow buffers -- |
cycle_lo_msb <= cycle_lo(cycle_lo'left); |
instret_lo_msb <= instret_lo(instret_lo'left); |
cycle_msb <= csr.cycle(csr.cycle'left); |
instret_msb <= csr.instret(csr.instret'left); |
-- low word counters -- |
cycle_lo <= std_ulogic_vector(unsigned(cycle_lo) + 1); |
if (state = EXECUTE) then |
instret_lo <= std_ulogic_vector(unsigned(instret_lo) + 1); |
csr.cycle <= std_ulogic_vector(unsigned(csr.cycle) + 1); |
if (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then |
csr.instret <= std_ulogic_vector(unsigned(csr.instret) + 1); |
end if; |
-- high word counters -- |
if ((cycle_lo_msb xor cycle_lo(cycle_lo'left)) = '1') then |
cycle_hi <= std_ulogic_vector(unsigned(cycle_hi) + 1); |
if ((cycle_msb xor csr.cycle(csr.cycle'left)) = '1') then |
csr.cycleh <= std_ulogic_vector(unsigned(csr.cycleh) + 1); |
end if; |
if ((instret_lo_msb xor instret_lo(instret_lo'left)) = '1') then |
instret_hi <= std_ulogic_vector(unsigned(instret_hi) + 1); |
if ((instret_msb xor csr.instret(csr.instret'left)) = '1') then |
csr.instreth <= std_ulogic_vector(unsigned(csr.instreth) + 1); |
end if; |
else -- counters are not available in embedded mode |
cycle_lo <= (others => '0'); |
instret_lo <= (others => '0'); |
cycle_hi <= (others => '0'); |
instret_hi <= (others => '0'); |
cycle_lo_msb <= '0'; |
instret_lo_msb <= '0'; |
end if; |
end if; |
end process csr_counters; |
/neorv32_cpu_cp_muldiv.vhd
2,8 → 2,8
-- # << NEORV32 - CPU Co-Processor: MULDIV unit >> # |
-- # ********************************************************************************************* # |
-- # Multiplier and Divider unit. Implements the RISC-V RV32-M CPU extension. # |
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+8 cycles latency # |
-- # Divider core (unsigned) uses serial algorithm. -> 32+8 cycles latency # |
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+4 cycles latency # |
-- # Divider core (unsigned) uses serial algorithm. -> 32+6 cycles latency # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
60,6 → 60,9
|
architecture neorv32_cpu_cp_muldiv_rtl of neorv32_cpu_cp_muldiv is |
|
-- constants -- |
constant all_zero_c : std_ulogic_vector(data_width_c-1 downto 0) := (others => '0'); |
|
-- controller -- |
type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED); |
signal state : state_t; |
70,6 → 73,7
signal opx, opy : std_ulogic_vector(data_width_c-1 downto 0); -- input operands |
signal opx_is_signed : std_ulogic; |
signal opy_is_signed : std_ulogic; |
signal opy_is_zero : std_ulogic; |
signal div_res_corr : std_ulogic; |
|
-- divider core -- |
101,6 → 105,7
start <= '0'; |
valid_o <= '0'; |
div_res_corr <= '0'; |
opy_is_zero <= '0'; |
elsif rising_edge(clk_i) then |
-- defaults -- |
start <= '0'; |
118,11 → 123,19
|
when DECODE => |
cnt <= "11111"; |
if (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) then -- result sign compensation for div? |
if (cp_op = cp_op_div_c) then -- result sign compensation for div? |
div_res_corr <= opx(opx'left) xor opy(opy'left); |
elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem? |
div_res_corr <= opx(opx'left); |
else |
div_res_corr <= '0'; |
end if; |
-- if (cp_op = cp_op_div_c) and (opy = all_zero_c) then -- *divide* by 0? |
if (opy = all_zero_c) then -- *divide* by 0? |
opy_is_zero <= '1'; |
else |
opy_is_zero <= '0'; |
end if; |
if (operation = '1') then -- division |
state <= INIT_OPX; |
else -- multiplication |
175,7 → 188,7
begin |
if rising_edge(clk_i) then |
if (start = '1') then -- start new multiplication |
mul_product(63 downto 32) <= (others => (opy(opy'left) and opy_is_signed)); -- sign extension |
mul_product(63 downto 32) <= (others => '0'); |
mul_product(31 downto 00) <= opy; |
elsif ((state = PROCESSING) or (state = FINALIZE)) and (operation = '0') then |
mul_product(63 downto 31) <= mul_do_add(32 downto 0); |
189,9 → 202,9
begin |
if (mul_product(0) = '1') then |
if (mul_sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opy'left) and opx_is_signed) & opx)); |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opx'left) and opx_is_signed) & opx)); |
else |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opy'left) and opx_is_signed) & opx)); |
mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opx'left) and opx_is_signed) & opx)); |
end if; |
else |
mul_do_add <= mul_p_sext & mul_product(63 downto 32); |
232,7 → 245,7
div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in)); |
|
-- result sign correction -- |
div_res <= div_sign_comp when (div_res_corr = '1') else div_sign_comp_in; |
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in; |
|
|
-- Data Output ---------------------------------------------------------------------------- |
240,6 → 253,7
operation_result: process(clk_i) |
begin |
if rising_edge(clk_i) then |
res_o <= (others => '0'); -- default |
case cp_op is |
when cp_op_mul_c => |
res_o <= mul_product(31 downto 00); |
250,7 → 264,11
when cp_op_divu_c => |
res_o <= quotient; |
when cp_op_rem_c => |
res_o <= div_res; |
if (opy_is_zero = '0') then |
res_o <= div_res; |
else |
res_o <= opx; |
end if; |
when cp_op_remu_c => |
res_o <= remainder; |
when others => -- undefined |
/neorv32_cpu_decompressor.vhd
44,7 → 44,6
-- instruction input -- |
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input |
-- instruction output -- |
ci_valid_o : out std_ulogic; -- is a compressed instruction |
ci_illegal_o : out std_ulogic; -- is an illegal compressed instruction |
ci_instr32_o : out std_ulogic_vector(31 downto 0) -- 32-bit decompressed instruction |
); |
147,7 → 146,7
ci_instr32_o(24) <= ci_instr16_i(11); |
ci_instr32_o(25) <= ci_instr16_i(12); |
ci_instr32_o(26) <= ci_instr16_i(5); |
ci_instr32_o(31 downto 26) <= (others => '0'); |
ci_instr32_o(31 downto 27) <= (others => '0'); |
ci_instr32_o(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_lw_c; |
ci_instr32_o(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "01" & ci_instr16_i(ci_rs1_3_msb_c downto ci_rs1_3_lsb_c); -- x8 - x15 |
ci_instr32_o(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & ci_instr16_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c); -- x8 - x15 |
432,8 → 431,5
end case; |
end process decompressor; |
|
-- is compressed instruction at all? -- |
ci_valid_o <= '0' when (ci_instr16_i(ci_opcode_msb_c downto ci_opcode_lsb_c) = "11") else '1'; |
|
|
end neorv32_cpu_decompressor_rtl; |
/neorv32_devnull.vhd
3,6 → 3,7
-- # ********************************************************************************************* # |
-- # In simulation: This unit will output the lowest 8 bit of the written data as ASCII chars # |
-- # to the simulator console and to a text file ("neorv32.devnull.out"). # |
-- # The complete data 32-bit data word is dumped to "neorv32.devnull.data.out". # |
-- # In real hardware: This unit implements a "/dev/null" device. # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
61,7 → 62,8
architecture neorv32_devnull_rtl of neorv32_devnull is |
|
-- configuration -- |
constant sim_output_en_c : boolean := true; -- output lowest byte as char to simulator when enabled |
constant sim_text_output_en_c : boolean := true; -- output lowest byte as char to simulator and file when enabled |
constant sim_data_output_en_c : boolean := true; -- dump 32-word to file when enabled |
|
-- IO space: module base address -- |
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit |
80,26 → 82,36
-- Read/Write Access ---------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
rw_access: process(clk_i) |
file file_devnull_out : text open write_mode is "neorv32.devnull.out"; |
file file_devnull_text_out : text open write_mode is "neorv32.devnull.out"; |
file file_devnull_data_out : text open write_mode is "neorv32.devnull.data.out"; |
variable i : integer; |
variable la, lb : line; -- we need to variables here since "writeline" seems to flush the source variable |
variable la, lb, lc : line; -- we need several variables here since "writeline" seems to flush the source variable |
begin |
if rising_edge(clk_i) then |
ack_o <= acc_en and (wren_i or rden_i); |
if ((acc_en and wren_i and ben_i(0)) = '1') and (sim_output_en_c = true) then |
-- print lowest byte as ASCII to console -- |
i := to_integer(unsigned(data_i(7 downto 0))); |
if (i >= 128) then -- out of range? |
i := 0; |
if (acc_en = '1') and (wren_i = '1') then |
if (sim_text_output_en_c = true) and (ben_i(0) = '1') then |
-- print lowest byte as ASCII to console -- |
i := to_integer(unsigned(data_i(7 downto 0))); |
if (i >= 128) then -- out of range? |
i := 0; |
end if; |
if (i /= 10) and (i /= 13) then -- skip line breaks - they are issued via "writeline" |
write(la, character'val(i)); |
write(lb, character'val(i)); |
end if; |
if (i = 10) then -- line break: write to screen and file |
writeline(output, la); |
writeline(file_devnull_text_out, lb); |
end if; |
end if; |
if (i /= 10) and (i /= 13) then -- skip line breaks - they are issued via "writeline" |
write(la, character'val(i)); |
write(lb, character'val(i)); |
if (sim_data_output_en_c = true) then |
-- dump raw data |
for x in 7 downto 0 loop |
write(lc, to_hexchar_f(data_i(3+x*4 downto 0+x*4))); -- write in hex form |
end loop; -- x |
writeline(file_devnull_data_out, lc); |
end if; |
if (i = 10) then -- line break: write to screen and file |
writeline(output, la); |
writeline(file_devnull_out, lb); |
end if; |
end if; |
end if; |
end process rw_access; |
/neorv32_mtime.vhd
108,6 → 108,7
else |
-- mtime low -- |
mtime_lo <= std_ulogic_vector(unsigned(mtime_lo) + 1); |
mtime_lo_msb_ff <= mtime_lo(mtime_lo'left); |
-- mtime high -- |
if ((mtime_lo_msb_ff xor mtime_lo(mtime_lo'left)) = '1') then -- mtime_lo carry? |
mtime_hi <= std_ulogic_vector(unsigned(mtime_hi) + 1); |
/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- data width - FIXED! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"00000206"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01000000"; -- no touchy! |
|
-- Internal Functions --------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
53,6 → 53,7
function and_all_f( a : std_ulogic_vector) return std_ulogic; |
function xor_all_f( a : std_ulogic_vector) return std_ulogic; |
function xnor_all_f(a : std_ulogic_vector) return std_ulogic; |
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character; |
|
-- Processor-internal Address Space Layout ------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
160,9 → 161,9
constant ctrl_alu_cmd1_c : natural := 21; -- ALU command bit 1 |
constant ctrl_alu_cmd2_c : natural := 22; -- ALU command bit 2 |
constant ctrl_alu_opa_mux_lsb_c : natural := 23; -- operand A select lsb (00=rs1, 01=PC) |
constant ctrl_alu_opa_mux_msb_c : natural := 24; -- operand A select msb (10=CSR, 11=CSR) |
constant ctrl_alu_opb_mux_lsb_c : natural := 25; -- operand B select lsb (00=rs2, 01=PC) |
constant ctrl_alu_opb_mux_msb_c : natural := 26; -- operand B select msb (10=rs1, 11=PC_increment(2/4)) |
constant ctrl_alu_opa_mux_msb_c : natural := 24; -- operand A select msb (10=CSR, 11=?) |
constant ctrl_alu_opb_mux_lsb_c : natural := 25; -- operand B select lsb (00=rs2, 01=IMM) |
constant ctrl_alu_opb_mux_msb_c : natural := 26; -- operand B select msb (10=rs1, 11=?) |
constant ctrl_alu_opc_mux_c : natural := 27; -- operand C select (0=IMM, 1=rs2) |
constant ctrl_alu_unsigned_c : natural := 28; -- is unsigned ALU operation |
constant ctrl_alu_shift_dir_c : natural := 29; -- shift direction (0=left, 1=right) |
177,24 → 178,23
constant ctrl_bus_mdo_we_c : natural := 37; -- memory data out register write enable |
constant ctrl_bus_mdi_we_c : natural := 38; -- memory data in register write enable |
constant ctrl_bus_unsigned_c : natural := 39; -- is unsigned load |
-- csr/system -- |
constant ctrl_csr_pc_we_c : natural := 40; -- PC write enable |
constant ctrl_csr_re_c : natural := 41; -- valid CSR read |
constant ctrl_csr_we_c : natural := 42; -- valid CSR write |
-- co-processor -- |
constant ctrl_cp_use_c : natural := 43; -- is cp operation |
constant ctrl_cp_id_lsb_c : natural := 44; -- cp select lsb |
constant ctrl_cp_id_msb_c : natural := 45; -- cp select msb |
constant ctrl_cp_cmd0_c : natural := 46; -- cp command bit 0 |
constant ctrl_cp_cmd1_c : natural := 47; -- cp command bit 1 |
constant ctrl_cp_cmd2_c : natural := 48; -- cp command bit 2 |
constant ctrl_cp_use_c : natural := 40; -- is cp operation |
constant ctrl_cp_id_lsb_c : natural := 41; -- cp select lsb |
constant ctrl_cp_id_msb_c : natural := 42; -- cp select msb |
constant ctrl_cp_cmd0_c : natural := 43; -- cp command bit 0 |
constant ctrl_cp_cmd1_c : natural := 44; -- cp command bit 1 |
constant ctrl_cp_cmd2_c : natural := 45; -- cp command bit 2 |
-- system -- |
constant ctrl_sys_c_ext_en_c : natural := 46; -- CPU C extension enabled |
constant ctrl_sys_m_ext_en_c : natural := 47; -- CPU M extension enabled |
-- control bus size -- |
constant ctrl_width_c : natural := 49; -- control bus size |
constant ctrl_width_c : natural := 48; -- control bus size |
|
-- ALU Comparator Bus --------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant alu_cmp_equal_c : natural := 0; |
constant alu_cmp_less_c : natural := 1; -- for signed and unsigned |
constant alu_cmp_less_c : natural := 1; -- for signed and unsigned comparisons |
|
-- RISC-V Opcode Layout ------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
279,14 → 279,14
-- cp ids -- |
constant cp_sel_muldiv_c : std_ulogic_vector(1 downto 0) := "00"; -- MULDIV CP |
-- muldiv cp -- |
constant cp_op_mul_c : std_ulogic_vector(2 downto 0) := "000"; -- mul |
constant cp_op_mulh_c : std_ulogic_vector(2 downto 0) := "001"; -- mulh |
constant cp_op_mulhsu_c : std_ulogic_vector(2 downto 0) := "010"; -- mulhsu |
constant cp_op_mulhu_c : std_ulogic_vector(2 downto 0) := "011"; -- mulhu |
constant cp_op_div_c : std_ulogic_vector(2 downto 0) := "100"; -- div |
constant cp_op_divu_c : std_ulogic_vector(2 downto 0) := "101"; -- divu |
constant cp_op_rem_c : std_ulogic_vector(2 downto 0) := "110"; -- rem |
constant cp_op_remu_c : std_ulogic_vector(2 downto 0) := "111"; -- remu |
constant cp_op_mul_c : std_ulogic_vector(2 downto 0) := "000"; -- mul |
constant cp_op_mulh_c : std_ulogic_vector(2 downto 0) := "001"; -- mulh |
constant cp_op_mulhsu_c : std_ulogic_vector(2 downto 0) := "010"; -- mulhsu |
constant cp_op_mulhu_c : std_ulogic_vector(2 downto 0) := "011"; -- mulhu |
constant cp_op_div_c : std_ulogic_vector(2 downto 0) := "100"; -- div |
constant cp_op_divu_c : std_ulogic_vector(2 downto 0) := "101"; -- divu |
constant cp_op_rem_c : std_ulogic_vector(2 downto 0) := "110"; -- rem |
constant cp_op_remu_c : std_ulogic_vector(2 downto 0) := "111"; -- remu |
|
-- ALU Function Codes --------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
337,6 → 337,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
390,9 → 391,9
uart_txd_o : out std_ulogic; -- UART send data |
uart_rxd_i : in std_ulogic := '0'; -- UART receive data |
-- SPI -- |
spi_sclk_o : out std_ulogic; -- serial clock line |
spi_mosi_o : out std_ulogic; -- serial data line out |
spi_miso_i : in std_ulogic := '0'; -- serial data line in |
spi_sck_o : out std_ulogic; -- SPI serial clock |
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in |
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- TWI -- |
twi_sda_io : inout std_logic := 'H'; -- twi serial data line |
413,6 → 414,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
471,6 → 473,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
515,8 → 518,9
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result |
-- data output -- |
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC |
alu_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC for ALU |
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch |
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction) |
next_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction) |
-- csr interface -- |
csr_wdata_i : in std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data |
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data |
531,7 → 535,8
be_instr_i : in std_ulogic; -- bus error on instruction access |
be_load_i : in std_ulogic; -- bus error on load data access |
be_store_i : in std_ulogic; -- bus error on store data access |
bus_exc_ack_o : out std_ulogic -- bus exception error acknowledge |
bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge |
bus_busy_i : in std_ulogic -- bus unit is busy |
); |
end component; |
|
559,10 → 564,6
-- Component: CPU ALU --------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_cpu_alu |
generic ( |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_M : boolean := false -- implement mul/div extension? |
); |
port ( |
-- global control -- |
clk_i : in std_ulogic; -- global clock, rising edge |
571,7 → 572,6
-- data input -- |
rs1_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1 |
rs2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- rf source 2 |
pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- current PC |
pc2_i : in std_ulogic_vector(data_width_c-1 downto 0); -- delayed PC |
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate |
csr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- csr read data |
610,8 → 610,7
-- ------------------------------------------------------------------------------------------- |
component neorv32_cpu_bus |
generic ( |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout |
MEM_EXT_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout |
); |
port ( |
-- global control -- |
634,6 → 633,7
be_load_o : out std_ulogic; -- bus error on load data access |
be_store_o : out std_ulogic; -- bus error on store data |
bus_wait_o : out std_ulogic; -- wait for bus operation to finish |
bus_busy_o : out std_ulogic; -- bus unit is busy |
exc_ack_i : in std_ulogic; -- exception controller ACK |
-- bus system -- |
bus_addr_o : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address |
654,7 → 654,6
-- instruction input -- |
ci_instr16_i : in std_ulogic_vector(15 downto 0); -- compressed instruction input |
-- instruction output -- |
ci_valid_o : out std_ulogic; -- is a compressed instruction |
ci_illegal_o : out std_ulogic; -- is an illegal compressed instruction |
ci_instr32_o : out std_ulogic_vector(31 downto 0) -- 32-bit decompressed instruction |
); |
838,9 → 837,9
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- com lines -- |
spi_sclk_o : out std_ulogic; -- SPI serial clock |
spi_mosi_o : out std_ulogic; -- SPI master out, slave in |
spi_miso_i : in std_ulogic; -- SPI master in, slave out |
spi_sck_o : out std_ulogic; -- SPI serial clock |
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in |
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- interrupt -- |
spi_irq_o : out std_ulogic -- transmission done interrupt |
1063,4 → 1062,31
return tmp_v; |
end function xnor_all_f; |
|
-- Function: Convert to hex char ---------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character is |
variable output_v : character; |
begin |
case input is |
when x"0" => output_v := '0'; |
when x"1" => output_v := '1'; |
when x"2" => output_v := '2'; |
when x"3" => output_v := '3'; |
when x"4" => output_v := '4'; |
when x"5" => output_v := '5'; |
when x"6" => output_v := '6'; |
when x"7" => output_v := '7'; |
when x"8" => output_v := '8'; |
when x"9" => output_v := '9'; |
when x"a" => output_v := 'a'; |
when x"b" => output_v := 'b'; |
when x"c" => output_v := 'c'; |
when x"d" => output_v := 'd'; |
when x"e" => output_v := 'e'; |
when x"f" => output_v := 'f'; |
when others => output_v := '?'; |
end case; |
return output_v; |
end function to_hexchar_f; |
|
end neorv32_package; |
/neorv32_spi.vhd
1,5 → 1,5
-- ################################################################################################# |
-- # << NEORV32 - Serial Peripheral Interface Master (SPI) >> # |
-- # << NEORV32 - Serial Peripheral Interface Controller (SPI) >> # |
-- # ********************************************************************************************* # |
-- # Frame format: 8/16/24/32-bit RTX, MSB or LSB first, 2 clock modes, 8 clock speeds, # |
-- # 8 dedicated CS lines (low-active). Interrupt: SPI_transfer_done # |
57,9 → 57,9
clkgen_en_o : out std_ulogic; -- enable clock generator |
clkgen_i : in std_ulogic_vector(07 downto 0); |
-- com lines -- |
spi_sclk_o : out std_ulogic; -- SPI serial clock |
spi_mosi_o : out std_ulogic; -- SPI master out, slave in |
spi_miso_i : in std_ulogic; -- SPI master in, slave out |
spi_sck_o : out std_ulogic; -- SPI serial clock |
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in |
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- interrupt -- |
spi_irq_o : out std_ulogic -- transmission done interrupt |
116,8 → 116,8
signal spi_rtx_sreg : std_ulogic_vector(31 downto 0); |
signal spi_rx_data : std_ulogic_vector(31 downto 0); |
signal spi_bitcnt : std_ulogic_vector(05 downto 0); |
signal spi_miso_ff0 : std_ulogic; |
signal spi_miso_ff1 : std_ulogic; |
signal spi_sdi_ff0 : std_ulogic; |
signal spi_sdi_ff1 : std_ulogic; |
|
begin |
|
217,9 → 217,9
spi_rtx_unit: process(clk_i) |
begin |
if rising_edge(clk_i) then |
-- input (MISO) synchronizer -- |
spi_miso_ff0 <= spi_miso_i; |
spi_miso_ff1 <= spi_miso_ff0; |
-- input (sdi) synchronizer -- |
spi_sdi_ff0 <= spi_sdi_i; |
spi_sdi_ff1 <= spi_sdi_ff0; |
|
-- serial engine -- |
spi_irq_o <= '0'; |
231,8 → 231,8
when others => spi_bitcnt <= "100000"; -- 32-bit mode |
end case; |
spi_state1 <= '0'; |
spi_mosi_o <= '0'; |
spi_sclk_o <= '0'; |
spi_sdo_o <= '0'; |
spi_sck_o <= '0'; |
if (ctrl(ctrl_spi_en_c) = '0') then -- disabled |
spi_busy <= '0'; |
elsif (spi_start = '1') then -- start new transmission |
249,19 → 249,19
else -- transmission in progress |
if (spi_state1 = '0') then -- first half of transmission |
|
spi_sclk_o <= ctrl(ctrl_spi_cpha_c); |
spi_sck_o <= ctrl(ctrl_spi_cpha_c); |
if (ctrl(ctrl_spi_dir_c) = '0') then |
spi_mosi_o <= spi_rtx_sreg(31); -- MSB first |
spi_sdo_o <= spi_rtx_sreg(31); -- MSB first |
else |
spi_mosi_o <= spi_rtx_sreg(0); -- LSB first |
spi_sdo_o <= spi_rtx_sreg(0); -- LSB first |
end if; |
if (spi_clk = '1') then |
spi_state1 <= '1'; |
if (ctrl(ctrl_spi_cpha_c) = '0') then |
if (ctrl(ctrl_spi_dir_c) = '0') then |
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_miso_ff1; -- MSB first |
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_sdi_ff1; -- MSB first |
else |
spi_rtx_sreg <= spi_miso_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first |
spi_rtx_sreg <= spi_sdi_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first |
end if; |
end if; |
spi_bitcnt <= std_ulogic_vector(unsigned(spi_bitcnt) - 1); |
268,14 → 268,14
end if; |
else -- second half of transmission |
|
spi_sclk_o <= not ctrl(ctrl_spi_cpha_c); |
spi_sck_o <= not ctrl(ctrl_spi_cpha_c); |
if (spi_clk = '1') then |
spi_state1 <= '0'; |
if (ctrl(ctrl_spi_cpha_c) = '1') then |
if (ctrl(ctrl_spi_dir_c) = '0') then |
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_miso_ff1; -- MSB first |
spi_rtx_sreg <= spi_rtx_sreg(30 downto 0) & spi_sdi_ff1; -- MSB first |
else |
spi_rtx_sreg <= spi_miso_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first |
spi_rtx_sreg <= spi_sdi_ff1 & spi_rtx_sreg(31 downto 1); -- LSB first |
end if; |
end if; |
if (spi_bitcnt = "000000") then |
/neorv32_top.vhd
50,6 → 50,7
CLOCK_FREQUENCY : natural := 0; -- clock frequency of clk_i in Hz |
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID |
BOOTLOADER_USE : boolean := true; -- implement processor-internal bootloader? |
CSR_COUNTERS_USE : boolean := true; -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- RISC-V CPU Extensions -- |
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? |
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? |
103,9 → 104,9
uart_txd_o : out std_ulogic; -- UART send data |
uart_rxd_i : in std_ulogic := '0'; -- UART receive data |
-- SPI (available if IO_SPI_USE = true) -- |
spi_sclk_o : out std_ulogic; -- serial clock line |
spi_mosi_o : out std_ulogic; -- serial data line out |
spi_miso_i : in std_ulogic := '0'; -- serial data line in |
spi_sck_o : out std_ulogic; -- SPI serial clock |
spi_sdo_o : out std_ulogic; -- controller data out, peripheral data in |
spi_sdi_i : in std_ulogic; -- controller data in, peripheral data out |
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS |
-- TWI (available if IO_TWI_USE = true) -- |
twi_sda_io : inout std_logic := 'H'; -- twi serial data line |
315,6 → 316,7
CLOCK_FREQUENCY => CLOCK_FREQUENCY, -- clock frequency of clk_i in Hz |
HART_ID => HART_ID, -- custom hardware thread ID |
BOOTLOADER_USE => BOOTLOADER_USE, -- implement processor-internal bootloader? |
CSR_COUNTERS_USE => CSR_COUNTERS_USE, -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])? |
-- 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? |
719,9 → 721,9
clkgen_en_o => spi_cg_en, -- enable clock generator |
clkgen_i => clk_gen, |
-- com lines -- |
spi_sclk_o => spi_sclk_o, -- SPI serial clock |
spi_mosi_o => spi_mosi_o, -- SPI master out, slave in |
spi_miso_i => spi_miso_i, -- SPI master in, slave out |
spi_sck_o => spi_sck_o, -- SPI serial clock |
spi_sdo_o => spi_sdo_o, -- controller data out, peripheral data in |
spi_sdi_i => spi_sdi_i, -- controller data in, peripheral data out |
spi_csn_o => spi_csn_o, -- SPI CS |
-- interrupt -- |
spi_irq_o => spi_irq -- transmission done interrupt |
732,8 → 734,8
if (IO_SPI_USE = false) generate |
spi_rdata <= (others => '0'); |
spi_ack <= '0'; |
spi_sclk_o <= '0'; |
spi_mosi_o <= '0'; |
spi_sck_o <= '0'; |
spi_sdo_o <= '0'; |
spi_csn_o <= (others => '1'); -- CSn lines are low-active |
spi_cg_en <= '0'; |
spi_irq <= '0'; |
/neorv32_twi.vhd
1,9 → 1,9
-- ################################################################################################# |
-- # << NEORV32 - Two-Wire Interface Master (TWI) >> # |
-- # << NEORV32 - Two-Wire Interface Controller (TWI) >> # |
-- # ********************************************************************************************* # |
-- # Supports START and STOP conditions, 8 bit data + ACK/NACK transfers and clock stretching. # |
-- # Supports ACKs by the master. No multi-master support and no slave mode support yet! # |
-- # Interrupt: TWI_transfer_done # |
-- # Supports ACKs by the constroller. No multi-controller support and no peripheral mode support # |
-- # yet. Interrupt: TWI_transfer_done # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
79,7 → 79,7
constant ctrl_twi_prsc0_c : natural := 4; -- r/w: CLK prsc bit 0 |
constant ctrl_twi_prsc1_c : natural := 5; -- r/w: CLK prsc bit 1 |
constant ctrl_twi_prsc2_c : natural := 6; -- r/w: CLK prsc bit 2 |
constant ctrl_twi_mack_c : natural := 7; -- r/w: generate ACK by master for transmission |
constant ctrl_twi_mack_c : natural := 7; -- r/w: generate ACK by controller for transmission |
-- |
constant ctrl_twi_ack_c : natural := 30; -- r/-: Set if ACK received |
constant ctrl_twi_busy_c : natural := 31; -- r/-: Set if TWI unit is busy |
201,7 → 201,7
-- TWI bus signals are set/sampled using 4 clock phases |
case arbiter is |
|
when "100" => -- IDLE: waiting for requests, bus might be still claimed by this master if no STOP condition was generated |
when "100" => -- IDLE: waiting for requests, bus might be still claimed by this controller if no STOP condition was generated |
twi_bitcnt <= (others => '0'); |
if (wr_en = '1') then |
if (addr = twi_ctrl_addr_c) then |
211,8 → 211,8
arbiter(1 downto 0) <= "10"; |
end if; |
elsif (addr = twi_rtx_addr_c) then -- start a data transmission |
-- one bit extra for ack, issued by master if ctrl_twi_mack_c is set, |
-- sampled from slave if ctrl_twi_mack_c is cleared |
-- one bit extra for ack, issued by controller if ctrl_twi_mack_c is set, |
-- sampled from peripheral if ctrl_twi_mack_c is cleared |
if (ben_i(0) = '1') then |
twi_rtx_sreg <= data_i(7 downto 0) & (not ctrl(ctrl_twi_mack_c)); |
arbiter(1 downto 0) <= "11"; |
279,10 → 279,10
-- ------------------------------------------------------------------------------------------- |
clock_stretching: process(arbiter, twi_scl_o, twi_scl_i_ff1) |
begin |
-- clock stretching by the slave can happen at "any time" |
-- clock stretching by the peripheral can happen at "any time" |
if (arbiter(2) = '1') and -- module enabled |
(twi_scl_o = '1') and -- master wants to pull scl high |
(twi_scl_i_ff1 = '0') then -- but scl is pulled low by slave |
(twi_scl_o = '1') and -- controller wants to pull scl high |
(twi_scl_i_ff1 = '0') then -- but scl is pulled low by peripheral |
twi_clk_halt <= '1'; |
else |
twi_clk_halt <= '0'; |