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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_decode.v] - Blame information for rev 46

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 module performs core ARM instruction decoding by translating ARM   --
25
// -- instructions into an internal long format that can be processed by core --
26
// -- logic. Note that the predecode stage must change the 32-bit instr. to   --
27
// -- 36-bit before feeding it into this unit.                                --
28
// --                                                                         --
29
// -----------------------------------------------------------------------------
30
 
31
 
32
`default_nettype none
33
 
34
module zap_decode (
35
 
36
i_irq,  // IRQ request from previous stage.
37
i_fiq,  // FIQ request from previous stage.
38
i_abt,  // Code abort flagged from previous stage.
39
 
40
// Instruction input from pre-decode.
41
i_instruction,
42
i_instruction_valid,
43
 
44
//
45
// CPU mode from active CPSR. Required to prevent CPSR change on MSR 
46
// instruction in USR mode.
47
//
48
i_cpsr_ff_mode,
49
 
50
//
51
// Bits related to decoded instruction...
52
// 
53
 
54
o_condition_code,       // 4-bit CC.
55
o_destination_index,    // Destination register.
56
o_alu_source,           // ALU source register.
57
o_alu_operation,        // ALU operation to be performed.
58
o_shift_source,         // Register to be treated as input to shifter.
59
o_shift_operation,      // Shift operation to perform.
60
o_shift_length,         // Length of the shift operation.
61
o_flag_update,          // 1 means flags must be updated.
62
 
63
// Memory related.
64
o_mem_srcdest_index,            // Data register.
65
o_mem_load,                     // Load operation.
66
o_mem_store,                    // Store operation.
67
o_mem_pre_index,                // Pre-Index.
68
o_mem_unsigned_byte_enable,     // Access treated as uint8_t.
69
o_mem_signed_byte_enable,       // Access treated as int8_t.
70
o_mem_signed_halfword_enable,   // Access treated as int16_t.
71
o_mem_unsigned_halfword_enable, // Access treated as uint16_t.
72
o_mem_translate,                // Force user view of memory.
73
 
74
o_und,   // Declare as undecodable. 
75
o_switch // Switch between ARM and Thumb may be needed if this is 1.
76
 
77
);
78
 
79
// ----------------------------------------------------------------------------
80
 
81
        // Number of architectural registers.
82
        parameter ARCH_REGS = 32;
83
 
84
        // Number of opcodes.
85
        parameter ALU_OPS   = 32;
86
 
87
        // Number of shift operations.
88
        parameter SHIFT_OPS = 6;
89
 
90
 
91
                // I/O Ports.
92
                input   wire                            i_irq, i_fiq, i_abt;
93
                input    wire   [35:0]                  i_instruction;
94
                input    wire                           i_instruction_valid;
95
                input   wire    [4:0]                   i_cpsr_ff_mode;
96
                output   reg    [3:0]                   o_condition_code;
97
                output   reg    [$clog2(ARCH_REGS)-1:0] o_destination_index;
98
                output   reg    [32:0]                  o_alu_source;
99
                output   reg    [$clog2(ALU_OPS)-1:0]   o_alu_operation;
100
                output   reg    [32:0]                  o_shift_source;
101
                output   reg    [$clog2(SHIFT_OPS)-1:0] o_shift_operation;
102
                output   reg    [32:0]                  o_shift_length;
103
                output  reg                             o_flag_update;
104
                output  reg   [$clog2(ARCH_REGS)-1:0]   o_mem_srcdest_index;
105
                output  reg                             o_mem_load;
106
                output  reg                             o_mem_store;
107
                output  reg                             o_mem_pre_index;
108
                output  reg                             o_mem_unsigned_byte_enable;
109
                output  reg                             o_mem_signed_byte_enable;
110
                output  reg                             o_mem_signed_halfword_enable;
111
                output  reg                             o_mem_unsigned_halfword_enable;
112
                output  reg                             o_mem_translate;
113
                output  reg                             o_und;
114
                output  reg                             o_switch;
115
 
116
// ----------------------------------------------------------------------------
117
 
118
`include "zap_defines.vh"
119
`include "zap_localparams.vh"
120
`include "zap_functions.vh"
121
 
122
// Related to memory operations.
123
localparam [1:0] SIGNED_BYTE            = 2'd0;
124
localparam [1:0] UNSIGNED_HALF_WORD     = 2'd1;
125
localparam [1:0] SIGNED_HALF_WORD       = 2'd2;
126
 
127 43 Revanth
// assertions_start
128 26 Revanth
 
129 43 Revanth
        // Debug only.
130
        reg bx, dp, br, mrs, msr, ls, mult, halfword_ls, swi, dp1, dp2, dp3, lmult, clz;
131
 
132
        always @*
133 26 Revanth
        begin
134 43 Revanth
                bx      = 0;
135
                dp      = 0;
136
                br      = 0;
137
                mrs     = 0;
138
                msr     = 0;
139
                ls      = 0;
140
                mult    = 0;
141
                halfword_ls = 0;
142
                swi = 0;
143
                dp1 = 0;
144
                dp2 = 0;
145
                dp3 = 0;
146
 
147
                //
148
                // Debugging purposes.
149
                //
150
                if ( i_instruction_valid )
151
                casez ( i_instruction[31:0] )
152
                CLZ_INSTRUCTION:                               clz = 1;
153
                BX_INST:                                       bx  = 1;
154
                MRS:                                           mrs = 1;
155
                MSR,MSR_IMMEDIATE:                             msr = 1;
156
                DATA_PROCESSING_IMMEDIATE,
157
                DATA_PROCESSING_REGISTER_SPECIFIED_SHIFT,
158
                DATA_PROCESSING_INSTRUCTION_SPECIFIED_SHIFT:   dp  = 1;
159
                BRANCH_INSTRUCTION:                            br  = 1;
160
                LS_INSTRUCTION_SPECIFIED_SHIFT,LS_IMMEDIATE:
161
                begin
162
                        if ( i_instruction[20] )
163
                                ls  = 1; // Load
164
                        else
165
                                ls  = 2;  // Store
166
                end
167
                MULT_INST:                        mult            = 1;
168
                LMULT_INST:                       lmult           = 1;
169
                HALFWORD_LS:                      halfword_ls     = 1;
170
                SOFTWARE_INTERRUPT:               swi             = 1;
171
                endcase
172 26 Revanth
        end
173
 
174 43 Revanth
// assertions_end
175 26 Revanth
 
176
// ----------------------------------------------------------------------------
177
 
178
always @*
179
begin: mainBlk1
180
        // If an unrecognized instruction enters this, the output
181
        // signals an NV state i.e., invalid.
182
        o_condition_code                = NV;
183
        o_destination_index             = 0;
184
        o_alu_source                    = 0;
185
        o_alu_operation                 = 0;
186
        o_shift_source                  = 0;
187
        o_shift_operation               = 0;
188
        o_shift_length                  = 0;
189
        o_flag_update                   = 0;
190
        o_mem_srcdest_index             = RAZ_REGISTER;
191
        o_mem_load                      = 0;
192
        o_mem_store                     = 0;
193
        o_mem_translate                 = 0;
194
        o_mem_pre_index                 = 0;
195
        o_mem_unsigned_byte_enable      = 0;
196
        o_mem_signed_byte_enable        = 0;
197
        o_mem_signed_halfword_enable    = 0;
198
        o_mem_unsigned_halfword_enable  = 0;
199
        o_mem_translate                 = 0;
200
        o_und                           = 0;
201
        o_switch                        = 0;
202
 
203
 
204
                // Based on our pattern match, call the appropriate task
205
                if ( i_fiq || i_irq || i_abt )
206
                begin
207
                        // Generate LR = PC - 4.
208
                        o_condition_code    = AL;
209
                        o_alu_operation     = SUB;
210
                        o_alu_source        = ARCH_PC;
211
                        o_alu_source[32]    = INDEX_EN;
212
                        o_destination_index = ARCH_LR;
213
                        o_shift_source      = 4;
214
                        o_shift_source[32]  = IMMED_EN;
215
                        o_shift_operation   = LSL;
216
                        o_shift_length      = 0;
217
                        o_shift_length[32]  = IMMED_EN;
218
                end
219
                else if ( i_instruction_valid )
220
                casez ( i_instruction[31:0] )
221 37 Revanth
                CLZ_INSTRUCTION:              decode_clz ( i_instruction );
222
                BX_INST:                      decode_bx  ( i_instruction );
223 26 Revanth
                MRS:                          decode_mrs ( i_instruction );
224
                MSR,MSR_IMMEDIATE:            decode_msr ( i_instruction );
225
 
226
                DATA_PROCESSING_IMMEDIATE,
227
                DATA_PROCESSING_REGISTER_SPECIFIED_SHIFT,
228
                DATA_PROCESSING_INSTRUCTION_SPECIFIED_SHIFT:
229
                                      decode_data_processing ( i_instruction );
230
 
231
                BRANCH_INSTRUCTION:    decode_branch ( i_instruction );
232
 
233
                LS_INSTRUCTION_SPECIFIED_SHIFT,
234
                LS_IMMEDIATE:    decode_ls ( i_instruction );
235
 
236
                MULT_INST:              decode_mult ( i_instruction );
237
                LMULT_INST:             decode_lmult( i_instruction );
238
                HALFWORD_LS:            decode_halfword_ls ( i_instruction );
239
                SOFTWARE_INTERRUPT:     decode_swi ( i_instruction );
240
 
241
                default:
242
                begin
243
                        decode_und ( i_instruction );
244
                end
245
                endcase
246
end
247
 
248
// ----------------------------------------------------------------------------
249
 
250
// =============================
251 37 Revanth
// Decode CLZ
252
// =============================
253
task decode_clz ( input [35:0] i_instruction );
254
begin: tskDecodeClz
255
        o_condition_code        =       i_instruction[31:28];
256
        o_flag_update           =       1'd0; // Instruction does not update any flags.
257
        o_alu_operation         =       CLZ;  // Added.
258
 
259
        // Rn = 0.
260
        o_alu_source            =       0;
261
        o_alu_source[32]        =       IMMED_EN;
262
 
263
        // Rm = register whose CLZ must be found.
264
        o_shift_source          =       {i_instruction[`DP_RB_EXTEND], i_instruction[`DP_RB]}; // Rm
265
        o_shift_source[32]      =       INDEX_EN;
266
        o_shift_operation       =       LSL;
267
        o_shift_length          =       0;
268
        o_shift_length[32]      =       IMMED_EN; // Shift length is 0 of course.
269
end
270
endtask
271
 
272
// =============================
273 26 Revanth
// Decode long multiplication.
274
// =============================
275
task decode_lmult ( input [35:0] i_instruction ); // Uses bit 35. rm.rs + {rh, rn}
276
begin: tskLDecodeMult
277
 
278
        o_condition_code        =       i_instruction[31:28];
279
        o_flag_update           =       i_instruction[20];
280
 
281
        // ARM rd.
282
        o_destination_index     =       {i_instruction[`DP_RD_EXTEND],
283
                                         i_instruction[19:16]};
284
        // For MUL, Rd and Rn are interchanged. 
285
        // For 64bit, this is normally high register.
286
 
287
        o_alu_source            =       i_instruction[11:8]; // ARM rs
288
        o_alu_source[32]        =       INDEX_EN;
289
 
290
        o_shift_source          =       {i_instruction[`DP_RB_EXTEND],
291
                                         i_instruction[`DP_RB]};
292
        o_shift_source[32]      =       INDEX_EN;            // ARM rm 
293
 
294
        // ARM rn
295
        o_shift_length          =       i_instruction[24] ?
296
                                        {i_instruction[`DP_RA_EXTEND],
297
                                         i_instruction[`DP_RD]} : 32'd0;
298
 
299
        o_shift_length[32]      =       i_instruction[24] ? INDEX_EN:IMMED_EN;
300
 
301
`ifdef DECODE_DEBUG
302
        $display($time, "Long multiplication detected!");
303
`endif
304
 
305
        // We need to generate output code.
306
        case ( i_instruction[22:21] )
307
        2'b00:
308
        begin
309
                // Unsigned MULT64
310
                o_alu_operation = UMLALH;
311
                o_mem_srcdest_index = RAZ_REGISTER; // rh.
312
        end
313
        2'b01:
314
        begin
315
                // Unsigned MAC64. Need mem_srcdest as source for RdHi.
316
                o_alu_operation = UMLALH;
317
                o_mem_srcdest_index = i_instruction[19:16];
318
        end
319
        2'b10:
320
        begin
321
                // Signed MULT64
322
                o_alu_operation = SMLALH;
323
                o_mem_srcdest_index = RAZ_REGISTER;
324
        end
325
        2'b11:
326
        begin
327
                // Signed MAC64. Need mem_srcdest as source of RdHi.
328
                o_alu_operation = SMLALH;
329
                o_mem_srcdest_index = i_instruction[19:16];
330
        end
331
        endcase
332
 
333
        if ( i_instruction[`OPCODE_EXTEND] == 1'd0 ) // Low request.
334
        begin
335
                        o_destination_index = i_instruction[15:12]; // Low register.
336
                        o_alu_operation[0]  = 1'd0;                 // Request low operation.
337
        end
338
end
339
endtask
340
 
341
// ----------------------------------------------------------------------------
342
 
343
// ===============================
344
// Decode undefined instructions.
345
// ===============================
346
task decode_und( input [34:0] i_instruction );
347
begin
348
        // Say instruction is undefined.
349
        o_und = 1;
350
 
351
        // Generate LR = PC - 4
352
        o_condition_code    = AL;
353
        o_alu_operation     = SUB;
354
        o_alu_source        = ARCH_PC;
355
        o_alu_source[32]    = INDEX_EN;
356
        o_destination_index = ARCH_LR;
357
        o_shift_source      = 4;
358
        o_shift_source[32]  = IMMED_EN;
359
        o_shift_operation   = LSL;
360
        o_shift_length      = 0;
361
        o_shift_length[32]  = IMMED_EN;
362
end
363
endtask
364
 
365
// ----------------------------------------------------------------------------
366
 
367
// ===========================================
368
// Decode software interrupt instructions.
369
// ===========================================
370
task decode_swi( input [34:0] i_instruction );
371
begin: tskDecodeSWI
372
 
373
        // Generate LR = PC - 4
374
        o_condition_code    = AL;
375
        o_alu_operation     = SUB;
376
        o_alu_source        = ARCH_PC;
377
        o_alu_source[32]    = INDEX_EN;
378
        o_destination_index = ARCH_LR;
379
        o_shift_source      = 4;
380
        o_shift_source[32]  = IMMED_EN;
381
        o_shift_operation   = LSL;
382
        o_shift_length      = 0;
383
        o_shift_length[32]  = IMMED_EN;
384
end
385
endtask
386
 
387
// ----------------------------------------------------------------------------
388
 
389
// ============================
390
// Decode halfword LOAD/STORE.
391
// ============================
392
task decode_halfword_ls( input [34:0] i_instruction );
393
begin: tskDecodeHalfWordLs
394
        reg [11:0] temp, temp1;
395
 
396
        temp = i_instruction;
397
        temp1 = i_instruction;
398
 
399
        o_condition_code = i_instruction[31:28];
400
 
401
        temp[7:4] = temp[11:8];
402
        temp[11:8] = 0;
403
        temp1[11:4] = 0;
404
 
405
        if ( i_instruction[22] ) // immediate
406
        begin
407
                process_immediate ( temp );
408
        end
409
        else
410
        begin
411
                process_instruction_specified_shift ( temp1 );
412
        end
413
 
414
        o_alu_operation     = i_instruction[23] ? ADD : SUB;
415
        o_alu_source        = { i_instruction[`BASE_EXTEND],
416
                                i_instruction[`BASE]}; // Pointer register.
417
        o_alu_source[32]    = INDEX_EN;
418
        o_mem_load          = i_instruction[20];
419
        o_mem_store         = !o_mem_load;
420
        o_mem_pre_index     = i_instruction[24];
421
 
422
        // If post-index is used or pre-index is used with writeback,
423
        // take is as a request to update the base register.
424
        o_destination_index = (i_instruction[21] || !o_mem_pre_index) ?
425
                                o_alu_source :
426
                                RAZ_REGISTER; // Pointer register already added.
427
 
428
        o_mem_srcdest_index = {i_instruction[`SRCDEST_EXTEND],
429
                               i_instruction[`SRCDEST]};
430
 
431
        // Transfer size.
432
 
433
        o_mem_unsigned_byte_enable      = 0;
434
        o_mem_unsigned_halfword_enable  = 0;
435
        o_mem_signed_halfword_enable    = 0;
436
 
437
        case ( i_instruction[6:5] )
438
        SIGNED_BYTE:            o_mem_signed_byte_enable = 1;
439
        UNSIGNED_HALF_WORD:     o_mem_unsigned_halfword_enable = 1;
440
        SIGNED_HALF_WORD:       o_mem_signed_halfword_enable = 1;
441
        default:
442
        begin
443
                o_mem_unsigned_byte_enable      = 0;
444
                o_mem_unsigned_halfword_enable  = 0;
445
                o_mem_signed_halfword_enable    = 0;
446
        end
447
        endcase
448
end
449
endtask
450
 
451
// ----------------------------------------------------------------------------
452
 
453
// ==============================
454
// Decode short multiplication.
455
// ==============================
456
task decode_mult( input [34:0] i_instruction );
457
begin: tskDecodeMult
458
 
459
`ifdef DECODE_DEBUG
460
        $display($time, "%m: MLT 32x32 -> 32 decode...");
461
`endif
462
 
463
        o_condition_code        =       i_instruction[31:28];
464
        o_flag_update           =       i_instruction[20];
465
        o_alu_operation         =       UMLALL;
466
        o_destination_index     =       {i_instruction[`DP_RD_EXTEND],
467
                                         i_instruction[19:16]};
468
 
469
        // For MUL, Rd and Rn are interchanged.
470
        o_alu_source            =       i_instruction[11:8]; // ARM rs
471
        o_alu_source[32]        =       INDEX_EN;
472
 
473
        o_shift_source          =       {i_instruction[`DP_RB_EXTEND],
474
                                         i_instruction[`DP_RB]};
475
        o_shift_source[32]      =       INDEX_EN;            // ARM rm 
476
 
477
        // ARM rn - Set for accumulate.
478
        o_shift_length          =       i_instruction[21] ?
479
                                        {i_instruction[`DP_RA_EXTEND],
480
                                         i_instruction[`DP_RD]} : 32'd0;
481
 
482
        o_shift_length[32]      =       i_instruction[21] ? INDEX_EN : IMMED_EN;
483
 
484
        // Set rh = 0.
485
        o_mem_srcdest_index = RAZ_REGISTER;
486
end
487
endtask
488
 
489
// ----------------------------------------------------------------------------
490
 
491
// =============================
492
// BX decode.
493
// =============================
494
// Converted into a MOV to PC. The task of setting the T-bit in the CPSR is
495
// the job of the writeback stage.
496
task decode_bx( input [34:0] i_instruction );
497
begin: tskDecodeBx
498 37 Revanth
        reg [34:0] temp;
499
 
500 26 Revanth
        temp = i_instruction[31:0];
501 37 Revanth
        temp[31:4] = 0; // Zero out stuff to avoid conflicts in the function.
502 26 Revanth
 
503 37 Revanth
        process_instruction_specified_shift(temp);
504 26 Revanth
 
505
        // The RAW ALU source does not matter.
506
        o_condition_code        = i_instruction[31:28];
507
        o_alu_operation         = MOV;
508
        o_destination_index     = ARCH_PC;
509
 
510
        // We will force an immediate in alu source to prevent unwanted locks.
511
        o_alu_source            = 0;
512
        o_alu_source[32]        = IMMED_EN;
513
 
514
        // Indicate switch. This is a primary differentiator. 
515
        o_switch = 1;
516
end
517
endtask
518
 
519
// ----------------------------------------------------------------------------
520
 
521
// =============================================
522
// Task for decoding load-store instructions.
523
// =============================================
524
task decode_ls( input [34:0] i_instruction );
525
begin: tskDecodeLs
526
 
527
`ifdef DECODE_DEBUG
528
        $display($time, "%m: LS decode...");
529
`endif
530
 
531
        o_condition_code = i_instruction[31:28];
532
 
533
        if ( !i_instruction[25] ) // immediate
534
        begin
535
                o_shift_source          = i_instruction[11:0];
536
                o_shift_source[32]      = IMMED_EN;
537
                o_shift_length          = 0;
538
                o_shift_length[32]      = IMMED_EN;
539
                o_shift_operation       = LSL;
540
        end
541
        else
542
        begin
543
              process_instruction_specified_shift ( i_instruction[11:0] );
544
        end
545
 
546
        o_alu_operation = i_instruction[23] ? ADD : SUB;
547
 
548
        // Pointer register.
549
        o_alu_source    = {i_instruction[`BASE_EXTEND], i_instruction[`BASE]};
550
        o_alu_source[32] = INDEX_EN;
551
        o_mem_load          = i_instruction[20];
552
        o_mem_store         = !o_mem_load;
553
        o_mem_pre_index     = i_instruction[24];
554
 
555
        // If post-index is used or pre-index is used with writeback,
556
        // take is as a request to update the base register.
557
        o_destination_index = (i_instruction[21] || !o_mem_pre_index) ?
558
                                o_alu_source :
559
                                RAZ_REGISTER; // Pointer register already added.
560
        o_mem_unsigned_byte_enable = i_instruction[22];
561
 
562
        o_mem_srcdest_index = {i_instruction[`SRCDEST_EXTEND], i_instruction[`SRCDEST]};
563
 
564
        if ( !o_mem_pre_index ) // Post-index, writeback has no meaning.
565
        begin
566
                if ( i_instruction[21] )
567
                begin
568
                        // Use it for force usr mode memory mappings.
569
                        o_mem_translate = 1'd1;
570
                end
571
        end
572
end
573
endtask
574
 
575
// ----------------------------------------------------------------------------
576
 
577
task decode_mrs( input [34:0] i_instruction );
578
begin
579
 
580
        process_immediate ( i_instruction[11:0] );
581
 
582
        o_condition_code    = i_instruction[31:28];
583
        o_destination_index = {i_instruction[`DP_RD_EXTEND], i_instruction[`DP_RD]};
584
        o_alu_source        = i_instruction[22] ? ARCH_CURR_SPSR : ARCH_CPSR;
585
        o_alu_source[32]    = INDEX_EN;
586
        o_alu_operation     = ADD;
587
end
588
endtask
589
 
590
// ----------------------------------------------------------------------------
591
 
592
task decode_msr( input [34:0] i_instruction );
593
begin
594
 
595
        if ( i_instruction[25] ) // Immediate present.
596
        begin
597
                process_immediate ( i_instruction[11:0] );
598
        end
599
        else
600
        begin
601
                process_instruction_specified_shift ( i_instruction[11:0] );
602
        end
603
 
604
        // Destination.
605
        o_destination_index = i_instruction[22] ? ARCH_CURR_SPSR : ARCH_CPSR;
606
 
607
        o_condition_code = i_instruction[31:28];
608
 
609
        // Make srcdest as SPSR. useful for MMOV.
610
        o_mem_srcdest_index = ARCH_CURR_SPSR;
611
 
612
        // Select SPSR or CPSR.
613
        o_alu_operation  = i_instruction[22] ? MMOV : FMOV;
614
 
615
        o_alu_source     = i_instruction[19:16];
616
        o_alu_source[32] = IMMED_EN;
617
 
618
        // Part of the instruction will silently fail when changing mode bits
619
        // in user mode. This is as per the ARM spec.
620
        if  ( i_cpsr_ff_mode == USR )
621
        begin
622
                o_alu_source[2:0] = 3'b0;
623
        end
624
end
625
endtask
626
 
627
// ----------------------------------------------------------------------------
628
 
629
// ========================
630
// Decode B
631
// ========================
632
task decode_branch( input [34:0] i_instruction );
633
begin
634
        // A branch is decayed into PC = PC + $signed(immed)
635
        o_condition_code        = i_instruction[31:28];
636
        o_alu_operation         = ADD;
637
        o_destination_index     = ARCH_PC;
638
        o_alu_source            = ARCH_PC;
639
        o_alu_source[32]        = INDEX_EN;
640
        o_shift_source          = ($signed(i_instruction[23:0]));
641
        o_shift_source[32]      = IMMED_EN;
642
        o_shift_operation       = LSL;
643
        o_shift_length          = i_instruction[34] ? 1 : 2; // Thumb branches sometimes need only a shift of 1.
644
        o_shift_length[32]      = IMMED_EN;
645
end
646
endtask
647
 
648
// ----------------------------------------------------------------------------
649
 
650
//
651
// Common data processing handles the common section of all 3 data processing
652
// formats.
653
//
654
task decode_data_processing( input [34:0] i_instruction );
655
begin
656
        o_condition_code        = i_instruction[31:28];
657
        o_alu_operation         = i_instruction[24:21];
658
        o_flag_update           = i_instruction[20];
659
        o_destination_index     = {i_instruction[`DP_RD_EXTEND], i_instruction[`DP_RD]};
660
        o_alu_source            = i_instruction[`DP_RA];
661
        o_alu_source[32]        = INDEX_EN;
662
        o_mem_srcdest_index     = ARCH_CURR_SPSR;
663
 
664
        if (    o_alu_operation == CMP ||
665
                o_alu_operation == CMN ||
666
                o_alu_operation == TST ||
667
                o_alu_operation == TEQ )
668
        begin
669
                o_destination_index = RAZ_REGISTER;
670
        end
671
 
672
        casez ( {i_instruction[25],i_instruction[7],i_instruction[4]} )
673
        3'b1zz: process_immediate ( i_instruction );
674
        3'b0z0: process_instruction_specified_shift ( i_instruction );
675
        3'b001: process_register_specified_shift ( i_instruction );
676
        default:
677
        begin
678
                $display("Error : Decoder Error.");
679
                $finish;
680
        end
681
        endcase
682
end
683
endtask
684
 
685
// ----------------------------------------------------------------------------
686
 
687
//
688
// If an immediate value is to be rotated right by an 
689
// immediate value, this mode is used.
690
//
691
task process_immediate ( input [34:0] instruction );
692
begin
693 43 Revanth
        dp1 = 1;
694 26 Revanth
 
695
        o_shift_length          = instruction[11:8] << 1'd1;
696
        o_shift_length[32]      = IMMED_EN;
697
        o_shift_source          = instruction[7:0];
698
        o_shift_source[32]      = IMMED_EN;
699
        o_shift_operation       = RORI;
700
end
701
endtask
702
 
703
// ----------------------------------------------------------------------------
704
 
705
//
706
// The shifter source is a register but the 
707
// amount to shift is in the instruction itself.
708
//
709
task process_instruction_specified_shift ( input [34:0] instruction );
710
begin
711 43 Revanth
         dp2 = 1;
712 26 Revanth
 
713
        // ROR #0 = RRC, ASR #0 = ASR #32, LSL #0 = LSL #0, LSR #0 = LSR #32 
714
        // ROR #n = ROR_1 #n ( n > 0 )
715
        o_shift_length          = instruction[11:7];
716
        o_shift_length[32]      = IMMED_EN;
717
        o_shift_source          = {i_instruction[`DP_RB_EXTEND],instruction[`DP_RB]};
718
        o_shift_source[32]      = INDEX_EN;
719
        o_shift_operation       = instruction[6:5];
720
 
721
        case ( o_shift_operation )
722
                LSR: if ( !o_shift_length[31:0] ) o_shift_length[31:0] = 32;
723
                ASR: if ( !o_shift_length[31:0] ) o_shift_length[31:0] = 32;
724
                ROR:
725
                begin
726
                        if ( !o_shift_length[31:0] )
727
                                o_shift_operation    = RRC;
728
                        else
729
                                o_shift_operation    = ROR_1;
730
                                // Differs in carry generation behavior.
731
                end
732
                default: // For lint.
733
                begin
734
                end
735
        endcase
736
 
737
        // Reinforce the fact.
738
        o_shift_length[32] = IMMED_EN;
739
end
740
endtask
741
 
742
// ----------------------------------------------------------------------------
743
 
744
// The source register and the amount of shift are both in registers.
745
task process_register_specified_shift ( input [34:0] instruction );
746
begin
747
`ifdef DECODE_DEBUG
748
        $display("%m Process register specified shift...");
749
`endif
750
 
751 43 Revanth
        dp3 = 1;
752 26 Revanth
 
753
        o_shift_length          = instruction[11:8];
754
        o_shift_length[32]      = INDEX_EN;
755
        o_shift_source          = {i_instruction[`DP_RB_EXTEND], instruction[`DP_RB]};
756
        o_shift_source[32]      = INDEX_EN;
757
        o_shift_operation       = instruction[6:5];
758
end
759
endtask
760
 
761
endmodule // zap_decode.v
762
`default_nettype wire

powered by: WebSVN 2.1.0

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