时钟分频器

文章目录

一、8分频

8倍时钟分频器是一种电路或设备,用于将输入时钟信号的频率分成原来的1/8。它可以在数字电子系统中用于将高频时钟信号降低到较低的频率,以满足特定的系统需求。

在这个电路中,CLK是输入的时钟信号,CLK_OUT是输出的时钟信号。通过适当的电路设计,8倍时钟分频器将输入时钟信号的频率除以8,得到的输出时钟信号频率为输入时钟频率的1/8。

具体实现时,可以使用计数器、分频器、频率除法等技术来设计8倍时钟分频器。常见的方法是通过基于触发器(如D触发器)的计数器电路实现分频功能。每经过8个输入时钟脉冲,计数器输出一个脉冲,从而生成1/8倍的输出时钟信号。
8分频时钟设计:时钟周期为160ns,及计数4次对信号进行反转。
代码实现:

verilog 复制代码
/*
 * @Description: 8分频
 * @Author: Fu Yu
 * @Date: 2023-07-21 15:00:40
 * @LastEditTime: 2023-07-21 15:23:59
 * @LastEditors: Fu Yu
 */


module time_clk (
    input       wire        clk         ,
    input       wire        rst_n       ,
    output      wire        clk_4   
);

parameter MAX_NUM = 2'd3;//计数最大值4

reg [1:0] cnt;
reg clk_4_r;

wire add_cnt;//开始计数信号
wire end_cnt;//结束计数信号

//计数器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin//初始化
        cnt <= 2'd0;
    end
    else if(add_cnt) begin
        if(end_cnt) begin//计满4个周期,计数器清零
            cnt <= 2'd0;
        end
        else begin
            cnt <= cnt + 1'd1;
        end
    end
    else begin
        cnt <= cnt;
    end
end

assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt == MAX_NUM;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin//初始化
        clk_4_r <= 1'b1;
    end
    else if(end_cnt) begin//计满四次输出信号进行一次反转
        clk_4_r <= ~clk_4_r;
    end
    else begin
        clk_4_r <= clk_4_r;
    end
end

assign clk_4 = clk_4_r;


endmodule //time_clk

测试文件:

verilog 复制代码
/*
 * @Description: 8分频仿真验证
 * @Author: Fu Yu
 * @Date: 2023-07-21 15:38:35
 * @LastEditTime: 2023-07-21 15:49:01
 * @LastEditors: Fu Yu
 */

`timescale 1ns/1ns
module time_clk_tb();
    //激励信号定义
    reg tb_clk;
    reg tb_rst_n;
 
    //输出信号定义
    wire tb_clk_4;

    parameter CYCLE = 20;

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

    initial begin
        tb_clk = 0;
        tb_rst_n = 0;//开始复位
        #(CYCLE/2);
        tb_rst_n = 1;//结束复位
        #(CYCLE*16);
        $stop;
    end

    time_clk u_time_clk(
    .        clk      (tb_clk)   ,
    .        rst_n    (tb_rst_n)   ,
    .        clk_4     (tb_clk_4)
);

 endmodule

二、n倍时钟分频器

代码实现:

verilog 复制代码
/*
 * @Description: 设计一个可配置的时钟分频器模块,能够将输入时钟信号按照给定的任意分频比例进行分频,并输出分频后的时钟信号。
 * @Author: Fu Yu
 * @Date: 2023-07-22 10:11:22
 * @LastEditTime: 2023-07-22 10:23:12
 * @LastEditors: Fu Yu
 */

module CLOCK_N #(parameter N = 8)(
    input       wire        clk         ,//时钟输入
    input       wire        rst_n       ,//复位信号

    output      wire        clk_n        //分频后的信号输出
);

reg  [N:0]  cnt;//用于记数
reg  clk_n_r;//存储当前分频信号的值

wire add_cnt;//开始计数信号
wire end_cnt;//结束计数信号

//计数器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt <= 26'd0;
    end
    else if(add_cnt)begin
        if(end_cnt)begin
            cnt <= 26'd0;
        end
        else begin
            cnt <= cnt + 1'd1;
        end
    end
    else begin
        cnt <= cnt;
    end
end

assign add_cnt = 1'b1;
assign end_cnt = add_cnt && (cnt == (N-1)/2);//记数到半个时钟周期

//时钟分频
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        clk_n_r <= 1'b1;
    end
    else if(end_cnt) begin//每到半个时钟周期,将分频信号进行反转
        clk_n_r <= ~clk_n_r;
    end
    else begin
        clk_n_r <= clk_n_r;
    end
end

assign clk_n = clk_n_r;

endmodule

测试文件:

verilog 复制代码
/*
 * @Description: n倍分频器仿真测试文件
 * @Author: Fu Yu
 * @Date: 2023-07-22 10:24:59
 * @LastEditTime: 2023-07-22 10:43:28
 * @LastEditors: Fu Yu
 */

`timescale 1ns/1ns
module clock_n_tb();
    
    parameter CYCLE = 20;//定义时钟周期
    parameter N = 10;//任意分频倍数

    //定义激励信号
    reg tb_clk;
    reg tb_rst_n;

    //定义输出信号
    wire tb_clk_n;

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

    initial begin
        tb_clk = 0;
        tb_rst_n = 0;//开始复位
        #(CYCLE/2);
        tb_rst_n = 1;//结束复位
        #(CYCLE*20);
        $stop;
    end

    //实例化
    CLOCK_N #(.N(N)) u_CLOCK_N(
        .   clk     (tb_clk)    ,
        .   rst_n   (tb_rst_n)  ,

        .   clk_n   (tb_clk_n)

    );



endmodule


改进:

博主发现以上方法对偶数倍分频效果很好,但对奇数倍分频效果很差,所以博主对n倍分频器做了以下改动:

verilog 复制代码
/*
 * @Description: 设计一个可配置的时钟分频器模块,能够将输入时钟信号按照给定的任意分频比例进行分频,
                并输出分频后的时钟信号。奇偶倍数均可实现
 * @Author: Fu Yu
 * @Date: 2023-07-24 16:49:26
 * @LastEditTime: 2023-07-24 19:51:02
 * @LastEditors: Fu Yu
 */

 module divede_clk #(parameter N = 8)(
    input       wire            clk         ,//系统时钟
    input       wire            rst_n       ,//复位信号

    output      wire            clk_out      //分频后的信号 
 );

 reg [N:0] cnt_pos;//检测时钟上升沿计数
 reg [N:0] cnt_neg;//检测时钟下降沿计数

 reg clk1;
 reg clk2;

 wire add_cnt_pos;//开始计数标志
 wire end_cnt_pos;//结束计数标志
 wire add_cnt_neg;//开始计数标志
 wire end_cnt_neg;//结束计数标志

 //时钟上升沿计数器
 always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_pos <= 'd0;
    end
    else if(add_cnt_pos) begin
        if(end_cnt_pos) begin
            cnt_pos <= 'd0;
        end
        else begin
            cnt_pos <= cnt_pos + 1'd1;
        end
    end
    else begin
        cnt_pos <= cnt_pos;
    end
 end

assign add_cnt_pos = 1'b1;
assign end_cnt_pos = add_cnt_pos && cnt_pos == (N - 1);

//对clk1进行赋值
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        clk1 <= 1'b0;
    end
    else if(cnt_pos <= (N-1)/2) begin
        clk1 <= 1'b1;
    end
    else begin
        clk1 <= 1'b0;
    end
end

//时钟下降沿计数器
 always @(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_neg <= 'd0;
    end
    else if(add_cnt_neg) begin
        if(end_cnt_neg) begin
            cnt_neg <= 'd0;
        end
        else begin
            cnt_neg <= cnt_neg + 1'd1;
        end
    end
    else begin
        cnt_neg <= cnt_neg;
    end
 end

assign add_cnt_neg = 1'b1;
assign end_cnt_neg = add_cnt_neg && cnt_neg == (N - 1);

//对clk1进行赋值
always @(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        clk2 <= 1'b0;
    end
    else if(cnt_neg <= N/2) begin
        clk2 <= 1'b1;
    end
    else begin
        clk2 <= 1'b0;
    end
end

assign clk_out = (N == 1) ? clk : N[0] ? (clk1&clk2) : clk1;
 
 endmodule //divede_clk

此次改动后奇数倍和偶数倍的分频器都能实现,用两个信号一个对于时钟上升沿检测,一个对于时钟下降沿检测。

相关推荐
DS小龙哥42 分钟前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师10 小时前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战11 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩1 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技1 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪1 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望1 天前
EDA技术简介
fpga开发
淘晶驰AK1 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发
最好有梦想~1 天前
FPGA时序分析和约束学习笔记(4、IO传输模型)
笔记·学习·fpga开发