Verilog 三种计数器写法

时钟周期 频率50MHz 倒数为1/(5*107)s=20ns,凑够一秒需要5 * 107个周期。
ms us ns ps

0计数器设计要点

1 初始值
a) 复位值
b)每轮初始值

2 . 加1 条件

3 . 结束条件
a)返回初始值
b)结束一轮计数的条件,一般为加1条件并列

4 计数器位宽
与2的n次幂相比,如2<3<22,则取上限,2

当不定时计数时,采用自减计数器

1 时序逻辑和组合逻辑彻底分开

//模10计数器,0到10循环累加
module Count_1
(
    input               clk                 ,
    input               rst_n               ,
    output reg [ 3:0]   cnt
);
//----------------------------------------------------------------------
//--   组合电路
//----------------------------------------------------------------------
reg [ 3:0]              cnt_n                ;
always @(*)begin
    if(cnt == 4'd9)
        cnt_n = 4'd0; 
    else
        cnt_n = cnt + 1'b1;
end
//----------------------------------------------------------------------
//--   时序电路
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt <= 4'b0;
    else
        cnt <= cnt_n;
end
endmodule
/*
//----------------------------------------------------------------------
//--   组合电路也可以这样写
//----------------------------------------------------------------------
wire [ 3:0]             cnt_n               ;
assign cnt_n = (cnt==4'd9)? 4'd0 : cnt+1'b1;
/

2最常见的写法


module Count_2
(
    input               clk                 ,
    input               rst_n               ,
    output reg [ 3:0]   cnt
);
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt <= 4'd0;
    else if(cnt==4'd9)
        cnt <= 4'd0;
    else
        cnt <= cnt + 1'b1;
end
endmodule

3至简设计法


module Count_3
//---------------------<端口声明>---------------------------------------
(
input                   clk                 ,
input                   rst_n               ,
output reg [ 3:0]       cnt
);
//---------------------<信号定义>---------------------------------------
wire                    add_cnt             ;
wire                    end_cnt             ;
//----------------------------------------------------------------------
//--   0-9计数
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt <= 4'd0;
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 4'd0;
        else
            cnt <= cnt + 1'b1;
    end
    else
        cnt <= cnt;
end
assign add_cnt = 1;
assign end_cnt = add_cnt && cnt==4'd9;
endmodule

在这里插入图片描述

4 总结

由此可见,三种写法对应的RTL视图是完全一致的。

第一种写法优点是时序和组合彻底分开,代码直接映射成电路,非常直观。缺点是写法较为麻烦。第二种写法是最常见的写法,不仅是小梅哥,大多数人都是这种写法。第三种明德杨FPGA教程的写法,把加一条件和结束条件独立出来,非常方便使用。我这里为了保持一致把每一个数字都加了位宽,其实位宽是也是可以省略的。这样第三种写法甚至变成了一种模板:

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end
assign add_cnt = 1;
assign end_cnt = add_cnt && cnt==x-1 ;

ref
https://www.cnblogs.com/xianyufpga/p/10908740.html
计数器用作分频及仿真
https://www.cnblogs.com/IClearner/p/7208871.html

                                </div><div><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet">
                            </div>
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值