本练习的目的是使用计数器。
Part I 用T触发器实现16-bit的计数器
参照图 1所示的4-bit的同步计数器,实现一个16-bit 的计数器。
代码16-bit counter
1
//
top-level file
2
module
part1(KEY0,SW,HEX3,HEX2,HEX1,HEX0);
3
input
KEY0;
//
时钟脉冲
4
input
[
1
:
0
]SW;
//
使能&复位
5
output
[
6
:
0
]HEX3,HEX2,HEX1,HEX0;
//
输出显示
6
wire
[
15
:
0
]q;
//
16-bit计数输出
7
8
counter_16(SW[
1
],KEY0,SW[
0
],q);
9
10
seg7_lut H0(q[
3
:
0
],HEX0);
11
seg7_lut H1(q[
7
:
4
],HEX1);
12
seg7_lut H2(q[
11
:
8
],HEX2);
13
seg7_lut H3(q[
15
:
12
],HEX3);
14
15
endmodule
1
//
由T触发器构建的16-bit计数器
2
module
counter_16(en,clk,clr,Q);
3
input
en,clk,clr;
4
wire
[
15
:
0
]q;
5
output
[
15
:
0
]Q;
6
t_ff u0(en,clk,clr,q[
0
]);
7
t_ff u1(en
&
q[
0
],clk,clr,q[
1
]);
8
t_ff u2(en
&
q[
0
]
&
q[
1
],clk,clr,q[
2
]);
9
t_ff u3(en
&
q[
0
]
&
q[
1
]
&
q[
2
],clk,clr,q[
3
]);
10
t_ff u4(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
],clk,clr,q[
4
]);
11
t_ff u5(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
],clk,clr,q[
5
]);
12
t_ff u6(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
],clk,clr,q[
6
]);
13
t_ff u7(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
],clk,clr,q[
7
]);
14
t_ff u8(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
],clk,clr,q[
8
]);
15
t_ff u9(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
],
16
clk,clr,q[
9
]);
17
t_ff u10(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
]
&
q[
9
],
18
clk,clr,q[
10
]);
19
t_ff u11(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
]
&
q[
9
]
&
q[
10
],
20
clk,clr,q[
11
]);
21
t_ff u12(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
]
&
q[
9
]
&
q[
10
]
&
q[
11
],
22
clk,clr,q[
12
]);
23
t_ff u13(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
]
&
q[
9
]
&
q[
10
]
&
q[
11
]
&
q[
12
],
24
clk,clr,q[
13
]);
25
t_ff u14(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
]
&
q[
9
]
&
q[
10
]
&
q[
11
]
&
q[
12
]
&
q[
13
],
26
clk,clr,q[
14
]);
27
t_ff u15(en
&
q[
0
]
&
q[
1
]
&
q[
2
]
&
q[
3
]
&
q[
4
]
&
q[
5
]
&
q[
6
]
&
q[
7
]
&
q[
8
]
&
q[
9
]
&
q[
10
]
&
q[
11
]
&
q[
12
]
&
q[
13
]
&
q[
14
],
28
clk,clr,q[
15
]);
29
30
assign
Q
=
q;
31
32
endmodule
1
//
T flip flop
2
module
t_ff(t,clk,rst_n,q);
3
input
t,clk,rst_n;
4
output
reg
q;
5
6
always
@(
posedge
clk)
7
begin
8
if
(
!
rst_n)
9
q
<=
0
;
10
else
11
begin
12
if
(t
==
1
'
b1)
13
q
<=~
q;
14
else
15
q
<=
q;
16
end
17
end
18
19
endmodule
图2 Fmax值
图3 占用的LE数量
Part II 用赋值语句实现16-bit计数器
代码
1
//
counter-16bit
2
module
part2(clk,rst_n,q);
3
input
clk,rst_n;
4
output
reg
[
15
:
0
]q;
5
6
always
@(
posedge
clk)
7
begin
8
if
(
!
rst_n)
9
q
<=
1
'
b0;
10
else
11
begin
12
if
(q
==
65535
)
13
q
<=
0
;
14
else
15
q
<=
q
+
1
;
16
end
17
end
18
19
endmodule
图4 16-bit计数器的RTL视图
图5 Fmax值
图6 16-bit计数器占用的LE
Part III 用LPM实现16-bit计数器
代码
1
//
Top-level file
2
module
counter_lpm(en,clk,clr,q);
3
input
en,clk,clr;
4
output
[
15
:
0
]q;
5
6
megcounter counter_16bit(.clock(clk),.cnt_en(en),.sclr(clr),
7
.q(q)
8
);
9
endmodule
1
//
synopsys translate_off
2
`timescale
1
ps
/
1
ps
3
//
synopsys translate_on
4
module
megcounter (
5
clock,
6
cnt_en,
7
sclr,
8
q);
9
10
input
clock;
11
input
cnt_en;
12
input
sclr;
13
output
[
15
:
0
] q;
14
15
wire
[
15
:
0
] sub_wire0;
16
wire
[
15
:
0
] q
=
sub_wire0[
15
:
0
];
17
18
lpm_counter lpm_counter_component (
19
.sclr (sclr),
20
.clock (clock),
21
.cnt_en (cnt_en),
22
.q (sub_wire0),
23
.aclr (
1
'
b0),
24
.aload (
1
'
b0),
25
.aset (
1
'
b0),
26
.cin (
1
'
b1),
27
.clk_en (
1
'
b1),
28
.cout (),
29
.data ({
16
{
1
'
b0}}),
30
.eq (),
31
.sload (
1
'
b0),
32
.sset (
1
'
b0),
33
.updown (
1
'
b1));
34
defparam
35
lpm_counter_component.lpm_direction
=
"
UP
"
,
36
lpm_counter_component.lpm_port_updown
=
"
PORT_UNUSED
"
,
37
lpm_counter_component.lpm_type
=
"
LPM_COUNTER
"
,
38
lpm_counter_component.lpm_width
=
16
;
39
40
41
endmodule
图7 用LPM实现16-bit计数器所占用的LE
Part IV 循环显示0-9
在HEX0上循环显示0-9,每秒刷新一次。
代码
1
//
top-level file
2
module
seg_number(
3
output
[
6
:
0
]HEX0,
4
input
CLOCK_50,
5
input
[
0
:
0
]KEY
6
);
7
8
wire
clk_1hz;
9
reg
[
3
:
0
]cnt;
10
11
div u0(
12
.o_clk(clk_1hz),
13
.i_clk(CLOCK_50),
14
.rst_n(KEY)
15
);
16
17
always
@(
posedge
clk_1hz
or
negedge
KEY)
18
begin
19
if
(
!
KEY)
20
cnt
<=
4
'
b0;
21
else
22
begin
23
if
(cnt
==
4
'
d9)
24
cnt
<=
4
'
b0;
25
else
26
cnt
<=
cnt
+
1
'
b1;
27
end
28
end
29
30
seg7_lut u1(
31
.oseg(HEX0),
32
.idig(cnt[
3
:
0
])
33
);
34
endmodule
35
36
//
divider
37
module
div(
38
output
reg
o_clk,
39
input
rst_n,
40
input
i_clk
41
);
42
43
parameter
N
=
50_000_000;
44
parameter
M
=
24_999_999;
45
46
reg
[
25
:
0
]cnt;
47
48
always
@(
posedge
i_clk
or
negedge
rst_n)
49
begin
50
if
(
!
rst_n)
51
cnt
<=
26
'
b0;
52
else
53
begin
54
if
(cnt
==
N
-
1
)
55
cnt
<=
26
'
b0;
56
else
57
cnt
<=
cnt
+
26
'
b1;
58
end
59
end
60
always
@(
posedge
i_clk
or
negedge
rst_n)
61
begin
62
if
(
!
rst_n)
63
o_clk
<=
0
;
64
else
65
begin
66
if
(cnt
<=
M)
67
o_clk
<=
1
;
68
else
69
o_clk
<=
0
;
70
end
71
end
72
73
endmodule
74
75
//
seg7_lut
76
module
seg7_lut (
77
output
reg
[
6
:
0
] oseg,
78
input
[
3
:
0
] idig
79
);
80
always
@ (idig)
81
begin
82
case
(idig)
83
4
'
h1: oseg = 7
'
b1111001;
//
---t---
84
4
'
h2: oseg = 7
'
b0100100;
//
| |
85
4
'
h3: oseg = 7
'
b0110000;
//
lt rt
86
4
'
h4: oseg = 7
'
b0011001;
//
| |
87
4
'
h5: oseg = 7
'
b0010010;
//
---m---
88
4
'
h6: oseg = 7
'
b0000010;
//
| |
89
4
'
h7: oseg = 7
'
b1111000;
//
lb rb
90
4
'
h8: oseg = 7
'
b0000000;
//
| |
91
4
'
h9: oseg = 7
'
b0011000;
//
---b---
92
4
'
ha: oseg = 7
'
b0001000;
93
4
'
hb: oseg = 7
'
b0000011;
94
4
'
hc: oseg = 7
'
b1000110;
95
4
'
hd: oseg = 7
'
b0100001;
96
4
'
he: oseg = 7
'
b0000110;
97
4
'
hf: oseg = 7
'
b0001110;
98
default
: oseg
=
7
'
b1000000;
99
endcase
100
end
101
endmodule
Part V 循环显示HELLO
在HEX7-HEX0上循环显示HELLO,如图8所示。
图8 8个7segment上循环显示HELLO
代码
top-level file
1
//
top-level file
2
module
hello(HEX7,HEX6,HEX5,HEX4,
3
HEX3,HEX2,HEX1,HEX0,
4
CLOCK_50,KEY);
5
input
CLOCK_50;
6
input
[
0
:
0
]KEY;
7
output
[
6
:
0
]HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,
8
HEX1,HEX0;
9
10
wire
clk_1hz;
11
reg
[
3
:
0
]cnt;
12
13
div u0(.o_clk(clk_1hz),
14
.rst_n(KEY),
15
.i_clk(CLOCK_50)
16
);
17
18
always
@(
posedge
clk_1hz
or
negedge
KEY)
19
begin
20
if
(
!
KEY)
21
cnt
<=
4
'
b0;
22
else
23
begin
24
if
(cnt
==
4
'
b0111)
25
cnt
<=
4
'
b0;
26
else
27
cnt
<=
cnt
+
1
'
b1;
28
end
29
end
30
31
seg7_h0 h0(.oseg(HEX0),
32
.idig(cnt)
33
);
34
seg7_h1 h1(.oseg(HEX1),
35
.idig(cnt)
36
);
37
seg7_h2 h2(.oseg(HEX2),
38
.idig(cnt)
39
);
40
seg7_h3 h3(.oseg(HEX3),
41
.idig(cnt)
42
);
43
seg7_h4 h4(.oseg(HEX4),
44
.idig(cnt)
45
);
46
seg7_h5 h5(.oseg(HEX5),
47
.idig(cnt)
48
);
49
seg7_h6 h6(.oseg(HEX6),
50
.idig(cnt)
51
);
52
seg7_h7 h7(.oseg(HEX7),
53
.idig(cnt)
54
);
55
endmodule
分频器
1
//
divider
2
module
div(
3
output
reg
o_clk,
4
input
rst_n,
5
input
i_clk
6
);
7
8
parameter
N
=
50_000_000;
9
parameter
M
=
24_999_999;
10
11
reg
[
25
:
0
]cnt;
12
13
always
@(
posedge
i_clk
or
negedge
rst_n)
14
begin
15
if
(
!
rst_n)
16
cnt
<=
26
'
b0;
17
else
18
begin
19
if
(cnt
==
N
-
1
)
20
cnt
<=
26
'
b0;
21
else
22
cnt
<=
cnt
+
26
'
b1;
23
end
24
end
25
always
@(
posedge
i_clk
or
negedge
rst_n)
26
begin
27
if
(
!
rst_n)
28
o_clk
<=
0
;
29
else
30
begin
31
if
(cnt
<=
M)
32
o_clk
<=
1
;
33
else
34
o_clk
<=
0
;
35
end
36
end
37
38
endmodule
译码0
1
//
seg7_lut
2
module
seg7_h0
3
(
4
output
reg
[
6
:
0
] oseg,
5
input
[
3
:
0
] idig
6
);
7
always
@ (idig)
8
begin
9
case
(idig)
10
4
'
h0: oseg = 7
'
b1000000;
//
O
11
//
4'h1: oseg = 7'b1111001;
12
//
4'h2: oseg = 7'b0100100;
13
//
4'h3: oseg = 7'b0110000;
14
4
'
h4: oseg = 7
'
b0001001;
//
H
15
4
'
h5: oseg = 7
'
b0000110;
//
E
16
4
'
h6: oseg = 7
'
b1000111;
//
L
17
4
'
h7: oseg = 7
'
b1000111;
//
L
18
19
default
: oseg
=
7
'
b1111111;
20
endcase
21
end
22
endmodule
译码1
1
//
seg7_lut
2
module
seg7_h1
3
(
4
output
reg
[
6
:
0
] oseg,
5
input
[
3
:
0
] idig
6
);
7
always
@ (idig)
8
begin
9
case
(idig)
10
4
'
h1: oseg = 7
'
b1000000;
//
O
11
//
4'h4: oseg = 7'b1111001;
12
//
4'h2: oseg = 7'b0100100;
13
//
4'h3: oseg = 7'b0110000;
14
4
'
h5: oseg = 7
'
b0001001;
//
H
15
4
'
h6: oseg = 7
'
b0000110;
//
E
16
4
'
h7: oseg = 7
'
b1000111;
//
L
17
4
'
h0: oseg = 7
'
b1000111;
//
L
18
19
default
: oseg
=
7
'
b1111111;
20
endcase
21
end
22
endmodule
共8个译码模块(略6)
解法2
1 module part5(CLOCK_50,HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0);
2 input CLOCK_50;
3 output reg [6:0] HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0;
4
5 parameter blank=7'b1_111_111,
6 H=7'b0_001_001,
7 E=7'b0_000_110,
8 L=7'b1_000_111,
9 O=7'b1_000_000;
10
11 wire clk_1hz;
12 wire [3:0] cnt;
13
14 div u0(CLOCK_50,clk_1hz,1'b1);
15 counter8 u1(clk_1hz,1'b1,cnt);
16
17 always @(cnt)
18 case(cnt)
19 4'd0:begin
20 HEX7=blank;
21 HEX6=blank;
22 HEX5=blank;
23 HEX4=H;
24 HEX3=E;
25 HEX2=L;
26 HEX1=L;
27 HEX0=O;
28 end
29 4'd1:begin
30 HEX0=blank;
31 HEX7=blank;
32 HEX6=blank;
33 HEX5=H;
34 HEX4=E;
35 HEX3=L;
36 HEX2=L;
37 HEX1=O;
38 end
39 4'd2:begin
40 HEX1=blank;
41 HEX0=blank;
42 HEX7=blank;
43 HEX6=H;
44 HEX5=E;
45 HEX4=L;
46 HEX3=L;
47 HEX2=O;
48 end
49 4'd3:begin
50 HEX2=blank;
51 HEX1=blank;
52 HEX0=blank;
53 HEX7=H;
54 HEX6=E;
55 HEX5=L;
56 HEX4=L;
57 HEX3=O;
58 end
59 4'd4:begin
60 HEX3=blank;
61 HEX2=blank;
62 HEX1=blank;
63 HEX0=H;
64 HEX7=E;
65 HEX6=L;
66 HEX5=L;
67 HEX4=O;
68 end
69 4'd5:begin
70 HEX4=blank;
71 HEX3=blank;
72 HEX2=blank;
73 HEX1=H;
74 HEX0=E;
75 HEX7=L;
76 HEX6=L;
77 HEX5=O;
78 end
79 4'd6:begin
80 HEX5=blank;
81 HEX4=blank;
82 HEX3=blank;
83 HEX2=H;
84 HEX1=E;
85 HEX0=L;
86 HEX7=L;
87 HEX6=O;
88 end
89 4'd7:begin
90 HEX6=blank;
91 HEX5=blank;
92 HEX4=blank;
93 HEX3=H;
94 HEX2=E;
95 HEX1=L;
96 HEX0=L;
97 HEX7=O;
98 end
99 endcase
100
101 endmodule
102
其实还可以利用字型码加1的方法。
Conclusion
Part1 有助于理解计数器的具体实现,Part4是Part5的基础,单个7segment循环显示操作成功,多个
自然不难。:)
Reference
《Using library modules in Verilog Designs 》