mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
rv_plic: Add lowrisc PLIC
Use a PLIC which has been developed as part of the lowrisc project. It has been integrated into the Ariane SoC as a submodule pointing to a fork which has some (temporary) custom patches on top.
This commit is contained in:
parent
095cda6194
commit
5bf0d9256b
15 changed files with 66 additions and 924 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -43,3 +43,6 @@
|
|||
[submodule "src/riscv-dbg"]
|
||||
path = src/riscv-dbg
|
||||
url = https://github.com/pulp-platform/riscv-dbg.git
|
||||
[submodule "src/rv_plic"]
|
||||
path = src/rv_plic
|
||||
url = https://github.com/pulp-platform/rv_plic.git
|
||||
|
|
|
@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- Fix bug in wt_axi_adapter (only appeared when dcache lines were wider than icache lines)
|
||||
- Fix potentially long timing path in `axi_lite_interface`
|
||||
- Fix VCS elab warning in `load_store_unit`
|
||||
- Bump `common_cells` to v1.12.0
|
||||
- Provision exponential backoff for AMO SC in L1 D$ miss handler
|
||||
- Add lowrisc PLIC
|
||||
|
||||
### 4.1.2
|
||||
|
||||
|
|
6
Makefile
6
Makefile
|
@ -58,6 +58,7 @@ ariane_pkg := include/riscv_pkg.sv \
|
|||
include/wt_cache_pkg.sv \
|
||||
src/axi/src/axi_pkg.sv \
|
||||
src/register_interface/src/reg_intf.sv \
|
||||
src/register_interface/src/reg_intf_pkg.sv \
|
||||
include/axi_intf.sv \
|
||||
tb/ariane_soc_pkg.sv \
|
||||
include/ariane_axi_pkg.sv \
|
||||
|
@ -112,10 +113,13 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
|
|||
$(wildcard src/clint/*.sv) \
|
||||
$(wildcard fpga/src/axi2apb/src/*.sv) \
|
||||
$(wildcard fpga/src/axi_slice/src/*.sv) \
|
||||
$(wildcard src/plic/*.sv) \
|
||||
$(wildcard src/axi_node/src/*.sv) \
|
||||
$(wildcard src/axi_riscv_atomics/src/*.sv) \
|
||||
$(wildcard src/axi_mem_if/src/*.sv) \
|
||||
src/rv_plic/rtl/rv_plic_target.sv \
|
||||
src/rv_plic/rtl/rv_plic_gateway.sv \
|
||||
src/rv_plic/rtl/plic_regmap.sv \
|
||||
src/rv_plic/rtl/plic_top.sv \
|
||||
src/riscv-dbg/src/dmi_cdc.sv \
|
||||
src/riscv-dbg/src/dmi_jtag.sv \
|
||||
src/riscv-dbg/src/dmi_jtag_tap.sv \
|
||||
|
|
|
@ -156,17 +156,31 @@ module ariane_peripherals #(
|
|||
.reg_o ( reg_bus )
|
||||
);
|
||||
|
||||
plic #(
|
||||
.ID_BITWIDTH ( ariane_soc::PLICIdWidth ),
|
||||
.PARAMETER_BITWIDTH ( ariane_soc::ParameterBitwidth ),
|
||||
.NUM_TARGETS ( ariane_soc::NumTargets ),
|
||||
.NUM_SOURCES ( ariane_soc::NumSources )
|
||||
reg_intf::reg_intf_resp_d32 plic_resp;
|
||||
reg_intf::reg_intf_req_a32_d32 plic_req;
|
||||
|
||||
assign plic_req.addr = reg_bus.addr;
|
||||
assign plic_req.write = reg_bus.write;
|
||||
assign plic_req.wdata = reg_bus.wdata;
|
||||
assign plic_req.wstrb = reg_bus.wstrb;
|
||||
assign plic_req.valid = reg_bus.valid;
|
||||
|
||||
assign reg_bus.rdata = plic_resp.rdata;
|
||||
assign reg_bus.error = plic_resp.error;
|
||||
assign reg_bus.ready = plic_resp.ready;
|
||||
|
||||
plic_top #(
|
||||
.N_SOURCE ( ariane_soc::NumSources ),
|
||||
.N_TARGET ( ariane_soc::NumTargets ),
|
||||
.MAX_PRIO ( ariane_soc::MaxPriority )
|
||||
) i_plic (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.irq_sources_i ( irq_sources ),
|
||||
.eip_targets_o ( irq_o ),
|
||||
.external_bus_io ( reg_bus )
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.req_i ( plic_req ),
|
||||
.resp_o ( plic_resp ),
|
||||
.le_i ( '0 ), // 0:level 1:edge
|
||||
.irq_sources_i ( irq_sources ),
|
||||
.eip_targets_o ( irq_o )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
|
|
155
src/plic/plic.sv
155
src/plic/plic.sv
|
@ -1,155 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : PLIC Core
|
||||
//-- File : plic_core.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: PLIC Top-level
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
module plic #(
|
||||
parameter int ADDR_WIDTH = 32, // can be either 32 or 64 bits (don't use 64bit at the moment as this causes memory map issues)
|
||||
parameter int DATA_WIDTH = 32, // can be either 32 or 64 bits (don't use 64bit at the moment as this causes memory map issues)
|
||||
parameter int ID_BITWIDTH = -1, // width of the gateway identifiers
|
||||
parameter int PARAMETER_BITWIDTH = -1, // width of the internal parameter e.g. priorities
|
||||
parameter int NUM_TARGETS = -1, // number of target slices
|
||||
parameter int NUM_SOURCES = -1 // number of sources = number of gateways
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic [NUM_SOURCES-1:0] irq_sources_i,
|
||||
output logic [NUM_TARGETS-1:0] eip_targets_o,
|
||||
REG_BUS.in external_bus_io
|
||||
);
|
||||
// declare all local variables
|
||||
// gateway arrays always go from NUM_SOURCES to 1 because gateway ids start at 1
|
||||
logic gateway_irq_pendings [NUM_SOURCES]; //for pending irqs of the gateways
|
||||
logic gateway_claimed [NUM_SOURCES]; //if a gateway is claimed, it masks its irq
|
||||
logic gateway_completed [NUM_SOURCES]; //if a gateway is completed, it is reenabled
|
||||
logic [ID_BITWIDTH-1:0 ] gateway_ids [NUM_SOURCES]; //ids of gateways
|
||||
logic [PARAMETER_BITWIDTH-1:0] gateway_priorities [NUM_SOURCES]; //priorities of gateways
|
||||
|
||||
logic irq_enableds [NUM_SOURCES][NUM_TARGETS];
|
||||
logic [PARAMETER_BITWIDTH-1:0] target_thresholds [NUM_TARGETS];
|
||||
logic [ID_BITWIDTH-1:0 ] identifier_of_largest_priority_per_target [NUM_TARGETS];
|
||||
|
||||
logic target_irq_claims [NUM_TARGETS];
|
||||
logic target_irq_completes [NUM_TARGETS];
|
||||
logic [ID_BITWIDTH-1:0 ] target_irq_completes_id [NUM_TARGETS];
|
||||
|
||||
//instantiate and connect gateways
|
||||
for (genvar counter = 0; counter < NUM_SOURCES; counter++) begin : gen_plic_gateway
|
||||
plic_gateway plic_gateway_instance (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.irq_source_i ( irq_sources_i [counter] ),
|
||||
.claim_i ( gateway_claimed [counter] ),
|
||||
.completed_i ( gateway_completed [counter] ),
|
||||
.irq_pending_o ( gateway_irq_pendings[counter] )
|
||||
);
|
||||
end
|
||||
|
||||
// assign ids to gateways
|
||||
for (genvar counter = 1; counter <= NUM_SOURCES; counter++) begin
|
||||
assign gateway_ids[counter-1] = counter;
|
||||
|
||||
end
|
||||
|
||||
// instantiate and connect target slices
|
||||
for (genvar counter = 0; counter < NUM_TARGETS; counter++) begin : gen_plic_target_slice
|
||||
|
||||
logic irq_enableds_slice[NUM_SOURCES];
|
||||
for (genvar inner_counter = 0; inner_counter < NUM_SOURCES; inner_counter++) begin
|
||||
assign irq_enableds_slice[inner_counter] = irq_enableds[inner_counter][counter];
|
||||
end
|
||||
|
||||
plic_target_slice #(
|
||||
.PRIORITY_BITWIDTH ( PARAMETER_BITWIDTH ),
|
||||
.ID_BITWIDTH ( ID_BITWIDTH ),
|
||||
.NUM_GATEWAYS ( NUM_SOURCES )
|
||||
) plic_target_slice_instance (
|
||||
.interrupt_pending_i ( gateway_irq_pendings ),
|
||||
.interrupt_priority_i ( gateway_priorities ),
|
||||
.interrupt_id_i ( gateway_ids ),
|
||||
.interrupt_enable_i ( irq_enableds_slice ),
|
||||
.threshold_i ( target_thresholds[counter] ),
|
||||
.ext_interrupt_present_o ( eip_targets_o[counter] ),
|
||||
.identifier_of_largest_o ( identifier_of_largest_priority_per_target[counter] )
|
||||
);
|
||||
end
|
||||
|
||||
//instantiate and connect plic_interface
|
||||
plic_interface #(
|
||||
.ADDR_WIDTH ( ADDR_WIDTH ),
|
||||
.DATA_WIDTH ( DATA_WIDTH ),
|
||||
.ID_BITWIDTH ( ID_BITWIDTH ),
|
||||
.PARAMETER_BITWIDTH ( PARAMETER_BITWIDTH ),
|
||||
.NUM_TARGETS ( NUM_TARGETS ),
|
||||
.NUM_GATEWAYS ( NUM_SOURCES )
|
||||
) plic_interface_instance (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.id_of_largest_priority_i ( identifier_of_largest_priority_per_target ),
|
||||
.pending_array_i ( gateway_irq_pendings ),
|
||||
.thresholds_o ( target_thresholds ),
|
||||
.gateway_priorities_o ( gateway_priorities ),
|
||||
.irq_enables_o ( irq_enableds ),
|
||||
.target_irq_claims_o ( target_irq_claims ),
|
||||
.target_irq_completes_o ( target_irq_completes ),
|
||||
.target_irq_completes_id_o ( target_irq_completes_id ),
|
||||
.external_bus_io ( external_bus_io )
|
||||
);
|
||||
|
||||
//instantiate and connect claim_complete_tracker
|
||||
plic_claim_complete_tracker #(
|
||||
.NUM_TARGETS ( NUM_TARGETS ),
|
||||
.NUM_GATEWAYS ( NUM_SOURCES ),
|
||||
.ID_BITWIDTH ( ID_BITWIDTH )
|
||||
) plic_claim_complete_tracker_instance (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.identifier_of_largest_priority_per_target ( identifier_of_largest_priority_per_target ),
|
||||
.target_irq_claims_i ( target_irq_claims ),
|
||||
.target_irq_completes_i ( target_irq_completes ),
|
||||
.target_irq_completes_identifier_i ( target_irq_completes_id ),
|
||||
.gateway_irq_claims_o ( gateway_claimed ),
|
||||
.gateway_irq_completes_o ( gateway_completed )
|
||||
);
|
||||
|
||||
//pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert((ADDR_WIDTH == 32) | (ADDR_WIDTH == 64)) else $error("Address width has to bei either 32 or 64 bit");
|
||||
assert((DATA_WIDTH == 32) | (DATA_WIDTH == 64)) else $error("Data width has to bei either 32 or 64 bit");
|
||||
assert(ID_BITWIDTH > 0 ) else $error("ID_BITWIDTH has to be larger than 1");
|
||||
assert(ID_BITWIDTH < 10 ) else $error("ID_BITWIDTH has to be smaller than 10");
|
||||
assert(PARAMETER_BITWIDTH > 0) else $error("PARAMETER_BITWIDTH has to be larger than 1");
|
||||
assert(PARAMETER_BITWIDTH < 8) else $error("PARAMETER_BITWIDTH has to be smaller than 8");
|
||||
assert(NUM_SOURCES > 0 ) else $error("Num od Gateways has to be larger than 1");
|
||||
assert(NUM_SOURCES < 512 ) else $error("Num of Gateways has to be smaller than 512");
|
||||
assert(NUM_TARGETS > 0 ) else $error("Num Target slices has to be larger than 1");
|
||||
assert(NUM_TARGETS < 15872 ) else $error("Num target slices has to be smaller than 15872");
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
endmodule
|
|
@ -1,125 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : Claim - Complete - Tracker
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- File : plic_claim_complete_tracker.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: Implements the control logic of the plic
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
//FSM that receives interrupt claims and interrupt completes from targets
|
||||
//and generates the fitting inerrupt claims and interrupt completes for sources
|
||||
module plic_claim_complete_tracker #(
|
||||
parameter int NUM_TARGETS = 1,
|
||||
parameter int NUM_GATEWAYS = 1,
|
||||
parameter int ID_BITWIDTH = 4
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
||||
input logic [ID_BITWIDTH-1:0] identifier_of_largest_priority_per_target[NUM_TARGETS],
|
||||
input logic target_irq_claims_i [NUM_TARGETS],
|
||||
input logic target_irq_completes_i[NUM_TARGETS],
|
||||
input logic [ID_BITWIDTH-1:0] target_irq_completes_identifier_i[NUM_TARGETS],
|
||||
|
||||
output logic gateway_irq_claims_o [NUM_GATEWAYS],
|
||||
output logic gateway_irq_completes_o[NUM_GATEWAYS]
|
||||
|
||||
);
|
||||
|
||||
// claimed_gateways_q[target] is 0 if the target has not claimed the irq of any gateway
|
||||
// and the is the identifier of the claimed gateway otherwise
|
||||
logic [ID_BITWIDTH-1:0] claimed_gateways_q[NUM_TARGETS];
|
||||
|
||||
// the +1 is because counting starts from 1 and goes to NUM_GATEWAYS+1
|
||||
logic claim_array [NUM_GATEWAYS+1][NUM_TARGETS];
|
||||
logic save_claims_array_q [NUM_GATEWAYS+1][NUM_TARGETS];
|
||||
logic complete_array [NUM_GATEWAYS+1][NUM_TARGETS];
|
||||
|
||||
// for handling claims
|
||||
for (genvar counter = 0; counter < NUM_TARGETS; counter++) begin
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_target
|
||||
|
||||
if (~rst_ni) begin
|
||||
claimed_gateways_q[counter] <= '0;
|
||||
|
||||
for (integer i = 0; i <= NUM_GATEWAYS; i++) begin
|
||||
claim_array[i][counter] <= '0;
|
||||
save_claims_array_q[i][counter] <= '0;
|
||||
end
|
||||
|
||||
end else begin
|
||||
// per default, all claims and completes are zero
|
||||
for (integer i = 0; i <= NUM_GATEWAYS; i++) begin
|
||||
claim_array[i][counter] <= 0;
|
||||
complete_array[i][counter] <= 0;
|
||||
end
|
||||
|
||||
// if a claim is issued, forward it to gateway with highest priority for the claiming target
|
||||
if (target_irq_claims_i[counter]) begin
|
||||
claim_array[identifier_of_largest_priority_per_target[counter]][counter] <= 1;
|
||||
// save claim for later when the complete-notification arrives
|
||||
save_claims_array_q[identifier_of_largest_priority_per_target[counter]][counter] <= 1;
|
||||
|
||||
end else begin
|
||||
// if a complete is issued, check if that gateway has previously been claimed by
|
||||
// this target and forward the
|
||||
// complete message to that gateway. if no claim has previously been issued, the
|
||||
// complete message is ignored
|
||||
if (target_irq_completes_i[counter] && (save_claims_array_q[target_irq_completes_identifier_i[counter]][counter] > 0)) begin
|
||||
complete_array[target_irq_completes_identifier_i[counter]][counter] <= 1;
|
||||
save_claims_array_q[target_irq_completes_identifier_i[counter]][counter] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// the outputs for an id are the ORs of all targets for that id
|
||||
always_comb begin : proc_result_computation
|
||||
for (integer gateway = 1; gateway <= NUM_GATEWAYS; gateway++) begin
|
||||
automatic logic is_claimed = '0;
|
||||
automatic logic is_completed = '0;
|
||||
|
||||
for (integer target = 0; target < NUM_TARGETS; target++) begin
|
||||
is_claimed = is_claimed | claim_array [gateway][target];
|
||||
is_completed = is_completed | complete_array[gateway][target];
|
||||
end
|
||||
|
||||
if (is_claimed) begin
|
||||
gateway_irq_claims_o [gateway-1] = 1;
|
||||
end else begin
|
||||
gateway_irq_claims_o [gateway-1] = 0;
|
||||
end
|
||||
|
||||
if (is_completed) begin
|
||||
gateway_irq_completes_o[gateway-1] = 1;
|
||||
end else begin
|
||||
gateway_irq_completes_o[gateway-1] = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule //plic_claim_complete_tracker
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : Comperator
|
||||
//-- File : plic_comperator.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: Comparator
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
// find larger operand (value and identifier)
|
||||
// chooses the left operand on equality
|
||||
module plic_comparator #(
|
||||
parameter int ID_BITWIDTH = -1,
|
||||
parameter int PRIORITY_BITWIDTH = -1
|
||||
)(
|
||||
input logic [PRIORITY_BITWIDTH-1:0] left_priority_i,
|
||||
input logic [PRIORITY_BITWIDTH-1:0] right_priority_i,
|
||||
input logic [ID_BITWIDTH-1:0 ] left_identifier_i,
|
||||
input logic [ID_BITWIDTH-1:0 ] right_identifier_i,
|
||||
output logic [PRIORITY_BITWIDTH-1:0] larger_priority_o,
|
||||
output logic[ ID_BITWIDTH-1:0 ] identifier_of_larger_o
|
||||
);
|
||||
|
||||
always_comb begin : proc_compare
|
||||
if (left_priority_i >= right_priority_i) begin
|
||||
larger_priority_o = left_priority_i;
|
||||
identifier_of_larger_o = left_identifier_i;
|
||||
end else begin
|
||||
larger_priority_o = right_priority_i;
|
||||
identifier_of_larger_o = right_identifier_i;
|
||||
end
|
||||
end
|
||||
|
||||
//pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert(ID_BITWIDTH > 0) else $error("ID_BITWIDTH has to be larger than 0");
|
||||
assert(PRIORITY_BITWIDTH > 0) else $error("PRIORITY_BITWIDTH has to be larger than 0");
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : Find Maximun
|
||||
//-- File : plic_find_max.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: Find the element with the largest priority
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
module plic_find_max #(
|
||||
parameter int NUM_OPERANDS = 2,
|
||||
parameter int ID_BITWIDTH = 4,
|
||||
parameter int PRIORITY_BITWIDTH = 3
|
||||
)(
|
||||
input logic [PRIORITY_BITWIDTH-1:0] priorities_i [NUM_OPERANDS],
|
||||
input logic [ID_BITWIDTH-1:0 ] identifiers_i [NUM_OPERANDS],
|
||||
output logic [PRIORITY_BITWIDTH-1:0] largest_priority_o,
|
||||
output logic [ID_BITWIDTH-1:0 ] identifier_of_largest_o
|
||||
);
|
||||
|
||||
localparam int max_stage = ($clog2(NUM_OPERANDS)-1);
|
||||
localparam int num_operands_aligned = 2**(max_stage+1);
|
||||
|
||||
logic [PRIORITY_BITWIDTH-1:0] priority_stages [max_stage + 2][num_operands_aligned];
|
||||
logic [ID_BITWIDTH-1:0 ] identifier_stages [max_stage + 2][num_operands_aligned];
|
||||
|
||||
|
||||
always_comb begin : proc_zero_padding
|
||||
for (integer operand = 0; operand < num_operands_aligned; operand++) begin
|
||||
if(operand < NUM_OPERANDS) begin
|
||||
priority_stages [0][operand] = priorities_i [operand];
|
||||
identifier_stages[0][operand] = identifiers_i [operand];
|
||||
end else begin
|
||||
priority_stages [0][operand] = '0;
|
||||
identifier_stages[0][operand] = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar comparator_stage = max_stage; comparator_stage >= 0 ; comparator_stage--) begin
|
||||
for (genvar stage_index = 0; stage_index < 2**comparator_stage; stage_index++) begin
|
||||
plic_comparator #(
|
||||
.ID_BITWIDTH (ID_BITWIDTH ),
|
||||
.PRIORITY_BITWIDTH (PRIORITY_BITWIDTH )
|
||||
) comp_instance(
|
||||
.left_priority_i ( priority_stages [max_stage - comparator_stage][2*stage_index] ),
|
||||
.right_priority_i ( priority_stages [max_stage - comparator_stage][2*stage_index + 1] ),
|
||||
.left_identifier_i ( identifier_stages[max_stage - comparator_stage][2*stage_index] ),
|
||||
.right_identifier_i ( identifier_stages[max_stage - comparator_stage][2*stage_index + 1] ),
|
||||
.larger_priority_o ( priority_stages [max_stage - (comparator_stage-1)][stage_index] ),
|
||||
.identifier_of_larger_o ( identifier_stages[max_stage - (comparator_stage-1)][stage_index] )
|
||||
);
|
||||
end
|
||||
end
|
||||
|
||||
assign largest_priority_o = priority_stages [max_stage+1][0];
|
||||
assign identifier_of_largest_o = identifier_stages[max_stage+1][0];
|
||||
endmodule
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : Interrupt Gateway
|
||||
//-- File : plic_gateway.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: Implementation of the Irq Gateway
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
// the gateway does enable or disable itself depending on the signals claim_i, completed_i
|
||||
// the gateway knows neither its gateway_id nor its priority
|
||||
module plic_gateway (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic irq_source_i,
|
||||
input logic claim_i,
|
||||
input logic completed_i,
|
||||
output logic irq_pending_o
|
||||
);
|
||||
logic irq_pending_q; // is 1 when an interrupt appears until the interrupt is claimed
|
||||
logic wait_completion_q; // is 1 when an interrupt appears until the interrupt is completed
|
||||
// also determines if the gateway is disabled, i.e. if interrupts are masked
|
||||
logic irq_trigger;
|
||||
|
||||
assign irq_trigger = (~wait_completion_q | completed_i) & irq_source_i;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_update_ff
|
||||
if (~rst_ni) begin
|
||||
irq_pending_q <= 1'b0;
|
||||
wait_completion_q <= 1'b0;
|
||||
end else begin
|
||||
//pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
assert (~(claim_i & (~wait_completion_q & irq_source_i)));
|
||||
assert (~(completed_i & (~wait_completion_q & irq_source_i)));
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
||||
//interrupts not masked and interrupt received -> output to 1
|
||||
if (irq_trigger) begin
|
||||
irq_pending_q <= 1;
|
||||
//interrupt claimed -> output to 0
|
||||
end else if (claim_i) begin
|
||||
irq_pending_q <= 0;
|
||||
end
|
||||
|
||||
//interrupts not masked and interrupt received -> interrupts masked from know on
|
||||
if (irq_trigger) begin
|
||||
wait_completion_q <= 1;
|
||||
//interrupt completed -> demask interrupts
|
||||
end else if (completed_i) begin
|
||||
wait_completion_q <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Make sure there is 0 cycles delay from claim_i to irq_pending_o.
|
||||
assign irq_pending_o = (irq_pending_q | irq_trigger) & ~claim_i;
|
||||
|
||||
endmodule
|
|
@ -1,304 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : Register Interface
|
||||
//-- File : plic_target_slice.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: Implementation of the plic's register interface
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
module plic_interface #(
|
||||
parameter int ADDR_WIDTH = 32, // width of external address bus
|
||||
parameter int DATA_WIDTH = 32, // width of external data bus
|
||||
parameter int ID_BITWIDTH = 10, // width of the gateway indecies
|
||||
parameter int PARAMETER_BITWIDTH = 3, // width of the internal parameter e.g. priorities
|
||||
parameter int NUM_TARGETS = 1, // number of target slices
|
||||
parameter int NUM_GATEWAYS = 1 // number of gateways
|
||||
)(
|
||||
input logic clk_i, // the clock signal
|
||||
input logic rst_ni, // asynchronous reset active low
|
||||
input logic[ID_BITWIDTH-1:0] id_of_largest_priority_i[NUM_TARGETS], // input array id of largest priority
|
||||
input logic pending_array_i[NUM_GATEWAYS], // array with the interrupt pending , idx0 is gateway 1
|
||||
output reg [PARAMETER_BITWIDTH-1:0] thresholds_o[NUM_TARGETS], // save internally the thresholds, communicate values over this port to the core
|
||||
output reg [PARAMETER_BITWIDTH-1:0] gateway_priorities_o[NUM_GATEWAYS], // save internally the the priorities, communicate values
|
||||
output logic irq_enables_o[NUM_GATEWAYS][NUM_TARGETS], // communicate enable bits over this port
|
||||
output logic target_irq_claims_o[NUM_TARGETS], // claim signals
|
||||
output logic target_irq_completes_o[NUM_TARGETS], // complete signals
|
||||
output logic[ID_BITWIDTH-1:0] target_irq_completes_id_o[NUM_TARGETS], // the id of the gateway to be completed
|
||||
REG_BUS.in external_bus_io // the bus
|
||||
);
|
||||
|
||||
//define ennumerated types
|
||||
enum logic [2:0] {INV, PRI, IPA, IEB, THR, CCP} funct; // the address mapping will primarily check what
|
||||
// function should be performed
|
||||
// INV: invalid, PRI: priorities, IPA: interrupt pending
|
||||
// IEB: interrupt enable, THR: threshold and claim/complete
|
||||
// CCP: claim/clear pulses
|
||||
|
||||
//calculate some parameter needed later
|
||||
localparam int num_gateway_bundles = (NUM_GATEWAYS-1) / DATA_WIDTH + 1; // how many bundles we have to consider
|
||||
localparam int bpw = DATA_WIDTH / 8; // how many bytes a data word consist of
|
||||
//internal signals
|
||||
logic [ADDR_WIDTH-12-1:0 ] page_address; // the upper part of the address
|
||||
logic [11:0 ] page_offset; // the lowest 12 bit describes the page offset
|
||||
logic [11-$clog2(bpw):0 ] page_word_offset; // the word address of each page offset
|
||||
logic [$clog2(bpw)-1:0 ] word_offset; // the byte in the word
|
||||
|
||||
logic [DATA_WIDTH/8-1:0 ] write_active; // 0 if inactive, else what byte ahs to be written
|
||||
logic read_active; // 0 if inactive, 1 when reading the word
|
||||
//bundle definitions
|
||||
logic [DATA_WIDTH-1:0 ] irq_pending_bundle[num_gateway_bundles];
|
||||
|
||||
//registers
|
||||
logic [PARAMETER_BITWIDTH-1:0] thresholds_d[NUM_TARGETS];
|
||||
logic [PARAMETER_BITWIDTH-1:0] thresholds_q[NUM_TARGETS];
|
||||
|
||||
logic [PARAMETER_BITWIDTH-1:0] priorities_d[NUM_GATEWAYS];
|
||||
logic [PARAMETER_BITWIDTH-1:0] priorities_q[NUM_GATEWAYS];
|
||||
|
||||
logic [ID_BITWIDTH-1:0 ] id_of_largest_priority_d[NUM_TARGETS];
|
||||
logic [ID_BITWIDTH-1:0 ] id_of_largest_priority_q[NUM_TARGETS];
|
||||
|
||||
logic [DATA_WIDTH/bpw-1:0 ] ena_bundles_d[num_gateway_bundles][NUM_TARGETS][DATA_WIDTH/8];
|
||||
logic [DATA_WIDTH/bpw-1:0 ] ena_bundles_q[num_gateway_bundles][NUM_TARGETS][DATA_WIDTH/8];
|
||||
|
||||
// assignments
|
||||
assign id_of_largest_priority_d = id_of_largest_priority_i;
|
||||
|
||||
// assign addresses
|
||||
assign page_address = external_bus_io.addr[ADDR_WIDTH-1:12];
|
||||
assign page_offset = external_bus_io.addr[11:0 ];
|
||||
assign page_word_offset = external_bus_io.addr[11:$clog2(bpw) ];
|
||||
assign word_offset = external_bus_io.addr[$clog2(bpw)-1:0];
|
||||
|
||||
assign write_active = (external_bus_io.valid & external_bus_io.write) ? external_bus_io.wstrb : '0;
|
||||
assign read_active = external_bus_io.valid & !external_bus_io.write;
|
||||
|
||||
// bundle signals
|
||||
for (genvar bundle = 0; bundle < num_gateway_bundles; bundle++) begin
|
||||
for (genvar ip_bit = 0; ip_bit < DATA_WIDTH; ip_bit++) begin
|
||||
if (bundle * DATA_WIDTH + ip_bit < NUM_GATEWAYS) begin
|
||||
assign irq_pending_bundle[bundle][ip_bit] = pending_array_i[bundle * DATA_WIDTH + ip_bit];
|
||||
end else begin
|
||||
assign irq_pending_bundle[bundle][ip_bit] = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar bundle = 0; bundle < num_gateway_bundles; bundle++) begin
|
||||
for (genvar target = 0; target < NUM_TARGETS; target++) begin
|
||||
for (genvar byte_in_word = 0; byte_in_word < DATA_WIDTH/8; byte_in_word++) begin
|
||||
for (genvar enable_bit = 0; enable_bit < 8; enable_bit++) begin
|
||||
assign irq_enables_o[bundle * DATA_WIDTH + enable_bit + byte_in_word * 8][target] =
|
||||
ena_bundles_q[bundle][target][byte_in_word][enable_bit];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// determine the function to be performed
|
||||
always_comb begin : proc_address_map
|
||||
// default values
|
||||
funct = INV;
|
||||
// only aligned access is allowed:
|
||||
if (word_offset == '0) begin
|
||||
// we have now an word alligned access -> check out page offset to determine
|
||||
// what type of access this is.
|
||||
if (page_address[13:0] == 0) begin // we access the gateway priority bits
|
||||
// the page_word_offset tells us now which gateway we consider
|
||||
// in order to grant or deny access, we have to check if the gateway
|
||||
// in question really exist.
|
||||
// Gateway 0 does not exist, so return an error
|
||||
if (page_word_offset <= NUM_GATEWAYS && page_word_offset > 0) begin //the gateway in question exists
|
||||
// set the current operation to be an access to the priority registers
|
||||
funct = PRI;
|
||||
end
|
||||
// we now access the IP Bits, read only
|
||||
end else if (page_address[13:0] == 1) begin
|
||||
// the page_word_offset tells us now, which word we have to consider,
|
||||
// the word, which includes the IP bit in question should be returned
|
||||
if (page_word_offset<num_gateway_bundles) begin
|
||||
funct = IPA;
|
||||
end
|
||||
// access of the enable bits for each target
|
||||
end else if (page_address[13:9] == 0) begin
|
||||
// the bottom part page_word_offset now tells us which gateway bundle we have to consider
|
||||
// part of the page_address and the upper part of the page_word_offset give us the target nr.
|
||||
if (page_offset[6:$clog2(bpw)] < num_gateway_bundles) begin
|
||||
if (({page_address[8:0], page_offset[11:7]} - 64) < NUM_TARGETS) begin
|
||||
funct = IEB;
|
||||
end
|
||||
end
|
||||
// priority / claim / complete
|
||||
end else begin
|
||||
// page address - 0h20 gives the target number
|
||||
if (page_address[13:0] - 'h200 < NUM_TARGETS) begin
|
||||
// check lowest bit of the page_word_offset to get the exact function
|
||||
if (page_word_offset == 0) begin
|
||||
funct = THR;
|
||||
end else if (page_word_offset == 1) begin
|
||||
funct = CCP;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin : proc_read_write
|
||||
// defalt values
|
||||
external_bus_io.rdata = 0;
|
||||
external_bus_io.error = 0;
|
||||
external_bus_io.ready = 0;
|
||||
|
||||
for (integer target = 0; target<NUM_TARGETS; target++) begin
|
||||
target_irq_claims_o [target] = '0;
|
||||
target_irq_completes_o [target] = '0;
|
||||
target_irq_completes_id_o[target] = '0;
|
||||
end
|
||||
|
||||
//just keep the values untouched as default
|
||||
priorities_d = priorities_q;
|
||||
ena_bundles_d = ena_bundles_q;
|
||||
thresholds_d = thresholds_q;
|
||||
|
||||
case (funct)
|
||||
PRI: begin
|
||||
// read case
|
||||
if (read_active != 0) begin
|
||||
external_bus_io.rdata = priorities_q[page_word_offset-1];
|
||||
external_bus_io.ready = 1;
|
||||
// write case
|
||||
end else if (write_active[0] == 1) begin
|
||||
priorities_d[page_word_offset-1] = external_bus_io.wdata[PARAMETER_BITWIDTH-1:0];
|
||||
external_bus_io.ready = 1;
|
||||
end
|
||||
end
|
||||
|
||||
IPA: begin
|
||||
// read case
|
||||
if (read_active != 0) begin
|
||||
external_bus_io.rdata = irq_pending_bundle[page_word_offset];
|
||||
external_bus_io.ready = 1;
|
||||
// write case
|
||||
end else if (write_active != 0) begin
|
||||
external_bus_io.error = 1; //not allowed
|
||||
end
|
||||
end
|
||||
|
||||
IEB: begin
|
||||
// read case
|
||||
if (read_active != 0) begin
|
||||
for (integer byte_in_word = 0; byte_in_word < DATA_WIDTH/8; byte_in_word++) begin
|
||||
external_bus_io.rdata[8*(byte_in_word) +: 8] = ena_bundles_q[page_offset[6:$clog2(bpw)]][({page_address[8:0], page_offset[11:7]} - 64)][byte_in_word];
|
||||
end
|
||||
external_bus_io.ready = 1;
|
||||
// write case
|
||||
end else if(write_active != 0) begin
|
||||
for (integer byte_in_word=0; byte_in_word<DATA_WIDTH/8; byte_in_word++) begin
|
||||
if(write_active[byte_in_word]) begin
|
||||
ena_bundles_d[page_offset[6:$clog2(bpw)]][({page_address[8:0], page_offset[11:7]} - 64)][byte_in_word] = external_bus_io.wdata[8*(byte_in_word) +: 8];
|
||||
end
|
||||
end
|
||||
external_bus_io.ready = 1;
|
||||
end
|
||||
end
|
||||
|
||||
THR: begin
|
||||
// read case
|
||||
if (read_active != 0) begin
|
||||
external_bus_io.rdata[PARAMETER_BITWIDTH-1:0] = thresholds_q[(page_address[13:0] - 'h200)];
|
||||
external_bus_io.ready = 1;
|
||||
// write case
|
||||
end else if (write_active != 0) begin
|
||||
thresholds_d[(page_address[13:0] - 'h200)] = external_bus_io.wdata[PARAMETER_BITWIDTH-1:0];
|
||||
external_bus_io.ready = 1;
|
||||
end
|
||||
end
|
||||
|
||||
CCP: begin
|
||||
// read case
|
||||
if (read_active != 0) begin
|
||||
target_irq_claims_o[(page_address[13:0] - 'h200)] = 1;
|
||||
external_bus_io.rdata[ID_BITWIDTH-1:0] = id_of_largest_priority_q[(page_address[13:0] - 'h200)];
|
||||
external_bus_io.ready = 1;
|
||||
// write case
|
||||
end else if (write_active != 0) begin
|
||||
target_irq_completes_o[(page_address[13:0] - 'h200)] = 1;
|
||||
target_irq_completes_id_o[(page_address[13:0] - 'h200)] = external_bus_io.wdata[ID_BITWIDTH-1:0];
|
||||
external_bus_io.ready = 1;
|
||||
end
|
||||
end
|
||||
|
||||
default : begin
|
||||
//per default: error
|
||||
external_bus_io.error = 1;
|
||||
external_bus_io.ready = 1;
|
||||
end
|
||||
endcase // funct
|
||||
end
|
||||
|
||||
// store data in flip flops
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_update_ff
|
||||
if (~rst_ni) begin // set all registers to 0
|
||||
for (integer gateway = 0; gateway < NUM_GATEWAYS; gateway++)
|
||||
priorities_q[gateway] <= 0;
|
||||
|
||||
for (integer bundle = 0; bundle < num_gateway_bundles; bundle++)
|
||||
for (integer target = 0; target < NUM_TARGETS; target++)
|
||||
for (integer byte_in_word = 0; byte_in_word < DATA_WIDTH/8; byte_in_word++)
|
||||
ena_bundles_q[bundle][target][byte_in_word] <= 0;
|
||||
|
||||
for (integer target = 0; target < NUM_TARGETS; target++) begin
|
||||
thresholds_q[target] <= 0;
|
||||
id_of_largest_priority_q[target] <= 0;
|
||||
end
|
||||
end else begin
|
||||
priorities_q <= priorities_d;
|
||||
ena_bundles_q <= ena_bundles_d;
|
||||
thresholds_q <= thresholds_d;
|
||||
id_of_largest_priority_q <= id_of_largest_priority_d;
|
||||
end
|
||||
end
|
||||
|
||||
//assign outputs
|
||||
assign thresholds_o = thresholds_q;
|
||||
assign gateway_priorities_o = priorities_q;
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert ((ADDR_WIDTH==32) | (ADDR_WIDTH==64)) else $error("Address width has to bei either 32 or 64 bit");
|
||||
assert ((DATA_WIDTH==32) | (DATA_WIDTH==64)) else $error("Data width has to bei either 32 or 64 bit");
|
||||
assert (ID_BITWIDTH>0) else $error("ID_BITWIDTH has to be larger than 1");
|
||||
assert (ID_BITWIDTH<10) else $error("ID_BITWIDTH has to be smaller than 10");
|
||||
assert (PARAMETER_BITWIDTH>0) else $error("PARAMETER_BITWIDTH has to be larger than 1");
|
||||
assert (PARAMETER_BITWIDTH<8) else $error("PARAMETER_BITWIDTH has to be smaller than 8");
|
||||
assert (NUM_GATEWAYS>0) else $error("Num od Gateways has to be larger than 1");
|
||||
assert (NUM_GATEWAYS<512) else $error("Num of Gateways has to be smaller than 512");
|
||||
assert (NUM_TARGETS>0) else $error("Num Target slices has to be larger than 1");
|
||||
assert (NUM_TARGETS<15872) else $error("Num target slices has to be smaller than 15872");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,92 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
//
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Title : Target Slice
|
||||
//-- File : plic_target_slice.sv
|
||||
//-- Author : Gian Marti <gimarti.student.ethz.ch>
|
||||
//-- Author : Thomas Kramer <tkramer.student.ethz.ch>
|
||||
//-- Author : Thomas E. Benz <tbenz.student.ethz.ch>
|
||||
//-- Company : Integrated Systems Laboratory, ETH Zurich
|
||||
//-- Created : 2018-03-31
|
||||
//-- Last update: 2018-03-31
|
||||
//-- Platform : ModelSim (simulation), Synopsys (synthesis)
|
||||
//-- Standard : SystemVerilog IEEE 1800-2012
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Description: Target Slice
|
||||
//-------------------------------------------------------------------------------
|
||||
//-- Revisions :
|
||||
//-- Date Version Author Description
|
||||
//-- 2018-03-31 2.0 tbenz Created header
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
// Note: The gateways are expected to be ordered by their IDs (ascending).
|
||||
// This resolves priority ties by choosing the gateway with the lower ID.
|
||||
module plic_target_slice #(
|
||||
parameter int PRIORITY_BITWIDTH = 8,
|
||||
parameter int ID_BITWIDTH = 8,
|
||||
parameter int NUM_GATEWAYS = 1
|
||||
)(
|
||||
// Input signals from gateways.
|
||||
input logic interrupt_pending_i [NUM_GATEWAYS],
|
||||
input logic [PRIORITY_BITWIDTH-1:0] interrupt_priority_i[NUM_GATEWAYS],
|
||||
input logic [ID_BITWIDTH-1:0 ] interrupt_id_i [NUM_GATEWAYS],
|
||||
input logic interrupt_enable_i [NUM_GATEWAYS],
|
||||
input logic [PRIORITY_BITWIDTH-1:0] threshold_i,
|
||||
output logic ext_interrupt_present_o,
|
||||
output logic [ID_BITWIDTH-1:0 ] identifier_of_largest_o
|
||||
);
|
||||
|
||||
logic[PRIORITY_BITWIDTH:0] interrupt_priority_masked[NUM_GATEWAYS];
|
||||
|
||||
|
||||
// Signals that represent the selected interrupt source.
|
||||
logic[PRIORITY_BITWIDTH:0] best_priority;
|
||||
logic[ID_BITWIDTH-1:0 ] best_id;
|
||||
|
||||
// Create a tree to find the best interrupt source.
|
||||
plic_find_max #(
|
||||
.NUM_OPERANDS ( NUM_GATEWAYS ),
|
||||
.ID_BITWIDTH ( ID_BITWIDTH ),
|
||||
.PRIORITY_BITWIDTH ( PRIORITY_BITWIDTH + 1 )
|
||||
) find_max_instance (
|
||||
.priorities_i ( interrupt_priority_masked ),
|
||||
.identifiers_i ( interrupt_id_i ),
|
||||
// Outputs
|
||||
.largest_priority_o ( best_priority ),
|
||||
.identifier_of_largest_o ( best_id )
|
||||
);
|
||||
|
||||
// Compare the priority of the best interrupt source to the threshold.
|
||||
always_comb begin : proc_compare_threshold
|
||||
if ((best_priority - 1 > threshold_i) && (best_priority != '0)) begin
|
||||
ext_interrupt_present_o = 1;
|
||||
identifier_of_largest_o = best_id;
|
||||
end else begin
|
||||
if ((best_priority - 1 <= threshold_i) && (best_priority != '0)) begin
|
||||
ext_interrupt_present_o = 0;
|
||||
identifier_of_largest_o = best_id;
|
||||
end else begin
|
||||
ext_interrupt_present_o = 0;
|
||||
identifier_of_largest_o = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin : proc_mask_gateway_outputs
|
||||
for (int i = 0; i < NUM_GATEWAYS; i++) begin
|
||||
if (interrupt_enable_i[i] && interrupt_pending_i[i]) begin
|
||||
interrupt_priority_masked[i] = interrupt_priority_i[i] + 1; //priority shift +1
|
||||
end else begin
|
||||
interrupt_priority_masked[i] = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -1 +1 @@
|
|||
Subproject commit d10dce04b7211da044d31baaa06c7044c84083d9
|
||||
Subproject commit d8aeccc65fdbbb30ef9dd28e065c2947a2396eab
|
1
src/rv_plic
Submodule
1
src/rv_plic
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6046cfa518237c06031e65030f250bb29555e913
|
|
@ -148,17 +148,31 @@ module ariane_peripherals #(
|
|||
.reg_o ( reg_bus )
|
||||
);
|
||||
|
||||
plic #(
|
||||
.ID_BITWIDTH ( ariane_soc::PLICIdWidth ),
|
||||
.PARAMETER_BITWIDTH ( ariane_soc::ParameterBitwidth ),
|
||||
.NUM_TARGETS ( ariane_soc::NumTargets ),
|
||||
.NUM_SOURCES ( ariane_soc::NumSources )
|
||||
reg_intf::reg_intf_resp_d32 plic_resp;
|
||||
reg_intf::reg_intf_req_a32_d32 plic_req;
|
||||
|
||||
assign plic_req.addr = reg_bus.addr;
|
||||
assign plic_req.write = reg_bus.write;
|
||||
assign plic_req.wdata = reg_bus.wdata;
|
||||
assign plic_req.wstrb = reg_bus.wstrb;
|
||||
assign plic_req.valid = reg_bus.valid;
|
||||
|
||||
assign reg_bus.rdata = plic_resp.rdata;
|
||||
assign reg_bus.error = plic_resp.error;
|
||||
assign reg_bus.ready = plic_resp.ready;
|
||||
|
||||
plic_top #(
|
||||
.N_SOURCE ( ariane_soc::NumSources ),
|
||||
.N_TARGET ( ariane_soc::NumTargets ),
|
||||
.MAX_PRIO ( ariane_soc::MaxPriority )
|
||||
) i_plic (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.irq_sources_i ( irq_sources ),
|
||||
.eip_targets_o ( irq_o ),
|
||||
.external_bus_io ( reg_bus )
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.req_i ( plic_req ),
|
||||
.resp_o ( plic_resp ),
|
||||
.le_i ( '0 ), // 0:level 1:edge
|
||||
.irq_sources_i ( irq_sources ),
|
||||
.eip_targets_o ( irq_o )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
// Description: Contains SoC information as constants
|
||||
package ariane_soc;
|
||||
// M-Mode Hart, S-Mode Hart
|
||||
localparam NumTargets = 2;
|
||||
// Uart, SPI, Ethernet
|
||||
localparam NumSources = 3;
|
||||
localparam PLICIdWidth = 3;
|
||||
localparam ParameterBitwidth = PLICIdWidth;
|
||||
localparam int unsigned NumTargets = 2;
|
||||
// Uart, SPI, Ethernet, reserved
|
||||
localparam int unsigned NumSources = 30;
|
||||
localparam int unsigned MaxPriority = 7;
|
||||
|
||||
localparam NrSlaves = 2; // actually masters, but slaves on the crossbar
|
||||
|
||||
// 4 is recommended by AXI standard, so lets stick to it, do not change
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue