Spaces:
Running
Running
| module tb_ring_buffer; | |
| parameter DEPTH = 8; | |
| parameter DATA_W = 8; | |
| reg clk, rst, push, pop; | |
| reg [DATA_W-1:0] push_data; | |
| wire [DATA_W-1:0] pop_data; | |
| wire full, empty; | |
| wire [$clog2(DEPTH):0] count; | |
| integer pass_count = 0; | |
| integer fail_count = 0; | |
| ring_buffer #(.DEPTH(DEPTH), .DATA_W(DATA_W)) dut ( | |
| .clk(clk), .rst(rst), | |
| .push(push), .push_data(push_data), | |
| .pop(pop), .pop_data(pop_data), | |
| .full(full), .empty(empty), .count(count) | |
| ); | |
| always #5 clk = ~clk; | |
| task check_flag; | |
| input actual, expected; | |
| input [63:0] test_id; | |
| input [127:0] name; | |
| begin | |
| if (actual === expected) begin | |
| $display("PASS: test %0d — %s=%0d", test_id, name, actual); | |
| pass_count = pass_count + 1; | |
| end else begin | |
| $display("FAIL: test %0d — %s got=%0d expected=%0d", test_id, name, actual, expected); | |
| fail_count = fail_count + 1; | |
| end | |
| end | |
| endtask | |
| task check_count; | |
| input [$clog2(DEPTH):0] expected; | |
| input [63:0] test_id; | |
| begin | |
| if (count === expected) begin | |
| $display("PASS: test %0d — count=%0d", test_id, count); | |
| pass_count = pass_count + 1; | |
| end else begin | |
| $display("FAIL: test %0d — count got=%0d expected=%0d", test_id, count, expected); | |
| fail_count = fail_count + 1; | |
| end | |
| end | |
| endtask | |
| task check_pop; | |
| input [DATA_W-1:0] expected; | |
| input [63:0] test_id; | |
| begin | |
| if (pop_data === expected) begin | |
| $display("PASS: test %0d — pop_data=%0d", test_id, pop_data); | |
| pass_count = pass_count + 1; | |
| end else begin | |
| $display("FAIL: test %0d — pop_data got=%0d expected=%0d", test_id, pop_data, expected); | |
| fail_count = fail_count + 1; | |
| end | |
| end | |
| endtask | |
| integer i; | |
| initial begin | |
| clk=0; rst=1; push=0; pop=0; push_data=0; | |
| @(posedge clk); #1; @(posedge clk); #1; | |
| rst=0; @(posedge clk); #1; | |
| // Test 1-3: reset state | |
| check_flag(empty, 1, 1, "empty"); | |
| check_flag(full, 0, 2, "full"); | |
| check_count(0, 3); | |
| // Test 4: push one item | |
| push=1; push_data=8'hAA; | |
| @(posedge clk); #1; push=0; #1; | |
| check_flag(empty, 0, 4, "empty"); | |
| check_count(1, 5); | |
| check_pop(8'hAA, 6); | |
| // Test 5: pop it back out | |
| pop=1; @(posedge clk); #1; pop=0; #1; | |
| check_flag(empty, 1, 7, "empty"); | |
| check_count(0, 8); | |
| // Test 6: fill to DEPTH (8 items) | |
| push=1; | |
| for (i=1; i<=8; i=i+1) begin | |
| push_data = i[DATA_W-1:0]; | |
| @(posedge clk); #1; | |
| end | |
| push=0; #1; | |
| check_flag(full, 1, 9, "full"); | |
| check_count(8, 10); | |
| // Test 7: push when full — ignored | |
| push=1; push_data=8'hFF; | |
| @(posedge clk); #1; push=0; #1; | |
| check_flag(full, 1, 11, "full"); | |
| check_count(8, 12); | |
| // Test 8: pop and verify FIFO order (items 1..8 in order) | |
| pop=1; | |
| for (i=1; i<=8; i=i+1) begin | |
| check_pop(i[DATA_W-1:0], 12+i); // tests 13..20 | |
| @(posedge clk); #1; | |
| end | |
| pop=0; #1; | |
| check_flag(empty, 1, 21, "empty"); | |
| // Test 9: simultaneous push+pop (count stays same) | |
| push=1; pop=0; push_data=8'h55; | |
| @(posedge clk); #1; | |
| // now count=1; do simultaneous push+pop | |
| push=1; pop=1; push_data=8'h66; | |
| @(posedge clk); #1; push=0; pop=0; #1; | |
| check_count(1, 22); // was 1, +1-1=1 | |
| // Test 10: wrap-around: push 8, pop 4, push 4 more, verify order | |
| // Start fresh | |
| rst=1; @(posedge clk); #1; rst=0; @(posedge clk); #1; | |
| push=1; | |
| for (i=0; i<8; i=i+1) begin | |
| push_data = 8'h10 + i[7:0]; | |
| @(posedge clk); #1; | |
| end | |
| push=0; #1; | |
| pop=1; #1; | |
| for (i=0; i<4; i=i+1) begin | |
| check_pop(8'h10 + i[7:0], 23+i); // tests 23..26 | |
| @(posedge clk); #1; | |
| end | |
| pop=0; #1; | |
| push=1; | |
| for (i=0; i<4; i=i+1) begin | |
| push_data = 8'h20 + i[7:0]; | |
| @(posedge clk); #1; | |
| end | |
| push=0; #1; | |
| pop=1; #1; | |
| for (i=4; i<8; i=i+1) begin | |
| check_pop(8'h10 + i[7:0], 27+i-4); // tests 27..30, expecting 0x14..0x17 | |
| @(posedge clk); #1; | |
| end | |
| for (i=0; i<4; i=i+1) begin | |
| check_pop(8'h20 + i[7:0], 31+i); // tests 31..34 | |
| @(posedge clk); #1; | |
| end | |
| pop=0; #1; | |
| check_flag(empty, 1, 35, "empty"); | |
| $display("SUMMARY: %0d passed, %0d failed", pass_count, fail_count); | |
| $finish; | |
| end | |
| initial #100000 begin | |
| $display("FAIL: timeout"); | |
| $finish; | |
| end | |
| endmodule | |