1.generate for循环语句
(1)使用场景
当同一模块需要多次例化,或同一赋值语句需要多次执行时使用。
(2)语法
genvar i;
generate
for(i;i<=10;i=i+1)begin:名字
循环执行代码;
end
endgenerate
说明:
( A )需要定义循环索引,关键字为genvar,索引名字任意取(这里举例用i)。索引可以定义在generate结构的内部或者generate结构的外部,这就决定了索引的作用范围,当定义在generate外部可以被多个generate使用,但是为了避免冲突,最好一个generate定义一个索引;
( B )generate for结构主体以generate 关键字开始,以endgenerate关键字结束;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1)**,只能是常量(genvar、parameter或lacalparam)类型,保证只会生成一种电路;
比如:我们想将循环次数10修改为一个参数:(i;i<=b;i=i+1) ,要求所有的参数i和b都是genvar,parameter或者lacalparam类型;
( D )循环的主体,在begin后最好命一个名字,如果不写这个名字,有的编译器会报警告;
(3)例子
A 例子1:四个一位半加器构成一个四位半加器
代码:
module half_addr(
input a ,
input b ,
output bin ,
output sum
);
assign sum = a^b;
assign bin = a&b;
endmodule
module generate_test_top(
input [3:0] add_a,
input [3:0] add_b,
output [3:0] bin,
output [3:0] sum
);
genvar i;
generate
for(i=0;i<4;i=i+1)begin:half_addr_f
half_addr u_half_addr(
.a (add_a[i] ),
.b (add_b[i] ),
.bin (bin[i] ),
.sum (sum[i] )
);
end
endgenerate
endmodule
testbench:
module generate_test_tb();
reg [3:0] add_a ;
reg [3:0] add_b ;
wire [3:0] bin ;
wire [3:0] sum ;
initial begin
add_a = 4'b0010;
add_b = 4'b1001;
#100;
add_a = 4'b1011;
add_b = 4'b0010;
end
generate_test_top u_generate_test_top(
.add_a (add_a ),
.add_b (add_b ),
.bin (bin ),
.sum (sum )
);
endmodule
结果:
B例子2:任意位宽数据高位到低位的倒序
代码:
module generate_test_top
#(
parameter data_width = 16
)(
input [15:0] data,
output [15:0] out_data
);
genvar i;
generate
for(i=0;i<data_width;i=i+1)begin:data_shift
assign out_data[data_width-1-i] = data[i];
end
endgenerate
endmodule
testbench:
module generate_test_tb;
reg [15:0] data;
wire [15:0] out_data;
initial begin
data = 16'b 0000_0000_0000_1000;
#100;
data = 16'b 0000_0000_1000_0000;
#100;
data = 16'b 0000_1000_0000_0000;
#100;
data = 16'b 1000_0000_0000_0000;
end
generate_test_top
#(
.data_width (16)
)
u_generate_test_top
(
.data (data ),
.out_data (out_data)
);
endmodule
结果:
2.基本for循环语句(SV中是允许的,verilog中也能运行,但是谨慎使用)
(1)使用场景
代码中同一赋值语句需要多次执行。
(2)语法
integer i;
always@(敏感事件列表)begin
...
for(i;i<=10;i=i+1)begin
循环执行代码;
end
end
说明:
( A )需要定义循环索引,关键字为integer,索引名字任意取(这里举例用i),integer的位宽为宿主机的字的位数,最小为32位,用integer的变量都可以用reg定义;
( B )既可以在组合逻辑中使用,又可以在时序逻辑中使用;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1),与generate for循环不同的是,既可以是常量也可以是变量,不过建议为常量,即(genvar、parameter或lacalparam)类型;
( D )循环的主体,注意与generate for**循环不同的是,循环不需要再begin后命名;
(3)例子
A 例子1:for循环在时序逻辑电路中的应用,实现8位循环移位寄存器
代码:
module for_test_top(
input sys_clk ,
input sys_rst_n ,
input [7:0] indata_a ,
output reg [7:0] outdata_b
);
integer i;
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
outdata_b <= indata_a;
else begin
for(i=0;i<7;i=i+1)begin
outdata_b[i] <= outdata_b[i+1];
end
outdata_b[7] <= outdata_b[0];
end
end
endmodule
testbench:
`timescale 1ns / 1ps
module for_test_tb;
reg sys_clk ;
reg sys_rst_n ;
reg [7:0] indata_a ;
wire [7:0] outdata_b ;
parameter T = 20;
initial begin
sys_clk = 1'b0;
sys_rst_n = 1'b0;
indata_a = 8'b1001_0110;
#T;
sys_rst_n = 1'b1;
end
always #(T/2) sys_clk = !sys_clk;
for_test_top u_for_test_top(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.indata_a (indata_a),
.outdata_b (outdata_b)
);
endmodule
结果:
B 例子2:for循环在组合逻辑电路中的应用,实现8位宽数据高位与低位的倒序
代码:
module for_test_top(
input [7:0] input_data,
output reg [7:0] output_data
);
integer i;
always@(*)begin
for(i=0;i<8;i=i+1)begin
output_data[i] = input_data[7-i];
end
end
endmodule
testbench:
`timescale 1ns / 1ps
module for_test_tb;
reg [7:0] input_data;
wire [7:0] output_data;
initial begin
input_data = 8'b0;
#100;
input_data = 8'b0000_1000;
#100;
input_data = 8'b0010_0000;
#100;
input_data = 8'b1000_0000;
end
for_test_top u_for_test_top(
.input_data (input_data),
.output_data (output_data)
);
endmodule
结果:
2.for循环在函数(function)中的使用
(1)使用场景
这种使用方法,是我在跑Xilinx的AXI4官方例程的时候看到的一种使用方法;
(2)语法
这种使用方法和基本for循环语句语法近似,就是将for循环定义在函数function内(function使用方法这里不在赘述)。
说明:
( A )需要定义循环索引,关键字为integer,索引名字任意取(这里举例用i),integer的位宽为宿主机的字的位数,最小为32位,用integer的变量都可以用reg定义;
( B )既可以在组合逻辑中使用,又可以在时序逻辑中使用;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1),与generate for循环不同的是,既可以是常量也可以是变量,不过建议为常量,即(genvar、parameter或lacalparam)类型;
( D )循环的主体,注意与generate for**循环不同的是,循环不需要再begin后命名;
(3)例子
A 例子1:for循环在function中的使用:求数据的位宽;
代码:
module for_test_top(
output wire [4:0] data_width
);
integer input_data = 32'b0000_1000_0000_0000_0000_0000_0000_0000;
reg [4:0] i = 0;
function [4:0] bit_wide;
input integer data_in;
for(bit_wide = 0;data_in>0;bit_wide = bit_wide + 1'b1)
data_in = data_in >> 1;
endfunction
always@(*)begin
i = bit_wide(input_data);
end
assign data_width = i[4:0];
endmodule
testbench:
`timescale 1ns / 1ps
module for_test_tb;
wire [4:0] data_width;
for_test_top u_for_test_top(
.data_width (data_width )
);
endmodule
结果:
结果为1c,换算成十进制无符号数就是28。
(4)注意(很重要)
A一般模块(模块)的输入变量是wire类型,在模块内是不能被赋值的,而在函数(function)内,输入数据是可以被赋值的;
B在函数内的for循环索引,也可以不是integer类型,也可以是reg类型;