Verilog 图像数据时序生成(timing_gen/output)
一、要求
图像输出时序如下图所示,其中VSYNC_OUT
为场同步信号,HSYNC_OUT
为行同步信号,DATA_OUT
为16bit
图像信号,单个通道进行数据传输,输出格式为4096行*4096列*16bit
。
- 时钟为
60MHZ
, - HBLANK为512CLK,
- HSIZE为4096CLK,
- VSIZE为(4096+512)*4096+512=18874880CLK,
- VBLANK为14458453CLK
- DATA_OUT为
16bit
,一次传输4096
个数据。
二、程序设计
//此工程为EMCCD增益控制芯片的输出时序
module hv_data_output(
input rst_n,
input clk_60m,
(*mark_debug = "true"*)output clk_out,
(*mark_debug = "true"*)output reg vsync_ot,
(*mark_debug = "true"*)output reg hsync_ot,
(*mark_debug = "true"*)output reg [15:0] data_out
);
assign clk_out = clk_60m;
localparam HSIZE=16;
localparam HBLANK=2;
localparam VSIZE=16;
localparam VBLANK=20;
/*
行场同步信号生成
*/
//延迟5个周期输出
reg hsync_pre_reg1;
reg hsync_pre_reg2;
reg hsync_pre_reg3;
reg hsync_pre_reg4;
reg vsync_pre_reg1;
reg vsync_pre_reg2;
reg vsync_pre_reg3;
reg vsync_pre_reg4;
(*mark_debug = "true"*)reg [12:0] hcnt;
(*mark_debug = "true"*)reg [12:0] ycnt;
(*mark_debug = "true"*)wire hsync_pre;
(*mark_debug = "true"*)wire vsync_pre;
assign hsync_pre = (hcnt >= HBLANK && ycnt <= VSIZE-1) ? 1 : 0;
//(ycnt==VSIZE && hcnt<=HBLANK-1)?1:0;这一句就是为了后面产生最后多出来的一个HBLANK
assign vsync_pre = (ycnt <= VSIZE-1) ? 1: (ycnt==VSIZE && hcnt<=HBLANK-1)?1:0;
//检测vsync_pre下降沿,用于VBLANK的控制
(*mark_debug = "true"*)wire vsync_pre_neg;
assign vsync_pre_neg = !vsync_pre & vsync_pre_reg1;
(*mark_debug = "true"*)reg [12:0]vblank_cnt;
(*mark_debug = "true"*)reg vblank_cnt_flag;
always@( posedge clk_60m or negedge rst_n )
begin
if(!rst_n)begin
vblank_cnt_flag<=0;
end
else if (vsync_pre_neg) begin
vblank_cnt_flag<=1;
end
else if (vblank_cnt == VBLANK - 2) begin
vblank_cnt_flag<=0;
end
end
always@( posedge clk_60m or negedge rst_n )
begin
if(!rst_n)begin
vblank_cnt<=0;
end
else if (vblank_cnt_flag) begin
if (vblank_cnt < VBLANK - 2) begin
vblank_cnt<=vblank_cnt + 1;
end
else
vblank_cnt<=0;
end
end
//行场计数器
always@(posedge clk_60m or negedge rst_n)
begin
if(!rst_n)
hcnt <= 13'b0;
else if (vsync_pre)
begin
if(hcnt >= HSIZE + HBLANK -1)
hcnt <= 'b0;
else
hcnt <= hcnt + 1;
end
else
hcnt <= 0;
end
always@(posedge clk_60m or negedge rst_n)
begin
if(!rst_n)
ycnt <= 'b0;
else if (vblank_cnt == VBLANK - 2)//4097
ycnt <= 0;
//vsync_pre下降沿的时候也+1,是为了不让ycnt满足vsync_pre变化的条件,这样vsync_pre拉低不变
//与此同时,拉低过程中也能保证hcnt始终为0,直到满足VBLANK后ycnt归零,vsync_pre再拉高
else if((hcnt == HSIZE + HBLANK -1)||vsync_pre_neg)
ycnt <= ycnt+1;
else
ycnt <= ycnt;
end
//行场信号的延迟打拍
always@( posedge clk_60m or negedge rst_n )
begin
if(!rst_n)
begin
hsync_pre_reg1<=0;
hsync_pre_reg2<=0;
hsync_pre_reg3<=0;
hsync_pre_reg4<=0;
hsync_ot<=0;
vsync_pre_reg1<=0;
vsync_pre_reg2<=0;
vsync_pre_reg3<=0;
vsync_pre_reg4<=0;
vsync_ot<=0;
end
else
begin
hsync_pre_reg1<=hsync_pre;
hsync_pre_reg2<=hsync_pre_reg1;
hsync_pre_reg3<=hsync_pre_reg2;
hsync_pre_reg4<=hsync_pre_reg3;
hsync_ot<=hsync_pre_reg4;
vsync_pre_reg1<=vsync_pre;
vsync_pre_reg2<=vsync_pre_reg1;
vsync_pre_reg3<=vsync_pre_reg2;
vsync_pre_reg4<=vsync_pre_reg3;
vsync_ot<=vsync_pre_reg4;
end
end
/*
图像数据生成
*/
(*mark_debug = "true"*)reg cnt_flag;
always@(posedge clk_60m or negedge rst_n) begin
if(!rst_n)begin
cnt_flag <= 1;
end
else if (data_out == 65535)begin
cnt_flag <= 0;
end
else if (data_out == 0)begin
cnt_flag <= 1;
end
end
always@(posedge clk_60m or negedge rst_n) begin
if(!rst_n)begin
data_out <= 16'b0;
end
else if(hsync_ot == 1)begin
if (cnt_flag)begin
data_out = data_out + 1;
end
else
data_out = data_out - 1;
end
else
data_out = data_out;
end
endmodule
这里为了方便仿真,就把各个参数都设置的比较小。实际使用时,根据自己的需要设置好各个参数的值即可。