| // Copyright 2020 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. |
| |
| // Wrapper for a RI5CY testbench, containing RI5CY, Memory and stdout peripheral |
| // Contributor: Robert Balas <balasr@iis.ee.ethz.ch> |
| |
| module tb_test_env #( |
| parameter int unsigned INSTR_RDATA_WIDTH = 32, |
| parameter int unsigned RAM_ADDR_WIDTH = 20, |
| parameter logic [31:0] BOOT_ADDR = 'h80, |
| parameter bit JTAG_BOOT = 1, |
| parameter int unsigned OPENOCD_PORT = 0, |
| parameter bit A_EXTENSION = 0 |
| ) ( |
| input logic clk_i, |
| input logic rst_ni, |
| |
| // currently we are not making use of those signals |
| input logic fetch_enable_i, |
| output logic tests_passed_o, |
| output logic tests_failed_o); |
| |
| // defs from pulpissimo |
| // localparam CLUSTER_ID = 6'd31; |
| // localparam CORE_ID = 4'd0; |
| // test defs |
| localparam CLUSTER_ID = 6'd0; |
| localparam CORE_ID = 4'd0; |
| |
| localparam CORE_MHARTID = {21'b0, CLUSTER_ID, 1'b0, CORE_ID}; |
| localparam NrHarts = 1; |
| localparam logic [NrHarts-1:0] SELECTABLE_HARTS = 1 << CORE_MHARTID; |
| localparam HARTINFO = {8'h0, 4'h2, 3'b0, 1'b1, dm::DataCount, dm::DataAddr}; |
| |
| // signals connecting core to memory |
| logic instr_req; |
| logic instr_gnt; |
| logic instr_rvalid; |
| logic [31:0] instr_addr; |
| logic [INSTR_RDATA_WIDTH-1:0] instr_rdata; |
| |
| logic data_req; |
| logic data_gnt; |
| logic data_rvalid; |
| logic [31:0] data_addr; |
| logic data_we; |
| logic [3:0] data_be; |
| logic [31:0] data_rdata; |
| logic [31:0] data_wdata; |
| |
| // jtag openocd bridge signals |
| logic sim_jtag_tck; |
| logic sim_jtag_tms; |
| logic sim_jtag_tdi; |
| logic sim_jtag_trstn; |
| logic sim_jtag_tdo; |
| logic [31:0] sim_jtag_exit; |
| logic sim_jtag_enable; |
| |
| // signals for debug unit |
| logic debug_req_ready; |
| dm::dmi_resp_t debug_resp; |
| logic jtag_req_valid; |
| dm::dmi_req_t jtag_dmi_req; |
| logic jtag_resp_ready; |
| logic jtag_resp_valid; |
| logic [NrHarts-1:0] dm_debug_req; |
| logic ndmreset, ndmreset_n; |
| |
| // debug unit slave interface |
| logic dm_grant; |
| logic dm_rvalid; |
| logic dm_req; |
| logic dm_we; |
| logic [31:0] dm_addr; |
| logic [31:0] dm_wdata; |
| logic [31:0] dm_rdata; |
| logic [3:0] dm_be; |
| |
| // debug unit master interface (system bus access) |
| logic sb_req; |
| logic [31:0] sb_addr; |
| logic sb_we; |
| logic [31:0] sb_wdata; |
| logic [3:0] sb_be; |
| logic sb_gnt; |
| logic sb_rvalid; |
| logic [31:0] sb_rdata; |
| |
| // irq signals (not used) |
| logic irq; |
| logic [0:4] irq_id_in; |
| logic irq_ack; |
| logic [0:4] irq_id_out; |
| |
| // make jtag bridge work |
| assign sim_jtag_enable = JTAG_BOOT; |
| |
| // instantiate the core |
| cv32e40p_core #( |
| .PULP_XPULP ( 0 ), |
| .PULP_CLUSTER ( 0 ), |
| .FPU ( 0 ), |
| .PULP_ZFINX ( 0 ), |
| .NUM_MHPMCOUNTERS ( 1 ) |
| ) riscv_core_i ( |
| .clk_i ( clk_i ), |
| .rst_ni ( ndmreset_n ), |
| |
| .pulp_clock_en_i ( '1 ), |
| .scan_cg_en_i ( '0 ), |
| |
| .boot_addr_i ( BOOT_ADDR ), |
| .mtvec_addr_i ( 32'h00000000 ), |
| .dm_halt_addr_i ( 32'h1A110800 ), |
| .hart_id_i ( CORE_MHARTID ), |
| .dm_exception_addr_i ( 32'h00000000 ), |
| |
| .instr_addr_o ( instr_addr ), |
| .instr_req_o ( instr_req ), |
| .instr_rdata_i ( instr_rdata ), |
| .instr_gnt_i ( instr_gnt ), |
| .instr_rvalid_i ( instr_rvalid ), |
| |
| .data_addr_o ( data_addr ), |
| .data_wdata_o ( data_wdata ), |
| .data_we_o ( data_we ), |
| .data_req_o ( data_req ), |
| .data_be_o ( data_be ), |
| .data_rdata_i ( data_rdata ), |
| .data_gnt_i ( data_gnt ), |
| .data_rvalid_i ( data_rvalid ), |
| |
| .apu_master_req_o ( ), |
| .apu_master_ready_o ( ), |
| .apu_master_gnt_i ( ), |
| .apu_master_operands_o ( ), |
| .apu_master_op_o ( ), |
| .apu_master_type_o ( ), |
| .apu_master_flags_o ( ), |
| .apu_master_valid_i ( ), |
| .apu_master_result_i ( ), |
| .apu_master_flags_i ( ), |
| |
| .irq_i ( 32'b0 ), |
| .irq_ack_o ( irq_ack ), |
| .irq_id_o ( irq_id_out ), |
| |
| .debug_req_i ( dm_debug_req[CORE_MHARTID] ), |
| |
| .fetch_enable_i ( fetch_enable_i ), |
| .core_sleep_o ( core_sleep_o ) |
| ); |
| |
| // this handles read to RAM and memory mapped pseudo peripherals |
| mm_ram #( |
| .RAM_ADDR_WIDTH (RAM_ADDR_WIDTH), |
| .INSTR_RDATA_WIDTH (INSTR_RDATA_WIDTH), |
| .JTAG_BOOT(JTAG_BOOT) |
| ) mm_ram_i ( |
| .clk_i ( clk_i ), |
| .rst_ni ( ndmreset_n ), |
| |
| // core instruction access |
| .instr_req_i ( instr_req ), |
| .instr_addr_i ( instr_addr ), |
| .instr_rdata_o ( instr_rdata ), |
| .instr_rvalid_o ( instr_rvalid ), |
| .instr_gnt_o ( instr_gnt ), |
| |
| // core data access |
| .data_req_i ( data_req ), |
| .data_addr_i ( data_addr ), |
| .data_we_i ( data_we ), |
| .data_be_i ( data_be ), |
| .data_wdata_i ( data_wdata ), |
| .data_rdata_o ( data_rdata ), |
| .data_rvalid_o ( data_rvalid ), |
| .data_gnt_o ( data_gnt ), |
| |
| // system bus access from debug unit |
| .sb_req_i ( sb_req ), |
| .sb_addr_i ( sb_addr ), |
| .sb_we_i ( sb_we ), |
| .sb_be_i ( sb_be ), |
| .sb_wdata_i ( sb_wdata ), |
| .sb_rdata_o ( sb_rdata ), |
| .sb_rvalid_o ( sb_rvalid ), |
| .sb_gnt_o ( sb_gnt ), |
| |
| // access to debug unit |
| .dm_req_o ( dm_req ), |
| .dm_addr_o ( dm_addr ), |
| .dm_we_o ( dm_we ), |
| .dm_be_o ( dm_be ), |
| .dm_wdata_o ( dm_wdata ), |
| .dm_rdata_i ( dm_rdata ), |
| .dm_rvalid_i ( dm_rvalid ), |
| .dm_gnt_i ( dm_gnt ), |
| |
| |
| .irq_id_i ( irq_id_out ), |
| .irq_ack_i ( irq_ack ), |
| .irq_id_o ( irq_id_in ), |
| .irq_o ( irq ), |
| |
| .tests_passed_o ( tests_passed_o ), |
| .tests_failed_o ( tests_failed_o ) |
| ); |
| |
| // debug subsystem |
| dmi_jtag #( |
| .IdcodeValue ( 32'h249511C3 ) |
| ) i_dmi_jtag ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| .testmode_i ( 1'b0 ), |
| .dmi_req_o ( jtag_dmi_req ), |
| .dmi_req_valid_o ( jtag_req_valid ), |
| .dmi_req_ready_i ( debug_req_ready ), |
| .dmi_resp_i ( debug_resp ), |
| .dmi_resp_ready_o ( jtag_resp_ready ), |
| .dmi_resp_valid_i ( jtag_resp_valid ), |
| .dmi_rst_no ( ), // not connected |
| .tck_i ( sim_jtag_tck ), |
| .tms_i ( sim_jtag_tms ), |
| .trst_ni ( sim_jtag_trstn ), |
| .td_i ( sim_jtag_tdi ), |
| .td_o ( sim_jtag_tdo ), |
| .tdo_oe_o ( ) |
| ); |
| |
| dm_top #( |
| .NrHarts ( NrHarts ), |
| .BusWidth ( 32 ), |
| .SelectableHarts ( SELECTABLE_HARTS ) |
| ) i_dm_top ( |
| |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni ), |
| .testmode_i ( 1'b0 ), |
| .ndmreset_o ( ndmreset ), |
| .dmactive_o ( ), // active debug session TODO |
| .debug_req_o ( dm_debug_req ), |
| .unavailable_i ( ~SELECTABLE_HARTS ), |
| .hartinfo_i ( HARTINFO ), |
| |
| .slave_req_i ( dm_req ), |
| .slave_we_i ( dm_we ), |
| .slave_addr_i ( dm_addr ), |
| .slave_be_i ( dm_be ), |
| .slave_wdata_i ( dm_wdata ), |
| .slave_rdata_o ( dm_rdata ), |
| |
| .master_req_o ( sb_req ), |
| .master_add_o ( sb_addr ), |
| .master_we_o ( sb_we ), |
| .master_wdata_o ( sb_wdata ), |
| .master_be_o ( sb_be ), |
| .master_gnt_i ( sb_gnt ), |
| .master_r_valid_i ( sb_rvalid ), |
| .master_r_err_i ( 1'b0 ), |
| .master_r_other_err_i ( 1'b0 ), |
| .master_r_rdata_i ( sb_rdata ), |
| |
| .dmi_rst_ni ( rst_ni ), |
| .dmi_req_valid_i ( jtag_req_valid ), |
| .dmi_req_ready_o ( debug_req_ready ), |
| .dmi_req_i ( jtag_dmi_req ), |
| .dmi_resp_valid_o ( jtag_resp_valid ), |
| .dmi_resp_ready_i ( jtag_resp_ready ), |
| .dmi_resp_o ( debug_resp ) |
| ); |
| |
| /////////////////////////////////////////////////////// |
| // Bind RTL assertions to Debug Module |
| /////////////////////////////////////////////////////// |
| |
| bind dm_top |
| dm_top_sva |
| #( |
| .NrHarts ( NrHarts ), |
| .BusWidth ( BusWidth ), |
| .SelectableHarts ( SelectableHarts )) |
| i_dm_top_sva (.*); |
| |
| bind dm_csrs |
| dm_csrs_sva |
| #( |
| .NrHarts ( NrHarts ), |
| .BusWidth ( BusWidth ), |
| .SelectableHarts ( SelectableHarts )) |
| i_dm_csrs_sva (.*); |
| |
| bind dm_sba |
| dm_sba_sva |
| #( |
| .BusWidth ( BusWidth ), |
| .ReadByteEnable ( ReadByteEnable )) |
| i_dm_sba_sva (.*); |
| |
| |
| // grant in the same cycle |
| assign dm_gnt = dm_req; |
| // valid read/write in the next cycle |
| always_ff @(posedge clk_i or negedge rst_ni) begin : dm_valid_handler |
| if(~rst_ni) begin |
| dm_rvalid <= '0; |
| end else begin |
| dm_rvalid <= dm_gnt; |
| end |
| end |
| |
| // reset handling with ndmreset |
| rstgen i_rstgen_main ( |
| .clk_i ( clk_i ), |
| .rst_ni ( rst_ni & (~ndmreset) ), |
| .test_mode_i ( '0 ), |
| .rst_no ( ndmreset_n ), |
| .init_no ( ) // keep open |
| ); |
| |
| // jtag calls from dpi |
| SimJTAG #( |
| .TICK_DELAY (1), |
| .PORT(OPENOCD_PORT) |
| ) i_sim_jtag ( |
| .clock ( clk_i ), |
| .reset ( ~rst_ni ), |
| .enable ( sim_jtag_enable ), |
| .init_done ( rst_ni ), |
| .jtag_TCK ( sim_jtag_tck ), |
| .jtag_TMS ( sim_jtag_tms ), |
| .jtag_TDI ( sim_jtag_tdi ), |
| .jtag_TRSTn ( sim_jtag_trstn ), |
| .jtag_TDO_data ( sim_jtag_tdo ), |
| .jtag_TDO_driven ( 1'b1 ), |
| .exit ( sim_jtag_exit ) |
| ); |
| |
| always_comb begin : jtag_exit_handler |
| if (sim_jtag_exit) |
| $finish(2); // print stats too |
| end |
| |
| endmodule // tb_test_env |