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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_alu_main.v] - Blame information for rev 43

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 Revanth
// ---------------------------------------------------------------------------
2
// --                                                                       --
3
// --                   (C) 2016-2018 Revanth Kamaraj.                      --
4
// --                                                                       -- 
5
// -- ------------------------------------------------------------------------
6
// --                                                                       --
7
// -- This program is free software; you can redistribute it and/or         --
8
// -- modify it under the terms of the GNU General Public License           --
9
// -- as published by the Free Software Foundation; either version 2        --
10
// -- of the License, or (at your option) any later version.                --
11
// --                                                                       --
12
// -- This program is distributed in the hope that it will be useful,       --
13
// -- but WITHOUT ANY WARRANTY; without even the implied warranty of        --
14
// -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         --
15
// -- GNU General Public License for more details.                          --
16
// --                                                                       --
17
// -- You should have received a copy of the GNU General Public License     --
18
// -- along with this program; if not, write to the Free Software           --
19
// -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         --
20
// -- 02110-1301, USA.                                                      --
21
// --                                                                       --
22
// ---------------------------------------------------------------------------
23
// --                                                                       --
24
// -- This is the main ZAP arithmetic and logic unit. Apart from shfits     --
25
// -- and multiplies, all other arithmetic and logic is performed here.     --
26
// -- Also data memory access signals are generated at the end of the clock --
27
// -- cycle.  Instructions that fail condition checks are invalidated here. --
28
// --                                                                       --
29
// ---------------------------------------------------------------------------
30
 
31
`default_nettype none
32
 
33
module zap_alu_main #(
34
 
35
        parameter [31:0] PHY_REGS  = 32'd46, // Number of physical registers.
36
        parameter [31:0] SHIFT_OPS = 32'd5,  // Number of shift operations.
37
        parameter [31:0] ALU_OPS   = 32'd32, // Number of arithmetic operations.
38
        parameter [31:0] FLAG_WDT  = 32'd32  // Width of active CPSR.
39
)
40
(
41
        // ------------------------------------------------------------------
42
        // Decompile Interface. Only for debug.
43
        // ------------------------------------------------------------------
44
 
45
        input wire      [64*8-1:0]              i_decompile,
46
        output reg      [64*8-1:0]              o_decompile,
47
 
48
        // ------------------------------------------------------------------
49
        // ALU Hijack Interface. For Thumb Data Abort address calculation.
50
        // ------------------------------------------------------------------
51
 
52
        input wire                              i_hijack,                    // Enable hijack.
53
        input wire      [31:0]                  i_hijack_op1,                // Hijack operand 1.
54
        input wire      [31:0]                  i_hijack_op2,                // Hijack operand 2.
55
        input wire                              i_hijack_cin,                // Hijack carry in.
56
        output wire     [31:0]                  o_hijack_sum,                // Hijack sum out.
57
 
58
        // ------------------------------------------------------------------
59
        // Clock and reset
60
        // ------------------------------------------------------------------
61
 
62
        input wire                              i_clk,                       // Clock.
63
        input wire                              i_reset,                     // sync active high reset.
64
 
65
        // -------------------------------------------------------------------
66
        // Clear and Stall signals.
67
        // -------------------------------------------------------------------
68
 
69
        input wire                              i_clear_from_writeback,      // Clear unit.
70
        input wire                              i_data_stall,                // DCACHE stall.
71
 
72
        // -------------------------------------------------------------------
73
        // Misc. signals
74
        // -------------------------------------------------------------------
75
 
76
        input wire  [31:0]                      i_cpsr_nxt,                  // From passive CPSR.
77
        input wire                              i_switch_ff,                 // Switch state.
78
        input wire   [1:0]                      i_taken_ff,                  // Branch prediction.
79
        input wire   [31:0]                     i_pc_ff,                     // Addr of instr.
80
        input wire                              i_nozero_ff,                 // Zero flag will not be set.
81
 
82
        // ------------------------------------------------------------------
83
        // Source values
84
        // ------------------------------------------------------------------
85
 
86
        input wire  [31:0]                      i_alu_source_value_ff,       // ALU source value.
87
        input wire  [31:0]                      i_shifted_source_value_ff,   // Shifted source value.
88
        input wire                              i_shift_carry_ff,            // Carry from shifter.        
89
        input wire  [31:0]                      i_pc_plus_8_ff,              // PC + 8 value.
90
 
91
        // ------------------------------------------------------------------
92
        // Interrupt Tagging
93
        // ------------------------------------------------------------------
94
 
95
        input wire                              i_abt_ff,                    // ABT flagged.
96
        input wire                              i_irq_ff,                    // IRQ flagged.
97
        input wire                              i_fiq_ff,                    // FIQ flagged.
98
        input wire                              i_swi_ff,                    // SWI flagged.
99
        input wire                              i_und_ff,                    // Flagged undefined instructions.
100
        input wire                              i_data_mem_fault,            // Flagged Data abort.
101
 
102
        // ------------------------------------------------------------------
103
        // Memory Access Related
104
        // ------------------------------------------------------------------
105
 
106
        input wire  [31:0]                      i_mem_srcdest_value_ff,           // Value to store. 
107
        input wire  [zap_clog2(PHY_REGS)-1:0]   i_mem_srcdest_index_ff,           // LD/ST Memory data register index.    
108
        input wire                              i_mem_load_ff,                    // LD/ST Memory load.
109
        input wire                              i_mem_store_ff,                   // LD/ST Memory store.                    
110
        input wire                              i_mem_pre_index_ff,               // LD/ST Pre/Post index.
111
        input wire                              i_mem_unsigned_byte_enable_ff,    // LD/ST uint8_t  data type.
112
        input wire                              i_mem_signed_byte_enable_ff,      // LD/ST int8_t   data type.
113
        input wire                              i_mem_signed_halfword_enable_ff,  // LD/ST int16_t data type.
114
        input wire                              i_mem_unsigned_halfword_enable_ff,// LD/ST uint16_t  data type.
115
        input wire                              i_mem_translate_ff,               // LD/ST Force user view of memory.
116
        input wire                              i_force32align_ff,                // Force address alignment to 32-bit.
117
 
118
        // -------------------------------------------------------------------
119
        // ALU controls
120
        // -------------------------------------------------------------------
121
 
122
        input wire  [3:0]                       i_condition_code_ff,            // CC associated with instr.
123
        input wire  [zap_clog2(PHY_REGS)-1:0]   i_destination_index_ff,         // Target register index.
124
        input wire  [zap_clog2(ALU_OPS)-1:0]    i_alu_operation_ff,             // Operation to perform.
125
        input wire                              i_flag_update_ff,               // Update flags if 1.
126
 
127
        // -----------------------------------------------------------------
128
        // ALU result
129
        // -----------------------------------------------------------------
130
 
131
        output reg [31:0]                       o_alu_result_nxt,           // For feedback. ALU result _nxt version.
132
        output reg [31:0]                       o_alu_result_ff,            // ALU result flopped version.
133
        output reg                              o_dav_ff,                   // Instruction valid.
134
        output reg                              o_dav_nxt,                  // Instruction valid _nxt version.
135
        output reg [FLAG_WDT-1:0]               o_flags_ff,                 // Output flags (CPSR).
136
        output reg [FLAG_WDT-1:0]               o_flags_nxt,                // CPSR next.
137
        output reg [zap_clog2(PHY_REGS)-1:0]    o_destination_index_ff,     // Destination register index.
138
 
139
        // -----------------------------------------------------------------
140
        // Interrupt Tagging
141
        // -----------------------------------------------------------------
142
 
143
        output reg                              o_abt_ff,                   // Instruction abort flagged.
144
        output reg                              o_irq_ff,                   // IRQ flagged.
145
        output reg                              o_fiq_ff,                   // FIQ flagged.
146
        output reg                              o_swi_ff,                   // SWI flagged.
147
        output reg                              o_und_ff,                   // Flagged undefined instructions
148
 
149
        // -----------------------------------------------------------------
150
        // Jump Controls, BP Confirm, PC + 8
151
        // -----------------------------------------------------------------
152
 
153
        output reg [31:0]                       o_pc_plus_8_ff,             // Instr address + 8.
154
        output reg                              o_clear_from_alu,           // ALU commands a pipeline clear and a predictor correction.
155
        output reg [31:0]                       o_pc_from_alu,              // Corresponding address to go to is provided here.
156
        output reg                              o_confirm_from_alu,         // Tell branch predictor it was correct.
157
 
158
        // ----------------------------------------------------------------
159
        // Memory access related
160
        // ----------------------------------------------------------------
161
 
162
        output reg  [zap_clog2(PHY_REGS)-1:0]   o_mem_srcdest_index_ff,  // LD/ST data register.
163
        output reg                              o_mem_load_ff,              // LD/ST load indicator.
164
        output reg                              o_mem_store_ff,             // LD/ST store indicator.
165
        output reg [31:0]                       o_mem_address_ff,           // LD/ST address to access.
166
        output reg                              o_mem_unsigned_byte_enable_ff,     // uint8_t
167
        output reg                              o_mem_signed_byte_enable_ff,       // int8_t
168
        output reg                              o_mem_signed_halfword_enable_ff,   // int16_t
169
        output reg                              o_mem_unsigned_halfword_enable_ff, // uint16_t
170
        output reg [31:0]                       o_mem_srcdest_value_ff,     // LD/ST value to store.
171
        output reg                              o_mem_translate_ff,         // LD/ST force user view of memory.
172
        output reg [3:0]                        o_ben_ff,                   // LD/ST byte enables (only for STore instructions).
173
        output reg  [31:0]                      o_address_nxt,              // D pin of address register to drive TAG RAMs.
174
 
175
        // -------------------------------------------------------------
176
        // Wishbone signal outputs.
177
        // -------------------------------------------------------------
178
 
179
        output reg                              o_data_wb_we_nxt,
180
        output reg                              o_data_wb_cyc_nxt,
181
        output reg                              o_data_wb_stb_nxt,
182
        output reg [31:0]                       o_data_wb_dat_nxt,
183
        output reg [3:0]                        o_data_wb_sel_nxt,
184
        output reg                              o_data_wb_we_ff,
185
        output reg                              o_data_wb_cyc_ff,
186
        output reg                              o_data_wb_stb_ff,
187
        output reg [31:0]                       o_data_wb_dat_ff,
188
        output reg [3:0]                        o_data_wb_sel_ff
189
);
190
 
191
// ----------------------------------------------------------------------------
192 43 Revanth
// Includes
193
// ----------------------------------------------------------------------------
194 26 Revanth
 
195
`include "zap_defines.vh"
196
`include "zap_localparams.vh"
197
`include "zap_functions.vh"
198
 
199 43 Revanth
// -----------------------------------------------------------------------------
200
// Localparams
201
// -----------------------------------------------------------------------------
202 26 Revanth
 
203
/*
204 43 Revanth
 *  These override global N,Z,C,V definitions which are on CPSR. These params
205
 *  are localized over the 4-bit flag structure.
206
 */
207 26 Revanth
localparam [1:0] _N  = 2'd3;
208
localparam [1:0] _Z  = 2'd2;
209
localparam [1:0] _C  = 2'd1;
210
localparam [1:0] _V  = 2'd0;
211
 
212
// Branch status.
213
localparam [1:0] SNT = 2'd0;
214
localparam [1:0] WNT = 2'd1;
215
localparam [1:0] WT  = 2'd2;
216
localparam [1:0] ST  = 2'd3;
217
 
218 43 Revanth
// ------------------------------------------------------------------------------
219
// Variables
220
// ------------------------------------------------------------------------------
221
 
222
// Memory srcdest value (i.e., data)
223
wire [31:0]                     mem_srcdest_value_nxt;
224
 
225
// Byte enable generator.
226
wire [3:0]                      ben_nxt;
227
 
228
// Address about to be output. Used to drive tag RAMs etc.
229
reg [31:0]                      mem_address_nxt;
230
 
231 26 Revanth
/*
232
   Sleep flop. When 1 unit sleeps i.e., does not produce any output except on
233
   the first clock cycle where LR is calculated using the ALU.
234
*/
235
reg                             sleep_ff, sleep_nxt;
236
 
237
/*
238
   CPSR (Active CPSR). The active CPSR is from the where the CPU flags are
239
   read out and the mode also is. Mode changes via manual writes to CPSR
240
   are first written to the active and they then propagate to the passive CPSR
241
   in the writeback stage. This reduces the pipeline flush penalty.
242
*/
243
reg [31:0]                      flags_ff, flags_nxt;
244
 
245
reg [31:0]                      rm, rn; // RM = shifted source value Rn for
246
                                        // non shifted source value. These are
247
                                        // values and not indices.
248
 
249
 
250 37 Revanth
reg [5:0]                       clz_rm; // Count leading zeros in Rm.
251 26 Revanth
 
252 43 Revanth
// Destination index about to be output.
253
reg [zap_clog2(PHY_REGS)-1:0]      o_destination_index_nxt;
254
 
255
// 1s complement of Rm and Rn.
256
wire [31:0]                     not_rm = ~rm;
257
wire [31:0]                     not_rn = ~rn;
258
 
259
// Wires which connect to an adder.
260
reg [31:0]                      op1, op2;
261
reg                             cin;
262
 
263
// 32-bit adder with carry input and carry output.
264
wire [32:0]                     sum = {1'd0, op1} + {1'd0, op2} + {32'd0, cin};
265
 
266
reg [31:0]                      tmp_flags, tmp_sum;
267
 
268
// Opcode.
269
wire [zap_clog2(ALU_OPS)-1:0]   opcode = i_alu_operation_ff;
270
 
271
// -------------------------------------------------------------------------------
272
// Assigns
273
// -------------------------------------------------------------------------------
274
 
275
/*
276
   For memory stores, we must generate correct byte enables. This is done
277
   by examining access type inputs. For loads, always 1111 is generated.
278
   If there is neither a load or a store, the old value is preserved.
279
*/
280
assign ben_nxt =                generate_ben (
281
                                                 i_mem_unsigned_byte_enable_ff,
282
                                                 i_mem_signed_byte_enable_ff,
283
                                                 i_mem_unsigned_halfword_enable_ff,
284
                                                 i_mem_unsigned_halfword_enable_ff,
285
                                                 mem_address_nxt);
286
 
287
assign mem_srcdest_value_nxt =  duplicate (
288
                                                 i_mem_unsigned_byte_enable_ff,
289
                                                 i_mem_signed_byte_enable_ff,
290
                                                 i_mem_unsigned_halfword_enable_ff,
291
                                                 i_mem_unsigned_halfword_enable_ff,
292
                                                 i_mem_srcdest_value_ff );
293
 
294
/*
295
   Hijack interface. Data aborts use the hijack interface to find return
296
   address. The writeback drives the ALU inputs to find the final output.
297
*/
298
assign o_hijack_sum = sum;
299
 
300
// -------------------------------------------------------------------------------
301
// CLZ logic.
302
// -------------------------------------------------------------------------------
303
 
304 37 Revanth
always @* // CLZ implementation.
305
begin
306
        casez(rm)
307
        32'b1???????????????????????????????:   clz_rm = 6'd00;
308
        32'b01??????????????????????????????:   clz_rm = 6'd01;
309
        32'b001?????????????????????????????:   clz_rm = 6'd02;
310
        32'b0001????????????????????????????:   clz_rm = 6'd03;
311
        32'b00001???????????????????????????:   clz_rm = 6'd04;
312
        32'b000001??????????????????????????:   clz_rm = 6'd05;
313
        32'b0000001?????????????????????????:   clz_rm = 6'd06;
314
        32'b00000001????????????????????????:   clz_rm = 6'd07;
315
        32'b000000001???????????????????????:   clz_rm = 6'd08;
316
        32'b0000000001??????????????????????:   clz_rm = 6'd09;
317
        32'b00000000001?????????????????????:   clz_rm = 6'd10;
318
        32'b000000000001????????????????????:   clz_rm = 6'd11;
319
        32'b0000000000001???????????????????:   clz_rm = 6'd12;
320
        32'b00000000000001??????????????????:   clz_rm = 6'd13;
321
        32'b000000000000001?????????????????:   clz_rm = 6'd14;
322
        32'b0000000000000001????????????????:   clz_rm = 6'd15;
323
        32'b00000000000000001???????????????:   clz_rm = 6'd16;
324
        32'b000000000000000001??????????????:   clz_rm = 6'd17;
325
        32'b0000000000000000001?????????????:   clz_rm = 6'd18;
326
        32'b00000000000000000001????????????:   clz_rm = 6'd19;
327
        32'b000000000000000000001???????????:   clz_rm = 6'd20;
328
        32'b0000000000000000000001??????????:   clz_rm = 6'd21;
329
        32'b00000000000000000000001?????????:   clz_rm = 6'd22;
330
        32'b000000000000000000000001????????:   clz_rm = 6'd23;
331
        32'b0000000000000000000000001???????:   clz_rm = 6'd24;
332
        32'b00000000000000000000000001??????:   clz_rm = 6'd25;
333
        32'b000000000000000000000000001?????:   clz_rm = 6'd26;
334
        32'b0000000000000000000000000001????:   clz_rm = 6'd27;
335
        32'b00000000000000000000000000001???:   clz_rm = 6'd28;
336
        32'b000000000000000000000000000001??:   clz_rm = 6'd29;
337
        32'b0000000000000000000000000000001?:   clz_rm = 6'd30;
338
        32'b00000000000000000000000000000001:   clz_rm = 6'd31;
339
        default:                                clz_rm = 6'd32; // All zeros.
340
        endcase
341
end
342
 
343 26 Revanth
// ----------------------------------------------------------------------------
344 43 Revanth
// Aliases
345
// ----------------------------------------------------------------------------
346 26 Revanth
 
347
always @*
348
begin
349
        rm          = i_shifted_source_value_ff;
350
        rn          = i_alu_source_value_ff;
351
        o_flags_ff  = flags_ff;
352
        o_flags_nxt = flags_nxt;
353
end
354
 
355 43 Revanth
// -----------------------------------------------------------------------------
356 26 Revanth
// Sequential logic.
357 43 Revanth
// -----------------------------------------------------------------------------
358
 
359 26 Revanth
always @ (posedge i_clk)
360
begin
361
        if ( i_reset )
362
        begin
363
                // On reset, processor enters supervisory mode with interrupts
364
                // masked.
365
                clear ( {1'd1,1'd1,1'd0,SVC} );
366
        end
367
        else if ( i_clear_from_writeback )
368
        begin
369
                // Clear but take CPSR from writeback.
370
                clear ( i_cpsr_nxt );
371
        end
372
        else if ( i_data_stall )
373
        begin
374
                // Preserve values.
375
        end
376
        else if ( i_data_mem_fault || sleep_ff )
377
        begin
378
                // Clear and preserve flags. Keep sleeping.
379
                clear(flags_ff);
380
                sleep_ff                         <= 1'd1;
381
                o_dav_ff                         <= 1'd0; // Don't give any output.
382
        end
383
        else
384
        begin
385
                // Clock out all flops normally.
386
 
387
                o_alu_result_ff                  <= o_alu_result_nxt;
388
                o_dav_ff                         <= o_dav_nxt;
389
                o_pc_plus_8_ff                   <= i_pc_plus_8_ff;
390
                o_destination_index_ff           <= o_destination_index_nxt;
391
                flags_ff                         <= flags_nxt;
392
                o_abt_ff                         <= i_abt_ff;
393
                o_irq_ff                         <= i_irq_ff;
394
                o_fiq_ff                         <= i_fiq_ff;
395
                o_swi_ff                         <= i_swi_ff;
396
                o_mem_srcdest_index_ff           <= i_mem_srcdest_index_ff;
397
                o_mem_srcdest_index_ff           <= i_mem_srcdest_index_ff;
398
 
399
                // Load or store must come up only if an actual LDR/STR is
400
                // detected.
401
                o_mem_load_ff                    <= o_dav_nxt ? i_mem_load_ff : 1'd0;
402
                o_mem_store_ff                   <= o_dav_nxt ? i_mem_store_ff: 1'd0;
403
 
404
                o_mem_unsigned_byte_enable_ff    <= i_mem_unsigned_byte_enable_ff;
405
                o_mem_signed_byte_enable_ff      <= i_mem_signed_byte_enable_ff;
406
                o_mem_signed_halfword_enable_ff  <= i_mem_signed_halfword_enable_ff;
407
                o_mem_unsigned_halfword_enable_ff<= i_mem_unsigned_halfword_enable_ff;
408
                o_mem_translate_ff               <= i_mem_translate_ff;
409
 
410
                //
411
                // The value to store will have to be duplicated for easier
412
                // memory controller design. See the duplicate() function.
413
                //
414
                o_mem_srcdest_value_ff           <= mem_srcdest_value_nxt;
415
 
416
                sleep_ff                         <= sleep_nxt;
417
                o_und_ff                         <= i_und_ff;
418
 
419
                // Generating byte enables based on the data type and address.
420
                o_ben_ff                         <= ben_nxt;
421
 
422
                // For debug
423
                o_decompile                     <= i_decompile;
424
        end
425
end
426
 
427
// ----------------------------------------------------------------------------
428
 
429 43 Revanth
always @ ( posedge i_clk ) // Wishbone flops.
430 26 Revanth
begin
431
                // Wishbone updates.    
432
                o_data_wb_cyc_ff                <= o_data_wb_cyc_nxt;
433
                o_data_wb_stb_ff                <= o_data_wb_stb_nxt;
434
                o_data_wb_we_ff                 <= o_data_wb_we_nxt;
435
                o_data_wb_dat_ff                <= o_data_wb_dat_nxt;
436
                o_data_wb_sel_ff                <= o_data_wb_sel_nxt;
437
                o_mem_address_ff                <= o_address_nxt;
438
end
439
 
440 43 Revanth
// -----------------------------------------------------------------------------
441
// WB next state logic.
442
// -----------------------------------------------------------------------------
443
 
444
always @*
445 26 Revanth
begin
446
        // Preserve values.
447
        o_data_wb_cyc_nxt = o_data_wb_cyc_ff;
448
        o_data_wb_stb_nxt = o_data_wb_stb_ff;
449
        o_data_wb_we_nxt  = o_data_wb_we_ff;
450
        o_data_wb_dat_nxt = o_data_wb_dat_ff;
451
        o_data_wb_sel_nxt = o_data_wb_sel_ff;
452
        o_address_nxt     = o_mem_address_ff;
453
 
454
        if ( i_reset )
455
        begin
456
                o_data_wb_cyc_nxt = 1'd0;
457
                o_data_wb_stb_nxt = 1'd0;
458
        end
459
        else if ( i_clear_from_writeback )
460
        begin
461
                o_data_wb_cyc_nxt = 0;
462
                o_data_wb_stb_nxt = 0;
463
        end
464 43 Revanth
        else if ( i_data_stall )
465
        begin
466
                // Save state.
467
        end
468 26 Revanth
        else if ( i_data_mem_fault || sleep_ff )
469 43 Revanth
        begin
470 26 Revanth
                o_data_wb_cyc_nxt = 0;
471
                o_data_wb_stb_nxt = 0;
472
        end
473
        else
474
        begin
475
                o_data_wb_cyc_nxt = o_dav_nxt ? i_mem_load_ff | i_mem_store_ff : 1'd0;
476
                o_data_wb_stb_nxt = o_dav_nxt ? i_mem_load_ff | i_mem_store_ff : 1'd0;
477
                o_data_wb_we_nxt  = o_dav_nxt ? i_mem_store_ff                 : 1'd0;
478
                o_data_wb_dat_nxt = mem_srcdest_value_nxt;
479
                o_data_wb_sel_nxt = ben_nxt;
480
                o_address_nxt     = mem_address_nxt;
481
        end
482
end
483
 
484
// ----------------------------------------------------------------------------
485 43 Revanth
// Used to generate access address.
486
// ----------------------------------------------------------------------------
487 26 Revanth
 
488 43 Revanth
always @ (*)
489
begin:pre_post_index_address_generator
490
        /*
491
         * Do not change address if not needed.
492
         * If not a load OR a store. Preserve this value. Power saving.
493
         */
494 26 Revanth
        if (!( (i_mem_load_ff || i_mem_store_ff) && o_dav_nxt ))
495
                mem_address_nxt = o_mem_address_ff;
496 43 Revanth
        else
497
        begin
498
                /*
499
                 * Memory address output based on pre or post index.
500
                 * For post-index, update is done after memory access.
501
                 * For pre-index, update is done before memory access.
502
                 */
503
                if ( i_mem_pre_index_ff == 0 )
504
                        mem_address_nxt = rn;               // Postindex; 
505
                else
506
                        mem_address_nxt = o_alu_result_nxt; // Preindex.
507
 
508
                // If a force 32 align is set, make the lower 2 bits as zero.
509
                if ( i_force32align_ff )
510
                        mem_address_nxt[1:0] = 2'b00;
511
        end
512 26 Revanth
end
513
 
514 43 Revanth
// ---------------------------------------------------------------------------------
515
// Used to generate ALU result + Flags
516
// ---------------------------------------------------------------------------------
517 26 Revanth
 
518
always @*
519
begin: alu_result
520
 
521
        // Default value.
522
        tmp_flags = flags_ff;
523
 
524
        // If it is a logical instruction.
525
        if (            opcode == AND ||
526
                        opcode == EOR ||
527
                        opcode == MOV ||
528
                        opcode == MVN ||
529
                        opcode == BIC ||
530
                        opcode == ORR ||
531
                        opcode == TST ||
532
                        opcode == TEQ ||
533
                        opcode == CLZ
534
                )
535
        begin
536
                // Call the logical processing function.
537
                {tmp_flags[31:28], tmp_sum} = process_logical_instructions (
538
                        rn, rm, flags_ff[31:28],
539
                        opcode, i_flag_update_ff, i_nozero_ff
540
                );
541
        end
542
 
543 43 Revanth
        /*
544
         * Flag MOV(FMOV) i.e., MOV to CPSR and MMOV handler.
545
         * FMOV moves to CPSR and flushes the pipeline.
546
         * MMOV moves to SPSR and does not flush the pipeline.
547
         */
548 26 Revanth
        else if ( opcode == FMOV || opcode == MMOV )
549
        begin: fmov_mmov
550
                integer i;
551
                reg [31:0] exp_mask;
552
 
553
                // Read entire CPSR or SPSR.
554
                tmp_sum = opcode == FMOV ? flags_ff : i_mem_srcdest_value_ff;
555
 
556
                // Generate a proper mask.
557
                exp_mask = {{8{rn[3]}},{8{rn[2]}},{8{rn[1]}},{8{rn[0]}}};
558
 
559
                // Change only specific bits as specified by the mask.
560
                for ( i=0;i<32;i=i+1 )
561
                begin
562
                        if ( exp_mask[i] )
563
                                tmp_sum[i] = rm[i];
564
                end
565
 
566 43 Revanth
                /*
567
                 * FMOV moves to the CPSR in ALU and writeback.
568
                 * No register is changed. The MSR out of this will have
569
                 * a target to CPSR.
570
                 */
571 26 Revanth
                if ( opcode == FMOV )
572
                begin
573
                        tmp_flags = tmp_sum;
574
                end
575
        end
576
        else
577
        begin: blk3
578
                reg [3:0] flags;
579
                reg [zap_clog2(ALU_OPS)-1:0] op;
580
                reg n,z,c,v;
581
 
582
                op         = opcode;
583
 
584 43 Revanth
                // Assign output of adder to flags after some minimal logic.
585 26 Revanth
                c = sum[32];
586
                z = (sum[31:0] == 0);
587
                n = sum[31];
588
 
589
                // Overflow.
590
                if ( ( op == ADD || op == ADC || op == CMN ) && (rn[31] == rm[31]) && (sum[31] != rn[31]) )
591
                        v = 1;
592
                else if ( (op == RSB || op == RSC) && (rm[31] == !rn[31]) && (sum[31] != rm[31] ) )
593
                        v = 1;
594
                else if ( (op == SUB || op == SBC || op == CMP) && (rn[31] == !rm[31]) && (sum[31] != rn[31]) )
595
                        v = 1;
596
                else
597
                        v = 0;
598
 
599
                //       
600
                // If you choose not to update flags, do not change the flags.
601
                // Otherwise, they will contain their newly computed values.
602
                //
603
                if ( i_flag_update_ff )
604
                        tmp_flags[31:28] = {n,z,c,v};
605
 
606
                // Write out the result.
607 37 Revanth
                tmp_sum = op == CLZ ? clz_rm : sum;
608 26 Revanth
        end
609
 
610
        // Drive nxt pin of result register.
611
        o_alu_result_nxt = tmp_sum;
612
end
613
 
614
// ----------------------------------------------------------------------------
615 43 Revanth
// Flag propagation and branch prediction feedback unit
616
// ----------------------------------------------------------------------------
617 26 Revanth
 
618
always @*
619
begin: flags_bp_feedback
620
 
621
       o_clear_from_alu         = 1'd0;
622
       o_pc_from_alu            = 32'd0;
623
       sleep_nxt                = sleep_ff;
624
       flags_nxt                = tmp_flags;
625
       o_destination_index_nxt  = i_destination_index_ff;
626
       o_confirm_from_alu       = 1'd0;
627
 
628
        // Check if condition is satisfied.
629
       o_dav_nxt = is_cc_satisfied ( i_condition_code_ff, flags_ff[31:28] );
630
 
631
        if ( i_irq_ff || i_fiq_ff || i_abt_ff || i_swi_ff || i_und_ff )
632
        begin
633
                //
634
                // Any sign of an interrupt is present, put unit to sleep.
635 43 Revanth
                // The current instruction will not be executed ultimately.
636
                // However o_dav_nxt = 1 since interrupt must be carried on.
637 26 Revanth
                //
638
                o_dav_nxt = 1'd1;
639
                sleep_nxt = 1'd1;
640
        end
641
        else if ( (opcode == FMOV) && o_dav_nxt ) // Writes to CPSR...
642
        begin
643
                o_clear_from_alu        = 1'd1; // Need to flush everything because we might end up fetching stuff in KERNEL instead of USER mode.
644
                o_pc_from_alu           = sum;  // NOT tmp_sum, that would be loaded into CPSR. 
645
 
646
                // USR cannot change mode. Will silently fail.
647
                flags_nxt[`CPSR_MODE]   = (flags_nxt[`CPSR_MODE] == USR) ? USR : flags_nxt[`CPSR_MODE]; // Security.
648
        end
649
        else if ( i_destination_index_ff == ARCH_PC && (i_condition_code_ff != NV))
650
        begin
651 43 Revanth
                if ( i_flag_update_ff && o_dav_nxt ) // PC update with S bit. Context restore. 
652 26 Revanth
                begin
653 43 Revanth
                        $display($time, " - %m :: Saw PC update with S bit set. Context restore initiated.");
654
 
655 26 Revanth
                        o_destination_index_nxt = PHY_RAZ_REGISTER;
656
                        o_clear_from_alu        = 1'd1;
657
                        o_pc_from_alu           = tmp_sum;
658
                        flags_nxt               = i_mem_srcdest_value_ff;                                       // Restore CPSR from SPSR.
659
                        flags_nxt[`CPSR_MODE]   = (flags_nxt[`CPSR_MODE] == USR) ? USR : flags_nxt[`CPSR_MODE]; // Security.
660
                end
661
                else if ( o_dav_nxt ) // Branch taken and no flag update.
662
                begin
663 43 Revanth
                        if ( i_taken_ff == SNT || i_taken_ff == WNT ) // Incorrectly predicted. 
664 26 Revanth
                        begin
665
                                // Quick branches - Flush everything before.
666 43 Revanth
                                // Dumping ground since PC change is done. Jump to branch target for fast switching.
667 26 Revanth
                                o_destination_index_nxt = PHY_RAZ_REGISTER;
668
                                o_clear_from_alu        = 1'd1;
669
                                o_pc_from_alu           = tmp_sum;
670 43 Revanth
 
671
                                if ( i_switch_ff )
672
                                begin
673
                                        flags_nxt[T]            = tmp_sum[0];
674
 
675
                                        if ( tmp_sum[0] )
676
                                                $display($time, " - %m :: Entering T state.");
677
                                        else
678
                                                $display($time, " - %m :: Entering A state.");
679
                                end
680 26 Revanth
                        end
681
                        else    // Correctly predicted.
682
                        begin
683
                                // If thumb bit changes, flush everything before
684
                                if ( i_switch_ff )
685
                                begin
686
                                        // Quick branches! PC goes to RAZ register since
687
                                        // change is done.
688 43 Revanth
 
689 26 Revanth
                                        o_destination_index_nxt = PHY_RAZ_REGISTER;
690
                                        o_clear_from_alu        = 1'd1;
691 43 Revanth
                                        o_pc_from_alu           = tmp_sum; // Jump to branch target.
692
                                        flags_nxt[T]            = tmp_sum[0];
693
 
694
                                        if ( tmp_sum[0] )
695
                                                $display($time, " - %m :: Entering T state.");
696
                                        else
697
                                                $display($time, " - %m :: Entering A state.");
698 26 Revanth
                                end
699
                                else
700
                                begin
701 43 Revanth
                                        // No mode change, do not change anything.
702
 
703 26 Revanth
                                        o_destination_index_nxt = PHY_RAZ_REGISTER;
704 43 Revanth
                                        o_clear_from_alu        = 1'd0;
705 26 Revanth
 
706 43 Revanth
                                        // Send confirmation message to branch predictor.
707
 
708 26 Revanth
                                        o_pc_from_alu      = 32'd0;
709
                                        o_confirm_from_alu = 1'd1;
710
                                end
711
                        end
712
                end
713
                else    // Branch not taken
714
                begin
715
                        if ( i_taken_ff == WT || i_taken_ff == ST )
716 43 Revanth
                        // Wrong prediction as taken. Go back to the same
717
                        // branch. Non branches are always predicted as not-taken.
718
                        // GO BACK TO THE SAME BRANCH AND INFORM PREDICTOR OF ITS   
719
                        // MISTAKE - THE NEXT TIME THE PREDICTION WILL BE NOT-TAKEN.
720 26 Revanth
                        begin
721
                                o_clear_from_alu = 1'd1;
722
                                o_pc_from_alu    = i_pc_ff;
723
                        end
724 43 Revanth
                        else // Correct prediction.
725 26 Revanth
                        begin
726
                                o_clear_from_alu = 1'd0;
727
                                o_pc_from_alu    = 32'd0;
728
                        end
729
                end
730
        end
731
        else if ( i_mem_srcdest_index_ff == ARCH_PC && o_dav_nxt && i_mem_load_ff)
732
        begin
733
                // Loads to PC also puts the unit to sleep.
734 43 Revanth
                $display($time, " - %m :: ALU saw a load to R15. Sleeping to prevent further instructions from executing.");
735 26 Revanth
                sleep_nxt = 1'd1;
736
        end
737
 
738
        // If the current instruction is invalid, do not update flags.
739
        if ( o_dav_nxt == 1'd0 )
740
                flags_nxt = flags_ff;
741
end
742
 
743
// ----------------------------------------------------------------------------
744 43 Revanth
// MUX structure on the inputs of the adder.
745
// ----------------------------------------------------------------------------
746 26 Revanth
 
747
// These are adder connections. Data processing and FMOV use these.
748
always @*
749
begin: adder_ip_mux
750
        reg [zap_clog2(ALU_OPS)-1:0] op;
751
        reg [31:0] flags;
752
 
753
        flags = flags_ff[31:28];
754
        op    = i_alu_operation_ff;
755
 
756
        if ( i_hijack )
757
        begin
758
                op1 = i_hijack_op1;
759
                op2 = i_hijack_op2;
760
                cin = i_hijack_cin;
761
        end
762
        else
763
        case ( op )
764
       FMOV: begin op1 = i_pc_plus_8_ff ; op2 = ~32'd4 ; cin =   1'd1;      end
765
        ADD: begin op1 = rn             ; op2 = rm     ; cin =   32'd0;     end
766
        ADC: begin op1 = rn             ; op2 = rm     ; cin =   flags[_C]; end
767
        SUB: begin op1 = rn             ; op2 = not_rm ; cin =   32'd1;     end
768
        RSB: begin op1 = rm             ; op2 = not_rn ; cin =   32'd1;     end
769
        SBC: begin op1 = rn             ; op2 = not_rm ; cin =   !flags[_C];end
770
        RSC: begin op1 = rm             ; op2 = not_rn ; cin =   !flags[_C];end
771
 
772
        // Target is not written.
773
        CMP: begin op1 = rn             ; op2 = not_rm ; cin =   32'd1;     end
774
        CMN: begin op1 = rn             ; op2 = rm     ; cin =   32'd0;     end
775 43 Revanth
 
776 26 Revanth
        default:
777
        begin
778
                op1 = 0;
779
                op2 = 0;
780
                cin = 0;
781
        end
782
        endcase
783
end
784
 
785
// ----------------------------------------------------------------------------
786 43 Revanth
// Functions
787
// ----------------------------------------------------------------------------
788 26 Revanth
 
789
// Process logical instructions.
790
function [35:0] process_logical_instructions
791 43 Revanth
(
792
                input [31:0] rn,
793
                input [31:0] rm,
794
                input [3:0]  flags,
795
                input [zap_clog2(ALU_OPS)-1:0] op,
796
                input i_flag_upd, input nozero
797
);
798 26 Revanth
begin: blk2
799
        reg [31:0] rd;
800
        reg [3:0] flags_out;
801
 
802
        // Avoid accidental latch inference.
803
        rd        = 0;
804
        flags_out = 0;
805
 
806
        case(op)
807
        AND: rd = rn & rm;
808
        EOR: rd = rn ^ rm;
809
        BIC: rd = rn & ~(rm);
810
        MOV: rd = rm;
811
        MVN: rd = ~rm;
812
        ORR: rd = rn | rm;
813
        TST: rd = rn & rm; // Target is not written.
814
        TEQ: rd = rn ^ rn; // Target is not written.
815
        default:
816
        begin
817
                rd = 0;
818
                $display("*Error: Logic unit got non logic opcode...");
819
                $finish;
820
        end
821
        endcase
822
 
823
        // Suppose flags are not going to change at ALL.
824
        flags_out = flags;
825
 
826
        // Assign values to the flags only if an update is requested. Note that V
827
        // is not touched even if change is requested.
828
        if ( i_flag_upd )
829
        begin
830
                // V is preserved since flags_out = flags assignment.
831
                flags_out[_C] = i_shift_carry_ff;
832
 
833
                if ( nozero )
834
                        // This specifically states that we must NOT set the 
835
                        // ZERO flag under any circumstance. 
836
                        flags_out[_Z] = 1'd0;
837
                else
838
                        flags_out[_Z] = (rd == 0);
839
 
840
                flags_out[_N] = rd[31];
841
        end
842
 
843
        process_logical_instructions = {flags_out, rd};
844
end
845
endfunction
846
 
847 43 Revanth
/*
848
 * This task clears out the flip-flops in this module.
849
 * The flag input is used to preserve/force flags to
850
 * a specific state.
851
 */
852 26 Revanth
task clear ( input [31:0] flags );
853
begin
854
                o_dav_ff                         <= 0;
855
                flags_ff                         <= flags;
856
                o_abt_ff                         <= 0;
857
                o_irq_ff                         <= 0;
858
                o_fiq_ff                         <= 0;
859
                o_swi_ff                         <= 0;
860
                o_und_ff                         <= 0;
861
                sleep_ff                         <= 0;
862
                o_mem_load_ff                    <= 0;
863
                o_mem_store_ff                   <= 0;
864
end
865
endtask
866
 
867 43 Revanth
/*
868
 * The reason we use the duplicate function is to copy value over the memory
869
 * bus for memory stores. If we have a byte write to address 1, then the
870
 * memory controller basically takes address 0 and byte enable 0010 and writes
871
 * to address 1. This enables implementation of a 32-bit memory controller
872
 * with byte enables to control updates as is commonly done. Basically this
873
 * is to faciliate byte and halfword based writes on a 32-bit aligned memory
874
 * bus using byte enables. The rules are simple:
875
 * For a byte access - duplicate the lower byte of the register 4 times.
876
 * For halfword access - duplicate the lower 16-bit of the register twice.
877
 */
878 26 Revanth
 
879
function [31:0] duplicate (     input ub, // Unsigned byte. 
880
                                input sb, // Signed byte.
881
                                input uh, // Unsigned halfword.
882
                                input sh, // Signed halfword.
883
                                input [31:0] val        );
884
reg [31:0] x;
885
begin
886
        if ( ub || sb)
887
        begin
888
                // Byte.
889
                x = {val[7:0], val[7:0], val[7:0], val[7:0]};
890
        end
891
        else if (uh || sh)
892
        begin
893
                // Halfword.
894
                x = {val[15:0], val[15:0]};
895
        end
896
        else
897
        begin
898
                x = val;
899
        end
900
 
901
        duplicate = x;
902
end
903
endfunction
904
 
905 43 Revanth
/*
906
 *  Generate byte enables based on access mode.
907
 *  This function is similar in spirit to the previous one. The
908
 *  byte enables are generated in such a way that along with
909
 *  duplicate - byte and halfword accesses are possible.
910
 *  Rules -
911
 *  For a byte access, generate a byte enable with a 1 at the
912
 *  position that the lower 2-bits read (0,1,2,3).
913
 *  For a halfword access, based on lower 2-bits, if it is 00,
914
 *  make no change to byte enable (0011) else if it is 10, then
915
 *  make byte enable as (1100) which is basically the 32-bit
916
 *  address + 2 (and 3) which will be written.
917
 */
918 26 Revanth
function [3:0] generate_ben (   input ub, // Unsigned byte. 
919
                                input sb, // Signed byte.
920
                                input uh, // Unsigned halfword.
921
                                input sh, // Signed halfword.
922
                                input [31:0] addr       );
923
reg [3:0] x;
924
begin
925
        if ( ub || sb ) // Byte oriented.
926
        begin
927
                case ( addr[1:0] ) // Based on address lower 2-bits.
928
                0: x = 1;
929
                1: x = 1 << 1;
930
                2: x = 1 << 2;
931
                3: x = 1 << 3;
932
                endcase
933
        end
934
        else if ( uh || sh ) // Halfword. A word = 2 half words.
935
        begin
936
                case ( addr[1] )
937
                0: x = 4'b0011;
938
                1: x = 4'b1100;
939
                endcase
940
        end
941
        else
942
        begin
943
                x = 4'b1111; // Word oriented.
944
        end
945
 
946
        generate_ben = x;
947
end
948
endfunction // generate_ben
949
 
950 43 Revanth
// assertions_start
951 26 Revanth
 
952 43 Revanth
        /*
953
         * This assertion ensures that no privilege escalation is possible.
954
         * It does so by ensuring that the flag register cannot change out
955
         * of USR during normal operation.
956
         */
957 26 Revanth
        always @*
958
        begin
959
                if ( flags_nxt[`CPSR_MODE] != USR && flags_ff[`CPSR_MODE] == USR )
960
                begin
961 43 Revanth
                        $display($time, " - %m :: Error: Privilege Escalation Error.");
962 26 Revanth
                        $stop;
963
                end
964
        end
965
 
966 43 Revanth
        reg [64*8-1:0] OPCODE;
967
 
968
        always @*
969
        case(opcode)
970
        AND:begin       OPCODE = "AND";    end
971
        EOR:begin       OPCODE = "EOR";    end
972
        MOV:begin       OPCODE = "MOV";    end
973
        MVN:begin       OPCODE = "MVN";    end
974
        BIC:begin       OPCODE = "BIC";    end
975
        ORR:begin       OPCODE = "ORR";    end
976
        TST:begin       OPCODE = "TST";    end
977
        TEQ:begin       OPCODE = "TEQ";    end
978
        CLZ:begin       OPCODE = "CLZ";    end
979
        FMOV:begin      OPCODE = "FMOV";   end
980
        ADD:begin       OPCODE = "ADD";    end
981
        ADC:begin       OPCODE = "ADC";    end
982
        SUB:begin       OPCODE = "SUB";    end
983
        RSB:begin       OPCODE = "RSB";    end
984
        SBC:begin       OPCODE = "SBC";    end
985
        RSC:begin       OPCODE = "RSC";    end
986
        CMP:begin       OPCODE = "CMP";    end
987
        CMN:begin       OPCODE = "CMN";    end
988
        endcase
989 26 Revanth
 
990 43 Revanth
// assertions_end
991
 
992 26 Revanth
endmodule // zap_alu_main.v
993
 
994
`default_nettype wire

powered by: WebSVN 2.1.0

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