Veirlog学习记录-6-数字频率计的设计与实现(附完整工程)

FPGA的课程的大作业,我们选的是数字频率计设计。下面分享一下代码,还有工程文件,还有自己写的论文(里面会有更加详细的介绍),希望可以对你有所启发。

工程文件github地址

开发环境:Vivado 2015.4+Modelsim(仅用于仿真波形)
开发板:赛灵思公司 xc7a100tcsg324-1

总体设计要求:

  • 可测量脉冲信号的频率
  • 被测信号由100MHz的系统时钟分频获得,频率为学号*1000 Hz
  • 测量结果在6位数码管上显示,高位若是零则不显示该位
  • 采用连续测量方式,每4秒为1个周期,其中1秒用于测量,3秒用于显示

总体设计框图:

子模块设计:

- 分频模块:

结构图:
代码如下:

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
module div(
input clk_100mhz, //系统给定的时钟频率
output clk_190hz, //数码管的动态扫描频率
output reg clk_1Hz, //控制模块的驱动频率
output reg fin //输出待测试信号的频率
);
reg [9:0] cnt0;
reg [30:0] cnt;
reg [18:0] cnt1;

always @(posedge clk_100mhz)
cnt1 = cnt1 + 1;
assign clk_190hz = cnt1[18];
always @(posedge clk_100mhz)
if(cnt == 50000000) begin
cnt = 0;
clk_1Hz = ~clk_1Hz;
end
else
cnt = cnt + 1;
always @(posedge clk_100mhz)
if(cnt0 == 499) begin //生成的测试信号的频率为100KHz
cnt0 = 0;
fin = ~fin;
end
else
cnt0 = cnt0 + 1;

endmodule

被测频率本来要求是学号*1000Hz,但是我的学号无法被整除,所以无法度量频率计的的精度,更无法进行误差分析。所以才选取了100KHz作为测试频率。

- 控制模块

结构图:

code:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
module control(clk_1Hz, rst, count_en, latch_en, clear);  
input clk_1Hz;
input rst; //复位信号
output count_en; //计数使能
output latch_en; //锁存使能
output clear; //清零信号
reg [2:0] state; //状态信号,用于控制各种使能信号
reg count_en;
reg latch_en;
reg clear;

always @(posedge clk_1Hz or negedge rst)
if(!rst) //复位信号有效
begin //各种使能信号清零
state <= 3'b000;
count_en <= 1'b0;
latch_en <=1'b0;
clear <= 1'b0;
end
else //遇到基准信号的下一个上升沿,状态变化一次,每次变化后状态持续1s
begin
case(state)
3'b000:
begin //第一个上升沿到达,开始计数,计数1个基准信号周期内待测信号的上升沿个数,此个数即为待测信号的频率
count_en <= 1'b1; //计数使能信号有效
latch_en <= 1'b0;
clear <= 1'b0;
state <= 3'b001;
end
3'b001:
begin //第二个上升沿到达,计数完成,锁存使能信号有效,测得频率锁存至锁存器中
count_en <= 1'b0;
latch_en <=1'b1;
clear <= 1'b0;
state <= 3'b010;
end
3'b010:
begin //第三个上升沿到达,计数完成,锁存使能信号有效,测得频率锁存至锁存器中
count_en <= 1'b0;
latch_en <=1'b1;
clear <= 1'b0;
state <= 3'b011;
end
3'b011:
begin //第四个上升沿到达,计数完成,锁存使能信号有效,测得频率锁存至锁存器中
count_en <= 1'b0;
latch_en <=1'b1;
clear <= 1'b0;
state <= 3'b100;
end
3'b100:
begin //第五个上升沿到达,清零使能信号有效,计数器清零,为下一次计数做准备
count_en <= 1'b0;
clear <= 1'b1;
latch_en <=1'b1;
state <= 3'b000; //状态清零,进入下一次测量
end
default:
begin
count_en <= 1'b0;
latch_en <=1'b0;
clear <= 1'b0;
state <= 3'b000;
end
endcase
end

1
endmodule

- 计数模块

结构图:

code:

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
41
42
module counter_10(en_in, rst, clear, fin, en_out, q);  
input en_in; //输入使能信号
input rst; //复位信号
input clear; //清零信号
input fin; //待测信号
output en_out; //输出使能,用于控制下一个计数器的状态,当输出使能有效时,下一个模10计数器计数加1
output [3:0] q; //计数器的输出,4位BCD码输出

reg en_out;
reg [3:0] q;

always@ (posedge fin or negedge rst) //输入待测信号的上升沿作为敏感信号
if(!rst) //复位信号有效,计数器输出清零
begin
en_out <= 1'b0;
q <= 4'b0;
end
else if(en_in) //进位输入使能信号有效
begin
if(q == 4'b1001) //若q = 4'b1001的话,q清零,同时进位输出使能有效,即en_out 赋值为1'b1
begin
q <= 4'b0;
en_out <= 1'b1;
end
else //若q未达到4'b1001时,每到达待测信号的一个上升沿,q加1,同时输出进位清零
begin
q <= q + 1'b1;
en_out <=1'b0;
end
end
else if(clear) //若清零信号有效,计数器清零,用于为下一次测量准备
begin
q <= 4'b0;
en_out <= 1'b0;
end
else
begin
q <= q;
en_out <=1'b0;
end

endmodule

锁存模块

结构图:

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
module latch(clk_1Hz, latch_en, rst, q0, q1, q2, q3, q4, q5, q6, q7,  
d0, d1, d2, d3, d4, d5, d6, d7);
input clk_1Hz, latch_en, rst;
input[3:0] q0, q1, q2, q3, q4, q5, q6, q7;
output[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
reg[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
always@ (posedge clk_1Hz or negedge rst)
if(!rst) //复位信号有效时输出清零
begin
d0 <= 4'b0; d1 <= 4'b0; d2 <= 4'b0; d3 <= 4'b0; d4 <= 4'b0;
d5 <= 4'b0; d6 <= 4'b0; d7 <= 4'b0;
end
else if(latch_en) //锁存信号有效时,将计数器的输出信号锁存至锁存器
begin
d0 <= q0; d1 <= q1; d2 <= q2; d3 <= q3; d4 <= q4;
d5 <= q5; d6 <= q6; d7 <= q7;
end
else //上面两种情况均未发生时,输入不变
begin
d0 <= d0; d1 <= d1; d2 <= d2; d3 <= d3; d4 <= d4;
d5 <= d5; d6 <= d6; d7 <= d7;
end

endmodule

显示模块

结构图:

code:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
module IP_seg_disp(
input clk_190hz,
input [3:0] d0,d1,d2,d3,d4,d5,d6,d7
output reg [7:0] duan,
output reg [7:0] wei
);

reg [3:0] disp;
reg [2:0] smg_ctl;

always @ ( posedge clk_190hz)
smg_ctl = smg_ctl + 1'b1;
always @ (*)
case ( smg_ctl )
3'b000:begin
wei = 8'b11111110;
disp = d0 [3:0];
end
3'b001:begin
wei = 8'b11111101;
disp = d1 [3:0];
end
3'b010:begin
wei = 8'b11111011;
disp = d2 [3:0];
end
3'b011:begin
wei = 8'b11110111;
disp = d3 [3:0];
end
3'b100:begin
wei = 8'b11101111;
disp = d4 [3:0];
end
3'b101:begin
wei = 8'b11011111;
disp = d5 [3:0];
end
3'b110:begin
wei = 8'b10111111;
disp = d6 [3:0];
if( disp==0 ) //如果高位数值为0,则不显示该位
disp <=4'b1111;
end
3'b111:begin
wei = 8'b01111111;
disp = d7 [3:0];
if( disp==0 )
disp <=4'b1111
end
default:;
endcase

always @ ( * )
case (disp)
4'b0000:duan = 8'b11000000;
4'b0001:duan = 8'b11111001;
4'b0010:duan = 8'b10100100;
4'b0011:duan = 8'b10110000;
4'b0100:duan = 8'b10011001;
4'b0101:duan = 8'b10010010;
4'b0110:duan = 8'b10000010;
4'b0111:duan = 8'b11111000;
4'b1000:duan = 8'b10000000;
4'b1001:duan = 8'b10010000;
4'b1010:duan = 8'b10001000;
4'b1011:duan = 8'b10000011;
4'b1100:duan = 8'b11000110;
4'b1101:duan = 8'b10100001;
4'b1110:duan = 8'b10000110;
4'b1111:duan = 8'b11111111;
default:duan = 8'b11000000;
endcase
endmodule

顶层模块

code:

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
41
42
43
44
45
46
47
48
49
50
51
52
module freDetect(clk_100mhz,rst,duan,wei);  
input clk_100mhz;
input rst; //复位信号
output [7:0] duan;
output [7:0] wei;
wire[3:0] q0, q1, q2, q3, q4, q5, q6, q7; //中间数据
wire[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
wire fin;
wire clk_1Hz;
wire clk_190hz;
//分频模块实例
div u_div(
.clk_1Hz(clk_1Hz),
.clk_190hz(clk_190hz),
.clk_100mhz(clk_100mhz),
.fin(fin)
);
//显示模块实例
IP_seg_disp u_IP_seg_disp( .clk_190hz(clk_190hz), .d0(d0),
.d1(d1), .d2(d2), .d3(d3), .d4(d4),
.d5(d5), .d6(d6), .d7(d7),
.duan(duan), .wei(wei)
);
//控制模块实例
control u_control(.clk_1Hz(clk_1Hz), .rst(rst), .count_en(count_en),
.latch_en(latch_en), .clear(clear));

//计数器模块实例
counter_10 counter0(.en_in(count_en), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out0), .q(q0));
counter_10 counter1(.en_in(en_out0), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out1), .q(q1));
counter_10 counter2(.en_in(en_out1), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out2), .q(q2));
counter_10 counter3(.en_in(en_out2), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out3), .q(q3));
counter_10 counter4(.en_in(en_out3), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out4), .q(q4));
counter_10 counter5(.en_in(en_out4), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out5), .q(q5));
counter_10 counter6(.en_in(en_out5), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out6), .q(q6));
counter_10 counter7(.en_in(en_out6), .clear(clear), .rst(rst),
.fin(fin), .en_out(en_out7), .q(q7));

//锁存器模块实例
latch u_latch(.clk_1Hz(clk_1Hz), .rst(rst), .latch_en(latch_en),
.q0(q0), .q1(q1), .q2(q2), .q3(q3), .q4(q4), .q5(q5),
.q6(q6), .q7(q7), .d0(d0), .d1(d1), .d2(d2), .d3(d3),
.d4(d4), .d5(d5), .d6(d6), .d7(d7));

endmodule

测试文件:

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
module freDetect_tb;  
parameter CLK_1HZ_DELAY = 50000000; //用于生成1Hz基准信号
parameter FIN_DELAY = 500; //用于生成100KHz待测信号
reg clk_1Hz;
reg fin;
reg rst; //复位
wire[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
initial
begin
rst =1'b0;
#1 rst = 1'b1;
end
initial
begin
fin = 1'b0;
forever
#FIN_DELAY fin = ~fin;
end
initial
begin
clk_1Hz = 1'b0;
forever
#CLK_1HZ_DELAY clk_1Hz = ~clk_1Hz;
end
freDetect freDetect1(.clk_1Hz(clk_1Hz), .rst(rst), .fin(fin),
.d0(d0), .d1(d1), .d2(d2), .d3(d3), .d4(d4), .d5(d5), .d6(d6), .d7(d7));
endmodule

波形仿真结果如图所示:
结果显示
实验结果:

两张图片分别为 测量计数时和复位时和显示计数时:
测量计数时和复位时的显示显示计数时

我也写了几篇关于Veirlog的文章,感兴趣的同学可以去看看。该模块链接如下:
Verilog学习

© 2021 XuXing's blog All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero