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
更多推荐
所有评论(0)