[rtl] Add memory and memory result interfaces

This commit adds memory interface and memory result interface
of the RISC-V Extension Interface.
This commit is contained in:
Hailin 2022-07-08 14:40:03 +02:00 committed by Pirmin Vogel
parent 8ad0d7c9d4
commit 129af7a53b
21 changed files with 698 additions and 81 deletions

View file

@ -113,6 +113,12 @@ parameters:
paramtype: vlogparam
description: "Enables the RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
MemInterface:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables Memory and Memory Result Interfaces for RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
targets:
sim:
default_tool: verilator
@ -135,6 +141,7 @@ targets:
- SecureIbex
- ICacheScramble
- XInterface
- MemInterface
toplevel: ibex_riscv_compliance
tools:
verilator:

View file

@ -152,7 +152,8 @@ module ibex_riscv_compliance (
.ICacheScramble (ICacheScramble ),
.DmHaltAddr (32'h00000000 ),
.DmExceptionAddr (32'h00000000 ),
.XInterface (XInterface )
.XInterface (XInterface ),
.MemInterface (MemInterface )
) u_top (
.clk_i (clk_sys ),
.rst_ni (rst_sys_n ),
@ -216,6 +217,12 @@ module ibex_riscv_compliance (
.x_issue_resp_i ('0 ),
.x_commit_valid_o ( ),
.x_commit_o ( ),
.x_mem_valid_i (1'b0 ),
.x_mem_ready_o ( ),
.x_mem_req_i ('0 ),
.x_mem_resp_o ( ),
.x_mem_result_valid_o ( ),
.x_mem_result_o ( ),
.x_result_valid_i (1'b0 ),
.x_result_ready_o ( ),
.x_result_i ('0 )

View file

@ -66,6 +66,7 @@ module core_ibex_tb_top;
parameter bit SecureIbex = 1'b0;
parameter bit ICacheScramble = 1'b0;
parameter bit XInterface = 1'b1;
parameter bit MemInterface = 1'b1;
ibex_top_tracing #(
.DmHaltAddr (32'h`BOOT_ADDR + 'h0 ),
@ -84,7 +85,8 @@ module core_ibex_tb_top;
.SecureIbex (SecureIbex ),
.ICacheScramble (ICacheScramble ),
.BranchPredictor (BranchPredictor ),
.XInterface (XInterface )
.XInterface (XInterface ),
.MemInterface (MemInterface )
) dut (
.clk_i (clk ),
.rst_ni (rst_n ),
@ -147,6 +149,12 @@ module core_ibex_tb_top;
.x_issue_resp_i ('0 ),
.x_commit_valid_o ( ),
.x_commit_o ( ),
.x_mem_valid_i (1'b0 ),
.x_mem_ready_o ( ),
.x_mem_req_i ('0 ),
.x_mem_resp_o ( ),
.x_mem_result_valid_o ( ),
.x_mem_result_o ( ),
.x_result_valid_i (1'b0 ),
.x_result_ready_o ( ),
.x_result_i ('0 )

View file

@ -112,6 +112,12 @@ parameters:
paramtype: vlogparam
description: "Enables the RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
MemInterface:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables Memory and Memory Result Interfaces for RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
targets:
default: &default_target
filesets:
@ -134,6 +140,7 @@ targets:
- ICacheScramble
- SRAMInitFile
- XInterface
- MemInterface
lint:
<<: *default_target

View file

@ -108,6 +108,12 @@ parameters:
paramtype: vlogparam
description: "Enables the RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
MemInterface:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables Memory and Memory Result Interfaces for RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
targets:
default: &default_target
filesets:
@ -130,6 +136,7 @@ targets:
- PMPNumRegions
- SRAMInitFile
- XInterface
- MemInterface
lint:
<<: *default_target

View file

@ -51,6 +51,7 @@ module ibex_simple_system (
parameter bit BranchPredictor = 1'b0;
parameter SRAMInitFile = "";
parameter bit XInterface = 1'b1;
parameter bit MemInterface = 1'b1;
logic clk_sys = 1'b0, rst_sys_n;
@ -202,7 +203,8 @@ module ibex_simple_system (
.BranchPredictor ( BranchPredictor ),
.DmHaltAddr ( 32'h00100000 ),
.DmExceptionAddr ( 32'h00100000 ),
.XInterface ( XInterface )
.XInterface ( XInterface ),
.MemInterface ( MemInterface )
) u_top (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
@ -266,6 +268,12 @@ module ibex_simple_system (
.x_issue_resp_i ('0),
.x_commit_valid_o (),
.x_commit_o (),
.x_mem_valid_i (1'b0),
.x_mem_ready_o (),
.x_mem_req_i ('0),
.x_mem_resp_o (),
.x_mem_result_valid_o (),
.x_mem_result_o (),
.x_result_valid_i (1'b0),
.x_result_ready_o (),
.x_result_i ('0)

View file

@ -23,6 +23,7 @@ small:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# Configuration to match that used in the OpenTitan project
opentitan:
@ -41,6 +42,7 @@ opentitan:
SecureIbex : 1
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# ===============================
# * EXPERIMENTAL CONFIGURATIONS *
@ -65,6 +67,7 @@ experimental-maxperf:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# experimental-maxperf config above plus PMP enabled with 16 regions.
experimental-maxperf-pmp:
@ -83,6 +86,7 @@ experimental-maxperf-pmp:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# experimental-maxperf-pmp config above with balanced bitmanip extension
experimental-maxperf-pmp-bmbalanced:
@ -101,6 +105,7 @@ experimental-maxperf-pmp-bmbalanced:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# experimental-maxperf-pmp config above with full bitmanip extension
experimental-maxperf-pmp-bmfull:
@ -119,6 +124,7 @@ experimental-maxperf-pmp-bmfull:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# experimental-maxperf-pmp-bmfull config above with icache enabled
experimental-maxperf-pmp-bmfull-icache:
@ -137,6 +143,7 @@ experimental-maxperf-pmp-bmfull-icache:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# experimental-maxperf with branch predictor switched on. This exists to allow
# easy use of Ibex with the branch predictor in particular for CI runs. The
@ -158,6 +165,7 @@ experimental-branch-predictor:
SecureIbex : 0
ICacheScramble : 0
XInterface : 0
MemInterface : 0
# Small with X-Interface
small-cvxif:
@ -176,6 +184,7 @@ small-cvxif:
SecureIbex : 0
ICacheScramble : 0
XInterface : 1
MemInterface : 1
# Opentitan with X-Interface
opentitan-cvxif:
@ -194,6 +203,7 @@ opentitan-cvxif:
SecureIbex : 1
ICacheScramble : 0
XInterface : 1
MemInterface : 1
# experimental-maxperf-pmp config with X-Interface
experimental-maxperf-pmp-bmfull-cvxif:
@ -212,3 +222,4 @@ experimental-maxperf-pmp-bmfull-cvxif:
SecureIbex : 0
ICacheScramble : 0
XInterface : 1
MemInterface : 1

View file

@ -150,6 +150,12 @@ parameters:
paramtype: vlogparam
description: "Enables the RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
MemInterface:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables Memory and Memory Result Interfaces for RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
targets:
default: &default_target
filesets:

View file

@ -138,6 +138,12 @@ parameters:
paramtype: vlogparam
description: "Enables the RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
MemInterface:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables Memory and Memory Result Interfaces for RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
targets:
default: &default_target
filesets:

View file

@ -113,6 +113,12 @@ parameters:
paramtype: vlogparam
description: "Enables the RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
MemInterface:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables Memory and Memory Result Interfaces for RISC-V Extension Interface (EXPERIMENTAL) [0/1]"
targets:
default: &default_target
filesets:
@ -141,6 +147,7 @@ targets:
- PMPGranularity
- PMPNumRegions
- XInterface
- MemInterface
default_tool: verilator
tools:
verilator:

View file

@ -29,7 +29,9 @@ module ibex_alu #(
output logic [31:0] result_o,
output logic comparison_result_o,
output logic is_equal_result_o
output logic is_equal_result_o,
input logic x_mem_lsu_req_i
);
import ibex_pkg::*;
@ -82,23 +84,31 @@ module ibex_alu #(
// prepare operand a
always_comb begin
unique case(1'b1)
multdiv_sel_i: adder_in_a = multdiv_operand_a_i;
adder_op_a_shift1: adder_in_a = {operand_a_i[30:0],2'b01};
adder_op_a_shift2: adder_in_a = {operand_a_i[29:0],3'b001};
adder_op_a_shift3: adder_in_a = {operand_a_i[28:0],4'b0001};
default: adder_in_a = {operand_a_i,1'b1};
endcase
if (x_mem_lsu_req_i) begin
adder_in_a = {operand_a_i,1'b1};
end else begin
unique case(1'b1)
multdiv_sel_i: adder_in_a = multdiv_operand_a_i;
adder_op_a_shift1: adder_in_a = {operand_a_i[30:0],2'b01};
adder_op_a_shift2: adder_in_a = {operand_a_i[29:0],3'b001};
adder_op_a_shift3: adder_in_a = {operand_a_i[28:0],4'b0001};
default: adder_in_a = {operand_a_i,1'b1};
endcase
end
end
// prepare operand b
assign operand_b_neg = {operand_b_i,1'b0} ^ {33{1'b1}};
always_comb begin
unique case (1'b1)
multdiv_sel_i: adder_in_b = multdiv_operand_b_i;
adder_op_b_negate: adder_in_b = operand_b_neg;
default: adder_in_b = {operand_b_i, 1'b0};
endcase
if (x_mem_lsu_req_i) begin
adder_in_b = {operand_b_i, 1'b0};
end else begin
unique case (1'b1)
multdiv_sel_i: adder_in_b = multdiv_operand_b_i;
adder_op_b_negate: adder_in_b = operand_b_neg;
default: adder_in_b = {operand_b_i, 1'b0};
endcase
end
end
// actual adder

View file

@ -43,7 +43,8 @@ module ibex_core import ibex_pkg::*; #(
parameter int unsigned MemDataWidth = MemECC ? 32 + 7 : 32,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808,
parameter bit XInterface = 1'b1
parameter bit XInterface = 1'b1,
parameter bit MemInterface = 1'b0
) (
// Clock and Reset
input logic clk_i,
@ -165,6 +166,14 @@ module ibex_core import ibex_pkg::*; #(
// Commit Interface
output logic x_commit_valid_o,
output x_commit_t x_commit_o,
// Memory Interface
input logic x_mem_valid_i,
output logic x_mem_ready_o,
input x_mem_req_t x_mem_req_i,
output x_mem_resp_t x_mem_resp_o,
// Memory Result Interface
output logic x_mem_result_valid_o,
output x_mem_result_t x_mem_result_o,
// Result Interface
input logic x_result_valid_i,
output logic x_result_ready_o,
@ -226,6 +235,7 @@ module ibex_core import ibex_pkg::*; #(
// LSU signals
logic lsu_addr_incr_req;
logic [31:0] lsu_addr_last;
logic [3:0] lsu_x_mem_be;
// Jump and branch target and decision (EX->IF)
logic [31:0] branch_target_ex;
@ -296,6 +306,7 @@ module ibex_core import ibex_pkg::*; #(
logic lsu_we;
logic [1:0] lsu_type;
logic lsu_sign_ext;
logic lsu_rdata_valid;
logic lsu_req;
logic [31:0] lsu_wdata;
logic lsu_req_done;
@ -318,6 +329,7 @@ module ibex_core import ibex_pkg::*; #(
logic rf_write_wb;
logic outstanding_load_wb;
logic outstanding_store_wb;
logic outstanding_xif_load_store;
// Interrupts
logic nmi_mode;
@ -343,6 +355,9 @@ module ibex_core import ibex_pkg::*; #(
logic [31:0] csr_mtval;
logic csr_mstatus_tw;
priv_lvl_e priv_mode_id;
priv_lvl_e priv_mode_lsu_csr;
priv_lvl_e priv_mode_lsu_xif;
logic priv_mode_lsu_xif_en;
priv_lvl_e priv_mode_lsu;
// debug mode and dcsr configuration
@ -375,6 +390,7 @@ module ibex_core import ibex_pkg::*; #(
logic perf_load;
logic perf_store;
logic x_mem_lsu_req;
logic [4:0] instr_rs1;
logic [4:0] instr_rs2;
logic [4:0] instr_rs3;
@ -538,8 +554,10 @@ module ibex_core import ibex_pkg::*; #(
.DataIndTiming (DataIndTiming),
.WritebackStage (WritebackStage),
.BranchPredictor(BranchPredictor),
.ResetAll (ResetAll),
.MemECC (MemECC),
.XInterface (XInterface)
.XInterface (XInterface),
.MemInterface (MemInterface)
) id_stage_i (
.clk_i (clk_i),
.rst_ni(rst_ni),
@ -625,6 +643,8 @@ module ibex_core import ibex_pkg::*; #(
.lsu_type_o (lsu_type), // to load store unit
.lsu_sign_ext_o(lsu_sign_ext), // to load store unit
.lsu_wdata_o (lsu_wdata), // to load store unit
.lsu_rdata_i (rf_wdata_lsu),
.lsu_x_mem_be_o(lsu_x_mem_be),
.lsu_req_done_i(lsu_req_done), // from load store unit
.lsu_addr_incr_req_i(lsu_addr_incr_req),
@ -700,6 +720,10 @@ module ibex_core import ibex_pkg::*; #(
.ecs_wr_o (ecs_wr),
.ecs_wen_o(ecs_wen),
// X-Interface LSU privilege signal, to PMP
.priv_mode_lsu_xif_o (priv_mode_lsu_xif),
.priv_mode_lsu_xif_en_o(priv_mode_lsu_xif_en),
// Issue Interface
.x_issue_valid_o(x_issue_valid_o),
.x_issue_ready_i(x_issue_ready_i),
@ -710,10 +734,26 @@ module ibex_core import ibex_pkg::*; #(
.x_commit_valid_o(x_commit_valid_o),
.x_commit_o (x_commit_o),
// Memory Interface
.x_mem_valid_i(x_mem_valid_i),
.x_mem_ready_o(x_mem_ready_o),
.x_mem_req_i (x_mem_req_i),
.x_mem_resp_o (x_mem_resp_o),
// Memory Result Interface
.x_mem_result_valid_o(x_mem_result_valid_o),
.x_mem_result_o (x_mem_result_o),
// Result Interface
.x_result_valid_i(x_result_valid_i),
.x_result_ready_o(x_result_ready_o),
.x_result_i (x_result_i)
.x_result_i (x_result_i),
// To ex block
.x_mem_lsu_req_o(x_mem_lsu_req),
// Only for assertion
.outstanding_xif_load_store_o(outstanding_xif_load_store)
);
assign icache_inval_o = icache_inval;
@ -755,6 +795,9 @@ module ibex_core import ibex_pkg::*; #(
.imd_val_d_o (imd_val_d_ex),
.imd_val_q_i (imd_val_q_ex),
// From ID
.x_mem_lsu_req_i(x_mem_lsu_req),
// Outputs
.alu_adder_result_ex_o(alu_adder_result_ex), // to LSU
.result_ex_o (result_ex), // to ID
@ -771,6 +814,7 @@ module ibex_core import ibex_pkg::*; #(
assign data_req_o = data_req_out & ~pmp_req_err[PMP_D];
assign lsu_resp_err = lsu_load_err | lsu_store_err;
assign rf_we_lsu = lsu_rdata_valid & ~x_mem_result_valid_o;
ibex_load_store_unit #(
.MemECC(MemECC),
@ -797,9 +841,10 @@ module ibex_core import ibex_pkg::*; #(
.lsu_type_i (lsu_type),
.lsu_wdata_i (lsu_wdata),
.lsu_sign_ext_i(lsu_sign_ext),
.lsu_x_mem_be_i(lsu_x_mem_be),
.lsu_rdata_o (rf_wdata_lsu),
.lsu_rdata_valid_o(rf_we_lsu),
.lsu_rdata_valid_o(lsu_rdata_valid),
.lsu_req_i (lsu_req),
.lsu_req_done_o (lsu_req_done),
@ -981,9 +1026,13 @@ module ibex_core import ibex_pkg::*; #(
end
`ASSERT(NoMemResponseWithoutPendingAccess,
data_rvalid_i |-> outstanding_load_resp | outstanding_store_resp, clk_i, !rst_ni)
data_rvalid_i |-> outstanding_load_resp | outstanding_store_resp | outstanding_xif_load_store,
clk_i, !rst_ni)
`endif
logic unused_outstanding_xif_load_store;
assign unused_outstanding_xif_load_store = outstanding_xif_load_store;
////////////////////////
// RF (Register File) //
////////////////////////
@ -1021,7 +1070,7 @@ module ibex_core import ibex_pkg::*; #(
// Hart ID from outside
.hart_id_i (hart_id_i),
.priv_mode_id_o (priv_mode_id),
.priv_mode_lsu_o(priv_mode_lsu),
.priv_mode_lsu_o(priv_mode_lsu_csr),
// mtvec
.csr_mtvec_o (csr_mtvec),
@ -1108,6 +1157,9 @@ module ibex_core import ibex_pkg::*; #(
.ecs_wen_i(ecs_wen)
);
// Multiplex between external and internal signals
assign priv_mode_lsu = priv_mode_lsu_xif_en ? priv_mode_lsu_xif : priv_mode_lsu_csr;
// These assertions are in top-level as instr_valid_id required as the enable term
`ASSERT(IbexCsrOpValid, instr_valid_id |-> csr_op inside {
CSR_OP_READ,

View file

@ -44,6 +44,9 @@ module ibex_ex_block #(
output logic [33:0] imd_val_d_o[2],
input logic [33:0] imd_val_q_i[2],
// From ID stage
input logic x_mem_lsu_req_i,
// Outputs
output logic [31:0] alu_adder_result_ex_o, // to LSU
output logic [31:0] result_ex_o,
@ -130,7 +133,8 @@ module ibex_ex_block #(
.adder_result_ext_o (alu_adder_result_ext),
.result_o (alu_result),
.comparison_result_o(alu_cmp_result),
.is_equal_result_o (alu_is_equal_result)
.is_equal_result_o (alu_is_equal_result),
.x_mem_lsu_req_i (x_mem_lsu_req_i)
);
////////////////

View file

@ -25,8 +25,10 @@ module ibex_id_stage import ibex_pkg::*; #(
parameter bit BranchTargetALU = 0,
parameter bit WritebackStage = 0,
parameter bit BranchPredictor = 0,
parameter bit ResetAll = 1'b0,
parameter bit MemECC = 1'b0,
parameter bit XInterface = 1'b1
parameter bit XInterface = 1'b1,
parameter bit MemInterface = 1'b0
) (
input logic clk_i,
input logic rst_ni,
@ -122,6 +124,8 @@ module ibex_id_stage import ibex_pkg::*; #(
input logic lsu_addr_incr_req_i,
input logic [31:0] lsu_addr_last_i,
input logic [31:0] lsu_rdata_i,
output logic [3:0] lsu_x_mem_be_o,
// Interrupt signals
input logic csr_mstatus_mie_i,
@ -199,6 +203,10 @@ module ibex_id_stage import ibex_pkg::*; #(
output logic [5:0] ecs_wr_o,
output logic [2:0] ecs_wen_o,
// Privilege mode output
output ibex_pkg::priv_lvl_e priv_mode_lsu_xif_o,
output logic priv_mode_lsu_xif_en_o,
// Issue Interface
output logic x_issue_valid_o,
input logic x_issue_ready_i,
@ -209,10 +217,26 @@ module ibex_id_stage import ibex_pkg::*; #(
output logic x_commit_valid_o,
output x_commit_t x_commit_o,
// Memory Interface
input logic x_mem_valid_i,
output logic x_mem_ready_o,
input x_mem_req_t x_mem_req_i,
output x_mem_resp_t x_mem_resp_o,
// Memory Result Interface
output logic x_mem_result_valid_o,
output x_mem_result_t x_mem_result_o,
// Result Interface
input logic x_result_valid_i,
output logic x_result_ready_o,
input x_result_t x_result_i
input x_result_t x_result_i,
// To ex block
output logic x_mem_lsu_req_o,
// For assertion only
output logic outstanding_xif_load_store_o
);
// Decoder/Controller, ID stage internal signals
@ -274,6 +298,11 @@ module ibex_id_stage import ibex_pkg::*; #(
logic x_result_err;
logic rf_rd_a_match_xif;
logic rf_rd_b_match_xif;
logic x_mem_load_err;
logic x_mem_store_err;
logic x_mem_lsu_req;
assign x_mem_lsu_req_o = x_mem_lsu_req;
// Immediate decoding and sign extension
logic [31:0] imm_i_type;
@ -677,9 +706,9 @@ module ibex_id_stage import ibex_pkg::*; #(
// LSU
.lsu_addr_last_i(lsu_addr_last_i),
.load_err_i (lsu_load_err_i),
.load_err_i (lsu_load_err_i | x_mem_load_err),
.load_intg_err_i(lsu_load_intg_err_i),
.store_err_i (lsu_store_err_i),
.store_err_i (lsu_store_err_i | x_mem_store_err),
.wb_exception_o (wb_exception),
.id_exception_o (id_exception),
@ -729,17 +758,13 @@ module ibex_id_stage import ibex_pkg::*; #(
.x_result_exccode_i (x_result_exccode)
);
assign multdiv_en_dec = mult_en_dec | div_en_dec;
assign multdiv_en_dec = mult_en_dec | div_en_dec;
assign lsu_req_o = x_mem_lsu_req | lsu_req;
assign lsu_req = instr_executing ? data_req_allowed & lsu_req_dec : 1'b0;
assign mult_en_id = instr_executing ? mult_en_dec : 1'b0;
assign div_en_id = instr_executing ? div_en_dec : 1'b0;
assign lsu_req_o = lsu_req;
assign lsu_we_o = lsu_we;
assign lsu_type_o = lsu_type;
assign lsu_sign_ext_o = lsu_sign_ext;
assign lsu_wdata_o = rf_rdata_b_fwd;
// csr_op_en_o is set when CSR access should actually happen.
// csv_access_o is set when CSR access instruction is present and is used to compute whether a CSR
// access is illegal. A combinational loop would be created if csr_op_en_o was used along (as
@ -747,8 +772,6 @@ module ibex_id_stage import ibex_pkg::*; #(
assign csr_op_en_o = csr_access_o & instr_executing & instr_id_internal_done_o;
assign alu_operator_ex_o = alu_operator;
assign alu_operand_a_ex_o = alu_operand_a;
assign alu_operand_b_ex_o = alu_operand_b;
assign mult_en_ex_o = mult_en_id;
assign div_en_ex_o = div_en_id;
@ -1222,15 +1245,19 @@ module ibex_id_stage import ibex_pkg::*; #(
// respond signals
logic x_issue_wb;
logic x_issue_exc;
logic unused_x_issue_ls;
logic x_issue_ls;
logic unused_x_issue_ecsw;
logic unused_x_issue_dw;
logic unused_x_issue_dr;
// For candidate signal
logic mem_xif;
// An valid instruction is an offload candidate for issue interface when:
// 1. It can not be recognized by the decoder, or
// 2. It access an illegal address in CSR.
assign x_issue_candidate = illegal_insn_dec | illegal_csr_insn_i;
// Both csr addr and external memory instruction use the same adder,
// csr instruction is illegal only if there will not be any external memory instruction.
assign x_issue_candidate = illegal_insn_dec | (illegal_csr_insn_i & ~mem_xif);
assign x_issue_valid_candidate = instr_valid_i & x_issue_candidate &
~instr_fetch_err_i & ~wb_exception & controller_run;
@ -1259,7 +1286,7 @@ module ibex_id_stage import ibex_pkg::*; #(
assign x_issue_reject = x_issue_handshake & ~x_issue_resp_i.accept;
assign x_issue_wb = x_issue_resp_i.writeback;
assign x_issue_exc = x_issue_resp_i.exc;
assign unused_x_issue_ls = x_issue_resp_i.loadstore;
assign x_issue_ls = x_issue_resp_i.loadstore;
assign unused_x_issue_ecsw = x_issue_resp_i.ecswrite;
assign unused_x_issue_dw = x_issue_resp_i.dualwrite;
assign unused_x_issue_dr = x_issue_resp_i.dualread;
@ -1364,13 +1391,275 @@ module ibex_id_stage import ibex_pkg::*; #(
assign unused_x_result_dbg = x_result_i.dbg;
////////////////////////////////////////
// Memory and Memory Result Interface //
////////////////////////////////////////
// Scoreboard Signals
logic [X_ID_WIDTH-1:0] x_mem_id_d;
logic x_mem_commit;
logic x_mem_result_fin;
logic [X_ID_WIDTH-1:0] x_mem_result_id;
logic x_mem_result_err;
if (MemInterface) begin : gen_mem_interface
logic [31:0] x_mem_addr;
logic x_mem_we;
logic [2:0] x_mem_size;
logic [1:0] x_mem_type;
logic [X_MEM_WIDTH/8-1:0] x_mem_be;
logic [1:0] unused_mem_attr;
logic [X_MEM_WIDTH-1:0] x_mem_wdata;
logic x_mem_last_d, x_mem_last_q;
logic x_mem_spec;
logic [X_ID_WIDTH-1:0] x_mem_id_q;
logic x_mem_handshake;
logic x_mem_size_err;
// State mechine for memory and memory result interface
typedef enum logic [1:0] { MEM_IDLE, MEM_LSU_REQ, MEM_WAIT_RESULT } x_mem_fsm_e;
x_mem_fsm_e x_mem_fsm_q, x_mem_fsm_d;
// Input request signals
assign x_mem_id_d = x_mem_req_i.id;
assign x_mem_addr = x_mem_req_i.addr;
assign x_mem_we = x_mem_req_i.we;
assign x_mem_size = x_mem_req_i.size;
assign x_mem_be = x_mem_req_i.be;
assign x_mem_wdata = x_mem_req_i.wdata;
assign x_mem_last_d = x_mem_req_i.last;
assign x_mem_spec = x_mem_req_i.spec;
assign unused_mem_attr = x_mem_req_i.attr;
// LSU privillege level
assign priv_mode_lsu_xif_o = x_mem_req_i.mode;
assign priv_mode_lsu_xif_en_o = 1'b1;
// Output respond signals
// Load and store exceptions supportted now are bus errors,
// the signals of which are transmitted through memory result interface.
assign x_mem_resp_o.exc = x_mem_load_err | x_mem_store_err;
assign x_mem_resp_o.exccode = x_mem_load_err ? 6'd05 : (x_mem_store_err ? 6'd07 : '0);
assign x_mem_resp_o.dbg = 1'b0;
// Output memory result signals
assign x_mem_result_id = x_mem_id_q;
assign x_mem_result_o.id = x_mem_id_q;
// Mux to avoid x in output, which will cause assertion failure in lockstep
assign x_mem_result_o.rdata = x_mem_result_valid_o ? lsu_rdata_i : '0;
assign x_mem_result_o.err = x_mem_result_err;
assign x_mem_result_o.dbg = 1'b0;
// Handshake
assign x_mem_handshake = x_mem_valid_i & x_mem_ready_o;
// Deal with memory request type
always_comb begin
x_mem_type = 2'b00;
x_mem_size_err = 1'b0;
unique case (x_mem_size)
// Byte
3'b000: begin
x_mem_type = 2'b10;
end
// Half word
3'b001: begin
x_mem_type = 2'b01;
end
// Word
3'b010: begin
x_mem_type = 2'b00;
end
// Other values are illegal, raise an exception
3'b011,
3'b100,
3'b101,
3'b110,
3'b111: begin
x_mem_size_err = 1'b1;
end
default: begin
end
endcase
end
// LSU signals
assign lsu_we_o = x_mem_lsu_req ? x_mem_we : lsu_we;
assign lsu_type_o = x_mem_lsu_req ? x_mem_type : lsu_type;
assign lsu_sign_ext_o = x_mem_lsu_req ? 1'b0 : lsu_sign_ext;
assign lsu_wdata_o = x_mem_lsu_req ? x_mem_wdata : rf_rdata_b_fwd;
// LSU address signals
assign alu_operand_a_ex_o = x_mem_lsu_req ? x_mem_addr : alu_operand_a;
assign alu_operand_b_ex_o = x_mem_lsu_req ? (lsu_addr_incr_req_i ? 32'h4 : 32'h0) :
alu_operand_b;
always_comb begin
x_mem_fsm_d = x_mem_fsm_q;
x_mem_ready_o = 1'b0;
x_mem_result_valid_o = 1'b0;
x_mem_result_fin = 1'b0;
x_mem_result_err = 1'b0;
x_mem_load_err = 1'b0;
x_mem_store_err = 1'b0;
// x_mem_lsu_req = 1'b0;
unique case (x_mem_fsm_q)
MEM_IDLE: begin
if (x_mem_valid_i & (~x_mem_spec | x_mem_commit)) begin
if (x_mem_size_err) begin
x_mem_fsm_d = MEM_IDLE;
x_mem_ready_o = 1'b1;
x_mem_load_err = ~x_mem_we;
x_mem_store_err = x_mem_we;
end else begin
x_mem_fsm_d = MEM_LSU_REQ;
// x_mem_lsu_req = 1'b1;
if (lsu_req_done_i) begin
x_mem_fsm_d = MEM_WAIT_RESULT;
x_mem_ready_o = 1'b1;
end
end
end
end
MEM_LSU_REQ: begin
// x_mem_lsu_req = 1'b1;
if (lsu_req_done_i) begin
x_mem_fsm_d = MEM_WAIT_RESULT;
x_mem_ready_o = 1'b1;
end
end
MEM_WAIT_RESULT: begin
if (lsu_resp_valid_i) begin
if (x_mem_valid_i & (~x_mem_spec | x_mem_commit)) begin
if (x_mem_size_err) begin
x_mem_fsm_d = MEM_IDLE;
x_mem_ready_o = 1'b1;
x_mem_load_err = ~x_mem_we;
x_mem_store_err = x_mem_we;
end else begin
x_mem_fsm_d = MEM_LSU_REQ;
// x_mem_lsu_req = 1'b1;
if (lsu_req_done_i) begin
x_mem_fsm_d = MEM_WAIT_RESULT;
x_mem_ready_o = 1'b1;
end
end
end else begin
x_mem_fsm_d = MEM_IDLE;
end
x_mem_result_valid_o = 1'b1;
x_mem_result_err = lsu_load_err_i | lsu_store_err_i | lsu_load_intg_err_i;
if (x_mem_last_q) begin
x_mem_result_fin = 1'b1;
end
end
end
default: begin
x_mem_fsm_d = MEM_IDLE;
end
endcase
end
// This code has the same function as the commented code in the state machine above.
// Make this change because verilator cannot compile the code above.
logic x_mem_status_idle;
assign x_mem_status_idle = x_mem_fsm_q == MEM_IDLE |
(x_mem_fsm_q == MEM_WAIT_RESULT & lsu_resp_valid_i);
assign x_mem_lsu_req = (x_mem_fsm_q == MEM_LSU_REQ) |
(x_mem_status_idle & ~x_mem_size_err &
x_mem_valid_i & (~x_mem_spec | x_mem_commit));
assign lsu_x_mem_be_o = x_mem_lsu_req ? x_mem_be : 4'b1111;
// Only for assertion.
assign outstanding_xif_load_store_o = (x_mem_fsm_q != MEM_IDLE) | (x_mem_fsm_d != MEM_IDLE);
// Flip-Flops
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
x_mem_fsm_q <= '0;
end else begin
x_mem_fsm_q <= x_mem_fsm_d;
end
end
if (ResetAll) begin : g_x_mem_ra
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
x_mem_last_q <= '0;
x_mem_id_q <= '0;
end else if (x_mem_handshake) begin
x_mem_last_q <= x_mem_last_d;
x_mem_id_q <= x_mem_id_d;
end
end
end else begin : g_x_mem_nr
always_ff @(posedge clk_i or negedge rst_ni) begin
if (x_mem_handshake) begin
x_mem_last_q <= x_mem_last_d;
x_mem_id_q <= x_mem_id_d;
end
end
end
end else begin : gen_no_mem_interface
// Assign inputs
logic unused_x_mem_valid;
x_mem_req_t unused_x_mem_req;
assign unused_x_mem_valid = x_mem_valid_i;
assign unused_x_mem_req = x_mem_req_i;
// Zero outputs
assign x_mem_ready_o = '0;
assign x_mem_resp_o = '0;
assign x_mem_result_valid_o = '0;
assign x_mem_result_o = '0;
assign x_mem_lsu_req = 1'b0;
// Signals from/to scoreboard
assign x_mem_id_d = '0;
assign x_mem_result_fin = '0;
assign x_mem_result_id = '0;
assign x_mem_result_err = 1'b0;
logic unused_mem_commit;
logic [31:0] unused_lsu_rdata;
assign unused_mem_commit = x_mem_commit;
assign unused_lsu_rdata = lsu_rdata_i;
// LSU signals
assign lsu_we_o = lsu_we;
assign lsu_type_o = lsu_type;
assign lsu_sign_ext_o = lsu_sign_ext;
assign lsu_wdata_o = rf_rdata_b_fwd;
assign lsu_x_mem_be_o = 4'b1111;
// Execution block signals
assign alu_operand_a_ex_o = alu_operand_a;
assign alu_operand_b_ex_o = alu_operand_b;
// LSU privillege level
assign priv_mode_lsu_xif_o = '0;
assign priv_mode_lsu_xif_en_o = 1'b0;
// Memory interface size error signals
assign x_mem_load_err = 1'b0;
assign x_mem_store_err = 1'b0;
// Signal only for assertion
assign outstanding_xif_load_store_o = 1'b0;
end
/////////////////
// SCORE BOARD //
/////////////////
// Signal to reset scoreboard and kill requests in issue-commit buffer
logic x_exc_err;
assign x_exc_err = x_result_exc | x_result_err;
assign x_exc_err = x_result_exc | x_result_err | x_mem_result_err |
x_mem_load_err | x_mem_store_err;
// Scoreboard registers
logic [31:0] scoreboard;
@ -1433,6 +1722,7 @@ module ibex_id_stage import ibex_pkg::*; #(
.wb_exception_i (wb_exception),
.mem_in_wb_i (outstanding_memory_access),
.external_exc_o (external_exc),
.mem_xif_o (mem_xif),
.illegal_insn_o (illegal_insn_id),
// issue interface
.issue_id_o (x_issue_id),
@ -1441,10 +1731,17 @@ module ibex_id_stage import ibex_pkg::*; #(
.issue_handshake_i(x_issue_handshake),
.issue_reject_i (x_issue_reject),
.issue_exc_i (x_issue_exc),
.issue_ls_i (x_issue_ls),
// commit interface
.commit_valid_o(x_commit_valid_o),
.commit_id_o (x_commit_id),
.commit_kill_o (x_commit_kill),
// memory interface
.mem_id_i (x_mem_id_d),
.mem_commit_o(x_mem_commit),
// memory result interface
.mem_result_fin_i(x_mem_result_fin),
.mem_result_id_i (x_mem_result_id),
// result interface
.result_handshake_i(x_result_handshake),
.result_id_i (x_result_id)
@ -1457,27 +1754,40 @@ module ibex_id_stage import ibex_pkg::*; #(
logic [5:0] unused_ecs_rd;
logic unused_x_issue_ready;
x_issue_resp_t unused_x_issue_resp;
logic unused_x_mem_valid;
x_mem_req_t unused_x_mem_req;
logic unused_x_result_valid;
x_result_t unused_x_result;
logic unused_x_issue_use_rs3;
logic unused_outstanding_memory_access;
logic [31:0] unused_lsu_rdata;
assign unused_ecs_rd = ecs_rd_i;
assign unused_x_issue_ready = x_issue_ready_i;
assign unused_x_issue_resp = x_issue_resp_i;
assign unused_x_mem_valid = x_mem_valid_i;
assign unused_x_mem_req = x_mem_req_i;
assign unused_x_result_valid = x_result_valid_i;
assign unused_x_result = x_result_i;
assign unused_lsu_rdata = lsu_rdata_i;
assign unused_x_issue_use_rs3 = x_issue_use_rs3;
assign unused_outstanding_memory_access = outstanding_memory_access;
assign ecs_wr_o = '0;
assign ecs_wen_o = '0;
assign x_issue_valid_o = 1'b0;
assign x_issue_req_o = '0;
assign x_commit_valid_o = 1'b0;
assign x_commit_o = '0;
assign x_result_ready_o = 1'b0;
assign ecs_wr_o = '0;
assign ecs_wen_o = '0;
assign x_issue_valid_o = 1'b0;
assign x_issue_req_o = '0;
assign x_commit_valid_o = 1'b0;
assign x_commit_o = '0;
assign x_result_ready_o = 1'b0;
assign x_mem_ready_o = 1'b0;
assign x_mem_resp_o = '0;
assign x_mem_result_valid_o = 1'b0;
assign x_mem_result_o = '0;
assign priv_mode_lsu_xif_o = '0;
assign priv_mode_lsu_xif_en_o = 1'b0;
assign outstanding_xif_load_store_o = 1'b0;
// X-Interface signals that needs to be set to 0
assign x_issue_candidate = 1'b0;
@ -1491,11 +1801,21 @@ module ibex_id_stage import ibex_pkg::*; #(
assign x_result_exc = 1'b0;
assign x_result_exccode = '0;
assign x_result_err = 1'b0;
assign x_mem_load_err = 1'b0;
assign x_mem_store_err = 1'b0;
assign x_mem_lsu_req = 1'b0;
// wire connections
assign illegal_insn_id = illegal_insn_dec | illegal_csr_insn_i;
assign rf_waddr_id_o = rf_waddr_dec;
assign rf_wdata_id_o = rf_wdata_mux;
assign illegal_insn_id = illegal_insn_dec | illegal_csr_insn_i;
assign rf_waddr_id_o = rf_waddr_dec;
assign rf_wdata_id_o = rf_wdata_mux;
assign lsu_we_o = lsu_we;
assign lsu_type_o = lsu_type;
assign lsu_sign_ext_o = lsu_sign_ext;
assign lsu_wdata_o = rf_rdata_b_fwd;
assign lsu_x_mem_be_o = 4'b1111;
assign alu_operand_a_ex_o = alu_operand_a;
assign alu_operand_b_ex_o = alu_operand_b;
end
//////////
@ -1555,6 +1875,10 @@ module ibex_id_stage import ibex_pkg::*; #(
`ASSERT(IbexMulticycleStageRegEnableUnique,
$onehot0({|imd_val_we_ex_i, imd_val_we_x_issue}))
// LSU enable must be unique.
`ASSERT(LoadStoreUnitEnableUnique,
$onehot0({x_mem_lsu_req, lsu_req}))
// Duplicated instruction flops must match
// === as DV environment can produce instructions with Xs in, so must use precise match that
// includes Xs

View file

@ -39,6 +39,7 @@ module ibex_load_store_unit #(
input logic [1:0] lsu_type_i, // data type: word, half word, byte -> from ID/EX
input logic [31:0] lsu_wdata_i, // data to write to memory -> from ID/EX
input logic lsu_sign_ext_i, // sign extension -> from ID/EX
input logic [3:0] lsu_x_mem_be_i,
output logic [31:0] lsu_rdata_o, // requested data -> to ID/EX
output logic lsu_rdata_valid_o,
@ -518,7 +519,7 @@ module ibex_load_store_unit #(
// output to data interface
assign data_addr_o = data_addr_w_aligned;
assign data_we_o = lsu_we_i;
assign data_be_o = data_be;
assign data_be_o = data_be & lsu_x_mem_be_i;
/////////////////////////////////////
// Write data integrity generation //

View file

@ -39,7 +39,8 @@ module ibex_lockstep import ibex_pkg::*; #(
parameter int unsigned MemDataWidth = MemECC ? 32 + 7 : 32,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808,
parameter bit XInterface = 1'b1
parameter bit XInterface = 1'b1,
parameter bit MemInterface = 1'b0
) (
input logic clk_i,
input logic rst_ni,
@ -115,6 +116,12 @@ module ibex_lockstep import ibex_pkg::*; #(
input x_issue_resp_t x_issue_resp_i,
input logic x_commit_valid_i,
input x_commit_t x_commit_i,
input logic x_mem_valid_i,
input logic x_mem_ready_i,
input x_mem_req_t x_mem_req_i,
input x_mem_resp_t x_mem_resp_i,
input logic x_mem_result_valid_i,
input x_mem_result_t x_mem_result_i,
input logic x_result_valid_i,
input logic x_result_ready_i,
input x_result_t x_result_i
@ -204,6 +211,8 @@ module ibex_lockstep import ibex_pkg::*; #(
x_compressed_resp_t x_compressed_resp;
logic x_issue_ready;
x_issue_resp_t x_issue_resp;
logic x_mem_valid;
x_mem_req_t x_mem_req;
logic x_result_valid;
x_result_t x_result;
} delayed_inputs_t;
@ -237,6 +246,8 @@ module ibex_lockstep import ibex_pkg::*; #(
assign shadow_inputs_in.x_compressed_resp = x_compressed_resp_i;
assign shadow_inputs_in.x_issue_ready = x_issue_ready_i;
assign shadow_inputs_in.x_issue_resp = x_issue_resp_i;
assign shadow_inputs_in.x_mem_valid = x_mem_valid_i;
assign shadow_inputs_in.x_mem_req = x_mem_req_i;
assign shadow_inputs_in.x_result_valid = x_result_valid_i;
assign shadow_inputs_in.x_result = x_result_i;
@ -297,6 +308,10 @@ module ibex_lockstep import ibex_pkg::*; #(
x_issue_req_t x_issue_req;
logic x_commit_valid;
x_commit_t x_commit;
logic x_mem_ready;
x_mem_resp_t x_mem_resp;
logic x_mem_result_valid;
x_mem_result_t x_mem_result;
logic x_result_ready;
} delayed_outputs_t;
@ -337,6 +352,10 @@ module ibex_lockstep import ibex_pkg::*; #(
assign core_outputs_in.x_issue_req = x_issue_req_i;
assign core_outputs_in.x_commit_valid = x_commit_valid_i;
assign core_outputs_in.x_commit = x_commit_i;
assign core_outputs_in.x_mem_ready = x_mem_ready_i;
assign core_outputs_in.x_mem_resp = x_mem_resp_i;
assign core_outputs_in.x_mem_result_valid = x_mem_result_valid_i;
assign core_outputs_in.x_mem_result = x_mem_result_i;
assign core_outputs_in.x_result_ready = x_result_ready_i;
// Delay the outputs
@ -383,7 +402,8 @@ module ibex_lockstep import ibex_pkg::*; #(
.MemDataWidth ( MemDataWidth ),
.DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr ),
.XInterface ( XInterface )
.XInterface ( XInterface ),
.MemInterface ( MemInterface )
) u_shadow_core (
.clk_i (clk_i),
.rst_ni (rst_shadow_n),
@ -487,6 +507,12 @@ module ibex_lockstep import ibex_pkg::*; #(
.x_issue_resp_i (shadow_inputs_q[0].x_issue_resp),
.x_commit_valid_o (shadow_outputs_d.x_commit_valid),
.x_commit_o (shadow_outputs_d.x_commit),
.x_mem_valid_i (shadow_inputs_q[0].x_mem_valid),
.x_mem_ready_o (shadow_outputs_d.x_mem_ready),
.x_mem_req_i (shadow_inputs_q[0].x_mem_req),
.x_mem_resp_o (shadow_outputs_d.x_mem_resp),
.x_mem_result_valid_o (shadow_outputs_d.x_mem_result_valid),
.x_mem_result_o (shadow_outputs_d.x_mem_result),
.x_result_valid_i (shadow_inputs_q[0].x_result_valid),
.x_result_ready_o (shadow_outputs_d.x_result_ready),
.x_result_i (shadow_inputs_q[0].x_result)

View file

@ -669,6 +669,7 @@ package ibex_pkg;
parameter int unsigned XLEN = 32;
parameter int unsigned X_NUM_RS = 3;
parameter int unsigned X_ID_WIDTH = 4;
parameter int unsigned X_MEM_WIDTH = 32;
parameter int unsigned X_RFR_WIDTH = 32;
parameter int unsigned X_RFW_WIDTH = 32;
parameter logic [31:0] X_MISA = 32'b0;
@ -712,6 +713,32 @@ package ibex_pkg;
logic commit_kill;
} x_commit_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic [31:0] addr;
priv_lvl_e mode;
logic we;
logic [2:0] size;
logic [X_MEM_WIDTH/8-1:0] be;
logic [1:0] attr;
logic [X_MEM_WIDTH-1:0] wdata;
logic last;
logic spec;
} x_mem_req_t;
typedef struct packed {
logic exc;
logic [5:0] exccode;
logic dbg;
} x_mem_resp_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic [X_MEM_WIDTH-1:0] rdata;
logic err;
logic dbg;
} x_mem_result_t;
typedef struct packed {
logic [X_ID_WIDTH-1:0] id;
logic [X_RFW_WIDTH-1:0] data;

View file

@ -36,6 +36,7 @@ module ibex_top import ibex_pkg::*; #(
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808,
parameter bit XInterface = 1'b1,
parameter bit MemInterface = 1'b0,
// Default seed and nonce for scrambling
parameter logic [SCRAMBLE_KEY_W-1:0] RndCnstIbexKey = RndCnstIbexKeyDefault,
parameter logic [SCRAMBLE_NONCE_W-1:0] RndCnstIbexNonce = RndCnstIbexNonceDefault
@ -147,6 +148,14 @@ module ibex_top import ibex_pkg::*; #(
// Commit Interface
output logic x_commit_valid_o,
output x_commit_t x_commit_o,
// Memory Interface
input logic x_mem_valid_i,
output logic x_mem_ready_o,
input x_mem_req_t x_mem_req_i,
output x_mem_resp_t x_mem_resp_o,
// Memory Result Interface
output logic x_mem_result_valid_o,
output x_mem_result_t x_mem_result_o,
// Result Interface
input logic x_result_valid_i,
output logic x_result_ready_o,
@ -299,7 +308,8 @@ module ibex_top import ibex_pkg::*; #(
.MemDataWidth (MemDataWidth),
.DmHaltAddr (DmHaltAddr),
.DmExceptionAddr (DmExceptionAddr),
.XInterface (XInterface)
.XInterface (XInterface),
.MemInterface (MemInterface)
) u_ibex_core (
.clk_i(clk),
.rst_ni,
@ -403,6 +413,12 @@ module ibex_top import ibex_pkg::*; #(
.x_issue_resp_i,
.x_commit_valid_o,
.x_commit_o,
.x_mem_valid_i,
.x_mem_ready_o,
.x_mem_req_i,
.x_mem_resp_o,
.x_mem_result_valid_o,
.x_mem_result_o,
.x_result_valid_i,
.x_result_ready_o,
.x_result_i
@ -700,6 +716,12 @@ module ibex_top import ibex_pkg::*; #(
x_issue_resp_i,
x_commit_valid_o,
x_commit_o,
x_mem_valid_i,
x_mem_ready_o,
x_mem_req_i,
x_mem_resp_o,
x_mem_result_valid_o,
x_mem_result_o,
x_result_valid_i,
x_result_ready_o,
x_result_i,
@ -772,6 +794,12 @@ module ibex_top import ibex_pkg::*; #(
x_issue_resp_t x_issue_resp_local;
logic x_commit_valid_local;
x_commit_t x_commit_local;
logic x_mem_valid_local;
logic x_mem_ready_local;
x_mem_req_t x_mem_req_local;
x_mem_resp_t x_mem_resp_local;
logic x_mem_result_valid_local;
x_mem_result_t x_mem_result_local;
logic x_result_valid_local;
logic x_result_ready_local;
x_result_t x_result_local;
@ -832,6 +860,12 @@ module ibex_top import ibex_pkg::*; #(
x_issue_resp_i,
x_commit_valid_o,
x_commit_o,
x_mem_valid_i,
x_mem_ready_o,
x_mem_req_i,
x_mem_resp_o,
x_mem_result_valid_o,
x_mem_result_o,
x_result_valid_i,
x_result_ready_o,
x_result_i,
@ -894,6 +928,12 @@ module ibex_top import ibex_pkg::*; #(
x_issue_resp_local,
x_commit_valid_local,
x_commit_local,
x_mem_valid_local,
x_mem_ready_local,
x_mem_req_local,
x_mem_resp_local,
x_mem_result_valid_local,
x_mem_result_local,
x_result_valid_local,
x_result_ready_local,
x_result_local,
@ -951,7 +991,8 @@ module ibex_top import ibex_pkg::*; #(
.MemECC (MemECC),
.DmHaltAddr (DmHaltAddr),
.DmExceptionAddr (DmExceptionAddr),
.XInterface (XInterface)
.XInterface (XInterface),
.MemInterface (MemInterface)
) u_ibex_lockstep (
.clk_i (clk),
.rst_ni (rst_ni),
@ -1027,6 +1068,12 @@ module ibex_top import ibex_pkg::*; #(
.x_issue_resp_i (x_issue_resp_local),
.x_commit_valid_i (x_commit_valid_local),
.x_commit_i (x_commit_local),
.x_mem_valid_i (x_mem_valid_local),
.x_mem_ready_i (x_mem_ready_local),
.x_mem_req_i (x_mem_req_local),
.x_mem_resp_i (x_mem_resp_local),
.x_mem_result_valid_i (x_mem_result_valid_local),
.x_mem_result_i (x_mem_result_local),
.x_result_valid_i (x_result_valid_local),
.x_result_ready_i (x_result_ready_local),
.x_result_i (x_result_local)

View file

@ -29,7 +29,8 @@ module ibex_top_tracing import ibex_pkg::*; #(
parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808,
parameter bit XInterface = 1'b1
parameter bit XInterface = 1'b1,
parameter bit MemInterface = 1'b0
) (
// Clock and Reset
input logic clk_i,
@ -101,6 +102,12 @@ module ibex_top_tracing import ibex_pkg::*; #(
input x_issue_resp_t x_issue_resp_i,
output logic x_commit_valid_o,
output x_commit_t x_commit_o,
input logic x_mem_valid_i,
output logic x_mem_ready_o,
input x_mem_req_t x_mem_req_i,
output x_mem_resp_t x_mem_resp_o,
output logic x_mem_result_valid_o,
output x_mem_result_t x_mem_result_o,
input logic x_result_valid_i,
output logic x_result_ready_o,
input x_result_t x_result_i
@ -174,7 +181,8 @@ module ibex_top_tracing import ibex_pkg::*; #(
.RndCnstLfsrPerm ( RndCnstLfsrPerm ),
.DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr ),
.XInterface ( XInterface )
.XInterface ( XInterface ),
.MemInterface ( MemInterface )
) u_ibex_top (
.clk_i,
.rst_ni,
@ -265,6 +273,12 @@ module ibex_top_tracing import ibex_pkg::*; #(
.x_issue_resp_i,
.x_commit_valid_o,
.x_commit_o,
.x_mem_valid_i,
.x_mem_ready_o,
.x_mem_req_i,
.x_mem_resp_o,
.x_mem_result_valid_o,
.x_mem_result_o,
.x_result_valid_i,
.x_result_ready_o,
.x_result_i

View file

@ -50,8 +50,8 @@ module ibex_wb_stage #(
output logic [31:0] rf_wdata_wb_o,
output logic rf_we_wb_o,
input logic lsu_resp_valid_i,
input logic lsu_resp_err_i,
input logic lsu_resp_valid_i,
input logic lsu_resp_err_i,
output logic instr_done_wb_o
);

View file

@ -20,6 +20,7 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
input logic wb_exception_i,
input logic mem_in_wb_i,
output logic external_exc_o,
output logic mem_xif_o,
output logic illegal_insn_o,
// issue interface
@ -30,12 +31,21 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
input logic issue_handshake_i,
input logic issue_reject_i,
input logic issue_exc_i,
input logic issue_ls_i,
// commit interface
output logic commit_valid_o,
output logic [X_ID_WIDTH-1:0] commit_id_o,
output logic commit_kill_o,
// memory interface
input logic [X_ID_WIDTH-1:0] mem_id_i,
output logic mem_commit_o,
// memory result interface
input logic mem_result_fin_i, // Mem requests from a certain ID has finished.
input logic [X_ID_WIDTH-1:0] mem_result_id_i,
// result interface
input logic result_handshake_i,
input logic [X_ID_WIDTH-1:0] result_id_i
@ -43,7 +53,9 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
// issue-commit buffer
logic [ICB_DEPTH-1:0] icb_valid_d, icb_valid_q;
logic [ICB_DEPTH-1:0] icb_commit_d, icb_commit_q;
logic [ICB_DEPTH-1:0] icb_exc_d, icb_exc_q;
logic [ICB_DEPTH-1:0] icb_mem_d, icb_mem_q;
logic [ICB_DEPTH-1:0] icb_reject_d, icb_reject_q;
// IDs
@ -56,7 +68,11 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
logic [ICB_ID_W-1:0] issue_id;
logic [ICB_ID_W-1:0] commit_id;
logic [ICB_ID_W-1:0] result_id;
logic [ICB_ID_W-1:0] mem_id;
logic [ICB_ID_W-1:0] mem_result_id;
logic [X_ID_WIDTH-ICB_ID_W-1:0] unused_result_id;
logic [X_ID_WIDTH-ICB_ID_W-1:0] unused_mem_id;
logic [X_ID_WIDTH-ICB_ID_W-1:0] unused_mem_result_id;
// Control signals
logic insn_reject;
@ -85,10 +101,15 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
// ID width transfer //
///////////////////////
assign issue_id_o = {{X_ID_WIDTH-ICB_ID_W{1'b0}}, issue_id};
assign commit_id_o = {{X_ID_WIDTH-ICB_ID_W{1'b0}}, commit_id};
assign result_id = result_id_i[ICB_ID_W-1:0];
assign unused_result_id = result_id_i[X_ID_WIDTH-1:ICB_ID_W];
assign issue_id_o = {{X_ID_WIDTH-ICB_ID_W{1'b0}}, issue_id};
assign commit_id_o = {{X_ID_WIDTH-ICB_ID_W{1'b0}}, commit_id};
assign result_id = result_id_i[ICB_ID_W-1:0];
assign mem_id = mem_id_i[ICB_ID_W-1:0];
assign mem_result_id = mem_result_id_i[ICB_ID_W-1:0];
assign unused_result_id = result_id_i[X_ID_WIDTH-1:ICB_ID_W];
assign unused_mem_id = mem_id_i[X_ID_WIDTH-1:ICB_ID_W];
assign unused_mem_result_id = mem_result_id_i[X_ID_WIDTH-1:ICB_ID_W];
///////////////
// ID lookup //
@ -143,8 +164,10 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
assign issue_icb_valid_o = issue_id_valid_q & (~issue_id_new_q | icf_push_ready) &
~insn_reject & ~is_killing;
assign insn_reject = |icb_reject_q;
assign external_exc_o = |icb_exc_d | insn_reject;
assign external_exc_o = |icb_exc_d | |icb_mem_d | insn_reject;
assign mem_xif_o = |icb_mem_q;
assign illegal_insn_o = icb_reject_q[commit_id] | (issue_reject_i & (issue_id == commit_id));
assign mem_commit_o = icb_commit_d[mem_id];
///////////////////////
// issue-commit FIFO //
@ -190,9 +213,9 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
assign lcb_id_d = icf_pop_data;
assign lcb_valid_d = lcb_push | (lcb_valid_q & ~lcb_pop);
// Push committed instructions into the buffer.
assign lcb_push = commit_valid_o & ~is_killing & ~icb_reject_q[commit_id];
assign lcb_push = commit_valid_o & ~is_killing & ~icb_reject_q[commit_id];
// Pop only if the instruction could not raise exception in the future.
assign lcb_pop = ~icb_exc_q[lcb_id_q] | is_killing;
assign lcb_pop = (~icb_exc_q[lcb_id_q] & (~icb_mem_q[lcb_id_q] | mem_result_fin_i)) | is_killing;
//////////////////////////
// finite state machine //
@ -230,38 +253,49 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
always_comb begin
icb_valid_d = icb_valid_q;
icb_commit_d = icb_commit_q;
icb_exc_d = icb_exc_q;
icb_mem_d = icb_mem_q;
icb_reject_d = icb_reject_q;
if (icf_push) begin
icb_valid_d[issue_id] = 1'b1;
// Set 1 since instruction not yet acceptted could raise exception in the future.
icb_exc_d[issue_id] = 1'b1;
icb_exc_d[issue_id] = 1'b1;
end
if (issue_handshake_i) begin
icb_valid_d[issue_id] = 1'b1;
icb_exc_d[issue_id] = issue_exc_i;
icb_reject_d[issue_id] = issue_reject_i;
icb_valid_d[issue_id] = 1'b1;
icb_exc_d[issue_id] = issue_exc_i;
icb_mem_d[issue_id] = issue_ls_i;
icb_reject_d[issue_id] = issue_reject_i;
end
// If result arrives at the same cycle, overwrite issue
if (result_handshake_i) begin
icb_valid_d[result_id] = 1'b0;
icb_commit_d[result_id] = 1'b0;
icb_exc_d[result_id] = 1'b0;
icb_mem_d[result_id] = 1'b0;
end
if (commit_valid_o & icb_reject_q[commit_id]) begin
// Clear all the bits for a rejected instruction
icb_valid_d[commit_id] = 1'b0;
icb_exc_d[commit_id] = 1'b0;
icb_reject_d[commit_id] = 1'b0;
if (mem_result_fin_i) begin
icb_mem_d[mem_result_id] = 1'b0;
end
if (commit_valid_o & is_killing) begin
// Clear all the bits for a killed instruction
icb_valid_d[commit_id] = 1'b0;
icb_exc_d[commit_id] = 1'b0;
icb_reject_d[commit_id] = 1'b0;
if (commit_valid_o) begin
if (icb_reject_q[commit_id] | is_killing) begin
// Clear all the bits for a rejected or killed instruction
icb_valid_d[commit_id] = 1'b0;
icb_commit_d[commit_id] = 1'b0;
icb_exc_d[commit_id] = 1'b0;
icb_mem_d[commit_id] = 1'b0;
icb_reject_d[commit_id] = 1'b0;
end else begin
icb_commit_d[commit_id] = 1'b1;
end
end
if (xif_exception_i) begin
icb_valid_d[lcb_id_q] = 1'b0;
icb_exc_d[lcb_id_q] = 1'b0;
icb_valid_d[lcb_id_q] = 1'b0;
icb_commit_d[lcb_id_q] = 1'b0;
icb_exc_d[lcb_id_q] = 1'b0;
icb_mem_d[lcb_id_q] = 1'b0;
icb_reject_d[lcb_id_q] = 1'b0;
end
end
@ -292,7 +326,9 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
lcb_valid_q <= 1'b0;
icb_fsm_q <= ICB_COMMIT;
icb_valid_q <= '0;
icb_commit_q <= '0;
icb_exc_q <= '0;
icb_mem_q <= '0;
icb_reject_q <= '0;
end else begin
issue_id_valid_q <= issue_id_valid_d;
@ -300,7 +336,9 @@ module ibex_xif_issue_commit_buffer import ibex_pkg::*; (
lcb_valid_q <= lcb_valid_d;
icb_fsm_q <= icb_fsm_d;
icb_valid_q <= icb_valid_d;
icb_commit_q <= icb_commit_d;
icb_exc_q <= icb_exc_d;
icb_mem_q <= icb_mem_d;
icb_reject_q <= icb_reject_d;
end
end