Skip to content

Commit df5aa06

Browse files
committed
working conv2d
1 parent 286f418 commit df5aa06

File tree

2 files changed

+228
-8
lines changed

2 files changed

+228
-8
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
`timescale 1ns/1ps
2+
3+
module Conv2D_tb;
4+
5+
// Clock and reset
6+
logic clk;
7+
logic reset;
8+
9+
// Test parameters
10+
parameter N = 4; // Can be 1, 2, 4, 8, or 16
11+
12+
// DUT signals
13+
logic valid_i;
14+
logic ready_i;
15+
logic[15:0][7:0] data_in;
16+
logic valid_o;
17+
logic ready_o;
18+
logic[15:0][7:0] data_out;
19+
int cycles, start_v, end_v;
20+
21+
// Verification variables
22+
logic pass;
23+
logic[7:0] expected;
24+
25+
// Instantiate DUT
26+
Conv2D #(.N(N)) dut (
27+
.clk(clk),
28+
.reset(reset),
29+
.valid_i(valid_i),
30+
.ready_i(ready_i),
31+
.i(data_in),
32+
.valid_o(valid_o),
33+
.ready_o(ready_o),
34+
.o(data_out)
35+
);
36+
37+
// Clock generation
38+
initial begin
39+
clk = 0;
40+
forever #5 clk = ~clk; // 100MHz clock
41+
end
42+
43+
// Dump waveforms
44+
initial begin
45+
$dumpfile("conv2d_tb.vcd");
46+
$dumpvars(0, Conv2D_tb);
47+
end
48+
49+
always_ff @(posedge clk) begin
50+
if (reset) cycles <= '0;
51+
else cycles <= cycles + 1;
52+
53+
if (cycles > 50) begin
54+
$display("timeout at 100 cycles!");
55+
$finish;
56+
end
57+
58+
if (valid_i) start_v <= cycles;
59+
if (valid_o) end_v <= cycles;
60+
end
61+
62+
// Test stimulus
63+
initial begin
64+
// Initialize signals
65+
reset = 1;
66+
valid_i = 0;
67+
ready_o = 0;
68+
data_in = '0;
69+
70+
// Hold reset for 5 cycles
71+
repeat(5) @(posedge clk);
72+
reset = 0;
73+
@(posedge clk);
74+
75+
// Prepare input data [0..15]
76+
for (int i = 0; i < 16; i++) begin
77+
data_in[i] = i[7:0];
78+
end
79+
80+
$display("Starting test with N=%0d", N);
81+
$display("Input data: ");
82+
for (int i = 0; i < 16; i++) begin
83+
$write("%3d ", data_in[i]);
84+
if ((i+1) % 4 == 0) $write("\n");
85+
end
86+
87+
// Wait for module to be ready
88+
@(posedge clk);
89+
while (!ready_i) begin
90+
@(posedge clk);
91+
end
92+
93+
// Send input data
94+
$display("\nSending data to Conv2D module...");
95+
valid_i = 1;
96+
@(posedge clk);
97+
98+
// Check if transaction occurred
99+
if (ready_i && valid_i) begin
100+
$display("Transaction accepted by module");
101+
end
102+
103+
valid_i = 0; // Clear valid after one cycle
104+
105+
// Wait for output to be valid
106+
$display("Waiting for output...");
107+
while (!valid_o) begin
108+
@(posedge clk);
109+
end
110+
111+
// Assert ready to accept output
112+
ready_o = 1;
113+
@(posedge clk);
114+
115+
// Print output
116+
$display("\nOutput data received:");
117+
for (int i = 0; i < 16; i++) begin
118+
$write("%3d ", data_out[i]);
119+
if ((i+1) % 4 == 0) $write("\n");
120+
end
121+
122+
// Verify output (should be input + 2)
123+
$display("\nVerifying output (each element should be input + 2):");
124+
pass = 1;
125+
for (int i = 0; i < 16; i++) begin
126+
expected = i[7:0] + 2;
127+
if (data_out[i] !== expected) begin
128+
$display("ERROR: data_out[%2d] = %3d, expected %3d", i, data_out[i], expected);
129+
pass = 0;
130+
end
131+
end
132+
133+
if (pass) begin
134+
$display("PASS: All outputs are correct!");
135+
end else begin
136+
$display("FAIL: Output mismatch detected!");
137+
end
138+
139+
ready_o = 0;
140+
141+
// Wait a few cycles then end
142+
repeat(10) @(posedge clk);
143+
144+
$display("\nTest completed! Latency: %0d, Cycles: %0d", end_v-start_v, cycles);
145+
$finish;
146+
end
147+
148+
endmodule

apps/guass-pyramid/ready-val/valid-hold.sv

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ module Conv2D#(
126126
// Interface with the convolution module
127127
logic conv_valid_i, conv_valid_o;
128128
logic[N-1:0][7:0] conv_out, conv_in;
129-
AetherlingConv#(.N) Conv(
129+
AetherlingConv#(.N(N)) Conv(
130130
.clk, .reset,
131131
.in(conv_in),
132132
.valid_i(conv_valid_i),
@@ -148,14 +148,14 @@ end
148148

149149
// The chunk we are working on.
150150
localparam Chunks = 16 / N;
151+
localparam Chunks_1 = Chunks - 1;
151152
logic[3:0] idx, nxt_idx;
152153
always_ff @(posedge clk) begin
153154
if (reset) idx <= '0;
154155
else idx <= nxt_idx;
155156
end
156157

157-
wire last_chunk = idx == Chunks[3:0]-1;
158-
158+
wire last_chunk = idx == Chunks_1[3:0];
159159

160160
// State machine
161161
logic[1:0] st, nxt_st;
@@ -170,14 +170,19 @@ always_comb begin
170170
end
171171
PROC_SEND: begin
172172
nxt_st = PROC_RECV;
173-
nxt_idx = idx + 1;
174173
conv_valid_i = 1;
175174
end
176175
PROC_RECV: begin
177176
// If the convolution module has returned a valid value.
178177
if (conv_valid_o) begin
179-
if (last_chunk) nxt_st = WRITING; // This is the last chunk. Finish processing.
180-
else nxt_st = PROC_SEND; // More chunks remain.
178+
// This is the last chunk. Finish processing.
179+
if (last_chunk) begin
180+
nxt_idx = '0;
181+
nxt_st = WRITING;
182+
end else begin
183+
nxt_idx = idx + 1;
184+
nxt_st = PROC_SEND;
185+
end
181186
end
182187
end
183188
WRITING: begin
@@ -195,7 +200,7 @@ always_comb begin
195200
conv_in = '0;
196201
for (int j = 0; j < Chunks; j++) begin
197202
if (idx == j[3:0]) begin
198-
conv_in = in[(N*(j+1)-1)+:N];
203+
conv_in = in[N*j+:N];
199204
end
200205
end
201206
end
@@ -206,15 +211,82 @@ always_comb begin
206211
for (int j = 0; j < Chunks; j++) begin
207212
// If the output is valid;
208213
if (conv_valid_o && idx == j[3:0]) begin
209-
out[(N*(j+1)-1)+:N] = conv_out;
214+
// $display("writing to chunk %0d: [%0d:%0d]", j[3:0], N*j+N, N*j);
215+
out[N*j+:N] = conv_out;
210216
end
211217
end
212218
end
213219
always_ff @(posedge clk) begin
214220
o <= out;
221+
/*
222+
if (conv_valid_o) begin
223+
$write("out: ");
224+
for (int i = 0; i < 16; i++)
225+
$write("%0d,", out[i]);
226+
$write("; conv_out: ");
227+
for (int i = 0; i < N; i++)
228+
$write("%0d,", conv_out[i]);
229+
$display("");
230+
end
231+
*/
215232
end
216233

217234
assign valid_o = st == WRITING;
218235
assign ready_i = st == IDLE;
219236

220237
endmodule
238+
239+
// Pad the input image by a row and a column;
240+
module Pad#(
241+
parameter D0 = 8,
242+
parameter D1 = 8,
243+
parameter W = 8
244+
) (
245+
input logic[D0-1:0][D1-1:0][W-1:0] in,
246+
output logic[D0+1:0][D1+1:0][W-1:0] out
247+
);
248+
249+
always_comb begin
250+
out = '0;
251+
// Copy input to the center of the output array
252+
for (int i = 0; i < D0; i++) begin
253+
for (int j = 0; j < D1; j++) begin
254+
out[i+1][j+1] = in[i][j];
255+
end
256+
end
257+
end
258+
259+
endmodule
260+
261+
// Downsample by taking every other row and column
262+
module Downsample#(
263+
parameter D0 = 8,
264+
parameter D1 = 8,
265+
parameter W = 8
266+
) (
267+
input logic[D0-1:0][D1-1:0][W-1:0] in,
268+
output logic[D0/2-1:0][D1/2-1:0][W-1:0] out
269+
);
270+
always_comb begin
271+
for (int i = 0; i < D0/2; i++) begin
272+
for (int j = 0; j < D1/2; j++) begin
273+
out[i][j] = in[2*i][2*j];
274+
end
275+
end
276+
end
277+
endmodule
278+
279+
module Pyramid (
280+
input logic clk,
281+
input logic reset,
282+
283+
input logic valid_i,
284+
output logic ready_i,
285+
input logic[15:0][7:0] in,
286+
287+
output logic valid_o,
288+
input logic ready_o,
289+
output logic[15:0][7:0] out
290+
);
291+
292+
endmodule

0 commit comments

Comments
 (0)