// 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. // Authors: // - Wolfgang Rönninger <wroennin@iis.ee.ethz.ch> // Test bench for `stream_to_mem` module stream_to_mem_tb #( parameter int unsigned NumReq = 32'd10000, parameter int unsigned BufDepth = 32'd1 ); localparam time CyclTime = 10ns; localparam time ApplTime = 2ns; localparam time TestTime = 8ns; typedef logic [15:0] payload_t; // Signals logic clk, rst_n, sim_done; payload_t req, resp, mem_req, mem_resp; logic req_valid, resp_valid, mem_req_valid, mem_resp_valid; logic req_ready, resp_ready, mem_req_ready; // check FIFO payload_t data_fifo[$]; // Generate Stream data initial begin : proc_stream_master automatic payload_t test_data; automatic int unsigned stall_cycles; @(posedge rst_n); req = '0; req_valid = '0; repeat (5) @(posedge clk); for (int unsigned i = 0; i < NumReq; i++) begin stall_cycles = $urandom_range(0, 5); repeat (stall_cycles) @(posedge clk); test_data = payload_t'($urandom()); data_fifo.push_back(test_data); req <= #ApplTime payload_t'(test_data); req_valid <= #ApplTime 1'b1; #TestTime; while (!req_ready) begin @(posedge clk); #TestTime; end @(posedge clk); req <= #ApplTime '0; req_valid <= #ApplTime 1'b0; end end // consume stream data and check that the result matches initial begin : proc_stream_slave automatic int unsigned stall_cycles; automatic payload_t test_data; automatic int unsigned num_tested = 32'd0; sim_done = 0; @(posedge rst_n); resp_ready = '0; repeat (5) @(posedge clk); while (num_tested < NumReq) begin resp_ready <= #ApplTime $urandom(); #TestTime; if (resp_valid && resp_ready) begin test_data = data_fifo.pop_front(); assert(test_data === resp) else $error("test_data: %h, resp_data: %0h", test_data, resp); num_tested++; end @(posedge clk); end repeat (50) @(posedge clk); sim_done = 1'b1; end // reflect the payload exactly `BufDepth` Cycles later, standin for memory initial begin : proc_mem_reflect automatic payload_t reflect_fifo[$]; @(posedge rst_n); mem_req_ready = '0; mem_resp = '0; mem_resp_valid = '0; forever begin mem_req_ready <= #ApplTime $urandom(); #(CyclTime / 2); if (mem_req_valid && mem_req_ready) begin reflect_fifo.push_back(mem_req); // respond with a one cycle pule BufDepth cycles later fork begin if (BufDepth) begin repeat (BufDepth) @(posedge clk); #ApplTime; end mem_resp = reflect_fifo.pop_front(); mem_resp_valid = 1'b1; @(posedge clk); #(ApplTime / 2); mem_resp_valid = 1'b0; end join_none end @(posedge clk); end end // stop the simulation initial begin : proc_sim_stop @(posedge rst_n); wait (sim_done); $stop(); end // CLK generator clk_rst_gen #( .ClkPeriod ( CyclTime ), .RstClkCycles ( 10 ) ) i_clk_rst_gen ( .clk_o ( clk ), .rst_no ( rst_n ) ); // DUT stream_to_mem #( .mem_req_t ( payload_t ), .mem_resp_t ( payload_t ), .BufDepth ( BufDepth ) ) i_stream_to_mem_dut ( .clk_i ( clk ), .rst_ni ( rst_n ), .req_i ( req ), .req_valid_i ( req_valid ), .req_ready_o ( req_ready ), .resp_o ( resp ), .resp_valid_o ( resp_valid ), .resp_ready_i ( resp_ready ), .mem_req_o ( mem_req ), .mem_req_valid_o ( mem_req_valid ), .mem_req_ready_i ( mem_req_ready ), .mem_resp_i ( mem_resp ), .mem_resp_valid_i ( mem_resp_valid ) ); endmodule