From c3b77caf3af8abeef11cd84bb5dfc893531ad656 Mon Sep 17 00:00:00 2001 From: Eunchan Kim Date: Thu, 6 Jun 2019 08:48:22 -0700 Subject: [PATCH] Adding Top module template - Added top module template to generate RTL based on the #source #target - README is revised accordingly --- README.md | 8 +- doc/rv_plic.tpl.sv | 219 +++++++++++++++++ rtl/rv_plic.sv | 588 ++++++++++++++++++++++----------------------- 3 files changed, 507 insertions(+), 308 deletions(-) create mode 100644 doc/rv_plic.tpl.sv diff --git a/README.md b/README.md index 0de4fcd..1d42b51 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,13 @@ Privileges specification Section ## `reg_rv_plic.py` -The tool is to create register hjson file given values of number of sources, -number of targets, and max value of priority. By default `target` is **1** and -`priority` is **7** (8 level of priorities supported) +The tool is to create register hjson and top module `rv_plic.sv` files given +values of number of sources, number of targets, and max value of priority. By +default `target` is **1** and `priority` is **7** (8 level of priorities +supported) To change the value and to re-create hjson, $ reg_rv_plic.py -s 64 -t 2 -p 15 rv_plic_reg.tpl.hjson > rv_plic_reg.hjson + $ reg_rv_plic.py -s 64 -t 2 -p 15 rv_plic.tpl.sv > ../rtl/rv_plic.sv diff --git a/doc/rv_plic.tpl.sv b/doc/rv_plic.tpl.sv new file mode 100644 index 0000000..2eb61dc --- /dev/null +++ b/doc/rv_plic.tpl.sv @@ -0,0 +1,219 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// RISC-V Platform-Level Interrupt Controller compliant INTC +// +// Current version doesn't support MSI interrupt but it is easy to add +// the feature. Create one external register and connect qe signal to the +// gateway module (as edge-triggered) +// +// Consider to set MAX_PRIO as small number as possible. It is main factor +// of area increase if edge-triggered counter isn't implemented. +// +// verilog parameter +// N_SOURCE: Number of interrupt sources +// N_TARGET: Number of interrupt targets (#receptor) +// MAX_PRIO: Maximum value of interrupt priority + +module rv_plic #( + parameter int N_SOURCE = ${src}, + parameter int N_TARGET = ${target}, + parameter FIND_MAX = "SEQUENTIAL", // SEQUENTIAL | MATRIX + + parameter int SRCW = $clog2(N_SOURCE+1) // derived parameter +) ( + input clk_i, + input rst_ni, + + // Bus Interface (device) + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, + + // Interrupt Sources + input [N_SOURCE-1:0] intr_src_i, + + // Interrupt notification to targets + output [N_TARGET-1:0] irq_o, + output [SRCW-1:0] irq_id_o [N_TARGET] +); + + import rv_plic_reg_pkg::*; + + rv_plic_reg2hw_t reg2hw; + rv_plic_hw2reg_t hw2reg; + + localparam int MAX_PRIO = ${prio}; + localparam int PRIOW = $clog2(MAX_PRIO+1); + + logic [N_SOURCE-1:0] le; // 0:level 1:edge + logic [N_SOURCE-1:0] ip; + + logic [N_SOURCE-1:0] ie [N_TARGET]; + + logic [N_TARGET-1:0] claim_re; // Target read indicator + logic [SRCW-1:0] claim_id [N_TARGET]; + logic [N_SOURCE-1:0] claim; // Converted from claim_re/claim_id + + logic [N_TARGET-1:0] complete_we; // Target write indicator + logic [SRCW-1:0] complete_id [N_TARGET]; + logic [N_SOURCE-1:0] complete; // Converted from complete_re/complete_id + + logic [SRCW-1:0] cc_id [N_TARGET]; // Write ID + + logic [PRIOW-1:0] prio [N_SOURCE]; + + logic [PRIOW-1:0] threshold [N_TARGET]; + + // Glue logic between rv_plic_reg_top and others + assign cc_id = irq_id_o; + + always_comb begin + claim = '0; + for (int i = 0 ; i < N_TARGET ; i++) begin + if (claim_re[i]) claim[claim_id[i] -1] = 1'b1; + end + end + always_comb begin + complete = '0; + for (int i = 0 ; i < N_TARGET ; i++) begin + if (complete_we[i]) complete[complete_id[i] -1] = 1'b1; + end + end + + //`ASSERT_PULSE(claimPulse, claim_re[i], clk_i, !rst_ni) + //`ASSERT_PULSE(completePulse, complete_we[i], clk_i, !rst_ni) + + `ASSERT(onehot0Claim, $onehot0(claim_re), clk_i, !rst_ni) + + `ASSERT(onehot0Complete, $onehot0(complete_we), clk_i, !rst_ni) + + ////////////////////////////////////////////////////////////////////////////// + // Priority +% for s in range(src): + assign prio[${s}] = reg2hw.prio${s}.q; +% endfor + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // Interrupt Enable +% for t in range(target): + % for s in range(src): + % if s > 32: + ## TODO: make regwidth configurable + assign ie[${t}][${s}] = reg2hw.ie${t}${s//32}.e${s%32}.q; + % else: + ## no multireg expands to multiple registers + assign ie[${t}][${s}] = reg2hw.ie${t}.e${s}.q; + % endif + % endfor +% endfor + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // THRESHOLD register +% for t in range(target): + assign threshold[${t}] = reg2hw.threshold${t}.q; +% endfor + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // CC register +% for t in range(target): + assign claim_re[${t}] = reg2hw.cc${t}.re; + assign claim_id[${t}] = irq_id_o[${t}]; + assign complete_we[${t}] = reg2hw.cc${t}.qe; + assign complete_id[${t}] = reg2hw.cc${t}.q; + assign hw2reg.cc${t}.d = cc_id[${t}]; +% endfor + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // IP +% for s in range(src): + % if s > 32: + ## TODO: make regwidth configurable + assign hw2reg.ip${s//32}.p${s%32}.de = 1'b1; // Always write + % else: + ## no multireg expands to multiple registers + assign hw2reg.ip.p${s}.de = 1'b1; // Always write + % endif +% endfor +% for s in range(src): + % if s > 32: + ## TODO: make regwidth configurable + assign hw2reg.ip${s//32}.p${s%32}.d = ip[${s}]; + % else: + ## no multireg expands to multiple registers + assign hw2reg.ip.p${s}.d = ip[${s}]; + % endif +% endfor + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // Detection:: 0: Level, 1: Edge +% for s in range(src): + % if s > 32: + ## TODO: make regwidth configurable + assign le[${s}] = reg2hw.le${s//32}.le${s%32}.q; + % else: + ## no multireg expands to multiple registers + assign le[${s}] = reg2hw.le.le${s}.q; + % endif +% endfor + //---------------------------------------------------------------------------- + + // Gateways + rv_plic_gateway #( + .N_SOURCE (N_SOURCE) + ) u_gateway ( + .clk_i, + .rst_ni, + + .src (intr_src_i), + .le, + + .claim, + .complete, + + .ip + ); + + + // Target interrupt notification + for (genvar i = 0 ; i < N_TARGET ; i++) begin : gen_target + rv_plic_target #( + .N_SOURCE (N_SOURCE), + .MAX_PRIO (MAX_PRIO), + .ALGORITHM(FIND_MAX) + ) u_target ( + .clk_i, + .rst_ni, + + .ip, + .ie (ie[i]), + + .prio, + .threshold (threshold[i]), + + .irq (irq_o[i]), + .irq_id (irq_id_o[i]) + + ); + end + + // Register interface + // Limitation of register tool prevents the module from having flexibility to parameters + // So, signals are manually tied at the top. + rv_plic_reg_top u_reg ( + .clk_i, + .rst_ni, + + .tl_i, + .tl_o, + + .reg2hw, + .hw2reg + ); + +endmodule diff --git a/rtl/rv_plic.sv b/rtl/rv_plic.sv index 55e67d4..4b4af8b 100644 --- a/rtl/rv_plic.sv +++ b/rtl/rv_plic.sv @@ -15,343 +15,321 @@ // N_SOURCE: Number of interrupt sources // N_TARGET: Number of interrupt targets (#receptor) // MAX_PRIO: Maximum value of interrupt priority -// SRCW: Do not specify this parameter. It is bit width to cover MAX_ID+1 module rv_plic #( - parameter int N_SOURCE = 32, - parameter int N_TARGET = 1, - parameter int MAX_PRIO = 7, - parameter FIND_MAX = "SEQUENTIAL", // SEQUENTIAL | MATRIX + parameter int N_SOURCE = 32, + parameter int N_TARGET = 1, + parameter FIND_MAX = "SEQUENTIAL", // SEQUENTIAL | MATRIX - // Local param (Do not change this through parameter) - parameter int SRCW = $clog2(N_SOURCE+1) + parameter int SRCW = $clog2(N_SOURCE+1) // derived parameter ) ( - input clk_i, - input rst_ni, + input clk_i, + input rst_ni, - // Bus Interface (device) - input tlul_pkg::tl_h2d_t tl_i, - output tlul_pkg::tl_d2h_t tl_o, + // Bus Interface (device) + input tlul_pkg::tl_h2d_t tl_i, + output tlul_pkg::tl_d2h_t tl_o, - // Interrupt Sources - input [N_SOURCE-1:0] intr_src_i, + // Interrupt Sources + input [N_SOURCE-1:0] intr_src_i, - // Interrupt notification to targets - output irq_o [N_TARGET], - output [SRCW-1:0] irq_id_o [N_TARGET] + // Interrupt notification to targets + output [N_TARGET-1:0] irq_o, + output [SRCW-1:0] irq_id_o [N_TARGET] ); -import rv_plic_reg_pkg::*; + import rv_plic_reg_pkg::*; -rv_plic_reg2hw_t reg2hw; -rv_plic_hw2reg_t hw2reg; + rv_plic_reg2hw_t reg2hw; + rv_plic_hw2reg_t hw2reg; -localparam PRIOW = $clog2(MAX_PRIO+1); + localparam int MAX_PRIO = 7; + localparam int PRIOW = $clog2(MAX_PRIO+1); -logic [N_SOURCE-1:0] le; // 0:level 1:edge -logic [N_SOURCE-1:0] ip; + logic [N_SOURCE-1:0] le; // 0:level 1:edge + logic [N_SOURCE-1:0] ip; -logic [N_SOURCE-1:0] ie [N_TARGET]; + logic [N_SOURCE-1:0] ie [N_TARGET]; -logic claim_re [N_TARGET]; // Target read indicator -logic [SRCW-1:0] claim_id [N_TARGET]; -logic [N_SOURCE-1:0] claim ; // Converted from claim_re/claim_id + logic [N_TARGET-1:0] claim_re; // Target read indicator + logic [SRCW-1:0] claim_id [N_TARGET]; + logic [N_SOURCE-1:0] claim; // Converted from claim_re/claim_id -logic complete_we [N_TARGET]; // Target write indicator -logic [SRCW-1:0] complete_id [N_TARGET]; -logic [N_SOURCE-1:0] complete ; // Converted from complete_re/complete_id + logic [N_TARGET-1:0] complete_we; // Target write indicator + logic [SRCW-1:0] complete_id [N_TARGET]; + logic [N_SOURCE-1:0] complete; // Converted from complete_re/complete_id -logic [SRCW-1:0] cc_id [N_TARGET]; // Write ID + logic [SRCW-1:0] cc_id [N_TARGET]; // Write ID -logic [PRIOW-1:0] prio [N_SOURCE]; + logic [PRIOW-1:0] prio [N_SOURCE]; -logic [PRIOW-1:0] threshold [N_TARGET]; + logic [PRIOW-1:0] threshold [N_TARGET]; -// Glue logic between rv_plic_reg_top and others -assign cc_id = irq_id_o; + // Glue logic between rv_plic_reg_top and others + assign cc_id = irq_id_o; -always_comb begin - claim = '0; - for (int i = 0 ; i < N_TARGET ; i++) begin - if (claim_re[i]) claim[claim_id[i] -1] = 1'b1; + always_comb begin + claim = '0; + for (int i = 0 ; i < N_TARGET ; i++) begin + if (claim_re[i]) claim[claim_id[i] -1] = 1'b1; + end end -end -always_comb begin - complete = '0; - for (int i = 0 ; i < N_TARGET ; i++) begin - if (complete_we[i]) complete[complete_id[i] -1] = 1'b1; + always_comb begin + complete = '0; + for (int i = 0 ; i < N_TARGET ; i++) begin + if (complete_we[i]) complete[complete_id[i] -1] = 1'b1; + end end -end - -`ifndef VERILATOR -//sequence pulse_seq (sig); -// sig ##1 ~sig; -//endsequence - -property pulse_prop (sig); - @(posedge clk_i) - sig |=> ##1 ~sig; -endproperty - -//claim_pulse_assert: assert property (pulse_prop(claim_re[i])); -//complete_pulse_assert: assert property (pulse_prop(complete_we[i])); -onehot0_claim_assert: assert property ( - @(posedge clk_i) disable iff (!rst_ni) - $onehot0(claim_re) -); -onehot0_complete_assert: assert property ( - @(posedge clk_i) disable iff (!rst_ni) - $onehot0(complete_we) -); -`endif // VERILATOR - -//pragma translate_off -if(SRCW != $clog2(N_SOURCE+1)) $fatal("SRCW shouldn't be modified"); -//pragma translate_on - -//////////////////////////////////////////////////////////////////////////////// -// PRIORITY : Need to connect manually -assign prio[ 0] = reg2hw.prio0.q; -assign prio[ 1] = reg2hw.prio1.q; -assign prio[ 2] = reg2hw.prio2.q; -assign prio[ 3] = reg2hw.prio3.q; -assign prio[ 4] = reg2hw.prio4.q; -assign prio[ 5] = reg2hw.prio5.q; -assign prio[ 6] = reg2hw.prio6.q; -assign prio[ 7] = reg2hw.prio7.q; -assign prio[ 8] = reg2hw.prio8.q; -assign prio[ 9] = reg2hw.prio9.q; -assign prio[10] = reg2hw.prio10.q; -assign prio[11] = reg2hw.prio11.q; -assign prio[12] = reg2hw.prio12.q; -assign prio[13] = reg2hw.prio13.q; -assign prio[14] = reg2hw.prio14.q; -assign prio[15] = reg2hw.prio15.q; -assign prio[16] = reg2hw.prio16.q; -assign prio[17] = reg2hw.prio17.q; -assign prio[18] = reg2hw.prio18.q; -assign prio[19] = reg2hw.prio19.q; -assign prio[20] = reg2hw.prio20.q; -assign prio[21] = reg2hw.prio21.q; -assign prio[22] = reg2hw.prio22.q; -assign prio[23] = reg2hw.prio23.q; -assign prio[24] = reg2hw.prio24.q; -assign prio[25] = reg2hw.prio25.q; -assign prio[26] = reg2hw.prio26.q; -assign prio[27] = reg2hw.prio27.q; -assign prio[28] = reg2hw.prio28.q; -assign prio[29] = reg2hw.prio29.q; -assign prio[30] = reg2hw.prio30.q; -assign prio[31] = reg2hw.prio31.q; -//------------------------------------------------------------------------------ - -//////////////////////////////////////////////////////////////////////////////// -// Interrupt Enable : Need to connect manually -assign ie[0][ 0] = reg2hw.ie0.e0.q; -assign ie[0][ 1] = reg2hw.ie0.e1.q; -assign ie[0][ 2] = reg2hw.ie0.e2.q; -assign ie[0][ 3] = reg2hw.ie0.e3.q; -assign ie[0][ 4] = reg2hw.ie0.e4.q; -assign ie[0][ 5] = reg2hw.ie0.e5.q; -assign ie[0][ 6] = reg2hw.ie0.e6.q; -assign ie[0][ 7] = reg2hw.ie0.e7.q; -assign ie[0][ 8] = reg2hw.ie0.e8.q; -assign ie[0][ 9] = reg2hw.ie0.e9.q; -assign ie[0][10] = reg2hw.ie0.e10.q; -assign ie[0][11] = reg2hw.ie0.e11.q; -assign ie[0][12] = reg2hw.ie0.e12.q; -assign ie[0][13] = reg2hw.ie0.e13.q; -assign ie[0][14] = reg2hw.ie0.e14.q; -assign ie[0][15] = reg2hw.ie0.e15.q; -assign ie[0][16] = reg2hw.ie0.e16.q; -assign ie[0][17] = reg2hw.ie0.e17.q; -assign ie[0][18] = reg2hw.ie0.e18.q; -assign ie[0][19] = reg2hw.ie0.e19.q; -assign ie[0][20] = reg2hw.ie0.e20.q; -assign ie[0][21] = reg2hw.ie0.e21.q; -assign ie[0][22] = reg2hw.ie0.e22.q; -assign ie[0][23] = reg2hw.ie0.e23.q; -assign ie[0][24] = reg2hw.ie0.e24.q; -assign ie[0][25] = reg2hw.ie0.e25.q; -assign ie[0][26] = reg2hw.ie0.e26.q; -assign ie[0][27] = reg2hw.ie0.e27.q; -assign ie[0][28] = reg2hw.ie0.e28.q; -assign ie[0][29] = reg2hw.ie0.e29.q; -assign ie[0][30] = reg2hw.ie0.e30.q; -assign ie[0][31] = reg2hw.ie0.e31.q; -//------------------------------------------------------------------------------ - -//////////////////////////////////////////////////////////////////////////////// -// THRESHOLD : Need to connect manually -assign threshold[0] = reg2hw.threshold0.q; -//------------------------------------------------------------------------------ - -//////////////////////////////////////////////////////////////////////////////// -// CC : Need to connect manually -assign claim_re[0] = reg2hw.cc0.re; -assign claim_id[0] = irq_id_o[0]; -assign complete_we[0] = reg2hw.cc0.qe; -assign complete_id[0] = reg2hw.cc0.q; - -assign hw2reg.cc0.d = cc_id[0]; -//------------------------------------------------------------------------------ - -//////////////////////////////////////////////////////////////////////////////// -// IP : Need to connect manually -assign hw2reg.ip.p0.de = 1'b1; // Always write -assign hw2reg.ip.p1.de = 1'b1; // Always write -assign hw2reg.ip.p2.de = 1'b1; // Always write -assign hw2reg.ip.p3.de = 1'b1; // Always write -assign hw2reg.ip.p4.de = 1'b1; // Always write -assign hw2reg.ip.p5.de = 1'b1; // Always write -assign hw2reg.ip.p6.de = 1'b1; // Always write -assign hw2reg.ip.p7.de = 1'b1; // Always write -assign hw2reg.ip.p8.de = 1'b1; // Always write -assign hw2reg.ip.p9.de = 1'b1; // Always write -assign hw2reg.ip.p10.de = 1'b1; // Always write -assign hw2reg.ip.p11.de = 1'b1; // Always write -assign hw2reg.ip.p12.de = 1'b1; // Always write -assign hw2reg.ip.p13.de = 1'b1; // Always write -assign hw2reg.ip.p14.de = 1'b1; // Always write -assign hw2reg.ip.p15.de = 1'b1; // Always write -assign hw2reg.ip.p16.de = 1'b1; // Always write -assign hw2reg.ip.p17.de = 1'b1; // Always write -assign hw2reg.ip.p18.de = 1'b1; // Always write -assign hw2reg.ip.p19.de = 1'b1; // Always write -assign hw2reg.ip.p20.de = 1'b1; // Always write -assign hw2reg.ip.p21.de = 1'b1; // Always write -assign hw2reg.ip.p22.de = 1'b1; // Always write -assign hw2reg.ip.p23.de = 1'b1; // Always write -assign hw2reg.ip.p24.de = 1'b1; // Always write -assign hw2reg.ip.p25.de = 1'b1; // Always write -assign hw2reg.ip.p26.de = 1'b1; // Always write -assign hw2reg.ip.p27.de = 1'b1; // Always write -assign hw2reg.ip.p28.de = 1'b1; // Always write -assign hw2reg.ip.p29.de = 1'b1; // Always write -assign hw2reg.ip.p30.de = 1'b1; // Always write -assign hw2reg.ip.p31.de = 1'b1; // Always write -assign hw2reg.ip.p0.d = ip[0]; -assign hw2reg.ip.p1.d = ip[1]; -assign hw2reg.ip.p2.d = ip[2]; -assign hw2reg.ip.p3.d = ip[3]; -assign hw2reg.ip.p4.d = ip[4]; -assign hw2reg.ip.p5.d = ip[5]; -assign hw2reg.ip.p6.d = ip[6]; -assign hw2reg.ip.p7.d = ip[7]; -assign hw2reg.ip.p8.d = ip[8]; -assign hw2reg.ip.p9.d = ip[9]; -assign hw2reg.ip.p10.d = ip[10]; -assign hw2reg.ip.p11.d = ip[11]; -assign hw2reg.ip.p12.d = ip[12]; -assign hw2reg.ip.p13.d = ip[13]; -assign hw2reg.ip.p14.d = ip[14]; -assign hw2reg.ip.p15.d = ip[15]; -assign hw2reg.ip.p16.d = ip[16]; -assign hw2reg.ip.p17.d = ip[17]; -assign hw2reg.ip.p18.d = ip[18]; -assign hw2reg.ip.p19.d = ip[19]; -assign hw2reg.ip.p20.d = ip[20]; -assign hw2reg.ip.p21.d = ip[21]; -assign hw2reg.ip.p22.d = ip[22]; -assign hw2reg.ip.p23.d = ip[23]; -assign hw2reg.ip.p24.d = ip[24]; -assign hw2reg.ip.p25.d = ip[25]; -assign hw2reg.ip.p26.d = ip[26]; -assign hw2reg.ip.p27.d = ip[27]; -assign hw2reg.ip.p28.d = ip[28]; -assign hw2reg.ip.p29.d = ip[29]; -assign hw2reg.ip.p30.d = ip[30]; -assign hw2reg.ip.p31.d = ip[31]; -//------------------------------------------------------------------------------ - -//////////////////////////////////////////////////////////////////////////////// -// LE : Need to connect manually -assign le[0] = reg2hw.le.le0.q; -assign le[1] = reg2hw.le.le1.q; -assign le[2] = reg2hw.le.le2.q; -assign le[3] = reg2hw.le.le3.q; -assign le[4] = reg2hw.le.le4.q; -assign le[5] = reg2hw.le.le5.q; -assign le[6] = reg2hw.le.le6.q; -assign le[7] = reg2hw.le.le7.q; -assign le[8] = reg2hw.le.le8.q; -assign le[9] = reg2hw.le.le9.q; -assign le[10] = reg2hw.le.le10.q; -assign le[11] = reg2hw.le.le11.q; -assign le[12] = reg2hw.le.le12.q; -assign le[13] = reg2hw.le.le13.q; -assign le[14] = reg2hw.le.le14.q; -assign le[15] = reg2hw.le.le15.q; -assign le[16] = reg2hw.le.le16.q; -assign le[17] = reg2hw.le.le17.q; -assign le[18] = reg2hw.le.le18.q; -assign le[19] = reg2hw.le.le19.q; -assign le[20] = reg2hw.le.le20.q; -assign le[21] = reg2hw.le.le21.q; -assign le[22] = reg2hw.le.le22.q; -assign le[23] = reg2hw.le.le23.q; -assign le[24] = reg2hw.le.le24.q; -assign le[25] = reg2hw.le.le25.q; -assign le[26] = reg2hw.le.le26.q; -assign le[27] = reg2hw.le.le27.q; -assign le[28] = reg2hw.le.le28.q; -assign le[29] = reg2hw.le.le29.q; -assign le[30] = reg2hw.le.le30.q; -assign le[31] = reg2hw.le.le31.q; -//------------------------------------------------------------------------------ - -// Gateways -rv_plic_gateway #( - .N_SOURCE (N_SOURCE) -) u_gateway ( - .clk_i, - .rst_ni, - - .src (intr_src_i), - .le, - - .claim, - .complete, - - .ip -); - -// Target interrupt notification -for (genvar i = 0 ; i < N_TARGET ; i++) begin : gen_target - rv_plic_target #( - .N_SOURCE (N_SOURCE), - .MAX_PRIO (MAX_PRIO), - .ALGORITHM(FIND_MAX) - ) u_target ( + //`ASSERT_PULSE(claimPulse, claim_re[i], clk_i, !rst_ni) + //`ASSERT_PULSE(completePulse, complete_we[i], clk_i, !rst_ni) + + `ASSERT(onehot0Claim, $onehot0(claim_re), clk_i, !rst_ni) + + `ASSERT(onehot0Complete, $onehot0(complete_we), clk_i, !rst_ni) + + ////////////////////////////////////////////////////////////////////////////// + // Priority + assign prio[0] = reg2hw.prio0.q; + assign prio[1] = reg2hw.prio1.q; + assign prio[2] = reg2hw.prio2.q; + assign prio[3] = reg2hw.prio3.q; + assign prio[4] = reg2hw.prio4.q; + assign prio[5] = reg2hw.prio5.q; + assign prio[6] = reg2hw.prio6.q; + assign prio[7] = reg2hw.prio7.q; + assign prio[8] = reg2hw.prio8.q; + assign prio[9] = reg2hw.prio9.q; + assign prio[10] = reg2hw.prio10.q; + assign prio[11] = reg2hw.prio11.q; + assign prio[12] = reg2hw.prio12.q; + assign prio[13] = reg2hw.prio13.q; + assign prio[14] = reg2hw.prio14.q; + assign prio[15] = reg2hw.prio15.q; + assign prio[16] = reg2hw.prio16.q; + assign prio[17] = reg2hw.prio17.q; + assign prio[18] = reg2hw.prio18.q; + assign prio[19] = reg2hw.prio19.q; + assign prio[20] = reg2hw.prio20.q; + assign prio[21] = reg2hw.prio21.q; + assign prio[22] = reg2hw.prio22.q; + assign prio[23] = reg2hw.prio23.q; + assign prio[24] = reg2hw.prio24.q; + assign prio[25] = reg2hw.prio25.q; + assign prio[26] = reg2hw.prio26.q; + assign prio[27] = reg2hw.prio27.q; + assign prio[28] = reg2hw.prio28.q; + assign prio[29] = reg2hw.prio29.q; + assign prio[30] = reg2hw.prio30.q; + assign prio[31] = reg2hw.prio31.q; + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // Interrupt Enable + assign ie[0][0] = reg2hw.ie0.e0.q; + assign ie[0][1] = reg2hw.ie0.e1.q; + assign ie[0][2] = reg2hw.ie0.e2.q; + assign ie[0][3] = reg2hw.ie0.e3.q; + assign ie[0][4] = reg2hw.ie0.e4.q; + assign ie[0][5] = reg2hw.ie0.e5.q; + assign ie[0][6] = reg2hw.ie0.e6.q; + assign ie[0][7] = reg2hw.ie0.e7.q; + assign ie[0][8] = reg2hw.ie0.e8.q; + assign ie[0][9] = reg2hw.ie0.e9.q; + assign ie[0][10] = reg2hw.ie0.e10.q; + assign ie[0][11] = reg2hw.ie0.e11.q; + assign ie[0][12] = reg2hw.ie0.e12.q; + assign ie[0][13] = reg2hw.ie0.e13.q; + assign ie[0][14] = reg2hw.ie0.e14.q; + assign ie[0][15] = reg2hw.ie0.e15.q; + assign ie[0][16] = reg2hw.ie0.e16.q; + assign ie[0][17] = reg2hw.ie0.e17.q; + assign ie[0][18] = reg2hw.ie0.e18.q; + assign ie[0][19] = reg2hw.ie0.e19.q; + assign ie[0][20] = reg2hw.ie0.e20.q; + assign ie[0][21] = reg2hw.ie0.e21.q; + assign ie[0][22] = reg2hw.ie0.e22.q; + assign ie[0][23] = reg2hw.ie0.e23.q; + assign ie[0][24] = reg2hw.ie0.e24.q; + assign ie[0][25] = reg2hw.ie0.e25.q; + assign ie[0][26] = reg2hw.ie0.e26.q; + assign ie[0][27] = reg2hw.ie0.e27.q; + assign ie[0][28] = reg2hw.ie0.e28.q; + assign ie[0][29] = reg2hw.ie0.e29.q; + assign ie[0][30] = reg2hw.ie0.e30.q; + assign ie[0][31] = reg2hw.ie0.e31.q; + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // THRESHOLD register + assign threshold[0] = reg2hw.threshold0.q; + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // CC register + assign claim_re[0] = reg2hw.cc0.re; + assign claim_id[0] = irq_id_o[0]; + assign complete_we[0] = reg2hw.cc0.qe; + assign complete_id[0] = reg2hw.cc0.q; + assign hw2reg.cc0.d = cc_id[0]; + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // IP + assign hw2reg.ip.p0.de = 1'b1; // Always write + assign hw2reg.ip.p1.de = 1'b1; // Always write + assign hw2reg.ip.p2.de = 1'b1; // Always write + assign hw2reg.ip.p3.de = 1'b1; // Always write + assign hw2reg.ip.p4.de = 1'b1; // Always write + assign hw2reg.ip.p5.de = 1'b1; // Always write + assign hw2reg.ip.p6.de = 1'b1; // Always write + assign hw2reg.ip.p7.de = 1'b1; // Always write + assign hw2reg.ip.p8.de = 1'b1; // Always write + assign hw2reg.ip.p9.de = 1'b1; // Always write + assign hw2reg.ip.p10.de = 1'b1; // Always write + assign hw2reg.ip.p11.de = 1'b1; // Always write + assign hw2reg.ip.p12.de = 1'b1; // Always write + assign hw2reg.ip.p13.de = 1'b1; // Always write + assign hw2reg.ip.p14.de = 1'b1; // Always write + assign hw2reg.ip.p15.de = 1'b1; // Always write + assign hw2reg.ip.p16.de = 1'b1; // Always write + assign hw2reg.ip.p17.de = 1'b1; // Always write + assign hw2reg.ip.p18.de = 1'b1; // Always write + assign hw2reg.ip.p19.de = 1'b1; // Always write + assign hw2reg.ip.p20.de = 1'b1; // Always write + assign hw2reg.ip.p21.de = 1'b1; // Always write + assign hw2reg.ip.p22.de = 1'b1; // Always write + assign hw2reg.ip.p23.de = 1'b1; // Always write + assign hw2reg.ip.p24.de = 1'b1; // Always write + assign hw2reg.ip.p25.de = 1'b1; // Always write + assign hw2reg.ip.p26.de = 1'b1; // Always write + assign hw2reg.ip.p27.de = 1'b1; // Always write + assign hw2reg.ip.p28.de = 1'b1; // Always write + assign hw2reg.ip.p29.de = 1'b1; // Always write + assign hw2reg.ip.p30.de = 1'b1; // Always write + assign hw2reg.ip.p31.de = 1'b1; // Always write + assign hw2reg.ip.p0.d = ip[0]; + assign hw2reg.ip.p1.d = ip[1]; + assign hw2reg.ip.p2.d = ip[2]; + assign hw2reg.ip.p3.d = ip[3]; + assign hw2reg.ip.p4.d = ip[4]; + assign hw2reg.ip.p5.d = ip[5]; + assign hw2reg.ip.p6.d = ip[6]; + assign hw2reg.ip.p7.d = ip[7]; + assign hw2reg.ip.p8.d = ip[8]; + assign hw2reg.ip.p9.d = ip[9]; + assign hw2reg.ip.p10.d = ip[10]; + assign hw2reg.ip.p11.d = ip[11]; + assign hw2reg.ip.p12.d = ip[12]; + assign hw2reg.ip.p13.d = ip[13]; + assign hw2reg.ip.p14.d = ip[14]; + assign hw2reg.ip.p15.d = ip[15]; + assign hw2reg.ip.p16.d = ip[16]; + assign hw2reg.ip.p17.d = ip[17]; + assign hw2reg.ip.p18.d = ip[18]; + assign hw2reg.ip.p19.d = ip[19]; + assign hw2reg.ip.p20.d = ip[20]; + assign hw2reg.ip.p21.d = ip[21]; + assign hw2reg.ip.p22.d = ip[22]; + assign hw2reg.ip.p23.d = ip[23]; + assign hw2reg.ip.p24.d = ip[24]; + assign hw2reg.ip.p25.d = ip[25]; + assign hw2reg.ip.p26.d = ip[26]; + assign hw2reg.ip.p27.d = ip[27]; + assign hw2reg.ip.p28.d = ip[28]; + assign hw2reg.ip.p29.d = ip[29]; + assign hw2reg.ip.p30.d = ip[30]; + assign hw2reg.ip.p31.d = ip[31]; + //---------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////////// + // Detection:: 0: Level, 1: Edge + assign le[0] = reg2hw.le.le0.q; + assign le[1] = reg2hw.le.le1.q; + assign le[2] = reg2hw.le.le2.q; + assign le[3] = reg2hw.le.le3.q; + assign le[4] = reg2hw.le.le4.q; + assign le[5] = reg2hw.le.le5.q; + assign le[6] = reg2hw.le.le6.q; + assign le[7] = reg2hw.le.le7.q; + assign le[8] = reg2hw.le.le8.q; + assign le[9] = reg2hw.le.le9.q; + assign le[10] = reg2hw.le.le10.q; + assign le[11] = reg2hw.le.le11.q; + assign le[12] = reg2hw.le.le12.q; + assign le[13] = reg2hw.le.le13.q; + assign le[14] = reg2hw.le.le14.q; + assign le[15] = reg2hw.le.le15.q; + assign le[16] = reg2hw.le.le16.q; + assign le[17] = reg2hw.le.le17.q; + assign le[18] = reg2hw.le.le18.q; + assign le[19] = reg2hw.le.le19.q; + assign le[20] = reg2hw.le.le20.q; + assign le[21] = reg2hw.le.le21.q; + assign le[22] = reg2hw.le.le22.q; + assign le[23] = reg2hw.le.le23.q; + assign le[24] = reg2hw.le.le24.q; + assign le[25] = reg2hw.le.le25.q; + assign le[26] = reg2hw.le.le26.q; + assign le[27] = reg2hw.le.le27.q; + assign le[28] = reg2hw.le.le28.q; + assign le[29] = reg2hw.le.le29.q; + assign le[30] = reg2hw.le.le30.q; + assign le[31] = reg2hw.le.le31.q; + //---------------------------------------------------------------------------- + + // Gateways + rv_plic_gateway #( + .N_SOURCE (N_SOURCE) + ) u_gateway ( .clk_i, .rst_ni, - .ip, - .ie (ie[i]), + .src (intr_src_i), + .le, - .prio, - .threshold (threshold[i]), - - .irq (irq_o[i]), - .irq_id (irq_id_o[i]) + .claim, + .complete, + .ip ); -end -// Register interface -// Limitation of register tool prevents the module from having flexibility to parameters -// So, signals are manually tied at the top. -rv_plic_reg_top u_reg ( - .clk_i, - .rst_ni, - .tl_i, - .tl_o, + // Target interrupt notification + for (genvar i = 0 ; i < N_TARGET ; i++) begin : gen_target + rv_plic_target #( + .N_SOURCE (N_SOURCE), + .MAX_PRIO (MAX_PRIO), + .ALGORITHM(FIND_MAX) + ) u_target ( + .clk_i, + .rst_ni, - .reg2hw, - .hw2reg -); + .ip, + .ie (ie[i]), + + .prio, + .threshold (threshold[i]), + + .irq (irq_o[i]), + .irq_id (irq_id_o[i]) + + ); + end + + // Register interface + // Limitation of register tool prevents the module from having flexibility to parameters + // So, signals are manually tied at the top. + rv_plic_reg_top u_reg ( + .clk_i, + .rst_ni, + + .tl_i, + .tl_o, + + .reg2hw, + .hw2reg + ); endmodule