Commit bec01f1540e932d0348d38758e0917d520972412
1 parent
c6a7a29337
Exists in
master
and in
5 other branches
Release v1.3 Mips_core extracted.
Showing 9 changed files with 973 additions and 761 deletions Inline Diff
README.txt
View file @
bec01f1
CSE148 Baseline Design v1.2 (1/11/11) | 1 | 1 | CSE148 Baseline Design v1.3 (04/29/2017) | |
by Pravin Prabhu & Todor Mollov | 2 | 2 | by Pravin Prabhu & Todor Mollov & Zinsser Zhang | |
3 | 3 | |||
//============================================================================== | 4 | 4 | //============================================================================== | |
Changelog: | 5 | 5 | Changelog: | |
6 | (04/29/2017)v1.3 released | |||
7 | - Extracted mips_core from other FPGA related components | |||
8 | ||||
(1/11/11) v1.2 released | 6 | 9 | (1/11/11) v1.2 released | |
- Now completely implementable in hardware! | 7 | 10 | - Now completely implementable in hardware! | |
- Renamed some top-level signals to more closely match H&P | 8 | 11 | - Renamed some top-level signals to more closely match H&P | |
clasic 5-stage pipeline design | 9 | 12 | clasic 5-stage pipeline design | |
10 | 13 | |||
(1/9/11) v1.1 released | 11 | 14 | (1/9/11) v1.1 released | |
- Changed cache sizes (smaller) | 12 | 15 | - Changed cache sizes (smaller) | |
- Fixed bug in ForwardingUnit | 13 | 16 | - Fixed bug in ForwardingUnit | |
- Fixed bug in dcache | 14 | 17 | - Fixed bug in dcache | |
- Made dcache & icache have correct address alignments | 15 | 18 | - Made dcache & icache have correct address alignments | |
16 | 19 | |||
(1/5/11) v1.0 released | 17 | 20 | (1/5/11) v1.0 released | |
18 | 21 | |||
19 | 22 | |||
//============================================================================== | 20 | 23 | //============================================================================== | |
Getting Started: | 21 | 24 | Getting Started: | |
To get started with the baseline design, it is recommended that you first | 22 | 25 | To get started with the baseline design, it is recommended that you first | |
download modelsim (student edition). Modelsim can be found at | 23 | 26 | download modelsim (student edition). Modelsim can be found at | |
24 | 27 | |||
http://model.com/ | 25 | 28 | http://model.com/ | |
26 | 29 | |||
27 | 30 | |||
You should also install QuartusII so you can eventually deploy your design | 28 | 31 | You should also install QuartusII so you can eventually deploy your design | |
to actual hardware. The QuartusII web install package can be downloaded from | 29 | 32 | to actual hardware. The QuartusII web install package can be downloaded from | |
Altera's website at: | 30 | 33 | Altera's website at: | |
31 | 34 | |||
http://www.altera.com/products/software/quartus-ii/web-edition/qts-we-index.html | 32 | 35 | http://www.altera.com/products/software/quartus-ii/web-edition/qts-we-index.html | |
33 | 36 | |||
34 | 37 | |||
I recommend that you use a text editor other than Modelsim or Quartus's | 35 | 38 | I recommend that you use a text editor other than Modelsim or Quartus's | |
built in editor -- notepad++ is an excellent alternative and even has syntax | 36 | 39 | built in editor -- notepad++ is an excellent alternative and even has syntax | |
highlighting for verilog. | 37 | 40 | highlighting for verilog. | |
38 | 41 | |||
39 | 42 | |||
(Other tips to help get started) | 40 | 43 | (Other tips to help get started) | |
The included files in the reference folder provide full documentation as | 41 | 44 | The included files in the reference folder provide full documentation as | |
to how instructions should execute -- you will probably be consulting these | 42 | 45 | to how instructions should execute -- you will probably be consulting these | |
files often. | 43 | 46 | files often. | |
44 | 47 | |||
When simulating your design, you can load wavesetup.do which will | 45 | 48 | When simulating your design, you can load wavesetup.do which will | |
automatically add and organize most signals in the design. Note that new signals | 46 | 49 | automatically add and organize most signals in the design. Note that new signals | |
you add yourself will not be in the default wavesetup.do file, but you can save | 47 | 50 | you add yourself will not be in the default wavesetup.do file, but you can save | |
them yourself to the file. | 48 | 51 | them yourself to the file. | |
49 | 52 | |||
To choose your compiled benchmark to run, simply open test_mips_cpu.v and | 50 | 53 | To choose your compiled benchmark to run, simply open test_mips_cpu.v and | |
change the parameter to 'readmemh' which is found near the end of the file. | 51 | 54 | change the parameter to 'readmemh' which is found near the end of the file. | |
Note that you must use an absolute path (I think this is a bug in modelsim) to | 52 | 55 | Note that you must use an absolute path (I think this is a bug in modelsim) to | |
the hex file you wish to load. The base benchmarks are nqueens.hex, esift.hex, | 53 | 56 | the hex file you wish to load. The base benchmarks are nqueens.hex, esift.hex, | |
qsort.hex and coin.hex. Descriptions as to what each of the benchmarks do can | 54 | 57 | qsort.hex and coin.hex. Descriptions as to what each of the benchmarks do can | |
be found in the ref folder under 'benchmarks.pdf'. The included c files serve | 55 | 58 | be found in the ref folder under 'benchmarks.pdf'. The included c files serve | |
as good representations of what to expect of each binary. Please note that in | 56 | 59 | as good representations of what to expect of each binary. Please note that in | |
some cases the included hex file does not exactly match the included disassembly | 57 | 60 | some cases the included hex file does not exactly match the included disassembly | |
file! Note: The included benchmarks.pdf should only be consulted for information | 58 | 61 | file! Note: The included benchmarks.pdf should only be consulted for information | |
about the execution behavior of each benchmark. The other information in the | 59 | 62 | about the execution behavior of each benchmark. The other information in the | |
document that outlines switch behavior and loading from flash is no longer | 60 | 63 | document that outlines switch behavior and loading from flash is no longer | |
relevant to the design. | 61 | 64 | relevant to the design. | |
62 | 65 | |||
After you program your design to the hardware, you can check its | 63 | 66 | After you program your design to the hardware, you can check its | |
performance by toggling the switches and examining the 7 segment display output. | 64 | 67 | performance by toggling the switches and examining the 7 segment display output. | |
The decoding is as follows: | 65 | 68 | The decoding is as follows: | |
66 | 69 | |||
Switches 0 and 1 form a binary number (00 = both off, 01, 10, 11) | 67 | 70 | Switches 0 and 1 form a binary number (00 = both off, 01, 10, 11) | |
68 | 71 | |||
00: Displays pass/done/fail status on HEX2, HEX1, and HEX0. | 69 | 72 | 00: Displays pass/done/fail status on HEX2, HEX1, and HEX0. | |
Displays lower 8 bits of the address going into IMEM. | 70 | 73 | Displays lower 8 bits of the address going into IMEM. | |
71 | 74 | |||
01: Displays the number of cycles that the cpu took to reach the done state. | 72 | 75 | 01: Displays the number of cycles that the cpu took to reach the done state. | |
73 | 76 | |||
02: Displays the number of (non-noop) instructions executed in total. | 74 | 77 | 02: Displays the number of (non-noop) instructions executed in total. | |
75 | 78 | |||
Thus, to calculate CPI, you would toggle the switches to first display | 76 | 79 | Thus, to calculate CPI, you would toggle the switches to first display | |
the total number of cycles that your design completed in and then divide | 77 | 80 | the total number of cycles that your design completed in and then divide | |
by the total number of instructions that the design executed to complete | 78 | 81 | by the total number of instructions that the design executed to complete | |
the benchmark. | 79 | 82 | the benchmark. | |
80 | 83 | |||
//============================================================================== | 81 | 84 | //============================================================================== | |
Details About the Design: | 82 | 85 | Details About the Design: | |
The baseline design implements a subset of the MIPS32 ISA. The provided | 83 | 86 | The baseline design implements a subset of the MIPS32 ISA. The provided | |
benchmarks -- nqueens, qsort, coin, and esift -- will be used in this class to | 84 | 87 | benchmarks -- nqueens, qsort, coin, and esift -- will be used in this class to | |
gauge the performance increases obtained through your processor enhancements. | 85 | 88 | gauge the performance increases obtained through your processor enhancements. | |
86 | 89 | |||
The nomenclature of wires is as follows: A wire/register typically has | 87 | 90 | The nomenclature of wires is as follows: A wire/register typically has | |
three components [TAG]_[DIRECTION]_[NAME]. TAG refers to the meta-unit associated | 88 | 91 | three components [TAG]_[DIRECTION]_[NAME]. TAG refers to the meta-unit associated | |
with the signal. For example, all signals that have to do with the DECODE stage | 89 | 92 | with the signal. For example, all signals that have to do with the DECODE stage | |
will be prefixed with DEC_. Next is DIRECTION -- it's either i_ or o_ depending | 90 | 93 | will be prefixed with DEC_. Next is DIRECTION -- it's either i_ or o_ depending | |
on whether the signal is an input or output in the given context. For example, | 91 | 94 | on whether the signal is an input or output in the given context. For example, | |
all input ports on the ALU will be labeled as i_(name), and all outputs will | 92 | 95 | all input ports on the ALU will be labeled as i_(name), and all outputs will | |
be labeled as o_(name). Finally, NAME is meant to convey the actual purpose of | 93 | 96 | be labeled as o_(name). Finally, NAME is meant to convey the actual purpose of | |
the signal. By using this convention, it is usually relatively easy to identify | 94 | 97 | the signal. By using this convention, it is usually relatively easy to identify | |
where a signal is, its I/O direction, and get some idea of its purpose. | 95 | 98 | where a signal is, its I/O direction, and get some idea of its purpose. | |
96 | 99 | |||
The design follows strongly from the 5-stage MIPS pipeline presented in | 97 | 100 | The design follows strongly from the 5-stage MIPS pipeline presented in | |
Computer Organization and Design (Hennessy and Patterson). The pipeline stages | 98 | 101 | Computer Organization and Design (Hennessy and Patterson). The pipeline stages | |
are laid out as follow: | 99 | 102 | are laid out as follow: | |
100 | 103 | |||
Instruction Fetch -> Decode -> Execute -> Mem Access -> Write-Back | 101 | 104 | Instruction Fetch -> Decode -> Execute -> Mem Access -> Write-Back | |
102 | 105 | |||
Important caveats to note include the fact that branch resolution happens in | 103 | 106 | Important caveats to note include the fact that branch resolution happens in | |
the execute stage and not the decode stage. This is done for regularity, though | 104 | 107 | the execute stage and not the decode stage. This is done for regularity, though | |
pushing branch resolution back to decode would technically improve performance. | 105 | 108 | pushing branch resolution back to decode would technically improve performance. | |
Second, keep in mind that IFetch and Mem both access the same main memory -- | 106 | 109 | Second, keep in mind that IFetch and Mem both access the same main memory -- | |
there is a level of arbitration outside of both of these stages that decides | 107 | 110 | there is a level of arbitration outside of both of these stages that decides | |
which of these sources will be given access to main memory when competing for | 108 | 111 | which of these sources will be given access to main memory when competing for | |
resources. Third, full forwarding is enabled. This means that an instruction | 109 | 112 | resources. Third, full forwarding is enabled. This means that an instruction | |
executing in a later stage (such as Mem) can have its result directly fed to an | 110 | 113 | executing in a later stage (such as Mem) can have its result directly fed to an | |
earlier stage if an instruction requires it. However, there are still scenarios | 111 | 114 | earlier stage if an instruction requires it. However, there are still scenarios | |
that present hazards in the pipeline, and when adding your own logic, it is | 112 | 115 | that present hazards in the pipeline, and when adding your own logic, it is | |
important to carefully consider hazard implications of said logic. | 113 | 116 | important to carefully consider hazard implications of said logic. | |
114 | 117 | |||
115 | 118 | |||
//============================================================================== | 116 | 119 | //============================================================================== | |
Tips for Optimizations: | 117 | 120 | Tips for Optimizations: | |
[Branch Predictors] | 118 | 121 | [Branch Predictors] | |
One of the more important optimizations to consider is a branch predictor. | 119 | 122 | One of the more important optimizations to consider is a branch predictor. | |
The processor currently always flushes the instruction following the delay slot | 120 | 123 | The processor currently always flushes the instruction following the delay slot | |
on resolving a branch in execute (i.e. it implicitly assumes not-taken). In | 121 | 124 | on resolving a branch in execute (i.e. it implicitly assumes not-taken). In | |
reality, most branches _are_ taken -- especially in code that contains loops | 122 | 125 | reality, most branches _are_ taken -- especially in code that contains loops | |
(as do many of the benchmarks...) | 123 | 126 | (as do many of the benchmarks...) | |
124 | 127 | |||
A branch predictor typically resides parallel to the Decode stage, looking | 125 | 128 | A branch predictor typically resides parallel to the Decode stage, looking | |
for possible branches and making predictions. When a branch is seen, a | 126 | 129 | for possible branches and making predictions. When a branch is seen, a | |
speculation bit can set to 1 and the PC can be told to branch/not branch. When | 127 | 130 | speculation bit can set to 1 and the PC can be told to branch/not branch. When | |
the branch is resolved, the instruction can be flushed if it was incorrect. | 128 | 131 | the branch is resolved, the instruction can be flushed if it was incorrect. |
src/core_memory_arbiter.v
View file @
bec01f1
File was created | 1 | /* core_memory_arbiter.v | ||
2 | * Author: Zinsser Zhang | |||
3 | * Last Revision: 04/29/2017 | |||
4 | * Based on Pravin P. Prabhu's memory_arbiter.v | |||
5 | * Abstract: | |||
6 | * Provides arbitration between i_cache and d_cache for request to memory. | |||
7 | * All addresses used in this scope are word addresses (32-bit/4-byte aligned) | |||
8 | * Will service sources in order of priority, which is: | |||
9 | * (high) | |||
10 | * imem | |||
11 | * dmem | |||
12 | * (low) | |||
13 | */ | |||
14 | module core_memory_arbiter #( parameter DATA_WIDTH=32, | |||
15 | parameter ADDRESS_WIDTH=21 | |||
16 | ) | |||
17 | ( | |||
18 | // General | |||
19 | input i_Clk, | |||
20 | input i_Reset_n, | |||
21 | ||||
22 | // Requests to/from IMEM - Assume we always read | |||
23 | input i_IMEM_Valid, // If IMEM request is valid | |||
24 | input [ADDRESS_WIDTH-1:0] i_IMEM_Address, // IMEM request addr. | |||
25 | output reg o_IMEM_Valid, | |||
26 | output reg o_IMEM_Last, | |||
27 | output reg [DATA_WIDTH-1:0] o_IMEM_Data, | |||
28 | ||||
29 | // Requests to/from DMEM | |||
30 | input i_DMEM_Valid, | |||
31 | input i_DMEM_Read_Write_n, | |||
32 | input [ADDRESS_WIDTH-1:0] i_DMEM_Address, | |||
33 | input [DATA_WIDTH-1:0] i_DMEM_Data, | |||
34 | output reg o_DMEM_Valid, | |||
35 | output reg o_DMEM_Data_Read, | |||
36 | output reg o_DMEM_Last, | |||
37 | output reg [DATA_WIDTH-1:0] o_DMEM_Data, | |||
38 | ||||
39 | // Interface to outside of the core | |||
40 | output reg o_MEM_Valid, | |||
41 | output reg [ADDRESS_WIDTH-1:0] o_MEM_Address, | |||
42 | output reg o_MEM_Read_Write_n, | |||
43 | ||||
44 | // Write data interface | |||
45 | output reg [DATA_WIDTH-1:0] o_MEM_Data, | |||
46 | input i_MEM_Data_Read, | |||
47 | ||||
48 | // Read data interface | |||
49 | input [DATA_WIDTH-1:0] i_MEM_Data, | |||
50 | input i_MEM_Valid, | |||
51 | ||||
52 | input i_MEM_Last // If we're on the last piece of the transaction | |||
53 | ); | |||
54 | ||||
55 | // Consts | |||
56 | localparam TRUE = 1'b1; | |||
57 | localparam FALSE = 1'b0; | |||
58 | localparam READ = 1'b1; | |||
59 | localparam WRITE = 1'b0; | |||
60 | ||||
61 | // State of the arbiter | |||
62 | localparam STATE_READY = 4'd0; | |||
63 | localparam STATE_SERVICING_IMEM = 4'd1; | |||
64 | localparam STATE_SERVICING_DMEM = 4'd2; | |||
65 | ||||
66 | reg [3:0] State; | |||
67 | reg [3:0] NextState; | |||
68 | ||||
69 | always @(*) | |||
70 | begin | |||
71 | NextState <= State; | |||
72 | case(State) | |||
73 | STATE_READY: | |||
74 | begin | |||
75 | if (i_IMEM_Valid) | |||
76 | NextState <= STATE_SERVICING_IMEM; | |||
77 | else if (i_DMEM_Valid) | |||
78 | NextState <= STATE_SERVICING_DMEM; | |||
79 | end | |||
80 | ||||
81 | STATE_SERVICING_IMEM: | |||
82 | begin | |||
83 | if (i_MEM_Last) | |||
84 | NextState <= STATE_READY; | |||
85 | end | |||
86 | ||||
87 | STATE_SERVICING_DMEM: | |||
88 | begin | |||
89 | if (i_MEM_Last) | |||
90 | NextState <= STATE_READY; | |||
91 | end | |||
92 | endcase | |||
93 | ||||
94 | o_IMEM_Valid <= FALSE; | |||
95 | o_IMEM_Last <= FALSE; | |||
96 | o_IMEM_Data <= {32{1'bx}}; | |||
97 | o_DMEM_Valid <= FALSE; | |||
98 | o_DMEM_Data_Read <= FALSE; | |||
99 | o_DMEM_Last <= FALSE; | |||
100 | o_DMEM_Data <= {32{1'bx}}; | |||
101 | o_MEM_Valid <= FALSE; | |||
102 | o_MEM_Address <= {ADDRESS_WIDTH{1'bx}}; | |||
103 | o_MEM_Read_Write_n <= READ; | |||
104 | o_MEM_Data <= {32{1'bx}}; | |||
105 | ||||
106 | if (State == STATE_SERVICING_IMEM || NextState == STATE_SERVICING_IMEM) | |||
107 | begin | |||
108 | o_MEM_Valid <= TRUE; | |||
109 | o_MEM_Address <= i_IMEM_Address; | |||
110 | o_MEM_Read_Write_n <= READ; | |||
111 | o_IMEM_Valid <= i_MEM_Valid; | |||
112 | o_IMEM_Last <= i_MEM_Last; | |||
113 | o_IMEM_Data <= i_MEM_Data; | |||
114 | end | |||
115 | else if (State == STATE_SERVICING_DMEM || NextState == STATE_SERVICING_DMEM) | |||
116 | begin | |||
117 | o_MEM_Valid <= TRUE; | |||
118 | o_MEM_Address <= i_DMEM_Address; | |||
119 | o_MEM_Read_Write_n <= i_DMEM_Read_Write_n; | |||
120 | o_MEM_Data <= i_DMEM_Data; | |||
121 | o_DMEM_Valid <= i_MEM_Valid; | |||
122 | o_DMEM_Data_Read <= i_MEM_Data_Read; |
src/d_cache.v
View file @
bec01f1
/* d_cache.v | 1 | 1 | /* d_cache.v | |
* Sam Chan, Tony Medeiros, Dean Tullsen, Todor Mollov, and Pravin Prabhu | 2 | 2 | * Sam Chan, Tony Medeiros, Dean Tullsen, Todor Mollov, Pravin Prabhu, Zinsser Zhang | |
* Abstract: | 3 | 3 | * Abstract: | |
* This is code for a direct-mapped cache, with 16-byte lines and 512 lines, for | 4 | 4 | * This is code for a direct-mapped cache, with 16-byte lines and 512 lines, for | |
* an 8 KB DM cache. 16-byte cache lines are formed via four one-word (four byte) | 5 | 5 | * an 8 KB DM cache. 16-byte cache lines are formed via four one-word (four byte) | |
* banks. This is done so that we can do a MIPS sw in a single access, rather than 2 | 6 | 6 | * banks. This is done so that we can do a MIPS sw in a single access, rather than 2 | |
* accesses (read whole line, modify the correct word, write back the line). This | 7 | 7 | * accesses (read whole line, modify the correct word, write back the line). This | |
* was done so that Quartus would map the cache data to RAM blocks. Thus, changing | 8 | 8 | * was done so that Quartus would map the cache data to RAM blocks. Thus, changing | |
* the size of this cache is pretty easy, changing the associativity is a bit more | 9 | 9 | * the size of this cache is pretty easy, changing the associativity is a bit more | |
* challenging, since the DM cache doesn't need any code for associativity, and | 10 | 10 | * challenging, since the DM cache doesn't need any code for associativity, and | |
* changing the line size is very messy since it changes the number of banks. | 11 | 11 | * changing the line size is very messy since it changes the number of banks. | |
* If someone wants to clean this up (e.g., paramterize the number of banks), please | 12 | 12 | * If someone wants to clean this up (e.g., paramterize the number of banks), please | |
* let me know. | 13 | 13 | * let me know. | |
14 | * All addresses used in this scope are word addresses (32-bit/4-byte aligned). | |||
*/ | 14 | 15 | */ | |
15 | 16 | |||
module d_cache #( | 16 | 17 | module d_cache #( | |
parameter DATA_WIDTH = 32, | 17 | 18 | parameter DATA_WIDTH = 32, | |
parameter TAG_WIDTH = 10, | 18 | 19 | parameter TAG_WIDTH = 10, | |
parameter INDEX_WIDTH = 9, | 19 | 20 | parameter INDEX_WIDTH = 9, | |
parameter BLOCK_OFFSET_WIDTH = 2, | 20 | 21 | parameter BLOCK_OFFSET_WIDTH = 2, | |
parameter MEM_MASK_WIDTH = 3 | 21 | 22 | parameter MEM_MASK_WIDTH = 3 | |
) | 22 | 23 | ) | |
( // Inputs | 23 | 24 | ( // Inputs | |
input i_Clk, | 24 | 25 | input i_Clk, | |
input i_Reset_n, | 25 | 26 | input i_Reset_n, | |
input i_Valid, | 26 | 27 | input i_Valid, | |
input [MEM_MASK_WIDTH-1:0] i_Mem_Mask, | 27 | 28 | input [MEM_MASK_WIDTH-1:0] i_Mem_Mask, | |
input [(TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH)-1:0] i_Address, // 32-bit aligned address | 28 | 29 | input [(TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH)-1:0] i_Address, // 32-bit aligned address | |
input i_Read_Write_n, | 29 | 30 | input i_Read_Write_n, | |
input [DATA_WIDTH-1:0] i_Write_Data, | 30 | 31 | input [DATA_WIDTH-1:0] i_Write_Data, | |
31 | 32 | |||
// Outputs | 32 | 33 | // Outputs | |
output o_Ready, | 33 | 34 | output o_Ready, | |
output reg o_Valid, // If done reading out a value. | 34 | 35 | output reg o_Valid, // If done reading out a value. | |
output [DATA_WIDTH-1:0] o_Data, | 35 | 36 | output [DATA_WIDTH-1:0] o_Data, | |
36 | 37 | |||
// Mem Transaction | 37 | 38 | // Mem Transaction | |
output reg o_MEM_Valid, | 38 | 39 | output reg o_MEM_Valid, | |
output reg o_MEM_Read_Write_n, | 39 | 40 | output reg o_MEM_Read_Write_n, | |
output reg [(TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH):0] o_MEM_Address, // output 2-byte aligned addresses | 40 | 41 | output reg [(TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH)-1:0] o_MEM_Address, | |
output reg [DATA_WIDTH-1:0] o_MEM_Data, | 41 | 42 | output reg [DATA_WIDTH-1:0] o_MEM_Data, | |
input i_MEM_Valid, | 42 | 43 | input i_MEM_Valid, | |
input i_MEM_Data_Read, | 43 | 44 | input i_MEM_Data_Read, | |
input i_MEM_Last, | 44 | 45 | input i_MEM_Last, | |
input [DATA_WIDTH-1:0] i_MEM_Data | 45 | 46 | input [DATA_WIDTH-1:0] i_MEM_Data | |
); | 46 | 47 | ); | |
47 | 48 | |||
// consts | 48 | 49 | // consts | |
localparam DEBUG = 1'b1; | 49 | 50 | localparam DEBUG = 1'b1; | |
localparam FALSE = 1'b0; | 50 | 51 | localparam FALSE = 1'b0; | |
localparam TRUE = 1'b1; | 51 | 52 | localparam TRUE = 1'b1; | |
localparam UNKNOWN = 1'bx; | 52 | 53 | localparam UNKNOWN = 1'bx; | |
53 | 54 | |||
localparam READ = 1'b1; | 54 | 55 | localparam READ = 1'b1; | |
localparam WRITE = 1'b0; | 55 | 56 | localparam WRITE = 1'b0; | |
56 | 57 | |||
localparam ADDRESS_WIDTH = TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH; | 57 | 58 | localparam ADDRESS_WIDTH = TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH; | |
58 | 59 | |||
wire debug; | 59 | 60 | wire debug; | |
// Internal | 60 | 61 | // Internal | |
// Reg'd inputs | 61 | 62 | // Reg'd inputs | |
reg [(TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH)-1:0] r_i_Address; | 62 | 63 | reg [(TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH)-1:0] r_i_Address; | |
reg [BLOCK_OFFSET_WIDTH:0] r_i_BlockOffset; | 63 | 64 | reg [BLOCK_OFFSET_WIDTH:0] r_i_BlockOffset; | |
reg [INDEX_WIDTH-1:0] r_i_Index; | 64 | 65 | reg [INDEX_WIDTH-1:0] r_i_Index; | |
reg [TAG_WIDTH-1:0] r_i_Tag; | 65 | 66 | reg [TAG_WIDTH-1:0] r_i_Tag; | |
reg [DATA_WIDTH-1:0] r_i_Write_Data, r_o_Data; | 66 | 67 | reg [DATA_WIDTH-1:0] r_i_Write_Data, r_o_Data; | |
reg r_i_Read_Write_n; | 67 | 68 | reg r_i_Read_Write_n; | |
68 | 69 | |||
// Parsing | 69 | 70 | // Parsing | |
wire [BLOCK_OFFSET_WIDTH-1:0] i_BlockOffset = i_Address[BLOCK_OFFSET_WIDTH-1:0]; | 70 | 71 | wire [BLOCK_OFFSET_WIDTH-1:0] i_BlockOffset = i_Address[BLOCK_OFFSET_WIDTH-1:0]; | |
wire [INDEX_WIDTH-1:0] i_Index = i_Address[INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:BLOCK_OFFSET_WIDTH]; | 71 | 72 | wire [INDEX_WIDTH-1:0] i_Index = i_Address[INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:BLOCK_OFFSET_WIDTH]; | |
wire [TAG_WIDTH-1:0] i_Tag = i_Address[TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:INDEX_WIDTH+BLOCK_OFFSET_WIDTH]; | 72 | 73 | wire [TAG_WIDTH-1:0] i_Tag = i_Address[TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:INDEX_WIDTH+BLOCK_OFFSET_WIDTH]; | |
73 | 74 | |||
// Tags | 74 | 75 | // Tags | |
reg [TAG_WIDTH-1:0] Tag_Array [0:(1<<INDEX_WIDTH)-1]; | 75 | 76 | reg [TAG_WIDTH-1:0] Tag_Array [0:(1<<INDEX_WIDTH)-1]; | |
// Data | 76 | 77 | // Data | |
reg [(DATA_WIDTH*4)-1:0] Data_Array [0:(1<<INDEX_WIDTH)-1]; | 77 | 78 | reg [(DATA_WIDTH*4)-1:0] Data_Array [0:(1<<INDEX_WIDTH)-1]; | |
// Valid | 78 | 79 | // Valid | |
reg Valid_Array [0:(1<<INDEX_WIDTH)-1]; | 79 | 80 | reg Valid_Array [0:(1<<INDEX_WIDTH)-1]; | |
// Dirty | 80 | 81 | // Dirty | |
reg Dirty_Array [0:(1<<INDEX_WIDTH)-1]; | 81 | 82 | reg Dirty_Array [0:(1<<INDEX_WIDTH)-1]; | |
82 | 83 | |||
//cache bank stuff | 83 | 84 | //cache bank stuff | |
wire [31:0] bank0readdata, bank1readdata, bank2readdata, bank3readdata; | 84 | 85 | wire [31:0] bank0readdata, bank1readdata, bank2readdata, bank3readdata; | |
reg [31:0] bank0writedata, bank1writedata, bank2writedata, bank3writedata; | 85 | 86 | reg [31:0] bank0writedata, bank1writedata, bank2writedata, bank3writedata; | |
reg bank0we, bank1we, bank2we, bank3we; | 86 | 87 | reg bank0we, bank1we, bank2we, bank3we; | |
reg finished_populate; | 87 | 88 | reg finished_populate; | |
// States | 88 | 89 | // States | |
reg [5:0] State; | 89 | 90 | reg [5:0] State; | |
90 | 91 | |||
localparam STATE_READY = 0; // Ready for incoming requests | 91 | 92 | localparam STATE_READY = 0; // Ready for incoming requests | |
localparam STATE_PAUSE = 1; | 92 | 93 | localparam STATE_PAUSE = 1; | |
localparam STATE_POPULATE = 2; // Cache miss - Populate cache line | 93 | 94 | localparam STATE_POPULATE = 2; // Cache miss - Populate cache line | |
localparam STATE_WRITEOUT = 3; // Writes out dirty cache lines | 94 | 95 | localparam STATE_WRITEOUT = 3; // Writes out dirty cache lines | |
95 | 96 | |||
96 | 97 | |||
// Counters | 97 | 98 | // Counters | |
integer i; | 98 | 99 | integer i; | |
reg [8:0] Gen_Count; // General counter | 99 | 100 | reg [8:0] Gen_Count; // General counter | |
100 | 101 | |||
// Hardwired assignments | 101 | 102 | // Hardwired assignments | |
assign o_Ready = (State==STATE_READY); | 102 | 103 | assign o_Ready = (State==STATE_READY); | |
103 | 104 | |||
assign debug = 0;//(i_Index == 9'h1c3); | 104 | 105 | assign debug = 0;//(i_Index == 9'h1c3); | |
105 | 106 | |||
wire populate = (r_i_Read_Write_n == WRITE) && i_MEM_Valid && (Gen_Count == r_i_BlockOffset) && (State == STATE_POPULATE); | 106 | 107 | wire populate = (r_i_Read_Write_n == WRITE) && i_MEM_Valid && (Gen_Count == r_i_BlockOffset) && (State == STATE_POPULATE); | |
wire [DATA_WIDTH-1:0] Populate_Data = populate ? r_i_Write_Data : i_MEM_Data; | 107 | 108 | wire [DATA_WIDTH-1:0] Populate_Data = populate ? r_i_Write_Data : i_MEM_Data; | |
wire cache_hit = i_Valid && Valid_Array[i_Index] && (Tag_Array[i_Index] == i_Tag) && !o_Valid; | 108 | 109 | wire cache_hit = i_Valid && Valid_Array[i_Index] && (Tag_Array[i_Index] == i_Tag) && !o_Valid; | |
wire cache_read_hit = cache_hit && (i_Read_Write_n == READ)&& (State == STATE_READY); | 109 | 110 | wire cache_read_hit = cache_hit && (i_Read_Write_n == READ)&& (State == STATE_READY); | |
wire cache_write_hit = cache_hit && (i_Read_Write_n == WRITE) && (State == STATE_READY); | 110 | 111 | wire cache_write_hit = cache_hit && (i_Read_Write_n == WRITE) && (State == STATE_READY); | |
wire cache_miss = !cache_hit && i_Valid && !o_Valid; | 111 | 112 | wire cache_miss = !cache_hit && i_Valid && !o_Valid; | |
wire valid_read = (r_i_Read_Write_n == READ) && o_Valid; | 112 | 113 | wire valid_read = (r_i_Read_Write_n == READ) && o_Valid; | |
113 | 114 | |||
114 | 115 | |||
//async config for 1 cycle write hits | 115 | 116 | //async config for 1 cycle write hits | |
wire w_bank0we = cache_write_hit && (i_BlockOffset == 0) || bank0we; | 116 | 117 | wire w_bank0we = cache_write_hit && (i_BlockOffset == 0) || bank0we; | |
wire w_bank1we = cache_write_hit && (i_BlockOffset == 1) || bank1we; | 117 | 118 | wire w_bank1we = cache_write_hit && (i_BlockOffset == 1) || bank1we; | |
wire w_bank2we = cache_write_hit && (i_BlockOffset == 2) || bank2we; | 118 | 119 | wire w_bank2we = cache_write_hit && (i_BlockOffset == 2) || bank2we; | |
wire w_bank3we = cache_write_hit && (i_BlockOffset == 3) || bank3we; | 119 | 120 | wire w_bank3we = cache_write_hit && (i_BlockOffset == 3) || bank3we; | |
wire [DATA_WIDTH-1:0] w_bank0writedata = cache_write_hit ? i_Write_Data : bank0writedata; | 120 | 121 | wire [DATA_WIDTH-1:0] w_bank0writedata = cache_write_hit ? i_Write_Data : bank0writedata; | |
wire [DATA_WIDTH-1:0] w_bank1writedata = cache_write_hit ? i_Write_Data : bank1writedata; | 121 | 122 | wire [DATA_WIDTH-1:0] w_bank1writedata = cache_write_hit ? i_Write_Data : bank1writedata; | |
wire [DATA_WIDTH-1:0] w_bank2writedata = cache_write_hit ? i_Write_Data : bank2writedata; | 122 | 123 | wire [DATA_WIDTH-1:0] w_bank2writedata = cache_write_hit ? i_Write_Data : bank2writedata; | |
wire [DATA_WIDTH-1:0] w_bank3writedata = cache_write_hit ? i_Write_Data : bank3writedata; | 123 | 124 | wire [DATA_WIDTH-1:0] w_bank3writedata = cache_write_hit ? i_Write_Data : bank3writedata; | |
124 | 125 | |||
//mux for async read hit outputs correctly on next cycle | 125 | 126 | //mux for async read hit outputs correctly on next cycle | |
assign o_Data = r_i_BlockOffset == 0 ? bank0readdata : | 126 | 127 | assign o_Data = r_i_BlockOffset == 0 ? bank0readdata : | |
r_i_BlockOffset == 1 ? bank1readdata : | 127 | 128 | r_i_BlockOffset == 1 ? bank1readdata : | |
r_i_BlockOffset == 2 ? bank2readdata : | 128 | 129 | r_i_BlockOffset == 2 ? bank2readdata : | |
r_i_BlockOffset == 3 ? bank3readdata : | 129 | 130 | r_i_BlockOffset == 3 ? bank3readdata : | |
r_o_Data; //STATE POPULATE | 130 | 131 | r_o_Data; //STATE POPULATE | |
131 | 132 | |||
132 | 133 | |||
wire [INDEX_WIDTH-1:0] bank_Index = (State == STATE_READY) ? i_Index : r_i_Index; | 133 | 134 | wire [INDEX_WIDTH-1:0] bank_Index = (State == STATE_READY) ? i_Index : r_i_Index; | |
134 | 135 | |||
cache_bank databank | 135 | 136 | cache_bank databank | |
( // Inputs | 136 | 137 | ( // Inputs | |
.i_Clk(i_Clk), | 137 | 138 | .i_Clk(i_Clk), | |
.i_address(bank_Index), | 138 | 139 | .i_address(bank_Index), | |
.i_writedata(w_bank0writedata), | 139 | 140 | .i_writedata(w_bank0writedata), | |
.i_we(w_bank0we), | 140 | 141 | .i_we(w_bank0we), | |
141 | 142 | |||
// Outputs | 142 | 143 | // Outputs | |
.o_readdata(bank0readdata) | 143 | 144 | .o_readdata(bank0readdata) | |
144 | 145 | |||
); | 145 | 146 | ); | |
146 | 147 | |||
cache_bank databank1 | 147 | 148 | cache_bank databank1 | |
( // Inputs | 148 | 149 | ( // Inputs | |
.i_Clk(i_Clk), | 149 | 150 | .i_Clk(i_Clk), | |
.i_address(bank_Index), | 150 | 151 | .i_address(bank_Index), | |
.i_writedata(w_bank1writedata), | 151 | 152 | .i_writedata(w_bank1writedata), | |
.i_we(w_bank1we), | 152 | 153 | .i_we(w_bank1we), | |
153 | 154 | |||
// Outputs | 154 | 155 | // Outputs | |
.o_readdata(bank1readdata) | 155 | 156 | .o_readdata(bank1readdata) | |
); | 156 | 157 | ); | |
157 | 158 | |||
cache_bank databank2 | 158 | 159 | cache_bank databank2 | |
( // Inputs | 159 | 160 | ( // Inputs | |
.i_Clk(i_Clk), | 160 | 161 | .i_Clk(i_Clk), | |
.i_address(bank_Index), | 161 | 162 | .i_address(bank_Index), | |
.i_writedata(w_bank2writedata), | 162 | 163 | .i_writedata(w_bank2writedata), | |
.i_we(w_bank2we), | 163 | 164 | .i_we(w_bank2we), | |
164 | 165 | |||
// Outputs | 165 | 166 | // Outputs | |
.o_readdata(bank2readdata) | 166 | 167 | .o_readdata(bank2readdata) | |
); | 167 | 168 | ); | |
168 | 169 | |||
cache_bank databank3 | 169 | 170 | cache_bank databank3 | |
( // Inputs | 170 | 171 | ( // Inputs | |
.i_Clk(i_Clk), | 171 | 172 | .i_Clk(i_Clk), | |
.i_address(bank_Index), | 172 | 173 | .i_address(bank_Index), | |
.i_writedata(w_bank3writedata), | 173 | 174 | .i_writedata(w_bank3writedata), | |
.i_we(w_bank3we), | 174 | 175 | .i_we(w_bank3we), | |
175 | 176 | |||
// Outputs | 176 | 177 | // Outputs | |
.o_readdata(bank3readdata) | 177 | 178 | .o_readdata(bank3readdata) | |
); | 178 | 179 | ); | |
179 | 180 | |||
always @(posedge i_Clk or negedge i_Reset_n) | 180 | 181 | always @(posedge i_Clk or negedge i_Reset_n) | |
begin | 181 | 182 | begin | |
182 | 183 | |||
/* | 183 | 184 | /* | |
if (i_Valid && i_Read_Write_n && o_Valid && DebugMemory[i_Address] != o_Data) | 184 | 185 | if (i_Valid && i_Read_Write_n && o_Valid && DebugMemory[i_Address] != o_Data) | |
$display("Invalid DCache read at %x value is %x expected ", i_Address, o_Data, DebugMemory[i_Address]); | 185 | 186 | $display("Invalid DCache read at %x value is %x expected ", i_Address, o_Data, DebugMemory[i_Address]); | |
else if (i_Valid && !i_Read_Write_n) | 186 | 187 | else if (i_Valid && !i_Read_Write_n) | |
begin | 187 | 188 | begin | |
DebugMemory[i_Address] <= i_Write_Data; | 188 | 189 | DebugMemory[i_Address] <= i_Write_Data; | |
$display("DCache write at %x value is %x", i_Address, i_Write_Data); | 189 | 190 | $display("DCache write at %x value is %x", i_Address, i_Write_Data); | |
end | 190 | 191 | end | |
*/ | 191 | 192 | */ | |
192 | 193 | |||
// Asynch. reset | 193 | 194 | // Asynch. reset | |
if( !i_Reset_n ) | 194 | 195 | if( !i_Reset_n ) | |
begin | 195 | 196 | begin | |
State <= STATE_READY; | 196 | 197 | State <= STATE_READY; | |
o_MEM_Valid <= FALSE; | 197 | 198 | o_MEM_Valid <= FALSE; | |
end else begin | 198 | 199 | end else begin | |
bank0we <= FALSE; | 199 | 200 | bank0we <= FALSE; | |
bank1we <= FALSE; | 200 | 201 | bank1we <= FALSE; | |
bank2we <= FALSE; | 201 | 202 | bank2we <= FALSE; | |
bank3we <= FALSE; | 202 | 203 | bank3we <= FALSE; | |
finished_populate <= FALSE; | 203 | 204 | finished_populate <= FALSE; | |
o_Valid <= FALSE; | 204 | 205 | o_Valid <= FALSE; | |
case(State) | 205 | 206 | case(State) | |
STATE_READY: begin | 206 | 207 | STATE_READY: begin | |
if(cache_read_hit) begin | 207 | 208 | if(cache_read_hit) begin | |
r_i_Read_Write_n <= READ; | 208 | 209 | r_i_Read_Write_n <= READ; | |
o_Valid <= TRUE; | 209 | 210 | o_Valid <= TRUE; | |
r_i_BlockOffset <= i_BlockOffset; | 210 | 211 | r_i_BlockOffset <= i_BlockOffset; | |
if(debug) | 211 | 212 | if(debug) | |
$display("read hit %x outputs %x", i_Address, r_o_Data); | 212 | 213 | $display("read hit %x outputs %x", i_Address, r_o_Data); | |
end else if(cache_write_hit) begin | 213 | 214 | end else if(cache_write_hit) begin | |
//Write hit!! | 214 | 215 | //Write hit!! | |
r_i_Read_Write_n <= WRITE; | 215 | 216 | r_i_Read_Write_n <= WRITE; | |
o_Valid <= TRUE; | 216 | 217 | o_Valid <= TRUE; | |
Dirty_Array[i_Index] <= TRUE; | 217 | 218 | Dirty_Array[i_Index] <= TRUE; | |
/* | 218 | 219 | /* | |
o_Data <= 0; | 219 | 220 | o_Data <= 0; | |
case( i_BlockOffset ) | 220 | 221 | case( i_BlockOffset ) | |
0: Data_Array[i_Index][(DATA_WIDTH*1)-1:0] <= i_Write_Data; | 221 | 222 | 0: Data_Array[i_Index][(DATA_WIDTH*1)-1:0] <= i_Write_Data; | |
1: Data_Array[i_Index][(DATA_WIDTH*2)-1:(DATA_WIDTH*1)] <= i_Write_Data; | 222 | 223 | 1: Data_Array[i_Index][(DATA_WIDTH*2)-1:(DATA_WIDTH*1)] <= i_Write_Data; | |
2: Data_Array[i_Index][(DATA_WIDTH*3)-1:(DATA_WIDTH*2)] <= i_Write_Data; | 223 | 224 | 2: Data_Array[i_Index][(DATA_WIDTH*3)-1:(DATA_WIDTH*2)] <= i_Write_Data; | |
3: Data_Array[i_Index][(DATA_WIDTH*4)-1:(DATA_WIDTH*3)] <= i_Write_Data; | 224 | 225 | 3: Data_Array[i_Index][(DATA_WIDTH*4)-1:(DATA_WIDTH*3)] <= i_Write_Data; | |
default: $display("Warning: Invalid Gen Count value @ d_cache"); | 225 | 226 | default: $display("Warning: Invalid Gen Count value @ d_cache"); | |
endcase */ | 226 | 227 | endcase */ | |
if(debug) | 227 | 228 | if(debug) | |
$display("write hit %x to %x", i_Write_Data, i_Address); | 228 | 229 | $display("write hit %x to %x", i_Write_Data, i_Address); | |
end else if(cache_miss) begin // miss | 229 | 230 | end else if(cache_miss) begin // miss | |
//prepare registers | 230 | 231 | //prepare registers | |
r_i_Address <= i_Address; | 231 | 232 | r_i_Address <= i_Address; | |
r_i_BlockOffset <= i_BlockOffset; | 232 | 233 | r_i_BlockOffset <= i_BlockOffset; | |
r_i_Index <= i_Index; | 233 | 234 | r_i_Index <= i_Index; | |
r_i_Tag <= i_Tag; | 234 | 235 | r_i_Tag <= i_Tag; | |
r_i_Write_Data <= i_Write_Data; | 235 | 236 | r_i_Write_Data <= i_Write_Data; | |
r_i_Read_Write_n <= i_Read_Write_n; | 236 | 237 | r_i_Read_Write_n <= i_Read_Write_n; | |
o_MEM_Valid <= TRUE; | 237 | 238 | o_MEM_Valid <= TRUE; | |
//if the cache line isnt dirty just populate | 238 | 239 | //if the cache line isnt dirty just populate | |
if(!Valid_Array[i_Index] || !Dirty_Array[i_Index]) begin | 239 | 240 | if(!Valid_Array[i_Index] || !Dirty_Array[i_Index]) begin | |
Gen_Count <= 0; | 240 | 241 | Gen_Count <= 0; | |
State <= STATE_POPULATE; | 241 | 242 | State <= STATE_POPULATE; | |
o_MEM_Read_Write_n <= READ; | 242 | 243 | o_MEM_Read_Write_n <= READ; | |
o_MEM_Address <= {i_Tag,i_Index,{BLOCK_OFFSET_WIDTH+1{1'b0}}}; | 243 | 244 | o_MEM_Address <= {i_Tag,i_Index,{BLOCK_OFFSET_WIDTH{1'b0}}}; | |
if(debug) | 244 | 245 | if(debug) | |
$display("read miss on address %x", i_Address); | 245 | 246 | $display("read miss on address %x", i_Address); | |
end else if(Dirty_Array[i_Index]) begin | 246 | 247 | end else if(Dirty_Array[i_Index]) begin | |
//if its dirty write it to mem before populating! | 247 | 248 | //if its dirty write it to mem before populating! | |
Gen_Count <= 0; | 248 | 249 | Gen_Count <= 0; | |
State <= STATE_WRITEOUT; | 249 | 250 | State <= STATE_WRITEOUT; | |
o_MEM_Address <= {Tag_Array[i_Index],i_Index,{BLOCK_OFFSET_WIDTH+1{1'b0}}}; | 250 | 251 | o_MEM_Address <= {Tag_Array[i_Index],i_Index,{BLOCK_OFFSET_WIDTH{1'b0}}}; | |
if(debug) | 251 | 252 | if(debug) | |
$display("write miss %x to %x", i_Write_Data, i_Address); | 252 | 253 | $display("write miss %x to %x", i_Write_Data, i_Address); | |
end | 253 | 254 | end | |
end | 254 | 255 | end | |
end | 255 | 256 | end | |
STATE_WRITEOUT: begin //State == 3 | 256 | 257 | STATE_WRITEOUT: begin //State == 3 | |
o_MEM_Read_Write_n <= WRITE; | 257 | 258 | o_MEM_Read_Write_n <= WRITE; | |
//o_MEM_Data <= bank0readdata; | 258 | 259 | //o_MEM_Data <= bank0readdata; | |
//Gen_Count <= 1; | 259 | 260 | //Gen_Count <= 1; | |
if(i_MEM_Data_Read) begin | 260 | 261 | if(i_MEM_Data_Read) begin | |
case( Gen_Count ) | 261 | 262 | case( Gen_Count ) | |
0: o_MEM_Data <= bank1readdata; //load next bank | 262 | 263 | 0: o_MEM_Data <= bank1readdata; //load next bank | |
1: o_MEM_Data <= bank2readdata; | 263 | 264 | 1: o_MEM_Data <= bank2readdata; | |
2: o_MEM_Data <= bank3readdata; | 264 | 265 | 2: o_MEM_Data <= bank3readdata; | |
3: o_MEM_Data <= bank3readdata; // keep displaying last one | 265 | 266 | 3: o_MEM_Data <= bank3readdata; // keep displaying last one | |
default: $display("Warning: Invalid Gen Count value @ d_cache writeout"); | 266 | 267 | default: $display("Warning: Invalid Gen Count value @ d_cache writeout"); | |
endcase | 267 | 268 | endcase | |
268 | 269 | |||
if(i_MEM_Last) begin | 269 | 270 | if(i_MEM_Last) begin | |
Gen_Count <= 0; | 270 | 271 | Gen_Count <= 0; | |
State <= STATE_POPULATE; | 271 | 272 | State <= STATE_POPULATE; | |
o_MEM_Valid <= TRUE; | 272 | 273 | o_MEM_Valid <= TRUE; | |
o_MEM_Address <= {r_i_Tag,r_i_Index,{BLOCK_OFFSET_WIDTH+1{1'b0}}}; | 273 | 274 | o_MEM_Address <= {r_i_Tag,r_i_Index,{BLOCK_OFFSET_WIDTH{1'b0}}}; | |
o_MEM_Read_Write_n <= READ; | 274 | 275 | o_MEM_Read_Write_n <= READ; | |
Dirty_Array[r_i_Index] <= FALSE; // Cache line was cleaned | 275 | 276 | Dirty_Array[r_i_Index] <= FALSE; // Cache line was cleaned | |
end else begin | 276 | 277 | end else begin | |
Gen_Count <= Gen_Count + 9'd1; | 277 | 278 | Gen_Count <= Gen_Count + 9'd1; | |
end | 278 | 279 | end | |
end | 279 | 280 | end | |
else | 280 | 281 | else | |
begin | 281 | 282 | begin | |
if (Gen_Count == 0) o_MEM_Data <= bank0readdata; | 282 | 283 | if (Gen_Count == 0) o_MEM_Data <= bank0readdata; | |
end | 283 | 284 | end | |
end | 284 | 285 | end | |
STATE_POPULATE: begin //State == 2 | 285 | 286 | STATE_POPULATE: begin //State == 2 | |
if( i_MEM_Valid ) begin | 286 | 287 | if( i_MEM_Valid ) begin | |
case( Gen_Count ) | 287 | 288 | case( Gen_Count ) | |
//populate data will = r_i_Data if we are writing and on the right gen count | 288 | 289 | //populate data will = r_i_Data if we are writing and on the right gen count | |
//otherwise it will just be i_MEM_Data | 289 | 290 | //otherwise it will just be i_MEM_Data | |
0: begin | 290 | 291 | 0: begin | |
bank0writedata <= Populate_Data; | 291 | 292 | bank0writedata <= Populate_Data; | |
bank0we <= 1; | 292 | 293 | bank0we <= 1; | |
end | 293 | 294 | end | |
1: begin | 294 | 295 | 1: begin | |
bank1writedata <= Populate_Data; | 295 | 296 | bank1writedata <= Populate_Data; | |
bank1we <= 1; | 296 | 297 | bank1we <= 1; | |
end | 297 | 298 | end | |
2: begin | 298 | 299 | 2: begin | |
bank2writedata <= Populate_Data; | 299 | 300 | bank2writedata <= Populate_Data; | |
bank2we <= 1; | 300 | 301 | bank2we <= 1; | |
end | 301 | 302 | end | |
3: begin | 302 | 303 | 3: begin | |
bank3writedata <= Populate_Data; | 303 | 304 | bank3writedata <= Populate_Data; | |
bank3we <= 1; | 304 | 305 | bank3we <= 1; | |
end | 305 | 306 | end | |
default: $display("Warning: Invalid Gen Count value @ d_cache"); | 306 | 307 | default: $display("Warning: Invalid Gen Count value @ d_cache"); | |
endcase | 307 | 308 | endcase | |
308 | 309 | |||
309 | 310 | |||
310 | 311 | |||
if((Gen_Count == r_i_BlockOffset) && (r_i_Read_Write_n == READ)) begin | 311 | 312 | if((Gen_Count == r_i_BlockOffset) && (r_i_Read_Write_n == READ)) begin | |
r_o_Data <= Populate_Data; | 312 | 313 | r_o_Data <= Populate_Data; | |
if(debug) | 313 | 314 | if(debug) | |
$display("Populate address %h data is %h", r_i_Address, Populate_Data); | 314 | 315 | $display("Populate address %h data is %h", r_i_Address, Populate_Data); | |
end | 315 | 316 | end | |
// Account for the input | 316 | 317 | // Account for the input | |
Gen_Count <= Gen_Count + 9'd1; | 317 | 318 | Gen_Count <= Gen_Count + 9'd1; | |
318 | 319 | |||
// If we're about to finish... | 319 | 320 | // If we're about to finish... | |
if( i_MEM_Last ) | 320 | 321 | if( i_MEM_Last ) | |
begin | 321 | 322 | begin | |
// Record info about transaction in tags & valid bits | 322 | 323 | // Record info about transaction in tags & valid bits | |
Tag_Array[r_i_Index] <= r_i_Tag; | 323 | 324 | Tag_Array[r_i_Index] <= r_i_Tag; | |
Valid_Array[r_i_Index] <= TRUE; | 324 | 325 | Valid_Array[r_i_Index] <= TRUE; | |
o_MEM_Valid <= FALSE; | 325 | 326 | o_MEM_Valid <= FALSE; | |
if( r_i_Read_Write_n == WRITE ) | 326 | 327 | if( r_i_Read_Write_n == WRITE ) | |
Dirty_Array[r_i_Index] <= TRUE; | 327 | 328 | Dirty_Array[r_i_Index] <= TRUE; | |
else | 328 | 329 | else | |
Dirty_Array[r_i_Index] <= FALSE; | 329 | 330 | Dirty_Array[r_i_Index] <= FALSE; | |
//tell that cache is ready | 330 | 331 | //tell that cache is ready | |
State <= STATE_PAUSE; | 331 | 332 | State <= STATE_PAUSE; | |
r_i_BlockOffset <= 4; | 332 | 333 | r_i_BlockOffset <= 4; | |
end | 333 | 334 | end | |
end | 334 | 335 | end | |
end | 335 | 336 | end | |
STATE_PAUSE: begin | 336 | 337 | STATE_PAUSE: begin | |
o_Valid <= TRUE; | 337 | 338 | o_Valid <= TRUE; | |
State <= STATE_READY; | 338 | 339 | State <= STATE_READY; | |
end | 339 | 340 | end | |
endcase | 340 | 341 | endcase |
src/decoder.v
View file @
bec01f1
/* decoder.v | 1 | 1 | /* decoder.v | |
* Author: Pravin P. Prabhu | 2 | 2 | * Author: Pravin P. Prabhu, and Zinsser Zhang | |
* Last Revision: 1/5/11 | 3 | 3 | * Last Revision: 04/28/2017 | |
* Abstract: | 4 | 4 | * Abstract: | |
* Provides decoding of instructions to control signals. | 5 | 5 | * Provides decoding of instructions to control signals. | |
6 | * All addresses used in this scope are word addresses (32-bit/4-byte aligned) | |||
*/ | 6 | 7 | */ | |
module decoder #( | 7 | 8 | module decoder #( | |
parameter ADDRESS_WIDTH = 32, | 8 | 9 | parameter ADDRESS_WIDTH = 21, | |
parameter DATA_WIDTH = 32, | 9 | 10 | parameter DATA_WIDTH = 32, | |
parameter REG_ADDRESS_WIDTH = 5, | 10 | 11 | parameter REG_ADDRESS_WIDTH = 5, | |
parameter ALUCTL_WIDTH = 8, | 11 | 12 | parameter ALUCTL_WIDTH = 8, | |
parameter MEM_MASK_WIDTH = 3, | 12 | 13 | parameter MEM_MASK_WIDTH = 3, | |
parameter DEBUG = 0 | 13 | 14 | parameter DEBUG = 0 | |
) | 14 | 15 | ) | |
( // Inputs | 15 | 16 | ( // Inputs | |
input [ADDRESS_WIDTH-1:0] i_PC, | 16 | 17 | input [ADDRESS_WIDTH-1:0] i_PC, | |
input [DATA_WIDTH-1:0] i_Instruction, | 17 | 18 | input [DATA_WIDTH-1:0] i_Instruction, | |
input i_Stall, // Not actually used for logic -- used in debugging statements | 18 | 19 | input i_Stall, // Not actually used for logic -- used in debugging statements | |
19 | 20 | |||
// Outputs | 20 | 21 | // Outputs | |
// Control signals | 21 | 22 | // Control signals | |
output reg o_Uses_ALU, | 22 | 23 | output reg o_Uses_ALU, | |
output reg [ALUCTL_WIDTH-1:0] o_ALUCTL, | 23 | 24 | output reg [ALUCTL_WIDTH-1:0] o_ALUCTL, | |
output reg o_Is_Branch, | 24 | 25 | output reg o_Is_Branch, | |
output reg [ADDRESS_WIDTH-1:0] o_Branch_Target, | 25 | 26 | output reg [ADDRESS_WIDTH-1:0] o_Branch_Target, | |
output reg o_Jump_Reg, | 26 | 27 | output reg o_Jump_Reg, | |
27 | 28 | |||
output reg o_Mem_Valid, | 28 | 29 | output reg o_Mem_Valid, | |
output reg [MEM_MASK_WIDTH-1:0] o_Mem_Mask, | 29 | 30 | output reg [MEM_MASK_WIDTH-1:0] o_Mem_Mask, | |
output reg o_Mem_Read_Write_n, | 30 | 31 | output reg o_Mem_Read_Write_n, | |
31 | 32 | |||
output reg o_Uses_RS, | 32 | 33 | output reg o_Uses_RS, | |
output reg [REG_ADDRESS_WIDTH-1:0] o_RS_Addr, | 33 | 34 | output reg [REG_ADDRESS_WIDTH-1:0] o_RS_Addr, | |
output reg o_Uses_RT, | 34 | 35 | output reg o_Uses_RT, | |
output reg [REG_ADDRESS_WIDTH-1:0] o_RT_Addr, | 35 | 36 | output reg [REG_ADDRESS_WIDTH-1:0] o_RT_Addr, | |
36 | 37 | |||
output reg o_Uses_Immediate, | 37 | 38 | output reg o_Uses_Immediate, | |
output reg [DATA_WIDTH-1:0] o_Immediate, | 38 | 39 | output reg [DATA_WIDTH-1:0] o_Immediate, | |
39 | 40 | |||
output reg o_Writes_Back, | 40 | 41 | output reg o_Writes_Back, | |
output reg [REG_ADDRESS_WIDTH-1:0] o_Write_Addr | 41 | 42 | output reg [REG_ADDRESS_WIDTH-1:0] o_Write_Addr | |
); | 42 | 43 | ); | |
43 | 44 | |||
// Constants | 44 | 45 | // Constants | |
// T/F | 45 | 46 | // T/F | |
localparam TRUE = 1'b1; | 46 | 47 | localparam TRUE = 1'b1; | |
localparam FALSE = 1'b0; | 47 | 48 | localparam FALSE = 1'b0; | |
48 | 49 | |||
localparam READ = 1'b1; | 49 | 50 | localparam READ = 1'b1; | |
localparam WRITE = 1'b0; | 50 | 51 | localparam WRITE = 1'b0; | |
51 | 52 | |||
localparam ALUCTL_NOP = 8'd0; // No Operation (noop) | 52 | 53 | localparam ALUCTL_NOP = 8'd0; // No Operation (noop) | |
localparam ALUCTL_ADD = 8'd1; // Add (signed) | 53 | 54 | localparam ALUCTL_ADD = 8'd1; // Add (signed) | |
localparam ALUCTL_ADDU = 8'd2; // Add (unsigned) | 54 | 55 | localparam ALUCTL_ADDU = 8'd2; // Add (unsigned) | |
localparam ALUCTL_SUB = 8'd3; // Subtract (signed) | 55 | 56 | localparam ALUCTL_SUB = 8'd3; // Subtract (signed) | |
localparam ALUCTL_SUBU = 8'd4; // Subtract (unsigned) | 56 | 57 | localparam ALUCTL_SUBU = 8'd4; // Subtract (unsigned) | |
localparam ALUCTL_AND = 8'd5; // AND | 57 | 58 | localparam ALUCTL_AND = 8'd5; // AND | |
localparam ALUCTL_OR = 8'd6; // OR | 58 | 59 | localparam ALUCTL_OR = 8'd6; // OR | |
localparam ALUCTL_XOR = 8'd7; // XOR | 59 | 60 | localparam ALUCTL_XOR = 8'd7; // XOR | |
localparam ALUCTL_SLT = 8'd8; // Set on Less Than | 60 | 61 | localparam ALUCTL_SLT = 8'd8; // Set on Less Than | |
localparam ALUCTL_SLTU = 8'd9; // Set on Less Than (unsigned) | 61 | 62 | localparam ALUCTL_SLTU = 8'd9; // Set on Less Than (unsigned) | |
localparam ALUCTL_SLL = 8'd10; // Shift Left Logical | 62 | 63 | localparam ALUCTL_SLL = 8'd10; // Shift Left Logical | |
localparam ALUCTL_SRL = 8'd11; // Shift Right Logical | 63 | 64 | localparam ALUCTL_SRL = 8'd11; // Shift Right Logical | |
localparam ALUCTL_SRA = 8'd12; // Shift Right Arithmetic | 64 | 65 | localparam ALUCTL_SRA = 8'd12; // Shift Right Arithmetic | |
localparam ALUCTL_SLLV = 8'd13; // Shift Left Logical Variable | 65 | 66 | localparam ALUCTL_SLLV = 8'd13; // Shift Left Logical Variable | |
localparam ALUCTL_SRLV = 8'd14; // Shift Right Logical Variable | 66 | 67 | localparam ALUCTL_SRLV = 8'd14; // Shift Right Logical Variable | |
localparam ALUCTL_SRAV = 8'd15; // Shift Right Arithmetic Variable | 67 | 68 | localparam ALUCTL_SRAV = 8'd15; // Shift Right Arithmetic Variable | |
localparam ALUCTL_NOR = 8'd16; // NOR | 68 | 69 | localparam ALUCTL_NOR = 8'd16; // NOR | |
localparam ALUCTL_LUI = 8'd17; // Load Upper Immediate | 69 | 70 | localparam ALUCTL_LUI = 8'd17; // Load Upper Immediate | |
localparam ALUCTL_MTCO_PASS = 8'd18; // Move to Coprocessor (PASS) | 70 | 71 | localparam ALUCTL_MTCO_PASS = 8'd18; // Move to Coprocessor (PASS) | |
localparam ALUCTL_MTCO_FAIL = 8'd19; // Move to Coprocessor (FAIL) | 71 | 72 | localparam ALUCTL_MTCO_FAIL = 8'd19; // Move to Coprocessor (FAIL) | |
localparam ALUCTL_MTCO_DONE = 8'd20; // Move to Coprocessor (DONE) | 72 | 73 | localparam ALUCTL_MTCO_DONE = 8'd20; // Move to Coprocessor (DONE) | |
73 | 74 | |||
localparam ALUCTL_BA = 8'd32; // Unconditional branch | 74 | 75 | localparam ALUCTL_BA = 8'd32; // Unconditional branch | |
localparam ALUCTL_BEQ = 8'd33; | 75 | 76 | localparam ALUCTL_BEQ = 8'd33; | |
localparam ALUCTL_BNE = 8'd34; | 76 | 77 | localparam ALUCTL_BNE = 8'd34; | |
localparam ALUCTL_BLEZ = 8'd35; | 77 | 78 | localparam ALUCTL_BLEZ = 8'd35; | |
localparam ALUCTL_BGTZ = 8'd36; | 78 | 79 | localparam ALUCTL_BGTZ = 8'd36; | |
localparam ALUCTL_BGEZ = 8'd37; | 79 | 80 | localparam ALUCTL_BGEZ = 8'd37; | |
localparam ALUCTL_BLTZ = 8'd38; | 80 | 81 | localparam ALUCTL_BLTZ = 8'd38; | |
81 | 82 | |||
localparam ALUCTL_J = 8'd64; | 82 | 83 | localparam ALUCTL_J = 8'd64; | |
localparam ALUCTL_JAL = 8'd65; | 83 | 84 | localparam ALUCTL_JAL = 8'd65; | |
localparam ALUCTL_JR = 8'd66; | 84 | 85 | localparam ALUCTL_JR = 8'd66; | |
localparam ALUCTL_JALR = 8'd67; | 85 | 86 | localparam ALUCTL_JALR = 8'd67; | |
86 | 87 | |||
// Combinatorial logic - Obtain control signals | 87 | 88 | // Combinatorial logic - Obtain control signals | |
always @(*) | 88 | 89 | always @(*) | |
begin | 89 | 90 | begin | |
// Set defaults to avoid latch inference | 90 | 91 | // Set defaults to avoid latch inference | |
o_Uses_ALU <= FALSE; | 91 | 92 | o_Uses_ALU <= FALSE; | |
o_ALUCTL <= ALUCTL_NOP; | 92 | 93 | o_ALUCTL <= ALUCTL_NOP; | |
o_Is_Branch <= FALSE; | 93 | 94 | o_Is_Branch <= FALSE; | |
o_Branch_Target <= 0; | 94 | 95 | o_Branch_Target <= 0; | |
o_Jump_Reg <= FALSE; | 95 | 96 | o_Jump_Reg <= FALSE; | |
o_Mem_Valid <= FALSE; | 96 | 97 | o_Mem_Valid <= FALSE; | |
o_Mem_Read_Write_n <= READ; | 97 | 98 | o_Mem_Read_Write_n <= READ; | |
o_Uses_RS <= FALSE; | 98 | 99 | o_Uses_RS <= FALSE; | |
o_RS_Addr <= 0; | 99 | 100 | o_RS_Addr <= 0; | |
o_Uses_RT <= FALSE; | 100 | 101 | o_Uses_RT <= FALSE; | |
o_RT_Addr <= 0; | 101 | 102 | o_RT_Addr <= 0; | |
o_Uses_Immediate <= FALSE; | 102 | 103 | o_Uses_Immediate <= FALSE; | |
o_Immediate <= 0; | 103 | 104 | o_Immediate <= 0; | |
o_Writes_Back <= FALSE; | 104 | 105 | o_Writes_Back <= FALSE; | |
o_Write_Addr <= 0; | 105 | 106 | o_Write_Addr <= 0; | |
o_Mem_Mask <= 0; | 106 | 107 | o_Mem_Mask <= 0; | |
107 | 108 | |||
case(i_Instruction[31:26]) | 108 | 109 | case(i_Instruction[31:26]) | |
6'h0: //r-type | 109 | 110 | 6'h0: //r-type | |
begin | 110 | 111 | begin | |
111 | 112 | |||
case (i_Instruction[5:0]) | 112 | 113 | case (i_Instruction[5:0]) | |
6'h20: | 113 | 114 | 6'h20: | |
begin | 114 | 115 | begin | |
o_Uses_ALU <= TRUE; | 115 | 116 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 116 | 117 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; // add | 117 | 118 | o_ALUCTL <= ALUCTL_ADD; // add | |
o_Uses_RS <= TRUE; | 118 | 119 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 119 | 120 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 120 | 121 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 121 | 122 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 122 | 123 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 123 | 124 | end | |
124 | 125 | |||
6'h21: | 125 | 126 | 6'h21: | |
begin | 126 | 127 | begin | |
o_Uses_ALU <= TRUE; | 127 | 128 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 128 | 129 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_ADDU; // addu | 129 | 130 | o_ALUCTL <= ALUCTL_ADDU; // addu | |
o_Uses_RS <= TRUE; | 130 | 131 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 131 | 132 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 132 | 133 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 133 | 134 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 134 | 135 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 135 | 136 | end | |
136 | 137 | |||
6'h22: | 137 | 138 | 6'h22: | |
begin | 138 | 139 | begin | |
o_Uses_ALU <= TRUE; | 139 | 140 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 140 | 141 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SUB; // sub | 141 | 142 | o_ALUCTL <= ALUCTL_SUB; // sub | |
o_Uses_RS <= TRUE; | 142 | 143 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 143 | 144 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 144 | 145 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 145 | 146 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 146 | 147 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 147 | 148 | end | |
148 | 149 | |||
6'h23: | 149 | 150 | 6'h23: | |
begin | 150 | 151 | begin | |
o_Uses_ALU <= TRUE; | 151 | 152 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 152 | 153 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SUBU; // subu | 153 | 154 | o_ALUCTL <= ALUCTL_SUBU; // subu | |
o_Uses_RS <= TRUE; | 154 | 155 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 155 | 156 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 156 | 157 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 157 | 158 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 158 | 159 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 159 | 160 | end | |
160 | 161 | |||
6'h24: | 161 | 162 | 6'h24: | |
begin | 162 | 163 | begin | |
o_Uses_ALU <= TRUE; | 163 | 164 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 164 | 165 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_AND; // and | 165 | 166 | o_ALUCTL <= ALUCTL_AND; // and | |
o_Uses_RS <= TRUE; | 166 | 167 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 167 | 168 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 168 | 169 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 169 | 170 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 170 | 171 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 171 | 172 | end | |
172 | 173 | |||
6'h25: | 173 | 174 | 6'h25: | |
begin | 174 | 175 | begin | |
o_Uses_ALU <= TRUE; | 175 | 176 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 176 | 177 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_OR; // or | 177 | 178 | o_ALUCTL <= ALUCTL_OR; // or | |
o_Uses_RS <= TRUE; | 178 | 179 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 179 | 180 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 180 | 181 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 181 | 182 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 182 | 183 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 183 | 184 | end | |
184 | 185 | |||
6'h26: | 185 | 186 | 6'h26: | |
begin | 186 | 187 | begin | |
o_Uses_ALU <= TRUE; | 187 | 188 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 188 | 189 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_XOR; // xor | 189 | 190 | o_ALUCTL <= ALUCTL_XOR; // xor | |
o_Uses_RS <= TRUE; | 190 | 191 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 191 | 192 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 192 | 193 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 193 | 194 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 194 | 195 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 195 | 196 | end | |
196 | 197 | |||
6'h27: | 197 | 198 | 6'h27: | |
begin | 198 | 199 | begin | |
o_Uses_ALU <= TRUE; | 199 | 200 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 200 | 201 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_NOR; // nor | 201 | 202 | o_ALUCTL <= ALUCTL_NOR; // nor | |
o_Uses_RS <= TRUE; | 202 | 203 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 203 | 204 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 204 | 205 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 205 | 206 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 206 | 207 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 207 | 208 | end | |
208 | 209 | |||
6'h00: | 209 | 210 | 6'h00: | |
begin | 210 | 211 | begin | |
o_Uses_ALU <= TRUE; | 211 | 212 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 212 | 213 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SLL; // sll | 213 | 214 | o_ALUCTL <= ALUCTL_SLL; // sll | |
o_Uses_RS <= TRUE; | 214 | 215 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[20:16]; | 215 | 216 | o_RS_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 216 | 217 | o_Write_Addr <= i_Instruction[15:11]; | |
o_Uses_Immediate <= TRUE; | 217 | 218 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{27{1'b0}},i_Instruction[10:6]}; | 218 | 219 | o_Immediate <= {{27{1'b0}},i_Instruction[10:6]}; | |
end | 219 | 220 | end | |
220 | 221 | |||
6'h02: | 221 | 222 | 6'h02: | |
begin | 222 | 223 | begin | |
o_Uses_ALU <= TRUE; | 223 | 224 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 224 | 225 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SRL; // srl | 225 | 226 | o_ALUCTL <= ALUCTL_SRL; // srl | |
o_Uses_RS <= TRUE; | 226 | 227 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[20:16]; | 227 | 228 | o_RS_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 228 | 229 | o_Write_Addr <= i_Instruction[15:11]; | |
o_Uses_Immediate <= TRUE; | 229 | 230 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{27{1'b0}},i_Instruction[10:6]}; | 230 | 231 | o_Immediate <= {{27{1'b0}},i_Instruction[10:6]}; | |
end | 231 | 232 | end | |
232 | 233 | |||
6'h03: | 233 | 234 | 6'h03: | |
begin | 234 | 235 | begin | |
o_Uses_ALU <= TRUE; | 235 | 236 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 236 | 237 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SRA; // sra | 237 | 238 | o_ALUCTL <= ALUCTL_SRA; // sra | |
o_Uses_RS <= TRUE; | 238 | 239 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[20:16]; | 239 | 240 | o_RS_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 240 | 241 | o_Write_Addr <= i_Instruction[15:11]; | |
o_Uses_Immediate <= TRUE; | 241 | 242 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{27{1'b0}},i_Instruction[10:6]}; | 242 | 243 | o_Immediate <= {{27{1'b0}},i_Instruction[10:6]}; | |
end | 243 | 244 | end | |
244 | 245 | |||
6'h04: | 245 | 246 | 6'h04: | |
begin | 246 | 247 | begin | |
o_Uses_ALU <= TRUE; | 247 | 248 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 248 | 249 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SLLV; // sllv | 249 | 250 | o_ALUCTL <= ALUCTL_SLLV; // sllv | |
o_Uses_RS <= TRUE; | 250 | 251 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 251 | 252 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 252 | 253 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 253 | 254 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 254 | 255 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 255 | 256 | end | |
256 | 257 | |||
6'h06: | 257 | 258 | 6'h06: | |
begin | 258 | 259 | begin | |
o_Uses_ALU <= TRUE; | 259 | 260 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 260 | 261 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SRLV; // srlv | 261 | 262 | o_ALUCTL <= ALUCTL_SRLV; // srlv | |
o_Uses_RS <= TRUE; | 262 | 263 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 263 | 264 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 264 | 265 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 265 | 266 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 266 | 267 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 267 | 268 | end | |
268 | 269 | |||
6'h07: | 269 | 270 | 6'h07: | |
begin | 270 | 271 | begin | |
o_Uses_ALU <= TRUE; | 271 | 272 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 272 | 273 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SRAV; // srav | 273 | 274 | o_ALUCTL <= ALUCTL_SRAV; // srav | |
o_Uses_RS <= TRUE; | 274 | 275 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 275 | 276 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 276 | 277 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 277 | 278 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 278 | 279 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 279 | 280 | end | |
280 | 281 | |||
6'h2a: | 281 | 282 | 6'h2a: | |
begin | 282 | 283 | begin | |
o_Uses_ALU <= TRUE; | 283 | 284 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 284 | 285 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SLT; // slt | 285 | 286 | o_ALUCTL <= ALUCTL_SLT; // slt | |
o_Uses_RS <= TRUE; | 286 | 287 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 287 | 288 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 288 | 289 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 289 | 290 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 290 | 291 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 291 | 292 | end | |
292 | 293 | |||
6'h2b: | 293 | 294 | 6'h2b: | |
begin | 294 | 295 | begin | |
o_Uses_ALU <= TRUE; | 295 | 296 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 296 | 297 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SLTU; // sltu | 297 | 298 | o_ALUCTL <= ALUCTL_SLTU; // sltu | |
o_Uses_RS <= TRUE; | 298 | 299 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 299 | 300 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 300 | 301 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 301 | 302 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Write_Addr <= i_Instruction[15:11]; | 302 | 303 | o_Write_Addr <= i_Instruction[15:11]; | |
end | 303 | 304 | end | |
304 | 305 | |||
6'h08: // JR | 305 | 306 | 6'h08: // JR | |
begin | 306 | 307 | begin | |
o_Is_Branch <= TRUE; | 307 | 308 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 308 | 309 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_JR; | 309 | 310 | o_ALUCTL <= ALUCTL_JR; | |
o_Uses_RS <= TRUE; | 310 | 311 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 311 | 312 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Jump_Reg <= TRUE; | 312 | 313 | o_Jump_Reg <= TRUE; | |
if( !i_Stall && DEBUG ) | 313 | 314 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Jump Register)",i_PC,i_Instruction); | 314 | 315 | $display("%x: %x (Jump Register)",i_PC,i_Instruction); | |
end | 315 | 316 | end | |
316 | 317 | |||
6'h09: | 317 | 318 | 6'h09: | |
begin //jalr | 318 | 319 | begin //jalr | |
o_Is_Branch <= TRUE; | 319 | 320 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 320 | 321 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_JR; | 321 | 322 | o_ALUCTL <= ALUCTL_JR; | |
o_Uses_RS <= TRUE; | 322 | 323 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 323 | 324 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Jump_Reg <= TRUE; | 324 | 325 | o_Jump_Reg <= TRUE; | |
o_Uses_Immediate <= TRUE; | 325 | 326 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= (i_PC + 2); | 326 | 327 | o_Immediate <= (i_PC + 2); | |
o_Writes_Back <= TRUE; | 327 | 328 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= 31; // Jump And Link always stores the PC into reg 31. | 328 | 329 | o_Write_Addr <= 31; // Jump And Link always stores the PC into reg 31. | |
if( !i_Stall && DEBUG ) | 329 | 330 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Jump and Link Register)",i_PC,i_Instruction); | 330 | 331 | $display("%x: %x (Jump and Link Register)",i_PC,i_Instruction); | |
end | 331 | 332 | end | |
332 | 333 | |||
6'h18: // mul | 333 | 334 | 6'h18: // mul | |
begin | 334 | 335 | begin | |
if( !i_Stall && DEBUG ) | 335 | 336 | if( !i_Stall && DEBUG ) | |
$display("Multiply is unsupported"); | 336 | 337 | $display("Multiply is unsupported"); | |
//o_Uses_ALU <= TRUE; | 337 | 338 | //o_Uses_ALU <= TRUE; | |
//o_Writes_Back <= TRUE; | 338 | 339 | //o_Writes_Back <= TRUE; | |
//o_ALUCTL <= ALUCTL_NOP; | 339 | 340 | //o_ALUCTL <= ALUCTL_NOP; | |
end | 340 | 341 | end | |
341 | 342 | |||
6'h19: //mulu | 342 | 343 | 6'h19: //mulu | |
begin | 343 | 344 | begin | |
if( !i_Stall && DEBUG ) | 344 | 345 | if( !i_Stall && DEBUG ) | |
$display("Multiply Unsigned is unsupported"); | 345 | 346 | $display("Multiply Unsigned is unsupported"); | |
//o_Uses_ALU <= TRUE; | 346 | 347 | //o_Uses_ALU <= TRUE; | |
//o_Writes_Back <= TRUE; | 347 | 348 | //o_Writes_Back <= TRUE; | |
//o_ALUCTL <= ALUCTL_NOP; | 348 | 349 | //o_ALUCTL <= ALUCTL_NOP; | |
end | 349 | 350 | end | |
350 | 351 | |||
6'h1a: //div | 351 | 352 | 6'h1a: //div | |
begin | 352 | 353 | begin | |
if( !i_Stall && DEBUG ) | 353 | 354 | if( !i_Stall && DEBUG ) | |
$display("Divide is unsupported"); | 354 | 355 | $display("Divide is unsupported"); | |
//o_Uses_ALU <= TRUE; | 355 | 356 | //o_Uses_ALU <= TRUE; | |
//o_Writes_Back <= TRUE; | 356 | 357 | //o_Writes_Back <= TRUE; | |
//o_ALUCTL <= ALUCTL_NOP; | 357 | 358 | //o_ALUCTL <= ALUCTL_NOP; | |
end | 358 | 359 | end | |
359 | 360 | |||
6'h1b: //divu | 360 | 361 | 6'h1b: //divu | |
begin | 361 | 362 | begin | |
if( !i_Stall && DEBUG ) | 362 | 363 | if( !i_Stall && DEBUG ) | |
$display("Divide Unsigned is unsupported"); | 363 | 364 | $display("Divide Unsigned is unsupported"); | |
//o_Uses_ALU <= TRUE; | 364 | 365 | //o_Uses_ALU <= TRUE; | |
//o_Writes_Back <= TRUE; | 365 | 366 | //o_Writes_Back <= TRUE; | |
//o_ALUCTL <= ALUCTL_NOP; | 366 | 367 | //o_ALUCTL <= ALUCTL_NOP; | |
end | 367 | 368 | end | |
368 | 369 | |||
default: | 369 | 370 | default: | |
begin | 370 | 371 | begin | |
if( !i_Stall && DEBUG ) | 371 | 372 | if( !i_Stall && DEBUG ) | |
$display("illegal i_Instruction[5:0] code %b\n", i_Instruction[5:0]); | 372 | 373 | $display("illegal i_Instruction[5:0] code %b\n", i_Instruction[5:0]); | |
end | 373 | 374 | end | |
endcase | 374 | 375 | endcase | |
end | 375 | 376 | end | |
376 | 377 | |||
6'h08: //addi | 377 | 378 | 6'h08: //addi | |
begin | 378 | 379 | begin | |
o_Uses_ALU <= TRUE; | 379 | 380 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 380 | 381 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 381 | 382 | o_ALUCTL <= ALUCTL_ADD; | |
o_Uses_RS <= TRUE; | 382 | 383 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 383 | 384 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 384 | 385 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 385 | 386 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 386 | 387 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
end | 387 | 388 | end | |
388 | 389 | |||
6'h09: //addiu | 389 | 390 | 6'h09: //addiu | |
begin | 390 | 391 | begin | |
o_Uses_ALU <= TRUE; | 391 | 392 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 392 | 393 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_ADDU; | 393 | 394 | o_ALUCTL <= ALUCTL_ADDU; | |
o_Uses_RS <= TRUE; | 394 | 395 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 395 | 396 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 396 | 397 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 397 | 398 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 398 | 399 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
end | 399 | 400 | end | |
400 | 401 | |||
6'h0c: //andi | 401 | 402 | 6'h0c: //andi | |
begin | 402 | 403 | begin | |
o_Uses_ALU <= TRUE; | 403 | 404 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 404 | 405 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_AND; | 405 | 406 | o_ALUCTL <= ALUCTL_AND; | |
o_Uses_RS <= TRUE; | 406 | 407 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 407 | 408 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 408 | 409 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 409 | 410 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{1'b0}},i_Instruction[15:0]}; | 410 | 411 | o_Immediate <= {{16{1'b0}},i_Instruction[15:0]}; | |
end | 411 | 412 | end | |
412 | 413 | |||
6'h0d: //ori | 413 | 414 | 6'h0d: //ori | |
begin | 414 | 415 | begin | |
o_Uses_ALU <= TRUE; | 415 | 416 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 416 | 417 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_OR; | 417 | 418 | o_ALUCTL <= ALUCTL_OR; | |
o_Uses_RS <= TRUE; | 418 | 419 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 419 | 420 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 420 | 421 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 421 | 422 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{1'b0}},i_Instruction[15:0]}; | 422 | 423 | o_Immediate <= {{16{1'b0}},i_Instruction[15:0]}; | |
end | 423 | 424 | end | |
424 | 425 | |||
6'h0e: //xori | 425 | 426 | 6'h0e: //xori | |
begin | 426 | 427 | begin | |
o_Uses_ALU <= TRUE; | 427 | 428 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 428 | 429 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_XOR; | 429 | 430 | o_ALUCTL <= ALUCTL_XOR; | |
o_Uses_RS <= TRUE; | 430 | 431 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 431 | 432 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 432 | 433 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 433 | 434 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{1'b0}},i_Instruction[15:0]}; | 434 | 435 | o_Immediate <= {{16{1'b0}},i_Instruction[15:0]}; | |
end | 435 | 436 | end | |
436 | 437 | |||
6'h0a: //slti | 437 | 438 | 6'h0a: //slti | |
begin | 438 | 439 | begin | |
o_Uses_ALU <= TRUE; | 439 | 440 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 440 | 441 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SLT; | 441 | 442 | o_ALUCTL <= ALUCTL_SLT; | |
o_Uses_RS <= TRUE; | 442 | 443 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 443 | 444 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 444 | 445 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 445 | 446 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 446 | 447 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
end | 447 | 448 | end | |
448 | 449 | |||
6'h0b: //sltiu | 449 | 450 | 6'h0b: //sltiu | |
begin | 450 | 451 | begin | |
o_Uses_ALU <= TRUE; | 451 | 452 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 452 | 453 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_SLTU; | 453 | 454 | o_ALUCTL <= ALUCTL_SLTU; | |
o_Uses_RS <= TRUE; | 454 | 455 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 455 | 456 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Write_Addr <= i_Instruction[20:16]; | 456 | 457 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 457 | 458 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 458 | 459 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
end | 459 | 460 | end | |
460 | 461 | |||
6'h0f: //lui | 461 | 462 | 6'h0f: //lui | |
begin | 462 | 463 | begin | |
o_Uses_ALU <= TRUE; | 463 | 464 | o_Uses_ALU <= TRUE; | |
o_Writes_Back <= TRUE; | 464 | 465 | o_Writes_Back <= TRUE; | |
o_ALUCTL <= ALUCTL_OR; // Implemented as A = 0 | Immediate | 465 | 466 | o_ALUCTL <= ALUCTL_OR; // Implemented as A = 0 | Immediate | |
o_RS_Addr <= 0; | 466 | 467 | o_RS_Addr <= 0; | |
o_Write_Addr <= i_Instruction[20:16]; | 467 | 468 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 468 | 469 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {i_Instruction[15:0],{16{1'b0}}}; | 469 | 470 | o_Immediate <= {i_Instruction[15:0],{16{1'b0}}}; | |
end | 470 | 471 | end | |
471 | 472 | |||
6'h04: //beq | 472 | 473 | 6'h04: //beq | |
begin | 473 | 474 | begin | |
o_Is_Branch <= TRUE; | 474 | 475 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 475 | 476 | o_Uses_ALU <= TRUE; | |
o_Uses_RS <= TRUE; | 476 | 477 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 477 | 478 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 478 | 479 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 479 | 480 | o_RT_Addr <= i_Instruction[20:16]; | |
o_ALUCTL <= ALUCTL_BEQ; | 480 | 481 | o_ALUCTL <= ALUCTL_BEQ; | |
o_Branch_Target <= i_PC + 22'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | 481 | 482 | o_Branch_Target <= i_PC + 21'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | |
if( !i_Stall && DEBUG ) | 482 | 483 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Branch on Equal)",i_PC,i_Instruction); | 483 | 484 | $display("%x: %x (Branch on Equal)",i_PC,i_Instruction); | |
end | 484 | 485 | end | |
485 | 486 | |||
6'h05: //bne | 486 | 487 | 6'h05: //bne | |
begin | 487 | 488 | begin | |
o_Is_Branch <= TRUE; | 488 | 489 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 489 | 490 | o_Uses_ALU <= TRUE; | |
o_Uses_RS <= TRUE; | 490 | 491 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 491 | 492 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 492 | 493 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 493 | 494 | o_RT_Addr <= i_Instruction[20:16]; | |
o_ALUCTL <= ALUCTL_BNE; | 494 | 495 | o_ALUCTL <= ALUCTL_BNE; | |
o_Branch_Target <= i_PC + 22'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | 495 | 496 | o_Branch_Target <= i_PC + 21'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | |
if( !i_Stall && DEBUG ) | 496 | 497 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Branch on Not Equal)",i_PC,i_Instruction); | 497 | 498 | $display("%x: %x (Branch on Not Equal)",i_PC,i_Instruction); | |
end | 498 | 499 | end | |
499 | 500 | |||
6'h06: //blez | 500 | 501 | 6'h06: //blez | |
begin | 501 | 502 | begin | |
o_Is_Branch <= TRUE; | 502 | 503 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 503 | 504 | o_Uses_ALU <= TRUE; | |
o_Uses_RS <= TRUE; | 504 | 505 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 505 | 506 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 506 | 507 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 507 | 508 | o_RT_Addr <= i_Instruction[20:16]; | |
o_ALUCTL <= ALUCTL_BLEZ; | 508 | 509 | o_ALUCTL <= ALUCTL_BLEZ; | |
o_Branch_Target <= i_PC + 22'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | 509 | 510 | o_Branch_Target <= i_PC + 21'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | |
if( !i_Stall && DEBUG ) | 510 | 511 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Branch on Less or Equal)",i_PC,i_Instruction); | 511 | 512 | $display("%x: %x (Branch on Less or Equal)",i_PC,i_Instruction); | |
end | 512 | 513 | end | |
513 | 514 | |||
6'h01: //bgez or bltz | 514 | 515 | 6'h01: //bgez or bltz | |
begin | 515 | 516 | begin | |
o_Is_Branch <= TRUE; | 516 | 517 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 517 | 518 | o_Uses_ALU <= TRUE; | |
o_Uses_RS <= TRUE; | 518 | 519 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 519 | 520 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 520 | 521 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 521 | 522 | o_RT_Addr <= i_Instruction[20:16]; | |
if( i_Instruction[16] ) | 522 | 523 | if( i_Instruction[16] ) | |
begin | 523 | 524 | begin | |
o_ALUCTL <= ALUCTL_BGEZ; | 524 | 525 | o_ALUCTL <= ALUCTL_BGEZ; | |
if( !i_Stall && DEBUG ) | 525 | 526 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Branch on Greater or Equal)",i_PC,i_Instruction); | 526 | 527 | $display("%x: %x (Branch on Greater or Equal)",i_PC,i_Instruction); | |
end | 527 | 528 | end | |
else | 528 | 529 | else | |
begin | 529 | 530 | begin | |
o_ALUCTL <= ALUCTL_BLTZ; | 530 | 531 | o_ALUCTL <= ALUCTL_BLTZ; | |
if( !i_Stall && DEBUG ) | 531 | 532 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Branch on Less or Equal)",i_PC,i_Instruction); | 532 | 533 | $display("%x: %x (Branch on Less or Equal)",i_PC,i_Instruction); | |
end | 533 | 534 | end | |
//o_ALUCTL <= i_Instruction[16]? ALUCTL_BGEZ: ALUCTL_BLTZ; // 1 <=> bgez : 0 <=> bltz | 534 | 535 | //o_ALUCTL <= i_Instruction[16]? ALUCTL_BGEZ: ALUCTL_BLTZ; // 1 <=> bgez : 0 <=> bltz | |
o_Branch_Target <= i_PC + 22'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | 535 | 536 | o_Branch_Target <= i_PC + 21'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | |
end | 536 | 537 | end | |
537 | 538 | |||
6'h07: //bgtz | 538 | 539 | 6'h07: //bgtz | |
begin | 539 | 540 | begin | |
o_Is_Branch <= TRUE; | 540 | 541 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 541 | 542 | o_Uses_ALU <= TRUE; | |
o_Uses_RS <= TRUE; | 542 | 543 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 543 | 544 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 544 | 545 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 545 | 546 | o_RT_Addr <= i_Instruction[20:16]; | |
o_ALUCTL <= ALUCTL_BGTZ; | 546 | 547 | o_ALUCTL <= ALUCTL_BGTZ; | |
o_Branch_Target <= i_PC + 22'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | 547 | 548 | o_Branch_Target <= i_PC + 21'd1 + {{(ADDRESS_WIDTH-16){i_Instruction[15]}},i_Instruction[15:0]}; | |
if( !i_Stall && DEBUG ) | 548 | 549 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Branch on Greater)",i_PC,i_Instruction); | 549 | 550 | $display("%x: %x (Branch on Greater)",i_PC,i_Instruction); | |
end | 550 | 551 | end | |
551 | 552 | |||
6'h02: // j | 552 | 553 | 6'h02: // j | |
begin | 553 | 554 | begin | |
o_Is_Branch <= TRUE; | 554 | 555 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 555 | 556 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_J; | 556 | 557 | o_ALUCTL <= ALUCTL_J; | |
//o_Branch_Target <= {i_PC[31:26],i_Instruction[25:0]}; | 557 | 558 | //o_Branch_Target <= {i_PC[31:26],i_Instruction[25:0]}; | |
o_Branch_Target <= i_Instruction[21:0]; | 558 | 559 | o_Branch_Target <= i_Instruction[20:0]; | |
if( !i_Stall && DEBUG ) | 559 | 560 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Jump)",i_PC,i_Instruction); | 560 | 561 | $display("%x: %x (Jump)",i_PC,i_Instruction); | |
end | 561 | 562 | end | |
562 | 563 | |||
6'h03: // jal | 563 | 564 | 6'h03: // jal | |
begin | 564 | 565 | begin | |
o_Is_Branch <= TRUE; | 565 | 566 | o_Is_Branch <= TRUE; | |
o_Uses_ALU <= TRUE; | 566 | 567 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_JAL; | 567 | 568 | o_ALUCTL <= ALUCTL_JAL; | |
//o_Branch_Target <= {i_PC[31:26],i_Instruction[25:0]}; | 568 | 569 | //o_Branch_Target <= {i_PC[31:26],i_Instruction[25:0]}; | |
o_Branch_Target <= i_Instruction[21:0]; | 569 | 570 | o_Branch_Target <= i_Instruction[20:0]; | |
o_Uses_Immediate <= TRUE; | 570 | 571 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= (i_PC + 2); | 571 | 572 | o_Immediate <= (i_PC + 2); | |
o_Writes_Back <= TRUE; | 572 | 573 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= 31; // Jump And Link always stores the PC into reg 31. | 573 | 574 | o_Write_Addr <= 31; // Jump And Link always stores the PC into reg 31. | |
if( !i_Stall && DEBUG ) | 574 | 575 | if( !i_Stall && DEBUG ) | |
$display("%x: %x (Jump and Link)",i_PC,i_Instruction); | 575 | 576 | $display("%x: %x (Jump and Link)",i_PC,i_Instruction); | |
end | 576 | 577 | end | |
577 | 578 | |||
6'h20: //lb | 578 | 579 | 6'h20: //lb | |
begin | 579 | 580 | begin | |
o_Uses_ALU <= TRUE; | 580 | 581 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 581 | 582 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 582 | 583 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= READ; | 583 | 584 | o_Mem_Read_Write_n <= READ; | |
o_Uses_RS <= TRUE; | 584 | 585 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 585 | 586 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_Immediate <= TRUE; | 586 | 587 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 587 | 588 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Writes_Back <= TRUE; | 588 | 589 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= i_Instruction[20:16]; | 589 | 590 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Mem_Mask <= 0; | 590 | 591 | o_Mem_Mask <= 0; | |
end | 591 | 592 | end | |
592 | 593 | |||
6'h24: //lbu | 593 | 594 | 6'h24: //lbu | |
begin | 594 | 595 | begin | |
o_Uses_ALU <= TRUE; | 595 | 596 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 596 | 597 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 597 | 598 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= READ; | 598 | 599 | o_Mem_Read_Write_n <= READ; | |
o_Uses_RS <= TRUE; | 599 | 600 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 600 | 601 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_Immediate <= TRUE; | 601 | 602 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 602 | 603 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Writes_Back <= TRUE; | 603 | 604 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= i_Instruction[20:16]; | 604 | 605 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Mem_Mask <= 1; | 605 | 606 | o_Mem_Mask <= 1; | |
end | 606 | 607 | end | |
607 | 608 | |||
6'h21: //lh | 608 | 609 | 6'h21: //lh | |
begin | 609 | 610 | begin | |
o_Uses_ALU <= TRUE; | 610 | 611 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 611 | 612 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 612 | 613 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= READ; | 613 | 614 | o_Mem_Read_Write_n <= READ; | |
o_Uses_Immediate <= TRUE; | 614 | 615 | o_Uses_Immediate <= TRUE; | |
o_Uses_RS <= TRUE; | 615 | 616 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 616 | 617 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 617 | 618 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Writes_Back <= TRUE; | 618 | 619 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= i_Instruction[20:16]; | 619 | 620 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Mem_Mask <= 2; | 620 | 621 | o_Mem_Mask <= 2; | |
end | 621 | 622 | end | |
622 | 623 | |||
6'h25: //lhu | 623 | 624 | 6'h25: //lhu | |
begin | 624 | 625 | begin | |
o_Uses_ALU <= TRUE; | 625 | 626 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 626 | 627 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 627 | 628 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= READ; | 628 | 629 | o_Mem_Read_Write_n <= READ; | |
o_Uses_Immediate <= TRUE; | 629 | 630 | o_Uses_Immediate <= TRUE; | |
o_Uses_RS <= TRUE; | 630 | 631 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 631 | 632 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_Immediate <= TRUE; | 632 | 633 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 633 | 634 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Writes_Back <= TRUE; | 634 | 635 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= i_Instruction[20:16]; | 635 | 636 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Mem_Mask <= 3; | 636 | 637 | o_Mem_Mask <= 3; | |
end | 637 | 638 | end | |
638 | 639 | |||
6'h23: //lw | 639 | 640 | 6'h23: //lw | |
begin | 640 | 641 | begin | |
o_Uses_ALU <= TRUE; | 641 | 642 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 642 | 643 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 643 | 644 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= READ; | 644 | 645 | o_Mem_Read_Write_n <= READ; | |
o_Uses_Immediate <= TRUE; | 645 | 646 | o_Uses_Immediate <= TRUE; | |
o_Uses_RS <= TRUE; | 646 | 647 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 647 | 648 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_Immediate <= TRUE; | 648 | 649 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 649 | 650 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Writes_Back <= TRUE; | 650 | 651 | o_Writes_Back <= TRUE; | |
o_Write_Addr <= i_Instruction[20:16]; | 651 | 652 | o_Write_Addr <= i_Instruction[20:16]; | |
o_Mem_Mask <= 4; | 652 | 653 | o_Mem_Mask <= 4; | |
end | 653 | 654 | end | |
654 | 655 | |||
6'h28: //sb | 655 | 656 | 6'h28: //sb | |
begin | 656 | 657 | begin | |
o_Uses_ALU <= TRUE; | 657 | 658 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 658 | 659 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 659 | 660 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= WRITE; | 660 | 661 | o_Mem_Read_Write_n <= WRITE; | |
o_Uses_Immediate <= TRUE; | 661 | 662 | o_Uses_Immediate <= TRUE; | |
o_Uses_RS <= TRUE; | 662 | 663 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 663 | 664 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 664 | 665 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 665 | 666 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 666 | 667 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 667 | 668 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Mem_Mask <= 0; | 668 | 669 | o_Mem_Mask <= 0; | |
end | 669 | 670 | end | |
670 | 671 | |||
6'h29: //sh | 671 | 672 | 6'h29: //sh | |
begin | 672 | 673 | begin | |
o_Uses_ALU <= TRUE; | 673 | 674 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 674 | 675 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 675 | 676 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= WRITE; | 676 | 677 | o_Mem_Read_Write_n <= WRITE; | |
o_Uses_Immediate <= TRUE; | 677 | 678 | o_Uses_Immediate <= TRUE; | |
o_Uses_RS <= TRUE; | 678 | 679 | o_Uses_RS <= TRUE; | |
o_RS_Addr <= i_Instruction[25:21]; | 679 | 680 | o_RS_Addr <= i_Instruction[25:21]; | |
o_Uses_RT <= TRUE; | 680 | 681 | o_Uses_RT <= TRUE; | |
o_RT_Addr <= i_Instruction[20:16]; | 681 | 682 | o_RT_Addr <= i_Instruction[20:16]; | |
o_Uses_Immediate <= TRUE; | 682 | 683 | o_Uses_Immediate <= TRUE; | |
o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | 683 | 684 | o_Immediate <= {{16{i_Instruction[15]}},i_Instruction[15:0]}; | |
o_Mem_Mask <= 2; | 684 | 685 | o_Mem_Mask <= 2; | |
end | 685 | 686 | end | |
686 | 687 | |||
6'h2b: //sw | 687 | 688 | 6'h2b: //sw | |
begin | 688 | 689 | begin | |
o_Uses_ALU <= TRUE; | 689 | 690 | o_Uses_ALU <= TRUE; | |
o_ALUCTL <= ALUCTL_ADD; | 690 | 691 | o_ALUCTL <= ALUCTL_ADD; | |
o_Mem_Valid <= TRUE; | 691 | 692 | o_Mem_Valid <= TRUE; | |
o_Mem_Read_Write_n <= WRITE; | 692 | 693 | o_Mem_Read_Write_n <= WRITE; | |
o_Uses_Immediate <= TRUE; | 693 | 694 | o_Uses_Immediate <= TRUE; | |
o_Uses_RS <= TRUE; | 694 | 695 | o_Uses_RS <= TRUE; |
src/hazard_detection_unit.v
View file @
bec01f1
/* hazard_detection_unit.v | 1 | 1 | /* hazard_detection_unit.v | |
* Author: Pravin P. Prabhu | 2 | 2 | * Author: Pravin P. Prabhu, and Zinsser Zhang | |
* Last Revision: 1/5/11 | 3 | 3 | * Last Revision: 04/28/2017 | |
* Abstract: | 4 | 4 | * Abstract: | |
* Contains all of the nightmarish logic for determining when the processor | 5 | 5 | * Contains all of the nightmarish logic for determining when the processor | |
* should stall, and how it should stall. You are not expected to understand this. | 6 | 6 | * should stall, and how it should stall. You are not expected to understand this. | |
*/ | 7 | 7 | */ | |
module hazard_detection_unit #( parameter DATA_WIDTH=32, | 8 | 8 | module hazard_detection_unit #( parameter DATA_WIDTH=32, | |
parameter ADDRESS_WIDTH=32, | 9 | 9 | parameter ADDRESS_WIDTH=32, | |
parameter REG_ADDR_WIDTH=5 | 10 | 10 | parameter REG_ADDR_WIDTH=5 | |
) | 11 | 11 | ) | |
( | 12 | 12 | ( | |
input i_Clk, | 13 | 13 | input i_Clk, | |
input i_Reset_n, | 14 | 14 | input i_Reset_n, | |
15 | 15 | |||
//============================================== | 16 | 16 | //============================================== | |
// Info about processor's overall state | 17 | 17 | // External stall issued by top level | |
input i_FlashLoader_Done, // Whether the flashloader has completed operation yet or not | 18 | 18 | input i_External_Stall, | |
input i_Done, // Whether we have observed the 'done' signal or not | 19 | |||
20 | 19 | |||
//============================================== | 21 | 20 | //============================================== | |
// Hazard in DECODE? | 22 | 21 | // Hazard in DECODE? | |
input i_DEC_Uses_RS, // DEC wants to use RS | 23 | 22 | input i_DEC_Uses_RS, // DEC wants to use RS | |
input [REG_ADDR_WIDTH-1:0] i_DEC_RS_Addr, // RS request addr. | 24 | 23 | input [REG_ADDR_WIDTH-1:0] i_DEC_RS_Addr, // RS request addr. | |
input i_DEC_Uses_RT, // DEC wants to use RT | 25 | 24 | input i_DEC_Uses_RT, // DEC wants to use RT | |
input [REG_ADDR_WIDTH-1:0] i_DEC_RT_Addr, // RT request addr. | 26 | 25 | input [REG_ADDR_WIDTH-1:0] i_DEC_RT_Addr, // RT request addr. | |
input i_DEC_Branch_Instruction, // There is a branch inst. in DEC. | 27 | 26 | input i_DEC_Branch_Instruction, // There is a branch inst. in DEC. | |
28 | 27 | |||
//=============================================== | 29 | 28 | //=============================================== | |
// Feedback from IF | 30 | 29 | // Feedback from IF | |
input i_IF_Done, // If IF's value has reached steady state | 31 | 30 | input i_IF_Done, // If IF's value has reached steady state | |
32 | 31 | |||
// Feedback from EX | 33 | 32 | // Feedback from EX | |
input i_EX_Writes_Back, // EX is valid for analysis | 34 | 33 | input i_EX_Writes_Back, // EX is valid for analysis | |
input i_EX_Uses_Mem, | 35 | 34 | input i_EX_Uses_Mem, | |
input [REG_ADDR_WIDTH-1:0] i_EX_Write_Addr, // What EX will write to | 36 | 35 | input [REG_ADDR_WIDTH-1:0] i_EX_Write_Addr, // What EX will write to | |
input i_EX_Branch, // If EX says we are branching | 37 | 36 | input i_EX_Branch, // If EX says we are branching | |
input [ADDRESS_WIDTH-1:0] i_EX_Branch_Target, | 38 | 37 | input [ADDRESS_WIDTH-1:0] i_EX_Branch_Target, | |
39 | 38 | |||
// Feedback from MEM | 40 | 39 | // Feedback from MEM | |
input i_MEM_Uses_Mem, // If it's a memop | 41 | 40 | input i_MEM_Uses_Mem, // If it's a memop | |
input i_MEM_Writes_Back, // MEM is valid for analysis | 42 | 41 | input i_MEM_Writes_Back, // MEM is valid for analysis | |
input [REG_ADDR_WIDTH-1:0] i_MEM_Write_Addr, // What MEM will write to | 43 | 42 | input [REG_ADDR_WIDTH-1:0] i_MEM_Write_Addr, // What MEM will write to | |
input i_MEM_Done, // If MEM's value has reached steady state | 44 | 43 | input i_MEM_Done, // If MEM's value has reached steady state | |
45 | 44 | |||
46 | 45 | |||
// Feedback from WB | 47 | 46 | // Feedback from WB | |
input i_WB_Writes_Back, // WB is valid for analysis | 48 | 47 | input i_WB_Writes_Back, // WB is valid for analysis | |
input [REG_ADDR_WIDTH-1:0] i_WB_Write_Addr, // What WB will write to | 49 | 48 | input [REG_ADDR_WIDTH-1:0] i_WB_Write_Addr, // What WB will write to | |
50 | 49 | |||
//=============================================== | 51 | 50 | //=============================================== | |
// Branch hazard handling | 52 | 51 | // Branch hazard handling | |
output o_IF_Branch, | 53 | 52 | output o_IF_Branch, | |
output [ADDRESS_WIDTH-1:0] o_IF_Branch_Target, | 54 | 53 | output [ADDRESS_WIDTH-1:0] o_IF_Branch_Target, | |
55 | 54 | |||
//=============================================== | 56 | 55 | //=============================================== | |
// IFetch validation | 57 | 56 | // IFetch validation | |
output reg o_IF_Stall, | 58 | 57 | output reg o_IF_Stall, | |
output o_IF_Smash, | 59 | 58 | output o_IF_Smash, | |
60 | 59 | |||
// DECODE validation | 61 | 60 | // DECODE validation | |
output reg o_DEC_Stall, // Causes decode stage to stall | 62 | 61 | output reg o_DEC_Stall, // Causes decode stage to stall | |
output reg o_DEC_Smash, // Smashes out contents of decode stage | 63 | 62 | output reg o_DEC_Smash, // Smashes out contents of decode stage | |
64 | 63 | |||
// EX validation | 65 | 64 | // EX validation | |
output reg o_EX_Stall, | 66 | 65 | output reg o_EX_Stall, | |
output reg o_EX_Smash, | 67 | 66 | output reg o_EX_Smash, | |
68 | 67 | |||
// MEM validation | 69 | 68 | // MEM validation | |
output reg o_MEM_Stall, | 70 | 69 | output reg o_MEM_Stall, | |
output reg o_MEM_Smash, | 71 | 70 | output reg o_MEM_Smash, | |
72 | 71 | |||
output reg o_WB_Stall, | 73 | 72 | output reg o_WB_Stall, | |
output reg o_WB_Smash | 74 | 73 | output reg o_WB_Smash | |
); | 75 | 74 | ); | |
// Consts | 76 | 75 | // Consts | |
localparam FALSE = 1'b0; | 77 | 76 | localparam FALSE = 1'b0; | |
localparam TRUE = 1'b1; | 78 | 77 | localparam TRUE = 1'b1; | |
79 | 78 | |||
// Internal wiring | 80 | 79 | // Internal wiring | |
wire Executing = i_FlashLoader_Done && !i_Done; // If 1, then we are currently executing code. | 81 | 80 | wire Executing = !i_External_Stall; // If 1, then we are currently executing code. | |
82 | 81 | |||
// Registers for latching branches during stall periods | 83 | 82 | // Registers for latching branches during stall periods | |
reg r_Branch_IF_Hazard_Smash; // If 1, then we must smash the next inst coming out of IF -- there was a branch while it was busy. | 84 | 83 | reg r_Branch_IF_Hazard_Smash; // If 1, then we must smash the next inst coming out of IF -- there was a branch while it was busy. | |
reg r_IF_Smash_Transient; | 85 | 84 | reg r_IF_Smash_Transient; | |
reg r_IF_Load; | 86 | 85 | reg r_IF_Load; | |
reg [ADDRESS_WIDTH-1:0] r_IF_Load_Address; | 87 | 86 | reg [ADDRESS_WIDTH-1:0] r_IF_Load_Address; | |
88 | 87 | |||
// Branch handling | 89 | 88 | // Branch handling | |
assign o_IF_Smash = (r_Branch_IF_Hazard_Smash || r_IF_Smash_Transient); | 90 | 89 | assign o_IF_Smash = (r_Branch_IF_Hazard_Smash || r_IF_Smash_Transient); | |
assign o_IF_Branch = i_EX_Branch || r_IF_Load; | 91 | 90 | assign o_IF_Branch = i_EX_Branch || r_IF_Load; | |
assign o_IF_Branch_Target = i_EX_Branch ? i_EX_Branch_Target : r_IF_Load_Address; | 92 | 91 | assign o_IF_Branch_Target = i_EX_Branch ? i_EX_Branch_Target : r_IF_Load_Address; | |
93 | 92 | |||
// Hazard prevention: Smash IF instructions that are partway | 94 | 93 | // Hazard prevention: Smash IF instructions that are partway | |
// fetched as we recognize a branch. Stop the instruction that | 95 | 94 | // fetched as we recognize a branch. Stop the instruction that | |
// will emerge from imem from propogating through the pipeline | 96 | 95 | // will emerge from imem from propogating through the pipeline | |
// erroneously. | 97 | 96 | // erroneously. | |
always @(posedge i_Clk or negedge i_Reset_n) | 98 | 97 | always @(posedge i_Clk or negedge i_Reset_n) | |
begin | 99 | 98 | begin | |
if( !i_Reset_n ) | 100 | 99 | if( !i_Reset_n ) | |
begin | 101 | 100 | begin | |
r_Branch_IF_Hazard_Smash <= FALSE; | 102 | 101 | r_Branch_IF_Hazard_Smash <= FALSE; | |
end | 103 | 102 | end | |
else | 104 | 103 | else | |
begin | 105 | 104 | begin | |
if( i_EX_Branch && !i_IF_Done ) // Hazard - if we had to branch during IMEM's busy period (likely), then record the smash request in this register. Smash inst upon it being ready. | 106 | 105 | if( i_EX_Branch && !i_IF_Done ) // Hazard - if we had to branch during IMEM's busy period (likely), then record the smash request in this register. Smash inst upon it being ready. | |
begin | 107 | 106 | begin | |
r_Branch_IF_Hazard_Smash <= TRUE; | 108 | 107 | r_Branch_IF_Hazard_Smash <= TRUE; | |
end | 109 | 108 | end | |
else if( i_IF_Done && r_Branch_IF_Hazard_Smash ) // Inst from IMEM is now valid - we must smash it. Account for the smash on this cycle by pulling down reg'd smash signal. | 110 | 109 | else if( i_IF_Done && r_Branch_IF_Hazard_Smash ) // Inst from IMEM is now valid - we must smash it. Account for the smash on this cycle by pulling down reg'd smash signal. | |
begin | 111 | 110 | begin | |
r_Branch_IF_Hazard_Smash <= FALSE; | 112 | 111 | r_Branch_IF_Hazard_Smash <= FALSE; | |
end | 113 | 112 | end | |
end | 114 | 113 | end | |
end | 115 | 114 | end | |
116 | 115 | |||
// Hazard prevention: If we recognize a branch, but IF is stalling, | 117 | 116 | // Hazard prevention: If we recognize a branch, but IF is stalling, | |
// then we should record the branch and apply it as soon as IF is | 118 | 117 | // then we should record the branch and apply it as soon as IF is | |
// done stalling. | 119 | 118 | // done stalling. | |
always @(posedge i_Clk or negedge i_Reset_n) | 120 | 119 | always @(posedge i_Clk or negedge i_Reset_n) | |
begin | 121 | 120 | begin | |
if( !i_Reset_n ) | 122 | 121 | if( !i_Reset_n ) | |
begin | 123 | 122 | begin | |
r_IF_Load <= FALSE; | 124 | 123 | r_IF_Load <= FALSE; | |
r_IF_Load_Address <= {ADDRESS_WIDTH{1'bx}}; | 125 | 124 | r_IF_Load_Address <= {ADDRESS_WIDTH{1'bx}}; | |
end | 126 | 125 | end | |
else | 127 | 126 | else | |
begin | 128 | 127 | begin | |
if( o_IF_Stall && | 129 | 128 | if( o_IF_Stall && | |
i_EX_Branch ) | 130 | 129 | i_EX_Branch ) | |
begin | 131 | 130 | begin | |
// Branch during a stalling period. Hold on to the branch. | 132 | 131 | // Branch during a stalling period. Hold on to the branch. | |
r_IF_Load <= TRUE; | 133 | 132 | r_IF_Load <= TRUE; | |
r_IF_Load_Address <= i_EX_Branch_Target; | 134 | 133 | r_IF_Load_Address <= i_EX_Branch_Target; | |
end | 135 | 134 | end | |
else if( r_IF_Load && | 136 | 135 | else if( r_IF_Load && | |
!o_IF_Stall ) | 137 | 136 | !o_IF_Stall ) | |
begin | 138 | 137 | begin | |
// Came out of the stall and we had a reg'd branch request. Clear it. | 139 | 138 | // Came out of the stall and we had a reg'd branch request. Clear it. | |
r_IF_Load <= FALSE; | 140 | 139 | r_IF_Load <= FALSE; | |
end | 141 | 140 | end | |
end | 142 | 141 | end | |
end | 143 | 142 | end | |
144 | 143 | |||
145 | 144 | |||
//============================================= | 146 | 145 | //============================================= | |
// Validation | 147 | 146 | // Validation | |
148 | 147 | |||
// IF validation | 149 | 148 | // IF validation | |
always @(*) | 150 | 149 | always @(*) | |
begin | 151 | 150 | begin | |
o_IF_Stall <= FALSE; | 152 | 151 | o_IF_Stall <= FALSE; | |
r_IF_Smash_Transient <= FALSE; | 153 | 152 | r_IF_Smash_Transient <= FALSE; | |
154 | 153 | |||
// If flashloader is done, check for other conditions | 155 | 154 | // If flashloader is done, check for other conditions | |
if( Executing ) | 156 | 155 | if( Executing ) | |
begin | 157 | 156 | begin | |
// If next stage is stalling, so is this stage | 158 | 157 | // If next stage is stalling, so is this stage | |
if( o_DEC_Stall || !i_IF_Done ) // Also stall on IMEM's output being invalid | 159 | 158 | if( o_DEC_Stall || !i_IF_Done ) // Also stall on IMEM's output being invalid | |
begin | 160 | 159 | begin | |
o_IF_Stall <= TRUE; | 161 | 160 | o_IF_Stall <= TRUE; | |
end | 162 | 161 | end | |
163 | 162 | |||
// If branching, smash. If output of imem is invalid, smash. | 164 | 163 | // If branching, smash. If output of imem is invalid, smash. | |
if( i_EX_Branch || !i_IF_Done ) | 165 | 164 | if( i_EX_Branch || !i_IF_Done ) | |
begin | 166 | 165 | begin | |
r_IF_Smash_Transient <= TRUE; | 167 | 166 | r_IF_Smash_Transient <= TRUE; | |
end | 168 | 167 | end | |
end | 169 | 168 | end | |
else // Flashloader not done | 170 | 169 | else // Flashloader not done | |
begin | 171 | 170 | begin | |
o_IF_Stall <= TRUE; | 172 | 171 | o_IF_Stall <= TRUE; | |
r_IF_Smash_Transient <= TRUE; | 173 | 172 | r_IF_Smash_Transient <= TRUE; | |
end | 174 | 173 | end | |
end | 175 | 174 | end | |
176 | 175 | |||
// DEC validation | 177 | 176 | // DEC validation | |
always @(*) | 178 | 177 | always @(*) | |
begin | 179 | 178 | begin | |
o_DEC_Stall <= FALSE; | 180 | 179 | o_DEC_Stall <= FALSE; | |
o_DEC_Smash <= FALSE; | 181 | 180 | o_DEC_Smash <= FALSE; | |
182 | 181 | |||
// If flash is done, check for other conditions | 183 | 182 | // If flash is done, check for other conditions | |
if( Executing ) | 184 | 183 | if( Executing ) | |
begin | 185 | 184 | begin | |
186 | 185 | |||
// If we have a branch operation in DEC, then we have to keep waiting | 187 | 186 | // If we have a branch operation in DEC, then we have to keep waiting | |
// until the delay slot inst has been successfully read from imem | 188 | 187 | // until the delay slot inst has been successfully read from imem | |
if( i_DEC_Branch_Instruction && | 189 | 188 | if( i_DEC_Branch_Instruction && | |
!i_IF_Done ) | 190 | 189 | !i_IF_Done ) | |
begin | 191 | 190 | begin | |
o_DEC_Smash <= TRUE; // Do not let the branch go to EX stage | 192 | 191 | o_DEC_Smash <= TRUE; // Do not let the branch go to EX stage | |
o_DEC_Stall <= TRUE; // Hold inst. until IF is ready | 193 | 192 | o_DEC_Stall <= TRUE; // Hold inst. until IF is ready | |
end | 194 | 193 | end | |
195 | 194 | |||
// If we have to wait on MEM for decoding, then do so. | 196 | 195 | // If we have to wait on MEM for decoding, then do so. | |
// RS/RT requires waiting on DMEM op in EX | 197 | 196 | // RS/RT requires waiting on DMEM op in EX | |
if( (i_DEC_Uses_RS && | 198 | 197 | if( (i_DEC_Uses_RS && | |
i_EX_Writes_Back && | 199 | 198 | i_EX_Writes_Back && | |
i_EX_Uses_Mem && | 200 | 199 | i_EX_Uses_Mem && | |
(i_EX_Write_Addr == i_DEC_RS_Addr)) || | 201 | 200 | (i_EX_Write_Addr == i_DEC_RS_Addr)) || | |
( i_DEC_Uses_RT && | 202 | 201 | ( i_DEC_Uses_RT && | |
i_EX_Writes_Back && | 203 | 202 | i_EX_Writes_Back && | |
i_EX_Uses_Mem && | 204 | 203 | i_EX_Uses_Mem && | |
(i_EX_Write_Addr == i_DEC_RT_Addr) ) | 205 | 204 | (i_EX_Write_Addr == i_DEC_RT_Addr) ) | |
) | 206 | 205 | ) | |
begin | 207 | 206 | begin | |
o_DEC_Smash <= TRUE; | 208 | 207 | o_DEC_Smash <= TRUE; | |
o_DEC_Stall <= TRUE; | 209 | 208 | o_DEC_Stall <= TRUE; | |
end | 210 | 209 | end | |
211 | 210 | |||
// Stall if next stage is stalling | 212 | 211 | // Stall if next stage is stalling | |
if( o_EX_Stall ) | 213 | 212 | if( o_EX_Stall ) | |
o_DEC_Stall <= TRUE; | 214 | 213 | o_DEC_Stall <= TRUE; | |
end | 215 | 214 | end | |
else | 216 | 215 | else | |
begin | 217 | 216 | begin | |
o_DEC_Stall <= TRUE; | 218 | 217 | o_DEC_Stall <= TRUE; | |
o_DEC_Smash <= TRUE; | 219 | 218 | o_DEC_Smash <= TRUE; | |
end | 220 | 219 | end | |
end | 221 | 220 | end | |
222 | 221 | |||
// EX validation | 223 | 222 | // EX validation | |
always @(*) | 224 | 223 | always @(*) | |
begin | 225 | 224 | begin | |
o_EX_Stall <= FALSE; | 226 | 225 | o_EX_Stall <= FALSE; | |
o_EX_Smash <= FALSE; | 227 | 226 | o_EX_Smash <= FALSE; | |
228 | 227 | |||
if( Executing ) | 229 | 228 | if( Executing ) | |
begin | 230 | 229 | begin | |
if( o_MEM_Stall ) | 231 | 230 | if( o_MEM_Stall ) | |
o_EX_Stall <= TRUE; | 232 | 231 | o_EX_Stall <= TRUE; | |
end | 233 | 232 | end | |
else | 234 | 233 | else | |
begin | 235 | 234 | begin | |
o_EX_Stall <= TRUE; | 236 | 235 | o_EX_Stall <= TRUE; | |
o_EX_Smash <= TRUE; | 237 | 236 | o_EX_Smash <= TRUE; | |
end | 238 | 237 | end | |
239 | 238 | |||
end | 240 | 239 | end | |
241 | 240 | |||
// MEM validation | 242 | 241 | // MEM validation | |
always @(*) | 243 | 242 | always @(*) | |
begin | 244 | 243 | begin | |
o_MEM_Stall <= FALSE; | 245 | 244 | o_MEM_Stall <= FALSE; | |
o_MEM_Smash <= FALSE; | 246 | 245 | o_MEM_Smash <= FALSE; | |
247 | 246 | |||
if( Executing ) | 248 | 247 | if( Executing ) | |
begin | 249 | 248 | begin | |
if( !i_MEM_Done ) | 250 | 249 | if( !i_MEM_Done ) |
src/i_cache.v
View file @
bec01f1
/* i_cache.v | 1 | 1 | /* i_cache.v | |
* Author: Pravin P. Prabhu | 2 | 2 | * Author: Pravin P. Prabhu, Zinsser Zhang | |
* Last Revision: 1/5/11 | 3 | 3 | * Last Revision: 04/28/2017 | |
* Abstract: | 4 | 4 | * Abstract: | |
* Provides caching of instructions from imem for quick access. Note that this | 5 | 5 | * Provides caching of instructions from imem for quick access. Note that this | |
* is a read only cache, and thus self-modifying code is not supported. | 6 | 6 | * is a read only cache, and thus self-modifying code is not supported. | |
7 | * All addresses used in this scope are word addresses (32-bit/4-byte aligned) | |||
*/ | 7 | 8 | */ | |
module i_cache #( parameter DATA_WIDTH = 32, | 8 | 9 | module i_cache #( parameter DATA_WIDTH = 32, | |
parameter TAG_WIDTH = 14, | 9 | 10 | parameter TAG_WIDTH = 14, | |
parameter INDEX_WIDTH = 5, | 10 | 11 | parameter INDEX_WIDTH = 5, | |
parameter BLOCK_OFFSET_WIDTH = 2 | 11 | 12 | parameter BLOCK_OFFSET_WIDTH = 2 | |
) | 12 | 13 | ) | |
( | 13 | 14 | ( | |
// General | 14 | 15 | // General | |
input i_Clk, | 15 | 16 | input i_Clk, | |
input i_Reset_n, | 16 | 17 | input i_Reset_n, | |
17 | 18 | |||
// Requests | 18 | 19 | // Requests | |
input i_Valid, | 19 | 20 | input i_Valid, | |
input [TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH:0] i_Address, | 20 | 21 | input [TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:0] i_Address, | |
21 | 22 | |||
// DMEM Transaction | 22 | 23 | // DMEM Transaction | |
output reg o_MEM_Valid, // If request to DMEM is valid | 23 | 24 | output reg o_MEM_Valid, // If request to MEM is valid | |
output reg [TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH:0] o_MEM_Address, // Address request to DMEM | 24 | 25 | output reg [TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:0] o_MEM_Address, // Address request to MEM | |
input i_MEM_Valid, // If data from main mem is valid | 25 | 26 | input i_MEM_Valid, // If data from main mem is valid | |
input i_MEM_Last, // If main mem is sending the last piece of data | 26 | 27 | input i_MEM_Last, // If main mem is sending the last piece of data | |
input [DATA_WIDTH-1:0] i_MEM_Data, // Data from main mem | 27 | 28 | input [DATA_WIDTH-1:0] i_MEM_Data, // Data from main mem | |
28 | 29 | |||
// Outputs | 29 | 30 | // Outputs | |
output o_Ready, | 30 | 31 | output o_Ready, | |
output reg o_Valid, // If the output is correct. | 31 | 32 | output reg o_Valid, // If the output is correct. | |
output reg [DATA_WIDTH-1:0] o_Data // The data requested. | 32 | 33 | output reg [DATA_WIDTH-1:0] o_Data // The data requested. | |
); | 33 | 34 | ); | |
34 | 35 | |||
// consts | 35 | 36 | // consts | |
localparam FALSE = 1'b0; | 36 | 37 | localparam FALSE = 1'b0; | |
localparam TRUE = 1'b1; | 37 | 38 | localparam TRUE = 1'b1; | |
38 | 39 | |||
// Internal | 39 | 40 | // Internal | |
// Reg'd inputs | 40 | 41 | // Reg'd inputs | |
reg [BLOCK_OFFSET_WIDTH-1:0] r_i_BlockOffset; | 41 | 42 | reg [BLOCK_OFFSET_WIDTH-1:0] r_i_BlockOffset; | |
reg [INDEX_WIDTH-1:0] r_i_Index; | 42 | 43 | reg [INDEX_WIDTH-1:0] r_i_Index; | |
reg [TAG_WIDTH-1:0] r_i_Tag; | 43 | 44 | reg [TAG_WIDTH-1:0] r_i_Tag; | |
44 | 45 | |||
// Parsing | 45 | 46 | // Parsing | |
wire [BLOCK_OFFSET_WIDTH-1:0] i_BlockOffset = i_Address[BLOCK_OFFSET_WIDTH-1:0]; | 46 | 47 | wire [BLOCK_OFFSET_WIDTH-1:0] i_BlockOffset = i_Address[BLOCK_OFFSET_WIDTH-1:0]; | |
wire [INDEX_WIDTH-1:0] i_Index = i_Address[INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:BLOCK_OFFSET_WIDTH]; | 47 | 48 | wire [INDEX_WIDTH-1:0] i_Index = i_Address[INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:BLOCK_OFFSET_WIDTH]; | |
wire [TAG_WIDTH-1:0] i_Tag = i_Address[TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:INDEX_WIDTH+BLOCK_OFFSET_WIDTH]; | 48 | 49 | wire [TAG_WIDTH-1:0] i_Tag = i_Address[TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH-1:INDEX_WIDTH+BLOCK_OFFSET_WIDTH]; | |
49 | 50 | |||
// Tags | 50 | 51 | // Tags | |
reg [TAG_WIDTH-1:0] Tag_Array [0:(1<<INDEX_WIDTH)-1]; | 51 | 52 | reg [TAG_WIDTH-1:0] Tag_Array [0:(1<<INDEX_WIDTH)-1]; | |
// Data | 52 | 53 | // Data | |
reg [(DATA_WIDTH*4)-1:0] Data_Array [0:(1<<INDEX_WIDTH)-1]; | 53 | 54 | reg [(DATA_WIDTH*4)-1:0] Data_Array [0:(1<<INDEX_WIDTH)-1]; | |
// Valid | 54 | 55 | // Valid | |
reg Valid_Array [0:(1<<INDEX_WIDTH)-1]; | 55 | 56 | reg Valid_Array [0:(1<<INDEX_WIDTH)-1]; | |
56 | 57 | |||
// States | 57 | 58 | // States | |
reg [5:0] State; | 58 | 59 | reg [5:0] State; | |
reg [5:0] NextState; | 59 | 60 | reg [5:0] NextState; | |
60 | 61 | |||
localparam STATE_READY = 0; // Ready for incoming requests | 61 | 62 | localparam STATE_READY = 0; // Ready for incoming requests | |
localparam STATE_MISS_READ = 1; // Missing on a read | 62 | 63 | localparam STATE_MISS_READ = 1; // Missing on a read | |
63 | 64 | |||
// Counters | 64 | 65 | // Counters | |
integer i; | 65 | 66 | integer i; | |
reg [8:0] Gen_Count; // General counter | 66 | 67 | reg [8:0] Gen_Count; // General counter | |
67 | 68 | |||
// Hardwired assignments | 68 | 69 | // Hardwired assignments | |
assign o_Ready = (State==STATE_READY); | 69 | 70 | assign o_Ready = (State==STATE_READY); | |
70 | 71 | |||
71 | 72 | |||
72 | 73 | |||
// Combinatorial logic: What state are we in? How should we handle I/O? | 73 | 74 | // Combinatorial logic: What state are we in? How should we handle I/O? | |
always @(*) | 74 | 75 | always @(*) | |
begin | 75 | 76 | begin | |
// Set defaults to avoid latch inference | 76 | 77 | // Set defaults to avoid latch inference | |
NextState <= State; | 77 | 78 | NextState <= State; | |
o_Valid <= FALSE; | 78 | 79 | o_Valid <= FALSE; | |
o_Data <= {DATA_WIDTH{1'bx}}; | 79 | 80 | o_Data <= {DATA_WIDTH{1'bx}}; | |
o_MEM_Valid <= FALSE; | 80 | 81 | o_MEM_Valid <= FALSE; | |
o_MEM_Address <= {TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH{1'bx}}; | 81 | 82 | o_MEM_Address <= {TAG_WIDTH+INDEX_WIDTH+BLOCK_OFFSET_WIDTH{1'bx}}; | |
82 | 83 | |||
// Act asynchronously based on state | 83 | 84 | // Act asynchronously based on state | |
case(State) | 84 | 85 | case(State) | |
// We're ready for requests | 85 | 86 | // We're ready for requests | |
STATE_READY: | 86 | 87 | STATE_READY: | |
begin | 87 | 88 | begin | |
// Valid request? | 88 | 89 | // Valid request? | |
if( i_Valid ) | 89 | 90 | if( i_Valid ) | |
begin | 90 | 91 | begin | |
if( Valid_Array[i_Index] && | 91 | 92 | if( Valid_Array[i_Index] && | |
Tag_Array[i_Index] == i_Tag | 92 | 93 | Tag_Array[i_Index] == i_Tag | |
) | 93 | 94 | ) | |
begin | 94 | 95 | begin | |
// Hit! | 95 | 96 | // Hit! | |
o_Valid <= TRUE; | 96 | 97 | o_Valid <= TRUE; | |
97 | 98 | |||
case( i_BlockOffset ) | 98 | 99 | case( i_BlockOffset ) | |
// Verilog doesn't allow generic indexing into arrays with operators.. | 99 | 100 | // Verilog doesn't allow generic indexing into arrays with operators.. | |
0: o_Data <= Data_Array[i_Index][(DATA_WIDTH*1)-1:0]; | 100 | 101 | 0: o_Data <= Data_Array[i_Index][(DATA_WIDTH*1)-1:0]; | |
1: o_Data <= Data_Array[i_Index][(DATA_WIDTH*2)-1:(DATA_WIDTH*1)]; | 101 | 102 | 1: o_Data <= Data_Array[i_Index][(DATA_WIDTH*2)-1:(DATA_WIDTH*1)]; | |
2: o_Data <= Data_Array[i_Index][(DATA_WIDTH*3)-1:(DATA_WIDTH*2)]; | 102 | 103 | 2: o_Data <= Data_Array[i_Index][(DATA_WIDTH*3)-1:(DATA_WIDTH*2)]; | |
3: o_Data <= Data_Array[i_Index][(DATA_WIDTH*4)-1:(DATA_WIDTH*3)]; | 103 | 104 | 3: o_Data <= Data_Array[i_Index][(DATA_WIDTH*4)-1:(DATA_WIDTH*3)]; | |
default: o_Data <= {DATA_WIDTH{1'bx}}; | 104 | 105 | default: o_Data <= {DATA_WIDTH{1'bx}}; | |
endcase | 105 | 106 | endcase | |
end | 106 | 107 | end | |
else | 107 | 108 | else | |
begin | 108 | 109 | begin | |
// Miss. Will proceed to Miss state. | 109 | 110 | // Miss. Will proceed to Miss state. | |
NextState <= STATE_MISS_READ; | 110 | 111 | NextState <= STATE_MISS_READ; | |
end | 111 | 112 | end | |
end | 112 | 113 | end | |
else | 113 | 114 | else | |
begin | 114 | 115 | begin | |
// Invalid output | 115 | 116 | // Invalid output | |
end | 116 | 117 | end | |
end | 117 | 118 | end | |
118 | 119 | |||
// We are handling a read miss | 119 | 120 | // We are handling a read miss | |
STATE_MISS_READ: | 120 | 121 | STATE_MISS_READ: | |
begin | 121 | 122 | begin | |
// Submit our request. | 122 | 123 | // Submit our request. | |
o_MEM_Valid <= TRUE; | 123 | 124 | o_MEM_Valid <= TRUE; | |
o_MEM_Address <= {r_i_Tag,r_i_Index,{BLOCK_OFFSET_WIDTH{1'b0}},1'b0}; | 124 | 125 | o_MEM_Address <= {r_i_Tag,r_i_Index,{BLOCK_OFFSET_WIDTH{1'b0}}}; | |
125 | 126 | |||
// Mem is communicating? | 126 | 127 | // Mem is communicating? | |
if( i_MEM_Valid ) | 127 | 128 | if( i_MEM_Valid ) | |
begin | 128 | 129 | begin | |
129 | 130 | |||
// Is this the data we were waiting on? | 130 | 131 | // Is this the data we were waiting on? | |
if( Gen_Count == r_i_BlockOffset ) | 131 | 132 | if( Gen_Count == r_i_BlockOffset ) | |
begin | 132 | 133 | begin | |
// Yes | 133 | 134 | // Yes | |
o_Valid <= TRUE; | 134 | 135 | o_Valid <= TRUE; | |
o_Data <= i_MEM_Data; | 135 | 136 | o_Data <= i_MEM_Data; | |
end | 136 | 137 | end | |
137 | 138 | |||
// Last piece of transaction? | 138 | 139 | // Last piece of transaction? | |
if( i_MEM_Last ) | 139 | 140 | if( i_MEM_Last ) | |
begin | 140 | 141 | begin | |
// This is the last piece of data. We will transition on the next cycle. | 141 | 142 | // This is the last piece of data. We will transition on the next cycle. | |
NextState <= STATE_READY; | 142 | 143 | NextState <= STATE_READY; | |
end | 143 | 144 | end | |
end | 144 | 145 | end | |
end | 145 | 146 | end | |
146 | 147 | |||
// Invalid state | 147 | 148 | // Invalid state | |
default: | 148 | 149 | default: | |
begin | 149 | 150 | begin | |
$display("Warning: Invalid state @ i_cache.v: %d",$time); | 150 | 151 | $display("Warning: Invalid state @ i_cache.v: %d",$time); | |
end | 151 | 152 | end | |
endcase | 152 | 153 | endcase | |
end | 153 | 154 | end | |
154 | 155 | |||
// State driver | 155 | 156 | // State driver | |
always @(posedge i_Clk or negedge i_Reset_n) | 156 | 157 | always @(posedge i_Clk or negedge i_Reset_n) | |
begin | 157 | 158 | begin | |
if( !i_Reset_n ) | 158 | 159 | if( !i_Reset_n ) | |
begin | 159 | 160 | begin | |
State <= STATE_READY; | 160 | 161 | State <= STATE_READY; | |
end | 161 | 162 | end | |
else | 162 | 163 | else | |
begin | 163 | 164 | begin | |
State <= NextState; | 164 | 165 | State <= NextState; | |
165 | 166 | |||
// Initialize for next state | 166 | 167 | // Initialize for next state | |
case( State ) | 167 | 168 | case( State ) | |
STATE_READY: | 168 | 169 | STATE_READY: | |
begin | 169 | 170 | begin | |
if( NextState == STATE_MISS_READ ) | 170 | 171 | if( NextState == STATE_MISS_READ ) | |
begin | 171 | 172 | begin | |
// Prepare counter | 172 | 173 | // Prepare counter | |
Gen_Count <= 0; | 173 | 174 | Gen_Count <= 0; | |
174 | 175 | |||
// Latch inputs | 175 | 176 | // Latch inputs | |
r_i_BlockOffset <= i_BlockOffset; | 176 | 177 | r_i_BlockOffset <= i_BlockOffset; | |
r_i_Index <= i_Index; | 177 | 178 | r_i_Index <= i_Index; | |
r_i_Tag <= i_Tag; | 178 | 179 | r_i_Tag <= i_Tag; | |
end | 179 | 180 | end | |
end | 180 | 181 | end | |
181 | 182 | |||
STATE_MISS_READ: | 182 | 183 | STATE_MISS_READ: | |
begin | 183 | 184 | begin | |
if( NextState == STATE_READY ) | 184 | 185 | if( NextState == STATE_READY ) | |
begin | 185 | 186 | begin | |
// Record info about transaction in tags & valid bits | 186 | 187 | // Record info about transaction in tags & valid bits | |
Tag_Array[r_i_Index] <= r_i_Tag; | 187 | 188 | Tag_Array[r_i_Index] <= r_i_Tag; | |
Valid_Array[r_i_Index] <= TRUE; | 188 | 189 | Valid_Array[r_i_Index] <= TRUE; | |
end | 189 | 190 | end | |
190 | 191 | |||
if( i_MEM_Valid ) | 191 | 192 | if( i_MEM_Valid ) | |
begin | 192 | 193 | begin | |
case( Gen_Count ) | 193 | 194 | case( Gen_Count ) | |
0: Data_Array[r_i_Index][(DATA_WIDTH*1)-1:0] <= i_MEM_Data; | 194 | 195 | 0: Data_Array[r_i_Index][(DATA_WIDTH*1)-1:0] <= i_MEM_Data; | |
1: Data_Array[r_i_Index][(DATA_WIDTH*2)-1:(DATA_WIDTH*1)] <= i_MEM_Data; | 195 | 196 | 1: Data_Array[r_i_Index][(DATA_WIDTH*2)-1:(DATA_WIDTH*1)] <= i_MEM_Data; | |
2: Data_Array[r_i_Index][(DATA_WIDTH*3)-1:(DATA_WIDTH*2)] <= i_MEM_Data; | 196 | 197 | 2: Data_Array[r_i_Index][(DATA_WIDTH*3)-1:(DATA_WIDTH*2)] <= i_MEM_Data; | |
3: Data_Array[r_i_Index][(DATA_WIDTH*4)-1:(DATA_WIDTH*3)] <= i_MEM_Data; | 197 | 198 | 3: Data_Array[r_i_Index][(DATA_WIDTH*4)-1:(DATA_WIDTH*3)] <= i_MEM_Data; | |
default: $display("Warning: Invalid Gen Count value @ i_cache"); | 198 | 199 | default: $display("Warning: Invalid Gen Count value @ i_cache"); |
src/memory_arbiter.v
View file @
bec01f1
/* memory_arbiter.v | 1 | 1 | /* memory_arbiter.v | |
* Author: Pravin P. Prabhu | 2 | 2 | * Author: Pravin P. Prabhu, Zinsser Zhang | |
* Last Revision: 1/5/11 | 3 | 3 | * Last Revision: 04/29/2017 | |
* Abstract: | 4 | 4 | * Abstract: | |
* Provides arbitration amongst sources that all wish to request from main | 5 | 5 | * Provides arbitration amongst sources that all wish to request from main | |
* memory. Will service sources in order of priority, which is: | 6 | 6 | * memory. Will service sources in order of priority, which is: | |
* (high) | 7 | 7 | * (high) | |
* flashloader | 8 | 8 | * flashloader | |
* imem | 9 | 9 | * CORE | |
* vga -- (to be included) | 10 | |||
* dmem | 11 | |||
* (low) | 12 | 10 | * (low) | |
*/ | 13 | 11 | */ | |
module memory_arbiter #( parameter DATA_WIDTH=32, | 14 | 12 | module memory_arbiter #( parameter DATA_WIDTH=32, | |
parameter ADDRESS_WIDTH=22 | 15 | 13 | parameter ADDRESS_WIDTH=22, | |
14 | parameter CORE_ADDRESS_WIDTH=21 | |||
) | 16 | 15 | ) | |
( | 17 | 16 | ( | |
// General | 18 | 17 | // General | |
input i_Clk, | 19 | 18 | input i_Clk, | |
input i_Reset_n, | 20 | 19 | input i_Reset_n, | |
21 | 20 | |||
// Requests to/from IMEM - Assume we always read | 22 | 21 | // Requests to/from CORE | |
input i_IMEM_Valid, // If IMEM request is valid | 23 | 22 | input i_CORE_Valid, | |
input [ADDRESS_WIDTH-1:0] i_IMEM_Address, // IMEM request addr. | 24 | 23 | input i_CORE_Read_Write_n, | |
output reg o_IMEM_Valid, | 25 | 24 | input [CORE_ADDRESS_WIDTH-1:0] i_CORE_Address, | |
output reg o_IMEM_Last, | 26 | 25 | input [DATA_WIDTH-1:0] i_CORE_Data, | |
output reg [DATA_WIDTH-1:0] o_IMEM_Data, | 27 | 26 | output reg o_CORE_Valid, | |
28 | 27 | output reg o_CORE_Data_Read, | ||
// Requests to/from DMEM | 29 | 28 | output reg o_CORE_Last, | |
input i_DMEM_Valid, | 30 | 29 | output reg [DATA_WIDTH-1:0] o_CORE_Data, | |
input i_DMEM_Read_Write_n, | 31 | 30 | ||
input [ADDRESS_WIDTH-1:0] i_DMEM_Address, | 32 | |||
input [DATA_WIDTH-1:0] i_DMEM_Data, | 33 | |||
output reg o_DMEM_Valid, | 34 | |||
output reg o_DMEM_Data_Read, | 35 | |||
output reg o_DMEM_Last, | 36 | |||
output reg [DATA_WIDTH-1:0] o_DMEM_Data, | 37 | |||
38 | ||||
// Requests to/from FLASH - Assume we always write | 39 | 31 | // Requests to/from FLASH - Assume we always write | |
input i_Flash_Valid, | 40 | 32 | input i_Flash_Valid, | |
input [DATA_WIDTH-1:0] i_Flash_Data, | 41 | 33 | input [DATA_WIDTH-1:0] i_Flash_Data, | |
input [ADDRESS_WIDTH-1:0] i_Flash_Address, | 42 | 34 | input [ADDRESS_WIDTH-1:0] i_Flash_Address, | |
output reg o_Flash_Data_Read, | 43 | 35 | output reg o_Flash_Data_Read, | |
output reg o_Flash_Last, | 44 | 36 | output reg o_Flash_Last, | |
45 | 37 | |||
// Interface with SDRAM Controller | 46 | 38 | // Interface with SDRAM Controller | |
output reg o_MEM_Valid, | 47 | 39 | output reg o_MEM_Valid, | |
output reg [ADDRESS_WIDTH-1:0] o_MEM_Address, | 48 | 40 | output reg [ADDRESS_WIDTH-1:0] o_MEM_Address, | |
output reg o_MEM_Read_Write_n, | 49 | 41 | output reg o_MEM_Read_Write_n, | |
50 | 42 | |||
// Write data interface | 51 | 43 | // Write data interface | |
output reg [DATA_WIDTH-1:0] o_MEM_Data, | 52 | 44 | output reg [DATA_WIDTH-1:0] o_MEM_Data, | |
input i_MEM_Data_Read, | 53 | 45 | input i_MEM_Data_Read, | |
54 | 46 | |||
// Read data interface | 55 | 47 | // Read data interface | |
input [DATA_WIDTH-1:0] i_MEM_Data, | 56 | 48 | input [DATA_WIDTH-1:0] i_MEM_Data, | |
input i_MEM_Data_Valid, | 57 | 49 | input i_MEM_Data_Valid, | |
58 | 50 | |||
input i_MEM_Last // If we're on the last piece of the transaction | 59 | 51 | input i_MEM_Last // If we're on the last piece of the transaction | |
); | 60 | 52 | ); | |
61 | 53 | |||
// Consts | 62 | 54 | // Consts | |
localparam TRUE = 1'b1; | 63 | 55 | localparam TRUE = 1'b1; | |
localparam FALSE = 1'b0; | 64 | 56 | localparam FALSE = 1'b0; | |
localparam READ = 1'b1; | 65 | 57 | localparam READ = 1'b1; | |
localparam WRITE = 1'b0; | 66 | 58 | localparam WRITE = 1'b0; | |
67 | 59 | |||
// State of the arbiter | 68 | 60 | // State of the arbiter | |
localparam STATE_READY = 4'd0; | 69 | 61 | localparam STATE_READY = 4'd0; | |
localparam STATE_SERVICING_FLASH = 4'd1; | 70 | 62 | localparam STATE_SERVICING_FLASH = 4'd1; | |
localparam STATE_SERVICING_IMEM = 4'd2; | 71 | 63 | localparam STATE_SERVICING_CORE = 4'd2; | |
localparam STATE_SERVICING_DMEM = 4'd3; | 72 | 64 | ||
localparam STATE_SERVICING_VGA = 4'd4; | 73 | |||
74 | ||||
reg [3:0] State; | 75 | 65 | reg [3:0] State; | |
66 | reg [3:0] NextState; | |||
76 | 67 | |||
always @(*) | 77 | 68 | always @(*) | |
begin | 78 | 69 | begin | |
o_IMEM_Valid <= FALSE; | 79 | 70 | NextState <= State; | |
o_IMEM_Last <= FALSE; | 80 | |||
o_IMEM_Data <= {32{1'bx}}; | 81 | |||
o_DMEM_Valid <= FALSE; | 82 | |||
o_DMEM_Data_Read <= FALSE; | 83 | |||
o_DMEM_Last <= FALSE; | 84 | |||
o_DMEM_Data <= {32{1'bx}}; | 85 | |||
o_Flash_Data_Read <= FALSE; | 86 | |||
o_Flash_Last <= FALSE; | 87 | |||
o_MEM_Valid <= FALSE; | 88 | |||
o_MEM_Address <= {ADDRESS_WIDTH{1'bx}}; | 89 | |||
o_MEM_Read_Write_n <= READ; | 90 | |||
o_MEM_Data <= {32{1'bx}}; | 91 | |||
92 | ||||
case(State) | 93 | 71 | case(State) | |
//======================= | 94 | |||
// Accept State | 95 | |||
STATE_READY: | 96 | 72 | STATE_READY: | |
begin | 97 | 73 | begin | |
74 | if (i_Flash_Valid) | |||
75 | NextState <= STATE_SERVICING_FLASH; | |||
76 | else if (i_CORE_Valid) | |||
77 | NextState <= STATE_SERVICING_CORE; | |||
end | 98 | 78 | end | |
99 | 79 | |||
//======================= | 100 | |||
// Services States | 101 | |||
STATE_SERVICING_FLASH: | 102 | 80 | STATE_SERVICING_FLASH: | |
begin | 103 | 81 | begin | |
// Servicing flash: Bridge flash I/O | 104 | 82 | if (i_MEM_Last) | |
o_MEM_Valid <= TRUE; | 105 | 83 | NextState <= STATE_READY; | |
o_MEM_Address <= i_Flash_Address; | 106 | |||
o_MEM_Read_Write_n <= WRITE; | 107 | |||
o_MEM_Data <= i_Flash_Data; | 108 | |||
o_Flash_Data_Read <= i_MEM_Data_Read; | 109 | |||
o_Flash_Last <= i_MEM_Last; | 110 | |||
end | 111 | 84 | end | |
112 | 85 | |||
STATE_SERVICING_IMEM: | 113 | 86 | STATE_SERVICING_CORE: | |
begin | 114 | 87 | begin | |
o_MEM_Valid <= TRUE; | 115 | 88 | if (i_MEM_Last) | |
o_MEM_Address <= i_IMEM_Address; | 116 | 89 | NextState <= STATE_READY; | |
o_MEM_Read_Write_n <= READ; | 117 | |||
o_IMEM_Valid <= i_MEM_Data_Valid; | 118 | |||
o_IMEM_Last <= i_MEM_Last; | 119 | |||
o_IMEM_Data <= i_MEM_Data; | 120 | |||
end | 121 | 90 | end | |
122 | ||||
STATE_SERVICING_DMEM: | 123 | |||
begin | 124 | |||
o_MEM_Valid <= TRUE; | 125 | |||
o_MEM_Address <= i_DMEM_Address; | 126 | |||
o_MEM_Read_Write_n <= i_DMEM_Read_Write_n; | 127 | |||
o_MEM_Data <= i_DMEM_Data; | 128 | |||
o_DMEM_Valid <= i_MEM_Data_Valid; | 129 | |||
o_DMEM_Data_Read <= i_MEM_Data_Read; | 130 | |||
o_DMEM_Last <= i_MEM_Last; | 131 | |||
o_DMEM_Data <= i_MEM_Data; | 132 | |||
end | 133 | |||
endcase | 134 | 91 | endcase | |
92 | ||||
93 | o_CORE_Valid <= FALSE; | |||
94 | o_CORE_Data_Read <= FALSE; | |||
95 | o_CORE_Last <= FALSE; | |||
96 | o_CORE_Data <= {32{1'bx}}; | |||
97 | o_Flash_Data_Read <= FALSE; | |||
98 | o_Flash_Last <= FALSE; | |||
99 | o_MEM_Valid <= FALSE; | |||
100 | o_MEM_Address <= {ADDRESS_WIDTH{1'bx}}; | |||
101 | o_MEM_Read_Write_n <= READ; | |||
102 | o_MEM_Data <= {32{1'bx}}; | |||
103 | ||||
104 | if (State == STATE_SERVICING_FLASH || NextState == STATE_SERVICING_FLASH) | |||
105 | begin | |||
106 | // Servicing flash: Bridge flash I/O | |||
107 | o_MEM_Valid <= TRUE; | |||
108 | o_MEM_Address <= i_Flash_Address; | |||
109 | o_MEM_Read_Write_n <= WRITE; | |||
110 | o_MEM_Data <= i_Flash_Data; | |||
111 | o_Flash_Data_Read <= i_MEM_Data_Read; | |||
112 | o_Flash_Last <= i_MEM_Last; | |||
113 | end | |||
114 | else if (State == STATE_SERVICING_CORE || NextState == STATE_SERVICING_CORE) | |||
115 | begin | |||
116 | o_MEM_Valid <= TRUE; | |||
117 | o_MEM_Address <= {i_CORE_Address, 1'b0}; | |||
118 | o_MEM_Read_Write_n <= i_CORE_Read_Write_n; | |||
119 | o_MEM_Data <= i_CORE_Data; | |||
120 | o_CORE_Valid <= i_MEM_Data_Valid; | |||
121 | o_CORE_Data_Read <= i_MEM_Data_Read; | |||
122 | o_CORE_Last <= i_MEM_Last; | |||
123 | o_CORE_Data <= i_MEM_Data; | |||
124 | end | |||
end | 135 | 125 | end | |
136 | 126 | |||
// State driver | 137 | 127 | // State driver | |
always @(posedge i_Clk or negedge i_Reset_n) | 138 | 128 | always @(posedge i_Clk or negedge i_Reset_n) | |
begin | 139 | 129 | begin | |
if( !i_Reset_n ) | 140 | 130 | if( !i_Reset_n ) | |
begin | 141 | 131 | // Defaults | |
// Defaults | 142 | 132 | State <= STATE_READY; | |
State <= STATE_READY; | 143 | |||
end | 144 | |||
else | 145 | 133 | else | |
begin | 146 | 134 | State <= NextState; | |
case(State) | 147 | |||
//======================= | 148 | |||
// Accept State | 149 | |||
STATE_READY: | 150 | |||
begin | 151 | |||
if( i_Flash_Valid ) | 152 | |||
begin | 153 | |||
State <= STATE_SERVICING_FLASH; | 154 | |||
end | 155 | |||
else if( i_IMEM_Valid ) | 156 | |||
begin | 157 | |||
State <= STATE_SERVICING_IMEM; | 158 | |||
end | 159 | |||
else if( i_DMEM_Valid ) | 160 | |||
begin | 161 | |||
State <= STATE_SERVICING_DMEM; | 162 | |||
end | 163 | |||
end | 164 | |||
165 | ||||
//======================= | 166 | |||
// Services States | 167 | |||
STATE_SERVICING_FLASH: | 168 | |||
begin | 169 | |||
// See if we're done transacting | 170 | |||
if( i_MEM_Last ) | 171 | |||
State <= STATE_READY; | 172 | |||
end | 173 | |||
174 | ||||
STATE_SERVICING_IMEM: | 175 | |||
begin | 176 | |||
// See if we're done transacting | 177 | |||
if( i_MEM_Last ) | 178 | |||
State <= STATE_READY; | 179 | |||
end | 180 | |||
181 | ||||
STATE_SERVICING_DMEM: | 182 | |||
begin | 183 | |||
// See if we're done transacting | 184 | |||
if( i_MEM_Last ) | 185 | |||
State <= STATE_READY; | 186 | |||
end | 187 | |||
188 | ||||
// Remain in current state by default | 189 | |||
default: | 190 | |||
begin | 191 | |||
end | 192 | |||
endcase | 193 | |||
end | 194 | |||
end | 195 | 135 | end | |
196 | ||||
endmodule | 197 | 136 | endmodule | |
198 | ||||
137 | ||||
src/mips_core.v
View file @
bec01f1
File was created | 1 | /* mips_core.v | ||
2 | * Author: Pravin P. Prabhu, Dean Tullsen, and Zinsser Zhang | |||
3 | * Last Revision: 04/28/2017 | |||
4 | * Abstract: | |||
5 | * The core module for the MIPS32 processor. This is a classic 5-stage | |||
6 | * MIPS pipeline architecture which is intended to follow heavily from the model | |||
7 | * presented in Hennessy and Patterson's Computer Organization and Design. | |||
8 | * All addresses used in this scope are word addresses (32-bit/4-byte aligned) | |||
9 | */ | |||
10 | module mips_core #( | |||
11 | parameter DATA_WIDTH = 32, | |||
12 | parameter WORD_ADDRESS_WIDTH = 21 | |||
13 | ) | |||
14 | ( // General | |||
15 | input i_Clk, | |||
16 | input i_Reset_n, | |||
17 | input i_External_Stall, // Global Stall issued by top level | |||
18 | ||||
19 | // Memory bus interface | |||
20 | output o_MEM_Valid, | |||
21 | output o_MEM_Read_Write_n, | |||
22 | output [WORD_ADDRESS_WIDTH-1:0] o_MEM_Address, | |||
23 | output [DATA_WIDTH-1:0] o_MEM_Data, | |||
24 | input i_MEM_Valid, | |||
25 | input i_MEM_Data_Read, | |||
26 | input i_MEM_Last, | |||
27 | input [DATA_WIDTH-1:0] i_MEM_Data, | |||
28 | ||||
29 | // Outputs for Done flag | |||
30 | output [15:0] o_Pass_Done_Value, // reports the value of a PASS/FAIL/DONE instruction | |||
31 | output [1:0] o_Pass_Done_Change, // indicates the above signal is meaningful | |||
32 | // 1 = pass, 2 = fail, 3 = done | |||
33 | ||||
34 | // Outputs for performance display | |||
35 | output [7:0] o_Num_Inst_Executed, | |||
36 | output [20:0] o_IMEM_i_Address | |||
37 | ); | |||
38 | ||||
39 | //=================================================================== | |||
40 | // Internal Wiring | |||
41 | //=================================================================== | |||
42 | ||||
43 | //=================================================================== | |||
44 | // General Signals | |||
45 | localparam FALSE = 1'b0; | |||
46 | localparam TRUE = 1'b1; | |||
47 | localparam BYTE_ADDRESS_WIDTH = WORD_ADDRESS_WIDTH + 2; | |||
48 | ||||
49 | //=================================================================== | |||
50 | // IFetch Signals | |||
51 | ||||
52 | wire IFetch_i_Flush; // Flush for IFetch | |||
53 | wire Hazard_Stall_IF; // Stall for IFetch | |||
54 | wire IFetch_i_Load; // Load signal - if high, load pc with vector | |||
55 | wire [WORD_ADDRESS_WIDTH-1:0] IFetch_i_PCSrc; // Vector to branch to | |||
56 | ||||
57 | wire [WORD_ADDRESS_WIDTH-1:0] IMEM_i_Address; // Current PC | |||
58 | ||||
59 | ||||
60 | wire IMEM_o_Ready; | |||
61 | wire IMEM_o_Valid; | |||
62 | wire [DATA_WIDTH-1:0] IMEM_o_Instruction; | |||
63 | ||||
64 | //============== | |||
65 | // Pipe signals: IF->ID | |||
66 | wire Hazard_Flush_IF; // 1st pipe flush | |||
67 | wire Hazard_Stall_DEC; // 1st pipe stall | |||
68 | wire imembubble_DEC; // set if instruction coming out of icache | |||
69 | // was not real instruction | |||
70 | //=================================================================== | |||
71 | // Decoder Signals | |||
72 | localparam ALU_CTLCODE_WIDTH = 8; | |||
73 | localparam REG_ADDR_WIDTH = 5; | |||
74 | localparam MEM_MASK_WIDTH = 3; | |||
75 | wire [WORD_ADDRESS_WIDTH-1:0] DEC_i_PC; // PC of inst | |||
76 | wire [DATA_WIDTH-1:0] DEC_i_Instruction; // Inst into decode | |||
77 | wire DEC_Noop = (DEC_i_Instruction == 32'd0); | |||
78 | ||||
79 | wire DEC_o_Uses_ALU; | |||
80 | wire [ALU_CTLCODE_WIDTH-1:0] DEC_o_ALUCTL; // ALU control code | |||
81 | wire DEC_o_Is_Branch; // If it's a branch | |||
82 | wire [WORD_ADDRESS_WIDTH-1:0] DEC_o_Branch_Target; // Where we will branch to | |||
83 | wire DEC_o_Jump_Reg; // If this is a special case where we jump TO a register value | |||
84 | ||||
85 | wire DEC_o_Mem_Valid; | |||
86 | wire DEC_o_Mem_Read_Write_n; | |||
87 | wire [MEM_MASK_WIDTH-1:0] DEC_o_Mem_Mask; // Used for masking individual memory ops - such as byte and halfword transactions | |||
88 | ||||
89 | wire DEC_o_Writes_Back; | |||
90 | wire [REG_ADDR_WIDTH-1:0] DEC_o_Write_Addr; | |||
91 | wire DEC_o_Uses_RS; | |||
92 | wire [REG_ADDR_WIDTH-1:0] DEC_o_Read_Register_1; | |||
93 | wire DEC_o_Uses_RT; | |||
94 | wire [REG_ADDR_WIDTH-1:0] DEC_o_Read_Register_2; | |||
95 | ||||
96 | wire [DATA_WIDTH-1:0] DEC_o_Read_Data_1; | |||
97 | wire [DATA_WIDTH-1:0] DEC_o_Read_Data_2; | |||
98 | ||||
99 | wire DEC_o_Uses_Immediate; | |||
100 | wire [DATA_WIDTH-1:0] DEC_o_Immediate; | |||
101 | ||||
102 | wire [DATA_WIDTH-1:0] FORWARD_o_Forwarded_Data_1,FORWARD_o_Forwarded_Data_2; // Looked up regs | |||
103 | ||||
104 | //============== | |||
105 | // Pipe signals: ID->EX | |||
106 | wire Hazard_Flush_DEC; // 2nd pipe flush | |||
107 | wire Hazard_Stall_EX; // 2nd pipe stall | |||
108 | ||||
109 | wire [WORD_ADDRESS_WIDTH-1:0] DEC_o_PC; | |||
110 | assign DEC_o_PC = DEC_i_PC; | |||
111 | ||||
112 | //=================================================================== | |||
113 | // Execute Signals | |||
114 | ||||
115 | wire [WORD_ADDRESS_WIDTH-1:0] ALU_i_PC; | |||
116 | ||||
117 | wire EX_i_Is_Branch; | |||
118 | wire EX_i_Mem_Valid; | |||
119 | wire [MEM_MASK_WIDTH-1:0] EX_i_Mem_Mask; | |||
120 | wire EX_i_Mem_Read_Write_n; | |||
121 | wire [DATA_WIDTH-1:0] EX_i_Mem_Write_Data; | |||
122 | wire EX_i_Writes_Back; | |||
123 | wire [REG_ADDR_WIDTH-1:0] EX_i_Write_Addr; | |||
124 | ||||
125 | wire ALU_i_Valid; // Whether input to ALU is valid or not | |||
126 | wire ALU_o_Valid; | |||
127 | wire [ALU_CTLCODE_WIDTH-1:0] ALU_i_ALUOp; // Control bus to ALU | |||
128 | wire [DATA_WIDTH-1:0] ALU_i_Operand1,ALU_i_Operand2; // Ops for ALU | |||
129 | wire [WORD_ADDRESS_WIDTH-1:0] EX_i_Branch_Target; | |||
130 | wire [DATA_WIDTH-1:0] ALU_o_Result; // Computation of ALU | |||
131 | wire ALU_o_Branch_Valid; // Whether branch is valid or not | |||
132 | wire ALU_o_Branch_Outcome; // Whether branch is taken or not | |||
133 | wire [15:0] ALU_o_Pass_Done_Value; // reports the value of a PASS/FAIL/DONE instruction | |||
134 | wire [1:0] ALU_o_Pass_Done_Change; // indicates the above signal is meaningful | |||
135 | // 1 = pass, 2 = fail, 3 = done | |||
136 | ||||
137 | // Cumulative signals | |||
138 | wire EX_Take_Branch = ALU_o_Valid && ALU_o_Branch_Valid && ALU_o_Branch_Outcome; // Whether we should branch or not. | |||
139 | ||||
140 | //============== | |||
141 | // Pipe signals: EX->MEM | |||
142 | wire Hazard_Flush_EX; // 3rd pipe flush | |||
143 | wire Hazard_Stall_MEM; // 3rd pipe stall | |||
144 | ||||
145 | ||||
146 | //=================================================================== | |||
147 | // Memory Signals | |||
148 | wire [DATA_WIDTH-1:0] DMEM_i_Result; // Result from the ALU | |||
149 | wire [DATA_WIDTH-1:0] DMEM_i_Mem_Write_Data; // What we will write back to mem (if applicable) | |||
150 | wire DMEM_i_Mem_Valid; // If the memory operation is valid | |||
151 | wire [MEM_MASK_WIDTH-1:0] DMEM_i_Mem_Mask; // Mem mask for sub-word operations | |||
152 | wire DMEM_i_Mem_Read_Write_n; // Type of memop | |||
153 | wire DMEM_i_Writes_Back; // If the result should be written back to regfile | |||
154 | wire [REG_ADDR_WIDTH-1:0] DMEM_i_Write_Addr; // Which reg in the regfile to write to | |||
155 | wire [DATA_WIDTH-1:0] DMEM_o_Read_Data; // The data READ from DMEM | |||
156 | wire DMEM_o_Mem_Ready; // If the DMEM is ready to service another request | |||
157 | wire DMEM_o_Mem_Valid; // If the value read from DMEM is valid | |||
158 | reg DMEM_o_Done; // If MEM's work is finalized | |||
159 | reg [DATA_WIDTH-1:0] DMEM_o_Write_Data; // Data we should write back to regfile | |||
160 | ||||
161 | wire MemToReg = DMEM_i_Mem_Valid; // Selects what we will write back -- mem or ALU result | |||
162 | ||||
163 | //============== | |||
164 | // Pipe signals: MEM->WB | |||
165 | wire Hazard_Flush_MEM; // 4th pipe flush | |||
166 | wire Hazard_Stall_WB; // 4th pipe stall | |||
167 | ||||
168 | ||||
169 | //=================================================================== | |||
170 | // Write-Back Signals | |||
171 | wire WB_i_Writes_Back; // If we will write back | |||
172 | wire [REG_ADDR_WIDTH-1:0] DEC_i_Write_Register; // Where we will write back to | |||
173 | wire [DATA_WIDTH-1:0] WB_i_Write_Data; // What we will write back | |||
174 | wire Hazard_Flush_WB; // Request to squash WB contents | |||
175 | ||||
176 | wire DEC_i_RegWrite = WB_i_Writes_Back && !Hazard_Flush_WB; | |||
177 | ||||
178 | //=================================================================== | |||
179 | // Core memory bus arbiter Signals | |||
180 | wire Arbiter_i_IMEM_Valid; | |||
181 | wire [WORD_ADDRESS_WIDTH-1:0] Arbiter_i_IMEM_Address; | |||
182 | wire Arbiter_o_IMEM_Valid; | |||
183 | wire Arbiter_o_IMEM_Last; | |||
184 | wire [DATA_WIDTH-1:0] Arbiter_o_IMEM_Data; | |||
185 | ||||
186 | wire Arbiter_i_DMEM_Valid; | |||
187 | wire Arbiter_i_DMEM_Read_Write_n; | |||
188 | wire [WORD_ADDRESS_WIDTH-1:0] Arbiter_i_DMEM_Address; | |||
189 | wire [DATA_WIDTH-1:0] Arbiter_i_DMEM_Data; | |||
190 | wire [DATA_WIDTH-1:0] Arbiter_o_DMEM_Data; | |||
191 | wire Arbiter_o_DMEM_Data_Read; | |||
192 | wire Arbiter_o_DMEM_Valid; | |||
193 | wire Arbiter_o_DMEM_Last; | |||
194 | ||||
195 | //=================================================================== | |||
196 | // Top-level Connections | |||
197 | ||||
198 | // Report number of instructions that is finishing up execution in Decode | |||
199 | // For this baseline this number can not exceed 1. | |||
200 | assign o_Num_Inst_Executed = !Hazard_Stall_DEC && !Hazard_Flush_DEC && !DEC_Noop; | |||
201 | ||||
202 | // Report current request address to i_cache | |||
203 | assign o_IMEM_i_Address = IMEM_i_Address; | |||
204 | ||||
205 | // Report Done flag/value | |||
206 | assign o_Pass_Done_Value = ALU_o_Pass_Done_Value; | |||
207 | assign o_Pass_Done_Change = ALU_o_Pass_Done_Change; | |||
208 | ||||
209 | //=================================================================== | |||
210 | // Structural Description - Pipeline stages | |||
211 | //=================================================================== | |||
212 | ||||
213 | //=================================================================== | |||
214 | // Instruction Fetch | |||
215 | fetch_unit #( .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH), | |||
216 | .DATA_WIDTH(DATA_WIDTH) | |||
217 | ) | |||
218 | IFETCH | |||
219 | ( // Inputs | |||
220 | .i_Clk(i_Clk), | |||
221 | .i_Reset_n(i_Reset_n), | |||
222 | .i_Stall(Hazard_Stall_IF), | |||
223 | ||||
224 | .i_Load(IFetch_i_Load), | |||
225 | .i_Load_Address(IFetch_i_PCSrc), | |||
226 | ||||
227 | // Outputs | |||
228 | .o_PC(IMEM_i_Address) | |||
229 | ); | |||
230 | ||||
231 | i_cache #( .DATA_WIDTH(DATA_WIDTH) | |||
232 | ) | |||
233 | I_CACHE | |||
234 | ( | |||
235 | // General | |||
236 | .i_Clk(i_Clk), | |||
237 | .i_Reset_n(i_Reset_n), | |||
238 | ||||
239 | // Requests | |||
240 | .i_Valid(!i_External_Stall), | |||
241 | .i_Address(IMEM_i_Address), | |||
242 | ||||
243 | // Mem Transaction | |||
244 | .o_MEM_Valid(Arbiter_i_IMEM_Valid), | |||
245 | .o_MEM_Address(Arbiter_i_IMEM_Address), | |||
246 | .i_MEM_Valid(Arbiter_o_IMEM_Valid), // If data from main mem is valid | |||
247 | .i_MEM_Last(Arbiter_o_IMEM_Last), // If main mem is sending the last piece of data | |||
248 | .i_MEM_Data(Arbiter_o_IMEM_Data), // Data from main mem | |||
249 | ||||
250 | // Outputs | |||
251 | .o_Ready(IMEM_o_Ready), | |||
252 | .o_Valid(IMEM_o_Valid), // If the output is correct. | |||
253 | .o_Data(IMEM_o_Instruction) // The data requested. | |||
254 | ); | |||
255 | ||||
256 | //=================================================================== | |||
257 | // Decode | |||
258 | pipe_if_dec #( .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH), | |||
259 | .DATA_WIDTH(DATA_WIDTH) | |||
260 | ) | |||
261 | PIPE_IF_DEC | |||
262 | ( // Inputs | |||
263 | .i_Clk(i_Clk), | |||
264 | .i_Reset_n(i_Reset_n), | |||
265 | .i_Flush(Hazard_Flush_IF), | |||
266 | .i_Stall(Hazard_Stall_DEC), | |||
267 | .i_imembubble(IMEM_o_Valid), | |||
268 | ||||
269 | // Pipe signals | |||
270 | .i_PC(IMEM_i_Address), | |||
271 | .o_PC(DEC_i_PC), | |||
272 | .i_Instruction(IMEM_o_Instruction), | |||
273 | .o_Instruction(DEC_i_Instruction), | |||
274 | .o_imembubble(imembubble_DEC) | |||
275 | ); | |||
276 | ||||
277 | decoder #( .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH), | |||
278 | .DATA_WIDTH(DATA_WIDTH), | |||
279 | .REG_ADDRESS_WIDTH(REG_ADDR_WIDTH), | |||
280 | .ALUCTL_WIDTH(ALU_CTLCODE_WIDTH), | |||
281 | .MEM_MASK_WIDTH(MEM_MASK_WIDTH) | |||
282 | ) | |||
283 | DECODE | |||
284 | ( // Inputs | |||
285 | .i_PC(DEC_i_PC), | |||
286 | .i_Instruction(DEC_i_Instruction), | |||
287 | .i_Stall(Hazard_Stall_DEC), | |||
288 | ||||
289 | // Outputs | |||
290 | .o_Uses_ALU(DEC_o_Uses_ALU), | |||
291 | .o_ALUCTL(DEC_o_ALUCTL), | |||
292 | .o_Is_Branch(DEC_o_Is_Branch), | |||
293 | .o_Jump_Reg(DEC_o_Jump_Reg), | |||
294 | ||||
295 | .o_Mem_Valid(DEC_o_Mem_Valid), | |||
296 | .o_Mem_Read_Write_n(DEC_o_Mem_Read_Write_n), | |||
297 | .o_Mem_Mask(DEC_o_Mem_Mask), | |||
298 | ||||
299 | .o_Writes_Back(DEC_o_Writes_Back), | |||
300 | .o_Write_Addr(DEC_o_Write_Addr), | |||
301 | ||||
302 | .o_Uses_RS(DEC_o_Uses_RS), | |||
303 | .o_RS_Addr(DEC_o_Read_Register_1), | |||
304 | .o_Uses_RT(DEC_o_Uses_RT), | |||
305 | .o_RT_Addr(DEC_o_Read_Register_2), | |||
306 | .o_Uses_Immediate(DEC_o_Uses_Immediate), | |||
307 | .o_Immediate(DEC_o_Immediate), | |||
308 | .o_Branch_Target(DEC_o_Branch_Target) | |||
309 | ); | |||
310 | ||||
311 | ||||
312 | regfile #( .DATA_WIDTH(DATA_WIDTH), | |||
313 | .REG_ADDR_WIDTH(REG_ADDR_WIDTH) | |||
314 | ) | |||
315 | REGFILE | |||
316 | ( // Inputs | |||
317 | .i_Clk(i_Clk), | |||
318 | ||||
319 | .i_RS_Addr(DEC_o_Read_Register_1), | |||
320 | .i_RT_Addr(DEC_o_Read_Register_2), | |||
321 | ||||
322 | .i_Write_Enable(DEC_i_RegWrite), // Account for squashing WB stage | |||
323 | .i_Write_Data(WB_i_Write_Data), | |||
324 | .i_Write_Addr(DEC_i_Write_Register), | |||
325 | ||||
326 | // Outputs | |||
327 | .o_RS_Data(DEC_o_Read_Data_1), | |||
328 | .o_RT_Data(DEC_o_Read_Data_2) | |||
329 | ); | |||
330 | ||||
331 | //=================================================================== | |||
332 | // Execute | |||
333 | pipe_dec_ex #( .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH), | |||
334 | .DATA_WIDTH(DATA_WIDTH), | |||
335 | .REG_ADDR_WIDTH(REG_ADDR_WIDTH), | |||
336 | .ALU_CTLCODE_WIDTH(ALU_CTLCODE_WIDTH), | |||
337 | .MEM_MASK_WIDTH(MEM_MASK_WIDTH) | |||
338 | ) | |||
339 | PIPE_DEC_EX | |||
340 | ( // Inputs | |||
341 | .i_Clk(i_Clk), | |||
342 | .i_Reset_n(i_Reset_n), | |||
343 | .i_Flush(Hazard_Flush_DEC), | |||
344 | .i_Stall(Hazard_Stall_EX), | |||
345 | ||||
346 | // Pipeline | |||
347 | .i_PC(DEC_o_PC), | |||
348 | .o_PC(ALU_i_PC), | |||
349 | .i_Uses_ALU(DEC_o_Uses_ALU), | |||
350 | .o_Uses_ALU(ALU_i_Valid), | |||
351 | .i_ALUCTL(DEC_o_ALUCTL), | |||
352 | .o_ALUCTL(ALU_i_ALUOp), | |||
353 | .i_Is_Branch(DEC_o_Is_Branch), | |||
354 | .o_Is_Branch(EX_i_Is_Branch), | |||
355 | .i_Mem_Valid(DEC_o_Mem_Valid), | |||
356 | .o_Mem_Valid(EX_i_Mem_Valid), | |||
357 | .i_Mem_Mask(DEC_o_Mem_Mask), | |||
358 | .o_Mem_Mask(EX_i_Mem_Mask), | |||
359 | .i_Mem_Read_Write_n(DEC_o_Mem_Read_Write_n), | |||
360 | .o_Mem_Read_Write_n(EX_i_Mem_Read_Write_n), | |||
361 | .i_Mem_Write_Data(FORWARD_o_Forwarded_Data_2), | |||
362 | .o_Mem_Write_Data(EX_i_Mem_Write_Data), | |||
363 | .i_Writes_Back(DEC_o_Writes_Back), | |||
364 | .o_Writes_Back(EX_i_Writes_Back), | |||
365 | .i_Write_Addr(DEC_o_Write_Addr), | |||
366 | .o_Write_Addr(EX_i_Write_Addr), | |||
367 | .i_Operand1(FORWARD_o_Forwarded_Data_1), | |||
368 | .o_Operand1(ALU_i_Operand1), | |||
369 | .i_Operand2(DEC_o_Uses_Immediate?DEC_o_Immediate:FORWARD_o_Forwarded_Data_2), // Convention - Operand2 mapped to immediates | |||
370 | .o_Operand2(ALU_i_Operand2), | |||
371 | .i_Branch_Target(DEC_o_Jump_Reg?FORWARD_o_Forwarded_Data_1[WORD_ADDRESS_WIDTH-1:0]:DEC_o_Branch_Target), | |||
372 | .o_Branch_Target(EX_i_Branch_Target) | |||
373 | ); | |||
374 | ||||
375 | alu #( .DATA_WIDTH(DATA_WIDTH), | |||
376 | .CTLCODE_WIDTH(ALU_CTLCODE_WIDTH) | |||
377 | ) | |||
378 | ALU | |||
379 | ( // Inputs | |||
380 | .i_Valid(ALU_i_Valid), | |||
381 | .i_ALUCTL(ALU_i_ALUOp), | |||
382 | .i_Operand1(ALU_i_Operand1), | |||
383 | .i_Operand2(ALU_i_Operand2), | |||
384 | ||||
385 | // Outputs | |||
386 | .o_Valid(ALU_o_Valid), | |||
387 | .o_Result(ALU_o_Result), | |||
388 | .o_Branch_Valid(ALU_o_Branch_Valid), | |||
389 | .o_Branch_Outcome(ALU_o_Branch_Outcome), | |||
390 | .o_Pass_Done_Value(ALU_o_Pass_Done_Value), | |||
391 | .o_Pass_Done_Change(ALU_o_Pass_Done_Change) | |||
392 | ); | |||
393 | ||||
394 | //=================================================================== | |||
395 | // Mem | |||
396 | pipe_ex_mem #( .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH), | |||
397 | .DATA_WIDTH(DATA_WIDTH), | |||
398 | .REG_ADDR_WIDTH(REG_ADDR_WIDTH), | |||
399 | .ALU_CTLCODE_WIDTH(ALU_CTLCODE_WIDTH) | |||
400 | ) | |||
401 | PIPE_EX_MEM | |||
402 | ( // Inputs | |||
403 | .i_Clk(i_Clk), | |||
404 | .i_Reset_n(i_Reset_n), | |||
405 | .i_Flush(Hazard_Flush_EX), | |||
406 | .i_Stall(Hazard_Stall_MEM), | |||
407 | ||||
408 | // Pipe in/out | |||
409 | .i_ALU_Result(ALU_o_Result), | |||
410 | .o_ALU_Result(DMEM_i_Result), | |||
411 | .i_Mem_Valid(EX_i_Mem_Valid), | |||
412 | .o_Mem_Valid(DMEM_i_Mem_Valid), | |||
413 | .i_Mem_Mask(EX_i_Mem_Mask), | |||
414 | .o_Mem_Mask(DMEM_i_Mem_Mask), | |||
415 | .i_Mem_Read_Write_n(EX_i_Mem_Read_Write_n), | |||
416 | .o_Mem_Read_Write_n(DMEM_i_Mem_Read_Write_n), | |||
417 | .i_Mem_Write_Data(EX_i_Mem_Write_Data), | |||
418 | .o_Mem_Write_Data(DMEM_i_Mem_Write_Data), | |||
419 | .i_Writes_Back(EX_i_Writes_Back), | |||
420 | .o_Writes_Back(DMEM_i_Writes_Back), | |||
421 | .i_Write_Addr(EX_i_Write_Addr), | |||
422 | .o_Write_Addr(DMEM_i_Write_Addr) | |||
423 | ); | |||
424 | ||||
425 | d_cache #( | |||
426 | .DATA_WIDTH(32), | |||
427 | .MEM_MASK_WIDTH(3) | |||
428 | ) | |||
429 | D_CACHE | |||
430 | ( // Inputs | |||
431 | .i_Clk(i_Clk), | |||
432 | .i_Reset_n(i_Reset_n), | |||
433 | .i_Valid(DMEM_i_Mem_Valid), | |||
434 | .i_Mem_Mask(DMEM_i_Mem_Mask), | |||
435 | .i_Address(DMEM_i_Result[BYTE_ADDRESS_WIDTH-1:2]), | |||
436 | .i_Read_Write_n(DMEM_i_Mem_Read_Write_n), //1=MemRead, 0=MemWrite | |||
437 | .i_Write_Data(DMEM_i_Mem_Write_Data), | |||
438 | ||||
439 | // Outputs | |||
440 | .o_Ready(DMEM_o_Mem_Ready), | |||
441 | .o_Valid(DMEM_o_Mem_Valid), | |||
442 | .o_Data(DMEM_o_Read_Data), | |||
443 | ||||
444 | // Mem Transaction | |||
445 | .o_MEM_Valid(Arbiter_i_DMEM_Valid), | |||
446 | .o_MEM_Read_Write_n(Arbiter_i_DMEM_Read_Write_n), | |||
447 | .o_MEM_Address(Arbiter_i_DMEM_Address), | |||
448 | .o_MEM_Data(Arbiter_i_DMEM_Data), | |||
449 | .i_MEM_Valid(Arbiter_o_DMEM_Valid), | |||
450 | .i_MEM_Data_Read(Arbiter_o_DMEM_Data_Read), | |||
451 | .i_MEM_Last(Arbiter_o_DMEM_Last), | |||
452 | .i_MEM_Data(Arbiter_o_DMEM_Data) | |||
453 | ); | |||
454 | ||||
455 | // Multiplexor - Select what we will write back | |||
456 | always @(*) | |||
457 | begin | |||
458 | if( MemToReg ) // If it was a memory operation | |||
459 | begin | |||
460 | DMEM_o_Write_Data <= DMEM_o_Read_Data; // We will write back value from memory | |||
461 | DMEM_o_Done <= DMEM_o_Mem_Valid; // Write back only if value is valid | |||
462 | end | |||
463 | else | |||
464 | begin | |||
465 | DMEM_o_Write_Data <= DMEM_i_Result; // Else we will write back value from ALU | |||
466 | DMEM_o_Done <= TRUE; | |||
467 | end | |||
468 | end | |||
469 | ||||
470 | //=================================================================== | |||
471 | // Write-Back | |||
472 | pipe_mem_wb #( .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH), | |||
473 | .DATA_WIDTH(DATA_WIDTH), | |||
474 | .REG_ADDR_WIDTH(REG_ADDR_WIDTH) | |||
475 | ) | |||
476 | PIPE_MEM_WB | |||
477 | ( // Inputs | |||
478 | .i_Clk(i_Clk), | |||
479 | .i_Reset_n(i_Reset_n), | |||
480 | .i_Flush(Hazard_Flush_MEM), | |||
481 | .i_Stall(Hazard_Stall_WB), | |||
482 | ||||
483 | // Pipe in/out | |||
484 | .i_WriteBack_Data(DMEM_o_Write_Data), | |||
485 | .o_WriteBack_Data(WB_i_Write_Data), | |||
486 | .i_Writes_Back(DMEM_i_Writes_Back), | |||
487 | .o_Writes_Back(WB_i_Writes_Back), | |||
488 | .i_Write_Addr(DMEM_i_Write_Addr), | |||
489 | .o_Write_Addr(DEC_i_Write_Register) | |||
490 | ); | |||
491 | ||||
492 | ||||
493 | // Write-Back is simply wires feeding back into regfile to perform writes | |||
494 | // (SEE REGFILE) | |||
495 | ||||
496 | ||||
497 | ||||
498 | //=================================================================== | |||
499 | // Arbitration Logic | |||
500 | ||||
501 | // Memory arbiter | |||
502 | core_memory_arbiter #( .DATA_WIDTH(DATA_WIDTH), | |||
503 | .ADDRESS_WIDTH(WORD_ADDRESS_WIDTH) | |||
504 | ) | |||
505 | ARBITER | |||
506 | ( | |||
507 | // General | |||
508 | .i_Clk(i_Clk), | |||
509 | .i_Reset_n(i_Reset_n), | |||
510 | ||||
511 | // Requests to/from IMEM - Assume we always read | |||
512 | .i_IMEM_Valid(Arbiter_i_IMEM_Valid), // If IMEM request is valid | |||
513 | .i_IMEM_Address(Arbiter_i_IMEM_Address), // IMEM request addr. | |||
514 | .o_IMEM_Valid(Arbiter_o_IMEM_Valid), | |||
515 | .o_IMEM_Last(Arbiter_o_IMEM_Last), | |||
516 | .o_IMEM_Data(Arbiter_o_IMEM_Data), | |||
517 | ||||
518 | // Requests to/from DMEM | |||
519 | .i_DMEM_Valid(Arbiter_i_DMEM_Valid), | |||
520 | .i_DMEM_Read_Write_n(Arbiter_i_DMEM_Read_Write_n), | |||
521 | .i_DMEM_Address(Arbiter_i_DMEM_Address), | |||
522 | .i_DMEM_Data(Arbiter_i_DMEM_Data), | |||
523 | .o_DMEM_Valid(Arbiter_o_DMEM_Valid), | |||
524 | .o_DMEM_Data_Read(Arbiter_o_DMEM_Data_Read), | |||
525 | .o_DMEM_Last(Arbiter_o_DMEM_Last), | |||
526 | .o_DMEM_Data(Arbiter_o_DMEM_Data), | |||
527 | ||||
528 | ||||
529 | // Interface to outside of the core | |||
530 | .o_MEM_Valid(o_MEM_Valid), | |||
531 | .o_MEM_Address(o_MEM_Address), | |||
532 | .o_MEM_Read_Write_n(o_MEM_Read_Write_n), | |||
533 | ||||
534 | // Write data interface | |||
535 | .o_MEM_Data(o_MEM_Data), | |||
536 | .i_MEM_Data_Read(i_MEM_Data_Read), | |||
537 | ||||
538 | // Read data interface | |||
539 | .i_MEM_Data(i_MEM_Data), | |||
540 | .i_MEM_Valid(i_MEM_Valid), | |||
541 | ||||
542 | .i_MEM_Last(i_MEM_Last) | |||
543 | ); | |||
544 | ||||
545 | // Forwarding logic | |||
546 | forwarding_unit #( .DATA_WIDTH(DATA_WIDTH), | |||
547 | .REG_ADDR_WIDTH(REG_ADDR_WIDTH) | |||
548 | ) | |||
549 | FORWARDING_UNIT | |||
550 | ( |
src/mips_cpu.v
View file @
bec01f1
/* mips_cpu.v | 1 | 1 | /* mips_cpu.v | |
* Author: Pravin P. Prabhu and Dean Tullsen | 2 | 2 | * Author: Pravin P. Prabhu, Dean Tullsen, and Zinsser Zhang | |
* Last Revision: 1/5/11 | 3 | 3 | * Last Revision: 04/28/2017 | |
* Abstract: | 4 | 4 | * Abstract: | |
* The top level module for the MIPS32 processor. This is a classic 5-stage | 5 | 5 | * The top level module for the MIPS32 processor. This top level module | |
* MIPS pipeline architecture which is intended to follow heavily from the model | 6 | 6 | * handles loading data from flash to SDRAM and keep track of core's performance | |
* presented in Hennessy and Patterson's Computer Organization and Design. | 7 | 7 | * The main classic 5-stage MIPS pipeline is defined in mips_core module. | |
*/ | 8 | 8 | */ | |
module mips_cpu(// General | 9 | 9 | module mips_cpu(// General | |
input CLOCK_50, //These inputs are all pre-defined input/output pin names | 10 | 10 | input CLOCK_50, //These inputs are all pre-defined input/output pin names | |
//input Global_Reset_n, // TEMP - Remove this after testing | 11 | 11 | //input Global_Reset_n, // TEMP - Remove this after testing | |
input [3:0] KEY, // which correspond to the DE2_pin_assignments,csv file. This | 12 | 12 | input [3:0] KEY, // which correspond to the DE2_pin_assignments,csv file. This | |
input [17:0] SW, // way, the mapping is automatically taken care of if we get the | 13 | 13 | input [17:0] SW, // way, the mapping is automatically taken care of if we get the | |
output [6:0] HEX7, HEX6, HEX5, HEX4, HEX3, HEX2, HEX1, HEX0, // name right. | 14 | 14 | output [6:0] HEX7, HEX6, HEX5, HEX4, HEX3, HEX2, HEX1, HEX0, // name right. | |
output [7:0] LEDG, | 15 | 15 | output [7:0] LEDG, | |
output [17:0] LEDR, | 16 | 16 | output [17:0] LEDR, | |
17 | 17 | |||
//SDRAM interface | 18 | 18 | //SDRAM interface | |
output [11:0] DRAM_ADDR, | 19 | 19 | output [11:0] DRAM_ADDR, | |
output DRAM_BA_0, | 20 | 20 | output DRAM_BA_0, | |
output DRAM_BA_1, | 21 | 21 | output DRAM_BA_1, | |
output DRAM_CAS_N, | 22 | 22 | output DRAM_CAS_N, | |
output DRAM_CKE, | 23 | 23 | output DRAM_CKE, | |
output DRAM_CLK, | 24 | 24 | output DRAM_CLK, | |
output DRAM_CS_N, | 25 | 25 | output DRAM_CS_N, | |
inout [15:0] DRAM_DQ, | 26 | 26 | inout [15:0] DRAM_DQ, | |
output DRAM_LDQM, | 27 | 27 | output DRAM_LDQM, | |
output DRAM_UDQM, | 28 | 28 | output DRAM_UDQM, | |
output DRAM_RAS_N, | 29 | 29 | output DRAM_RAS_N, | |
output DRAM_WE_N, | 30 | 30 | output DRAM_WE_N, | |
31 | 31 | |||
//Flash RAM interface | 32 | 32 | //Flash RAM interface | |
output [21:0] FL_ADDR, | 33 | 33 | output [21:0] FL_ADDR, | |
inout [7:0] FL_DQ, | 34 | 34 | inout [7:0] FL_DQ, | |
output FL_CE_N, | 35 | 35 | output FL_CE_N, | |
output FL_OE_N, | 36 | 36 | output FL_OE_N, | |
output FL_RST_N, | 37 | 37 | output FL_RST_N, | |
output FL_WE_N, | 38 | 38 | output FL_WE_N, | |
39 | 39 | |||
//SRAM interface | 40 | 40 | //SRAM interface | |
output [17:0] SRAM_ADDR, | 41 | 41 | output [17:0] SRAM_ADDR, | |
inout [15:0] SRAM_DQ, | 42 | 42 | inout [15:0] SRAM_DQ, | |
output SRAM_UB_N, | 43 | 43 | output SRAM_UB_N, | |
output SRAM_LB_N, | 44 | 44 | output SRAM_LB_N, | |
output SRAM_WE_N, | 45 | 45 | output SRAM_WE_N, | |
output SRAM_OE_N, | 46 | 46 | output SRAM_OE_N, | |
output SRAM_CE_N | 47 | 47 | output SRAM_CE_N | |
); | 48 | 48 | ); | |
49 | 49 | |||
//=================================================================== | 50 | 50 | //=================================================================== | |
// Internal Wiring | 51 | 51 | // Internal Wiring | |
//=================================================================== | 52 | 52 | //=================================================================== | |
53 | 53 | |||
//=================================================================== | 54 | 54 | //=================================================================== | |
// General Signals | 55 | 55 | // General Signals | |
localparam FALSE = 1'b0; | 56 | 56 | localparam FALSE = 1'b0; | |
localparam TRUE = 1'b1; | 57 | 57 | localparam TRUE = 1'b1; | |
localparam ADDRESS_WIDTH = 22; | 58 | 58 | localparam ADDRESS_WIDTH = 22; | |
59 | localparam CORE_ADDRESS_WIDTH = 21; | |||
localparam DATA_WIDTH = 32; | 59 | 60 | localparam DATA_WIDTH = 32; | |
//wire Global_Reset_n; // Global reset | 60 | 61 | //wire Global_Reset_n; // Global reset | |
wire Global_Reset_n = KEY[0]; | 61 | 62 | wire Global_Reset_n = KEY[0]; | |
62 | 63 | |||
// MTC0 codes - Did we pass/fail a test or reach the done state? | 63 | 64 | // MTC0 codes - Did we pass/fail a test or reach the done state? | |
localparam MTC0_NOOP = 0; // No significance | 64 | 65 | localparam MTC0_NOOP = 0; // No significance | |
localparam MTC0_PASS = 1; // Passed a test | 65 | 66 | localparam MTC0_PASS = 1; // Passed a test | |
localparam MTC0_FAIL = 2; // Failed a test | 66 | 67 | localparam MTC0_FAIL = 2; // Failed a test | |
localparam MTC0_DONE = 3; // Have completed execution | 67 | 68 | localparam MTC0_DONE = 3; // Have completed execution | |
68 | 69 | |||
assign LEDG[7:1] = 0; | 69 | 70 | assign LEDG[7:1] = 0; | |
assign LEDR[17:1] = 0; | 70 | 71 | assign LEDR[17:1] = 0; | |
71 | 72 | |||
assign SRAM_ADDR = 0; | 72 | 73 | assign SRAM_ADDR = 0; | |
assign SRAM_UB_N = 0; | 73 | 74 | assign SRAM_UB_N = 0; | |
assign SRAM_LB_N = 0; | 74 | 75 | assign SRAM_LB_N = 0; | |
assign SRAM_WE_N = 0; | 75 | 76 | assign SRAM_WE_N = 0; | |
assign SRAM_OE_N = 0; | 76 | 77 | assign SRAM_OE_N = 0; | |
assign SRAM_CE_N = 0; | 77 | 78 | assign SRAM_CE_N = 0; | |
78 | 79 | |||
//=================================================================== | 79 | 80 | //=================================================================== | |
// IFetch Signals | 80 | 81 | // CORE Signals | |
82 | wire CORE_i_External_Stall; | |||
83 | wire CORE_o_MEM_Valid; | |||
84 | wire CORE_o_MEM_Read_Write_n; | |||
85 | wire [CORE_ADDRESS_WIDTH-1:0] CORE_o_MEM_Address; | |||
86 | wire [DATA_WIDTH-1:0] CORE_o_MEM_Data; | |||
87 | wire CORE_i_MEM_Valid; | |||
88 | wire CORE_i_MEM_Data_Read; | |||
89 | wire CORE_i_MEM_Last; | |||
90 | wire [DATA_WIDTH-1:0] CORE_i_MEM_Data; | |||
81 | 91 | |||
wire IFetch_i_Flush; // Flush for IFetch | 82 | 92 | // Outputs for Done flag | |
wire Hazard_Stall_IF; // Stall for IFetch | 83 | 93 | wire [15:0] CORE_o_Pass_Done_Value; // reports the value of a PASS/FAIL/DONE instruction | |
wire IFetch_i_Load; // Load signal - if high, load pc with vector | 84 | 94 | wire [1:0] CORE_o_Pass_Done_Change; // indicates the above signal is meaningful | |
wire [ADDRESS_WIDTH-1:0] IFetch_i_PCSrc; // Vector to branch to | 85 | 95 | // 1 = pass, 2 = fail, 3 = done | |
86 | 96 | |||
wire [ADDRESS_WIDTH-1:0] IMEM_i_Address; // Current PC | 87 | 97 | // Outputs for performance display | |
98 | wire [7:0] CORE_o_Num_Inst_Executed; | |||
99 | wire [20:0] CORE_o_IMEM_i_Address; | |||
88 | 100 | |||
89 | ||||
wire IMEM_o_Ready; | 90 | |||
wire IMEM_o_Valid; | 91 | |||
wire [DATA_WIDTH-1:0] IMEM_o_Instruction; | 92 | |||
93 | ||||
//============== | 94 | |||
// Pipe signals: IF->ID | 95 | |||
wire Hazard_Flush_IF; // 1st pipe flush | 96 | |||
wire Hazard_Stall_DEC; // 1st pipe stall | 97 | |||
wire imembubble_DEC; // set if instruction coming out of icache | 98 | |||
// was not real instruction | 99 | |||
//=================================================================== | 100 | 101 | //=================================================================== | |
// Decoder Signals | 101 | |||
localparam ALU_CTLCODE_WIDTH = 8; | 102 | |||
localparam REG_ADDR_WIDTH = 5; | 103 | |||
localparam MEM_MASK_WIDTH = 3; | 104 | |||
wire [ADDRESS_WIDTH-1:0] DEC_i_PC; // PC of inst | 105 | |||
wire [DATA_WIDTH-1:0] DEC_i_Instruction; // Inst into decode | 106 | |||
wire DEC_Noop = (DEC_i_Instruction == 32'd0); | 107 | |||
108 | ||||
wire DEC_o_Uses_ALU; | 109 | |||
wire [ALU_CTLCODE_WIDTH-1:0] DEC_o_ALUCTL; // ALU control code | 110 | |||
wire DEC_o_Is_Branch; // If it's a branch | 111 | |||
wire [ADDRESS_WIDTH-1:0] DEC_o_Branch_Target; // Where we will branch to | 112 | |||
wire DEC_o_Jump_Reg; // If this is a special case where we jump TO a register value | 113 | |||
114 | ||||
wire DEC_o_Mem_Valid; | 115 | |||
wire DEC_o_Mem_Read_Write_n; | 116 | |||
wire [MEM_MASK_WIDTH-1:0] DEC_o_Mem_Mask; // Used for masking individual memory ops - such as byte and halfword transactions | 117 | |||
118 | ||||
wire DEC_o_Writes_Back; | 119 | |||
wire [REG_ADDR_WIDTH-1:0] DEC_o_Write_Addr; | 120 | |||
wire DEC_o_Uses_RS; | 121 | |||
wire [REG_ADDR_WIDTH-1:0] DEC_o_Read_Register_1; | 122 | |||
wire DEC_o_Uses_RT; | 123 | |||
wire [REG_ADDR_WIDTH-1:0] DEC_o_Read_Register_2; | 124 | |||
125 | ||||
wire [DATA_WIDTH-1:0] DEC_o_Read_Data_1; | 126 | |||
wire [DATA_WIDTH-1:0] DEC_o_Read_Data_2; | 127 | |||
128 | ||||
wire DEC_o_Uses_Immediate; | 129 | |||
wire [DATA_WIDTH-1:0] DEC_o_Immediate; | 130 | |||
131 | ||||
wire [DATA_WIDTH-1:0] FORWARD_o_Forwarded_Data_1,FORWARD_o_Forwarded_Data_2; // Looked up regs | 132 | |||
133 | ||||
//============== | 134 | |||
// Pipe signals: ID->EX | 135 | |||
wire Hazard_Flush_DEC; // 2nd pipe flush | 136 | |||
wire Hazard_Stall_EX; // 2nd pipe stall | 137 | |||
138 | ||||
wire [ADDRESS_WIDTH-1:0] DEC_o_PC; | 139 | |||
assign DEC_o_PC = DEC_i_PC; | 140 | |||
141 | ||||
//=================================================================== | 142 | |||
// Execute Signals | 143 | |||
144 | ||||
wire [ADDRESS_WIDTH-1:0] ALU_i_PC; | 145 | |||
146 | ||||
wire EX_i_Is_Branch; | 147 | |||
wire EX_i_Mem_Valid; | 148 | |||
wire [MEM_MASK_WIDTH-1:0] EX_i_Mem_Mask; | 149 | |||
wire EX_i_Mem_Read_Write_n; | 150 | |||
wire [DATA_WIDTH-1:0] EX_i_Mem_Write_Data; | 151 | |||
wire EX_i_Writes_Back; | 152 | |||
wire [REG_ADDR_WIDTH-1:0] EX_i_Write_Addr; | 153 | |||
154 | ||||
wire ALU_i_Valid; // Whether input to ALU is valid or not | 155 | |||
wire ALU_o_Valid; | 156 | |||
wire [ALU_CTLCODE_WIDTH-1:0] ALU_i_ALUOp; // Control bus to ALU | 157 | |||
wire [DATA_WIDTH-1:0] ALU_i_Operand1,ALU_i_Operand2; // Ops for ALU | 158 | |||
wire [ADDRESS_WIDTH-1:0] EX_i_Branch_Target; | 159 | |||
wire [DATA_WIDTH-1:0] ALU_o_Result; // Computation of ALU | 160 | |||
wire ALU_o_Branch_Valid; // Whether branch is valid or not | 161 | |||
wire ALU_o_Branch_Outcome; // Whether branch is taken or not | 162 | |||
wire [15:0] ALU_o_Pass_Done_Value; // reports the value of a PASS/FAIL/DONE instruction | 163 | |||
wire [1:0] ALU_o_Pass_Done_Change; // indicates the above signal is meaningful | 164 | |||
// 1 = pass, 2 = fail, 3 = done | 165 | |||
166 | ||||
// Cumulative signals | 167 | |||
wire EX_Take_Branch = ALU_o_Valid && ALU_o_Branch_Valid && ALU_o_Branch_Outcome; // Whether we should branch or not. | 168 | |||
169 | ||||
//============== | 170 | |||
// Pipe signals: EX->MEM | 171 | |||
wire Hazard_Flush_EX; // 3rd pipe flush | 172 | |||
wire Hazard_Stall_MEM; // 3rd pipe stall | 173 | |||
174 | ||||
175 | ||||
//=================================================================== | 176 | |||
// Memory Signals | 177 | |||
wire [DATA_WIDTH-1:0] DMEM_i_Result; // Result from the ALU | 178 | |||
wire [DATA_WIDTH-1:0] DMEM_i_Mem_Write_Data; // What we will write back to mem (if applicable) | 179 | |||
wire DMEM_i_Mem_Valid; // If the memory operation is valid | 180 | |||
wire [MEM_MASK_WIDTH-1:0] DMEM_i_Mem_Mask; // Mem mask for sub-word operations | 181 | |||
wire DMEM_i_Mem_Read_Write_n; // Type of memop | 182 | |||
wire DMEM_i_Writes_Back; // If the result should be written back to regfile | 183 | |||
wire [REG_ADDR_WIDTH-1:0] DMEM_i_Write_Addr; // Which reg in the regfile to write to | 184 | |||
wire [DATA_WIDTH-1:0] DMEM_o_Read_Data; // The data READ from DMEM | 185 | |||
wire DMEM_o_Mem_Ready; // If the DMEM is ready to service another request | 186 | |||
wire DMEM_o_Mem_Valid; // If the value read from DMEM is valid | 187 | |||
reg DMEM_o_Done; // If MEM's work is finalized | 188 | |||
reg [DATA_WIDTH-1:0] DMEM_o_Write_Data; // Data we should write back to regfile | 189 | |||
190 | ||||
wire MemToReg = DMEM_i_Mem_Valid; // Selects what we will write back -- mem or ALU result | 191 | |||
192 | ||||
//============== | 193 | |||
// Pipe signals: MEM->WB | 194 | |||
wire Hazard_Flush_MEM; // 4th pipe flush | 195 | |||
wire Hazard_Stall_WB; // 4th pipe stall | 196 | |||
197 | ||||
198 | ||||
//=================================================================== | 199 | |||
// Write-Back Signals | 200 | |||
wire WB_i_Writes_Back; // If we will write back | 201 | |||
wire [REG_ADDR_WIDTH-1:0] DEC_i_Write_Register; // Where we will write back to | 202 | |||
wire [DATA_WIDTH-1:0] WB_i_Write_Data; // What we will write back | 203 | |||
wire Hazard_Flush_WB; // Request to squash WB contents | 204 | |||
205 | ||||
wire DEC_i_RegWrite = WB_i_Writes_Back && !Hazard_Flush_WB; | 206 | |||
207 | ||||
//=================================================================== | 208 | |||
// Flash Signals | 209 | 102 | // Flash Signals | |
wire o_FlashLoader_Done; // Raised when the loader finishes | 210 | 103 | wire o_FlashLoader_Done; // Raised when the loader finishes | |
wire o_FlashLoader_SDRAM_Read_Write_n; // FlashLoader's actual request to dmem | 211 | 104 | wire o_FlashLoader_SDRAM_Read_Write_n; // FlashLoader's actual request to dmem | |
wire o_FlashLoader_SDRAM_Req_Valid; // FlashLoader's verification of request to dmem | 212 | 105 | wire o_FlashLoader_SDRAM_Req_Valid; // FlashLoader's verification of request to dmem | |
wire [ADDRESS_WIDTH-1:0] o_FlashLoader_SDRAM_Addr; // FlashLoader's request addrto dmem | 213 | 106 | wire [ADDRESS_WIDTH-1:0] o_FlashLoader_SDRAM_Addr; // FlashLoader's request addrto dmem | |
wire [DATA_WIDTH-1:0] o_FlashLoader_SDRAM_Data; // FlashLoader's output data | 214 | 107 | wire [DATA_WIDTH-1:0] o_FlashLoader_SDRAM_Data; // FlashLoader's output data | |
wire i_FlashLoader_SDRAM_Data_Read; // FlashLoader's input callback from dmem | 215 | 108 | wire i_FlashLoader_SDRAM_Data_Read; // FlashLoader's input callback from dmem | |
wire i_FlashLoader_SDRAM_Last; // "" | 216 | 109 | wire i_FlashLoader_SDRAM_Last; // "" | |
wire [21:0] o_FlashLoader_FL_Addr; // FlashLoader's addr request to flash | 217 | 110 | wire [21:0] o_FlashLoader_FL_Addr; // FlashLoader's addr request to flash | |
wire [7:0] i_FlashLoader_FL_Data; // FlashLoader's data coming back from flash | 218 | 111 | wire [7:0] i_FlashLoader_FL_Data; // FlashLoader's data coming back from flash | |
wire o_FlashLoader_FL_Chip_En_n; // FlashLoader's chip enable to flash | 219 | 112 | wire o_FlashLoader_FL_Chip_En_n; // FlashLoader's chip enable to flash | |
wire o_FlashLoader_FL_Output_En_n; // "" (output enable) | 220 | 113 | wire o_FlashLoader_FL_Output_En_n; // "" (output enable) | |
wire o_FlashLoader_FL_Reset_n; // "" (flash reset) | 221 | 114 | wire o_FlashLoader_FL_Reset_n; // "" (flash reset) | |
wire o_FlashLoader_FL_Write_En_n; // Write enable going out to flash | 222 | 115 | wire o_FlashLoader_FL_Write_En_n; // Write enable going out to flash | |
223 | 116 | |||
// Top level connections | 224 | 117 | // Top level connections | |
assign FL_ADDR = o_FlashLoader_FL_Addr; // Addr we're requesting to deal with | 225 | 118 | assign FL_ADDR = o_FlashLoader_FL_Addr; // Addr we're requesting to deal with | |
assign i_FlashLoader_FL_Data = FL_DQ; // Incoming data from flash (for reads) | 226 | 119 | assign i_FlashLoader_FL_Data = FL_DQ; // Incoming data from flash (for reads) | |
assign FL_CE_N = o_FlashLoader_FL_Chip_En_n; // Flash chip enable | 227 | 120 | assign FL_CE_N = o_FlashLoader_FL_Chip_En_n; // Flash chip enable | |
assign FL_OE_N = o_FlashLoader_FL_Output_En_n; // Flash output enable | 228 | 121 | assign FL_OE_N = o_FlashLoader_FL_Output_En_n; // Flash output enable | |
assign FL_WE_N = o_FlashLoader_FL_Write_En_n; // Flash write enable | 229 | 122 | assign FL_WE_N = o_FlashLoader_FL_Write_En_n; // Flash write enable | |
assign FL_RST_N = o_FlashLoader_FL_Reset_n; // Flash reset | 230 | 123 | assign FL_RST_N = o_FlashLoader_FL_Reset_n; // Flash reset | |
231 | 124 | |||
232 | 125 | |||
//=================================================================== | 233 | 126 | //=================================================================== | |
// Arbiter Signals | 234 | 127 | // Arbiter Signals | |
wire Arbiter_i_IMEM_Valid; | 235 | |||
wire [ADDRESS_WIDTH-1:0] Arbiter_i_IMEM_Address; | 236 | |||
wire Arbiter_o_IMEM_Valid; | 237 | |||
wire Arbiter_o_IMEM_Last; | 238 | |||
wire [DATA_WIDTH-1:0] Arbiter_o_IMEM_Data; | 239 | |||
240 | 128 | |||
wire Arbiter_i_DMEM_Valid; | 241 | |||
wire Arbiter_i_DMEM_Read_Write_n; | 242 | |||
wire [ADDRESS_WIDTH-1:0] Arbiter_i_DMEM_Address; | 243 | |||
wire [DATA_WIDTH-1:0] Arbiter_i_DMEM_Data; | 244 | |||
wire [DATA_WIDTH-1:0] Arbiter_o_DMEM_Data; | 245 | |||
wire Arbiter_o_DMEM_Data_Read; | 246 | |||
wire Arbiter_o_DMEM_Valid; | 247 | |||
wire Arbiter_o_DMEM_Last; | 248 | |||
249 | ||||
wire Arbiter_i_Flash_Valid; | 250 | 129 | wire Arbiter_i_Flash_Valid; | |
wire [DATA_WIDTH-1:0] Arbiter_i_Flash_Data; | 251 | 130 | wire [DATA_WIDTH-1:0] Arbiter_i_Flash_Data; | |
wire [ADDRESS_WIDTH-1:0] Arbiter_i_Flash_Address; | 252 | 131 | wire [ADDRESS_WIDTH-1:0] Arbiter_i_Flash_Address; | |
wire Arbiter_o_Flash_Data_Read; | 253 | 132 | wire Arbiter_o_Flash_Data_Read; | |
//wire [DATA_WIDTH-1:0] Arbiter_o_Flash_Data_Read; | 254 | 133 | //wire [DATA_WIDTH-1:0] Arbiter_o_Flash_Data_Read; | |
wire Arbiter_o_Flash_Last; | 255 | 134 | wire Arbiter_o_Flash_Last; | |
256 | 135 | |||
assign Arbiter_i_Flash_Valid = o_FlashLoader_SDRAM_Req_Valid; | 257 | 136 | assign Arbiter_i_Flash_Valid = o_FlashLoader_SDRAM_Req_Valid; | |
assign Arbiter_i_Flash_Data = o_FlashLoader_SDRAM_Data; | 258 | 137 | assign Arbiter_i_Flash_Data = o_FlashLoader_SDRAM_Data; | |
assign Arbiter_i_Flash_Address = o_FlashLoader_SDRAM_Addr; | 259 | 138 | assign Arbiter_i_Flash_Address = o_FlashLoader_SDRAM_Addr; | |
assign i_FlashLoader_SDRAM_Data_Read = Arbiter_o_Flash_Data_Read; | 260 | 139 | assign i_FlashLoader_SDRAM_Data_Read = Arbiter_o_Flash_Data_Read; | |
assign i_FlashLoader_SDRAM_Last = Arbiter_o_Flash_Last; | 261 | 140 | assign i_FlashLoader_SDRAM_Last = Arbiter_o_Flash_Last; | |
262 | 141 | |||
263 | 142 | |||
//==================================================================== | 264 | 143 | //==================================================================== | |
// Controller Signals | 265 | 144 | // Controller Signals | |
wire [ADDRESS_WIDTH-1:0] SDRAM_i_Address; // Transact address | 266 | 145 | wire [ADDRESS_WIDTH-1:0] SDRAM_i_Address; // Transact address | |
wire SDRAM_i_Valid; // If request is valid | 267 | 146 | wire SDRAM_i_Valid; // If request is valid | |
wire SDRAM_i_Read_Write_n; // Request type | 268 | 147 | wire SDRAM_i_Read_Write_n; // Request type | |
269 | 148 | |||
wire [DATA_WIDTH-1:0] SDRAM_i_Data; // What to write | 270 | 149 | wire [DATA_WIDTH-1:0] SDRAM_i_Data; // What to write | |
wire SDRAM_o_Data_Read; // If data was read or not | 271 | 150 | wire SDRAM_o_Data_Read; // If data was read or not | |
272 | 151 | |||
wire [DATA_WIDTH-1:0] SDRAM_o_Data; // Read in data from SDRAM | 273 | 152 | wire [DATA_WIDTH-1:0] SDRAM_o_Data; // Read in data from SDRAM | |
wire SDRAM_o_Data_Valid; // If read in data is valid | 274 | 153 | wire SDRAM_o_Data_Valid; // If read in data is valid | |
275 | 154 | |||
wire SDRAM_o_Last; // If we're on the last part of the burst | 276 | 155 | wire SDRAM_o_Last; // If we're on the last part of the burst | |
277 | 156 | |||
278 | 157 | |||
wire i_Clk; | 279 | 158 | wire i_Clk; | |
//=================================================================== | 280 | 159 | //=================================================================== | |
// Top-level Connections | 281 | 160 | // Top-level Connections | |
// Clock handling for mem & processor | 282 | 161 | // Clock handling for mem & processor | |
wire Done = (ALU_o_Pass_Done_Change == MTC0_DONE); | 283 | 162 | wire Done = (CORE_o_Pass_Done_Change == MTC0_DONE); | |
wire Local_Clock; | 284 | 163 | wire Local_Clock; | |
wire Internal_Reset_n; | 285 | 164 | wire Internal_Reset_n; | |
165 | assign CORE_i_External_Stall = !o_FlashLoader_Done || Done; | |||
286 | 166 | |||
//integer file; | 287 | |||
//initial | 288 | |||
// begin | 289 | |||
// file = $fopen("dumppcs"); | 290 | |||
// end | 291 | |||
292 | ||||
293 | ||||
`ifdef MODEL_TECH | 294 | 167 | `ifdef MODEL_TECH | |
assign Internal_Reset_n = Global_Reset_n; | 295 | 168 | assign Internal_Reset_n = Global_Reset_n; | |
assign Local_Clock = CLOCK_50; | 296 | 169 | assign Local_Clock = CLOCK_50; | |
297 | 170 | |||
`else | 298 | 171 | `else | |
wire PLL_Locked; | 299 | 172 | wire PLL_Locked; | |
pll my_pll( | 300 | 173 | pll my_pll( | |
.areset(!Global_Reset_n), | 301 | 174 | .areset(!Global_Reset_n), | |
.inclk0(CLOCK_50), | 302 | 175 | .inclk0(CLOCK_50), | |
.c0(Local_Clock), | 303 | 176 | .c0(Local_Clock), | |
.locked(PLL_Locked) | 304 | 177 | .locked(PLL_Locked) | |
); | 305 | 178 | ); | |
assign Internal_Reset_n = PLL_Locked && Global_Reset_n; | 306 | 179 | assign Internal_Reset_n = PLL_Locked && Global_Reset_n; | |
307 | 180 | |||
`endif | 308 | 181 | `endif | |
309 | 182 | |||
assign i_Clk = Local_Clock; | 310 | 183 | assign i_Clk = Local_Clock; | |
311 | 184 | |||
// Performance metrics | 312 | 185 | // Performance metrics | |
reg [31:0] CycleCount; // # of cycles that have passed since reset | 313 | 186 | reg [31:0] CycleCount; // # of cycles that have passed since reset | |
reg [31:0] InstructionsExecuted; // # of insts that have went through WB stage since reset | 314 | 187 | reg [31:0] InstructionsExecuted; // # of insts that have went through WB stage since reset | |
reg displaystop; | 315 | 188 | reg displaystop; | |
316 | 189 | |||
317 | 190 | |||
always @(posedge i_Clk or negedge Internal_Reset_n) | 318 | 191 | always @(posedge i_Clk or negedge Internal_Reset_n) | |
319 | 192 | |||
begin | 320 | 193 | begin | |
if( !Internal_Reset_n ) | 321 | 194 | if( !Internal_Reset_n ) | |
begin | 322 | 195 | begin | |
// Asynch. reset on counters | 323 | 196 | // Asynch. reset on counters | |
CycleCount <= 32'b0; | 324 | 197 | CycleCount <= 32'b0; | |
InstructionsExecuted <= 32'b0; | 325 | 198 | InstructionsExecuted <= 32'b0; | |
displaystop <= 0; | 326 | 199 | displaystop <= 0; | |
end | 327 | 200 | end | |
else | 328 | 201 | else | |
begin | 329 | 202 | begin | |
// If we're currently executing instructions... | 330 | 203 | // If we're currently executing instructions... | |
if( o_FlashLoader_Done && !Done ) | 331 | 204 | if( o_FlashLoader_Done && !Done ) | |
begin | 332 | 205 | begin | |
// If we have a valid instruction that is finishing up execution in Decode, then count it | 333 | 206 | if (!displaystop && InstructionsExecuted > 1000000000) | |
if( !Hazard_Stall_DEC && !Hazard_Flush_DEC && !DEC_Noop ) | 334 | |||
begin | 335 | 207 | begin | |
if (!displaystop) | 336 | 208 | displaystop <= 1; | |
begin | 337 | |||
//$fwrite(file, "%h\n", (DEC_o_PC<<2) + 'h20240); | 338 | |||
if (InstructionsExecuted > 1000000000) | 339 | |||
begin | 340 | |||
displaystop <= 1; | 341 | |||
// $fflush(file); | 342 | |||
// $fclose(file); | 343 | |||
end | 344 | |||
end | 345 | |||
InstructionsExecuted <= InstructionsExecuted + 32'b1; | 346 | |||
end | 347 | 209 | end | |
210 | InstructionsExecuted <= InstructionsExecuted + CORE_o_Num_Inst_Executed; | |||
211 | ||||
CycleCount <= CycleCount + 32'b1; // Always count another cycle | 348 | 212 | CycleCount <= CycleCount + 32'b1; // Always count another cycle | |
end | 349 | 213 | end | |
end | 350 | 214 | end | |
end | 351 | 215 | end | |
352 | 216 | |||
// Visual output | 353 | 217 | // Visual output | |
assign LEDG[0] = (Done); | 354 | 218 | assign LEDG[0] = (Done); | |
assign LEDR[0] = (!Done); | 355 | 219 | assign LEDR[0] = (!Done); | |
356 | 220 | |||
reg[3:0] HEX_Buf [7:0]; // Buffers for visualization of data | 357 | 221 | reg[3:0] HEX_Buf [7:0]; // Buffers for visualization of data | |
358 | 222 | |||
always @(posedge i_Clk) | 359 | 223 | always @(posedge i_Clk) | |
begin | 360 | 224 | begin | |
HEX_Buf[0] <= 4'd0; | 361 | 225 | HEX_Buf[0] <= 4'd0; | |
HEX_Buf[1] <= 4'd0; | 362 | 226 | HEX_Buf[1] <= 4'd0; | |
HEX_Buf[2] <= 4'd0; | 363 | 227 | HEX_Buf[2] <= 4'd0; | |
HEX_Buf[3] <= 4'd0; | 364 | 228 | HEX_Buf[3] <= 4'd0; | |
HEX_Buf[4] <= 4'd0; | 365 | 229 | HEX_Buf[4] <= 4'd0; | |
HEX_Buf[5] <= 4'd0; | 366 | 230 | HEX_Buf[5] <= 4'd0; | |
HEX_Buf[6] <= 4'd0; | 367 | 231 | HEX_Buf[6] <= 4'd0; | |
HEX_Buf[7] <= 4'd0; | 368 | 232 | HEX_Buf[7] <= 4'd0; | |
369 | 233 | |||
case(SW[1:0]) | 370 | 234 | case(SW[1:0]) | |
2'd0: // Default: Display Pass/Done/Fail, PC, and PDF Value information | 371 | 235 | 2'd0: // Default: Display Pass/Done/Fail, PC, and PDF Value information | |
begin | 372 | 236 | begin | |
HEX_Buf[0] <= ALU_o_Pass_Done_Value[3:0]; | 373 | 237 | HEX_Buf[0] <= CORE_o_Pass_Done_Value[3:0]; | |
HEX_Buf[1] <= ALU_o_Pass_Done_Value[7:4]; | 374 | 238 | HEX_Buf[1] <= CORE_o_Pass_Done_Value[7:4]; | |
HEX_Buf[6] <= IMEM_i_Address[3:0]; | 375 | 239 | HEX_Buf[6] <= CORE_o_IMEM_i_Address[3:0]; | |
HEX_Buf[7] <= IMEM_i_Address[7:4]; | 376 | 240 | HEX_Buf[7] <= CORE_o_IMEM_i_Address[7:4]; | |
end | 377 | 241 | end | |
378 | 242 | |||
2'd1: // Cycle Count | 379 | 243 | 2'd1: // Cycle Count | |
begin | 380 | 244 | begin | |
HEX_Buf[0] <= CycleCount[3:0]; | 381 | 245 | HEX_Buf[0] <= CycleCount[3:0]; | |
HEX_Buf[1] <= CycleCount[7:4]; | 382 | 246 | HEX_Buf[1] <= CycleCount[7:4]; | |
HEX_Buf[2] <= CycleCount[11:8]; | 383 | 247 | HEX_Buf[2] <= CycleCount[11:8]; | |
HEX_Buf[3] <= CycleCount[15:12]; | 384 | 248 | HEX_Buf[3] <= CycleCount[15:12]; | |
HEX_Buf[4] <= CycleCount[19:16]; | 385 | 249 | HEX_Buf[4] <= CycleCount[19:16]; | |
HEX_Buf[5] <= CycleCount[23:20]; | 386 | 250 | HEX_Buf[5] <= CycleCount[23:20]; | |
HEX_Buf[6] <= CycleCount[27:24]; | 387 | 251 | HEX_Buf[6] <= CycleCount[27:24]; | |
HEX_Buf[7] <= CycleCount[31:28]; | 388 | 252 | HEX_Buf[7] <= CycleCount[31:28]; | |
end | 389 | 253 | end | |
390 | 254 | |||
2'd2: // Instructions Executed | 391 | 255 | 2'd2: // Instructions Executed | |
begin | 392 | 256 | begin | |
HEX_Buf[0] <= InstructionsExecuted[3:0]; | 393 | 257 | HEX_Buf[0] <= InstructionsExecuted[3:0]; | |
HEX_Buf[1] <= InstructionsExecuted[7:4]; | 394 | 258 | HEX_Buf[1] <= InstructionsExecuted[7:4]; | |
HEX_Buf[2] <= InstructionsExecuted[11:8]; | 395 | 259 | HEX_Buf[2] <= InstructionsExecuted[11:8]; | |
HEX_Buf[3] <= InstructionsExecuted[15:12]; | 396 | 260 | HEX_Buf[3] <= InstructionsExecuted[15:12]; | |
HEX_Buf[4] <= InstructionsExecuted[19:16]; | 397 | 261 | HEX_Buf[4] <= InstructionsExecuted[19:16]; | |
HEX_Buf[5] <= InstructionsExecuted[23:20]; | 398 | 262 | HEX_Buf[5] <= InstructionsExecuted[23:20]; | |
HEX_Buf[6] <= InstructionsExecuted[27:24]; | 399 | 263 | HEX_Buf[6] <= InstructionsExecuted[27:24]; | |
HEX_Buf[7] <= InstructionsExecuted[31:28]; | 400 | 264 | HEX_Buf[7] <= InstructionsExecuted[31:28]; | |
end | 401 | 265 | end | |
402 | 266 | |||
2'd3: // (free for any other metric) | 403 | 267 | 2'd3: // (free for any other metric) | |
begin | 404 | 268 | begin | |
end | 405 | 269 | end | |
406 | 270 | |||
endcase | 407 | 271 | endcase | |
end | 408 | 272 | end | |
409 | 273 | |||
wire [6:0] HEX2_SSD, HEX2_PFD; | 410 | 274 | wire [6:0] HEX2_SSD, HEX2_PFD; | |
SevenSegmentDisplayDecoder SSD0 (i_Clk, HEX0, HEX_Buf[0]); | 411 | 275 | SevenSegmentDisplayDecoder SSD0 (i_Clk, HEX0, HEX_Buf[0]); | |
SevenSegmentDisplayDecoder SSD1 (i_Clk, HEX1, HEX_Buf[1]); | 412 | 276 | SevenSegmentDisplayDecoder SSD1 (i_Clk, HEX1, HEX_Buf[1]); | |
SevenSegmentDisplayDecoder SSD2 (i_Clk, HEX2_SSD, HEX_Buf[2]); | 413 | 277 | SevenSegmentDisplayDecoder SSD2 (i_Clk, HEX2_SSD, HEX_Buf[2]); | |
SevenSegmentDisplayDecoder SSD3 (i_Clk, HEX3, HEX_Buf[3]); | 414 | 278 | SevenSegmentDisplayDecoder SSD3 (i_Clk, HEX3, HEX_Buf[3]); | |
SevenSegmentDisplayDecoder SSD4 (i_Clk, HEX4, HEX_Buf[4]); | 415 | 279 | SevenSegmentDisplayDecoder SSD4 (i_Clk, HEX4, HEX_Buf[4]); | |
SevenSegmentDisplayDecoder SSD5 (i_Clk, HEX5, HEX_Buf[5]); | 416 | 280 | SevenSegmentDisplayDecoder SSD5 (i_Clk, HEX5, HEX_Buf[5]); | |
SevenSegmentDisplayDecoder SSD6 (i_Clk, HEX6, HEX_Buf[6]); | 417 | 281 | SevenSegmentDisplayDecoder SSD6 (i_Clk, HEX6, HEX_Buf[6]); | |
SevenSegmentDisplayDecoder SSD7 (i_Clk, HEX7, HEX_Buf[7]); | 418 | 282 | SevenSegmentDisplayDecoder SSD7 (i_Clk, HEX7, HEX_Buf[7]); | |
SevenSegmentPFD PFD2 (i_Clk, HEX2_PFD, ALU_o_Pass_Done_Change); // display pass/done/fail status | 419 | 283 | SevenSegmentPFD PFD2 (i_Clk, HEX2_PFD, CORE_o_Pass_Done_Change); // display pass/done/fail status | |
420 | 284 | |||
// Special case: If SW is 0, then HEX2 output comes from PFD. Else, comes from SSD. | 421 | 285 | // Special case: If SW is 0, then HEX2 output comes from PFD. Else, comes from SSD. | |
assign HEX2 = (SW[1:0]==2'd0 ? HEX2_PFD : HEX2_SSD); | 422 | 286 | assign HEX2 = (SW[1:0]==2'd0 ? HEX2_PFD : HEX2_SSD); | |
423 | 287 | |||
/* | 424 | 288 | /* | |
SevenSegmentPFD SSD3 (i_Clk, HEX2, ALU_o_Pass_Done_Change); // display pass/done/fail status | 425 | 289 | SevenSegmentPFD SSD3 (i_Clk, HEX2, CORE_o_Pass_Done_Change); // display pass/done/fail status | |
426 | 290 | |||
SevenSegmentDisplayDecoder SSD0 (i_Clk, HEX0, ALU_o_Pass_Done_Value[3:0]); | 427 | 291 | SevenSegmentDisplayDecoder SSD0 (i_Clk, HEX0, CORE_o_Pass_Done_Value[3:0]); | |
SevenSegmentDisplayDecoder SSD1 (i_Clk, HEX1, ALU_o_Pass_Done_Value[7:4]); | 428 | 292 | SevenSegmentDisplayDecoder SSD1 (i_Clk, HEX1, CORE_o_Pass_Done_Value[7:4]); | |
429 | 293 | |||
SevenSegmentDisplayDecoder SSD7 (i_Clk, HEX7, IMEM_i_Address[7:4]); | 430 | 294 | SevenSegmentDisplayDecoder SSD7 (i_Clk, HEX7, IMEM_i_Address[7:4]); | |
SevenSegmentDisplayDecoder SSD6 (i_Clk, HEX6, IMEM_i_Address[3:0]); | 431 | 295 | SevenSegmentDisplayDecoder SSD6 (i_Clk, HEX6, IMEM_i_Address[3:0]); | |
432 | 296 | |||
*/ | 433 | 297 | */ | |
434 | 298 | |||
//=================================================================== | 435 | 299 | //=================================================================== | |
// Structural Description - Overhead | 436 | 300 | // Structural Description - CORE | |
//=================================================================== | 437 | 301 | //=================================================================== | |
302 | mips_core #( | |||
303 | .DATA_WIDTH(DATA_WIDTH), | |||
304 | .WORD_ADDRESS_WIDTH(CORE_ADDRESS_WIDTH) | |||
305 | ) CORE ( | |||
306 | .i_Clk(i_Clk), | |||
307 | .i_Reset_n(Internal_Reset_n), | |||
308 | .i_External_Stall(CORE_i_External_Stall), | |||
438 | 309 | |||
310 | .o_MEM_Valid(CORE_o_MEM_Valid), | |||
311 | .o_MEM_Read_Write_n(CORE_o_MEM_Read_Write_n), | |||
312 | .o_MEM_Address(CORE_o_MEM_Address), | |||
313 | .o_MEM_Data(CORE_o_MEM_Data), | |||
314 | .i_MEM_Valid(CORE_i_MEM_Valid), | |||
315 | .i_MEM_Data_Read(CORE_i_MEM_Data_Read), | |||
316 | .i_MEM_Last(CORE_i_MEM_Last), | |||
317 | .i_MEM_Data(CORE_i_MEM_Data), | |||
439 | 318 | |||
//=================================================================== | 440 | 319 | .o_Pass_Done_Value(CORE_o_Pass_Done_Value), | |
// Structural Description - Pipeline stages | 441 | 320 | .o_Pass_Done_Change(CORE_o_Pass_Done_Change), | |
//=================================================================== | 442 | |||
443 | 321 | |||
//=================================================================== | 444 | 322 | .o_Num_Inst_Executed(CORE_o_Num_Inst_Executed), | |
// Instruction Fetch | 445 | 323 | .o_IMEM_i_Address(CORE_o_IMEM_i_Address) | |
fetch_unit #( .ADDRESS_WIDTH(ADDRESS_WIDTH), | 446 | |||
.DATA_WIDTH(DATA_WIDTH) | 447 | |||
) | 448 | |||
IFETCH | 449 | |||
( // Inputs | 450 | |||
.i_Clk(i_Clk), | 451 | |||
.i_Reset_n(Internal_Reset_n), | 452 | |||
.i_Stall(Hazard_Stall_IF), | 453 | |||
454 | ||||
.i_Load(IFetch_i_Load), | 455 | |||
.i_Load_Address(IFetch_i_PCSrc), | 456 | |||
457 | ||||
// Outputs | 458 | |||
.o_PC(IMEM_i_Address) | 459 | |||
); | 460 | |||
461 | ||||
i_cache #( .DATA_WIDTH(DATA_WIDTH) | 462 | |||
) | 463 | |||
I_CACHE | 464 | |||
( | 465 | |||
// General | 466 | |||
.i_Clk(i_Clk), | 467 | |||
.i_Reset_n(Internal_Reset_n), | 468 | |||
469 | ||||
// Requests | 470 | |||
.i_Valid(o_FlashLoader_Done), | 471 | |||
.i_Address(IMEM_i_Address), | 472 | |||
473 | ||||
// Mem Transaction | 474 | |||
.o_MEM_Valid(Arbiter_i_IMEM_Valid), | 475 | |||
.o_MEM_Address(Arbiter_i_IMEM_Address), | 476 | |||
.i_MEM_Valid(Arbiter_o_IMEM_Valid), // If data from main mem is valid | 477 | |||
.i_MEM_Last(Arbiter_o_IMEM_Last), // If main mem is sending the last piece of data | 478 | |||
.i_MEM_Data(Arbiter_o_IMEM_Data), // Data from main mem | 479 | |||
480 | ||||
// Outputs | 481 | |||
.o_Ready(IMEM_o_Ready), | 482 | |||
.o_Valid(IMEM_o_Valid), // If the output is correct. | 483 | |||
.o_Data(IMEM_o_Instruction) // The data requested. | 484 | |||
); | 485 | |||
486 | ||||
//=================================================================== | 487 | |||
// Decode | 488 | |||
pipe_if_dec #( .ADDRESS_WIDTH(ADDRESS_WIDTH), | 489 | |||
.DATA_WIDTH(DATA_WIDTH) | 490 | |||
) | 491 | |||
PIPE_IF_DEC | 492 | |||
( // Inputs | 493 | |||
.i_Clk(i_Clk), | 494 | |||
.i_Reset_n(Internal_Reset_n), | 495 | |||
.i_Flush(Hazard_Flush_IF), | 496 | |||
.i_Stall(Hazard_Stall_DEC), | 497 | |||
.i_imembubble(IMEM_o_Valid), | 498 | |||
499 | ||||
// Pipe signals | 500 | |||
.i_PC(IMEM_i_Address), | 501 | |||
.o_PC(DEC_i_PC), | 502 | |||
.i_Instruction(IMEM_o_Instruction), | 503 | |||
.o_Instruction(DEC_i_Instruction), | 504 | |||
.o_imembubble(imembubble_DEC) | 505 | |||
); | 506 | |||
507 | ||||
decoder #( .ADDRESS_WIDTH(ADDRESS_WIDTH), | 508 | |||
.DATA_WIDTH(DATA_WIDTH), | 509 | |||
.REG_ADDRESS_WIDTH(REG_ADDR_WIDTH), | 510 | |||
.ALUCTL_WIDTH(ALU_CTLCODE_WIDTH), | 511 | |||
.MEM_MASK_WIDTH(MEM_MASK_WIDTH) | 512 | |||
) | 513 | |||
DECODE | 514 | |||
( // Inputs | 515 | |||
.i_PC(DEC_i_PC), | 516 | |||
.i_Instruction(DEC_i_Instruction), | 517 | |||
.i_Stall(Hazard_Stall_DEC), | 518 | |||
519 | ||||
// Outputs | 520 | |||
.o_Uses_ALU(DEC_o_Uses_ALU), | 521 | |||
.o_ALUCTL(DEC_o_ALUCTL), | 522 | |||
.o_Is_Branch(DEC_o_Is_Branch), | 523 | |||
.o_Jump_Reg(DEC_o_Jump_Reg), | 524 | |||
525 | ||||
.o_Mem_Valid(DEC_o_Mem_Valid), | 526 | |||
.o_Mem_Read_Write_n(DEC_o_Mem_Read_Write_n), | 527 | |||
.o_Mem_Mask(DEC_o_Mem_Mask), | 528 | |||
529 | ||||
.o_Writes_Back(DEC_o_Writes_Back), | 530 | |||
.o_Write_Addr(DEC_o_Write_Addr), | 531 | |||
532 | ||||
.o_Uses_RS(DEC_o_Uses_RS), | 533 | |||
.o_RS_Addr(DEC_o_Read_Register_1), | 534 | |||
.o_Uses_RT(DEC_o_Uses_RT), | 535 | |||
.o_RT_Addr(DEC_o_Read_Register_2), | 536 | |||
.o_Uses_Immediate(DEC_o_Uses_Immediate), | 537 | |||
.o_Immediate(DEC_o_Immediate), | 538 | |||
.o_Branch_Target(DEC_o_Branch_Target) | 539 | |||
); | 540 | |||
541 | ||||
542 | ||||
regfile #( .DATA_WIDTH(DATA_WIDTH), | 543 | |||
.REG_ADDR_WIDTH(REG_ADDR_WIDTH) | 544 | |||
) | 545 | |||
REGFILE | 546 | |||
( // Inputs | 547 | |||
.i_Clk(i_Clk), | 548 | |||
549 | ||||
.i_RS_Addr(DEC_o_Read_Register_1), | 550 | |||
.i_RT_Addr(DEC_o_Read_Register_2), | 551 | |||
552 | ||||
.i_Write_Enable(DEC_i_RegWrite), // Account for squashing WB stage | 553 | |||
.i_Write_Data(WB_i_Write_Data), | 554 | |||
.i_Write_Addr(DEC_i_Write_Register), | 555 | |||
556 | ||||
// Outputs | 557 | |||
.o_RS_Data(DEC_o_Read_Data_1), | 558 | |||
.o_RT_Data(DEC_o_Read_Data_2) | 559 | |||
); | 560 | |||
561 | ||||
//=================================================================== | 562 | |||
// Execute | 563 | |||
pipe_dec_ex #( .ADDRESS_WIDTH(ADDRESS_WIDTH), | 564 | |||
.DATA_WIDTH(DATA_WIDTH), | 565 | |||
.REG_ADDR_WIDTH(REG_ADDR_WIDTH), | 566 | |||
.ALU_CTLCODE_WIDTH(ALU_CTLCODE_WIDTH), | 567 | |||
.MEM_MASK_WIDTH(MEM_MASK_WIDTH) | 568 | |||
) | 569 | |||
PIPE_DEC_EX | 570 | |||
( // Inputs | 571 | |||
.i_Clk(i_Clk), | 572 | |||
.i_Reset_n(Internal_Reset_n), | 573 | |||
.i_Flush(Hazard_Flush_DEC), | 574 | |||
.i_Stall(Hazard_Stall_EX), | 575 | |||
576 | ||||
// Pipeline | 577 | |||
.i_PC(DEC_o_PC), | 578 | |||
.o_PC(ALU_i_PC), | 579 | |||
.i_Uses_ALU(DEC_o_Uses_ALU), | 580 | |||
.o_Uses_ALU(ALU_i_Valid), | 581 | |||
.i_ALUCTL(DEC_o_ALUCTL), | 582 | |||
.o_ALUCTL(ALU_i_ALUOp), | 583 | |||
.i_Is_Branch(DEC_o_Is_Branch), | 584 | |||
.o_Is_Branch(EX_i_Is_Branch), | 585 | |||
.i_Mem_Valid(DEC_o_Mem_Valid), | 586 | |||
.o_Mem_Valid(EX_i_Mem_Valid), | 587 | |||
.i_Mem_Mask(DEC_o_Mem_Mask), | 588 | |||
.o_Mem_Mask(EX_i_Mem_Mask), | 589 | |||
.i_Mem_Read_Write_n(DEC_o_Mem_Read_Write_n), | 590 | |||
.o_Mem_Read_Write_n(EX_i_Mem_Read_Write_n), | 591 | |||
.i_Mem_Write_Data(FORWARD_o_Forwarded_Data_2), | 592 | |||
.o_Mem_Write_Data(EX_i_Mem_Write_Data), | 593 | |||
.i_Writes_Back(DEC_o_Writes_Back), | 594 | |||
.o_Writes_Back(EX_i_Writes_Back), | 595 | |||
.i_Write_Addr(DEC_o_Write_Addr), | 596 | |||
.o_Write_Addr(EX_i_Write_Addr), | 597 | |||
.i_Operand1(FORWARD_o_Forwarded_Data_1), | 598 | |||
.o_Operand1(ALU_i_Operand1), | 599 | |||
.i_Operand2(DEC_o_Uses_Immediate?DEC_o_Immediate:FORWARD_o_Forwarded_Data_2), // Convention - Operand2 mapped to immediates | 600 | |||
.o_Operand2(ALU_i_Operand2), | 601 | |||
.i_Branch_Target(DEC_o_Jump_Reg?FORWARD_o_Forwarded_Data_1[ADDRESS_WIDTH-1:0]:DEC_o_Branch_Target), | 602 | |||
.o_Branch_Target(EX_i_Branch_Target) | 603 | |||
); | 604 | |||
605 | ||||
alu #( .DATA_WIDTH(DATA_WIDTH), | 606 | |||
.CTLCODE_WIDTH(ALU_CTLCODE_WIDTH) | 607 | |||
) | 608 | |||
ALU | 609 | |||
( // Inputs | 610 | |||
.i_Valid(ALU_i_Valid), | 611 | |||
.i_ALUCTL(ALU_i_ALUOp), | 612 | |||
.i_Operand1(ALU_i_Operand1), | 613 | |||
.i_Operand2(ALU_i_Operand2), | 614 | |||
615 | ||||
// Outputs | 616 | |||
.o_Valid(ALU_o_Valid), | 617 | |||
.o_Result(ALU_o_Result), | 618 | |||
.o_Branch_Valid(ALU_o_Branch_Valid), | 619 | |||
.o_Branch_Outcome(ALU_o_Branch_Outcome), | 620 | |||
.o_Pass_Done_Value(ALU_o_Pass_Done_Value), | 621 | |||
.o_Pass_Done_Change(ALU_o_Pass_Done_Change) | 622 | |||
); | 623 | 324 | ); | |
624 | 325 | |||
//=================================================================== | 625 | 326 | //=================================================================== | |
// Mem | 626 | |||
pipe_ex_mem #( .ADDRESS_WIDTH(ADDRESS_WIDTH), | 627 | |||
.DATA_WIDTH(DATA_WIDTH), | 628 | |||
.REG_ADDR_WIDTH(REG_ADDR_WIDTH), | 629 | |||
.ALU_CTLCODE_WIDTH(ALU_CTLCODE_WIDTH) | 630 | |||
) | 631 | |||
PIPE_EX_MEM | 632 | |||
( // Inputs | 633 | |||
.i_Clk(i_Clk), | 634 | |||
.i_Reset_n(Internal_Reset_n), | 635 | |||
.i_Flush(Hazard_Flush_EX), | 636 | |||
.i_Stall(Hazard_Stall_MEM), | 637 | |||
638 | ||||
// Pipe in/out | 639 | |||
.i_ALU_Result(ALU_o_Result), | 640 | |||
.o_ALU_Result(DMEM_i_Result), | 641 | |||
.i_Mem_Valid(EX_i_Mem_Valid), | 642 | |||
.o_Mem_Valid(DMEM_i_Mem_Valid), | 643 | |||
.i_Mem_Mask(EX_i_Mem_Mask), | 644 | |||
.o_Mem_Mask(DMEM_i_Mem_Mask), | 645 | |||
.i_Mem_Read_Write_n(EX_i_Mem_Read_Write_n), | 646 | |||
.o_Mem_Read_Write_n(DMEM_i_Mem_Read_Write_n), | 647 | |||
.i_Mem_Write_Data(EX_i_Mem_Write_Data), | 648 | |||
.o_Mem_Write_Data(DMEM_i_Mem_Write_Data), | 649 | |||
.i_Writes_Back(EX_i_Writes_Back), | 650 | |||
.o_Writes_Back(DMEM_i_Writes_Back), | 651 | |||
.i_Write_Addr(EX_i_Write_Addr), | 652 | |||
.o_Write_Addr(DMEM_i_Write_Addr) | 653 | |||
); | 654 | |||
655 | ||||
d_cache #( | 656 | |||
.DATA_WIDTH(32), | 657 | |||
.MEM_MASK_WIDTH(3) | 658 | |||
) | 659 | |||
D_CACHE | 660 | |||
( // Inputs | 661 | |||
.i_Clk(i_Clk), | 662 | |||
.i_Reset_n(Internal_Reset_n), | 663 | |||
.i_Valid(DMEM_i_Mem_Valid), | 664 | |||
.i_Mem_Mask(DMEM_i_Mem_Mask), | 665 | |||
.i_Address(DMEM_i_Result[ADDRESS_WIDTH:2]), | 666 | |||
.i_Read_Write_n(DMEM_i_Mem_Read_Write_n), //1=MemRead, 0=MemWrite | 667 | |||
.i_Write_Data(DMEM_i_Mem_Write_Data), | 668 | |||
669 | ||||
// Outputs | 670 | |||
.o_Ready(DMEM_o_Mem_Ready), | 671 | |||
.o_Valid(DMEM_o_Mem_Valid), | 672 | |||
.o_Data(DMEM_o_Read_Data), | 673 | |||
674 | ||||
// Mem Transaction | 675 | |||
.o_MEM_Valid(Arbiter_i_DMEM_Valid), | 676 | |||
.o_MEM_Read_Write_n(Arbiter_i_DMEM_Read_Write_n), | 677 | |||
.o_MEM_Address(Arbiter_i_DMEM_Address), | 678 | |||
.o_MEM_Data(Arbiter_i_DMEM_Data), | 679 | |||
.i_MEM_Valid(Arbiter_o_DMEM_Valid), | 680 | |||
.i_MEM_Data_Read(Arbiter_o_DMEM_Data_Read), | 681 | |||
.i_MEM_Last(Arbiter_o_DMEM_Last), | 682 | |||
.i_MEM_Data(Arbiter_o_DMEM_Data) | 683 | |||
); | 684 | |||
685 | ||||
// Multiplexor - Select what we will write back | 686 | |||
always @(*) | 687 | |||
begin | 688 | |||
if( MemToReg ) // If it was a memory operation | 689 | |||
begin | 690 | |||
DMEM_o_Write_Data <= DMEM_o_Read_Data; // We will write back value from memory | 691 | |||
DMEM_o_Done <= DMEM_o_Mem_Valid; // Write back only if value is valid | 692 | |||
end | 693 | |||
else | 694 | |||
begin | 695 | |||
DMEM_o_Write_Data <= DMEM_i_Result; // Else we will write back value from ALU | 696 | |||
DMEM_o_Done <= TRUE; | 697 | |||
end | 698 | |||
end | 699 | |||
700 | ||||
//=================================================================== | 701 | |||
// Write-Back | 702 | |||
pipe_mem_wb #( .ADDRESS_WIDTH(ADDRESS_WIDTH), | 703 | |||
.DATA_WIDTH(DATA_WIDTH), | 704 | |||
.REG_ADDR_WIDTH(REG_ADDR_WIDTH) | 705 | |||
) | 706 | |||
PIPE_MEM_WB | 707 | |||
( // Inputs | 708 | |||
.i_Clk(i_Clk), | 709 | |||
.i_Reset_n(Internal_Reset_n), | 710 | |||
.i_Flush(Hazard_Flush_MEM), | 711 | |||
.i_Stall(Hazard_Stall_WB), | 712 | |||
713 | ||||
// Pipe in/out | 714 | |||
.i_WriteBack_Data(DMEM_o_Write_Data), | 715 | |||
.o_WriteBack_Data(WB_i_Write_Data), | 716 | |||
.i_Writes_Back(DMEM_i_Writes_Back), | 717 | |||
.o_Writes_Back(WB_i_Writes_Back), | 718 | |||
.i_Write_Addr(DMEM_i_Write_Addr), | 719 | |||
.o_Write_Addr(DEC_i_Write_Register) | 720 | |||
); | 721 | |||
722 | ||||
723 | ||||
// Write-Back is simply wires feeding back into regfile to perform writes | 724 | |||
// (SEE REGFILE) | 725 | |||
726 | ||||
727 | ||||
728 | ||||
//=================================================================== | 729 | |||
// Arbitration Logic | 730 | 327 | // Arbitration Logic | |
731 | 328 | |||
// Memory arbiter | 732 | 329 | // Memory arbiter | |
memory_arbiter #( .DATA_WIDTH(DATA_WIDTH), | 733 | 330 | memory_arbiter #( .DATA_WIDTH(DATA_WIDTH), | |
.ADDRESS_WIDTH(ADDRESS_WIDTH) | 734 | 331 | .ADDRESS_WIDTH(ADDRESS_WIDTH) | |
) | 735 | 332 | ) | |
ARBITER | 736 | 333 | ARBITER | |
( | 737 | 334 | ( | |
// General | 738 | 335 | // General | |
.i_Clk(i_Clk), | 739 | 336 | .i_Clk(i_Clk), | |
.i_Reset_n(Internal_Reset_n), | 740 | 337 | .i_Reset_n(Internal_Reset_n), | |
741 | ||||
// Requests to/from IMEM - Assume we always read | 742 | |||
.i_IMEM_Valid(Arbiter_i_IMEM_Valid), // If IMEM request is valid | 743 | |||
.i_IMEM_Address(Arbiter_i_IMEM_Address), // IMEM request addr. | 744 | |||
.o_IMEM_Valid(Arbiter_o_IMEM_Valid), | 745 | |||
.o_IMEM_Last(Arbiter_o_IMEM_Last), | 746 | |||
.o_IMEM_Data(Arbiter_o_IMEM_Data), | 747 | |||
748 | 338 | |||
// Requests to/from DMEM | 749 | 339 | // Requests to/from CORE | |
.i_DMEM_Valid(Arbiter_i_DMEM_Valid), | 750 | 340 | .i_CORE_Valid(CORE_o_MEM_Valid), | |
.i_DMEM_Read_Write_n(Arbiter_i_DMEM_Read_Write_n), | 751 | 341 | .i_CORE_Read_Write_n(CORE_o_MEM_Read_Write_n), | |
.i_DMEM_Address(Arbiter_i_DMEM_Address), | 752 | 342 | .i_CORE_Address(CORE_o_MEM_Address), | |
.i_DMEM_Data(Arbiter_i_DMEM_Data), | 753 | 343 | .i_CORE_Data(CORE_o_MEM_Data), | |
.o_DMEM_Valid(Arbiter_o_DMEM_Valid), | 754 | 344 | .o_CORE_Valid(CORE_i_MEM_Valid), | |
.o_DMEM_Data_Read(Arbiter_o_DMEM_Data_Read), | 755 | 345 | .o_CORE_Data_Read(CORE_i_MEM_Data_Read), | |
.o_DMEM_Last(Arbiter_o_DMEM_Last), | 756 | 346 | .o_CORE_Last(CORE_i_MEM_Last), | |
.o_DMEM_Data(Arbiter_o_DMEM_Data), | 757 | 347 | .o_CORE_Data(CORE_i_MEM_Data), | |
758 | 348 | |||
// Requests to/from FLASH - Assume we always write | 759 | 349 | // Requests to/from FLASH - Assume we always write | |
.i_Flash_Valid(Arbiter_i_Flash_Valid), | 760 | 350 | .i_Flash_Valid(Arbiter_i_Flash_Valid), | |
.i_Flash_Data(Arbiter_i_Flash_Data), | 761 | 351 | .i_Flash_Data(Arbiter_i_Flash_Data), | |
.i_Flash_Address(Arbiter_i_Flash_Address), | 762 | 352 | .i_Flash_Address(Arbiter_i_Flash_Address), | |
.o_Flash_Data_Read(Arbiter_o_Flash_Data_Read), | 763 | 353 | .o_Flash_Data_Read(Arbiter_o_Flash_Data_Read), | |
.o_Flash_Last(Arbiter_o_Flash_Last), | 764 | 354 | .o_Flash_Last(Arbiter_o_Flash_Last), | |
765 | 355 | |||
// Interface with SDRAM Controller | 766 | 356 | // Interface with SDRAM Controller | |
.o_MEM_Valid(SDRAM_i_Valid), | 767 | 357 | .o_MEM_Valid(SDRAM_i_Valid), | |
.o_MEM_Address(SDRAM_i_Address), | 768 | 358 | .o_MEM_Address(SDRAM_i_Address), | |
.o_MEM_Read_Write_n(SDRAM_i_Read_Write_n), | 769 | 359 | .o_MEM_Read_Write_n(SDRAM_i_Read_Write_n), | |
770 | 360 | |||
// Write data interface | 771 | 361 | // Write data interface | |
.o_MEM_Data(SDRAM_i_Data), | 772 | 362 | .o_MEM_Data(SDRAM_i_Data), | |
.i_MEM_Data_Read(SDRAM_o_Data_Read), | 773 | 363 | .i_MEM_Data_Read(SDRAM_o_Data_Read), | |
774 | 364 | |||
// Read data interface | 775 | 365 | // Read data interface | |
.i_MEM_Data(SDRAM_o_Data), | 776 | 366 | .i_MEM_Data(SDRAM_o_Data), | |
.i_MEM_Data_Valid(SDRAM_o_Data_Valid), | 777 | 367 | .i_MEM_Data_Valid(SDRAM_o_Data_Valid), | |
778 | 368 | |||
.i_MEM_Last(SDRAM_o_Last) | 779 | 369 | .i_MEM_Last(SDRAM_o_Last) | |
); | 780 | 370 | ); | |
781 | 371 | |||
sdram_controller memory_controller( | 782 | 372 | sdram_controller memory_controller( | |
.i_Clk(i_Clk), | 783 | 373 | .i_Clk(i_Clk), | |
.i_Reset(!Internal_Reset_n), | 784 | 374 | .i_Reset(!Internal_Reset_n), | |
785 | 375 | |||
// Request interface | 786 | 376 | // Request interface | |
.i_Addr(SDRAM_i_Address), | 787 | 377 | .i_Addr(SDRAM_i_Address), | |
.i_Req_Valid(SDRAM_i_Valid), | 788 | 378 | .i_Req_Valid(SDRAM_i_Valid), | |
.i_Read_Write_n(SDRAM_i_Read_Write_n), | 789 | 379 | .i_Read_Write_n(SDRAM_i_Read_Write_n), | |
790 | 380 | |||
// Write .data interface | 791 | 381 | // Write .data interface | |
.i_Data(SDRAM_i_Data), | 792 | 382 | .i_Data(SDRAM_i_Data), | |
.o_Data_Read(SDRAM_o_Data_Read), | 793 | 383 | .o_Data_Read(SDRAM_o_Data_Read), | |
794 | 384 | |||
// Read data .interface | 795 | 385 | // Read data .interface | |
.o_Data(SDRAM_o_Data), | 796 | 386 | .o_Data(SDRAM_o_Data), | |
.o_Data_Valid(SDRAM_o_Data_Valid), | 797 | 387 | .o_Data_Valid(SDRAM_o_Data_Valid), | |
798 | 388 | |||
// output | 799 | 389 | // output | |
.o_Last(SDRAM_o_Last), | 800 | 390 | .o_Last(SDRAM_o_Last), | |
801 | 391 | |||
// SDRAM interface | 802 | 392 | // SDRAM interface | |
.b_Dq(DRAM_DQ), | 803 | 393 | .b_Dq(DRAM_DQ), | |
.o_Addr(DRAM_ADDR), | 804 | 394 | .o_Addr(DRAM_ADDR), | |
.o_Ba({DRAM_BA_0,DRAM_BA_1}), | 805 | 395 | .o_Ba({DRAM_BA_0,DRAM_BA_1}), | |
.o_Clk(DRAM_CLK), | 806 | 396 | .o_Clk(DRAM_CLK), | |
.o_Cke(DRAM_CKE), | 807 | 397 | .o_Cke(DRAM_CKE), | |
.o_Cs_n(DRAM_CS_N), | 808 | 398 | .o_Cs_n(DRAM_CS_N), | |
.o_Ras_n(DRAM_RAS_N), | 809 | 399 | .o_Ras_n(DRAM_RAS_N), | |
.o_Cas_n(DRAM_CAS_N), | 810 | 400 | .o_Cas_n(DRAM_CAS_N), | |
.o_We_n(DRAM_WE_N), | 811 | 401 | .o_We_n(DRAM_WE_N), | |
.o_Dqm({DRAM_UDQM,DRAM_LDQM}) | 812 | 402 | .o_Dqm({DRAM_UDQM,DRAM_LDQM}) | |
); | 813 | 403 | ); | |
814 | ||||
815 | ||||
// Forwarding logic | 816 | |||
forwarding_unit #( .DATA_WIDTH(DATA_WIDTH), | 817 | |||
.REG_ADDR_WIDTH(REG_ADDR_WIDTH) | 818 | |||
) | 819 | |||
FORWARDING_UNIT | 820 | |||
( | 821 | |||
// Feedback from DEC | 822 | |||
.i_DEC_Uses_RS(DEC_o_Uses_RS), | 823 | |||
.i_DEC_RS_Addr(DEC_o_Read_Register_1), | 824 | |||
.i_DEC_Uses_RT(DEC_o_Uses_RT), // DEC wants to use RT | 825 | |||
.i_DEC_RT_Addr(DEC_o_Read_Register_2), // RT request addr. | 826 | |||
.i_DEC_RS_Data(DEC_o_Read_Data_1), | 827 | |||
.i_DEC_RT_Data(DEC_o_Read_Data_2), | 828 | |||
829 | ||||
// Feedback from EX | 830 | |||
.i_EX_Writes_Back(EX_i_Writes_Back), // EX is valid for analysis | 831 | |||
.i_EX_Valid(ALU_i_Valid), // If it's a valid ALU op or not | 832 | |||
.i_EX_Write_Addr(EX_i_Write_Addr), // What EX will write to | 833 | |||
.i_EX_Write_Data(ALU_o_Result), | 834 | |||
835 | ||||
// Feedback from MEM | 836 | |||
.i_MEM_Writes_Back(DMEM_i_Writes_Back), // MEM is valid for analysis | 837 | |||
.i_MEM_Write_Addr(DMEM_i_Write_Addr), // What MEM will write to | 838 | |||
.i_MEM_Write_Data(DMEM_o_Write_Data), | 839 | |||
840 | ||||
// Feedback from WB | 841 | |||
.i_WB_Writes_Back(WB_i_Writes_Back), // WB is valid for analysis | 842 | |||
.i_WB_Write_Addr(DEC_i_Write_Register), // What WB will write to | 843 |