计数器进位链
可以使用几行 Verilog 行构建一个快速高效的二进制计数器。例如,这是一个 10位计数器。此类计数器从 0 计数到 1023,(2^10=1024),然后回滚 0 以继续其过程。 由于隐藏的进位链,它占用的资源很少,并且在 FPGA 中运行速度快。
reg [9:0] cnt = 0;//为防止综合工具随意定值,最好指定起始值,即使是0
always @(posedge clk) begin
cnt <= cnt+1;
end
假设设计中需要一个每 1024 clock拉高一次的 “tick” 信号
//solution 1
wire tick = (cnt==1023);
另一种写法:
这种写法会创建一大块 logic,比如这里就会用一个 10bit AND 门,计数器位宽越大消耗资源越多,有点浪费
//solution 2
wire tick = &cnt; // 对cnt按位与,全 1 的时候tick拉高
使用进位链
//solution 3
reg [10:0] cnt_test = 0; // 比cnt多一个bit位
always @(posedge clk) begin
cnt_test <= cnt_test[9:0] + 1 ;
end
wire tick = cnt_test [10] ; //通过进位链拉高最高位来实现tick拉高
虽然原理相同,但进位链是不会消耗额外的资源
小技巧:
在进行计数器比较时,可以不用把cnt所有的位数与目标值进行比较
例如:
reg [3:0] cnt = 0;
always @(posedge clk) cnt <= (cnt==9) ? 0 : cnt+1;
可以改为如下,这样在比较中仅使用bit 0 和bit 3
always @(posedge clk) cnt <= ((cnt & 9)==9) ? 0 : cnt+1;