基于 Verilog 的经典数字电路设计(9)分频器

关于分频器,不详细描述了,这里针对笔试面试给出了各种分频器的代码,例如华为就喜欢出这种手撕代码的大题,找工作的小伙伴们可以收藏一下。

下面是 2 分频的 Verilog 代码实现:(通过上升沿、然后翻转)

module Two_Div(
    input clk_in,
    input rst_n,
    output reg clk_out
    );

    always @(posedge clk_in) begin
        if (!rst_n)
            clk_out <= 0;
        else
            clk_out <= ~clk_out;
    end

endmodule

  下面是 2^n 分频的 Verilog 代码实现:(通过计数器、然后对位入座)

module random_even_div(
    input clk_in,
    input rst_n,
    output reg clk_out1,clk_out2,clk_out3,clk_out4
    );

    reg [3:0] counter ;

/*---------------------计数模块----------------------*/
    always @(posedge clk_in or negedge rst_n)
        if (!rst_n)
            counter <= 0;
        else begin
            if (counter == 4'b1111)
                counter <= 4'b0000;
            else
                counter <= counter + 1'b1;
        end

/*---------------------产生分频----------------------*/
    always @(posedge clk_in or negedge rst_n)
        if (!rst_n) begin
            clk_out1 <= 0;
            clk_out2 <= 0;
            clk_out3 <= 0;
            clk_out4 <= 0;
        end
        else begin
            clk_out1 <= counter[0];    // 2分频
            clk_out2 <= counter[1];    // 4分频
            clk_out3 <= counter[2];    // 8分频
            clk_out4 <= counter[3];    // 16分频
        end

endmodule

  下面是非 2^n 分频的 Verilog 代码实现:(通过计数器、然后翻转)

module random_even_div(
    input      clk_in,
    input      rst_n,
    output reg clk_out
    );

    reg [2:0] cnt; // log2(6) = 2.5850 <= 3;这里,6也可以换成 10、12、14 ...

    always @(posedge clk_in or negedge rst_n) begin
        if (!rst_n)
            cnt <= 0;
        else begin
            if (cnt == 5) // 6 bits 计数器: 0 - 5;实现置零;
                cnt <= 0;
            else
                cnt <= cnt + 1'b1;
        end
    end

    always @(posedge clk_in, negedge rst_n) begin
        if (!rst_n)
            clk_out <= 0;
        else begin
            if (cnt <= 2) // 3 bits 计数器: 0 - 2;实现翻转;
                clk_out <= 1;
            else
                clk_out <= 0;
        end
    end

endmodule

  下面是 3 分频的 Verilog 代码实现(附加仿真图):(通过上升沿和下降沿、然后取或)(1 : 3 的占空比简单粗暴,占空比就是指在一个脉冲循环内,通电时间相对于总时间所占的比例,这里是高电平 1 相对于整个时钟周期所占的比例)

module Three_Div(
    input  clk_in,
    input  rst_n,
    output clk_out
    );

    parameter N = 3;

    reg clk_n;
    reg clk_p;
    reg [3:0] cnt_p;
    reg [3:0] cnt_n;

    always @(posedge clk_in or negedge rst_n) begin
        if (!rst_n) begin
            clk_p <= 1'b0;
            cnt_p <= 4'b0;
        end
        else begin
            if (cnt_p == N-1) begin
                clk_p <= ~clk_p;
                cnt_p <= 4'b0;
            end
            else if (cnt_p == (N-1)/2) begin
                clk_p <= ~clk_p;
                cnt_p <= cnt_p + 1;
            end
            else begin
                cnt_p <= cnt_p + 1;
                clk_p <= clk_p;
            end
        end
    end

    always @(negedge clk_in or negedge rst_n) begin
        if (!rst_n) begin
            clk_n <= 1'b0;
            cnt_n <= 4'b0;
        end
        else begin
            if (cnt_n == N-1) begin
                clk_n <= ~clk_n;
                cnt_n <= 4'b0;
            end
            else if (cnt_n == (N-1)/2) begin
                clk_n <= ~clk_n;
                cnt_n <= cnt_n + 1;
            end
            else begin
                cnt_n <= cnt_n + 1;
                clk_n <= clk_n;
            end
        end
    end

    assign clk_out = clk_n | clk_p;

endmodule

基于 Verilog 的经典数字电路设计(9)分频器_第1张图片

下面是 3 分频的 Verilog 代码实现(附加仿真图):(通过上升沿和下降沿、然后取与)(50% 占空比简直完美,亦可以实现 5、7、9 ... 等分频)

module Three_Div(
    input  clk_in,
    input  rst_n,
    output clk_out
    );

    reg [1:0] cnt_p; // log2(3) = 1.5850 <= 2

    always @(posedge clk_in or negedge rst_n) begin
        if (!rst_n)
            cnt_p <= 0;
        else begin
            if (cnt_p == 2)
                cnt_p <= 0;
            else
                cnt_p <= cnt_p + 1'b1;
        end
    end

    reg [1:0] cnt_n; // log2(3) = 1.5850 <= 2

    always @(negedge clk_in or negedge rst_n) begin // negedge clk
        if (!rst_n)
            cnt_n <= 0;
        else begin
            if (cnt_n == 2)
                cnt_n <= 0;
            else
                cnt_n <= cnt_n + 1'b1;
        end
    end

    reg clk_out_p; // 上升沿时钟输出寄存器

    always @(posedge clk_in or negedge rst_n) begin
        if (!rst_n)
            clk_out_p <= 0;
        else begin
            if (cnt_p <= 1)
                clk_out_p <= 1;
            else
                clk_out_p <= 0;
        end
    end

    reg clk_out_n; // 下降沿时钟输出寄存器

    always @(negedge clk_in or negedge rst_n) begin
        if (!rst_n)
            clk_out_n <= 0;
        else begin
            if (cnt_n <= 1)
                clk_out_n <= 1;
            else
                clk_out_n <= 0;
        end
    end

  assign clk_out = clk_out_n & clk_out_p;

endmodule

基于 Verilog 的经典数字电路设计(9)分频器_第2张图片

总结一下 3 分频的规律(毕竟是最常考的),就是占空比 1/3 的是求或操作,占空比为 2/3 的是求与操作,可以自己画画时序图看看(不过,博主这里仿真图都给出来了,我想你都不用自己画咯)

你可能感兴趣的:(基于,Verilog,的经典数字电路设计)