|  | // Copyright 2020-2022 F4PGA Authors | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //		 http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the 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. | 
|  | // | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | `timescale 1ns/1ps | 
|  |  | 
|  | `define STRINGIFY(x) `"x`" | 
|  |  | 
|  | module TB; | 
|  | localparam PERIOD = 30; | 
|  | localparam ADDR_INCR = 1; | 
|  |  | 
|  | reg clk0; | 
|  | reg clk1; | 
|  | reg flush; | 
|  | reg pop; | 
|  | wire [`DATA_WIDTH1-1:0] dout; | 
|  | reg push; | 
|  | reg [`DATA_WIDTH0-1:0] din; | 
|  | wire almost_full,almost_empty; | 
|  | wire full, empty; | 
|  | wire full_watermark, empty_watermark; | 
|  | wire overrun_error, underrun_error; | 
|  |  | 
|  | initial | 
|  | begin | 
|  | clk0 = 0; | 
|  | clk1 = 0; | 
|  | pop = 0; | 
|  | push = 0; | 
|  | flush = 1; | 
|  | din = 0; | 
|  | #40 | 
|  | flush = 0; | 
|  | end | 
|  |  | 
|  | initial forever #(PERIOD / 3.0) clk0 = ~clk0; | 
|  | initial forever #(PERIOD / 2.0) clk1 = ~clk1; | 
|  |  | 
|  | initial begin | 
|  | $dumpfile(`STRINGIFY(`VCD)); | 
|  | $dumpvars; | 
|  | end | 
|  |  | 
|  | integer a; | 
|  |  | 
|  | reg done; | 
|  | initial done = 1'b0; | 
|  |  | 
|  | reg read_test; | 
|  | initial read_test = 0; | 
|  |  | 
|  | reg [`DATA_WIDTH1-1:0] expected; | 
|  | initial expected = 0; | 
|  |  | 
|  | always @(posedge clk1) begin | 
|  | expected <= (a | (a << 20) | 20'h55000) & {`DATA_WIDTH1{1'b1}}; | 
|  | end | 
|  |  | 
|  | wire error = ((a != 0) && read_test) ? dout !== expected : 0; | 
|  |  | 
|  | integer error_cnt = 0; | 
|  | always @ (posedge clk1) | 
|  | begin | 
|  | if (error) | 
|  | error_cnt <= error_cnt + 1'b1; | 
|  | end | 
|  |  | 
|  |  | 
|  | initial #(50) begin | 
|  | @(posedge clk0) | 
|  | // Write data | 
|  | for (a = 0; a < (1<<`ADDR_WIDTH0); a = a + ADDR_INCR) begin | 
|  | @(negedge clk0) begin | 
|  | din = a | (a << 20) | 20'h55000; | 
|  | push = 1; | 
|  | end | 
|  | @(posedge clk0) begin | 
|  | #(PERIOD/10) push = 0; | 
|  | end | 
|  | end | 
|  | // Read data | 
|  | read_test = 1; | 
|  | for (a = 0; a < (1<<`ADDR_WIDTH1); a = a + ADDR_INCR) begin | 
|  | @(posedge clk1) begin | 
|  | #(PERIOD/10) pop = 0; | 
|  | if ( dout !== expected) begin | 
|  | $display("%d: FAIL: mismatch act=%x exp=%x at %x", $time, dout, expected, a); | 
|  | end else begin | 
|  | $display("%d: OK: act=%x exp=%x at %x", $time, dout, expected, a); | 
|  | end | 
|  | end | 
|  | @(negedge clk1) begin | 
|  | pop = 1; | 
|  | end | 
|  | end | 
|  | done = 1'b1; | 
|  | end | 
|  |  | 
|  | // Scan for simulation finish | 
|  | always @(posedge clk1) begin | 
|  | if (done) | 
|  | $finish_and_return( (error_cnt == 0) ? 0 : -1 ); | 
|  | end | 
|  |  | 
|  | case (`STRINGIFY(`TOP)) | 
|  | "af1024x36_1024x36": begin | 
|  | af1024x36_1024x36 #() afifo ( | 
|  | .DIN(din), | 
|  | .PUSH(push), | 
|  | .POP(pop), | 
|  | .clock0(clk0), | 
|  | .clock1(clk1), | 
|  | .Async_Flush(flush), | 
|  | .Almost_Full(almost_full), | 
|  | .Almost_Empty(almost_empty), | 
|  | .Full(full), | 
|  | .Empty(empty), | 
|  | .Full_Watermark(full_watermark), | 
|  | .Empty_Watermark(empty_watermark), | 
|  | .Overrun_Error(overrun_error), | 
|  | .Underrun_Error(underrun_error), | 
|  | .DOUT(dout) | 
|  | ); | 
|  | end | 
|  | "af2048x18_2048x18": begin | 
|  | af2048x18_2048x18 #() afifo ( | 
|  | .DIN(din), | 
|  | .PUSH(push), | 
|  | .POP(pop), | 
|  | .clock0(clk0), | 
|  | .clock1(clk1), | 
|  | .Async_Flush(flush), | 
|  | .Almost_Full(almost_full), | 
|  | .Almost_Empty(almost_empty), | 
|  | .Full(full), | 
|  | .Empty(empty), | 
|  | .Full_Watermark(full_watermark), | 
|  | .Empty_Watermark(empty_watermark), | 
|  | .Overrun_Error(overrun_error), | 
|  | .Underrun_Error(underrun_error), | 
|  | .DOUT(dout) | 
|  | ); | 
|  | end | 
|  | "af4096x9_4096x9": begin | 
|  | af4096x9_4096x9 #() afifo ( | 
|  | .DIN(din), | 
|  | .PUSH(push), | 
|  | .POP(pop), | 
|  | .clock0(clk0), | 
|  | .clock1(clk1), | 
|  | .Async_Flush(flush), | 
|  | .Almost_Full(almost_full), | 
|  | .Almost_Empty(almost_empty), | 
|  | .Full(full), | 
|  | .Empty(empty), | 
|  | .Full_Watermark(full_watermark), | 
|  | .Empty_Watermark(empty_watermark), | 
|  | .Overrun_Error(overrun_error), | 
|  | .Underrun_Error(underrun_error), | 
|  | .DOUT(dout) | 
|  | ); | 
|  | end | 
|  | endcase | 
|  | endmodule |