zynq分频的例子

计数器奇数分频的问题

markdown 复制代码
i_clk= x HZ
o_clk_div 是 i_clk 的 n 分频

n个i_clk周期 对应  o_clk_div的一个周期
n=2k 时 ,o_clk_div 有k个高,k个低
n=2k+1 时,o_clk_div 有 k个高 或 k+1个高

简单计数分频仅适用偶分频 clock_div.v

verilog 复制代码
`timescale 1ns / 1ps
module clock_div#(
    parameter P_CLK_DIV_CNT = 2 //MAX = 65535
)(
    input    i_clk     ,
    input    i_rst_n     ,
    output   o_clk_div
    );
reg         ro_clk_div ;

reg  [15:0] r_cnt      ;
assign o_clk_div = ro_clk_div;

localparam L_COMPARE_CNT = P_CLK_DIV_CNT/2 - 1;

always @(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n)
        r_cnt <= 'd0;
    else if(r_cnt == L_COMPARE_CNT)
        r_cnt <= 'd0;
    else
        r_cnt <= r_cnt + 1;
end

always @(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n)
        ro_clk_div <= 'd0;
    else if(r_cnt == L_COMPARE_CNT)
        ro_clk_div <= ~ro_clk_div;
    else
        ro_clk_div <= ro_clk_div;
end

endmodule

双边补充 clk_div_50duty.v

verilog 复制代码
module clk_div_50duty #(
    parameter integer P_CLK_DIV_CNT = 3  // N ≥ 2
)(
    input  wire i_clk,       // 输入时钟
    input  wire i_rst_n,       // 同步复位,高有效
    output wire o_clk_div    // 输出分频时钟,占空比约 50%
);

    // ----------------------------------------
    // 判定奇偶
    // ----------------------------------------
    localparam L_IS_ODD   = P_CLK_DIV_CNT[0];           // 奇数为 1,偶数为 0
    localparam L_HALF_CNT = (P_CLK_DIV_CNT >> 1);       // N/2,用于偶数情况

    // ----------------------------------------
    // 偶数分频逻辑
    // ----------------------------------------
    reg [$clog2(P_CLK_DIV_CNT):0] r_cnt_even = 0;
    reg                           r_clk_even = 0;

    always @(posedge i_clk) begin
        if (!i_rst_n) begin
            r_cnt_even <= 0;
            r_clk_even <= 0;
        end else if (!L_IS_ODD) begin
            if (r_cnt_even == L_HALF_CNT - 1) begin
                r_cnt_even <= 0;
                r_clk_even <= ~r_clk_even;
            end else begin
                r_cnt_even <= r_cnt_even + 1;
            end
        end
    end

    // ----------------------------------------
    // 奇数分频逻辑(双沿互补法)
    // ----------------------------------------
    reg [$clog2(P_CLK_DIV_CNT):0] r_cnt_odd = 0;
    reg r_clk1 = 1, r_clk2 = 1;

    // 上升沿:clk1
    always @(posedge i_clk) begin
        if (!i_rst_n) begin
            r_cnt_odd <= 0;
            r_clk1    <= 1;
        end else if (L_IS_ODD) begin
            if (r_cnt_odd == P_CLK_DIV_CNT - 1)
                r_cnt_odd <= 0;
            else
                r_cnt_odd <= r_cnt_odd + 1;

            if (r_cnt_odd == (P_CLK_DIV_CNT >> 1))
                r_clk1 <= 0;
            else if (r_cnt_odd == P_CLK_DIV_CNT - 1)
                r_clk1 <= 1;
        end
    end

    // 下降沿:clk2
    always @(negedge i_clk) begin
        if (!i_rst_n)
            r_clk2 <= 1;
        else if (L_IS_ODD) begin
            if (r_cnt_odd == (P_CLK_DIV_CNT >> 1))
                r_clk2 <= 0;
            else if (r_cnt_odd == P_CLK_DIV_CNT - 1)
                r_clk2 <= 1;
        end
    end

    // ----------------------------------------
    // 输出选择
    // ----------------------------------------
    assign o_clk_div = (L_IS_ODD) ? (r_clk1 & r_clk2) : r_clk_even;

endmodule

tb.v

verilog 复制代码
`timescale 1ns / 1ps

module tb;

    // ---------------------------------
    // 参数:分频系数
    // 可尝试 3(奇数),4(偶数),5(奇数)等
    // ---------------------------------
    parameter P_CLK_DIV_CNT = 2;

    // ---------------------------------
    // 信号声明
    // ---------------------------------
    reg  i_clk;
    reg  i_rstn;
    wire o_clk_div;

    // ---------------------------------
    // 实例化被测模块
    // ---------------------------------
    clk_div_50duty #(
        .P_CLK_DIV_CNT(P_CLK_DIV_CNT)
    ) dut (
        .i_clk     (!i_clk),
        .i_rst_n     (i_rstn),
        .o_clk_div (o_clk_div)
    );

    // ---------------------------------
    // 生成时钟:50MHz (周期 = 20ns)
    // ---------------------------------
    initial i_clk = 0;
    always #10 i_clk = ~i_clk;

    // ---------------------------------
    // 复位过程
    // ---------------------------------
    initial begin
        i_rst_n = 0;
        #100;           // 保持复位 100ns
        i_rst_n = 1;
    end

    // ---------------------------------
    // 仿真时间控制
    // ---------------------------------
    initial begin
        $display("===== Start clk_div_50duty simulation (N = %0d) =====", P_CLK_DIV_CNT);
        #2000;          // 仿真 2000ns
        $display("===== End clk_div_50duty simulation =====");
        $stop;
    end

endmodule
相关推荐
9527华安1 小时前
国产安路FPGA开发设计培训课程,提供开发板+工程源码+视频教程+技术支持
fpga开发·fpga·安路·视频教程·培训·安路fpga
UVM_ERROR8 小时前
硬件设计实战:解决Valid单拍采样失效问题(附非阻塞赋值与时序对齐核心要点)
驱动开发·fpga开发·github·芯片
brave and determined9 小时前
可编程逻辑器件学习(day36):从沙粒到智能核心:芯片设计、制造与封装的万字全景解析
fpga开发·制造·verilog·fpga·芯片设计·硬件设计·芯片制造
步达硬件1 天前
【FPGA】FPGA开发流程
fpga开发
我爱C编程1 天前
【仿真测试】基于FPGA的完整16QAM通信链路实现,含频偏锁定,帧同步,定时点,Viterbi译码,信道,误码统计
fpga开发·16qam·帧同步·卷积编码·viterbi译码·维特比译码·频偏锁定
s09071362 天前
ZYNQ DMA to UDP 数据传输系统设计文档
网络协议·fpga开发·udp
燎原星火*2 天前
QSPI IP核 基本参数
fpga开发
XINVRY-FPGA2 天前
XCVU9P-2FLGC2104I Xilinx AMD Virtex UltraScale+ FPGA
嵌入式硬件·机器学习·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
FPGA_小田老师2 天前
FPGA Debug:PCIE一直自动重启(link up一直高低切换)
fpga开发·pcie debug·pcie初始化问题
hexiaoyan8272 天前
视频信号检测板卡:208-Base Camera Link 图像信号模拟器
fpga开发·图像信号模拟器·视频信号检测·视频信号分析·智能图像分析