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

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_writeback.v] - Blame information for rev 51

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 51 Revanth
// ----------------------------------------------------------------------------
123 43 Revanth
// Localparams
124 51 Revanth
// ----------------------------------------------------------------------------
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 51 Revanth
// ----------------------------------------------------------------------------
139 43 Revanth
// Variables
140 51 Revanth
// ----------------------------------------------------------------------------
141 26 Revanth
 
142 43 Revanth
reg     [31:0]                  cpsr_ff, cpsr_nxt;
143
reg     [31:0]                  pc_ff, pc_nxt;
144
reg [$clog2(PHY_REGS)-1:0]      wa1, wa2;
145
reg [31:0]                      wdata1, wdata2;
146
reg                             wen;
147
reg [31:0]                      pc_shelve_ff, pc_shelve_nxt;
148
reg                             shelve_ff, shelve_nxt;
149 26 Revanth
 
150 43 Revanth
assign  o_shelve        = shelve_ff; // Shelve the PC until it is needed.
151
assign  o_pc            = pc_ff;
152
assign  o_pc_nxt        = pc_nxt & 32'hfffffffe;
153
assign  o_cpsr_nxt      = cpsr_nxt;
154 26 Revanth
 
155 51 Revanth
// ----------------------------------------------------------------------------
156 43 Revanth
// Register file
157 51 Revanth
// ----------------------------------------------------------------------------
158 26 Revanth
 
159
zap_register_file u_zap_register_file
160
(
161
.i_clk(i_clk),
162
 .i_reset        (       i_reset         ),
163
 
164
 .i_wr_addr_a    (       wa1             ),
165
 .i_wr_addr_b    (       wa2             ),
166
 
167
 .i_wr_data_a    (       wdata1          ),
168
 .i_wr_data_b    (       wdata2          ),
169
 
170
 .i_wen          (       wen             ),
171
 
172
 .i_rd_addr_a    ( i_copro_reg_en ? i_copro_reg_rd_index : i_rd_index_0 ),
173
 .i_rd_addr_b    (       i_rd_index_1    ),
174
 .i_rd_addr_c    (       i_rd_index_2    ),
175
 .i_rd_addr_d    (       i_rd_index_3    ),
176
 
177
 .o_rd_data_a    (       o_rd_data_0     ),
178
 .o_rd_data_b    (       o_rd_data_1     ),
179
 .o_rd_data_c    (       o_rd_data_2     ),
180
 .o_rd_data_d    (       o_rd_data_3     )
181
);
182
 
183 51 Revanth
// ----------------------------------------------------------------------------
184 43 Revanth
// Combinational Logic
185 51 Revanth
// ----------------------------------------------------------------------------
186 26 Revanth
 
187 43 Revanth
always @ (*)
188 26 Revanth
begin: blk1
189
 
190
        integer i;
191
 
192 43 Revanth
        shelve_nxt    = shelve_ff;
193 26 Revanth
        pc_shelve_nxt = pc_shelve_ff;
194
 
195 43 Revanth
        o_hijack     = 0;
196 26 Revanth
        o_hijack_op1 = 0;
197
        o_hijack_op2 = 0;
198
        o_hijack_cin = 0;
199
 
200 43 Revanth
        wen     = 1'd0;
201
        wa1     = PHY_RAZ_REGISTER;
202
        wa2     = PHY_RAZ_REGISTER;
203
        wdata1  = 32'd0;
204
        wdata2  = 32'd0;
205 26 Revanth
 
206
        o_clear_from_writeback = 0;
207
 
208 43 Revanth
        pc_nxt   = pc_ff;
209 26 Revanth
        cpsr_nxt = cpsr_ff;
210
 
211
 
212 43 Revanth
        // Low priority PC control tree.
213 26 Revanth
 
214
        if ( i_clear_from_alu )
215
        begin
216
                pc_shelve(i_pc_from_alu);
217
        end
218
 
219
        else if ( i_clear_from_decode )
220
        begin
221
                pc_shelve(i_pc_from_decode);
222
        end
223
 
224
        else if ( i_code_stall )
225
        begin
226
                pc_nxt = pc_ff;
227
        end
228
        else if ( shelve_ff )
229
        begin
230
 
231
                pc_nxt     = pc_shelve_ff;
232
                shelve_nxt = 1'd0;
233
        end
234
        else
235
        begin
236
                pc_nxt = pc_ff + (i_thumb ? 32'd2 : 32'd4);
237
        end
238
 
239
 
240
        // The stuff below has more priority than the above. This means even in
241
        // a global stall, interrupts can overtake execution. Further, writes to 
242
        // PC that reach writeback can cancel a global stall. On interrupts or 
243
        // jumps, all units are flushed effectively clearing any global stalls.
244
 
245
        if ( i_data_abt         ||
246
                i_fiq           ||
247
                i_irq           ||
248
                i_instr_abt     ||
249
                i_swi           ||
250
                i_und )
251
        begin
252
                o_clear_from_writeback  = 1'd1;
253
                cpsr_nxt[I]      = 1'd1; // Mask interrupts.
254
                cpsr_nxt[T]      = 1'd0; // Go to ARM mode.
255
        end
256
 
257
        if ( i_data_abt )
258
        begin
259
                o_hijack    =  1'd1;
260
                o_hijack_op1 = i_pc_buf_ff;
261
                o_hijack_op2 = 32'd4;
262
                o_hijack_cin = 1'd0;
263
 
264
                // Returns do LR - 8 to get back to the same instruction.
265
                pc_shelve( DABT_VECTOR );
266
 
267 43 Revanth
                wen                     = 1;
268
                wdata1                  = `ARM_MODE ? i_pc_buf_ff : i_hijack_sum[31:0];
269
                wa1                     = PHY_ABT_R14;
270
                wa2                     = PHY_ABT_SPSR;
271
                wdata2                  = cpsr_ff;
272
                cpsr_nxt[`CPSR_MODE]    = ABT;
273 26 Revanth
        end
274
        else if ( i_fiq )
275
        begin
276
                // Returns do LR - 4 to get back to the same instruction.
277
                pc_shelve ( FIQ_VECTOR );
278
 
279 43 Revanth
                wen                     = 1;
280
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
281
                wa1                     = PHY_FIQ_R14;
282
                wa2                     = PHY_FIQ_SPSR;
283
                wdata2                  = cpsr_ff;
284
                cpsr_nxt[`CPSR_MODE]    = FIQ;
285
                cpsr_nxt[F]             = 1'd1;
286 26 Revanth
        end
287
        else if ( i_irq )
288
        begin
289
                pc_shelve (IRQ_VECTOR);
290
 
291 43 Revanth
                wen                     = 1;
292
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
293
                wa1                     = PHY_IRQ_R14;
294
                wa2                     = PHY_IRQ_SPSR;
295
                wdata2                  = cpsr_ff;
296
                cpsr_nxt[`CPSR_MODE]    = IRQ;
297 26 Revanth
                // Returns do LR - 4 to get back to the same instruction.
298
        end
299
        else if ( i_instr_abt )
300
        begin
301
                // Returns do LR - 4 to get back to the same instruction.
302
                pc_shelve (PABT_VECTOR);
303 43 Revanth
 
304 26 Revanth
                wen    = 1;
305
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
306
                wa1    = PHY_ABT_R14;
307
                wa2    = PHY_ABT_SPSR;
308
                wdata2 = cpsr_ff;
309
                cpsr_nxt[`CPSR_MODE]  = ABT;
310
        end
311
        else if ( i_swi )
312
        begin
313
                // Returns do LR to return to the next instruction.
314
                pc_shelve(SWI_VECTOR);
315
 
316 43 Revanth
                wen                     = 1;
317
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
318
                wa1                     = PHY_SVC_R14;
319
                wa2                     = PHY_SVC_SPSR;
320
                wdata2                  = cpsr_ff;
321
                cpsr_nxt[`CPSR_MODE]    = SVC;
322 26 Revanth
        end
323
        else if ( i_und )
324
        begin
325
                // Returns do LR to return to the next instruction.
326
                pc_shelve(UND_VECTOR);
327
 
328 43 Revanth
                wen                     = 1;
329
                wdata1                  = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
330
                wa1                     = PHY_UND_R14;
331
                wa2                     = PHY_UND_SPSR;
332
                wdata2                  = cpsr_ff;
333
                cpsr_nxt[`CPSR_MODE]    = UND;
334 26 Revanth
        end
335
        else if ( i_copro_reg_en )
336
        begin
337 43 Revanth
               // Write to register (Coprocessor command).
338 26 Revanth
               wen      = 1;
339
               wa1      = i_copro_reg_wr_index;
340
               wdata1   = i_copro_reg_wr_data;
341
        end
342 43 Revanth
        else if ( i_valid ) // If valid,
343 26 Revanth
        begin
344
                // Only then execute the instruction at hand...
345
                cpsr_nxt                =   i_flags;
346
 
347
                // Dual write port.
348
                wen    = 1;
349
 
350
                // Port from arithmetic side
351
                wa1    = i_wr_index;
352
                wdata1 = i_wr_data;
353
 
354
                // Port from memory side.
355
                wa2    = i_mem_load_ff ? i_wr_index_1 : PHY_RAZ_REGISTER;
356
                wdata2 = i_wr_data_1;
357
 
358
                // Load to PC will trigger from writeback.
359
                if ( i_mem_load_ff && i_wr_index_1 == ARCH_PC)
360
                begin
361
                        pc_shelve (i_wr_data_1);
362
                        o_clear_from_writeback  = 1'd1;
363
                end
364
        end
365
 
366 43 Revanth
        // Ensure lower 2 bits of PC are always tied to VSS.
367 26 Revanth
        pc_nxt = pc_nxt & 32'hffff_fffe;
368
end
369
 
370 51 Revanth
// ----------------------------------------------------------------------------
371 43 Revanth
// Sequential Logic
372 51 Revanth
// ----------------------------------------------------------------------------
373 26 Revanth
 
374 43 Revanth
always @ ( posedge i_clk )
375 26 Revanth
begin
376
        if ( i_reset )
377
        begin
378
                // On reset, the CPU starts at 0 in
379
                // supervisor mode.
380
                shelve_ff                  <= 1'd0;
381
                pc_ff                      <= 32'd0;
382
                cpsr_ff                    <= SVC;
383
                cpsr_ff[I]                 <= 1'd1; // Mask IRQ.
384
                cpsr_ff[F]                 <= 1'd1; // Mask FIQ.
385
                cpsr_ff[T]                 <= 1'd0; // Start CPU in ARM mode.
386
        end
387
        else
388
        begin
389 43 Revanth
                shelve_ff                 <= shelve_nxt;
390
                pc_shelve_ff              <= pc_shelve_nxt;
391
                pc_ff                     <= pc_nxt;
392
                cpsr_ff                   <= cpsr_nxt;
393
                o_decompile               <= i_decompile;
394
                o_copro_reg_rd_data_ff    <= o_rd_data_0;
395 26 Revanth
        end
396
end
397
 
398 51 Revanth
// ----------------------------------------------------------------------------
399 43 Revanth
// Tasks
400 51 Revanth
// ----------------------------------------------------------------------------
401 26 Revanth
 
402
task pc_shelve (input [31:0] new_pc);
403
begin
404
        if (!i_code_stall )
405
        begin
406
                pc_nxt = new_pc;
407
                shelve_nxt = 1'd0; // BUG FIX.
408
        end
409
        else
410
        begin
411
                shelve_nxt = 1'd1;
412
                pc_shelve_nxt = new_pc;
413
                pc_nxt = pc_ff;
414
        end
415
end
416
endtask
417
 
418 51 Revanth
always @ (*)
419
if ( cpsr_nxt[`CPSR_MODE] != USR && cpsr_ff[`CPSR_MODE] == USR )
420
begin
421
        if (
422
                i_data_abt      ||
423
                i_fiq           ||
424
                i_irq           ||
425
                i_instr_abt     ||
426
                i_swi           ||
427
                i_und
428
         )
429 26 Revanth
        begin
430 51 Revanth
                // OKAY...
431 26 Revanth
        end
432 51 Revanth
        else
433
        begin
434
                $display($time, "Error : %m CPU is changing out of USR mode without an exception...");
435
                $stop;
436
        end
437
end
438 26 Revanth
 
439 51 Revanth
endmodule // zap_register_file.v
440 26 Revanth
 
441
`default_nettype wire
442 51 Revanth
 
443
// ----------------------------------------------------------------------------
444
// END OF FILE
445
// ----------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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