题目:
1、频率和周期测量:正弦波,1Hz~~10MHz,50mV~1V幅度,相对误差绝对值小于等于10^-4
2、时间间隔测量:方波,100Hz~~1MHz,50mV~1V幅度,时间间隔范围是0.1us~100ms,相对误差绝对值小于等于10^-2
3、增加脉冲信号占空比测量:矩形波,1Hz~5MHz,50mV~1V幅度,占空比范围10%~90%,相对误差绝对值小于等于10^-2
本组信号发生器可以达到的范围
最大频率5MHz,占空比50%
4MHz,占空比40~60%
其他频率20~80%
我的完成程度:
频率测量达到精度
占空比有0.1%的误差
间隔时间测量因为从题目无法理解实际时间间隔多少,完成了输出异或后信号的占空比输出,没有继续调试
一、总体思路
gate表示门限使能,在门限内进行测量
1、测频率——等精度测量法
对待测信号fx计数5000个周期,在此期间gate为高,基准信号f=50MHz,比待测信号都快,对应也产生一个门限使能gate_f0(与gate同电平但对应的时钟上升沿不同),在gate_f0高电平计数基准信号,得到的数值通过计数就是频率。
2、占空比
同样在gate为高,在待测信号高电平时计数,与测频率时的数字做比得到占空比
问题在于fpga没有小数,我输出的比值是小数点后移一位的,单片机显示再做除10
另一种方法:
倍频50MHz时钟,对待测时钟测两个周期高电平时候的计数
原因:测5000个周期会有5000次跳变,容易产生误差,测两个周期可能少些误差
3、时间间隔
输入两路信号clk1,clk2,二分频后异或,产生clk3,测占空比
目前代码输出的结果是clk3的占空比,没有转换成时间
二、代码
1、测频率
输入:CLK,基准时钟;
clk_in:待测时钟;
clr:清零;
输出:
gate_f0:基准时钟的gate;
gate_f0_down:基准时钟的gate下降沿标志
fx:待测信号的频率;
cnt_CLK:基准时钟的计数值;
module freq_cnt(
input CLK,
input clk_in,
input clr,
output reg gate_f0,
output wire gate_f0_down,
output wire [wid32-1:0] fx,
output reg [wid32-1:0] cnt_CLK);
//output reg [N-1:0] N3
parameter CNTVAL_x=5000;
parameter wid16=16;
parameter wid32=32;
parameter wid64=64;
reg [64-1:0]cnt_fx;
reg gate,gate_fx_d0,gate_fx_d1; wire gate_fx_down;
reg gate_temp;
reg gate_f0_d0,gate_f0_d1; //wire gate_f0_down;
reg [wid16-1:0]cnt;
reg [wid32-1:0] cnt_f0;
counter of clock for test
always @(posedge clk_in or negedge clr) begin
if(!clr)
cnt<=0;
else if(cnt >= CNTVAL_x + 5'd20)
cnt <= 0;
else
cnt <= cnt + 1'b1;
end
///clock's gate for test
always @(posedge clk_in or negedge clr) begin
if(!clr)
gate<=0;
else if(cnt<=4'd10)
gate<=0;
else if(cnt<=CNTVAL_x+4'd10)
gate<=1;
else if(cnt<CNTVAL_x+5'd20)
gate<=0;
else
gate<=0;
if(!clr)begin
gate_fx_d1<=0;
gate_fx_d0<=0;
end
else begin
gate_fx_d0<=gate;
gate_fx_d1<=gate_fx_d0;
end
end
assign gate_fx_down = gate_fx_d1 & (~gate_fx_d0);
//50Mclock's gate
always @(posedge CLK or negedge clr) begin
if(!clr)begin
gate_temp<=0;
gate_f0<=0;
end
else begin
gate_temp<=gate;
gate_f0<=gate_temp;
end
if(!clr)begin
gate_f0_d1<=0;
gate_f0_d0<=0;
end
else begin
gate_f0_d0<=gate_f0;
gate_f0_d1<=gate_f0_d0;
end
end
assign gate_f0_down = gate_f0_d1 & (~gate_f0_d0);
assign fx=cnt_fx;
always @ (posedge CLK or negedge clr) begin
if(!clr)begin
cnt_CLK<=0;
cnt_f0<=0;
cnt_fx<=0;
end
else if(gate_f0_down) begin
cnt_f0<=0;
cnt_CLK<=cnt_f0;
cnt_fx<=(CNTVAL_x*50000000)/cnt_f0;
end
else if(gate_f0)
cnt_f0<=cnt_f0+1'b1;
end
endmodule
第一个always:对待测时钟计数5000,因为延时问题,多出20便于产生gate;
第二个always:产生待测时钟的gate和下降沿标志gate_down,因为延时,gate在非清零,10~5000+10内是高电平;
第三个always:产生基准时钟的gate和gate_down,注意:两个always使用的时钟沿不同;
第四个always:对基准时钟计数,并且计算频率。注意:因为5000*50M数字过大,中间使用了一个64bit的cnt_fx,时序电路赋值给32bit的fx
2、占空比
输入:gate、gate_down来控制占空比数字的计算和输出;
cnt_CLK:5000待测信号对应的基准时钟周期数;
输出
pwm:10倍占空比
module pwm_in(
input CLK ,
input clk_in,
input clr,
input gate,
input gate_down,
input [31:0]cnt_CLK,
output reg [wid32-1:0]pwm);
parameter wid32=32;
reg [wid32-1:0]cnt_clk_in;
reg [wid32-1:0]cnt_clk_in_high;
reg [63:0]pwm_temp;
always @(posedge CLK or negedge clr) begin
if(!clr)begin
cnt_clk_in<=0;
cnt_clk_in_high<=0;
pwm<=0;
end
else if(gate_down) begin
cnt_clk_in_high<=cnt_clk_in;
cnt_clk_in<=0;
pwm_temp<=((cnt_clk_in_high*10000)/cnt_CLK)/10;
pwm<=pwm_temp[15:0];
end
else if(gate & clk_in)
cnt_clk_in <=cnt_clk_in+1'b1;
end
endmodule
always中要使用基准时钟,所以使用的gate是来自基准时钟产生的,对应的时钟沿不同、高电平时间长度不同
3、时间间隔
输出pwm_clk3:异或之后clk3的占空比
module interval_2(
input CLK,
input clk1,
input clk2,
input clr,
input gate,
input gate_down,
input [31:0]cnt_CLK,
output wire [31:0] pwm_clk3);
wire r_clk1,r_clk2;
wire clk3;
freq_div_2 freq1(
.clk (clk1),
.rst_n (clr),
.clk_div(r_clk1));
freq_div_2 freq2(
.clk (clk2),
.rst_n (clr),
.clk_div(r_clk2));
assign clk3 = (r_clk1) ^ (r_clk2);
//assign clk3 =clk1 ^clk2;
pwm_in pwm_in(
.CLK (CLK),
.clk_in (clk3),
.cnt_CLK (cnt_CLK),
.clr (clr),
.gate (gate),
.gate_down(gate_down),
.pwm (pwm));
assign pwm_clk3=pwm*2;
endmodule
先分别对clk1和clk2二分频,异或产生clk3,使用占空比测量模块,输出clk3的占空比,时间间隔对应的数字需要×2
三、signaltap波形
暂时用这个完成5kHz以上的测频率,5kHz以下使用另外的方法测,以免需要太大的时间
--------------------------------------分割线--------------------------------------
博客是写低频之前写的,后面写完低频,可以完成1Hz的检测,但是时间要略慢一些。
对低频信号的测量
思路:之前的测量无法测低频信号的原因是对低频信号计数5000个时间过长,计数后对基准时钟的计数值过大,使用64位二进制数有些浪费。通过同样的测量方法,对低频信号测8个周期对应的基准时钟计数值计算得到频率。
重新写了一个模块,使用了两个子模块,先算8个周期,测的频率高于5000就使用5000个周期得出的数据,低于5000,就直接输出这个频率
freq_cnt freq_cnt_H(
.CLK (CLK),
.clk_in (clk_in),
.clr (clr),
.gate_f0 (gate_H),
.gate_f0_down(gate_down_H),
.fx (fx_H),
.cnt_CLK (cnt_CLK_H));
defparam freq_cnt_L.CNTVAL_x=8;
freq_cnt freq_cnt_L(
.CLK (CLK),
.clk_in (clk_in),
.clr (clr),
.gate_f0 (gate_L),
.gate_f0_down(gate_down_L),
.fx (fx_L),
.cnt_CLK (cnt_CLK_L));
always @(posedge CLK or negedge clr)begin
if(!clr)
fx<=0;
else if(fx_L>5000)begin
fx<=fx_H;
gate<=gate_H;
gate_down<=gate_down_H;
cnt_CLK<=cnt_CLK_H;
end
else begin
fx<=fx_L;
gate<=gate_L;
gate_down<=gate_down_L;
cnt_CLK<=cnt_CLK_L;
end
end
endmodule
以下测了1Hz,12Hz,123Hz,1234Hz
两路波形是从信号发生器同相位输出,且因为周期比较长,略有时间差在周期内的占比也很低。
--------------------------------------分割线--------------------------------------
加了spi模块后完成了与单片机的通信
一、顶层设计
图一主要是频率计的部分
图二是spi通信部分的连接
RTL视图
二、spi通信总结
单片机输入有四个:sclk,cs,sdin,sdout
sdin是单片机串行输入,spi_bus_32b_A15RD1WR0模块移位成32位并行输出,低16位是数据,高16位是地址,在单片机读时,地址指向不同的功能,例如WE[7]是select_in_to_out模块的选择使能,单片机输入高16位0x00,0x07表示单片机要读取数据;
select_in_to_out模块的输入有待测信号频率的高16,低16,占空比的高16位,低16位,两路间隔时间的占空比高16位,低16位,,单片机输入的低16位进行选择,例如:0x00,0x00表示频率的高16位从FPGA输出到单片机。
FPGA输出是串行从sdout输出。