18.双线性插值缩放算法的matlab与FPGA实现(三)

`timescale 1ns / 1ps
//本模块目前设置的参数最大支持4K输入与4K输出30帧 K7 250Mhz A7 200Mhz

/*
	模块的实现思想
*/
module scaler_inact #(//原图像的大小
	parameter SRC_IW = 640 	,
	parameter SRC_IH = 480 	,
	//缩放后的大小
	parameter DST_IW = 1280 ,
	parameter DST_IH = 720 
)
(
	input				clk				, 	//输入时钟
	input				rst				, 	//复位
				
	input				pre_ready		, 	//DMA的后端FIFO准备好信号
	output				pre_req			, 	//数据请求信号
	input		[7:0]	pre_data		, 	//像素数据
	
	input				post_clk		,	//数据输出时钟
	output	reg			post_ready		, 	//数据输出准备好,用于后面模块的启动
	input				post_req		, 	//数据请求信号
	output		[7:0]	post_data		, 	//像素数据输出
	output				post_empty		 	//
);
//状态机   用于控制模块是处于读数据还是处理数据
reg		[2:0]	state				;
reg		[2:0]	state_r				;

reg				src_de				;
reg		[13:0]	src_hcnt			;
reg		[13:0]	src_vcnt			;
	
reg				dst_de				;
reg		[13:0]	dst_hcnt			;
reg		[13:0]	dst_vcnt			;

//计算期望的原图像行数标志
reg		[15:0]	expt_src_vcnt0		;		
reg		[31:0]	expt_src_vcnt1		;
reg		[25:0]	expt_src_vcnt2		;
reg		[13:0]	expt_src_vcnt3		;

//计算期望的原图像行数   两个计算期望的行数使能
reg				expt_src_vcnt_de	;
reg				expt_src_vcntp1_de	;
	
//计算期望的原图像行数的中间数据
reg				expt_src_vcnt_de0	;		
reg				expt_src_vcnt_de1	;
reg				expt_src_vcnt_de2	;
reg				expt_src_vcnt_de3	;

reg		[15:0]	src_xf0				;		
reg		[31:0]	src_xf1				;
reg		[25:0]	src_xf2				;
reg		[25:0]	src_xf3				;

reg		[15:0]	src_yf0				;		
reg		[31:0]	src_yf1				;
reg		[25:0]	src_yf2				;
reg		[25:0]	src_yf3				;

reg		[13:0]	src_x0				;
reg		[13:0]	src_x1              ;

reg		[13:0]	src_y0				;
reg		[13:0]	src_y1              ;

wire			full				;	
wire	[13:0]	rd_data_count		;	
wire	[13:0]	wr_data_count		;

//fix16_12
//计算缩放系数
localparam  [15:0]	sx  =  SRC_IW*4096/DST_IW	;
localparam  [15:0]	sy  =  SRC_IH*4096/DST_IH	;
localparam          buf_line  =  3;

always@(posedge clk)
	if(rst)
		begin
			dst_de 		<= 0;
			state  		<= 0;
		end
	else if(pre_ready==1'b1)
		case(state)
			0:	 
				if(wr_data_count<DST_IW*buf_line-13) //缩放数据存储未达标
					begin
						state 	 <= 2;	//开始判断是往RAM里面读数据还是进行缩放像素计算
					end		
				else
					begin
						state 	 <= state;
					end	
			1:  
				if(src_hcnt==SRC_IW-1) 	 	//一行数据读取完毕
					begin
						state 	<= 2; 		//继续判断是往RAM里面读数据还是进行缩放像素计算
					end
				else 
					begin
						state 	<= state;
					end		
			2:  
				if(src_vcnt>=expt_src_vcnt3&&expt_src_vcnt_de3==1'b1) 	//计算出当前行数符合缩放需要的行
					begin
						state 	<= 3; 			//跳转到缩放像素计算的状态
					end
				else if(src_vcnt<expt_src_vcnt3&&expt_src_vcnt_de3==1'b1) 	//计算出当前行数不符合缩放需要的行
					begin
						state 	<= 1; 		//跳转到行数读取状态
					end
				else 
					begin
						state 	<= state;
					end					
			3:  
				if(dst_hcnt==DST_IW-1)  	//一行缩放后的像素计算完毕
					begin
						dst_de  <= 0;
						state 	<= 0; 		//进入等待行缓存填满
					end
				else 
					begin
						dst_de  <= 1; 	 	//一行像素计算未完毕,继续计算
						state 	<= state;
					end	
			default:;
		endcase				
	else
		begin
			dst_de <= 0;
			state  <= 0;
		end

always@(posedge clk)
	if(rst)
		state_r <= 'd0;
	else
		state_r <= state;
/**********************************************原图像的读入****************************************************/
//当进入2状态的时候计算使能拉高
always@(posedge clk)
	if(rst)
		expt_src_vcnt_de <= 1'b0;
	else if(state_r!=2&&state==2)
		expt_src_vcnt_de <= 1'b1;
	else
		expt_src_vcnt_de <= 1'b0;	

//当进入3状态的时候,计算使能也拉高
always@(posedge clk)
	if(rst)
		expt_src_vcntp1_de <= 1'b0;
	else if(state_r!=3&&state==3)
		expt_src_vcntp1_de <= 1'b1;	
	else
		expt_src_vcntp1_de <= 1'b0;	

//状态1的时候拉高原图像的读使能  让数据进来   且在状态3的时候也让数据进来
always@(posedge clk)
	if(rst)
		src_de <= 1'b0;
	else if(src_hcnt==SRC_IW-1)
		src_de <= 1'b0;
	else if(state_r!=1&&state==1) 	//进入1状态的时候拉高读数据使能
		src_de <= 1'b1;
  	else if(src_vcnt<expt_src_vcnt3&&expt_src_vcnt_de3==1'b1&&state==3)	   //在3状态的时候计算出下一行不符合行数要求的时候也拉高
		src_de <= 1'b1;
	else
		src_de <= src_de;

//原图像的行列计数以及使能
always@(posedge clk)
	if(rst)		
		src_hcnt <= 'd0;
	else if(src_hcnt==SRC_IW-1)
		src_hcnt <= 'd0;
	else if(src_de==1'b1)
		src_hcnt <= src_hcnt + 1'b1;
	else
		src_hcnt <= src_hcnt;

always@(posedge clk)
	if(rst)		
		src_vcnt <= 'd0;
	else if(src_vcnt==SRC_IH&&dst_hcnt==DST_IW-1&&dst_vcnt==DST_IH-1)	
		src_vcnt <= 'd0;
	else if(src_hcnt==SRC_IW-1)
		src_vcnt <= src_vcnt + 1'b1;
	else
		src_vcnt <= src_vcnt;

assign pre_req = src_de;

/*********************************************原图像的存储*********************************************************/
reg		[13:0]	wr_addr_cnt			;		
reg		[1:0]	wr_addr_sel			;

//二维数组  [3:0]独热码区分四个不同的RAM
reg		[11:0]	pre_wr_addr	[3:0]	;

wire			wr_addr_de	[3:0]	;
reg		[11:0]	wr_addr		[3:0]	;

reg		[11:0]	rd_addr		[3:0]	;
reg		[11:0]	rd_addr_w	[3:0]	;

wire	[7:0]	douta   	[3:0]	;
wire	[7:0]	doutb   	[3:0]	;
//按照0-1-2-3-0这样的顺序依次循环存储
always@(posedge clk)
	if(rst)		
		wr_addr_sel <= 'd0;
	else if(wr_addr_cnt==SRC_IW-1&&wr_addr_sel==3)
		wr_addr_sel <= 'd0;
	else if(wr_addr_cnt==SRC_IW-1)
		wr_addr_sel <= wr_addr_sel + 1'b1;
	else
		wr_addr_sel <= wr_addr_sel;
		
always@(posedge clk)
	if(rst)		
		wr_addr_cnt <= 'd0;
	else if(wr_addr_cnt==SRC_IW-1)
		wr_addr_cnt <= 'd0;
	else if(pre_req==1'b1)
		wr_addr_cnt <= wr_addr_cnt + 1'b1;
	else
		wr_addr_cnt <= wr_addr_cnt;

genvar i;
generate
  for (i=0; i < 4; i=i+1)
  begin: wr_src_data
	
	assign wr_addr_de[i] = (pre_req==1'b1&&wr_addr_sel==i);
	//四个RAM的读数据的地址信号
	always@(posedge clk)
		if(rst)			
			pre_wr_addr[i] <= 'd0;
		else if(pre_wr_addr[i]==SRC_IW-1)
			pre_wr_addr[i] <= 'd0;
		else if(wr_addr_de[i]==1'b1)
			pre_wr_addr[i] <= pre_wr_addr[i] + 1'b1;
		else
			pre_wr_addr[i] <= pre_wr_addr[i];
	//这里读写端口分别对应x0 和x1
	always@(*)
		if(rst)			
			wr_addr[i] = 'd0;
		else if(wr_addr_de[i]==1'b1)
			wr_addr[i] = pre_wr_addr[i];
		else
			wr_addr[i] = rd_addr_w[i];			
		
		tdpram #(
			.AW (12),
			.DW (8 )  
		)
		u1_tdpram 
		(
		  .clka		(clk			),
		  .wea		(wr_addr_de[i]	),
		  .addra	(wr_addr[i]		),
		  .dina		(pre_data		),
		  .douta	(douta[i]		),
		  .clkb		(clk			),
		  .web		(1'b0			),
		  .addrb	(rd_addr[i]		),
		  .dinb		(8'd0			),
		  .doutb	(doutb[i]		) 
		);		
  end
endgenerate
		
always@(posedge clk)
	if(rst)		
		dst_hcnt <= 'd0;
	else if(dst_hcnt==DST_IW-1)
		dst_hcnt <= 'd0;
	else if(dst_de==1'b1)
		dst_hcnt <= dst_hcnt + 1'b1;
	else
		dst_hcnt <= dst_hcnt;

always@(posedge clk)
	if(rst)		
		dst_vcnt <= 'd0;
	else if(dst_hcnt==DST_IW-1&&dst_vcnt==DST_IH-1)
		dst_vcnt <= 'd0;
	else if(dst_hcnt==DST_IW-1)
		dst_vcnt <= dst_vcnt + 1'b1;
	else
		dst_vcnt <= dst_vcnt;
/*****************************************************根据读的目标图像的行列计数来计算出原图像应该的行列计数*************************************************************/
always@(posedge clk)
	if(rst)		
		begin
			expt_src_vcnt_de0 <= 1'b0;
			expt_src_vcnt_de1 <= 1'b0;
			expt_src_vcnt_de2 <= 1'b0;
			expt_src_vcnt_de3 <= 1'b0;
		end
	else
		begin
			expt_src_vcnt_de0 <= expt_src_vcnt_de||expt_src_vcntp1_de;
			expt_src_vcnt_de1 <= expt_src_vcnt_de0;
			expt_src_vcnt_de2 <= expt_src_vcnt_de1;
			expt_src_vcnt_de3 <= expt_src_vcnt_de2;
		end		
//**************************计算src_yf = ((i-1)+0.5) * sy - 0.5;%的过程*******************/
//fix16_2 + fix0_2 = fix16_2
always@(posedge clk)
	if(rst)	
		expt_src_vcnt0 <= 'd0;
	else if(expt_src_vcnt_de==1'b1)
		expt_src_vcnt0 <= {dst_vcnt,2'd0} + 2;//0.5*4;	
	else if(expt_src_vcntp1_de==1'b1&&dst_vcnt<DST_IH-1)
		expt_src_vcnt0 <= {dst_vcnt+1,2'd0} + 2;	
	else
		expt_src_vcnt0 <= 'd0;
//fix16_2 * fix16_12 = fix32_14
always@(posedge clk)
	if(rst)	
		expt_src_vcnt1 <= 'd0;
	else
		expt_src_vcnt1 <= expt_src_vcnt0*sy;
//fix26_12 - fix12_12 = fix26_12		
always@(posedge clk)
	if(rst)	
		expt_src_vcnt2 <= 'd0;
	else
		expt_src_vcnt2 <= expt_src_vcnt1[27:2] - 2048;
//fix26_12	-> 取整 + 2 = fix14_0 + 2	
always@(posedge clk)
	if(rst)	
		expt_src_vcnt3 <= 'd0;
	else if(expt_src_vcnt2[25]==1'b1)
		expt_src_vcnt3 <= 'd2; 			//这里取2是因为这个值代表了原图像的像素读到第几行为止,根据状态机可知当这个数等于2时会读取0和1行
	else if(expt_src_vcnt2[25:12]>SRC_IH-2)
		expt_src_vcnt3 <= SRC_IH;
	else
		expt_src_vcnt3 <= expt_src_vcnt2[25:12] + 2;
/*****************************************************根据目标图像的行列计数来计算插值所需的四个点坐标x0  x1   y0   y1*************************************************************/
reg		dst_de0	 	;
reg		dst_de1  	;
reg		dst_de2  	;

reg		src_xy_de   ;

always@(posedge clk)
	if(rst)	
		begin	
			dst_de0 <= 1'b0;
			dst_de1 <= 1'b0;
			dst_de2 <= 1'b0;
		end
	else
		begin	
			dst_de0 <= dst_de;
			dst_de1 <= dst_de0;
			dst_de2 <= dst_de1;
		end		

always@(posedge clk)
	if(rst)	
		src_xy_de <= 1'b0;
	else
		src_xy_de <= dst_de2;
	
//**************************计算src_xf的过程*******************/
/*
	src_xf = ((j-1)+0.5) * sx - 0.5;%浮点数
	if(src_xf<0)
		src_x0 = 0;
	else
		src_x0 = floor(src_xf);
	end

	src_x1 = src_x0 + 1;
*/

//fix16_2 + fix2_2  = fix16_2
always@(posedge clk)
	if(rst)	
		src_xf0 <= 'd0;
	else if(dst_de==1'b1)
		src_xf0 <= {dst_hcnt,2'd0} + 2;
	else
		src_xf0 <= 'd0;
//fix16_2 * fix16_12  = fix32_14		
always@(posedge clk)
	if(rst)	
		src_xf1 <= 'd0;
	else
		src_xf1 <= src_xf0*sx;
//fix26_12 - fix12_12  = fix26_12 可能为负数
always@(posedge clk)
	if(rst)	
		src_xf2 <= 'd0;
	else
		src_xf2 <= src_xf1[27:2] - 2048;
//这里的打拍用于计算权重	
always@(posedge clk)
	if(rst)	
		src_xf3 <= 'd0;
	else
		src_xf3 <= src_xf2;		

always@(posedge clk)
	if(rst)	
		src_x0 <= 'd0;
	else if(src_xf2[25]==1'b1)
		src_x0 <= 'd0;		
	else
		src_x0 <= src_xf2[25:12];
		
always@(posedge clk)
	if(rst)	
		src_x1 <= 'd0;
	else if(src_xf2[25]==1'b1)
		src_x1 <= 'd1;
	else
		src_x1 <= src_xf2[25:12] + 1'b1;
	
//**************************计算src_yf的过程*******************/
/*
    src_yf = ((i-1)+0.5) * sy - 0.5;%浮点数
        if(src_yf<0)
            src_y0 = 0;
        else 
            src_y0 = floor(src_yf);
        end

        src_y1 = src_y0 + 1;
*/

//fix16_2 + fix2_2  = fix16_2
always@(posedge clk)
	if(rst)	
		src_yf0 <= 'd0;
	else if(dst_de==1'b1)
		src_yf0 <= {dst_vcnt,2'd0} + 2;
	else
		src_yf0 <= 'd0;
//fix16_2 * fix16_12  = fix32_14		
always@(posedge clk)
	if(rst)	
		src_yf1 <= 'd0;
	else
		src_yf1 <= src_yf0*sy;
//fix26_12 - fix12_12  = fix26_12 可能为负数
always@(posedge clk)
	if(rst)	
		src_yf2 <= 'd0;
	else
		src_yf2 <= src_yf1[27:2] - 2048;

always@(posedge clk)
	if(rst)	
		src_yf3 <= 'd0;
	else
		src_yf3 <= src_yf2;

always@(posedge clk)
	if(rst)	
		src_y0 <= 'd0;
	else if(src_yf2[25]==1'b1)
		src_y0 <= 'd0;
	else
		src_y0 <= src_yf2[25:12];		

always@(posedge clk)
	if(rst)	
		src_y1 <= 'd0;
	else if(src_yf2[25]==1'b1)
		src_y1 <= 'd1;
	else
		src_y1 <= src_yf2[25:12] + 1'b1;
/*****************************************************开始插值计算*************************************************************/		
/*
	%根据四个点坐标以及待求点坐标计算出四个权重
	w11 = (src_x1 - src_xf) * (src_y1 - src_yf);   
	w21 = (src_xf - src_x0) * (src_y1 - src_yf);
	w12 = (src_x1 - src_xf) * (src_yf - src_y0);
	w22 = (src_xf - src_x0) * (src_yf - src_y0);
	%下面的+1是为了对应索引  与上面的+1求相邻坐标不一样
	if(src_y0 >= row - 1 && src_x0 >= col - 1)
		line_data(i,j) =    src_data(src_y0 + 1,src_x0 + 1) * w11;
	elseif(src_y0 >= row - 1)
		line_data(i,j) =    src_data(src_y0 + 1,src_x0 + 1) * w11 + ...
							src_data(src_y0 + 1,src_x1 + 1) * w12;
	elseif(src_x0 >= col - 1)
		line_data(i,j) =    src_data(src_y0 + 1,src_x0 + 1) * w11 + ...
							src_data(src_y1 + 1,src_x0 + 1) * w21;
	else
		line_data(i,j) =    src_data(src_y0 + 1,src_x0 + 1) * w11 + ...
							src_data(src_y1 + 1,src_x0 + 1) * w21 + ...
							src_data(src_y0 + 1,src_x1 + 1) * w12 + ...
							src_data(src_y1 + 1,src_x1 + 1) * w22;
	end 
*/
reg	[2:0]	region_type		;   //当前的像素属于什么区域,不同的像素区域对应不同的插值计算方式(权重不同)
reg	[2:0]	region_type_r	;
reg	[2:0]	region_type_r1	;
reg	[2:0]	region_type_r2	;
reg	[2:0]	region_type_r3	;
reg	[2:0]	region_type_r4	;

always@(posedge clk)
	if(rst)	
		region_type <= 0;
	else if(src_x0>=SRC_IW-1&&src_y0>=SRC_IH-1&&src_xy_de==1'b1)    //最后一个像素点
		region_type <= 1;
	else if(src_y0>=SRC_IH-1&&src_xy_de==1'b1)       //最下面一行像素
		region_type <= 2;
	else if(src_x0>=SRC_IW-1&&src_xy_de==1'b1)	  	//最右边一行像素
		region_type <= 3;
	else
		region_type <= 4; 				//其余的像素

always@(posedge clk)
	if(rst)	
		begin
			region_type_r	<=  'd0;
			region_type_r1  <=  'd0;
			region_type_r2  <=  'd0;
			region_type_r3  <=  'd0;
			region_type_r4  <=  'd0;			
		end
	else
		begin
			region_type_r	<=  region_type		;
			region_type_r1  <=  region_type_r	;
			region_type_r2  <=  region_type_r1	;
			region_type_r3  <=  region_type_r2	;
			region_type_r4  <=  region_type_r3	;
		end		

//得到4个地址
wire	[1:0]	src_mod		;//四行RAM的片选
reg		[1:0]	src_mod_r	;
reg		[1:0]	src_mod_r1	;
reg		[1:0]	src_mod_r2	;

reg		[7:0]	data00		;	
reg		[7:0]	data01		;	
reg		[7:0]	data10		;	
reg		[7:0]	data11		;

reg		[7:0]	data00_r	;	
reg		[7:0]	data01_r	;	
reg		[7:0]	data10_r	;	
reg		[7:0]	data11_r	;

assign src_mod = src_y0%4;

always@(posedge clk)
	if(rst)	
		begin
			src_mod_r	<=	'd0;
		    src_mod_r1	<=	'd0;
			src_mod_r2	<=	'd0;
		end
	else
		begin
			src_mod_r	<=	src_mod		;
		    src_mod_r1	<=	src_mod_r	;
			src_mod_r2	<=	src_mod_r1	;
		end		   

reg	[7:0]	multi_data_de;	
//src_x0  src_x1  src_y0  src_y1四个数据计算完毕信号
always@(posedge clk)
	if(rst)	
		multi_data_de <= 'd0;
	else
		multi_data_de <= {multi_data_de[6:0],src_xy_de};

wire	rd_addr_de	;

assign rd_addr_de = multi_data_de[0]; 

//不同的片选从不同的RAM地址拿数据
always@(posedge clk)
	case(src_mod)
		0:
			begin
				rd_addr_w[0] <= src_x0;
				rd_addr[0]   <= src_x1;
				rd_addr_w[1] <= src_x0;
				rd_addr[1]   <= src_x1;
			end	
		1:
			begin
				rd_addr_w[1] <= src_x0;
				rd_addr[1]   <= src_x1;				
				rd_addr_w[2] <= src_x0;
				rd_addr[2]   <= src_x1;
			end			
		2:
			begin
				rd_addr_w[2] <= src_x0;
				rd_addr[2]   <= src_x1;
				rd_addr_w[3] <= src_x0;
				rd_addr[3]   <= src_x1;
			end			
		3:
			begin
				rd_addr_w[3] <= src_x0;
				rd_addr[3]   <= src_x1;
				rd_addr_w[0] <= src_x0;
				rd_addr[0]   <= src_x1;
			end
		default:;
	endcase		

wire	data_de	;

assign data_de = multi_data_de[2]; 
/****************************************************************************x0 x1 y0 y1四个数赋值**********************************************************/
always@(posedge clk)
	case(src_mod_r1)
		0:
			begin
				data00 <= douta[0];
				data01 <= doutb[0];
				data10 <= douta[1];	
				data11 <= doutb[1];
			end	
		1:
			begin
				data00 <= douta[1];
				data01 <= doutb[1];
				data10 <= douta[2];	
				data11 <= doutb[2];
			end			
		2:
			begin
				data00 <= douta[2];
				data01 <= doutb[2];
				data10 <= douta[3];	
				data11 <= doutb[3];
			end			
		3:
			begin
				data00 <= douta[3];
				data01 <= doutb[3];
				data10 <= douta[0];	
				data11 <= doutb[0];
			end
		default:;
	endcase		

wire	data_de_r	;

assign data_de_r = multi_data_de[3]; 

always@(posedge clk)
	if(rst)
		begin
			data00_r <= 'd0;
			data01_r <= 'd0;
			data10_r <= 'd0;
			data11_r <= 'd0;
		end
	else
		begin
			data00_r <= data00;
			data01_r <= data01;
			data10_r <= data10;
			data11_r <= data11;
		end		
			
//fix26_12
reg		[25:0]		v		;
reg		[13:0]		v_r		;
reg		[13:0]		v_r1	;

reg		[13:0]		rv		;

reg		[25:0]		u		;
reg		[13:0]		u_r		;
reg		[13:0]		u_r1	;

reg		[13:0]		ru		;

reg		[27:0]      ru_rv	;
reg		[27:0]      ru_v	;
reg		[27:0]      u_rv	;
reg		[27:0]      u_v		;

wire	u_v_de	;

assign u_v_de = multi_data_de[2]; 

reg	[13:0]	u_v_hcnt	;
reg	[13:0]	u_v_vcnt	;

always@(posedge clk)
	if(rst)		
		u_v_hcnt <= 'd0;
	else if(u_v_hcnt==DST_IW-1)
		u_v_hcnt <= 'd0;
	else if(u_v_de==1'b1)
		u_v_hcnt <= u_v_hcnt + 1'b1;
	else
		u_v_hcnt <= u_v_hcnt;

always@(posedge clk)
	if(rst)		
		u_v_vcnt <= 'd0;
	else if(u_v_hcnt==DST_IW-1&&u_v_vcnt==DST_IH-1)
		u_v_vcnt <= 'd0;
	else if(u_v_hcnt==DST_IW-1)
		u_v_vcnt <= u_v_vcnt + 1'b1;
	else
		u_v_vcnt <= u_v_vcnt;

/************************************************************************开始计算w11 w12  w21   w22*********************************************************/
/*
	w11 = (src_x1 - src_xf) * (src_y1 - src_yf);   
	w21 = (src_xf - src_x0) * (src_y1 - src_yf);
	w12 = (src_x1 - src_xf) * (src_yf - src_y0);
	w22 = (src_xf - src_x0) * (src_yf - src_y0);
*/
//fix26_12 - fix26_12 = fix26_12
always@(posedge clk)
	if(rst)	
		v <= 'd0;
	else
		v <= $signed(src_xf3) - $signed({src_x0,12'd0});	
//fix14_12 - fix14_12 = fix14_12
always@(posedge clk)
	if(rst)	
		rv <= 'd0;
	else
		rv <= $signed({1'b0,1'b1,12'd0}) - $signed(v_r);
//fix26_12 - fix26_12 = fix26_12
always@(posedge clk)
	if(rst)	
		u <= 'd0;
	else
		u <= $signed(src_yf3) - $signed({src_y0,12'd0});	
//fix14_12 - fix14_12 = fix14_12		
always@(posedge clk)
	if(rst)	
		ru <= 'd0;
	else
		ru <= $signed({1'b0,1'b1,12'd0}) - $signed(u_r);
//fix1_12		
always@(posedge clk)
	if(rst)	
		begin
			v_r  <= 'd0;
			v_r1 <= 'd0;
		end
	else
		begin
			v_r  <= v[13:0]; 
			v_r1 <= v_r;
		end		
	
always@(posedge clk)
	if(rst)	
		begin
			u_r  <= 'd0;
			u_r1 <= 'd0;
		end
	else
		begin
			u_r  <= u[13:0];
			u_r1 <= u_r;
		end	
		
wire	uv_de	;

assign uv_de = multi_data_de[3]; 	
		
//fix14_12 * fix14_12 = fix28_24
always@(posedge clk)
	if(rst)	
		begin
			ru_rv	<= 'd0;
		    ru_v	<= 'd0;
		    u_rv	<= 'd0;
		    u_v		<= 'd0;
		end
	else
		begin
			ru_rv	<=  $signed(ru	)*$signed(rv  );
		    ru_v	<=	$signed(ru	)*$signed(v_r1);
		    u_rv	<=	$signed(u_r1)*$signed(rv  );
		    u_v		<=	$signed(u_r1)*$signed(v_r1);
		end			

reg	[22:0]	line_data11		 = 0;
								
reg	[22:0]	line_data21		 = 0;
reg	[22:0]	line_data22		 = 0;
							
reg	[22:0]	line_data31		 = 0;
reg	[22:0]	line_data32		 = 0;
							
reg	[22:0]	line_data41		 = 0;
reg	[22:0]	line_data42		 = 0;
reg	[22:0]	line_data43		 = 0;
reg	[22:0]	line_data44		 = 0;
							
reg	[23:0]	line_data11_11	 = 0;
								
reg	[23:0]	line_data21_22	 = 0;
							
reg	[23:0]	line_data31_32	 = 0;
							
reg	[23:0]	line_data41_42	 = 0;
reg	[23:0]	line_data43_44	 = 0;
								
reg	[24:0]	line_data		 = 0;

wire	line_de	;

assign line_de = multi_data_de[4]; 
/*****************************************************根据权重计算出四个点的加权值*******************************************************/	
//fix14_12 * fix9_0 = fix23_12 
always@(posedge clk)
	case(region_type_r2)
		1:
			begin
				line_data11 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
			end	
		2:
			begin
				line_data21 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
				line_data22 <= $signed(ru_v[25:12])*$signed({1'b0,data01_r});
			end			
		3:
			begin
				line_data31 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
				line_data32 <= $signed(u_rv[25:12])*$signed({1'b0,data10_r});				
			end			
		4:
			begin
				line_data41 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
				line_data42 <= $signed(ru_v[25:12])*$signed({1'b0,data01_r});
				line_data43 <= $signed(u_rv[25:12])*$signed({1'b0,data10_r});
				line_data44 <= $signed(u_v[25:12])*$signed({1'b0,data11_r});
			end
		default:;
	endcase	

wire	line2_de	;
/**************************************************************根据加权值计算放缩后的值***********************************************************/
assign line2_de = multi_data_de[5]; 
//fix23_12 + fix23_12 = fix24_12 
always@(posedge clk)
	case(region_type_r3)
		1:
			begin
				line_data11_11 <= $signed(line_data11);
			end	
		2:
			begin
				line_data21_22 <= $signed(line_data21) + $signed(line_data22);
			end			
		3:
			begin
				line_data31_32 <= $signed(line_data31) + $signed(line_data32);
			end			
		4:
			begin
				line_data41_42 <= $signed(line_data41) + $signed(line_data42);
				line_data43_44 <= $signed(line_data43) + $signed(line_data44);
			end
		default:;
	endcase	

wire	line4_de	;

assign line4_de = multi_data_de[6]; 
//fix24_12 + fix24_12 = fix25_12 
always@(posedge clk)
	case(region_type_r4)
		1:
			begin
				line_data <= $signed(line_data11_11);
			end	
		2:
			begin
				line_data <= $signed(line_data21_22);
			end			
		3:
			begin
				line_data <= $signed(line_data31_32);
			end			
		4:
			begin
				line_data <= $signed(line_data41_42) + $signed(line_data43_44);
			end
		default:;
	endcase	
/***************************************************************放缩后的行列计数**************************************************/
wire		cast_de		;	
reg	[7:0]   cast_data	;

reg	[13:0]	cast_hcnt	;
reg	[13:0]	cast_vcnt	;

assign cast_de = multi_data_de[7]; 	
//fix25_12
always@(posedge clk)
	if(rst)
		cast_data <= 'd0;
	else if(line_data[24]==1'b1)
		cast_data <= 0;	
	else if(line_data[22:12]>=255)
		cast_data <= 255;
	else
		cast_data <= line_data[11] ? line_data[19:12] + 1'b1 : line_data[19:12];

always@(posedge clk)
	if(rst)		
		cast_hcnt <= 'd0;
	else if(cast_hcnt==DST_IW-1)
		cast_hcnt <= 'd0;
	else if(cast_de==1'b1)
		cast_hcnt <= cast_hcnt + 1'b1;
	else
		cast_hcnt <= cast_hcnt;

always@(posedge clk)
	if(rst)		
		cast_vcnt <= 'd0;
	else if(cast_hcnt==DST_IW-1&&cast_vcnt==DST_IH-1)
		cast_vcnt <= 'd0;
	else if(cast_hcnt==DST_IW-1)
		cast_vcnt <= cast_vcnt + 1'b1;
	else
		cast_vcnt <= cast_vcnt;
	
xpm_asfifo #(
	.FIFO_MEMORY_TYPE  		("block"), //block distributed
	.WRITE_DATA_WIDTH  		(8		),
	.FIFO_WRITE_DEPTH  		(16384	),
	.WR_DATA_COUNT_WIDTH    (15  	),
	.READ_MODE         		("fwft"	),//"std" "fwft" 
	.READ_DATA_WIDTH   		(8   	),
	.RD_DATA_COUNT_WIDTH    (15     ),
	.FIFO_READ_LATENCY 		(0		) 	 	
)
u1_xpm_asfifo
(
	.rst         		(1'b0			),
	.wr_clk				(clk			),            
	.rd_clk				(post_clk  		),           
	.din				(cast_data		),	           
	.wr_en				(cast_de		),           
	.rd_en				(post_req		),            
	.dout				(post_data		),              
	.full				(full			),                   
	.empty				(post_empty		),                 
	.rd_data_count		(rd_data_count	), 
	.wr_data_count		(wr_data_count	)
);

always@(posedge post_clk)
	if(rst)
		post_ready <= 1'b0;
	else if(rd_data_count>=DST_IW*buf_line)
		post_ready <= 1'b1;
	else
		post_ready <= post_ready;








endmodule

`timescale 1ns / 1ps
module scaler_act #(
	parameter SRC_IW = 640 	,
	parameter SRC_IH = 480 	,
	parameter DST_IW = 320  ,
	parameter DST_IH = 240  
)
(
	input				clk				,
	input				rst				,
				
	input				pre_vs			,
	input				pre_de			,
	input		[7:0]	pre_data		,
	
	output	reg			cast_vs			,
	output				cast_de			,
	output	reg	[7:0]	cast_data			
);

reg		[2:0]	state				;
reg		[2:0]	state_r				;

reg		[13:0]	src_hcnt			;
reg		[13:0]	src_vcnt			;
	
reg				dst_de				;
reg		[13:0]	dst_hcnt			;
reg		[13:0]	dst_vcnt			;
	
reg		[15:0]	expt_src_vcnt0		;		
reg		[31:0]	expt_src_vcnt1		;
reg		[25:0]	expt_src_vcnt2		;
reg		[13:0]	expt_src_vcnt3		;

reg				expt_src_vcnt_de	;
reg				expt_src_vcntp1_de	;
	
reg				expt_src_vcnt_de0	;		
reg				expt_src_vcnt_de1	;
reg				expt_src_vcnt_de2	;
reg				expt_src_vcnt_de3	;

reg		[15:0]	src_xf0				;		
reg		[31:0]	src_xf1				;
reg		[25:0]	src_xf2				;
reg		[25:0]	src_xf3				;

reg		[15:0]	src_yf0				;		
reg		[31:0]	src_yf1				;
reg		[25:0]	src_yf2				;
reg		[25:0]	src_yf3				;

reg		[13:0]	src_x0				;
reg		[13:0]	src_x1              ;

reg		[13:0]	src_y0				;
reg		[13:0]	src_y1              ;

//fix16_12
localparam  [15:0]	sx_recip  =  SRC_IW*4096/DST_IW	;
localparam  [15:0]	sy_recip  =  SRC_IH*4096/DST_IH	;

always@(posedge clk)
	if(rst)
		begin
			dst_de 		<= 0;
			state  		<= 0;
		end
	else
		case(state)
			0:	
				begin
					state 	<= 1;
				end		
			1:  
				begin
					state 	<= 2;
				end		
			2:  
				if(src_vcnt>=expt_src_vcnt3&&expt_src_vcnt_de3==1'b1)
					begin
						state 	<= 3;
					end
				else if(src_vcnt<expt_src_vcnt3&&expt_src_vcnt_de3==1'b1)
					begin
						state 	<= 1;
					end					
				else 
					begin
						state 	<= state;
					end					
			3:  
				if(dst_hcnt==DST_IW-1)
					begin
						dst_de  <= 0;
						state 	<= 1;
					end
				else 
					begin
						dst_de  <= 1;
						state 	<= state;
					end	
			default:;
		endcase				

always@(posedge clk)
	if(rst)
		state_r <= 'd0;
	else
		state_r <= state;
		
always@(posedge clk)
	if(rst)
		expt_src_vcnt_de <= 1'b0;
	else if(state_r!=2&&state==2)
		expt_src_vcnt_de <= 1'b1;
	else
		expt_src_vcnt_de <= 1'b0;	

always@(posedge clk)
	if(rst)
		expt_src_vcntp1_de <= 1'b0;
	else if(state_r!=3&&state==3)
		expt_src_vcntp1_de <= 1'b1;	
	else
		expt_src_vcntp1_de <= 1'b0;	
		
always@(posedge clk)
	if(rst)		
		src_hcnt <= 'd0;
	else if(src_hcnt==SRC_IW-1)
		src_hcnt <= 'd0;
	else if(pre_de==1'b1)
		src_hcnt <= src_hcnt + 1'b1;
	else
		src_hcnt <= src_hcnt;

always@(posedge clk)
	if(rst)		
		src_vcnt <= 'd0;
	else if(src_vcnt==SRC_IH&&dst_hcnt==DST_IW-1&&dst_vcnt==DST_IH-1)	
		src_vcnt <= 'd0;
	else if(src_hcnt==SRC_IW-1)
		src_vcnt <= src_vcnt + 1'b1;
	else
		src_vcnt <= src_vcnt;

reg		[13:0]	wr_addr_cnt			;		
reg		[1:0]	wr_addr_sel			;

reg		[11:0]	pre_wr_addr	[3:0]	;

wire			wr_addr_de	[3:0]	;
reg		[11:0]	wr_addr		[3:0]	;

reg		[11:0]	rd_addr		[3:0]	;
reg		[11:0]	rd_addr_w	[3:0]	;

wire	[7:0]	douta   	[3:0]	;
wire	[7:0]	doutb   	[3:0]	;

always@(posedge clk)
	if(rst)		
		wr_addr_sel <= 'd0;
	else if(wr_addr_cnt==SRC_IW-1&&wr_addr_sel==3)
		wr_addr_sel <= 'd0;
	else if(wr_addr_cnt==SRC_IW-1)
		wr_addr_sel <= wr_addr_sel + 1'b1;
	else
		wr_addr_sel <= wr_addr_sel;
		
always@(posedge clk)
	if(rst)		
		wr_addr_cnt <= 'd0;
	else if(wr_addr_cnt==SRC_IW-1)
		wr_addr_cnt <= 'd0;
	else if(pre_de==1'b1)
		wr_addr_cnt <= wr_addr_cnt + 1'b1;
	else
		wr_addr_cnt <= wr_addr_cnt;

genvar i;
generate
  for (i=0; i < 4; i=i+1)
  begin: wr_src_data
	
	assign wr_addr_de[i] = (pre_de==1'b1&&wr_addr_sel==i);
	
	always@(posedge clk)
		if(rst)			
			pre_wr_addr[i] <= 'd0;
		else if(pre_wr_addr[i]==SRC_IW-1)
			pre_wr_addr[i] <= 'd0;
		else if(wr_addr_de[i]==1'b1)
			pre_wr_addr[i] <= pre_wr_addr[i] + 1'b1;
		else
			pre_wr_addr[i] <= pre_wr_addr[i];
		
	always@(*)
		if(rst)			
			wr_addr[i] = 'd0;
		else if(wr_addr_de[i]==1'b1)
			wr_addr[i] = pre_wr_addr[i];
		else
			wr_addr[i] = rd_addr_w[i];			
		
		tdpram #(
			.AW (12),
			.DW (8 )  
		)
		u1_tdpram 
		(
		  .clka		(clk			),
		  .wea		(wr_addr_de[i]	),
		  .addra	(wr_addr[i]		),
		  .dina		(pre_data		),
		  .douta	(douta[i]		),
		  .clkb		(clk			),
		  .web		(1'b0			),
		  .addrb	(rd_addr[i]		),
		  .dinb		(8'd0			),
		  .doutb	(doutb[i]		) 
		);		
  end
endgenerate
		
always@(posedge clk)
	if(rst)		
		dst_hcnt <= 'd0;
	else if(dst_hcnt==DST_IW-1)
		dst_hcnt <= 'd0;
	else if(dst_de==1'b1)
		dst_hcnt <= dst_hcnt + 1'b1;
	else
		dst_hcnt <= dst_hcnt;

always@(posedge clk)
	if(rst)		
		dst_vcnt <= 'd0;
	else if(dst_hcnt==DST_IW-1&&dst_vcnt==DST_IH-1)
		dst_vcnt <= 'd0;
	else if(dst_hcnt==DST_IW-1)
		dst_vcnt <= dst_vcnt + 1'b1;
	else
		dst_vcnt <= dst_vcnt;

always@(posedge clk)
	if(rst)		
		begin
			expt_src_vcnt_de0 <= 1'b0;
			expt_src_vcnt_de1 <= 1'b0;
			expt_src_vcnt_de2 <= 1'b0;
			expt_src_vcnt_de3 <= 1'b0;
		end
	else
		begin
			expt_src_vcnt_de0 <= expt_src_vcnt_de||expt_src_vcntp1_de;
			expt_src_vcnt_de1 <= expt_src_vcnt_de0;
			expt_src_vcnt_de2 <= expt_src_vcnt_de1;
			expt_src_vcnt_de3 <= expt_src_vcnt_de2;
		end		
		
//fix16_2 + fix0_2 = fix16_2
always@(posedge clk)
	if(rst)	
		expt_src_vcnt0 <= 'd0;
	else if(expt_src_vcnt_de==1'b1)
		expt_src_vcnt0 <= {dst_vcnt,2'd0} + 2;	
	else if(expt_src_vcntp1_de==1'b1&&dst_vcnt<DST_IH-1)
		expt_src_vcnt0 <= {dst_vcnt+1,2'd0} + 2;	
	else
		expt_src_vcnt0 <= 'd0;
//fix16_2 * fix16_12 = fix32_14
always@(posedge clk)
	if(rst)	
		expt_src_vcnt1 <= 'd0;
	else
		expt_src_vcnt1 <= expt_src_vcnt0*sy_recip;
//fix26_12 - fix12_12 = fix26_12		
always@(posedge clk)
	if(rst)	
		expt_src_vcnt2 <= 'd0;
	else
		expt_src_vcnt2 <= expt_src_vcnt1[27:2] - 2048;
//fix26_12	-> 取整 + 2 = fix14_0 + 2	
always@(posedge clk)
	if(rst)	
		expt_src_vcnt3 <= 'd0;
	else if(expt_src_vcnt2[25]==1'b1)
		expt_src_vcnt3 <= 'd2;
	else if(expt_src_vcnt2[25:12]>SRC_IH-2)
		expt_src_vcnt3 <= SRC_IH;
	else
		expt_src_vcnt3 <= expt_src_vcnt2[25:12] + 2;
		
reg		dst_de0	 	;
reg		dst_de1  	;
reg		dst_de2  	;

reg		src_xy_de   ;

always@(posedge clk)
	if(rst)	
		begin	
			dst_de0 <= 1'b0;
			dst_de1 <= 1'b0;
			dst_de2 <= 1'b0;
		end
	else
		begin	
			dst_de0 <= dst_de;
			dst_de1 <= dst_de0;
			dst_de2 <= dst_de1;
		end		

always@(posedge clk)
	if(rst)	
		src_xy_de <= 1'b0;
	else
		src_xy_de <= dst_de2;
	
//src_xf
always@(posedge clk)
	if(rst)	
		src_xf0 <= 'd0;
	else if(dst_de==1'b1)
		src_xf0 <= {dst_hcnt,2'd0} + 2;
	else
		src_xf0 <= 'd0;
		
always@(posedge clk)
	if(rst)	
		src_xf1 <= 'd0;
	else
		src_xf1 <= src_xf0*sx_recip;

always@(posedge clk)
	if(rst)	
		src_xf2 <= 'd0;
	else
		src_xf2 <= src_xf1[27:2] - 2048;
		
always@(posedge clk)
	if(rst)	
		src_xf3 <= 'd0;
	else
		src_xf3 <= src_xf2;		

always@(posedge clk)
	if(rst)	
		src_x0 <= 'd0;
	else if(src_xf2[25]==1'b1)
		src_x0 <= 'd0;		
	else
		src_x0 <= src_xf2[25:12];
		
always@(posedge clk)
	if(rst)	
		src_x1 <= 'd0;
	else if(src_xf2[25]==1'b1)
		src_x1 <= 'd1;
	else
		src_x1 <= src_xf2[25:12] + 1'b1;
	
//src_yf
always@(posedge clk)
	if(rst)	
		src_yf0 <= 'd0;
	else if(dst_de==1'b1)
		src_yf0 <= {dst_vcnt,2'd0} + 2;
	else
		src_yf0 <= 'd0;
		
always@(posedge clk)
	if(rst)	
		src_yf1 <= 'd0;
	else
		src_yf1 <= src_yf0*sy_recip;

always@(posedge clk)
	if(rst)	
		src_yf2 <= 'd0;
	else
		src_yf2 <= src_yf1[27:2] - 2048;

always@(posedge clk)
	if(rst)	
		src_yf3 <= 'd0;
	else
		src_yf3 <= src_yf2;

always@(posedge clk)
	if(rst)	
		src_y0 <= 'd0;
	else if(src_yf2[25]==1'b1)
		src_y0 <= 'd0;
	else
		src_y0 <= src_yf2[25:12];		

always@(posedge clk)
	if(rst)	
		src_y1 <= 'd0;
	else if(src_yf2[25]==1'b1)
		src_y1 <= 'd1;
	else
		src_y1 <= src_yf2[25:12] + 1'b1;
		
reg	[2:0]	region_type		;
reg	[2:0]	region_type_r	;
reg	[2:0]	region_type_r1	;
reg	[2:0]	region_type_r2	;
reg	[2:0]	region_type_r3	;
reg	[2:0]	region_type_r4	;

always@(posedge clk)
	if(rst)	
		region_type <= 0;
	else if(src_x0>=SRC_IW-1&&src_y0>=SRC_IH-1&&src_xy_de==1'b1)
		region_type <= 1;
	else if(src_y0>=SRC_IH-1&&src_xy_de==1'b1)
		region_type <= 2;
	else if(src_x0>=SRC_IW-1&&src_xy_de==1'b1)	
		region_type <= 3;
	else
		region_type <= 4;

always@(posedge clk)
	if(rst)	
		begin
			region_type_r	<=  'd0;
			region_type_r1  <=  'd0;
			region_type_r2  <=  'd0;
			region_type_r3  <=  'd0;
			region_type_r4  <=  'd0;			
		end
	else
		begin
			region_type_r	<=  region_type		;
			region_type_r1  <=  region_type_r	;
			region_type_r2  <=  region_type_r1	;
			region_type_r3  <=  region_type_r2	;
			region_type_r4  <=  region_type_r3	;
		end		

//得到4个地址
wire	[1:0]	src_mod		;
reg		[1:0]	src_mod_r	;
reg		[1:0]	src_mod_r1	;
reg		[1:0]	src_mod_r2	;

reg		[7:0]	data00		;	
reg		[7:0]	data01		;	
reg		[7:0]	data10		;	
reg		[7:0]	data11		;

reg		[7:0]	data00_r	;	
reg		[7:0]	data01_r	;	
reg		[7:0]	data10_r	;	
reg		[7:0]	data11_r	;

assign src_mod = src_y0%4;

always@(posedge clk)
	if(rst)	
		begin
			src_mod_r	<=	'd0;
		    src_mod_r1	<=	'd0;
			src_mod_r2	<=	'd0;
		end
	else
		begin
			src_mod_r	<=	src_mod		;
		    src_mod_r1	<=	src_mod_r	;
			src_mod_r2	<=	src_mod_r1	;
		end		   

reg	[7:0]	multi_data_de;	
		
always@(posedge clk)
	if(rst)	
		multi_data_de <= 'd0;
	else
		multi_data_de <= {multi_data_de[6:0],src_xy_de};

wire	rd_addr_de	;

assign rd_addr_de = multi_data_de[0]; 

always@(posedge clk)
	case(src_mod)
		0:
			begin
				rd_addr_w[0] <= src_x0;
				rd_addr[0]   <= src_x1;
				rd_addr_w[1] <= src_x0;
				rd_addr[1]   <= src_x1;
			end	
		1:
			begin
				rd_addr_w[1] <= src_x0;
				rd_addr[1]   <= src_x1;				
				rd_addr_w[2] <= src_x0;
				rd_addr[2]   <= src_x1;
			end			
		2:
			begin
				rd_addr_w[2] <= src_x0;
				rd_addr[2]   <= src_x1;
				rd_addr_w[3] <= src_x0;
				rd_addr[3]   <= src_x1;
			end			
		3:
			begin
				rd_addr_w[3] <= src_x0;
				rd_addr[3]   <= src_x1;
				rd_addr_w[0] <= src_x0;
				rd_addr[0]   <= src_x1;
			end
		default:;
	endcase		

wire	data_de	;

assign data_de = multi_data_de[2]; 

always@(posedge clk)
	case(src_mod_r1)
		0:
			begin
				data00 <= douta[0];
				data01 <= doutb[0];
				data10 <= douta[1];	
				data11 <= doutb[1];
			end	
		1:
			begin
				data00 <= douta[1];
				data01 <= doutb[1];
				data10 <= douta[2];	
				data11 <= doutb[2];
			end			
		2:
			begin
				data00 <= douta[2];
				data01 <= doutb[2];
				data10 <= douta[3];	
				data11 <= doutb[3];
			end			
		3:
			begin
				data00 <= douta[3];
				data01 <= doutb[3];
				data10 <= douta[0];	
				data11 <= doutb[0];
			end
		default:;
	endcase		

wire	data_de_r	;

assign data_de_r = multi_data_de[3]; 

always@(posedge clk)
	if(rst)
		begin
			data00_r <= 'd0;
			data01_r <= 'd0;
			data10_r <= 'd0;
			data11_r <= 'd0;
		end
	else
		begin
			data00_r <= data00;
			data01_r <= data01;
			data10_r <= data10;
			data11_r <= data11;
		end		
			
//fix26_12
reg		[25:0]		v		;
reg		[13:0]		v_r		;
reg		[13:0]		v_r1	;

reg		[13:0]		rv		;

reg		[25:0]		u		;
reg		[13:0]		u_r		;
reg		[13:0]		u_r1	;

reg		[13:0]		ru		;

reg		[27:0]      ru_rv	;
reg		[27:0]      ru_v	;
reg		[27:0]      u_rv	;
reg		[27:0]      u_v		;

wire	u_v_de	;

assign u_v_de = multi_data_de[2]; 

reg	[13:0]	u_v_hcnt	;
reg	[13:0]	u_v_vcnt	;

always@(posedge clk)
	if(rst)		
		u_v_hcnt <= 'd0;
	else if(u_v_hcnt==DST_IW-1)
		u_v_hcnt <= 'd0;
	else if(u_v_de==1'b1)
		u_v_hcnt <= u_v_hcnt + 1'b1;
	else
		u_v_hcnt <= u_v_hcnt;

always@(posedge clk)
	if(rst)		
		u_v_vcnt <= 'd0;
	else if(u_v_hcnt==DST_IW-1&&u_v_vcnt==DST_IH-1)
		u_v_vcnt <= 'd0;
	else if(u_v_hcnt==DST_IW-1)
		u_v_vcnt <= u_v_vcnt + 1'b1;
	else
		u_v_vcnt <= u_v_vcnt;
		
always@(posedge clk)
	if(rst)	
		v <= 'd0;
	else
		v <= $signed(src_xf3) - $signed({src_x0,12'd0});	

always@(posedge clk)
	if(rst)	
		rv <= 'd0;
	else
		rv <= $signed({1'b0,1'b1,12'd0}) - $signed(v_r);

always@(posedge clk)
	if(rst)	
		u <= 'd0;
	else
		u <= $signed(src_yf3) - $signed({src_y0,12'd0});	
		
always@(posedge clk)
	if(rst)	
		ru <= 'd0;
	else
		ru <= $signed({1'b0,1'b1,12'd0}) - $signed(u_r);
//fix1_12		
always@(posedge clk)
	if(rst)	
		begin
			v_r  <= 'd0;
			v_r1 <= 'd0;
		end
	else
		begin
			v_r  <= v[13:0]; 
			v_r1 <= v_r;
		end		
	
always@(posedge clk)
	if(rst)	
		begin
			u_r  <= 'd0;
			u_r1 <= 'd0;
		end
	else
		begin
			u_r  <= u[13:0];
			u_r1 <= u_r;
		end	
		
wire	uv_de	;

assign uv_de = multi_data_de[3]; 	
		
//fix26_24
always@(posedge clk)
	if(rst)	
		begin
			ru_rv	<= 'd0;
		    ru_v	<= 'd0;
		    u_rv	<= 'd0;
		    u_v		<= 'd0;
		end
	else
		begin
			ru_rv	<=  $signed(ru	)*$signed(rv  );
		    ru_v	<=	$signed(ru	)*$signed(v_r1);
		    u_rv	<=	$signed(u_r1)*$signed(rv  );
		    u_v		<=	$signed(u_r1)*$signed(v_r1);
		end			

reg	[22:0]	line_data11		 = 0;
								
reg	[22:0]	line_data21		 = 0;
reg	[22:0]	line_data22		 = 0;
							
reg	[22:0]	line_data31		 = 0;
reg	[22:0]	line_data32		 = 0;
							
reg	[22:0]	line_data41		 = 0;
reg	[22:0]	line_data42		 = 0;
reg	[22:0]	line_data43		 = 0;
reg	[22:0]	line_data44		 = 0;
							
reg	[23:0]	line_data11_11	 = 0;
								
reg	[23:0]	line_data21_22	 = 0;
							
reg	[23:0]	line_data31_32	 = 0;
							
reg	[23:0]	line_data41_42	 = 0;
reg	[23:0]	line_data43_44	 = 0;
								
reg	[24:0]	line_data		 = 0;

wire	line_de	;

assign line_de = multi_data_de[4]; 	
//2位符号 9位整数 12bit小数 
always@(posedge clk)
	case(region_type_r2)
		1:
			begin
				line_data11 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
			end	
		2:
			begin
				line_data21 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
				line_data22 <= $signed(ru_v[25:12])*$signed({1'b0,data01_r});
			end			
		3:
			begin
				line_data31 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
				line_data32 <= $signed(u_rv[25:12])*$signed({1'b0,data10_r});				
			end			
		4:
			begin
				line_data41 <= $signed(ru_rv[25:12])*$signed({1'b0,data00_r});
				line_data42 <= $signed(ru_v[25:12])*$signed({1'b0,data01_r});
				line_data43 <= $signed(u_rv[25:12])*$signed({1'b0,data10_r});
				line_data44 <= $signed(u_v[25:12])*$signed({1'b0,data11_r});
			end
		default:;
	endcase	

wire	line2_de	;

assign line2_de = multi_data_de[5]; 
//2位符号 10位整数 12bit小数 
always@(posedge clk)
	case(region_type_r3)
		1:
			begin
				line_data11_11 <= $signed(line_data11);
			end	
		2:
			begin
				line_data21_22 <= $signed(line_data21) + $signed(line_data22);
			end			
		3:
			begin
				line_data31_32 <= $signed(line_data31) + $signed(line_data32);
			end			
		4:
			begin
				line_data41_42 <= $signed(line_data41) + $signed(line_data42);
				line_data43_44 <= $signed(line_data43) + $signed(line_data44);
			end
		default:;
	endcase	

wire	line4_de	;

assign line4_de = multi_data_de[6]; 
//2位符号 11位整数 12bit小数 
always@(posedge clk)
	case(region_type_r4)
		1:
			begin
				line_data <= $signed(line_data11_11);
			end	
		2:
			begin
				line_data <= $signed(line_data21_22);
			end			
		3:
			begin
				line_data <= $signed(line_data31_32);
			end			
		4:
			begin
				line_data <= $signed(line_data41_42) + $signed(line_data43_44);
			end
		default:;
	endcase	

reg	[13:0]	cast_hcnt	;
reg	[13:0]	cast_vcnt	;

always@(posedge clk)
	if(rst)
		cast_vs <= 1'b0;
	else
		cast_vs <= pre_vs;

assign cast_de = multi_data_de[7]; 	
//2位符号 11位整数 12bit小数 
always@(posedge clk)
	if(rst)
		cast_data <= 'd0;
	else if(line_data[24]==1'b1)
		cast_data <= 0;	
	else if(line_data[22:12]>=255)
		cast_data <= 255;
	else
		cast_data <= line_data[11] ? line_data[19:12] + 1'b1 : line_data[19:12];

always@(posedge clk)
	if(rst)		
		cast_hcnt <= 'd0;
	else if(cast_hcnt==DST_IW-1)
		cast_hcnt <= 'd0;
	else if(cast_de==1'b1)
		cast_hcnt <= cast_hcnt + 1'b1;
	else
		cast_hcnt <= cast_hcnt;

always@(posedge clk)
	if(rst)		
		cast_vcnt <= 'd0;
	else if(cast_hcnt==DST_IW-1&&cast_vcnt==DST_IH-1)
		cast_vcnt <= 'd0;
	else if(cast_hcnt==DST_IW-1)
		cast_vcnt <= cast_vcnt + 1'b1;
	else
		cast_vcnt <= cast_vcnt;
endmodule

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值