diff --git a/plic_regmap.sv b/plic_regmap.sv new file mode 100644 index 0000000..fe20222 --- /dev/null +++ b/plic_regmap.sv @@ -0,0 +1,353 @@ +// Do not edit - auto-generated +module plic_regs ( + input logic [30:0][2:0] prio_i, + output logic [30:0][2:0] prio_o, + output logic [30:0] prio_we_o, + output logic [30:0] prio_re_o, + input logic [0:0][30:0] ip_i, + output logic [0:0] ip_re_o, + input logic [1:0][30:0] ie_i, + output logic [1:0][30:0] ie_o, + output logic [1:0] ie_we_o, + output logic [1:0] ie_re_o, + input logic [1:0][2:0] threshold_i, + output logic [1:0][2:0] threshold_o, + output logic [1:0] threshold_we_o, + output logic [1:0] threshold_re_o, + input logic [1:0][4:0] cc_i, + output logic [1:0][4:0] cc_o, + output logic [1:0] cc_we_o, + output logic [1:0] cc_re_o, + // Bus Interface + input reg_intf::reg_intf_req_a32_d32 req_i, + output reg_intf::reg_intf_resp_d32 resp_o +); +always_comb begin + resp_o.ready = 1'b1; + resp_o.rdata = '0; + resp_o.error = '0; + prio_o = '0; + prio_we_o = '0; + prio_re_o = '0; + ie_o = '0; + ie_we_o = '0; + ie_re_o = '0; + threshold_o = '0; + threshold_we_o = '0; + threshold_re_o = '0; + cc_o = '0; + cc_we_o = '0; + cc_re_o = '0; + if (req_i.valid) begin + if (req_i.write) begin + unique case(req_i.addr) + 32'hc000000: begin + prio_o[0][2:0] = req_i.wdata[2:0]; + prio_we_o[0] = 1'b1; + end + 32'hc000004: begin + prio_o[1][2:0] = req_i.wdata[2:0]; + prio_we_o[1] = 1'b1; + end + 32'hc000008: begin + prio_o[2][2:0] = req_i.wdata[2:0]; + prio_we_o[2] = 1'b1; + end + 32'hc00000c: begin + prio_o[3][2:0] = req_i.wdata[2:0]; + prio_we_o[3] = 1'b1; + end + 32'hc000010: begin + prio_o[4][2:0] = req_i.wdata[2:0]; + prio_we_o[4] = 1'b1; + end + 32'hc000014: begin + prio_o[5][2:0] = req_i.wdata[2:0]; + prio_we_o[5] = 1'b1; + end + 32'hc000018: begin + prio_o[6][2:0] = req_i.wdata[2:0]; + prio_we_o[6] = 1'b1; + end + 32'hc00001c: begin + prio_o[7][2:0] = req_i.wdata[2:0]; + prio_we_o[7] = 1'b1; + end + 32'hc000020: begin + prio_o[8][2:0] = req_i.wdata[2:0]; + prio_we_o[8] = 1'b1; + end + 32'hc000024: begin + prio_o[9][2:0] = req_i.wdata[2:0]; + prio_we_o[9] = 1'b1; + end + 32'hc000028: begin + prio_o[10][2:0] = req_i.wdata[2:0]; + prio_we_o[10] = 1'b1; + end + 32'hc00002c: begin + prio_o[11][2:0] = req_i.wdata[2:0]; + prio_we_o[11] = 1'b1; + end + 32'hc000030: begin + prio_o[12][2:0] = req_i.wdata[2:0]; + prio_we_o[12] = 1'b1; + end + 32'hc000034: begin + prio_o[13][2:0] = req_i.wdata[2:0]; + prio_we_o[13] = 1'b1; + end + 32'hc000038: begin + prio_o[14][2:0] = req_i.wdata[2:0]; + prio_we_o[14] = 1'b1; + end + 32'hc00003c: begin + prio_o[15][2:0] = req_i.wdata[2:0]; + prio_we_o[15] = 1'b1; + end + 32'hc000040: begin + prio_o[16][2:0] = req_i.wdata[2:0]; + prio_we_o[16] = 1'b1; + end + 32'hc000044: begin + prio_o[17][2:0] = req_i.wdata[2:0]; + prio_we_o[17] = 1'b1; + end + 32'hc000048: begin + prio_o[18][2:0] = req_i.wdata[2:0]; + prio_we_o[18] = 1'b1; + end + 32'hc00004c: begin + prio_o[19][2:0] = req_i.wdata[2:0]; + prio_we_o[19] = 1'b1; + end + 32'hc000050: begin + prio_o[20][2:0] = req_i.wdata[2:0]; + prio_we_o[20] = 1'b1; + end + 32'hc000054: begin + prio_o[21][2:0] = req_i.wdata[2:0]; + prio_we_o[21] = 1'b1; + end + 32'hc000058: begin + prio_o[22][2:0] = req_i.wdata[2:0]; + prio_we_o[22] = 1'b1; + end + 32'hc00005c: begin + prio_o[23][2:0] = req_i.wdata[2:0]; + prio_we_o[23] = 1'b1; + end + 32'hc000060: begin + prio_o[24][2:0] = req_i.wdata[2:0]; + prio_we_o[24] = 1'b1; + end + 32'hc000064: begin + prio_o[25][2:0] = req_i.wdata[2:0]; + prio_we_o[25] = 1'b1; + end + 32'hc000068: begin + prio_o[26][2:0] = req_i.wdata[2:0]; + prio_we_o[26] = 1'b1; + end + 32'hc00006c: begin + prio_o[27][2:0] = req_i.wdata[2:0]; + prio_we_o[27] = 1'b1; + end + 32'hc000070: begin + prio_o[28][2:0] = req_i.wdata[2:0]; + prio_we_o[28] = 1'b1; + end + 32'hc000074: begin + prio_o[29][2:0] = req_i.wdata[2:0]; + prio_we_o[29] = 1'b1; + end + 32'hc000078: begin + prio_o[30][2:0] = req_i.wdata[2:0]; + prio_we_o[30] = 1'b1; + end + 32'hc002000: begin + ie_o[0][30:0] = req_i.wdata[30:0]; + ie_we_o[0] = 1'b1; + end + 32'hc002080: begin + ie_o[1][30:0] = req_i.wdata[30:0]; + ie_we_o[1] = 1'b1; + end + 32'hc200000: begin + threshold_o[0][2:0] = req_i.wdata[2:0]; + threshold_we_o[0] = 1'b1; + end + 32'hc201000: begin + threshold_o[1][2:0] = req_i.wdata[2:0]; + threshold_we_o[1] = 1'b1; + end + 32'hc200004: begin + cc_o[0][4:0] = req_i.wdata[4:0]; + cc_we_o[0] = 1'b1; + end + 32'hc201004: begin + cc_o[1][4:0] = req_i.wdata[4:0]; + cc_we_o[1] = 1'b1; + end + default: resp_o.error = 1'b1; + endcase + end else begin + unique case(req_i.addr) + 32'hc000000: begin + resp_o.rdata[2:0] = prio_i[0][2:0]; + prio_re_o[0] = 1'b1; + end + 32'hc000004: begin + resp_o.rdata[2:0] = prio_i[1][2:0]; + prio_re_o[1] = 1'b1; + end + 32'hc000008: begin + resp_o.rdata[2:0] = prio_i[2][2:0]; + prio_re_o[2] = 1'b1; + end + 32'hc00000c: begin + resp_o.rdata[2:0] = prio_i[3][2:0]; + prio_re_o[3] = 1'b1; + end + 32'hc000010: begin + resp_o.rdata[2:0] = prio_i[4][2:0]; + prio_re_o[4] = 1'b1; + end + 32'hc000014: begin + resp_o.rdata[2:0] = prio_i[5][2:0]; + prio_re_o[5] = 1'b1; + end + 32'hc000018: begin + resp_o.rdata[2:0] = prio_i[6][2:0]; + prio_re_o[6] = 1'b1; + end + 32'hc00001c: begin + resp_o.rdata[2:0] = prio_i[7][2:0]; + prio_re_o[7] = 1'b1; + end + 32'hc000020: begin + resp_o.rdata[2:0] = prio_i[8][2:0]; + prio_re_o[8] = 1'b1; + end + 32'hc000024: begin + resp_o.rdata[2:0] = prio_i[9][2:0]; + prio_re_o[9] = 1'b1; + end + 32'hc000028: begin + resp_o.rdata[2:0] = prio_i[10][2:0]; + prio_re_o[10] = 1'b1; + end + 32'hc00002c: begin + resp_o.rdata[2:0] = prio_i[11][2:0]; + prio_re_o[11] = 1'b1; + end + 32'hc000030: begin + resp_o.rdata[2:0] = prio_i[12][2:0]; + prio_re_o[12] = 1'b1; + end + 32'hc000034: begin + resp_o.rdata[2:0] = prio_i[13][2:0]; + prio_re_o[13] = 1'b1; + end + 32'hc000038: begin + resp_o.rdata[2:0] = prio_i[14][2:0]; + prio_re_o[14] = 1'b1; + end + 32'hc00003c: begin + resp_o.rdata[2:0] = prio_i[15][2:0]; + prio_re_o[15] = 1'b1; + end + 32'hc000040: begin + resp_o.rdata[2:0] = prio_i[16][2:0]; + prio_re_o[16] = 1'b1; + end + 32'hc000044: begin + resp_o.rdata[2:0] = prio_i[17][2:0]; + prio_re_o[17] = 1'b1; + end + 32'hc000048: begin + resp_o.rdata[2:0] = prio_i[18][2:0]; + prio_re_o[18] = 1'b1; + end + 32'hc00004c: begin + resp_o.rdata[2:0] = prio_i[19][2:0]; + prio_re_o[19] = 1'b1; + end + 32'hc000050: begin + resp_o.rdata[2:0] = prio_i[20][2:0]; + prio_re_o[20] = 1'b1; + end + 32'hc000054: begin + resp_o.rdata[2:0] = prio_i[21][2:0]; + prio_re_o[21] = 1'b1; + end + 32'hc000058: begin + resp_o.rdata[2:0] = prio_i[22][2:0]; + prio_re_o[22] = 1'b1; + end + 32'hc00005c: begin + resp_o.rdata[2:0] = prio_i[23][2:0]; + prio_re_o[23] = 1'b1; + end + 32'hc000060: begin + resp_o.rdata[2:0] = prio_i[24][2:0]; + prio_re_o[24] = 1'b1; + end + 32'hc000064: begin + resp_o.rdata[2:0] = prio_i[25][2:0]; + prio_re_o[25] = 1'b1; + end + 32'hc000068: begin + resp_o.rdata[2:0] = prio_i[26][2:0]; + prio_re_o[26] = 1'b1; + end + 32'hc00006c: begin + resp_o.rdata[2:0] = prio_i[27][2:0]; + prio_re_o[27] = 1'b1; + end + 32'hc000070: begin + resp_o.rdata[2:0] = prio_i[28][2:0]; + prio_re_o[28] = 1'b1; + end + 32'hc000074: begin + resp_o.rdata[2:0] = prio_i[29][2:0]; + prio_re_o[29] = 1'b1; + end + 32'hc000078: begin + resp_o.rdata[2:0] = prio_i[30][2:0]; + prio_re_o[30] = 1'b1; + end + 32'hc001000: begin + resp_o.rdata[30:0] = ip_i[0][30:0]; + ip_re_o[0] = 1'b1; + end + 32'hc002000: begin + resp_o.rdata[30:0] = ie_i[0][30:0]; + ie_re_o[0] = 1'b1; + end + 32'hc002080: begin + resp_o.rdata[30:0] = ie_i[1][30:0]; + ie_re_o[1] = 1'b1; + end + 32'hc200000: begin + resp_o.rdata[2:0] = threshold_i[0][2:0]; + threshold_re_o[0] = 1'b1; + end + 32'hc201000: begin + resp_o.rdata[2:0] = threshold_i[1][2:0]; + threshold_re_o[1] = 1'b1; + end + 32'hc200004: begin + resp_o.rdata[4:0] = cc_i[0][4:0]; + cc_re_o[0] = 1'b1; + end + 32'hc201004: begin + resp_o.rdata[4:0] = cc_i[1][4:0]; + cc_re_o[1] = 1'b1; + end + default: resp_o.error = 1'b1; + endcase + end + end +end +endmodule diff --git a/plic_top.sv b/plic_top.sv new file mode 100644 index 0000000..aaf13b4 --- /dev/null +++ b/plic_top.sv @@ -0,0 +1,166 @@ +module plic_top #( + parameter int N_SOURCE = 30, + parameter int N_TARGET = 2, + parameter int MAX_PRIO = 7, + parameter int SRCW = $clog2(N_SOURCE+1) +) ( + input logic clk_i, // Clock + input logic rst_ni, // Asynchronous reset active low + // Bus Interface + input reg_intf::reg_intf_req_a32_d32 req_i, + output reg_intf::reg_intf_resp_d32 resp_o, + input logic [N_SOURCE-1:0] le_i, // 0:level 1:edge + // Interrupt Sources + input logic [N_SOURCE-1:0] irq_sources_i, + // Interrupt notification to targets + output logic [N_TARGET-1:0] eip_targets_o +); + localparam PRIOW = $clog2(MAX_PRIO+1); + + logic [N_SOURCE-1:0] ip; + + logic [N_TARGET-1:0][PRIOW-1:0] threshold_q; + + logic [N_TARGET-1:0] claim_re; //Target read indicator + logic [N_TARGET-1:0][SRCW-1:0] claim_id; + logic [N_SOURCE-1:0] claim; //Converted from claim_re/claim_id + + logic [N_TARGET-1:0] complete_we; //Target write indicator + logic [N_TARGET-1:0][SRCW-1:0] complete_id; + logic [N_SOURCE-1:0] complete; //Converted from complete_re/complete_id + + logic [N_SOURCE-1:0][PRIOW-1:0] prio_q; + logic [N_TARGET-1:0][N_SOURCE-1:0] ie_q; + + always_comb begin + claim = '0; + complete = '0; + for (int i = 0 ; i < N_TARGET ; i++) begin + if (claim_re[i] && claim_id[i] != 0) claim[claim_id[i]-1] = 1'b1; + if (complete_we[i] && complete_id[i] != 0) complete[complete_id[i]-1] = 1'b1; + end + end + + // Gateways + rv_plic_gateway #( + .N_SOURCE (N_SOURCE) + ) i_rv_plic_gateway ( + .clk_i, + .rst_ni, + .src(irq_sources_i), + .le(le_i), + .claim(claim), + .complete(complete), + .ip(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 ( "SEQUENTIAL" ) + ) i_target ( + .clk_i, + .rst_ni, + .ip(ip), + .ie(ie_q[i]), + .prio(prio_q), + .threshold(threshold_q[i]), + .irq(eip_targets_o[i]), + .irq_id(claim_id[i]) + ); + end + + logic [N_TARGET-1:0] threshold_we_o; + logic [N_TARGET-1:0][PRIOW-1:0] threshold_o; + + logic [N_SOURCE:0][PRIOW-1:0] prio_i, prio_o; + logic [N_SOURCE:0] prio_we_o; + + // TODO(zarubaf): This needs more graceful handling + // it will break if the number of sources is larger than 32 + logic [N_TARGET-1:0][N_SOURCE:0] ie_i, ie_o; + logic [N_TARGET-1:0] ie_we_o; + + plic_regs i_plic_regs ( + .prio_i(prio_i), + .prio_o(prio_o), + .prio_we_o(prio_we_o), + .prio_re_o(), // don't care + // source zero is always zero + .ip_i({ip, 1'b0}), + .ip_re_o(), // don't care + .ie_i(ie_i), + .ie_o(ie_o), + .ie_we_o(ie_we_o), + .ie_re_o(), // don't care + .threshold_i(threshold_q), + .threshold_o(threshold_o), + .threshold_we_o(threshold_we_o), + .threshold_re_o(), // don't care + .cc_i(claim_id), + .cc_o(complete_id), + .cc_we_o(complete_we), + .cc_re_o(claim_re), + .req_i, + .resp_o + ); + +`ifdef XLNX_ILA_PLIC +xlnx_ila_plic plic_ila ( + .clk(clk_i), + .probe0(prio_i), + .probe1(prio_o), + .probe2(prio_we_o), + .probe3(ip), + .probe4(ie_i), + .probe5(ie_o), + .probe6(ie_we_o), + .probe7(threshold_q), + .probe8(threshold_o), + .probe9(threshold_we_o), + .probe10(claim_id), + .probe11(complete_id), + .probe12(complete_we), + .probe13(claim_re), + .probe14(req_i), + .probe15(resp_o), + .probe16(claim), + .probe17(complete), + .probe18(prio_q), + .probe19(ie_q), + .probe20(irq_sources_i), + .probe21(eip_targets_o) +); +`endif + + assign prio_i[0] = '0; + + for (genvar i = 0; i < N_TARGET; i++) begin + assign ie_i[i] = {ie_q[i][N_SOURCE-1:0], 1'b0}; + end + + for (genvar i = 1; i < N_SOURCE + 1; i++) begin + assign prio_i[i] = prio_q[i - 1]; + end + + // registers + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + prio_q <= '0; + ie_q <= '0; + threshold_q <= '0; + end else begin + // source zero is 0 + for (int i = 0; i < N_SOURCE; i++) begin + prio_q[i] <= prio_we_o[i + 1] ? prio_o[i + 1] : prio_q[i]; + end + for (int i = 0; i < N_TARGET; i++) begin + threshold_q[i] <= threshold_we_o[i] ? threshold_o[i] : threshold_q[i]; + ie_q[i] <= ie_we_o[i] ? ie_o[i][N_SOURCE:1] : ie_q[i]; + end + + end + end +endmodule diff --git a/rtl/rv_plic_gateway.sv b/rtl/rv_plic_gateway.sv index c68f78c..0aec3a7 100644 --- a/rtl/rv_plic_gateway.sv +++ b/rtl/rv_plic_gateway.sv @@ -7,14 +7,14 @@ module rv_plic_gateway #( parameter int N_SOURCE = 32 ) ( - input clk_i, - input rst_ni, + input logic clk_i, + input logic rst_ni, - input [N_SOURCE-1:0] src, - input [N_SOURCE-1:0] le, // Level0 Edge1 + input logic [N_SOURCE-1:0] src, + input logic [N_SOURCE-1:0] le, // Level0 Edge1 - input [N_SOURCE-1:0] claim, // $onehot0(claim) - input [N_SOURCE-1:0] complete, // $onehot0(complete) + input logic [N_SOURCE-1:0] claim, // $onehot0(claim) + input logic [N_SOURCE-1:0] complete, // $onehot0(complete) output logic [N_SOURCE-1:0] ip ); diff --git a/rtl/rv_plic_target.sv b/rtl/rv_plic_target.sv index 9526b34..40b6613 100644 --- a/rtl/rv_plic_target.sv +++ b/rtl/rv_plic_target.sv @@ -22,8 +22,8 @@ module rv_plic_target #( input [N_SOURCE-1:0] ip, input [N_SOURCE-1:0] ie, - input [PRIOW-1:0] prio [N_SOURCE], - input [PRIOW-1:0] threshold, + input [N_SOURCE-1:0][PRIOW-1:0] prio, + input [PRIOW-1:0] threshold, output logic irq, output logic [SRCW-1:0] irq_id