条件三元运算符(Conditional ternary operator)
Verilog 有一个三元条件运算符 ( ? : ) 很像 C:
(条件 ? if_true : if_false)
这可用于根据一行上的条件(多路复用!)选择两个值之一,而无需在组合始终块中使用 if-then。
例子:
(0 ? 3 : 5) // This is 5 because the condition is false.
(sel ? b : a) // A 2-to-1 multiplexer between a and b selected by sel.
always @(posedge clk) // A T-flip-flop.
q <= toggle ? ~q : q;
always @(*) // State transition logic for a one-input FSM
case (state)
A: next = w ? B : A;
B: next = w ? A : B;
endcase
assign out = ena ? q : 1'bz; // A tri-state buffer
((sel[1:0] == 2'h0) ? a : // A 3-to-1 mux
(sel[1:0] == 2'h1) ? b :
c )
一点练习
给定四个无符号数字,找到最小值。无符号数字可以与标准比较运算符(a < b)进行比较。使用条件运算符制作双向最小电路,然后组合其中的几个以创建 4 路最小电路。您可能需要一些用于中间结果的线向量。
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
wire [7:0]min1,min2;
assign min1=(a<b)?a:b;
assign min2=(c<d)?c:d;
assign min=(min1<min2)?min1:min2;
// assign intermediate_result1 = compare? true: false;
endmodule
归约运算符(Reduction operators)
您已经熟悉两个值之间的按位运算,例如 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])。
一点练习
奇偶校验通常用作通过不完美通道传输数据时检测错误的简单方法。创建一个电路,该电路将计算 8 位字节的奇偶校验位(这将向该字节添加第 9 位)。我们将使用“偶数”奇偶校验,其中奇偶校验位只是所有 8 个数据位的 XOR。
module top_module (
input [7:0] in,
output parity);
assign parity=^in;
endmodule
Reduction:Even wider gates
构建一个具有 100 个输入的组合电路,在 [99:0] 中。
有 3 个输出:
out_and:100输入AND门的输出。
out_or:100输入OR门的输出。
out_xor:100输入异或门的输出。
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循环(Combinational for-loop):Vector reversal 2
给定一个 100 位输入向量 [99:0],反转其位顺序。
4.7 Verilog 循环语句 | 菜鸟教程 (runoob.com)
Verilog 循环语句有 4 种类型,分别是 while,for,repeat,和 forever 循环。循环语句只能在 always 或 initial 块中使用,但可以包含延迟表达式。
四种循环的表达式如下
while
while (condition) begin
…
end
for
for(initial_assignment; condition ; step_assignment) begin
…
end
repeat
repeat (loop_times) begin
…
end
forwever
forever begin
…
end
module top_module(
input [99:0] in,
output [99:0] out
);
always@(*) begin
integer i;
for(i=0;i<=99;i=i+1) begin
out[i]=in[99-i];
end
end
endmodule
组合电路for循环(Combinational for-loop):255-bit population count
“总体计数”电路对输入向量中的“1”数进行计数。为255位输入向量构建一个人口计数电路。
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
always@(*) begin
out=0;
for(i=0;i<255;i=i+1) begin
if(in[i])
out=out+1;
end
end
endmodule
generate for循环(Generate for-loop):100-bit binary adder 2
通过实例化 100 个完整加法器来创建 100 位二进制纹波进位加法器。加法器将两个 100 位数字和一个进位相加,以产生 100 位和并执行。为了鼓励您实际实例化全加器,还要在纹波进位加法器中输出每个全加器的带出。cout[99] 是最后一个完整加法器的最终结转,也是您通常看到的外转。
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
add1 add0(.a(a[0]), .b(b[0]), .cin(cin),.sum(sum[0]), .cout(cout[0]));
genvar i;
generate
for(i=1;i<100;i=i+1)begin: add
add1 U_PROC( .a(a[i]), .b(b[i]), .cin(cout[i-1]),.sum(sum[i]), .cout(cout[i]));
end
endgenerate
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
always@(*) begin
case({a,b,cin})
3'b000:{sum,cout}=2'b00;
3'b001:{sum,cout}=2'b10;
3'b010:{sum,cout}=2'b10;
3'b011:{sum,cout}=2'b01;
3'b100:{sum,cout}=2'b10;
3'b101:{sum,cout}=2'b01;
3'b110:{sum,cout}=2'b01;
3'b111:{sum,cout}=2'b11;
endcase
end
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 纹波进位加法器。您的加法器应添加两个 100 位 BCD 数字(打包到 400 位向量中)和一个携带,以生成 100 位的总和并执行
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire [99:0]cout0;
bcd_fadd bcd0(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(cout0[0]),.sum(sum[3:0]));
genvar i;
generate for(i=1;i<100;i=i+1)begin: bcd
bcd_fadd prog (.a(a[4*i+3:4*i]),.b(b[4*i+3:4*i]),.cin(cout0[i-1]),.cout(cout0[i]),.sum(sum[4*i+3:4*i]));
end
endgenerate
assign cout=cout0[99];
endmodule
值得注意的是
4i+1的表述在verilog中是错误的
4*i+1中乘号不可省略