ãŸããã
ç§ã¯ãããªåŠçã®ãããã¯ã«é·ãéèå³ãæã£ãŠããŸãããã第7ããã³ç¬¬9 ARMã®ãããã°ããŒãã§ã®ã¿éåžžã«ãã£ãããšå€æããããããã¯é¢çœããªããªããŸããã
çŸåšã匷åãªãã«ãã³ã¢ã¢ã€ãã³ããã£ã±ãã§ããããªãæäœããããã®å€ãã®ã©ã€ãã©ãªãäœæãããŠããŸãããç§ã®éžæã¯FPGAã«ããã£ãŠããŸããã
ãã®ãããžã§ã¯ãã¯ã5幎ãŸãã¯6幎åã«ãAliexpressã®åºèãé¡äŒŒã®åºèããªãã£ããšãã«ãFPGAãæèŒããããžã¿ã«ã«ã¡ã©ã¢ãžã¥ãŒã«ããããã°ããŒãããšãã§ããªããéã§è³Œå
¥ã§ããããã«ãªããŸããã ãããžã§ã¯ãã®æåã®ããŒãžã§ã³ã¯ãä»®èšããŒãäžã®æºåž¯é»è©±ããã®HV7131GPã«ã¡ã©ãSiemens S65ããã®ãã£ã¹ãã¬ã€ãããã³Terasic DE2ãããã°ããŒãã䜿çšããŠéå§ãããŸããã ããããçŽ5幎ã§ããããžã§ã¯ãã¯æ£ãšãã£ã¹ã¯ã«ã»ãããéããŠããŸããã
ãã®ããã«èŠããïŒ
ãã®åŸããã®ãããžã§ã¯ãå°çšã®ã¢ã«ãã©Cyclone II EP2C8F256 FPGAããŒããšOV7670ã«ã¡ã©ã¢ãžã¥ãŒã«ã賌å
¥ãããŸããã ããŒãã賌å
¥ããåŸãããŒãããªãã売ãæããªã¯ãšã¹ãã«å¿çããªãã£ãããšãå€æããŸããã ãããã¯ãŒã¯ãé·æéæãäžããåŸããã®ããŒãã§äœæããããããžã§ã¯ããèŠã€ããããããå²ãåœãŠãåããŸããã


ãã®èšäºã§ã¯ãã«ã¡ã©ããç»åããã£ããã£ããè²ç©ºéãå€æãããºãŒã ããHDMIã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠç»åã衚瀺ããã¢ã«ãã©FPGAã䜿çšããŠãããªã¹ããªãŒã å
ã®ãªããžã§ã¯ãã®åããæ€åºããæ¹æ³ã玹ä»ããŸãã
FPGAããã°ã©ãã³ã°ã¯ç§ã®äž»ãªå°éåéã§ã¯ãªãã空ãæéã®è¶£å³ã§ããããšã«ããã«æ°ä»ããŸãã ãããã£ãŠãç§ãäžããçµè«ã«èª€ã£ãŠããå¯èœæ§ããããç§ã®æ±ºå®ã¯æé©ãšã¯ã»ã©é ããããããŸããã Fmaxãè¿œæ±ããŠãã³ãŒãã®å€ãã®ã»ã¯ã·ã§ã³ã¯ãåé·ã§ãå¥åŠã§ãæå³ããªããæé©ã§ã¯ãªãããã«æžãããŠããŸãã
ããŒã«ããã
äž»ãªéçºç°å¢ãšããŠãMentor Graphicsã®HDL DesignerãéžæããŸããã ãã¹ãŠã®ã°ã©ãã£ãã¯ãããã¯ãšãããã®éã®ãã³ãã«ãå«ãŸããŠããŸãã ã¢ã«ãã©Quartus IIã¯ãåæãšãã¬ãŒã¹ã«äœ¿çšãããŸãã
ãããžã§ã¯ãæ§é
ãããžã§ã¯ãã®æ§é å³ã次ã®å³ã«ç€ºããŸãã 以äžã«è©³çŽ°ã«èª¬æããäž»ãªæ©èœãŠãããã®ã¿ãåæ ããŠããŸãã

HDL Designerãšãã£ã¿ãŒã§ã¯ã次ã®ããã«ãªããŸãã

ãã¹ãŠã®ãããžã§ã¯ããããã¯ãå³ã«è¡šç€ºãããããã§ã¯ãããŸããã ãããã¯ããé«ãã¬ãã«ã«ãããŸãã

ãã£ããã£ã¢ãžã¥ãŒã«

ãããªãã£ããã£ã¢ãžã¥ãŒã«ã¯ãYCbCr 4ïŒ2ïŒ2ãŸãã¯RGBïŒ565圢åŒã®ãã¯ã»ã«ããŒã¿ã«ã¡ã©ããå
¥åãåä¿¡ããhsyncãvsyncãã¬ãŒã ããã³ã©ã€ã³ã¹ãã£ã³å¶åŸ¡ä¿¡å·ãclkãã¡ã€ã³ïŒ50 MHzïŒã«è»¢éããå¶åŸ¡ä¿¡å·out_pixel_validãçæãã out_vclkãšããããããŒã¿åœ¢åŒå€æã¢ãžã¥ãŒã«ã«æž¡ããŸãã ãŸãããã®ã¢ãžã¥ãŒã«ã¯ã1ãã¬ãŒã ãããã®åä¿¡ããŒã¿éã«é¢ããout_statçµ±èšãçæããŸãã çµ±èšã¯UARTçµç±ã§èªã¿åãããšãã§ããŸãã ã¢ãžã¥ãŒã«ã¯ãå€éšcapt_enããŒã¿ãã£ããã£ã€ããŒãã«ä¿¡å·ã«ãã£ãŠå¶åŸ¡ãããŸãã ãã®ä¿¡å·ã¯ãèšå®ã®å®äºæã«ã«ã¡ã©èšå®ã¢ãžã¥ãŒã«ã«ãã£ãŠèšå®ãããŸãã Verilogã³ãŒãïŒ
ãã£ããã£ãŒalways @(posedge clk) begin hs_sync_1 <= hsync;hs_sync_2 <= hs_sync_1; vs_sync_1 <= vsync;vs_sync_2 <= vs_sync_1; vclk_sync_1 <= pclk;vclk_sync_2 <= vclk_sync_1; pixdata_sync_1 <= pixel_data;pixdata_sync_2 <= pixdata_sync_1; end reg vclk_old; always @(posedge clk)vclk_old <= vclk_sync_2; wire vclk_posedge = (vclk_old == 1'b0) && (vclk_sync_2 == 1'b1); reg sample_new,sample_hsync,sample_vsync; reg [7:0] sample_pixel; always @(posedge clk) begin sample_new <= vclk_posedge; if (vclk_posedge) begin sample_hsync <= hs_sync_2; sample_vsync <= vs_sync_2; sample_pixel <= pixdata_sync_2; end End reg last_vsync_sample,P2_vsync_triggered,P2_vsync_end_triggered; reg P2_sample_vsync,P2_sample_new,P2_sample_hsync; reg [7:0] P2_sample_pixel; reg P2_new_frame,capt_done,capt_enable; always @(posedge clk) begin if (capt_en == 1'b1 || P2_vsync_triggered == 1'b1) capt_enable <= 1'b1; else capt_enable <= 1'b0; end always @(posedge clk) if (!nRst) begin last_vsync_sample <= 1'b0,P2_vsync_triggered <= 1'b0; P2_vsync_end_triggered <= 1'b0,P2_new_frame <= 1'b0; capt_done <= 1'b0; end else begin if (capt_enable) begin if (sample_new) begin last_vsync_sample <= (sample_vsync); P2_sample_pixel <= sample_pixel; P2_sample_hsync <= sample_hsync; P2_sample_vsync <= sample_vsync; end // Pipeline Step P2_sample_new <= sample_new; if (!P2_vsync_end_triggered) begin if ((last_vsync_sample == 1'b1) && (sample_vsync == 1'b0)) begin P2_vsync_triggered <= 1'b1; P2_new_frame <= 1'b1; end if (P2_vsync_triggered && sample_vsync) begin P2_vsync_end_triggered <= 1'b1; P2_vsync_triggered <= 1'b0; capt_done <= ~capt_done; end end else begin P2_vsync_end_triggered <= 1'b0; P2_vsync_triggered <= 1'b0; end if (P2_new_frame) P2_new_frame <= 1'b0; end else begin last_vsync_sample <= 1'b0;P2_vsync_triggered <= 1'b0; P2_vsync_end_triggered <= 1'b0;P2_new_frame <= 1'b0;capt_done <= 1'b0; end end
ãã©ãŒãããå€æã¢ãžã¥ãŒã«

YCbCr 4ïŒ2ïŒ2圢åŒã¯ã以éã®äœæ¥ã«ã¯ããŸã䟿å©ã§ã¯ãããŸããã ããŒã¿ã¯æ¬¡ã®é åºã§ç¶ããŸããY0 Cb0 Y1 Cr1 Y2 Cb2 Y3 Cr3 ...ãããã£ãŠãYCbCr 4ïŒ4ïŒ4圢åŒã«å€æããŸãã å®éãå€æå
šäœã¯ãdata_strobä¿¡å·ã®1ã¯ããã¯ãµã€ã¯ã«ããšã«Y Cb CrããŒã¿ãåºåããããšã«ãªããŸãã Verilogã§ã¯ã次ã®ããã«ãªããŸãã
YCbCr 4ïŒ2ïŒ2 => 4ïŒ4ïŒ4 always @(posedge clk) if (!nRst) pix_ctr <= 2'b0; else begin if (pixel_valid) begin if (vclk) pix_ctr <= pix_ctr + 1'b1; end else pix_ctr <= 2'd0; end always @(posedge clk) case (pix_ctr) 2'd0:begin YYY <= pixel_data; CCr <= Crr; CCb <= Cbb; Ypix_clock <= 1'b1;end 2'd1:begin Cbb <= pixel_data; YY <= YYY; end 2'd2:begin YYY <= pixel_data; CCr <= Crr; CCb <= Cbb; Ypix_clock <= 1'b1;end 2'd3:begin Crr <= pixel_data; YY <= YYY; end endcase assign data_strob = Ypix_clock; assign Y = YY; assign Cb = CCb; assign Cr = CCr;
è²ç©ºéå€æã¢ãžã¥ãŒã«

æçµçã«ã¯ãåžžã«RGB圢åŒã®ããŒã¿ãåŠçãããããYCbCrããååŸããå¿
èŠããããŸãã ããã¯ãããŒã¿ã·ãŒãããã«ã¡ã©ãžã®åŒã«åŸã£ãŠè¡ãããŸãã
R = Y + 1.402ïŒCr-128ïŒ
G = Y-0.714ïŒCr-128ïŒ-0.344ïŒCb-128ïŒ
B = Y + 1.772ïŒCb-128ïŒVerilogã§ã¯ã次ã®ããã«ãªããŸãã
YCbCr => RGB parameter PRECISION = 11; parameter OUTPUT = 8; parameter INPUT = 8; parameter OUT_SIZE = PRECISION + OUTPUT; parameter BUS_MSB = OUT_SIZE + 2; always @ (posedge clk) if (!nRst) begin R_int <= 22'd0; G_int <= 22'd0; B_int <= 22'd0; end else begin if (istrb) begin //R = Y + 1.371(Cr - 128) R_int <= (Y_reg << PRECISION)+(C1*(Cr_reg-8'd128)); //G = Y - 0.698(Cr-128)-0.336(Cb-128) G_int <= (Y_reg << PRECISION)-(C2*(Cr_reg-8'd128))-(C3*(Cb_reg-8'd128)); //B = Y + 1.732(Cb-128) B_int <= (Y_reg << PRECISION)+(C4*(Cb_reg-8'd128)); end end assign R = (R_int[BUS_MSB]) ? 8'd16 : (R_int[OUT_SIZE+1:OUT_SIZE] == 2'b00) ? R_int[OUT_SIZE-1:PRECISION] : 8'd240; assign G = (G_int[BUS_MSB]) ? 8'd16 : (G_int[OUT_SIZE+1:OUT_SIZE] == 2'b00) ? G_int[OUT_SIZE-1:PRECISION] : 8'd240; assign B = (B_int[BUS_MSB]) ? 8'd16 : (B_int[OUT_SIZE+1:OUT_SIZE] == 2'b00) ? B_int[OUT_SIZE-1:PRECISION] : 8'd240;
RGBïŒ24ããRGBïŒ565å€æã¢ãžã¥ãŒã«

ãã®ã¢ãžã¥ãŒã«ã¯ã24ãããRGB圢åŒãã16ããããäœæããŸãã ç§ãã¡ã«ãšã£ãŠäŸ¿å©ã§ã ã¡ã¢ãªã¹ããŒã¹ãç¯çŽãããããã¬ãŒããåæžããç®çã«åã£ãã«ã©ãŒã¬ã³ããªã³ã°ãåããŠããŸããæãéèŠãªããšã¯ãSDRAMããŒã¿ã®1ã¯ãŒãã«åãŸããããäœæ¥ã倧å¹
ã«ç°¡çŽ åãããŸãã ããŒã¿ã¹ãããŒãä¿¡å·ã¯ãåã®ã¢ãžã¥ãŒã«ããåçŽã«éä¿¡ãããŸãã
ã¢ãžã¥ãŒã«ã³ãŒãã¯éåžžã«ç°¡åã§ãã
assign oRGB = {iR[7:3], iG[7:2], iB[7:3]}; assign ostrb = istrb;
ãªã¹ã±ãŒã©ãŒ

ãã®ã¢ãžã¥ãŒã«ã¯æåãããããžã§ã¯ãã«å°å
¥ãããŸããã ãã®ç®æšã¯ã640x480ãã¯ã»ã«ã®å
¥åã¹ããªãŒã ã320x240ã160x120ã128x120ã80x60ããã³320x480ã®ã¹ããªãŒã ã«å€æããããšã§ãã ãããã®ãã©ãŒãããã¯ãArduinoããŒãçšã®TFTãã£ã¹ãã¬ã€ã§ããSiemens S65ã®LCDãã£ã¹ãã¬ã€ã§åäœããCORDICã¢ã«ãŽãªãºã ã䜿çšããŠFPGAããã³SDRAMãããã¯ã¡ã¢ãªã«ç»åå転ãå®è£
ããããã«å¿
èŠã§ããã ã€ãŸããããã¯ä»ã®ãããžã§ã¯ãã®éºç£ã§ãã ãã®ãããžã§ã¯ãã§ã¯ãç»é¢ã®è§£å床ããã®å Žã§å€æŽããããšãã§ãããã®ã¢ãžã¥ãŒã«ã¯ããã§æåã®ãã€ãªãªã³ãæŒå¥ããŸãã ãã®ã¢ãžã¥ãŒã«ã¯ããããã°çšã«ãã¬ãŒã ããšã®ããŒã¿éã®çµ±èšãçæããŸãã ã¢ãžã¥ãŒã«ã¯é·ãéäœæãããŠããããã®ã³ãŒãã¯ãµãã¿ã€ãºããå¿
èŠããããŸãããåäœããŠããéã¯è§ŠããŸããã
ã¢ãžã¥ãŒã«ã³ãŒãã¯éåžžã«å®¹éã倧ããããããã®èšäºã§ã¯ãã®äž»èŠéšåã®ã¿ã説æããŸãã
ãªã¹ã±ãŒã©ãŒ always @(posedge clk) if (!nRst) begin w_ctr <= 16'd0;h_ctr <= 16'd0;frame_start <= 1'b0; rsmp_w <= 8'd0;rsmp_h <= 8'd0; end else begin if (resampler_init) begin w_ctr <= 16'd0;h_ctr <= 16'd0;frame_start <= 1'b0; rsmp_w <= 8'd0;rsmp_h <= 8'd0; end else begin /* This case works ONLY if the input strobe is valid */ if (istrb) begin if (w_ctr == I_WIDTH-1'b1) begin w_ctr <= 16'd0; if (h_ctr == I_HEIGHT-1'b1) begin h_ctr <= 16'd0; frame_start <= 1'b1; end else begin h_ctr <= h_ctr + 1'b1;frame_start <= 1'b0; end if (rsmp_h == H_FACT-1'b1) begin rsmp_h <= 8'd0; end else begin rsmp_h <= rsmp_h + 1'b1; end end else begin w_ctr <= w_ctr + 1'b1; frame_start <= 1'b0; end if (rsmp_w == W_FACT-1'b1) begin rsmp_w <= 8'd0; end else begin rsmp_w <= rsmp_w + 1'b1; end end end end reg pix_valid; always @(rsmp_w or rsmp_h or wh_multiply or H_FACT) begin if (wh_multiply == 1'b1) begin pix_valid = ((rsmp_w == 8'd0) && (rsmp_h == 8'd0))?1'b1:1'b0; end else begin pix_valid = ((rsmp_w == 8'd0) && (rsmp_h != 8'd0 ))?1'b1:1'b0; end end assign pixel_valid = pix_valid; always @(posedge clk) if (!nRst) begin frame_enable <= 1'b0; end else begin if (resampler_init) begin frame_enable <= 1'b0; end else begin if (frame_start) begin if (!lcd_busy) frame_enable <= 1'b1; else frame_enable <= 1'b0; end end end reg local_frame_start = 1'b0; always @(posedge clk) if (!nRst) begin ostrb_port <= 1'b0; dout_port <= 17'd0; local_frame_start <= 1'b0; end else begin local_frame_start <= frame_start ? 1'b1: local_frame_start; if (istrb && !resampler_init && !lcd_busy) begin if (pixel_valid) begin // if our column and our row if (frame_enable && !dout_dis) begin dout_port[16:0] <= {local_frame_start, din[15:0]}; ostrb_port <= 1'b1; local_frame_start <= 1'b0; end else begin ostrb_port <= 1'b0; end end else ostrb_port <= 1'b0; end else ostrb_port <= 1'b0; end
FIFO IN

ããã¯ã2ã¯ã©ããFIFO dcfifoãã¡ã¬ãã¡ã³ã¯ã·ã§ã³ã¢ã«ãã©256x17ã§ãã 16çªç®ã®ããã-frame_startä¿¡å·ã¯ããªã¹ã±ãŒã©ã®åŸã®æ°ãããã¬ãŒã ã®éå§ã瀺ãããã«è¿œå ãããŸãã
æžã蟌ã¿clocã¯50 MHzãèªã¿åãclocã¯100 MHzãã³ã³ãããŒã©ã®SDRAM clocã§ããããŸãã
èªã¿åã/æžã蟌ã¿ã³ã³ãããŒã©ãŒ

ãã®ããã°ãã¢ãžã¥ãŒã«ã¯ãFIFO INã¢ãžã¥ãŒã«ããããŒã¿ãååŸããŠãå¶æ°ãã¬ãŒã ãšå¥æ°ãã¬ãŒã ã®ç°ãªãã¡ã¢ãªé åã§äº€äºã«SDRAMã«æžã蟌ãã©ã€ã¿ãŒãšãSDRAMããããŒã¿ãèªã¿åããããããç¬èªã®ã¡ã¢ãªé åããé±æ«ã«æžã蟌ã2人ã®ãªãŒããŒã§ãã FIFO ãªãŒããŒã¯25 MHzïŒ640x480ïŒã®åšæ³¢æ°ã®HDMIã³ã³ãããŒã©ãŒã§åäœããé
延ã«èããããªãããããªãŒããŒãåªå
ãããŸããåŠçããã³è¡šç€ºçšã®ããŒã¿ã¯åžžã«FIFOã«ããå¿
èŠããããŸãã åºåFIFOæéãåããã®ã«æ®ã£ãŠããæéã¯ãç»é¢ã®éã¢ã¯ãã£ãé åã®æéã«FIFOã空ã«ããæéã足ãããã®ã§ãã©ã€ã¿ãŒã¯åäœããŸãã
ãã®ã¢ãžã¥ãŒã«ãéçºãããšããç§ã¯åé¡ã«ééããŸãããFIFOãã«ããã³ç©ºã®ä¿¡å·ã䜿çšãããšãFIFOãã¯ã©ãã·ã¥ããããŒã¿ãå£ãå§ããŸãã ããã¯FIFO INã§ã¯èµ·ãããŸããã ãã®äžã®æžã蟌ã¿ãããã¯ã®é »åºŠã¯ãããããã®èªã¿åãã®é »åºŠãããããªãäœãã§ãã ãã®ãã°ã¯ãFIFOã®é±æ«ã«çŸããŸãã 100 MHzã®æžã蟌ã¿ãããã¯ã¯ã25 MHzã®èªã¿åããããã¯ããã4åé«ããããç§ã®æšæž¬ã«ããã°ãæžã蟌ã¿ãã€ã³ã¿ãŒã¯èªã¿åããã€ã³ã¿ãŒã«è¿œãã€ããè¿œãè¶ããŸãã Alter FIFOã®ç¹å®ã®ãã°ã«é¢ãããããã¯ãŒã¯äžã®åç
§ãèŠã€ããŸãããããããåé¡ã«é¢é£ããŠãããã©ããã¯ããããŸããã wr_fullããã³rd_emptyã·ã°ãã«ã䜿çšããã®ã§ã¯ãªããwrusedwããã³rdusedwã·ã°ãã«ã䜿çšããŠãåé¡ã解決ããããšãã§ããŸããã fifo_almost_fullããã³fifo_almost_emptyãã§ãŒã³ã«æ²¿ã£ãŠFIFOç¶æ
ã³ã³ãããŒã©ãŒãäœæããŸããã 次ã®ããã«ãªããŸãã
// FIFO 1 wire out_fifo_almost_full = &fifo_wr_used[9:4]; wire out_fifo_almost_empty = !(|fifo_wr_used[10:8]); // FIFO 2 wire out_fifo_almost_full_2 = &fifo_wr_used_2[9:4]; wire out_fifo_almost_empty_2 = !(|fifo_wr_used_2[10:8]);
ãŸããã¢ãžã¥ãŒã«ã¯åäœã¢ãŒãã®å€æŽãå®è£
ããŸãïŒããã¯ã°ã©ãŠã³ãæžç®ãŸãã¯ãã¬ãŒã å·®åã ããã¯ãããŒãäžã®ã¯ããã¯ãã¿ã³ã«æ¥ç¶ãããŠããåŠç¿ä¿¡å·ã«ãã£ãŠå®çŸãããŸãã
ã¢ãžã¥ãŒã«ã®ã³ãŒãå
šäœã玹ä»ããããã§ã¯ãããŸãããããªãå€ããããŠããŠããããŸããã ãã®ã¢ãžã¥ãŒã«ã¯ãSDRAM 100 MHzã®åšæ³¢æ°ã§åäœããŸãã
SDRAMã³ã³ãããŒã©ãŒ

ãµã€ã
fpga4fun.comããã®ã¢ãžã¥ãŒã«ã¯
åºç€ãšããŠ
æ¡çšããããããåæåã®è¿œå ãšäžæã¯ããã¯ã®éµå®ã®ããã®è¿œå ã®é
延ã«ãããSDRAM K4S561632ãããã®ã¿ã€ãã«ãããã«ããçŽãããŸããã
è¡ã¢ã¯ãã£ãããè¡ã¢ã¯ãã£ãé
延ïŒtRRD 15 nç§
è¡ã®ããªãã£ãŒãžæéïŒtRP 20 nç§ã¢ãžã¥ãŒã«ã³ãŒãã¯ãäžèšã®ãªã³ã¯ã®ãµã€ãããããŠã³ããŒãã§ããŸãã äž»ãªåé¡ã¯ãSDRAMã®æ£ããåäœãšPLLã䜿çšããSDRAM_CLKãã³ãžã®ããã¯ã®äœçžã·ããã®éžæã®ããã«ãTimeQuestã«å®æ°ãæžã蟌ãããšã§ããã ããã§ãªããã°ããã¹ãŠãããã«æ©èœããŸããã æžã蟌ã¿ãšèªã¿åãã¯ããŒã¹ãã«ãã£ãŠè¡ãããã¢ã¯ãã£ããã³ã¯ã¯1ã€ã ãã4ã¡ã¬ãœãŒãã«äœ¿çšããããªãã¬ãã·ã¥ã¯äœ¿çšãããŸããã
FIFOåºå

FIFO INãšåæ§ã«ããããã®FIFOã¯2ãããã¯ã®1024x16 dcfifoã¡ã¬ãã¡ã³ã¯ã·ã§ã³ã§ãã
æžã蟌ã¿ã¯ããã¯ã¯100 MHzãèªã¿åãã¯ããã¯ã¯25 MHzã§ãã
åãæ€åºåš

ããã§ããã®ãããžã§ã¯ãã®å°çã®å¡©ã§ããã¢ãžã¥ãŒã«ã«ãã©ãçããŸããã ã芧ã®ãšãããäž¡æ¹ã®åºåFIFOã25 MHz HDMIã³ã³ãããŒã©ãŒã¯ããã¯pixel_clockãã«ãŠã³ã¿ãŒã«ãŠã³ã¿ãŒãã¯ã»ã«counter_xãcounter_yãããã³ã¢ã¯ãã£ããªãã£ã¹ãã¬ã€ä¿¡å·ãã©ã³ã¯ããããŒã¿ãšå¶åŸ¡ä¿¡å·ãåä¿¡ããŸãã RGBä¿¡å·ãåºåããã衚瀺ã®æºåãæŽããŸãã
ãŸããFIFOå æãã§ãŒã³ãå®è£
ããŸãã
// FIFO 1 wire in_fifo_data_avail = |fifo_rd_used[10:4]; wire in_fifo_almost_empty = !(|fifo_rd_used[10:4]); // FIFO 2 wire in_fifo_data_avail_2 = |fifo_rd_used_2[10:4]; wire in_fifo_almost_empty_2 = !(|fifo_rd_used_2[10:4]); wire fifos_available = in_fifo_data_avail & in_fifo_data_avail_2; wire fifos_almost_empty = in_fifo_almost_empty | in_fifo_almost_empty_2;
ã«ã¡ã©ããã®ç»åã衚瀺ããç»é¢ã®é åãå¶åŸ¡ããå¿
èŠããããŸãã
wire in_frame = ((counter_x < RES_X) && (counter_y < RES_Y))?1'b1:1'b0; wire frame_start = ((counter_x == 0) && (counter_y == 0))?1'b1:1'b0;
äž¡æ¹ã®FIFOã¯ãäž¡æ¹ã®ããŒã¿å¯çšæ§ãã©ã°ã«ãã£ãŠåæã«èªã¿åãããŸãã
// Reader FIFO 1 & 2 always @(posedge pix_clk or negedge nRst) if (!nRst) begin fifo_rd_req <= 1'b0; fifo_rd_req_2 <= 1'b0; pixel_data <= 16'h0000; worker_state <= 2'h1; end else begin case (worker_state) 2'h0: begin if (in_frame) begin if (fifos_almost_empty) begin //worker_state <= 2'h1; fifo_rd_req <= 1'b0; fifo_rd_req_2 <= 1'b0; end else begin pixel_data <= fifo_data; pixel_data_2 <= fifo_data_2; fifo_rd_req <= 1'b1; fifo_rd_req_2 <= 1'b1; end end else begin fifo_rd_req <= 1'b0; fifo_rd_req_2 <= 1'b0; end end 2'h1: begin if (blank) begin worker_state <= 2'h2; end end 2'h2: begin // start reading if more than 16 words are already in the fifo if (fifos_available && frame_start) begin fifo_rd_req <= 1'b1; fifo_rd_req_2 <= 1'b1; worker_state <= 2'h0; nd end endcase end
FIFOããèªã¿åãããããŒã¿ã¯RGBïŒ565圢åŒã§ãããã®ç®çã®ããã«ã¯ãçœé»ã«å€æããå¿
èŠããããŸãã ããã¯æ¬¡ã®ããã«è¡ãããŸãã
// Convert to grayscale frame 1 wire [7:0] R1 = {pixel_data[15 : 11], pixel_data[15 : 13]}; wire [7:0] G1 = {pixel_data[10 : 5], pixel_data[10 : 9]}; wire [7:0] B1 = {pixel_data[4 : 0], pixel_data[4 : 2]}; wire [7:0] GS1 = (R1 >> 2)+(R1 >> 5)+(G1 >> 1)+(G1 >> 4)+(B1 >> 4)+(B1 >> 5); // Convert to grayscale frame 2 wire [7:0] R2 = {pixel_data_2[15 : 11], pixel_data_2[15 : 13]}; wire [7:0] G2 = {pixel_data_2[10 : 5], pixel_data_2[10 : 9]}; wire [7:0] B2 = {pixel_data_2[4 : 0], pixel_data_2[4 : 2]}; wire [7:0] GS2 = (R2 >> 2)+(R2 >> 5)+(G2 >> 1)+(G2 >> 4)+(B2 >> 4)+(B2 >> 5);
GS1ããã³
GS2ä¿¡å·ã¯ãçœé»ã®ããã©ãŒãã³ã¹ã§ãã
ã¢ã«ãŽãªãºã ã«ã€ããŠå°ã説æããŸãã åããæ€åºããæ¹æ³ã¯ãããããããŸãã ãã®èšäºã§ã¯ããã®ãããžã§ã¯ãã®ãã¬ãŒã ã¯ãŒã¯å
ã§æãç°¡åã§æãç°¡åã«å®è£
ã§ããããã®ãã¡ã®2ã€ã ããæ€èšããŸãã
æåã®æ¹æ³ã ããã¯ã°ã©ãŠã³ãæžç®ã
ãã®èãæ¹ã¯ãæžç®ã䜿çšããŠãããªã¹ããªãŒã å
ã®åããŸãã¯ãªããžã§ã¯ããèŠã€ããããšã§ãã
P [FïŒtïŒ] = P [IïŒtïŒ]-P [B]P [FïŒtïŒ]ã¯çµæã®å·®ã§ãã
P [IïŒtïŒ]-ã«ã¡ã©ã®çŸåšã®ãã¬ãŒã ã
P [B]-åç
§ãã¬ãŒã ãŸãã¯èæ¯
åºæºãã¬ãŒã ãŸãã¯èæ¯ã¯éåžžãåãããªããšãã«æ®åœ±ãããŸãã ããšãã°ãéšå±ã®1ã€ã®ã³ãŒããŒã§åããæ€åºããå Žåããã®åã«åãããªããšãã«ãã®ã³ãŒããŒã®åçãæ®ã£ãŠèšæ¶ãããã¯ã»ã«ããšã«åŸç¶ã®åç»åãããã®èæ¯ãæžç®ããå¿
èŠããããŸãã ãã¹ãŠãéåžžã«ç°¡åã§ãã ãã ããç»åã®ãã€ãºãã«ã¡ã©ã®èªåãã¯ã€ããã©ã³ã¹ãããã³ãã®ä»ã®èŠå ã«ãããæ€åºåšã®ãããå€ãé©çšããå¿
èŠããããŸãã ãã®ãããå€ã¯ããã¬ãŒã ã®å·®ã«é©çšãããŸãã å·®ããããå€ãã倧ããå Žåã¯åãããããããã§ãªãå Žåã¯ãããŸããã
P [FïŒtïŒ]>ãããå€
ãã®æ¹æ³ã®çæã¯é·æ以äžã§ãããå®è£
ã容æãªãããã¢ãŒã·ã§ã³æ€åºã«äœ¿çšãããŸãã æ¬ ç¹ã¯æ¬¡ã®ãšããã§ãã
- å
äŸåæ§
- ã«ã¡ã©ãªãã»ãã
- 倩åã«äŸå
- èªåãã¯ã€ããã©ã³ã¹ã®å¹æ
å€éšèŠå ã®å€åã¯ãåãã®æ€åºãšæ€åºåšã®èª€æ€åºã«ã€ãªãããŸãã
æ¯Figçã«ãæ€åºåè·¯ã¯æ¬¡ã®ããã«ãªããŸãã

2çªç®ã®æ¹æ³ã ãã¬ãŒã å·®
ãã®å®è£
æ¹æ³ã¯ã以åã®å®è£
æ¹æ³ãšå€§å·®ãããŸããã ãã¹ãŠã®éãã¯ãèæ¯ã§ã¯ãªããåã®ãã¬ãŒã ãçŸåšã®ãã¬ãŒã ããå·®ãåŒããããã®å·®ããããå€ãšæ¯èŒãããããšã§ãã
æ°åŠçãªè¡šçŸã¯æ¬¡ã®ããã«ãªããŸãã
P [FïŒtïŒ] = P [IïŒtïŒ]-P [IïŒt-1ïŒ]>ãããå€ãã®æ¹æ³ã®å©ç¹ã¯ãå€éšèŠå ã«å¯Ÿããçžå¯Ÿçãªèæ§ã§ãã ã«ã¡ã©ã®äœçœ®ãç
§æã®å€åããã£ãŠããããã¯é·æçãªèª€å¿çãåŒãèµ·ãããã2ã€ã®é£ç¶ãããã¬ãŒã å
ã®çã誀å¿çã®ã¿ãåŒãèµ·ãããŸãã
æ¬ ç¹ã¯æ¬¡ã®ãšããã§ãã
- ãã¬ãŒã ã¬ãŒãäŸå
- äžåã®ãªããžã§ã¯ããæ€åºããããšã¯äžå¯èœ
- äœéã§ã®ãªããžã§ã¯ãã®åŒ±ãæ€åº
äžèšã®æ¬ ç¹ã®ããããã®æ¹æ³ã¯çŽç²ãªåœ¢ã§åºã䜿çšãããŠããŸããã
Verilogã®å®è£
ã
ç§ãã¡ã®å Žåãã©ã®ãã¬ãŒã ããæžç®ãããã«é¢ä¿ãªãããããã®éã®çµ¶å¯Ÿçãªå·®ã¯éèŠã§ãã
reg [7:0] difference = 0; wire [7:0] max_val = (GS1 > GS2) ? GS1 : GS2; wire [7:0] min_val = (GS1 < GS2) ? GS1 : GS2; always @(posedge pix_clk) begin if (in_frame) begin difference <= max_val - min_val; end else difference <= 8'h00; end wire [15:0] out_val = in_frame ? (difference > `BS_THRESHOLD) ? 16'hF1_00 : pixel_data_2 : in_frame2 ? pixel_data_diff : 16'h00_00;
ã³ãŒããããããããã«ãå·®ã
BS_THRESHOLDãããå€ãã倧ããå Žåããã¯ã»ã«ãèµ€è²ïŒ16'hF1_00ïŒã«
眮ãæããŸãã
ç»é¢ã«è¡šç€ºããã«ã¯ãããŒã¿ãRGBïŒ565圢åŒããRGBïŒ24圢åŒã«å€æããå¿
èŠããããŸã
HDMIã³ã³ãããŒã©ãŒ


äžéšããã®ã¢ãžã¥ãŒã«ã¯åããµã€ã
fpga4fun.com ããååŸããã
marsohod.orgã®èšäºã«åŸã£ãŠããçŽã
ããŸãã ã å·®åã䜿çšãã代ããã«ã LVDSãã¢ã¡ã¬ãã¡ã³ã¯ã·ã§ã³DDIOã䜿çšããŸããã ãããè¡ãããçç±ã¯ãäžèšã®ãªã³ã¯ã®èšäºãèªãããšã§èŠã€ããããšãã§ããŸãã
ãºã¿ãºã¿


50 MHzãããã¯ã¯ãã·ã¹ãã äžã®ãžã§ãã¬ãŒã¿ãŒãšããŠããŒãäžã®ãžã§ãã¬ãŒã¿ãŒããååŸãããŸããã SDRAMã³ã³ãããŒã©ããã³SDRAMãããã®ã¯ããã¯ã¯ãããã§æ§æãããŠããŸãã ãããã®ã·ã¥ã¬ããã®åšæ³¢æ°ã¯åã100 MHzã§ãããäœçžã90床ãããŠããŸãã ããã«ã¯ãã¡ã¬ãã¡ã³ã¯ã·ã§ã³PLLã䜿çšãããŸãã
Clok 125 MHzïŒclk_TMDS2ïŒã¯DDIOã«äœ¿çšããããã®åŸ250 MHzã«å€ãããŸãã ãã®ãããªããªãã¯ã
pixel_clockãããªããŒã¿ãããã¯ã¯25 MHzã§ã50 MHzã2ã€ã®ã·ã¹ãã ãããã¯ã«åå²ããŠäœæãããŸãã
OV7670ã«ã¡ã©ã®ã»ããã¢ãã

ã«ã¡ã©ãèšå®ããã«ã¯ã
ãµãŒãããŒãã£ã®SCCBã€ã³ã¿ãŒãã§ã€ã¹ã¢ãžã¥ãŒã«ã䜿çšãããŸãã ãããžã§ã¯ãã®ããŒãºã«åãããŠãããã«ããçŽããUARTã€ã³ã¿ãŒãã§ã€ã¹ããã³ãã³ãããªã³ã¶ãã©ã€ã§ã«ã¡ã©ã¬ãžã¹ã¿ã®å€ãèšé²ããããšãã§ããŸãã
UART

ã¢ãžã¥ãŒã«ã¯ãUARTã¬ã·ãŒããŒããã³ãã©ã³ã¹ããã¿ãŒãšio_controllerã¢ãžã¥ãŒã«ã§æ§æãããŠããŸã
åä¿¡æ©ãšéä¿¡æ©ã®ã¢ãžã¥ãŒã«ã®ã³ãŒãã¯ã€ã³ã¿ãŒãããããååŸãããŸããã ã¢ãžã¥ãŒã«ã¯ã8N1èšå®ã§115200ããŒã§åäœããŸãã

ãã®ã¢ãžã¥ãŒã«ïŒio_controllerïŒã¯ãUARTãã©ã³ã·ãŒããŒãšãããžã§ã¯ãã®å€éšã¢ãžã¥ãŒã«éã®ãªã³ã¯ã§ãã UARTã§çµ±èšåºåãæäŸããã³ãã³ããåä¿¡ããã³åŠçããŸãã ããã«ããã衚瀺解å床ã®å€æŽãã«ã¡ã©ããã®ããŒã¿ã®åºå圢åŒïŒYCbCrãŸãã¯RGBïŒã®å€æŽãã¬ãžã¹ã¿ãŒã®èšé²ãèŠæ±ãããçµ±èšã®è¡šç€ºãè¡ãããšãã§ããŸãã
çµæã瀺ããããª
ãããªå質ç§ã¯ãããªã®å質ããpoã³ããŸããç§ã¯ãã®ãããªé»è©±ãæã£ãŠããŸãã
ãããª1.ãã¬ãŒã ã®éã320x240圢åŒã®ã«ã¡ã©ããã®ç»åã¯ç»é¢ã®å·ŠåŽã«è¡šç€ºããããããå€ã®ãã¬ãŒã ã®éãã¯å³åŽã«ãããŸãã å·Šã®ç»åã¯ãåããæ€åºããå Žæã§èµ€ãæãŸã£ãŠããŸãã
ãããªã¯ããªããžã§ã¯ããåæ¢ããŠãããšãã¯åããæ€åºãããããªããžã§ã¯ãã®é床ãäœäžãããšæ€åºãèããæªåããããšã瀺ããŠããŸãã
ãããª2.ããã¯ã°ã©ãŠã³ãæžç®ãªããžã§ã¯ããã«ã¡ã©ã«è¿ã¥ããšããã¯ã€ããã©ã³ã¹ãå€åããæ€åºåšãã誀ã£ãå¿çãåãåãããšã«æ°ä»ããããããŸããã ãã®ãããªçŸè±¡ã¯ãã£ã«ã¿ãªã³ã°ãŸãã¯è£æ£ã§ããŸãã è£æ£æ¹æ³ã®1ã€ã¯ãåç
§ç»åïŒè¿äŒŒã¡ãã£ã¢ã³ãã£ã«ã¿ãŒïŒãå¹³ååãããã¬ãŒãã³ã°ã§ãã
çµè«
ãã®éçºã¯ãæ€åºã¢ã«ãŽãªãºã ãè€éã«ããããšã§æ¹åã§ããŸãã ãŸãããªããžã§ã¯ãã®åšå²ã«é·æ¹åœ¢ã®ãã¬ãŒã ãæç»ããããšã«ããã移åãããªããžã§ã¯ãã®è¿œè·¡ãå®è£
ãããšäŸ¿å©ã§ãã
ãããªã«ã¯æ°Žå¹³ã®é·æ¹åœ¢ã衚瀺ãããŸãã ãã®çŸè±¡ã¯ãSDRAMã³ã³ãããŒã©ãŒã®èªã¿åããã°ã«ãããã®ã§ããŸã å®å
šã«ã¯è§£æ±ºã§ããŠããŸããã
é¢é£è³æ
â
OpenCVã®ã¢ãŒã·ã§ã³æ€åºåšã«é¢ããèšäºâ
OpenCVã®ãã1ã€ã®æ€åºåšâ
ããã¯ã°ã©ãŠã³ãæžç®â
æ€åºåŒ·åæ¹æ³UPD
çŽæã©ããããããžã§ã¯ããå
¬éããŸãã Yandexãã£ã¹ã¯ã§å©çšå¯èœã ããã¯Quartusã§äœæããããããžã§ã¯ãã®ã³ããŒã§ããHDLDesignerã«ã¯æçš¿ããŸããããæçš¿ããŠã誰ã§ãéå§ãããããšã¯ã»ãšãã©ãããŸããããããžã§ã¯ããªã³ã¯