目录
Combinational for-loop: Vector reversal 2
Combinational for-loop: 255-bit population count
Generate for-loop: 100-bit binary adder 2
Generate for-loop: 100-digit BCD adder
代码中有些根据自己的理解做了一下注释
Verilog Language
Vectors
Vectors
module top_module (
input wire [2:0] vec,
output wire [2:0] outv,
output wire o2,
output wire o1,
output wire o0 ); // 模块主体在模块声明后开始
assign outv = vec;
assign {o2,o1,o0} = vec;
endmodule
Vectors in more detail
`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
Vector part select
module top_module(
input [31:0] in,
output [31:0] out );//
assign out[31:24] = in[7:0]; //将输入的低8位赋给输出的高8位
assign out[23:16] = in[15:8];
assign out[15:8] = in[23:16];
assign out[7:0] = in[31:24];
endmodule
Bitwise operators
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 = {~b,~a};
endmodule
Four-input gates
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
Vector concatenation operator
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
// assign { ... } = { ... };
assign {w,x,y,z} = {a,b,c,d,e,f,2'b11}; //后面两个11需要说明其位数和类型
endmodule
Vector reversal 1
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
Replication operator
module top_module (
input [7:0] in,
output [31:0] out );//
// assign out = { replicate-sign-bit , the-input };
assign out = {{24{in[7]}},in[7:0]};
endmodule
More replication
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
Modules
module top_module ( input a, input b, output out );
mod_a mod_a_inst1 (.in1(a), .in2(b), .out(out) ); //调用模块,随便取一个模块名,括号外面是内部要牵出来的线,
//括号里面是外部要连接的线
endmodule
Connecting ports by position
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a mod_a_inst1 (out1,out2,a,b,c,d);
endmodule
Connecting ports by name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a mod_a_inst1(.in1(a), .in2(b), .in3(c), .in4(d), .out1(out1), .out2(out2) ); //按照名字来例化
endmodule
Three modules
module top_module ( input clk, input d, output q );
wire w1,w2;
my_dff my_dff_inst1(.clk(clk), .d(d), .q(w1));
my_dff my_dff_inst2(.clk(clk), .d(w1), .q(w2));
my_dff my_dff_inst3(.clk(clk), .d(w2), .q(q));
endmodule
Modules and vectors
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] w1,w2,w3;
my_dff8 my_dff8_inst1(.clk(clk), .d(d), .q(w1));
my_dff8 my_dff8_inst2(.clk(clk), .d(w1), .q(w2));
my_dff8 my_dff8_inst3(.clk(clk), .d(w2), .q(w3));
always @(*)
begin
case(sel)
2'b00 : begin q = d; end
2'b01 : begin q = w1; end
2'b10 : begin q = w2; end
2'b11 : begin q = w3; end
endcase
end
endmodule
Adder 1
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire [15:0] sum1,sum2;
wire count_temp;
add16 add16_inst1(.a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum1), .cout(count_temp));
add16 add16_inst2(.a(a[31:16]), .b(b[31:16]), .cin(count_temp), .sum(sum2));
assign sum = {sum2,sum1};
endmodule
Adder 2
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire [15:0] sum1,sum2;
wire w1;
add16 add16_inst1(.a(a[15:0]), .b(b[15:0]), .cin(1'b0), .sum(sum1), .cout(w1) );
add16 add16_inst2(.a(a[31:16]), .b(b[31:16]), .cin(w1), .sum(sum2) );
assign sum = {sum2,sum1};
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
// Full adder module here
assign sum = a ^ b ^ cin;
assign cout = (a & b) | (a & cin) | (b & cin);
endmodule
Carry-select adder
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire w1;
wire [15:0] sum0,sum1;
add16 add16_inst1(.a(a[15:0]), .b(b[15:0]), .cin(1'b0), .cout(w1), .sum(sum[15:0]) );
add16 add16_inst2(.a(a[31:16]), .b(b[31:16]), .cin(1'b0), .sum(sum0) );
add16 add16_inst3(.a(a[31:16]), .b(b[31:16]), .cin(1'b1), .sum(sum1) );
always @(*) begin //所有的行为语句需要在initial 或 always 块中执行
case (w1)
1'b0 : begin
sum[31:16] = sum0;
end
1'b1 : begin
sum[31:16] = sum1;
end
endcase
end
endmodule
Adder-subtractor
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0]sub_b;
wire w1;
assign sub_b = {32{sub}} ^ b; //位宽不同进行异或
//先把小数位的值进行扩展,然后在进行按位异或。
add16 add16_low(.a(a[15:0]), .b(sub_b[15:0]), .cin(sub), .cout(w1), .sum(sum[15:0]) );
add16 add16_high(.a(a[31:16]), .b(sub_b[31:16]), .cin(w1), .sum(sum[31:16]) );
endmodule
Procedures
Always blocks (combinational)
// 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
Always blocks (clocked)
// 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
If statement
// 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 & sel_b2) ? (b) : (a);
always @(*)
begin
if(sel_b1 & sel_b2)
begin
out_always = b;
end
else
begin
out_always = a;
end
end
endmodule
If statement latches
// 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
Case statement
// 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'b000 : begin
out = data0 ;
end
3'b001 : begin
out = data1;
end
3'b010 : begin
out = data2;
end
3'b011 : begin
out = data3;
end
3'b100 : begin
out = data4;
end
3'b101 : begin
out = data5;
end
default : out = 4'b0000;
endcase
end
endmodule
Priority encoder
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @(*) begin
casex(in)
4'bxxx1 : pos = 2'b00; //第0位为有效位
4'bxx1x : pos = 2'b01; //第1位为有效位
4'bx1xx : pos = 2'b10; //第2位为有效位
4'b1xxx : pos = 2'b11; //第3位为有效位
default : pos = 2'b00; //所有位为0时
endcase
end
endmodule
Priority encoder with casez
// synthesis verilog_input_version verilog_2001
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez(in)
8'bzzzz_zzz1 : pos = 3'b000;
8'bzzzz_zz1z : pos = 3'b001;
8'bzzzz_z1zz : pos = 3'b010;
8'bzzzz_1zzz : pos = 3'b011;
8'bzzz1_zzzz : pos = 3'b100;
8'bzz1z_zzzz : pos = 3'b101;
8'bz1zz_zzzz : pos = 3'b110;
8'b1zzz_zzzz : pos = 3'b111;
default : pos = 3'b000;
endcase
end
endmodule
Avoiding latches
// 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[15:0])
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 ternary operator
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
// assign intermediate_result1 = compare? true: false;
assign min = (a<b ? (a<c ? (a<d ? a : d) :(c<d ? c:d) ) : (b<c ? (b<d ? b :d):(c<d ? c:d) ) );
endmodule
Reduction operators
module top_module (
input [7:0] in,
output parity);
assign parity = ^in[7:0];
endmodule
Reduction: Even wider gates
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
Combinational for-loop: Vector reversal 2
module top_module(
input [99:0] in,
output [99:0] out
);
reg [7:0] i; //i是系统默认为二进制数
always @(*)
begin
for(i=0;i<100;i=i+1)
out[99-i] = in[i];
end
endmodule
Combinational for-loop: 255-bit population count
module top_module(
input [254:0] in,
output [7:0] out );
always @(*) begin
out = 0;
for(int i=0;i<255;i=i+1)
out = out +in[i]; //计算in中有多少个1;
end
endmodule
Generate for-loop: 100-bit binary adder 2
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 :adder100i //生成块的名字必须要有
if(i==0)
assign {cout[0],sum[0]} = a[0] + b[0] + cin; //cin为进位输入,cout为进位输出
else
assign {cout[i],sum[i]} = a[i] + b[i] + cout[i-1]; //100位的全加器是将上一个的进位输出与下一个的进位输入相连
end
endgenerate
endmodule
Generate for-loop: 100-digit BCD adder
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
if(i==0)
bcd_fadd inst1(
.a(a[3:0]),
.b(b[3:0]),
.cin(cin),
.cout(cout_temp[0]),
.sum(sum[3:0])
);
else
bcd_fadd inst2(
.a(a[4*i+3:4*i]),
.b(b[4*i+3:4*i]),
.cin(cout_temp[i-1]),
.cout(cout_temp[i]),
.sum(sum[4*i+3:4*i]) );
end
endgenerate
assign cout = cout_temp[99];
endmodule