贴出我项目代码中一部分的generate代码,跟大家分享一下这种表达方式,期待大家领略其精神实质。
genvar i;
generate
for(i=0;i<32;i=i+1) begin:down_wreq_gen
always @(posedge up_clk )down_wreq[i]<=(up_waddr[13:9]==i)&&(up_wreq==1);
end
endgenerate
这其实是一种类似脚本语言的描述方法,就是循环展开32次。我们可以用C语言写个小代码实现这部分展开:
void main (void){
int i ;
for(i=0;i<32;i=i+1) // begin:down_wreq_gen
printf("always @(posedge up_clk )down_wreq[%-2d]<=(up_waddr[13:9]==%-2d)&&(up_wreq==1);\n",i,i);
//end
}
从上面程序段很清晰看到其实就是generate语句用c语言复述一遍。
C语言执行后,打印出来的结果如下:
always @(posedge up_clk )down_wreq[0 ]<=(up_waddr[13:9]==0 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[1 ]<=(up_waddr[13:9]==1 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[2 ]<=(up_waddr[13:9]==2 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[3 ]<=(up_waddr[13:9]==3 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[4 ]<=(up_waddr[13:9]==4 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[5 ]<=(up_waddr[13:9]==5 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[6 ]<=(up_waddr[13:9]==6 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[7 ]<=(up_waddr[13:9]==7 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[8 ]<=(up_waddr[13:9]==8 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[9 ]<=(up_waddr[13:9]==9 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[10]<=(up_waddr[13:9]==10)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[11]<=(up_waddr[13:9]==11)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[12]<=(up_waddr[13:9]==12)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[13]<=(up_waddr[13:9]==13)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[14]<=(up_waddr[13:9]==14)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[15]<=(up_waddr[13:9]==15)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[16]<=(up_waddr[13:9]==16)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[17]<=(up_waddr[13:9]==17)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[18]<=(up_waddr[13:9]==18)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[19]<=(up_waddr[13:9]==19)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[20]<=(up_waddr[13:9]==20)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[21]<=(up_waddr[13:9]==21)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[22]<=(up_waddr[13:9]==22)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[23]<=(up_waddr[13:9]==23)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[24]<=(up_waddr[13:9]==24)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[25]<=(up_waddr[13:9]==25)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[26]<=(up_waddr[13:9]==26)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[27]<=(up_waddr[13:9]==27)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[28]<=(up_waddr[13:9]==28)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[29]<=(up_waddr[13:9]==29)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[30]<=(up_waddr[13:9]==30)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[31]<=(up_waddr[13:9]==31)&&(up_wreq==1);
这一堆代码就对应上述generate描述的内容。这些代码完全可以替代之前的用generate的描述。
通过这个是不是很形象的理解generate作为脚本语言实现循环罗列的功能了呢?
另外还有一个重要功能就是条件编译,就类似于预处理语句ifdef。这方面例子很多,不多说。

本文通过一个具体的Verilog代码示例,深入解析generate语句的使用方法及其与C语言循环的等价性,展示了如何利用generate进行循环展开,以简化大规模并行信号赋值的编写。
1511

被折叠的 条评论
为什么被折叠?



