Spaces:
Running
Running
File size: 6,852 Bytes
3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 12ac0fd 3951517 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | `timescale 1ns/1ps
module tb_mac_unit;
reg clk, rst, en, clear;
reg signed [7:0] a, b;
wire signed [31:0] acc_out;
integer pass_count = 0;
integer fail_count = 0;
mac_unit dut (
.clk(clk), .rst(rst), .en(en), .clear(clear),
.a(a), .b(b), .acc_out(acc_out)
);
always #5 clk = ~clk;
task check;
input signed [31:0] expected;
input [63:0] test_id;
begin
if (acc_out === expected) begin
$display("PASS: test %0d — acc_out=%0d (expected %0d)", test_id, acc_out, expected);
pass_count = pass_count + 1;
end else begin
$display("FAIL: test %0d — acc_out=%0d (expected %0d)", test_id, acc_out, expected);
fail_count = fail_count + 1;
end
end
endtask
initial begin
clk = 0; rst = 1; en = 0; clear = 0; a = 0; b = 0;
@(posedge clk); @(posedge clk); @(posedge clk);
#1; rst = 0; @(posedge clk); #1;
// Test 1: single accumulation a=3, b=4
en = 1; a = 8'sd3; b = 8'sd4;
@(posedge clk); #1; // Stage 1 captures 3,4
en = 0; a = 0; b = 0;
repeat(2) @(posedge clk); #1; // Stage 2 adds 12 to 0
check(32'sd12, 1);
// Test 2-3: back-to-back accumulation
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd1; b = 8'sd1;
@(posedge clk); #1; // Stage 1 captures 1,1
a = 8'sd2; b = 8'sd2;
@(posedge clk); #1; // Stage 2 adds 1 to 0. Stage 1 captures 2,2.
check(32'sd1, 2);
en = 0; a = 0; b = 0;
@(posedge clk); #1; // Stage 2 adds 4 to 1.
check(32'sd5, 3);
// Test 4: negative inputs
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = -8'sd5; b = 8'sd3;
@(posedge clk); #1;
en = 0; a = 0; b = 0;
repeat(2) @(posedge clk); #1;
check(-32'sd15, 4);
// Test 5: enable hold
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd2; b = 8'sd2;
@(posedge clk); #1;
en = 0; a = 8'sd9; b = 8'sd9;
repeat(2) @(posedge clk); #1;
check(32'sd4, 5);
// Test 6: clear signal
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd5; b = 8'sd5;
@(posedge clk); #1; // s1 captures 25
en = 0; a = 0; b = 0; clear = 1;
@(posedge clk); #1; // s2 adds 25 to 0. s1 captures clear=1.
@(posedge clk); #1; // s2 clears acc.
check(32'sd0, 6);
clear = 0;
// Test 7: rst clears everything
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd7; b = 8'sd7;
@(posedge clk); #1;
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
check(32'sd0, 7);
// Test 8: Large positive numbers
rst = 1; repeat(3) @(posedge clk); #1; rst = 0;
a = 0; b = 0; en = 0;
repeat(2) @(posedge clk); #1;
en = 1; a = 8'sd127; b = 8'sd127;
@(posedge clk); #1;
en = 0; a = 0; b = 0;
repeat(2) @(posedge clk); #1;
check(32'sd16129, 8);
// Test 9: Large negative numbers
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = -8'sd128; b = -8'sd128;
@(posedge clk); #1;
en = 0; a = 0; b = 0;
repeat(2) @(posedge clk); #1;
check(32'sd16384, 9);
// Test 10: Mixed signs
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = -8'sd10; b = 8'sd10;
@(posedge clk); #1;
en = 0; a = 0; b = 0;
repeat(2) @(posedge clk); #1;
check(-32'sd100, 10);
// Test 11-13: Accumulate multiple values
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd2; b = 8'sd3;
@(posedge clk); #1; // s1 captures 6
a = 8'sd4; b = 8'sd5;
@(posedge clk); #1; // s2 adds 6 to 0. s1 captures 20.
check(32'sd6, 11);
a = 8'sd6; b = 8'sd7;
@(posedge clk); #1; // s2 adds 20 to 6. s1 captures 42.
check(32'sd26, 12);
en = 0; a = 0; b = 0;
@(posedge clk); #1; // s2 adds 42 to 26.
check(32'sd68, 13);
// Test 14: Clear in middle of computation
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd5; b = 8'sd5;
@(posedge clk); #1;
a = 8'sd10; b = 8'sd10;
@(posedge clk); #1;
en = 0; a = 0; b = 0; clear = 1;
@(posedge clk); #1;
clear = 0;
@(posedge clk); #1; @(posedge clk); #1;
check(32'sd0, 14);
// Test 15: Alternating enable/disable
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd1; b = 8'sd1;
@(posedge clk); #1;
en = 0; a = 8'sd2; b = 8'sd2;
@(posedge clk); #1;
en = 1; a = 8'sd3; b = 8'sd3;
@(posedge clk); #1;
en = 0; a = 0; b = 0;
repeat(2) @(posedge clk); #1;
check(32'sd10, 15);
// Test 16: Zero inputs
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd0; b = 8'sd0;
@(posedge clk); #1;
en = 0;
repeat(2) @(posedge clk); #1;
check(32'sd0, 16);
// Test 17: One zero input
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd50; b = 8'sd0;
@(posedge clk); #1;
en = 0;
repeat(2) @(posedge clk); #1;
check(32'sd0, 17);
// Test 18-21: Continuous accumulation
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1;
a = 8'sd1; b = 8'sd2;
@(posedge clk); #1; // s1 = 2
a = 8'sd2; b = 8'sd2;
@(posedge clk); #1; // s2 = 2, s1 = 4
check(32'sd2, 18);
a = 8'sd3; b = 8'sd2;
@(posedge clk); #1; // s2 = 6, s1 = 6
check(32'sd6, 19);
a = 8'sd4; b = 8'sd2;
@(posedge clk); #1; // s2 = 12, s1 = 8
check(32'sd12, 20);
en = 0; a = 0; b = 0;
@(posedge clk); #1; // s2 = 20
check(32'sd20, 21);
// Test 22: Boundary cases
rst = 1; repeat(3) @(posedge clk); #1; rst = 0; @(posedge clk); #1;
en = 1; a = 8'sd1; b = 8'sd127;
@(posedge clk); #1;
en = 0;
repeat(2) @(posedge clk); #1;
check(32'sd127, 22);
$display("SUMMARY: %0d passed, %0d failed", pass_count, fail_count);
$finish;
end
initial #10000 begin
$display("FAIL: timeout");
$finish;
end
endmodule
|