1 逻辑门1.1 n 位与门1.1.1 写法一1.1.2 写法二1.1.3 测试代码1.2 n 位或门1.2.1 写法一1.2.2 写法二1.2.3 测试代码1.3 非门1.3.1 模块代码1.3.2 测试代码1.4 n 位与非门1.4.1 写法一1.4.2 写法二1.4.3 写法三1.4.4 测试代码1.5 n 位或非门1.5.1 写法一1.5.2 写法二1.5.3 写法三1.5.4 测试代码1.6 n 位异或门1.6.1 写法一1.6.2 写法二1.6.3 测试代码1.7 n 位同或门1.7.1 写法一1.7.2 写法二1.7.3 写法三1.7.4 测试代码2 触发器2.1 RS 触发器2.1.1 基本 RSFF2.1.2 同步 RSFF2.1.3 主从 RSFF2.1.4 测试代码2.2 D 触发器2.2.1 同步 DFF2.2.2 边沿 DFF2.2.3 测试代码2.3 JK 触发器2.3.1 同步 JKFF2.3.2 主从 JKFF2.3.3 边沿 JKFF2.3.4 测试代码2.4 T 触发器2.4.1 同步 TFF2.4.2 同步 T'FF2.4.3 测试代码3 组合逻辑电路3.1 编码器3.1.1 普通编码器1 方法一2 方法二3 方法三4 测试代码3.1.2 优先编码器1 方法一2 方法二3 方法三4 方法四5 测试代码3.2 译码器3.2.1 二进制译码器1 方法一2 方法二3 方法三4 测试代码3.2.2 七段译码管1 模块代码2 测试代码3.3 数据分配器3.3.1 模块代码3.3.2 测试代码3.4 数据选择器3.4.1 双四选一1 模块代码2 测试代码3.4.2 八选一1 模块代码2 测试代码3.5 n 位数值比较器3.5.1 模块代码3.5.2 测试代码3.6 算术运算电路3.6.1 半加器1 方法一2 方法二3 测试代码3.6.2 全加器1 方法一2 方法二3 测试代码3.6.3 半减器1 方法一2 方法二3 测试代码3.6.4 全减器1 方法一2 方法二3 方法三4 测试代码3.7 奇偶校验器3.7.1 模块代码3.7.2 测试代码4 时序逻辑电路4.1 寄存器4.1.1 n 位数码寄存器1 模块代码2 测试代码4.1.2 n 位锁存器1 模块代码2 测试代码4.1.3 n 位移位寄存器1 模块代码2 测试代码4.2 2n 分频器4.2.1 模块代码4.2.2 测试代码4.3 计数器4.3.1 n 位二进制加法计数器1 模块代码2 测试代码4.3.2 n 位二进制可逆计数器1 模块代码2 测试代码4.3.3 BCD 码 24 进制计数器1 模块代码2 测试代码4.3.4 BCD 码 60 进制计数器1 模块代码2 测试代码5 代码下载
x1// method 1
2module and_gate(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 assign out in;
8endmodule
xxxxxxxxxx
1171// method 2
2module and_gate2(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 reg temp;
8 integer i;
9 always @(in) begin
10 temp in[0];
11 for (i 1; i < n; i i 1) begin
12 temp temp in[i];
13 end
14 end
15
16 assign out temp;
17endmodule
x
1// testbench of and_gate
2`timescale 1ns10ps
3module and_gate_tb;
4 reg[2:0] in;
5 wire out1, out2;
6
7 and_gate #3 and_gate_1(.in(in), .out(out1));
8 and_gate2 #3 and_gate_2(.in(in), .out(out2));
9
10 initial begin
11 in < 0;
12 #200 ;
13 end
14
15 always #5 in < in 1;
16endmodule
xxxxxxxxxx
11// method 1
2module or_gate(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 assign out in;
8endmodule
xxxxxxxxxx
1171// method 2
2module or_gate2(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 reg temp;
8 integer i;
9 always @(in) begin
10 temp in[0];
11 for (i 1; i < n; i i 1) begin
12 temp temp in[i];
13 end
14 end
15
16 assign out temp;
17endmodule
x
1// testbench of or_gate
2`timescale 1ns10ps
3module or_gate_tb;
4 reg[2:0] in;
5 wire out1, out2;
6
7 or_gate #3 or_gate_1(.in(in), .out(out1));
8 or_gate2 #3 or_gate_2(.in(in), .out(out2));
9
10 initial begin
11 in < 0;
12 #200 ;
13 end
14
15 always #5 in < in 1;
16endmodule
xxxxxxxxxx
11// not-gate
2module not_gate(in, out);
3 input in;
4 output out;
5
6 assign out in;
7endmodule
x
1// testbench of not_gate
2`timescale 1ns10ps
3module not_gate_tb;
4 reg in;
5 wire out;
6
7 not_gate not_gate(.in(in), .out(out));
8
9 initial begin
10 in < 0;
11 #10 in < 1;
12 #10 ;
13 end
14endmodule
xxxxxxxxxx
11// method 1
2module nand_gate(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 assign out (in);
8endmodule
xxxxxxxxxx
1171// method 2
2module nand_gate2(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 reg temp;
8 integer i;
9 always @(in) begin
10 temp in[0];
11 for (i 1; i < n; i i 1) begin
12 temp temp in[i];
13 end
14 end
15
16 assign out temp;
17endmodule
xxxxxxxxxx
1101// method 3
2module nand_gate3(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 wire temp;
8 and_gate #n and_gate_temp(.in(in), .out(temp));
9 assign out temp;
10endmodule
x
1// testbench of nand_gate
2`timescale 1ns10ps
3module nand_gate_tb;
4 reg[2:0] in;
5 wire out1, out2, out3;
6
7 nand_gate #3 nand_gate_1(.in(in), .out(out1));
8 nand_gate2 #3 nand_gate_2(.in(in), .out(out2));
9 nand_gate3 #3 nand_gate_3(.in(in), .out(out3));
10
11 initial begin
12 in < 0;
13 #200 ;
14 end
15
16 always #5 in < in 1;
17endmodule
xxxxxxxxxx
11// method 1
2module nor_gate(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 assign out (in);
8endmodule
xxxxxxxxxx
1171// method 2
2module nor_gate2(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 reg temp;
8 integer i;
9 always @(in) begin
10 temp in[0];
11 for (i 1; i < n; i i 1) begin
12 temp temp in[i];
13 end
14 end
15
16 assign out temp;
17endmodule
xxxxxxxxxx
1101// method 3
2module nor_gate3(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 wire temp;
8 or_gate #n or_gate_temp(.in(in), .out(temp));
9 assign out temp;
10endmodule
x
1// testbench of nor_gate
2`timescale 1ns10ps
3module nor_gate_tb;
4 reg[2:0] in;
5 wire out1, out2, out3;
6
7 nor_gate #3 nor_gate_1(.in(in), .out(out1));
8 nor_gate2 #3 nor_gate_2(.in(in), .out(out2));
9 nor_gate3 #3 nor_gate_3(.in(in), .out(out3));
10
11 initial begin
12 in < 0;
13 #200 ;
14 end
15
16 always #5 in < in 1;
17endmodule
xxxxxxxxxx
11// method 1
2module xor_gate(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 assign out in;
8endmodule
xxxxxxxxxx
1171// method 2
2module xor_gate2(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 reg temp;
8 integer i;
9 always @(in) begin
10 temp in[0];
11 for (i 1; i < n; i i 1) begin
12 temp temp in[i];
13 end
14 end
15
16 assign out temp;
17endmodule
x
1// testbench of xor_gate
2`timescale 1ns10ps
3module xor_gate_tb;
4 reg[2:0] in;
5 wire out1, out2;
6
7 xor_gate #3 xor_gate_1(.in(in), .out(out1));
8 xor_gate2 #3 xor_gate_2(.in(in), .out(out2));
9
10 initial begin
11 in < 0;
12 #200 ;
13 end
14
15 always #5 in < in 1;
16endmodule
xxxxxxxxxx
11// method 1
2module xnor_gate(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 assign out (in);
8endmodule
xxxxxxxxxx
1171// method 2
2module xnor_gate2(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 reg temp;
8 integer i;
9 always @(in) begin
10 temp in[0];
11 for (i 1; i < n; i i 1) begin
12 temp temp in[i];
13 end
14 end
15
16 assign out temp;
17endmodule
xxxxxxxxxx
1101// method 3
2module xnor_gate3(in, out);
3 parameter n 2;
4 input[n1:0] in;
5 output out;
6
7 wire temp;
8 xor_gate #n xor_gate_temp(.in(in), .out(temp));
9 assign out temp;
10endmodule
x
1// testbench of xnor_gate
2`timescale 1ns10ps
3module xnor_gate_tb;
4 reg[2:0] in;
5 wire out1, out2, out3;
6
7 xnor_gate #3 xnor_gate_1(.in(in), .out(out1));
8 xnor_gate2 #3 xnor_gate_2(.in(in), .out(out2));
9 xnor_gate3 #3 xnor_gate_3(.in(in), .out(out3));
10
11 initial begin
12 in < 0;
13 #200 ;
14 end
15
16 always #5 in < in 1;
17endmodule
xxxxxxxxxx
1151// 1. 基本 RS 触发器
2module RSFF1(S, R, Q);
3 input S, R; // 低电平有效
4 output reg Q;
5
6 always @(S or R) begin
7 if (S) begin // S 有效
8 if (R) Q < 1'bx; // S 与 R 有效
9 else Q < 1; // 仅 S 有效
10 end
11 else if (R) begin
12 Q < 0; // 仅 R 有效
13 end // 均无效则不变
14 end
15endmodule
xxxxxxxxxx
1151// 2. 同步 RS 触发器
2module RSFF2(S, R, CP, Q);
3 input S, R, CP;
4 output reg Q;
5
6 always @(S or R or CP) if (CP) begin
7 case ({S, R})
8 2'b00: Q < 1'bx;
9 2'b01: Q < 1'b1;
10 2'b10: Q < 1'b0;
11 2'b11: ; // Q <= Q;
12 default Q < 1'bx;
13 endcase
14 end
15endmodule
xxxxxxxxxx
151// 3. 主从 RSFF
2module RSFF3(S, R, CP, Q);
3 input S, R, CP;
4 output reg Q;
5
6 reg Q1;
7 always @(CP) begin
8 if (CP) begin // 上升沿
9 Q1 < S (RQ1:0) : (R1:1'bx);
10 end
11 else begin // 下降沿
12 Q < Q1 1 : 0;
13 end
14 end
15endmodule
x
1// testbench of RSFF
2`timescale 1ns10ps
3module RSFF_tb;
4 reg S, R, CP;
5 wire Q1, Q2;
6
7 RSFF1 RSFF1(.S(S), .R(R), .Q(Q1));
8 RSFF2 RSFF2(.S(S), .R(R), .Q(Q2), .CP(CP));
9 RSFF3 RSFF3(.S(S), .R(R), .Q(Q3), .CP(CP));
10
11 integer i;
12 initial begin
13 S < 0; R < 1; CP < 1;
14 for (i 0; i < 64; i i 1) begin
15 #10 {S, R} 4;
16 end
17 ;
18 end
19
20 always #10 CP < CP;
21endmodule
xxxxxxxxxx
11// 1. 同步 DFF (时序逻辑电路)
2module DFF1(D, CP, Q);
3 input D, CP;
4 output reg Q;
5
6 always @(D or CP) if (CP) Q < D;
7endmodule
xxxxxxxxxx
11// 2. 边沿 DFF
2module DFF2(D, CP, Q);
3 input D, CP;
4 output reg Q;
5
6 always @(posedge CP) Q < D;
7endmodule
x
1// testbench of DFF
2`timescale 1ns10ps
3module DFF_tb;
4 reg D, CP;
5 wire Q1, Q2;
6
7 DFF1 DFF1(.D(D), .CP(CP), .Q(Q1));
8 DFF2 DFF2(.D(D), .CP(CP), .Q(Q2));
9
10 integer i;
11 initial begin
12 D < 0; CP < 0;
13 for (i 0; i < 16; i i 1) begin
14 #10 D < 2;
15 end
16 ;
17 end
18
19 always #10 CP < CP;
20endmodule
xxxxxxxxxx
1231// 1. 同步 JKFF & 异步置数 & 异步清零
2module JKFF1(J, K, CP, R, S, Q);
3 input J, K, R, S, CP; // 只有 CP 为高电平有效
4 output reg Q;
5
6 always @() begin
7 if (R) begin
8 if (S) Q < 1'bx;
9 else Q < 0;
10 end
11 else if (S) Q < 1;
12 else if (CP) begin
13 if (J) begin
14 if (K) Q < Q;
15 else Q < 1;
16 end
17 else begin
18 if (K) Q < 0;
19 else Q < Q;
20 end
21 end
22 end
23endmodule
xxxxxxxxxx
1151// 2. 主从 JKFF
2module JKFF2(J, K, CP, Q);
3 input J, K, CP; // 只有 CP 为高电平有效
4 output reg Q;
5
6 reg Q1;
7 always @(CP) begin
8 if (CP) begin // 上升沿
9 Q1 < J (K Q1 : 1) : (K 0 : Q1);
10 end
11 else begin // 下降沿
12 Q < Q1 1 : 0;
13 end
14 end
15endmodule
xxxxxxxxxx
1111// 3. 边沿 JKFF
2module JKFF3(J, K, CP, Q);
3 input J, K, CP;
4 output reg Q;
5
6 always @(posedge CP) begin
7 Q < (JK) J : (J Q : Q);
8 // 或 Q <= (J&K) ? (~Q) : ((J|K) ? J : Q);
9 // 或 Q <= J ? (K ? ~Q : 1) : (K ? 0 : Q);
10 end
11endmodule
x
1// testbench of JKFF
2`timescale 1ns10ps
3module JKFF_tb;
4 reg J, K, R, S, CP;
5 wire Q1, Q2, Q3;
6
7 JKFF1 JKFF1(.J(J), .K(K), .R(R), .S(S), .CP(CP), .Q(Q1));
8 JKFF2 JKFF2(.J(J), .K(K), .CP(CP), .Q(Q2));
9 JKFF3 JKFF3(.J(J), .K(K), .CP(CP), .Q(Q3));
10
11 integer i;
12 initial begin
13 J < 0; K < 0; R < 1; S < 1; CP < 0;
14 for (i 0; i < 64; i i 1) begin
15 #10 {J, K} < 4;
16 end
17 #10 ;
18 end
19
20 always #10 CP < CP;
21endmodule
xxxxxxxxxx
1101// 1. 同步 TFF
2module TFF1(T, CP, Q, res);
3 input T, CP, res; // res 为低电平有效同步清零端
4 output reg Q;
5
6 always @(posedge CP) begin
7 if (res) Q < 0;
8 else Q < T Q;
9 end
10endmodule
xxxxxxxxxx
1101// 2. 同步 T'FF
2module TFF2(CP, Q, res);
3 input CP, res; // res 为低电平有效同步清零端
4 output reg Q;
5
6 always @(posedge CP) begin
7 if (res) Q < 0;
8 else Q < Q;
9 end
10endmodule
x
1// testbench of TFF
2`timescale 1ns10ps
3module TFF_tb;
4 reg T, CP, res;
5 wire Q1, Q2;
6
7 TFF1 TFF1(.T(T), .CP(CP), .Q(Q1), .res(res));
8 TFF2 TFF2(.CP(CP), .Q(Q2), .res(res));
9
10 initial begin
11 T < 0; CP < 0; res < 0;
12 #20 res < 1;
13 #100 ;
14 end
15
16 always #5 CP < CP;
17 always #8 T < T;
18endmodule
xxxxxxxxxx
1491// 普通编码器 (8-3 线)
2/*
3- 注 1: 本文件中所有端口均为低电平有效;
4- 注 2: 如果使用 Quartus 仿真, 则需要建新的文件,
5 使模块名与文件名相同, 且顶层模块名与项目名相同.
6- 后记: 前两种方法都挺好的, 前者清晰, 后者简洁; 最主要的是一遍写完就能跑.
7 不喜欢第三种方法, 因为花了很久调试, 最后问了 new bing 才知道, 原来在
8 比较 wire 型和 integer 型变量时, 需要用 $signed() 函数进行强制类型转换.
9 从其它编程语言的角度来看, 第三种方法最好, 因为很容易可以扩展到更多线编码器,
10 但是对于 Verilog 则不然, 使用多个模块例化后级联, 应当是更为清晰的做法.
11*/
12
13// 方法 1: always 块 + case 语句
14module encoder1_1(sin, I, A, eout, sout);
15 input sin; // 控制端 (输入使能端)
16 input[7:0] I; // 编码输入, 某一时刻只能对应一个输入信号编码
17 output reg eout; // 扩展端, 当且仅当控制端有效且有信号输入时有效
18 output reg sout; // 选通输出端, 当且仅当控制端有效且无信号输入时有效
19 output reg[2:0] A; // 编码输出, 为二进制数据
20
21 always @(sin or I) if (sin) begin
22 // 控制端有效, 正常编码
23 if (I 8'b1111_1111) begin
24 eout < 1; sout < 0;
25 end // 工作时, 无输入则 sout 有效
26 else begin
27 eout < 0; sout < 1;
28 end // 工作时, 有输入则 eout 有效
29
30 case (I)
31 8'b1111_1111, // 无输入与 0 输出相同
32 8'b1111_1110: A < 3'b111; // 0
33 8'b1111_1101: A < 3'b110; // 1
34 8'b1111_1011: A < 3'b101; // 2
35 8'b1111_0111: A < 3'b100; // 3
36 8'b1110_1111: A < 3'b011; // 4
37 8'b1101_1111: A < 3'b010; // 5
38 8'b1011_1111: A < 3'b001; // 6
39 8'b0111_1111: A < 3'b000; // 7
40 default: A < 3'bx;
41 endcase // 普通编码器不考虑其它情况
42 end
43 else begin
44 // 控制端无效, 不进行编码
45 A < 3'b111;
46 eout < 1;
47 sout < 1;
48 end
49endmodule
xxxxxxxxxx
1171// 方法 2: 逻辑表达式 + assign 语句
2module encoder1_2(sin, I, A, eout, sout);
3 input sin; // 控制端
4 input[7:0] I; // 输入端
5 output eout; // 扩展端
6 output sout; // 选通端
7 output[2:0] A; // 输出端
8
9 // 不能写成 sin | {}, 因为位数不统一
10 assign A sin 3'b111 : {
11 I[4] I[5] I[6] I[7], // 第三位
12 I[2] I[3] I[6] I[7], // 第二位
13 I[1] I[3] I[5] I[7] // 第一位
14 };
15 assign eout sin I;
16 assign sout sin I;
17endmodule
xxxxxxxxxx
1381// 方法 3: always 块 + for 循环
2module encoder1_3(sin, I, A, eout, sout);
3 input sin; // 控制端
4 input[7:0] I; // 输入端
5 output reg eout; // 扩展端
6 output reg sout; // 选通端
7 output reg[2:0] A; // 输出端
8
9 integer i;
10 always @(sin or I) if (sin) begin
11 // 控制端有效, 正常编码
12 // 初始默认无输入
13 if (I) begin
14 A < 3'b111;
15 eout < 1;
16 sout < 0;
17 end
18 else begin
19 A < 3'bx;
20 eout < 0;
21 sout < 1;
22 end
23
24 for (i 0; i < 8; i i 1) begin
25 if ((I) (1<<i)) begin
26 A < 7 i;
27 eout < 0;
28 sout < 1;
29 end
30 end
31 end
32 else begin
33 // 控制端无效, 不进行编码
34 A < 3'b111;
35 eout < 1;
36 sout < 1;
37 end
38endmodule
x
1// testbench of encoder1 (common 8-3 encoder)
2`timescale 1ns10ps
3module encoder1_tb;
4 reg sin;
5 reg[7:0] I;
6 wire eout1, eout2, eout3;
7 wire sout1, sout2, sout3;
8 wire[2:0] A1, A2, A3;
9
10 encoder1_1 encoder1_1(
11 .sin(sin), .I(I), .A(A1),
12 .eout(eout1), .sout(sout1)
13 );
14 encoder1_2 encoder1_2(
15 .sin(sin), .I(I), .A(A2),
16 .eout(eout2), .sout(sout2)
17 );
18 encoder1_3 encoder1_3(
19 .sin(sin), .I(I), .A(A3),
20 .eout(eout3), .sout(sout3)
21 );
22
23 initial begin
24 sin < 0; I < 8'b0;
25 #2560 sin < 1;
26 #100 ;
27 end
28
29 always #10 I < I 1;
30endmodule
xxxxxxxxxx
1321// 优先编码器 (8-3 线), 即 74148
2// 注 1: 本文件中所有端口均为低电平有效;
3// 注 2: 本文件中优先编码器均为高位优先;
4
5// 方法 1: always 块 + if 语句
6module encoder2_1(sin, I, A, eout, sout);
7 input sin; // 控制端 (输入使能端)
8 input[7:0] I; // 编码输入, 某一时刻只能对应一个输入信号编码
9 output reg eout; // 扩展端, 当且仅当控制端有效且有信号输入时有效
10 output reg sout; // 选通输出端, 当且仅当控制端有效且无信号输入时有效
11 output reg[2:0] A; // 编码输出, 为二进制数据
12
13 reg[4:0] outvec; // 为方便起见
14 assign {eout, sout, A} outvec;
15
16 always @(sin or I) if (sin) begin
17 // 控制端有效, 正常编码
18 if (I[7]) outvec < 5'b01_000;
19 else if (I[6]) outvec < 5'b01_001;
20 else if (I[5]) outvec < 5'b01_010;
21 else if (I[4]) outvec < 5'b01_011;
22 else if (I[3]) outvec < 5'b01_100;
23 else if (I[2]) outvec < 5'b01_101;
24 else if (I[1]) outvec < 5'b01_110;
25 else if (I[0]) outvec < 5'b01_111;
26 else outvec < 5'b10_111;
27 end
28 else begin
29 // 控制端无效, 不进行编码
30 outvec < 5'b11111;
31 end
32endmodule
xxxxxxxxxx
1261// 方法 2: always 块 + for 循环
2module encoder2_2(sin, I, A, eout, sout);
3 input sin; // 控制端
4 input[7:0] I; // 输入端
5 output reg eout; // 扩展端
6 output reg sout; // 选通端
7 output reg[2:0] A; // 输出端
8
9 integer i;
10 always @(sin or I) if (sin) begin
11 // 控制端有效, 正常编码
12 // 默认无输入, 先赋初值
13 {eout, sout} < 2'b10;
14 for (i 0; i < 8; i i 1) begin
15 if (I[i]) begin
16 A < 7 i;
17 {eout, sout} < 2'b01;
18 end
19 end
20 end
21 else begin
22 // 控制端无效, 不进行编码
23 A < 3'b111;
24 {eout, sout} < 2'b11;
25 end
26endmodule
xxxxxxxxxx
1201// 方法 3: assign 语句 + 条件判断
2module encoder2_3(sin, I, A, eout, sout);
3 input sin; // 控制端
4 input[7:0] I; // 输入端
5 output eout; // 扩展端
6 output sout; // 选通端
7 output[2:0] A; // 输出端
8
9 wire[4:0] outvec; // 为了方便起见
10 assign outvec I[7] 5'b01_000 :
11 I[6] 5'b01_001 :
12 I[5] 5'b01_010 :
13 I[4] 5'b01_011 :
14 I[3] 5'b01_100 :
15 I[2] 5'b01_101 :
16 I[1] 5'b01_110 :
17 I[0] 5'b01_111 :
18 5'b10_111;
19 assign {eout, sout, A} sin 5'b11_111 : outvec;
20endmodule
xxxxxxxxxx
1251// 方法 4: assign 语句 + 逻辑表达式
2module encoder2_4(sin, I, A, eout, sout);
3 input sin; // 控制端
4 input[7:0] I; // 输入端
5 output eout; // 扩展端
6 output sout; // 选通端
7 output[2:0] A; // 输出端
8
9 // // 或者写为 A = sin ? 3'b111 : {}
10 assign A {sin, sin, sin} {
11 I[7] I[6] I[5] I[4], // 第三位
12 I[7] I[6] (
13 I[5] I[4] I[3]
14 ) (
15 I[5] I[4] I[2]
16 ), // 第二位
17 I[7] (I[6] I[5]) (
18 I[6] I[4] I[3]
19 ) (
20 I[6] I[4] I[2] I[1]
21 ) // 第一位
22 }; // 更多线的编码器可用类似的方式写出表达式
23 assign eout sin I;
24 assign sout sin I;
25endmodule
x
1// testbench of encoder2 (priority 8-3 encoder)
2`timescale 1ns10ps
3module encoder2_tb;
4 reg sin;
5 reg[7:0] I;
6 wire eout1, eout2, eout3, eout4;
7 wire sout1, sout2, sout3, sout4;
8 wire[2:0] A1, A2, A3, A4;
9
10 encoder2_1 encoder2_1(
11 .sin(sin), .I(I), .A(A1),
12 .eout(eout1), .sout(sout1)
13 );
14 encoder2_2 encoder2_2(
15 .sin(sin), .I(I), .A(A2),
16 .eout(eout2), .sout(sout2)
17 );
18 encoder2_3 encoder2_3(
19 .sin(sin), .I(I), .A(A3),
20 .eout(eout3), .sout(sout3)
21 );
22 encoder2_4 encoder2_4(
23 .sin(sin), .I(I), .A(A4),
24 .eout(eout4), .sout(sout4)
25 );
26
27 initial begin
28 sin < 0; I < 8'b0;
29 #2560 sin < 1;
30 #100 ;
31 end
32
33 always #10 I < I 1;
34endmodule
xxxxxxxxxx
11// 二进制 8-3 线译码器 74138
2// 方法 1: assign 语句 + 移位法
3module decoder1_1(A, S, F);
4 input[2:0] A, S; // A 为高电平输入端, S 为使能端, 3'b100 有效
5 output[7:0] F; // F 为低电平输出端
6
7 assign F (S 3'b100) (1'b1 << A) : (8'b0);
8endmodule
xxxxxxxxxx
1131// 方法 2: always 块 + 置数法
2module decoder1_2(A, S, F);
3 input[2:0] A, S; // A 为低电平输入端, S 为使能端, 3'b100 有效
4 output reg[7:0] F; // F 为低电平输出端
5
6 always @(A or S) if (S 3'b100) begin
7 F (8'b0);
8 F[A] 0;
9 end
10 else begin
11 F < (8'b0);
12 end
13endmodule
xxxxxxxxxx
1221// 方法 3: assign 语句 + case 语句
2module decoder1_3(A, S, F);
3 input[2:0] A, S; // A 为低电平输入端, S 为使能端, 3'b100 有效
4 output reg[7:0] F; // F 为低电平输出端
5
6 always @(A or S) if (S 3'b100) begin
7 case (A)
8 3'b000: F < 8'b1111_1110;
9 3'b001: F < 8'b1111_1101;
10 3'b010: F < 8'b1111_1011;
11 3'b011: F < 8'b1111_0111;
12 3'b100: F < 8'b1110_1111;
13 3'b101: F < 8'b1101_1111;
14 3'b110: F < 8'b1011_1111;
15 3'b111: F < 8'b0111_1111;
16 default: F < 8'bx;
17 endcase
18 end
19 else begin
20 F < (8'b0);
21 end
22endmodule
x
1// testbench of decoder1
2`timescale 1ns10ps
3module decoder1_tb;
4 reg[2:0] A, S;
5 wire[7:0] F1, F2, F3;
6
7 decoder1_1 decoder1_1(.A(A), .S(S), .F(F1));
8 decoder1_2 decoder1_2(.A(A), .S(S), .F(F2));
9 decoder1_3 decoder1_3(.A(A), .S(S), .F(F3));
10
11 initial begin
12 A < 3'b0; S < 3'b100; // 有效
13 #100 S < 3'b000; // 无效
14 #100 ;
15 end
16
17 always #10 A < A 1;
18endmodule
xxxxxxxxxx
1211// 七段码译码器;
2module seg_dec(num, a_g);
3 input[3:0] num; // 待译码、显示的数字
4 output reg[6:0] a_g; // a_g --> {a, b, c, d, e, f, g}
5
6 always @(num) begin
7 case(num)
8 4'd0: a_g < 7'b111_1110;
9 4'd1: a_g < 7'b011_0000;
10 4'd2: a_g < 7'b110_1101;
11 4'd3: a_g < 7'b111_1001;
12 4'd4: a_g < 7'b011_0011;
13 4'd5: a_g < 7'b101_1011;
14 4'd6: a_g < 7'b101_1111;
15 4'd7: a_g < 7'b111_0000;
16 4'd8: a_g < 7'b111_1111;
17 4'd9: a_g < 7'b111_1001;
18 default: a_g < 7'b1;
19 endcase
20 end
21endmodule
x
1// testbench of seg_dec
2`timescale 1ns10ps
3module seg_dec_tb;
4 reg[3:0] num;
5 wire[6:0] a_g;
6
7 seg_dec seg_dec(.num(num), .a_g(a_g));
8
9 initial begin
10 num < 0;
11 #200 ;
12 end
13
14 always #10 num < num 1;
15endmodule
xxxxxxxxxx
11// 数据分配器
2module demux(I, A, S, F);
3 input I, S; // I 为输入端, S 为低电平控制端
4 input[2:0] A; // A 为高电平控制端
5 input[7:0] F; // F 为高电平输出端
6
7 assign F S (8'b0 (I << A));
8endmodule
x
1// testbench of demux
2`timescale 1ns10ps
3module demux_tb;
4 reg I, S;
5 reg[2:0] A;
6 wire[7:0] F;
7
8 demux demux(.I(I), .A(A), .S(S), .F(F));
9
10 initial begin
11 I < 0; S < 0; A < 3'b0;
12 #200 ;
13 end
14
15 always #10 A < A 1;
16 always #80 I < I;
17 always #160 S < S;
18endmodule
xxxxxxxxxx
1101// 双四选一 74153
2module mux74153(E, Ia, Ib, A, F1, F2);
3 input E; // 低电平使能端
4 input[1:0] A; // 高电平控制端
5 input[3:0] Ia, Ib; // 输入端
6 output F1, F2; // 输出端
7
8 assign F1 E Ia[A];
9 assign F2 E Ib[A];
10endmodule
x
1// testbench of mux74153
2`timescale 1ns10ps
3module mux74153_tb;
4 reg E;
5 reg[1:0] A;
6 reg[3:0] Ia, Ib;
7 wire F1, F2;
8
9 mux74153 mux74153(
10 .E(E), .Ia(Ia), .Ib(Ib),
11 .A(A), .F1(F1), .F2(F2)
12 );
13
14 initial begin
15 E < 0; A < 2'b0;
16 Ia < 4'b0001; Ib < 4'b0001;
17 #200 ;
18 end
19
20 always #10 A < A 1;
21 always #40 begin
22 Ia < Ia << 1;
23 Ib < Ib << 1;
24 end
25 always #160 E < E;
26endmodule
xxxxxxxxxx
11// 八选一 74151
2module mux74151(E, I, A, L);
3 input E; // 低电平使能端
4 input[2:0] A; // 高电平控制端
5 input[7:0] I; // 输入端
6 output L; // 输出端
7
8 assign L E I[A];
9endmodule
x
1// testbench of mux74151
2`timescale 1ns10ps
3module mux74151_tb;
4 reg E;
5 reg[2:0] A;
6 reg[7:0] I;
7 wire L;
8
9 mux74151 mux74151(.E(E), .I(I), .A(A), .L(L));
10
11 initial begin
12 E < 0; A < 3'b0;
13 I < 8'b0000_0001;
14 #700 ;
15 end
16
17 always #10 A < A 1;
18 always #80 I < I << 1;
19 always #640 E < E;
20endmodule
xxxxxxxxxx
1111// 4 位数值比较器 7485
2module comparactor(A, B, Ig, Ie, Il, Fg, Fe, Fl);
3 parameter n 4; // 位数
4 input[n1:0] A, B; // 输入
5 input Ig, Ie, Il; // 级间输入, greater, equal, less
6 output Fg, Fe, Fl; // 级间输出, greater, equal, less
7
8 assign Fg (A > B) (A B Ig);
9 assign Fe (A B) Ie;
10 assign Fl (A < B) (A B Il);
11endmodule
x
1// testbench of comparactor
2`timescale 1ns10ps
3module comparactor_tb;
4 parameter n 4;
5 reg[n1:0] A, B;
6 reg Ig, Ie, Il;
7 wire Fg, Fe, Fl;
8
9 comparactor #n comparactor(
10 .A(A), .B(B),
11 .Ig(Ig), .Ie(Ie), .Il(Il),
12 .Fg(Fg), .Fe(Fe), .Fl(Fl)
13 );
14
15 initial begin
16 A < 4'b0; B < 4'b0;
17 {Ig, Ie, Il} < 3'b000;
18 #10 {Ig, Ie, Il} < 3'b001;
19 #10 {Ig, Ie, Il} < 3'b010;
20 #10 {Ig, Ie, Il} < 3'b100;
21 #10 A < 4'b0101;
22 #10 B < 4'b1010;
23 #10 ;
24 end
25endmodule
xxxxxxxxxx
11// 方法 1
2module HA1(A, B, S, C);
3 input A, B;
4 output S, C;
5
6 assign S A B;
7 assign C A B;
8endmodule
xxxxxxxxxx
11// 方法 2
2module HA2(A, B, S, C);
3 input A, B;
4 output S, C;
5
6 assign {C, S} A B;
7endmodule
x
1// testbench of HA
2`timescale 1ns10ps
3module HA_tb;
4 reg A, B;
5 wire S1, S2;
6 wire C1, C2;
7
8 HA1 HA1(.A(A), .B(B), .S(S1), .C(C1));
9 HA2 HA2(.A(A), .B(B), .S(S2), .C(C2));
10
11 initial begin
12 A < 0; B < 0;
13 #50 ;
14 end
15
16 always #10 {A, B} < {A, B} 1;
17endmodule
xxxxxxxxxx
11// 方法 1
2module FA1(A, B, Cin, S, Cout);
3 input A, B, Cin;
4 output S, Cout;
5
6 assign S A B Cin;
7 assign Cout (A B) Cin A B;
8endmodule
xxxxxxxxxx
11// 方法 2
2module FA2(A, B, Cin, S, Cout);
3 input A, B, Cin;
4 output S, Cout;
5
6 assign {Cout, S} A B Cin;
7endmodule
x
1// testbench of FA
2`timescale 1ns10ps
3module FA_tb;
4 reg A, B, Cin;
5 wire S1, S2;
6 wire Cout1, Cout2;
7
8 FA1 FA1(.A(A), .B(B), .Cin(Cin), .S(S1), .Cout(Cout1));
9 FA2 FA2(.A(A), .B(B), .Cin(Cin), .S(S2), .Cout(Cout2));
10
11 initial begin
12 A < 0; B < 0; Cin < 0;
13 #100 ;
14 end
15
16 always #10 {A, B, Cin} < {A, B, Cin} 1;
17endmodule
xxxxxxxxxx
11// 方法 1
2module HS1(A, B, S, C);
3 input A, B;
4 output S, C;
5
6 assign S A B;
7 assign C A B;
8endmodule
xxxxxxxxxx
11// 方法 2
2module HS2(A, B, S, C);
3 input A, B;
4 output S, C;
5
6 assign {C, S} 2'b10 (2'b10 A B);
7endmodule
x
1// testbench of HS
2`timescale 1ns10ps
3module HS_tb;
4 reg A, B;
5 wire S1, S2;
6 wire C1, C2;
7
8 HS1 HS1(.A(A), .B(B), .S(S1), .C(C1));
9 HS2 HS2(.A(A), .B(B), .S(S2), .C(C2));
10
11 initial begin
12 A < 0; B < 0;
13 #50 ;
14 end
15
16 always #10 {A, B} < {A, B} 1;
17endmodule
xxxxxxxxxx
11// 方法 1
2module FS1(A, B, C, S, Cout);
3 input A, B, C;
4 output S, Cout;
5
6 assign S A B C;
7 // 没必要列真值表, 除非是考试
8 assign Cout (A B) (A C) (B C);
9endmodule
xxxxxxxxxx
11// 方法 2
2module FS2(A, B, C, S, Cout);
3 input A, B, C;
4 output S, Cout;
5
6 assign S A B C;
7 assign Cout (A (B C)) (B C);
8 // 只需写一个括号: assign Cout = ~A & (B | C) | B & C;
9endmodule
xxxxxxxxxx
11// 方法 3
2module FS3(A, B, C, S, Cout);
3 input A, B, C;
4 output S, Cout;
5
6 assign {Cout, S} 2'b10 (2 A B C);
7endmodule
x
1// testbench of FS
2`timescale 1ns10ps
3module FS_tb;
4 reg A, B, C;
5 wire S1, Cout1;
6 wire S2, Cout2;
7 wire S3, Cout3;
8
9 FS1 FS1(.A(A), .B(B), .C(C), .S(S1), .Cout(Cout1));
10 FS2 FS2(.A(A), .B(B), .C(C), .S(S2), .Cout(Cout2));
11 FS3 FS3(.A(A), .B(B), .C(C), .S(S3), .Cout(Cout3));
12
13 initial begin
14 A < 0; B < 0; C < 0;
15 #100 ;
16 end
17
18 always #10 {A, B, C} < {A, B, C} 1;
19endmodule
x
1// n 位奇偶校验器
2module parity_check(I, F);
3 parameter n 8; // 二进制位数
4 input[n1:0] I; // 待检测的 n 位二进制数
5 output reg F; // 输出二进制数的异或和
6
7 integer i;
8 always @() begin
9 F I[0];
10 for (i 1; i < n; i i 1) begin
11 F F I[i];
12 end
13 end
14endmodule
x
1// testbench of parity_check
2`timescale 1ns10ps
3module parity_check_tb;
4 parameter n 8;
5 reg[n1:0] I;
6 wire F;
7 parity_check parity_check(.I(I), .F(F));
8
9 generate genvar i;
10 for (i 0; i < n; i i 1) begin
11 always #(10i10) I[i] < I[i];
12 end // 用生成块遍历所有可能的情况
13 endgenerate
14
15 initial begin
16 I < 0; // 即 n'b0
17 #(2n2) ; // 2 的 n 次方
18 end // 两个周期后停止测试
19endmodule
xxxxxxxxxx
1121// n 位数码寄存器 (类似 74175, 但多了 rst)
2module register1(clk, rst, D, Q);
3 parameter n 4;
4 input clk, rst; // 时钟脉冲, 异步清零
5 input[n1:0] D; // 输入端
6 output reg[n1:0] Q; // 状态, 也是输出端
7
8 always @(posedge clk or negedge rst) begin
9 if (rst) Q < 0;
10 else Q < D;
11 end
12endmodule
xxxxxxxxxx
1191// testbench of register1
2`timescale 1ns10ps
3module register1_tb;
4 parameter n 4;
5 reg clk, rst;
6 reg[n1:0] D;
7 wire[n1:0] Q;
8
9 register1 register1(.clk(clk), .rst(rst), .D(D), .Q(Q));
10
11 initial begin
12 clk < 0; rst < 1; D < 0;
13 #150 rst < 0;
14 #20 ;
15 end
16
17 always #5 clk < clk;
18 always #6 D < D 1;
19endmodule
xxxxxxxxxx
1141// n 位锁存器 (74373)
2module register2(CP, E, D, Q);
3 parameter n 8;
4 input CP; // 锁存信号
5 input E; // 使能端口, 为 0 时有信号输出, 为 1 时输出高阻态
6 input[n1:0] D; // 输入信号
7 output reg[n1:0] Q; // 输出信号
8
9 always @(CP or E or D) begin
10 if (E) Q < 'bz; // E = 1, 输出高阻态
11 else if (CP) Q < D; // CP = 0, 输入输出一致
12 // CP = 1, 输出不会改变
13 end
14endmodule
xxxxxxxxxx
1191// testbench of register2
2`timescale 1ns10ps
3module register2_tb;
4 parameter n 8;
5 reg CP, E;
6 reg[n1:0] D;
7 wire[n1:0] Q;
8
9 register2 register2(.CP(CP), .E(E), .D(D), .Q(Q));
10
11 initial begin
12 CP < 0; E < 0; D < 0;
13 #500 ;
14 end
15
16 always #5 D < D 1;
17 always #20 CP < CP;
18 always #100 E < E;
19endmodule
xxxxxxxxxx
1191// n 位移位寄存器 (74194)
2module register3(clk, rst, S, D, Q);
3 parameter n 4;
4 input clk, rst; // 时钟脉冲, 异步清零
5 input[1:0] S; // {0, 0} 保持, {0, 1} 右移, {1, 0} 左移, {1, 1} 送数
6 input[n1:0] D; // 置入数据
7 output reg[n1:0] Q; // 输出数据
8
9 always @(posedge clk or negedge rst) begin
10 if (rst) Q < 0;
11 else case (S)
12 2'b00: Q < Q; // 不变
13 2'b01: Q < Q >> 1; // 右移
14 2'b10: Q < Q << 1; // 左移
15 2'b11: Q < D; // 置数
16 default: Q < 'bx; // 不定值
17 endcase
18 end
19endmodule
xxxxxxxxxx
1301// testbench of register3
2`timescale 1ns10ps
3module register3_tb;
4 parameter n 4;
5 reg clk, rst;
6 reg[1:0] S;
7 reg[n1:0] D;
8 wire[n1:0] Q;
9
10 register3 register3(
11 .clk(clk), .rst(rst),
12 .S(S), .D(D), .Q(Q)
13 );
14
15 initial begin
16 clk < 0; rst < 0;
17 D < 0; S < 2'b00;
18 #10 rst < 1; // 保持
19 #10 S < 2'b11; // 计数
20 #50 S < 2'b01; // 右移
21 #50 S < 2'b11; // 计数
22 #50 S < 2'b10; // 左移
23 #50 S < 2'b11; // 计数
24 #50 rst < 0; // 清零
25 #20 ;
26 end
27
28 always #5 clk < clk;
29 always #15 D < D 1;
30endmodule
xxxxxxxxxx
1251// 2n 分频器
2module freqDivider(in, out, rst);
3 parameter n 2; // 默认为 4 分频
4 input in, rst; // 异步复位
5 output reg out;
6 parameter m (2n); // 位数
7 reg[m1:0] cnt;
8
9 always @(posedge in or negedge rst) begin
10 if (rst) begin
11 out < 0;
12 cnt < 0;
13 end
14 else if (cnt n 1) begin
15 out < 1;
16 cnt < cnt 1;
17 end
18 else if (cnt 2n 1) begin
19 out < 0;
20 cnt < 0;
21 end
22 else cnt < cnt 1;
23 end
24endmodule
xxxxxxxxxx
1191// testbench of freqDivider
2`timescale 1ns10ps
3module freqDivider_tb;
4 reg in, rst;
5 wire out1, out2;
6
7 freqDivider #2 freqDivider1(.in(in), .out(ou1), .rst(rst));
8 freqDivider #4 freqDivider1(.in(in), .out(ou2), .rst(rst));
9
10 initial begin
11 in < 0; rst < 1;
12 #1 rst < 0;
13 #1 rst < 1;
14 #200 rst < 0;
15 #20 ;
16 end
17
18 always #5 in < in;
19endmodule
xxxxxxxxxx
1191// n 位二进制计数器
2module counter(clk, rst, cin, cout, Q, D, load);
3 parameter n 4;
4 input clk, rst; // 时钟脉冲, 异步清零
5 input cin, load; // 进位输入, 同步置数
6 input[n1:0] D; // 置入数据
7 output cout; // 进位输出
8 output reg[n1:0] Q; // 输出输出
9
10 always @(posedge clk or negedge rst) begin
11 if (rst) Q < 0;
12 else if (cin) begin
13 if (load) Q < D;
14 else Q < Q 1;
15 end
16 end
17
18 assign cout (Q (1 << n) 1);
19endmodule
xxxxxxxxxx
1291// testbench of counter
2`timescale 1ns10ps
3module counter_tb;
4 parameter n 4;
5 reg clk, rst;
6 reg cin, load;
7 reg[n1:0] D;
8 wire cout;
9 wire[n1:0] Q;
10
11 counter #n counter(
12 .clk(clk), .rst(rst),
13 .cin(cin), .load(load),
14 .D(D), .cout(cout), .Q(Q)
15 );
16
17 initial begin
18 clk < 0; rst < 1;
19 cin < 1; load < 1;
20 D < 4'b0101;
21 #1 rst < 0;
22 #1 rst < 1;
23 #100 load < 0;
24 #8 load < 1;
25 #200 ;
26 end
27
28 always #5 clk < clk;
29endmodule
xxxxxxxxxx
1211// 可逆计数器
2module reversibleCounter(clk, add, rst, D, Q, load, cin, cout);
3 parameter n 4;
4 input clk, rst; // 时钟脉冲, 加法复位
5 input add; // 为 1 则加法, 为 0 则减法
6 input cin, load; // 进位输入, 同步置数
7 input[n1:0] D; // 置入数据
8 output reg[n1:0] Q; // 输出数据
9 output cout; // 进位输出
10
11 always @(posedge clk or negedge rst) begin
12 if (rst) Q < 0;
13 else if (cin) begin
14 if (load) Q < D;
15 else if (add) Q < Q 1;
16 else Q < Q 1;
17 end
18 end
19
20 assign cout (add (Q (1 << n) 1)) (add Q 0);
21endmodule
xxxxxxxxxx
1311// testbench of reversibleCounter
2`timescale 1ns10ps
3module reversibleCounter_tb;
4 parameter n 4;
5 reg clk, rst;
6 reg add;
7 reg cin, load;
8 reg[n1:0] D;
9 wire cout;
10 wire[n1:0] Q;
11
12 reversibleCounter #n reversibleCounter(
13 .clk(clk), .rst(rst), .add(add),
14 .cin(cin), .load(load), .D(D),
15 .cout(cout), .Q(Q)
16 );
17
18 initial begin
19 clk < 0; rst < 1;
20 cin < 1; load < 1;
21 add < 1; D < 4'b0101;
22 #1 rst < 0;
23 #1 rst < 1;
24 #100 load < 0;
25 #8 load < 1;
26 #200 add < 0;
27 #200 ;
28 end
29
30 always #5 clk < clk;
31endmodule
xxxxxxxxxx
1331// 24 进制计数器
2module counter24(clk, rst, d0, d1, load, cin, cout, y0, y1);
3 input clk; // 时钟信号, 上升沿触发
4 input rst; // 异步清零, 低电平有效
5 input[3:0] d0, d1; // 置入数据, 分别为四位
6 input load; // 同步置数, 低电平有效
7 input cin; // 使能端口, 高电平有效
8 output cout; // 进位信号, 五十九为一
9 output reg[3:0] y0, y1; // 前者个位, 后者为十位
10 // 这里数字的个位与十位都采用四位二进制, 是为了方便之后译码
11 // 之后将 1'd9 即 4'b1001 简写为 9, 诸如此类, 以提高易读性
12
13 // 进位端口
14 assign cout cin (y0 3) (y1 2);
15
16 always @(posedge clk or negedge load or negedge rst) begin
17 if (load) begin // 异步置数
18 y0 < d0; y1 < d1;
19 end
20 else if (rst) begin // 异步清零
21 y0 < 0; y1 < 0;
22 end
23 else if (cin) begin // 时钟脉冲
24 if (y1 2 y0 3) begin
25 y0 < 0; y1 < 0; // 23 后为 00
26 end
27 else if (y0 9) begin // 十位进一
28 y0 < 0; y1 < y1 1;
29 end
30 else y0 < y0 1; // 个位进一
31 end
32 end
33endmodule
xxxxxxxxxx
1231`timescale 1ns10ps
2module counter24_tb;
3 reg clk, rst, load, cin;
4 reg[3:0] d0, d1;
5 wire[3:0] y0, y1;
6 wire cout;
7
8 counter24 counter24(
9 .clk(clk), .rst(rst), .cin(cin),
10 .d0(d0), .d1(d1), .load(load),
11 .y0(y0), .y1(y1), .cout(cout)
12 );
13
14 initial begin
15 clk < 0; rst < 1; cin < 1;
16 d0 < 0; d1 < 0; load < 1;
17 #10 rst < 0; // 先清零, 否则 y0 与 y1 为不定值
18 #10 rst < 1; // 复位端的恢复
19 #1000 ;
20 end
21
22 always #5 clk < clk; // 周期为 10
23endmodule
xxxxxxxxxx
1321// 60 进制计数器
2module counter60(clk, rst, d0, d1, load, cin, cout, y0, y1);
3 input clk; // 时钟信号, 上升沿触发
4 input rst; // 异步清零, 低电平有效
5 input[3:0] d0, d1; // 置入数据, 分别为四位
6 input load; // 同步置数, 低电平有效
7 input cin; // 使能端口, 高电平有效
8 output cout; // 进位信号, 五十九为一
9 output reg[3:0] y0, y1; // 前者个位, 后者为十位
10 // 这里数字的个位与十位都采用四位二进制, 是为了方便之后译码
11 // 之后将 1'd9 即 4'b1001 简写为 9, 诸如此类, 以提高易读性
12
13 // 进位端口
14 assign cout cin (y0 9) (y1 5);
15
16 always @(posedge clk or negedge load or negedge rst) begin
17 if (load) begin // 异步置数
18 y0 < d0; y1 < d1;
19 end
20 else if (rst) begin // 异步清零
21 y0 < 0; y1 < 0; // 不能写成 y0 <= y1 <= 0;
22 end
23 else if (cin) begin // 时钟脉冲
24 if (y0 9) begin
25 y0 < 0; // 进位为 0
26 if (y1 5) y1 < 0; // 59 后为 00
27 else y1 < y1 1; // 十位进一
28 end
29 else y0 < y0 1; // 个位进一
30 end
31 end
32endmodule
xxxxxxxxxx
1231`timescale 1ns10ps
2module counter60_tb;
3 reg clk, rst, load, cin;
4 reg[3:0] d0, d1;
5 wire[3:0] y0, y1;
6 wire cout;
7
8 counter60 counter60(
9 .clk(clk), .rst(rst), .cin(cin),
10 .d0(d0), .d1(d1), .load(load),
11 .y0(y0), .y1(y1), .cout(cout)
12 );
13
14 initial begin
15 clk < 0; rst < 1; cin < 1;
16 d0 < 0; d1 < 0; load < 1;
17 #10 rst < 0; // 先清零, 否则 y0 与 y1 为不定值
18 #10 rst < 1; // 复位端的恢复
19 #1000 ;
20 end
21
22 always #5 clk < clk; // 周期为 10
23endmodule