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