【Verilog代码题】任意整数分频

【Verilog代码题】任意整数分频,第1张

题目要求

设计一个module,实现任意整数分频,含奇数和偶数,要求占空比为50%,如3分频、4分频,要求分频参数可配置。

以3分频为例,表示分频后的时钟周期是原时钟周期的3倍,即高电平和低电平时间各占1.5个周期,波形如下:


解题思路

为了实现题目要求,实际上是将我前两篇任意奇数分频和任意偶数分频的一个综合,在两块分别实现后,只需要加一个选择语句就可以了:
assign out_clk = (N == 1'b1) ? clk :(N[0] ? out_clk_odd : out_clk_even);


代码实现
//任意整数分频
module divider_odd_even_n
#(
    parameter N = 3'd4
)(
    input   wire            clk     ,
    input   wire            rst_n   ,
    output  wire            out_clk
);

    `define N_WIDTH ($clog2(N) - 1'b1)  //N的位宽
    
    //偶数相关变量定义
    reg  [`N_WIDTH - 1 : 0] even_cnt       ;
    reg                     out_clk_even    ;
    
    //偶数的 *** 作
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            even_cnt <= 'd0;
        else if(even_cnt == (N >> 1'b1) - 1'b1)
            even_cnt <= 'd0;
        else
            even_cnt <= even_cnt + 1'b1;
    end

    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            out_clk_even <= 1'b0;
        else if(even_cnt == (N >> 1'b1) - 1'b1)
            out_clk_even <= ~out_clk_even;
        else
            out_clk_even <= out_clk_even;
    end
    
    
    //奇数相关变量定义
    reg  [`N_WIDTH : 0]     odd_cnt     ;
    reg                     odd_clk_1   ;
    reg                     odd_clk_2   ;
    wire                    out_clk_odd ;
    
    //奇数的 *** 作
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            odd_cnt <= 'd0;
        else if(odd_cnt == N - 1'b1)
            odd_cnt <= 'd0;
        else
            odd_cnt <= odd_cnt + 'd1;
    end
            
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            odd_clk_1 <= 1'b0;
        else if(odd_cnt == N>>1'b1 | odd_cnt == N-1'b1)
            odd_clk_1 <= ~odd_clk_1;
        else
            odd_clk_1 <= odd_clk_1;
    end
            
    always@(negedge clk or negedge rst_n) begin
        if(!rst_n)
            odd_clk_2 <= 1'b0;
        else if(odd_cnt == N>>1'b1 | odd_cnt == N-1'b1)
            odd_clk_2 <= ~odd_clk_2;
        else
            odd_clk_2 <= odd_clk_2;
    end
            
    assign out_clk_odd = odd_clk_1 | odd_clk_2;

    //最终的输出
    assign out_clk = (N == 1'b1) ? clk :(N[0] ? out_clk_odd : out_clk_even);

endmodule

代码中需要注意的细节:
①`define和c语言中的define是一样的,只是引用的时候左上角也要加一个点;
②$clog2是系统内置函数,是求出该数转换为二进制需要占的位数。

Testbench

此题的testbench很简单啦,只需要给好时钟信号和复位信号就可以啦,具体如下:

`timescale 1ns/1ns

module divider_odd_even_n_tb();

reg     clk     ;
reg     rst_n   ;
wire    out_clk ;

always #10 clk = ~clk;
initial
begin
    rst_n = 1'b0;
    clk = 1'b1;
    #10
    rst_n = 1'b1;
end


divider_odd_even_n
#(
   .N(3'd4) //支持1及以上的任意整数
)
divider_odd_even_n_inst
(
    .clk    (clk    ),
    .rst_n  (rst_n  ),
    .out_clk(out_clk)
);

endmodule

仿真波形

五分频的波形图:

四分频的波形图:

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1295895.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存