FPGA学习系列:34. 频率计的设计

描述

设计背景:

频率计又称为频率计数器,是一种专门对被测信号频率进行测量的电子测量仪器。频率计主要由四个部分构成:时基(T)电路、输入电路、计数显示电路以及控制电路。

频率,即使信号周期的倒数,也就是说,信号每单位时间完成周期的个数,一般去一秒为基本单位时间。

 

设计原理: 

 

本次的设计主要是一个简单的二选一数据选择器,我们的设计主

频率=1s/T,T=高电平的时间+低电平的时间。时间=周期数*周期。占空比=(高电平的时间/周期)100%。我们的时间单位都是以ns来计算的,所以要把1s换成1_000_000_000ns,驱动时钟是50MHz的,周期为20ns。计算占空比的时候,我们把周期20ns全部省略了。所以计算公式如下:

freq = 1_000_000_000/(low_time * 20 + high_time * 20);

duty_cycle = (high_time * 100)/(high_time + low_time);

设计架构图:

FPGA


设计代码:

设计模块

0 module freq_meter (clk, rst_n, wave, freq, duty_cycle);  //端口列表

1 

2  input clk;                   //时钟

3  input rst_n;                 //复位

4  input wave;                  //被测频率

5  output [25:0] freq;          //输出频率

6  output [6:0] duty_cycle;  //输出占空比

7 

8  reg [25:0] low_cnt;

9  reg [25:0] high_cnt;

10 reg [25:0] low_time;

11 reg [25:0] high_time;

12 reg state;

13

14 localparam high_state = 1'b0;

15 localparam low_state = 1'b1;

16

17 always @ (posedge clk or negedge rst_n)

18  begin

19   if (!rst_n)

20    begin

21    low_cnt <= 26'd0;

22    high_cnt <= 26'd0;

23    low_time <= 26'd0;

24    high_time <= 26'd0;

25    state <= high_state;

26    end

27   else

28   begin

29    case (state)

30     high_state : begin

31       if (wave == 1'b1)       //判断输入为高电平

32        begin

33         high_cnt <= high_cnt + 1'b1;

34         state <= high_state;

35        end

36       else

37        begin

38         high_cnt <= 26'd0;

39         high_time <= high_cnt;

40         state <= low_state;

41        end

42      end

43      

44     low_state : begin

45       if (wave == 1'b0)  //判断输入为低电平

46        begin

47         low_cnt <= low_cnt + 1'b1;

48         state <= low_state;

49        end

50       else

51        begin

52         low_cnt <= 26'd0;

53         low_time <= low_cnt;

54         state <= high_state;

55        end

56      end

57     default : state <= low_state;

58     endcase

59   end

60  end

61  

62 assign freq = 1_000_000_000/(low_time * 20 + high_time * 20);  //求频率

63  assign duty_cycle = (high_time * 100)/(high_time + low_time);  //求占空比

64

65 endmodule

 

测试模块

0 `timescale 1ns/1ps

1 module freq_meter_tb;

2  reg clk;

3  reg rst_n;

4  reg wave;

5  wire [25:0] freq;

6  wire [6:0] duty_cycle;

7 

8  initial begin

9   clk = 1'b1;

10  rst_n = 1'b0;

11  

12  # 200.1

13   rst_n = 1'b1;

14  # 1_000_000_0//仿真10ms

15   $stop;

16 end

17

18 always # 10 clk = ~clk;

19

20 initial begin

21  wave = 1'b1;

22  forever begin//产生占空比为60%,频率为1KHz的方波

23   # 600_000

24    wave = 1'b0;

25   # 400_000

26    wave = 1'b1;

27  end

28 end

29

30 freq_meter freq_meter_dut(

31  .clk(clk),

32  .rst_n(rst_n),

33  .wave(wave),

34  .freq(freq),

35  .duty_cycle(duty_cycle)

36 );

37

38 endmodule 

 

 

仿真图:


由于在前面没有测完一个周期出现了不稳定的因素,就出现了不准确的数值,当测试完一个周期以后,测到的数值就比较的准确,基本的没有什么误差。

相对的,如果测试的频率越大,测到的数值就越准确。


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分