module dvp_capture(
input clk,
input rst_n,
input vsync, href,
input [7:0] data,
output [15:0] pix_data,
output [11:0] haddr, vaddr,
output data_vld
);
reg [11:0] h_cnt, v_cnt;
reg [7:0] data_r1, data_r2;
reg href_r, vsync_r;
// 信号打拍用于边沿检测
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
href_r <= 0; vsync_r <= 0; data_r1 <= 0; data_r2 <= 0;
end else begin
href_r <= href; vsync_r <= vsync;
data_r1 <= data; data_r2 <= data_r1;
end
// 行计数器
always @(posedge clk or negedge rst_n)
if(!rst_n) h_cnt <= 0;
else if(href_r) h_cnt <= h_cnt + 1;
else h_cnt <= 0;
// 列计数器
always @(posedge clk or negedge rst_n)
if(!rst_n) v_cnt <= 0;
else if({vsync_r, vsync} == 2'b10) v_cnt <= 0;
else if({href_r, href} == 2'b10) v_cnt <= v_cnt + 1;
// RGB565 数据拼接
always @(posedge clk or negedge rst_n)
if(!rst_n) pix_data <= 0;
else pix_data <= {pix_data[7:0], data_r2};
assign data_vld = href_r && h_cnt[0];
assign haddr = h_cnt[11:1];
assign vaddr = v_cnt;
endmodule
module vga_timing(
input clk, rst_n,
output hsync, vsync, de,
output [11:0] haddr, vaddr
);
parameter H_TOTAL = 2200, H_ACTIVE = 1920;
parameter H_SYNC_START = 2008, H_SYNC_END = 2052;
parameter V_TOTAL = 1125, V_ACTIVE = 1080;
parameter V_SYNC_START = 1084, V_SYNC_END = 1089;
reg [11:0] h_cnt, v_cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n) h_cnt <= 0;
else if(h_cnt == H_TOTAL - 1) h_cnt <= 0;
else h_cnt <= h_cnt + 1;
always @(posedge clk or negedge rst_n)
if(!rst_n) v_cnt <= 0;
else if(h_cnt == H_TOTAL - 1)
if(v_cnt == V_TOTAL - 1) v_cnt <= 0;
else v_cnt <= v_cnt + 1;
assign hsync = (h_cnt >= H_SYNC_START) && (h_cnt < H_SYNC_END);
assign vsync = (v_cnt >= V_SYNC_START) && (v_cnt < V_SYNC_END);
assign de = (h_cnt < H_ACTIVE) && (v_cnt < V_ACTIVE);
assign haddr = h_cnt;
assign vaddr = v_cnt;
endmodule
module top(
input clk_100m, rst_n,
// DVP 接口
input [7:0] dvp_data, dvp_pclk, dvp_href, dvp_vsync,
output dvp_xclk, dvp_reset, dvp_pwdn,
// SCCB 接口
inout sccb_sda, sccb_scl,
// HDMI 接口
output hdmi_clk_p, hdmi_clk_n,
output [2:0] hdmi_d_p, hdmi_d_n
);
wire pclk, clk_5x;
// 时钟生成
clk_pll u_pll(.clk_in(clk_100m), .clk_out1(pclk), .clk_out3(clk_5x));
// 采集模块
dvp_capture u_capture(.clk(pclk), .rst_n(rst_n), .vsync(dvp_vsync), .href(dvp_href), .data(dvp_data), .pix_data(capture_data), .haddr(capture_h), .vaddr(capture_v), .data_vld(capture_vld));
// 帧缓冲控制
frame_buffer_ctrl u_fbuf(.clk(pclk), .rst_n(rst_n), .vsync(dvp_vsync), .display_vsync(display_vsync), .write_base_addr(write_addr), .read_base_addr(read_addr));
// SDRAM 控制器
sdram_ctrl u_sdram(.clk(clk_100m_pll), .rst_n(rst_n), .wr_addr(sdram_wr_addr), .wr_data(sdram_wr_data), .wr_en(sdram_wr_en), .rd_addr(sdram_rd_addr), .rd_data(sdram_rd_data), .rd_en(sdram_rd_en), /* SDRAM 芯片接口 */);
// HDMI 驱动
hdmi_driver u_hdmi(.clk(pclk), .clk_5x(clk_5x), .rst_n(rst_n), .rgb_data(display_data), .hdmi_clk_p(hdmi_clk_p), .hdmi_clk_n(hdmi_clk_n), .hdmi_d_p(hdmi_d_p), .hdmi_d_n(hdmi_d_n));
// SCCB 控制器
sccb_master u_sccb(.clk(clk_100m), .rst_n(rst_n), .sda(sccb_sda), .scl(sccb_scl));
endmodule