hw/top_earlgrey/ip/rv_plic/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+1)
  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:   import rv_plic_reg_pkg::*;
  47: 
  48:   rv_plic_reg2hw_t reg2hw;
  49:   rv_plic_hw2reg_t hw2reg;
  50: 
  51:   localparam int MAX_PRIO    = 3;
  52:   localparam int PRIOW = $clog2(MAX_PRIO+1);
  53: 
  54:   logic [NumSrc-1:0] le; // 0:level 1:edge
  55:   logic [NumSrc-1:0] ip;
  56: 
  57:   logic [NumSrc-1:0] ie [NumTarget];
  58: 
  59:   logic [NumTarget-1:0] claim_re; // Target read indicator
  60:   logic [SRCW-1:0]      claim_id [NumTarget];
  61:   logic [NumSrc-1:0]    claim; // Converted from claim_re/claim_id
  62: 
  63:   logic [NumTarget-1:0] complete_we; // Target write indicator
  64:   logic [SRCW-1:0]      complete_id [NumTarget];
  65:   logic [NumSrc-1:0]    complete; // Converted from complete_re/complete_id
  66: 
  67:   logic [SRCW-1:0]      cc_id [NumTarget]; // Write ID
  68: 
  69:   logic [PRIOW-1:0] prio [NumSrc];
  70: 
  71:   logic [PRIOW-1:0] threshold [NumTarget];
  72: 
  73:   // Glue logic between rv_plic_reg_top and others
  74:   assign cc_id = irq_id_o;
  75: 
  76:   always_comb begin
  77:     claim = '0;
  78:     for (int i = 0 ; i < NumTarget ; i++) begin
  79:       if (claim_re[i]) claim[claim_id[i] -1] = 1'b1;
  80:     end
  81:   end
  82:   always_comb begin
  83:     complete = '0;
  84:     for (int i = 0 ; i < NumTarget ; i++) begin
  85:       if (complete_we[i]) complete[complete_id[i] -1] = 1'b1;
  86:     end
  87:   end
  88: 
  89:   //`ASSERT_PULSE(claimPulse, claim_re[i], clk_i, !rst_ni)
  90:   //`ASSERT_PULSE(completePulse, complete_we[i], clk_i, !rst_ni)
  91: 
  92:   `ASSERT(onehot0Claim, $onehot0(claim_re), clk_i, !rst_ni)
  93: 
  94:   `ASSERT(onehot0Complete, $onehot0(complete_we), clk_i, !rst_ni)
  95: 
  96:   //////////////
  97:   // Priority //
  98:   //////////////
  99:   assign prio[0] = reg2hw.prio0.q;
 100:   assign prio[1] = reg2hw.prio1.q;
 101:   assign prio[2] = reg2hw.prio2.q;
 102:   assign prio[3] = reg2hw.prio3.q;
 103:   assign prio[4] = reg2hw.prio4.q;
 104:   assign prio[5] = reg2hw.prio5.q;
 105:   assign prio[6] = reg2hw.prio6.q;
 106:   assign prio[7] = reg2hw.prio7.q;
 107:   assign prio[8] = reg2hw.prio8.q;
 108:   assign prio[9] = reg2hw.prio9.q;
 109:   assign prio[10] = reg2hw.prio10.q;
 110:   assign prio[11] = reg2hw.prio11.q;
 111:   assign prio[12] = reg2hw.prio12.q;
 112:   assign prio[13] = reg2hw.prio13.q;
 113:   assign prio[14] = reg2hw.prio14.q;
 114:   assign prio[15] = reg2hw.prio15.q;
 115:   assign prio[16] = reg2hw.prio16.q;
 116:   assign prio[17] = reg2hw.prio17.q;
 117:   assign prio[18] = reg2hw.prio18.q;
 118:   assign prio[19] = reg2hw.prio19.q;
 119:   assign prio[20] = reg2hw.prio20.q;
 120:   assign prio[21] = reg2hw.prio21.q;
 121:   assign prio[22] = reg2hw.prio22.q;
 122:   assign prio[23] = reg2hw.prio23.q;
 123:   assign prio[24] = reg2hw.prio24.q;
 124:   assign prio[25] = reg2hw.prio25.q;
 125:   assign prio[26] = reg2hw.prio26.q;
 126:   assign prio[27] = reg2hw.prio27.q;
 127:   assign prio[28] = reg2hw.prio28.q;
 128:   assign prio[29] = reg2hw.prio29.q;
 129:   assign prio[30] = reg2hw.prio30.q;
 130:   assign prio[31] = reg2hw.prio31.q;
 131:   assign prio[32] = reg2hw.prio32.q;
 132:   assign prio[33] = reg2hw.prio33.q;
 133:   assign prio[34] = reg2hw.prio34.q;
 134:   assign prio[35] = reg2hw.prio35.q;
 135:   assign prio[36] = reg2hw.prio36.q;
 136:   assign prio[37] = reg2hw.prio37.q;
 137:   assign prio[38] = reg2hw.prio38.q;
 138:   assign prio[39] = reg2hw.prio39.q;
 139:   assign prio[40] = reg2hw.prio40.q;
 140:   assign prio[41] = reg2hw.prio41.q;
 141:   assign prio[42] = reg2hw.prio42.q;
 142:   assign prio[43] = reg2hw.prio43.q;
 143:   assign prio[44] = reg2hw.prio44.q;
 144:   assign prio[45] = reg2hw.prio45.q;
 145:   assign prio[46] = reg2hw.prio46.q;
 146:   assign prio[47] = reg2hw.prio47.q;
 147:   assign prio[48] = reg2hw.prio48.q;
 148:   assign prio[49] = reg2hw.prio49.q;
 149:   assign prio[50] = reg2hw.prio50.q;
 150:   assign prio[51] = reg2hw.prio51.q;
 151:   assign prio[52] = reg2hw.prio52.q;
 152:   assign prio[53] = reg2hw.prio53.q;
 153:   assign prio[54] = reg2hw.prio54.q;
 154:   assign prio[55] = reg2hw.prio55.q;
 155:   assign prio[56] = reg2hw.prio56.q;
 156:   assign prio[57] = reg2hw.prio57.q;
 157:   assign prio[58] = reg2hw.prio58.q;
 158:   assign prio[59] = reg2hw.prio59.q;
 159:   assign prio[60] = reg2hw.prio60.q;
 160:   assign prio[61] = reg2hw.prio61.q;
 161:   assign prio[62] = reg2hw.prio62.q;
 162: 
 163:   //////////////////////
 164:   // Interrupt Enable //
 165:   //////////////////////
 166:   for (genvar s = 0; s < 63; s++) begin : gen_ie0
 167:     assign ie[0][s] = reg2hw.ie0[s].q;
 168:   end
 169: 
 170:   ////////////////////////
 171:   // THRESHOLD register //
 172:   ////////////////////////
 173:   assign threshold[0] = reg2hw.threshold0.q;
 174: 
 175:   /////////////////
 176:   // CC register //
 177:   /////////////////
 178:   assign claim_re[0]    = reg2hw.cc0.re;
 179:   assign claim_id[0]    = irq_id_o[0];
 180:   assign complete_we[0] = reg2hw.cc0.qe;
 181:   assign complete_id[0] = reg2hw.cc0.q;
 182:   assign hw2reg.cc0.d   = cc_id[0];
 183: 
 184:   ///////////////////
 185:   // MSIP register //
 186:   ///////////////////
 187:   assign msip_o[0] = reg2hw.msip0.q;
 188: 
 189:   ////////
 190:   // IP //
 191:   ////////
 192:   for (genvar s = 0; s < 63; s++) begin : gen_ip
 193:     assign hw2reg.ip[s].de = 1'b1; // Always write
 194:     assign hw2reg.ip[s].d  = ip[s];
 195:   end
 196: 
 197:   ///////////////////////////////////
 198:   // Detection:: 0: Level, 1: Edge //
 199:   ///////////////////////////////////
 200:   for (genvar s = 0; s < 63; s++) begin : gen_le
 201:     assign le[s] = reg2hw.le[s].q;
 202:   end
 203: 
 204:   //////////////
 205:   // Gateways //
 206:   //////////////
 207:   rv_plic_gateway #(
 208:     .N_SOURCE (NumSrc)
 209:   ) u_gateway (
 210:     .clk_i,
 211:     .rst_ni,
 212: 
 213:     .src (intr_src_i),
 214:     .le,
 215: 
 216:     .claim,
 217:     .complete,
 218: 
 219:     .ip
 220:   );
 221: 
 222:   ///////////////////////////////////
 223:   // Target interrupt notification //
 224:   ///////////////////////////////////
 225:   for (genvar i = 0 ; i < NumTarget ; i++) begin : gen_target
 226:     rv_plic_target #(
 227:       .N_SOURCE (NumSrc),
 228:       .MAX_PRIO (MAX_PRIO)
 229:     ) u_target (
 230:       .clk_i,
 231:       .rst_ni,
 232: 
 233:       .ip,
 234:       .ie        (ie[i]),
 235: 
 236:       .prio,
 237:       .threshold (threshold[i]),
 238: 
 239:       .irq       (irq_o[i]),
 240:       .irq_id    (irq_id_o[i])
 241: 
 242:     );
 243:   end
 244: 
 245:   ////////////////////////
 246:   // Register interface //
 247:   ////////////////////////
 248:   //  Limitation of register tool prevents the module from having flexibility to parameters
 249:   //  So, signals are manually tied at the top.
 250:   rv_plic_reg_top u_reg (
 251:     .clk_i,
 252:     .rst_ni,
 253: 
 254:     .tl_i,
 255:     .tl_o,
 256: 
 257:     .reg2hw,
 258:     .hw2reg,
 259: 
 260:     .devmode_i  (1'b1)
 261:   );
 262: 
 263:   // Assertions
 264:   `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid, clk_i, !rst_ni)
 265:   `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready, clk_i, !rst_ni)
 266:   `ASSERT_KNOWN(IrqKnownO_A, irq_o, clk_i, !rst_ni)
 267:   `ASSERT_KNOWN(MsipKnownO_A, msip_o, clk_i, !rst_ni)
 268:   for (genvar k = 0; k < NumTarget; k++) begin : gen_irq_id_known
 269:     `ASSERT_KNOWN(IrqIdKnownO_A, irq_id_o[k], clk_i, !rst_ni)
 270:   end
 271: 
 272: endmodule
 273: