mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 13:47:13 -04:00
✅ Add fetch fifo testbench stub
This commit is contained in:
parent
5fe47f0786
commit
851faa7851
10 changed files with 280 additions and 106 deletions
2
Makefile
2
Makefile
|
@ -8,7 +8,7 @@ library = work
|
|||
top_level = core_tb
|
||||
test_top_level = core_tb
|
||||
# test targets
|
||||
tests = alu scoreboard fifo mem_arbiter store_queue lsu core
|
||||
tests = alu scoreboard fifo mem_arbiter store_queue lsu core fetch_fifo
|
||||
# UVM agents
|
||||
agents = include/ariane_pkg.svh $(wildcard tb/agents/*/*.sv)
|
||||
# path to interfaces
|
||||
|
|
|
@ -66,29 +66,31 @@ module branch_engine (
|
|||
resolved_branch_o.is_taken = 1'b0;
|
||||
resolved_branch_o.valid = valid_i;
|
||||
resolved_branch_o.is_mispredict = 1'b0;
|
||||
resolved_branch_o.is_lower_16 = 1'b0;
|
||||
// calculate next PC, depending on whether the instruction is compressed or not this may be different
|
||||
next_pc = pc_i + ((is_compressed_instr_i) ? 64'h2 : 64'h4);
|
||||
// calculate target address simple 64 bit addition
|
||||
target_address = $unsigned($signed(operand_c_i) + $signed(imm_i));
|
||||
// save PC - we need this to get the target row in the branch target buffer
|
||||
// we play this trick with the branch instruction which wraps a byte boundary:
|
||||
// |---------- Place the prediction on this PC
|
||||
// \/
|
||||
// ____________________________________________________
|
||||
// |branch [15:0] | branch[31:16] | compressed 1[15:0] |
|
||||
// |____________________________________________________
|
||||
// This will relief the prefetcher to re-fetch partially fetched unaligned branch instructions e.g.:
|
||||
// we don't have a back arch between prefetcher and decoder/instruction FIFO.
|
||||
resolved_branch_o.pc = (is_compressed_instr_i || pc_i[1] == 1'b0) ? pc_i : ({pc_i[63:2], 2'b0} + 64'h4);
|
||||
// save if the branch instruction was in the lower 16 bit of the instruction word
|
||||
// the first case is a compressed instruction which is in slot 0
|
||||
// the other case is a misaligned uncompressed instruction which we only predict in the next cycle (see notes above)
|
||||
resolved_branch_o.is_lower_16 = (is_compressed_instr_i && pc_i[1] == 1'b0) || (!is_compressed_instr_i && pc_i[1] == 1'b1);
|
||||
// write target address which goes to pc gen
|
||||
resolved_branch_o.target_address = (comparison_result) ? target_address : next_pc;
|
||||
resolved_branch_o.is_taken = comparison_result;
|
||||
// we've detected a branch in ID with the following parameters
|
||||
|
||||
if (valid_i) begin
|
||||
// save PC - we need this to get the target row in the branch target buffer
|
||||
// we play this trick with the branch instruction which wraps a byte boundary:
|
||||
// |---------- Place the prediction on this PC
|
||||
// \/
|
||||
// ____________________________________________________
|
||||
// |branch [15:0] | branch[31:16] | compressed 1[15:0] |
|
||||
// |____________________________________________________
|
||||
// This will relief the prefetcher to re-fetch partially fetched unaligned branch instructions e.g.:
|
||||
// we don't have a back arch between prefetcher and decoder/instruction FIFO.
|
||||
resolved_branch_o.pc = (is_compressed_instr_i || pc_i[1] == 1'b0) ? pc_i : ({pc_i[63:2], 2'b0} + 64'h4);
|
||||
// save if the branch instruction was in the lower 16 bit of the instruction word
|
||||
// the first case is a compressed instruction which is in slot 0
|
||||
// the other case is a misaligned uncompressed instruction which we only predict in the next cycle (see notes above)
|
||||
resolved_branch_o.is_lower_16 = (is_compressed_instr_i && pc_i[1] == 1'b0) || (!is_compressed_instr_i && pc_i[1] == 1'b1);
|
||||
// write target address which goes to pc gen
|
||||
resolved_branch_o.target_address = (comparison_result) ? target_address : next_pc;
|
||||
resolved_branch_o.is_taken = comparison_result;
|
||||
// we've detected a branch in ID with the following parameters
|
||||
// we mis-predicted e.g.: the predicted address is unequal to the actual address
|
||||
if (target_address[0] == 1'b0) begin
|
||||
// TODO in case of branch which is not taken it is not necessary to check for the address
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import ariane_pkg::*;
|
||||
|
||||
module btb #(
|
||||
parameter int NR_ENTRIES = 64,
|
||||
parameter int NR_ENTRIES = 1024,
|
||||
parameter int BITS_SATURATION_COUNTER = 2
|
||||
)
|
||||
(
|
||||
|
|
|
@ -1,36 +1,30 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna //
|
||||
// All rights reserved. //
|
||||
// //
|
||||
// This code is under development and not yet released to the public. //
|
||||
// Until it is released, the code is under the copyright of ETH Zurich //
|
||||
// and the University of Bologna, and may contain unpublished work. //
|
||||
// Any reuse/redistribution should only be under explicit permission. //
|
||||
// //
|
||||
// Bug fixes and contributions will eventually be released under the //
|
||||
// SolderPad open hardware license and under the copyright of ETH Zurich //
|
||||
// and the University of Bologna. //
|
||||
// //
|
||||
// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Design Name: Fetch Fifo for 32 bit memory interface //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Fetch fifo //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 14.05.2017
|
||||
// Description: Dual Port fetch FIFO with instruction aligner and support for compressed instructions
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
|
||||
import ariane_pkg::*;
|
||||
|
||||
// input port: send address one cycle before the data
|
||||
// clear_i clears the FIFO for the following cycle.
|
||||
module fetch_fifo
|
||||
(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
// control signals
|
||||
input logic clear_i, // clears the contents of the fifo
|
||||
// input port
|
||||
input logic flush_i, // clears the contents of the FIFO -> quasi reset
|
||||
// branch prediction at in_addr_i address, as this is an address and not PC it can be the case
|
||||
// that we have two compressed instruction (or one compressed instruction and one unaligned instruction) so we need
|
||||
// keep two prediction inputs: [c1|c0] <- prediction for c1 and c0
|
||||
|
@ -68,7 +62,7 @@ module fetch_fifo
|
|||
logic [$clog2(DEPTH)-1:0] status_cnt_n, status_cnt_q; // this integer will be truncated by the synthesis tool
|
||||
|
||||
// status signals
|
||||
logic full, empty, one_left;
|
||||
logic full, empty;
|
||||
// the last instruction was unaligned
|
||||
logic unaligned_n, unaligned_q;
|
||||
// save the unaligned part of the instruction to this ff
|
||||
|
@ -79,8 +73,7 @@ module fetch_fifo
|
|||
// we always need two empty places
|
||||
// as it could happen that we get two compressed instructions/cycle
|
||||
/* verilator lint_off WIDTH */
|
||||
assign full = (status_cnt_q > DEPTH - 2);
|
||||
assign one_left = (status_cnt_q == DEPTH - 1); // two spaces are left
|
||||
assign full = (status_cnt_q >= DEPTH - 2);
|
||||
assign empty = (status_cnt_q == 0);
|
||||
/* verilator lint_on WIDTH */
|
||||
// the output is valid if we are either empty or just got a valid
|
||||
|
@ -106,7 +99,7 @@ module fetch_fifo
|
|||
branch_predict_n = branch_predict_i;
|
||||
end
|
||||
// flush the input registers
|
||||
if (clear_i) begin
|
||||
if (flush_i) begin
|
||||
in_valid_n = 1'b0;
|
||||
end
|
||||
end
|
||||
|
@ -251,17 +244,17 @@ module fetch_fifo
|
|||
out_rdata_o = {in_rdata_q[15:0], unaligned_instr_q};
|
||||
end
|
||||
// there is currently no valid instruction in the pipeline register push this instruction
|
||||
if (out_ready_i || !pipelein_register_valid_q) begin
|
||||
pipelein_register_valid_n = 1'b1;
|
||||
read_pointer_n = read_pointer_q + 1;
|
||||
status_cnt--;
|
||||
end
|
||||
// if (out_ready_i) begin
|
||||
// pipelein_register_valid_n = 1'b1;
|
||||
// read_pointer_n = read_pointer_q + 1;
|
||||
// status_cnt--;
|
||||
// end
|
||||
// regular read but do not issue if we are already empty
|
||||
// this can happen since we have an output latch in the IF stage and the ID stage will only know a cycle
|
||||
// later that we do not have any valid instructions anymore
|
||||
end
|
||||
|
||||
if (out_ready_i && !empty) begin
|
||||
if (out_ready_i) begin
|
||||
read_pointer_n = read_pointer_q + 1;
|
||||
status_cnt--;
|
||||
end
|
||||
|
@ -273,39 +266,55 @@ module fetch_fifo
|
|||
write_pointer_n = write_pointer;
|
||||
status_cnt_n = status_cnt;
|
||||
|
||||
if (clear_i)
|
||||
status_cnt_n = '0;
|
||||
if (flush_i) begin
|
||||
status_cnt_n = '0;
|
||||
write_pointer_n = 'b0;
|
||||
read_pointer_n = 'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
status_cnt_q <= '{default: 0};
|
||||
mem_q <= '{default: 0};
|
||||
read_pointer_q <= '{default: 0};
|
||||
write_pointer_q <= '{default: 0};
|
||||
unaligned_q <= 1'b0;
|
||||
unaligned_instr_q <= 16'b0;
|
||||
unaligned_address_q <= 64'b0;
|
||||
status_cnt_q <= '{default: 0};
|
||||
mem_q <= '{default: 0};
|
||||
read_pointer_q <= '{default: 0};
|
||||
write_pointer_q <= '{default: 0};
|
||||
unaligned_q <= 1'b0;
|
||||
unaligned_instr_q <= 16'b0;
|
||||
unaligned_address_q <= 64'b0;
|
||||
// input registers
|
||||
in_addr_q <= 64'b0;
|
||||
in_rdata_q <= 32'b0;
|
||||
in_valid_q <= 1'b0;
|
||||
branch_predict_q <= '{default: 0};
|
||||
in_addr_q <= 64'b0;
|
||||
in_rdata_q <= 32'b0;
|
||||
in_valid_q <= 1'b0;
|
||||
branch_predict_q <= '{default: 0};
|
||||
pipelein_register_valid_q <= 1'b0;
|
||||
end else begin
|
||||
status_cnt_q <= status_cnt_n;
|
||||
mem_q <= mem_n;
|
||||
read_pointer_q <= read_pointer_n;
|
||||
write_pointer_q <= write_pointer_n;
|
||||
unaligned_q <= unaligned_n;
|
||||
unaligned_instr_q <= unaligned_instr_n;
|
||||
unaligned_address_q <= unaligned_address_n;
|
||||
status_cnt_q <= status_cnt_n;
|
||||
mem_q <= mem_n;
|
||||
read_pointer_q <= read_pointer_n;
|
||||
write_pointer_q <= write_pointer_n;
|
||||
unaligned_q <= unaligned_n;
|
||||
unaligned_instr_q <= unaligned_instr_n;
|
||||
unaligned_address_q <= unaligned_address_n;
|
||||
// input registers
|
||||
in_addr_q <= in_addr_n;
|
||||
in_rdata_q <= in_rdata_n;
|
||||
in_valid_q <= in_valid_n;
|
||||
branch_predict_q <= branch_predict_n;
|
||||
in_addr_q <= in_addr_n;
|
||||
in_rdata_q <= in_rdata_n;
|
||||
in_valid_q <= in_valid_n;
|
||||
branch_predict_q <= branch_predict_n;
|
||||
pipelein_register_valid_q <= pipelein_register_valid_n;
|
||||
end
|
||||
end
|
||||
|
||||
//-------------
|
||||
// Assertions
|
||||
//-------------
|
||||
`ifndef SYNTHESIS
|
||||
`ifndef VERILATOR
|
||||
// since this is a dual port queue the status count of the queue should never change more than two
|
||||
assert property (@(posedge clk_i) ((status_cnt_n - status_cnt_q) < 3 || (status_cnt_n - status_cnt_q) > 3)) else $error("FIFO underflowed or overflowed");
|
||||
// assert property (
|
||||
// @(posedge clk_i) (instr_gnt_i) |-> (instr_req_o) )
|
||||
// else $warning("There was a grant without a request");
|
||||
`endif
|
||||
`endif
|
||||
endmodule
|
|
@ -66,12 +66,12 @@ module if_stage (
|
|||
// ---------------------
|
||||
// IF <-> ID Registers
|
||||
// ---------------------
|
||||
logic [63:0] pc_n, pc_q;
|
||||
logic instr_valid_n, instr_valid_q;
|
||||
logic [31:0] instr_rdata_n, instr_rdata_q;
|
||||
logic instr_is_compressed_n, instr_is_compressed_q;
|
||||
logic [63:0] pc_n, pc_q;
|
||||
logic instr_valid_n, instr_valid_q;
|
||||
logic [31:0] instr_rdata_n, instr_rdata_q;
|
||||
logic instr_is_compressed_n, instr_is_compressed_q;
|
||||
// branch predict registers
|
||||
logic branch_predict_n, branch_predict_q;
|
||||
branchpredict_sbe branch_predict_n, branch_predict_q;
|
||||
|
||||
// compressed instruction decoding, or more precisely compressed instruction expander
|
||||
// since it does not matter where we decompress instructions, we do it here to ease timing closure
|
||||
|
@ -116,7 +116,7 @@ module if_stage (
|
|||
if (flush_i) begin
|
||||
instr_valid_n = 1'b0;
|
||||
end
|
||||
// exception forwarding in here
|
||||
// TODO: exception forwarding in here
|
||||
end
|
||||
|
||||
// --------------------------------------------------------------
|
||||
|
@ -125,7 +125,7 @@ module if_stage (
|
|||
always_ff @(posedge clk_i, negedge rst_ni) begin : IF_ID_PIPE_REGISTERS
|
||||
if (~rst_ni) begin
|
||||
ex_o <= '{default: 0};
|
||||
branch_predict_q <= '{default: 0};
|
||||
branch_predict_q <= '0;
|
||||
pc_q <= 64'b0;
|
||||
instr_valid_q <= 1'b0;
|
||||
instr_rdata_q <= 32'b0;
|
||||
|
|
|
@ -42,10 +42,10 @@ module pcgen (
|
|||
logic [63:0] npc_n, npc_q;
|
||||
branchpredict_sbe branch_predict_btb;
|
||||
|
||||
assign pc_if_o = npc_q;
|
||||
assign fetch_address_o = npc_q;
|
||||
|
||||
btb #(
|
||||
.NR_ENTRIES(64),
|
||||
.NR_ENTRIES(1024),
|
||||
.BITS_SATURATION_COUNTER(2)
|
||||
)
|
||||
btb_i
|
||||
|
|
|
@ -64,18 +64,13 @@ module prefetch_buffer
|
|||
//---------------------------------
|
||||
// we are busy if we are either waiting for a grant
|
||||
// or if the fifo is full
|
||||
assign busy_o = (CS inside {WAIT_GNT, WAIT_ABORTED}) || !fifo_ready;
|
||||
assign busy_o = (CS inside {WAIT_GNT, WAIT_ABORTED} && !instr_req_o) || !fifo_ready;
|
||||
|
||||
//---------------------------------
|
||||
// Fetch FIFO
|
||||
// consumes addresses and rdata
|
||||
//---------------------------------
|
||||
fetch_fifo fifo_i (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n_i ),
|
||||
|
||||
.clear_i ( flush_i ),
|
||||
|
||||
.branch_predict_i ( branchpredict_q ),
|
||||
.in_addr_i ( instr_addr_q ),
|
||||
.in_rdata_i ( instr_rdata_i ),
|
||||
|
@ -86,7 +81,8 @@ module prefetch_buffer
|
|||
.out_valid_o ( valid_o ),
|
||||
.out_ready_i ( ready_i ),
|
||||
.out_rdata_o ( rdata_o ),
|
||||
.out_addr_o ( addr_o )
|
||||
.out_addr_o ( addr_o ),
|
||||
.*
|
||||
);
|
||||
|
||||
//--------------------------------------------------
|
||||
|
@ -113,7 +109,11 @@ module prefetch_buffer
|
|||
|
||||
|
||||
if(instr_gnt_i) //~> granted request
|
||||
NS = WAIT_RVALID;
|
||||
// we have one outstanding rvalid: wait for it
|
||||
if (flush_i)
|
||||
NS = WAIT_ABORTED;
|
||||
else
|
||||
NS = WAIT_RVALID;
|
||||
else begin //~> got a request but no grant
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
|
@ -126,7 +126,11 @@ module prefetch_buffer
|
|||
instr_req_o = 1'b1;
|
||||
|
||||
if(instr_gnt_i)
|
||||
NS = WAIT_RVALID;
|
||||
// we have one outstanding rvalid: wait for it
|
||||
if (flush_i)
|
||||
NS = WAIT_ABORTED;
|
||||
else
|
||||
NS = WAIT_RVALID;
|
||||
else
|
||||
NS = WAIT_GNT;
|
||||
end // case: WAIT_GNT
|
||||
|
@ -137,15 +141,18 @@ module prefetch_buffer
|
|||
|
||||
if (fifo_ready) begin
|
||||
// prepare for next request
|
||||
|
||||
if (fifo_ready && fetch_valid_i) begin
|
||||
instr_req_o = 1'b1;
|
||||
// if we are receiving a data item during a flush ignore it
|
||||
fifo_valid = 1'b1;
|
||||
addr_valid = 1'b1;
|
||||
|
||||
|
||||
if (instr_gnt_i) begin
|
||||
NS = WAIT_RVALID;
|
||||
// we have one outstanding rvalid: wait for it
|
||||
if (flush_i)
|
||||
NS = WAIT_ABORTED;
|
||||
else
|
||||
NS = WAIT_RVALID;
|
||||
end else begin
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
|
@ -153,12 +160,13 @@ module prefetch_buffer
|
|||
// we are requested to abort our current request
|
||||
// we didn't get an rvalid yet, so wait for it
|
||||
if (flush_i) begin
|
||||
NS = WAIT_ABORTED;
|
||||
NS = WAIT_ABORTED;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
// just wait for rvalid and go back to IDLE, no new request
|
||||
if (instr_rvalid_i) begin
|
||||
// if we are receiving a data item during a flush ignore it
|
||||
fifo_valid = 1'b1;
|
||||
NS = IDLE;
|
||||
end
|
||||
|
@ -169,33 +177,37 @@ module prefetch_buffer
|
|||
// there was no new request sent yet
|
||||
// we assume that req_i is set to high
|
||||
WAIT_ABORTED: begin
|
||||
instr_addr_o = instr_addr_q;
|
||||
instr_addr_o = fetch_address_i;
|
||||
|
||||
if (instr_rvalid_i) begin
|
||||
instr_req_o = 1'b1;
|
||||
// no need to send address, already done in WAIT_RVALID
|
||||
|
||||
if (instr_gnt_i) begin
|
||||
NS = WAIT_RVALID;
|
||||
// we have one outstanding rvalid
|
||||
if (flush_i)
|
||||
NS = WAIT_ABORTED;
|
||||
else
|
||||
NS = WAIT_RVALID;
|
||||
end else begin
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
default: begin
|
||||
NS = IDLE;
|
||||
instr_req_o = 1'b0;
|
||||
end
|
||||
endcase
|
||||
|
||||
end
|
||||
|
||||
//-------------
|
||||
// Registers
|
||||
//-------------
|
||||
|
||||
always_ff @(posedge clk_i, negedge rst_n_i)
|
||||
always_ff @(posedge clk_i, negedge rst_ni)
|
||||
begin
|
||||
if (~rst_ni) begin
|
||||
CS <= IDLE;
|
||||
|
|
53
tb/agents/fetch_fifo_if/fetch_fifo_if.sv
Executable file
53
tb/agents/fetch_fifo_if/fetch_fifo_if.sv
Executable file
|
@ -0,0 +1,53 @@
|
|||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 14.5.2017
|
||||
// Description: Fetch FIFO interface
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
`ifndef FETCH_FIFO_IF_SV
|
||||
`define FETCH_FIFO_IF_SV
|
||||
import ariane_pkg::*;
|
||||
|
||||
interface fetch_fifo_if #(
|
||||
parameter type dtype = logic[7:0]
|
||||
)(
|
||||
input clk
|
||||
);
|
||||
|
||||
wire flush;
|
||||
wire [$bits(branchpredict_sbe)-1:0] in_branch_predict;
|
||||
wire [63:0] in_addr;
|
||||
wire [31:0] in_rdata;
|
||||
wire in_valid;
|
||||
wire in_ready;
|
||||
wire [$bits(branchpredict_sbe)-1:0] out_branch_predict;
|
||||
wire [63:0] out_addr;
|
||||
wire [31:0] out_rdata;
|
||||
wire out_valid;
|
||||
wire out_ready;
|
||||
|
||||
clocking mck @(posedge clk);
|
||||
input in_ready, out_branch_predict, out_addr, out_rdata, out_valid;
|
||||
output flush, in_branch_predict, in_addr, in_rdata, in_valid, out_ready;
|
||||
endclocking
|
||||
|
||||
clocking pck @(posedge clk);
|
||||
input in_ready, out_branch_predict, out_addr, out_rdata, out_valid,
|
||||
flush, in_branch_predict, in_addr, in_rdata, in_valid, out_ready;
|
||||
endclocking
|
||||
|
||||
endinterface
|
||||
`endif
|
75
tb/fetch_fifo_tb.sv
Executable file
75
tb/fetch_fifo_tb.sv
Executable file
|
@ -0,0 +1,75 @@
|
|||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 14.5.2017
|
||||
// Description: Fetch FIFO testbench
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
|
||||
module fetch_fifo_tb;
|
||||
|
||||
logic rst_ni, clk_i;
|
||||
fetch_fifo_if fetch_fifo_if (clk);
|
||||
|
||||
fetch_fifo
|
||||
dut (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( fetch_fifo_if.flush ),
|
||||
.branch_predict_i ( fetch_fifo_if.in_branch_predict ),
|
||||
.in_addr_i ( fetch_fifo_if.in_addr ),
|
||||
.in_rdata_i ( fetch_fifo_if.in_rdata ),
|
||||
.in_valid_i ( fetch_fifo_if.in_valid ),
|
||||
.in_ready_o ( fetch_fifo_if.in_ready ),
|
||||
.branch_predict_o ( fetch_fifo_if.out_branch_predict ),
|
||||
.out_addr_o ( fetch_fifo_if.out_addr ),
|
||||
.out_rdata_o ( fetch_fifo_if.out_rdata ),
|
||||
.out_valid_o ( fetch_fifo_if.out_valid ),
|
||||
.out_ready_i ( fetch_fifo_if.out_ready )
|
||||
);
|
||||
|
||||
initial begin
|
||||
clk_i = 1'b0;
|
||||
rst_ni = 1'b0;
|
||||
repeat(8)
|
||||
#10ns clk_i = ~clk_i;
|
||||
|
||||
rst_ni = 1'b1;
|
||||
forever
|
||||
#10ns clk_i = ~clk_i;
|
||||
end
|
||||
|
||||
// simulator stopper, this is suboptimal better go for coverage
|
||||
initial begin
|
||||
#10000000ns
|
||||
$stop;
|
||||
end
|
||||
|
||||
program testbench (fetch_fifo_if fetch_fifo_if);
|
||||
|
||||
initial begin
|
||||
fetch_fifo_if.mck.flush <= 1'b0;
|
||||
fetch_fifo_if.mck.in_branch_predict <= 'b0;
|
||||
fetch_fifo_if.mck.in_addr <= 'b0;
|
||||
fetch_fifo_if.mck.in_rdata <= 'b0;
|
||||
fetch_fifo_if.mck.in_valid <= 'b0;
|
||||
fetch_fifo_if.mck.out_ready <= 'b0;
|
||||
|
||||
end
|
||||
|
||||
endprogram
|
||||
|
||||
testbench tb(fetch_fifo_if);
|
||||
endmodule
|
23
tb/test/fetch_fifo/fetch_fifo_pkg.sv
Executable file
23
tb/test/fetch_fifo/fetch_fifo_pkg.sv
Executable file
|
@ -0,0 +1,23 @@
|
|||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 14.5.2017
|
||||
// Description: Fetch FIFO Pkg
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
//
|
||||
|
||||
package fetch_fifo_pkg;
|
||||
|
||||
endpackage
|
Loading…
Add table
Add a link
Reference in a new issue