1.原理
场同步信号的单位是像素点
场同步信号的单位是一行
@60的含义是每秒钟刷新60帧图像
全0表示黑色
2.1 CLK_gen.v
module CLK_gen(
input wire sys_clk ,
input wire sys_rst_n ,
output wire CLK_out ,
output wire locked
);
parameter STATE=1'b0;
reg [1:0] cnt;
reg flag_clk;
assign locked=STATE;
assign CLK_out=flag_clk;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
cnt<=2'b0;
else if(cnt==2'd1)
cnt<=2'b0;
else
cnt<=cnt+1'b1;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
flag_clk<=1'b0;
else if(cnt==2'd1)
flag_clk<=1'b1;
else
flag_clk<=1'b0;
endmodule
2.2 Vga_ctrl.v
module Vga_ctrl(
input wire Vga_clk ,
input wire sys_rst_n ,
input wire [15:0] Pix_data ,
output wire [9:0] Pix_x ,
output wire [9:0] Pix_y ,
output wire [15:0] rgb ,
output wire hsync ,
output wire vsync
);
parameter H_SYNC=10'd96 ,
H_BACK=10'd40 ,
H_LEFT=10'd8 ,
H_VALID=10'd640 ,
H_RIGHT=10'd8 ,
H_FRONT=10'd8 ,
H_TOTAL=10'd800 ;
parameter V_SYNC=10'd2 ,
V_BACK=10'd25 ,
V_TOP=10'd8 ,
V_VALID=10'd480 ,
V_BOTTOM=10'd8 ,
V_FRONT=10'd2 ,
V_TOTAL=10'd525;
reg [9:0] Cnt_h;
reg [9:0] Cnt_v;
wire Rgb_valid;
wire pix_data_req;
assign Rgb_valid=(Cnt_h>=H_SYNC+H_BACK+H_LEFT
&&Cnt_h<H_SYNC+H_BACK+H_LEFT+H_VALID
&&Cnt_v>=V_SYNC+V_BACK+V_TOP
&&Cnt_v<V_SYNC+V_BACK+V_TOP+V_VALID)
?1'b1:1'b0;
//这里为什么不减1呢,画个简单的图就知道了
//因为前面的时间要满足H_SYNC+H_BACK+H_LEFT,
//有效信号是从他们之和加1开始计数的
//比如Cnt_h=10,就是计数了11个,
//而H_SYNC+H_BACK+H_LEFT=1+2+3=5
//所以前面要计满5个,也就是计数到4,10-5=5刚好是大于等于5开始信号有效
assign pix_data_req=(Cnt_h>=H_SYNC+H_BACK+H_LEFT-1'b1
&&Cnt_h<H_SYNC+H_BACK+H_LEFT+H_VALID-1'b1
&&Cnt_v>=V_SYNC+V_BACK+V_TOP
&&Cnt_v<V_SYNC+V_BACK+V_TOP+V_VALID)
?1'b1:1'b0;
assign Pix_x=pix_data_req?Cnt_h-(H_SYNC+H_BACK+H_LEFT-1'b1):10'h3ff;
assign Pix_y=pix_data_req?Cnt_v-(V_SYNC+V_BACK+V_TOP):10'h3ff;
//assign Pix_x=Rgb_valid?Cnt_h-(H_SYNC+H_BACK+H_LEFT):10'd0;
//assign Pix_y=Rgb_valid?Cnt_v-(V_SYNC+V_BACK+V_TOP):10'd0;
//这里也没有减1为什么呢
//同理Cnt_h是从0开始计数的,假如Cnt_h=10
//H_SYNC+H_BACK+H_LEFT=1+2+3=5
//那么此时的行坐标就等于10-5=5,因为前面的0-4是5个周期
//如果此时在H_SYNC+H_BACK+H_LEFT的基础上减1的话
//那么10-4=6,前面就是0-5等于6个时钟周期了,时序不符合
assign hsync=(Cnt_h<=H_SYNC-1'b1)?1'b1:1'b0;
assign vsync=(Cnt_v<=V_SYNC-1'b1)?1'b1:1'b0;
//为什么这里要减呢,因为Cnt_h是从0开始计数的,假如说计数到了10,就是0-11
//假如行同步信号是2个时钟周期,那么有效的就是第3个时钟周期,也就是计数到1.
//举个例子就能看出是不是需要减了
assign rgb=(Rgb_valid==1'b1)?Pix_data:16'd0;
always@(posedge Vga_clk or negedge sys_rst_n )
if(sys_rst_n==1'b0)
Cnt_h<=10'd0;
else if(Cnt_h==H_TOTAL-1'b1)
Cnt_h<=10'd0;
else
Cnt_h<=Cnt_h+1'b1;
always@(posedge Vga_clk or negedge sys_rst_n )
if(sys_rst_n==1'b0)
Cnt_v<=10'd0;
else if((Cnt_v==V_TOTAL-1'b1)&&(Cnt_h==H_TOTAL-1'b1))
Cnt_v<=10'd0;
else if(Cnt_h==H_TOTAL-1'b1)
Cnt_v<=Cnt_v+1'b1;
else
Cnt_v<=Cnt_v;
endmodule
2.3 tb_Vga_ctrl.v
module tb_Vga_ctrl();
reg sys_clk;
reg sys_rst_n ;
reg[15:0] Pix_data ;
wire [9:0] Pix_x ;
wire [9:0] Pix_y ;
wire [15:0]rgb ;
wire hsync ;
wire vsync ;
wire CLK_out ;
wire locked ;
wire rst_n;
initial
begin
sys_clk=1'b1;
sys_rst_n<=1'b0;
#20
sys_rst_n=1'b1;
end
assign rst_n=(sys_rst_n&&locked);
always#10 sys_clk=~sys_clk;
always@(posedge CLK_out or negedge rst_n)
if(rst_n==1'b0)
Pix_data<=16'h0000;
else if (Pix_x>=10'd0&&Pix_x<=10'd639
&&Pix_y>=10'd0&&Pix_y<=10'd479)
Pix_data<=16'hffff;
else
Pix_data<=16'h0000;
defparam CLK_gen_inst.STATE=1'b1;
Vga_ctrl Vga_ctrl_inst(
.Vga_clk (CLK_out) ,
.sys_rst_n (rst_n),
.Pix_data (Pix_data),
.Pix_x (Pix_x ),
.Pix_y (Pix_y ),
.rgb (rgb ) ,
.hsync (hsync ),
.vsync (vsync )
);
CLK_gen CLK_gen_inst(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ),
.CLK_out (CLK_out ) ,
.locked (locked )
);
endmodule
要显示1帧图像,1s是60帧,1帧就是0.0167s,所以等于16.7ms
时钟正确25mhz,锁定信号是拉高的,表示锁定信号在高电平时,时钟的输出有效,因为若锁定信号为0,那么复位信号就一直为0,时钟就起不了作用。
复位信号为0,数据就为0,坐标信号大于等于0且小于一定范围就为全为白色ffff。否则就全为0。
完成一帧
场同步信号也正确。
这里有错。因为有效信号多记了一个时钟周期
因此这里要修改数据有效信号
现在计数正确了
修改时钟换成分频后的信号
还是有问题,当数据有效时,数据仍为0。说明数据滞后数据有效信号一个时钟周期,所以得让数据提前一个时钟周期,解决方法是增加一个数据请求信号,比数据有效信号提前1时钟周期,然后rgb刚好滞后数据请求信号一个时钟周期。就达到了rgb和数据有效信号同步得效果。
末尾没有问题,原因是因为是时序逻辑,修改代码
行可以超前,但是场不用,场超前就是超前一行了,而行超前就是超前一个时钟周期。这里修改是要将pix_x超前一个时钟周期,然后再pi_data滞后一个周期,从而达到同步的效果
行计数器这里也要减1
请求信号确实超前有效信号一个时钟周期
末尾也正确
但是坐标还是不对
这下对了,为什么要让括号里面的信号减1呢?因为pix_data_req比数据有效信号提前了一个时钟周期,如果按照原来的不减1,那么坐标就会变小,提前数据有效信号一个时钟周期,要让坐标不变,就得让计数得值变大,所以减1。
数据和有效信号是同步的