Verilog Language
Basics
Wire
module top_module( input in, output out );
assign out = in;
endmodule
Wire4
module top_module(
input a,b,c,
output w,x,y,z );
assign w = a;
assign x = b;
assign y = b;
assign z = c;
endmodule
Notgate
module top_module( input in, output out );
assign out = ~in;
endmodule
Andgate
module top_module(
input a,
input b,
output out );
assign out = a && b;
endmodule
Norgate
或非门(英语:NOR gate)是数字逻辑电路中的基本元件,实现逻辑或非功能。有多个输入端,1个输出端,多输入或非门可由2输入或非门和反相器构成。
只有当两个输入A和B为低电平(逻辑0)时输出为高电平(逻辑1)。也可以理解为任意输入为高电平(逻辑1),输出为低电平(逻辑0)。
module top_module(
input a,
input b,
output out );
//或非门(英语:NOR gate)是数字逻辑电路中的基本元件,实现逻辑或非功能。
//有多个输入端,1个输出端,多输入或非门可由2输入或非门和反相器构成。
//只有当两个输入A和B为低电平(逻辑0)时输出为高电平(逻辑1)。也可以理解为任意输入为高电平(逻辑1),输出为低电平(逻辑0)。
assign out = ((a == 1'b0) && (b == 1'b0) ) ? 1'b1 : 1'b0;
endmodule
Xnorgate
module top_module(
input a,
input b,
output out );
//同或门(英语:XNOR gate或equivalence gate)也称为异或非门,
//在异或门的输出端再加上一个非门就构成了异或非门,是数字逻辑电路的基本单元,有2个输入端、1个输出端。
//当2个输入端中有且只有一个是低电平(逻辑0)时,输出为低电平。亦即当输入电平相同时,输出为高电平(逻辑1)。
assign out = (a == b) ? 1'b1 :1'b0;
endmodule
同或门(英语:XNOR gate或equivalence gate)也称为异或非门,
在异或门的输出端再加上一个非门就构成了异或非门,是数字逻辑电路的基本单元,有2个输入端、1个输出端。
当2个输入端中有且只有一个是低电平(逻辑0)时,输出为低电平。亦即当输入电平相同时,输出为高电平(逻辑1)。
Wire decl
//`default_nettype none
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
wire first;
wire second;
assign first = a && b;
assign second = c && d;
assign out = first || second;
assign out_n = ~out;
endmodule
7458
module top_module (
input p1a, p1b, p1c, p1d, p1e, p1f,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
wire wire1;
wire wire2;
wire wire3;
wire wire4;
assign wire1 = p2a && p2b;
assign wire2 = p2c && p2d;
assign p2y = wire1 || wire2;
assign wire3 = p1a && p1b && p1c;
assign wire4 = p1f && p1e && p1d;
assign p1y = wire3 || wire4;
endmodule
Vectors
Vector0
module top_module (
input wire [2:0] vec,
output wire [2:0] outv,
output wire o2,
output wire o1,
output wire o0 ); // Module body starts after module declaration
assign outv = vec;
assign o0 = vec[0];
assign o1 = vec[1];
assign o2 = vec[2];
endmodule
Vector1
`default_nettype none // Disable implicit nets. Reduces some types of bugs.
module top_module(
input wire [15:0] in,
output wire [7:0] out_hi,
output wire [7:0] out_lo );
assign out_hi = in[15:8];
assign out_lo = in[7:0];
endmodule
Vector2
module top_module(
input [31:0] in,
output [31:0] out );//
// assign out[31:24] = ...;
assign out[31:24] = in[7:0];
assign out[23:16] = in[15:8];
assign out[15:8] = in[23:16];
assign out[7:0] = in[31:24];
endmodule
Vectorgates
module top_module(
input [2:0] a,
input [2:0] b,
output [2:0] out_or_bitwise,
output out_or_logical,
output [5:0] out_not
);
assign out_or_bitwise = a | b;
assign out_or_logical = a || b;
assign out_not[5:3] = ~b;
assign out_not[2:0] = ~a;
endmodule
Gates4
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = in[3] & in[2] & in[1] & in[0] ;
assign out_or = in[3] | in[2] | in[1] | in[0] ;
assign out_xor = (in[3] == in[2] == in[1] == in[0]) ? 1'b0 : 1'b1;
endmodule
Vector3
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
// assign { ... } = { ... };
assign w = {a,b[4:2]};
assign x = {b[1:0],c,d[4]};
assign y = {d[3:0],e[4:1]};
assign z = {e[0],f,2'b11};
endmodule
Vectorr
module top_module(
input [7:0] in,
output [7:0] out
);
assign out = {in[0],in[1],in[2],in[3],in[4],in[5],in[6],in[7]};
endmodule
// I know you're dying to know how to use a loop to do this:
//Create a combinational always block. This creates combinational logic that computes the same result
//as sequential code. for-loops describe circuit *behaviour*, not *structure*, so they can only be used
//inside procedural blocks (e.g., always block).
//The circuit created (wires and gates) does NOT do any iteration: It only produces the same result
//AS IF the iteration occurred. In reality, a logic synthesizer will do the iteration at compile time to
//figure out what circuit to produce. (In contrast, a Verilog simulator will execute the loop sequentially
//during simulation.)
//always @(*) begin
// for (int i=0; i<8; i++) // int is a SystemVerilog type. Use integer for pure Verilog.
// out[i] = in[8-i-1];
//end
//It is also possible to do this with a generate-for loop. Generate loops look like procedural for loops,
//but are quite different in concept, and not easy to understand. Generate loops are used to make instantiations
//of "things" (Unlike procedural loops, it doesn't describe actions). These "things" are assign statements,
//module instantiations, net/variable declarations, and procedural blocks (things you can create when NOT inside
//a procedure). Generate loops (and genvars) are evaluated entirely at compile time. You can think of generate
//blocks as a form of preprocessing to generate more code, which is then run though the logic synthesizer.
//In the example below, the generate-for loop first creates 8 assign statements at compile time, which is then
//synthesized.
//Note that because of its intended usage (generating code at compile time), there are some restrictions
//on how you use them. Examples: 1. Quartus requires a generate-for loop to have a named begin-end block
//attached (in this example, named "my_block_name"). 2. Inside the loop body, genvars are read only.
//generate
// genvar i;
// for (i=0; i<8; i = i+1) begin: my_block_name
// assign out[i] = in[8-i-1];
// end
//endgenerate
Vector4
module top_module (
input [7:0] in,
output [31:0] out );//
// assign out = { replicate-sign-bit , the-input };
assign out ={{24{in[7]}},in};
endmodule
Vector5
module top_module (
input a, b, c, d, e,
output [24:0] out );//
// The output is XNOR of two vectors created by
// concatenating and replicating the five inputs.
// assign out = ~{ ... } ^ { ... };
assign out = ~{{5{a}},{5{b}},{5{c}},{5{d}},{5{e}}} ^ {{5{a,b,c,d,e}}};
endmodule
Modules Hierarchy
Module
module top_module ( input a, input b, output out );
mod_a instance2 (
.out(out),
.in1(a),
.in2(b)
);
endmodule
Module pos
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a u_mod_a(
out1,
out2,
a,
b,
c,
d
);
endmodule
Module name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a u_mod_a(
.out1(out1),
.out2(out2),
.in1(a),
.in2(b),
.in3(c),
.in4(d)
);
endmodule
Module shift
module top_module ( input clk, input d, output q );
wire wire1;
wire wire2;
my_dff my_dff_1(
.clk(clk),
.d(d),
.q(wire1)
);
my_dff my_dff_2(
.clk(clk),
.d(wire1),
.q(wire2)
);
my_dff my_dff_3(
.clk(clk),
.d(wire2),
.q(q)
);
endmodule
Module shift8
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] wire1;
wire [7:0] wire2;
wire [7:0] wire3;
my_dff8 my_dff8_u1(
.clk(clk),
.d(d),
.q(wire1)
);
my_dff8 my_dff8_u2(
.clk(clk),
.d(wire1),
.q(wire2)
);
my_dff8 my_dff8_u3(
.clk(clk),
.d(wire2),
.q(wire3)
);
always @( *) begin
case (sel)
2'd0:q <= d;
2'd1:q <= wire1;
2'd2:q <= wire2;
2'd3:q <= wire3;
endcase
end
endmodule
Module add
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire [15:0] low;
wire [15:0] heigh;
wire wire1;
add16 add16_low(
.a(a[15:0]),
.b(b[15:0]),
.cin(1'b0),
.sum(low),
.cout(wire1)
);
add16 add16_heigh(
.a(a[31:16]),
.b(b[31:16]),
.cin(wire1),
.sum(heigh),
.cout()
);
assign sum = {heigh,low};
endmodule
Module fadd
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire [15:0] low;
wire [15:0] heigh;
wire wire1;
add16 add16_low(
.a(a[15:0]),
.b(b[15:0]),
.cin(1'b0),
.sum(low),
.cout(wire1)
);
add16 add16_heigh(
.a(a[31:16]),
.b(b[31:16]),
.cin(wire1),
.sum(heigh),
.cout()
);
assign sum = {heigh,low};
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
// Full adder module here
/*
reg sum1;
reg cout1;
always @( *) begin
case (a + b + cin)
1'b0:begin
cout1 <= 1'b0;
sum1 <= 1'b0;
end
1'b1:
begin
cout1 <= 1'b0;
sum1 <= 1'b1;
end
2'b10:
begin
cout1 <= 1'b1;
sum1 <= 1'b0;
end
2'b11:
begin
cout1 <= 1'b1;
sum1 <= 1'b1;
end
endcase
end
assign sum = sum1;
assign cout = cout1;*/
//Full adder equations:
assign sum = a ^ b ^ cin;//位异或,加法器可以用异或来实现
assign cout = a&b | a&cin | b&cin;
//太复杂了,直接位运算就好了
endmodule
Module cseladd
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire [15:0] low;
wire [15:0] heigh1;
wire [15:0] heigh2;
wire wire1;
add16 add16_low(
.a(a[15:0]),
.b(b[15:0]),
.cin(1'b0),
.sum(low),
.cout(wire1)
);
add16 add16_heigh0(
.a(a[31:16]),
.b(b[31:16]),
.cin(1'b0),
.sum(heigh1),
.cout()
);
add16 add16_heigh1(
.a(a[31:16]),
.b(b[31:16]),
.cin(1'b1),
.sum(heigh2),
.cout()
);
assign sum = (wire1) ? {heigh2,low} : {heigh1,low};
endmodule
Module addsub
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0] new_b;
wire [15:0] low;
wire [15:0] heigh;
wire wire1;
assign new_b = (sub == 1'b1) ? ((~b) + 1'b1) : (b);//补码
add16 add16_low(
.a(a[15:0]),
.b(new_b[15:0]),
.cin(1'b0),
.sum(low),
.cout(wire1)
);
add16 add16_heigh(
.a(a[31:16]),
.b(new_b[31:16]),
.cin(wire1),
.sum(heigh),
.cout()
);
assign sum = {heigh,low};
endmodule
Procedures
Alwaysblock1
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
output wire out_assign,
output reg out_alwaysblock
);
assign out_assign = a & b;
always @( *) begin
out_alwaysblock <= a & b;
end
endmodule
Alwaysblock2
// synthesis verilog_input_version verilog_2001
module top_module(
input clk,
input a,
input b,
output wire out_assign,
output reg out_always_comb,
output reg out_always_ff );
assign out_assign = a ^ b;
always @( *) begin
out_always_comb <= a ^ b;
end
always @(posedge clk) begin
out_always_ff <= a ^b;
end
endmodule
Always if
// synthesis verilog_input_version verilog_2001
module top_module(
input a,
input b,
input sel_b1,
input sel_b2,
output wire out_assign,
output reg out_always );
assign out_assign = ((sel_b1 == 1'b1) && (sel_b2 == 1'b1)) ? b : a;
always @( *) begin
if ((sel_b1 == 1'b1) && (sel_b2 == 1'b1)) begin
out_always <= b;
end
else
out_always <= a;
end
endmodule
Always if2
// synthesis verilog_input_version verilog_2001
module top_module (
input cpu_overheated,
output reg shut_off_computer,
input arrived,
input gas_tank_empty,
output reg keep_driving ); //
always @(*) begin
if (cpu_overheated)
shut_off_computer = 1;
else
shut_off_computer = 0;
end
always @(*) begin
if (~arrived)
keep_driving = ~gas_tank_empty;
else
keep_driving = 0;
end
endmodule
Always case
// synthesis verilog_input_version verilog_2001
module top_module (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output reg [3:0] out );//
always@(*) begin // This is a combinational circuit
case(sel)
3'd0:
out <= data0;
3'd1:
out <= data1;
3'd2:
out <= data2;
3'd3:
out <= data3;
3'd4:
out <= data4;
3'd5:
out <= data5;
default :
out <= 4'b0;
endcase
end
endmodule
Always case2
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @( *) begin
casez (in[3:0])
4'b0000:
pos = 2'd0;
4'bzzz1:
pos = 2'd0;
4'bzz1z:
pos = 2'd1;
4'bz1zz:
pos = 2'd2;
4'b1zzz:
pos = 2'd3;
default :
pos <= 2'd0;
endcase
end
endmodule
Always casez
// synthesis verilog_input_version verilog_2001
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @( *) begin
casez (in)
8'bzzzzzzz1:pos = 3'd0;
8'bzzzzzz1z:pos = 3'd1;
8'bzzzzz1zz:pos = 3'd2;
8'bzzzz1zzz:pos = 3'd3;
8'bzzz1zzzz:pos = 3'd4;
8'bzz1zzzzz:pos = 3'd5;
8'bz1zzzzzz:pos = 3'd6;
8'b1zzzzzzz:pos = 3'd7;
default :pos = 3'd0;
endcase
end
endmodule
Always nolatches
// synthesis verilog_input_version verilog_2001
module top_module (
input [15:0] scancode,
output reg left,
output reg down,
output reg right,
output reg up );
always @( *) begin
left = 1'b0;
down = 1'b0;
right = 1'b0;
up = 1'b0;
case (scancode)
16'he06b:left = 1'b1;
16'he072:down = 1'b1;
16'he074:right = 1'b1;
16'he075:up = 1'b1;
endcase
end
endmodule
More Verilog Features
Conditional
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
// assign intermediate_result1 = compare? true: false;
wire [7:0] ab;
wire [7:0] cd;
assign ab = (a < b) ? a : b;
assign cd = (c < d) ? c : d;
assign min = (ab < cd) ? ab : cd;
endmodule
Reduction
module top_module (
input [7:0] in,
output parity);
assign parity = ^ in[7:0];
endmodule
Gates100
module top_module(
input [99:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = & in[99:0];
assign out_or = | in[99:0];
assign out_xor = ^ in[99:0];
endmodule
Vector100r
module top_module(
input [99:0] in,
output [99:0] out
);
reg [99:0] out1;
always @( *) begin
for (integer i = 0;i<=99 ;i=i+1 ) begin
out1[99-i] <= in[i];
end
end
assign out = out1;
endmodule
/*
integer类型也是一种寄存器数据类型,integer类型的变量为有符号数,而reg类型的变量则为无符号数,用integer的变量都可以用reg定
义,只是用于计数更方便而已。
module top_module (
input [99:0] in,
output reg [99:0] out
);
always @(*) begin
for (int i=0;i<$bits(out);i++) // $bits() is a system function that returns the width of a signal.
out[i] = in[$bits(out)-i-1]; // $bits(out) is 100 because out is 100 bits wide.
end
endmodule
*/
Popcount255
module top_module(
input [254:0] in,
output [7:0] out );
reg [7:0] out1;
always @( *) begin
out1 = 8'b0;//赋值语句一定要放在always块里
for (integer i =0 ;i<=254 ;i=i+1 ) begin
if (in[i] == 1'b1) begin
out1 <= out1 +1'b1;
end
else
out1 <= out1;
end
end
assign out = out1;
endmodule
Adder100i
module top_module(
input [99:0] a, b,
input cin,
output [99:0] cout,
output [99:0] sum );
assign sum[0] = a[0] ^ b[0]^ cin;
assign cout[0] = a[0]&b[0] | a[0]&cin | b[0]&cin;
//这两句就可以实现一个一位全加器
genvar i;
generate
for( i=1; i<=99; i=i+1) begin:add1
assign sum[i] = a[i] ^ b[i]^ cout[i-1];
assign cout[i] = a[i]&b[i] | a[i]&cout[i-1] | b[i]&cout[i-1];
end
endgenerate
endmodule
Bcdadd100
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
reg [99:0] cout_reg;
bcd_fadd (
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.cout(cout_reg[0]),
.sum(sum[3:0])
);
genvar i;
generate
for (i = 1;i<=99 ; i=i+1) begin:fadd
bcd_fadd fadd(
.a(a[4*(i+1)-1:4*(i+1)-4]),
.b(b[4*(i+1)-1:4*(i+1)-4]),
.cin(cout_reg[i-1]),
.cout(cout_reg[i]),
.sum(sum[4*(i+1)-1:4*(i+1)-4])
);
end
endgenerate
assign cout = cout_reg[99];
endmodule