OpenCores
URL https://opencores.org/ocsvn/openfire2/openfire2/trunk

Subversion Repositories openfire2

[/] [openfire2/] [trunk/] [rtl/] [openfire_decode.v] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.