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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_predecode_mem_fsm.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 module sequences ARM LDM/STM CISC instructions into simpler RISC --  
25
// --   instructions. Basically LDM -> LDRs and STM -> STRs. Supports a base  --  
26
// --   restored abort model. Start instruction carries interrupt information --  
27
// --   so this cannot  block interrupts if there is a sequence of these.     --  
28
// --                                                                         --          
29
// --  Also handles SWAP instruction.                                         --  
30
// --                                                                         --  
31
// --  SWAP steps:                                                            --  
32
// --  - Read data from [Rn] into DUMMY. - LDR DUMMY0, [Rn]                   --  
33
// --  - Write data in Rm to [Rn]        - STR Rm, [Rn]                       --  
34
// --  - Copy data from DUMMY to Rd.     - MOV Rd, DUMMY0                     --          
35
// --                                                                         --          
36
// -----------------------------------------------------------------------------
37
 
38
`default_nettype none
39
 
40
module zap_predecode_mem_fsm
41
(
42
        // Clock and reset.
43
        input wire              i_clk,                  // ZAP clock.
44
        input wire              i_reset,                // ZAP reset.
45
 
46
        // Instruction information from the fetch.
47
        input wire  [34:0]      i_instruction,
48
        input wire              i_instruction_valid,
49
 
50
        // Interrupt information from the fetch.
51
        input wire              i_irq,
52
        input wire              i_fiq,
53
 
54
        // CPSR
55
        input wire              i_cpsr_t,
56
 
57
        // Pipeline control signals.
58
        input wire              i_clear_from_writeback,
59
        input wire              i_data_stall,
60
        input wire              i_clear_from_alu,
61
        input wire              i_stall_from_shifter,
62
        input wire              i_issue_stall,
63
 
64
        // Instruction output.
65
        output reg [35:0]       o_instruction,
66
        output reg              o_instruction_valid,
67
 
68
        // We generate a stall.
69
        output reg              o_stall_from_decode,
70
 
71
        // Possibly masked interrupts.
72
        output reg              o_irq,
73
        output reg              o_fiq
74
);
75
 
76
///////////////////////////////////////////////////////////////////////////////
77
 
78
`include "zap_defines.vh"
79
`include "zap_localparams.vh"
80
`include "zap_functions.vh"
81
 
82
///////////////////////////////////////////////////////////////////////////////
83
 
84
// Instruction breakup
85 43 Revanth
wire [3:0]  cc                  ;
86
wire [2:0]  id                  ;
87
wire        pre_index           ;
88
wire        up                  ;
89
wire        s_bit               ;
90
wire        writeback           ;
91
wire        load                ;
92
wire [3:0]  base                ;
93
wire [15:0] reglist             ;
94 26 Revanth
 
95 43 Revanth
// Instruction breakup assignment.
96
assign {cc, id, pre_index, up, s_bit, writeback, load, base, reglist} = i_instruction;
97 26 Revanth
 
98 43 Revanth
wire        store                = !load;
99
wire        link                 = i_instruction[24];
100
wire [11:0] branch_offset        = i_instruction[11:0];
101 26 Revanth
 
102 43 Revanth
wire [11:0] oc_offset;                  // Ones counter offset.
103
reg  [3:0]  state_ff, state_nxt;        // State.
104
reg  [15:0] reglist_ff, reglist_nxt;    // Register list.
105
reg     [31:0]  const_ff, const_nxt;    // For BLX - const reg.
106 37 Revanth
 
107 26 Revanth
///////////////////////////////////////////////////////////////////////////////
108
 
109
// States.
110
localparam IDLE         = 0;
111
localparam MEMOP        = 1;
112
localparam WRITE_PC     = 2;
113
localparam SWAP1        = 3;
114
localparam SWAP2        = 4;
115
localparam LMULT_BUSY   = 5;
116
localparam BL_S1        = 6;
117
localparam SWAP3        = 7;
118 37 Revanth
localparam BLX1_ARM_S0  = 8;
119
localparam BLX1_ARM_S1  = 9;
120
localparam BLX1_ARM_S2  = 10;
121
localparam BLX1_ARM_S3  = 11;
122
localparam BLX1_ARM_S4  = 12;
123
localparam BLX1_ARM_S5  = 13;
124
localparam BLX2_ARM_S0  = 14;
125 26 Revanth
 
126
///////////////////////////////////////////////////////////////////////////////
127
 
128
assign oc_offset = ones_counter(i_instruction);
129
 
130
///////////////////////////////////////////////////////////////////////////////
131
 
132
// Next state and output logic.
133
always @*
134
begin
135 37 Revanth
        const_nxt = const_ff;
136
 
137 26 Revanth
        // Block interrupts by default.
138
        o_irq = 0;
139
        o_fiq = 0;
140
 
141
        // Avoid latch inference.
142
        state_nxt               = state_ff;
143
        o_instruction           = i_instruction;
144
        o_instruction_valid     = i_instruction_valid;
145
        reglist_nxt             = reglist_ff;
146
        o_stall_from_decode     = 1'd0;
147
 
148
        case ( state_ff )
149 37 Revanth
                BLX1_ARM_S0: // SCONST = ($signed(constant) << 2) + ( H << 1 ))
150
                begin: blk3223
151
                        reg H;
152
 
153
                        o_stall_from_decode = 1'd1;
154
 
155
                        H = i_instruction[24];
156
                        const_nxt = ( { {8{i_instruction[23]}} , i_instruction[23:0] } << 2 ) + ( H << 1 );
157
 
158
                        // MOV DUMMY0, SCONST[7:0] ror 0
159
                        o_instruction[31:0] = {AL, 2'b00, 1'b1, MOV, 1'd0, 4'd0, 4'd0, 4'd0, const_nxt[7:0]};
160
                        {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0;
161
                end
162
 
163
                BLX1_ARM_S1:
164
                begin
165
                        o_stall_from_decode = 1'd1;
166
 
167
                        // ORR DUMMY0, DUMMY0, SCONST[15:8]  ror 12*2 
168
                        o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd12, const_nxt[15:8]};
169
                        {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0;
170
                        {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0;
171
                end
172
 
173
                BLX1_ARM_S2:
174
                begin
175
                        o_stall_from_decode = 1'd1;
176
 
177
                        // ORR DUMMY0, DUMMY0, SCONST[23:16] ror 8*2
178
                         o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd8, const_nxt[23:16]};
179
                        {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0;
180
                        {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0;
181
                end
182
 
183
                BLX1_ARM_S3:
184
                begin
185
                        o_stall_from_decode = 1'd1;
186
 
187
                        // ORR DUMMY0, DUMMY0, SCONST[31:24] ror 4*2
188
                         o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd4, const_nxt[31:24]};
189
                        {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0;
190
                        {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0;
191
                end
192
 
193
                BLX1_ARM_S4:
194
                begin
195
                        o_stall_from_decode = 1'd1;
196
 
197
                        // ORR DUMMY0, DUMMY0, 1 - Needed to indicate a switch
198 38 Revanth
                        // to Thumb if needed.                       
199 37 Revanth
                         o_instruction[31:0] = {AL, 2'b00, 1'b1, ORR, 1'd0, 4'd0, 4'd0, 4'd0, !i_cpsr_t};
200
                        {o_instruction[`DP_RD_EXTEND], o_instruction[`DP_RD]} = ARCH_DUMMY_REG0;
201
                        {o_instruction[`DP_RA_EXTEND], o_instruction[`DP_RA]} = ARCH_DUMMY_REG0;
202
                end
203
 
204
                BLX1_ARM_S5:
205
                begin
206
                        // Remove stall.
207
                        o_stall_from_decode = 1'd0;
208
 
209
                        // BX DUMMY0
210
                        o_instruction = 32'hE12FFF10;
211
                        {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]} = ARCH_DUMMY_REG0;
212
                end
213
 
214
                BLX2_ARM_S0:
215
                begin
216
                        // Remove stall.
217
                        o_stall_from_decode     = 1'd0;
218
 
219
                        // BX Rm. Just remove the L bit. Conditional is passed
220
                        // on.
221
                        o_instruction           = i_instruction;
222
                        o_instruction[5]        = 1'd0;
223
                end
224
 
225 26 Revanth
                IDLE:
226
                begin
227 37 Revanth
                        // BLX1 detected. Unconditional!!!
228
                        // Immediate Offset.
229
                        if ( i_instruction[31:25] == BLX1[31:25] && i_instruction_valid )
230
                        begin
231
                                $display($time, "%m: BLX1 detected!");
232 38 Revanth
 
233 37 Revanth
                                // We must generate a SUBAL LR,PC,4 ROR 0
234
                                // This makes LR have the value
235
                                // PC+8-4=PC+4 which is the address of
236
                                // the next instruction.
237
                                o_instruction           = {AL, 2'b00, 1'b1, SUB, 1'd0, 4'd14, 4'd15, 12'd4};
238
 
239
                                // In Thumb mode, we must generate PC+4-2
240
                                if ( i_cpsr_t )
241
                                begin
242
                                        o_instruction[11:0] = 12'd2; // Modify the instruction.
243
                                end
244
 
245
                                o_stall_from_decode     = 1'd1; // Stall the core.
246
                                state_nxt               = BLX1_ARM_S0;
247
                        end
248
                        else if ( i_instruction[27:4] == BLX2[27:4] && i_instruction_valid ) // BLX2 detected. Register offset. CONDITIONAL.
249
                        begin
250
                                $display($time, "%m: BLX2 detected!");
251 38 Revanth
 
252 37 Revanth
                                // Write address of next instruction to LR. Now this
253
                                // depends on the mode we're in. Mode in the sense
254
                                // ARM/Thumb. We need to look at i_cpsr_t.
255
 
256
                                // We need to generate a SUBcc LR,PC,4 ROR 0
257
                                // to store the next instruction address in
258
                                // LR.
259
                                o_instruction           = {i_instruction[31:28], 2'b00, 1'b1, SUB, 1'd0, 4'd14, 4'd15, 12'd4};
260
 
261
                                // In Thumb mode, we need to remove 2 from PC
262
                                // instead of 4.
263
                                if ( i_cpsr_t )
264
                                begin
265
                                        o_instruction[11:0] = 12'd2; // modify instr.
266
                                end
267
 
268
                                o_stall_from_decode     = 1'd1; // Stall the core.
269
                                state_nxt               = BLX2_ARM_S0;
270
                        end
271 26 Revanth
                        // LDM/STM detected...
272 37 Revanth
                        else if ( id == 3'b100 && i_instruction_valid )
273 26 Revanth
                        begin
274
                                // Backup base register.
275
                                // MOV DUMMY0, Base
276
`ifdef LDM_DEBUG
277
                                $display($time, "%m: Load/Store Multiple detected!");
278
`endif
279
 
280
                                if ( up )
281
                                begin
282
                                        o_instruction = {cc, 2'b00, 1'b0, MOV,
283
                                                 1'b0, 4'd0, 4'd0, 8'd0, base};
284
 
285
                                        {o_instruction[`DP_RD_EXTEND],
286
                                         o_instruction[`DP_RD]}
287
                                                = ARCH_DUMMY_REG0;
288
                                end
289
                                else
290
                                begin
291
                                        // SUB DUMMY0, BASE, OFFSET
292
                                        o_instruction = {cc, 2'b00, 1'b1, SUB,
293
                                                  1'd0, base, 4'd0, oc_offset};
294
 
295
                                        {o_instruction[`DP_RD_EXTEND],
296
                                         o_instruction[`DP_RD]} =
297
                                                ARCH_DUMMY_REG0;
298
                                end
299
 
300
                                o_instruction_valid = 1'd1;
301
                                reglist_nxt = reglist;
302
 
303
                                state_nxt = MEMOP;
304
                                o_stall_from_decode = 1'd1;
305
 
306
                                // Since this instruction does not change the 
307
                                // actual state of the CPU, an interrupt may be 
308
                                // taken on this.
309
                                o_irq = i_irq;
310
                                o_fiq = i_fiq;
311
                        end
312
                        else if ( i_instruction[27:23] == 5'b00010 &&
313
                                  i_instruction[21:20] == 2'b00 &&
314 37 Revanth
                                  i_instruction[11:4] == 4'b1001 && i_instruction_valid ) // SWAP
315 26 Revanth
                        begin
316
                                // Swap 
317
`ifdef LDM_DEBUG
318
                                $display($time, "%m: Detected SWAP instruction!");
319
`endif
320
 
321
                                o_irq = i_irq;
322
                                o_fiq = i_fiq;
323
 
324
                                // dummy = *(rn) - LDR ARCH_DUMMY_REG0, [rn, #0]
325
                                state_nxt = SWAP1;
326
 
327
                                o_instruction  = {cc, 3'b010, 1'd1, 1'd0,
328
                                i_instruction[22], 1'd0, 1'd1,
329
                                i_instruction[19:16], 4'b0000, 12'd0};
330
                                // The 0000 is replaced with dummy0 below.
331
 
332
                                {o_instruction[`SRCDEST_EXTEND],
333
                                 o_instruction[`SRCDEST]} = ARCH_DUMMY_REG0;
334
 
335
                                o_instruction_valid = 1'd1;
336
                                o_stall_from_decode = 1'd1;
337
                        end
338
                        else if ( i_instruction[27:23] == 5'd1 &&
339 37 Revanth
                                  i_instruction[7:4] == 4'b1001 && i_instruction_valid )
340 26 Revanth
                        begin
341
                                        // LMULT
342
                                        state_nxt           = LMULT_BUSY;
343
                                        o_stall_from_decode = 1'd1;
344
                                        o_irq               = i_irq;
345
                                        o_fiq               = i_fiq;
346
                                        o_instruction       = i_instruction;
347
                                        o_instruction_valid = i_instruction_valid;
348
                        end
349
                        else if ( i_instruction[27:25] == 3'b101 &&
350 37 Revanth
                                  i_instruction[24] && i_instruction_valid ) // BL.
351 26 Revanth
                        begin
352
                                // Move to new state. In that state, we will 
353
                                // generate a plain branch.
354
                                state_nxt = BL_S1;
355
 
356
                                // PC will stall preventing the fetch from 
357
                                // presenting new data.
358
                                o_stall_from_decode = 1'd1;
359
 
360
                                if ( i_cpsr_t == 1'd0 ) // ARM
361
                                begin
362
                                        // PC is 8 bytes ahead.
363
                                        // Craft a SUB LR, PC, 4.
364
                                        o_instruction = {i_instruction[31:28],
365
                                                         28'h24FE004};
366
                                end
367
                                else
368
                                begin
369
                                        // PC is 4 bytes ahead...
370
                                        // Craft a SUB LR, PC, 1 so that return 
371
                                        // goes to the next 16bit instruction 
372
                                        // and making LSB of LR = 1.
373
                                         o_instruction = {i_instruction[31:28],
374
                                                                28'h24FE001};
375
                                end
376
 
377
                                // Sell it as a valid instruction
378
                                o_instruction_valid = 1;
379
 
380
                                // Silence interrupts if a BL instruction is 
381
                                // seen.
382
                                o_irq = 0;
383
                                o_fiq = 0;
384
                        end
385
                        else
386
                        begin
387
                                // Be transparent.
388
                                state_nxt               = state_ff;
389
                                o_stall_from_decode     = 1'd0;
390
                                o_instruction           = i_instruction;
391
                                o_instruction_valid     = i_instruction_valid;
392
                                reglist_nxt             = 16'd0;
393
                                o_irq                   = i_irq;
394
                                o_fiq                   = i_fiq;
395
                        end
396
                end
397
 
398
                BL_S1:
399
                begin
400
                        // Launch out the original instruction clearing the
401
                        // link bit. This is like MOV PC, <Whatever>
402
                        o_instruction = i_instruction & ~(1 << 24);
403
                        o_instruction_valid = i_instruction_valid;
404
 
405
                        // Move to IDLE state.
406
                        state_nxt       =       IDLE;
407
 
408
                        // Free the fetch from your clutches.
409
                        o_stall_from_decode = 1'd0;
410
 
411
                        // Continue to silence interrupts.
412
                        o_irq           = 0;
413
                        o_fiq           = 0;
414
                end
415
 
416
                LMULT_BUSY:
417
                begin
418
                        o_irq                   = 0;
419
                        o_fiq                   = 0;
420
                        o_instruction           = {1'd1, i_instruction};
421
                        o_instruction_valid     = i_instruction_valid;
422
                        o_stall_from_decode     = 1'd0;
423
                        state_nxt               = IDLE;
424
                end
425
 
426
                SWAP1, SWAP3:
427
                begin
428
                        // STR Rm, [Rn, #0]
429
 
430
                        o_irq = 0;
431
                        o_fiq = 0;
432
 
433
                        // If in SWAP3, end the sequence so get next operation
434
                        // in when we move to IDLE.
435
                        o_stall_from_decode = state_ff == SWAP3 ? 1'd0 : 1'd1;
436
 
437
                        o_instruction_valid = 1;
438
                        o_instruction = {cc, 3'b010, 1'd1, 1'd0,
439
                                        i_instruction[22], 1'd0, 1'd0,
440
                                        i_instruction[19:16],
441
                                        i_instruction[3:0], 12'd0}; // BUG FIX
442
 
443
                        state_nxt = state_ff == SWAP3 ? IDLE : SWAP2;
444
                end
445
 
446
                SWAP2:
447
                begin:SWP2BLK
448
                        // MOV Rd, DUMMY0
449
 
450
                        reg [3:0] rd;
451
 
452
                        rd = i_instruction[15:12];
453
 
454
                        // Keep waiting. Next we initiate a read to ensure
455
                        // write buffer gets flushed.
456
                        o_stall_from_decode = 1'd1;
457
                        o_instruction_valid = 1'd1;
458
 
459
                        o_irq = 0;
460
                        o_fiq = 0;
461
 
462
                        o_instruction = {cc, 2'b00, 1'd0, MOV, 1'd0, 4'b0000,
463
                                         rd, 12'd0}; // ALU src doesn't matter.
464
 
465
                        {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]}
466
                                        = ARCH_DUMMY_REG0;
467
 
468
                        state_nxt = SWAP3;
469
                end
470
 
471
                MEMOP:
472
                begin: mem_op_blk_1
473
 
474
                        // Memory operations happen here.
475
 
476
                        reg [3:0] pri_enc_out;
477
 
478
                        pri_enc_out = pri_enc(reglist_ff);
479
                        reglist_nxt = reglist_ff & ~(16'd1 << pri_enc_out);
480
 
481
                        o_irq = 0;
482
                        o_fiq = 0;
483
 
484
                        // The map function generates a base restore 
485
                        // instruction if reglist = 0.
486
                        o_instruction = map ( i_instruction, pri_enc_out,
487
                                                                reglist_ff );
488
                        o_instruction_valid = 1'd1;
489
 
490
                        if ( reglist_ff == 0 )
491
                        begin
492
                                if ( i_instruction[ARCH_PC] && load )
493
                                begin
494
                                        o_stall_from_decode     = 1'd1;
495
                                        state_nxt               = WRITE_PC;
496
                                end
497
                                else
498
                                begin
499
                                        o_stall_from_decode     = 1'd0;
500
                                        state_nxt               = IDLE;
501
                                end
502
                        end
503
                        else
504
                        begin
505
                                state_nxt = MEMOP;
506
                                o_stall_from_decode = 1'd1;
507
                        end
508
                end
509
 
510
                // If needed, we finally write to the program counter as 
511
                // either a MOV PC, LR or MOVS PC, LR.
512
                WRITE_PC:
513
                begin
514
                        // MOV(S) PC, ARCH_DUMMY_REG1
515
                        state_nxt = IDLE;
516
                        o_stall_from_decode = 1'd0;
517
 
518
                        o_instruction =
519
                        { cc, 2'b00, 1'd0, MOV, s_bit, 4'd0, ARCH_PC,
520
                                                                8'd0, 4'd0 };
521
 
522
                        {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]}
523
                                        = ARCH_DUMMY_REG1;
524
 
525
                        o_instruction_valid = 1'd1;
526
                        o_irq = 0;
527
                        o_fiq = 0;
528
                end
529
        endcase
530
end
531
 
532
///////////////////////////////////////////////////////////////////////////////
533
 
534
function [33:0] map ( input [31:0] instr, input [3:0] enc, input [15:0] list );
535
// These override the globals within the function scope.
536 43 Revanth
reg [3:0]       cc;
537
reg [2:0]       id;
538
reg             pre_index;
539
reg             up;
540
reg             s_bit;
541
reg             writeback;
542
reg             load;
543
reg [3:0]       base;
544
reg [15:0]      reglist;
545
reg             store;
546
reg             restore;
547 26 Revanth
begin
548
        restore = 0;
549
 
550 43 Revanth
        {cc, id, pre_index, up, s_bit, writeback, load, base, reglist} = instr;
551 26 Revanth
 
552 43 Revanth
        store = !load;
553 26 Revanth
        map = instr;
554
        map = map & ~(1<<22); // No byte access.
555
        map = map & ~(1<<25); // Constant Offset (of 4).
556
        map[23] = 1'd1;       // Hard wired to increment.
557
 
558
        map[11:0] = 12'd4;          // Offset
559
        map[27:26] = 2'b01;         // Memory instruction.
560
 
561
        map[`SRCDEST] = enc;
562
        {map[`BASE_EXTEND],map[`BASE]} = ARCH_DUMMY_REG0;//Use as base register.
563
 
564
        // If not up, then DA -> IB and DB -> IA.
565
        if ( !up ) // DA or DB.
566
        begin
567
                map[24]   = !map[24];   // Post <---> Pre switch.
568
        end
569
 
570
        // Since the indexing has swapped (possibly), we must rethink map[21].
571
        if ( map[24] == 0 ) // Post index.
572
        begin
573
                map[21] = 1'd0; // Writeback is implicit.
574
        end
575
        else // Pre-index - Must specify writeback.
576
        begin
577
                map[21] = 1'd1;
578
        end
579
 
580
        if ( list == 0 ) // Catch 0 list here itself...
581
        begin
582
                // Restore base. MOV Rbase, DUMMY0
583
                if ( writeback )
584
                begin
585
                        restore = 1;
586
 
587
                        if ( up ) // Original instruction asked increment.
588
                        begin
589
                                map =
590
                                { cc, 2'b0, 1'b0, MOV, 1'b0, 4'd0,
591
                                                base, 8'd0, 4'd0 };
592
 
593
                                {map[`DP_RB_EXTEND],map[`DP_RB]} =
594
                                                ARCH_DUMMY_REG0;
595
                        end
596
                        else
597
                        begin // Restore.
598
                                // SUB BASE, BASE, #OFFSET
599
                                map = {cc, 2'b00, 1'b1, SUB,
600
                                                1'd0, base, base, oc_offset};
601
                        end
602
                end
603
                else
604
                begin
605
                        map = 32'd0; // Wasted cycle.
606
                end
607
        end
608
        else if ( (store && s_bit) || (load && s_bit && !list[15]) )
609
        // STR with S bit or LDR with S bit and no PC - force user bank access.
610
        begin
611
                        case ( map[`SRCDEST] ) // Force user bank.
612
                        8: {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R8;
613
                        9: {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R9;
614
                        10:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R10;
615
                        11:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R11;
616
                        12:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R12;
617
                        13:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R13;
618
                        14:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R14;
619
                        endcase
620
        end
621
        else if ( load && enc == 15  )
622
        //
623
        // Load with PC in register list. Load to dummy register. 
624
        // Will never use user bank.
625
        //
626
        begin
627
                        //
628
                        // If S = 1, perform an atomic return.
629
                        // If S = 0, just write to PC i.e., a jump.
630
                        //
631
                        // For now, load to ARCH_DUMMY_REG1.
632
                        //
633
                        {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_DUMMY_REG1;
634
        end
635
end
636
endfunction
637
 
638
///////////////////////////////////////////////////////////////////////////////
639
 
640
always @ (posedge i_clk)
641
begin
642
        if      ( i_reset )                             clear;
643
        else if ( i_clear_from_writeback)               clear;
644
        else if ( i_data_stall )                        begin end // Stall CPU.
645
        else if ( i_clear_from_alu )                    clear;
646
        else if ( i_stall_from_shifter )                begin end
647
        else if ( i_issue_stall )                       begin end
648
        else
649
        begin
650
                state_ff   <= state_nxt;
651
                reglist_ff <= reglist_nxt;
652 37 Revanth
                const_ff   <= const_nxt;
653 26 Revanth
        end
654
end
655
 
656
///////////////////////////////////////////////////////////////////////////////
657
 
658
// Unit is reset.
659
task clear;
660
begin
661
        state_ff                <= IDLE;
662
        reglist_ff              <= 16'd0;
663 37 Revanth
        const_ff                <= 32'd0;
664 26 Revanth
end
665
endtask
666
 
667
// Counts the number of ones and multiplies that by 4 to get final
668
// address offset.
669
function  [11:0] ones_counter (
670
        input [15:0]    i_word    // Register list.
671
);
672
begin: blk1
673
        integer i;
674
        reg [11:0] offset;
675
 
676
        offset = 0;
677
 
678
        // Counter number of ones.
679
        for(i=0;i<16;i=i+1)
680
                offset = offset + i_word[i];
681
 
682
        // Since LDM and STM occur only on 4 byte regions, compute the
683
        // net offset.
684
        offset = (offset << 2); // Multiply by 4.
685
 
686
        ones_counter = offset;
687
end
688
endfunction
689
 
690
//
691
// Function to model a 16-bit priority encoder.
692
//
693
 
694
// Priority encoder.
695
function  [3:0] pri_enc ( input [15:0] in );
696
begin: priEncFn
697
                casez ( in )
698
                16'b????_????_????_???1: pri_enc = 4'd0;
699
                16'b????_????_????_??10: pri_enc = 4'd1;
700
                16'b????_????_????_?100: pri_enc = 4'd2;
701
                16'b????_????_????_1000: pri_enc = 4'd3;
702
                16'b????_????_???1_0000: pri_enc = 4'd4;
703
                16'b????_????_??10_0000: pri_enc = 4'd5;
704
                16'b????_????_?100_0000: pri_enc = 4'd6;
705
                16'b????_????_1000_0000: pri_enc = 4'd7;
706
                16'b????_???1_0000_0000: pri_enc = 4'd8;
707
                16'b????_??10_0000_0000: pri_enc = 4'd9;
708
                16'b????_?100_0000_0000: pri_enc = 4'hA;
709
                16'b????_1000_0000_0000: pri_enc = 4'hB;
710
                16'b???1_0000_0000_0000: pri_enc = 4'hC;
711
                16'b??10_0000_0000_0000: pri_enc = 4'hD;
712
                16'b?100_0000_0000_0000: pri_enc = 4'hE;
713
                16'b1000_0000_0000_0000: pri_enc = 4'hF;
714
                default:                 pri_enc = 4'h0;
715
                endcase
716
end
717
endfunction
718
 
719
endmodule // zap_predecode_mem_fsm.v
720
`default_nettype wire

powered by: WebSVN 2.1.0

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