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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_writeback.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
`default_nettype none
25
 
26
module zap_writeback #(
27
        parameter FLAG_WDT = 32, // Flags width a.k.a CPSR.
28
        parameter PHY_REGS = 46  // Number of physical registers.
29
)
30
(
31
        // Decompile.
32 43 Revanth
        input   wire    [64*8-1:0]           i_decompile,
33
        output  reg     [64*8-1:0]           o_decompile,
34 26 Revanth
 
35
        // Shelve output.
36
        output wire                          o_shelve,
37
 
38
        // Clock and reset.
39
        input wire                           i_clk,
40 43 Revanth
        input wire                           i_reset,
41 26 Revanth
 
42
        // Inputs from memory unit valid signal.
43
        input wire                           i_valid,
44
 
45
        // The PC can either be frozen in place or changed based on signals
46
        // from other units. If a unit clears the PC, it must provide the
47
        // appropriate new value.
48
        input wire                           i_code_stall,
49
        input wire                           i_data_stall,
50
        input wire                           i_clear_from_alu,
51
        input wire      [31:0]               i_pc_from_alu,
52
        input wire                           i_stall_from_decode,
53
        input wire                           i_stall_from_issue,
54
        input wire                           i_stall_from_shifter,
55
        input wire                           i_clear_from_decode,
56
        input wire      [31:0]               i_pc_from_decode,
57
 
58
        // 4 read ports for high performance.
59
        input wire   [$clog2(PHY_REGS)-1:0] i_rd_index_0,
60
        input wire   [$clog2(PHY_REGS)-1:0] i_rd_index_1,
61
        input wire   [$clog2(PHY_REGS)-1:0] i_rd_index_2,
62
        input wire   [$clog2(PHY_REGS)-1:0] i_rd_index_3,
63
 
64
        // Memory load indicator.
65
        input wire                          i_mem_load_ff,
66
 
67
        // Write index and data and flag updates.
68
        input   wire [$clog2(PHY_REGS)-1:0] i_wr_index,
69
        input   wire [31:0]                 i_wr_data,
70
        input   wire [FLAG_WDT-1:0]         i_flags,
71
        input   wire                        i_thumb,
72
        input   wire [$clog2(PHY_REGS)-1:0] i_wr_index_1,
73
        input   wire [31:0]                 i_wr_data_1,
74
 
75
        // Interrupt indicators.
76
        input   wire                         i_irq,
77
        input   wire                         i_fiq,
78
        input   wire                         i_instr_abt,
79
        input   wire                         i_data_abt,
80
        input   wire                         i_swi,
81
        input   wire                         i_und,
82
 
83
        // Program counter, PC + 8. This value is captured in the fetch
84
        // stage and is buffered all the way through.
85
        input   wire    [31:0]               i_pc_buf_ff,
86
 
87
        // Coprocessor.
88
        input wire                              i_copro_reg_en,
89
        input wire      [$clog2(PHY_REGS)-1:0]  i_copro_reg_wr_index,
90
        input wire      [$clog2(PHY_REGS)-1:0]  i_copro_reg_rd_index,
91
        input wire      [31:0]                  i_copro_reg_wr_data,
92
        output reg      [31:0]                  o_copro_reg_rd_data_ff,
93
 
94
        // Read data from the register file.
95
        output wire     [31:0]               o_rd_data_0,
96
        output wire     [31:0]               o_rd_data_1,
97
        output wire     [31:0]               o_rd_data_2,
98
        output wire     [31:0]               o_rd_data_3,
99
 
100
        // Program counter (dedicated port).
101 43 Revanth
        output wire     [31:0]               o_pc,
102
        output wire     [31:0]               o_pc_nxt,
103 26 Revanth
 
104
        // CPSR output
105 43 Revanth
        output wire      [31:0]              o_cpsr_nxt,
106 26 Revanth
 
107
        // Clear from writeback
108
        output reg                           o_clear_from_writeback,
109
 
110
        // Hijack I/F
111
        output reg    [31:0]                  o_hijack_op1,
112
        output reg    [31:0]                  o_hijack_op2,
113
        output reg                            o_hijack_cin,
114
        output reg                            o_hijack,
115
        input wire     [31:0]                 i_hijack_sum
116
);
117
 
118 43 Revanth
`include "zap_defines.vh"
119
`include "zap_localparams.vh"
120
`include "zap_functions.vh"
121 26 Revanth
 
122 43 Revanth
// ----------------------------------------------
123
// Localparams
124
// ----------------------------------------------
125 26 Revanth
 
126 43 Revanth
`ifndef ARM_MODE
127
        `define ARM_MODE (cpsr_ff[T] == 1'd0)
128 26 Revanth
`endif
129
 
130
localparam RST_VECTOR   = 32'h00000000;
131
localparam UND_VECTOR   = 32'h00000004;
132
localparam SWI_VECTOR   = 32'h00000008;
133
localparam PABT_VECTOR  = 32'h0000000C;
134
localparam DABT_VECTOR  = 32'h00000010;
135
localparam IRQ_VECTOR   = 32'h00000018;
136
localparam FIQ_VECTOR   = 32'h0000001C;
137
 
138 43 Revanth
// ----------------------------------------------
139
// Variables
140
// ----------------------------------------------
141 26 Revanth
 
142 43 Revanth
// assertions_start
143
        reg fiq_ack;
144
        reg irq_ack;
145
        reg und_ack;
146
        reg dabt_ack;
147
        reg iabt_ack;
148
        reg swi_ack;
149
        integer irq_addr = 0;
150
        reg temp_set = 0;
151
        reg error = 0;
152
// assertions_end
153 26 Revanth
 
154 43 Revanth
reg     [31:0]                  cpsr_ff, cpsr_nxt;
155
reg     [31:0]                  pc_ff, pc_nxt;
156
reg [$clog2(PHY_REGS)-1:0]      wa1, wa2;
157
reg [31:0]                      wdata1, wdata2;
158
reg                             wen;
159
reg [31:0]                      pc_shelve_ff, pc_shelve_nxt;
160
reg                             shelve_ff, shelve_nxt;
161 26 Revanth
 
162 43 Revanth
assign  o_shelve        = shelve_ff; // Shelve the PC until it is needed.
163
assign  o_pc            = pc_ff;
164
assign  o_pc_nxt        = pc_nxt & 32'hfffffffe;
165
assign  o_cpsr_nxt      = cpsr_nxt;
166 26 Revanth
 
167 43 Revanth
// ----------------------------------------------
168
// Register file
169
// ----------------------------------------------
170 26 Revanth
 
171
zap_register_file u_zap_register_file
172
(
173
.i_clk(i_clk),
174
 .i_reset        (       i_reset         ),
175
 
176
 .i_wr_addr_a    (       wa1             ),
177
 .i_wr_addr_b    (       wa2             ),
178
 
179
 .i_wr_data_a    (       wdata1          ),
180
 .i_wr_data_b    (       wdata2          ),
181
 
182
 .i_wen          (       wen             ),
183
 
184
 .i_rd_addr_a    ( i_copro_reg_en ? i_copro_reg_rd_index : i_rd_index_0 ),
185
 .i_rd_addr_b    (       i_rd_index_1    ),
186
 .i_rd_addr_c    (       i_rd_index_2    ),
187
 .i_rd_addr_d    (       i_rd_index_3    ),
188
 
189
 .o_rd_data_a    (       o_rd_data_0     ),
190
 .o_rd_data_b    (       o_rd_data_1     ),
191
 .o_rd_data_c    (       o_rd_data_2     ),
192
 .o_rd_data_d    (       o_rd_data_3     )
193
);
194
 
195 43 Revanth
// ---------------------------------------------
196
// Combinational Logic
197
// ---------------------------------------------
198 26 Revanth
 
199 43 Revanth
always @ (*)
200 26 Revanth
begin: blk1
201
 
202
        integer i;
203
 
204 43 Revanth
        shelve_nxt    = shelve_ff;
205 26 Revanth
        pc_shelve_nxt = pc_shelve_ff;
206
 
207 43 Revanth
        // assertions_start
208
                fiq_ack  = 0;
209
                irq_ack  = 0;
210
                und_ack  = 0;
211 26 Revanth
                dabt_ack = 0;
212
                iabt_ack = 0;
213 43 Revanth
                swi_ack  = 0;
214
        // assertions_end
215 26 Revanth
 
216 43 Revanth
        o_hijack     = 0;
217 26 Revanth
        o_hijack_op1 = 0;
218
        o_hijack_op2 = 0;
219
        o_hijack_cin = 0;
220
 
221 43 Revanth
        wen     = 1'd0;
222
        wa1     = PHY_RAZ_REGISTER;
223
        wa2     = PHY_RAZ_REGISTER;
224
        wdata1  = 32'd0;
225
        wdata2  = 32'd0;
226 26 Revanth
 
227
        o_clear_from_writeback = 0;
228
 
229 43 Revanth
        pc_nxt   = pc_ff;
230 26 Revanth
        cpsr_nxt = cpsr_ff;
231
 
232
 
233 43 Revanth
        // Low priority PC control tree.
234 26 Revanth
 
235
        if ( i_clear_from_alu )
236
        begin
237
                pc_shelve(i_pc_from_alu);
238
        end
239
 
240
        else if ( i_clear_from_decode )
241
        begin
242
                pc_shelve(i_pc_from_decode);
243
        end
244
 
245
        else if ( i_code_stall )
246
        begin
247
                pc_nxt = pc_ff;
248
        end
249
        else if ( shelve_ff )
250
        begin
251
 
252
                pc_nxt     = pc_shelve_ff;
253
                shelve_nxt = 1'd0;
254
        end
255
        else
256
        begin
257
                pc_nxt = pc_ff + (i_thumb ? 32'd2 : 32'd4);
258
        end
259
 
260
 
261
        // The stuff below has more priority than the above. This means even in
262
        // a global stall, interrupts can overtake execution. Further, writes to 
263
        // PC that reach writeback can cancel a global stall. On interrupts or 
264
        // jumps, all units are flushed effectively clearing any global stalls.
265
 
266
        if ( i_data_abt         ||
267
                i_fiq           ||
268
                i_irq           ||
269
                i_instr_abt     ||
270
                i_swi           ||
271
                i_und )
272
        begin
273
                o_clear_from_writeback  = 1'd1;
274
                cpsr_nxt[I]      = 1'd1; // Mask interrupts.
275
                cpsr_nxt[T]      = 1'd0; // Go to ARM mode.
276
        end
277
 
278
        if ( i_data_abt )
279
        begin
280
                o_hijack    =  1'd1;
281
                o_hijack_op1 = i_pc_buf_ff;
282
                o_hijack_op2 = 32'd4;
283
                o_hijack_cin = 1'd0;
284
 
285
                // Returns do LR - 8 to get back to the same instruction.
286
                pc_shelve( DABT_VECTOR );
287
 
288 43 Revanth
                wen                     = 1;
289
                wdata1                  = `ARM_MODE ? i_pc_buf_ff : i_hijack_sum[31:0];
290
                wa1                     = PHY_ABT_R14;
291
                wa2                     = PHY_ABT_SPSR;
292
                wdata2                  = cpsr_ff;
293
                cpsr_nxt[`CPSR_MODE]    = ABT;
294
 
295
                // assertions_start
296 26 Revanth
                        dabt_ack = 1'd1;
297 43 Revanth
                // assertions_end
298 26 Revanth
 
299
        end
300
        else if ( i_fiq )
301
        begin
302 43 Revanth
                $display($time, " - %m :: FIQ detected.");
303
 
304 26 Revanth
                // Returns do LR - 4 to get back to the same instruction.
305
                pc_shelve ( FIQ_VECTOR );
306
 
307 43 Revanth
                wen                     = 1;
308
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
309
                wa1                     = PHY_FIQ_R14;
310
                wa2                     = PHY_FIQ_SPSR;
311
                wdata2                  = cpsr_ff;
312
                cpsr_nxt[`CPSR_MODE]    = FIQ;
313
                cpsr_nxt[F]             = 1'd1;
314
 
315
                // assertions_start
316 26 Revanth
                        fiq_ack = 1'd1;
317 43 Revanth
                // assertions_end
318 26 Revanth
        end
319
        else if ( i_irq )
320
        begin
321 43 Revanth
                $display($time, " - %m :: IRQ detected.");
322
 
323 26 Revanth
                pc_shelve (IRQ_VECTOR);
324
 
325 43 Revanth
                wen                     = 1;
326
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
327
                wa1                     = PHY_IRQ_R14;
328
                wa2                     = PHY_IRQ_SPSR;
329
                wdata2                  = cpsr_ff;
330
                cpsr_nxt[`CPSR_MODE]    = IRQ;
331 26 Revanth
                // Returns do LR - 4 to get back to the same instruction.
332
 
333 43 Revanth
                // assertions_start
334
                        irq_addr = wdata1;
335
                        irq_ack  = 1'd1;
336
                // assertions_end
337 26 Revanth
        end
338
        else if ( i_instr_abt )
339
        begin
340
                // Returns do LR - 4 to get back to the same instruction.
341
                pc_shelve (PABT_VECTOR);
342 43 Revanth
 
343 26 Revanth
                wen    = 1;
344
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
345
                wa1    = PHY_ABT_R14;
346
                wa2    = PHY_ABT_SPSR;
347
                wdata2 = cpsr_ff;
348
                cpsr_nxt[`CPSR_MODE]  = ABT;
349
 
350 43 Revanth
                // assertions_start
351 26 Revanth
                        iabt_ack = 1'd1;
352 43 Revanth
                // assertions_end
353 26 Revanth
        end
354
        else if ( i_swi )
355
        begin
356
                // Returns do LR to return to the next instruction.
357
                pc_shelve(SWI_VECTOR);
358
 
359 43 Revanth
                wen                     = 1;
360
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
361
                wa1                     = PHY_SVC_R14;
362
                wa2                     = PHY_SVC_SPSR;
363
                wdata2                  = cpsr_ff;
364
                cpsr_nxt[`CPSR_MODE]    = SVC;
365
 
366
                // assertions_start
367 26 Revanth
                        swi_ack = 1'd1;
368 43 Revanth
                // assertions_end
369 26 Revanth
        end
370
        else if ( i_und )
371
        begin
372
                // Returns do LR to return to the next instruction.
373
                pc_shelve(UND_VECTOR);
374
 
375 43 Revanth
                wen                     = 1;
376
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
377
                wa1                     = PHY_UND_R14;
378
                wa2                     = PHY_UND_SPSR;
379
                wdata2                  = cpsr_ff;
380
                cpsr_nxt[`CPSR_MODE]    = UND;
381
 
382
                // assertions_start
383 26 Revanth
                        und_ack = 1'd1;
384 43 Revanth
                // assertions_end
385 26 Revanth
        end
386
        else if ( i_copro_reg_en )
387
        begin
388 43 Revanth
               // Write to register (Coprocessor command).
389 26 Revanth
               wen      = 1;
390
               wa1      = i_copro_reg_wr_index;
391
               wdata1   = i_copro_reg_wr_data;
392
        end
393 43 Revanth
        else if ( i_valid ) // If valid,
394 26 Revanth
        begin
395
                // Only then execute the instruction at hand...
396
                cpsr_nxt                =   i_flags;
397
 
398
                // Dual write port.
399
                wen    = 1;
400
 
401
                // Port from arithmetic side
402
                wa1    = i_wr_index;
403
                wdata1 = i_wr_data;
404
 
405
                // Port from memory side.
406
                wa2    = i_mem_load_ff ? i_wr_index_1 : PHY_RAZ_REGISTER;
407
                wdata2 = i_wr_data_1;
408
 
409
                // Load to PC will trigger from writeback.
410
                if ( i_mem_load_ff && i_wr_index_1 == ARCH_PC)
411
                begin
412 43 Revanth
                        $display($time, " - %m :: Detected load to PC. Trigger a writeback.");
413
 
414 26 Revanth
                        pc_shelve (i_wr_data_1);
415
                        o_clear_from_writeback  = 1'd1;
416
                end
417
        end
418
 
419 43 Revanth
        // Ensure lower 2 bits of PC are always tied to VSS.
420 26 Revanth
        pc_nxt = pc_nxt & 32'hffff_fffe;
421
end
422
 
423 43 Revanth
// ----------------------------------------------
424
// Sequential Logic
425
// ----------------------------------------------
426 26 Revanth
 
427 43 Revanth
always @ ( posedge i_clk )
428 26 Revanth
begin
429
        if ( i_reset )
430
        begin
431
                // On reset, the CPU starts at 0 in
432
                // supervisor mode.
433
                shelve_ff                  <= 1'd0;
434
                pc_ff                      <= 32'd0;
435
                cpsr_ff                    <= SVC;
436
                cpsr_ff[I]                 <= 1'd1; // Mask IRQ.
437
                cpsr_ff[F]                 <= 1'd1; // Mask FIQ.
438
                cpsr_ff[T]                 <= 1'd0; // Start CPU in ARM mode.
439
        end
440
        else
441
        begin
442 43 Revanth
                shelve_ff                 <= shelve_nxt;
443
                pc_shelve_ff              <= pc_shelve_nxt;
444
                pc_ff                     <= pc_nxt;
445
                cpsr_ff                   <= cpsr_nxt;
446
                o_decompile               <= i_decompile;
447
                o_copro_reg_rd_data_ff    <= o_rd_data_0;
448 26 Revanth
        end
449
end
450
 
451 43 Revanth
// ----------------------------------------------
452
// Tasks
453
// ----------------------------------------------
454 26 Revanth
 
455
task pc_shelve (input [31:0] new_pc);
456
begin
457
        if (!i_code_stall )
458
        begin
459
                pc_nxt = new_pc;
460
                shelve_nxt = 1'd0; // BUG FIX.
461
        end
462
        else
463
        begin
464
                shelve_nxt = 1'd1;
465
                pc_shelve_nxt = new_pc;
466
                pc_nxt = pc_ff;
467
        end
468
end
469
endtask
470
 
471 43 Revanth
// assertions_start 
472 26 Revanth
 
473 43 Revanth
        always @ (*)
474
        if ( cpsr_nxt[`CPSR_MODE] != USR && cpsr_ff[`CPSR_MODE] == USR )
475 26 Revanth
        begin
476 43 Revanth
                if (
477
                        i_data_abt      ||
478
                        i_fiq           ||
479
                        i_irq           ||
480
                        i_instr_abt     ||
481
                        i_swi           ||
482
                        i_und
483
                 )
484
                begin
485
                        // OKAY...
486
                end
487
                else
488
                begin
489
                        $display($time, "Error : %m CPU is changing out of USR mode without an exception...");
490
                        $stop;
491
                end
492 26 Revanth
        end
493
 
494 43 Revanth
// assertions_end
495 26 Revanth
 
496
endmodule // zap_register_file.v
497
`default_nettype wire

powered by: WebSVN 2.1.0

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