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 51

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 51 Revanth
        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 26 Revanth
 
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 51 Revanth
// Local N,Z,C,V structures.
204 26 Revanth
localparam [1:0] _N  = 2'd3;
205
localparam [1:0] _Z  = 2'd2;
206
localparam [1:0] _C  = 2'd1;
207
localparam [1:0] _V  = 2'd0;
208
 
209
// Branch status.
210
localparam [1:0] SNT = 2'd0;
211
localparam [1:0] WNT = 2'd1;
212
localparam [1:0] WT  = 2'd2;
213
localparam [1:0] ST  = 2'd3;
214
 
215 43 Revanth
// ------------------------------------------------------------------------------
216
// Variables
217
// ------------------------------------------------------------------------------
218
 
219
// Memory srcdest value (i.e., data)
220
wire [31:0]                     mem_srcdest_value_nxt;
221
 
222
// Byte enable generator.
223
wire [3:0]                      ben_nxt;
224
 
225
// Address about to be output. Used to drive tag RAMs etc.
226
reg [31:0]                      mem_address_nxt;
227
 
228 26 Revanth
/*
229
   Sleep flop. When 1 unit sleeps i.e., does not produce any output except on
230
   the first clock cycle where LR is calculated using the ALU.
231
*/
232
reg                             sleep_ff, sleep_nxt;
233
 
234
/*
235
   CPSR (Active CPSR). The active CPSR is from the where the CPU flags are
236
   read out and the mode also is. Mode changes via manual writes to CPSR
237
   are first written to the active and they then propagate to the passive CPSR
238
   in the writeback stage. This reduces the pipeline flush penalty.
239
*/
240
reg [31:0]                      flags_ff, flags_nxt;
241
 
242
reg [31:0]                      rm, rn; // RM = shifted source value Rn for
243
                                        // non shifted source value. These are
244
                                        // values and not indices.
245
 
246
 
247 37 Revanth
reg [5:0]                       clz_rm; // Count leading zeros in Rm.
248 26 Revanth
 
249 43 Revanth
// Destination index about to be output.
250
reg [zap_clog2(PHY_REGS)-1:0]      o_destination_index_nxt;
251
 
252
// 1s complement of Rm and Rn.
253
wire [31:0]                     not_rm = ~rm;
254
wire [31:0]                     not_rn = ~rn;
255
 
256
// Wires which connect to an adder.
257
reg [31:0]                      op1, op2;
258
reg                             cin;
259
 
260
// 32-bit adder with carry input and carry output.
261
wire [32:0]                     sum = {1'd0, op1} + {1'd0, op2} + {32'd0, cin};
262
 
263
reg [31:0]                      tmp_flags, tmp_sum;
264
 
265
// Opcode.
266
wire [zap_clog2(ALU_OPS)-1:0]   opcode = i_alu_operation_ff;
267
 
268
// -------------------------------------------------------------------------------
269
// Assigns
270
// -------------------------------------------------------------------------------
271
 
272
/*
273
   For memory stores, we must generate correct byte enables. This is done
274
   by examining access type inputs. For loads, always 1111 is generated.
275
   If there is neither a load or a store, the old value is preserved.
276
*/
277
assign ben_nxt =                generate_ben (
278
                                                 i_mem_unsigned_byte_enable_ff,
279
                                                 i_mem_signed_byte_enable_ff,
280
                                                 i_mem_unsigned_halfword_enable_ff,
281
                                                 i_mem_unsigned_halfword_enable_ff,
282
                                                 mem_address_nxt);
283
 
284
assign mem_srcdest_value_nxt =  duplicate (
285
                                                 i_mem_unsigned_byte_enable_ff,
286
                                                 i_mem_signed_byte_enable_ff,
287
                                                 i_mem_unsigned_halfword_enable_ff,
288
                                                 i_mem_unsigned_halfword_enable_ff,
289
                                                 i_mem_srcdest_value_ff );
290
 
291
/*
292
   Hijack interface. Data aborts use the hijack interface to find return
293
   address. The writeback drives the ALU inputs to find the final output.
294
*/
295
assign o_hijack_sum = sum;
296
 
297
// -------------------------------------------------------------------------------
298
// CLZ logic.
299
// -------------------------------------------------------------------------------
300
 
301 37 Revanth
always @* // CLZ implementation.
302
begin
303
        casez(rm)
304
        32'b1???????????????????????????????:   clz_rm = 6'd00;
305
        32'b01??????????????????????????????:   clz_rm = 6'd01;
306
        32'b001?????????????????????????????:   clz_rm = 6'd02;
307
        32'b0001????????????????????????????:   clz_rm = 6'd03;
308
        32'b00001???????????????????????????:   clz_rm = 6'd04;
309
        32'b000001??????????????????????????:   clz_rm = 6'd05;
310
        32'b0000001?????????????????????????:   clz_rm = 6'd06;
311
        32'b00000001????????????????????????:   clz_rm = 6'd07;
312
        32'b000000001???????????????????????:   clz_rm = 6'd08;
313
        32'b0000000001??????????????????????:   clz_rm = 6'd09;
314
        32'b00000000001?????????????????????:   clz_rm = 6'd10;
315
        32'b000000000001????????????????????:   clz_rm = 6'd11;
316
        32'b0000000000001???????????????????:   clz_rm = 6'd12;
317
        32'b00000000000001??????????????????:   clz_rm = 6'd13;
318
        32'b000000000000001?????????????????:   clz_rm = 6'd14;
319
        32'b0000000000000001????????????????:   clz_rm = 6'd15;
320
        32'b00000000000000001???????????????:   clz_rm = 6'd16;
321
        32'b000000000000000001??????????????:   clz_rm = 6'd17;
322
        32'b0000000000000000001?????????????:   clz_rm = 6'd18;
323
        32'b00000000000000000001????????????:   clz_rm = 6'd19;
324
        32'b000000000000000000001???????????:   clz_rm = 6'd20;
325
        32'b0000000000000000000001??????????:   clz_rm = 6'd21;
326
        32'b00000000000000000000001?????????:   clz_rm = 6'd22;
327
        32'b000000000000000000000001????????:   clz_rm = 6'd23;
328
        32'b0000000000000000000000001???????:   clz_rm = 6'd24;
329
        32'b00000000000000000000000001??????:   clz_rm = 6'd25;
330
        32'b000000000000000000000000001?????:   clz_rm = 6'd26;
331
        32'b0000000000000000000000000001????:   clz_rm = 6'd27;
332
        32'b00000000000000000000000000001???:   clz_rm = 6'd28;
333
        32'b000000000000000000000000000001??:   clz_rm = 6'd29;
334
        32'b0000000000000000000000000000001?:   clz_rm = 6'd30;
335
        32'b00000000000000000000000000000001:   clz_rm = 6'd31;
336
        default:                                clz_rm = 6'd32; // All zeros.
337
        endcase
338
end
339
 
340 26 Revanth
// ----------------------------------------------------------------------------
341 43 Revanth
// Aliases
342
// ----------------------------------------------------------------------------
343 26 Revanth
 
344
always @*
345
begin
346
        rm          = i_shifted_source_value_ff;
347
        rn          = i_alu_source_value_ff;
348
        o_flags_ff  = flags_ff;
349
        o_flags_nxt = flags_nxt;
350
end
351
 
352 43 Revanth
// -----------------------------------------------------------------------------
353 26 Revanth
// Sequential logic.
354 43 Revanth
// -----------------------------------------------------------------------------
355
 
356 26 Revanth
always @ (posedge i_clk)
357
begin
358
        if ( i_reset )
359
        begin
360
                // On reset, processor enters supervisory mode with interrupts
361
                // masked.
362
                clear ( {1'd1,1'd1,1'd0,SVC} );
363
        end
364
        else if ( i_clear_from_writeback )
365
        begin
366
                // Clear but take CPSR from writeback.
367
                clear ( i_cpsr_nxt );
368
        end
369
        else if ( i_data_stall )
370
        begin
371
                // Preserve values.
372
        end
373
        else if ( i_data_mem_fault || sleep_ff )
374
        begin
375
                // Clear and preserve flags. Keep sleeping.
376
                clear(flags_ff);
377
                sleep_ff                         <= 1'd1;
378
                o_dav_ff                         <= 1'd0; // Don't give any output.
379
        end
380
        else
381
        begin
382
                // Clock out all flops normally.
383
 
384
                o_alu_result_ff                  <= o_alu_result_nxt;
385
                o_dav_ff                         <= o_dav_nxt;
386
                o_pc_plus_8_ff                   <= i_pc_plus_8_ff;
387
                o_destination_index_ff           <= o_destination_index_nxt;
388
                flags_ff                         <= flags_nxt;
389
                o_abt_ff                         <= i_abt_ff;
390
                o_irq_ff                         <= i_irq_ff;
391
                o_fiq_ff                         <= i_fiq_ff;
392
                o_swi_ff                         <= i_swi_ff;
393
                o_mem_srcdest_index_ff           <= i_mem_srcdest_index_ff;
394
                o_mem_srcdest_index_ff           <= i_mem_srcdest_index_ff;
395
 
396
                // Load or store must come up only if an actual LDR/STR is
397
                // detected.
398
                o_mem_load_ff                    <= o_dav_nxt ? i_mem_load_ff : 1'd0;
399
                o_mem_store_ff                   <= o_dav_nxt ? i_mem_store_ff: 1'd0;
400
 
401
                o_mem_unsigned_byte_enable_ff    <= i_mem_unsigned_byte_enable_ff;
402
                o_mem_signed_byte_enable_ff      <= i_mem_signed_byte_enable_ff;
403
                o_mem_signed_halfword_enable_ff  <= i_mem_signed_halfword_enable_ff;
404
                o_mem_unsigned_halfword_enable_ff<= i_mem_unsigned_halfword_enable_ff;
405
                o_mem_translate_ff               <= i_mem_translate_ff;
406
 
407
                //
408
                // The value to store will have to be duplicated for easier
409
                // memory controller design. See the duplicate() function.
410
                //
411
                o_mem_srcdest_value_ff           <= mem_srcdest_value_nxt;
412
 
413
                sleep_ff                         <= sleep_nxt;
414
                o_und_ff                         <= i_und_ff;
415
 
416
                // Generating byte enables based on the data type and address.
417
                o_ben_ff                         <= ben_nxt;
418
 
419
                // For debug
420
                o_decompile                     <= i_decompile;
421
        end
422
end
423
 
424
// ----------------------------------------------------------------------------
425
 
426 43 Revanth
always @ ( posedge i_clk ) // Wishbone flops.
427 26 Revanth
begin
428
                // Wishbone updates.    
429
                o_data_wb_cyc_ff                <= o_data_wb_cyc_nxt;
430
                o_data_wb_stb_ff                <= o_data_wb_stb_nxt;
431
                o_data_wb_we_ff                 <= o_data_wb_we_nxt;
432
                o_data_wb_dat_ff                <= o_data_wb_dat_nxt;
433
                o_data_wb_sel_ff                <= o_data_wb_sel_nxt;
434
                o_mem_address_ff                <= o_address_nxt;
435
end
436
 
437 43 Revanth
// -----------------------------------------------------------------------------
438
// WB next state logic.
439
// -----------------------------------------------------------------------------
440
 
441
always @*
442 26 Revanth
begin
443
        // Preserve values.
444
        o_data_wb_cyc_nxt = o_data_wb_cyc_ff;
445
        o_data_wb_stb_nxt = o_data_wb_stb_ff;
446
        o_data_wb_we_nxt  = o_data_wb_we_ff;
447
        o_data_wb_dat_nxt = o_data_wb_dat_ff;
448
        o_data_wb_sel_nxt = o_data_wb_sel_ff;
449
        o_address_nxt     = o_mem_address_ff;
450
 
451 51 Revanth
        if ( i_reset )  // Synchronous reset. 
452 26 Revanth
        begin
453
                o_data_wb_cyc_nxt = 1'd0;
454
                o_data_wb_stb_nxt = 1'd0;
455
        end
456
        else if ( i_clear_from_writeback )
457
        begin
458
                o_data_wb_cyc_nxt = 0;
459
                o_data_wb_stb_nxt = 0;
460
        end
461 43 Revanth
        else if ( i_data_stall )
462
        begin
463
                // Save state.
464
        end
465 26 Revanth
        else if ( i_data_mem_fault || sleep_ff )
466 43 Revanth
        begin
467 26 Revanth
                o_data_wb_cyc_nxt = 0;
468
                o_data_wb_stb_nxt = 0;
469
        end
470
        else
471
        begin
472
                o_data_wb_cyc_nxt = o_dav_nxt ? i_mem_load_ff | i_mem_store_ff : 1'd0;
473
                o_data_wb_stb_nxt = o_dav_nxt ? i_mem_load_ff | i_mem_store_ff : 1'd0;
474
                o_data_wb_we_nxt  = o_dav_nxt ? i_mem_store_ff                 : 1'd0;
475
                o_data_wb_dat_nxt = mem_srcdest_value_nxt;
476
                o_data_wb_sel_nxt = ben_nxt;
477
                o_address_nxt     = mem_address_nxt;
478
        end
479
end
480
 
481
// ----------------------------------------------------------------------------
482 43 Revanth
// Used to generate access address.
483
// ----------------------------------------------------------------------------
484 26 Revanth
 
485 43 Revanth
always @ (*)
486
begin:pre_post_index_address_generator
487
        /*
488
         * Do not change address if not needed.
489
         * If not a load OR a store. Preserve this value. Power saving.
490
         */
491 26 Revanth
        if (!( (i_mem_load_ff || i_mem_store_ff) && o_dav_nxt ))
492
                mem_address_nxt = o_mem_address_ff;
493 43 Revanth
        else
494
        begin
495
                /*
496
                 * Memory address output based on pre or post index.
497
                 * For post-index, update is done after memory access.
498
                 * For pre-index, update is done before memory access.
499
                 */
500
                if ( i_mem_pre_index_ff == 0 )
501
                        mem_address_nxt = rn;               // Postindex; 
502
                else
503
                        mem_address_nxt = o_alu_result_nxt; // Preindex.
504
 
505
                // If a force 32 align is set, make the lower 2 bits as zero.
506
                if ( i_force32align_ff )
507
                        mem_address_nxt[1:0] = 2'b00;
508
        end
509 26 Revanth
end
510
 
511 43 Revanth
// ---------------------------------------------------------------------------------
512
// Used to generate ALU result + Flags
513
// ---------------------------------------------------------------------------------
514 26 Revanth
 
515
always @*
516
begin: alu_result
517
 
518
        // Default value.
519
        tmp_flags = flags_ff;
520
 
521
        // If it is a logical instruction.
522
        if (            opcode == AND ||
523
                        opcode == EOR ||
524
                        opcode == MOV ||
525
                        opcode == MVN ||
526
                        opcode == BIC ||
527
                        opcode == ORR ||
528
                        opcode == TST ||
529
                        opcode == TEQ ||
530
                        opcode == CLZ
531
                )
532
        begin
533
                // Call the logical processing function.
534
                {tmp_flags[31:28], tmp_sum} = process_logical_instructions (
535
                        rn, rm, flags_ff[31:28],
536
                        opcode, i_flag_update_ff, i_nozero_ff
537
                );
538
        end
539
 
540 43 Revanth
        /*
541
         * Flag MOV(FMOV) i.e., MOV to CPSR and MMOV handler.
542
         * FMOV moves to CPSR and flushes the pipeline.
543
         * MMOV moves to SPSR and does not flush the pipeline.
544
         */
545 26 Revanth
        else if ( opcode == FMOV || opcode == MMOV )
546
        begin: fmov_mmov
547
                integer i;
548
                reg [31:0] exp_mask;
549
 
550
                // Read entire CPSR or SPSR.
551
                tmp_sum = opcode == FMOV ? flags_ff : i_mem_srcdest_value_ff;
552
 
553
                // Generate a proper mask.
554
                exp_mask = {{8{rn[3]}},{8{rn[2]}},{8{rn[1]}},{8{rn[0]}}};
555
 
556
                // Change only specific bits as specified by the mask.
557
                for ( i=0;i<32;i=i+1 )
558
                begin
559
                        if ( exp_mask[i] )
560
                                tmp_sum[i] = rm[i];
561
                end
562
 
563 43 Revanth
                /*
564
                 * FMOV moves to the CPSR in ALU and writeback.
565
                 * No register is changed. The MSR out of this will have
566
                 * a target to CPSR.
567
                 */
568 26 Revanth
                if ( opcode == FMOV )
569
                begin
570
                        tmp_flags = tmp_sum;
571
                end
572
        end
573
        else
574
        begin: blk3
575
                reg [3:0] flags;
576
                reg [zap_clog2(ALU_OPS)-1:0] op;
577
                reg n,z,c,v;
578
 
579
                op         = opcode;
580
 
581 43 Revanth
                // Assign output of adder to flags after some minimal logic.
582 26 Revanth
                c = sum[32];
583
                z = (sum[31:0] == 0);
584
                n = sum[31];
585
 
586
                // Overflow.
587
                if ( ( op == ADD || op == ADC || op == CMN ) && (rn[31] == rm[31]) && (sum[31] != rn[31]) )
588
                        v = 1;
589
                else if ( (op == RSB || op == RSC) && (rm[31] == !rn[31]) && (sum[31] != rm[31] ) )
590
                        v = 1;
591
                else if ( (op == SUB || op == SBC || op == CMP) && (rn[31] == !rm[31]) && (sum[31] != rn[31]) )
592
                        v = 1;
593
                else
594
                        v = 0;
595
 
596
                //       
597
                // If you choose not to update flags, do not change the flags.
598
                // Otherwise, they will contain their newly computed values.
599
                //
600
                if ( i_flag_update_ff )
601
                        tmp_flags[31:28] = {n,z,c,v};
602
 
603
                // Write out the result.
604 37 Revanth
                tmp_sum = op == CLZ ? clz_rm : sum;
605 26 Revanth
        end
606
 
607
        // Drive nxt pin of result register.
608
        o_alu_result_nxt = tmp_sum;
609
end
610
 
611
// ----------------------------------------------------------------------------
612 43 Revanth
// Flag propagation and branch prediction feedback unit
613
// ----------------------------------------------------------------------------
614 26 Revanth
 
615
always @*
616
begin: flags_bp_feedback
617
 
618
       o_clear_from_alu         = 1'd0;
619
       o_pc_from_alu            = 32'd0;
620
       sleep_nxt                = sleep_ff;
621
       flags_nxt                = tmp_flags;
622
       o_destination_index_nxt  = i_destination_index_ff;
623
       o_confirm_from_alu       = 1'd0;
624
 
625
        // Check if condition is satisfied.
626
       o_dav_nxt = is_cc_satisfied ( i_condition_code_ff, flags_ff[31:28] );
627
 
628
        if ( i_irq_ff || i_fiq_ff || i_abt_ff || i_swi_ff || i_und_ff )
629
        begin
630
                //
631
                // Any sign of an interrupt is present, put unit to sleep.
632 43 Revanth
                // The current instruction will not be executed ultimately.
633
                // However o_dav_nxt = 1 since interrupt must be carried on.
634 26 Revanth
                //
635
                o_dav_nxt = 1'd1;
636
                sleep_nxt = 1'd1;
637
        end
638
        else if ( (opcode == FMOV) && o_dav_nxt ) // Writes to CPSR...
639
        begin
640
                o_clear_from_alu        = 1'd1; // Need to flush everything because we might end up fetching stuff in KERNEL instead of USER mode.
641
                o_pc_from_alu           = sum;  // NOT tmp_sum, that would be loaded into CPSR. 
642
 
643
                // USR cannot change mode. Will silently fail.
644
                flags_nxt[`CPSR_MODE]   = (flags_nxt[`CPSR_MODE] == USR) ? USR : flags_nxt[`CPSR_MODE]; // Security.
645
        end
646
        else if ( i_destination_index_ff == ARCH_PC && (i_condition_code_ff != NV))
647
        begin
648 43 Revanth
                if ( i_flag_update_ff && o_dav_nxt ) // PC update with S bit. Context restore. 
649 26 Revanth
                begin
650
                        o_destination_index_nxt = PHY_RAZ_REGISTER;
651
                        o_clear_from_alu        = 1'd1;
652
                        o_pc_from_alu           = tmp_sum;
653
                        flags_nxt               = i_mem_srcdest_value_ff;                                       // Restore CPSR from SPSR.
654
                        flags_nxt[`CPSR_MODE]   = (flags_nxt[`CPSR_MODE] == USR) ? USR : flags_nxt[`CPSR_MODE]; // Security.
655
                end
656
                else if ( o_dav_nxt ) // Branch taken and no flag update.
657
                begin
658 43 Revanth
                        if ( i_taken_ff == SNT || i_taken_ff == WNT ) // Incorrectly predicted. 
659 26 Revanth
                        begin
660
                                // Quick branches - Flush everything before.
661 43 Revanth
                                // Dumping ground since PC change is done. Jump to branch target for fast switching.
662 26 Revanth
                                o_destination_index_nxt = PHY_RAZ_REGISTER;
663
                                o_clear_from_alu        = 1'd1;
664
                                o_pc_from_alu           = tmp_sum;
665 43 Revanth
 
666
                                if ( i_switch_ff )
667
                                begin
668
                                        flags_nxt[T]            = tmp_sum[0];
669
                                end
670 26 Revanth
                        end
671
                        else    // Correctly predicted.
672
                        begin
673
                                // If thumb bit changes, flush everything before
674
                                if ( i_switch_ff )
675
                                begin
676
                                        // Quick branches! PC goes to RAZ register since
677
                                        // change is done.
678 43 Revanth
 
679 26 Revanth
                                        o_destination_index_nxt = PHY_RAZ_REGISTER;
680
                                        o_clear_from_alu        = 1'd1;
681 43 Revanth
                                        o_pc_from_alu           = tmp_sum; // Jump to branch target.
682
                                        flags_nxt[T]            = tmp_sum[0];
683 26 Revanth
                                end
684
                                else
685
                                begin
686 43 Revanth
                                        // No mode change, do not change anything.
687
 
688 26 Revanth
                                        o_destination_index_nxt = PHY_RAZ_REGISTER;
689 43 Revanth
                                        o_clear_from_alu        = 1'd0;
690 26 Revanth
 
691 43 Revanth
                                        // Send confirmation message to branch predictor.
692
 
693 26 Revanth
                                        o_pc_from_alu      = 32'd0;
694
                                        o_confirm_from_alu = 1'd1;
695
                                end
696
                        end
697
                end
698
                else    // Branch not taken
699
                begin
700
                        if ( i_taken_ff == WT || i_taken_ff == ST )
701 51 Revanth
                        //
702 43 Revanth
                        // Wrong prediction as taken. Go back to the same
703
                        // branch. Non branches are always predicted as not-taken.
704 51 Revanth
                        //
705 43 Revanth
                        // GO BACK TO THE SAME BRANCH AND INFORM PREDICTOR OF ITS   
706
                        // MISTAKE - THE NEXT TIME THE PREDICTION WILL BE NOT-TAKEN.
707 51 Revanth
                        //
708 26 Revanth
                        begin
709
                                o_clear_from_alu = 1'd1;
710
                                o_pc_from_alu    = i_pc_ff;
711
                        end
712 43 Revanth
                        else // Correct prediction.
713 26 Revanth
                        begin
714
                                o_clear_from_alu = 1'd0;
715
                                o_pc_from_alu    = 32'd0;
716
                        end
717
                end
718
        end
719
        else if ( i_mem_srcdest_index_ff == ARCH_PC && o_dav_nxt && i_mem_load_ff)
720
        begin
721
                // Loads to PC also puts the unit to sleep.
722
                sleep_nxt = 1'd1;
723
        end
724
 
725
        // If the current instruction is invalid, do not update flags.
726
        if ( o_dav_nxt == 1'd0 )
727
                flags_nxt = flags_ff;
728
end
729
 
730
// ----------------------------------------------------------------------------
731 43 Revanth
// MUX structure on the inputs of the adder.
732
// ----------------------------------------------------------------------------
733 26 Revanth
 
734
// These are adder connections. Data processing and FMOV use these.
735
always @*
736
begin: adder_ip_mux
737
        reg [zap_clog2(ALU_OPS)-1:0] op;
738
        reg [31:0] flags;
739
 
740
        flags = flags_ff[31:28];
741
        op    = i_alu_operation_ff;
742
 
743
        if ( i_hijack )
744
        begin
745
                op1 = i_hijack_op1;
746
                op2 = i_hijack_op2;
747
                cin = i_hijack_cin;
748
        end
749
        else
750
        case ( op )
751
       FMOV: begin op1 = i_pc_plus_8_ff ; op2 = ~32'd4 ; cin =   1'd1;      end
752
        ADD: begin op1 = rn             ; op2 = rm     ; cin =   32'd0;     end
753
        ADC: begin op1 = rn             ; op2 = rm     ; cin =   flags[_C]; end
754
        SUB: begin op1 = rn             ; op2 = not_rm ; cin =   32'd1;     end
755
        RSB: begin op1 = rm             ; op2 = not_rn ; cin =   32'd1;     end
756
        SBC: begin op1 = rn             ; op2 = not_rm ; cin =   !flags[_C];end
757
        RSC: begin op1 = rm             ; op2 = not_rn ; cin =   !flags[_C];end
758
 
759
        // Target is not written.
760
        CMP: begin op1 = rn             ; op2 = not_rm ; cin =   32'd1;     end
761
        CMN: begin op1 = rn             ; op2 = rm     ; cin =   32'd0;     end
762 43 Revanth
 
763 26 Revanth
        default:
764
        begin
765
                op1 = 0;
766
                op2 = 0;
767
                cin = 0;
768
        end
769
        endcase
770
end
771
 
772
// ----------------------------------------------------------------------------
773 43 Revanth
// Functions
774
// ----------------------------------------------------------------------------
775 26 Revanth
 
776
// Process logical instructions.
777
function [35:0] process_logical_instructions
778 43 Revanth
(
779
                input [31:0] rn,
780
                input [31:0] rm,
781
                input [3:0]  flags,
782
                input [zap_clog2(ALU_OPS)-1:0] op,
783
                input i_flag_upd, input nozero
784
);
785 26 Revanth
begin: blk2
786
        reg [31:0] rd;
787
        reg [3:0] flags_out;
788
 
789
        // Avoid accidental latch inference.
790
        rd        = 0;
791
        flags_out = 0;
792
 
793
        case(op)
794
        AND: rd = rn & rm;
795
        EOR: rd = rn ^ rm;
796
        BIC: rd = rn & ~(rm);
797
        MOV: rd = rm;
798
        MVN: rd = ~rm;
799
        ORR: rd = rn | rm;
800
        TST: rd = rn & rm; // Target is not written.
801
        TEQ: rd = rn ^ rn; // Target is not written.
802
        default:
803
        begin
804
                rd = 0;
805
                $display("*Error: Logic unit got non logic opcode...");
806
                $finish;
807
        end
808
        endcase
809
 
810
        // Suppose flags are not going to change at ALL.
811
        flags_out = flags;
812
 
813
        // Assign values to the flags only if an update is requested. Note that V
814
        // is not touched even if change is requested.
815
        if ( i_flag_upd )
816
        begin
817
                // V is preserved since flags_out = flags assignment.
818
                flags_out[_C] = i_shift_carry_ff;
819
 
820
                if ( nozero )
821
                        // This specifically states that we must NOT set the 
822
                        // ZERO flag under any circumstance. 
823
                        flags_out[_Z] = 1'd0;
824
                else
825
                        flags_out[_Z] = (rd == 0);
826
 
827
                flags_out[_N] = rd[31];
828
        end
829
 
830
        process_logical_instructions = {flags_out, rd};
831
end
832
endfunction
833
 
834 43 Revanth
/*
835
 * This task clears out the flip-flops in this module.
836
 * The flag input is used to preserve/force flags to
837
 * a specific state.
838
 */
839 26 Revanth
task clear ( input [31:0] flags );
840
begin
841
                o_dav_ff                         <= 0;
842
                flags_ff                         <= flags;
843
                o_abt_ff                         <= 0;
844
                o_irq_ff                         <= 0;
845
                o_fiq_ff                         <= 0;
846
                o_swi_ff                         <= 0;
847
                o_und_ff                         <= 0;
848
                sleep_ff                         <= 0;
849
                o_mem_load_ff                    <= 0;
850
                o_mem_store_ff                   <= 0;
851
end
852
endtask
853
 
854 43 Revanth
/*
855
 * The reason we use the duplicate function is to copy value over the memory
856
 * bus for memory stores. If we have a byte write to address 1, then the
857
 * memory controller basically takes address 0 and byte enable 0010 and writes
858
 * to address 1. This enables implementation of a 32-bit memory controller
859
 * with byte enables to control updates as is commonly done. Basically this
860
 * is to faciliate byte and halfword based writes on a 32-bit aligned memory
861
 * bus using byte enables. The rules are simple:
862
 * For a byte access - duplicate the lower byte of the register 4 times.
863
 * For halfword access - duplicate the lower 16-bit of the register twice.
864
 */
865 26 Revanth
 
866
function [31:0] duplicate (     input ub, // Unsigned byte. 
867
                                input sb, // Signed byte.
868
                                input uh, // Unsigned halfword.
869
                                input sh, // Signed halfword.
870
                                input [31:0] val        );
871
reg [31:0] x;
872
begin
873
        if ( ub || sb)
874
        begin
875
                // Byte.
876
                x = {val[7:0], val[7:0], val[7:0], val[7:0]};
877
        end
878
        else if (uh || sh)
879
        begin
880
                // Halfword.
881
                x = {val[15:0], val[15:0]};
882
        end
883
        else
884
        begin
885
                x = val;
886
        end
887
 
888
        duplicate = x;
889
end
890
endfunction
891
 
892 43 Revanth
/*
893
 *  Generate byte enables based on access mode.
894
 *  This function is similar in spirit to the previous one. The
895
 *  byte enables are generated in such a way that along with
896
 *  duplicate - byte and halfword accesses are possible.
897
 *  Rules -
898
 *  For a byte access, generate a byte enable with a 1 at the
899
 *  position that the lower 2-bits read (0,1,2,3).
900
 *  For a halfword access, based on lower 2-bits, if it is 00,
901
 *  make no change to byte enable (0011) else if it is 10, then
902
 *  make byte enable as (1100) which is basically the 32-bit
903
 *  address + 2 (and 3) which will be written.
904
 */
905 26 Revanth
function [3:0] generate_ben (   input ub, // Unsigned byte. 
906
                                input sb, // Signed byte.
907
                                input uh, // Unsigned halfword.
908
                                input sh, // Signed halfword.
909
                                input [31:0] addr       );
910
reg [3:0] x;
911
begin
912
        if ( ub || sb ) // Byte oriented.
913
        begin
914
                case ( addr[1:0] ) // Based on address lower 2-bits.
915
                0: x = 1;
916
                1: x = 1 << 1;
917
                2: x = 1 << 2;
918
                3: x = 1 << 3;
919
                endcase
920
        end
921
        else if ( uh || sh ) // Halfword. A word = 2 half words.
922
        begin
923
                case ( addr[1] )
924
                0: x = 4'b0011;
925
                1: x = 4'b1100;
926
                endcase
927
        end
928
        else
929
        begin
930
                x = 4'b1111; // Word oriented.
931
        end
932
 
933
        generate_ben = x;
934
end
935
endfunction // generate_ben
936
 
937 51 Revanth
/*
938
 * This assertion ensures that no privilege escalation is possible.
939
 * It does so by ensuring that the flag register cannot change out
940
 * of USR during normal operation.
941
 */
942
always @*
943
begin
944
        if ( flags_nxt[`CPSR_MODE] != USR && flags_ff[`CPSR_MODE] == USR )
945 26 Revanth
        begin
946 51 Revanth
                $display($time, " - %m :: Error: Privilege Escalation Error.");
947
                $stop;
948 26 Revanth
        end
949 51 Revanth
end
950 26 Revanth
 
951 51 Revanth
reg [64*8-1:0] OPCODE;
952
 
953
always @*
954
case(opcode)
955 43 Revanth
        AND:begin       OPCODE = "AND";    end
956
        EOR:begin       OPCODE = "EOR";    end
957
        MOV:begin       OPCODE = "MOV";    end
958
        MVN:begin       OPCODE = "MVN";    end
959
        BIC:begin       OPCODE = "BIC";    end
960
        ORR:begin       OPCODE = "ORR";    end
961
        TST:begin       OPCODE = "TST";    end
962
        TEQ:begin       OPCODE = "TEQ";    end
963
        CLZ:begin       OPCODE = "CLZ";    end
964
        FMOV:begin      OPCODE = "FMOV";   end
965
        ADD:begin       OPCODE = "ADD";    end
966
        ADC:begin       OPCODE = "ADC";    end
967
        SUB:begin       OPCODE = "SUB";    end
968
        RSB:begin       OPCODE = "RSB";    end
969
        SBC:begin       OPCODE = "SBC";    end
970
        RSC:begin       OPCODE = "RSC";    end
971
        CMP:begin       OPCODE = "CMP";    end
972
        CMN:begin       OPCODE = "CMN";    end
973 51 Revanth
endcase
974 26 Revanth
 
975
endmodule // zap_alu_main.v
976
 
977
`default_nettype wire
978 51 Revanth
 
979
// ----------------------------------------------------------------------------
980
// END OF FILE
981
// ----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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