我是靠谱客的博主 欢喜大米,最近开发中收集的这篇文章主要介绍verilog实现分频器总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、偶数分频

偶数分频可以通过计数器或者D触发器级联方式实现,使用计数器进行N倍(偶数)分频时,当计数器计数到(N-1)/2时进行反转一次。

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_cnt<=4'd0;
    else if(clk_cnt==(N/2-1))
        clk_cnt<=4'd0;
    else
        clk_cnt<=clk_cnt+1'b1;

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_div<=1'b0;
    else if(clk_cnt==(N/2-1))
        clk_div<=~clk_div;

D触发器级联

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_div <= 1'b0;
    else 
        clk_div <= ~clk_div;

always@(posedge clk_div or negedge rst_n)
    if(~rst_n)
        clk_div_r <= 1'b0;
    else 
        clk_div_r <= ~clk_div_r;

二、奇数分频

占空比不为50%的奇数分频可以通过奇数和moor状态机来实现,使用计数器进行N倍(奇数)分频时,当计数器计数到N/2-1和o时各进行一次反转。

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_cnt<=4'd0;
    else if(clk_cnt==(N-1))
        clk_cnt<=4'd0;
    else
        clk_cnt<=clk_cnt+1'b1;

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_div<=1'b0;
    else if(clk_cnt==(N-1)/2)
        clk_div<=~clk_div;
    else if(clk_cnt==4'd0)
        clk_div<=~clk_div;

占空比为50%的奇数分频,需要通过上升沿计数器、下降沿计数器各产生一个分频信号,将两个信号进行相与便可以得到占空比为50%的奇数分频。

reg clk_n,clk_p;
always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_cnt<=4'd0;
    else if(clk_cnt==(N-1))
        clk_cnt<=4'd0;
    else
        clk_cnt<=clk_cnt+1'b1;

always@(negedge clk or negedge rst_n)
    if(~rst_n)
        clk_cnt_n<=4'd0;
    else if(clk_cnt_n==(N-1))
        clk_cnt_n<=4'd0;
    else
        clk_cnt_n<=clk_cnt_n+1'b1;

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_p<=1'b0;
    else if(clk_cnt==(N-1)/2)
        clk_p<=~clk_p;
    else if(clk_cnt==4'd0)
        clk_p<=~clk_p;

always@(negedge clk or negedge rst_n)
    if(~rst_n)
        clk_n<=1'b0;
    else if(clk_cnt_n==(N-1)/2)
        clk_n<=~clk_n;
    else if(clk_cnt_n==4'd0)
        clk_n<=~clk_n;

assign clk_div = clk_n|clk_p;

状态机实现

localparam  s0 = 7'b000_0001,
            s1 = 7'b000_0010,
            s2 = 7'b000_0100,
            s3 = 7'b000_1000,
            s4 = 7'b001_0000,
            s5 = 7'b010_0000,
            s6 = 7'b100_0000;
reg [6:0] state,next_state;
always@(posedge clk or negedge rst_n)
    if(~rst_n)
        state<=s0;
    else
        state<=next_state;

always@(*)
    case(state)
        s0:next_state = s1;
        s1:next_state = s2;
        s2:next_state = s3;
        s3:next_state = s4;
        s4:next_state = s5;
        s5:next_state = s6;
        s6:next_state = s0;
        default:next_state = s0;
    endcase

always@(posedge clk or negedge rst_n)
    if(~rst_n)
        clk_div<=1'b0;
    else
        case(next_state)
            s0:clk_div <= 1'b0;
            s1:clk_div <= 1'b0;
            s2:clk_div <= 1'b0;
            s3:clk_div <= 1'b1;
            s4:clk_div <= 1'b1;
            s5:clk_div <= 1'b1;
            s6:clk_div <= 1'b1;
            default:clk_div <= 1'b0;
        endcase

三、小数分频

输入频率f_in、输出频率f_out,计数器位宽N、计数器步长M之间存在f_in/f_out=(2^N)/M的关系,以M为计数步长进行计数,当计数值大于等于(2^N)/2时为高电平否则为低电平。

always@(posedge clk or negedge rst_n)   
 if(~rst_n)
        clk_cnt <= 'h0;
 else if(&clk_cnt)
        clk_cnt <= 'h0;
 else
        clk_cnt <= clk_cnt+32'haaaa_aaaa;

always@(posedge clk or negedge rst_n)   
 if(~rst_n)
        clk_div <= 1'b0;
 else if(clk_cnt>=32'h7fff_ffff)
        clk_div<=1'b1;
 else
        clk_div<=1'b0;

最后

以上就是欢喜大米为你收集整理的verilog实现分频器总结的全部内容,希望文章能够帮你解决verilog实现分频器总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部