blob: bca6b278ada0aa1e40ce7e4bd178ccb28a15a5a9 [file] [log] [blame]
// Copyright 2017 Embecosm Limited <www.embecosm.com>
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
// 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.
// Top level wrapper for a RI5CY testbench
// Contributor: Robert Balas <balasr@iis.ee.ethz.ch>
// Jeremy Bennett <jeremy.bennett@embecosm.com>
module tb_top #(
parameter int unsigned INSTR_RDATA_WIDTH = 32,
parameter int unsigned RAM_ADDR_WIDTH = 22,
parameter logic [31:0] BOOT_ADDR = 'h1A00_0180,
parameter bit JTAG_BOOT = 1,
parameter int unsigned OPENOCD_PORT = 9999
);
// comment to record execution trace
//`define TRACE_EXECUTION
const time CLK_PHASE_HI = 5ns;
const time CLK_PHASE_LO = 5ns;
const time CLK_PERIOD = CLK_PHASE_HI + CLK_PHASE_LO;
const time STIM_APPLICATION_DEL = CLK_PERIOD * 0.1;
const time RESP_ACQUISITION_DEL = CLK_PERIOD * 0.9;
const time RESET_DEL = STIM_APPLICATION_DEL;
const int RESET_WAIT_CYCLES = 4;
// clock and reset for tb
logic clk = 'b1;
logic rst_n = 'b0;
// testbench result
logic tests_passed;
logic tests_failed;
// signals for ri5cy
logic fetch_enable;
// make the core start fetching instruction immediately
assign fetch_enable = '1;
// allow vcd dump
initial begin: dump_vars
if ($test$plusargs("vcd")) begin
$dumpfile("riscy_tb.vcd");
$dumpvars(0, tb_top);
end
`ifdef QUESTA
if ($test$plusargs("wlfdump")) begin
$wlfdumpvars(0, tb_top);
end
`endif
end
// we either load the provided firmware or execute a small test program that
// doesn't do more than an infinite loop with some I/O
initial begin: load_prog
automatic logic [1023:0] firmware;
automatic int prog_size = 6;
if($value$plusargs("firmware=%s", firmware)) begin
if($test$plusargs("verbose"))
$display("[TESTBENCH] %t: loading firmware %0s ...",
$time, firmware);
$readmemh(firmware, tb_test_env_i.mm_ram_i.dp_ram_i.mem);
end else begin
$display("No firmware specified");
end
end
// clock generation
initial begin: clock_gen
forever begin
#CLK_PHASE_HI clk = 1'b0;
#CLK_PHASE_LO clk = 1'b1;
end
end: clock_gen
// reset generation
initial begin: reset_gen
rst_n = 1'b0;
// wait a few cycles
repeat (RESET_WAIT_CYCLES) begin
@(posedge clk); //TODO: was posedge, see below
end
// start running
#RESET_DEL rst_n = 1'b1;
if($test$plusargs("verbose"))
$display("reset deasserted", $time);
end: reset_gen
// set timing format
initial begin: timing_format
$timeformat(-9, 0, "ns", 9);
end: timing_format
// check if we succeded
always_ff @(posedge clk, negedge rst_n) begin
if (tests_passed) begin
$display("Exit Success");
$finish;
end
if (tests_failed) begin
$display("Exit FAILURE");
$finish;
end
end
// wrapper for riscv, the memory system and stdout peripheral
tb_test_env #(
.INSTR_RDATA_WIDTH (INSTR_RDATA_WIDTH),
.RAM_ADDR_WIDTH (RAM_ADDR_WIDTH),
.BOOT_ADDR (BOOT_ADDR),
.JTAG_BOOT (JTAG_BOOT),
.OPENOCD_PORT (OPENOCD_PORT)
) tb_test_env_i(
.clk_i ( clk ),
.rst_ni ( rst_n ),
.fetch_enable_i ( fetch_enable ),
.tests_passed_o ( tests_passed ),
.tests_failed_o ( tests_failed )
);
endmodule // tb_top