Verilog FPGA Video Capture Code:
//////////////////////////////////////////////////// // // Module Video Capture Written By: Kenneth Maxon // On or about... March-2004 ... // //////////////////////////////////////////////////// module video_capture( input wire sys_clock, input wire force_reset, input wire begin_capture, output reg [17:0] video1_addr, output wire [14:0] video1_data_filtered, output reg video1_store_strb, input wire video1_llc, input wire video1_hsync, input wire video1_vsync, input wire [14:0] video1_raw, output wire [23:0] blob1_x_out, output wire [23:0] blob1_y_out, output wire blob_capture_done, input wire data_valid, output reg [3:0] debug_state ); reg video1_llc_reg; reg video1_llc2_reg; wire llc_edge_found; reg video1_hsync_reg; reg video1_hsync2_reg; wire hsync_edge_found; reg video1_vsync_reg; reg video1_vsync2_reg; wire vsync_edge_found; reg [9:0] vid_cap_state_var; reg [17:0] addr_index_count; reg [14:0] video1_data; reg [8:0] pixel_count; reg [7:0] line_count; reg end_of_screen_capture; reg beginning_of_screen_capture; always@(posedge sys_clock) // always double buffer across clock domains. begin video1_llc_reg <= #1 video1_llc; video1_hsync_reg <= #1 video1_hsync; video1_vsync_reg <= #1 video1_vsync; video1_llc2_reg <= #1 video1_llc_reg; video1_hsync2_reg <= #1 video1_hsync_reg; video1_vsync2_reg <= #1 video1_vsync_reg; end assign #1 llc_edge_found = (~video1_llc2_reg & video1_llc_reg); assign #1 hsync_edge_found = (~video1_hsync2_reg & video1_hsync_reg); assign #1 vsync_edge_found = (~video1_vsync2_reg & video1_vsync_reg); parameter[9:0] DISPATCH_STATE = 10'b0000000001, VID_CAP1_STATE = 10'b0000000010, VID_CAP2_STATE = 10'b0000000100, VID_CAP3_STATE = 10'b0000001000, VID_CAP4_STATE = 10'b0000010000, VID_CAP45_STATE = 10'b0000100000, VID_CAP5_STATE = 10'b0001000000, VID_CAP6_STATE = 10'b0010000000, VID_CAP7_STATE = 10'b0100000000, VID_CAP8_STATE = 10'b1000000000; parameter[9:0] DISPATCH_CASE = 10'bxxxxxxxxx1, VID_CAP1_CASE = 10'bxxxxxxxx1x, VID_CAP2_CASE = 10'bxxxxxxx1xx, VID_CAP3_CASE = 10'bxxxxxx1xxx, VID_CAP4_CASE = 10'bxxxxx1xxxx, VID_CAP45_CASE = 10'bxxxx1xxxxx, VID_CAP5_CASE = 10'bxxx1xxxxxx, VID_CAP6_CASE = 10'bxx1xxxxxxx, VID_CAP7_CASE = 10'bx1xxxxxxxx, VID_CAP8_CASE = 10'b1xxxxxxxxx; always @(posedge sys_clock or posedge force_reset)begin : vid_gen_state_fsm if (force_reset) vid_cap_state_var[9:0] <= #1 DISPATCH_STATE; else begin casex (vid_cap_state_var[9:0]) // synopsys parallel_case full_case DISPATCH_CASE: // wait for processor to tell us to start begin if(begin_capture) vid_cap_state_var[9:0] <= #1 VID_CAP1_STATE; else vid_cap_state_var[9:0] <= #1 DISPATCH_STATE; end VID_CAP1_CASE: // wait for vsync begin addr_index_count[17:0] <= #1 18'd01605; line_count[7:0] <= #1 8'h00; if(vsync_edge_found) vid_cap_state_var[9:0] <= #1 VID_CAP2_STATE; else vid_cap_state_var[9:0] <= #1 VID_CAP1_STATE; end VID_CAP2_CASE: // wait for hsync begin pixel_count[8:0] <= #1 9'h000; if(hsync_edge_found) vid_cap_state_var[9:0] <= #1 VID_CAP3_STATE; else vid_cap_state_var[9:0] <= #1 VID_CAP2_STATE; end VID_CAP3_CASE: // wait for llc2 & latch in same state begin if(llc_edge_found) begin video1_addr[17:0] <= #1 addr_index_count[17:0]; video1_data[14:0] <= #1 video1_raw[14:0]; vid_cap_state_var[9:0] <= #1 VID_CAP4_STATE; end else vid_cap_state_var[9:0] <= #1 VID_CAP3_STATE; end VID_CAP4_CASE: // send out data strobe to the RAM scheduler begin addr_index_count[17:0] <= addr_index_count[17:0] + 18'h00001; pixel_count[8:0] <= #1 pixel_count[8:0] + 9'h001; vid_cap_state_var[9:0] <= #1 VID_CAP45_STATE; end VID_CAP45_CASE: // skip every other pixel begin if(llc_edge_found) vid_cap_state_var[9:0] <= #1 VID_CAP5_STATE; else vid_cap_state_var[9:0] <= #1 VID_CAP45_STATE; end VID_CAP5_CASE: // check to see if we are at the end of the line pixel wise begin if(pixel_count[8:0] < 9'd310) vid_cap_state_var[9:0] <= #1 VID_CAP3_STATE; else vid_cap_state_var[9:0] <= #1 VID_CAP6_STATE; end VID_CAP6_CASE: // add the rest of the address to the address counter to make up for rest of the line begin addr_index_count[17:0] <= addr_index_count[17:0] + 18'd010; line_count[7:0] <= line_count[7:0] + 8'd01; vid_cap_state_var[9:0] <= #1 VID_CAP7_STATE; end VID_CAP7_CASE: // check to see if we're at the end of the screen begin if(line_count[7:0] < 8'd230) vid_cap_state_var[9:0] <= #1 VID_CAP2_STATE; else vid_cap_state_var[9:0] <= #1 VID_CAP8_STATE; end VID_CAP8_CASE: // done begin vid_cap_state_var[9:0] <= #1 DISPATCH_STATE; end endcase end end // video_gen_state_fsm always @(vid_cap_state_var[9:0])begin : vid_gen_state_assn casex (vid_cap_state_var[9:0]) // synopsys parallel_case full_case DISPATCH_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'ha; beginning_of_screen_capture = 1'h1; end_of_screen_capture = 1'b0; end VID_CAP1_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h2; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP2_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h3; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP3_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h4; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP4_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h5; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP45_CASE: begin video1_store_strb = 1'b1; debug_state[3:0] = 4'h6; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP5_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h7; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP6_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h8; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP7_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'h9; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b0; end VID_CAP8_CASE: begin video1_store_strb = 1'b0; debug_state[3:0] = 4'ha; beginning_of_screen_capture = 1'h0; end_of_screen_capture = 1'b1; // used to trigger blob calculation end endcase end //video_gen_state_assn assign #1 video1_data_filtered[14:0] = data_valid ? video1_data[14:0] : 15'h0000; blob_detection my_blob_detector( .sys_clock(sys_clock), .force_reset(force_reset), .line_count(line_count[7:0]), .pixel_count(pixel_count[8:0]), .video1_out_strb(video1_store_strb), .video_filter_data_valid(data_valid), .end_of_screen_capture(end_of_screen_capture), .beginning_of_screen_capture(beginning_of_screen_capture), .x_output(blob1_x_out[23:0]), .y_output(blob1_y_out[23:0]), .blob_capture_done(blob_capture_done) ); endmodule |