FPGA.计数器书写——以60进制、24进制举例

计数器在数字系统中主要是对脉冲的个数进行计数,以实现测量、计数和控制的功能,同时兼有分频功能。其实说白了,就是正常使用的情况下,你来个脉冲信号,我给你+1。当然实际情况下,为满足我的需要,我们会为计数器加上一“功能”,如:置数,复位。具体情况根据需要而定,但不管怎样,计数器都是较为简单的。

60进制计数器

60机制计数器,也就是从0数到59,然后清零,再来过。如此反复,每到60的时候输出一次脉冲信号。废话不多说,直接看代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
------------------------
-创建时间:2017.10.20
-创建人:Robin
-文件名:counter60
-----------------------
`timescale 1ns / 1ps
module counter60(
input clk,clear,load,en, //时钟,清零,置数,使能
input [3:0]dl,dh, //输入
output reg [3:0] ql,qh, //输出
output cout //进位
);

always @(posedge clk,negedge clear)
if(!clear) //清零
begin
ql<=0;qh<=0;
end
else if(load)
begin
ql<=dl; //置数
qh<=dh;
end
else if(en)
if(ql==4'h9)
begin
ql<=0;
if(qh==4'h5)
qh<=0;
else
qh<=qh+1;
end
else
ql<=ql+1;
assign cout=(en==1'b1 && qh==4'd5 && ql==4'd9)?1'b1:1'b0;
endmodule

简单说下书写的思路,设计60进制的高低位为[3:0]ql,qh。用高、低两位数表示60因为我们人习惯使用十进制,但是计算机是用二进制的,所以ql,qh是[3:0]四位二进制。cout为计数器的输出。通常来说,低位一直+1,由0~9,当低位是9,如果高位没到5,那么下一个脉冲来的时候,低位清零,高位+1,就像29,变为30。若低位是9,而且高位是5,也就是数到59了,再来个脉冲,两者清零。至于清零,和使能,置数这些,看代码应该很容易理解的。

Tb文件

以下的Tb测试文件,该部分请根据需要改变参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
------------------------
-创建时间:2017.10.20
-创建人:Robin
-文件名:Tb_counter60
-----------------------
`timescale 1ns / 1ps
module tb_counter;
reg clk,clear,load,en;
reg [3:0] dl,dh;
wire [3:0] ql,qh;
wire cout;
//例化语句
counter60 uut(.clk(clk),.clear(clear),.load(load),.en(en),.dl(dl),.dh(dh),.ql(ql),.qh(qh),.cout(cout));
//时钟信号,周期是30ns
always
begin
clk<=1;#15;
clk<=0;#15;
end
//清零,先清零让ql,qh等于0,再启动
initial
begin
clear=0;#30;
clear=1;
end
//置数
initial
begin
dl=1;dh=1;
load=0;#800;
load=1;#500;
end
//使能信号
initial
begin
en=0;#200;
en=1;
end
endmodule

24进制计数器

下面放上24进制的计数器源代码,代码不难理解,就不再过多解释了。Tb文件与60进制的相差不大,把例化语句里的源文件名称修改下就好,我也不再重复贴上去了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
------------------------
-创建时间:2017.10.20
-创建人:Robin
-文件名:counter24
-----------------------
`timescale 1ns / 1ps
module counter24(
input clk,clear,load,en, //时钟,清零,置数,使能
input [3:0]dl,dh, //输入
output reg [3:0] ql,qh, //输出
output cout //进位
);
always @(posedge clk,negedge clear)
//清零
if(!clear)
begin
ql<=0;qh<=0;
end
else if(load)
begin
ql<=dl; //置数
qh<=dh;
end
else if(en)
if(ql==4'h3 && qh==4'h2)
begin
qh<=0;
ql<=0;
end
else if(ql==4'h9&&(qh==4'h1||qh==4'h0))
begin
qh<=qh+1;
ql<=0;
end
else
ql<=ql+1;
else
ql<=ql;
assign cout=(en==1'b1 && qh==4'd2 && ql==4'd3)?1'b1:1'b0;
endmodule

代码的写法有很多,各有优劣,我这也只是给出一种解决办法,有错误请斧正,欢迎大家在评论区与我交流。

本文完。

请我喝杯咖啡~
------ 本文结束------
0%