1 |
3 |
toni32 |
/* MODULE: openfire_decode
|
2 |
|
|
|
3 |
|
|
DESCRIPTION: The decode module received the instruction from the fetch module
|
4 |
|
|
and produces all control signals needed by the execute stage and the register
|
5 |
|
|
file. In the case of IMM instructions, the decode module will stall the
|
6 |
|
|
execute module by issuing a NoOp instruction.
|
7 |
|
|
|
8 |
|
|
The COMPARE module is used for calculating if a branch is taken and CMPU
|
9 |
|
|
ops if support is selected. The DECODE module commands the comparator to output
|
10 |
|
|
a 1 for unconditional branchs and a 0 for all other non-branch instructions (other
|
11 |
|
|
than CMPU)..
|
12 |
|
|
|
13 |
|
|
While FSL instructions are optionally implemented (if FSL_LINK is defined),
|
14 |
|
|
only one link (FSL0) is currently supported.
|
15 |
|
|
|
16 |
|
|
MISSING INSTRUCTIONS:
|
17 |
|
|
- special register instruction: MSRCLR, MSRSET
|
18 |
|
|
- all instructions requiring extra hardware, except for optional multiply: IDIV, BS
|
19 |
|
|
- cache-related instruction: WDC, WIC
|
20 |
|
|
|
21 |
|
|
TO DO:
|
22 |
|
|
- Complete instruction set
|
23 |
|
|
- Simplify instruction extension
|
24 |
|
|
|
25 |
|
|
AUTHOR:
|
26 |
|
|
Stephen Douglas Craven
|
27 |
|
|
Configurable Computing Lab
|
28 |
|
|
Virginia Tech
|
29 |
|
|
scraven@vt.edu
|
30 |
|
|
|
31 |
|
|
REVISION HISTORY:
|
32 |
|
|
Revision 0.2, 8/10/2005 SDC
|
33 |
|
|
Initial release
|
34 |
|
|
|
35 |
|
|
Revision 0.3, 12/17/2005 SDC
|
36 |
|
|
Fixed PC size bug
|
37 |
|
|
|
38 |
|
|
Revision 0.4, 15/03/2007 SDC
|
39 |
|
|
Fixed CMP[U] with IMM bit
|
40 |
|
|
|
41 |
|
|
Revision 0.5 27/03/2007 Antonio J. Anton
|
42 |
|
|
Handling of interrupts/exceptions
|
43 |
|
|
MSR opcodes (mfs, mts)
|
44 |
|
|
|
45 |
|
|
COPYRIGHT:
|
46 |
|
|
Copyright (c) 2005 Stephen Douglas Craven
|
47 |
|
|
|
48 |
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
49 |
|
|
this software and associated documentation files (the "Software"), to deal in
|
50 |
|
|
the Software without restriction, including without limitation the rights to
|
51 |
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
52 |
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
53 |
|
|
so, subject to the following conditions:
|
54 |
|
|
|
55 |
|
|
The above copyright notice and this permission notice shall be included in all
|
56 |
|
|
copies or substantial portions of the Software.
|
57 |
|
|
|
58 |
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
59 |
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
60 |
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
61 |
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
62 |
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
63 |
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
64 |
|
|
SOFTWARE. */
|
65 |
|
|
|
66 |
|
|
`include "openfire_define.v"
|
67 |
|
|
|
68 |
|
|
module openfire_decode(
|
69 |
|
|
`ifdef ENABLE_MSR_BIP
|
70 |
|
|
update_msr_bip, value_msr_bip,
|
71 |
|
|
`endif
|
72 |
|
|
`ifdef ENABLE_INTERRUPTS
|
73 |
|
|
int_ip, int_dc, set_msr_ie,
|
74 |
|
|
`endif
|
75 |
|
|
`ifdef ENABLE_OPCODE_EXCEPTION
|
76 |
|
|
opcode_exception,
|
77 |
|
|
`endif
|
78 |
|
|
`ifdef ENABLE_EXCEPTIONS
|
79 |
|
|
reset_msr_eip, insert_exception,
|
80 |
|
|
`endif
|
81 |
|
|
`ifdef ENABLE_MSR_OPCODES
|
82 |
|
|
rS_update,
|
83 |
|
|
`endif
|
84 |
4 |
toni32 |
`ifdef FSL_LINK
|
85 |
|
|
fsl_get, fsl_control, fsl_blocking, fsl_cmd_vld, // fsl signals
|
86 |
|
|
`endif
|
87 |
3 |
toni32 |
clock, stall, reset, // top level
|
88 |
|
|
pc_decode, instruction, flush, // inputs
|
89 |
|
|
regA_addr, regB_addr, regD_addr, immediate, // outputs
|
90 |
|
|
alu_inputA_sel, alu_inputB_sel, alu_inputC_sel,
|
91 |
|
|
alu_fns_sel, comparator_fns_sel, branch_instr,
|
92 |
|
|
we_alu_branch, we_load, we_store, regfile_input_sel,
|
93 |
|
|
dmem_input_sel, delay_bit, update_carry, pc_exe
|
94 |
|
|
);
|
95 |
|
|
|
96 |
|
|
// From top level -- all active high unless otherwise noted
|
97 |
|
|
input stall;
|
98 |
|
|
input reset;
|
99 |
|
|
input clock;
|
100 |
|
|
|
101 |
|
|
// From DECODE module
|
102 |
|
|
input [`A_SPACE+1:0] pc_decode;
|
103 |
|
|
input [31:0] instruction;
|
104 |
|
|
|
105 |
|
|
// From Pipeline Controller
|
106 |
|
|
input flush; // a branch was taken... flush the pipeline
|
107 |
|
|
|
108 |
|
|
output [4:0] regA_addr;
|
109 |
|
|
output [4:0] regB_addr;
|
110 |
|
|
output [4:0] regD_addr;
|
111 |
|
|
output [31:0] immediate;
|
112 |
|
|
output [`A_SPACE+1:0] pc_exe; // pc for use by EXECUTE
|
113 |
|
|
output [2:0] alu_inputA_sel;
|
114 |
|
|
output [1:0] alu_inputB_sel;
|
115 |
|
|
output [1:0] alu_inputC_sel;
|
116 |
|
|
output [3:0] alu_fns_sel;
|
117 |
|
|
output [2:0] comparator_fns_sel;
|
118 |
|
|
output we_load; // write_en for regfile on Load
|
119 |
|
|
output we_store; // write_en for DMEM
|
120 |
|
|
output we_alu_branch; // write_en for regfile on ALU / Branch instr
|
121 |
|
|
output [3:0] regfile_input_sel; // selects input to regfile
|
122 |
|
|
output [1:0] dmem_input_sel; // selects input to DMEM
|
123 |
|
|
output delay_bit;
|
124 |
|
|
output update_carry; // tells EXECUTE to update carry bit in MSR
|
125 |
|
|
output branch_instr; // tells EXECUTE to use comparator for branching
|
126 |
|
|
`ifdef ENABLE_MSR_BIP
|
127 |
|
|
output update_msr_bip; // handle MSR[BIP]
|
128 |
|
|
output value_msr_bip;
|
129 |
|
|
`endif
|
130 |
|
|
`ifdef ENABLE_INTERRUPTS
|
131 |
|
|
input int_ip;
|
132 |
|
|
output int_dc;
|
133 |
|
|
output set_msr_ie;
|
134 |
|
|
`endif
|
135 |
|
|
`ifdef ENABLE_OPCODE_EXCEPTION
|
136 |
|
|
output opcode_exception;
|
137 |
|
|
input insert_exception;
|
138 |
|
|
`endif
|
139 |
|
|
`ifdef ENABLE_EXCEPTIONS
|
140 |
|
|
output reset_msr_eip;
|
141 |
|
|
`endif
|
142 |
|
|
`ifdef ENABLE_MSR_OPCODES
|
143 |
|
|
output rS_update;
|
144 |
|
|
`endif
|
145 |
4 |
toni32 |
`ifdef FSL_LINK
|
146 |
|
|
output fsl_get;
|
147 |
|
|
output fsl_control;
|
148 |
|
|
output fsl_blocking;
|
149 |
|
|
output fsl_cmd_vld;
|
150 |
|
|
`endif
|
151 |
3 |
toni32 |
|
152 |
|
|
// Register All Outputs
|
153 |
|
|
reg [31:0] immediate;
|
154 |
|
|
reg [`A_SPACE+1:0] pc_exe; // Prog Cnter of instr being executed
|
155 |
|
|
reg [2:0] alu_inputA_sel;
|
156 |
|
|
reg [1:0] alu_inputB_sel;
|
157 |
|
|
reg [1:0] alu_inputC_sel;
|
158 |
|
|
reg [3:0] alu_fns_sel; // selects ALU function
|
159 |
|
|
reg [2:0] comparator_fns_sel;
|
160 |
|
|
reg we_load; // reg file write enable for load operations
|
161 |
|
|
reg we_store;
|
162 |
|
|
reg we_alu_branch; // reg file write enable for ALU or branch ops
|
163 |
|
|
reg [3:0] regfile_input_sel;
|
164 |
|
|
reg [1:0] dmem_input_sel;
|
165 |
|
|
reg [4:0] regA_addr; // 5-bit addresses into Reg File
|
166 |
|
|
reg [4:0] regB_addr;
|
167 |
|
|
reg [4:0] regD_addr;
|
168 |
|
|
reg update_carry; // update the Carry bit in the status reg for ADDs
|
169 |
|
|
reg delay_bit; // Use delay slot in Branches
|
170 |
|
|
reg branch_instr;
|
171 |
|
|
`ifdef ENABLE_MSR_BIP
|
172 |
|
|
reg update_msr_bip;
|
173 |
|
|
reg value_msr_bip;
|
174 |
|
|
`endif
|
175 |
|
|
`ifdef ENABLE_INTERRUPTS
|
176 |
|
|
reg int_dc;
|
177 |
|
|
reg set_msr_ie;
|
178 |
|
|
`endif
|
179 |
|
|
`ifdef ENABLE_OPCODE_EXCEPTION
|
180 |
|
|
reg opcode_exception;
|
181 |
|
|
`endif
|
182 |
|
|
`ifdef ENABLE_EXCEPTIONS
|
183 |
|
|
reg reset_msr_eip;
|
184 |
|
|
`endif
|
185 |
|
|
`ifdef ENABLE_MSR_OPCODES
|
186 |
|
|
reg rS_update;
|
187 |
|
|
`endif
|
188 |
4 |
toni32 |
`ifdef FSL_LINK
|
189 |
|
|
reg fsl_get;
|
190 |
|
|
reg fsl_control;
|
191 |
|
|
reg fsl_blocking;
|
192 |
|
|
reg fsl_cmd_vld;
|
193 |
|
|
`endif
|
194 |
3 |
toni32 |
|
195 |
|
|
// Internal registers
|
196 |
|
|
reg [15:0] imm; // contains imm value from IMM instr
|
197 |
|
|
reg imm_valid; // indicates imm value is valid (aka previous instr was IMM)
|
198 |
|
|
|
199 |
|
|
always@(posedge clock)
|
200 |
|
|
begin
|
201 |
|
|
if (reset | (flush & !stall)) // flush only if not stalled, if not we may miss the executing state
|
202 |
|
|
begin
|
203 |
|
|
if (reset)
|
204 |
|
|
pc_exe <= 0;
|
205 |
|
|
else
|
206 |
|
|
pc_exe <= pc_decode;
|
207 |
|
|
update_carry <= 0;
|
208 |
|
|
regA_addr <= 0;
|
209 |
|
|
regB_addr <= 0;
|
210 |
|
|
regD_addr <= 0;
|
211 |
|
|
immediate <= 0;
|
212 |
|
|
alu_inputA_sel <= 0;
|
213 |
|
|
alu_inputB_sel <= 0;
|
214 |
|
|
alu_inputC_sel <= 0;
|
215 |
|
|
delay_bit <= 0;
|
216 |
|
|
branch_instr <= 0;
|
217 |
|
|
// EXECUTE NoOp on Reset / Flush. NoOp is OR r0, r0, r0
|
218 |
|
|
alu_fns_sel <= `ALU_logic_or;
|
219 |
|
|
comparator_fns_sel<= 0;
|
220 |
|
|
we_load <= 0;
|
221 |
|
|
we_store <= 0;
|
222 |
|
|
we_alu_branch <= 0;
|
223 |
|
|
regfile_input_sel <= `RF_zero; // write zero to r0 on reset -- R0 always zero
|
224 |
|
|
dmem_input_sel <= 0;
|
225 |
|
|
imm <= 0;
|
226 |
|
|
imm_valid <= 0;
|
227 |
|
|
`ifdef ENABLE_MSR_BIP
|
228 |
|
|
update_msr_bip <= 0;
|
229 |
|
|
value_msr_bip <= 0;
|
230 |
|
|
`endif
|
231 |
|
|
`ifdef ENABLE_INTERRUPTS
|
232 |
|
|
int_dc <= 0;
|
233 |
|
|
set_msr_ie <= 0;
|
234 |
|
|
`endif
|
235 |
|
|
`ifdef ENABLE_OPCODE_EXCEPTION
|
236 |
|
|
opcode_exception <= 0;
|
237 |
|
|
`endif
|
238 |
|
|
`ifdef ENABLE_EXCEPTIONS
|
239 |
|
|
reset_msr_eip <= 0;
|
240 |
|
|
`endif
|
241 |
|
|
`ifdef ENABLE_MSR_OPCODES
|
242 |
|
|
rS_update <= 0;
|
243 |
|
|
`endif
|
244 |
4 |
toni32 |
`ifdef FSL_LINK
|
245 |
|
|
fsl_control <= 0;
|
246 |
|
|
fsl_get <= 0;
|
247 |
|
|
fsl_blocking <= 0;
|
248 |
|
|
fsl_cmd_vld <= 0;
|
249 |
|
|
`endif
|
250 |
3 |
toni32 |
`ifdef DEBUG_DECODE
|
251 |
|
|
$display("DECODE RESET/FLUSH: pc_exe=%x", pc_exe);
|
252 |
|
|
`endif
|
253 |
|
|
end
|
254 |
|
|
else if (!stall)
|
255 |
|
|
begin
|
256 |
|
|
// defaults for most instructions
|
257 |
|
|
branch_instr <= 0;
|
258 |
|
|
pc_exe <= pc_decode;
|
259 |
|
|
// Delay bit is tricky as each type of branch has a different location
|
260 |
|
|
delay_bit <= `uncond_branch ? ((`opcode == `RETURN) ? 1 : `D_bit_uncond) : `cond_branch ? `D_bit_cond : 0;
|
261 |
|
|
we_load <= 0;
|
262 |
|
|
we_store <= 0;
|
263 |
|
|
update_carry <= 0;
|
264 |
|
|
regA_addr <= `regA_sel;
|
265 |
|
|
regB_addr <= `regB_sel;
|
266 |
|
|
regD_addr <= `regD_sel;
|
267 |
|
|
immediate <= imm_valid ? {imm, `imm_value} : {{16{instruction[15]}}, `imm_value}; // 32-bit datapath
|
268 |
|
|
we_alu_branch <= 1'b1; // most instrs write to reg file
|
269 |
|
|
regfile_input_sel <= `RF_alu_result;
|
270 |
|
|
alu_inputA_sel <= `aluA_ra;
|
271 |
|
|
alu_inputB_sel <= `IMM_bit ? `aluB_imm : `aluB_rb;
|
272 |
|
|
alu_inputC_sel <= `aluC_zero;
|
273 |
|
|
alu_fns_sel <= `ALU_add;
|
274 |
|
|
comparator_fns_sel<= 0; // Not using comparator
|
275 |
|
|
imm_valid <= 0;
|
276 |
|
|
`ifdef ENABLE_MSR_BIP
|
277 |
|
|
update_msr_bip <= 0;
|
278 |
|
|
value_msr_bip <= 0;
|
279 |
|
|
`endif
|
280 |
|
|
`ifdef ENABLE_INTERRUPTS
|
281 |
|
|
set_msr_ie <= 0;
|
282 |
|
|
int_dc <= 0;
|
283 |
|
|
`endif
|
284 |
|
|
`ifdef ENABLE_OPCODE_EXCEPTION
|
285 |
|
|
opcode_exception <= 0;
|
286 |
|
|
`endif
|
287 |
|
|
`ifdef ENABLE_EXCEPTIONS
|
288 |
|
|
reset_msr_eip <= 0;
|
289 |
|
|
`endif
|
290 |
|
|
`ifdef ENABLE_MSR_OPCODES
|
291 |
|
|
rS_update <= 0;
|
292 |
|
|
`endif
|
293 |
4 |
toni32 |
`ifdef FSL_LINK
|
294 |
|
|
fsl_control <= 0;
|
295 |
|
|
fsl_get <= 0;
|
296 |
|
|
fsl_blocking <= 0;
|
297 |
|
|
fsl_cmd_vld <= 0;
|
298 |
|
|
`endif
|
299 |
3 |
toni32 |
`ifdef ENABLE_OPCODE_EXCEPTION
|
300 |
|
|
// CPU asks to insert exception break: "brali r17,0x20"
|
301 |
|
|
if(insert_exception)
|
302 |
|
|
begin
|
303 |
|
|
branch_instr <= 1;
|
304 |
|
|
alu_inputA_sel <= `aluA_zero;
|
305 |
|
|
alu_inputB_sel <= `aluB_imm;
|
306 |
|
|
comparator_fns_sel <= `CMP_one; // force a branch
|
307 |
|
|
regfile_input_sel <= `RF_pc;
|
308 |
|
|
regD_addr <= `REG_RET_FROM_EXCEPTION;
|
309 |
|
|
immediate <= `ADDRESS_EXCEPTION_VECTOR;
|
310 |
|
|
$display("DECODE: Inserting OPCODE-EXCEPTION at pc_decode=0x%x, pc_exe=0x%x", pc_decode, pc_exe);
|
311 |
|
|
end
|
312 |
|
|
else
|
313 |
|
|
`endif
|
314 |
|
|
`ifdef ENABLE_INTERRUPTS
|
315 |
|
|
// when EXECUTE notifies "interrupt in progress", the DECODE module must insert "brali r14,0x10" when
|
316 |
|
|
// possible; this is not after a IMM opcode nor in a delay slot. When inserted the interrupt opcode,
|
317 |
|
|
// notify EXECUTE that the decode is completed
|
318 |
|
|
if(int_ip && !imm_valid && !delay_bit)
|
319 |
|
|
begin
|
320 |
|
|
branch_instr <= 1;
|
321 |
|
|
alu_inputA_sel <= `aluA_zero;
|
322 |
|
|
alu_inputB_sel <= `aluB_imm;
|
323 |
|
|
comparator_fns_sel <= `CMP_one; // force a branch
|
324 |
|
|
regfile_input_sel <= `RF_pc;
|
325 |
|
|
regD_addr <= `REG_RET_FROM_INTERRUPT;
|
326 |
|
|
immediate <= `ADDRESS_INTERRUPT_VECTOR;
|
327 |
|
|
int_dc <= 1; // notify that DECODE is completed
|
328 |
|
|
$display("DECODE: Inserting INTERRUPT at pc_decode=0x%x, pc_exe=0x%x", pc_decode, pc_exe);
|
329 |
|
|
end
|
330 |
|
|
else
|
331 |
|
|
`endif
|
332 |
|
|
// BIG Case statement here
|
333 |
|
|
// see openfire_define.v for definitions
|
334 |
|
|
casez (`opcode)
|
335 |
|
|
`ADD:
|
336 |
|
|
begin
|
337 |
|
|
alu_inputC_sel <= `C_bit ? `aluC_carry : `aluC_zero;
|
338 |
|
|
update_carry <= ~`K_bit;
|
339 |
|
|
end
|
340 |
|
|
`SUBTRACT:
|
341 |
|
|
begin
|
342 |
|
|
update_carry <= ~`K_bit;
|
343 |
|
|
if (`U_bit & `CMP_bit & !`IMM_bit) // CMPU
|
344 |
|
|
begin
|
345 |
|
|
alu_fns_sel <= `ALU_compare_uns;
|
346 |
|
|
comparator_fns_sel <= `CMP_dual_inputs;
|
347 |
|
|
end
|
348 |
|
|
else if (`CMP_bit & !`IMM_bit) // CMP
|
349 |
|
|
alu_fns_sel <= `ALU_compare;
|
350 |
|
|
else
|
351 |
|
|
alu_fns_sel <= `ALU_add;
|
352 |
|
|
alu_inputA_sel <= `aluA_ra_bar;
|
353 |
|
|
alu_inputC_sel <= `C_bit ? `aluC_carry : `aluC_one;
|
354 |
|
|
end
|
355 |
|
|
`LOGIC_OR: alu_fns_sel <= `ALU_logic_or;
|
356 |
|
|
`LOGIC_AND: alu_fns_sel <= `ALU_logic_and;
|
357 |
|
|
`LOGIC_XOR: alu_fns_sel <= `ALU_logic_xor;
|
358 |
|
|
`LOGIC_ANDN:
|
359 |
|
|
begin
|
360 |
|
|
alu_fns_sel <= `ALU_logic_and;
|
361 |
|
|
alu_inputB_sel <= `IMM_bit ? `aluB_imm_bar : `aluB_rb_bar;
|
362 |
|
|
end
|
363 |
|
|
`LOGIC_BIT:
|
364 |
|
|
begin
|
365 |
|
|
alu_inputC_sel <= `aluC_carry;
|
366 |
|
|
update_carry <= 1;
|
367 |
|
|
casez (`imm_value)
|
368 |
|
|
16'b1: alu_fns_sel <= `ALU_shiftR_arth;
|
369 |
|
|
16'b100001: alu_fns_sel <= `ALU_shiftR_c;
|
370 |
|
|
16'b1000001: alu_fns_sel <= `ALU_shiftR_log;
|
371 |
|
|
16'b1100000: alu_fns_sel <= `ALU_sex8;
|
372 |
|
|
16'b1100001: alu_fns_sel <= `ALU_sex16;
|
373 |
|
|
endcase
|
374 |
|
|
end
|
375 |
|
|
`BRANCH_UNCON: // Handles BREAKs as well
|
376 |
|
|
begin
|
377 |
|
|
branch_instr <= 1;
|
378 |
|
|
alu_inputA_sel <= `A_bit ? `aluA_zero : `aluA_pc;
|
379 |
|
|
alu_inputB_sel <= `IMM_bit ? `aluB_imm : `aluB_rb;
|
380 |
|
|
comparator_fns_sel <= `CMP_one; // force a branch
|
381 |
|
|
regfile_input_sel <= `RF_pc;
|
382 |
|
|
`ifdef ENABLE_MSR_BIP
|
383 |
|
|
update_msr_bip <= ~`D_bit_uncond & `A_bit & `L_bit; // is br[i]al --> break
|
384 |
|
|
value_msr_bip <= 1; // BREAK --> MSR[BIP] <= 1
|
385 |
|
|
`endif
|
386 |
|
|
end
|
387 |
|
|
`BRANCH_CON:
|
388 |
|
|
begin
|
389 |
|
|
branch_instr <= 1;
|
390 |
|
|
alu_inputA_sel <= `aluA_pc;
|
391 |
|
|
comparator_fns_sel<= `branch_compare;
|
392 |
|
|
we_alu_branch <= 1'b0;
|
393 |
|
|
end
|
394 |
|
|
`ifdef ENABLE_MSR_OPCODES
|
395 |
|
|
`SPECIAL_REG: // Handle mfs, mts
|
396 |
|
|
begin
|
397 |
|
|
if(`is_mfs) // mfs rD,rS --> move rS to ALU input A
|
398 |
|
|
begin
|
399 |
|
|
casez(`regS_sel_msr) // select corresponding ALU input based on rS
|
400 |
|
|
`rS_PC : alu_inputA_sel <= `aluA_pc;
|
401 |
|
|
`rS_MSR : alu_inputA_sel <= `aluA_msr;
|
402 |
|
|
default: $display("mfs: invalid rS=%x", `regS_sel_msr);
|
403 |
|
|
endcase
|
404 |
|
|
end
|
405 |
|
|
else if(`is_mts) // mts rS,rD (rS is only MSR). Ask EXE to update MSR from rA
|
406 |
|
|
rS_update <= 1;
|
407 |
|
|
end
|
408 |
|
|
`endif
|
409 |
|
|
`IMMEDIATE:
|
410 |
|
|
begin
|
411 |
|
|
we_alu_branch <= 1'b0; // have EXE do nothing
|
412 |
|
|
imm_valid <= 1;
|
413 |
|
|
imm <= `imm_value;
|
414 |
|
|
end
|
415 |
|
|
`RETURN: // ignores MSR, exceptions, and interrupts
|
416 |
|
|
begin
|
417 |
|
|
branch_instr <= 1;
|
418 |
|
|
alu_inputB_sel <= `aluB_imm;
|
419 |
|
|
comparator_fns_sel<= `CMP_one; // force a branch
|
420 |
|
|
we_alu_branch <= 1'b0;
|
421 |
|
|
`ifdef ENABLE_MSR_BIP
|
422 |
|
|
update_msr_bip <= `BRK_bit; // return from break?
|
423 |
|
|
value_msr_bip <= 0; // rtbd? MSR[BIP] <= 0
|
424 |
|
|
`endif
|
425 |
|
|
`ifdef ENABLE_INTERRUPTS
|
426 |
|
|
set_msr_ie <= `INT_bit; // MSR[IE] <= 1 if return from interrupt
|
427 |
|
|
`ifdef DEBUG_DECODE
|
428 |
|
|
`ifdef ENABLE_EXCEPTIONS
|
429 |
|
|
reset_msr_eip <= `EXC_bit; // MSR[EIP] <= 0 if return from exception
|
430 |
|
|
`endif
|
431 |
|
|
$display("DECODE: RETURN FROM INTERRUPT -- pc_exe=%x", pc_exe);
|
432 |
|
|
`endif
|
433 |
|
|
`endif
|
434 |
|
|
end
|
435 |
|
|
`LOAD:
|
436 |
|
|
begin
|
437 |
|
|
we_alu_branch <= 1'b0;
|
438 |
|
|
we_load <= 1'b1;
|
439 |
|
|
dmem_input_sel <= `word_size;
|
440 |
|
|
regfile_input_sel <= `word_size;
|
441 |
|
|
end
|
442 |
|
|
`STORE:
|
443 |
|
|
begin
|
444 |
|
|
we_alu_branch <= 1'b0;
|
445 |
|
|
we_store <= 1'b1;
|
446 |
|
|
dmem_input_sel <= `word_size;
|
447 |
|
|
end
|
448 |
|
|
`ifdef FSL_LINK
|
449 |
|
|
`FSL:
|
450 |
4 |
toni32 |
begin
|
451 |
|
|
fsl_control <= `FSL_control;
|
452 |
|
|
fsl_get <= ~`fsl_get_put;
|
453 |
|
|
fsl_blocking <= ~`FSL_nblock;
|
454 |
|
|
fsl_cmd_vld <= 1;
|
455 |
|
|
we_alu_branch <= 0;
|
456 |
|
|
regfile_input_sel <= `RF_fsl;
|
457 |
|
|
end
|
458 |
3 |
toni32 |
`endif
|
459 |
|
|
`ifdef MUL
|
460 |
|
|
`MULTIPLY:
|
461 |
|
|
begin
|
462 |
|
|
alu_fns_sel <= `ALU_multiply;
|
463 |
|
|
// 32-bit mult takes several cycles -- do not write to Reg File until complete
|
464 |
|
|
we_alu_branch <= 1'b0;
|
465 |
|
|
end
|
466 |
|
|
`endif
|
467 |
|
|
default:
|
468 |
|
|
begin
|
469 |
|
|
$display("ERROR! Malformed OpCode! 0x%x", `opcode);
|
470 |
|
|
`ifdef ENABLE_OPCODE_EXCEPTION
|
471 |
|
|
opcode_exception <= 1; // notify EXECUTE that we are in "opcode exception"
|
472 |
|
|
`endif
|
473 |
|
|
end
|
474 |
|
|
endcase
|
475 |
|
|
`ifdef DEBUG_DECODE
|
476 |
|
|
$display("DECODE: pc_exe=%x, instruction=%x", pc_exe, instruction);
|
477 |
|
|
`endif
|
478 |
|
|
end
|
479 |
|
|
|
480 |
|
|
end // end of always@
|
481 |
|
|
|
482 |
|
|
endmodule
|