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 37

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

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

powered by: WebSVN 2.1.0

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