(一)Basic
掌握与门、或门、同或门、异或门的符号及其写法即可。
(二)Vector
(1)Vectors must be declared -> type [upper:lower] vector_name;
for example:
wire [7:0] w; // 8-bit wire
reg [4:1] x; // 4-bit reg
output reg [0:0] y; // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z; // 6-bit wire input (negative ranges are allowed)
output [3:0] a; // 4-bit output wire. Type is ‘wire’ unless specified otherwise.
wire [0:7] b; // 8-bit wire where b[0] is the most-significant bit.
注意:The endianness (or, informally, “direction”) of a vector is whether the the least significant bit has a lower index (little-endian, e.g., [3:0]) or a higher index (big-endian, e.g., [0:3]).
(2)Implicit nets ->Implicit nets are always one-bit wires and causes bugs if you had intended to use a vector.
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.
尤其要注意这种隐式规则,在不写位宽时,常常会出现错误。
例如: assign z={e[0],f[4:0],2’b11};后两位必须加上位宽。
(3)Unpacked vs. Packed Arrays
reg [7:0] mem [255:0]; // 256 unpacked elements, each of which is a 8-bit packed vector of reg.
reg mem2 [28:0]; // 29 unpacked elements, each of which is a 1-bit reg.
(4)位操作,逻辑操作,递减操作(递减运算符(Reduction Operators)为单目运算符,运算符紧跟变量,结果为1bit值)的关系要掌握.
(5)位拼接:注意数字也需要用花括号括起来
The replication operator allows repeating a vector and concatenating them together: {num{vector}}
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.
(三)module
(1)connecting ports by position(不写端口名字按照位置来例化)
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a u1(
out1,out2,a,b,c,d);
endmodule
module top_module ( input clk, input d, output q );
wire q1;
wire q2;
my_dff u1(
.clk(clk),
.d(d),
.q(q1));
my_dff u2(
.clk(clk),
.d(q1),
.q(q2));
my_dff u3(
.clk(clk),
.d(q2),
.q(q));
endmodule
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire [31:0] cout;
add1 u2(
.a(a[0]),
.b(b[0]),
.cin(0),
.cout(cout[0]),
.sum(sum[0]));
genvar i;
generate
for(i=0;i<=30;i=i+1)
begin:loop
add1 u1(
.a(a[i+1]),
.b(b[i+1]),
.cin(cout[i]),
.cout(cout[i+1]),
.sum(sum[i+1]));
end
endgenerate
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
assign {cout,sum}=a+b+cin;
endmodule
(3)加减器
采用补码的形式:
(1)当为加法时,(a+b+0)
(2)当为减法时,(a+~b+1)
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] result
);
reg [31:0] b1;
wire cin1;
wire [31:0] sum;
always@(*)
begin
integer i;
for(i=0;i<=31;i=i+1)
begin
b1[i]=b[i]^sub;
end
end
add16 u1(
.a(a[15:0]),
.b(b1[15:0]),
.cin(sub),
.cout(cin1),
.sum(sum[15:0]));
add16 u2(
.a(a[31:16]),
.b(b1[31:16]),
.cin(cin1),
.cout(),
.sum(sum[31:16]));
assign result={sum[31:16],sum[15:0]};
endmodule
(四)procedures
(1)For synthesizing hardware, two types of always blocks are relevant:
Procedural blocks have a richer set of statements (e.g., if-then, case), cannot contain continuous assignments*, but also introduces many new non-intuitive ways of making errors.
For example, the assign and combinational always block describe the same circuit. Both create the same blob of combinational logic. Both will recompute the output whenever any of the inputs (right side) changes value.
(2)Blocking vs. Non-Blocking Assignment
There are three types of assignments in Verilog:
(3)Always if and case
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;
(4)how to avoid making latches
Syntactically-correct code does not necessarily result in a reasonable circuit (combinational logic + flip-flops). The usual reason is: “What happens in the cases other than those you specified?”. Verilog’s answer is: Keep the outputs unchanged.
This behaviour of “keep outputs unchanged” means the current state needs to be remembered, and thus produces a latch. Combinational logic (e.g., logic gates) cannot remember any state.Unless the latch was intentional, it almost always indicates a bug. Combinational circuits must have a value assigned to all outputs under all conditions. This usually means you always need else clauses or a default value assigned to the outputs.
(5)casex 与 casez
其中casez 语句用来处理不考虑高阻态z的比较过程,casex语句则将高阻态和不定态x都视为不必关心的情况。
For example, this would implement the 4-input priority encoder from the previous exercise:
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