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

Subversion Repositories openfire2

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 toni32
/*      MODULE: openfire_execute
2
 
3
        DESCRIPTION: The execute module instantiates the alu and comparator and
4
updates the Machine Status Register (MSR).  This module produces a status
5
signal, instr_complete, when the currently executing instruction is finished.
6
 
7
TO DO:
8
- Add interrupt handling
9
- Add exception handling
10
- Complete MSR
11
- Add all other special registers: EAR, ESR, ESS
12
- Add OPB interface
13
 
14
AUTHOR:
15
Stephen Douglas Craven
16
Configurable Computing Lab
17
Virginia Tech
18
scraven@vt.edu
19
 
20
REVISION HISTORY:
21
Revision 0.2, 8/10/2005 SDC
22
Initial release
23
 
24
Revision 0.3, 12/17/2005 SDC
25
Fixed PC size bug and CMP bug for case when both rA and rB are negative.
26
 
27
Revision 0.4  27/03/2007 Antonio J. Anton
28
Memory handshaking protocol
29
Removed memory read/write alignment code
30
Interrupt handling
31
Exception handling
32
MSR register handling
33
 
34
COPYRIGHT:
35
Copyright (c) 2005 Stephen Douglas Craven
36
 
37
Permission is hereby granted, free of charge, to any person obtaining a copy of
38
this software and associated documentation files (the "Software"), to deal in
39
the Software without restriction, including without limitation the rights to
40
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
41
of the Software, and to permit persons to whom the Software is furnished to do
42
so, subject to the following conditions:
43
 
44
The above copyright notice and this permission notice shall be included in all
45
copies or substantial portions of the Software.
46
 
47
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53
SOFTWARE.
54
 
55
*/
56
 
57
`include "openfire_define.v"
58
 
59
module openfire_execute (
60
`ifdef ENABLE_MSR_BIP
61
        update_msr_bip, value_msr_bip,
62
`endif
63
`ifdef ENABLE_INTERRUPTS
64
        interrupt, int_ip, int_dc, set_msr_ie,
65
`endif
66
`ifdef ENABLE_MSR_OPCODES
67
        rS_update,
68
`endif
69
`ifdef ENABLE_OPCODE_EXCEPTION
70
        opcode_exception,
71
`endif
72
`ifdef ENABLE_EXCEPTIONS
73
        reset_msr_eip,
74
`endif
75
`ifdef ENABLE_ALIGNMENT_EXCEPTION
76
        dmem_alignment_exception,
77
`endif
78 4 toni32
`ifdef FSL_LINK
79
        fsl_m_control, fsl_m_write, fsl_s_read,
80
        fsl_cmd_vld, fsl_get, fsl_blocking, fsl_control,        //FSL
81
        fsl_m_full, fsl_s_control, fsl_s_exists,
82
`endif
83 3 toni32
        clock, reset, stall,                                                                                    // top level
84
        immediate, pc_exe, alu_inputA_sel, alu_inputB_sel, // inputs
85
        alu_inputC_sel, alu_fns_sel, comparator_fns_sel,
86
        we_load, we_store, regA,
87
        regB, regD, update_carry, branch_instr,
88
        alu_result, pc_branch, branch_taken,                                    // outputs
89
        we_regfile, dmem_addr,
90
        dmem_data_out, instr_complete, dmem_done,
91
        dmem_we, dmem_re
92
);
93
 
94
// From top level -- all active high unless otherwise noted
95
input           stall;
96
input           reset;
97
input           clock;
98
 
99
// From DECODE module
100
input   [31:0]   immediate;
101
input   [`A_SPACE+1:0]   pc_exe;                 // pc for use by EXECUTE
102
input   [2:0]            alu_inputA_sel;
103
input   [1:0]            alu_inputB_sel;
104
input   [1:0]            alu_inputC_sel;
105
input   [3:0]            alu_fns_sel;
106
input   [2:0]            comparator_fns_sel;
107
input                   we_load;                                        // write_en for regfile on Load
108
input                           we_store;                               // we on DMEM on Store
109
input                           update_carry;
110
input                           branch_instr;
111
input                           dmem_done;
112
output                  dmem_re;
113
output                  dmem_we;
114
`ifdef ENABLE_MSR_BIP
115
input                           update_msr_bip;
116
input                           value_msr_bip;
117
`endif
118
`ifdef ENABLE_INTERRUPTS
119
input                           interrupt;
120
output                  int_ip;
121
input                      int_dc;
122
input                      set_msr_ie;
123
`endif
124
`ifdef ENABLE_MSR_OPCODES
125
input                           rS_update;
126
`endif
127
`ifdef ENABLE_OPCODE_EXCEPTION
128
input                           opcode_exception;
129
`endif
130
`ifdef ENABLE_EXCEPTIONS
131
input                           reset_msr_eip;
132
output                  insert_exception;
133
`endif
134
`ifdef ENABLE_ALIGNMENT_EXCEPTION
135
input                           dmem_alignment_exception;
136
`endif
137 4 toni32
`ifdef FSL_LINK
138
input                   fsl_get;
139
input                   fsl_control;
140
input                   fsl_blocking;
141
input                   fsl_cmd_vld;
142
input                   fsl_s_control;          //From FSL
143
input                   fsl_s_exists;
144
input                   fsl_m_full;
145
output          fsl_m_control;
146
output          fsl_m_write;
147
output          fsl_s_read;
148
`endif
149 3 toni32
 
150
// From REGFILE
151
input   [31:0]   regA;
152
input   [31:0]   regB;
153
input   [31:0]   regD;
154
 
155
output  [31:0]   alu_result;
156
output  [`A_SPACE+1:0]   pc_branch;
157
output                          branch_taken;
158
output                          we_regfile;                     // we for load and alu
159
output  [31:0]   dmem_addr;
160
output  [31:0]   dmem_data_out;
161
output                          instr_complete; // status of execution, active high
162
 
163
// register all outputs EXCEPT:
164
//      - branch_taken and pc_branch -- registered in FETCH
165
//      - alu_result -- REGFILE registers
166
//      - dmem_addr -- DMEM registers
167
//      - instr_complete -- needed before rise of clock by PIPLINE_CTRL
168
assign dmem_data_out = regD;
169
 
170
// internal registers
171
reg     [31:0]   MSR;                            // **TODO** Working: C, BIP, IE
172
reg     [31:0]   alu_a_input;
173
reg     [31:0]   alu_b_input;
174
reg                             alu_c_input;
175
reg                             MSB_signed_compare;
176
 
177 4 toni32
`ifdef FSL_LINK
178
reg                     fsl_complete;
179
reg                     fsl_m_write;
180
reg                     fsl_s_read;
181
reg                     fsl_m_control;
182
`endif
183
 
184 3 toni32
wire                    alu_multicycle_instr;
185
wire                    alu_multicycle_instr_complete;
186
wire                    multicycle_instr;
187
wire                    multicycle_instr_complete;
188
wire                    c_out;
189
wire                    compare_out;
190
wire [31:0]      alu_out_internal;
191
wire [31:0]      extended_pc;    // PC with leading zeros addded
192
 
193
`ifdef ENABLE_EXCEPTIONS
194
reg                     insert_exception;                       // to ask DECODE to insert "brali r17,0x20"
195
wire                    exception =                             // 1 if any exception happened
196
`ifdef ENABLE_ALIGNMENT_EXCEPTION
197
                                                                dmem_alignment_exception |
198
`endif
199
`ifdef ENABLE_OPCODE_EXCEPTION
200
                                                                opcode_exception |
201
`endif
202
                                                                0;
203
`endif
204
 
205
`ifdef ENABLE_INTERRUPTS
206
// this code is to signal an interrupt when interrupts are enabled (MSR[IE]=1)
207
reg     int_requested;
208
always @(interrupt or MSR[`MSR_IE])                             // if interrupt == 1, then raise a request for
209
begin                                                                                                           // clear the request based on clear_interrupt
210
  if(interrupt && MSR[`MSR_IE]) int_requested <= 1;
211
  else if(!MSR[`MSR_IE])                        int_requested <= 0;
212
end
213
 
214
reg      int_ip;                                                                                        // interrupt in progress
215
wire     can_interrupt  =                                                       // cpu can be interrupted if...
216
`ifdef ENABLE_EXCEPTION
217
                                                   ~MSR[`MSR_EIP] &                     // no Exception in Progress
218
`endif
219
`ifdef ENABLE_MSR_BIP
220 4 toni32
                                                        ~MSR[`MSR_BIP] &                        // no Break in Progress
221 3 toni32
`endif
222 4 toni32
                                                        (~int_ip | set_msr_ie); // not interrupt in progress 
223
`endif                                                                                                  // and interrupts are enabled
224 3 toni32
 
225
assign branch_taken  = branch_instr ? compare_out : 0;
226
assign pc_branch     = alu_out_internal[`A_SPACE+1:0];   // ALU calculates next instr address
227
 
228
// instr_complete is always high EXCEPT for optional MUL (alu_multicycle_instr)
229
// all other instructions currently implemented are single-cycle execution except
230
// load / store that are multicycle (controlled by dmem_done)
231
// also re/we enable are only valid if EXECUTE is not stalled
232
assign dmem_we                                                  = we_store & ~stall;
233
assign dmem_re                                                  = we_load  & ~stall;
234
 
235
assign memory_instr                                     = we_load | we_store;
236
assign memory_instr_complete            = memory_instr & dmem_done;
237
 
238 4 toni32
assign multicycle_instr                         =
239
`ifdef FSL_LINK
240
                                                                                                fsl_cmd_vld |
241
`endif
242
                                                                                                memory_instr | alu_multicycle_instr;
243
assign multicycle_instr_complete =
244
`ifdef FSL_LINK
245
                                                                                                fsl_complete |
246
`endif
247
                                                                                                memory_instr_complete | alu_multicycle_instr_complete;
248 3 toni32
 
249
assign instr_complete                           = ~multicycle_instr | multicycle_instr_complete;
250
assign we_regfile                                       = (we_load & dmem_done) | alu_multicycle_instr_complete;
251
 
252
// for CMP/CMPU
253
// use comparator output for CMPU
254
// use ALU output for CMP -- signed comparison result is a function of input signs and output sign
255
assign alu_result[31] = (alu_fns_sel == `ALU_compare_uns) ? compare_out :
256
                        (alu_fns_sel == `ALU_compare) ?  MSB_signed_compare :
257
                        alu_out_internal[31];
258
assign alu_result[30:0] = alu_out_internal[30:0];
259
 
260
always@(regA[31] or regB[31] or alu_out_internal[31])
261
begin
262
        case ({regB[31], regA[31]})     // look at signs of input numbers
263
        2'b00: MSB_signed_compare <= alu_out_internal[31];      // both inputs positive
264
        2'b01: MSB_signed_compare <= 0;                  // A is negative, B is positive => B is greater
265
        2'b10: MSB_signed_compare <= 1;                 // B is negative, A is positive => A is greater
266
        2'b11: MSB_signed_compare <= alu_out_internal[31];      // both inputs negative
267
        endcase
268
end
269
 
270
// extend PC to datapath width to store in Reg File
271
assign extended_pc[31:`A_SPACE+2] = 0;
272
assign extended_pc[`A_SPACE+1:0]  = pc_exe;
273
 
274
// Stateful logic to handle multi-cycle instructions
275
always@(posedge clock)
276
begin
277
        if(reset)
278
                begin
279
                        MSR[`MSR_C]             <= 0;            // Carry
280
`ifdef ENABLE_INTERRUPTS
281
                   int_ip                       <= 0;
282
                        MSR[`MSR_IE]    <= 1;           // Interrupt Enable
283
`endif
284
`ifdef ENABLE_EXCEPTIONS
285
                        insert_exception <= 0;
286
                        MSR[`MSR_E_Ena]  <= 1;  // Enable Exceptions
287
                        MSR[`MSR_EIP]     <= 0;  // Exception in Progress
288
`endif
289
`ifdef ENABLE_MSR_BIP
290
                   MSR[`MSR_BIP`]         <= 0;  // Break In Progress
291
`endif
292 4 toni32
`ifdef  FSL_LINK
293
                        fsl_complete    <= 0;
294
                        fsl_m_write     <= 0;
295
                        fsl_s_read              <= 0;
296
`endif
297 3 toni32
                end
298
        else if (~stall)
299
                begin
300
                        // Update MSR[BIP] due to BREAK / RTBD
301
`ifdef ENABLE_MSR_BIP
302
                        if(update_msr_bip) MSR[`MSR_BIP]        <= value_msr_bip;
303
`endif
304
`ifdef ENABLE_INTERRUPTS
305
                        if(int_requested & can_interrupt)       // interrupt requested and cpu can be interrupted?
306
                        begin
307
                           MSR[`MSR_IE] <= 0;                    // disable further interrupts
308
                                int_ip           <= 1;                  // ask DECODE to insert "brali r14,0x10" asap
309
                        end
310
                        else if(int_ip & int_dc)                // if DECODE completed the instruction insert
311
                           int_ip                <= 0;                   // finish interrupt in progress
312
                        if(set_msr_ie) MSR[`MSR_IE] <= 1;               // decode asks to enable interrupts again
313
`endif
314
`ifdef ENABLE_EXCEPTIONS
315
                        /* TODO: exceptions handling ---
316
                                        r17             <- PC
317
                                        PC                      <- 0x20
318
                                        MSR[EE]         <- 0
319
                                        MSR[EIP] <- 1
320
                                        ESR[DS] <- exception in delay slot
321
                                        ESR[EC]  <- exception specific value
322
                                        ESR[ESS] <- exception specific value
323
                                        EAR             <- exception specific value
324
                                        FSR             <- exception specific value
325
                        */
326
                        if(reset_msr_eip)                       // return from an exception handler
327
                        begin
328
                         MSR[`MSR_EIP]  <= 0;    // disable EIP flag due to rted opcode
329
                         MSR[`MSR_E_Ena]        <= 1;   // enable exceptions agains
330
                         // ESR <- 0                            // reset exception cause
331
                        end
332
`endif
333
                        `ifdef ENABLE_MSR_OPCODES
334
                        if(rS_update) MSR <= regA;      // mts instruction
335
                        `endif
336
                        // Update Carry Bit in Status Register
337
                        if ((alu_fns_sel == `ALU_add) & update_carry)
338
                                MSR[`MSR_C]     <= c_out;
339
                        if ((alu_fns_sel == `ALU_shiftR_arth) | (alu_fns_sel == `ALU_shiftR_log) |
340
                                (alu_fns_sel == `ALU_shiftR_c))
341
                                MSR[`MSR_C]     <= regA[0];
342 4 toni32
`ifdef FSL_LINK
343
                        // FSL get & put commands
344
                        // Reset control signals after write / read
345
                        if ((fsl_cmd_vld & fsl_complete) | ~fsl_cmd_vld)
346
                                begin
347
                                        fsl_s_read              <= 0;
348
                                        fsl_complete    <= 0;
349
                                        fsl_m_write             <= 0;
350
                                end
351
                        else if (fsl_cmd_vld & ~fsl_get & ~fsl_blocking) // nonblocking put
352
                                begin
353
                                        fsl_complete    <= 1;
354
                                        MSR[`MSR_C]             <= fsl_m_full;          //**CHECK**
355
                                        if (~fsl_m_full)
356
                                                begin
357
                                                        fsl_m_write     <= 1;
358
                                                        fsl_m_control   <= fsl_control;
359
                                                end
360
                                end
361
                        else if (fsl_cmd_vld & fsl_get & ~fsl_blocking) // nonblocking get
362
                                begin
363
                                        fsl_complete    <= 1;
364
                                        fsl_s_read      <= 1;
365
                                        MSR[`MSR_C] <= ~fsl_s_exists;           //**CHECK**
366
                                        if (fsl_s_exists)
367
                                                we_load_dly <= 1;
368
                                        if (fsl_s_control == fsl_control)
369
                                                MSR[`MSR_FSL_Err]       <= 0;    // MSR[4] = FSL_Error bit
370
                                        else
371
                                                MSR[`MSR_FSL_Err]       <= 1;
372
                                end
373
                        else if (fsl_cmd_vld & ~fsl_get & ~fsl_m_full & fsl_blocking) // blocking put
374
                                begin
375
                                        fsl_complete    <= 1;
376
                                        fsl_m_write     <= 1;
377
                                        fsl_m_control   <= fsl_control;
378
                                end
379
                        else if (fsl_cmd_vld & fsl_get & fsl_s_exists & fsl_blocking) // blocking get
380
                                begin
381
                                        fsl_complete    <= 1;
382
                                        we_load_dly     <= 1;
383
                                        fsl_s_read      <= 1;
384
                                        if (fsl_s_control == fsl_control)
385
                                                MSR[`MSR_FSL_Err]       <= 0;
386
                                        else
387
                                                MSR[`MSR_FSL_Err]       <= 1;
388
                                end
389
`endif // End FSL extensions                            
390 3 toni32
`ifdef DEBUG_EXECUTE
391
                $display("EXECUTE: pc_exe=%x", pc_exe);
392
`endif
393
                end // end elseif (~stall)
394
end // always@
395
 
396
/**************************
397
 * Module input selectors *
398
 **************************/
399
always@(
400
`ifdef ENABLE_MSR_OPCODES
401
        MSR or
402
`endif
403
        alu_inputA_sel or extended_pc or regA
404
)
405
begin
406
        case(alu_inputA_sel)
407
        `aluA_ra:               alu_a_input <= regA;
408
        `aluA_ra_bar:   alu_a_input <= ~regA;
409
        `aluA_pc:               alu_a_input <= extended_pc;
410
        `aluA_zero:             alu_a_input <= 0;
411
`ifdef ENABLE_MSR_OPCODES
412
        `aluA_msr:              alu_a_input     <= MSR; // msr instruction feed to regfile via ALU
413
`endif
414
        endcase
415
end // always @ ALU_input_A
416
 
417
always@(alu_inputB_sel or immediate or regB)
418
begin
419
        case(alu_inputB_sel)
420
        `aluB_rb:               alu_b_input <= regB;
421
        `aluB_imm:              alu_b_input <= immediate;
422
        `aluB_rb_bar:   alu_b_input <= ~regB;
423
        `aluB_imm_bar:  alu_b_input <= ~immediate;
424
        endcase
425
end // always @ ALU_input_B
426
 
427
always@(alu_inputC_sel or MSR)
428
begin
429
        case(alu_inputC_sel)
430
        `aluC_zero:             alu_c_input <= 1'b0;
431
        `aluC_one:              alu_c_input <= 1'b1;
432
        `aluC_carry:    alu_c_input <= MSR[`MSR_C];
433
        default:
434
                begin   // for simulation
435
                        $display("ERROR! Illegal ALU Input Selection! PC %x", pc_exe);
436
                        alu_c_input <= 1'b0;
437
                end
438
        endcase
439
end // always @ ALU_input_C
440
 
441
// Instantiate ALU and comparator
442
openfire_alu    ALU0 (
443
        .clock(clock),
444
        .reset(reset),
445
        .stall(stall),
446
        .a(alu_a_input),
447
        .b(alu_b_input),
448
        .c_in(alu_c_input),
449
        .fns(alu_fns_sel),
450
        .alu_result(alu_out_internal),
451
        .c_out(c_out),
452
        .alu_multicycle_instr(alu_multicycle_instr),
453
        .dmem_addr(dmem_addr),
454
        .alu_multicycle_instr_complete(alu_multicycle_instr_complete)
455
);
456
// comparator used only for branches (and optional CMPU instruction)
457
// DECODE unit forces COMPARE output high for unconditional branchs by selecting a 1 output
458
//      with comparator_fns_sel
459
openfire_compare        CMP0 (
460
        .in0(regA),
461
        .in1(regB),
462
        .out(compare_out),
463
        .fns(comparator_fns_sel)
464
);
465
 
466
endmodule

powered by: WebSVN 2.1.0

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