HDLBits
Created: Apr 25, 2021
Created by: Martin Ma
Tags: Work
Implicit nets are often a source of hard-to-detect bugs. In Verilog, net-type signals can be implicitly created by an assign statement or by attaching something undeclared to a module port. Implicit nets are always one-bit wires and causes bugs if you had intended to use a vector. Disabling creation of implicit nets can be done using the `default_nettype none directive.
隐式网络通常是难以发现的错误的来源。在Verilog中,网络类型的信号可以通过Assign语句或通过将未声明的内容附加到模块端口来隐式创建。隐式网络始终是一位导线,如果您打算使用矢量,则会导致错误。可以使用`default_nettype none指令禁用隐式网络的创建。
wire [2:0] a, c; // Two vectors
assign a = 3'b101; // a = 101
assign b = a; // b = 1 implicitly-created wire
assign c = b; // c = 001 <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
// This could be a bug if the port was intended to be a vector.
Adding `default_nettype none would make the second line of code an error, which makes the bug more visible.
添加`default_nettype none不会使第二行代码出错,从而使该错误更明显。
When using vectors, the distinction between the two operator types (bitwise or logical) becomes important. A bitwise operation between two N-bit vectors replicates the operation for each bit of the vector and produces a N-bit output, while a logical operation treats the entire vector as a boolean value (true = non-zero, false = zero) and produces a 1-bit output.
使用向量时,两种运算符类型(位运算符或逻辑运算符)之间的区别变得很重要。两个N位向量之间的按位运算会复制该向量的每个位的运算并产生N位输出,而逻辑运算会将整个向量视为布尔值(真=非零,假=零),并且产生1位输出。
This replicates vector by num times. num must be a constant. Both sets of braces are required.
Examples:
{5{1'b1}} // 5'b11111 (or 5'd31 or 5'h1f)
{2{a,b,c}} // The same as {a,b,c,a,b,c}
{3'd5, {2{3'd6}}} // 9'b101_110_110. It's a concatenation of 101 with
// the second vector, which is two copies of 3'b110.
By name
Connecting signals to a module’s ports by name allows wires to remain correctly connected even if the port list changes. This syntax is more verbose, however.
mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );
The above line instantiates a module of type mod_a named “instance2”, then connects signal wa (outside the module) to the port named in1, wb to the port named in2, and wc to the port named out. Notice how the ordering of ports is irrelevant here because the connection will be made to the correct name, regardless of its position in the sub-module’s port list. Also notice the period immediately preceding the port name in this syntax.
1-bit full adder
sum = a ^ b ^ cin
将三个输入a,b,cin按位进行异或。
addsub 减法器,可由加法器得来,当 cin = ‘0’ 时,sum = a+b+0 ; 当 cin = ‘1’ 时,sum = a+(~b)+1
There are three types of assignments in Verilog:
- Continuous assignments (). Can only be used when not inside a procedure (“always block”). assign x = y;(连续赋值)
- Procedural blocking assignment: (). Can only be used inside a procedure. x = y;(阻塞赋值)
- Procedural non-blocking assignment: (). Can only be used inside a procedure. x <= y;(非阻塞赋值)

In a combinational always block, use blocking assignments. In a clocked always block, use non-blocking assignments. A full understanding of why is not particularly useful for hardware design and requires a good understanding of how Verilog simulators keep track of events. Not following this rule results in extremely hard to find errors that are both non-deterministic and differ between simulation and synthesized hardware.
在组合逻辑块中,使用阻塞赋值。在时序逻辑块中,使用非阻塞赋值。

An if statement usually creates a 2-to-1 multiplexer, selecting one input if the condition is true, and the other input if the condition is false.
always @(*) begin
if (condition) begin
out = x;
end
else begin
out = y;
end
end
This is equivalent to using a continuous assignment with a conditional operator:
assign out = (condition) ? x : y;
However, the procedural if statement provides a new way to make mistakes. The circuit is combinational only if out is always assigned a value.
casez
//检测第一个‘1’在哪一位
always @(*) begin
casez (in[3:0])
4'bzzz1: out = 0; // in[3:1] can be anything
4'bzz1z: out = 1;
4'bz1zz: out = 2;
4'b1zzz: out = 3;
default: out = 0;
endcase
end
在每个分支一定要对所有输出都进行赋值
always @(posedge clk) // A T-flip-flop.
q <= toggle ? ~q : q;
//多输入逻辑门
& 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]
奇偶校验(parity check):通过检查输入的数据中“1”的个数来确定传输数据的正确性。奇偶校验位可以通过对数据的每一位按位逐一进行异或操作来得到。对于奇校验,偶数个“1”,输出为0;奇数个“1”,输出为1。偶校验则相反。(eg. 1 ^ 0 ^ 1 ^ 1 ^ 0,结果为1)
//计算输入中含有多少个“1”
module pop_count(
input [254:0] in,
output [7:0] out
);
integer i;
always@(*) begin
out = 8'd0; //essential!!
for(i=0;i<255;i=i+1) begin
if(in[i]==1) out = out + 1'b1;
else out = out;
end
end
endmodule
//100bits ripple-adder 100位行波进位加法器
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
full_adder 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: adder_inst
full_adder add_inst(
.a(a[i]),
.b(b[i]),
.cin(cout[i-1]),
.sum(sum[i]),
.cout(cout[i])
);
end
endgenerate
endmodule
module full_adder(
input a,b,
input cin,
output sum,
output cout
);
assign sum = a ^ b ^ cin;
assign cout = a&b | a&cin | b&cin;
endmodule
同或 = 异或非;
Gatesv
//my code
module top_module(
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different );
genvar i;
generate
for(i=0;i<3;i=i+1) begin:both
assign out_both[i] = (in[i] & in[i+1]) ? 1'b1 : 1'b0;
end
endgenerate
genvar j;
generate
for(j=1;j<4;j=j+1) begin:any
assign out_any[j] = (in[j] | in[j-1]) ? 1'b1 : 1'b0;
end
endgenerate
assign out_different[3] = in[3] ^ in[0];
genvar k;
generate
for(k=0;k<3;k=k+1) begin:different
assign out_different[k] = (in[k] ^ in[k+1]) ? 1'b1 : 1'b0;
end
endgenerate
endmodule
//solution
module top_module (
input [3:0] in,
output [2:0] out_both,
output [3:1] out_any,
output [3:0] out_different
);
// Use bitwise operators and part-select to do the entire calculation in one line of code
// in[3:1] is this vector: in[3] in[2] in[1]
// in[2:0] is this vector: in[2] in[1] in[0]
// Bitwise-OR produces a 3 bit vector. | | |
// Assign this 3-bit result to out_any[3:1]: o_a[3] o_a[2] o_a[1]
// Thus, each output bit is the OR of the input bit and its neighbour to the right:
// e.g., out_any[1] = in[1] | in[0];
// Notice how this works even for long vectors.
assign out_any = in[3:1] | in[2:0];
assign out_both = in[2:0] & in[3:1];
// XOR 'in' with a vector that is 'in' rotated to the right by 1 position: {in[0], in[3:1]}
// The rotation is accomplished by using part selects[] and the concatenation operator{}.
assign out_different = in ^ {in[0], in[3:1]};
endmodule
动态位宽的verilog表示
module top_module (
input [1023:0] in,
input [7:0] sel,
output [3:0] out
);
// We can't part-select multiple bits without an error, but we can select one bit at a time,
// four times, then concatenate them together.
assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};
// Alternatively, "indexed vector part select" works better, but has an unfamiliar syntax:
// assign out = in[sel*4 +: 4]; // Select starting at index "sel*4", then select a total width of 4 bits with increasing (+:) index number.
// assign out = in[sel*4+3 -: 4]; // Select starting at index "sel*4+3", then select a total width of 4 bits with decreasing (-:) index number.
// Note: The width (4 in this case) must be constant.
endmodule
半加器(hadd)
module top_module(
input a, b,
output cout, sum );
assign sum = a ^ b;
assign cout = a & b;
endmodule
全加器(fadd)
module top_module(
input a, b, cin,
output cout, sum );
assign sum = a ^ b ^ cin;
assign cout = a&b | a&cin | b&cin;
endmodule
//行为级描述
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum} = a+b+cin;
endmodule
//同步高电平复位
module top_module (
input clk,
input reset, // Synchronous reset
input [7:0] d,
output [7:0] q
);
always@(posedge clk) begin //reset 不在敏感表中
if(reset) q <= 8'd0;
else q <= d;
end
endmodule
//异步高电平复位
module top_module(
input clk,
input [7:0] d,
input areset,
output reg [7:0] q);
// The only difference in code compared to synchronous reset is in the sensitivity list.
always @(posedge clk, posedge areset)
if (areset)
q <= 0;
else
q <= d;
// In Verilog, the sensitivity list looks strange. The FF's reset is sensitive to the
// *level* of areset, so why does using "posedge areset" work?
// To see why it works, consider the truth table for all events that change the input
// signals, assuming clk and areset do not switch at precisely the same time:
// clk areset output
// x 0->1 q <= 0; (because areset = 1)
// x 1->0 no change (always block not triggered)
// 0->1 0 q <= d; (not resetting)
// 0->1 1 q <= 0; (still resetting, q was 0 before too)
// 1->0 x no change (always block not triggered)
endmodule
本文深入探讨了Verilog语言在数字电路设计中的应用,包括如何避免隐式网络引起的错误、位运算与逻辑运算的区别、不同类型的赋值语句及其适用场景、组合逻辑与时序逻辑的设计方法,以及常见电路模块如加法器、触发器等的行为级描述。
373

被折叠的 条评论
为什么被折叠?



