HDLBits习题讲解_More Verilog Features
条件运算符
- verilog中有跟c语言类似的三目运算符,这可以用于在一行中根据条件选择两个值中的一个,而不用在组合always块中使用if-else。
信号 = 条件?表达式1:表达式2; //即当条件成立时,信号取表达式1的值,反之取表达式2的值。
Conditional ternary operator
- 题目要求,给定4个无符号数,求最小值。无符号数可以用比较运算符(a < b)进行比较。代码如下:
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);
wire [7:0] mintemp1,mintemp2;
assign mintemp1 = (a<b)? a:b;
assign mintemp2 = (c<mintemp1)?c:mintemp1;
assign min = (d<mintemp2)?d:mintemp2;
endmodule
缩减运算符
- 缩位运算符可以对向量的各个位进行和、或和异或操作,产生1位的输出。例如:
b = &a; // 等效于b = ((a[0] & a[1]) & a[2]) & a[3];
/////////////////////////////////////////////////////////
A = 5'b11001;
&A; //值等于0, 只有A的各位都为1时,其与缩减运算的值才为1
|A; //值等于1, 只有A的各位都为0时,其或缩减运算的值才为0
Reduction operators
- 奇偶校验经常被用作传输数据时检测错误的简单方法。题目要求,创建一个电路,为一个8位字节计算一个奇偶校验位(它将在1个字节的基础上增加1位)。我们将使用偶校验,其中偶校验位是8个数据位的异或(XOR)。代码如下:
module top_module (
input [7:0] in,
output parity);
assign parity = ^ in;
endmodule
Reduction: Even wider gates
- 题目要求,构建一个组合电路,包括一个100位输入,in[99:0];三个输出:
- out_and:输出100个输入和门。
- out_or:输出100个输入或门。
- out_xor:输出100个输入XOR门。
- 代码如下:
module top_module(
input [99:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
循环语句
- for语句
for(循环变量赋初值;循环结束条件; 循环变量增值) 执行语句;
- 先给控制循环次数的变量赋初值。再判定控制循环的表达式的值, 如为假则跳出循环语句,如为真则执行指定的语句后,执行一条赋值语句来修正控制循环变量次数的变量的值,然后再次判断。
- repeat语句
repeat(循环次数表达式) 语句;
// or
repeat(循环次数表达式)begin……end;
- 连续执行一条语句或者一个语句块 n 次。
- while语句
while(循环执行条件表达式) 语句;
// or
while(循环执行条件表达式) begin……end;
- 执行一条语句直到某个条件不满足。如果一开始条件即不满足(为假),则语句一次也不能被执行。
- forever语句
forever 语句;
// or
forever begin……end;
- forever循环语句连续不断地执行后面的语句或语句块,常用来产生周期性的波形,作为仿真激励信号。它与always语句的不同之处在于它一般用在initial语句块中。若要用它进行模块描述,可用disable语句进行中断。
Combinational for-loop: Vector reversal 2
- 题目要求,给定一个100位的输入向量[99:0],将其逐位倒置。代码如下:
module top_module(
input [99:0] in,
output [99:0] out
);
reg [99:0] out_r;
integer i;
always @(*) begin
for(i=0;i<100;i++) begin
out_r[i]=in[99-i];
end
end
assign out=out_r;
endmodule
Combinational for-loop: 255-bit population count
- 题目要求,对一个255为的输入向量设计一个计数器电路,计数向量中
1
的个数。代码如下:
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
reg [7:0] out_r;
always @(*) begin
out_r = 8'd0;
for(i=0;i<255;i++) begin
out_r = out_r + in[i];
end
end
assign out=out_r;
endmodule
- __tips:__需要注意,在此处代码中,会产生锁存器电路,在实际应用中应酌情使用。如不希望产生锁存器则需要通过遍历所有种可能(2^255),在代码书写上具有较大的代码量。
生成语句
- 循环生成的主要目的是简化我们的代码书写,利用循环生成语句我们可以将之前需要写很多条比较相似的语句才能实现的功能用很简短的循环生成语句来代替。
- 循环生成语句
- 基本语法如下:
///////generate-for语句///////
generate
genvar <var1>;
for (<var1> = 0 ; <var1> < num ; <var1>=<var1>+1)
begin: <label_1>
<code>;
end
endgenerate
- 条件生成语句
- 基本语法如下:
///////generate-if语句///////
generate
if (<condition>) begin: <label_1>
<code>;
end
else if (<condition>) begin: <label_2>
<code>;
end
else begin: <label_3>
<code>;
end
endgenerate
///////generate-case语句///////
generate
case (<constant_expression>)
<value>: begin: <label_1>
<code>
end
<value>: begin: <label_2>
<code>
end
……
default: begin: <label_N>
<code>
end
endcase
endgenerate
Generate for-loop: 100-bit binary adder 2
- 题目要求,通过实例化100个全加器,创建一个100位的进位加法器。代码如下:
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
assign{cout[0],sum[0]}=a[0]+b[0]+cin;//最低位需要进位,单独书写
generate
genvar i; //定义循环变量i
for(i=1;i<100;i++)
begin:adder //给循环生成模块命名
assign{cout[i],sum[i]}=a[i]+b[i]+cout[i-1];//高位均采用循环生成语句
end
endgenerate
endmodule
Generate for-loop: 100-digit BCD adder
- 题目提供了一个名为bcd_fadd的BCD一位加法器,它的输入为两个BCD数字和进位输入信号,并生成求和输出和进位输出信号。
module bcd_fadd {
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
- 要求实例化100个bcd_fadd模块,以创建一个100位的BCD进位加法器。代码如下:
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire cout_temp[99:0];
bcd_fadd u_bcd_fadd_0(
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.cout(cout_temp[0]),
.sum(sum[3:0])
);
generate
genvar i;
for(i=1;i<100;i=i+1)
begin:u_bcd_fadd
bcd_fadd u_bcd_fadd(
.a(a[4*i+3 : 4*i]),
.b(b[4*i+3 : 4*i]),
.cin(cout_temp[i-1]),
.cout(cout_temp[i]),
.sum(sum[4*i+3 : 4*i])
);
end
endgenerate
assign cout = cout_temp[99];
endmodule