Verilog频率计设计

数字频率计的基本设计思路是在给定一个time开始测量的时候产生的T的个数,也就是采用一个标准的基准时钟,在单位时间(1秒)里对被测信号的脉冲数进行计数。测频法包括直接测频法、等精度频率测量法、周期法等。

    数字频率计的原理如图6-1所示。对系统时钟的信号分频后产生1Hz的输出频率被作为控制模块的时钟输入,由控制模块产生的计数使能信号和清零信号对计数模块进行控制,而由其产生的锁存信号load对锁存模块进行控制,一旦计数使能信号为高电平,并且时钟上升沿到来,计数器便开始正常计数,清零信号到来则计数清零,而当锁存信号为高电平时,数据便被锁存器锁存,然后将锁存的数据输出到显示模块显示出来,数据锁存保证系统可以稳定显示数据,显示译码驱动电路将二进制表示的计数结果转换成相应的能够在数码显示管上可以显示的十进制结果。

(1)分频器模块

    分频器模块将对系统时钟进行分频,输出1Hz赫兹的信号,作为测频控制模块的输入信号。例如,假设系统时钟为1024Hz,则对其进行2的10次方分频即可得到1Hz的分频输出信号。

(2)测频控制模块

    测频控制模块的输出包括计数器的使能端,清零端以及数据锁存器的锁存信号。分别控制计数器的计数和清零。当锁存信号为高电平时,计数器的计数结果被锁存并输出到显示模块显示。

 View Code

   该模块的仿真结果可参考图6-2。

(3)计数器模块

    计数器是完成计数步骤的一个单元。它也可用与分频、定时、产生节拍脉冲和脉冲序列等。本设计中为了可以使计数器正常工作,必须只有当使能端为1的时候才开始计数,每个时钟的上升沿到来时计数器加1,当累加到10的时候就清零,同时产生进位信号,同时计数器也应带有清零信号,一旦清零信号有效时,计数器立即清零。

(4)锁存器模块

    锁存,就是把信号暂存以维持某种电平状态。测量模块的工作任务成功后,在load信号的上升沿到来时把测量值存入reg当中,之后发送到显示模块当中。锁存器主要是为了保护数据,使其在下次触发或者复位时仍然有效。

(5)显示模块

    LED显示器在许多的数字系统中作为显示输出设备,使用非常广泛。它内部有七个发光的a、b、d、e、f和g二极管。通过点亮不同的LED字段,可显示数字0,1,┅,9和A,b,C,d,E,F等不同的字符及自定义一些段发光代表简单符号。

(6)顶层模块

       按照图一所示的数字频率计的框图,调用各单元模块,完成数字频率计的顶层设计,并进行仿真,实现频率测量。

 练习

(1)分频器模块

1 module fre_div (clk, clk_out);
2 input clk;
3 output clk_out;
4 reg [8:0] counter;
5 reg clk_out;
6 parameter N = 1000; //改变N的值变成任意偶分频,同时counter的范围需要相应修改
7
8 always @ (posedge clk)
9 begin
10 if (counter == N/2 - 1) //偶分频数一半时反相
11 begin
12 clk_out <= ~clk_out;
13 counter <= 0; //置0,从0计数
14 end
15 else
16 counter <= counter + 1;
17 end
18 endmodule

(2)测频控制模块1 module testctl (clk_out_ctl, tsten, rst_ctl, load);
2 input clk_out_ctl;
3 output tsten, rst_ctl, load;
4 reg rst_ctl, div2;
5 always @(posedge clk_out_ctl) begin
6 div2 = ~div2;
7 end
8 always @(clk_out_ctl or div2) begin
9 if (clk_out_ctl == 0 && div2 == 0) begin
10 rst_ctl = 1;
11 end
12 else
13 begin
14 rst_ctl = 0;
15 end
16 end
17 assign load = ~div2;
18 assign tsten = div2;
19 endmodule

(3)计数器模块(改正在注释里

1 module counter (enable,clk_t,rst_count,dout,cout);
2 input enable,clk_t,rst_count;
3 output [15:0] dout;
4 output cout;
5 reg cout;
6 reg [15:0] dout;
7 always @(posedge clk_t) begin//有问题,always @(posedge clk_t or posedge rst_count) //异步复位
8 if (!rst_count) begin// if (rst_count) begin dout = 16'd0; cout = 1'b0; end //先写复位,首先考虑复位信号
9 if (enable) begin// else begin
10 if(dout == 65535) begin // if (enable) begin
11 dout = 16'd0; // if(dout == 65535) begin dout = 16'd0; cout = 1'b1; end
12 cout = 1'b1; // else dout = dout + 16'd1;
13 end // end
14 else begin // end
15 dout = dout + 16'd1;
16 end
17 end
18 end
19 else begin
20 dout = 16'd0;
21 cout = 1'b0;
22 end
23 end
24 endmodule
25
26
27

 (4)锁存器模块

 1 module latch_out (in_dout, save_dout, load_in);
 2     input load_in;
 3     input [15:0] in_dout;
 4     output [15:0] save_dout;
 5     reg [15:0] reg_in;
 6     wire [15:0] save_dout;
 7     always @(load_in)
 8     if (load_in)    
 9     reg_in = in_dout;
10     assign save_dout = reg_in;
11 endmodule

(5)显示模块

  【1】二进制转BCD码模块(参考

 1 module bin_bcd_cp (bin, wan, qian, bai, shi, ge, bcd); 
 2     input [15:0] bin;
 3     output [31:0] bcd;
 4     output reg [3:0] wan;
 5     output reg [3:0] qian;
 6     output reg [3:0] bai;
 7     output reg [3:0] shi;
 8     output reg [3:0] ge;
 9     integer i;
10     always @(bin) begin
11         wan = 4'd0;
12         qian = 4'd0;
13         bai = 4'd0;
14         shi = 4'd0;
15         ge = 4'd0;
16         for (i = 15; i >= 0; i = i - 1) begin
17             if (wan > 4) wan = wan + 3;
18             if (qian > 4) qian = qian + 3;
19             if (bai > 4) bai = bai + 3;
20             if (shi > 4) shi = shi + 3;
21             if (ge > 4) ge = ge + 3;
22             
23             wan = wan << 1;
24             wan[0] = qian[3];
25             qian = qian << 1;
26             qian[0] = bai[3];
27             bai = bai << 1;
28             bai[0] = shi[3];
29             shi = shi << 1;
30             shi[0] = ge[3];
31             ge = ge << 1;
32             ge[0] = bin[i];
33         end
34     end
35     assign bcd = {{12{1'b0}}, wan, qian, bai, shi, ge};
36 endmodule

  【2】八段显示数码管

module seg7 (data_in, data_out );
    input [3:0] data_in ;
    output [7:0] data_out ;
    reg [7:0] data_out ;
    always @(data_in) begin
        data_out = 7'b1111111;
            case (data_in )
            4'b0000: data_out = 8'b1100_0000; // 0
            4'b0001: data_out = 8'b1111_1001; // 1
            4'b0010: data_out = 8'b1010_0100; // 2
            4'b0011: data_out = 8'b1011_0000; // 3
            4'b0100: data_out = 8'b1001_1001; // 4
            4'b0101: data_out = 8'b1001_0010; // 5
            4'b0110: data_out = 8'b1000_0011; // 6
            4'b0111: data_out = 8'b1111_1000; // 7
            4'b1000: data_out = 8'b1000_0000; // 8
            4'b1001: data_out = 8'b1001_1000; // 9
            4'b1010: data_out = 8'b1000_1000; // A
            4'b1011: data_out = 8'b1000_0011; // b
            4'b1100: data_out = 8'b1010_0111; // c
            4'b1101: data_out = 8'b1010_0001; // d
            4'b1110: data_out = 8'b1000_0110; // E
            4'b1111: data_out = 8'b1000_1110; // F
            default: data_out = 8'b1111_1111;
            endcase
    end
endmodule

(6)顶层模块

    把各个模块生成symbol,通过创建 block diagram/schematic file 手动连线生成。

RTL:

仿真波形:

注:各个小模块的仿真测试都要一个一个做(在此我省略了)

猜你喜欢

转载自blog.csdn.net/l471094842/article/details/91889169