├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md └── hdl ├── common.vh ├── ctrl ├── dual_engine.sv ├── exception_alpha.sv └── pipeline_ctrl.sv ├── decode ├── decoder_alpha.sv └── decoder_ctrl.sv ├── exu ├── alu_alpha.sv ├── alu_beta.sv ├── alu_op.vh ├── branch.sv ├── divider.sv └── multplier.sv ├── ifu ├── instruction_fifo.sv └── pc.sv ├── lsu ├── data_fifo.sv ├── memory.sv ├── mmu_data.sv ├── mmu_inst.sv └── mmu_top.sv ├── mmu ├── mmu_map.sv ├── mmu_map_top.sv ├── tlb_common.sv └── tlb_top.sv ├── mycpu_top.v ├── reg ├── cp0.sv ├── forwarding_unit.sv ├── hilo.sv ├── register.sv ├── writeback_alpha.sv └── writeback_beta.sv └── sirius.sv /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/name1e5s/Sirius/22eb3aa1ec01710b6e8598a225909d05048a2dbf/.gitignore -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "doc"] 2 | path = doc 3 | url = https://github.com/name1e5s/nscscc-miscellaneous.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sirius 2 | Asymmetric dual issue in-order microprocessor. 3 | 4 | ![](http://florin.myip.org/blog/files/640px-Sirius_A_and_B_artwork.jpg) 5 | -------------------------------------------------------------------------------- /hdl/common.vh: -------------------------------------------------------------------------------- 1 | // JUMP instruction type 2 | `define B_EQNE 3'b000 3 | `define B_LTGE 3'b001 4 | `define B_JUMP 3'b010 5 | `define B_JREG 3'b011 6 | `define B_INVA 3'b111 7 | 8 | `define MEM_LOAD 2'b10 9 | `define MEM_STOR 2'b01 10 | `define MEM_NOOP 2'b00 11 | `define MEM_CACH 2'b11 12 | 13 | `define SZ_FULL 3'b111 14 | `define SZ_HALF 3'b010 15 | `define SZ_BYTE 3'b000 16 | `define SZ_LEFT 3'b101 17 | `define SZ_RIGH 3'b110 18 | 19 | `define SRC_REG 2'd0 20 | `define SRC_IMM 2'd1 21 | `define SRC_SFT 2'd2 22 | `define SRC_PCA 2'd3 23 | 24 | `define SIGN_EXTENDED 1'b0 25 | `define ZERO_EXTENDED 1'b1 -------------------------------------------------------------------------------- /hdl/ctrl/dual_engine.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "common.vh" 3 | 4 | // Dual issue detect engine. 5 | module dual_engine( 6 | // Infomation about master pipeline 7 | input id_priv_inst_master, 8 | input [4:0] id_wb_reg_dest_master, 9 | input id_wb_reg_en_master, 10 | input id_is_hilo_accessed_master, 11 | 12 | // For load-use stall detection... 13 | input [1:0] id_ex_mem_type, 14 | input [4:0] id_ex_mem_wb_reg_dest, 15 | 16 | // Infomation about slave pipeline 17 | input [5:0] id_opcode_slave, 18 | input [4:0] id_rs_slave, 19 | input [4:0] id_rt_slave, 20 | input [1:0] id_mem_type_slave, 21 | input id_is_branch_instr_slave, 22 | input id_priv_inst_slave, 23 | input id_is_hilo_accessed_slave, 24 | input id_tlb_error, 25 | 26 | // Info about FIFO 27 | input fifo_empty, 28 | input fifo_almost_empty, 29 | 30 | input enable_master, 31 | output logic enable_slave 32 | ); 33 | 34 | wire fifo = ~(fifo_empty || fifo_almost_empty); 35 | logic load_use_stall_slave; 36 | logic _enable_slave; 37 | assign enable_slave = _enable_slave && (!load_use_stall_slave) && fifo; 38 | 39 | always_comb begin : check_slave_enable 40 | if( (!enable_master) || 41 | (id_priv_inst_master) || 42 | (id_priv_inst_slave) || 43 | (id_is_branch_instr_slave) || 44 | (id_mem_type_slave != `MEM_NOOP) || 45 | (id_is_hilo_accessed_slave) || 46 | (id_tlb_error) 47 | ) begin 48 | _enable_slave = 1'b0; 49 | end 50 | else begin 51 | if(id_wb_reg_en_master && (id_wb_reg_dest_master != 5'd0)) begin 52 | if(id_opcode_slave == 6'd0) begin // R type 53 | _enable_slave = (|((id_wb_reg_dest_master ^ id_rs_slave) & (id_wb_reg_dest_master ^ id_rt_slave))); 54 | end 55 | else begin 56 | _enable_slave = (|((id_wb_reg_dest_master ^ id_rs_slave))); 57 | end 58 | end 59 | else begin 60 | _enable_slave = 1'b1; 61 | end 62 | end 63 | end 64 | 65 | always_comb begin 66 | if(id_ex_mem_type == `MEM_LOAD && ((id_ex_mem_wb_reg_dest == id_rs_slave) || 67 | (id_ex_mem_wb_reg_dest == id_rt_slave))) 68 | load_use_stall_slave = 1'd1; 69 | else 70 | load_use_stall_slave = 1'd0; 71 | end 72 | endmodule -------------------------------------------------------------------------------- /hdl/ctrl/exception_alpha.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module exception_alpha( 3 | input clk, 4 | input rst, 5 | 6 | input iaddr_alignment_error, 7 | input iaddr_tlb_miss, 8 | input iaddr_tlb_invalid, 9 | input daddr_alignment_error, 10 | input daddr_tlb_miss, 11 | input daddr_tlb_invalid, 12 | input daddr_tlb_dirty, 13 | input invalid_instruction, 14 | input priv_instruction, 15 | input syscall, 16 | input break_, 17 | input eret, 18 | input overflow, 19 | input mem_wen, 20 | input is_branch_instruction, 21 | input is_branch_slot, 22 | input [31:0] pc_address, 23 | input [31:0] mem_address, 24 | input [31:0] epc_address, 25 | input allow_interrupt, 26 | input [ 7:0] interrupt_flag, 27 | input is_inst, 28 | input slave_exp_undefined_inst, 29 | input slave_exp_overflow, 30 | 31 | 32 | // MIPS32r1 33 | input [31:0] cp0_ebase, 34 | input cp0_use_special_iv, 35 | input cp0_use_bootstrap_iv, 36 | input exl_set_if, 37 | input exl_set_mem, 38 | input [7:0] asid_if, 39 | input [7:0] asid_mem, 40 | 41 | output logic exp_detect, 42 | output logic exp_detect_salve, 43 | output logic cp0_exp_en, 44 | output logic cp0_exl_clean, 45 | output logic [31:0] cp0_exp_epc, 46 | output logic [4:0] cp0_exp_code, 47 | output logic [31:0] cp0_exp_bad_vaddr, 48 | output logic cp0_exp_bad_vaddr_wen, 49 | output logic [31:0] exp_pc_address, 50 | output logic cp0_exp_bd, 51 | output logic [7:0] cp0_exp_asid, 52 | output logic cp0_exp_asid_en 53 | ); 54 | 55 | wire [31:0] ebase = cp0_use_bootstrap_iv? 32'hbfc0_0200 : {2'b10, cp0_ebase[29:12], 12'd0}; 56 | always_comb begin : check_exceotion 57 | exp_pc_address = ebase + 32'h180; 58 | cp0_exp_en = 1'd1; 59 | cp0_exl_clean = 1'b0; 60 | cp0_exp_bad_vaddr_wen = 1'b0; 61 | cp0_exp_bad_vaddr = 32'd0; 62 | exp_detect = 1'b1; 63 | exp_detect_salve = 1'd0; 64 | cp0_exp_bd = is_branch_slot; 65 | cp0_exp_epc = is_branch_slot ? pc_address - 32'd4: pc_address; 66 | cp0_exp_asid = 8'd0; 67 | cp0_exp_asid_en = 1'd0; 68 | if(is_inst && allow_interrupt && interrupt_flag != 8'd0) begin 69 | if(cp0_use_special_iv) 70 | exp_pc_address = ebase + 32'h200; 71 | cp0_exp_code = 5'h00; 72 | $display("[EXP] Interrupt at 0x%x",pc_address); 73 | end 74 | else if(iaddr_alignment_error) begin 75 | cp0_exp_code = 5'h04; 76 | cp0_exp_bad_vaddr = pc_address; 77 | cp0_exp_bad_vaddr_wen = 1'b1; 78 | $display("[EXP] Illegal iaddr at 0x%x",pc_address); 79 | end 80 | else if(iaddr_tlb_miss) begin 81 | if(~exl_set_if) 82 | exp_pc_address = ebase + 32'h0; 83 | cp0_exp_asid = asid_if; 84 | cp0_exp_asid_en = 1'd1; 85 | cp0_exp_bad_vaddr = pc_address; 86 | cp0_exp_bad_vaddr_wen = 1'b1; 87 | cp0_exp_code = 5'h02; 88 | $display("[EXP] ITLB Miss at 0x%x",pc_address); 89 | end 90 | else if(iaddr_tlb_invalid) begin 91 | cp0_exp_asid = asid_if; 92 | cp0_exp_asid_en = 1'd1; 93 | cp0_exp_bad_vaddr = pc_address; 94 | cp0_exp_bad_vaddr_wen = 1'b1; 95 | cp0_exp_code = 5'h02; 96 | $display("[EXP] ITLB Invalid at 0x%x",pc_address); 97 | end 98 | else if(syscall) begin 99 | cp0_exp_code = 5'h08; 100 | $display("[EXP] System call at 0x%x",pc_address); 101 | end 102 | else if(break_) begin 103 | cp0_exp_code = 5'h09; 104 | $display("[EXP] Break point at 0x%x",pc_address); 105 | end 106 | else if(invalid_instruction) begin 107 | cp0_exp_code = 5'h0a; 108 | $display("[EXP] RI at 0x%x",pc_address); 109 | end 110 | else if(priv_instruction) begin 111 | cp0_exp_code = 5'h0b; 112 | $display("[EXP] CpU at 0x%x",pc_address); 113 | end 114 | else if(overflow) begin 115 | cp0_exp_code = 5'h0c; 116 | $display("[EXP] Overflow at 0x%x",pc_address); 117 | end 118 | else if(eret) begin 119 | cp0_exp_code = 5'h00; 120 | cp0_exp_en = 1'b0; 121 | cp0_exl_clean = 1'b1; 122 | exp_pc_address = epc_address; 123 | end 124 | else if(daddr_alignment_error) begin 125 | cp0_exp_code = mem_wen ? 5'h05:5'h04; 126 | cp0_exp_bad_vaddr = mem_address; 127 | cp0_exp_bad_vaddr_wen = 1'b1; 128 | end 129 | else if(daddr_tlb_miss) begin 130 | if(~exl_set_mem) 131 | exp_pc_address = ebase + 32'h0; 132 | cp0_exp_asid = asid_mem; 133 | cp0_exp_asid_en = 1'd1; 134 | cp0_exp_bad_vaddr = mem_address; 135 | cp0_exp_bad_vaddr_wen = 1'b1; 136 | cp0_exp_code = mem_wen? 5'h03 : 5'h02; 137 | $display("[EXP] DTLB Miss at 0x%x",pc_address); 138 | end 139 | else if(daddr_tlb_invalid) begin 140 | cp0_exp_asid = asid_mem; 141 | cp0_exp_asid_en = 1'd1; 142 | cp0_exp_bad_vaddr = mem_address; 143 | cp0_exp_bad_vaddr_wen = 1'b1; 144 | cp0_exp_code = mem_wen? 5'h03 : 5'h02; 145 | $display("[EXP] DTLB Invalid at 0x%x",pc_address); 146 | end 147 | else if(mem_wen && !daddr_tlb_dirty) begin 148 | cp0_exp_asid = asid_if; 149 | cp0_exp_asid_en = 1'd1; 150 | cp0_exp_bad_vaddr = mem_address; 151 | cp0_exp_bad_vaddr_wen = 1'b1; 152 | cp0_exp_code = 5'h01; 153 | $display("[EXP] DTLB Invalid at 0x%x",pc_address); 154 | end 155 | else if(slave_exp_undefined_inst) begin 156 | cp0_exp_bd = is_branch_instruction; 157 | cp0_exp_epc = is_branch_instruction? pc_address : pc_address + 32'd4; 158 | cp0_exp_code = 5'h0a; 159 | exp_detect_salve = 1'd1; 160 | end 161 | else if(slave_exp_overflow) begin 162 | cp0_exp_bd = is_branch_instruction; 163 | cp0_exp_epc = is_branch_instruction? pc_address : pc_address + 32'd4; 164 | cp0_exp_code = 5'h0c; 165 | exp_detect_salve = 1'd1; 166 | end 167 | else begin 168 | cp0_exp_en = 1'b0; 169 | exp_detect = 1'b0; 170 | cp0_exp_code = 5'd0; 171 | end 172 | end 173 | 174 | endmodule 175 | -------------------------------------------------------------------------------- /hdl/ctrl/pipeline_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "alu_op.vh" 3 | `include "common.vh" 4 | 5 | // Pipeline stall control 6 | module pipe_ctrl( 7 | input clk, 8 | input rst, 9 | input icache_stall, 10 | input ex_stall, 11 | input mem_stall, 12 | 13 | input [5:0] id_ex_alu_op, 14 | input [1:0] id_ex_mem_type, 15 | input [4:0] id_ex_mem_wb_reg_dest, 16 | input ex_mem_cp0_wen, 17 | input [1:0] ex_mem_mem_type, 18 | input [4:0] ex_mem_mem_wb_reg_dest, 19 | input [4:0] id_rs, 20 | input [4:0] id_rt, 21 | input id_branch_taken, 22 | input fifo_full, 23 | input exp_detect, 24 | 25 | output logic en_if, 26 | output logic en_if_id, 27 | output logic en_id_ex, 28 | output logic en_ex_mem, 29 | output logic en_mem_wb 30 | ); 31 | 32 | logic [4:0] en; 33 | assign { en_if, en_if_id, en_id_ex, en_ex_mem, en_mem_wb } = en; 34 | 35 | logic load_use_stall; 36 | always_comb begin : set_control_logic 37 | load_use_stall = 1'd0; 38 | if(rst) 39 | en = 5'b11111; 40 | else if(icache_stall) begin 41 | if(exp_detect || mem_stall) 42 | en = 5'b00000; 43 | else begin 44 | en = 5'b00001; 45 | end 46 | end 47 | else if(mem_stall) begin 48 | if(id_branch_taken) 49 | en = 5'b00000; 50 | else 51 | en = 5'b10000; 52 | end 53 | else if(ex_stall) 54 | en = 5'b10001; 55 | else if(id_ex_alu_op == `ALU_MFC0 && ex_mem_cp0_wen) 56 | en = 5'b10011; 57 | else if(id_ex_mem_type == `MEM_LOAD && 58 | ((id_ex_mem_wb_reg_dest == id_rs) || 59 | (id_ex_mem_wb_reg_dest == id_rt))) begin 60 | en = 5'b10011; 61 | load_use_stall = 1'd1; 62 | end 63 | else 64 | en = 5'b11111; 65 | end 66 | 67 | // For perftunning... 68 | logic [63:0] icache_stall_counter; 69 | always_ff @(posedge clk) begin 70 | if(rst) 71 | icache_stall_counter <= 64'd0; 72 | else if(icache_stall) 73 | icache_stall_counter <= icache_stall_counter + 64'd1; 74 | end 75 | 76 | logic [63:0] mem_stall_counter; 77 | always_ff @(posedge clk) begin 78 | if(rst) 79 | mem_stall_counter <= 64'd0; 80 | else if(mem_stall) 81 | mem_stall_counter <= mem_stall_counter + 64'd1; 82 | end 83 | 84 | logic [63:0] ex_stall_counter; 85 | always_ff @(posedge clk) begin 86 | if(rst) 87 | ex_stall_counter <= 64'd0; 88 | else if(ex_stall) 89 | ex_stall_counter <= ex_stall_counter + 64'd1; 90 | end 91 | 92 | logic [63:0] load_use_stall_counter; 93 | always_ff @(posedge clk) begin 94 | if(rst) 95 | load_use_stall_counter <= 64'd0; 96 | else if(load_use_stall) 97 | load_use_stall_counter <= load_use_stall_counter + 64'd1; 98 | end 99 | 100 | endmodule -------------------------------------------------------------------------------- /hdl/decode/decoder_alpha.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "common.vh" 3 | 4 | module decoder_alpha( 5 | input [31:0] instruction, 6 | 7 | output logic [5:0] opcode, 8 | output logic [4:0] rs, 9 | output logic [4:0] rt, 10 | output logic [4:0] rd, 11 | output logic [4:0] shamt, 12 | output logic [5:0] funct, 13 | output logic [15:0] immediate, 14 | output logic [25:0] instr_index, 15 | 16 | output logic [2:0] branch_type, 17 | output logic is_branch_instr, 18 | output logic is_branch_link, 19 | output logic is_hilo_accessed 20 | ); 21 | 22 | assign opcode = instruction[31:26]; 23 | assign rs = instruction[25:21]; 24 | assign rt = instruction[20:16]; 25 | assign rd = instruction[15:11]; 26 | assign shamt = instruction[10:6]; 27 | assign funct = instruction[5:0]; 28 | assign immediate = instruction[15:0]; 29 | assign instr_index = instruction[25:0]; 30 | 31 | // Check if the instruction is a branch/jump function 32 | always_comb begin 33 | //BEQ, BNE, BLEZ and BGTZ live here 34 | if(opcode[5:2] == 4'b0001) begin 35 | is_branch_instr = 1'b1; 36 | branch_type = `B_EQNE; 37 | is_branch_link = 1'b0; 38 | // BLTZ, BGEZ, BLTZL, BGEZL lives here, but we 39 | // don't care those branch-likely instructions 40 | end 41 | else if(opcode == 6'b000001 && rt[3:1] == 3'b000) begin 42 | is_branch_instr = 1'b1; 43 | branch_type = `B_LTGE; 44 | is_branch_link = rt[4]; 45 | // J, JAL is here 46 | end 47 | else if(opcode[5:1] == 5'b00001) begin 48 | is_branch_instr = 1'b1; 49 | branch_type = `B_JUMP; 50 | is_branch_link = opcode[0]; 51 | // JR, JALR is here 52 | end 53 | else if(opcode == 6'b000000 && funct[5:1] == 5'b00100) begin 54 | is_branch_instr = 1'b1; 55 | branch_type = `B_JREG; 56 | is_branch_link = funct[0]; 57 | end 58 | else begin 59 | is_branch_instr = 1'b0; 60 | branch_type = `B_INVA; 61 | is_branch_link = 1'b0; 62 | end 63 | end 64 | 65 | // Check if the instruction needs HILO register(s) 66 | // Note: the multplier and divier requires more than one cycle to 67 | // complete the operation and they write their results to inner 68 | // ``hilo'' register(s). Hence we can perform those operations 69 | // without stalling the whole pipeline when the result in the hilo 70 | // is not needed. 71 | always_comb begin 72 | if(instruction[31:26] == 6'b000000 && 73 | (instruction[5:2] == 4'b0100 || instruction[5:2] == 4'b0110)) 74 | is_hilo_accessed = 1'b1; 75 | else if(instruction[31:26] == 6'b011100 && (instruction[5:3] == 3'b000)) 76 | case(instruction[2:0]) 77 | 3'b000, 3'b001, 3'b010, 3'b100, 3'b101: 78 | is_hilo_accessed = 1'b1; 79 | default: 80 | is_hilo_accessed = 1'b0; 81 | endcase 82 | else 83 | is_hilo_accessed = 1'b0; 84 | end 85 | endmodule -------------------------------------------------------------------------------- /hdl/decode/decoder_ctrl.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "common.vh" 3 | `include "alu_op.vh" 4 | 5 | // Alpha and Beta shares the same ctrl signal. 6 | module decoder_ctrl( 7 | input [31:0] instruction, 8 | input [5:0] opcode, 9 | input [4:0] rt, 10 | input [4:0] rd, 11 | input [5:0] funct, 12 | input is_branch, 13 | input is_branch_al, 14 | 15 | output logic undefined_inst, // 1 as received a unknown operation. 16 | output logic [5:0] alu_op, // ALU operation 17 | output logic [1:0] alu_src, // ALU oprand 2 source(0 as rt, 1 as immed) 18 | output logic alu_imm_src, // ALU immediate src - 1 as unsigned, 0 as signed. 19 | output logic [1:0] mem_type, // Memory operation type -- load or store 20 | output logic [2:0] mem_size, // Memory operation size -- B,H,W,WL,WR 21 | output logic [4:0] wb_reg_dest, // Writeback register address 22 | output logic wb_reg_en, // Writeback is enabled 23 | output logic unsigned_flag, // Is this a unsigned operation in MEM stage. 24 | output logic priv_inst // Is this instruction a priv inst? 25 | ); 26 | 27 | // Control logic. 28 | always_comb begin : decoder 29 | // To prevent latch... 30 | undefined_inst = 1'b0; 31 | priv_inst = 1'b0; 32 | alu_op = `ALU_ADDU; 33 | alu_src = 2'd0; 34 | alu_imm_src = 1'd1; 35 | mem_type = `MEM_NOOP; 36 | mem_size = `SZ_FULL; 37 | wb_reg_dest = 5'd0; 38 | wb_reg_en = 1'd0; 39 | unsigned_flag = 1'd0; 40 | casex({opcode, funct}) 41 | {6'b000000, 6'b100000}: // ADD 42 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 43 | {`ALU_ADD, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 44 | {6'b001000, 6'bxxxxxx}: // ADDI 45 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 46 | {`ALU_ADD, `SRC_IMM, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 47 | {6'b000000, 6'b100001}: // ADDU 48 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 49 | {`ALU_ADDU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 50 | {6'b001001, 6'bxxxxxx}: // ADDIU 51 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 52 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 53 | {6'b000000, 6'b100010}: // SUB 54 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 55 | {`ALU_SUB, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 56 | {6'b000000, 6'b100011}: // SUBU 57 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 58 | {`ALU_SUBU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 59 | {6'b000000, 6'b101010}: // SLT 60 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 61 | {`ALU_SLT, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 62 | {6'b001010, 6'bxxxxxx}: // SLTI 63 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 64 | {`ALU_SLT, `SRC_IMM, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 65 | {6'b000000, 6'b101011}: // SLTU 66 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 67 | {`ALU_SLTU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 68 | {6'b001011, 6'bxxxxxx}: // SLTIU 69 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 70 | {`ALU_SLTU, `SRC_IMM, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 71 | {6'b000000, 6'b011010}: // DIV 72 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 73 | {`ALU_DIV, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 74 | {6'b000000, 6'b011011}: // DIVU 75 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 76 | {`ALU_DIVU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 77 | {6'b000000, 6'b011000}: // MULT 78 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 79 | {`ALU_MULT, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 80 | {6'b000000, 6'b011001}: // MULTU 81 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 82 | {`ALU_MULTU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 83 | {6'b000000, 6'b100100}: // AND 84 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 85 | {`ALU_AND, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 86 | {6'b001100, 6'bxxxxxx}: // ANDI 87 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 88 | {`ALU_AND, `SRC_IMM, `ZERO_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 89 | {6'b001111, 6'bxxxxxx}: // LUI 90 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 91 | {`ALU_LUI, `SRC_IMM, `ZERO_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 92 | {6'b000000, 6'b100111}: // NOR 93 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 94 | {`ALU_NOR, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 95 | {6'b000000, 6'b100101}: // OR 96 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 97 | {`ALU_OR, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 98 | {6'b001101, 6'bxxxxxx}: // ORI 99 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 100 | {`ALU_OR, `SRC_IMM, `ZERO_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 101 | {6'b000000, 6'b100110}: // XOR 102 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 103 | {`ALU_XOR, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 104 | {6'b001110, 6'bxxxxxx}: // XORI 105 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 106 | {`ALU_XOR, `SRC_IMM, `ZERO_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 107 | {6'b000000, 6'b000100}: // SLLV 108 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 109 | {`ALU_SLL, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 110 | {6'b000000, 6'b000000}: // SLL 111 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 112 | {`ALU_SLL, `SRC_SFT, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 113 | {6'b000000, 6'b000111}: // SRAV 114 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 115 | {`ALU_SRA, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 116 | {6'b000000, 6'b000011}: // SRA 117 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 118 | {`ALU_SRA, `SRC_SFT, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 119 | {6'b000000, 6'b000110}: // SRLV 120 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 121 | {`ALU_SRL, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 122 | {6'b000000, 6'b000010}: // SRL 123 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 124 | {`ALU_SRL, `SRC_SFT, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 125 | {6'b000000, 6'b010000}: // MFHI 126 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 127 | {`ALU_MFHI, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 128 | {6'b000000, 6'b010010}: // MFLO 129 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 130 | {`ALU_MFLO, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 131 | {6'b000000, 6'b010001}: // MTHI 132 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 133 | {`ALU_MTHI, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 134 | {6'b000000, 6'b010011}: // MTLO 135 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 136 | {`ALU_MTLO, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 137 | {6'b000000, 6'b001101}: begin // BREAK 138 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 139 | {`ALU_BREK, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 140 | priv_inst = 1'b1; 141 | end 142 | {6'b000000, 6'b001100}: begin // SYSCALL 143 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 144 | {`ALU_SYSC, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 145 | priv_inst = 1'b1; 146 | end 147 | {6'b100000, 6'bxxxxxx}: // LB 148 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 149 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_BYTE, rt, 1'b1, `SIGN_EXTENDED}; 150 | {6'b100100, 6'bxxxxxx}: // LBU 151 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 152 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_BYTE, rt, 1'b1, `ZERO_EXTENDED}; 153 | {6'b100001, 6'bxxxxxx}: // LH 154 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 155 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_HALF, rt, 1'b1, `SIGN_EXTENDED}; 156 | {6'b100101, 6'bxxxxxx}: // LHU 157 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 158 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_HALF, rt, 1'b1, `ZERO_EXTENDED}; 159 | {6'b100011, 6'bxxxxxx}: // LW 160 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 161 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 162 | {6'b101000, 6'bxxxxxx}: // SB 163 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 164 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_STOR, `SZ_BYTE, rt, 1'b0, `SIGN_EXTENDED}; 165 | {6'b101001, 6'bxxxxxx}: // SH 166 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 167 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_STOR, `SZ_HALF, rt, 1'b0, `SIGN_EXTENDED}; 168 | {6'b101011, 6'bxxxxxx}: // SW 169 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 170 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_STOR, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 171 | {6'b010000, 6'bxxxxxx}: begin // PRIV_INST 172 | priv_inst = 1'b1; 173 | if(instruction == 32'b01000010000000000000000000011000) // ERET 174 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 175 | {`ALU_ERET, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 176 | else if(instruction[25:21] == 5'b00000) // MFC0 177 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 178 | {`ALU_MFC0, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b1, `ZERO_EXTENDED}; 179 | else if(instruction[25:21] == 5'b00100) // MTC0 180 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 181 | {`ALU_MTC0, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 182 | else if(instruction[25] && instruction[5:0] == 6'b001000) // TLBP 183 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 184 | {`ALU_TLBP, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 185 | else if(instruction[25] && instruction[5:0] == 6'b000001) // TLBR 186 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 187 | {`ALU_TLBR, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 188 | else if(instruction[25] && instruction[5:0] == 6'b000010) // TLBWI 189 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 190 | {`ALU_TLBWI, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 191 | else if(instruction[25] && instruction[5:0] == 6'b000110) // TLBWR 192 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 193 | {`ALU_TLBWR, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 194 | else 195 | undefined_inst = 1'd1; 196 | end 197 | // MIPS32r1 begin 198 | {6'b011100, 6'b100001}: // CLO 199 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 200 | {`ALU_CLO, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 201 | {6'b011100, 6'b100000}: // CLZ 202 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 203 | {`ALU_CLZ, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 204 | {6'b011100, 6'b000000}: // MADD 205 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 206 | {`ALU_MADD, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 207 | {6'b011100, 6'b000001}: // MADDU 208 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 209 | {`ALU_MADDU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 210 | {6'b011100, 6'b000100}: // MSUB 211 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 212 | {`ALU_MSUB, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 213 | {6'b011100, 6'b000010}: // MUL 214 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 215 | {`ALU_MUL, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 216 | {6'b011100, 6'b000101}: // MSUBU 217 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 218 | {`ALU_MSUBU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 219 | {6'b000000, 6'b001011}: // MOVN 220 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 221 | {`ALU_MOVN, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 222 | {6'b000000, 6'b001010}: // MOVZ 223 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 224 | {`ALU_MOVZ, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b1, `ZERO_EXTENDED}; 225 | {6'b110011, 6'bxxxxxx}: begin // PREF -- as NOP 226 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 227 | {`ALU_SLL, `SRC_SFT, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 228 | priv_inst = 1'b1; 229 | end 230 | {6'b000000, 6'b001111}: // SYSC -- sa NOP 231 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 232 | {`ALU_SLL, `SRC_SFT, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 233 | {6'b010000, 6'b100000}: begin // WAIT -- as NOP 234 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 235 | {`ALU_SLL, `SRC_SFT, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rd, 1'b0, `ZERO_EXTENDED}; 236 | priv_inst = 1'b1; 237 | end 238 | {6'b101010, 6'bxxxxxx}: // SWL 239 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 240 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_STOR, `SZ_LEFT, rt, 1'b0, `ZERO_EXTENDED}; 241 | {6'b101110, 6'bxxxxxx}: // SWR 242 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 243 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_STOR, `SZ_RIGH, rt, 1'b0, `ZERO_EXTENDED}; 244 | {6'b100010, 6'bxxxxxx}: // LWL 245 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 246 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_LEFT, rt, 1'b1, `ZERO_EXTENDED}; 247 | {6'b100110, 6'bxxxxxx}: // LWR 248 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 249 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_LOAD, `SZ_RIGH, rt, 1'b1, `ZERO_EXTENDED}; 250 | {6'b101111, 6'bxxxxxx}: begin // CACHE 251 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 252 | {`ALU_ADDU, `SRC_IMM, `SIGN_EXTENDED, `MEM_CACH, `SZ_BYTE, rt, 1'b0, `ZERO_EXTENDED}; 253 | priv_inst = 1'b1; 254 | end 255 | // MIPS32r1 end 256 | default: begin 257 | if(is_branch && is_branch_al) 258 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 259 | {`ALU_OUTA, `SRC_PCA, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, 5'd31, 1'b1, `ZERO_EXTENDED}; 260 | else begin 261 | undefined_inst = ~is_branch; 262 | {alu_op, alu_src, alu_imm_src, mem_type, mem_size, wb_reg_dest, wb_reg_en, unsigned_flag} = 263 | {`ALU_ADDU, `SRC_REG, `SIGN_EXTENDED, `MEM_NOOP, `SZ_FULL, rt, 1'b0, `ZERO_EXTENDED}; 264 | end 265 | end 266 | endcase 267 | end 268 | endmodule 269 | -------------------------------------------------------------------------------- /hdl/exu/alu_alpha.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "alu_op.vh" 3 | // In our design, hilo-related operations and is handled ONLY by 4 | // alpha pipeline. 5 | 6 | // Changelog 2019-06-12: now priv_inst signal is asserted by decoder. 7 | module alu_alpha( 8 | input clk, 9 | input rst, 10 | input flush_i, 11 | 12 | input [5:0] alu_op, 13 | input [31:0] src_a, 14 | input [31:0] src_b, 15 | input [63:0] src_hilo, 16 | 17 | // For MFC0/MTC0 18 | input [4:0] rd, 19 | input [2:0] sel, 20 | output [7:0] cop0_addr, // rd || sel 21 | input [31:0] cop0_data, 22 | output logic cop0_wen, 23 | output logic exp_overflow, 24 | output logic exp_eret, 25 | output logic exp_syscal, 26 | output logic exp_break, 27 | output logic tlb_tlbwi, 28 | output logic tlb_tlbwr, 29 | output logic tlb_tlbr, 30 | output logic tlb_tlbp, 31 | 32 | output logic ex_reg_en, 33 | output logic hilo_wen, 34 | output logic [63:0] hilo_result, 35 | output logic [31:0] result, 36 | output logic stall_o // Stall pipeline when a mdu operation is running and an instruction needs 37 | // result in hilo. 38 | ); 39 | 40 | wire [63:0] hilo = src_hilo; 41 | wire [31:0] hi = hilo[63:32]; 42 | wire [31:0] lo = hilo[31:0]; 43 | wire [31:0] add_result = src_a + src_b; 44 | wire [31:0] sub_result = src_a - src_b; 45 | 46 | logic [5:0] clo_result, clz_result; 47 | 48 | // COP0 49 | assign cop0_addr = {rd, sel}; 50 | assign exp_eret = alu_op == `ALU_ERET; 51 | assign exp_syscal = alu_op == `ALU_SYSC; 52 | assign exp_break = alu_op == `ALU_BREK; 53 | assign tlb_tlbp = alu_op == `ALU_TLBP; 54 | assign tlb_tlbwi = alu_op == `ALU_TLBWI; 55 | assign tlb_tlbwr = alu_op == `ALU_TLBWR; 56 | assign tlb_tlbr = alu_op == `ALU_TLBR; 57 | 58 | always_comb begin : write_c0 59 | if(alu_op == `ALU_MTC0) 60 | cop0_wen = 1'b1; 61 | else 62 | cop0_wen = 1'b0; 63 | end 64 | 65 | // For mult/div 66 | reg mult_done_prev, div_done_prev; 67 | logic mult_done, div_done; 68 | logic [63:0] _hilo_mult, _hilo_div; 69 | // logic [63:0] hilo_mult, hilo_div; 70 | logic [1:0] mult_op, div_op; 71 | logic mult_commit, div_commit; 72 | // Pipeline control. 73 | wire mdu_running = ~(mult_done & div_done) || mdu_prepare; 74 | logic mdu_prepare; 75 | 76 | assign stall_o = flush_i? 0 : (mdu_running); 77 | assign mult_commit = mult_done && (mult_done_prev != mult_done); 78 | assign div_commit = div_done && (div_done_prev != div_done); 79 | 80 | always_ff @(posedge clk) begin : is_mdu_done 81 | if(rst) begin 82 | mult_done_prev <= 1'b0; 83 | div_done_prev <= 1'b0; 84 | end 85 | else begin 86 | mult_done_prev <= mult_done; 87 | div_done_prev <= div_done; 88 | end 89 | end 90 | 91 | // The mult/div unit. 92 | always_comb begin : mdu_control 93 | div_op = 2'd0; 94 | mult_op = 2'd0; 95 | mdu_prepare = 1'b0; 96 | if(!flush_i && (mult_done & div_done) && 97 | (mult_done_prev == mult_done) && (div_done_prev == div_done)) begin 98 | mdu_prepare = 1'b1; 99 | unique case(alu_op) 100 | `ALU_DIV: 101 | div_op = 2'b10; 102 | `ALU_DIVU: 103 | div_op = 2'b01; 104 | `ALU_MULT, `ALU_MADD, `ALU_MSUB, `ALU_MUL: 105 | mult_op = 2'b10; 106 | `ALU_MULTU, `ALU_MADDU, `ALU_MSUBU: 107 | mult_op = 2'b01; 108 | default: begin 109 | mdu_prepare = 1'b0; 110 | end 111 | endcase 112 | end 113 | else begin 114 | mdu_prepare = 1'b0; 115 | end 116 | end 117 | 118 | divider div_alpha( 119 | .clk (clk), 120 | .rst (rst), 121 | .div_op (div_op), 122 | .divisor (src_b), 123 | .dividend (src_a), 124 | .result (_hilo_div), 125 | .done (div_done) 126 | ); 127 | 128 | multplier mult_alpha( 129 | .clk (clk), 130 | .rst (rst), 131 | .op (mult_op), 132 | .a (src_a), 133 | .b (src_b), 134 | .c (_hilo_mult), 135 | .done (mult_done) 136 | ); 137 | 138 | // Regular operation. 139 | always_comb begin : alu_operation 140 | unique case(alu_op) 141 | `ALU_ADD, `ALU_ADDU: 142 | result = add_result; 143 | `ALU_SUB, `ALU_SUBU: 144 | result = sub_result; 145 | `ALU_SLT: 146 | result = $signed(src_a) < $signed(src_b) ? 32'd1 : 32'd0; 147 | `ALU_SLTU: 148 | result = src_a < src_b? 32'd1 : 32'd0; 149 | `ALU_AND: 150 | result = src_a & src_b; 151 | `ALU_LUI: 152 | result = { src_b[15:0], 16'h0000 }; 153 | `ALU_NOR: 154 | result = ~(src_a | src_b); 155 | `ALU_OR: 156 | result = src_a | src_b; 157 | `ALU_XOR: 158 | result = src_a ^ src_b; 159 | `ALU_SLL: 160 | result = src_b << src_a[4:0]; 161 | `ALU_SRA: 162 | result = $signed(src_b) >>> src_a[4:0]; 163 | `ALU_SRL: 164 | result = src_b >> src_a[4:0]; 165 | `ALU_MFHI: 166 | result = hi; 167 | `ALU_MFLO: 168 | result = lo; 169 | `ALU_OUTA, `ALU_MOVN, `ALU_MOVZ: 170 | result = src_a; 171 | `ALU_OUTB: 172 | result = src_b; 173 | `ALU_MFC0: 174 | result = cop0_data; 175 | `ALU_MTC0: 176 | result = cop0_addr; 177 | `ALU_CLO: 178 | result = {26'd0,clo_result}; 179 | `ALU_CLZ: 180 | result = {26'd0,clz_result}; 181 | `ALU_MUL: 182 | result = _hilo_mult[31:0]; 183 | default: 184 | result = 32'h0000_0000; // Prevent dcache error 185 | endcase 186 | end 187 | 188 | always_comb begin : set_reg_en 189 | unique case(alu_op) 190 | `ALU_MOVN: 191 | ex_reg_en = (src_b != 32'd0); 192 | `ALU_MOVZ: 193 | ex_reg_en = (src_b == 32'd0); 194 | default: 195 | ex_reg_en = 1'd1; 196 | endcase 197 | end 198 | 199 | always_comb begin : set_overflow 200 | unique case (alu_op) 201 | `ALU_ADD: 202 | exp_overflow = ((src_a[31] ~^ src_b[31]) & (src_a[31] ^ add_result[31])); 203 | `ALU_SUB: 204 | exp_overflow = ((src_a[31] ^ src_b[31]) & (src_a[31] ^ sub_result[31])); 205 | default: 206 | exp_overflow = 1'b0; 207 | endcase 208 | end 209 | 210 | // HiLo read/write 211 | always_comb begin : hilo_read_write 212 | hilo_wen = 1'd1; 213 | hilo_result = 64'd0; 214 | if(div_commit) 215 | hilo_result = _hilo_div; 216 | else if(mult_commit) begin 217 | unique case(alu_op) 218 | `ALU_MSUB, `ALU_MSUBU: 219 | hilo_result = src_hilo - _hilo_mult; 220 | `ALU_MADD, `ALU_MADDU: 221 | hilo_result = _hilo_mult + src_hilo; 222 | default: 223 | hilo_result = _hilo_mult; 224 | endcase 225 | end 226 | else begin 227 | unique case(alu_op) 228 | `ALU_MTHI: 229 | hilo_result = { src_a, lo }; 230 | `ALU_MTLO: 231 | hilo_result = { hi, src_a }; 232 | default: 233 | hilo_wen = 1'd0; 234 | endcase 235 | end 236 | end 237 | 238 | always_comb begin 239 | casex (src_a) 240 | 32'b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 241 | clo_result <= 6'd0; 242 | 32'b10xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 243 | clo_result <= 6'd1; 244 | 32'b110xxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 245 | clo_result <= 6'd2; 246 | 32'b1110xxxxxxxxxxxxxxxxxxxxxxxxxxxx: 247 | clo_result <= 6'd3; 248 | 32'b11110xxxxxxxxxxxxxxxxxxxxxxxxxxx: 249 | clo_result <= 6'd4; 250 | 32'b111110xxxxxxxxxxxxxxxxxxxxxxxxxx: 251 | clo_result <= 6'd5; 252 | 32'b1111110xxxxxxxxxxxxxxxxxxxxxxxxx: 253 | clo_result <= 6'd6; 254 | 32'b11111110xxxxxxxxxxxxxxxxxxxxxxxx: 255 | clo_result <= 6'd7; 256 | 32'b111111110xxxxxxxxxxxxxxxxxxxxxxx: 257 | clo_result <= 6'd8; 258 | 32'b1111111110xxxxxxxxxxxxxxxxxxxxxx: 259 | clo_result <= 6'd9; 260 | 32'b11111111110xxxxxxxxxxxxxxxxxxxxx: 261 | clo_result <= 6'd10; 262 | 32'b111111111110xxxxxxxxxxxxxxxxxxxx: 263 | clo_result <= 6'd11; 264 | 32'b1111111111110xxxxxxxxxxxxxxxxxxx: 265 | clo_result <= 6'd12; 266 | 32'b11111111111110xxxxxxxxxxxxxxxxxx: 267 | clo_result <= 6'd13; 268 | 32'b111111111111110xxxxxxxxxxxxxxxxx: 269 | clo_result <= 6'd14; 270 | 32'b1111111111111110xxxxxxxxxxxxxxxx: 271 | clo_result <= 6'd15; 272 | 32'b11111111111111110xxxxxxxxxxxxxxx: 273 | clo_result <= 6'd16; 274 | 32'b111111111111111110xxxxxxxxxxxxxx: 275 | clo_result <= 6'd17; 276 | 32'b1111111111111111110xxxxxxxxxxxxx: 277 | clo_result <= 6'd18; 278 | 32'b11111111111111111110xxxxxxxxxxxx: 279 | clo_result <= 6'd19; 280 | 32'b111111111111111111110xxxxxxxxxxx: 281 | clo_result <= 6'd20; 282 | 32'b1111111111111111111110xxxxxxxxxx: 283 | clo_result <= 6'd21; 284 | 32'b11111111111111111111110xxxxxxxxx: 285 | clo_result <= 6'd22; 286 | 32'b111111111111111111111110xxxxxxxx: 287 | clo_result <= 6'd23; 288 | 32'b1111111111111111111111110xxxxxxx: 289 | clo_result <= 6'd24; 290 | 32'b11111111111111111111111110xxxxxx: 291 | clo_result <= 6'd25; 292 | 32'b111111111111111111111111110xxxxx: 293 | clo_result <= 6'd26; 294 | 32'b1111111111111111111111111110xxxx: 295 | clo_result <= 6'd27; 296 | 32'b11111111111111111111111111110xxx: 297 | clo_result <= 6'd28; 298 | 32'b111111111111111111111111111110xx: 299 | clo_result <= 6'd29; 300 | 32'b1111111111111111111111111111110x: 301 | clo_result <= 6'd30; 302 | 32'b11111111111111111111111111111110: 303 | clo_result <= 6'd31; 304 | 32'b11111111111111111111111111111111: 305 | clo_result <= 6'd32; 306 | default: 307 | clo_result <= 6'd0; 308 | endcase 309 | end 310 | 311 | always_comb begin 312 | casex (src_a) 313 | 32'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 314 | clz_result <= 6'd0; 315 | 32'b01xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 316 | clz_result <= 6'd1; 317 | 32'b001xxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 318 | clz_result <= 6'd2; 319 | 32'b0001xxxxxxxxxxxxxxxxxxxxxxxxxxxx: 320 | clz_result <= 6'd3; 321 | 32'b00001xxxxxxxxxxxxxxxxxxxxxxxxxxx: 322 | clz_result <= 6'd4; 323 | 32'b000001xxxxxxxxxxxxxxxxxxxxxxxxxx: 324 | clz_result <= 6'd5; 325 | 32'b0000001xxxxxxxxxxxxxxxxxxxxxxxxx: 326 | clz_result <= 6'd6; 327 | 32'b00000001xxxxxxxxxxxxxxxxxxxxxxxx: 328 | clz_result <= 6'd7; 329 | 32'b000000001xxxxxxxxxxxxxxxxxxxxxxx: 330 | clz_result <= 6'd8; 331 | 32'b0000000001xxxxxxxxxxxxxxxxxxxxxx: 332 | clz_result <= 6'd9; 333 | 32'b00000000001xxxxxxxxxxxxxxxxxxxxx: 334 | clz_result <= 6'd10; 335 | 32'b000000000001xxxxxxxxxxxxxxxxxxxx: 336 | clz_result <= 6'd11; 337 | 32'b0000000000001xxxxxxxxxxxxxxxxxxx: 338 | clz_result <= 6'd12; 339 | 32'b00000000000001xxxxxxxxxxxxxxxxxx: 340 | clz_result <= 6'd13; 341 | 32'b000000000000001xxxxxxxxxxxxxxxxx: 342 | clz_result <= 6'd14; 343 | 32'b0000000000000001xxxxxxxxxxxxxxxx: 344 | clz_result <= 6'd15; 345 | 32'b00000000000000001xxxxxxxxxxxxxxx: 346 | clz_result <= 6'd16; 347 | 32'b000000000000000001xxxxxxxxxxxxxx: 348 | clz_result <= 6'd17; 349 | 32'b0000000000000000001xxxxxxxxxxxxx: 350 | clz_result <= 6'd18; 351 | 32'b00000000000000000001xxxxxxxxxxxx: 352 | clz_result <= 6'd19; 353 | 32'b000000000000000000001xxxxxxxxxxx: 354 | clz_result <= 6'd20; 355 | 32'b0000000000000000000001xxxxxxxxxx: 356 | clz_result <= 6'd21; 357 | 32'b00000000000000000000001xxxxxxxxx: 358 | clz_result <= 6'd22; 359 | 32'b000000000000000000000001xxxxxxxx: 360 | clz_result <= 6'd23; 361 | 32'b0000000000000000000000001xxxxxxx: 362 | clz_result <= 6'd24; 363 | 32'b00000000000000000000000001xxxxxx: 364 | clz_result <= 6'd25; 365 | 32'b000000000000000000000000001xxxxx: 366 | clz_result <= 6'd26; 367 | 32'b0000000000000000000000000001xxxx: 368 | clz_result <= 6'd27; 369 | 32'b00000000000000000000000000001xxx: 370 | clz_result <= 6'd28; 371 | 32'b000000000000000000000000000001xx: 372 | clz_result <= 6'd29; 373 | 32'b0000000000000000000000000000001x: 374 | clz_result <= 6'd30; 375 | 32'b00000000000000000000000000000001: 376 | clz_result <= 6'd31; 377 | 32'b00000000000000000000000000000000: 378 | clz_result <= 6'd32; 379 | default: 380 | clz_result <= 6'd0; 381 | endcase 382 | end 383 | endmodule 384 | -------------------------------------------------------------------------------- /hdl/exu/alu_beta.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "alu_op.vh" 3 | // Slave ALU, thie ALU doesn't handle HILO operations and 4 | // priv instructions. 5 | module alu_beta( 6 | input clk, 7 | input rst, 8 | 9 | input [5:0] alu_op, 10 | input [31:0] src_a, 11 | input [31:0] src_b, 12 | 13 | output logic ex_reg_en, 14 | output logic exp_overflow, 15 | output logic [31:0] result 16 | ); 17 | 18 | wire [31:0] add_result = src_a + src_b; 19 | wire [31:0] sub_result = src_a - src_b; 20 | logic [5:0] clo_result, clz_result; 21 | 22 | // Regular operation. 23 | always_comb begin : alu_operation 24 | unique case(alu_op) 25 | `ALU_ADD, `ALU_ADDU: 26 | result = add_result; 27 | `ALU_SUB, `ALU_SUBU: 28 | result = sub_result; 29 | `ALU_SLT: 30 | result = $signed(src_a) < $signed(src_b) ? 32'd1 : 32'd0; 31 | `ALU_SLTU: 32 | result = src_a < src_b? 32'd1 : 32'd0; 33 | `ALU_AND: 34 | result = src_a & src_b; 35 | `ALU_LUI: 36 | result = { src_b[15:0], 16'h0000 }; 37 | `ALU_NOR: 38 | result = ~(src_a | src_b); 39 | `ALU_OR: 40 | result = src_a | src_b; 41 | `ALU_XOR: 42 | result = src_a ^ src_b; 43 | `ALU_SLL: 44 | result = src_b << src_a[4:0]; 45 | `ALU_SRA: 46 | result = $signed(src_b) >>> src_a[4:0]; 47 | `ALU_SRL: 48 | result = src_b >> src_a[4:0]; 49 | `ALU_OUTA, `ALU_MOVN, `ALU_MOVZ: 50 | result = src_a; 51 | `ALU_OUTB: 52 | result = src_b; 53 | `ALU_CLO: 54 | result = {26'd0,clo_result}; 55 | `ALU_CLZ: 56 | result = {26'd0,clz_result}; 57 | default: 58 | result = 32'h0000_0000; 59 | endcase 60 | end 61 | 62 | always_comb begin : set_reg_en 63 | unique case(alu_op) 64 | `ALU_MOVN: 65 | ex_reg_en = (src_b != 32'd0); 66 | `ALU_MOVZ: 67 | ex_reg_en = (src_b == 32'd0); 68 | default: 69 | ex_reg_en = 1'd1; 70 | endcase 71 | end 72 | 73 | always_comb begin : set_overflow 74 | unique case (alu_op) 75 | `ALU_ADD: 76 | exp_overflow = ((src_a[31] ~^ src_b[31]) & (src_a[31] ^ add_result[31])); 77 | `ALU_SUB: 78 | exp_overflow = ((src_a[31] ^ src_b[31]) & (src_a[31] ^ sub_result[31])); 79 | default: 80 | exp_overflow = 1'b0; 81 | endcase 82 | end 83 | 84 | always_comb begin 85 | casex (src_a) 86 | 32'b0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 87 | clo_result <= 6'd0; 88 | 32'b10xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 89 | clo_result <= 6'd1; 90 | 32'b110xxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 91 | clo_result <= 6'd2; 92 | 32'b1110xxxxxxxxxxxxxxxxxxxxxxxxxxxx: 93 | clo_result <= 6'd3; 94 | 32'b11110xxxxxxxxxxxxxxxxxxxxxxxxxxx: 95 | clo_result <= 6'd4; 96 | 32'b111110xxxxxxxxxxxxxxxxxxxxxxxxxx: 97 | clo_result <= 6'd5; 98 | 32'b1111110xxxxxxxxxxxxxxxxxxxxxxxxx: 99 | clo_result <= 6'd6; 100 | 32'b11111110xxxxxxxxxxxxxxxxxxxxxxxx: 101 | clo_result <= 6'd7; 102 | 32'b111111110xxxxxxxxxxxxxxxxxxxxxxx: 103 | clo_result <= 6'd8; 104 | 32'b1111111110xxxxxxxxxxxxxxxxxxxxxx: 105 | clo_result <= 6'd9; 106 | 32'b11111111110xxxxxxxxxxxxxxxxxxxxx: 107 | clo_result <= 6'd10; 108 | 32'b111111111110xxxxxxxxxxxxxxxxxxxx: 109 | clo_result <= 6'd11; 110 | 32'b1111111111110xxxxxxxxxxxxxxxxxxx: 111 | clo_result <= 6'd12; 112 | 32'b11111111111110xxxxxxxxxxxxxxxxxx: 113 | clo_result <= 6'd13; 114 | 32'b111111111111110xxxxxxxxxxxxxxxxx: 115 | clo_result <= 6'd14; 116 | 32'b1111111111111110xxxxxxxxxxxxxxxx: 117 | clo_result <= 6'd15; 118 | 32'b11111111111111110xxxxxxxxxxxxxxx: 119 | clo_result <= 6'd16; 120 | 32'b111111111111111110xxxxxxxxxxxxxx: 121 | clo_result <= 6'd17; 122 | 32'b1111111111111111110xxxxxxxxxxxxx: 123 | clo_result <= 6'd18; 124 | 32'b11111111111111111110xxxxxxxxxxxx: 125 | clo_result <= 6'd19; 126 | 32'b111111111111111111110xxxxxxxxxxx: 127 | clo_result <= 6'd20; 128 | 32'b1111111111111111111110xxxxxxxxxx: 129 | clo_result <= 6'd21; 130 | 32'b11111111111111111111110xxxxxxxxx: 131 | clo_result <= 6'd22; 132 | 32'b111111111111111111111110xxxxxxxx: 133 | clo_result <= 6'd23; 134 | 32'b1111111111111111111111110xxxxxxx: 135 | clo_result <= 6'd24; 136 | 32'b11111111111111111111111110xxxxxx: 137 | clo_result <= 6'd25; 138 | 32'b111111111111111111111111110xxxxx: 139 | clo_result <= 6'd26; 140 | 32'b1111111111111111111111111110xxxx: 141 | clo_result <= 6'd27; 142 | 32'b11111111111111111111111111110xxx: 143 | clo_result <= 6'd28; 144 | 32'b111111111111111111111111111110xx: 145 | clo_result <= 6'd29; 146 | 32'b1111111111111111111111111111110x: 147 | clo_result <= 6'd30; 148 | 32'b11111111111111111111111111111110: 149 | clo_result <= 6'd31; 150 | 32'b11111111111111111111111111111111: 151 | clo_result <= 6'd32; 152 | default: 153 | clo_result <= 6'd0; 154 | endcase 155 | end 156 | 157 | always_comb begin 158 | casex (src_a) 159 | 32'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 160 | clz_result <= 6'd0; 161 | 32'b01xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 162 | clz_result <= 6'd1; 163 | 32'b001xxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 164 | clz_result <= 6'd2; 165 | 32'b0001xxxxxxxxxxxxxxxxxxxxxxxxxxxx: 166 | clz_result <= 6'd3; 167 | 32'b00001xxxxxxxxxxxxxxxxxxxxxxxxxxx: 168 | clz_result <= 6'd4; 169 | 32'b000001xxxxxxxxxxxxxxxxxxxxxxxxxx: 170 | clz_result <= 6'd5; 171 | 32'b0000001xxxxxxxxxxxxxxxxxxxxxxxxx: 172 | clz_result <= 6'd6; 173 | 32'b00000001xxxxxxxxxxxxxxxxxxxxxxxx: 174 | clz_result <= 6'd7; 175 | 32'b000000001xxxxxxxxxxxxxxxxxxxxxxx: 176 | clz_result <= 6'd8; 177 | 32'b0000000001xxxxxxxxxxxxxxxxxxxxxx: 178 | clz_result <= 6'd9; 179 | 32'b00000000001xxxxxxxxxxxxxxxxxxxxx: 180 | clz_result <= 6'd10; 181 | 32'b000000000001xxxxxxxxxxxxxxxxxxxx: 182 | clz_result <= 6'd11; 183 | 32'b0000000000001xxxxxxxxxxxxxxxxxxx: 184 | clz_result <= 6'd12; 185 | 32'b00000000000001xxxxxxxxxxxxxxxxxx: 186 | clz_result <= 6'd13; 187 | 32'b000000000000001xxxxxxxxxxxxxxxxx: 188 | clz_result <= 6'd14; 189 | 32'b0000000000000001xxxxxxxxxxxxxxxx: 190 | clz_result <= 6'd15; 191 | 32'b00000000000000001xxxxxxxxxxxxxxx: 192 | clz_result <= 6'd16; 193 | 32'b000000000000000001xxxxxxxxxxxxxx: 194 | clz_result <= 6'd17; 195 | 32'b0000000000000000001xxxxxxxxxxxxx: 196 | clz_result <= 6'd18; 197 | 32'b00000000000000000001xxxxxxxxxxxx: 198 | clz_result <= 6'd19; 199 | 32'b000000000000000000001xxxxxxxxxxx: 200 | clz_result <= 6'd20; 201 | 32'b0000000000000000000001xxxxxxxxxx: 202 | clz_result <= 6'd21; 203 | 32'b00000000000000000000001xxxxxxxxx: 204 | clz_result <= 6'd22; 205 | 32'b000000000000000000000001xxxxxxxx: 206 | clz_result <= 6'd23; 207 | 32'b0000000000000000000000001xxxxxxx: 208 | clz_result <= 6'd24; 209 | 32'b00000000000000000000000001xxxxxx: 210 | clz_result <= 6'd25; 211 | 32'b000000000000000000000000001xxxxx: 212 | clz_result <= 6'd26; 213 | 32'b0000000000000000000000000001xxxx: 214 | clz_result <= 6'd27; 215 | 32'b00000000000000000000000000001xxx: 216 | clz_result <= 6'd28; 217 | 32'b000000000000000000000000000001xx: 218 | clz_result <= 6'd29; 219 | 32'b0000000000000000000000000000001x: 220 | clz_result <= 6'd30; 221 | 32'b00000000000000000000000000000001: 222 | clz_result <= 6'd31; 223 | 32'b00000000000000000000000000000000: 224 | clz_result <= 6'd32; 225 | default: 226 | clz_result <= 6'd0; 227 | endcase 228 | end 229 | endmodule 230 | -------------------------------------------------------------------------------- /hdl/exu/alu_op.vh: -------------------------------------------------------------------------------- 1 | `define ALU_ADD 6'd0 2 | `define ALU_ADDU 6'd1 3 | `define ALU_SUB 6'd2 4 | `define ALU_SUBU 6'd3 5 | `define ALU_SLT 6'd4 6 | `define ALU_SLTU 6'd5 7 | `define ALU_DIV 6'd6 8 | `define ALU_DIVU 6'd7 9 | `define ALU_MULT 6'd8 10 | `define ALU_MULTU 6'd9 11 | `define ALU_AND 6'd10 12 | `define ALU_LUI 6'd11 13 | `define ALU_NOR 6'd12 14 | `define ALU_OR 6'd13 15 | `define ALU_XOR 6'd14 16 | `define ALU_SLL 6'd15 17 | `define ALU_SRA 6'd16 18 | `define ALU_SRL 6'd17 19 | `define ALU_MFHI 6'd18 20 | `define ALU_MFLO 6'd19 21 | `define ALU_MTHI 6'd20 22 | `define ALU_MTLO 6'd21 23 | // FAKE ALU OP 24 | `define ALU_OUTA 6'd22 25 | `define ALU_OUTB 6'd23 26 | // C0 27 | `define ALU_MFC0 6'd24 28 | `define ALU_MTC0 6'd25 29 | `define ALU_ERET 6'd26 30 | `define ALU_SYSC 6'd27 31 | `define ALU_BREK 6'd28 32 | 33 | // MIPS32r2 34 | `define ALU_MUL 6'd29 35 | `define ALU_CLO 6'd30 36 | `define ALU_CLZ 6'd31 37 | `define ALU_MADD 6'd32 38 | `define ALU_MADDU 6'd33 39 | `define ALU_MSUB 6'd34 40 | `define ALU_MSUBU 6'd35 41 | `define ALU_MOVN 6'd36 42 | `define ALU_MOVZ 6'd37 43 | `define ALU_TLBWI 6'd38 44 | `define ALU_TLBWR 6'd39 45 | `define ALU_TLBR 6'd40 46 | `define ALU_TLBP 6'd41 -------------------------------------------------------------------------------- /hdl/exu/branch.sv: -------------------------------------------------------------------------------- 1 | `include "common.vh" 2 | // Branch unit in ex stage. 3 | module branch( 4 | input en, 5 | input [31:0] pc_address, 6 | input [31:0] instruction, 7 | input is_branch_instr, 8 | input [2:0] branch_type, 9 | 10 | input [31:0] data_rs, 11 | input [31:0] data_rt, 12 | 13 | output logic branch_taken, 14 | output logic [31:0] branch_address 15 | ); 16 | 17 | reg [31:0] next_pc; 18 | reg [31:0] branch_immed; 19 | 20 | always_comb begin : get_target 21 | next_pc = pc_address + 32'd4; 22 | branch_immed = pc_address + 32'd4 + {{14{instruction[15]}}, instruction[15:0], 2'b00}; 23 | end 24 | 25 | always_comb begin : take_branch 26 | if(!en) begin 27 | branch_taken = 1'b0; 28 | branch_address = 32'hxxxxxxxx; 29 | end else if(is_branch_instr) begin 30 | unique case(branch_type) 31 | `B_EQNE: 32 | unique case(instruction[27:26]) 33 | 2'b00: // BEQ 34 | if(data_rs == data_rt) begin 35 | branch_address = branch_immed; 36 | branch_taken = 1'b1; 37 | end 38 | else begin 39 | branch_address = 32'hxxxxxxxx; 40 | branch_taken = 1'b0; 41 | end 42 | 2'b01: // BNE 43 | if(data_rs != data_rt) begin 44 | branch_address = branch_immed; 45 | branch_taken = 1'b1; 46 | end 47 | else begin 48 | branch_address = 32'hxxxxxxxx; 49 | branch_taken = 1'b0; 50 | end 51 | 2'b10: // BLEZ 52 | if(data_rs[31] || data_rs==32'b0) begin 53 | branch_address = branch_immed; 54 | branch_taken = 1'b1; 55 | end 56 | else begin 57 | branch_address = 32'hxxxxxxxx; 58 | branch_taken = 1'b0; 59 | end 60 | 2'b11: // BGTZ 61 | if(data_rs[31] == 0 && data_rs) begin 62 | branch_address = branch_immed; 63 | branch_taken = 1'b1; 64 | end 65 | else begin 66 | branch_address = 32'hxxxxxxxx; 67 | branch_taken = 1'b0; 68 | end 69 | default: // Make compiler happy 70 | begin 71 | branch_address = 32'hxxxxxxxx; 72 | branch_taken = 1'b0; 73 | end 74 | endcase 75 | `B_LTGE: 76 | unique case(instruction[16]) 77 | 1'b0: // BLTZ 78 | if(data_rs[31] && data_rs) begin 79 | branch_address = branch_immed; 80 | branch_taken = 1'b1; 81 | end 82 | else begin 83 | branch_address = 32'hxxxxxxxx; 84 | branch_taken = 1'b0; 85 | end 86 | 1'b1: // BGEZ 87 | if(data_rs[31] == 0 || data_rs==32'b0) begin 88 | branch_address = branch_immed; 89 | branch_taken = 1'b1; 90 | end 91 | else begin 92 | branch_address = 32'hxxxxxxxx; 93 | branch_taken = 1'b0; 94 | end 95 | default: // Make compiler happy 96 | begin 97 | branch_address = 32'hxxxxxxxx; 98 | branch_taken = 1'b0; 99 | end 100 | endcase 101 | `B_JUMP: begin 102 | branch_address = {next_pc[31:28], instruction[25:0], 2'b00}; 103 | branch_taken = 1'b1; 104 | end 105 | `B_JREG: begin 106 | branch_address = data_rs; 107 | branch_taken = 1'b1; 108 | end 109 | default: begin 110 | branch_address = 32'hxxxxxxxx; 111 | branch_taken = 1'b0; 112 | end 113 | endcase 114 | end 115 | else begin 116 | branch_address = 32'hxxxxxxxx; 117 | branch_taken = 1'b0; 118 | end 119 | end 120 | 121 | endmodule 122 | -------------------------------------------------------------------------------- /hdl/exu/divider.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | // A simple divider module. 3 | // Takes 34 cycles to get result. 4 | // DIVIDEND \div DIVISOR = QOUTIENT ...... REMAINDER 5 | module divider( 6 | input clk, 7 | input rst, 8 | 9 | input [ 1:0] div_op, 10 | input [31:0] divisor, 11 | input [31:0] dividend, 12 | 13 | output [63:0] result, 14 | output done 15 | ); 16 | logic [5:0] counter; 17 | logic [31:0] _divisor, _dividend; 18 | logic sign; 19 | logic dividend_sign; 20 | 21 | reg [63:0] _result; 22 | 23 | wire [31:0] quotient = sign? (~_result[63:32] + 32'd1) : _result[63:32]; 24 | wire [31:0] remainder = dividend_sign? (~_result[31:0] + 32'd1) : _result[31:0]; 25 | 26 | assign done = counter == 6'd0; 27 | assign result = { remainder, quotient }; 28 | 29 | always_ff @(posedge clk) begin : get_operands 30 | if(rst) begin 31 | counter <= 6'd0; 32 | _divisor <= 32'd0; 33 | _dividend <= 32'd0; 34 | sign <= 1'b0; 35 | end 36 | else begin 37 | if(!done) 38 | counter <= counter - 1; 39 | else begin 40 | if(div_op == 2'b10) begin 41 | sign <= divisor[31] ^ dividend[31]; 42 | _divisor <= divisor[31]? ~divisor + 1 : divisor; 43 | _dividend <= dividend[31]? ~dividend + 1 : dividend; 44 | dividend_sign <= dividend[31]; 45 | counter <= 6'd34; 46 | end 47 | else if(div_op == 2'b01) begin 48 | sign <= 1'b0; 49 | _divisor <= divisor; 50 | _dividend <= dividend; 51 | dividend_sign <= 1'b0; 52 | counter <= 6'd34; 53 | end 54 | else begin 55 | end 56 | end 57 | end 58 | end 59 | 60 | div_gen_0 div( 61 | .aclk (clk), 62 | .s_axis_divisor_tdata (_divisor), 63 | .s_axis_divisor_tvalid (1'd1), 64 | .s_axis_dividend_tdata (_dividend), 65 | .s_axis_dividend_tvalid (1'd1), 66 | .m_axis_dout_tdata (_result) 67 | ); 68 | 69 | endmodule 70 | -------------------------------------------------------------------------------- /hdl/exu/multplier.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | // A four-stage pipeline multiplier. 3 | // However, pipeline feature is disabled in 4 | // our design. 5 | // OP: 10 as signed operation 6 | // 01 as unsigned operation 7 | // 00 as invalid. 8 | module multplier( 9 | input clk, 10 | input rst, 11 | 12 | input [ 1:0] op, 13 | input [31:0] a, 14 | input [31:0] b, 15 | output logic [63:0] c, 16 | output logic done 17 | ); 18 | 19 | reg [31:0] _a, _b; 20 | reg [63:0] _c; 21 | reg sign; 22 | reg [2:0] counter; 23 | 24 | assign c = sign? -_c : _c; 25 | assign done = counter == 3'b000; 26 | 27 | // Unsigned multplier IP core from xilinx, configured with pipeline stages as 4. 28 | mult_gen_0 mult( 29 | .CLK (clk), 30 | .SCLR (rst), 31 | .A (_a), 32 | .B (_b), 33 | .P (_c) 34 | ); 35 | 36 | always_ff @(posedge clk) begin 37 | if(rst) begin 38 | _a <= 32'd0; 39 | _b <= 32'd0; 40 | counter <= 3'd0; 41 | sign <= 1'b0; 42 | end 43 | else begin 44 | if(!done) begin 45 | counter <= counter - 1; 46 | end 47 | else if(op == 2'b01) begin 48 | sign <= 0; 49 | _a <= a; 50 | _b <= b; 51 | counter <= 3'd4; 52 | end 53 | else if(op == 2'b10) begin 54 | sign <= a[31] ^ b[31]; 55 | _a <= a[31]? ~a + 1 : a; 56 | _b <= b[31]? ~b + 1 : b; 57 | counter <= 3'd4; 58 | end 59 | else begin 60 | end 61 | end 62 | end 63 | 64 | endmodule 65 | -------------------------------------------------------------------------------- /hdl/ifu/instruction_fifo.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module instruction_fifo( 4 | input clk, 5 | input debug_rst, 6 | input rst, 7 | input rst_with_delay, 8 | input master_is_branch, 9 | 10 | // Read inputs 11 | input read_en1, 12 | input read_en2, 13 | 14 | // Write inputs 15 | input write_en1, 16 | input write_en2, 17 | input [31:0] write_data1, 18 | input [11:0] write_inst_exp1, 19 | input [31:0] write_address1, 20 | input [31:0] write_data2, 21 | input [31:0] write_address2, 22 | 23 | // Read outputs 24 | output logic [31:0] data_out1, 25 | output logic [31:0] data_out2, 26 | output logic [31:0] address_out1, 27 | output logic [31:0] address_out2, 28 | output logic [11:0] inst_exp1, 29 | output logic [11:0] inst_exp2, 30 | output logic delay_slot_out1, 31 | output logic empty, 32 | output logic almost_empty, 33 | output logic full 34 | ); 35 | 36 | // Reset status 37 | reg in_delay_slot; 38 | reg in_delay_slot_without_rst; 39 | reg [11:0] delayed_inst_exp; 40 | reg [31:0] delayed_data; 41 | reg [31:0] delayed_pc; 42 | // Store data here 43 | reg [31:0] data[0:15]; 44 | reg [31:0] address[0:15]; 45 | reg [11:0] inst_exp[0:15]; 46 | 47 | // Internal variables 48 | reg [3:0] write_pointer; 49 | reg [3:0] read_pointer; 50 | reg [3:0] data_count; 51 | 52 | // Status monitor 53 | assign full = &data_count[3:1]; 54 | assign empty = (data_count == 4'd0); 55 | assign almost_empty = (data_count == 4'd1); 56 | 57 | // Output data 58 | wire [31:0] _data_out1 = data[read_pointer]; 59 | wire [31:0] _data_out2 = data[read_pointer + 4'd1]; 60 | wire [31:0] _address_out1 = address[read_pointer]; 61 | wire [31:0] _address_out2 = address[read_pointer + 4'd1]; 62 | wire [11:0] _inst_exp1 = inst_exp[read_pointer]; 63 | wire [11:0] _inst_exp2 = inst_exp[read_pointer + 4'd1]; 64 | 65 | // Delay slot data FSM 66 | reg delay_slot_refill; 67 | 68 | logic [63:0] rst_with_delay_counter; 69 | always_ff @(posedge clk) begin 70 | if(rst) 71 | rst_with_delay_counter <= 64'd0; 72 | else if(rst_with_delay) 73 | rst_with_delay_counter <= rst_with_delay_counter + 64'd1; 74 | end 75 | 76 | always_ff @(posedge clk) begin 77 | if(rst && rst_with_delay && !write_en1 && 78 | (read_pointer + 4'd1 == write_pointer || read_pointer == write_pointer)) begin 79 | delay_slot_refill <= 1'd1; 80 | end 81 | else if(delay_slot_refill && write_en1) 82 | delay_slot_refill <= 1'd0; 83 | else if(delay_slot_refill) 84 | delay_slot_refill <= delay_slot_refill; 85 | else 86 | delay_slot_refill <= 1'd0; 87 | end 88 | 89 | always_comb begin : select_output 90 | if(in_delay_slot) begin 91 | data_out1 = delayed_data; 92 | data_out2 = 32'd0; 93 | address_out1 = delayed_pc; 94 | address_out2 = 32'd0; 95 | inst_exp1 = delayed_inst_exp; 96 | inst_exp2 = 12'd0; 97 | delay_slot_out1 = 1'd1; 98 | end 99 | else if(empty) begin 100 | data_out1 = 32'd0; 101 | data_out2 = 32'd0; 102 | address_out1 = 32'd0; 103 | address_out2 = 32'd0; 104 | inst_exp1 = 12'd0; 105 | inst_exp2 = 12'd0; 106 | delay_slot_out1 = 1'd0; 107 | end 108 | else if(almost_empty) begin 109 | data_out1 = _data_out1; 110 | data_out2 = 32'd0; 111 | address_out1 = _address_out1; 112 | address_out2 = 32'd0; 113 | inst_exp1 = _inst_exp1; 114 | inst_exp2 = 12'd0; 115 | delay_slot_out1 = in_delay_slot_without_rst; 116 | end 117 | else begin 118 | data_out1 = _data_out1; 119 | data_out2 = _data_out2; 120 | address_out1 = _address_out1; 121 | address_out2 = _address_out2; 122 | inst_exp1 = _inst_exp1; 123 | inst_exp2 = _inst_exp2; 124 | delay_slot_out1 = in_delay_slot_without_rst; 125 | end 126 | end 127 | 128 | always_ff @(posedge clk) begin : update_in_delay_slot_without_rst 129 | if(rst) 130 | in_delay_slot_without_rst <= 1'd0; 131 | else if(master_is_branch && read_en1) begin 132 | in_delay_slot_without_rst <= 1'd1; 133 | end 134 | else if(read_en1) 135 | in_delay_slot_without_rst <= 1'd0; 136 | end 137 | 138 | always_ff @(posedge clk) begin : update_delayed 139 | if(rst && rst_with_delay) begin 140 | in_delay_slot <= 1'd1; 141 | delayed_data <= (read_pointer + 4'd1 == write_pointer || read_pointer == write_pointer)? write_data1 : data[read_pointer + 4'd1]; 142 | delayed_pc <= (read_pointer + 4'd1 == write_pointer || read_pointer == write_pointer)? write_address1 : address[read_pointer + 4'd1]; 143 | delayed_inst_exp<= (read_pointer + 4'd1 == write_pointer || read_pointer == write_pointer)? write_inst_exp1 : inst_exp[read_pointer + 4'd1]; 144 | end 145 | else if(delay_slot_refill && write_en1) begin 146 | delayed_data <= write_data1; 147 | delayed_inst_exp<= write_inst_exp1; 148 | end 149 | else if(!delay_slot_refill && read_en1) begin 150 | in_delay_slot <= 1'd0; 151 | delayed_data <= 32'd0; 152 | delayed_pc <= 32'd0; 153 | delayed_inst_exp<= 12'd0; 154 | end 155 | end 156 | 157 | always_ff @(posedge clk) begin : update_write_pointer 158 | if(rst) 159 | write_pointer <= 4'd0; 160 | else if(write_en1 && write_en2) 161 | write_pointer <= write_pointer + 4'd2; 162 | else if(write_en1) 163 | write_pointer <= write_pointer + 4'd1; 164 | end 165 | 166 | always_ff @(posedge clk) begin : update_read_pointer 167 | if(rst) 168 | read_pointer <= 4'd0; 169 | else if(empty) 170 | read_pointer <= read_pointer; 171 | else if(read_en1 && read_en2) 172 | read_pointer <= read_pointer + 4'd2; 173 | else if(read_en1) 174 | read_pointer <= read_pointer + 4'd1; 175 | end 176 | 177 | always_ff @(posedge clk) begin : update_counter 178 | if(rst) 179 | data_count <= 4'd0; 180 | else if(empty) begin 181 | case({write_en1, write_en2}) 182 | 2'b10: begin 183 | data_count <= data_count + 4'd1; 184 | end 185 | 2'b11: begin 186 | data_count <= data_count + 4'd2; 187 | end 188 | default: 189 | data_count <= data_count; 190 | endcase 191 | end 192 | else begin 193 | case({write_en1, write_en2, read_en1, read_en2}) 194 | 4'b1100: begin 195 | data_count <= data_count + 4'd2; 196 | end 197 | 4'b1110, 4'b1000: begin 198 | data_count <= data_count + 4'd1; 199 | end 200 | 4'b1011, 4'b0010: begin 201 | data_count <= data_count - 4'd1; 202 | end 203 | 4'b0011: begin 204 | data_count <= data_count == 4'd1 ? 4'd0 : data_count - 4'd2; 205 | end 206 | default: 207 | data_count <= data_count; 208 | endcase 209 | end 210 | end 211 | 212 | always_ff @(posedge clk) begin : write_data 213 | if(write_en1) begin 214 | data[write_pointer] <= write_data1; 215 | address[write_pointer] <= write_address1; 216 | inst_exp[write_pointer] <= write_inst_exp1; 217 | end 218 | if(write_en2) begin 219 | data[write_pointer + 4'd1] <= write_data2; 220 | address[write_pointer + 4'd1] <= write_address2; 221 | inst_exp[write_pointer + 4'd1] <= write_inst_exp1; // EXP (I) 222 | end 223 | end 224 | 225 | logic [63:0] master_counter; 226 | logic [63:0] slave_counter; 227 | 228 | always_ff @(posedge clk) begin 229 | if(debug_rst) 230 | master_counter <= 64'd0; 231 | else if(read_en1 && (!empty || in_delay_slot)) 232 | master_counter <= master_counter + 64'd1; 233 | end 234 | 235 | always_ff @(posedge clk) begin 236 | if(debug_rst) 237 | slave_counter <= 64'd0; 238 | else if(read_en2 && (!empty && !in_delay_slot && !almost_empty)) 239 | slave_counter <= slave_counter + 64'd1; 240 | end 241 | 242 | wire [63:0] total_inst = master_counter + slave_counter; 243 | 244 | endmodule -------------------------------------------------------------------------------- /hdl/ifu/pc.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module pc( 4 | input clk, 5 | input rst, 6 | input pc_en, 7 | input inst_ok_1, 8 | input inst_ok_2, 9 | input fifo_full, 10 | 11 | input branch_taken, 12 | input [31:0] branch_address, 13 | input exception_taken, 14 | input [31:0] exception_address, 15 | 16 | output logic [31:0] pc_address 17 | ); 18 | 19 | reg [31:0] real_pc_address; 20 | logic [31:0] pc_address_next; 21 | 22 | assign pc_address = real_pc_address; 23 | 24 | always_comb begin : compute_next_pc_address 25 | if(rst) 26 | pc_address_next = 32'hbfc0_0000; // Initial valud 27 | else if(pc_en) begin 28 | if(exception_taken) 29 | pc_address_next = exception_address; 30 | else if(branch_taken) 31 | pc_address_next = branch_address; 32 | else if(fifo_full) 33 | pc_address_next = pc_address; 34 | else if(inst_ok_1 && inst_ok_2) 35 | pc_address_next = pc_address + 32'd8; 36 | else if(inst_ok_1) 37 | pc_address_next = pc_address + 32'd4; 38 | else 39 | pc_address_next = pc_address; 40 | end 41 | else begin 42 | pc_address_next = pc_address; 43 | end 44 | end 45 | 46 | always_ff @(posedge clk) begin 47 | real_pc_address <= pc_address_next; 48 | end 49 | 50 | endmodule -------------------------------------------------------------------------------- /hdl/lsu/data_fifo.sv: -------------------------------------------------------------------------------- 1 | // FIFO used for UNCACHED MEMORY WRITE... 2 | module data_fifo( 3 | input clk, 4 | input rst, 5 | 6 | // Input channel 7 | input [2:0] size_in, 8 | input [31:0] addr_in, 9 | input [31:0] data_in, 10 | input [3:0] dwen_in, 11 | 12 | // Output channel 13 | output wire [2:0] size_out, 14 | output wire [31:0] addr_out, 15 | output wire [31:0] data_out, 16 | output wire [3:0] dwen_out, 17 | 18 | // Control channel 19 | input read_en, 20 | input write_en, 21 | 22 | output logic full, 23 | output logic empty 24 | ); 25 | 26 | wire [70:0] din; 27 | wire [70:0] dout; 28 | 29 | assign din = { size_in, dwen_in, data_in, addr_in }; 30 | assign { size_out, dwen_out, data_out, addr_out } = dout; 31 | 32 | /* 33 | fifo_generator_0 fifo_generator( 34 | .clk (clk), 35 | .srst (rst), 36 | .din (din), 37 | .dout (dout), 38 | .full (full), 39 | .empty (empty), 40 | .wr_en (write_en), 41 | .rd_en (read_en) 42 | ); 43 | */ 44 | 45 | // Use registers as fifo... Fuck xilinx 46 | reg [70:0] _fifo[0:63]; 47 | 48 | reg [5:0] read_pointer; 49 | reg [5:0] write_pointer; 50 | 51 | assign full = read_pointer == (write_pointer + 5'd1); 52 | assign empty = read_pointer == write_pointer; 53 | assign dout = _fifo[read_pointer]; 54 | 55 | always_ff @(posedge clk) begin 56 | if(rst) begin 57 | read_pointer <= 6'd0; 58 | end 59 | else if(read_en) 60 | read_pointer <= read_pointer + 6'd1; 61 | end 62 | 63 | always_ff @(posedge clk) begin 64 | if(rst) begin 65 | write_pointer <= 6'd0; 66 | end 67 | else if(write_en) 68 | write_pointer <= write_pointer + 6'd1; 69 | end 70 | 71 | always_ff @(posedge clk) begin 72 | if(rst) begin 73 | for(int i = 0; i < 64; i++) 74 | _fifo[i] <= 70'd0; 75 | end 76 | else if(write_en) 77 | _fifo[write_pointer] <= din; 78 | end 79 | 80 | endmodule -------------------------------------------------------------------------------- /hdl/lsu/memory.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "common.vh" 3 | module memory( 4 | input clk, 5 | input rst, 6 | 7 | input [31:0] address, 8 | input [31:0] ex_result, 9 | input [31:0] rt_value, 10 | input [ 4:0] rt_addr, 11 | input [ 1:0] mem_type, 12 | input [ 2:0] mem_size, 13 | input mem_signed, 14 | 15 | // Exceptions... 16 | input [ 2:0] inst_exp, 17 | input data_miss, 18 | input data_illegal, 19 | input data_tlb_invalid, 20 | input data_dirty, 21 | 22 | // Connect to sram. 23 | output logic mem_en, 24 | output logic [3:0] mem_wen, 25 | output logic [31:0] mem_addr, 26 | output logic [31:0] mem_wdata, 27 | input logic [31:0] mem_rdata, 28 | output logic [2:0] data_size, 29 | 30 | output logic [31:0] result, 31 | // Report error 32 | output logic address_error, 33 | output logic tlb_modified, 34 | 35 | // Cache operation 36 | output logic inst_hit_invalidate, 37 | output logic data_hit_writeback, 38 | output logic index_invalidate 39 | ); 40 | 41 | assign mem_en = (|mem_type || data_hit_writeback) && (~address_error) && 42 | (~(|inst_exp)) && (~data_miss) && (~data_tlb_invalid) && 43 | ~((~data_dirty && |mem_wen)); 44 | assign mem_addr = address; 45 | assign tlb_modified = (data_dirty && |mem_wen); 46 | 47 | assign inst_hit_invalidate = (mem_type == `MEM_CACH) && (rt_addr == 5'b00000 || rt_addr == 5'b10000); 48 | assign data_hit_writeback = (mem_type == `MEM_CACH) && (rt_addr == 5'b00001 || rt_addr == 5'b10101); 49 | assign index_invalidate = (mem_type == `MEM_CACH) && (rt_addr == 5'b00000 || rt_addr == 5'b00001); 50 | 51 | always_comb begin : detect_write_size 52 | if(mem_size == `SZ_BYTE) 53 | data_size = 3'd0; 54 | else if(mem_size == `SZ_HALF) 55 | data_size = 3'd1; 56 | else 57 | data_size = 3'd2; 58 | end 59 | 60 | always_comb begin : detect_alignment_error 61 | if(mem_type != `MEM_NOOP) begin 62 | unique case(mem_size) 63 | `SZ_HALF: 64 | address_error = address[0]; 65 | `SZ_FULL: 66 | address_error = |address[1:0]; 67 | default: 68 | address_error = 1'b0; 69 | endcase 70 | end 71 | else 72 | address_error = 1'b0; 73 | end 74 | 75 | // Read or write 76 | always_comb begin : memory_control 77 | result = ex_result; 78 | mem_wen = 4'b0; 79 | mem_wdata = rt_value; 80 | if(address_error) begin 81 | // We do noting when align error 82 | end 83 | else begin 84 | if(mem_type == `MEM_STOR) begin 85 | unique case(mem_size) 86 | `SZ_FULL: 87 | mem_wen = 4'b1111; 88 | `SZ_HALF: begin 89 | mem_wdata = {2{rt_value[15:0]}}; 90 | mem_wen = {address[1],address[1],~address[1],~address[1]}; 91 | end 92 | `SZ_BYTE: begin 93 | mem_wdata = {4{rt_value[7:0]}}; 94 | unique case(address[1:0]) 95 | 2'd0: 96 | mem_wen = 4'b0001; 97 | 2'd1: 98 | mem_wen = 4'b0010; 99 | 2'd2: 100 | mem_wen = 4'b0100; 101 | 2'd3: 102 | mem_wen = 4'b1000; 103 | default: 104 | mem_wen = 4'b0000; 105 | endcase 106 | end 107 | `SZ_LEFT: begin 108 | unique case(address[1:0]) 109 | 2'd0: begin 110 | mem_wen = 4'b0001; 111 | mem_wdata = {4{rt_value[31:24]}}; 112 | end 113 | 2'd1: begin 114 | mem_wen = 4'b0011; 115 | mem_wdata = {2{rt_value[31:16]}}; 116 | end 117 | 2'd2: begin 118 | mem_wen = 4'b0111; 119 | mem_wdata = {8'd0,{rt_value[31:8]}}; 120 | end 121 | 2'd3: begin 122 | mem_wen = 4'b1111; 123 | mem_wdata = rt_value; 124 | end 125 | default: 126 | mem_wen = 4'b0000; 127 | endcase 128 | end 129 | `SZ_RIGH: begin 130 | unique case(address[1:0]) 131 | 2'd0: begin 132 | mem_wen = 4'b1111; 133 | mem_wdata = rt_value; 134 | end 135 | 2'd1: begin 136 | mem_wen = 4'b1110; 137 | mem_wdata = {rt_value[23:0],8'd0}; 138 | end 139 | 2'd2: begin 140 | mem_wen = 4'b1100; 141 | mem_wdata = {2{rt_value[15:0]}}; 142 | end 143 | 2'd3: begin 144 | mem_wen = 4'b1000; 145 | mem_wdata = {4{rt_value[7:0]}}; 146 | end 147 | default: 148 | mem_wen = 4'b0000; 149 | endcase 150 | end 151 | default: 152 | mem_wen = 4'b1111; 153 | endcase 154 | end 155 | else if(mem_type == `MEM_LOAD) begin 156 | mem_wen = 4'b0; 157 | unique case(mem_size) 158 | `SZ_HALF: begin 159 | if(address[1]) 160 | result = mem_signed? { 16'b0 ,mem_rdata[31:16]} : 161 | {{16{mem_rdata[31]}}, mem_rdata[31:16]}; 162 | else 163 | result = mem_signed? { 16'b0 ,mem_rdata[15:0]} : 164 | {{16{mem_rdata[15]}}, mem_rdata[15:0]}; 165 | end 166 | `SZ_BYTE: begin 167 | unique case(address[1:0]) 168 | 2'b01: 169 | result = mem_signed? { 24'b0, mem_rdata[15:8]} : 170 | {{24{mem_rdata[15]}}, mem_rdata[15:8]}; 171 | 2'b10: 172 | result = mem_signed? { 24'b0, mem_rdata[23:16]} : 173 | {{24{mem_rdata[23]}}, mem_rdata[23:16]}; 174 | 2'b11: 175 | result = mem_signed? { 24'b0, mem_rdata[31:24]} : 176 | {{24{mem_rdata[31]}}, mem_rdata[31:24]}; 177 | default: 178 | result = mem_signed? { 24'b0, mem_rdata[7:0]} : 179 | {{24{mem_rdata[7]}}, mem_rdata[7:0]}; 180 | endcase 181 | end 182 | `SZ_LEFT: begin 183 | unique case(address[1:0]) 184 | 2'b00: 185 | result = {mem_rdata[7:0],rt_value[23:0]}; 186 | 2'b01: 187 | result = {mem_rdata[16:0],rt_value[16:0]}; 188 | 2'b10: 189 | result = {mem_rdata[23:0],rt_value[7:0]}; 190 | default: 191 | result = mem_rdata; 192 | endcase 193 | end 194 | `SZ_RIGH: begin 195 | unique case(address[1:0]) 196 | 2'b00: 197 | result = mem_rdata; 198 | 2'b01: 199 | result = {rt_value[31:24],mem_rdata[31:8]}; 200 | 2'b10: 201 | result = {rt_value[31:16],mem_rdata[31:16]}; 202 | default: 203 | result = {rt_value[31:8],mem_rdata[31:24]}; 204 | endcase 205 | end 206 | default: 207 | result = mem_rdata; 208 | endcase 209 | end 210 | end 211 | end 212 | 213 | endmodule -------------------------------------------------------------------------------- /hdl/lsu/mmu_data.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | // daddr_psy should not be changed when pipeline stall 4 | // now the mmu_data shares the same structure with mmu_inst 5 | // FUCK VERILOG!!! 6 | module mmu_data( 7 | input clk, 8 | input rst, 9 | 10 | // From/to sirius 11 | input den, 12 | input [3:0] dwen, 13 | input [31:0] daddr_psy, 14 | input [31:0] wdata, 15 | input daddr_type, // 0 as cacahe... 16 | input [2:0] data_size_in, 17 | output logic [2:0] data_size_out, 18 | 19 | output logic data_ok, 20 | output logic [31:0] data_data, 21 | 22 | // Cache control 23 | input data_hit_writeback, 24 | input index_invalidate, 25 | 26 | // From/to MMU 27 | output logic mmu_running, 28 | // read channel 29 | output logic [31:0] daddr_req, 30 | output logic read_en, 31 | output logic read_type, // o as cache refill, 1 as uncached 32 | input daddr_req_ok, 33 | input [31:0] ddata_rdata, 34 | input ddata_rvalid, 35 | input ddata_rlast, 36 | // write channel 37 | output logic [31:0] daddr_wreq, 38 | output logic write_en, 39 | output logic write_type, 40 | output logic [3:0] write_byte_en, 41 | output logic dwvalid, 42 | output logic [31:0] dwdata, 43 | output logic dwlast, 44 | input daddr_wreq_ok, 45 | input ddata_wready, 46 | input ddata_bvalid 47 | ); 48 | 49 | enum logic [3:0] { 50 | IDLE = 4'b0000, 51 | FIFO_WAIT = 4'b0101, 52 | CACHED_RSHAKE = 4'b0001, 53 | CACHED_RWAIT = 4'b0100, 54 | CACHED_REFILL = 4'b0010, 55 | CACHED_WWAIT = 4'b0111, 56 | UNCACHED_SHAKE = 4'b1001, 57 | UNCACHED_WWAIT = 4'b1100, 58 | UNCACHED_RETURN = 4'b1010, 59 | CACHECTRL_WAIT = 4'b1111 60 | } cstate, nstate; 61 | 62 | enum logic [2:0] { 63 | WIDLE = 3'b000, 64 | UNCACHED_WSHAKE = 3'b001, 65 | UNCACHED_WWRITE = 3'b011, 66 | UNCACHED_WRESULT= 3'b010, 67 | CACHED_WSHAKE = 3'b101, 68 | CACHED_WWRITE = 3'b110, 69 | CACHED_WRESULT = 3'b111 70 | } wcstate, wnstate; 71 | 72 | reg [127:0] dcache_valid; 73 | reg [127:0] dcache_dirty; 74 | 75 | wire [ 18:0] data_tag = daddr_psy[31:13]; 76 | wire [ 6:0] data_index = daddr_psy[12:6]; 77 | wire [ 3:0] data_offset = daddr_psy[5:2]; 78 | wire [ 6:0] ram_dpra = data_index; 79 | wire [ 6:0] ram_a = data_index; 80 | logic[530:0] _ram_d, ram_d, ram_d_buffer; 81 | logic ram_we; 82 | 83 | wire [530:0] dcache_return; // Connect to output channel of ram. 84 | wire [ 31:0] dcache_return_data[0:15]; 85 | 86 | reg [ 31:0] receive_buffer[0:15]; 87 | logic[ 31:0] ram_buffer[0:15]; 88 | 89 | logic write_required; 90 | logic writeback_required; 91 | logic valid_change; 92 | 93 | wire [18:0]dcache_return_tag = dcache_return[18:0]; 94 | assign dcache_return_data[0] = dcache_return[50:19]; 95 | assign dcache_return_data[1] = dcache_return[82:51]; 96 | assign dcache_return_data[2] = dcache_return[114:83]; 97 | assign dcache_return_data[3] = dcache_return[146:115]; 98 | assign dcache_return_data[4] = dcache_return[178:147]; 99 | assign dcache_return_data[5] = dcache_return[210:179]; 100 | assign dcache_return_data[6] = dcache_return[242:211]; 101 | assign dcache_return_data[7] = dcache_return[274:243]; 102 | assign dcache_return_data[8] = dcache_return[306:275]; 103 | assign dcache_return_data[9] = dcache_return[338:307]; 104 | assign dcache_return_data[10] = dcache_return[370:339]; 105 | assign dcache_return_data[11] = dcache_return[402:371]; 106 | assign dcache_return_data[12] = dcache_return[434:403]; 107 | assign dcache_return_data[13] = dcache_return[466:435]; 108 | assign dcache_return_data[14] = dcache_return[498:467]; 109 | assign dcache_return_data[15] = dcache_return[530:499]; 110 | 111 | assign _ram_d[18:0] = data_tag; 112 | assign _ram_d[50:19] = receive_buffer[0]; 113 | assign _ram_d[82:51] = receive_buffer[1]; 114 | assign _ram_d[114:83] = receive_buffer[2]; 115 | assign _ram_d[146:115] = receive_buffer[3]; 116 | assign _ram_d[178:147] = receive_buffer[4]; 117 | assign _ram_d[210:179] = receive_buffer[5]; 118 | assign _ram_d[242:211] = receive_buffer[6]; 119 | assign _ram_d[274:243] = receive_buffer[7]; 120 | assign _ram_d[306:275] = receive_buffer[8]; 121 | assign _ram_d[338:307] = receive_buffer[9]; 122 | assign _ram_d[370:339] = receive_buffer[10]; 123 | assign _ram_d[402:371] = receive_buffer[11]; 124 | assign _ram_d[434:403] = receive_buffer[12]; 125 | assign _ram_d[466:435] = receive_buffer[13]; 126 | assign _ram_d[498:467] = receive_buffer[14]; 127 | assign _ram_d[530:499] = receive_buffer[15]; 128 | 129 | assign ram_d_buffer[18:0] = data_tag; 130 | assign ram_d_buffer[50:19] = ram_buffer[0]; 131 | assign ram_d_buffer[82:51] = ram_buffer[1]; 132 | assign ram_d_buffer[114:83] = ram_buffer[2]; 133 | assign ram_d_buffer[146:115] = ram_buffer[3]; 134 | assign ram_d_buffer[178:147] = ram_buffer[4]; 135 | assign ram_d_buffer[210:179] = ram_buffer[5]; 136 | assign ram_d_buffer[242:211] = ram_buffer[6]; 137 | assign ram_d_buffer[274:243] = ram_buffer[7]; 138 | assign ram_d_buffer[306:275] = ram_buffer[8]; 139 | assign ram_d_buffer[338:307] = ram_buffer[9]; 140 | assign ram_d_buffer[370:339] = ram_buffer[10]; 141 | assign ram_d_buffer[402:371] = ram_buffer[11]; 142 | assign ram_d_buffer[434:403] = ram_buffer[12]; 143 | assign ram_d_buffer[466:435] = ram_buffer[13]; 144 | assign ram_d_buffer[498:467] = ram_buffer[14]; 145 | assign ram_d_buffer[530:499] = ram_buffer[15]; 146 | 147 | 148 | dist_mem_gen_icache dcache_ram( 149 | .clk (clk), 150 | .dpra (ram_dpra), 151 | .a (ram_a), 152 | .d (ram_d), 153 | .we (ram_we), 154 | .dpo (dcache_return) 155 | ); 156 | 157 | logic [31:0] dfifo_addr; 158 | logic [31:0] dfifo_data; 159 | logic [3:0] dfifo_dwen; 160 | logic dfifo_read_en; 161 | logic dfifo_write_en; 162 | logic dfifo_full; 163 | logic dfifo_empty; 164 | 165 | 166 | data_fifo dfifo( 167 | .clk (clk), 168 | .rst (rst), 169 | .size_in (data_size_in), 170 | .addr_in (daddr_psy), 171 | .data_in (wdata), 172 | .dwen_in (dwen), 173 | .addr_out (dfifo_addr), 174 | .data_out (dfifo_data), 175 | .dwen_out (dfifo_dwen), 176 | .size_out (data_size_out), 177 | .read_en (dfifo_read_en), 178 | .write_en (dfifo_write_en), 179 | .full (dfifo_full), 180 | .empty (dfifo_empty) 181 | ); 182 | 183 | always_ff @(posedge clk) begin : update_status 184 | if(rst) 185 | cstate <= IDLE; 186 | else 187 | cstate <= nstate; 188 | end 189 | 190 | always_ff @(posedge clk) begin : update_wstatus 191 | if(rst) 192 | wcstate <= WIDLE; 193 | else 194 | wcstate <= wnstate; 195 | end 196 | 197 | always_ff @(posedge clk) begin : update_valid_info 198 | if(rst) begin 199 | dcache_valid <= 128'd0; 200 | end 201 | else if(cstate == CACHED_REFILL) begin 202 | dcache_valid[data_index] <= 1'b1; 203 | end 204 | else if(valid_change) 205 | dcache_valid[data_index] <= 1'b0; 206 | end 207 | 208 | always_ff @(posedge clk) begin : update_dirty_info 209 | if(rst) begin 210 | dcache_dirty <= 128'd0; 211 | end 212 | else if(cstate == CACHED_REFILL || valid_change) begin 213 | dcache_dirty[data_index] <= 1'b0; 214 | end 215 | else if(writeback_required) begin 216 | dcache_dirty[data_index] <= 1'b1; 217 | end 218 | end 219 | 220 | reg [3:0] receive_counter; 221 | 222 | always_ff @(posedge clk) begin : update_receive_counter 223 | if(rst || cstate != CACHED_RWAIT) begin 224 | receive_counter <= 4'd0; 225 | end 226 | else if(cstate == CACHED_RWAIT && ddata_rvalid) begin// receive new data 227 | receive_counter <= receive_counter + 4'd1; 228 | end 229 | end 230 | 231 | always_ff @(posedge clk) begin : write_data_to_buffer 232 | if(rst) begin // Clear buffer 233 | for(int i = 0; i < 16; i++) 234 | receive_buffer[i] <= 32'd0; 235 | end 236 | else if(cstate == CACHED_RWAIT && ddata_rvalid) begin 237 | receive_buffer[receive_counter] <= ddata_rdata; 238 | end 239 | end 240 | 241 | reg [3:0] output_counter; 242 | 243 | always_ff @(posedge clk) begin : update_output_counter 244 | if(rst || wcstate != CACHED_WWRITE) begin 245 | output_counter <= 4'd0; 246 | end 247 | else if(wcstate == CACHED_WWRITE && ddata_wready) begin // receive new data 248 | output_counter <= output_counter + 4'd1; 249 | end 250 | end 251 | 252 | always_comb begin 253 | if(writeback_required) 254 | ram_d = ram_d_buffer; 255 | else 256 | ram_d = _ram_d; 257 | end 258 | 259 | // For performance tunning... 260 | reg [63:0] cache_hit_counter; 261 | reg [63:0] cache_miss_counter; 262 | reg [63:0] cache_swap_counter; 263 | reg [63:0] uncached_read_counter; 264 | reg [63:0] uncached_write_counter; 265 | 266 | logic cache_hit; 267 | logic cache_miss; 268 | logic cache_swap; 269 | logic uncached_read; 270 | logic uncached_write; 271 | 272 | always_ff @(posedge clk) begin 273 | if(rst) begin 274 | cache_hit_counter <= 64'd0; 275 | cache_miss_counter <= 64'd0; 276 | end 277 | else begin 278 | if(cache_hit) 279 | cache_hit_counter <= cache_hit_counter + 64'd1; 280 | else if(cache_miss) 281 | cache_miss_counter <= cache_miss_counter + 64'd1; 282 | end 283 | end 284 | 285 | always_ff @(posedge clk) begin 286 | if(rst) begin 287 | cache_swap_counter <= 64'd0; 288 | end 289 | else if(cache_swap) begin 290 | cache_swap_counter <= cache_swap_counter + 64'd1; 291 | $display("[DBEUG] Cache swap at index %d for address 0x%08x", data_index, daddr_psy); 292 | end 293 | end 294 | 295 | always_ff @(posedge clk) begin 296 | if(rst) begin 297 | uncached_read_counter <= 64'd0; 298 | end 299 | else if(uncached_read) begin 300 | uncached_read_counter <= uncached_read_counter + 64'd1; 301 | end 302 | end 303 | 304 | always_ff @(posedge clk) begin 305 | if(rst) begin 306 | uncached_write_counter <= 64'd0; 307 | end 308 | else if(uncached_write) begin 309 | uncached_write_counter <= uncached_write_counter + 64'd1; 310 | end 311 | end 312 | 313 | wire hit_it = (dcache_valid[data_index] && (dcache_return_tag == data_tag || index_invalidate)); 314 | 315 | // Read channel 316 | always_comb begin 317 | data_ok = 1'd0; 318 | data_data = 32'd0; 319 | 320 | daddr_req = 32'd0; 321 | read_en = 1'd0; 322 | read_type = 1'd0; 323 | write_required = 1'd0; 324 | writeback_required = 1'd0; 325 | mmu_running = 1'd0; 326 | 327 | nstate = IDLE; 328 | ram_we = 1'd0; 329 | 330 | // For perf tunning... 331 | cache_hit = 1'd0; 332 | cache_miss = 1'd0; 333 | cache_swap = 1'd0; 334 | uncached_read = 1'd0; 335 | uncached_write = 1'd0; 336 | 337 | dfifo_write_en = 1'd0; 338 | valid_change = 1'd0; 339 | 340 | 341 | for(int i = 0; i < 16; i++) begin 342 | ram_buffer[i] = dcache_return_data[i]; 343 | end 344 | 345 | unique case(cstate) 346 | IDLE: begin 347 | if(rst || !den) begin 348 | // Make vivado happy 349 | end 350 | else if(data_hit_writeback) begin 351 | if(hit_it && dcache_dirty[data_index] && ~(dfifo_empty && wcstate == WIDLE)) 352 | nstate = FIFO_WAIT; 353 | valid_change = hit_it; 354 | write_required = hit_it && dcache_dirty[data_index]; 355 | data_ok = ~hit_it; 356 | if(hit_it) 357 | nstate = CACHECTRL_WAIT; 358 | end 359 | else if(daddr_type) begin // Uncached access 360 | mmu_running = 1'd1; 361 | if(dwen) begin 362 | dfifo_write_en = ~dfifo_full; 363 | data_ok = ~dfifo_full; 364 | nstate = IDLE; 365 | uncached_write = 1'd1; 366 | end 367 | else begin // Read 368 | if(dfifo_empty && wcstate == WIDLE) begin 369 | daddr_req = daddr_psy; 370 | read_en = 1'd1; 371 | read_type = 1'd1; 372 | uncached_read = 1'd1; 373 | if(daddr_req_ok) begin 374 | nstate = UNCACHED_RETURN; 375 | end 376 | else begin 377 | nstate = UNCACHED_SHAKE; 378 | end 379 | end 380 | else 381 | nstate = FIFO_WAIT; 382 | end 383 | end 384 | else if(hit_it) begin 385 | cache_hit = 1'd1; 386 | if(dwen != 4'd0) begin 387 | writeback_required = 1'd1; 388 | ram_we = 1'd1; 389 | data_ok = 1'd1; 390 | data_data = 32'd0; 391 | ram_buffer[data_offset] = (dcache_return_data[data_offset] & {{8{~dwen[3]}}, {8{~dwen[2]}}, {8{~dwen[1]}}, {8{~dwen[0]}}}) | 392 | (wdata & {{8{dwen[3]}}, {8{dwen[2]}}, {8{dwen[1]}}, {8{dwen[0]}}}); 393 | end 394 | else begin 395 | data_ok = 1'd1; 396 | data_data = dcache_return_data[data_offset]; 397 | end 398 | nstate = IDLE; 399 | end 400 | else begin // Cache miss 401 | cache_miss = 1'd1; 402 | if(dcache_dirty[data_index] && ~(dfifo_empty && wcstate == WIDLE)) begin 403 | nstate = FIFO_WAIT; 404 | end 405 | else begin 406 | daddr_req = {daddr_psy[31:6], 6'd0}; 407 | mmu_running = 1'd1; 408 | read_en = 1'd1; 409 | read_type = 1'd0; 410 | cache_swap = dcache_valid[data_index]; 411 | write_required = dcache_dirty[data_index]; 412 | if(daddr_req_ok) begin 413 | nstate = CACHED_RWAIT; 414 | end 415 | else begin 416 | nstate = CACHED_RSHAKE; 417 | end 418 | end 419 | 420 | end 421 | end 422 | 423 | CACHECTRL_WAIT: begin 424 | if(dfifo_empty && (wcstate == WIDLE)) begin 425 | nstate = IDLE; 426 | data_ok = 1'd1; 427 | end 428 | else 429 | nstate = CACHECTRL_WAIT; 430 | end 431 | 432 | FIFO_WAIT: begin 433 | if(dfifo_empty && (wcstate == WIDLE)) 434 | nstate = IDLE; 435 | else 436 | nstate = FIFO_WAIT; 437 | end 438 | 439 | UNCACHED_SHAKE: begin 440 | daddr_req = daddr_psy; 441 | read_en = 1'd1; 442 | read_type = 1'd1; 443 | mmu_running = 1'd1; 444 | if(daddr_req_ok) begin 445 | nstate = UNCACHED_RETURN; 446 | end 447 | else begin 448 | nstate = UNCACHED_SHAKE; 449 | end 450 | end 451 | UNCACHED_RETURN: begin 452 | data_ok = ddata_rvalid; 453 | data_data = ddata_rdata; 454 | mmu_running = 1'd1; 455 | if(ddata_rvalid && ddata_rlast) begin 456 | nstate = IDLE; 457 | end 458 | else begin 459 | nstate = UNCACHED_RETURN; 460 | end 461 | end 462 | UNCACHED_WWAIT: begin 463 | mmu_running = 1'd1; 464 | if(wcstate == UNCACHED_WRESULT && ddata_bvalid) begin 465 | data_ok = 1'd1; 466 | nstate = IDLE; 467 | end 468 | else 469 | nstate = UNCACHED_WWAIT; 470 | end 471 | CACHED_RSHAKE: begin 472 | mmu_running = 1'd1; 473 | daddr_req = {daddr_psy[31:6], 6'd0}; 474 | read_en = 1'd1; 475 | read_type = 1'd0; 476 | if(daddr_req_ok) begin 477 | nstate = CACHED_RWAIT; 478 | end 479 | else begin 480 | nstate = CACHED_RSHAKE; 481 | end 482 | end 483 | CACHED_RWAIT: begin 484 | mmu_running = 1'd1; 485 | if(ddata_rvalid && ddata_rlast && wcstate == WIDLE) begin 486 | nstate = CACHED_REFILL; 487 | end 488 | else if(ddata_rvalid && ddata_rlast) begin 489 | nstate = CACHED_WWAIT; 490 | end 491 | else begin 492 | nstate = CACHED_RWAIT; 493 | end 494 | end 495 | CACHED_WWAIT: begin 496 | mmu_running = 1'd1; 497 | if(wcstate != WIDLE) begin 498 | nstate = CACHED_WWAIT; 499 | end 500 | else begin 501 | nstate = CACHED_REFILL; 502 | end 503 | end 504 | CACHED_REFILL: begin 505 | mmu_running = 1'd1; 506 | ram_we = 1'd1; 507 | nstate = IDLE; 508 | 509 | data_ok = ~(|dwen); 510 | data_data = receive_buffer[data_offset]; 511 | end 512 | default: begin 513 | // Make vivado happy :) 514 | end 515 | endcase 516 | end 517 | 518 | // Write channel 519 | always_comb begin 520 | daddr_wreq = 32'd0; 521 | write_en = 1'd0; 522 | write_type = 1'd0; 523 | write_byte_en = 4'd0; 524 | dwvalid = 1'd0; 525 | dwdata = 32'd0; 526 | dwlast = 1'd0; 527 | 528 | wnstate = WIDLE; 529 | 530 | // FIFO default value 531 | dfifo_read_en = 1'd0; 532 | 533 | case(wcstate) 534 | WIDLE: begin 535 | if(~dfifo_empty) begin // Uncached write 536 | daddr_wreq = dfifo_addr; 537 | write_en = 1'd1; 538 | write_type = 1'd1; 539 | write_byte_en = dfifo_dwen; 540 | if(daddr_wreq_ok) begin 541 | wnstate = UNCACHED_WWRITE; 542 | end 543 | else begin 544 | wnstate = UNCACHED_WSHAKE; 545 | end 546 | end 547 | else if(write_required) begin 548 | daddr_wreq = { dcache_return_tag, data_index, 6'd0 }; 549 | write_en = 1'd1; 550 | write_type = 1'd0; 551 | if(daddr_wreq_ok) begin 552 | wnstate = CACHED_WWRITE; 553 | end 554 | else begin 555 | wnstate = CACHED_WSHAKE; 556 | end 557 | end 558 | end 559 | UNCACHED_WSHAKE: begin 560 | daddr_wreq = dfifo_addr; 561 | write_en = 1'd1; 562 | write_type = 1'd1; 563 | if(daddr_wreq_ok) begin 564 | wnstate = UNCACHED_WWRITE; 565 | end 566 | else begin 567 | wnstate = UNCACHED_WSHAKE; 568 | end 569 | end 570 | UNCACHED_WWRITE: begin 571 | write_byte_en = dfifo_dwen; 572 | dwdata = dfifo_data; 573 | dwvalid = 1'd1; 574 | dwlast = 1'd1; 575 | dfifo_read_en = ddata_wready; 576 | if(ddata_wready) 577 | wnstate = UNCACHED_WRESULT; 578 | else 579 | wnstate = UNCACHED_WWRITE; 580 | end 581 | UNCACHED_WRESULT: begin 582 | if(ddata_bvalid) 583 | wnstate = WIDLE; 584 | else 585 | wnstate = UNCACHED_WRESULT; 586 | end 587 | CACHED_WSHAKE: begin 588 | daddr_wreq = { dcache_return_tag, data_index, 6'd0 }; 589 | write_en = 1'd1; 590 | write_type = 1'd0; 591 | if(daddr_wreq_ok) begin 592 | wnstate = CACHED_WWRITE; 593 | end 594 | else begin 595 | wnstate = CACHED_WSHAKE; 596 | end 597 | end 598 | CACHED_WWRITE: begin 599 | write_byte_en = 4'b1111; 600 | dwdata = dcache_return_data[output_counter]; 601 | dwvalid = 1'd1; 602 | dwlast = &output_counter; 603 | if(&output_counter && ddata_wready) 604 | wnstate = CACHED_WRESULT; 605 | else 606 | wnstate = CACHED_WWRITE; 607 | end 608 | CACHED_WRESULT: begin 609 | if(ddata_bvalid) 610 | wnstate = WIDLE; 611 | else 612 | wnstate = CACHED_WRESULT; 613 | end 614 | default: begin 615 | // Make vivado happy :) 616 | end 617 | endcase 618 | end 619 | 620 | endmodule 621 | -------------------------------------------------------------------------------- /hdl/lsu/mmu_inst.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | // I choose to trust xilinx... 3 | 4 | // The instruction cache. 5 | // Format: 6 | // | Tag[18:0] | data... 64Bytes | * 128 7 | // Address format: 8 | // addr[31:13] as Tag 9 | // addr[12:6] as Index 10 | // addr[5:2] as Offset 11 | // addr[1:0] is unused in i$ 12 | 13 | // iaddr_psy should not be changed when pipeline is stalling... 14 | module mmu_inst( 15 | input clk, 16 | input rst, 17 | 18 | // From/to sirius 19 | input ien, 20 | input [31:0] iaddr_psy, 21 | input iaddr_type, // 0 as cached, 1 as uncacahed 22 | 23 | // Cache control 24 | input inst_hit_invalidate, 25 | input index_invalidate, 26 | 27 | output logic inst_ok, 28 | output logic inst_ok_1, 29 | output logic inst_ok_2, 30 | output logic [31:0] inst_data_1, 31 | output logic [31:0] inst_data_2, 32 | 33 | // From/to mmu_top 34 | output logic mmu_running, 35 | output logic [31:0] iaddr_req, 36 | output logic read_en, 37 | output logic read_type, // o as cache refill, 1 as uncached 38 | input iaddr_req_ok, 39 | input [31:0] idata_rdata, 40 | input idata_rvalid, 41 | input idata_rlast 42 | ); 43 | 44 | enum logic [2:0] { 45 | IDLE = 3'b000, 46 | CACHED_SHAKE = 3'b001, 47 | CACHED_WAIT = 3'b010, 48 | CACHED_REFILL = 3'b011, 49 | UNCACHED_SHAKE = 3'b101, 50 | UNCACHED_RETURN = 3'b110, 51 | CACHECTRL_WAIT = 3'b111 52 | } cstate, nstate; 53 | 54 | reg [127:0] icache_valid; 55 | 56 | wire [ 18:0] inst_tag = iaddr_psy[31:13]; 57 | wire [ 6:0] inst_index = iaddr_psy[12:6]; 58 | wire [ 3:0] inst_offset = iaddr_psy[5:2]; 59 | wire [ 6:0] ram_dpra = inst_index; 60 | wire [ 6:0] ram_a = inst_index; 61 | wire [530:0] ram_d; 62 | logic ram_we; 63 | logic clear_valid; 64 | 65 | wire [530:0] icache_return; // Connect to output channel of ram. 66 | wire [ 31:0] icache_return_data[0:15]; 67 | 68 | reg [ 31:0] receive_buffer[0:15]; 69 | 70 | wire [18:0]icache_return_tag = icache_return[18:0]; 71 | assign icache_return_data[0] = icache_return[50:19]; 72 | assign icache_return_data[1] = icache_return[82:51]; 73 | assign icache_return_data[2] = icache_return[114:83]; 74 | assign icache_return_data[3] = icache_return[146:115]; 75 | assign icache_return_data[4] = icache_return[178:147]; 76 | assign icache_return_data[5] = icache_return[210:179]; 77 | assign icache_return_data[6] = icache_return[242:211]; 78 | assign icache_return_data[7] = icache_return[274:243]; 79 | assign icache_return_data[8] = icache_return[306:275]; 80 | assign icache_return_data[9] = icache_return[338:307]; 81 | assign icache_return_data[10] = icache_return[370:339]; 82 | assign icache_return_data[11] = icache_return[402:371]; 83 | assign icache_return_data[12] = icache_return[434:403]; 84 | assign icache_return_data[13] = icache_return[466:435]; 85 | assign icache_return_data[14] = icache_return[498:467]; 86 | assign icache_return_data[15] = icache_return[530:499]; 87 | 88 | assign ram_d[18:0] = inst_tag; 89 | assign ram_d[50:19] = receive_buffer[0]; 90 | assign ram_d[82:51] = receive_buffer[1]; 91 | assign ram_d[114:83] = receive_buffer[2]; 92 | assign ram_d[146:115] = receive_buffer[3]; 93 | assign ram_d[178:147] = receive_buffer[4]; 94 | assign ram_d[210:179] = receive_buffer[5]; 95 | assign ram_d[242:211] = receive_buffer[6]; 96 | assign ram_d[274:243] = receive_buffer[7]; 97 | assign ram_d[306:275] = receive_buffer[8]; 98 | assign ram_d[338:307] = receive_buffer[9]; 99 | assign ram_d[370:339] = receive_buffer[10]; 100 | assign ram_d[402:371] = receive_buffer[11]; 101 | assign ram_d[434:403] = receive_buffer[12]; 102 | assign ram_d[466:435] = receive_buffer[13]; 103 | assign ram_d[498:467] = receive_buffer[14]; 104 | assign ram_d[530:499] = receive_buffer[15]; 105 | 106 | dist_mem_gen_icache icache_ram( 107 | .clk (clk), 108 | .dpra (ram_dpra), 109 | .a (ram_a), 110 | .d (ram_d), 111 | .we (ram_we), 112 | .dpo (icache_return) 113 | ); 114 | 115 | always_ff @(posedge clk) begin : update_status 116 | if(rst) 117 | cstate <= IDLE; 118 | else 119 | cstate <= nstate; 120 | end 121 | 122 | always_ff @(posedge clk) begin : update_valid_info 123 | if(rst) begin 124 | icache_valid <= 128'd0; 125 | end 126 | else if(cstate == CACHED_REFILL) begin 127 | icache_valid[inst_index] <= 1'b1; 128 | end 129 | else if(clear_valid) 130 | icache_valid[inst_index] <= 1'b0; 131 | end 132 | 133 | reg [3:0] receive_counter; 134 | 135 | always_ff @(posedge clk) begin : update_receive_counter 136 | if(rst || cstate != CACHED_WAIT) begin 137 | receive_counter <= 4'd0; 138 | end 139 | else if(cstate == CACHED_WAIT && idata_rvalid) begin// receive new data 140 | receive_counter <= receive_counter + 4'd1; 141 | end 142 | end 143 | 144 | always_ff @(posedge clk) begin : write_data_to_buffer 145 | if(rst) begin // Clear buffer 146 | for(int i = 0; i < 16; i++) 147 | receive_buffer[i] <= 32'd0; 148 | end 149 | else if(cstate == CACHED_WAIT && idata_rvalid) begin 150 | receive_buffer[receive_counter] <= idata_rdata; 151 | end 152 | end 153 | // For performance tunning... 154 | reg [63:0] cache_hit_counter; 155 | reg [63:0] cache_miss_counter; 156 | 157 | logic cache_hit; 158 | logic cache_miss; 159 | 160 | always_ff @(posedge clk) begin 161 | if(rst) begin 162 | cache_hit_counter <= 64'd0; 163 | cache_miss_counter <= 64'd0; 164 | end 165 | else begin 166 | if(cache_hit) 167 | cache_hit_counter <= cache_hit_counter + 64'd1; 168 | else if(cache_miss) 169 | cache_miss_counter <= cache_miss_counter + 64'd1; 170 | end 171 | end 172 | 173 | wire hit_it = ((inst_tag == icache_return_tag || index_invalidate) && 174 | icache_valid[inst_index]); 175 | 176 | // WARNING -- COMPLEX COMB LOGIC 177 | // "We will still hate the tools." 178 | always_comb begin : set_all_output 179 | // Set default signals 180 | // Output.. 181 | inst_ok = 1'd0; 182 | inst_ok_1 = 1'd0; 183 | inst_ok_2 = 1'd0; 184 | inst_data_1 = 32'd0; 185 | inst_data_2 = 32'd0; 186 | iaddr_req = 32'd0; 187 | read_en = 1'd0; 188 | read_type = 1'd0; 189 | // Internal signals... 190 | ram_we = 1'd0; 191 | mmu_running = 1'd0; 192 | 193 | clear_valid = 1'd0; 194 | 195 | // For perf tunning... 196 | cache_hit = 1'd0; 197 | cache_miss = 1'd0; 198 | 199 | nstate = IDLE; 200 | unique case(cstate) 201 | IDLE: begin 202 | if(rst || !ien) begin // We do nothing here. 203 | end 204 | else if(inst_hit_invalidate) begin 205 | clear_valid = hit_it; 206 | if(hit_it) 207 | nstate = CACHECTRL_WAIT; 208 | end 209 | else if(iaddr_type) begin// Uncacahed read 210 | iaddr_req = iaddr_psy; 211 | read_en = 1'd1; 212 | mmu_running = 1'd1; 213 | read_type = 1'd1; 214 | if(iaddr_req_ok) begin 215 | nstate = UNCACHED_RETURN; 216 | end 217 | else begin 218 | nstate = UNCACHED_SHAKE; 219 | end 220 | end 221 | else if(hit_it) begin // Cache hit 222 | cache_hit = 1'd1; 223 | inst_ok = 1'd1; 224 | inst_ok_1 = 1'd1; 225 | inst_ok_2 = ~(&inst_offset); 226 | inst_data_1 = icache_return_data[inst_offset]; 227 | inst_data_2 = &inst_offset? 32'd0 : icache_return_data[inst_offset + 4'd1]; 228 | end 229 | else begin // Cache miss 230 | cache_miss = 1'd1; 231 | iaddr_req = {iaddr_psy[31:6], 6'd0}; 232 | read_en = 1'd1; 233 | mmu_running = 1'd1; 234 | read_type = 1'd0; 235 | if(iaddr_req_ok) begin 236 | nstate = CACHED_WAIT; 237 | end 238 | else begin 239 | nstate = CACHED_SHAKE; 240 | end 241 | end 242 | end 243 | CACHECTRL_WAIT: begin 244 | nstate = IDLE; 245 | end 246 | UNCACHED_SHAKE: begin 247 | iaddr_req = iaddr_psy; 248 | read_en = 1'd1; 249 | mmu_running = 1'd1; 250 | read_type = 1'd1; 251 | if(iaddr_req_ok) begin 252 | nstate = UNCACHED_RETURN; 253 | end 254 | else begin 255 | nstate = UNCACHED_SHAKE; 256 | end 257 | end 258 | UNCACHED_RETURN: begin 259 | inst_ok = idata_rvalid; 260 | inst_ok_1 = idata_rvalid; 261 | inst_data_1 = idata_rdata; 262 | mmu_running = 1'd1; 263 | if(idata_rvalid && idata_rlast) begin 264 | nstate = IDLE; 265 | end 266 | else begin 267 | nstate = UNCACHED_RETURN; 268 | end 269 | end 270 | CACHED_SHAKE: begin 271 | iaddr_req = {iaddr_psy[31:6], 6'd0}; 272 | read_en = 1'd1; 273 | read_type = 1'd0; 274 | mmu_running = 1'd1; 275 | if(iaddr_req_ok) begin 276 | nstate = CACHED_WAIT; 277 | end 278 | else begin 279 | nstate = CACHED_SHAKE; 280 | end 281 | end 282 | CACHED_WAIT: begin 283 | mmu_running = 1'd1; 284 | if(idata_rvalid && idata_rlast) begin 285 | nstate = CACHED_REFILL; 286 | end 287 | else begin 288 | nstate = CACHED_WAIT; 289 | end 290 | end 291 | CACHED_REFILL: begin 292 | mmu_running = 1'd1; 293 | ram_we = 1'd1; 294 | nstate = IDLE; 295 | 296 | inst_ok = 1'd1; 297 | inst_ok_1 = 1'd1; 298 | inst_ok_2 = ~(&inst_offset); 299 | inst_data_1 = receive_buffer[inst_offset]; 300 | inst_data_2 = &inst_offset? 32'd0 : receive_buffer[inst_offset + 4'd1]; 301 | end 302 | default: begin // Make vivado happy :) 303 | end 304 | endcase 305 | end 306 | 307 | endmodule -------------------------------------------------------------------------------- /hdl/lsu/mmu_top.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module mmu_top( 4 | input clk, 5 | input rst, 6 | // Inst channel 7 | input inst_en, 8 | input [31:0] inst_addr, 9 | input inst_uncached, 10 | output logic inst_ok, 11 | output logic inst_ok_1, 12 | output logic inst_ok_2, 13 | output logic [31:0] inst_data_1, 14 | output logic [31:0] inst_data_2, 15 | // Data channel 16 | input data_en, 17 | input [3:0] data_wen, 18 | input [31:0] data_addr, 19 | input data_uncached, 20 | input [31:0] data_wdata, 21 | input [2:0] data_size, 22 | output logic data_ok, 23 | output logic [31:0] data_data, 24 | 25 | // Cache control 26 | input inst_hit_invalidate, 27 | input data_hit_writeback, 28 | input index_invalidate, 29 | 30 | // AXI 31 | //ar 32 | output logic [3 :0] arid, 33 | output logic [31:0] araddr, 34 | output logic [7 :0] arlen, 35 | output logic [2 :0] arsize, 36 | output logic [1 :0] arburst, 37 | output logic [1 :0] arlock, 38 | output logic [3 :0] arcache, 39 | output logic [2 :0] arprot, 40 | output logic arvalid, 41 | input arready, 42 | //r 43 | input [3 :0] rid, 44 | input [31:0] rdata, 45 | input [1 :0] rresp, 46 | input rlast, 47 | input rvalid, 48 | output logic rready, 49 | //aw 50 | output logic [3 :0] awid, 51 | output logic [31:0] awaddr, 52 | output logic [7 :0] awlen, 53 | output logic [2 :0] awsize, 54 | output logic [1 :0] awburst, 55 | output logic [1 :0] awlock, 56 | output logic [3 :0] awcache, 57 | output logic [2 :0] awprot, 58 | output logic awvalid, 59 | input awready, 60 | //w 61 | output logic [3 :0] wid, 62 | output logic [31:0] wdata, 63 | output logic [3 :0] wstrb, 64 | output logic wlast, 65 | output logic wvalid, 66 | input wready, 67 | //b 68 | input [3 :0] bid, 69 | input [1 :0] bresp, 70 | input bvalid, 71 | output logic bready 72 | ); 73 | 74 | // Set default value 75 | assign arid = 4'd0; 76 | assign arlock = 2'd0; 77 | assign arcache = 4'd0; 78 | assign arprot = 3'd0; 79 | 80 | assign rready = 1'b1; 81 | 82 | assign awid = 4'd0; 83 | assign awlock = 2'd0; 84 | assign awcache = 4'd0; 85 | assign awprot = 3'd0; 86 | 87 | assign wid = 4'd0; 88 | assign bready = 1'b1; 89 | 90 | // Addr tran 91 | logic [31:0] iaddr_psy, daddr_psy; 92 | logic iaddr_type, daddr_type; 93 | 94 | always_comb begin 95 | iaddr_psy = inst_addr; 96 | iaddr_type = inst_uncached; 97 | daddr_psy = data_addr; 98 | daddr_type = data_uncached; 99 | end 100 | 101 | // Inst channel 102 | wire inst_running; 103 | wire [31:0] iaddr_req; 104 | wire iread_en; 105 | wire iread_type; 106 | logic iaddr_req_ok; 107 | logic[31:0] idata_rdata; 108 | logic idata_rvalid; 109 | logic idata_rlast; 110 | 111 | mmu_inst inst_ctrl( 112 | .clk (clk), 113 | .rst (rst), 114 | .ien (inst_en), 115 | .iaddr_psy (inst_hit_invalidate? daddr_psy : iaddr_psy), 116 | .iaddr_type (iaddr_type), 117 | .inst_ok (inst_ok), 118 | .inst_ok_1 (inst_ok_1), 119 | .inst_ok_2 (inst_ok_2), 120 | .inst_data_1 (inst_data_1), 121 | .inst_data_2 (inst_data_2), 122 | .iaddr_req (iaddr_req), 123 | .read_en (iread_en), 124 | .read_type (iread_type), 125 | .iaddr_req_ok (iaddr_req_ok), 126 | .idata_rdata (idata_rdata), 127 | .idata_rvalid (idata_rvalid), 128 | .idata_rlast (idata_rlast), 129 | .mmu_running (inst_running), 130 | .inst_hit_invalidate(inst_hit_invalidate), 131 | .index_invalidate(index_invalidate) 132 | ); 133 | 134 | // Data channel 135 | wire data_running; 136 | wire [31:0] daddr_req; 137 | wire dread_en; 138 | wire dread_type; 139 | logic daddr_req_ok; 140 | logic[31:0] ddata_rdata; 141 | logic ddata_rvalid; 142 | logic ddata_rlast; 143 | 144 | wire [31:0] daddr_wreq; 145 | wire write_en; 146 | wire write_type; 147 | wire [3:0] write_byte_en; 148 | wire dwvalid; 149 | wire [31:0] dwdata; 150 | wire dwlast; 151 | logic daddr_wreq_ok; 152 | logic ddata_wready; 153 | logic ddata_bvalid; 154 | logic [2:0] data_size_out; 155 | 156 | mmu_data data_ctrl( 157 | .clk (clk), 158 | .rst (rst), 159 | .den (data_en), 160 | .dwen (data_wen), 161 | .daddr_psy (daddr_psy), 162 | .wdata (data_wdata), 163 | .daddr_type (daddr_type), 164 | .data_ok (data_ok), 165 | .data_data (data_data), 166 | .daddr_req (daddr_req), 167 | .read_en (dread_en), 168 | .read_type (dread_type), 169 | .daddr_req_ok (daddr_req_ok), 170 | .ddata_rdata (ddata_rdata), 171 | .ddata_rvalid (ddata_rvalid), 172 | .ddata_rlast (ddata_rlast), 173 | .daddr_wreq (daddr_wreq), 174 | .write_en (write_en), 175 | .write_type (write_type), 176 | .write_byte_en (write_byte_en), 177 | .data_size_in (data_size), 178 | .data_size_out (data_size_out), 179 | .dwvalid (dwvalid), 180 | .dwdata (dwdata), 181 | .dwlast (dwlast), 182 | .daddr_wreq_ok (daddr_wreq_ok), 183 | .ddata_wready (ddata_wready), 184 | .ddata_bvalid (ddata_bvalid), 185 | .mmu_running (data_running), 186 | .data_hit_writeback(data_hit_writeback), 187 | .index_invalidate(index_invalidate) 188 | ); 189 | 190 | // Read channel 191 | always_comb begin 192 | if((iread_en && inst_running && dread_en && data_running) || (data_running && ~dread_en && inst_running) || (data_running && ~inst_running)) begin // Data first 193 | araddr = daddr_req; 194 | arlen = dread_type ? 8'd0 : 8'd15; 195 | arburst = dread_type ? 2'd0 : 2'd1; 196 | arvalid = dread_en; 197 | daddr_req_ok = arready; 198 | ddata_rdata = rdata; 199 | ddata_rvalid = rvalid; 200 | ddata_rlast = rlast; 201 | iaddr_req_ok = 1'd0; 202 | idata_rdata = 32'd0; 203 | idata_rvalid = 1'd0; 204 | idata_rlast = 1'd0; 205 | arsize = dread_type ? data_size : 3'b010; 206 | end 207 | else begin 208 | araddr = iaddr_req; 209 | arlen = iread_type ? 8'd0 : 8'd15; 210 | arburst = iread_type ? 2'd0 : 2'd1; 211 | arsize = 3'b010; 212 | arvalid = iread_en; 213 | iaddr_req_ok = arready; 214 | idata_rdata = rdata; 215 | idata_rvalid = rvalid; 216 | idata_rlast = rlast; 217 | daddr_req_ok = 1'd0; 218 | ddata_rdata = 32'd0; 219 | ddata_rvalid = 1'd0; 220 | ddata_rlast = 1'd0; 221 | end 222 | end 223 | 224 | // Write channel 225 | always_comb begin 226 | awaddr = daddr_wreq; 227 | awlen = write_type ? 8'd0 : 8'd15; 228 | awburst = write_type ? 2'd0 : 2'd1; 229 | awvalid = write_en; 230 | wstrb = write_byte_en; 231 | wdata = dwdata; 232 | wvalid = dwvalid; 233 | wlast = dwlast; 234 | daddr_wreq_ok = awready; 235 | ddata_wready = wready; 236 | ddata_bvalid = bvalid; 237 | awsize = write_type ? data_size_out : 3'b010; 238 | end 239 | 240 | endmodule -------------------------------------------------------------------------------- /hdl/mmu/mmu_map.sv: -------------------------------------------------------------------------------- 1 | module mmu_map( 2 | input clk, 3 | input rst, 4 | 5 | input en, 6 | input [31:0] vaddr, 7 | input user_mode, 8 | input cp0_kseg0_uncached, 9 | 10 | output logic [31:0] paddr, 11 | output logic addr_invalid, 12 | output logic addr_uncached, 13 | output logic addr_in_tlb 14 | ); 15 | 16 | assign addr_invalid = (en && user_mode && vaddr[31]); 17 | 18 | always_comb begin : get_psy_addr_directly 19 | paddr = 32'd0; 20 | addr_uncached = 1'd0; 21 | addr_in_tlb = 1'd0; 22 | if (en) begin 23 | unique case(vaddr[31:29]) 24 | 3'b100: begin // kseg0 25 | addr_uncached = cp0_kseg0_uncached; 26 | paddr = { 3'b0, vaddr[28:0]}; 27 | end 28 | 3'b101: begin // kseg1 29 | addr_uncached = 1; 30 | paddr = { 3'b0, vaddr[28:0]}; 31 | end 32 | default: begin // kseg2, kseg3 and kuseg 33 | addr_in_tlb = 1'b1; 34 | end 35 | endcase 36 | end 37 | end 38 | endmodule -------------------------------------------------------------------------------- /hdl/mmu/mmu_map_top.sv: -------------------------------------------------------------------------------- 1 | module mmu_map_top( 2 | input clk, 3 | input rst, 4 | 5 | input tlbwi, 6 | input tlbwr, 7 | input tlbp, 8 | 9 | input [31:0] iaddr, 10 | input inst_en, 11 | output logic [31:0] iaddr_psy, 12 | output logic inst_uncached, 13 | output logic inst_miss, 14 | output logic inst_illegal, 15 | output logic inst_tlb_invalid, 16 | 17 | input [31:0] daddr, 18 | input data_en, 19 | output logic [31:0] daddr_psy, 20 | output logic data_uncached, 21 | output logic data_miss, 22 | output logic data_illegal, 23 | output logic data_tlb_invalid, 24 | output logic data_dirty, 25 | 26 | output logic miss_probe, 27 | output logic [3:0] matched_index_probe, 28 | 29 | // From/to CP0 30 | input user_mode, 31 | input cp0_kseg0_uncached, 32 | input [7:0] curr_ASID, 33 | input [3:0] cp0_index, 34 | input [3:0] cp0_random, 35 | input [85:0] cp0_tlb_conf_in, 36 | output logic [85:0] cp0_tlb_conf_out 37 | ); 38 | 39 | 40 | wire [31:0] ipaddr_direct; 41 | wire [31:0] dpaddr_direct; 42 | wire [31:0] ipaddr_tlb; 43 | wire [31:0] dpaddr_tlb; 44 | 45 | wire iaddr_uncached_direct; 46 | wire daddr_uncached_direct; 47 | 48 | wire iaddr_in_tlb; 49 | wire daddr_in_tlb; 50 | 51 | logic miss_inst; 52 | logic valid_inst; 53 | logic dirty_inst; 54 | logic uncached_inst; 55 | 56 | logic miss_data; 57 | logic valid_data; 58 | logic dirty_data; 59 | logic uncached_data; 60 | 61 | assign iaddr_psy = iaddr_in_tlb ? ipaddr_tlb : ipaddr_direct; 62 | assign inst_uncached = iaddr_in_tlb ? uncached_inst : iaddr_uncached_direct; 63 | assign inst_miss = iaddr_in_tlb && miss_inst; 64 | assign inst_tlb_invalid = iaddr_in_tlb && ~valid_inst; 65 | 66 | assign daddr_psy = daddr_in_tlb ? dpaddr_tlb : dpaddr_direct; 67 | assign data_uncached = daddr_in_tlb ? uncached_data : daddr_uncached_direct; 68 | assign data_miss = daddr_in_tlb && miss_data; 69 | assign data_tlb_invalid = daddr_in_tlb && ~valid_data; 70 | assign data_dirty = ~daddr_in_tlb || dirty_data; 71 | 72 | mmu_map mmu_map_inst( 73 | .clk (clk), 74 | .rst (rst), 75 | .en (inst_en), 76 | .vaddr (iaddr), 77 | .user_mode (user_mode), 78 | .cp0_kseg0_uncached (cp0_kseg0_uncached), 79 | .paddr (ipaddr_direct), 80 | .addr_invalid (inst_illegal), 81 | .addr_uncached (iaddr_uncached_direct), 82 | .addr_in_tlb (iaddr_in_tlb) 83 | ); 84 | 85 | mmu_map mmu_map_data( 86 | .clk (clk), 87 | .rst (rst), 88 | .en (data_en), 89 | .vaddr (daddr), 90 | .user_mode (user_mode), 91 | .cp0_kseg0_uncached (cp0_kseg0_uncached), 92 | .paddr (dpaddr_direct), 93 | .addr_invalid (data_illegal), 94 | .addr_uncached (daddr_uncached_direct), 95 | .addr_in_tlb (daddr_in_tlb) 96 | ); 97 | 98 | tlb_top tlb( 99 | .clk (clk), 100 | .rst (rst), 101 | .tlbwi (tlbwi), 102 | .tlbwr (tlbwr), 103 | .tlbp (tlbp), 104 | .curr_ASID (curr_ASID), 105 | .vaddr_inst (iaddr), 106 | .paddr_inst (ipaddr_tlb), 107 | .miss_inst (miss_inst), 108 | .valid_inst (valid_inst), 109 | .dirty_inst (dirty_inst), 110 | .uncached_inst (uncached_inst), 111 | .vaddr_data (daddr), 112 | .paddr_data (dpaddr_tlb), 113 | .miss_data (miss_data), 114 | .valid_data (valid_data), 115 | .dirty_data (dirty_data), 116 | .uncached_data (uncached_data), 117 | .miss_probe (miss_probe), 118 | .matched_index_probe (matched_index_probe), 119 | .cp0_index (cp0_index), 120 | .cp0_random (cp0_random), 121 | .cp0_tlb_conf_in (cp0_tlb_conf_in), 122 | .cp0_tlb_conf_out (cp0_tlb_conf_out) 123 | ); 124 | 125 | endmodule -------------------------------------------------------------------------------- /hdl/mmu/tlb_common.sv: -------------------------------------------------------------------------------- 1 | module tlb_common( 2 | input clk, 3 | input rst, 4 | 5 | input tlbwi, 6 | input tlbwr, 7 | 8 | input [7:0] curr_ASID, 9 | input [31:0] vaddr, 10 | output logic [31:0] paddr, 11 | 12 | output logic miss, 13 | output logic valid, 14 | output logic dirty, 15 | output logic uncached, 16 | output logic [3:0] matched_index, 17 | 18 | // Connects to CP0 19 | input [3:0] cp0_index, 20 | input [3:0] cp0_random, 21 | input [85:0] cp0_tlb_conf_in, 22 | output logic [85:0] cp0_tlb_conf_out 23 | ); 24 | 25 | reg [85:0] tlb_data[0:15]; 26 | assign cp0_tlb_conf_out = tlb_data[cp0_index]; 27 | 28 | // Cache registers 29 | // VPN2 19bits [85:67] 30 | // G 1bits 66 31 | // ASID 8bits [65:58] 32 | // PFN0 24bits [57:34] 33 | // C 3bits [33:31] 34 | // D 1bits 30 35 | // V 1bits 29 36 | // PFN1 24bits [28:5] 37 | // C 3bits [4:2] 38 | // D 1bits 1 39 | // V 1bits 0 40 | always_ff @(posedge clk) begin 41 | if(rst) begin 42 | for(int i = 0; i < 16; i++) 43 | tlb_data[i] <= 86'd0; 44 | end 45 | else if(tlbwi) 46 | tlb_data[cp0_index] <= cp0_tlb_conf_in; 47 | else if(tlbwr) 48 | tlb_data[cp0_random] <= cp0_tlb_conf_in; 49 | end 50 | 51 | logic [15:0] matched; 52 | always_comb begin 53 | for(int i = 0; i < 16; i++) 54 | matched[i] = (vaddr[31:13] == tlb_data[i][85:67]) && 55 | (tlb_data[i][65:58] == curr_ASID || tlb_data[i][66]); 56 | end 57 | 58 | always_comb begin 59 | matched_index = 4'd0; 60 | for(int i = 0; i < 16; i++) begin 61 | if(matched[i]) begin 62 | matched_index = i; 63 | end 64 | end 65 | end 66 | 67 | assign miss = (matched == 16'd0); 68 | assign valid = miss? 1'd1 : (vaddr[12] ? tlb_data[matched_index][0] : tlb_data[matched_index][29]); 69 | assign dirty = vaddr[12] ? tlb_data[matched_index][1] : tlb_data[matched_index][30]; 70 | assign uncached = vaddr[12] ? (tlb_data[matched_index][4:2] == 3'd2) : (tlb_data[matched_index][33:31] == 3'd2); 71 | assign paddr = vaddr[12] ? {tlb_data[matched_index][24:5], vaddr[11:0]} : {tlb_data[matched_index][53:34],vaddr[11:0]}; 72 | 73 | endmodule -------------------------------------------------------------------------------- /hdl/mmu/tlb_top.sv: -------------------------------------------------------------------------------- 1 | module tlb_top( 2 | input clk, 3 | input rst, 4 | 5 | input tlbwi, 6 | input tlbwr, 7 | input tlbp, 8 | 9 | input [7:0] curr_ASID, 10 | 11 | input [31:0] vaddr_inst, 12 | output logic [31:0] paddr_inst, 13 | output logic miss_inst, 14 | output logic valid_inst, 15 | output logic dirty_inst, 16 | output logic uncached_inst, 17 | 18 | input [31:0] vaddr_data, 19 | output logic [31:0] paddr_data, 20 | output logic miss_data, 21 | output logic valid_data, 22 | output logic dirty_data, 23 | output logic uncached_data, 24 | 25 | output logic miss_probe, 26 | output logic [3:0] matched_index_probe, 27 | 28 | // Connects to CP0 29 | input [3:0] cp0_index, 30 | input [3:0] cp0_random, 31 | input [85:0] cp0_tlb_conf_in, 32 | output logic [85:0] cp0_tlb_conf_out 33 | ); 34 | 35 | tlb_common tlb_inst( 36 | .clk (clk), 37 | .rst (rst), 38 | .tlbwi (tlbwi), 39 | .tlbwr (tlbwr), 40 | .curr_ASID (curr_ASID), 41 | .vaddr (vaddr_inst), 42 | .paddr (paddr_inst), 43 | .miss (miss_inst), 44 | .valid (valid_inst), 45 | .dirty (dirty_inst), 46 | .uncached (uncached_inst), 47 | .cp0_index (cp0_index), 48 | .cp0_random (cp0_random), 49 | .cp0_tlb_conf_in (cp0_tlb_conf_in), 50 | .cp0_tlb_conf_out (cp0_tlb_conf_out) 51 | ); 52 | 53 | tlb_common tlb_data( 54 | .clk (clk), 55 | .rst (rst), 56 | .tlbwi (tlbwi), 57 | .tlbwr (tlbwr), 58 | .curr_ASID (curr_ASID), 59 | .vaddr (vaddr_data), 60 | .paddr (paddr_data), 61 | .miss (miss_data), 62 | .valid (valid_data), 63 | .dirty (dirty_data), 64 | .uncached (uncached_data), 65 | .cp0_index (cp0_index), 66 | .cp0_random (cp0_random), 67 | .cp0_tlb_conf_in (cp0_tlb_conf_in) 68 | ); 69 | 70 | tlb_common tlb_probe( 71 | .clk (clk), 72 | .rst (rst), 73 | .tlbwi (tlbwi), 74 | .tlbwr (tlbwr), 75 | .curr_ASID (curr_ASID), 76 | .vaddr ({cp0_tlb_conf_in[85:67],13'd0}), 77 | .miss (miss_probe), 78 | .matched_index (matched_index_probe), 79 | .cp0_index (cp0_index), 80 | .cp0_random (cp0_random), 81 | .cp0_tlb_conf_in (cp0_tlb_conf_in) 82 | ); 83 | 84 | endmodule -------------------------------------------------------------------------------- /hdl/mycpu_top.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module mycpu_top( 4 | input [4 :0] int, 5 | input aclk, 6 | input aresetn, 7 | 8 | //axi 9 | //ar 10 | output [3 :0] arid , 11 | output [31:0] araddr , 12 | output [7 :0] arlen , 13 | output [2 :0] arsize , 14 | output [1 :0] arburst , 15 | output [1 :0] arlock , 16 | output [3 :0] arcache , 17 | output [2 :0] arprot , 18 | output arvalid , 19 | input arready , 20 | //r 21 | input [3 :0] rid , 22 | input [31:0] rdata , 23 | input [1 :0] rresp , 24 | input rlast , 25 | input rvalid , 26 | output rready , 27 | //aw 28 | output [3 :0] awid , 29 | output [31:0] awaddr , 30 | output [7 :0] awlen , 31 | output [2 :0] awsize , 32 | output [1 :0] awburst , 33 | output [1 :0] awlock , 34 | output [3 :0] awcache , 35 | output [2 :0] awprot , 36 | output awvalid , 37 | input awready , 38 | //w 39 | output [3 :0] wid , 40 | output [31:0] wdata , 41 | output [3 :0] wstrb , 42 | output wlast , 43 | output wvalid , 44 | input wready , 45 | //b 46 | input [3 :0] bid , 47 | input [1 :0] bresp , 48 | input bvalid , 49 | output bready 50 | ); 51 | 52 | wire ien, iok, iok1, iok2, den, dok; 53 | wire [ 3:0] dwen; 54 | wire [31:0] iaddr_i, idata_i, idata2_i, daddr_i, drdata_i, dwdata_i; 55 | wire inst_uncached, data_uncached; 56 | wire inst_hit_invalidate, data_hit_writeback, index_invalidate; 57 | wire [2:0] data_size; 58 | mmu_top mmu_0( 59 | .clk (aclk), 60 | .rst (~aresetn), 61 | .inst_en (ien), 62 | .inst_addr (iaddr_i), 63 | .inst_data_1 (idata_i), 64 | .inst_ok (iok), 65 | .inst_ok_1 (iok1), 66 | .inst_ok_2 (iok2), 67 | .inst_data_2 (idata2_i), 68 | 69 | .data_en (den), 70 | .data_wen (dwen), 71 | .data_addr (daddr_i), 72 | .data_wdata (dwdata_i), 73 | .data_data (drdata_i), 74 | .data_ok (dok), 75 | .data_size (data_size), 76 | 77 | .inst_uncached (inst_uncached), 78 | .data_uncached (data_uncached), 79 | .inst_hit_invalidate(inst_hit_invalidate), 80 | .data_hit_writeback (data_hit_writeback), 81 | .index_invalidate (index_invalidate), 82 | 83 | .arid (arid), 84 | .araddr (araddr), 85 | .arlen (arlen), 86 | .arsize (arsize), 87 | .arburst (arburst), 88 | .arlock (arlock), 89 | .arcache (arcache), 90 | .arprot (arprot), 91 | .arvalid (arvalid), 92 | .arready (arready), 93 | .rid (rid), 94 | .rdata (rdata), 95 | .rresp (rresp), 96 | .rlast (rlast), 97 | .rvalid (rvalid), 98 | .rready (rready), 99 | .awid (awid), 100 | .awaddr (awaddr), 101 | .awlen (awlen), 102 | .awsize (awsize), 103 | .awburst (awburst), 104 | .awlock (awlock), 105 | .awcache (awcache), 106 | .awprot (awprot), 107 | .awvalid (awvalid), 108 | .awready (awready), 109 | .wid (wid), 110 | .wdata (wdata), 111 | .wstrb (wstrb), 112 | .wlast (wlast), 113 | .wvalid (wvalid), 114 | .wready (wready), 115 | .bid (bid), 116 | .bresp (bresp), 117 | .bvalid (bvalid), 118 | .bready (bready) 119 | ); 120 | 121 | sirius cpu( 122 | .clk (aclk), 123 | .rst (~aresetn), 124 | .interrupt (int), 125 | .inst_en (ien), 126 | .inst_addr (iaddr_i), 127 | .inst_data_1 (idata_i), 128 | .inst_ok (iok), 129 | .inst_ok_1 (iok1), 130 | .inst_ok_2 (iok2), 131 | .inst_data_2 (idata2_i), 132 | 133 | .data_en (den), 134 | .data_wen (dwen), 135 | .data_addr (daddr_i), 136 | .data_wdata (dwdata_i), 137 | .data_data (drdata_i), 138 | .data_ok (dok), 139 | .data_size (data_size), 140 | 141 | .inst_uncached (inst_uncached), 142 | .data_uncached (data_uncached), 143 | 144 | .inst_hit_invalidate(inst_hit_invalidate), 145 | .data_hit_writeback (data_hit_writeback), 146 | .index_invalidate (index_invalidate) 147 | ); 148 | 149 | endmodule 150 | -------------------------------------------------------------------------------- /hdl/reg/cp0.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | // The COP0 3 | module cp0( 4 | input clk, 5 | input rst, 6 | 7 | input [4:0] hint, 8 | input [7:0] raddr, 9 | output logic [31:0] rdata, 10 | 11 | input wen, 12 | input [7:0] waddr, 13 | input [31:0] wdata, 14 | 15 | // Exceptions 16 | input exp_en, 17 | input exp_badvaddr_en, 18 | input [31:0] exp_badvaddr, 19 | input exp_bd, 20 | input [4:0] exp_code, 21 | input [31:0] exp_epc, 22 | input exl_clean, 23 | input exp_asid_en, 24 | input [7:0] exp_asid, 25 | 26 | 27 | // TLB instructions 28 | input tlbr, 29 | input tlbp, 30 | 31 | // TLB... 32 | input miss_probe, 33 | input [3:0] matched_index_probe, 34 | output logic user_mode, 35 | output logic cp0_kseg0_uncached, 36 | output logic [7:0] curr_ASID, 37 | output logic [3:0] cp0_index, 38 | output logic [3:0] cp0_random, 39 | output logic [85:0] cp0_tlb_conf_out, 40 | input [85:0] cp0_tlb_conf_in, 41 | 42 | // MIPS32r1 43 | output logic [31:0] ebase_address, 44 | output logic use_special_iv, 45 | output logic use_bootstrap_iv, 46 | output logic exl_set, 47 | 48 | output logic [31:0] epc_address, 49 | output logic allow_interrupt, 50 | output logic [7:0] interrupt_flag 51 | ); 52 | 53 | // Control register definition\ 54 | reg [31:0] Index; // 0 0 55 | reg [31:0] Random; // 1 0 -- NEW 56 | reg [31:0] EntryLo0; // 2 0 57 | reg [31:0] EntryLo1; // 3 0 58 | reg [31:0] Context; // 4 0 -- NEW 59 | reg [31:0] Wired; // 6 0 -- NEW 60 | reg [31:0] BadVAddr; // 8 0 61 | reg [32:0] Count; // 9 0 62 | reg [31:0] EntryHi; // 10 0 63 | reg [31:0] Compare; // 11 0 64 | reg [31:0] Status; // 12 0 65 | reg [31:0] Cause; // 13 0 66 | reg [31:0] EPC; // 14 0 67 | reg [31:0] PRId; // 15 0 -- NEW 68 | reg [31:0] EBase; // 15 1 -- NEW 69 | reg [31:0] Config; // 16 0 -- NEW 70 | reg [31:0] Config1; // 16 1 -- NEW 71 | 72 | assign epc_address = EPC; 73 | assign allow_interrupt = Status[2:0] == 3'b001; 74 | assign interrupt_flag = Status[15:8] & Cause[15:8]; 75 | assign curr_ASID = EntryHi[7:0]; 76 | assign cp0_index = Index[3:0]; 77 | assign cp0_random = {28'd0, Random[3:0]}; 78 | assign user_mode = Status[4:1]==4'b1000; 79 | assign cp0_kseg0_uncached = Config[2:0] == 3'd2; 80 | assign cp0_tlb_conf_out = { EntryHi[31:13], EntryLo0[0] && EntryLo1[0], EntryHi[7:0], EntryLo0[29:1], EntryLo1[29:1]}; 81 | assign ebase_address = EBase; 82 | assign use_special_iv = Cause[23]; 83 | assign use_bootstrap_iv = Status[22]; 84 | assign exl_set = Status[1]; 85 | 86 | logic timer_int; 87 | 88 | always_comb begin : cop0_data_read 89 | unique case(raddr) 90 | { 5'd8, 3'd0 }: 91 | rdata = BadVAddr; 92 | { 5'd9, 3'd0 }: 93 | rdata = Count[32:1]; 94 | { 5'd12, 3'd0 }: 95 | rdata = Status; 96 | { 5'd13, 3'd0 }: 97 | rdata = Cause; 98 | { 5'd14, 3'd0 }: 99 | rdata = EPC; 100 | // SiriusG begin 101 | { 5'd10, 3'd0 }: 102 | rdata = EntryHi; 103 | { 5'd1, 3'd0 }: 104 | rdata = {28'd0, Random[3:0]}; 105 | { 5'd2, 3'd0 }: 106 | rdata = EntryLo0; 107 | { 5'd3, 3'd0 }: 108 | rdata = EntryLo1; 109 | { 5'd0, 3'd0 }: 110 | rdata = Index; 111 | { 5'd4, 3'd0 }: 112 | rdata = Context; 113 | { 5'd11, 3'd0 }: 114 | rdata = Compare; 115 | { 5'd15, 3'd0 }: 116 | rdata = PRId; 117 | { 5'd16, 3'd0 }: 118 | rdata = Config; 119 | { 5'd16, 3'd1 }: 120 | rdata = Config1; 121 | { 5'd6, 3'd0 }: 122 | rdata = Wired; 123 | { 5'd15, 3'd1 }: 124 | rdata = EBase; 125 | // SiriusG end 126 | default: 127 | rdata = 32'd0; 128 | endcase 129 | end 130 | 131 | always_ff @(posedge clk) begin : cop0_data_update 132 | if(rst) begin 133 | Count <= 32'd0; 134 | Status <= 32'h1040_0004; 135 | Cause <= 32'd0; 136 | EntryHi <= 32'd0; 137 | EntryLo0[31:30] <= 2'd0; 138 | EntryLo1[31:30] <= 2'd0; 139 | EBase <= 32'h8000_0000; 140 | Index <= 32'd0; 141 | Context <= 32'd0; 142 | Compare <= 32'd0; 143 | Context <= 32'd0; 144 | PRId <= 32'h0001_8000; // MIPS 4KC 145 | Config <= {1'b1, 21'b0, 3'b1, 7'b0}; // MIPS32R1 146 | Config1 <= {1'd0, 6'd15, 3'd1, 3'd5, 3'd0, 3'd1, 3'd5, 3'd0, 7'd0}; 147 | timer_int <= 1'd0; 148 | Wired <= 32'd0; 149 | Random <= 32'd0; 150 | end 151 | else begin 152 | Cause[15:10] <= {timer_int,hint}; 153 | Count <= Count + 33'd1; 154 | Random <= Wired + Count[31:0]; 155 | if(Compare != 32'd0 && Compare == Count[32:1]) 156 | timer_int <= 1'd1; 157 | if(wen) begin 158 | unique case(waddr) 159 | { 5'd9, 3'd0 }: 160 | Count <= {wdata, 1'b0}; 161 | { 5'd12, 3'd0}: begin 162 | Status[28] <= wdata[28]; 163 | Status[22] <= wdata[22]; 164 | Status[15:8] <= wdata[15:8]; 165 | Status[4] <= wdata[4]; 166 | Status[2:0] <= wdata[2:0]; 167 | end 168 | { 5'd13 , 3'd0 }: begin 169 | Cause[9:8] <= wdata[9:8]; 170 | Cause[23] <= wdata[23]; 171 | end 172 | { 5'd14 , 3'd0 }: 173 | EPC <= wdata; 174 | { 5'd10, 3'd0}: begin 175 | EntryHi[31:13] <= wdata[31:13]; 176 | EntryHi[7:0] <= wdata[7:0]; 177 | end 178 | { 5'd2 , 3'd0 }: 179 | EntryLo0[29:0] <= wdata[29:0]; 180 | { 5'd3 , 3'd0 }: 181 | EntryLo1[29:0] <= wdata[29:0]; 182 | { 5'd0, 5'd0 }: 183 | Index[3:0] <= wdata[3:0]; // Only 16 entries here... 184 | { 5'd4, 3'd0 }: 185 | Context[31:13] <= wdata[31:13]; 186 | { 5'd11, 3'd0 }: begin 187 | Compare <= wdata; 188 | timer_int <= 1'd0; 189 | end 190 | { 5'd16, 3'd1 }: begin 191 | Config[2:0] <= wdata[2:0]; 192 | end 193 | { 5'd6, 3'd0 }: begin 194 | Wired[3:0] <= wdata[3:0]; 195 | end 196 | { 5'd15, 3'd1 }: begin 197 | EBase[29:12] <= wdata[29:12]; 198 | EBase[9:0] <= wdata[9:0]; 199 | end 200 | default: begin 201 | // Make vivado happy. :) 202 | end 203 | endcase 204 | end 205 | if(exp_en) begin 206 | if(exp_badvaddr_en) 207 | BadVAddr <= exp_badvaddr; 208 | if(exp_asid_en) 209 | EntryHi[7:0] <= exp_asid; 210 | Context[22:4] <= exp_badvaddr[31:13]; 211 | EntryHi[31:13] <= exp_badvaddr[31:13]; 212 | Status[1] <= ~exl_clean; 213 | Cause[31] <= exp_bd; 214 | Cause[6:2] <= exp_code; 215 | EPC <= exp_epc; 216 | end 217 | if(tlbr) begin 218 | EntryHi[31:13] <= cp0_tlb_conf_in[85:67]; 219 | EntryHi[7:0] <= cp0_tlb_conf_in[65:58]; 220 | EntryLo0 <= {2'd0,cp0_tlb_conf_in[57:29],cp0_tlb_conf_in[66]}; 221 | EntryLo1 <= {2'd0,cp0_tlb_conf_in[28:0],cp0_tlb_conf_in[66]}; 222 | end 223 | if(tlbp) begin 224 | Index[3:0] <= matched_index_probe; 225 | Index[31] <= miss_probe; 226 | end 227 | end 228 | end 229 | endmodule -------------------------------------------------------------------------------- /hdl/reg/forwarding_unit.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module forwarding_unit( 4 | input slave_ex_reg_en, 5 | input [ 4:0] slave_ex_addr, 6 | input [31:0] slave_ex_data, 7 | input master_ex_reg_en, 8 | input [ 4:0] master_ex_addr, 9 | input [31:0] master_ex_data, 10 | input slave_mem_reg_en, 11 | input [ 4:0] slave_mem_addr, 12 | input [31:0] slave_mem_data, 13 | input master_mem_reg_en, 14 | input [ 4:0] master_mem_addr, 15 | input [31:0] master_mem_data, 16 | input [ 4:0] reg_addr, 17 | input [31:0] reg_data, 18 | output logic [31:0] result_data 19 | ); 20 | 21 | always_comb begin : get_result 22 | if(reg_addr != 32'd0) begin 23 | if(slave_ex_reg_en && slave_ex_addr == reg_addr) 24 | result_data = slave_ex_data; 25 | else if(master_ex_reg_en && master_ex_addr == reg_addr) 26 | result_data = master_ex_data; 27 | else if(slave_mem_reg_en && slave_mem_addr == reg_addr) 28 | result_data = slave_mem_data; 29 | else if(master_mem_reg_en && master_mem_addr == reg_addr) 30 | result_data = master_mem_data; 31 | else 32 | result_data = reg_data; 33 | end 34 | else begin 35 | result_data = 32'd0; 36 | end 37 | end 38 | 39 | endmodule -------------------------------------------------------------------------------- /hdl/reg/hilo.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module hilo( 4 | input clk, 5 | input rst, 6 | 7 | input hilo_wen_wb, 8 | input [63:0] hilo_result_wb, 9 | 10 | input hilo_wen_mem, 11 | input [63:0] hilo_result_mem, 12 | 13 | output logic [63:0] hilo_value 14 | ); 15 | 16 | reg [63:0] hilo_register; 17 | 18 | always_ff @(posedge clk) begin : write_to_hilo 19 | if(rst) 20 | hilo_register <= 64'd0; 21 | else if(hilo_wen_wb) 22 | hilo_register <= hilo_result_wb; 23 | end 24 | 25 | always_comb begin : select_output 26 | if(hilo_wen_mem) 27 | hilo_value = hilo_result_mem; 28 | else if(hilo_wen_wb) 29 | hilo_value = hilo_result_wb; 30 | else 31 | hilo_value = hilo_register; 32 | end 33 | 34 | endmodule -------------------------------------------------------------------------------- /hdl/reg/register.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | // The register file. 3 | // Note that when both pipelines try to 4 | // write to the same port, the slave pipeline 5 | // has a higher priority. 6 | module register( 7 | input clk, 8 | input rst, 9 | 10 | input [4:0] raddr1_a, 11 | output logic [31:0] rdata1_a, 12 | 13 | input [4:0] raddr1_b, 14 | output logic [31:0] rdata1_b, 15 | 16 | input wen1_a, 17 | input [4:0] waddr1_a, 18 | input [31:0] wdata1_a, 19 | 20 | input [4:0] raddr2_a, 21 | output logic [31:0] rdata2_a, 22 | 23 | input [4:0] raddr2_b, 24 | output logic [31:0] rdata2_b, 25 | 26 | input wen2_a, 27 | input [4:0] waddr2_a, 28 | input [31:0] wdata2_a 29 | ); 30 | 31 | reg [31:0] _register[0:31]; 32 | 33 | always_comb begin : read_data1_a 34 | if(raddr1_a == 5'b00000) 35 | rdata1_a = 32'h0000_0000; 36 | else if(wen2_a && waddr2_a == raddr1_a) 37 | rdata1_a = wdata2_a; 38 | else if(wen1_a && waddr1_a == raddr1_a) 39 | rdata1_a = wdata1_a; 40 | else 41 | rdata1_a = _register[raddr1_a]; 42 | end 43 | 44 | always_comb begin : read_data1_b 45 | if(raddr1_b == 5'b00000) 46 | rdata1_b = 32'h0000_0000; 47 | else if(wen2_a && waddr2_a == raddr1_b) 48 | rdata1_b = wdata2_a; 49 | else if(wen1_a && waddr1_a == raddr1_b) 50 | rdata1_b = wdata1_a; 51 | else 52 | rdata1_b = _register[raddr1_b]; 53 | end 54 | 55 | always_comb begin : read_data2_a 56 | if(raddr2_a == 5'b00000) 57 | rdata2_a = 32'h0000_0000; 58 | else if(wen2_a && waddr2_a == raddr2_a) 59 | rdata2_a = wdata2_a; 60 | else if(wen1_a && waddr1_a == raddr2_a) 61 | rdata2_a = wdata1_a; 62 | else 63 | rdata2_a = _register[raddr2_a]; 64 | end 65 | 66 | always_comb begin : read_data2_b 67 | if(raddr2_b == 5'b00000) 68 | rdata2_b = 32'h0000_0000; 69 | else if(wen2_a && waddr2_a == raddr2_b) 70 | rdata2_b = wdata2_a; 71 | else if(wen1_a && waddr1_a == raddr2_b) 72 | rdata2_b = wdata1_a; 73 | else 74 | rdata2_b = _register[raddr2_b]; 75 | end 76 | 77 | always_ff @(posedge clk) begin : write_data 78 | if(rst) begin 79 | for(int i = 0; i < 31; i++) 80 | _register[i] <= 32'h0000_0000; 81 | end 82 | else begin 83 | if(wen1_a && wen2_a && waddr1_a == waddr2_a) 84 | _register[waddr2_a] <= wdata2_a; 85 | else begin 86 | if(wen1_a) 87 | _register[waddr1_a] <= wdata1_a; 88 | if(wen2_a) 89 | _register[waddr2_a] <= wdata2_a; 90 | end 91 | end 92 | end 93 | endmodule 94 | -------------------------------------------------------------------------------- /hdl/reg/writeback_alpha.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "common.vh" 3 | module writeback_alpha( 4 | input clk, 5 | input rst, 6 | input [31:0] result, 7 | input [31:0] pc_address, 8 | input [4:0] reg_dest, 9 | input write_en, 10 | input branch_link, 11 | 12 | output logic reg_write_en, 13 | output logic [4:0] reg_write_dest, 14 | output logic [31:0] reg_write_data 15 | ); 16 | 17 | always_comb begin : generate_output 18 | if(branch_link) begin 19 | reg_write_dest = 5'h1f; 20 | reg_write_data = pc_address + 32'd8; 21 | reg_write_en = 1'b1; 22 | end 23 | else begin 24 | reg_write_en = write_en; 25 | reg_write_dest = reg_dest; 26 | reg_write_data = result; 27 | end 28 | end 29 | endmodule 30 | -------------------------------------------------------------------------------- /hdl/reg/writeback_beta.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `include "common.vh" 3 | module writeback_beta( 4 | input [31:0] result, 5 | input [4:0] reg_dest, 6 | input write_en, 7 | 8 | output logic reg_write_en, 9 | output logic [4:0] reg_write_dest, 10 | output logic [31:0] reg_write_data 11 | ); 12 | 13 | always_comb begin : generate_output 14 | reg_write_en = write_en; 15 | reg_write_dest = reg_dest; 16 | reg_write_data = result; 17 | end 18 | 19 | endmodule 20 | --------------------------------------------------------------------------------