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 38

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 38 Revanth
                        // to Thumb if needed.                       
206 37 Revanth
                         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
                                $display($time, "%m: BLX1 detected!");
239 38 Revanth
 
240 37 Revanth
                                // We must generate a SUBAL LR,PC,4 ROR 0
241
                                // This makes LR have the value
242
                                // PC+8-4=PC+4 which is the address of
243
                                // the next instruction.
244
                                o_instruction           = {AL, 2'b00, 1'b1, SUB, 1'd0, 4'd14, 4'd15, 12'd4};
245
 
246
                                // In Thumb mode, we must generate PC+4-2
247
                                if ( i_cpsr_t )
248
                                begin
249
                                        o_instruction[11:0] = 12'd2; // Modify the instruction.
250
                                end
251
 
252
                                o_stall_from_decode     = 1'd1; // Stall the core.
253
                                state_nxt               = BLX1_ARM_S0;
254
                        end
255
                        else if ( i_instruction[27:4] == BLX2[27:4] && i_instruction_valid ) // BLX2 detected. Register offset. CONDITIONAL.
256
                        begin
257
                                $display($time, "%m: BLX2 detected!");
258 38 Revanth
 
259 37 Revanth
                                // Write address of next instruction to LR. Now this
260
                                // depends on the mode we're in. Mode in the sense
261
                                // ARM/Thumb. We need to look at i_cpsr_t.
262
 
263
                                // We need to generate a SUBcc LR,PC,4 ROR 0
264
                                // to store the next instruction address in
265
                                // LR.
266
                                o_instruction           = {i_instruction[31:28], 2'b00, 1'b1, SUB, 1'd0, 4'd14, 4'd15, 12'd4};
267
 
268
                                // In Thumb mode, we need to remove 2 from PC
269
                                // instead of 4.
270
                                if ( i_cpsr_t )
271
                                begin
272
                                        o_instruction[11:0] = 12'd2; // modify instr.
273
                                end
274
 
275
                                o_stall_from_decode     = 1'd1; // Stall the core.
276
                                state_nxt               = BLX2_ARM_S0;
277
                        end
278 26 Revanth
                        // LDM/STM detected...
279 37 Revanth
                        else if ( id == 3'b100 && i_instruction_valid )
280 26 Revanth
                        begin
281
                                // Backup base register.
282
                                // MOV DUMMY0, Base
283
`ifdef LDM_DEBUG
284
                                $display($time, "%m: Load/Store Multiple detected!");
285
`endif
286
 
287
                                if ( up )
288
                                begin
289
                                        o_instruction = {cc, 2'b00, 1'b0, MOV,
290
                                                 1'b0, 4'd0, 4'd0, 8'd0, base};
291
 
292
                                        {o_instruction[`DP_RD_EXTEND],
293
                                         o_instruction[`DP_RD]}
294
                                                = ARCH_DUMMY_REG0;
295
                                end
296
                                else
297
                                begin
298
                                        // SUB DUMMY0, BASE, OFFSET
299
                                        o_instruction = {cc, 2'b00, 1'b1, SUB,
300
                                                  1'd0, base, 4'd0, oc_offset};
301
 
302
                                        {o_instruction[`DP_RD_EXTEND],
303
                                         o_instruction[`DP_RD]} =
304
                                                ARCH_DUMMY_REG0;
305
                                end
306
 
307
                                o_instruction_valid = 1'd1;
308
                                reglist_nxt = reglist;
309
 
310
                                state_nxt = MEMOP;
311
                                o_stall_from_decode = 1'd1;
312
 
313
                                // Since this instruction does not change the 
314
                                // actual state of the CPU, an interrupt may be 
315
                                // taken on this.
316
                                o_irq = i_irq;
317
                                o_fiq = i_fiq;
318
                        end
319
                        else if ( i_instruction[27:23] == 5'b00010 &&
320
                                  i_instruction[21:20] == 2'b00 &&
321 37 Revanth
                                  i_instruction[11:4] == 4'b1001 && i_instruction_valid ) // SWAP
322 26 Revanth
                        begin
323
                                // Swap 
324
`ifdef LDM_DEBUG
325
                                $display($time, "%m: Detected SWAP instruction!");
326
`endif
327
 
328
                                o_irq = i_irq;
329
                                o_fiq = i_fiq;
330
 
331
                                // dummy = *(rn) - LDR ARCH_DUMMY_REG0, [rn, #0]
332
                                state_nxt = SWAP1;
333
 
334
                                o_instruction  = {cc, 3'b010, 1'd1, 1'd0,
335
                                i_instruction[22], 1'd0, 1'd1,
336
                                i_instruction[19:16], 4'b0000, 12'd0};
337
                                // The 0000 is replaced with dummy0 below.
338
 
339
                                {o_instruction[`SRCDEST_EXTEND],
340
                                 o_instruction[`SRCDEST]} = ARCH_DUMMY_REG0;
341
 
342
                                o_instruction_valid = 1'd1;
343
                                o_stall_from_decode = 1'd1;
344
                        end
345
                        else if ( i_instruction[27:23] == 5'd1 &&
346 37 Revanth
                                  i_instruction[7:4] == 4'b1001 && i_instruction_valid )
347 26 Revanth
                        begin
348
                                        // LMULT
349
                                        state_nxt           = LMULT_BUSY;
350
                                        o_stall_from_decode = 1'd1;
351
                                        o_irq               = i_irq;
352
                                        o_fiq               = i_fiq;
353
                                        o_instruction       = i_instruction;
354
                                        o_instruction_valid = i_instruction_valid;
355
                        end
356
                        else if ( i_instruction[27:25] == 3'b101 &&
357 37 Revanth
                                  i_instruction[24] && i_instruction_valid ) // BL.
358 26 Revanth
                        begin
359
                                // Move to new state. In that state, we will 
360
                                // generate a plain branch.
361
                                state_nxt = BL_S1;
362
 
363
                                // PC will stall preventing the fetch from 
364
                                // presenting new data.
365
                                o_stall_from_decode = 1'd1;
366
 
367
                                if ( i_cpsr_t == 1'd0 ) // ARM
368
                                begin
369
                                        // PC is 8 bytes ahead.
370
                                        // Craft a SUB LR, PC, 4.
371
                                        o_instruction = {i_instruction[31:28],
372
                                                         28'h24FE004};
373
                                end
374
                                else
375
                                begin
376
                                        // PC is 4 bytes ahead...
377
                                        // Craft a SUB LR, PC, 1 so that return 
378
                                        // goes to the next 16bit instruction 
379
                                        // and making LSB of LR = 1.
380
                                         o_instruction = {i_instruction[31:28],
381
                                                                28'h24FE001};
382
                                end
383
 
384
                                // Sell it as a valid instruction
385
                                o_instruction_valid = 1;
386
 
387
                                // Silence interrupts if a BL instruction is 
388
                                // seen.
389
                                o_irq = 0;
390
                                o_fiq = 0;
391
                        end
392
                        else
393
                        begin
394
                                // Be transparent.
395
                                state_nxt               = state_ff;
396
                                o_stall_from_decode     = 1'd0;
397
                                o_instruction           = i_instruction;
398
                                o_instruction_valid     = i_instruction_valid;
399
                                reglist_nxt             = 16'd0;
400
                                o_irq                   = i_irq;
401
                                o_fiq                   = i_fiq;
402
                        end
403
                end
404
 
405
                BL_S1:
406
                begin
407
                        // Launch out the original instruction clearing the
408
                        // link bit. This is like MOV PC, <Whatever>
409
                        o_instruction = i_instruction & ~(1 << 24);
410
                        o_instruction_valid = i_instruction_valid;
411
 
412
                        // Move to IDLE state.
413
                        state_nxt       =       IDLE;
414
 
415
                        // Free the fetch from your clutches.
416
                        o_stall_from_decode = 1'd0;
417
 
418
                        // Continue to silence interrupts.
419
                        o_irq           = 0;
420
                        o_fiq           = 0;
421
                end
422
 
423
                LMULT_BUSY:
424
                begin
425
                        o_irq                   = 0;
426
                        o_fiq                   = 0;
427
                        o_instruction           = {1'd1, i_instruction};
428
                        o_instruction_valid     = i_instruction_valid;
429
                        o_stall_from_decode     = 1'd0;
430
                        state_nxt               = IDLE;
431
                end
432
 
433
                SWAP1, SWAP3:
434
                begin
435
                        // STR Rm, [Rn, #0]
436
 
437
                        o_irq = 0;
438
                        o_fiq = 0;
439
 
440
                        // If in SWAP3, end the sequence so get next operation
441
                        // in when we move to IDLE.
442
                        o_stall_from_decode = state_ff == SWAP3 ? 1'd0 : 1'd1;
443
 
444
                        o_instruction_valid = 1;
445
                        o_instruction = {cc, 3'b010, 1'd1, 1'd0,
446
                                        i_instruction[22], 1'd0, 1'd0,
447
                                        i_instruction[19:16],
448
                                        i_instruction[3:0], 12'd0}; // BUG FIX
449
 
450
                        state_nxt = state_ff == SWAP3 ? IDLE : SWAP2;
451
                end
452
 
453
                SWAP2:
454
                begin:SWP2BLK
455
                        // MOV Rd, DUMMY0
456
 
457
                        reg [3:0] rd;
458
 
459
                        rd = i_instruction[15:12];
460
 
461
                        // Keep waiting. Next we initiate a read to ensure
462
                        // write buffer gets flushed.
463
                        o_stall_from_decode = 1'd1;
464
                        o_instruction_valid = 1'd1;
465
 
466
                        o_irq = 0;
467
                        o_fiq = 0;
468
 
469
                        o_instruction = {cc, 2'b00, 1'd0, MOV, 1'd0, 4'b0000,
470
                                         rd, 12'd0}; // ALU src doesn't matter.
471
 
472
                        {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]}
473
                                        = ARCH_DUMMY_REG0;
474
 
475
                        state_nxt = SWAP3;
476
                end
477
 
478
                MEMOP:
479
                begin: mem_op_blk_1
480
 
481
                        // Memory operations happen here.
482
 
483
                        reg [3:0] pri_enc_out;
484
 
485
                        pri_enc_out = pri_enc(reglist_ff);
486
                        reglist_nxt = reglist_ff & ~(16'd1 << pri_enc_out);
487
 
488
                        o_irq = 0;
489
                        o_fiq = 0;
490
 
491
                        // The map function generates a base restore 
492
                        // instruction if reglist = 0.
493
                        o_instruction = map ( i_instruction, pri_enc_out,
494
                                                                reglist_ff );
495
                        o_instruction_valid = 1'd1;
496
 
497
                        if ( reglist_ff == 0 )
498
                        begin
499
                                if ( i_instruction[ARCH_PC] && load )
500
                                begin
501
                                        o_stall_from_decode     = 1'd1;
502
                                        state_nxt               = WRITE_PC;
503
                                end
504
                                else
505
                                begin
506
                                        o_stall_from_decode     = 1'd0;
507
                                        state_nxt               = IDLE;
508
                                end
509
                        end
510
                        else
511
                        begin
512
                                state_nxt = MEMOP;
513
                                o_stall_from_decode = 1'd1;
514
                        end
515
                end
516
 
517
                // If needed, we finally write to the program counter as 
518
                // either a MOV PC, LR or MOVS PC, LR.
519
                WRITE_PC:
520
                begin
521
                        // MOV(S) PC, ARCH_DUMMY_REG1
522
                        state_nxt = IDLE;
523
                        o_stall_from_decode = 1'd0;
524
 
525
                        o_instruction =
526
                        { cc, 2'b00, 1'd0, MOV, s_bit, 4'd0, ARCH_PC,
527
                                                                8'd0, 4'd0 };
528
 
529
                        {o_instruction[`DP_RB_EXTEND], o_instruction[`DP_RB]}
530
                                        = ARCH_DUMMY_REG1;
531
 
532
                        o_instruction_valid = 1'd1;
533
                        o_irq = 0;
534
                        o_fiq = 0;
535
                end
536
        endcase
537
end
538
 
539
///////////////////////////////////////////////////////////////////////////////
540
 
541
function [33:0] map ( input [31:0] instr, input [3:0] enc, input [15:0] list );
542
// These override the globals within the function scope.
543
reg [3:0] base;
544
reg [3:0] srcdest;
545
reg [3:0] cc;
546
reg [2:0] id;
547
reg pre_index;
548
reg up;
549
reg s_bit;
550
reg writeback;
551
reg load;
552
reg store;
553
reg [15:0] reglist;
554
reg restore;
555
begin
556
        restore = 0;
557
 
558
        // All variables used inside the function depend solely on the i/p args.
559
        // Thus repeating the assignments.
560
 
561
        base            = instr[`BASE];
562
        srcdest         = instr[`SRCDEST];
563
        cc              = instr[31:28];
564
        id              = instr[27:25];
565
        pre_index       = instr[24];
566
        up              = instr[23];
567
        s_bit           = instr[22];
568
        writeback       = instr[21];
569
        load            = instr[20];
570
        store           = !load;
571
        reglist         = instr[15:0];
572
 
573
        map = instr;
574
        map = map & ~(1<<22); // No byte access.
575
        map = map & ~(1<<25); // Constant Offset (of 4).
576
        map[23] = 1'd1;       // Hard wired to increment.
577
 
578
        map[11:0] = 12'd4;          // Offset
579
        map[27:26] = 2'b01;         // Memory instruction.
580
 
581
        map[`SRCDEST] = enc;
582
        {map[`BASE_EXTEND],map[`BASE]} = ARCH_DUMMY_REG0;//Use as base register.
583
 
584
        // If not up, then DA -> IB and DB -> IA.
585
        if ( !up ) // DA or DB.
586
        begin
587
                map[24]   = !map[24];   // Post <---> Pre switch.
588
        end
589
 
590
        // Since the indexing has swapped (possibly), we must rethink map[21].
591
        if ( map[24] == 0 ) // Post index.
592
        begin
593
                map[21] = 1'd0; // Writeback is implicit.
594
        end
595
        else // Pre-index - Must specify writeback.
596
        begin
597
                map[21] = 1'd1;
598
        end
599
 
600
        if ( list == 0 ) // Catch 0 list here itself...
601
        begin
602
                // Restore base. MOV Rbase, DUMMY0
603
                if ( writeback )
604
                begin
605
                        restore = 1;
606
 
607
                        if ( up ) // Original instruction asked increment.
608
                        begin
609
                                map =
610
                                { cc, 2'b0, 1'b0, MOV, 1'b0, 4'd0,
611
                                                base, 8'd0, 4'd0 };
612
 
613
                                {map[`DP_RB_EXTEND],map[`DP_RB]} =
614
                                                ARCH_DUMMY_REG0;
615
                        end
616
                        else
617
                        begin // Restore.
618
                                // SUB BASE, BASE, #OFFSET
619
                                map = {cc, 2'b00, 1'b1, SUB,
620
                                                1'd0, base, base, oc_offset};
621
                        end
622
                end
623
                else
624
                begin
625
                        map = 32'd0; // Wasted cycle.
626
                end
627
        end
628
        else if ( (store && s_bit) || (load && s_bit && !list[15]) )
629
        // STR with S bit or LDR with S bit and no PC - force user bank access.
630
        begin
631
                        case ( map[`SRCDEST] ) // Force user bank.
632
                        8: {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R8;
633
                        9: {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R9;
634
                        10:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R10;
635
                        11:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R11;
636
                        12:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R12;
637
                        13:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R13;
638
                        14:{map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_USR2_R14;
639
                        endcase
640
        end
641
        else if ( load && enc == 15  )
642
        //
643
        // Load with PC in register list. Load to dummy register. 
644
        // Will never use user bank.
645
        //
646
        begin
647
                        //
648
                        // If S = 1, perform an atomic return.
649
                        // If S = 0, just write to PC i.e., a jump.
650
                        //
651
                        // For now, load to ARCH_DUMMY_REG1.
652
                        //
653
                        {map[`SRCDEST_EXTEND],map[`SRCDEST]} = ARCH_DUMMY_REG1;
654
        end
655
end
656
endfunction
657
 
658
///////////////////////////////////////////////////////////////////////////////
659
 
660
always @ (posedge i_clk)
661
begin
662
        if      ( i_reset )                             clear;
663
        else if ( i_clear_from_writeback)               clear;
664
        else if ( i_data_stall )                        begin end // Stall CPU.
665
        else if ( i_clear_from_alu )                    clear;
666
        else if ( i_stall_from_shifter )                begin end
667
        else if ( i_issue_stall )                       begin end
668
        else
669
        begin
670
                state_ff   <= state_nxt;
671
                reglist_ff <= reglist_nxt;
672 37 Revanth
                const_ff   <= const_nxt;
673 26 Revanth
        end
674
end
675
 
676
///////////////////////////////////////////////////////////////////////////////
677
 
678
// Unit is reset.
679
task clear;
680
begin
681
        state_ff                <= IDLE;
682
        reglist_ff              <= 16'd0;
683 37 Revanth
        const_ff                <= 32'd0;
684 26 Revanth
end
685
endtask
686
 
687
// Counts the number of ones and multiplies that by 4 to get final
688
// address offset.
689
//
690
function  [11:0] ones_counter (
691
        input [15:0]    i_word    // Register list.
692
);
693
begin: blk1
694
        integer i;
695
        reg [11:0] offset;
696
 
697
        offset = 0;
698
 
699
        // Counter number of ones.
700
        for(i=0;i<16;i=i+1)
701
                offset = offset + i_word[i];
702
 
703
        // Since LDM and STM occur only on 4 byte regions, compute the
704
        // net offset.
705
        offset = (offset << 2); // Multiply by 4.
706
 
707
        ones_counter = offset;
708
end
709
endfunction
710
 
711
//
712
// Function to model a 16-bit priority encoder.
713
//
714
 
715
// Priority encoder.
716
function  [3:0] pri_enc ( input [15:0] in );
717
begin: priEncFn
718
                casez ( in )
719
                16'b????_????_????_???1: pri_enc = 4'd0;
720
                16'b????_????_????_??10: pri_enc = 4'd1;
721
                16'b????_????_????_?100: pri_enc = 4'd2;
722
                16'b????_????_????_1000: pri_enc = 4'd3;
723
                16'b????_????_???1_0000: pri_enc = 4'd4;
724
                16'b????_????_??10_0000: pri_enc = 4'd5;
725
                16'b????_????_?100_0000: pri_enc = 4'd6;
726
                16'b????_????_1000_0000: pri_enc = 4'd7;
727
                16'b????_???1_0000_0000: pri_enc = 4'd8;
728
                16'b????_??10_0000_0000: pri_enc = 4'd9;
729
                16'b????_?100_0000_0000: pri_enc = 4'hA;
730
                16'b????_1000_0000_0000: pri_enc = 4'hB;
731
                16'b???1_0000_0000_0000: pri_enc = 4'hC;
732
                16'b??10_0000_0000_0000: pri_enc = 4'hD;
733
                16'b?100_0000_0000_0000: pri_enc = 4'hE;
734
                16'b1000_0000_0000_0000: pri_enc = 4'hF;
735
                default:                 pri_enc = 4'h0;
736
                endcase
737
end
738
endfunction
739
 
740
endmodule // zap_predecode_mem_fsm.v
741
`default_nettype wire

powered by: WebSVN 2.1.0

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