计数器使用很常见也很实用。以下是几个例子
1,简单的cnt计数
//Verilog
reg [31:0] cnt;
always @(posedge clk) cnt <= cnt+1;
这是一个简单的计数器,计数从0开始计数,计数范围0~2^32-1.
2,带有方向的cnt计数
//Verilog
reg [31:0] cnt = 100;
reg cnt_direction; // 0 计数器递减, 1 计数器递增
always @(posedge clk) cnt <= cnt_direction ? cnt+1 : cnt-1
计数器初值是100,方向选择信号cnt_direction决定cnt是递增还是递减。
3,带有生成tick的cnt计数
//Verilog
wire max_tick;
wire min tick;
reg [31:0] cnt;
always @(posedge clk) cnt <= cnt+1;
//计数到32’h0产生min_tick
//计数到32’hffffffff产生max_tick
assign min_tick = (cnt == 32'h0);
assign max_tick = (cnt == 32'hffffffff);
在Verilog中有按位操作符运算,&和|,&cnt表示每一位均为1时值为1,|cnt表示只要有一位为1值则为1,只有cnt全为0时则为0,所以|cnt取反表示全为0时值为1,上述代码可以简化为如下代码
//Verilog
wire max_tick;
wire min tick;
reg [31:0] cnt;
always @(posedge clk) cnt <= cnt+1;
//计数到32’h0产生min_tick
//计数到32’hffffffff产生max_tick
//&cnt表示每一位均为1时值为1,|cnt表示只要有一位为1值则为1,只有cnt全为0时则为0,所以|cnt取反表示
//全为0时值为1
assign min_tick = ~|cnt;
assign max_tick = &cnt;
4,使用计数器进行复位设置
系统做复位管理的时候,需要上电复位1ms,系统稳定的时候复位释放,此时就需要计数器计数1ms,假如clk时钟100M,则需要计数100k。此时如下设计,cnt计数到100k时候有cnt == 32’d100_000和cnt > 32’d100_000两种方式,采用大于的方式写,可以避免单粒子翻转导致错误无法恢复。
//Verilog
reg [31:0] cnt = 0 ;
reg rst = 0 ;
always @(posedge clk)
begin
cnt <= (cnt > 32'd100_000) ? cnt : cnt+1;
rst <= (cnt > 32'd100_000) ? 0 : 1;
end
5,使用计数器调节占空比进行PWM设置
通过调节输出占空比来完成PWM的操作,此时使用cnt可以完美的调节占空比,假设系统clk=100M,1s完成从占空比0到1的变化,步进按照1ms步进。代码可以如下方式编写
parameter STEP = 100;//1ms/1000 = 100_000/1000
reg [31:0] cnt_1ms = 0 ;
wire tick_1ms;
always @(posedge clk) cnt_1ms <= (cnt_1ms >= 32'd99_999) ? 0 : cnt_1ms+1;
assign tick_1ms =(cnt_1ms==32'd99_999);
reg [31:0] h_lever_cnt = 0;//高电平计数值
wire pwm_out;
always @(posedge clk)
if(tick_1ms)
h_lever_cnt <= (h_lever_cnt >= (32'd100_000 - STEP)) ? 0 : h_lever_cnt + STEP;
else
h_lever_cnt <= h_lever_cnt;
assign pwm_out =(cnt_1ms < h_lever_cnt) ? 1 : 0;