栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

题目要求

设计一个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

仿真波形

五分频的波形图:

四分频的波形图:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/917385.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号