FPGA 测频与蓝牙通信
实现功能
显示待测信号频率; 输出特定频率信号; 蓝牙通信: 从手机发送特定信息给下位机改变输出信号频率并显示。
自顶向下的管理
顶模块根据三个SW开关选择进行不同行为模式。
1、显示学号模式,数码管译码模块根据预设数字字典进行显示。
2、显示待测信号频率,信号整型方波模块将输入信号变为0,1的数字方波,频率计数模块将整型后的方波进行计数(这里采用计算1s内有几个方波信号的方法)。
3、输出特定频率正弦信号,通过分频模块改变输入时钟与DDS模块产生正弦波,输出特定频率正弦信号。
4、蓝牙通信:通过蓝牙模块接收上位机发送的消息,改变数码管显示值,输出对应频率正弦信号。
项目难点
蓝牙通信
注意传送时序(波特率限制) 注意传送逻辑(传送时是8位(8bit) 传送, 0和1之间包裹8bit 信息) 传送时是1位1位传送 需要考虑传送数据位数,最终填满32位信息,对应四个传送周期(4*8bit)
顶模块
负责管理子模块 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
module Top_module(
input wire clk,clr ,//模式、时钟、清零
input wire [2:0] mode,
input [7:0] SW,
input [9:0]din,//输入D/A信号
input rx,//输入串行的蓝牙信号,0101010...
input pause,
output wire [6:0] a_to_g0,//两个段选
output wire [6:0] a_to_g1,
output wire [7:0] position,//8个位选
output wire point4,//小数点
output wire point5,
output [5:0] D,
output aclk,//给D/A转换器一个时钟
output clk_AD,
// output [31:0] fre_Hz,
output wire [7 : 0] douta, // output wire [7 : 0] douta
output [1:0] led,
output [4:0]BTD,
output tx
);
assign BTD=5'b10111;
assign D=6'b000000; //DA转换上六位输入
wire [31:0]fre_Hz;
assign fre_Hz=c1.fre_Hz;
sub_Frequency_div d1(
.clk(clk),
.clr(clr),
.d(5000)
);//分频10000 10kHx
//七段译码显示:三种模式
sub_7seg s1 (
.B3_BCD(B3.BCD),
.B4_BCD(B4.BCD),
.B5_BCD(B5.BCD),
.pause(pause),
.clk1(clk),
.clk(d1.div_frequency),
.SW(SW),
.mode(mode),
.point4(point4),
.point5(point5),
.a_to_g1(a_to_g1),
.a_to_g0(a_to_g0),
.position(position)
// .din(sin1.douta)
);
//.....................DDS,调用ROM IP核................................//
sub_Frequency_div d2(
.clk(clk),
.clr(clr),
.d(5)
);//分频10 10MHx
assign aclk=d2.div_frequency;
assign clk_AD=d2.div_frequency;
reg[7:0]SW_inside;
sub_DDS_sine sin1(
.clk(d2.div_frequency),
.clr(clr),
.SW(SW_inside),
.douta(douta)
);
//。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。//
//转换为0,1方波
clk_ut u1(
.clk(clk),
.din(din)//输入信号
//.din(douta)//仿真测试
);
sub_cal_freq c1( //高频
.clk(clk),
.clr(clr),
.ulk(u1.ulk)
);
sub_cal_low_freq c2( //低频
.clk(clk),
.clr(clr),
.ulk(u1.ulk)
);
sub_get_f_BCD B3(
.clk(clk),
.f(c1.fre_Hz)
);
sub_get_f_BCD B4( //测量低频
.clk(clk),
.f(c2.Fre_Hz_low)
);
//蓝牙
wire [31:0]f2;
assign f2=(SW_inside[0]+SW_inside[1]*2+SW_inside[2]*4+SW_inside[3]*8+SW_inside[4]*16+SW_inside[5]*32+SW_inside[6]*64+SW_inside[7]*128)*78125/2;
wire[31:0] message;
assign message=bt.message;
always@(posedge clk)begin
if(mode==3'b111)
SW_inside<=message;
else
SW_inside<=SW;
end
sub_Blue_teeth bt(
.sys_clk(clk),
.rx(rx),
.led(led)
);
sub_get_f_BCD B5(
.clk(clk),
.f(f2)
);
endmodule
分频模块
通过每隔n基准脉冲翻转一次进行分频,分频结果为 f/(2n) 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
module sub_Frequency_div(
input clk,clr,
input [18:0]d,
output div_frequency
);
reg[32:0] div=1;
reg y=1;
assign div_frequency=y;
always@(posedge clk)
begin
if(div<=d)//10000
begin
div<=div+1;
y<=0;
end
else if(div>=d+d)
begin
div<=1;
y<=1;
end
else
begin
div<=div+1;
y<=1;
end
end
endmodule
数码管译码模块
模块主控
根据 SW 3位开关输入改变显示模式; 模式1: 显示学号; 模式2: 显示待测信号频率; 模式3: 显示输出信号频率; 显示思路: 片选+段选,循环导通每一位数码管进行显示,只要频率够快,看起来是同时显示。
1 |
|
译码子模块
进行简单的字典翻译工作,只翻译一位七段译码管 输出脚控制七段译码管
a_to_g 七个二极管 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
module sub_7seg_translate(
input [4:0] seg7,
input clk
);
wire [4:0]seg77;
assign seg77=seg7;
reg [6:0] seg_output;
always@(posedge clk)begin
case(seg7)
0: seg_output<=`zero;
1: seg_output<=`one;
2:seg_output<=`two;
3:seg_output<=`three;
4:seg_output<=`four;
5:seg_output<=`five;
6:seg_output<=`six;
7:seg_output<=`seven;
8:seg_output<=`eight;
9:seg_output<=`nine;
endcase
end
endmodule
DDS模块
DDS原理
根据 DDS 原理产生正弦信号,SW为步进 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module sub_DDS_sine(
input clk,clr,
input[7:0]SW,
output wire [7 : 0] douta
);
//相位累加器
reg [7:0]Fre_acc;
always @(posedge clk or negedge clr)
if(!clr)
Fre_acc <= 9'd0;
else
Fre_acc <= Fre_acc + SW;
blk_mem_gen_0 rom_addr_douta (
.clka(clk), // input wire clka
.addra(Fre_acc), // input wire [7 : 0] addra
.douta(douta) // output wire [7 : 0] douta
);
endmodule
信号整型为方波模块
1 |
|
频率计数模块
1 |
|
BCD译码模块
Q:
为什么要进行 BCD 译码?
A:
为了知道八个七段数码管每一位都是哪个数字,需要对测量出来的频率 f 每一位进行分割,对于 f 每一位来说,都是正常的四位二进制表示,对于32位的f来说,它被转换成了 BCD 码 。
1 |
|
蓝牙模块(接收)
注意传送时序(波特率限制) 注意传送逻辑(传送时是8位(8bit) 传送, 0和1之间包裹8bit 信息) 传送时是1位1位传送 cycle_4 为偏移量,0,1,2,3 循环变化,最终填满32位信息,对应四个传送周期(4*8bit) message 用来输出32位接收内容 r_start 用来判断第一个 0位(8bit 信息传送开始)
1 |
|
DDS coe 文件
1 | MEMORY_INITIALIZATION_RADIX=10; |
约束文件
1 |
|