FPGA project : frequency_measure

module frequency_measure (
    input           wire                sys_clk     ,
    input           wire                sys_rst_n   ,
    input           wire                test_clk    ,

    output          reg     [19:00]     frequency   
);                                          // 输出信号,应该在sys_clk时钟域下
                                            // 频率,单位是 Khz 0Khz ~ 50_000Khz // 最高50Mhz
    parameter       TIME_250MS = 24'd12_500_000 ; // 0.25秒
    parameter       FS         = 27'd100_000_000 ; // 100Mhz  
    // 获取 X
    reg     [26:00]     cnt_gate_s ; // 1.25秒计时器,在sys_clk下。
    reg                 gate_s     ; // 1秒钟的闸门信号,在sys_clk下。
    reg                 gate_a     ; // 闸门信号的同步信号,在test_clk下。
    reg     [47:00]     cnt_test_clk ; // 对gate_a 计数,在test_clk下。 
    reg                 gate_a_reg_test ; // 对gate_a 打拍,在test_clk下。
    (* keep *) wire     test_clk_gate_nege ; // 闸门信号的下降沿检测,用于计数器的最终值采集。
    reg     [47:00]     cnt_test_clk_reg ; // 计数器的最终值采集.

    // 获取 Y
    wire                stand_clk ; // 100Mhz标准时钟,通过pll产生。
    wire                stand_locked ;
    reg     [26:00]     cnt_stand_clk_gate_a ; // 1秒种的闸门信号gate_a内,在100Mhz下的计数。
    reg                 stand_clk_gate_a_reg ; // 在stand_clk下,对gate_a打拍。
    (* keep *) wire     stand_clk_gate_nege ; // 闸门信号的下降沿检测,用于计数器的最终值采集。
    reg     [26:00]     cnt_stand_clk_reg ; // 对cnt_stand_clk_gate_a 最终值采样。

    // 计算标志
    reg                 calc_flag ; // test_clk_gate_nege == 1'b1 在 test_clk下
    reg     [47:00]     data_frequency_reg1 ;
    reg     [26:00]     data_frequency_reg2 ;

    // reg     [26:00]     cnt_gate_s ; // 1.25秒计时器,在sys_clk下。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_gate_s <= 27'd0 ;
        end else begin
            if(cnt_gate_s == TIME_250MS * 6 - 1'b1) begin
                cnt_gate_s <= 27'd0 ;  
            end else begin
                cnt_gate_s <= cnt_gate_s + 1'b1 ;
            end
        end
    end

    // reg                 gate_s     ; // 1秒钟的闸门信号,在sys_clk下。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            gate_s <= 1'b0 ;
        end else begin
            if(((cnt_gate_s >= 0) && (cnt_gate_s <= TIME_250MS - 1'b1)) || 
                    ((cnt_gate_s >= TIME_250MS * 5) && (cnt_gate_s <= TIME_250MS * 6 - 1'b1))) begin
                gate_s <= 1'b0 ;
            end else begin
                if((cnt_gate_s >= TIME_250MS) && (cnt_gate_s <= TIME_250MS * 5 - 1'b1)) begin
                    gate_s <= 1'b1 ;
                end else begin
                    gate_s <= gate_s ; 
                end
            end
        end
    end

    // reg                 gate_a     ; // 闸门信号的同步信号,在test_clk下。
    always @(posedge test_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            gate_a <= 1'b0 ;
        end else begin
            gate_a <= gate_s ;
            // if(gate_s == 1'b1) begin
            //     gate_a <= 1'b1 ;
            // end else begin
            //     gate_a <= 1'b0 ;
            // end
        end
    end
    // reg     [47:00]     cnt_test_clk ; // 对gate_a 计数,在test_clk下。
    always @(posedge test_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_test_clk <= 48'd0 ;
        end else begin
            if(gate_a == 1'b1) begin
                cnt_test_clk <= cnt_test_clk +1'b1 ;
            end else begin
                cnt_test_clk <= 26'd0 ;
            end
        end
    end
    // reg                 gate_a_reg_test ; // 对gate_a 打拍,在test_clk下。
    always @(posedge test_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            gate_a_reg_test <= 1'b0 ;
        end else begin
            gate_a_reg_test <= gate_a ;
        end
    end
    // wire                test_clk_gate_nege ; // 闸门信号的下降沿检测。
    assign test_clk_gate_nege = (gate_a == 1'b0 && gate_a_reg_test == 1'b1) ? 1'b1 : 1'b0 ;
    // reg     [47:00]     cnt_test_clk_reg ; // 计数器的最终值采集.
    always @(posedge test_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_test_clk_reg <= 48'd0 ;
        end else begin
            if(test_clk_gate_nege == 1'b1) begin
                cnt_test_clk_reg <= cnt_test_clk ;
            end else begin
                cnt_test_clk_reg <= cnt_test_clk_reg ;
            end
        end
    end

    // 产生标准时钟
    // wire                stand_clk ; // 100Mhz标准时钟,通过pll产生。    
    pll_100mhz	pll_100mhz_inst (
	.areset         ( ~sys_rst_n    ),
	.inclk0         ( sys_clk       ),
	.c0             ( stand_clk     ),
	.locked         ( stand_locked  ) 
	);

    // reg     [26:00]     cnt_stand_clk_gate_a ; // 1秒种的闸门信号gate_a内,在100Mhz下的计数。
    always @(posedge stand_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_stand_clk_gate_a <= 26'd0 ;
        end else begin
            if(gate_a == 1'b1) begin
                cnt_stand_clk_gate_a <= cnt_stand_clk_gate_a + 1'b1 ;
            end else begin
                cnt_stand_clk_gate_a <= 37'd0 ;
            end
        end
    end
    // reg                 stand_clk_gate_a_reg ; // 在stand_clk下,对gate_a打拍。
    always @(posedge stand_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            stand_clk_gate_a_reg <= 1'b0 ;
        end else begin
            stand_clk_gate_a_reg <= gate_a ;
        end
    end
    // wire                stand_clk_gate_nege ; // 闸门信号的下降沿检测。
    assign stand_clk_gate_nege = (gate_a == 1'b0) && (stand_clk_gate_a_reg == 1'b1) ? 1'b1 : 1'b0 ;
    // reg     [26:00]     cnt_stand_clk_reg ; // 对cnt_stand_clk_gate_a 最终值采样。
        always @(posedge stand_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_stand_clk_reg <= 26'd0 ;
        end else begin
            if(stand_clk_gate_nege == 1'b1) begin
                cnt_stand_clk_reg <= cnt_stand_clk_gate_a ;
            end else begin
                cnt_stand_clk_reg <= cnt_stand_clk_reg ;
            end
        end
    end

    // 计算标志
    // reg                 calc_flag ; // test_clk_gate_nege == 1'b1 在 test_clk下
    always @(posedge test_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            calc_flag <= 1'b0 ;
        end else begin
            if(test_clk_gate_nege == 1'b1) begin
                calc_flag <= 1'b1 ;
            end else begin
                calc_flag <= 1'b0 ; 
            end
        end
    end 

    // out signal
    // reg     [47:00]     data_frequency_reg1 ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            data_frequency_reg1 <= 48'd0 ;
        end else begin
            if(calc_flag == 1'b1) begin
                data_frequency_reg1 <= (cnt_test_clk_reg / 1000) ;
            end else  begin
                data_frequency_reg1 <= data_frequency_reg1 ;
            end
        end
    end
    // reg     [26:00]     data_frequency_reg2 ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            data_frequency_reg2 <= 48'd0 ;
        end else begin
            if(calc_flag == 1'b1) begin
                data_frequency_reg2 <= (FS / cnt_stand_clk_reg) ;
            end else  begin
                data_frequency_reg2 <= data_frequency_reg2 ;
            end
        end
    end
    reg  calc_flag_reg ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            calc_flag_reg <= 1'b0 ;
        end else begin
            calc_flag_reg <= calc_flag ;
        end
    end
    // [19:00]     frequency
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            frequency <= 20'd0 ;
        end else begin
            if(calc_flag_reg == 1'b1 && calc_flag == 1'b0) begin 
                frequency <= data_frequency_reg1 / data_frequency_reg2 ;
            end else  begin
                frequency <= frequency ;
            end
        end
    end
    // // [19:00]     frequency
    // always @(posedge sys_clk or negedge sys_rst_n) begin
    //     if(~sys_rst_n) begin
    //         frequency <= 20'd0 ;
    //     end else begin
    //         if(calc_flag == 1'b1) begin
    //             frequency <= (cnt_test_clk_reg / 1000 * FS / cnt_stand_clk_reg); 
    //             // frequency <= (cnt_test_clk_reg * FS ) / (cnt_stand_clk_reg * 1000) ; 会出错
    //         end else begin
    //             frequency <= frequency ;
    //         end
    //     end
    // end
endmodule

module top(
    input           wire            sys_clk     ,
    input           wire            sys_rst_n   ,
    input           wire            test_clk    ,

    output          wire            test_clk_out,
    output          wire            ds          ,
    output          wire            oe          ,
    output          wire            shcp        ,
    output          wire            stcp        
);

    // 例化间连线
    wire   [19:00]     frequency_w ;   
    wire                locked_sig ;
    wire    [05:00]     point      ;
    assign  point = 6'b001000      ;
    wire                sign       ;
    assign sign = 1'b0 ;
    wire                seg_en     ;
    assign seg_en = 1'b1 ;
    // frequency_measure
frequency_measure frequency_measure_insert     (
    .sys_clk                        ( sys_clk       ) ,
    .sys_rst_n                      ( sys_rst_n     ) ,
    .test_clk                       ( test_clk      ) ,

    .frequency                      ( frequency_w   )   
); 
    // 输出待测频率
pll_32mhz	pll_32mhz_inst (
	.areset     ( ~sys_rst_n     ) ,
	.inclk0     ( sys_clk        ) ,
	.c0         ( test_clk_out   ) ,
	.locked     ( locked_sig     )
	);
    // 数码管静态显示模块
seg_595_dynamic seg_595_dynamic_insert(
    .sys_clk                ( sys_clk     ) ,
    .sys_rst_n              ( sys_rst_n   ) ,
    .data                   ( frequency_w ) ,
    .point                  ( point       ) ,
    .sign                   ( sign        ) ,
    .seg_en                 ( seg_en      ) ,

    .ds                     ( ds          ) ,
    .oe                     ( oe          ) ,
    .shcp                   ( shcp        ) ,
    .stcp                   ( stcp        )    
);
endmodule

数码管模块,就是之前工程里的。

`timescale 1ns/1ns
module test_frequency_measure();
    reg                 sys_clk     ;
    reg                 sys_rst_n   ;
    wire                test_clk    ;
    wire                locked_sig  ;

    wire    [19:00]     frequency   ;

    defparam       frequency_measure_insert.TIME_250MS = 1250  ; // 0.25秒
    defparam       frequency_measure_insert.FS         = 1000000 ; // 100Mhz
// Instantiation
pll_32mhz	pll_32mhz_inst (
	.areset             ( ~sys_rst_n ),
	.inclk0             ( sys_clk    ),
	.c0                 ( test_clk   ),
	.locked             ( locked_sig )
	);


frequency_measure frequency_measure_insert(
    .sys_clk            ( sys_clk   ) ,
    .sys_rst_n          ( sys_rst_n ) ,
    .test_clk           ( test_clk  ) ,

    .frequency          ( frequency )  
);   
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        
        #( CYCLE * 1000 ) ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;


endmodule
`timescale 1ns/1ns
module test_top();

    reg             sys_clk     ;
    reg             sys_rst_n   ;
    wire            test_clk    ; // 有pll32mhz产生。

    wire            test_clk_out;
    wire            ds          ;
    wire            oe          ;
    wire            shcp        ;
    wire            stcp        ; 
	 wire  			  locked_sig  ;


    defparam       top_insert.frequency_measure_insert.TIME_250MS = 1250  ; // 0.25秒
    defparam       top_insert.frequency_measure_insert.FS         = 1000000 ; // 100Mhz
// Instantiation
pll_32mhz	pll_32mhz_inst_test (
	.areset             ( ~sys_rst_n ),
	.inclk0             ( sys_clk    ),
	.c0                 ( test_clk   ),
	.locked             ( locked_sig )
	);


top top_insert(
    .sys_clk            ( sys_clk      ) ,
    .sys_rst_n          ( sys_rst_n    ) ,
    .test_clk           ( test_clk     ) ,

    .test_clk_out       ( test_clk_out ) ,
    .ds                 ( ds           ) ,
    .oe                 ( oe           ) ,
    .shcp               ( shcp         ) ,
    .stcp               ( stcp         )        
); 
    parameter CYCLE = 20 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( 210 )          ;
        sys_rst_n <= 1'b0 ;
        #( 10 )           ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        
        #( CYCLE * 1000 ) ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;


endmodule

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值