Verilog语法:for循环的使用心得

📅 2026/7/13 14:18:43
Verilog语法:for循环的使用心得
在硬件设计中往往会遇到大量相同电路的设计需求。在这种情况下如果能够总结出这些电路的一般规律使用for语句不仅可以减少代码量如果代码量是工作量的话不推荐使用for语句并且在一定程度上提高可读性。在硬件电路中for循环的本质是电路的复制for语句的理解可以把辅助变量i代入把所有情况列举出来。当然在仿真的时候也可以当成类似C语言的循环体来用。设计时for语句是空间维度上的仿真时for语句是时间维度上的。Verilog中的for循环有两种用法第一种是放在always块外面用generate for来生成大量的always块第二种则是放在always块的里面用来给信号进行大量的赋值。下面有一些常见的示意用法。1 generate for用法1.1 always用法时序和组合皆适用output [31:0]dout; reg [7:0]data[0:3];//索引为0~3的reg数组元素为8bit genvar i;//辅助电路生成的变量32bit generate for(i0;i4;ii1) begin: inst_name always(posedge clk or negedge rst_n) if(!rst_n) data[i] 8d0; else if(in_valid) data[i] data[i] 8d1; end endgenerate assign dout {data[3],data[2],data[1],data[0]};该写法相当于产生了4组完全相同的电路i只是起到了辅助的作用生成的示意图如下。1.2 assign用法input [31:0]din; output [31:0]dout; wire [7:0]data[0:3]; //索引为0~3的wire数组元素为8bit genvar i; generate for(i0;i4;ii1) begin: inst_name assign data[i] din[8*i7 : 8*i] 8d1; end endgenerate assign dout {data[3],data[2],data[1],data[0]};该写法同样对assign语句有效即对任意组合逻辑电路同样生效。在verilog的语法规则中类似于wire [7:0]data[0:3]或者reg [7:0]data[0:3]的这种申明不能出现在input和output的端口申明中。示意图如下。1.3 模块的例化用法input [31:0]a; input [31:0]b; output [35:0]dout; wire [8:0]a_b[0:3];//索引为0~3的wire数组元素为8bit genvar i; generate for(i0;i4;ii1) begin: inst_name add add_inst( .clk(clk), .rst_n(rst_n), .din1(a[8*i7 : 8*i]), //8bit .din2(b[8*i7 : 8*i]), //8bit .dout(a_b[i])//9bit ); end assign dout {a_b[3],a_b[2],a_b[1],a_b[0]};generate for也可以用来进行大量有规律的模块例化示意图如下。2 放在always内部使用适用于组合和时序逻辑放在always内部使用时辅助变量的i的申明不能用genvar而应该使用integer i。input [7:0]din; output [7:0]dout3,dout2,dout1,dout0; reg [7:0]r_data[0:3];//索引为0~3的reg数组元素为8bit integer i; always(posedge clk or negedge rst_n) if(!rst_n) for(i0;i4;ii1)begin r_data[i] 8d0; end else begin r_data[0] din; for(i1;i4;ii1)begin r_data[i] r_data[i-1]; end end assign dout0 r_data[0]; assign dout1 r_data[1]; assign dout2 r_data[2]; assign dout3 r_data[3];用for语句生成了一个多bit信号的打拍器一共打了4拍示意图如下所示。3 类似C语言的循环用法主要用于仿真中module add_tb; reg [7:0]din1; reg [7:0]din2; wire [8:0]dout; add add_inst( .din1(din1),//8bit .din2(din2),//8bit .dout(dout)//9bit ); integer seed; initial seed $time; integer i0; initial begin din1 0; din2 0; #20; for(i0;i16;ii1)begin din1 i; //din1 i din2 {$random(seed)} % 256; //生成随机数0~255 #10; end $stop; end endmodule根据for循环生成了16组din1和din2数据用于仿真中仿真图如下图。再举一个常见的for循环用于仿真的例子生成串口的波形图的例子。task Gen_Uart_Rx; input [7:0]byte; integer i; begin uart_rx 1b0; #8680;//115200 for(i0;i8;ii1)begin uart_rx byte[i]; //利用for循环从低到高生成uart图形 #8680; end uart_rx 1b1; #8680; end endtask initial begin uart_rx 1; Rx_Done 0; #10; Gen_Uart_Rx(8h55); //调用task Rx_Done 1b1; #10 Rx_Done 1b0; Gen_Uart_Rx(8hb9); //调用task Rx_Done 1b1; #10 Rx_Done 1b0; #100; $stop; end生成的图形如下所示。这就是Verilog的for循环常见的用法如果还有别的什么用法请在评论区进行补充。