牛客网分频原理

1、Verilog刷题进阶版VL13时钟分频偶数

描述

请使用D触发器设计一个同时输出2/4/8分频的50%占空比的时钟分频器

注意rst为低电平复位

波形示意图:

`timescale 1ns/1ns

module even_div
    (
    input     wire rst ,
    input     wire clk_in,
    output    wire clk_out2,
    output    wire clk_out4,
    output    wire clk_out8
    );
//*************code***********//
    reg [2:0] cnt8;
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                cnt8<=3'b000;
            else
                cnt8<=cnt8-3'd1;//注意这里用减法,为了满足题目的时序图,248同时拉高
        end
    assign clk_out2=(cnt8[0]==1'b1)?1:0;
    assign clk_out4=(cnt8[1]==1'b1)?1:0;
    assign clk_out8=(cnt8[2]==1'b1)?1:0;

//*************code***********//
endmodule

2、Verilog刷题进阶版VL18无占空比要求的奇数分频

描述

请设计一个同时输出5分频的时钟分频器,本题对占空比没有要求

注意rst为低电平复位

波形示意图:
 

1)由波形图可以看出每隔5个clk,clk_out5出现一次上升沿

2)其中clk_out5中间的一次由高到低的跳变,题目没有要求,随时可以跳变,题目中 的跳变方式占空比为50%

`timescale 1ns/1ns

module odd_div (    
    input     wire rst ,
    input     wire clk_in,
    output    wire clk_out5
);
//*************code***********//
    parameter N=5;
    
    reg [2:0] cnt;
    reg       clk_n;
    
    //cnt在0,1,2,3,4之间循环
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                cnt<=3'b000;
            else if(cnt==N-1)
                cnt<=3'b000;
            else
                cnt<=cnt+1'b1;
        end
    
    //clk_out5下降沿的位置,第二个时钟周期时从高到低跳变
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                clk_n<=1'b0;
            else if(cnt==(N-1)/2)
                clk_n<=~clk_n;
            else if(cnt<=3'b000)
                clk_n<=~clk_n;
            else
                clk_n<=clk_n;
        end
    
    assign clk_out5=clk_n;


//*************code***********//
endmodule

3、Verilog刷题进阶版VL16占空比为50%的奇数分频

描述

设计一个同时输出7分频的时钟分频器,占空比要求为50%

注意rst为低电平复位

波形示意图:

由波形图可以看出,clk_out7是在clk的下降沿拉高的,在clk的上升拉低

`timescale 1ns/1ns

module odo_div_or
   (
    input    wire  rst ,
    input    wire  clk_in,
    output   wire  clk_out7
    );

//*************code***********//
    parameter N=7;
    
    reg [3:0] cnt;
    
    //分频计数:0,1,2,3,4,5,6
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                cnt<=4'b0000;
            else if(cnt==N-1)
                cnt<=4'b0000;
            else
                cnt<=cnt+1'b1;
        end
    
    //clk上升沿驱动的分频
    reg clkp;
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                clkp<=1'b0;
            else if(cnt==(N>>1))//N右移一位,相当于除以2,结果为3;从3~6中间有3个时钟周期为高电频
                clkp<=1;
            else if(cnt==N-1)
                clkp<=0;
            else
                clkp<=clkp;
        end
    
    //clk下降沿驱动的分频
    reg clkn;
    always@(negedge clk_in or negedge rst)
        begin
            if(!rst)
                clkn<=1'b0;
            else if(cnt==(N>>1))
                clkn<=1;
            else if(cnt==N-1)
                clkn<=0;
            else
                clkn<=clkn;
        end
    
    assign clk_out7=clkp|clkn;


//*************code***********//
endmodule

4、Verilog刷题进阶版VL17任意小数分频

描述

请设计一个可以实现任意小数分频的时钟分频器,比如说8.7分频的时钟信号

注意rst为低电平复位

波形示意图:

1)N=7,意味着在87个clk_in时钟周期里面,clk_out要翻转10次,即87个输入上升沿对应10个输出上升沿

87=10*8.7           //这10个输出上升沿,我们允许它们有些差别

87=9*9+1*6;   //前9个输出的周期 ,每个周期占9个输入,最后一个输出周期占6个输入时钟

87=8*9+2*7.5

87=7*9+3*8     //前7个输出周期,每个周期占9个输入,最后三个输出周期,每个周期占8个输入时钟

... ...

2)一个周期包含一个高电平加一个低电平,即两个上升沿之间的时间

3)选择87=7*9+3*8 ;3个8分频,7个9分频

`timescale 1ns/1ns

module div_M_N(
 input  wire clk_in,
 input  wire rst,
 output wire clk_out
);
parameter M_N = 8'd87; 
parameter c89 = 8'd24; // 8/9时钟切换点
parameter div_e = 5'd8; //偶数周期
parameter div_o = 5'd9; //奇数周期
//*************code***********//
    reg [6:0] cnt;    //总计数器
    reg [3:0] cnt_e;  //偶数周期技术
    reg [3:0] cnt_o;  //奇数周期计数
    reg clk_MN;
    assign clk_out=clk_MN;
    
    //总计数器,0~86
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                cnt<=7'd0;
            else begin
                if(cnt==M_N-1'b1)
                    cnt<=7'd0;
                else
                    cnt<=cnt+1'b1;
            end
        end
            
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst) begin
                cnt_e<=4'd0;
                cnt_o<=4'd0;
            end
            else if(cnt<=c89-1'b1)  begin//parameter c89 = 8'd24;  8/9时钟切换点
                cnt_o=4'd0;
                if(cnt_e==div_e-1'b1)//parameter div_e = 5'd8; 偶数周期
                    cnt_e<=4'd0;
                else
                    cnt_e<=cnt_e+1'b1;
            end
            else if(cnt>c89-1'b1) begin  //实现7个9分频的时钟周期
                cnt_e<=4'd0;
                if(cnt_o==div_o-1'b1)//parameter div_o = 5'd9; 奇数周期
                    cnt_o<=4'd0;
                else
                    cnt_o<=cnt_o+1'b1;
            end
        end
    
    always@(posedge clk_in or negedge rst)
        begin
            if(!rst)
                clk_MN<=1'b0;
            else begin
                if(cnt<c89)
                    if(cnt_e==4'd0 || cnt_e==div_e/2)
                        clk_MN<=~clk_MN;
                if(cnt>=c89)
                    if(cnt_o==4'd0 || cnt_o==(div_o-1'b1)/2)
                        clk_MN<=~clk_MN;
                
            end
        end


//*************code***********//
endmodule

 

 

posted @ 2022-06-02 11:25  super_sweet  阅读(141)  评论(0编辑  收藏  举报