维纳滤波器

最近刚好要处理项目中噪声大的问题,在网上看到这篇博客,就用FPGA实现了一下,效果还可以,原文https://blog.csdn.net/baimafujinji/article/details/73302911

下面是基于HSV数据格式的维纳滤波器

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
View Code

这是基于RGB数据格式的维纳滤波器

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
View Code

猜你喜欢

转载自www.cnblogs.com/xingjian92/p/9257539.html