../src/lowrisc_top_earlgrey_rv_plic_0.1/rtl/autogen/rv_plic.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: //
   5: // ------------------- W A R N I N G: A U T O - G E N E R A T E D   C O D E !! -------------------//
   6: // PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
   7: // util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson --plic-only -o hw/top_earlgrey/
   8: 
   9: // Copyright lowRISC contributors.
  10: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
  11: // SPDX-License-Identifier: Apache-2.0
  12: //
  13: // RISC-V Platform-Level Interrupt Controller compliant INTC
  14: //
  15: //   Current version doesn't support MSI interrupt but it is easy to add
  16: //   the feature. Create one external register and connect qe signal to the
  17: //   gateway module (as edge-triggered)
  18: //
  19: //   Consider to set MAX_PRIO as small number as possible. It is main factor
  20: //   of area increase if edge-triggered counter isn't implemented.
  21: //
  22: // Verilog parameter
  23: //   MAX_PRIO: Maximum value of interrupt priority
  24: 
  25: module rv_plic import rv_plic_reg_pkg::*; #(
  26:   // derived parameter
  27:   localparam int SRCW    = $clog2(NumSrc)
  28: ) (
  29:   input     clk_i,
  30:   input     rst_ni,
  31: 
  32:   // Bus Interface (device)
  33:   input  tlul_pkg::tl_h2d_t tl_i,
  34:   output tlul_pkg::tl_d2h_t tl_o,
  35: 
  36:   // Interrupt Sources
  37:   input  [NumSrc-1:0] intr_src_i,
  38: 
  39:   // Interrupt notification to targets
  40:   output [NumTarget-1:0] irq_o,
  41:   output [SRCW-1:0]      irq_id_o [NumTarget],
  42: 
  43:   output logic [NumTarget-1:0] msip_o
  44: );
  45: 
  46:   rv_plic_reg2hw_t reg2hw;
  47:   rv_plic_hw2reg_t hw2reg;
  48: 
  49:   localparam int MAX_PRIO    = 3;
  50:   localparam int PRIOW = $clog2(MAX_PRIO+1);
  51: 
  52:   logic [NumSrc-1:0] le; // 0:level 1:edge
  53:   logic [NumSrc-1:0] ip;
  54: 
  55:   logic [NumSrc-1:0] ie [NumTarget];
  56: 
  57:   logic [NumTarget-1:0] claim_re; // Target read indicator
  58:   logic [SRCW-1:0]      claim_id [NumTarget];
  59:   logic [NumSrc-1:0]    claim; // Converted from claim_re/claim_id
  60: 
  61:   logic [NumTarget-1:0] complete_we; // Target write indicator
  62:   logic [SRCW-1:0]      complete_id [NumTarget];
  63:   logic [NumSrc-1:0]    complete; // Converted from complete_re/complete_id
  64: 
  65:   logic [SRCW-1:0]      cc_id [NumTarget]; // Write ID
  66: 
  67:   logic [PRIOW-1:0] prio [NumSrc];
  68: 
  69:   logic [PRIOW-1:0] threshold [NumTarget];
  70: 
  71:   // Glue logic between rv_plic_reg_top and others
  72:   assign cc_id = irq_id_o;
  73: 
  74:   always_comb begin
  75:     claim = '0;
  76:     for (int i = 0 ; i < NumTarget ; i++) begin
  77:       if (claim_re[i]) claim[claim_id[i]] = 1'b1;
  78:     end
  79:   end
  80:   always_comb begin
  81:     complete = '0;
  82:     for (int i = 0 ; i < NumTarget ; i++) begin
  83:       if (complete_we[i]) complete[complete_id[i]] = 1'b1;
  84:     end
  85:   end
  86: 
  87:   //`ASSERT_PULSE(claimPulse, claim_re[i])
  88:   //`ASSERT_PULSE(completePulse, complete_we[i])
  89: 
  90:   `ASSERT(onehot0Claim, $onehot0(claim_re))
  91: 
  92:   `ASSERT(onehot0Complete, $onehot0(complete_we))
  93: 
  94:   //////////////
  95:   // Priority //
  96:   //////////////
  97:   assign prio[0] = reg2hw.prio0.q;
  98:   assign prio[1] = reg2hw.prio1.q;
  99:   assign prio[2] = reg2hw.prio2.q;
 100:   assign prio[3] = reg2hw.prio3.q;
 101:   assign prio[4] = reg2hw.prio4.q;
 102:   assign prio[5] = reg2hw.prio5.q;
 103:   assign prio[6] = reg2hw.prio6.q;
 104:   assign prio[7] = reg2hw.prio7.q;
 105:   assign prio[8] = reg2hw.prio8.q;
 106:   assign prio[9] = reg2hw.prio9.q;
 107:   assign prio[10] = reg2hw.prio10.q;
 108:   assign prio[11] = reg2hw.prio11.q;
 109:   assign prio[12] = reg2hw.prio12.q;
 110:   assign prio[13] = reg2hw.prio13.q;
 111:   assign prio[14] = reg2hw.prio14.q;
 112:   assign prio[15] = reg2hw.prio15.q;
 113:   assign prio[16] = reg2hw.prio16.q;
 114:   assign prio[17] = reg2hw.prio17.q;
 115:   assign prio[18] = reg2hw.prio18.q;
 116:   assign prio[19] = reg2hw.prio19.q;
 117:   assign prio[20] = reg2hw.prio20.q;
 118:   assign prio[21] = reg2hw.prio21.q;
 119:   assign prio[22] = reg2hw.prio22.q;
 120:   assign prio[23] = reg2hw.prio23.q;
 121:   assign prio[24] = reg2hw.prio24.q;
 122:   assign prio[25] = reg2hw.prio25.q;
 123:   assign prio[26] = reg2hw.prio26.q;
 124:   assign prio[27] = reg2hw.prio27.q;
 125:   assign prio[28] = reg2hw.prio28.q;
 126:   assign prio[29] = reg2hw.prio29.q;
 127:   assign prio[30] = reg2hw.prio30.q;
 128:   assign prio[31] = reg2hw.prio31.q;
 129:   assign prio[32] = reg2hw.prio32.q;
 130:   assign prio[33] = reg2hw.prio33.q;
 131:   assign prio[34] = reg2hw.prio34.q;
 132:   assign prio[35] = reg2hw.prio35.q;
 133:   assign prio[36] = reg2hw.prio36.q;
 134:   assign prio[37] = reg2hw.prio37.q;
 135:   assign prio[38] = reg2hw.prio38.q;
 136:   assign prio[39] = reg2hw.prio39.q;
 137:   assign prio[40] = reg2hw.prio40.q;
 138:   assign prio[41] = reg2hw.prio41.q;
 139:   assign prio[42] = reg2hw.prio42.q;
 140:   assign prio[43] = reg2hw.prio43.q;
 141:   assign prio[44] = reg2hw.prio44.q;
 142:   assign prio[45] = reg2hw.prio45.q;
 143:   assign prio[46] = reg2hw.prio46.q;
 144:   assign prio[47] = reg2hw.prio47.q;
 145:   assign prio[48] = reg2hw.prio48.q;
 146:   assign prio[49] = reg2hw.prio49.q;
 147:   assign prio[50] = reg2hw.prio50.q;
 148:   assign prio[51] = reg2hw.prio51.q;
 149:   assign prio[52] = reg2hw.prio52.q;
 150:   assign prio[53] = reg2hw.prio53.q;
 151:   assign prio[54] = reg2hw.prio54.q;
 152:   assign prio[55] = reg2hw.prio55.q;
 153:   assign prio[56] = reg2hw.prio56.q;
 154:   assign prio[57] = reg2hw.prio57.q;
 155:   assign prio[58] = reg2hw.prio58.q;
 156:   assign prio[59] = reg2hw.prio59.q;
 157:   assign prio[60] = reg2hw.prio60.q;
 158:   assign prio[61] = reg2hw.prio61.q;
 159:   assign prio[62] = reg2hw.prio62.q;
 160:   assign prio[63] = reg2hw.prio63.q;
 161:   assign prio[64] = reg2hw.prio64.q;
 162:   assign prio[65] = reg2hw.prio65.q;
 163:   assign prio[66] = reg2hw.prio66.q;
 164:   assign prio[67] = reg2hw.prio67.q;
 165:   assign prio[68] = reg2hw.prio68.q;
 166:   assign prio[69] = reg2hw.prio69.q;
 167:   assign prio[70] = reg2hw.prio70.q;
 168:   assign prio[71] = reg2hw.prio71.q;
 169:   assign prio[72] = reg2hw.prio72.q;
 170:   assign prio[73] = reg2hw.prio73.q;
 171:   assign prio[74] = reg2hw.prio74.q;
 172:   assign prio[75] = reg2hw.prio75.q;
 173:   assign prio[76] = reg2hw.prio76.q;
 174:   assign prio[77] = reg2hw.prio77.q;
 175:   assign prio[78] = reg2hw.prio78.q;
 176:   assign prio[79] = reg2hw.prio79.q;
 177:   assign prio[80] = reg2hw.prio80.q;
 178: 
 179:   //////////////////////
 180:   // Interrupt Enable //
 181:   //////////////////////
 182:   for (genvar s = 0; s < 81; s++) begin : gen_ie0
 183:     assign ie[0][s] = reg2hw.ie0[s].q;
 184:   end
 185: 
 186:   ////////////////////////
 187:   // THRESHOLD register //
 188:   ////////////////////////
 189:   assign threshold[0] = reg2hw.threshold0.q;
 190: 
 191:   /////////////////
 192:   // CC register //
 193:   /////////////////
 194:   assign claim_re[0]    = reg2hw.cc0.re;
 195:   assign claim_id[0]    = irq_id_o[0];
 196:   assign complete_we[0] = reg2hw.cc0.qe;
 197:   assign complete_id[0] = reg2hw.cc0.q;
 198:   assign hw2reg.cc0.d   = cc_id[0];
 199: 
 200:   ///////////////////
 201:   // MSIP register //
 202:   ///////////////////
 203:   assign msip_o[0] = reg2hw.msip0.q;
 204: 
 205:   ////////
 206:   // IP //
 207:   ////////
 208:   for (genvar s = 0; s < 81; s++) begin : gen_ip
 209:     assign hw2reg.ip[s].de = 1'b1; // Always write
 210:     assign hw2reg.ip[s].d  = ip[s];
 211:   end
 212: 
 213:   ///////////////////////////////////
 214:   // Detection:: 0: Level, 1: Edge //
 215:   ///////////////////////////////////
 216:   for (genvar s = 0; s < 81; s++) begin : gen_le
 217:     assign le[s] = reg2hw.le[s].q;
 218:   end
 219: 
 220:   //////////////
 221:   // Gateways //
 222:   //////////////
 223:   rv_plic_gateway #(
 224:     .N_SOURCE (NumSrc)
 225:   ) u_gateway (
 226:     .clk_i,
 227:     .rst_ni,
 228: 
 229:     .src (intr_src_i),
 230:     .le,
 231: 
 232:     .claim,
 233:     .complete,
 234: 
 235:     .ip
 236:   );
 237: 
 238:   ///////////////////////////////////
 239:   // Target interrupt notification //
 240:   ///////////////////////////////////
 241:   for (genvar i = 0 ; i < NumTarget ; i++) begin : gen_target
 242:     rv_plic_target #(
 243:       .N_SOURCE (NumSrc),
 244:       .MAX_PRIO (MAX_PRIO)
 245:     ) u_target (
 246:       .clk_i,
 247:       .rst_ni,
 248: 
 249:       .ip,
 250:       .ie        (ie[i]),
 251: 
 252:       .prio,
 253:       .threshold (threshold[i]),
 254: 
 255:       .irq       (irq_o[i]),
 256:       .irq_id    (irq_id_o[i])
 257: 
 258:     );
 259:   end
 260: 
 261:   ////////////////////////
 262:   // Register interface //
 263:   ////////////////////////
 264:   //  Limitation of register tool prevents the module from having flexibility to parameters
 265:   //  So, signals are manually tied at the top.
 266:   rv_plic_reg_top u_reg (
 267:     .clk_i,
 268:     .rst_ni,
 269: 
 270:     .tl_i,
 271:     .tl_o,
 272: 
 273:     .reg2hw,
 274:     .hw2reg,
 275: 
 276:     .devmode_i  (1'b1)
 277:   );
 278: 
 279:   // Assertions
 280:   `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid)
 281:   `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready)
 282:   `ASSERT_KNOWN(IrqKnownO_A, irq_o)
 283:   `ASSERT_KNOWN(MsipKnownO_A, msip_o)
 284:   for (genvar k = 0; k < NumTarget; k++) begin : gen_irq_id_known
 285:     `ASSERT_KNOWN(IrqIdKnownO_A, irq_id_o[k])
 286:   end
 287: 
 288:   // Assume
 289:   `ASSUME(Irq0Tied_A, intr_src_i[0] == 1'b0)
 290: 
 291: endmodule
 292: