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

Subversion Repositories steelcore

[/] [rtl/] [csr_file.v] - Blame information for rev 11

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 rafaelcalc
//////////////////////////////////////////////////////////////////////////////////
2
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
3
// 
4
// Create Date: 26.04.2020 23:33:34
5
// Module Name: csr_file
6
// Project Name: Steel Core 
7
// Description: Control and Status Register File 
8
// 
9
// Dependencies: globals.vh
10
// 
11
// Version 0.01
12
// 
13
//////////////////////////////////////////////////////////////////////////////////
14
 
15
/*********************************************************************************
16
 
17
MIT License
18
 
19
Copyright (c) 2020 Rafael de Oliveira Calçada
20
 
21
Permission is hereby granted, free of charge, to any person obtaining a copy
22
of this software and associated documentation files (the "Software"), to deal
23
in the Software without restriction, including without limitation the rights
24
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25
copies of the Software, and to permit persons to whom the Software is
26
furnished to do so, subject to the following conditions:
27
 
28
The above copyright notice and this permission notice shall be included in all
29
copies or substantial portions of the Software.
30
 
31
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37
SOFTWARE.
38
 
39
********************************************************************************/
40
 
41
`timescale 1ns / 1ps
42
`include "globals.vh"
43
 
44
module csr_file(
45
 
46
    input wire CLK,
47
    input wire RESET,
48
 
49
    input wire WR_EN,
50
    input wire [11:0] CSR_ADDR,
51
    input wire [2:0] CSR_OP,
52
    input wire [4:0] CSR_UIMM,
53
    input wire [31:0] CSR_DATA_IN,
54
    output reg [31:0] CSR_DATA_OUT,
55
 
56
    // from pipeline stage 1
57
    input wire [31:0] PC,
58
 
59
    // from pipeline stage 3
60
    input wire [31:0] IADDER_OUT,
61
 
62
    // interface with CLIC
63
    input wire E_IRQ,
64
    input wire T_IRQ,
65
    input wire S_IRQ,
66
 
67
    // interface with Machine Control Module
68
    input wire I_OR_E,
69
    input wire SET_CAUSE,
70
    input wire [3:0] CAUSE_IN,
71
    input wire SET_EPC,
72
    input wire INSTRET_INC,
73
    input wire MIE_CLEAR,
74
    input wire MIE_SET,
75
    input wire MISALIGNED_EXCEPTION,
76
    output reg MIE,
77
    output wire MEIE_OUT,
78
    output wire MTIE_OUT,
79
    output wire MSIE_OUT,
80
    output wire MEIP_OUT,
81
    output wire MTIP_OUT,
82
    output wire MSIP_OUT,
83
 
84
    // platform real time CLK value
85
    input wire [63:0] REAL_TIME,
86
 
87
    // these two outputs are connected to the PC MUX
88
    output wire [31:0] EPC_OUT,
89
    output wire [31:0] TRAP_ADDRESS
90
 
91
    );
92
 
93
    // Machine trap setup
94
    wire [31:0] mstatus; // machine status register
95
    wire [31:0] misa; // machine ISA register
96
    wire [31:0] mie_reg; // machine interrupt enable register
97
    wire [31:0] mtvec;
98
    wire [1:0] mxl; // machine XLEN
99
    wire [25:0] mextensions; // ISA extensions
100
    reg [1:0] mtvec_mode; // machine trap mode
101
    reg [29:0] mtvec_base; // machine trap base address
102
    reg mpie; // mach. prior interrupt enable
103
    reg meie; // mach. external interrupt enable
104
    reg mtie; // mach. timer interrupt enable
105
    reg msie; // mach. software interrupt enable
106
 
107
    // Machine trap handling
108
    reg [31:0] mscratch; // machine scratch register
109
    reg [31:0] mepc; // machine exception program counter
110
    reg [31:0] mtval; // machine trap value register
111
    wire [31:0] mcause; // machine trap cause register
112
    wire [31:0] mip_reg; // machine interrupt pending register
113
    reg int_or_exc; // interrupt or exception signal
114
    reg [3:0] cause; // interrupt cause
115
    reg [26:0] cause_rem; // remaining bits of mcause register 
116
    reg meip; // mach. external interrupt pending
117
    reg mtip; // mach. timer interrupt pending
118
    reg msip; // mach. software interrupt pending
119
 
120
    // Machine counters
121
    reg [63:0] mcycle;
122
    reg [63:0] mtime;
123
    reg [63:0] minstret;
124
 
125
    // Machine counters setup
126
    wire [31:0] mcountinhibit;
127
    reg mcountinhibit_cy;
128
    reg mcountinhibit_ir;
129
 
130
    // CSR operation control
131
    // ----------------------------------------------------------------------------
132
 
133
    reg [31:0] data_wr;
134
    wire [31:0] pre_data;
135
 
136
    assign pre_data = CSR_OP[2] == 1'b1 ? {27'b0, CSR_UIMM} : CSR_DATA_IN;
137
 
138
    always @*
139
    begin
140
        case(CSR_OP[1:0])
141
            `CSR_RW: data_wr <= pre_data;
142
            `CSR_RS: data_wr <= CSR_DATA_OUT | pre_data;
143
            `CSR_RC: data_wr <= CSR_DATA_OUT & ~pre_data;
144
            `CSR_NOP: data_wr <= CSR_DATA_OUT;
145
        endcase
146
    end
147
 
148
    always @*
149
    begin
150
        case(CSR_ADDR)
151
            `CYCLE:         CSR_DATA_OUT = mcycle[31:0];
152
            `CYCLEH:        CSR_DATA_OUT = mcycle[63:32];
153
            `TIME:          CSR_DATA_OUT = mtime[31:0];
154
            `TIMEH:         CSR_DATA_OUT = mtime[63:32];
155
            `INSTRET:       CSR_DATA_OUT = minstret[31:0];
156
            `INSTRETH:      CSR_DATA_OUT = minstret[63:32];
157
            `MSTATUS:       CSR_DATA_OUT = mstatus;
158
            `MISA:          CSR_DATA_OUT = misa;
159
            `MIE:           CSR_DATA_OUT = mie_reg;
160
            `MTVEC:         CSR_DATA_OUT = mtvec;
161
            `MSCRATCH:      CSR_DATA_OUT = mscratch;
162
            `MEPC:          CSR_DATA_OUT = mepc;
163
            `MCAUSE:        CSR_DATA_OUT = mcause;
164
            `MTVAL:         CSR_DATA_OUT = mtval;
165
            `MIP:           CSR_DATA_OUT = mip_reg;
166
            `MCYCLE:        CSR_DATA_OUT = mcycle[31:0];
167
            `MCYCLEH:       CSR_DATA_OUT = mcycle[63:32];
168
            `MINSTRET:      CSR_DATA_OUT = minstret[31:0];
169
            `MINSTRETH:     CSR_DATA_OUT = minstret[63:32];
170
            `MCOUNTINHIBIT: CSR_DATA_OUT = mcountinhibit;
171
            default:        CSR_DATA_OUT = 32'b0;
172
        endcase
173
    end
174
 
175
    // MSTATUS register
176
    //                       MPP           
177
    assign mstatus = {19'b0, 2'b11, 3'b0, mpie, 3'b0 , MIE, 3'b0};
178
    always @(posedge CLK)
179
    begin
180
        if(RESET)
181
        begin
182
            MIE <= 1'b0;
183
            mpie <= 1'b1;
184
        end
185
        else if(CSR_ADDR == `MSTATUS && WR_EN)
186
        begin
187
            MIE <= data_wr[3];
188
            mpie <= data_wr[7];
189
        end
190
        else if(MIE_CLEAR == 1'b1)
191
        begin
192
            mpie <= MIE;
193
            MIE <= 1'b0;
194
        end
195
        else if(MIE_SET == 1'b1)
196
        begin
197
            MIE <= mpie;
198
            mpie <= 1'b1;
199
        end
200
    end
201
 
202
    // MISA register
203
    assign mxl = 2'b01;
204
    assign mextensions = 26'b00000000000000000100000000;
205
    assign misa = {mxl, 4'b0, mextensions};
206
 
207
    // MIE register
208
    assign mie_reg = {20'b0, meie, 3'b0, mtie, 3'b0, msie, 3'b0};
209
    assign MEIE_OUT = meie;
210
    assign MTIE_OUT = mtie;
211
    assign MSIE_OUT = msie;
212
    always @(posedge CLK)
213
    begin
214
        if(RESET)
215
        begin
216
            meie <= 1'b0;
217
            mtie <= 1'b0;
218
            msie <= 1'b0;
219
        end
220
        else if(CSR_ADDR == `MIE && WR_EN)
221
        begin
222
            meie <= data_wr[11];
223
            mtie <= data_wr[7];
224
            msie <= data_wr[3];
225
        end
226
    end
227
 
228
    // MTVEC register
229
    assign mtvec = {mtvec_base, mtvec_mode};
230
    wire [31:0] trap_mux_out;
231
    wire [31:0] vec_mux_out;
232
    wire [31:0] base_offset;
233
    assign base_offset = cause << 2;
234
    assign trap_mux_out = int_or_exc ? vec_mux_out : {mtvec_base, 2'b00};
235
    assign vec_mux_out = mtvec[0] ? {mtvec_base, 2'b00} + base_offset : {mtvec_base, 2'b00};
236
    assign TRAP_ADDRESS = trap_mux_out;
237
    always @(posedge CLK)
238
    begin
239
        if(RESET)
240
        begin
241
            mtvec_mode <= `MTVEC_MODE_RESET;
242
            mtvec_base <= `MTVEC_BASE_RESET;
243
        end
244
        else if(CSR_ADDR == `MTVEC && WR_EN)
245
        begin
246
            mtvec_mode <= data_wr[1:0];
247
            mtvec_base <= data_wr[31:2];
248
        end
249
    end
250
 
251
    // MSCRATCH register
252
    always @(posedge CLK)
253
    begin
254
        if(RESET) mscratch <= `MSCRATCH_RESET;
255
        else if(CSR_ADDR == `MSCRATCH && WR_EN) mscratch <= data_wr;
256
    end
257
 
258
    // MEPC register
259
    assign EPC_OUT = mepc;
260
    always @(posedge CLK)
261
    begin
262
        if(RESET) mepc <= `MEPC_RESET;
263
        else if(SET_EPC) mepc <= PC;
264
        else if(CSR_ADDR == `MEPC && WR_EN) mepc <= {data_wr[31:2], 2'b00};
265
    end
266
 
267
    // MCAUSE register
268
    assign mcause = {int_or_exc, cause_rem, cause};
269
    always @(posedge CLK)
270
    begin
271
        if(RESET)
272
        begin
273
            cause <= 4'b0000;
274
            cause_rem <= 27'b0;
275
            int_or_exc <= 1'b0;
276
        end
277
        else if(SET_CAUSE)
278
        begin
279
            cause <= CAUSE_IN;
280
            cause_rem <= 27'b0;
281
            int_or_exc <= I_OR_E;
282
        end
283
        else if(CSR_ADDR == `MCAUSE && WR_EN)
284
        begin
285
            cause <= data_wr[3:0];
286
            cause_rem <= data_wr[30:4];
287
            int_or_exc <= data_wr[31];
288
 
289
        end
290
    end
291
 
292
    // MIP register
293
    assign mip_reg = {20'b0, meip, 3'b0, mtip, 3'b0, msip, 3'b0};
294
    assign MEIP_OUT = meip;
295
    assign MTIP_OUT = mtip;
296
    assign MSIP_OUT = msip;
297
    always @(posedge CLK)
298
    begin
299
        if(RESET)
300
        begin
301
            meip <= 1'b0;
302
            mtip <= 1'b0;
303
            msip <= 1'b0;
304
        end
305
        else
306
        begin
307
            meip <= E_IRQ;
308
            mtip <= T_IRQ;
309
            msip <= S_IRQ;
310
        end
311
    end
312
 
313
    // MTVAL register
314
    always @(posedge CLK)
315
    begin
316
        if(RESET) mtval <= 32'b0;
317
        else if(SET_CAUSE)
318
        begin
319
            if(MISALIGNED_EXCEPTION) mtval <= IADDER_OUT;
320
            else mtval <= 32'b0;
321
        end
322
        else if(CSR_ADDR == `MTVAL && WR_EN) mtval <= data_wr;
323
    end
324
 
325
    // MCOUNTINHIBIT register
326
    assign mcountinhibit = {29'b0, mcountinhibit_ir, 1'b0, mcountinhibit_cy};
327
    always @(posedge CLK)
328
    begin
329
        if(RESET)
330
        begin
331
            mcountinhibit_cy <= `MCOUNTINHIBIT_CY_RESET;
332
            mcountinhibit_ir <= `MCOUNTINHIBIT_IR_RESET;
333
        end
334
        else if(CSR_ADDR == `MCOUNTINHIBIT && WR_EN)
335
        begin
336
            mcountinhibit_cy <= data_wr[2];
337
            mcountinhibit_ir <= data_wr[0];
338
        end
339
    end
340
 
341
    // Counters
342
    always @(posedge CLK)
343
    begin
344
        if(RESET)
345
        begin
346
            mcycle <= {`MCYCLEH_RESET, `MCYCLE_RESET};
347
            minstret <= {`MINSTRETH_RESET, `MINSTRET_RESET};
348
            mtime <= {`TIMEH_RESET, `TIME_RESET};
349
        end
350
        else
351
        begin
352
            mtime <= REAL_TIME;
353
 
354
            if(CSR_ADDR == `MCYCLE && WR_EN)
355
            begin
356
                if(mcountinhibit_cy == 1'b0) mcycle <= {mcycle[63:32], data_wr} + 1;
357
                else mcycle <= {mcycle[63:32], data_wr};
358
            end
359
            else if(CSR_ADDR == `MCYCLEH && WR_EN)
360
            begin
361
                if(mcountinhibit_cy == 1'b0) mcycle <= {data_wr, mcycle[31:0]} + 1;
362
                else mcycle <= {data_wr, mcycle[31:0]};
363
            end
364
            else
365
            begin
366
                if(mcountinhibit_cy == 1'b0) mcycle <= mcycle + 1;
367
                else mcycle <= mcycle;
368
            end
369
 
370
            if(CSR_ADDR == `MINSTRET && WR_EN)
371
            begin
372
                if(mcountinhibit_ir == 1'b0) minstret <= {minstret[63:32], data_wr} + INSTRET_INC;
373
                else minstret <= {minstret[63:32], data_wr};
374
            end
375
            else if(CSR_ADDR == `MINSTRETH && WR_EN)
376
            begin
377
                if(mcountinhibit_ir == 1'b0) minstret <= {data_wr, minstret[31:0]} + INSTRET_INC;
378
                else minstret <= {data_wr, minstret[31:0]};
379
            end
380
            else
381
            begin
382
                if(mcountinhibit_ir == 1'b0) minstret <= minstret + INSTRET_INC;
383
                else minstret <= minstret;
384
            end
385
 
386
        end
387
    end
388
 
389
endmodule

powered by: WebSVN 2.1.0

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