摄像头初始化通过IIC协议或者SCCB协议写入寄存器改写数据。初始化之前满足的条件如图所示。
module OV7670_INIT_IIC(
Clk,
Rst_n,
Start,
Iic_clk,
Sda,
Init_done
);
input Clk;
input Rst_n;
input Start;
output Iic_clk;
inout Sda;
output reg Init_done;
reg [7:0]data_cnt;//计数115个数据计数计数器
localparam DATA_SIZE = 8'd115;
wire [15:0]q_rom;
wire done_iic;
reg wr_en;
wire [7:0]wr_data;//写入的数据
wire [15:0]word_adrr;
reg [1:0]main_state;
wire ack ;
reg [9:0] cnt;
reg ok ;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 1'b0;
else
if(done_iic)
cnt <= 1'b0;
else
if(cnt == 10'd99) //计数2us
cnt <= 1'b0;
else
cnt <= cnt + 1'b1;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
ok <= 1'b0;
else
if(cnt == 10'd99)
ok <= 1'b1;
else
ok <= 1'b0;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
data_cnt <= 1'b0;
else
if(Start)
data_cnt <= 1'b0;
else
if(data_cnt < DATA_SIZE)
begin
if(done_iic && (!ack))
data_cnt <= data_cnt + 1'b1;
else
data_cnt <= data_cnt;
end
else
data_cnt <= DATA_SIZE;
//产生初始化完成标志信号
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Init_done <= 1'b0;
else
if(data_cnt == DATA_SIZE)
Init_done <= 1'b1;
else
Init_done <= 1'b0;
//状态机发送数据
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
begin
main_state <= 2'b0;
wr_en <= 1'b0;
end
else
begin
if(data_cnt < DATA_SIZE)
begin
case(main_state)
2'b0:
begin
if(Start)
main_state <= 2'd1;
else
main_state <= 2'd0;
end
2'd1:
begin
wr_en <= 1'b1;
main_state <= 2'd2;
end
2'd2:
begin
wr_en <= 1'b0;
if(ok)
main_state <= 2'd1;
else
main_state <= 2'd2;
end
default : main_state <= 1'b0;
endcase
end
else
begin
wr_en <= 1'b0;
main_state <= 1'b0;
end
end
//IIC模块
IIC IIC(
.Clk(Clk),
.Rst_n(Rst_n),
.Wr(wr_en),
.Read(1'b0),
.Wdata_num(1),
.Rdata_num(1'b1),
.Address_num(2'd1),
.Device_adress(8'h42), //器件片选地址
.Word_adrr(word_adrr), //存储单元地址
.Wr_data(wr_data),
.Rd_data(),
.Wr_data_vaule(),
.Rd_data_vaule(),
.Done(done_iic),
.ack(ack),
.Sda(Sda),
.Iic_clk(Iic_clk)
);
assign wr_data = q_rom[7:0];
assign word_adrr = q_rom[15:8];
OV7670_TABLE_ROM OV7670_TABLE_ROM
(
.addr(data_cnt),
.clk(Clk),
.q(q_rom)
);
endmodule
IIC单次写入8位115个不同寄存器地址的数据。
使用IIC协议初始化失败的原因主要是IIC总线空闲时间太短,及上一次写入完成产生停止位(上升沿)与下一次开始写入产生起始位(下降沿)间隔时间太短,不满足摄像头器件要求。器件要求如图所示。
而使用逻辑分析仪测得实际波形如图所示。
由图可以清楚的看到,当IIC协议第二次写入不同的寄存器地址时,从机未产生应答位,导致初始化失败,实际的总线空闲时间为700ns。
module OV7670_INIT_SCCB(
Clk ,
Rst_n ,
Start ,
Sccb_clk ,
Sda ,
Init_done
);
input Clk ;
input Rst_n ;
input Start ;
output Sccb_clk ;
output Sda ;
output reg Init_done ;
reg [7:0] addr_cnt ; //计数115次地址计数器
wire [15:0] q_rom ;
wire [7:0] wr_data ;
wire [7:0] word_adrr ;
wire wr_done ;
reg wr_en ;
reg [1:0] main_state ;
localparam DATA_SIZE = 115 ;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
addr_cnt <= 1'b0;
else
if(Start)
addr_cnt <= 1'b0;
else
if(addr_cnt < DATA_SIZE)
begin
if(wr_done)
addr_cnt <= addr_cnt + 1'b1;
else
addr_cnt <= addr_cnt ;
end
else
addr_cnt <= DATA_SIZE ;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Init_done <= 1'b0;
else
if(addr_cnt == DATA_SIZE)
Init_done <= 1'b1;
else
Init_done <= 1'b0;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
begin
main_state <= 2'b0;
wr_en <= 1'b0;
end
else
begin
if(addr_cnt < DATA_SIZE)
begin
case(main_state)
2'b0:
begin
if(Start)
main_state <= 2'd1;
else
main_state <= 2'd0;
end
2'd1:
begin
wr_en <= 1'b1;
main_state <= 2'd2;
end
2'd2:
begin
wr_en <= 1'b0;
if(wr_done)
main_state <= 2'd1;
end
default : main_state <= 1'b0;
endcase
end
else
begin
wr_en <= 1'b0;
main_state <= 1'b0;
end
end
assign wr_data = q_rom[7:0] ;
assign word_adrr = q_rom[15:8] ;
SCCB SCCB_inst(
.Clk (Clk ) ,
.Rst_n (Rst_n ) ,
.Wr (wr_en ) ,
.Wr_data (wr_data ) ,
.Wr_data_vaule () ,
.Wr_done (wr_done ) ,
.Word_adrr (word_adrr ) , //存储单元地址
.Device_adress (8'h42) , //器件地址
.Read () ,
.Rd_data () ,
.Rd_data_vaule () ,
.Rd_done () ,
.Sda (Sda ) ,
.Sccb_clk (Sccb_clk )
);
OV7670_TABLE_ROM OV7670_TABLE_ROM_insy
(
.addr (addr_cnt ) ,
.clk (Clk ) ,
.q (q_rom )
);
endmodule
与IIC初始化代码基本相同,因为只写不读数据。
SCCB模块代码中,在同一个always语句中第一个if语句判断优先级高于第二个if判断,由于初始化代码中的SCCB使能信号保持高电平导致一直产生SCCB协议时钟信号CLK,在CLK高电平时SDA信号未有产生下降沿及起始位,导致初始化失败。问题代码如图所示。
实际问题波形与正确波形比较如图所示。两个波形在CLK信号为高电平时产生上升沿即停止位,但是错误波形在CLK为高时没有产生下降沿即停止位。
module OV7670_TABLE_ROM
#(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=8)
(
input [(ADDR_WIDTH-1):0] addr,
input clk,
output reg [(DATA_WIDTH-1):0] q
);
// Declare the ROM variable
reg [DATA_WIDTH-1:0] rom[2**ADDR_WIDTH-1:0];
// Initialize the ROM with $readmemb. Put the memory contents
// in the file single_port_rom_init.txt. Without this file,
// this design will not compile.
// See Verilog LRM 1364-2001 Section 17.2.8 for details on the
// format of this file, or see the "Using $readmemb and $readmemh"
// template later in this section.
initial
begin
/*OV7670 VGA RGB565参数 */
rom[0 ][15:0] = 16'h3a_04; //
rom[1 ][15:0] = 16'h40_d0;
rom[2 ][15:0] = 16'h12_04; //VGA,RGB输出
//输出窗口设置
rom[3 ][15:0] = 16'h32_b6;
rom[4 ][15:0] = 16'h17_13;
rom[5 ][15:0] = 16'h18_01; //5
rom[6 ][15:0] = 16'h19_02;
rom[7 ][15:0] = 16'h1a_7a; //0x7a,
rom[8 ][15:0] = 16'h03_0a; //0x0a,
rom[9 ][15:0] = 16'h0c_00;
rom[10 ][15:0] = 16'h15_00;
rom[11 ][15:0] = 16'h3e_00; //10
rom[12 ][15:0] = 16'h70_00;
rom[13 ][15:0] = 16'h71_01;
rom[14 ][15:0] = 16'h72_11;
rom[15 ][15:0] = 16'h73_00; //
rom[16 ][15:0] = 16'ha2_02; //15
rom[17 ][15:0] = 16'h11_80; //时钟分频设置,0,不分频.
rom[18 ][15:0] = 16'h7a_20;
rom[19 ][15:0] = 16'h7b_1c;
rom[20 ][15:0] = 16'h7c_28;
rom[21 ][15:0] = 16'h7d_3c; //20
rom[22 ][15:0] = 16'h7e_55;
rom[23 ][15:0] = 16'h7f_68;
rom[24 ][15:0] = 16'h80_76;
rom[25 ][15:0] = 16'h81_80;
rom[26 ][15:0] = 16'h82_88;
rom[27 ][15:0] = 16'h83_8f;
rom[28 ][15:0] = 16'h84_96;
rom[29 ][15:0] = 16'h85_a3;
rom[30 ][15:0] = 16'h86_af;
rom[31 ][15:0] = 16'h87_c4; //30
rom[32 ][15:0] = 16'h88_d7;
rom[33 ][15:0] = 16'h89_e8;
rom[34 ][15:0] = 16'h13_e0;
rom[35 ][15:0] = 16'h00_00; //AGC
rom[36 ][15:0] = 16'h10_00;
rom[37 ][15:0] = 16'h0d_00;
rom[38 ][15:0] = 16'h14_28; //0x38, limit the max gain
rom[39 ][15:0] = 16'ha5_05;
rom[40 ][15:0] = 16'hab_07;
rom[41 ][15:0] = 16'h24_75; //40
rom[42 ][15:0] = 16'h25_63;
rom[43 ][15:0] = 16'h26_A5;
rom[44 ][15:0] = 16'h9f_78;
rom[45 ][15:0] = 16'ha0_68;
rom[46 ][15:0] = 16'ha1_03; //0x03,
rom[47 ][15:0] = 16'ha6_df; //0xdf,
rom[48 ][15:0] = 16'ha7_df; //0xdf,
rom[49 ][15:0] = 16'ha8_f0;
rom[50 ][15:0] = 16'ha9_90;
rom[51 ][15:0] = 16'haa_94; //
rom[52 ][15:0] = 16'h13_ef;
rom[53 ][15:0] = 16'h0e_61;
rom[54 ][15:0] = 16'h0f_4b;
rom[55 ][15:0] = 16'h16_02;
rom[56 ][15:0] = 16'h1e_11; //图像输出镜像控制.0x07,
rom[57 ][15:0] = 16'h21_02;
rom[58 ][15:0] = 16'h22_91;
rom[59 ][15:0] = 16'h29_07;
rom[60 ][15:0] = 16'h33_0b;
rom[61 ][15:0] = 16'h35_0b; //60
rom[62 ][15:0] = 16'h37_1d;
rom[63 ][15:0] = 16'h38_71;
rom[64 ][15:0] = 16'h39_2a;
rom[65 ][15:0] = 16'h3c_78;
rom[66 ][15:0] = 16'h4d_40;
rom[67 ][15:0] = 16'h4e_20;
rom[68 ][15:0] = 16'h69_00;
rom[69 ][15:0] = 16'h6b_00; //PLL*4=48Mhz
rom[70 ][15:0] = 16'h74_19;
rom[71 ][15:0] = 16'h8d_4f;
rom[72 ][15:0] = 16'h8e_00; //70
rom[73 ][15:0] = 16'h8f_00;
rom[74 ][15:0] = 16'h90_00;
rom[75 ][15:0] = 16'h91_00;
rom[76 ][15:0] = 16'h92_00; //0x19,//0x66
rom[77 ][15:0] = 16'h96_00;
rom[78 ][15:0] = 16'h9a_80;
rom[79 ][15:0] = 16'hb0_84;
rom[80 ][15:0] = 16'hb1_0c;
rom[81 ][15:0] = 16'hb2_0e;
rom[82 ][15:0] = 16'hb3_82; //80
rom[83 ][15:0] = 16'hb8_0a;
rom[84 ][15:0] = 16'h43_14;
rom[85 ][15:0] = 16'h44_f0;
rom[86 ][15:0] = 16'h45_34;
rom[87 ][15:0] = 16'h46_58;
rom[88 ][15:0] = 16'h47_28;
rom[89 ][15:0] = 16'h48_3a;
rom[90 ][15:0] = 16'h59_88;
rom[91 ][15:0] = 16'h5a_88;
rom[92 ][15:0] = 16'h5b_44; //90
rom[93 ][15:0] = 16'h5c_67;
rom[94 ][15:0] = 16'h5d_49;
rom[95 ][15:0] = 16'h5e_0e;
rom[96 ][15:0] = 16'h64_04;
rom[97 ][15:0] = 16'h65_20;
rom[98 ][15:0] = 16'h66_05;
rom[99 ][15:0] = 16'h94_04;
rom[100][15:0] = 16'h95_08;
rom[101][15:0] = 16'h6c_0a;
rom[102][15:0] = 16'h6d_55;
rom[103][15:0] = 16'h4f_80;
rom[104][15:0] = 16'h50_80;
rom[105][15:0] = 16'h51_00;
rom[106][15:0] = 16'h52_22;
rom[107][15:0] = 16'h53_5e;
rom[108][15:0] = 16'h54_80;
rom[109][15:0] = 16'h09_03; //驱动能力最大
rom[110][15:0] = 16'h6e_11; //100
rom[111][15:0] = 16'h6f_9f; //0x9e for advance AWB
rom[112][15:0] = 16'h55_00; //亮度
rom[113][15:0] = 16'h56_40; //对比度
rom[114][15:0] = 16'h57_80; //0x40, change according to Jim's request
end
always @ (posedge clk)
begin
q <= rom[addr];
end
endmodule
PCLK:摄像头输出时钟信号传输FPGA,不同分辨率频率不同。
VSYNC: 传输一张图片产生两个VSYNC脉冲,脉冲之间的低电平传输一次显示的整张图片。
HREF:在VSYNC两次脉冲之间传输有效,一次HREF高电平表示传输一行图片像素点,第二个HREF高电平表示传输第二行图片像素点。
Data:输出为RGB565数据(红5位,绿6位,蓝5位, 节省存储空间,提高存储器带宽利用率)。在HREF为高电平时传有效数据,每个PCLK上升沿变换数据。
每一个像素点由RGB三种颜色表示,两个8位Data数据传输一个像素点RGB(16位)数据。
module CAMERA_OV7670_DVP(
Rst_n ,
Clk_cmos , //驱动摄像头时钟
Cmos_pclk , //摄像头输入时钟
Cmos_vsync ,
Cmos_href ,
Cmos_data ,
Cmos_data_value ,
Cmos_data_pixel ,
Xaddress ,
Yaddress ,
Wr_rst , //·SDRAM中写缓存清零标志位
Cmos_xclk
);
input Cmos_pclk ;
input Rst_n ;
input Cmos_vsync ;
input Cmos_href ;
input [7:0] Cmos_data ;
input Clk_cmos ;
output Cmos_data_value ;//一行传输一个像素点RGB数据有效标志位
output [15:0] Cmos_data_pixel ;
output [11:0] Xaddress ;
output [11:0] Yaddress ;
output Cmos_xclk ;
output reg Wr_rst ;
reg mid_Cmos_vsync;
reg mid_Cmos_href;
reg [7:0]mid_Cmos_data;
reg [12:0]hcnt; //计数一行像素计数器 比地址多一位 地址两倍 每个像素点16位计数一个传8位
reg [11:0]ycnt; //计数多列像素计数器
reg [15:0]mid_Cmos_data_pixel;
reg mid_Cmos_data_value;//一行传输一个像素点RGB数据有效标志位
reg [3:0]del_frame_cnt;
reg delete_en;
assign Cmos_data_pixel = mid_Cmos_data_pixel;
assign Cmos_data_value = mid_Cmos_data_value && delete_en;
assign Cmos_xclk = Clk_cmos;
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
Wr_rst <= 1'b1;
else
if(mid_Cmos_vsync)
Wr_rst <= 1'b0;
else
Wr_rst <= Wr_rst;
always @(posedge Cmos_pclk or negedge Rst_n) //快速IO 使用IO寄存器提高时序性能
if(!Rst_n)
begin
mid_Cmos_href <= 1'b0;
mid_Cmos_vsync <= 1'b0;
mid_Cmos_data <= 8'd0;
end
else
begin
mid_Cmos_href <= Cmos_href;
mid_Cmos_vsync <= Cmos_vsync;
mid_Cmos_data <= Cmos_data;
end
//计数每行Cmos_data数据,每个Cmos_data8位
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
hcnt <= 1'b0;
else
if(mid_Cmos_href)
hcnt <= hcnt + 1'b1;
else
hcnt <= 1'b0;
assign Xaddress = hcnt[12:1]; //取高12位 相当于右移 FPGA避免除法
//输出两个Cmos_data8位数据 组成一个像素点16位数据
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
mid_Cmos_data_pixel <= 16'd0;
else
if(!hcnt[0]) //偶数传高8位 奇数传低8位
mid_Cmos_data_pixel[15:8] <= mid_Cmos_data; //偶数
else
mid_Cmos_data_pixel[7:0] <= mid_Cmos_data;
//一个像素点RGB数据传输成功标志信号
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
mid_Cmos_data_value <= 1'd0;
else
if(hcnt[0])
mid_Cmos_data_value <= 1'd1; //奇数
else
mid_Cmos_data_value <= 1'd0;
//多列计数器计数多列像素点
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
ycnt <= 1'b0;
else
if(mid_Cmos_vsync)
ycnt <= 1'b0;
else
if({mid_Cmos_href,Cmos_href} == 2'b01) //检测mid_Cmos_href上升沿 前 后
ycnt <= ycnt + 1'b1;
else
ycnt <= ycnt;
assign Yaddress = ycnt;
//舍弃前10帧
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
del_frame_cnt <= 1'b0;
else
if({mid_Cmos_vsync,Cmos_vsync} == 2'b01)
begin
if(del_frame_cnt >= 4'd10) //高速数据
del_frame_cnt <= 4'd10;
else
del_frame_cnt <= del_frame_cnt + 1'b1;
end
else
del_frame_cnt <= del_frame_cnt;
always @(posedge Cmos_pclk or negedge Rst_n)
if(!Rst_n)
delete_en <= 1'b0;
else
if(del_frame_cnt >= 4'd10)
delete_en <= 1'b1;
else
delete_en <= 1'b0;
endmodule
`timescale 1ns/1ns
`define Clk_period 60
module CAMERA_OV7670_DVP_tb;
reg Pclk;
reg Rst_n;
reg Vsync;
reg Href;
reg [7:0]Data;
wire Data_value;
wire [15:0]Data_pixel;
wire [11:0]Xaddress;
wire [11:0]Yaddress;
CAMERA_OV7670_DVP CAMERA_OV7670_DVP(
.Pclk(Pclk),
.Rst_n(Rst_n),
.Vsync(Vsync),
.Href(Href),
.Data(Data),
.Data_value(Data_value),
.Data_pixel(Data_pixel),
.Xaddress(Xaddress),
.Yaddress(Yaddress)
);
integer i,j ; //定义变量
parameter WITH = 16;
parameter HIGH = 12;
initial Pclk = 1;
always #(`Clk_period) Pclk = ~Pclk;
initial
begin
Rst_n = 0;
Vsync = 0;
Href = 0;
Data = 0;
#(200+1);
Rst_n = 1;
#200;
repeat(15)
begin
Vsync = 1;
#200;
Vsync = 0;
#300
for(i=0;i
仿真结果如图所示
Cmos_data_pixel输出Cmos_data位拼接的16位数据.
`include "disp_parameter.v"
module DVP_SDRAM_VGA(
//global port
input wire Clk ,
input wire Rst_n ,
//camera interface
input wire Cmos_pclk ,
input wire Cmos_vsync ,
input wire Cmos_href ,
input wire [7:0] Cmos_data ,
output wire Cmos_xclk , //驱动摄像头时钟
output wire Cmos_sclk ,
inout wire Cmos_sda ,
output wire Cmos_pwdn ,
output wire Cmos_rst_n ,
//SDRAM port
output wire Sdram_clk ,
output wire Sdram_cke ,
output wire Sdram_cs_n ,
output wire Sdram_cas_n ,
output wire Sdram_ras_n ,
output wire Sdram_we_n ,
output wire [1:0] Sdram_ba ,
output wire [12:0] Sdram_addr ,
inout wire [15:0] Sdram_dq ,
output wire [1:0] Sdram_dqm ,
//VGA port
output wire [`Red_Bits - 1 :0] Disp_red ,
output wire [`Green_Bits - 1 :0] Disp_green ,
output wire [`Blue_Bits - 1 :0] Disp_blue ,
output wire Hsync ,
output wire Vsync ,
output wire Clk_vga ,
output wire Clk_blk
);
reg [31:0] cnt ;
wire go ;
wire sys_rst_n ;
wire clk_cmos_24M ;
wire clk_100M ;
wire clk_shift_100M ;
wire clk_vga_24M ;
wire lock ;
wire init_done ;
wire wr_req ; //读SDRAM请求信号
wire [15:0] data_cmos ; //摄像头信号
wire pix_reg ;
wire [15:0] pix_data ;
wire wr_rst ;
wire [10:0] pix_x ;
wire [10:0] pix_y ;
wire rd_value_r ;
reg rd_value ;
assign Cmos_pwdn = 1'b0;
assign Cmos_rst_n = (cnt > 32'd175_000); //3.5ms
assign sys_rst_n = Rst_n && lock;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 1'b0 ;
else
if(cnt < 32'd6500_001) // 6.5ms
cnt <= cnt + 1'b1 ;
else
cnt <= cnt ;
assign go = (cnt == 32'd6500_000 ) ? 1'b1:1'b0;
assign rd_value_r = ((pix_x == 0) && (pix_y == 0))?1'b1:1'b0; //读缓存模块清零标志位
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
rd_value <= 1'b0;
else
if(rd_value_r)
rd_value <= 1'b1;
else
rd_value <= rd_value ;
pll pll_inst (
.areset ( !Rst_n ),
.inclk0 ( Clk ),
.c0 ( clk_cmos_24M ),
.c1 ( clk_100M ),
.c2 ( clk_shift_100M ),
.c3 ( clk_vga_24M ),
.locked ( lock )
);
OV7670_INIT_IIC OV7670_INIT_IIC_inst(
.Clk (Clk ) ,
.Rst_n (sys_rst_n ) ,
.Start (go ) ,
.Iic_clk (Cmos_sclk ) ,
.Sda (Cmos_sda ) ,
.Init_done (init_done )
);
CAMERA_OV7670_DVP CAMERA_OV7670_DVP_inst(
.Rst_n (sys_rst_n) ,
.Clk_cmos (clk_cmos_24M) , //驱动摄像头时钟
.Cmos_pclk (Cmos_pclk ) , //摄像头输入时钟
.Cmos_vsync (Cmos_vsync) ,
.Cmos_href (Cmos_href ) ,
.Cmos_data (Cmos_data ) ,
.Cmos_data_value (wr_req ) ,
.Cmos_data_pixel (data_cmos) ,
.Xaddress () ,
.Yaddress () ,
.Wr_rst (wr_rst) ,
.Cmos_xclk (Cmos_xclk)
);
SDRAM_TOP SDRAM_TOP_inst(
.Clk (clk_100M) ,
.Rst_n (sys_rst_n) ,
.Clk_out (clk_shift_100M) , //输入相位偏移时钟
.Wr_fifo_wr_clk (Cmos_pclk) ,
.Wr_fifo_wr_req (wr_req) ,
.Wr_fifo_wr_data (data_cmos) , //写入写FIFO中的
.Sdram_wr_b_addr (0) ,
.Sdram_wr_e_addr (640*480) ,
.Wr_burst_len (10'd512) ,
.Wr_rst (!sys_rst_n) , //写复位信号
.Rd_fifo_rd_clk (clk_vga_24M) ,
.Rd_fifo_rd_req (pix_reg) ,
.Sdram_rd_b_addr (0) ,
.Sdram_rd_e_addr (640*480) ,
.Rd_burst_len (10'd512) , //读突发长度
.Rd_rst (!sys_rst_n) , //读复位信号
.Rd_value (rd_value) ,
.Rd_fifo_rd_data (pix_data) , //读FIFO中读出的数据
.Rd_fifo_num () , //读FIFO中存在的数据个数
.Sdram_clk (Sdram_clk ) ,
.Sdram_cke (Sdram_cke ) ,
.Sdram_cs_n (Sdram_cs_n ) ,
.Sdram_cas_n (Sdram_cas_n) ,
.Sdram_ras_n (Sdram_ras_n) ,
.Sdram_we_n (Sdram_we_n ) ,
.Sdram_ba (Sdram_ba ) ,
.Sdram_addr (Sdram_addr ) ,
.Sdram_dq (Sdram_dq ) , // SDRAM 数据总线
.Sdram_dqm (Sdram_dqm )
);
VGA_CTRL VGA_CTRL_inst(
.Clk (clk_vga_24M) ,
.Rst_n (sys_rst_n) ,
.Pix_data ({pix_data[15:11],3'd0,pix_data[10:5],2'd0,pix_data[4:0],3'd0}) , //R G B
.Disp_red (Disp_red ) ,
.Disp_green (Disp_green) ,
.Disp_blue (Disp_blue ) ,
.Hsync (Hsync ) ,
.Vsync (Vsync ) ,
.Pix_x (pix_x) ,
.Pix_y (pix_y) ,
.Clk_vga (Clk_vga) ,
.Vga_blk (Clk_blk) , //VGA 场消隐信号
.Pix_reg (pix_reg)
);
// VGA_CTRL VGA_CTRL_inst(
// .Clk (clk_vga_24M) ,
// .Rst_n (sys_rst_n) ,
// .Pix_data (pix_data) , //R G B
// .Disp_red (Disp_red ) ,
// .Disp_green (Disp_green) ,
// .Disp_blue (Disp_blue ) ,
// .Hsync (Hsync ) ,
// .Vsync (Vsync ) ,
// .Pix_x (pix_x) ,
// .Pix_y (pix_y) ,
// .Clk_vga (Clk_vga) ,
// .Vga_blk (Clk_blk) , //VGA 场消隐信号
// .Pix_reg (pix_reg)
// );
endmodule
在文件中调用"disp_parameter.v"文件,可以选择RGB565或者RGB888模式展示。
实际运行如图所示。