最近恰好要處理項目中噪聲大的問題,在網上看到這篇博客,就用FPGA實現了一下,效果還能夠,原文https://blog.csdn.net/baimafujinji/article/details/73302911緩存
下面是基於HSV數據格式的維納濾波器ide
module winnerfilter( input wire clk, input wire reset, input wire vdin, input wire hdin, input wire[8:0] din_h, input wire[7:0] din_s, input wire[7:0] din_v, output reg vdout, output reg hdout, output reg[8:0] dout_h, output reg[7:0] dout_s, output reg[7:0] dout_v ); reg vdin_d0; reg[37:0] hdin_dly; reg[7:0] din_dly[5:0]; reg[11:0] hd_data; reg[11:0] vd_data; //==================================================// reg wr_en_h; (*KEEP = "TRUE"*)reg wr_en_s; reg rd_en_h; (*KEEP = "TRUE"*)reg rd_en_s; reg[8:0] din4; reg[7:0] din5; wire[8:0] dout4; wire[7:0] dout5; reg[8:0] dout4_dly[34:0]; reg[7:0] dout5_dly[34:0]; //=================================================// reg wr_en1; reg wr_en2; reg wr_en3; reg rd_en1; reg rd_en2; reg rd_en3; reg [7:0] din1; reg [7:0] din2; reg [7:0] din3; wire[7:0] dout1; wire[7:0] dout2; wire[7:0] dout3; reg[7:0] dout1_d0; reg[7:0] dout1_d1; reg[7:0] dout1_d2; reg[7:0] dout1_d3; reg[7:0] dout2_d0; reg[7:0] dout2_d1; reg[7:0] dout2_d2; reg[7:0] dout2_d3; (*KEEP = "TRUE"*)reg[7:0] dout3_dly[34:0]; reg[9:0] line_1; reg[9:0] line_2; reg[9:0] line_3; reg[9:0] line_4; wire[11:0] temp; reg [7:0] avg_window; reg [7:0] a2; reg [7:0] b2; wire[15:0] p2; reg [7:0] a4; reg [7:0] b4; wire[15:0] p4; reg [7:0] a5; reg [7:0] b5; wire[15:0] p5; reg [7:0] a6; reg [7:0] b6; wire[15:0] p6; reg [7:0] a7; reg [7:0] b7; wire[15:0] p7; reg [15:0] p4_d0; reg [15:0] p4_d1; reg [15:0] p4_d2; reg [15:0] p4_d3; reg [15:0] p5_d0; reg [15:0] p5_d1; reg [15:0] p5_d2; reg [15:0] p5_d3; reg [15:0] p6_d0; reg [15:0] p6_d1; reg [15:0] p6_d2; reg [15:0] p6_d3; reg [15:0] p7_d0; reg [15:0] p7_d1; reg [15:0] p7_d2; reg [15:0] p7_d3; reg [17:0] sum_1; reg [17:0] sum_2; reg [17:0] sum_3; reg [17:0] sum_4; reg [19:0] temp3; reg [15:0] variance_window; reg [37:0] temp2; reg [21:0] numbel; reg srst; reg[23:0] dividend1; reg[15:0] divisor1; wire[23:0] quotient1; reg[7:0] diff_value; reg[15:0] a3; reg[7:0] b3; wire[23:0] p3; reg[23:0] dividend2; reg[15:0] divisor2; wire[23:0] quotient2; reg flag; reg flag_diff_value; reg[33:0] flag_diff_value_dly; always@(posedge clk) hdin_dly <= {hdin_dly[36:0],hdin}; always@(posedge clk) begin vdin_d0 <= vdin; end always@(posedge clk) begin din_dly[0] <= din_v; dout3_dly[0] <= dout3; end always@(posedge clk) begin:u1 integer i; for(i=0;i<5;i=i+1) begin din_dly[i+1] <= din_dly[i]; end end always@(posedge clk) begin:u2 integer i; for(i=0;i<34;i=i+1) begin dout3_dly[i+1] <= dout3_dly[i]; end end //列計數 always@(posedge clk or posedge reset) if(reset) hd_data <= 12'd0; else if(vdin==1 && vdin_d0==0) hd_data <= 12'd0; else if(hd_data==12'd2093) hd_data <= 12'd0; else hd_data <= hd_data + 1'd1; //行計數 always@(posedge clk or posedge reset) if(reset) vd_data <= 12'd0; else if(vdin==1 && vdin_d0==0) vd_data <= 12'd0; else if(hd_data==12'd2093) vd_data <= vd_data + 1'd1; //===============================================================// always@(posedge clk) begin dout4_dly[0] <= dout4; dout5_dly[0] <= dout5; end always@(posedge clk) begin:u3 integer i; for(i=0;i<34;i=i+1) begin dout4_dly[i+1] <= dout4_dly[i]; dout5_dly[i+1] <= dout5_dly[i]; end end //=======================================================================// always@(posedge clk or posedge reset) if(reset) wr_en_h <= 1'd0; else wr_en_h <= hdin; always@(posedge clk or posedge reset) if(reset) rd_en_h <= 1'd0; else if(vd_data>=12'd1 && vd_data<=12'd1440) rd_en_h <= hdin; else rd_en_h <= 1'd0; always@(posedge clk or posedge reset) if(reset) wr_en_s <= 1'd0; else wr_en_s <= hdin; always@(posedge clk or posedge reset) if(reset) rd_en_s <= 1'd0; else if(vd_data>=12'd1 && vd_data<=12'd1440) rd_en_s <= hdin; else rd_en_s <= 1'd0; always@(posedge clk or posedge reset) if(reset) din4 <= 9'd0; else if(vdin && hdin) din4 <= din_h; else din4 <= 9'd0; always@(posedge clk or posedge reset) if(reset) din5 <= 8'd0; else if(vdin && hdin) din5 <= din_s; else din5 <= 8'd0; //===============================================================// //4x4窗口 //緩存第一行數據 always@(posedge clk or posedge reset) if(reset) wr_en3 <= 1'd0; else wr_en3 <= hdin; always@(posedge clk or posedge reset) if(reset) rd_en3 <= 1'd0; else if(vd_data>=12'd1 && vd_data<=12'd1440) rd_en3 <= hdin; else rd_en3 <= 1'd0; //緩存第二行數據 always@(posedge clk or posedge reset) if(reset) wr_en2 <= 1'd0; else if(vd_data>=12'd1 && vd_data<=12'd1439) wr_en2 <= hdin_dly[1]; always@(posedge clk or posedge reset) if(reset) rd_en2 <= 1'd0; else if(vd_data>=12'd2 && vd_data<=12'd1439) rd_en2 <= hdin; //緩存第三行數據 always@(posedge clk or posedge reset) if(reset) wr_en1 <= 1'd0; else if(vd_data>=12'd2 && vd_data<=12'd1439) wr_en1 <= hdin_dly[1]; always@(posedge clk or posedge reset) if(reset) rd_en1 <= 1'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) rd_en1 <= hdin; always@(posedge clk or posedge reset) if(reset) din3 <= 8'd0; else if(vdin && hdin) din3 <= din_v; else din3 <= 8'd0; always@(posedge clk or posedge reset) if(reset) din2 <= 8'd0; else if(vd_data>=12'd1 && vd_data<=12'd1439) din2 <= dout3; else din2 <= 8'd0; always@(posedge clk or posedge reset) if(reset) din1 <= 8'd0; else if(vd_data>=12'd2 && vd_data<=12'd1439) din1 <= dout2; else din1 <= 8'd0; always@(posedge clk) begin dout1_d0 <= dout1; dout1_d1 <= dout1_d0; dout1_d2 <= dout1_d1; dout1_d3 <= dout1_d2; dout2_d0 <= dout2; dout2_d1 <= dout2_d0; dout2_d2 <= dout2_d1; dout2_d3 <= dout2_d2; end always@(posedge clk or posedge reset) if(reset) line_1 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_1 <= dout1_d3 + dout1_d2 + dout1_d1 + dout1_d0; else line_1 <= 10'd0; always@(posedge clk or posedge reset) if(reset) line_2 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_2 <= dout2_d3 + dout2_d2 + dout2_d1 + dout2_d0; else line_2 <= 10'd0; always@(posedge clk or posedge reset) if(reset) line_3 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_3 <= dout3_dly[3] + dout3_dly[2] + dout3_dly[1] + dout3_dly[0]; else line_3 <= 10'd0; always@(posedge clk or posedge reset) if(reset) line_4 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_4 <= din_dly[5] + din_dly[4] + din_dly[3] + din_dly[2]; else line_4 <= 10'd0; assign temp = line_1 + line_2 + line_3 + line_4; //4x4窗口均值 always@(posedge clk or posedge reset) if(reset) avg_window <= 8'd0; else if(vd_data>=12'd3 && hdin_dly[6]==1) avg_window <= temp[11:4]; else avg_window <= 8'd0; //計算4x4窗口平方的均值 always@(posedge clk or posedge reset) if(reset) begin a4 <= 8'd0; b4 <= 8'd0; a5 <= 8'd0; b5 <= 8'd0; a6 <= 8'd0; b6 <= 8'd0; a7 <= 8'd0; b7 <= 8'd0; end else if(vd_data>=12'd3 && hdin_dly[1]==1) begin a4 <= dout1; b4 <= dout1; a5 <= dout2; b5 <= dout2; a6 <= dout3; b6 <= dout3; a7 <= din_dly[1]; b7 <= din_dly[1]; end always@(posedge clk) begin p4_d0 <= p4; p4_d1 <= p4_d0; p4_d2 <= p4_d1; p4_d3 <= p4_d2; p5_d0 <= p5; p5_d1 <= p5_d0; p5_d2 <= p5_d1; p5_d3 <= p5_d2; p6_d0 <= p6; p6_d1 <= p6_d0; p6_d2 <= p6_d1; p6_d3 <= p6_d2; p7_d0 <= p7; p7_d1 <= p7_d0; p7_d2 <= p7_d1; p7_d3 <= p7_d2; end always@(posedge clk or posedge reset) if(reset) begin sum_1 <= 18'd0; sum_2 <= 18'd0; sum_3 <= 18'd0; sum_4 <= 18'd0; end else if(vd_data>=12'd3 && hdin_dly[7]==1) begin sum_1 <= p4_d0 + p4_d1 + p4_d2 + p4_d3; sum_2 <= p5_d0 + p5_d1 + p5_d2 + p5_d3; sum_3 <= p6_d0 + p6_d1 + p6_d2 + p6_d3; sum_4 <= p7_d0 + p7_d1 + p7_d2 + p7_d3; end else begin sum_1 <= 18'd0; sum_2 <= 18'd0; sum_3 <= 18'd0; sum_4 <= 18'd0; end always@(posedge clk or posedge reset) if(reset) temp3 <= 20'd0; else if(vd_data>=12'd3 && hdin_dly[8]==1) temp3 <= sum_1 + sum_2 + sum_3 + sum_4; else temp3 <= 20'd0; always@(posedge clk or posedge reset) if(reset) begin a2 <= 8'd0; a2 <= 8'd0; end else if(vd_data>=12'd3 && vd_data<=12'd1439) begin a2 <= avg_window; b2 <= avg_window; end else begin a2 <= 8'd0; b2 <= 8'd0; end always@(posedge clk or posedge reset) if(reset) flag <= 1'd0; else if(temp3[19:4]>p2) flag <= 1'd1; else flag <= 1'd0; //4x4窗口裏的平方差 always@(posedge clk or posedge reset) if(reset) variance_window <= 16'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(temp3[19:4]>p2) variance_window <= temp3[19:4] - p2; else variance_window <= p2 - temp3[19:4]; end else variance_window <= 16'd0; always@(posedge clk or posedge reset) if(reset) temp2 <= 38'd0; else if(vdin==1'd1 && vdin_d0==1'd0) temp2 <= 38'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[10] && hdin_dly[7]) begin if(flag==1) temp2 <= temp2 + variance_window; else temp2 <= temp2 - variance_window; end end always@(posedge clk or posedge reset) if(reset) numbel <= 22'd0; else if(vdin==1'd1 && vdin_d0==1'd0) numbel <= 22'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[10] && hdin_dly[7]) numbel <= numbel + 1'd1; end always@(posedge clk or posedge reset) if(reset) begin dividend1 <= 24'd0; divisor1 <= 16'd1; end else if(vdin==1'd0 && vdin_d0==1'd1) begin dividend1 <= temp2[37:14]; divisor1 <= {8'd0,numbel[21:14]}; end //4x4窗口差值 像素值 - 窗口均值 (有正負值) always@(posedge clk or posedge reset) if(reset) diff_value <= 8'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[7]) begin if(dout3_dly[4]>avg_window) diff_value <= dout3_dly[4] - avg_window; else diff_value <= avg_window - dout3_dly[4]; end else diff_value <= 8'd0; end else diff_value <= 8'd0; always@(posedge clk or posedge reset) if(reset) flag_diff_value <= 1'd0; else if(dout3_dly[4]>=avg_window) flag_diff_value <= 1'd1; else flag_diff_value <= 1'd0; always@(posedge clk) flag_diff_value_dly <= {flag_diff_value_dly[32:0],flag_diff_value}; always@(posedge clk or posedge reset) if(reset) begin a3 <= 16'd0; b3 <= 8'd0; end else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[8]) begin a3 <= quotient1[15:0]; b3 <= diff_value; end else begin a3 <= 16'd0; b3 <= 8'd0; end end else begin a3 <= 16'd0; b3 <= 8'd0; end always@(posedge clk or posedge reset) if(reset) begin dividend2 <= 24'd0; divisor2 <= 16'd1; end else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[10]) begin if(variance_window>quotient1) begin dividend2 <= p3; divisor2 <= variance_window; end else begin dividend2 <= p3; divisor2 <= quotient1[15:0]; end end else begin dividend2 <= 24'd0; divisor2 <= 16'd1; end end else begin dividend2 <= 24'd0; divisor2 <= 16'd1; end always@(posedge clk or posedge reset) if(reset) dout_v <= 8'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[35] && hdin_dly[37]) begin if(flag_diff_value_dly[28]==1) begin if(dout3_dly[34]>quotient2) dout_v <= dout3_dly[34] - quotient2; else dout_v <= 8'd0; end else begin if(dout3_dly[34]+quotient2>=8'd255) dout_v <= 8'd255; else dout_v <= dout3_dly[34] + quotient2; end end else dout_v <= dout3_dly[34]; end else dout_v <= dout3_dly[34]; //=====================================================// always@(posedge clk or posedge reset) if(reset) dout_h <= 9'd0; else dout_h <= dout4_dly[34]; always@(posedge clk or posedge reset) if(reset) dout_s <= 8'd0; else dout_s <= dout5_dly[34]; //=====================================================// always@(posedge clk or posedge reset) if(reset) vdout <= 1'd0; else if(vd_data==12'd1 && hd_data==12'd36) vdout <= 1'd1; else if(vd_data==12'd1441 && hd_data==12'd2093) vdout <= 1'd0; always@(posedge clk or posedge reset) if(reset) hdout <= 1'd0; else if(vdout==1) begin if(hd_data>=12'd62 && hd_data<=12'd1981) hdout <= 1'd1; else hdout <= 1'd0; end else hdout <= 1'd0; always@(posedge clk or posedge reset) if(reset) srst <= 1'd0; else if(vd_data==12'd1450) srst <= 1'd1; else srst <= 1'd0; //========================================================================// fifo_1920x9 fifo_h ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din4 ), // input [8 : 0] din .wr_en (wr_en_h), // input wr_en .rd_en (rd_en_h), // input rd_en .dout (dout4 ), // output [8 : 0] dout .full ( ), // output full .empty ( ) // output empty ); fifo_1920x8 fifo_s ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din5 ), // input [7 : 0] din .wr_en (wr_en_s), // input wr_en .rd_en (rd_en_s), // input rd_en .dout (dout5 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); //========================================================================// fifo_1920x8 fifo1 ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din1 ), // input [7 : 0] din .wr_en (wr_en1), // input wr_en .rd_en (rd_en1), // input rd_en .dout (dout1 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); fifo_1920x8 fifo2 ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din2 ), // input [7 : 0] din .wr_en (wr_en2), // input wr_en .rd_en (rd_en2), // input rd_en .dout (dout2 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); fifo_1920x8 fifo3 ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din3 ), // input [7 : 0] din .wr_en (wr_en3), // input wr_en .rd_en (rd_en3), // input rd_en .dout (dout3 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); //u8xu8 avg_window*avg_window; mult_u8_u8 u_mult_u8_u8_2( .clk (clk ), .a (a2 ), .b (b2 ), .p (p2 ) ); //u8xu8 dout1*dout1; mult_u8_u8 u_mult_u8_u8_4( .clk (clk ), .a (a4 ), .b (b4 ), .p (p4 ) ); //u8xu8 dout2*dout2; mult_u8_u8 u_mult_u8_u8_5( .clk (clk ), .a (a5 ), .b (b5 ), .p (p5 ) ); //u8xu8 dout3*dout3; mult_u8_u8 u_mult_u8_u8_6( .clk (clk ), .a (a6 ), .b (b6 ), .p (p6 ) ); //u8xu8 din*din; mult_u8_u8 u_mult_u8_u8_7( .clk (clk ), .a (a7 ), .b (b7 ), .p (p7 ) ); //計算噪聲的方差 div_u21_u13 u_div_u24_u16_1 ( .clk (clk ), // input clk .rfd ( ), // output rfd .dividend (dividend1 ), // input [30 : 0] dividend .divisor (divisor1 ), // input [15 : 0] divisor .quotient (quotient1 ), // output [20 : 0] quotient .fractional ( ) // output [6 : 0] fractional ); //u16*u8 diff_value*quotient1; mult_u13_u8 u_mult_u13_u8( .clk (clk ), .a (a3 ), .b (b3 ), .p (p3 ) ); div_u21_u13 u_div_u24_u16_2 ( .clk (clk ), // input clk .rfd ( ), // output rfd .dividend (dividend2 ), // input [30 : 0] dividend .divisor (divisor2 ), // input [15 : 0] divisor .quotient (quotient2 ), // output [20 : 0] quotient .fractional ( ) // output [6 : 0] fractional ); endmodule
這是基於RGB數據格式的維納濾波器spa
module winnerfilter( input wire clk, input wire reset, input wire vdin, input wire hdin, input wire[7:0] din, output reg vdout, output reg hdout, output reg[7:0] dout ); reg vdin_d0; reg[37:0] hdin_dly; reg[7:0] din_dly[5:0]; reg[11:0] hd_data; reg[11:0] vd_data; reg wr_en1; reg wr_en2; reg wr_en3; reg rd_en1; reg rd_en2; reg rd_en3; reg [7:0] din1; reg [7:0] din2; reg [7:0] din3; wire[7:0] dout1; wire[7:0] dout2; wire[7:0] dout3; reg[7:0] dout1_d0; reg[7:0] dout1_d1; reg[7:0] dout1_d2; reg[7:0] dout1_d3; reg[7:0] dout2_d0; reg[7:0] dout2_d1; reg[7:0] dout2_d2; reg[7:0] dout2_d3; (*KEEP = "TRUE"*)reg[7:0] dout3_dly[34:0]; reg[9:0] line_1; reg[9:0] line_2; reg[9:0] line_3; reg[9:0] line_4; wire[11:0] temp; reg [7:0] avg_window; reg [7:0] a2; reg [7:0] b2; wire[15:0] p2; reg [7:0] a4; reg [7:0] b4; wire[15:0] p4; reg [7:0] a5; reg [7:0] b5; wire[15:0] p5; reg [7:0] a6; reg [7:0] b6; wire[15:0] p6; reg [7:0] a7; reg [7:0] b7; wire[15:0] p7; reg [15:0] p4_d0; reg [15:0] p4_d1; reg [15:0] p4_d2; reg [15:0] p4_d3; reg [15:0] p5_d0; reg [15:0] p5_d1; reg [15:0] p5_d2; reg [15:0] p5_d3; reg [15:0] p6_d0; reg [15:0] p6_d1; reg [15:0] p6_d2; reg [15:0] p6_d3; reg [15:0] p7_d0; reg [15:0] p7_d1; reg [15:0] p7_d2; reg [15:0] p7_d3; reg [17:0] sum_1; reg [17:0] sum_2; reg [17:0] sum_3; reg [17:0] sum_4; reg [19:0] temp3; reg [15:0] variance_window; reg [37:0] temp2; reg [21:0] numbel; reg srst; reg[23:0] dividend1; reg[15:0] divisor1; wire[23:0] quotient1; reg[7:0] diff_value; reg[15:0] a3; reg[7:0] b3; wire[23:0] p3; reg[23:0] dividend2; reg[15:0] divisor2; wire[23:0] quotient2; reg flag; reg flag_diff_value; reg[33:0] flag_diff_value_dly; always@(posedge clk) hdin_dly <= {hdin_dly[36:0],hdin}; always@(posedge clk) begin vdin_d0 <= vdin; end always@(posedge clk) begin din_dly[0] <= din; dout3_dly[0] <= dout3; end always@(posedge clk) begin:u1 integer i; for(i=0;i<5;i=i+1) begin din_dly[i+1] <= din_dly[i]; end end always@(posedge clk) begin:u2 integer i; for(i=0;i<34;i=i+1) begin dout3_dly[i+1] <= dout3_dly[i]; end end //列計數 always@(posedge clk or posedge reset) if(reset) hd_data <= 12'd0; else if(vdin==1 && vdin_d0==0) hd_data <= 12'd0; else if(hd_data==12'd2093) hd_data <= 12'd0; else hd_data <= hd_data + 1'd1; //行計數 always@(posedge clk or posedge reset) if(reset) vd_data <= 12'd0; else if(vdin==1 && vdin_d0==0) vd_data <= 12'd0; else if(hd_data==12'd2093) vd_data <= vd_data + 1'd1; //4x4窗口 //緩存第一行數據 always@(posedge clk or posedge reset) if(reset) wr_en3 <= 1'd0; else wr_en3 <= hdin; always@(posedge clk or posedge reset) if(reset) rd_en3 <= 1'd0; else if(vd_data>=12'd1 && vd_data<=12'd1440) rd_en3 <= hdin; else rd_en3 <= 1'd0; //緩存第二行數據 always@(posedge clk or posedge reset) if(reset) wr_en2 <= 1'd0; else if(vd_data>=12'd1 && vd_data<=12'd1439) wr_en2 <= hdin_dly[1]; always@(posedge clk or posedge reset) if(reset) rd_en2 <= 1'd0; else if(vd_data>=12'd2 && vd_data<=12'd1439) rd_en2 <= hdin; //緩存第三行數據 always@(posedge clk or posedge reset) if(reset) wr_en1 <= 1'd0; else if(vd_data>=12'd2 && vd_data<=12'd1439) wr_en1 <= hdin_dly[1]; always@(posedge clk or posedge reset) if(reset) rd_en1 <= 1'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) rd_en1 <= hdin; always@(posedge clk or posedge reset) if(reset) din3 <= 8'd0; else if(vdin && hdin) din3 <= din; else din3 <= 8'd0; always@(posedge clk or posedge reset) if(reset) din2 <= 8'd0; else if(vd_data>=12'd1 && vd_data<=12'd1439) din2 <= dout3; else din2 <= 8'd0; always@(posedge clk or posedge reset) if(reset) din1 <= 8'd0; else if(vd_data>=12'd2 && vd_data<=12'd1439) din1 <= dout2; else din1 <= 8'd0; always@(posedge clk) begin dout1_d0 <= dout1; dout1_d1 <= dout1_d0; dout1_d2 <= dout1_d1; dout1_d3 <= dout1_d2; dout2_d0 <= dout2; dout2_d1 <= dout2_d0; dout2_d2 <= dout2_d1; dout2_d3 <= dout2_d2; end always@(posedge clk or posedge reset) if(reset) line_1 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_1 <= dout1_d3 + dout1_d2 + dout1_d1 + dout1_d0; else line_1 <= 10'd0; always@(posedge clk or posedge reset) if(reset) line_2 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_2 <= dout2_d3 + dout2_d2 + dout2_d1 + dout2_d0; else line_2 <= 10'd0; always@(posedge clk or posedge reset) if(reset) line_3 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_3 <= dout3_dly[3] + dout3_dly[2] + dout3_dly[1] + dout3_dly[0]; else line_3 <= 10'd0; always@(posedge clk or posedge reset) if(reset) line_4 <= 10'd0; else if(vd_data>=12'd3 && hdin_dly[5]==1) line_4 <= din_dly[5] + din_dly[4] + din_dly[3] + din_dly[2]; else line_4 <= 10'd0; assign temp = line_1 + line_2 + line_3 + line_4; //4x4窗口均值 always@(posedge clk or posedge reset) if(reset) avg_window <= 8'd0; else if(vd_data>=12'd3 && hdin_dly[6]==1) avg_window <= temp[11:4]; else avg_window <= 8'd0; //計算4x4窗口平方的均值 always@(posedge clk or posedge reset) if(reset) begin a4 <= 8'd0; b4 <= 8'd0; a5 <= 8'd0; b5 <= 8'd0; a6 <= 8'd0; b6 <= 8'd0; a7 <= 8'd0; b7 <= 8'd0; end else if(vd_data>=12'd3 && hdin_dly[1]==1) begin a4 <= dout1; b4 <= dout1; a5 <= dout2; b5 <= dout2; a6 <= dout3; b6 <= dout3; a7 <= din_dly[1]; b7 <= din_dly[1]; end always@(posedge clk) begin p4_d0 <= p4; p4_d1 <= p4_d0; p4_d2 <= p4_d1; p4_d3 <= p4_d2; p5_d0 <= p5; p5_d1 <= p5_d0; p5_d2 <= p5_d1; p5_d3 <= p5_d2; p6_d0 <= p6; p6_d1 <= p6_d0; p6_d2 <= p6_d1; p6_d3 <= p6_d2; p7_d0 <= p7; p7_d1 <= p7_d0; p7_d2 <= p7_d1; p7_d3 <= p7_d2; end always@(posedge clk or posedge reset) if(reset) begin sum_1 <= 18'd0; sum_2 <= 18'd0; sum_3 <= 18'd0; sum_4 <= 18'd0; end else if(vd_data>=12'd3 && hdin_dly[7]==1) begin sum_1 <= p4_d0 + p4_d1 + p4_d2 + p4_d3; sum_2 <= p5_d0 + p5_d1 + p5_d2 + p5_d3; sum_3 <= p6_d0 + p6_d1 + p6_d2 + p6_d3; sum_4 <= p7_d0 + p7_d1 + p7_d2 + p7_d3; end else begin sum_1 <= 18'd0; sum_2 <= 18'd0; sum_3 <= 18'd0; sum_4 <= 18'd0; end always@(posedge clk or posedge reset) if(reset) temp3 <= 20'd0; else if(vd_data>=12'd3 && hdin_dly[8]==1) temp3 <= sum_1 + sum_2 + sum_3 + sum_4; else temp3 <= 20'd0; always@(posedge clk or posedge reset) if(reset) begin a2 <= 8'd0; a2 <= 8'd0; end else if(vd_data>=12'd3 && vd_data<=12'd1439) begin a2 <= avg_window; b2 <= avg_window; end else begin a2 <= 8'd0; b2 <= 8'd0; end always@(posedge clk or posedge reset) if(reset) flag <= 1'd0; else if(temp3[19:4]>p2) flag <= 1'd1; else flag <= 1'd0; //4x4窗口裏的平方差 always@(posedge clk or posedge reset) if(reset) variance_window <= 16'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(temp3[19:4]>p2) variance_window <= temp3[19:4] - p2; else variance_window <= p2 - temp3[19:4]; end else variance_window <= 16'd0; always@(posedge clk or posedge reset) if(reset) temp2 <= 38'd0; else if(vdin==1'd1 && vdin_d0==1'd0) temp2 <= 38'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[10] && hdin_dly[7]) begin if(flag==1) temp2 <= temp2 + variance_window; else temp2 <= temp2 - variance_window; end end always@(posedge clk or posedge reset) if(reset) numbel <= 22'd0; else if(vdin==1'd1 && vdin_d0==1'd0) numbel <= 22'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[10] && hdin_dly[7]) numbel <= numbel + 1'd1; end always@(posedge clk or posedge reset) if(reset) begin dividend1 <= 24'd0; divisor1 <= 16'd1; end else if(vdin==1'd0 && vdin_d0==1'd1) begin dividend1 <= temp2[37:14]; divisor1 <= {8'd0,numbel[21:14]}; end //4x4窗口差值 像素值 - 窗口均值 (有正負值) always@(posedge clk or posedge reset) if(reset) diff_value <= 8'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[7]) begin if(dout3_dly[4]>avg_window) diff_value <= dout3_dly[4] - avg_window; else diff_value <= avg_window - dout3_dly[4]; end else diff_value <= 8'd0; end else diff_value <= 8'd0; always@(posedge clk or posedge reset) if(reset) flag_diff_value <= 1'd0; else if(dout3_dly[4]>=avg_window) flag_diff_value <= 1'd1; else flag_diff_value <= 1'd0; always@(posedge clk) flag_diff_value_dly <= {flag_diff_value_dly[32:0],flag_diff_value}; always@(posedge clk or posedge reset) if(reset) begin a3 <= 16'd0; b3 <= 8'd0; end else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[8]) begin a3 <= quotient1[15:0]; b3 <= diff_value; end else begin a3 <= 16'd0; b3 <= 8'd0; end end else begin a3 <= 16'd0; b3 <= 8'd0; end always@(posedge clk or posedge reset) if(reset) begin dividend2 <= 24'd0; divisor2 <= 16'd1; end else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[10]) begin if(variance_window>quotient1) begin dividend2 <= p3; divisor2 <= variance_window; end else begin dividend2 <= p3; divisor2 <= quotient1[15:0]; end end else begin dividend2 <= 24'd0; divisor2 <= 16'd1; end end else begin dividend2 <= 24'd0; divisor2 <= 16'd1; end always@(posedge clk or posedge reset) if(reset) dout <= 8'd0; else if(vd_data>=12'd3 && vd_data<=12'd1439) begin if(hdin_dly[35] && hdin_dly[37]) begin if(flag_diff_value_dly[28]==1) begin if(dout3_dly[34]>quotient2) dout <= dout3_dly[34] - quotient2; else dout <= 8'd0; end else begin if(dout3_dly[34]+quotient2>=8'd255) dout <= 8'd255; else dout <= dout3_dly[34] + quotient2; end end else dout <= dout3_dly[34]; end else dout <= dout3_dly[34]; always@(posedge clk or posedge reset) if(reset) vdout <= 1'd0; else if(vd_data==12'd1 && hd_data==12'd36) vdout <= 1'd1; else if(vd_data==12'd1441 && hd_data==12'd2093) vdout <= 1'd0; always@(posedge clk or posedge reset) if(reset) hdout <= 1'd0; else if(vdout==1) begin if(hd_data>=12'd62 && hd_data<=12'd1981) hdout <= 1'd1; else hdout <= 1'd0; end else hdout <= 1'd0; always@(posedge clk or posedge reset) if(reset) srst <= 1'd0; else if(vd_data==12'd1450) srst <= 1'd1; else srst <= 1'd0; fifo_1920x8 fifo1 ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din1 ), // input [7 : 0] din .wr_en (wr_en1), // input wr_en .rd_en (rd_en1), // input rd_en .dout (dout1 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); fifo_1920x8 fifo2 ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din2 ), // input [7 : 0] din .wr_en (wr_en2), // input wr_en .rd_en (rd_en2), // input rd_en .dout (dout2 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); fifo_1920x8 fifo3 ( .clk (clk ), // input clk .srst (srst ), // input srst .din (din3 ), // input [7 : 0] din .wr_en (wr_en3), // input wr_en .rd_en (rd_en3), // input rd_en .dout (dout3 ), // output [7 : 0] dout .full ( ), // output full .empty ( ) // output empty ); //u8xu8 avg_window*avg_window; mult_u8_u8 u_mult_u8_u8_2( .clk (clk ), .a (a2 ), .b (b2 ), .p (p2 ) ); //u8xu8 dout1*dout1; mult_u8_u8 u_mult_u8_u8_4( .clk (clk ), .a (a4 ), .b (b4 ), .p (p4 ) ); //u8xu8 dout2*dout2; mult_u8_u8 u_mult_u8_u8_5( .clk (clk ), .a (a5 ), .b (b5 ), .p (p5 ) ); //u8xu8 dout3*dout3; mult_u8_u8 u_mult_u8_u8_6( .clk (clk ), .a (a6 ), .b (b6 ), .p (p6 ) ); //u8xu8 din*din; mult_u8_u8 u_mult_u8_u8_7( .clk (clk ), .a (a7 ), .b (b7 ), .p (p7 ) ); //計算噪聲的方差 div_u21_u13 u_div_u24_u16_1 ( .clk (clk ), // input clk .rfd ( ), // output rfd .dividend (dividend1 ), // input [30 : 0] dividend .divisor (divisor1 ), // input [15 : 0] divisor .quotient (quotient1 ), // output [20 : 0] quotient .fractional ( ) // output [6 : 0] fractional ); //u16*u8 diff_value*quotient1; mult_u13_u8 u_mult_u13_u8( .clk (clk ), .a (a3 ), .b (b3 ), .p (p3 ) ); div_u21_u13 u_div_u24_u16_2 ( .clk (clk ), // input clk .rfd ( ), // output rfd .dividend (dividend2 ), // input [30 : 0] dividend .divisor (divisor2 ), // input [15 : 0] divisor .quotient (quotient2 ), // output [20 : 0] quotient .fractional ( ) // output [6 : 0] fractional ); endmodule