diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 65250396f..1485cb316 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,6 +13,17 @@ testALU: paths: - covhtmlreport +testFIFO: + stage: test + script: + - make build + - make fifo + - vcover report fifo.ucdb + - vcover report -html fifo.ucdb + artifacts: + paths: + - covhtmlreport + testScoreboard: stage: test script: diff --git a/Makefile b/Makefile index d2860667c..6b8503de8 100644 --- a/Makefile +++ b/Makefile @@ -7,17 +7,17 @@ library = work # Top level module to compile top_level = core_tb test_top_level = core_tb -tests = alu scoreboard +tests = alu scoreboard fifo # path to agents agents = tb/agents/fu_if/fu_if.sv tb/agents/fu_if/fu_if_agent_pkg.sv \ include/ariane_pkg.svh tb/agents/scoreboard_if/scoreboard_if.sv tb/agents/scoreboard_if/scoreboard_if_agent_pkg.sv -interfaces = include/debug_if.svh include/mem_if.svh +interfaces = include/debug_if.svh include/mem_if.svh tb/agents/fifo_if/fifo_if.sv # this list contains the standalone components src = alu.sv tb/sequences/alu_sequence_pkg.sv tb/env/alu_env_pkg.sv tb/test/alu_lib_pkg.sv tb/alu_tb.sv \ tb/scoreboard_tb.sv \ if_stage.sv compressed_decoder.sv fetch_fifo.sv commit_stage.sv prefetch_buffer.sv \ - mmu.sv lsu.sv \ + mmu.sv lsu.sv fifo.sv tb/fifo_tb.sv \ scoreboard.sv issue_read_operands.sv decoder.sv id_stage.sv util/cluster_clock_gating.sv regfile.sv ex_stage.sv ariane.sv \ tb/core_tb.sv diff --git a/fifo.sv b/fifo.sv index a63276cfb..af810da48 100644 --- a/fifo.sv +++ b/fifo.sv @@ -50,6 +50,7 @@ module fifo #( write_pointer_n = write_pointer_q; status_cnt_n = status_cnt_q; data_o = mem_q[read_pointer_q]; + mem_n = mem_q; // push a new element to the queue if (push_i && ~full_o) begin // push the data onto the queue @@ -67,7 +68,11 @@ module fifo #( // ... and decrement the overall count status_cnt_n = status_cnt_q - 1; end + // keep the count pointer stable if we push and pop at the same time + if (push_i && ~full_o && pop_i && ~empty_o) + status_cnt_n = status_cnt_q; end + // sequential process always_ff @(posedge clk_i or negedge rst_ni) begin if(~rst_ni) begin @@ -82,4 +87,21 @@ module fifo #( mem_q <= mem_n; end end + + `ifndef SYNTHESIS + `ifndef verilator + initial begin + assert (DEPTH == 2**$clog2(DEPTH)) else $fatal("FIFO size needs to be a power of two."); + + assert property( + @(posedge clk_i) (rst_ni && full_o |-> ~push_i)) + else $error ("Trying to push new data although the FIFO is full."); + + assert property( + @(posedge clk_i) (rst_ni && empty_o |-> ~pop_i)) + else $error ("Trying to pop data although the FIFO is empty."); + `endif + `endif +end + endmodule \ No newline at end of file diff --git a/tb/agents/fifo_if/fifo_if.sv b/tb/agents/fifo_if/fifo_if.sv new file mode 100755 index 000000000..945493298 --- /dev/null +++ b/tb/agents/fifo_if/fifo_if.sv @@ -0,0 +1,47 @@ +// Author: Florian Zaruba, ETH Zurich +// Date: 24.4.2017 +// Description: 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 FIFO_IF_SV +`define FIFO_IF_SV +interface fifo_if #(parameter type dtype = logic[7:0]) + (input clk); + + wire full; + wire empty; + dtype wdata; + wire push; + dtype rdata; + wire pop; + + clocking mck @(posedge clk); + input full, empty, rdata; + output wdata, push, pop; + endclocking + + clocking sck @(posedge clk); + input wdata, push, pop; + output full, empty, rdata; + endclocking + + clocking pck @(posedge clk); + input wdata, push, pop, full, empty, rdata; + endclocking + +endinterface +`endif \ No newline at end of file diff --git a/tb/fifo_tb.sv b/tb/fifo_tb.sv new file mode 100755 index 000000000..9fd404498 --- /dev/null +++ b/tb/fifo_tb.sv @@ -0,0 +1,125 @@ +// Author: Florian Zaruba, ETH Zurich +// Date: 24.4.2017 +// Description: 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 fifo_tb; + logic rst_ni, clk; + + fifo_if #(.dtype ( logic[7:0] )) fifo_if (clk); + + logic push, pop; + + assign fifo_if.push = ~fifo_if.full & push; + assign fifo_if.pop = ~fifo_if.empty & pop; + + fifo + #(.dtype ( logic[7:0] )) + dut + ( + .clk_i ( clk ), + .rst_ni ( rst_ni ), + .full_o ( fifo_if.full ), + .empty_o ( fifo_if.empty ), + .data_i ( fifo_if.wdata ), + .push_i ( fifo_if.push ), + .data_o ( fifo_if.rdata ), + .pop_i ( fifo_if.pop ) + ); + + initial begin + clk = 1'b0; + rst_ni = 1'b0; + repeat(8) + #10ns clk = ~clk; + + rst_ni = 1'b1; + forever + #10ns clk = ~clk; + end + + // simulator stopper, this is suboptimal better go for coverage + initial begin + #10000000ns + $finish; + end + + program testbench (fifo_if fifo_if, output logic push, output logic pop); + logic[7:0] queue [$]; + + // ---------- + // Driver + // ---------- + initial begin + fifo_if.mck.wdata <= $urandom_range(0,256); + push <= 1'b0; + // wait for reset to be high + wait(rst_ni == 1'b1); + // push + forever begin + repeat($urandom_range(0, 8)) @(fifo_if.mck) + // if there is space lets push some random data + if (~fifo_if.mck.full) begin + fifo_if.mck.wdata <= $urandom_range(0,256); + + push <= 1'b1; + end else begin + fifo_if.mck.wdata <= $urandom_range(0,256); + push <= 1'b0; + end + end + end + + initial begin + // wait for reset to be high + wait(rst_ni == 1'b1); + // pop from queue + forever begin + @(fifo_if.mck) + pop <= 1'b1; + repeat($urandom_range(0, 8)) @(fifo_if.mck) + pop <= 1'b0; + end + end + + // ------------------- + // Monitor && Checker + // ------------------- + initial begin + + automatic logic [7:0] data; + forever begin + @(fifo_if.pck) + + if (fifo_if.pck.push) begin + queue.push_back(fifo_if.pck.wdata); + end + + if (fifo_if.pck.pop) begin + data = queue.pop_front(); + // $display("Time: %t, Expected: %0h Got %0h", $time, data, fifo_if.pck.rdata); + assert(data == fifo_if.mck.rdata) else $error("Mismatch, Expected: %0h Got %0h", data, fifo_if.pck.rdata); + end + + end + end + + endprogram + + testbench tb(fifo_if, push, pop); +endmodule \ No newline at end of file