天天看點

【FPGA實作GA】基于FPGA的GA優化算法的設計與實作

`timescale 1ns / 1ps



module GA_tops(
              input i_clk,
              input i_rst,
              input signed[15:0]i_x1,i_x2,i_x3,i_x4,
              output  signed[15:0]o_x1,o_x2,o_x3,o_x4
              );

parameter NUM  = 8;//定義種群數量,8個,FPGA資源消耗為嚴重,是以種群個數定義8    
parameter ITER = 200;//定義疊代次數


//産生用于交叉和變異的随機序列
reg[15:0]PN1;
reg[15:0]PN2;
always@(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     PN1<= 16'b0000_1111_1010_1000;
     PN2<= 16'b0000_0111_0010_1000;
     end
else begin
     PN1<= {PN1[14:0],PN1[3]^PN1[5]};
     PN2<= {PN2[14:0],PN1[1]^PN1[5]};
     end
end
wire pc;
wire pe;

assign pc = PN1[15];
assign pe = PN2[15];    





reg[9:0]iter;//定義一個疊代計數器,用來反映GA優化過程的疊代次數

//for i = 1:4
//    Areas =[Areas,[-0.005;0.005]];
//end
//for i = 1:4
//    Areas =[Areas,[-0.005;0.005]];
//end
//for i = 1:4
//    Areas =[Areas,[-0.01;0.01]];
//end
reg[15:0]pep11[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep12[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep13[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep14[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep21[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep22[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep23[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep24[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep31[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep32[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep33[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg[15:0]pep34[NUM:1];//定義種群數量,32個,FPGA資源消耗為嚴重,是以種群個數定義32
reg finish;
   
reg[31:0]fitness[NUM:1];//定義目标函數   
reg[31:0]err1[NUM:1];//定義目标函數   
reg[31:0]err2[NUM:1];//定義目标函數   
reg[31:0]err3[NUM:1];//定義目标函數   
reg[31:0]err4[NUM:1];//定義目标函數  
     
integer i;
always@(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
          finish  <= 1'd0;
          for(i=1;i<=NUM;i=i+1)
          begin
                  pep11[i]<=16'd12;
                  pep12[i]<=16'd3;
                  pep13[i]<=16'd5;
                  pep14[i]<=16'd2;
                  pep21[i]<=16'd3;
                  pep22[i]<=16'd77;
                  pep23[i]<=16'd12;
                  pep24[i]<=16'd5;
                  pep31[i]<=16'd32;
                  pep32[i]<=16'd45;
                  pep33[i]<=16'd66;
                  pep34[i]<=16'd12;
          end
     end
else begin
          //開始疊代
          if(iter < ITER)
          begin
               //選擇
                  for(i=1;i<=NUM;i=i+1)
                  begin
                  
                          if(fitness[i] > {PN1,PN2})//和一個随機數比較
                          begin
                                  pep11[i]<=pep11[i]>>2;
                                  pep12[i]<=pep12[i]>>2;
                                  pep13[i]<=pep13[i]>>2;
                                  pep14[i]<=pep14[i]>>2;
                                  pep21[i]<=pep21[i]>>2;
                                  pep22[i]<=pep22[i]>>2;
                                  pep23[i]<=pep23[i]>>2;
                                  pep24[i]<=pep24[i]>>2;
                                  pep31[i]<=pep31[i]>>2;
                                  pep32[i]<=pep32[i]>>2;
                                  pep33[i]<=pep33[i]>>2;
                                  pep34[i]<=pep34[i]>>2;
                          end
                          else
                          begin
                              pep11[i]<=16'd12;
                              pep12[i]<=16'd3;
                              pep13[i]<=16'd5;
                              pep14[i]<=16'd2;
                              pep21[i]<=16'd3;
                              pep22[i]<=16'd77;
                              pep23[i]<=16'd12;
                              pep24[i]<=16'd5;
                              pep31[i]<=16'd32;
                              pep32[i]<=16'd45;
                              pep33[i]<=16'd66;
                              pep34[i]<=16'd12;
                          end

                  end
               //交叉
                     if(pc == 1'b0)//不交叉
                     begin
                          for(i=1;i<=NUM;i=i+1)
                          begin
                                  pep11[i]<=pep11[i];
                                  pep12[i]<=pep12[i];
                                  pep13[i]<=pep13[i];
                                  pep14[i]<=pep14[i];
                                  pep21[i]<=pep21[i];
                                  pep22[i]<=pep22[i];
                                  pep23[i]<=pep23[i];
                                  pep24[i]<=pep24[i];
                                  pep31[i]<=pep31[i];
                                  pep32[i]<=pep32[i];
                                  pep33[i]<=pep33[i];
                                  pep34[i]<=pep34[i];
                          end
                     end
                     else begin//交叉
                          for(i=1;i<=NUM;i=i+1)
                          begin
                                  pep11[i]<={pep11[i][15],pep11[i][15:1]} + {pep11[i][15],pep11[NUM+1-i][15:1]};
                                  pep12[i]<={pep12[i][15],pep12[i][15:1]} + {pep12[i][15],pep12[NUM+1-i][15:1]};
                                  pep13[i]<={pep13[i][15],pep13[i][15:1]} + {pep13[i][15],pep13[NUM+1-i][15:1]};
                                  pep14[i]<={pep14[i][15],pep14[i][15:1]} + {pep14[i][15],pep14[NUM+1-i][15:1]};
                                  pep21[i]<={pep21[i][15],pep21[i][15:1]} + {pep21[i][15],pep21[NUM+1-i][15:1]};
                                  pep22[i]<={pep22[i][15],pep22[i][15:1]} + {pep22[i][15],pep22[NUM+1-i][15:1]};
                                  pep23[i]<={pep23[i][15],pep23[i][15:1]} + {pep23[i][15],pep23[NUM+1-i][15:1]};
                                  pep24[i]<={pep24[i][15],pep24[i][15:1]} + {pep24[i][15],pep24[NUM+1-i][15:1]};
                                  pep31[i]<={pep31[i][15],pep31[i][15:1]} + {pep31[i][15],pep31[NUM+1-i][15:1]};
                                  pep32[i]<={pep32[i][15],pep32[i][15:1]} + {pep32[i][15],pep32[NUM+1-i][15:1]};
                                  pep33[i]<={pep33[i][15],pep33[i][15:1]} + {pep33[i][15],pep33[NUM+1-i][15:1]};
                                  pep34[i]<={pep34[i][15],pep34[i][15:1]} + {pep34[i][15],pep34[NUM+1-i][15:1]};
                          end
                     end
               //變異
                     if(pc == 1'b1)//變異
                     begin
                          for(i=1;i<=NUM;i=i+1)
                          begin
                                  pep11[i]<=pep11[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep12[i]<=pep12[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep13[i]<=pep13[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep14[i]<=pep14[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep21[i]<=pep21[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep22[i]<=pep22[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep23[i]<=pep23[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep24[i]<=pep24[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep31[i]<=pep31[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep32[i]<=pep32[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep33[i]<=pep33[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                                  pep34[i]<=pep34[i] + {PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15],PN2[15:7]};
                          end
                     end
                     else begin//不變異
                          for(i=1;i<=NUM;i=i+1)
                          begin
                                  pep11[i]<=pep11[i];//o
                                  pep12[i]<=pep12[i];
                                  pep13[i]<=pep13[i];
                                  pep14[i]<=pep14[i];
                                  pep21[i]<=pep21[i];//g
                                  pep22[i]<=pep22[i];
                                  pep23[i]<=pep23[i];
                                  pep24[i]<=pep24[i];
                                  pep31[i]<=pep31[i];//r
                                  pep32[i]<=pep32[i];
                                  pep33[i]<=pep33[i];
                                  pep34[i]<=pep34[i];
                          end
                     end
          end
     end
end

//标準信号,用來檢測GA優化誤差
wire signed[15:0]sin1;
wire signed[15:0]sin2;
wire signed[15:0]sin3;
wire signed[15:0]sin4;
stardand_sin stardand_sin_u(
                  .i_clk      (i_clk),
                  .i_rst      (i_rst),
                  .o_x1       (sin1),
                  .o_x2       (sin2),
                  .o_x3       (sin3),
                  .o_x4       (sin4),                  
                  .o_en       (),
                  .o_start    ()
                  ); 


//sin,cos
wire[15:0]m_axis_data_tdata1;
dds_compiler_0 dds_compiler_u1(
  .aclk(i_clk),                                  // input wire aclk
  .aresetn(~i_rst),                            // input wire aresetn
  .s_axis_config_tvalid(1'b1),  // input wire s_axis_config_tvalid
  .s_axis_config_tdata(32'd1000000+pep31[1]),    // input wire [39 : 0] s_axis_config_tdata
  .m_axis_data_tvalid(),      // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata1)        // output wire [15 : 0] m_axis_data_tdata
);

wire signed[7:0]sin1;
wire signed[7:0]cos1;
assign sin1 = m_axis_data_tdata1[15:8];
assign cos1 = m_axis_data_tdata1[7:0];

//sin,cos
wire[15:0]m_axis_data_tdata2;
dds_compiler_0 dds_compiler_u2(
  .aclk(i_clk),                                  // input wire aclk
  .aresetn(~i_rst),                            // input wire aresetn
  .s_axis_config_tvalid(1'b1),  // input wire s_axis_config_tvalid
  .s_axis_config_tdata(32'd1000000+pep32[1]),    // input wire [39 : 0] s_axis_config_tdata
  .m_axis_data_tvalid(),      // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata2)        // output wire [15 : 0] m_axis_data_tdata
);

wire signed[7:0]sin2;
wire signed[7:0]cos2;
assign sin2 = m_axis_data_tdata2[15:8];
assign cos2 = m_axis_data_tdata2[7:0];

//sin,cos
wire[15:0]m_axis_data_tdata3;
dds_compiler_0 dds_compiler_u3(
  .aclk(i_clk),                                  // input wire aclk
  .aresetn(~i_rst),                            // input wire aresetn
  .s_axis_config_tvalid(1'b1),  // input wire s_axis_config_tvalid
  .s_axis_config_tdata(32'd1000000+pep33[1]),    // input wire [39 : 0] s_axis_config_tdata
  .m_axis_data_tvalid(),      // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata3)        // output wire [15 : 0] m_axis_data_tdata
);

wire signed[7:0]sin3;
wire signed[7:0]cos3;
assign sin3 = m_axis_data_tdata3[15:8];
assign cos3 = m_axis_data_tdata3[7:0];

//sin,cos
wire[15:0]m_axis_data_tdata4;
dds_compiler_0 dds_compiler_u4(
  .aclk(i_clk),                                  // input wire aclk
  .aresetn(~i_rst),                            // input wire aresetn
  .s_axis_config_tvalid(1'b1),  // input wire s_axis_config_tvalid
  .s_axis_config_tdata(32'd1000000+pep34[1]),    // input wire [39 : 0] s_axis_config_tdata
  .m_axis_data_tvalid(),      // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata4)        // output wire [15 : 0] m_axis_data_tdata
);






wire signed[7:0]sin4;
wire signed[7:0]cos4;
assign sin4 = m_axis_data_tdata4[15:8];
assign cos4 = m_axis_data_tdata4[7:0];

//計算目标值,根據種群的進化的值計算目标函數結果
reg[31:0]sr1[NUM:1];//定義目标函數   
reg[31:0]sr2[NUM:1];//定義目标函數   
reg[31:0]sr3[NUM:1];//定義目标函數   
reg[31:0]sr4[NUM:1];//定義目标函數  

reg[15:0]x10;//定義目标函數   
reg[15:0]x20;//定義目标函數   
reg[15:0]x30;//定義目标函數   
reg[15:0]x40;//定義目标函數  

always@(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
          for(i=1;i<=NUM;i=i+1)
          begin
          fitness[i]<=32'd0;
          err1[i]   <=32'd0;
          err2[i]   <=32'd0;
          err3[i]   <=32'd0;
          err4[i]   <=32'd0;
          sr1[i]    <=32'd0;
          sr2[i]    <=32'd0;
          sr3[i]    <=32'd0;
          sr4[i]    <=32'd0;
          end
          
          x10<=16'd0;
          x20<=16'd0;
          x30<=16'd0;
          x40<=16'd0;
     end
else begin
          for(i=1;i<=NUM;i=i+1)
          begin
           x10<=(i_x1-pep11[i])/(1+pep21[i]);
           x20<=(i_x2-pep12[i])/(1+pep22[i]);
           x30<=(i_x3-pep13[i])/(1+pep23[i]);
           x40<=(i_x4-pep14[i])/(1+pep24[i]);
           sr1[i]<=x10*cos1 - (16'h7fff-x10)*sin1;//根号近似減法運算,
           sr2[i]<=x20*cos2 - (16'h7fff-x20)*sin2;
           sr3[i]<=x30*cos3 - (16'h7fff-x30)*sin3;
           sr4[i]<=x40*cos4 - (16'h7fff-x40)*sin4;
          end
 
          for(i=1;i<=NUM;i=i+1)
          begin
           err1[i]<=sin1-sr1[i];
           err2[i]<=sin2-sr2[i];
           err3[i]<=sin3-sr3[i];
           err4[i]<=sin4-sr4[i];
          end

          for(i=1;i<=NUM;i=i+1)
          begin
           fitness[i]<=err1[i]+err2[i]+err3[i]+err4[i];
          end
     end
end


always@(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     iter<= 10'd0;
     end
else begin
          if(finish == 1'b1)//完成一次疊代運算,那麼finish産生一個1,疊代次數增加1
          iter <= iter+ 10'd1;
          else
          iter <= iter;
     end
end

//選擇fitness最優的對應的輸出作為校正值
reg[3:0]idx;
always@(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     idx<= 4'd0;
     end
else begin
          if(fitness[1] <= fitness[2] & fitness[1] <= fitness[3] &fitness[1] <= fitness[4] &fitness[1] <= fitness[5] &fitness[1] <= fitness[6] &fitness[1] <= fitness[7] &fitness[1] <= fitness[8]) 
          idx<= 4'd1;
          if(fitness[2] <= fitness[1] & fitness[2] <= fitness[3] &fitness[2] <= fitness[4] &fitness[2] <= fitness[5] &fitness[2] <= fitness[6] &fitness[2] <= fitness[7] &fitness[2] <= fitness[8]) 
          idx<= 4'd2;
          if(fitness[3] <= fitness[1] & fitness[3] <= fitness[2] &fitness[3] <= fitness[4] &fitness[3] <= fitness[5] &fitness[3] <= fitness[6] &fitness[3] <= fitness[7] &fitness[3] <= fitness[8]) 
          idx<= 4'd3;
          if(fitness[4] <= fitness[1] & fitness[4] <= fitness[2] &fitness[4] <= fitness[3] &fitness[4] <= fitness[5] &fitness[4] <= fitness[6] &fitness[4] <= fitness[7] &fitness[4] <= fitness[8]) 
          idx<= 4'd4;
          if(fitness[5] <= fitness[1] & fitness[5] <= fitness[2] &fitness[5] <= fitness[3] &fitness[5] <= fitness[4] &fitness[5] <= fitness[6] &fitness[5] <= fitness[7] &fitness[5] <= fitness[8]) 
          idx<= 4'd5;   
          if(fitness[6] <= fitness[1] & fitness[6] <= fitness[2] &fitness[6] <= fitness[3] &fitness[6] <= fitness[4] &fitness[6] <= fitness[5] &fitness[6] <= fitness[7] &fitness[6] <= fitness[8]) 
          idx<= 4'd6;          
          if(fitness[7] <= fitness[1] & fitness[7] <= fitness[2] &fitness[7] <= fitness[3] &fitness[7] <= fitness[4] &fitness[7] <= fitness[5] &fitness[7] <= fitness[6] &fitness[7] <= fitness[8]) 
          idx<= 4'd7;       
          if(fitness[8] <= fitness[1] & fitness[8] <= fitness[2] &fitness[8] <= fitness[3] &fitness[8] <= fitness[4] &fitness[8] <= fitness[5] &fitness[8] <= fitness[6] &fitness[8] <= fitness[7]) 
          idx<= 4'd8; 
     end
end 
    
//優化輸出
wire signed[15:0]o1;
wire signed[15:0]o2;
wire signed[15:0]o3;
wire signed[15:0]o4;
wire signed[15:0]g1;
wire signed[15:0]g2;
wire signed[15:0]g3;
wire signed[15:0]g4;
wire signed[15:0]r1;
wire signed[15:0]r2;
wire signed[15:0]r3;
wire signed[15:0]r4;    


assign o1 = pep11[idx];
assign o2 = pep12[idx];
assign o3 = pep13[idx];
assign o4 = pep14[idx];

assign g1 = pep21[idx];
assign g2 = pep22[idx];
assign g3 = pep23[idx];
assign g4 = pep24[idx];    
            

assign r1 = pep31[idx];
assign r2 = pep32[idx];
assign r3 = pep33[idx];
assign r4 = pep34[idx]; 

//%将估計結果通過校正
//x1_0 = (x1b-o_(1))/(1+g_(1));
//x2_0 = (x2b-o_(2))/(1+g_(2));
//x3_0 = (x3b-o_(3))/(1+g_(3));
//x4_0 = (x4b-o_(4))/(1+g_(4));
reg signed[15:0]rr1;
reg signed[15:0]rr2;
reg signed[15:0]rr3;
reg signed[15:0]rr4;
reg signed[15:0]w_x1,w_x2,w_x3,w_x4;
always@(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
     begin
     w_x1<= 16'd0;
     w_x2<= 16'd0;
     w_x3<= 16'd0;
     w_x4<= 16'd0;
     
     rr1<= 16'd0;
     rr2<= 16'd0;
     rr3<= 16'd0;
     rr4<= 16'd0;
     end
else begin
     rr1<= i_x1-{o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15],o1[15:12]};
     rr2<= i_x2-{o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15],o2[15:12]};
     rr3<= i_x3-{o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15],o3[15:12]};
     rr4<= i_x4-{o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15],o4[15:12]};
     //近似計算
     w_x1<= {rr1}+16'h003f-{g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15],g1[15:12]};
     w_x2<= {rr2}+16'h003f-{g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15],g2[15:12]};
     w_x3<= {rr3}+16'h003f-{g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15],g3[15:12]};
     w_x4<= {rr4}+16'h003f-{g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15],g4[15:12]};
     end
end



dtrigger dtrigger_u1(
              .i_clk (i_clk),
              .i_rst (i_rst),
              .i_x1  (w_x1),
              .o_x1  (o_x1)
    );

dtrigger dtrigger_u2(
              .i_clk (i_clk),
              .i_rst (i_rst),
              .i_x1  (w_x2),
              .o_x1  (o_x2)
    );
    
dtrigger dtrigger_u3(
              .i_clk (i_clk),
              .i_rst (i_rst),
              .i_x1  (w_x3),
              .o_x1  (o_x3)
    );
    
dtrigger dtrigger_u4(
              .i_clk (i_clk),
              .i_rst (i_rst),
              .i_x1  (w_x4),
              .o_x1  (o_x4)
    );


   
endmodule