├── .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 | 
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 |
--------------------------------------------------------------------------------