hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   3: // SPDX-License-Identifier: Apache-2.0
   4: 
   5: /**
   6:  * Ibex RISC-V core
   7:  *
   8:  * 32 bit RISC-V core supporting the RV32I + optionally EMC instruction sets.
   9:  * Instruction and data bus are 32 bit wide TileLink-UL (TL-UL).
  10:  */
  11: module rv_core_ibex #(
  12:   parameter bit          PMPEnable        = 1'b0,
  13:   parameter int unsigned PMPGranularity   = 0,
  14:   parameter int unsigned PMPNumRegions    = 4,
  15:   parameter int unsigned MHPMCounterNum   = 8,
  16:   parameter int unsigned MHPMCounterWidth = 40,
  17:   parameter bit          RV32E            = 0,
  18:   parameter bit          RV32M            = 1,
  19:   parameter int unsigned DmHaltAddr       = 32'h1A110800,
  20:   parameter int unsigned DmExceptionAddr  = 32'h1A110808,
  21:   parameter bit          PipeLine         = 0
  22: ) (
  23:   // Clock and Reset
  24:   input  logic        clk_i,
  25:   input  logic        rst_ni,
  26: 
  27:   input  logic        test_en_i,     // enable all clock gates for testing
  28: 
  29:   input  logic [31:0] hart_id_i,
  30:   input  logic [31:0] boot_addr_i,
  31: 
  32:   // Instruction memory interface
  33:   output tlul_pkg::tl_h2d_t     tl_i_o,
  34:   input  tlul_pkg::tl_d2h_t     tl_i_i,
  35: 
  36:   // Data memory interface
  37:   output tlul_pkg::tl_h2d_t     tl_d_o,
  38:   input  tlul_pkg::tl_d2h_t     tl_d_i,
  39: 
  40:   // Interrupt inputs
  41:   input  logic        irq_software_i,
  42:   input  logic        irq_timer_i,
  43:   input  logic        irq_external_i,
  44:   input  logic [14:0] irq_fast_i,
  45:   input  logic        irq_nm_i,
  46: 
  47:   // Debug Interface
  48:   input  logic        debug_req_i,
  49: 
  50:   // CPU Control Signals
  51:   input  logic        fetch_enable_i,
  52:   output logic        core_sleep_o
  53: );
  54: 
  55:   import top_pkg::*;
  56:   import tlul_pkg::*;
  57: 
  58:   // if pipeline=1, do not allow pass through and always break the path
  59:   // if pipeline is 0, passthrough the fifo completely
  60:   localparam int FifoPass = PipeLine ? 1'b0 : 1'b1;
  61:   localparam int FifoDepth = PipeLine ? 4'h2 : 4'h0;
  62:   localparam int WordSize = $clog2(TL_DW / 8);
  63: 
  64:   // Inst interface (internal)
  65:   logic        instr_req_o;
  66:   logic        instr_gnt_i;
  67:   logic        instr_rvalid_i;
  68:   logic [31:0] instr_addr_o;
  69:   logic [31:0] instr_rdata_i;
  70:   logic        instr_err_i;
  71: 
  72:   logic        data_req_o;
  73:   logic        data_gnt_i;
  74:   logic        data_rvalid_i;
  75:   logic        data_we_o;
  76:   logic [3:0]  data_be_o;
  77:   logic [31:0] data_addr_o;
  78:   logic [31:0] data_wdata_o;
  79:   logic [31:0] data_rdata_i;
  80:   logic        data_err_i;
  81: 
  82:   // Pipeline interfaces
  83:   tl_h2d_t tl_i_ibex2fifo;
  84:   tl_d2h_t tl_i_fifo2ibex;
  85:   tl_h2d_t tl_d_ibex2fifo;
  86:   tl_d2h_t tl_d_fifo2ibex;
  87: 
  88: `ifdef RVFI
  89:   logic        rvfi_valid;
  90:   logic [63:0] rvfi_order;
  91:   logic [31:0] rvfi_insn;
  92:   logic        rvfi_trap;
  93:   logic        rvfi_halt;
  94:   logic        rvfi_intr;
  95:   logic [ 1:0] rvfi_mode;
  96:   logic [ 4:0] rvfi_rs1_addr;
  97:   logic [ 4:0] rvfi_rs2_addr;
  98:   logic [31:0] rvfi_rs1_rdata;
  99:   logic [31:0] rvfi_rs2_rdata;
 100:   logic [ 4:0] rvfi_rd_addr;
 101:   logic [31:0] rvfi_rd_wdata;
 102:   logic [31:0] rvfi_pc_rdata;
 103:   logic [31:0] rvfi_pc_wdata;
 104:   logic [31:0] rvfi_mem_addr;
 105:   logic [ 3:0] rvfi_mem_rmask;
 106:   logic [ 3:0] rvfi_mem_wmask;
 107:   logic [31:0] rvfi_mem_rdata;
 108:   logic [31:0] rvfi_mem_wdata;
 109: `endif
 110: 
 111:   ibex_core #(
 112:      .PMPEnable        ( PMPEnable         ),
 113:      .PMPGranularity   ( PMPGranularity    ),
 114:      .PMPNumRegions    ( PMPNumRegions     ),
 115:      .MHPMCounterNum   ( MHPMCounterNum    ),
 116:      .MHPMCounterWidth ( MHPMCounterWidth  ),
 117:      .RV32E            ( RV32E             ),
 118:      .RV32M            ( RV32M             ),
 119:      .DmHaltAddr       ( DmHaltAddr        ),
 120:      .DmExceptionAddr  ( DmExceptionAddr   )
 121:   ) u_core (
 122:      .clk_i,
 123:      .rst_ni,
 124: 
 125:      .test_en_i,
 126: 
 127:      .hart_id_i,
 128:      .boot_addr_i,
 129: 
 130:      .instr_req_o,
 131:      .instr_gnt_i,
 132:      .instr_rvalid_i,
 133:      .instr_addr_o,
 134:      .instr_rdata_i,
 135:      .instr_err_i,
 136: 
 137:      .data_req_o,
 138:      .data_gnt_i,
 139:      .data_rvalid_i,
 140:      .data_we_o,
 141:      .data_be_o,
 142:      .data_addr_o,
 143:      .data_wdata_o,
 144:      .data_rdata_i,
 145:      .data_err_i,
 146: 
 147:      .irq_software_i,
 148:      .irq_timer_i,
 149:      .irq_external_i,
 150:      .irq_fast_i,
 151:      .irq_nm_i,
 152: 
 153:      .debug_req_i,
 154: 
 155: `ifdef RVFI
 156:      .rvfi_valid,
 157:      .rvfi_order,
 158:      .rvfi_insn,
 159:      .rvfi_trap,
 160:      .rvfi_halt,
 161:      .rvfi_intr,
 162:      .rvfi_mode,
 163:      .rvfi_rs1_addr,
 164:      .rvfi_rs2_addr,
 165:      .rvfi_rs1_rdata,
 166:      .rvfi_rs2_rdata,
 167:      .rvfi_rd_addr,
 168:      .rvfi_rd_wdata,
 169:      .rvfi_pc_rdata,
 170:      .rvfi_pc_wdata,
 171:      .rvfi_mem_addr,
 172:      .rvfi_mem_rmask,
 173:      .rvfi_mem_wmask,
 174:      .rvfi_mem_rdata,
 175:      .rvfi_mem_wdata,
 176: `endif
 177: 
 178:      .fetch_enable_i,
 179:      .core_sleep_o
 180:   );
 181: 
 182:   //
 183:   // Convert ibex data/instruction bus to TL-UL
 184:   //
 185: 
 186:   // Generate a_source fields by toggling between 0 and 1
 187:   logic tl_i_source, tl_d_source;
 188:   always_ff @(posedge clk_i or negedge rst_ni) begin
 189:     if (!rst_ni) begin
 190:       {tl_i_source, tl_d_source} <= '0;
 191:     end else begin
 192:       if (instr_req_o && instr_gnt_i) tl_i_source <= !tl_i_source;
 193:       if (data_req_o && data_gnt_i)  tl_d_source <= !tl_d_source;
 194:     end
 195:   end
 196: 
 197:   // Convert core instruction interface to TL-UL
 198:   // The outgoing address is always word aligned
 199:   assign tl_i_ibex2fifo = '{
 200:     a_valid:   instr_req_o,
 201:     a_opcode:  tlul_pkg::Get,
 202:     a_param:   3'h0,
 203:     a_size:    2'(WordSize),
 204:     a_mask:    {TL_DBW{1'b1}},
 205:     a_source:  TL_AIW'(tl_i_source),
 206:     a_address: {instr_addr_o[31:WordSize], {WordSize{1'b0}}},
 207:     a_data:    {TL_DW{1'b0}},
 208:     a_user:    '{default:'0},
 209: 
 210:     d_ready:   1'b1
 211:   };
 212: 
 213:   assign instr_gnt_i    = tl_i_fifo2ibex.a_ready & tl_i_ibex2fifo.a_valid;
 214:   assign instr_rvalid_i = tl_i_fifo2ibex.d_valid;
 215:   assign instr_rdata_i  = tl_i_fifo2ibex.d_data;
 216:   assign instr_err_i    = tl_i_fifo2ibex.d_error;
 217: 
 218:   tlul_fifo_sync #(
 219:     .ReqPass(FifoPass),
 220:     .RspPass(FifoPass),
 221:     .ReqDepth(FifoDepth),
 222:     .RspDepth(FifoDepth)
 223:   ) fifo_i (
 224:     .clk_i,
 225:     .rst_ni,
 226:     .tl_h_i      (tl_i_ibex2fifo),
 227:     .tl_h_o      (tl_i_fifo2ibex),
 228:     .tl_d_o      (tl_i_o),
 229:     .tl_d_i      (tl_i_i),
 230:     .spare_req_i (1'b0),
 231:     .spare_req_o (),
 232:     .spare_rsp_i (1'b0),
 233:     .spare_rsp_o ());
 234: 
 235:   // Convert core data interface to TL-UL
 236:   // The outgoing address is always word aligned.  If it's a write access that occupies
 237:   // all lanes, then the operation is always PutFullData; otherwise it is always PutPartialData
 238:   // When in partial opertaion, tlul allows writes smaller than the operation size, thus
 239:   // size / mask information can be directly passed through
 240:   assign tl_d_ibex2fifo = '{
 241:     a_valid:   data_req_o,
 242:     a_opcode:  (~data_we_o)        ? tlul_pkg::Get           :
 243:                (data_be_o == 4'hf) ? tlul_pkg::PutFullData   :
 244:                                      tlul_pkg::PutPartialData,
 245:     a_param:   3'h0,
 246:     a_size:    2'(WordSize),
 247:     a_mask:    data_be_o,
 248:     a_source:  TL_AIW'(tl_d_source),
 249:     a_address: {data_addr_o[31:WordSize], {WordSize{1'b0}}},
 250:     a_data:    data_wdata_o,
 251:     a_user:    '{default:'0},
 252: 
 253:     d_ready:   1'b1
 254:   };
 255:   assign data_gnt_i    = tl_d_fifo2ibex.a_ready & tl_d_ibex2fifo.a_valid;
 256:   assign data_rvalid_i = tl_d_fifo2ibex.d_valid;
 257:   assign data_rdata_i  = tl_d_fifo2ibex.d_data;
 258:   assign data_err_i    = tl_d_fifo2ibex.d_error;
 259: 
 260:   tlul_fifo_sync #(
 261:     .ReqPass(FifoPass),
 262:     .RspPass(FifoPass),
 263:     .ReqDepth(FifoDepth),
 264:     .RspDepth(FifoDepth)
 265:   ) fifo_d (
 266:     .clk_i,
 267:     .rst_ni,
 268:     .tl_h_i      (tl_d_ibex2fifo),
 269:     .tl_h_o      (tl_d_fifo2ibex),
 270:     .tl_d_o      (tl_d_o),
 271:     .tl_d_i      (tl_d_i),
 272:     .spare_req_i (1'b0),
 273:     .spare_req_o (),
 274:     .spare_rsp_i (1'b0),
 275:     .spare_rsp_o ());
 276: 
 277: 
 278: `ifdef RVFI
 279:   ibex_tracer ibex_tracer_i (
 280:     .clk_i,
 281:     .rst_ni,
 282: 
 283:     .hart_id_i,
 284: 
 285:     .rvfi_valid,
 286:     .rvfi_order,
 287:     .rvfi_insn,
 288:     .rvfi_trap,
 289:     .rvfi_halt,
 290:     .rvfi_intr,
 291:     .rvfi_mode,
 292:     .rvfi_rs1_addr,
 293:     .rvfi_rs2_addr,
 294:     .rvfi_rs1_rdata,
 295:     .rvfi_rs2_rdata,
 296:     .rvfi_rd_addr,
 297:     .rvfi_rd_wdata,
 298:     .rvfi_pc_rdata,
 299:     .rvfi_pc_wdata,
 300:     .rvfi_mem_addr,
 301:     .rvfi_mem_rmask,
 302:     .rvfi_mem_wmask,
 303:     .rvfi_mem_rdata,
 304:     .rvfi_mem_wdata
 305:   );
 306: `endif
 307: 
 308: 
 309: endmodule
 310: