数字IC手撕代码50题(11-20)

十一、偶数分频--二分频|四分频|八分频

        所有的分频器其实属于计数器电路中的一种,这篇文章主要讲这个类型的题目。

11.1 题目描述与分析

        实现二分频|四分频|八分频电路,满足50%占空比。

       一、寄存器级联法能实现2^N的偶数分频,具体是采用寄存器结构的电路,每当时钟上升沿到来的时候输出结果进行翻转,以此来实现偶数分频。

        二、计数器法可以实现任意偶数分频,以八分频为例,电路需要实现的是:计数器从0开始计数至3,当clock上升沿取到clock=3时,输出clock进行翻转。

        这里我们用寄存器级联法实现。(一个触发器的输出做下一级触发器的时钟)

  11.2 寄存器实现2^N的偶数分频

module even_divide(clk,rst_n,clk2,clk4,clk8);

input clk;
input rst_n;
output reg clk2;
output reg clk4;
output reg clk8;

always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk2 <= 1'b0;
else
clk2 <= !clk2;
end

always@(posedge clk2 or negedge rst_n)
begin
if(!rst_n)
clk4 <= 1'b0;
else
clk4 <= !clk4;
end

always@(posedge clk4 or negedge rst_n)
begin
if(!rst_n)
clk8 <= 1'b0;
else
clk8 <= !clk8;
end

endmodule

十二、任意偶数分频--占空比50%

12.1 题目描述与分析

        实现6分频电路,占空比为50%。

        由上面的分析可知,计数器法可以实现任意偶数分频。

        以六分频为例,电路需要实现的是:计数器从0开始计数至3=2,当clock上升沿取到clock=2时,输出clock进行翻转。

12.2 计数器法实现六分频

module moduleName (
    input clk,
    input rst_n,
    output reg clk_6
);
    reg [1:0] cnt6;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            cnt6 <= 2'd0;
        else if(cnt6 == 2'd2)
            cnt6 <= 2'd0;
        else
            cnt6 <= cnt6 + 2'd1;
    end
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            clk_6 <= 1'b0;
        else if(cnt6 == 2'd2)
            clk_6 <= ~clk_6;
        else
            clk_6 <= clk_6;
    end
endmodule

十三、奇数分频--不要求占空比

        不要求占空比,比较好实现。比如实现五分频,可以对5个时钟周期计数,比如1高4低,2高3低等等。

        再举个例子。如图,可以发现,假如Clock是输入的时钟信号,Clock2是输出的50%占空比的三分频信号,那么对于计数器,Clock2实现的操作是:当采样边沿每次遇到count=0的时候进行翻转,每次遇到1的时候再次完成翻转,根据此,加上复位信号,我们即可完成RTL代码。

module moduleName (
    input clk,
    input rst_n,
    output reg clk_5
);
    reg [1:0] cnt5;
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            cnt5 <= 2'd0;
        else if(cnt5 == 2'd4)
            cnt5 <= 2'd0;
        else
            cnt5 <= cnt5 + 2'd1;
    end
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n)
            clk_5 <= 1'b0;
        else if(cnt5 == 2'd0 || cnt5 == 2'd1)  // 这样写是1 - 4  1 - 6  万能写法
            clk_5 <= ~clk_5;
        else
            clk_5 <= clk_5;
    end
endmodule

十四、奇数分频--50%的占空比

  14.1 题目描述与分析 

        实现奇数分频,50%的占空比。

        分析:如果要实现占空比为50%的三分频时钟,可以通过待分频时钟下降沿触发计数,和上升沿同样的方法计数进行三分频,然后下降沿产生的三分频时钟和上升沿产生的时钟进行相或运算,即可得到占空比为50%的三分频时钟。这种方法可以实现任意的奇数分频。

        归类为一般的方法为:对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%奇数n分频时钟。(0翻转一次,(3-1)/2 = 1,翻转一次)再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟相或运算,得到占空比为50%的奇数n分频时钟。

        可以理解为生成两个占空比非50%的n分频,再进行相或运算。

14.2 三分频电路的RTL实现

module f3(clk, rst_n,clk2);

input clk;
input rst_n;
output clk2;


reg [2:0] negedge_count;
reg [2:0] posedge_count;
reg posedge_clk2;
reg negedge_clk2;
parameter N = 3;


always@(posedge clk or negedge rst_n)
begin
if(!rst_n || posedge_count == N-1)
posedge_count <= 3'd0;
else
posedge_count <= posedge_count +1'd1;
end


always@(negedge clk or negedge rst_n)
begin
if(!rst_n || negedge_count == N-1)
negedge_count <= 3'd0;
else
negedge_count <= negedge_count +1'd1;
end

always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
posedge_clk2 <= 3'd0;
else if (posedge_count == 3'd1 || posedge_count == 3'd0)
posedge_clk2 <= !posedge_clk2;
else
posedge_clk2 <= posedge_clk2;
end


always@(negedge clk or negedge rst_n)
begin
if(!rst_n)
negedge_clk2 <= 3'd0;
else if (negedge_count == 3'd1 || negedge_count == 3'd0)
negedge_clk2 <= !negedge_clk2;
else
negedge_clk2 <= negedge_clk2;
end

assign clk2 = posedge_clk2 || negedge_clk2;

十五、数字电子时钟

15.1 题目描述和分析

        实质:是一个计数器问题。最近秋招遇到了好几次这个的笔试题,其实还是比较简单的。关键还是计数器的写法,所以做下总结,之后不论是秋招还是实习面试笔试,尽量可以把这个送分题拿到。

基于f = 100Hz的Clock设计一个数字时钟,用Verilog实现,产生时、分、秒的计时。

分析:

前提,首先将100hz倍频为1hz的时钟,这样一拍就是1s了。

其实就是一个 进位操作,设置hour、minute、second三个进位标志,second计数器记满60清零,second计数器记满60时,minute计数器加1。当minute记满60且second记满60时,hour加1且minute清零。当hour计数器记满24时,且minute记满60,second记满60时,hour清零。

15.2 RTL实现

module clock (
    input clk,
    input rst_n,
    output reg[5:0]hour,
    output reg[5:0]minute,
    output reg[5:0]second
);
// 产生1hz时钟
reg[6:0] clk_cnt;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        clk_cnt <= 0;
    else if (clk_cnt == 99)
        clk_cnt <= 0;
    else
        clk_cnt <= clk_cnt + 1;
end
reg clk1;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        clk1 <= 0;
    else if(clk_cnt < 50)
        clk <= 0;
    else    
        clk <= 1;
end
// 秒模块
always @(posedge clk1 or negedge rst_n) begin
    if(!rst_n)
        second <= 0;
    else if(second == 59)
        second <= 0;
    else    
        second <= second + 1;
end
// 分模块
always @(posedge clk1 or negedge rst_n) begin
    if(!rst_n)
        minute <= 0;
    else if((minute == 59)&&(second == 59))
        minute <= 0;
    else if(second == 59)   
        minute <= minute + 1;
end
// 时模块
always @(posedge clk1 or negedge rst_n) begin
    if(!rst_n)
        hour <= 0;
    else if((minute == 59)&&(second == 59)&&(hour == 23))
        hour <= 0;
    else if((minute == 59)&&(second == 59))   
        hour <= hour + 1;
end
endmodule

        

猜你喜欢

转载自blog.csdn.net/lgk1996/article/details/126008178