PMU_raw.sv 35.7 KB
Newer Older
Guillem's avatar
Guillem committed
1
2
3
4
//-----------------------------------------------------
// ProjectName: LEON3_kc705_pmu
// Function   : Integrate PMU features under one module
// Description: Interface agnostic implementation of the  PMU. Values of the
5
//              PMU are not registered in this module.
Guillem's avatar
Guillem committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//              
//              This module is responsible of configure the memory map, handle
//              write / read syncronization with a higher level module that
//              integrates standar bus interfaces such as AXI, AHB or wishbone.
//
//              Parametrization of the features is configured here by
//              replicating instances of features and adjusting basic
//              parameters such as counters width.
//
// Coder      : G.Cabo
// References : Implementation of Maximum-Contention Control Unit (MCCU): 
//              ResourceAccess Count and Contention Time Enforcement. 
//              https://upcommons.upc.edu/handle/2117/133656

`default_nettype none
`timescale 1 ns / 1 ps

`ifndef SYNT
    `ifdef FORMAL 
        `define ASSERTIONS
    `endif
`endif
	module PMU_raw #
	(
Guillem's avatar
Guillem committed
30
        //------------- External parameters 
Guillem's avatar
Guillem committed
31
32
33
34
		// Width of registers data bus
		parameter integer REG_WIDTH	= 32,
		// Amount of counters
		parameter integer N_COUNTERS	= 9,
35
36
		// Amount of SoC events going through the crossbar
		parameter integer N_SOC_EV	= 32,
Guillem's avatar
Guillem committed
37
38
		// Configuration registers
		parameter integer N_CONF_REGS	= 1,
GuillemCabo's avatar
GuillemCabo committed
39
        // Fault tolerance mechanisms (FT==0 -> FT disabled)
40
        parameter integer FT  = 0,                                           
Guillem's avatar
Guillem committed
41
42

        //------------- Internal Parameters 
Guillem's avatar
Guillem committed
43
44
45
46
47
48
49
50
51
52
		
        // *** Active functions and global configuration
        //---- Overflow
		localparam integer OVERFLOW	= 1, //Yes/No
		//---- Quota
		localparam integer QUOTA	= 1, //Yes/No
		//---- MCCU - Maximum-contention Control Unit mode
		localparam integer MCCU	= 1, //Yes/No
		//---- RDC - Request Duration Counters
		localparam integer RDC	= 1, //Yes/No
53
54
		//---- Crossbar
		localparam integer CROSSBAR	= 1, //Yes/No
Guillem's avatar
Guillem committed
55
56
57
58
       
        // *** Memory map related features
        
        //---- Main configuration registers
Guillem's avatar
Guillem committed
59
60
        localparam BASE_CFG = 0,
        localparam END_CFG = BASE_CFG + N_CONF_REGS -1,
Guillem's avatar
Guillem committed
61
        
Guillem's avatar
Guillem committed
62
63
64
        //---- Counter registers
        localparam BASE_COUNTERS = END_CFG + 1,
        localparam END_COUNTERS = BASE_COUNTERS + N_COUNTERS-1, 
Guillem's avatar
Guillem committed
65
66
        
        //---- Overflow interruption  registers
Guillem's avatar
Guillem committed
67
68
69
70
71
72
73
74
            // General parameters feature  
        localparam BASE_OVERFLOW_INTR = END_COUNTERS + 1,
            // mask feature
            // OVERFLOW_INTR_MASK_REGS is equivalent to $ceil(N_COUNTERS/REG_WIDTH)
        localparam BASE_OVERFLOW_MASK = BASE_OVERFLOW_INTR,
        localparam N_OVERFLOW_MASK_REGS = ((N_COUNTERS-1)/REG_WIDTH+1), 
        localparam END_OVERFLOW_MASK = BASE_OVERFLOW_MASK + N_OVERFLOW_MASK_REGS -1,
            // overflow interruption vector feature
Guillem's avatar
Guillem committed
75
            // OVERFLOW_INTR_VECT_REGS is equivalent to $ceil(N_COUNTERS/REG_WIDTH)
Guillem's avatar
Guillem committed
76
77
78
        localparam BASE_OVERFLOW_VECT = (END_OVERFLOW_MASK+1),
        localparam N_OVERFLOW_VECT_REGS = ((N_COUNTERS-1)/REG_WIDTH+1), 
        localparam END_OVERFLOW_VECT = BASE_OVERFLOW_VECT + N_OVERFLOW_VECT_REGS -1,
Guillem's avatar
Guillem committed
79
            // General parameters overflow feature  
Guillem's avatar
Guillem committed
80
81
        localparam N_OVERFLOW_REGS = (N_OVERFLOW_VECT_REGS + N_OVERFLOW_VECT_REGS) * OVERFLOW,
        localparam END_OVERFLOW_INTR = BASE_OVERFLOW_INTR + N_OVERFLOW_REGS -1,
Guillem's avatar
Guillem committed
82
83
84
85
86
87
        
        //---- Quota interruption  registers
            // General parameters feature  
        localparam BASE_QUOTA_INTR = END_OVERFLOW_INTR + 1,
            // mask feature
                // QUOTA_INTR_MASK_REGS equivalentto to $ceil(N_COUNTERS/REG_WIDTH)
Guillem's avatar
Guillem committed
88
        localparam BASE_QUOTA_MASK = BASE_QUOTA_INTR,
Guillem's avatar
Guillem committed
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
        localparam N_QUOTA_MASK_REGS = ((N_COUNTERS-1)/REG_WIDTH+1), 
        localparam END_QUOTA_MASK = BASE_QUOTA_MASK + N_QUOTA_MASK_REGS -1,
            // Available quota aka quota limit
        localparam BASE_QUOTA_LIMIT = END_QUOTA_MASK + 1, 
        localparam N_QUOTA_LIMIT_REGS = 1,
        localparam END_QUOTA_LIMIT = BASE_QUOTA_LIMIT + N_QUOTA_LIMIT_REGS -1,
            // General parameters overflow feature  
        localparam N_QUOTA_REGS = (N_QUOTA_MASK_REGS + N_QUOTA_LIMIT_REGS ) * QUOTA,
        localparam END_QUOTA_INTR = BASE_QUOTA_INTR + N_QUOTA_REGS -1,
        
        //---- MCCU registers and parameters
            // General parameters feature
                // Width of the assigned weights for each event
        localparam MCCU_WEIGHTS_WIDTH = 8,
                // Number of cores with MCCU capabilities
104
        parameter MCCU_N_CORES = 4, 
Guillem's avatar
Guillem committed
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
                // Number of events per core
        localparam MCCU_N_EVENTS = 2 , 
            // Main configuration register for the MCCU 
        localparam BASE_MCCU_CFG = END_QUOTA_INTR + 1,
        localparam N_MCCU_CFG = 1,
        localparam END_MCCU_CFG = BASE_MCCU_CFG + N_MCCU_CFG -1 ,
            // Quota limit assgined to each core
        localparam BASE_MCCU_LIMITS = END_MCCU_CFG +1,
        localparam N_MCCU_LIMITS = MCCU_N_CORES,
        localparam END_MCCU_LIMITS = BASE_MCCU_LIMITS + N_MCCU_LIMITS -1,
            // Currently available Quota for each core
        localparam BASE_MCCU_QUOTA = END_MCCU_LIMITS +1,
        localparam N_MCCU_QUOTA = MCCU_N_CORES,
        localparam END_MCCU_QUOTA = BASE_MCCU_QUOTA + N_MCCU_QUOTA -1,
            // Weights for each one of the available events
        localparam BASE_MCCU_WEIGHTS = END_MCCU_QUOTA + 1,
                // (((....)-1)/(...)+1) is equivalent to ceil
        localparam N_MCCU_WEIGHTS = (((MCCU_N_CORES*MCCU_N_EVENTS*MCCU_WEIGHTS_WIDTH)-1)/REG_WIDTH+1),
        localparam END_MCCU_WEIGHTS = BASE_MCCU_WEIGHTS + N_MCCU_WEIGHTS -1,
            // General parameters feature  
        localparam N_MCCU_REGS = (N_MCCU_CFG + N_MCCU_LIMITS+ N_MCCU_QUOTA + N_MCCU_WEIGHTS) * MCCU,
        
        //---- RDC registers and parameters. Shared with MCCU 
            // General parameters feature
                // Width of the assigned weights for each event
        localparam RDC_WEIGHTS_WIDTH = MCCU_WEIGHTS_WIDTH,
                // Number of cores with RDC capabilities
        localparam RDC_N_CORES = MCCU_N_CORES, 
                // Number of events per core
        localparam RDC_N_EVENTS = MCCU_N_EVENTS, 
            // Interruption vector 
        localparam BASE_RDC_VECT = (END_MCCU_WEIGHTS+1),
                // (((....)-1)/(...)+1) is equivalent to ceil
        localparam N_RDC_VECT_REGS = ((RDC_N_CORES*RDC_N_EVENTS-1)/REG_WIDTH+1), 
        localparam END_RDC_VECT = BASE_RDC_VECT + N_RDC_VECT_REGS -1 ,
            // Weights for each one of the available events. SHARED with MCCU
        localparam BASE_RDC_WEIGHTS = BASE_MCCU_WEIGHTS, 
                // (((....)-1)/(...)+1) is equivalent to ceil
        localparam N_RDC_WEIGHTS = 0, 
        localparam END_RDC_WEIGHTS = END_MCCU_WEIGHTS,
145
146
147
148
149
            // Watermark for each one of the available events
        localparam BASE_RDC_WATERMARK = END_RDC_VECT + 1,
                // (((....)-1)/(...)+1) is equivalent to ceil
        localparam N_RDC_WATERMARK = (((MCCU_N_CORES*MCCU_N_EVENTS*MCCU_WEIGHTS_WIDTH)-1)/REG_WIDTH+1),
        localparam END_RDC_WATERMARK = BASE_RDC_WATERMARK + N_RDC_WATERMARK -1,
Guillem's avatar
Guillem committed
150
            // General parameters feature  
151
        localparam N_RDC_REGS = (N_RDC_WEIGHTS + N_RDC_VECT_REGS+N_RDC_WATERMARK) * RDC,
152
153
154
155
156
157
158
159
160
161
        //---- CROSSBAR registers and parameters.
            // General parameters feature
        localparam CROSSBAR_INPUTS = N_SOC_EV,
        localparam CROSSBAR_OUTPUTS = N_COUNTERS,
        //number of bits for each configuration field
        localparam CROSSBAR_CFG_BITS= $clog2(CROSSBAR_INPUTS),
        localparam BASE_CROSSBAR = END_RDC_WATERMARK +1,
        localparam N_CROSSBAR_CFG =((CROSSBAR_OUTPUTS*CROSSBAR_CFG_BITS-1)/REG_WIDTH+1) * CROSSBAR,
        localparam END_CROSSBAR = BASE_CROSSBAR + N_CROSSBAR_CFG - 1,
        localparam N_CROSSBAR_REGS = N_CROSSBAR_CFG,
Guillem's avatar
Guillem committed
162
163
        
        //---- Total of registers used
Guillem's avatar
Guillem committed
164
165
        localparam integer TOTAL_NREGS =
                                    N_COUNTERS + N_CONF_REGS + N_OVERFLOW_REGS
166
                                    +N_QUOTA_REGS + N_MCCU_REGS + N_RDC_REGS + N_CROSSBAR_REGS
Guillem's avatar
Guillem committed
167
168
	)
	(
Guillem's avatar
Guillem committed
169
170
171
172
173
174
		// Global Clock Signal
		input wire  clk_i,
		// Global Reset Signal. This Signal is Active LOW
		input wire  rstn_i,
        // Input/output wire from registers of the wrapper to PMU_raw internal
        // registers
Guillem's avatar
Guillem committed
175
176
        input wire [REG_WIDTH-1:0] regs_i [0:TOTAL_NREGS-1],
        output wire [REG_WIDTH-1:0] regs_o [0:TOTAL_NREGS-1],
Guillem's avatar
Guillem committed
177
178
179
180
        // Wrapper writte enable, prevents slaves to write in to registers and
        // uploads the content with external values
        input wire wrapper_we_i,
        // Event signals
181
        input wire [N_SOC_EV-1:0] events_i,
Guillem's avatar
Guillem committed
182
        //interruption rises when one of the counters overflows
Guillem's avatar
Guillem committed
183
        output wire intr_overflow_o,
Guillem's avatar
Guillem committed
184
        //interruption rises when overall events quota is exceeded 
Guillem's avatar
Guillem committed
185
186
187
188
        output wire intr_quota_o,
        // MCCU interruption for exceeded quota. One signal per core
        output wire [MCCU_N_CORES-1:0] intr_MCCU_o,
        // RDC (Request Duration Counter) interruption for exceeded quota
189
190
191
192
193
        output wire intr_RDC_o,
        // FT (Fault tolerance) interrupt, error detected and recovered
        output wire intr_FT1_o,
        // FT (Fault tolerance) interrupt, error detected but not recoverable
        output wire intr_FT2_o
Guillem's avatar
Guillem committed
194
	);
Guillem's avatar
Guillem committed
195
196
197
198
199
200
201
    //----------------------------------------------
    // VIVADO: list of debug signals for ILA 
    //----------------------------------------------     
    `ifdef ILA_DEBUG_PMU_RAW                                                           
    (* MARK_DEBUG = "TRUE" *) logic [REG_WIDTH-1:0] debug_regs_i [0:TOTAL_NREGS-1];
    (* MARK_DEBUG = "TRUE" *) logic [REG_WIDTH-1:0] debug_regs_o [0:TOTAL_NREGS-1]; 
    (* MARK_DEBUG = "TRUE" *) wire debug_wrapper_we_i;              
202
    (* MARK_DEBUG = "TRUE" *) wire [N_SOC_EV-1:0] debug_events_i;                 
Guillem's avatar
Guillem committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    (* MARK_DEBUG = "TRUE" *) wire debug_intr_overflow_o;                 
    (* MARK_DEBUG = "TRUE" *) wire debug_intr_quota_o;                           
    (* MARK_DEBUG = "TRUE" *) wire [MCCU_N_CORES-1:0] debug_intr_MCCU_o;            
    (* MARK_DEBUG = "TRUE" *) wire debug_intr_RDC_o;            
                                                                                    
    assign debug_regs_i = regs_i;                                                   
    assign debug_regs_o = regs_o;                                                   
    assign debug_wrapper_we_i = wrapper_we_i;                                       
    assign debug_events_i = events_i;                                               
    assign debug_intr_overflow_o = intr_overflow_o;                                 
    assign debug_intr_quota_o = intr_quota_o;                                       
    assign debug_intr_MCCU_o = intr_MCCU_o;                                         
    assign debug_intr_RDC_o = intr_RDC_o;                                           
    `endif                                                                          
      
Guillem's avatar
Guillem committed
218
//----------------------------------------------
Guillem's avatar
Guillem committed
219
220
//------------- Declare wires from/to  wrapper registers
//----------------------------------------------
Guillem's avatar
Guillem committed
221
    
Guillem's avatar
Guillem committed
222
    //---- configuration signals
Guillem's avatar
Guillem committed
223
    wire [1:0] selftest_mode;
Guillem's avatar
Guillem committed
224
225
    wire en_i;
    wire softrst_i;
226
227
228
    wire overflow_en_i;
    wire overflow_softrst_i;
    wire quota_softrst_i;
Guillem's avatar
Guillem committed
229
    //---- Counter signals
Guillem's avatar
Guillem committed
230
    wire [REG_WIDTH-1:0] counter_regs_o [0 : N_COUNTERS-1];
Guillem's avatar
Guillem committed
231
232
233
234
    wire [REG_WIDTH-1:0] counter_regs_int [0 : N_COUNTERS-1];
    //---- Overflow interruption  signals
    wire [N_COUNTERS-1:0] overflow_intr_mask_i [0 : N_OVERFLOW_MASK_REGS-1]; 
    wire [N_COUNTERS-1:0] overflow_intr_vect_o [0 : N_OVERFLOW_VECT_REGS-1];
235
236
237
    //---- RDC watermark signals
    wire [MCCU_WEIGHTS_WIDTH-1:0] MCCU_watermark_int [0:MCCU_N_CORES-1]
                                                     [0:MCCU_N_EVENTS-1];
Guillem's avatar
Guillem committed
238
//----------------------------------------------
Guillem's avatar
Guillem committed
239
240
//------------- Map registers from wrapper to slave functions
//----------------------------------------------
Guillem's avatar
Guillem committed
241
242
243
244
    //Selftest mode. Bypass events and sets internal values
    assign selftest_mode [0] =regs_i [BASE_CFG][30];
    assign selftest_mode [1] =regs_i [BASE_CFG][31];

245
    //counters
Guillem's avatar
Guillem committed
246
247
    assign en_i = regs_i [BASE_CFG][0];
    assign softrst_i = regs_i [BASE_CFG][1];
248
249
250
251
252
253
    //overflow
    assign overflow_en_i = regs_i [BASE_CFG][2];
    assign overflow_softrst_i = regs_i [BASE_CFG][3];
    //quota    
    assign quota_softrst_i = regs_i [BASE_CFG][4];
    // Register never set by PMU, only written by master
254
255
256
257
258
259
    genvar y;
    generate
        for(y=BASE_CFG;y<=END_CFG;y++) begin
               assign regs_o[y] = regs_i[y];
        end
    endgenerate
Guillem's avatar
Guillem committed
260
261
262
    //---- Counter registers
    genvar x;
    generate
Guillem's avatar
Guillem committed
263
264
        for(x=BASE_COUNTERS;x<=END_COUNTERS;x++) begin
            assign counter_regs_int[x-BASE_COUNTERS] = regs_i[x];
Guillem's avatar
Guillem committed
265
266
267
            assign regs_o[x] = counter_regs_o[x-BASE_COUNTERS];
        end
    endgenerate
Guillem's avatar
Guillem committed
268
269
270
    //---- Overflow interruption  registers
    generate
        for(x=0;x<N_OVERFLOW_MASK_REGS;x++) begin
Guillem's avatar
Guillem committed
271
            assign overflow_intr_mask_i[x] = (rstn_i == 1'b0)? {N_COUNTERS{1'b0}} :regs_i [x+BASE_OVERFLOW_MASK][N_COUNTERS-1:0];
Guillem's avatar
Guillem committed
272
273
        end
        for(x=BASE_OVERFLOW_VECT;x<=END_OVERFLOW_VECT;x++) begin
Guillem's avatar
Guillem committed
274
            assign regs_o [x] = (rstn_i == 1'b0)? {REG_WIDTH{1'b0}} : REG_WIDTH'(overflow_intr_vect_o[x-BASE_OVERFLOW_VECT]);
Guillem's avatar
Guillem committed
275
276
        end
    endgenerate
Guillem's avatar
Guillem committed
277
        // Register never set by PMU, only written by master
Guillem's avatar
Guillem committed
278
279
280
281
282
    generate
        for(x=0;x<N_OVERFLOW_MASK_REGS;x++) begin
            assign regs_o[BASE_OVERFLOW_MASK+x] = regs_i[BASE_OVERFLOW_MASK+x];
        end
    endgenerate
Guillem's avatar
Guillem committed
283
    //---- Quota interruption  registers
Guillem's avatar
Guillem committed
284
        // Register never set by PMU, only written by master
Guillem's avatar
Guillem committed
285
286
287
288
289
290
291
292
293
294
    generate
        for(x=0;x<N_QUOTA_MASK_REGS;x++) begin
            assign regs_o[BASE_QUOTA_MASK+x] = regs_i[BASE_QUOTA_MASK+x];
        end
    endgenerate
    generate
        for(x=0;x<N_QUOTA_LIMIT_REGS;x++) begin
            assign regs_o[BASE_QUOTA_LIMIT+x] = regs_i[BASE_QUOTA_LIMIT+x];
        end
    endgenerate
Guillem's avatar
Guillem committed
295
    //---- MCCU  registers
Guillem's avatar
Guillem committed
296
        // Register never set by PMU, only written by master
Guillem's avatar
Guillem committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    generate
        for(x=0;x<N_MCCU_CFG;x++) begin
            assign regs_o[BASE_MCCU_CFG+x] = regs_i[BASE_MCCU_CFG+x];
        end
    endgenerate
    generate
        for(x=0;x<N_MCCU_LIMITS;x++) begin
            assign regs_o[BASE_MCCU_LIMITS+x] = regs_i[BASE_MCCU_LIMITS+x];
        end
    endgenerate
    generate
        for(x=0;x<N_MCCU_WEIGHTS;x++) begin
            assign regs_o[BASE_MCCU_WEIGHTS+x] = regs_i[BASE_MCCU_WEIGHTS+x];
        end
    endgenerate
Guillem's avatar
Guillem committed
312
    //---- Request Duration Counter (RDC) registers 
GuillemCabo's avatar
GuillemCabo committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
    genvar q;
    genvar j;
    generate
        for(q=0;q<N_MCCU_WEIGHTS;q++) begin
            for(j=0;j<(REG_WIDTH/MCCU_WEIGHTS_WIDTH);j++) begin
                   // q - Iterate over registers that we have to fill
                   // j - Iterate over fields of each register
                   // assign regs_o [c][d:e] =  MCCU_watermark_int[a][b];
                   // a - Index of the core owning the signal
                   // b - Index of the signal within the asigned core
                   // c - Index of the signal in the PMU register bank
                   // d - Upper bit of the field within PMU register bank
                   // d - Lower bit of the field within PMU register bank
                 assign regs_o[BASE_RDC_WATERMARK+q][MCCU_WEIGHTS_WIDTH*(j+1)-1:MCCU_WEIGHTS_WIDTH*j]
                        = MCCU_watermark_int [(q*(REG_WIDTH/MCCU_WEIGHTS_WIDTH)+j)/RDC_N_EVENTS]
                            [((q*(REG_WIDTH/MCCU_WEIGHTS_WIDTH)+j))%RDC_N_EVENTS];
            end
        end
    endgenerate
Guillem's avatar
Guillem committed
332

Guillem's avatar
Guillem committed
333
//----------------------------------------------
334
335
336
337
338
//------------- Crossbar 
//----------------------------------------------
logic [CROSSBAR_CFG_BITS-1:0]crossbar_cfg [0:CROSSBAR_OUTPUTS-1]; 
logic [CROSSBAR_OUTPUTS-1:0] crossbar_o;
logic [N_CROSSBAR_CFG*REG_WIDTH-1:0] concat_cfg_crossbar;
GuillemCabo's avatar
GuillemCabo committed
339
340
341
342
343
344
345
    
//Drive outputs that are never set by the PMU    
    generate
        for(y=BASE_CROSSBAR;y<=END_CROSSBAR;y++) begin
               assign regs_o[y] = regs_i[y];
        end
    endgenerate
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

//Concatenate all the registers to have easier access with missaligned registers 
integer i;
always_comb begin
    for (i=0; i < N_CROSSBAR_CFG; i++) begin
       concat_cfg_crossbar[i*REG_WIDTH+:REG_WIDTH] = regs_i[BASE_CROSSBAR+i]; 
    end
end

//map configuration fields to each mux
generate
    for (q=0;q<CROSSBAR_OUTPUTS;q++) begin
        assign crossbar_cfg[q] = concat_cfg_crossbar [q*CROSSBAR_CFG_BITS+:CROSSBAR_CFG_BITS];
    end
endgenerate

//Unpack crossbar inputs
logic unpacked_cbi_int[0:CROSSBAR_INPUTS-1];

generate
    for(q=0;q<CROSSBAR_INPUTS;q++) begin
        assign unpacked_cbi_int[q] = events_i[q];
    end
endgenerate
//Pack crossbar output
logic unpacked_cbo_int [0:CROSSBAR_OUTPUTS-1] ;
generate
    for(q=0;q<CROSSBAR_OUTPUTS;q++) begin
        assign crossbar_o[q] = unpacked_cbo_int[q];
    end
endgenerate

//Crossbar instance
crossbar # (
		.N_OUT	(CROSSBAR_OUTPUTS),
		.N_IN	(CROSSBAR_INPUTS)
	)
inst_cross   (
		.clk_i(clk_i),
		.rstn_i(rstn_i),
        .vector_i(unpacked_cbi_int),
        .vector_o(unpacked_cbo_int),
        .cfg_i(crossbar_cfg)
    );
//----------------------------------------------
Guillem's avatar
Guillem committed
391
392
393
394
395
396
397
398
399
400
401
402
//------------- Selftest configuration
//----------------------------------------------
logic [N_COUNTERS-1:0] events_int;

localparam NO_SELF_TEST = 2'b00;
localparam ALL_ACTIVE = 2'b01;
localparam ALL_OFF = 2'b10;
localparam ONE_ON = 2'b11;

always_comb begin
    case (selftest_mode)
        NO_SELF_TEST : begin
403
            events_int = crossbar_o;
Guillem's avatar
Guillem committed
404
405
406
407
408
409
410
411
412
413
414
415
416
417
        end
        ALL_ACTIVE : begin
            events_int = {N_COUNTERS{1'b1}};
        end
        ALL_OFF : begin
            events_int = {N_COUNTERS{1'b0}};
        end
        ONE_ON : begin
            events_int[0] = 1'b1;
            events_int[N_COUNTERS-1:1] = {(N_COUNTERS-1){1'b0}};
        end
    endcase
end

Guillem's avatar
Guillem committed
418
419
420
//----------------------------------------------
//------------- Counters instance
//----------------------------------------------
421
422
//TODO: What happen if we is active but no write is done to the range of the
//counters?
423
    logic counters_fte2;
Guillem's avatar
Guillem committed
424
425
426
427
428
429
430
431
432
433
434
435
    PMU_counters # (
		.REG_WIDTH	(REG_WIDTH),
		.N_COUNTERS	(N_COUNTERS)
	)
    inst_counters (
		.clk_i      (clk_i),
		.rstn_i     (rstn_i),
		.softrst_i  (softrst_i),
		.en_i       (en_i),
		.we_i       (wrapper_we_i),
        .regs_i     (counter_regs_int),
        .regs_o     (counter_regs_o),
436
437
        .events_i   (events_int), 
        .intr_FT2_o (counters_fte2)
Guillem's avatar
Guillem committed
438
439
	);

Guillem's avatar
Guillem committed
440
//----------------------------------------------
Guillem's avatar
Guillem committed
441
442
//------------- Overflow interuption instance
//----------------------------------------------
Guillem's avatar
Guillem committed
443
    PMU_overflow # (
Guillem's avatar
Guillem committed
444
445
		.REG_WIDTH	(REG_WIDTH),
		.N_COUNTERS	(N_COUNTERS)
Guillem's avatar
Guillem committed
446
447
	)
    inst_overflow (
Guillem's avatar
Guillem committed
448
449
		.clk_i              (clk_i),
		.rstn_i             (rstn_i),
450
451
		.softrst_i          (overflow_softrst_i),
		.en_i               (overflow_en_i),
Guillem's avatar
Guillem committed
452
453
454
455
        .counter_regs_i     (counter_regs_o),
        .over_intr_mask_i   (overflow_intr_mask_i[0][N_COUNTERS-1:0]), 
        .intr_overflow_o    (intr_overflow_o), 
        .over_intr_vect_o   (overflow_intr_vect_o[0][N_COUNTERS-1:0])
Guillem's avatar
Guillem committed
456
	);
Guillem's avatar
Guillem committed
457

Guillem's avatar
Guillem committed
458
459
460
//----------------------------------------------
//------------- Quota interruption instance
//----------------------------------------------
Guillem's avatar
Guillem committed
461
462
    
    PMU_quota # (
Guillem's avatar
Guillem committed
463
464
        .REG_WIDTH	(REG_WIDTH),
        .N_COUNTERS	(N_COUNTERS)
Guillem's avatar
Guillem committed
465
466
    )
    inst_quota(
Guillem's avatar
Guillem committed
467
468
469
        .clk_i          (clk_i),
        .rstn_i         (rstn_i),
        .counter_value_i(counter_regs_o),
470
        .softrst_i      (quota_softrst_i),
Guillem's avatar
Guillem committed
471
472
473
        .quota_limit_i  (regs_i[BASE_QUOTA_LIMIT]),
        .quota_mask_i   (regs_i[BASE_QUOTA_MASK][N_COUNTERS-1:0]), 
        .intr_quota_o   (intr_quota_o) 
Guillem's avatar
Guillem committed
474
    );
Guillem's avatar
Guillem committed
475

Guillem's avatar
Guillem committed
476
477
478
//----------------------------------------------
//------------- MCCU instance
//----------------------------------------------
Guillem's avatar
Guillem committed
479
480
    /*wire MCCU_enable_int;
    assign MCCU_enable_int = regs_i[BASE_MCCU_CFG][0];*/
Guillem's avatar
Guillem committed
481
482
483
484
    
    wire MCCU_softrst;
    assign MCCU_softrst = regs_i[BASE_MCCU_CFG][1];
    
Guillem's avatar
Guillem committed
485
    
486
    //One bit for each core to trigger quota update
Guillem's avatar
Guillem committed
487
    wire MCCU_update_quota_int [0:MCCU_N_CORES-1];
488
489
490
491
492
    generate
        for(q=0;q<MCCU_N_CORES;q++) begin
            assign MCCU_update_quota_int[q] = regs_i[BASE_MCCU_CFG][q+2]; 
        end
    endgenerate
Guillem's avatar
Guillem committed
493
    
494
495
496
497
498
499
    //TODO: document MCCU capable events for each core configuration
        //2Cores -> events 0 to 3
        //3Cores -> events 0 to 5
        //4Cores -> events 0 to 7
        //5Cores -> events 0 to 9
        //6Cores -> events 0 to 11
Guillem's avatar
Guillem committed
500
    wire [MCCU_N_EVENTS-1:0] MCCU_events_int[0:MCCU_N_CORES-1];
501
502
503
504
505
    generate
        for(q=0;q<MCCU_N_CORES;q++) begin
            assign MCCU_events_int [q] = {{events_int[2*q+1]},{events_int[q*2]}};
        end
    endgenerate
Guillem's avatar
Guillem committed
506
507
508
        
    wire [MCCU_WEIGHTS_WIDTH-1:0] MCCU_events_weights_int [0:MCCU_N_CORES-1]
                                                     [0:MCCU_N_EVENTS-1];
509
    generate
GuillemCabo's avatar
GuillemCabo committed
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
        // Registers
        for(q=0;q<N_MCCU_WEIGHTS;q++) begin
            //fields
            for(j=0;j<(REG_WIDTH/MCCU_WEIGHTS_WIDTH);j++) begin
                   // q - Iterate over registers that we have to fill
                   // j - Iterate over fields of each register
                   // assign MCCU_events_weights_int [a][b] =  regs_i[c][d:e];
                   // a - Index of the core owning the signal
                   // b - Index of the signal within the asigned core
                   // c - Index of the signal in the PMU register bank
                   // d - Upper bit of the field within PMU register bank
                   // d - Lowe bit of the field within PMU register bank
                 assign MCCU_events_weights_int [(q*(REG_WIDTH/MCCU_WEIGHTS_WIDTH)+j)/MCCU_N_EVENTS]
                                                [((q*(REG_WIDTH/MCCU_WEIGHTS_WIDTH)+j))%MCCU_N_EVENTS] 
                        =  regs_i[BASE_MCCU_WEIGHTS+q][MCCU_WEIGHTS_WIDTH*(j+1)-1:MCCU_WEIGHTS_WIDTH*j];
525
526
            end
        end
GuillemCabo's avatar
GuillemCabo committed
527
    endgenerate
528
    //unpack to pack
Guillem's avatar
Guillem committed
529
    wire MCCU_intr_up [MCCU_N_CORES-1:0];
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
    generate
        case (MCCU_N_CORES)
            2 : begin
                assign intr_MCCU_o = {{MCCU_intr_up[1]},{MCCU_intr_up[0]}};
            end
            3 : begin
                assign intr_MCCU_o = {{MCCU_intr_up[2]}
                                    ,{MCCU_intr_up[1]},{MCCU_intr_up[0]}};
            end
            4 : begin
                assign intr_MCCU_o = {{MCCU_intr_up[3]},{MCCU_intr_up[2]}
                                    ,{MCCU_intr_up[1]},{MCCU_intr_up[0]}};
            end
            5 : begin
                assign intr_MCCU_o = {{MCCU_intr_up[4]}
                                    ,{MCCU_intr_up[3]},{MCCU_intr_up[2]}
                                    ,{MCCU_intr_up[1]},{MCCU_intr_up[0]}};
            end
            6 : begin
                assign intr_MCCU_o = {{MCCU_intr_up[5]},{MCCU_intr_up[4]}
                                    ,{MCCU_intr_up[3]},{MCCU_intr_up[2]}
                                    ,{MCCU_intr_up[1]},{MCCU_intr_up[0]}};
            end
            default : begin
                assign intr_MCCU_o = '{default:1};
                $error("Core configuration not supported by MCCU");
            end
        endcase
    endgenerate

Guillem's avatar
Guillem committed
560
    //register enable to solve Hazards
GuillemCabo's avatar
GuillemCabo committed
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
    logic MCCU_rstn_Q;
    if (FT==0) begin : Nft_mccu_rst
        logic MCCU_rstn; 
        always @(posedge clk_i) begin: MCCU_glitchless_rstn
                if (!rstn_i) begin
                    MCCU_rstn <= 0;
                end else begin
                    MCCU_rstn <= rstn_i && !MCCU_softrst;
                end
        end
        assign MCCU_rstn_Q = MCCU_rstn; 
    end else begin : Ft_mccu_rst
        logic MCCU_rstn_D;
        logic MCCU_rstn_fte1,MCCU_rstn_fte2;
        always_comb begin: MCCU_rstn
                if (!rstn_i) begin
                    MCCU_rstn_D = 0;
                end else begin
                    MCCU_rstn_D = rstn_i && !MCCU_softrst;
                end
        end
        triple_reg#(.IN_WIDTH(1)
        )mccu_rst_trip(
        .clk_i(clk_i),
        .rstn_i(rstn_i),
        .din_i(MCCU_rstn_D),
        .dout_o(MCCU_rstn_Q),
        .error1_o(MCCU_rstn_fte1), // ignore corrected errors
        .error2_o(MCCU_rstn_fte2)
        );
Guillem's avatar
Guillem committed
591
592
593
594
    end
    
    //register enable to solve Hazards
    reg MCCU_enable_int;
GuillemCabo's avatar
GuillemCabo committed
595
    always @(posedge clk_i) begin: MCCU_glitchless_enable
Guillem's avatar
Guillem committed
596
597
598
599
600
601
            if (!rstn_i) begin
                MCCU_enable_int <= 0;
            end else begin
                MCCU_enable_int <= regs_i[BASE_MCCU_CFG][0];
            end
    end
602
    logic MCCU_intr_FT1, MCCU_intr_FT2; 
Guillem's avatar
Guillem committed
603
    MCCU # (
Guillem's avatar
Guillem committed
604
        // Width of data registers
Guillem's avatar
Guillem committed
605
        .DATA_WIDTH     (REG_WIDTH),
Guillem's avatar
Guillem committed
606
607
608
609
        // Width of weights registers
        .WEIGHTS_WIDTH  (MCCU_WEIGHTS_WIDTH),
        //Cores. Change this may break Verilator TB
        .N_CORES        (MCCU_N_CORES),
610
611
        // Fault tolerance mechanisms (FT==0 -> FT disabled)
        .FT (FT),
Guillem's avatar
Guillem committed
612
        //Signals per core. Change this may break Verilator TB
Guillem's avatar
Guillem committed
613
        .CORE_EVENTS    (MCCU_N_EVENTS)
Guillem's avatar
Guillem committed
614
615
616
    )
    inst_MCCU(
        .clk_i                  (clk_i),
GuillemCabo's avatar
GuillemCabo committed
617
        .rstn_i                 (MCCU_rstn_Q),//active low
Guillem's avatar
Guillem committed
618
        .enable_i               (MCCU_enable_int),// Software map
Guillem's avatar
Guillem committed
619
620
        .events_i               (MCCU_events_int),
        .quota_i                (regs_i[BASE_MCCU_LIMITS:END_MCCU_LIMITS]),//One register per core
Guillem's avatar
Guillem committed
621
        .update_quota_i         (MCCU_update_quota_int),//Software map
Guillem's avatar
Guillem committed
622
        .quota_o                (regs_o[BASE_MCCU_QUOTA:END_MCCU_QUOTA]),//write back to a read register
Guillem's avatar
Guillem committed
623
        .events_weights_i       (MCCU_events_weights_int),//core_events times WEIGHTS_WIDTH registers
624
625
        .intr_FT1_o             (MCCU_intr_FT1),
        .intr_FT2_o             (MCCU_intr_FT2),
Guillem's avatar
Guillem committed
626
        .interruption_quota_o   (MCCU_intr_up)//N_CORES output signals Add this to top or single toplevel interrupt and an interrupt vector that identifies the source?
Guillem's avatar
Guillem committed
627
628
629
630
                                   // Individual interrupts allow each core to
                                   // handle their own interrupts , therefore
                                   //it seems to be te right solution.
    );
Guillem's avatar
Guillem committed
631

Guillem's avatar
Guillem committed
632
633
634
//----------------------------------------------
//------------- Request Duration Counter (RDC) 
//----------------------------------------------
Guillem's avatar
Guillem committed
635
636
637
    
    //Interruption vector to indicate signal exceeding weight
    wire [MCCU_N_EVENTS-1:0] interruption_rdc_o [0:MCCU_N_CORES-1];
638
639
640
641
    generate
        for(q=0;q<MCCU_N_CORES;q++) begin
            assign regs_o[BASE_RDC_VECT][2*q+1:q*2] = interruption_rdc_o [q] ;
        end
Guillem's avatar
Guillem committed
642
        //spare bits on RDC_VECT
643
644
        assign regs_o[BASE_RDC_VECT][REG_WIDTH-1:MCCU_N_CORES*2] = '{default:0} ;
    endgenerate
Guillem's avatar
Guillem committed
645
    
GuillemCabo's avatar
GuillemCabo committed
646
    if (FT==0) begin
647
648
   //register enable to solve Hazards
    reg RDC_rstn;
GuillemCabo's avatar
GuillemCabo committed
649
    always @(posedge clk_i) begin: RDC_glitchless_rstn
650
651
652
            if (!rstn_i) begin
                RDC_rstn <= 0;
            end else begin
GuillemCabo's avatar
GuillemCabo committed
653
654
                // Offset RDC enable, MCCU soft rest, enable and individual core updates
                RDC_rstn <= rstn_i && !regs_i[BASE_MCCU_CFG][MCCU_N_CORES+2+2];
655
656
657
            end
    end
    //register enable to solve Hazards
GuillemCabo's avatar
GuillemCabo committed
658
659
660
        // Does not nid replication since regs_i is already protected
        // RDC_enable_int may be disabled for a single cycle but
        // it will not be a permanent fault
661
    reg RDC_enable_int;
GuillemCabo's avatar
GuillemCabo committed
662
    always @(posedge clk_i) begin: RDC_glitchless_enable
663
664
665
            if (!rstn_i) begin
                RDC_enable_int <= 0;
            end else begin
GuillemCabo's avatar
GuillemCabo committed
666
667
                // Offset MCCU soft rest, enable and individual core updates
                RDC_enable_int <= regs_i[BASE_MCCU_CFG][MCCU_N_CORES+2+1];
668
669
            end
    end 
Guillem's avatar
Guillem committed
670
671
    RDC #(
        // Width of data registers
Guillem's avatar
Guillem committed
672
        .DATA_WIDTH     (REG_WIDTH),
Guillem's avatar
Guillem committed
673
        // Width of weights registers
Guillem's avatar
Guillem committed
674
        .WEIGHTS_WIDTH  (RDC_WEIGHTS_WIDTH),
Guillem's avatar
Guillem committed
675
        //Cores. 
Guillem's avatar
Guillem committed
676
        .N_CORES        (RDC_N_CORES),
Guillem's avatar
Guillem committed
677
        //Signals per core. 
Guillem's avatar
Guillem committed
678
        .CORE_EVENTS    (RDC_N_EVENTS)
Guillem's avatar
Guillem committed
679
680
    ) inst_RDC(
        .clk_i                  (clk_i),
681
        .rstn_i                 (RDC_rstn), //active low
Guillem's avatar
Guillem committed
682
        .enable_i               (RDC_enable_int),// Software map
Guillem's avatar
Guillem committed
683
        .events_i               (MCCU_events_int),
Guillem's avatar
Guillem committed
684
685
686
687
        .events_weights_i       (MCCU_events_weights_int),
        // interruption signaling a signal has exceed the expected maximum request time
        .interruption_rdc_o(intr_RDC_o),
        // vector with offending signals. One hot encoding. Cleared when MCCU is disabled.
688
689
690
        .interruption_vector_rdc_o(interruption_rdc_o),
        //maximum pulse length of a given core event
        .watermark_o(MCCU_watermark_int) 
Guillem's avatar
Guillem committed
691
    );
GuillemCabo's avatar
GuillemCabo committed
692
    end else begin : Rdctrip
GuillemCabo's avatar
GuillemCabo committed
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
   //register enable to solve Hazards
    logic RDC_rstn_D, RDC_rstn_Q;
    logic RDC_rstn_fte1,RDC_rstn_fte2;
    always_comb begin: RDC_rstn
            if (!rstn_i) begin
                RDC_rstn_D = 0;
            end else begin
                RDC_rstn_D = rstn_i && !regs_i[BASE_MCCU_CFG][7];
            end
    end
    triple_reg#(.IN_WIDTH(1)
    )mccu_rst_trip(
    .clk_i(clk_i),
    .rstn_i(rstn_i),
    .din_i(RDC_rstn_D),
    .dout_o(RDC_rstn_Q),
    .error1_o(RDC_rstn_fte1), // ignore corrected errors
    .error2_o(RDC_rstn_fte2)
    );
GuillemCabo's avatar
GuillemCabo committed
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
    //register enable to solve Hazards
        // Does not nid replication since regs_i is already protected
        // RDC_enable_int may be disabled for a single cycle but
        // it will not be a permanent fault
    logic RDC_enable_int_D, RDC_enable_int_Q;
    logic RDC_enable_fte1, RDC_enable_fte2;
    triple_reg#(.IN_WIDTH(1)
    )RDC_enable_trip(
    .clk_i(clk_i),
    .rstn_i(rstn_i),
    .din_i(RDC_enable_int_D),
    .dout_o(RDC_enable_int_Q),
    .error1_o(RDC_enable_fte1), // ignore corrected errors
    .error2_o(RDC_enable_fte2)
    );

    always @(posedge clk_i) begin: RDC_glitchless_enable
            if (!rstn_i) begin
                RDC_enable_int_D <= 0;
            end else begin
                RDC_enable_int_D <= regs_i[BASE_MCCU_CFG][6];
            end
    end 
    
    //Signals from instances to way3 voter
        //inst
    logic intr_RDC_ft0 ;
    logic [MCCU_N_EVENTS-1:0] interruption_rdc_ft0 [0:MCCU_N_CORES-1];
    logic [MCCU_WEIGHTS_WIDTH-1:0] MCCU_watermark_ft0 [0:MCCU_N_CORES-1]
                                                     [0:MCCU_N_EVENTS-1];
        //inst1
    logic intr_RDC_ft1 ;
    logic [MCCU_N_EVENTS-1:0] interruption_rdc_ft1 [0:MCCU_N_CORES-1];
    logic [MCCU_WEIGHTS_WIDTH-1:0] MCCU_watermark_ft1 [0:MCCU_N_CORES-1]
                                                     [0:MCCU_N_EVENTS-1];
        //inst2
    logic intr_RDC_ft2 ;
    logic [MCCU_N_EVENTS-1:0] interruption_rdc_ft2 [0:MCCU_N_CORES-1];
    logic [MCCU_WEIGHTS_WIDTH-1:0] MCCU_watermark_ft2 [0:MCCU_N_CORES-1]
                                                     [0:MCCU_N_EVENTS-1];

    //FT error detected signals
    //Even when the error is corrected latent faults may be present on this signals
        // and software shall clear them
    logic    intr_RDC_fte1, interruption_rdc_fte1, MCCU_watermark_fte1; 
    logic    intr_RDC_fte2, interruption_rdc_fte2, MCCU_watermark_fte2;
    RDC #(
        .DATA_WIDTH     (REG_WIDTH),
        .WEIGHTS_WIDTH  (RDC_WEIGHTS_WIDTH),
        .N_CORES        (RDC_N_CORES),
        .CORE_EVENTS    (RDC_N_EVENTS)
    ) inst_RDC(
        .clk_i                  (clk_i),
GuillemCabo's avatar
GuillemCabo committed
765
        .rstn_i                 (RDC_rstn_Q), //active low
GuillemCabo's avatar
GuillemCabo committed
766
767
768
769
770
771
772
773
774
775
776
777
778
779
        .enable_i               (RDC_enable_int_Q),// Software map
        .events_i               (MCCU_events_int),
        .events_weights_i       (MCCU_events_weights_int),
        .interruption_rdc_o(intr_RDC_ft0),
        .interruption_vector_rdc_o(interruption_rdc_ft0),
        .watermark_o(MCCU_watermark_ft0) 
    );
    RDC #(
        .DATA_WIDTH     (REG_WIDTH),
        .WEIGHTS_WIDTH  (RDC_WEIGHTS_WIDTH),
        .N_CORES        (RDC_N_CORES),
        .CORE_EVENTS    (RDC_N_EVENTS)
    ) inst1_RDC(
        .clk_i                  (clk_i),
GuillemCabo's avatar
GuillemCabo committed
780
        .rstn_i                 (RDC_rstn_Q), //active low
GuillemCabo's avatar
GuillemCabo committed
781
782
783
784
785
786
787
788
789
790
791
792
793
794
        .enable_i               (RDC_enable_int_Q),// Software map
        .events_i               (MCCU_events_int),
        .events_weights_i       (MCCU_events_weights_int),
        .interruption_rdc_o(intr_RDC_ft1),
        .interruption_vector_rdc_o(interruption_rdc_ft1),
        .watermark_o(MCCU_watermark_ft1) 
    );
    RDC #(
        .DATA_WIDTH     (REG_WIDTH),
        .WEIGHTS_WIDTH  (RDC_WEIGHTS_WIDTH),
        .N_CORES        (RDC_N_CORES),
        .CORE_EVENTS    (RDC_N_EVENTS)
    ) inst2_RDC(
        .clk_i                  (clk_i),
GuillemCabo's avatar
GuillemCabo committed
795
        .rstn_i                 (RDC_rstn_Q), //active low
GuillemCabo's avatar
GuillemCabo committed
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
        .enable_i               (RDC_enable_int_Q),// Software map
        .events_i               (MCCU_events_int),
        .events_weights_i       (MCCU_events_weights_int),
        .interruption_rdc_o(intr_RDC_ft2),
        .interruption_vector_rdc_o(interruption_rdc_ft2),
        .watermark_o(MCCU_watermark_ft2) 
    );
    // intr_RDC_ft
    way3_voter #(
		.IN_WIDTH(1)
	)intr_RDC_way3(
        .in0(intr_RDC_ft0),
        .in1(intr_RDC_ft1),
        .in2(intr_RDC_ft2),
        .out(intr_RDC_o),
        .error1_o(intr_RDC_fte1),
        .error2_o(intr_RDC_fte2)
	);

    // interruption_rdc_ft
    way3ua_voter #(
		.W(MCCU_N_EVENTS),
		.U(MCCU_N_CORES)
	)interruption_rdc_way3(
        .in0(interruption_rdc_ft0),
        .in1(interruption_rdc_ft1),
        .in2(interruption_rdc_ft2),
        .out(interruption_rdc_o),
        .error1_o(interruption_rdc_fte1),
        .error2_o(interruption_rdc_fte2)
	);
    // MCCU_watermark_ft
    way3u2a_voter #(
		.W(MCCU_WEIGHTS_WIDTH),
		.U(MCCU_N_CORES),
		.D(MCCU_N_EVENTS)
	)watermark_way3(
        .in0(MCCU_watermark_ft0),
        .in1(MCCU_watermark_ft1),
        .in2(MCCU_watermark_ft2),
        .out(MCCU_watermark_int),
        .error1_o(MCCU_watermark_fte1),
        .error2_o(MCCU_watermark_fte2)
	);

    end
842
843
844
845
846
847
848
849
850
851
852
    //----------------------------------------------
    //------------- Generate intr_FT_o
    //----------------------------------------------
    if (FT == 0 ) begin
            assign intr_FT1_o = 1'b0;
            assign intr_FT2_o = 1'b0;
    end else begin 
            //Gather all the signals of corrected errors from FT scopes
                // Codestyle. All scopes start with a capital letter
            assign intr_FT1_o = |{
                                Rdctrip.MCCU_watermark_fte1,Rdctrip.intr_RDC_fte1,
853
                                Rdctrip.interruption_rdc_fte1,Rdctrip.RDC_enable_fte1,
GuillemCabo's avatar
GuillemCabo committed
854
855
                                MCCU_intr_FT1, Ft_mccu_rst.MCCU_rstn_fte1,
                                Rdctrip.RDC_rstn_fte1
856
857
858
859
860
                                 };
            //Gather all the signals of uncorrected errors from FT scopes
                // Codestyle. All scopes start with a capital letter
            assign intr_FT2_o = |{
                                Rdctrip.MCCU_watermark_fte2,Rdctrip.intr_RDC_fte2,
861
                                Rdctrip.interruption_rdc_fte2,Rdctrip.RDC_enable_fte2,
GuillemCabo's avatar
GuillemCabo committed
862
                                MCCU_intr_FT2, Ft_mccu_rst.MCCU_rstn_fte2,
863
                                Rdctrip.RDC_rstn_fte2, counters_fte2
864
865
                                 };
    end
Guillem's avatar
Guillem committed
866
/////////////////////////////////////////////////////////////////////////////////
Guillem's avatar
Guillem committed
867
868
869
870
871
//
// Formal Verification section begins here.
//
////////////////////////////////////////////////////////////////////////////////
`ifdef	FORMAL
Guillem's avatar
Guillem committed
872
873
874
875
876
877
878
879
880
881
882
883
884
    //auxiliar registers
    reg f_past_valid ;
    initial f_past_valid = 1'b0;
    //Set f_past_valid after first clock cycle
    always@( posedge clk_i )
        f_past_valid <= 1'b1;
   
    //assume that if f_past is not valid you have to reset
    always @(*) begin
		if(0 == f_past_valid) begin
            assume(0 == rstn_i);
         end
    end
Guillem's avatar
Guillem committed
885
886
887
888
    
    default clocking @(posedge clk_i); endclocking   
    // Cover that all the bits in the mask are driven
    cover property ((overflow_intr_mask_i[0]==32'b111111111) && f_past_valid );
Guillem's avatar
Guillem committed
889
890
891
892
893
894
`endif

endmodule

`default_nettype wire //allow compatibility with legacy code and xilinx ip