FPGA-for循環對應verilog代碼

爲啥要在FPGA上實現for循環的代碼?

    在現在的編程和算法中,有一部分的算法的速度已經到達了瓶頸,爲了提高算法的速度,提高效率,經常會遇到將c或者c++的代碼轉換爲Verilog語言進行在FPGA上實現。

    下文中,我借鑑的是明德揚的FPGA專題for循環對應verilog代碼,上面是視頻鏈接,本文是博主的學習筆記,喜歡可以拿去借鑑。

例1

for(i=0;i<8;i++){
}

對於這樣一個for循環,我們很容易理解的就是i這裏相當於一個計數器,不斷自加一,但是爲了保證模塊的功能完整,即for循環只執行8次而且只執行一次,所以我們需要一個en使能信號和一個flag來標識計數一次的完成。 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end

assign add_cnt = flag_add;       
assign end_cnt = add_cnt && cnt==8-1;

   
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag_add<=0;
    end
    else if(en==1)begin
        flag_add<=1;
    end
    else if(end_cnt==1)begin
        flag_add<=0;
    end
end


例2

for(i=0;i<8;i++){
    sum +=a[i];
}
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end

assign add_cnt = flag_add;       
assign end_cnt = add_cnt && cnt==8-1 ;

reg [7:0]a [7: 0];

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag_add<=0;
    end
    else if(en==1)begin
        flag_add<=1;
    end
    else if(end_cnt==1)begin
        flag_add<=0;
    end
end
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        sum<=0;
    end
    else begin
        sum<= sum +a[cnt];
    end
end

 if判斷的其中的一種情況:

for(i=0;i<8;i++){
    if(i==6)
        sum +=a[i];
}

 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end

assign add_cnt = flag_add;       
assign end_cnt = add_cnt && cnt==8-1 ;   

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag_add<=0;
    end
    else if(en==1)begin
        flag_add<=1;
    end
    else if(end_cnt==1)begin
        flag_add<=0;
    end
end
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        sum<=0;
    end
    else if(add_cnt && cnt==7-1)begin
        sum<= sum +a[cnt];
    end
end

例3

for(i=0;i<8;i++){
    for(j=0;j<4;j++){
        sum +=a[i][j];
    }
}

 在這裏的雙重循環,我們根據前面想到的是調用兩個計數器,但是這裏不同於二維數組的是,這裏使用 sum <= sum + a[cnt1][cnt0];語法上可能不支持,所以我們可以根據數組的大小來聲明爲對應位寬的線,讓下標索引單線的不同位的切片,從而得到這樣雙重循環的實現。

  同樣的方法我們可以想到常用的ram,我們可以進行聲明對應大小的ram從而對其地址進行索引

//-------------------------------------------------------
//-------------------------------------------------------
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag_add<=0;
    end
    else if(en==1)begin
        flag_add<=1;
    end
    else if(end_cnt==1)begin
        flag_add<=0;
    end
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
       cnt0 <= 0;
   end
   else if(add_cnt0)begin
       if(end_cnt0)
          cnt0 <= 0;
     else
        cnt0 <= cnt0 + 1;
end
end

assign add_cnt0 =flag_add;
assign end_cnt0 = add_cnt0 && cnt0==4-1;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt1 <= 0;
    end
    else if(add_cnt1)begin
        if(end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1;
    end
end

assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==8-1;

reg [7:0]a[7:0][3:0];
reg [255:0]a;
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        sum <= 0;
    end
    else if(add_cnt0==1)begin
        sum <= sum + a[cnt1][cnt0];//可能語法不支持
        sum <= sum + a[(cnt1*32+cnt0*8 + 8-1) -:8];

    end
end

注:固定數的乘法,可以直接使用乘號

例4

for(i=0;i<8;i++){
    if(i==1){
        a = b + 1;
        c = a + d;
        a = 2;
    }
}

 

always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        a <=0;
    end
    else if(add_cnt && cnt ==2-1)begin
        a <=2;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        c <= 0;
    end
    else if(add_cnt && cnt ==2-1)begin
        c = b + 1+ d;
    end
end

例5

 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt0 <= 0;
    end
    else if(add_cnt0)begin
        if(end_cnt0)
            cnt0 <= 0;
        else
            cnt0 <= cnt0 + 1;
    end
end

assign add_cnt0 =flag_add;
assign end_cnt0 = add_cnt0 && cnt0==x-1;

always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt1 <= 0;
    end
    else if(add_cnt1)begin
        if(end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1;
    end
end

assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==y-1;

always  @(*)begin
    x= (len-1) - cnt1;
    y= (len-1);
end
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        vec <=0;
    end
    else if(add_cnt0 && vec[cnt0]<vec[cnt0+1])begin
        vec[cnt0] <= vec[cnt0+1];
        vec[cnt0+1]<= vec[cnt0] ;
    end
end 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章