Commit bec01f1540e932d0348d38758e0917d520972412

Authored by zinsser
1 parent c6a7a29337

Release v1.3 Mips_core extracted.

Showing 9 changed files with 973 additions and 761 deletions Inline Diff

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