Verilog的更多功能
三元条件运算符
对于条件表达式b ? x : y
,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值。一个条件表达式绝不会既计算x,又计算y。
Verilog中有一个三元条件运算符很像C语言,这可以用于在一行中根据条件选择两个值中的一个,而不用在组合always块中使用if-then。
题目:给定四个无符号数,求最小值。无符号数可以与标准比较运算符(a <b)进行比较。
答案:
module top_module (a, b, c, d,min);
input [7:0] a, b, c, d;
output [7:0] min;
wire [7:0] min1;
wire [7:0] min2;
assign min1 = (a<b)? a:b;
assign min2 = (c<min1)?c:min1;
assign min = (d<min2)?d:min2;
endmodule
缩位(归约)运算符
归约运算符是一元操作数,相当于C语言中的单目运算符。它是对一个操作数进行位操作,最后得到一个一位的数。
归约运算的过程是第一步先用操作数的第一位和第二位进行位操作,然后再用第一步的结果和操作的数的下一位。
进行位操作,如此重复直到最后一位。
Verilog中的归约运算符包含归约与(&
),归约与非(~&
)、归约或(|
)、归约或非(~|
)、归约异或(^
)、归约同或(~^
)
我们已经熟悉了两个值之间的位运算,例如a&b或a^b。有时,需要创建一个对一个向量的所有位进行操作的宽门,如(a[0]&a[1]&a[2]&a[3]…),如果向量很长的话会很乏味。
归约运算符可以对向量的位进行AND、OR和XOR运算,产生一位输出:
& a[3:0] // AND: a[3]&a[2]&a[1]&a[0]. Equivalent to (a[3:0] == 4'hf)
| b[3:0] // OR: b[3]|b[2]|b[1]|b[0]. Equivalent to (b[3:0] != 4'h0)
^ c[2:0] // XOR: c[2]^c[1]^c[0]
这些是只有一个操作数的一元运算符(类似于NOT运算符!)。您还可以反转这些门的输出来创建NAND、NOR和XNOR门,例如(~&d[7:0]
)
归约运算符与位运算符的异同:
相同点:
1)这些运算符与位运算符使用的符号相同。
2)逻辑运算结果遵从相同的运算规则。
3)基本运算符只有三个&、|、^,其他在这三个的基础上取反组成,如~&
区别:
1)位运算为二元操作符,而归约运算符为一元操作符。
2)位运算符运算结果可以为一位位宽,也可以为多位位宽(向量运算),而归约运算符只有位宽为一位的运算结果。
组合for循环:向量翻转
题目:给定一个100位的输入向量,翻转它的位顺序。
答案:
module top_module(in, out);
input [99:0] in;
output [99:0] out;
integer i;
always @(*)
begin
for(i=0;i<100;i++) begin
out[i]=in[99-i];
end
end
endmodule
组合for循环:255bit计数
题目:“计数”电路对输入向量中的1进行计数。为一个255位输入向量建立一个“计数”电路。
答案:
module top_module(in, out);
input [254:0] in;
output [7:0] out;
integer i;
integer temp;
always @(*)
begin
out = 8'd0;
for(i=0;i<255;i++) begin
out = out + in[i];
end
end
endmodule
生成循环语句
Verilog中的generate语句常用于编写可配置的、可综合的RTL的设计结构。它可用于创建模块的多个实例化,或者有条件的实例化代码块。
1)generate循环结构
generate循环的语法与for循环语句的语法很相似。但是在使用时必须先在genvar声明中声明循环中使用的索引变量名,然后才能使用它。genvar声明的索引变量被用作整数用来判断generate循环。genvar声明可以是generate结构的内部或外部区域,并且相同的循环索引变量可以在多个generate循环中,只要这些环不嵌套。genvar只有在建模的时候才会出现,在仿真时就已经消失了。
2)条件if-generate构造
条件语句从很多的备选块中选择最多一个generate块,请注意,在这我说的是最多,因为有可能是一个也不选择的。在建模中,条件必须为常量表达式。
条件if-generate不关心是否命名,并且可以不具有begin / end。当然,上述两个条件只能包含一项。它也会创建单独的范围和层次结构级别,这个和generate循环是一样的。由于最多选择一个代码块,因此在单个的if-generate中以相同的名称命名所有的备用代码块是合法的,而且这有助于保持对代码的分层引用。但是,不同的generate构造中必须具有不同的名称。
3)条件case-generate构造
与if-generate类似,case-generate也可用于从几个块中有条件地选择一个代码块。它的用法类似于基本case语句,并且if-generate中的所有规则也适用于case-generate块。
题目1:通过实例化100个全加器来创建一个100位二进制行波进位加法器。加法器将两个100位数字和一个进位相加,产生100位和并执行。
答案:
module top_module(a, b, cin, cout, sum);
input [99:0] a, b;
input cin;
output [99:0] cout;
output [99:0] sum;
genvar i;
generate
for(i=0;i<100;i++)
begin:adder
if(i==0)
assign{cout[0],sum[0]}=a[0]+b[0]+cin;
else
assign{cout[i],sum[i]}=a[i]+b[i]+cout[i-1];
end
endgenerate
endmodule
题目2:我们为您提供了一个名为BCD_fadd的BCD一位加法器,它将两个BCD数字相加并执行进位,然后生成一个求和并执行进位。
module bcd_fadd {
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
实例化bcd_fadd的100个副本,以创建一个100位的BCD行波进位加法器。
答案:
module top_module(a, b, cin, cout, sum);
input [399:0] a, b;
input cin;
output cout;
output [399:0] sum;
wire [99:0] cout_temp;
genvar i;
generate
for(i=0;i<100;i++)
begin:bcd_fadd
if(i == 0)
bcd_fadd bcd_inst(a[3:0],b[3:0],cin,cout_temp[0],sum[3:0]);
else
bcd_fadd bcd_inst(a[4*i+3:4*i],b[4*i+3:4*i],cout_temp[i-1],cout_temp[i],sum[4*i+3:4*i]);
end
assign cout=cout_temp[99];
endgenerate
endmodule
以上是HDLBits Verilog语言刷题网站中的More Verilog Features部分,后续部分会继续更新。对一些基础性知识点进行归纳总结,有错误请指正。仅供学习参考,谢谢!!!