概述
本篇文章参考自常见六种计数器
用D触发器搭建计数器
要求实现一个4进制的计数器,但要用D触发器来搭建,这显然不会像写Verilog实现一样容易,所以我们要用数字电路中的传统方法来设计。
4进制计数器必须有4个不同的状态,所以需要两个D触发器组成这个电路。电路的状态表如下所示:
通过状态表可以画出卡诺图,对其化简可得次态输出。
电路次态的卡诺图如下所示:
通过卡诺图化简可得
Q0* = Q0’
Q1* = Q1’Q0+Q1Q0*;
C = Q1Q0;
因此RTL代码如下
01 module test(
02 input wireclk,
03 input wirerst_n,
04
05 outputwire[1:0]counter
06 );
07
08 reg Q1, Q0;
09 wireD1, D0;
10
11 always@(posedge clk or negedge rst_n)
12 if(!rst_n)
13 Q0 <= 1'b0;
14 else
15 Q0 <= D0;
16
17 always@(posedge clk or negedge rst_n)
18 if(!rst_n)
19 Q1 <= 1'b0;
20 else
21 Q1 <= D1;
22
23 assign D0 = ~Q0;
24 assign D1 = (~Q1&Q0)|(Q1&(~Q0));
25 assign counter = {Q1,Q0};
26
27 endmodule
用D触发器搭建分频电路
这里为一个引申
数字电路D触发器的时序电路设计方法,画出D触发器的反馈函数,卡诺图化简,然后根据状态方程来画出D触发器的电路连接图。
我们的目的是通过D触发器和组合逻辑实现占空比为50%的9分频电路**,具体的思路是先使用D触发器构成序列发生器**,输出000001111循环脉冲,实现占空比非50%的9分频,然后用下降沿的D触发器打一拍,将两个信号相或后输出即可。
根据上述思路画出波形图,out是通过序列生成的占空比非50%的信号,它的周期为原来时钟的9倍,刚好是9分频。信号out_reg是通过负触发沿打一拍,最后将信号out和out_reg相或后输出得到div_clk的占空比为50%。
关键点在于000001111序列的生成,由于循环需要9个状态,最少需要4个触发器(2^4 > 9),但是这个序列有5个连续的0,相邻的状态之间会有重复,故不能使用4个触发器。使用5个触发器列出如下的反馈函数:
通过反馈函数的状态表可知,红色箭头代表触发器移入的单个数值,触发器从初始状态00000开始经过9个状态变化后回到00000完成一次循环,中间的状态不可以有重复相同的,如果有一样的状态,需要增加触发器个数再重新循环。通过状态表列出卡诺图,由于设计中有5个变量,会涉及到5变量的卡诺图化简,我们平时做的最多的就是4变量的卡诺图,一下5变量的化简好像以前数字电路课也没怎么学过的样子。一开始觉得5变量有点麻烦,但是当画完之后,发现好像一个圈就可以搞定,并没有想象中的那么复杂,可能这也是题目设计的用意。
图中的 j 为不确定态,在化简的时候可以变为0或者1,最后得到的化简结果为:D=Q4’Q3’=(Q4+Q3)’。实现50%的占空比虽然题目没有要求,但是设计中我们还是用到了,然后在画电路图的时候需要增加一个触发器和或的逻辑门作为Y输出。只有最后一个触发器是下降沿触发,图中的圆圈代表是取反的意思,其余的触发器均为上升沿触发。
得到第一级触发器的输入为(Q4+Q3)’,设计中要求使用同步高复位,完整的Verilog代码如图所示:
定义了5个触发器通过打拍的方式实现级连,将前面卡诺图化简的结果输入到端,将通过负触发沿打拍给out_reg,最后将两者相或,输出的div_clk为9分频时钟信号。
常规带使能计数器
以带使能的模100异步清零计数器为例
设计代码
module cnt #(parameter COUNT=100)(
input clk,
input rst_n,
input cnt_en,
outputreg[6:0]out//如果参数化中COUNT比较大,需要更改out的位宽来适配
);
reg flg;
always@(posedge clk ornegedge rst_n)//异步清零
if(!rst_n)begin
out<=7'd0;
flg<=1'b0;
end
else if(cnt_en)begin
//写法1:
if(out!=COUNT-1)begin
out<=out+1'b1;
flg<=1'b0;
end
else begin
out<=7'd0;
flg<=1'b1;
end
/*
//写法2:
if(out==COUNT-1)begin
out<=7'd0;
flg<=1'b1;
end
else begin
out<=out+1'b1;
flg<=1'b0; end */
end
else begin
out<=7'd0;
flg<=1'b0;
end//maybe
endmodule
加减法计数器
module add_sub_cnt(
input clk,
input rst_n,
input [1:0]cnt_ctr,
output reg [2:0]cnt
);
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt<=3'd0;
else begin
if(cnt_ctr==2'b00||cnt_ctr==2'b11)
cnt<=cnt;
else if(cnt_ctr==2'b01)
cnt<=cnt+1'b1;
else if(cnt_ctr==2'b10)
cnt<=cnt-1'b1;
end
endmodule
环形计数器
环形计数器,n个触发器表示n个状态。所谓环形如下图所示,是指图中的“1”,在每一组数中出现的位置形成的效果图,像一个环一样,依次循环,以4bit环形计数器为例子,“1”的位置依次在第0bit、第1bit,第2bit,第3bit,再回到第0bit,依次类推,就像一个环。如 4bit环形计数器:复位有效时输出0001,复位释放后依次输出0010,0100,1000,0001,0010…,如下图所示:
设计文件
module ring_counter#(parameter word_size=4)(
input clk,
input rst_n,
input enable,
output reg [word_size-1:0]count
);
always@(posedge clk,negedge rst_n)
if(!rst_n)
count<={{(word_size-1){1'b0}},1'b1};
else if(enable==1'b1)
count<={count[word_size-2:0],count[word_size-1]};
endmodule
约翰逊计数器
约翰逊(Johnson)计数器又称扭环计数器,是一种用n位触发器来表示2n个状态的计数器。约翰逊(Johnson)计数器有一个非常明显地好处,相邻两组数只有一位不同,具体如下例子所示,因此在计数过程中不会存在竞争冒险问题。
module johnson_cnt(
input wire clk,
input wire rst_n,
output reg [3:0] out
);
always_ff @(posedge clk or negedge rst_n) begin : proc_out
if(~rst_n) begin
out <= 'd0;
end else begin
out <= {~out[0], out[3:1]} ;
end
end
endmodule
线性反馈移位计数器(LFSR)
欢迎大家关注公众号 知芯者,每天更新IC设计验证相关的文章,还包括常见笔试面试题及企业原题,找工作的同学看过来
最后
以上就是耍酷玫瑰为你收集整理的各种计数器用D触发器搭建计数器用D触发器搭建分频电路常规带使能计数器加减法计数器环形计数器约翰逊计数器线性反馈移位计数器(LFSR)的全部内容,希望文章能够帮你解决各种计数器用D触发器搭建计数器用D触发器搭建分频电路常规带使能计数器加减法计数器环形计数器约翰逊计数器线性反馈移位计数器(LFSR)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复