链接:https://pan.baidu.com/s/1AjCw2kyBkggQ5doQ2vNWkg
提取码:1234
一、 设计要求
利用FPGA设计一个信号测频器,要求:
(1)测量脉冲信号;
(2)频率测量1-10MHz以及占空比10%-99% 精确到1%;
(3)将测出频率和占空比显示在LCD1602上;
二、 设计方案
FPGA设计主要分为三个大模块来设计:1.被测信号产生模块;2.被测信号检测模块;3.数字显示模块。设计框图如图 1所示。
图 1 基于FPGA的信号测频器设计框图
-
被测信号产生模块
该模块主要是用来产生被测信号,可以在模块中设置被测信号的频率和占空比。采用的方法是对系统时钟进行计数分频产生被测信号。这部分也采用了一个PLL,输出一个100MHz的时钟作为检测模块的采样时钟。该部分涉及的模块:signal_gen模块和PLL模块。 -
被测信号检测模块
该模块对被测信号进行检测的方法是等精度测频法:
(1)被测信号频率检测
检测被测信号的频率,通过在外部使能信号有效时(即一段时间内),计数系统时钟脉冲数Ns与被测信号脉冲数Nd,若系统时钟频率为Fs,被测信号频率为Fd,则有Fs/Ns=Fd/Nd 最后有Fd=(Fs/Ns)·Nd。
(2)被测信号占空比检测:
检测被测信号的占空比,利用系统时钟,在外部使能信号有效时(即一段时间内),计数被测信号的正脉宽数Np和负脉宽数Nn,则占空比ducy=Np/(Np+Nn)*100%。
该部分涉及的模块:signal_detect模块。 -
数字显示模块
该模块主要分为两个部分:一个部分是把检测的频率码转换为十进制BCD码,采用这种方法虽然会提高运算时间,但却可以大大节省FPGA的资源(面积与速度的折衷);另外一个部分是驱动LCD1602进行显示。这里给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例): 1.将二进制码左移一位(或者乘2);2.找到左移后的码所对应的个,十,百位;3.判断在个位,十位和百位的码是否大于等于5;4.继续重复以上三步直到移位8次后停止;5.如果是则该段码加3。该部分涉及的模块:BCD2to10模块和lcd1602模块。
最终在FPGA的RTL视图如图 2所示:
//synopsys translate_off
`timescale 1 ns/ 1 ps
//synopsys translate_on
module BCD2to10(
clk_100M,
rst_n,
d_clk_freq,
qw,
bw,
sw,
w,
q,
b,
s,
g);
input clk_100M; // 采样时钟 100MHz
input rst_n; // 复位信号
input [31:0] d_clk_freq; // 被测信号频率
output [3:0] qw; // 转换提取千万位
output [3:0] bw; // 转换提取百万位
output [3:0] sw; // 转换提取十万位
output [3:0] w; // 转换提取万位
output [3:0] q; // 转换提取千位
output [3:0] b; // 转换提取百位
output [3:0] s; // 转换提取十位
output [3:0] g; // 转换提取个位
parameter ST0 = 2'b00;
parameter ST1 = 2'b01;
parameter ST2 = 2'b10;
//-------------------------------------------------------------------
// 首先给出二进制码转换为十进制BCD码的几个步骤(以8bit二进制码为例)
// 1.将二进制码左移一位(或者乘2)
// 2.找到左移后的码所对应的个,十,百位。?
// 3.判断在个位,十位和百位的码是否大于等于5
// 4.继续重复以上三步直到移位8次后停止。
// 5,如果是则该段码加3。
//-----------------------------------------------------------------
reg [31:0] d_clk_shift_reg;
reg [5:0] shift_count;
reg shift_done;
reg [31:0] bcd_reg;
reg [3:0] qw;
reg [3:0] bw;
reg [3:0] sw;
reg [3:0] w;
reg [3:0] q;
reg [3:0] b;
reg [3:0] s;
reg [3:0] g;
reg [1:0] state;
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
d_clk_shift_reg <= #1 32'b0;
else
begin
if(shift_done == 1'b1)
d_clk_shift_reg <= #1 32'b0;
else
d_clk_shift_reg <= #1 d_clk_freq << shift_count;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
shift_done <= #1 1'b0;
else
begin
if(shift_count == 6'd32)
shift_done <= #1 1'b1;
else
shift_done <= #1 1'b0;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
bcd_reg <= #1 32'b0;
shift_count <= #1 6'b0;
state <= #1 ST0;
end
else
begin
if(shift_done == 1'b0)
begin
case(state)
ST0:begin
bcd_reg <= #1 {bcd_reg[31:1],d_clk_shift_reg[31]}; //移位
state <= #1 ST1;
end
ST1:begin
if(bcd_reg[31:28] >= 4'd5) // qw
bcd_reg[31:28] <=#1 bcd_reg[31:28] + 4'd3;
else
bcd_reg[31:28] <=#1 bcd_reg[31:28];
if(bcd_reg[27:24] >= 4'd5) // bw
bcd_reg[27:24] <=#1 bcd_reg[27:24] + 4'd3;
else
bcd_reg[27:24] <=#1 bcd_reg[27:24];
if(bcd_reg[23:20] >= 4'd5) // sw
bcd_reg[23:20] <=#1 bcd_reg[23:20] + 4'd3;
else
bcd_reg[23:20] <=#1 bcd_reg[23:20];
if(bcd_reg[19:16] >= 4'd5) // w
bcd_reg[19:16] <=#1 bcd_reg[19:16] + 4'd3;
else
bcd_reg[19:16] <=#1 bcd_reg[19:16];
if(bcd_reg[15:12] >= 4'd5) // q
bcd_reg[15:12] <=#1 bcd_reg[15:12] + 4'd3;
else
bcd_reg[15:12] <=#1 bcd_reg[15:12];
if(bcd_reg[11:8] >= 4'd5) // b
bcd_reg[11:8] <=#1 bcd_reg[11:8] + 4'd3;
else
bcd_reg[11:8] <=#1 bcd_reg[11:8];
if(bcd_reg[7:4] >= 4'd5) // s
bcd_reg[7:4] <=#1 bcd_reg[7:4] + 4'd3;
else
bcd_reg[7:4] <=#1 bcd_reg[7:4];
if(bcd_reg[3:0] >= 4'd5) // g
bcd_reg[3:0] <=#1 bcd_reg[3:0] + 4'd3;
else
bcd_reg[3:0] <=#1 bcd_reg[3:0];
state <= #1 ST2;
end
ST2:begin
bcd_reg <= #1 bcd_reg << 1'b1; //移位
shift_count <= #1 shift_count + 1'b1;
state <= #1 ST0;
end
default:bcd_reg <= #1 bcd_reg;
endcase
end
else
begin
state <= #1 ST0;
bcd_reg <= #1 32'b0;
shift_count <= #1 6'b0;
end
end
end
reg [31:0] bcd_reg2;
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
bcd_reg2 <= #1 32'b0;
else
begin
if(shift_count == 6'd32)
bcd_reg2 <= #1 bcd_reg;
else
bcd_reg2 <= #1 bcd_reg2;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
qw <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
qw <= #1 bcd_reg2[31:28];
else
qw <= #1 qw;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
bw <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
bw <= #1 bcd_reg2[27:24];
else
bw <= #1 bw;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
sw <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
sw <= #1 bcd_reg2[23:20];
else
sw <= #1 sw;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
w <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
w <= #1 bcd_reg2[19:16];
else
w <= #1 w;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
q <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
q <= #1 bcd_reg2[15:12];
else
q <= #1 q;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
b <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
b <= #1 bcd_reg2[11:8];
else
b <= #1 b;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
s <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
s <= #1 bcd_reg2[7:4];
else
s <= #1 s;
end
end
always@(posedge clk_100M or negedge rst_n)
begin
if(rst_n == 1'b0)
g <= #1 4'b0;
else
begin
if(shift_done == 1'b1)
g <= #1 bcd_reg2[3:0];
else
g <= #1 g;
end
end
endmodule