2.5More Verilog Features
2.5.1 Conditional ternary operator
问题陈述:
给定四个无符号数,求最小值。无符号数可以与标准比较运算符(a < b)进行比较。使用条件运算符制作两路最小电路,然后将其中的一些组成一个四路最小电路。您可能需要一些线向量作为中间结果。
Verilog代码:
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
// assign intermediate_result1 = compare? true: false;
wire [7:0]w1,w2;
assign w1=(a<b)?a:b;
assign w2=(c<d)?c:d;
assign min=(w1<w2)?w1:w2;
endmodule
2.5.2 Reduction operation
问题陈述:
当通过不完善的通道传输数据时,奇偶校验通常用作检测错误的简单方法。创建一个电路,计算 8 位字节的奇偶校验位(这将向字节添加第 9 位)。我们将使用“偶数”奇偶校验,其中奇偶校验位只是所有 8 个数据位的 XOR。
Verilog代码:
module top_module (
input [7:0] in,
output parity);
assign parity=^in;
endmodule
2.5.3Reduction:Even wider gates
问题陈述:
在 [99:0] 中构建一个具有 100 个输入的组合电路。
有3个输出:out_and:100 输入与门的输出。 out_or:100 输入或门的输出。 out_xor:100 输入异或门的输出。
Verilog代码:
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
2.5.4Combinational for_loop:Vector reversal 2
问题陈述:
给定一个 100 位输入向量 [99:0],反转其位顺序。
Verilog代码:
module top_module(
input [99:0] in,
output [99:0] out
);
integer n;
always@(*)
begin
for( n=99;n>=0;n--)
out[n]=in[99-n];
end
endmodule
//方法2
module top_module (
input [99:0] in,
output reg [99:0] out
);
always @(*) begin
for (int i=0;i<$bits(out);i++) // $bits() 是一个返回信号宽度的函数
out[i] = in[$bits(out)-i-1];
end
endmodule
2.5.5 Combinational for_loop:255-bit population count
问题陈述:
“人口计数”电路计算输入向量中“1”的数量。为 255 位输入向量构建人口计数电路。
Verilog代码:
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
always@(*)
begin
out=8'b0;
for(i=0;i<255;i++)
out=out+in[i];
end
endmodule
2.5.6 Generate for-loop:100-bit binary adder 2
问题陈述:
通过实例化 100 个全加器来创建一个 100 位二进制波纹进位加法器。加法器将两个 100 位数字和一个进位相加,产生一个 100 位和并执行。为了鼓励您实际实例化全加器,还要输出纹波进位加法器中每个全加器的进位。cout[99] 是最后一个全加器的最终进位,也是您通常看到的进位。
Verilog代码:
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
wire [100:0]w1;
assign cout[99:0]=w1[100:1];
mode_fadd u_0 (.a(a[0]),.b(b[0]),.cin(cin),.cout(w1[1]),.sum(sum[0]));
generate
genvar i;
for(i=1;i<$bits(a);i++)
begin :Go//一定不能忘
mode_fadd u_i (.a(a[i]),.b(b[i]),.cin(w1[i]),.cout(w1[i+1]),.sum(sum[i]));
end
endgenerate
endmodule
module mode_fadd(input a,input b,input cin,output cout,output sum);
assign {cout,sum}=a+b+cin;
endmodule
分析:
这里需要对100个全加器进行例化,而子模块不可以在always模块内部进行调用,可以生成模块重复调用
另外不用实例化的方法:
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
integer i;
always @(*) begin
{cout[0],sum[0]}=a[0]+b[0]+cin;
for(i=1;i<$bits(a);i++)
{cout[i],sum[i]}=a[i]+b[i]+cout[i-1];
end
endmodule
2.5.7
问题陈述:
为您提供了一个名为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 波纹进位加法器。您的加法器应将两个 100 位 BCD 数字(打包成 400 位向量)和一个进位相加,以产生一个 100 位和并执行。
Verilog代码:
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire [400:0] middle;
assign cout=middle[400];
bcd_fadd u_0(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(middle[4]),.sum(sum[3:0]));
generate //子模块不可以在always模块内部进行调用,可以生成模块重复调用
genvar i;
for(i=4;i<400;i=i+4)
begin :Never
bcd_fadd u_i(.a(a[i+3:i]),.b(b[i+3:i]),.cin(middle[i]),.cout(middle[i+4]),.sum(sum[i+3:i]));
end
endgenerate
endmodule