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

Subversion Repositories openfire2

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

Go to most recent revision | 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
        clock, reset, stall,                                                                                    // top level
79
        immediate, pc_exe, alu_inputA_sel, alu_inputB_sel, // inputs
80
        alu_inputC_sel, alu_fns_sel, comparator_fns_sel,
81
        we_load, we_store, regA,
82
        regB, regD, update_carry, branch_instr,
83
        alu_result, pc_branch, branch_taken,                                    // outputs
84
        we_regfile, dmem_addr,
85
        dmem_data_out, instr_complete, dmem_done,
86
        dmem_we, dmem_re
87
);
88
 
89
// From top level -- all active high unless otherwise noted
90
input           stall;
91
input           reset;
92
input           clock;
93
 
94
// From DECODE module
95
input   [31:0]   immediate;
96
input   [`A_SPACE+1:0]   pc_exe;                 // pc for use by EXECUTE
97
input   [2:0]            alu_inputA_sel;
98
input   [1:0]            alu_inputB_sel;
99
input   [1:0]            alu_inputC_sel;
100
input   [3:0]            alu_fns_sel;
101
input   [2:0]            comparator_fns_sel;
102
input                   we_load;                                        // write_en for regfile on Load
103
input                           we_store;                               // we on DMEM on Store
104
input                           update_carry;
105
input                           branch_instr;
106
input                           dmem_done;
107
output                  dmem_re;
108
output                  dmem_we;
109
`ifdef ENABLE_MSR_BIP
110
input                           update_msr_bip;
111
input                           value_msr_bip;
112
`endif
113
`ifdef ENABLE_INTERRUPTS
114
input                           interrupt;
115
output                  int_ip;
116
input                      int_dc;
117
input                      set_msr_ie;
118
`endif
119
`ifdef ENABLE_MSR_OPCODES
120
input                           rS_update;
121
`endif
122
`ifdef ENABLE_OPCODE_EXCEPTION
123
input                           opcode_exception;
124
`endif
125
`ifdef ENABLE_EXCEPTIONS
126
input                           reset_msr_eip;
127
output                  insert_exception;
128
`endif
129
`ifdef ENABLE_ALIGNMENT_EXCEPTION
130
input                           dmem_alignment_exception;
131
`endif
132
 
133
// From REGFILE
134
input   [31:0]   regA;
135
input   [31:0]   regB;
136
input   [31:0]   regD;
137
 
138
output  [31:0]   alu_result;
139
output  [`A_SPACE+1:0]   pc_branch;
140
output                          branch_taken;
141
output                          we_regfile;                     // we for load and alu
142
output  [31:0]   dmem_addr;
143
output  [31:0]   dmem_data_out;
144
output                          instr_complete; // status of execution, active high
145
 
146
// register all outputs EXCEPT:
147
//      - branch_taken and pc_branch -- registered in FETCH
148
//      - alu_result -- REGFILE registers
149
//      - dmem_addr -- DMEM registers
150
//      - instr_complete -- needed before rise of clock by PIPLINE_CTRL
151
assign dmem_data_out = regD;
152
 
153
// internal registers
154
reg     [31:0]   MSR;                            // **TODO** Working: C, BIP, IE
155
reg     [31:0]   alu_a_input;
156
reg     [31:0]   alu_b_input;
157
reg                             alu_c_input;
158
reg                             MSB_signed_compare;
159
 
160
wire                    alu_multicycle_instr;
161
wire                    alu_multicycle_instr_complete;
162
wire                    multicycle_instr;
163
wire                    multicycle_instr_complete;
164
wire                    c_out;
165
wire                    compare_out;
166
wire [31:0]      alu_out_internal;
167
wire [31:0]      extended_pc;    // PC with leading zeros addded
168
 
169
`ifdef ENABLE_EXCEPTIONS
170
reg                     insert_exception;                       // to ask DECODE to insert "brali r17,0x20"
171
wire                    exception =                             // 1 if any exception happened
172
`ifdef ENABLE_ALIGNMENT_EXCEPTION
173
                                                                dmem_alignment_exception |
174
`endif
175
`ifdef ENABLE_OPCODE_EXCEPTION
176
                                                                opcode_exception |
177
`endif
178
                                                                0;
179
`endif
180
 
181
`ifdef ENABLE_INTERRUPTS
182
// this code is to signal an interrupt when interrupts are enabled (MSR[IE]=1)
183
reg     int_requested;
184
always @(interrupt or MSR[`MSR_IE])                             // if interrupt == 1, then raise a request for
185
begin                                                                                                           // clear the request based on clear_interrupt
186
  if(interrupt && MSR[`MSR_IE]) int_requested <= 1;
187
  else if(!MSR[`MSR_IE])                        int_requested <= 0;
188
end
189
 
190
reg      int_ip;                                                                                        // interrupt in progress
191
wire     can_interrupt  =                                                       // cpu can be interrupted if...
192
`ifdef ENABLE_EXCEPTION
193
                                                   ~MSR[`MSR_EIP] &                     // no Exception in Progress
194
`endif
195
`ifdef ENABLE_MSR_BIP
196
                                                        ~MSR[`MSR_BIP] & (              // no Break in Progress
197
`endif
198
                                                         ~int_ip | set_msr_ie   // not interrupt in progress 
199
`ifdef ENABLE_MSR_BIP                                                           // and interrupts are enabled
200
                                                         )
201
`endif
202
                                                        ;
203
`endif
204
 
205
assign branch_taken  = branch_instr ? compare_out : 0;
206
assign pc_branch     = alu_out_internal[`A_SPACE+1:0];   // ALU calculates next instr address
207
 
208
// instr_complete is always high EXCEPT for optional MUL (alu_multicycle_instr)
209
// all other instructions currently implemented are single-cycle execution except
210
// load / store that are multicycle (controlled by dmem_done)
211
// also re/we enable are only valid if EXECUTE is not stalled
212
assign dmem_we                                                  = we_store & ~stall;
213
assign dmem_re                                                  = we_load  & ~stall;
214
 
215
assign memory_instr                                     = we_load | we_store;
216
assign memory_instr_complete            = memory_instr & dmem_done;
217
 
218
assign multicycle_instr                         = memory_instr | alu_multicycle_instr;
219
assign multicycle_instr_complete = memory_instr_complete | alu_multicycle_instr_complete;
220
 
221
assign instr_complete                           = ~multicycle_instr | multicycle_instr_complete;
222
assign we_regfile                                       = (we_load & dmem_done) | alu_multicycle_instr_complete;
223
 
224
// for CMP/CMPU
225
// use comparator output for CMPU
226
// use ALU output for CMP -- signed comparison result is a function of input signs and output sign
227
assign alu_result[31] = (alu_fns_sel == `ALU_compare_uns) ? compare_out :
228
                        (alu_fns_sel == `ALU_compare) ?  MSB_signed_compare :
229
                        alu_out_internal[31];
230
assign alu_result[30:0] = alu_out_internal[30:0];
231
 
232
always@(regA[31] or regB[31] or alu_out_internal[31])
233
begin
234
        case ({regB[31], regA[31]})     // look at signs of input numbers
235
        2'b00: MSB_signed_compare <= alu_out_internal[31];      // both inputs positive
236
        2'b01: MSB_signed_compare <= 0;                  // A is negative, B is positive => B is greater
237
        2'b10: MSB_signed_compare <= 1;                 // B is negative, A is positive => A is greater
238
        2'b11: MSB_signed_compare <= alu_out_internal[31];      // both inputs negative
239
        endcase
240
end
241
 
242
// extend PC to datapath width to store in Reg File
243
assign extended_pc[31:`A_SPACE+2] = 0;
244
assign extended_pc[`A_SPACE+1:0]  = pc_exe;
245
 
246
// Stateful logic to handle multi-cycle instructions
247
always@(posedge clock)
248
begin
249
        if(reset)
250
                begin
251
                        MSR[`MSR_C]             <= 0;            // Carry
252
`ifdef ENABLE_INTERRUPTS
253
                   int_ip                       <= 0;
254
                        MSR[`MSR_IE]    <= 1;           // Interrupt Enable
255
`endif
256
`ifdef ENABLE_EXCEPTIONS
257
                        insert_exception <= 0;
258
                        MSR[`MSR_E_Ena]  <= 1;  // Enable Exceptions
259
                        MSR[`MSR_EIP]     <= 0;  // Exception in Progress
260
`endif
261
`ifdef ENABLE_MSR_BIP
262
                   MSR[`MSR_BIP`]         <= 0;  // Break In Progress
263
`endif
264
                end
265
        else if (~stall)
266
                begin
267
                        // Update MSR[BIP] due to BREAK / RTBD
268
`ifdef ENABLE_MSR_BIP
269
                        if(update_msr_bip) MSR[`MSR_BIP]        <= value_msr_bip;
270
`endif
271
`ifdef ENABLE_INTERRUPTS
272
                        if(int_requested & can_interrupt)       // interrupt requested and cpu can be interrupted?
273
                        begin
274
                           MSR[`MSR_IE] <= 0;                    // disable further interrupts
275
                                int_ip           <= 1;                  // ask DECODE to insert "brali r14,0x10" asap
276
                        end
277
                        else if(int_ip & int_dc)                // if DECODE completed the instruction insert
278
                           int_ip                <= 0;                   // finish interrupt in progress
279
                        if(set_msr_ie) MSR[`MSR_IE] <= 1;               // decode asks to enable interrupts again
280
`endif
281
`ifdef ENABLE_EXCEPTIONS
282
                        /* TODO: exceptions handling ---
283
                                        r17             <- PC
284
                                        PC                      <- 0x20
285
                                        MSR[EE]         <- 0
286
                                        MSR[EIP] <- 1
287
                                        ESR[DS] <- exception in delay slot
288
                                        ESR[EC]  <- exception specific value
289
                                        ESR[ESS] <- exception specific value
290
                                        EAR             <- exception specific value
291
                                        FSR             <- exception specific value
292
                        */
293
                        if(reset_msr_eip)                       // return from an exception handler
294
                        begin
295
                         MSR[`MSR_EIP]  <= 0;    // disable EIP flag due to rted opcode
296
                         MSR[`MSR_E_Ena]        <= 1;   // enable exceptions agains
297
                         // ESR <- 0                            // reset exception cause
298
                        end
299
`endif
300
                        `ifdef ENABLE_MSR_OPCODES
301
                        if(rS_update) MSR <= regA;      // mts instruction
302
                        `endif
303
                        // Update Carry Bit in Status Register
304
                        if ((alu_fns_sel == `ALU_add) & update_carry)
305
                                MSR[`MSR_C]     <= c_out;
306
                        if ((alu_fns_sel == `ALU_shiftR_arth) | (alu_fns_sel == `ALU_shiftR_log) |
307
                                (alu_fns_sel == `ALU_shiftR_c))
308
                                MSR[`MSR_C]     <= regA[0];
309
 
310
`ifdef DEBUG_EXECUTE
311
                $display("EXECUTE: pc_exe=%x", pc_exe);
312
`endif
313
                end // end elseif (~stall)
314
end // always@
315
 
316
/**************************
317
 * Module input selectors *
318
 **************************/
319
always@(
320
`ifdef ENABLE_MSR_OPCODES
321
        MSR or
322
`endif
323
        alu_inputA_sel or extended_pc or regA
324
)
325
begin
326
        case(alu_inputA_sel)
327
        `aluA_ra:               alu_a_input <= regA;
328
        `aluA_ra_bar:   alu_a_input <= ~regA;
329
        `aluA_pc:               alu_a_input <= extended_pc;
330
        `aluA_zero:             alu_a_input <= 0;
331
`ifdef ENABLE_MSR_OPCODES
332
        `aluA_msr:              alu_a_input     <= MSR; // msr instruction feed to regfile via ALU
333
`endif
334
        endcase
335
end // always @ ALU_input_A
336
 
337
always@(alu_inputB_sel or immediate or regB)
338
begin
339
        case(alu_inputB_sel)
340
        `aluB_rb:               alu_b_input <= regB;
341
        `aluB_imm:              alu_b_input <= immediate;
342
        `aluB_rb_bar:   alu_b_input <= ~regB;
343
        `aluB_imm_bar:  alu_b_input <= ~immediate;
344
        endcase
345
end // always @ ALU_input_B
346
 
347
always@(alu_inputC_sel or MSR)
348
begin
349
        case(alu_inputC_sel)
350
        `aluC_zero:             alu_c_input <= 1'b0;
351
        `aluC_one:              alu_c_input <= 1'b1;
352
        `aluC_carry:    alu_c_input <= MSR[`MSR_C];
353
        default:
354
                begin   // for simulation
355
                        $display("ERROR! Illegal ALU Input Selection! PC %x", pc_exe);
356
                        alu_c_input <= 1'b0;
357
                end
358
        endcase
359
end // always @ ALU_input_C
360
 
361
// Instantiate ALU and comparator
362
openfire_alu    ALU0 (
363
        .clock(clock),
364
        .reset(reset),
365
        .stall(stall),
366
        .a(alu_a_input),
367
        .b(alu_b_input),
368
        .c_in(alu_c_input),
369
        .fns(alu_fns_sel),
370
        .alu_result(alu_out_internal),
371
        .c_out(c_out),
372
        .alu_multicycle_instr(alu_multicycle_instr),
373
        .dmem_addr(dmem_addr),
374
        .alu_multicycle_instr_complete(alu_multicycle_instr_complete)
375
);
376
// comparator used only for branches (and optional CMPU instruction)
377
// DECODE unit forces COMPARE output high for unconditional branchs by selecting a 1 output
378
//      with comparator_fns_sel
379
openfire_compare        CMP0 (
380
        .in0(regA),
381
        .in1(regB),
382
        .out(compare_out),
383
        .fns(comparator_fns_sel)
384
);
385
 
386
endmodule

powered by: WebSVN 2.1.0

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