Generate实例化模块

HDLBits链接


三目运算符(形式:condition ? if_true : if_false)

verilog中有跟c语言类似的三目运算符,这可以用于在一行中根据条件选择两个值中的一个,而不用在组合always块中使用if-then。下面给出一些示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(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 )

题目描述

给定4个无符号数,求最小值。无符号数可以用比较运算符(a <b)进行比较。

Solution

1
2
3
4
5
6
7
8
9
10
11
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);

wire [7:0] mintemp1;
wire [7:0] mintemp2;
assign mintemp1 = (a<b)? a:b;
assign mintemp2 = (c<mintemp1)?c:mintemp1;
assign min = (d<mintemp2)?d:mintemp2;

endmodule

缩位运算符

缩位运算符可以对向量的各个位进行和、或和异或操作,产生1位的输出:

1
2
3
& 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]

我们可以通过翻转上述缩位运算的输出来获得NAND、NOR和XNOR缩位运算的输出。

题目描述1:奇偶校验经常被用作传输数据时检测错误的简单方法。创建一个电路,为一个8位字节计算一个奇偶校验位(它将在1个字节的基础上增加1位)。我们将使用“偶数”奇偶校验,其中奇偶校验位只是所有8位数据位的异或。

Solution1

1
2
3
4
5
module top_module (
input [7:0] in,
output parity);
assign parity = ^ in;
endmodule

题目描述2:构建一个组合电路,包括100个输入,in[99:0];

3个输出:

  • out_and:100个与门的输出
  • out_or:100个或门的输出
  • out_xor:100个异或门的输出

Solution2

1
2
3
4
5
6
7
8
9
10
module top_module( 
input [99:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = &in;
assign out_or = |in;
assign out_xor = ^in;
endmodule

for循环的组合逻辑:向量顺序翻转

题目描述

给定一个100位的输入向量,翻转它的位顺序。

Solution

1
2
3
4
5
6
7
8
9
10
11
module top_module( 
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操作

题目描述

“计数”电路对输入向量中的1进行计数。为一个255位输入向量建立一个“计数”电路。

Solution

1
2
3
4
5
6
7
8
9
10
11
12
module top_module( 
input [254:0] in,
output [7:0] out );

integer i;
always @(*) begin
out = 8'd0;
for(i=0;i<255;i++) begin
out = out + in[i];
end
end
endmodule

锁存器会对电路产生哪些影响呢?

  1. 锁存器对毛刺敏感,无异步复位端,不能让芯片在上电时处在确定的状态;
  2. 锁存器会使静态时序分析变得很复杂,不利于设计的可重用。

所以,在ASIC设计中,除了CPU高速电路,或者RAM这种对面积很敏感的电路,一般不提倡用锁存器。


循环生成语句

tips:Verilog中的generate语句常用于编写可配置的、可综合的RTL的设计结构。它可用于创建模块的多个实例化,或者有条件的实例化代码块。

generate循环的语法与for循环语句的语法很相似。但是在使用时必须先在genvar声明中声明循环中使用的索引变量名,然后才能使用它。genvar声明的索引变量被用作整数用来判断generate循环。genvar声明可以是generate结构的内部或外部区域,并且相同的循环索引变量可以在多个generate循环中,只要这些环不嵌套。genvar只有在建模的时候才会出现,在仿真时就已经消失了。

Verilog中generate循环中的generate块可以命名也可以不命名。如果已命名,则会创建一个generate块实例数组。如果未命名,则有些仿真工具会出现警告,因此,最好始终对它们进行命名。

题目描述1

通过实例化100个全加法器,创建一个100位行波进位加法器。

Solution1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module top_module( 
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数字和进位输入信号,并生成求和输出和进位输出信号。

1
2
3
4
5
6
module bcd_fadd {
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );

实例化bcd_fadd的100个副本,以创建一个100位的BCD行波进位加法器。

Solution2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module top_module( 
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

总结

本节设计大量的设计技巧,如for循环的巧用,批量进行例程的例化,这些可以在设计过程中简化工作量。