@@ -309,21 +309,113 @@ endmodule
309309module Blur # (
310310 parameter D0 = 8 ,
311311 parameter D1 = 8 ,
312- parameter W = 8
312+ parameter N = 1
313313) (
314314 input logic clk,
315315 input logic reset,
316316
317317 input logic valid_i,
318318 output logic ready_i,
319- input logic [D0 - 1 : 0 ][D1 - 1 : 0 ][W - 1 : 0 ] in,
319+ input logic [D0 - 1 : 0 ][D1 - 1 : 0 ][7 : 0 ] in,
320320
321321 output logic valid_o,
322322 input logic ready_o,
323- output logic [D0 - 2 : 0 ][D1 - 2 : 0 ][W - 1 : 0 ] out // Convolution reduces size by kernel-1
323+ output logic [D0 - 3 : 0 ][D1 - 3 : 0 ][7 : 0 ] out // Convolution reduces size by kernel-2
324324);
325325// TODO: Implement Gaussian blur convolution with proper state machine
326326// Should apply blur kernel to each pixel neighborhood and manage ready/valid protocol
327+
328+ logic conv_ready_i, conv_ready_o, conv_valid_i, conv_valid_o;
329+ logic [15 : 0 ][7 : 0 ] conv_in, conv_out;
330+
331+ Conv2D # (.N (N )) conv2d (
332+ .clk, .reset,
333+ .valid_i (conv_valid_i),
334+ .valid_o (conv_valid_o),
335+ .ready_i (conv_ready_i),
336+ .ready_o (conv_ready_o),
337+ .i (conv_in),
338+ .o (conv_out)
339+ );
340+
341+ localparam Idle= 0 , Send_Conv= 1 , Recv_Conv= 2 , Writing= 3 ;
342+
343+ logic [1 : 0 ] st, nxt_st;
344+ always_ff @ (posedge clk) begin
345+ if (reset) st <= '0 ;
346+ else st <= nxt_st;
347+ end
348+
349+ always_comb begin
350+ nxt_st = st;
351+ case (st)
352+ Idle: begin // If there is a new input, we start processing it.
353+ if (valid_i) nxt_st = Send_Conv;
354+ end
355+ Send_Conv: if (conv_ready_i) nxt_st = Recv_Conv;
356+ Recv_Conv: begin
357+ if (valid_o) begin
358+ if (last_chunk) nxt_st = Writing;
359+ else nxt_st = Send_Conv;
360+ end
361+ end
362+ Writing: if (ready_o) nxt_st = Recv_Conv;
363+ endcase
364+ end
365+
366+ // The current image we are working on. We latch the value when a valid input
367+ // is accepted.
368+ logic [D1 - 1 : 0 ][D1 - 1 : 0 ][7 : 0 ] image;
369+ always_ff @ (posedge clk) begin
370+ if (reset) image <= '0 ;
371+ else if (st == Idle && valid_i) image <= in;
372+ else image <= image;
373+ end
374+
375+ // Index management logic: determines which part of the input image we are
376+ // working on and where to place the output;
377+
378+ // TODO: define correct widths for idx and nxt_idx. we probably need two
379+ // indices.
380+ logic [31 : 0 ] idx, nxt_idx;
381+
382+ wire last_chunk; // TODO: Condition for when we have reached the last index.
383+
384+ always_comb begin
385+ nxt_idx = idx;
386+ if (st == Recv_Conv && conv_valid_o) nxt_idx = idx + 1 ;
387+ else if (st == Writing && ready_o) nxt_idx = 0 ;
388+ end
389+ always_ff @ (posedge clk) begin
390+ if (reset) idx <= '0 ;
391+ else idx <= nxt_idx;
392+ end
393+
394+
395+ // Set up the input for the convolution
396+ always_comb begin
397+ if (st == Send_Conv) conv_valid_i = 1 ;
398+ else conv_valid_i = 0 ;
399+ end
400+ always_comb begin
401+ // TODO: define the input pixels to be sent.
402+ end
403+
404+ // Capture output when valid
405+ logic [D0 - 3 : 0 ][D1 - 3 : 0 ][7 : 0 ] tmp_out;
406+ always_comb begin
407+ if (st == Recv_Conv && conv_valid_o) begin
408+ // TODO: capture the pixels in the right location
409+ end
410+ end
411+ always_ff @ (posedge clk) begin
412+ out <= tmp_out;
413+ end
414+
415+
416+ assign ready_i = st == Idle;
417+ assign valid_o = st == Writing;
418+
327419endmodule
328420
329421// Blend two pyramid levels with weighted combination
0 commit comments