目录
Combinational for-loop;Vector reversal2
Combinational for-loop : 255-bit population count
Generatefor-loop:100-bit binary adder 2
verilog language
base
simple wire
module top_module( input in, output out );
endmodule
four wires
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
inverter
module top_module( input in, output out );
assign out = ~in;
endmodule
and gate
module top_module(
input a,
input b,
output out );
assign out = a & b;
endmodule
nor gate
module top_module(
input a,
input b,
output out );
assign out = ~(a | b);
endmodule
xnor gate
module top_module(
input a,
input b,
output out );
assign out = ~(a^b);
endmodule
declaring wire
`default_nettype none
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
wire wire_1,wire_2;
assign wire_1 = a & b;
assign wire_2 = c & d;
assign out = wire_1 | wire_2;
assign out_n = ~out;
endmodule
7845 chip
module top_module (
input p1a, p1b, p1c, p1d, p1e, p1f,
output p1y,
input p2a, p2b, p2c, p2d,
output p2y );
assign p2y =( p2a & p2b) | (p2c & p2d);
assign p1y = (p1a & p1c & p1b) | (p1d & p1e & p1f);
endmodule
vectors
vectors
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 o2 = vec[2];
assign o1 = vec[1];
assign o0 = vec[0];
endmodule
Vector1
Build a combinational circuit that splits an input half-word (16 bits, [15:0] ) into lower [7:0] and upper[15:8] bytes.
`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
A 32-bit vector can be viewed as containing 4 bytes (bits [31:24], [23:16], etc.). Build a circuit that will reverse the byte ordering of the 4-byte word.
AaaaaaaaBbbbbbbbCcccccccDddddddd => DdddddddCcccccccBbbbbbbbAaaaaaaa
This operation is often used when the endianness of a piece of data needs to be swapped, for example between little-endian x86 systems and the big-endian formats used in many Internet protocols
module top_module(
input [31:0] in,
output [31:0] out );//
assign out = {in[7:0],in[15:8],in[23:16],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 = {~b,~a};
endmodule
Gates4
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
Vector3
module top_module (
input [4:0] a, b, c, d, e, f,
output [7:0] w, x, y, z );//
assign { w,x,y,z} = {a,b,c,d,e,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
Vector4\
module top_module (
input [7:0] in,
output [31:0] out );//
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 = ~{ {5{a}},{5{b}},{5{c}},{5{d}},{5{e}} } ^ { 5{a,b,c,d,e} };
endmodule
//second way
wire [24:0] way1;
wire [24:0] way2;
assign way1 = ~{{5{a}}, {5{b}}, {5{c}}, {5{d}}, {5{e}}};
assign way2 = {5{a, b, c, d, e}};
assign out = way1 ^ way2;
Modules:Hierarchy
Module
这里主要考察模块例化,介绍中介绍了两种例化方式基于位置(by position)和基于名称(by name)
By position :mod_a instance1(wa,wb,wc);从左到右依次对应相应端口,这种写法简洁,如果模块的端口列表发生更改,则需要找到并更改模块的所有实例以匹配新模块。
By name :mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) ); 他是将模块外部的信号与模块的端口相连接,与顺序无关,故不论子模块的端口列表位置如何,都将对应名称一一连接。
module top_module ( input a, input b, output out );
// mod_a instance1(a,b,out);
mod_a mod_a_inst(
.in1 (a),
.in2 (b),
.out (out)
);
endmodule
/*module mod_a ( input in1, input in2, output out );
// Module body
endmodule*/
Connecting ports by position
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a mod_a_inst(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_inst(
.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 wire_1;
wire wire_2;
my_dff my_dff_inst1(
.clk (clk),
.d (d),
.q (wire_1)
);
my_dff my_dff_inst2(
.clk (clk),
.d (wire_1),
.q (wire_2)
);
my_dff my_dff_inst3(
.clk (clk),
.d (wire_2),
.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] wire_1;
wire [7:0] wire_2;
wire [7:0] wire_3;
my_dff8 my_dff8_inst1(
.clk (clk),
.d (d),
.q (wire_1)
);
my_dff8 my_dff8_inst2(
.clk (clk),
.d (wire_1),
.q (wire_2)
);
my_dff8 my_dff8_inst3(
.clk (clk),
.d (wire_2),
.q (wire_3)
);
always @(*)begin
case (sel)
2'd3: q = wire_3;
2'd2: q = wire_2;
2'd1: q = wire_1;
2'd0: q = d;
endcase
end
endmodule
adder1
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire wire_1;
add16 add16_inst1(
.a (a[15:0]),
.b (b[15:0]),
.cin (0),
.cout (wire_1),
.sum(sum[15:0])
);
add16 add16_inst2(
.a (a[31:16]),
.b (b[31:16]),
.cin (wire_1) ,
.sum (sum[31:16]),
.cout ()
);
endmodule
adder2
add16是已提供的 将两个add16例化,并且写出add1全加器
例图的画法容易混淆 a[15:0] b[15:0] sum[15:0]就已经代表了16个1bit的add1连在一块。不需要重复16次1bit的例化。
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire wire_1;
add16 add16_inst1(
.a (a[15:0]),
.b (b[15:0]),
.cin (0),
.cout (wire_1),
.sum(sum[15:0])
);
add16 add16_inst2(
.a (a[31:16]),
.b (b[31:16]),
.cin (wire_1) ,
.sum (sum[31:16]),
.cout ()
);
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
assign sum = a^b^cin;
assign cout = (a|b)&cin |(a&b);
// assign {count,sum} = a+b+cin;
endmodule
Carry-select adder
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire wire_1;
wire [15:0]sum1;
wire [15:0]sum2;
add16 add16_inst1(
.a (a[15:0]),
.b (b[15:0]),
.cin (0),
.cout (wire_1),
.sum(sum[15:0])
);
add16 add16_inst2(
.a (a[31:16]),
.b (b[31:16]),
.cin (0) ,
.sum (sum1),
.cout ()
);
add16 add16_inst3(
.a (a[31:16]),
.b (b[31:16]),
.cin (1),
.sum (sum2),
.cout ()
);
always @(*)begin
case(wire_1)
1'b0 : sum[31:16] = sum1;
1'b1 : sum[31:16] = sum2;
default :;
endcase
end
//assign sum[31:16] = (wire_1)?sum2:sum1;
endmodule
Adder-subtractor
此题要求做一个具有可切换的(sub)加法—减法器,这个电路由两个可执行操作的电路组成:(a+b+0),(a+~b+1)这里0,1既作为计算的一个数值,同时也作为判断做加法还是减法的控制信号,这个操作由一个异或门形成。
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire [31:0]yihuo;
wire wire_cout;
assign yihuo = b^{32{sub}};
add16 add16_inst1(
.a(a[15:0]),
.b(yihuo[15:0]),
.cin(sub),
.cout(wire_cout),
.sum (sum[15:0])
);
add16 add16_inst2(
.a(a[31:16]),
.b(yihuo[31:16]),
.cin(wire_cout),
.cout(),
.sum (sum[31:16])
);
endmodule
procedures
Always blocks(combinational)
always块中被赋值的要为寄存器型的(reg)变量,而在assign块中被赋值的为线网型(wire)变量。
// 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)
用三种描述方式 描述XOR电路
// 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)
out_always_ff <= a^b;
endmodule
If statement
分别用assign语句和always语句 描述一个二选一多路器,如果sel_b1、sel_b2为1则输出b,否则输出a。
// 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
endmodul
If statement latches
此题主要讲的是; 为什么if语句会引入新的错误,怎么去避免自锁,但我们在在设计电路时我们首先会想:需要一个怎样的逻辑门、需要一个什么样的逻辑块他们以规定的输入产生想要的输出、设置一个触发使电路动作
在设计电路时不要指望自己写的代码会生成一个正确的电路,例如:
If (cpu_overheated) then shut_off_computer = 1;
If (~arrived) then keep_driving = ~gas_tank_empty;
一个正确的语法不一定会获得一个正确的结果,它主要的原因就是当出现你预想其他情况出现的时候,在verilog中会使输出保持不变。那么就意味着这个输出被“记录了”,在组合逻辑电路中是没有“记忆功能的”,所以但我们没有考虑全部的情况,在预想情况的其他情况出现时,他就会输出上一状态的值(latches),这就不符合我们逻辑组合电路设计的本质。
如何避免:对于if语句我们就需要一个else,或一个默认值申明,保证电路在任何时候都能有一个确切的output。
// 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)begin
shut_off_computer = 1;
end
else begin
shut_off_computer = 0;
end
end
always @(*) begin
if (~arrived)begin
keep_driving = ~gas_tank_empty;
end
else begin
keep_driving = 0;
end
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'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 = 'd0;
endcase
end
endmodule
Pority encoder
// synthesis verilog_input_version verilog_2001
module top_module (
input [3:0] in,
output reg [1:0] pos );
always @(*)begin
pos = 'd0;//这里如果没赋初值 那么default : pos = 'd0;
casex (in)
4'bxxx1: pos = 2'd0;
4'bxx10: pos = 2'd1;
4'bx100: pos = 2'd2;
4'b1000: pos = 2'd3;
default :;
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'bzzzzzzz1 : pos = 3'd0;
8'bzzzzzz10 : pos = 3'd1;
8'bzzzzz100 : pos = 3'd2;
8'bzzzz1000 : pos = 3'd3;
8'bzzz10000 : pos = 3'd4;
8'bzz100000 : pos = 3'd5;
8'bz1000000 : pos = 3'd6;
8'b10000000 : pos = 3'd7;
default: pos='d0;
endcase
end
endmodule
Avoiding latches
在case语句中为了避免自锁,要在case赋初值
// 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;
/* default : begin//为什么这个方法结果不对?
left = 1'b0;
down = 1'b0;
right = 1'b0;
up = 1'b0;
end*/
endcase
end
endmodule
More Verilog Features
Conditional ternary operator
构造一个8bit的最小比较器
module top_module (
input [7:0] a, b, c, d,
output [7:0] min);//
wire [7:0] compar_1;
wire[7:0] compar_2;
assign compar_1 = (a<b)?a:b;
assign compar_2 = (compar_1 < c)? compar_1 : c;
assign min= (compar_2 <d )? compar_2:d;// assign intermediate_result1 = compare? true: false;
endmodule
Reduction operators
构建一个8bit奇偶校验电路 偶数为parity= 1 奇数 parity= 0.
module top_module (
input [7:0] in,
output parity);
assign parity = ^in;
endmodule
Reduction even wider gates
module top_module(
input [99:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
Combinational for-loop;Vector reversal2
方法一
module top_module(
input [99:0] in,
output [99:0] out
);
integer i;
always @(*)begin
for (i = 0 ; i <= 99; i++)
out[99-i] = in[i];
end
endmodule
方法二(generate)
module top_module(
input [99:0] in,
output [99:0] out
);
genvar i;
generate
for (i = 0 ; i<= 99; i++)begin:reversal
assign out[99-i] = in[i];
end
endgenerate
endmodule
Combinational for-loop : 255-bit population count
构造一个255的记数器,具有能计255位二进制数中1的个数的功能
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
always @(*)begin
out = 'd0;
for (i = 0 ; i<= 254 ; i++)begin
if(in[i])begin
out = out + 1'b1;
end
else begin
out = out + 1'b0;
end
end
end
endmodule
module top_module(
input [254:0] in,
output [7:0] out );
integer i;
always @(*)begin
out = 'd0;
for (i = 0 ; i<= 254 ; i++)begin
out = out +in[i];
end
end
endmodule