Verilog 图像数据时序生成(timing_gen/output)

一、要求

图像输出时序如下图所示,其中VSYNC_OUT为场同步信号,HSYNC_OUT为行同步信号,DATA_OUT16bit图像信号,单个通道进行数据传输,输出格式为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

这里为了方便仿真,就把各个参数都设置的比较小。实际使用时,根据自己的需要设置好各个参数的值即可。

在这里插入图片描述
在这里插入图片描述

posted @ 2021-10-16 20:44  耐心的小黑  阅读(438)  评论(0编辑  收藏  举报