前言
2023.5.12
一、二进制计数器(n位 2^n状态)
1.1 可置位计数器
编写一个十六进制计数器模块,计数器输出信号递增每次到达0,给出指示信号zero
,当置位信号set
有效时,将当前输出置为输入的数值set_num
。
注意:这里zero=1和num=0是同一拍输出的,按道理如果根据num=0,然后去输出zero=1应该延迟一拍。所以这里考虑将number延迟一拍输出,就能和zero=1变化同步了。
module count_module(
input clk,
input rst_n,
input set,
input [3:0] set_num,
output reg [3:0]number,
output reg zero
);
reg [3:0] cnt;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt<=0;
else if(set)
cnt<=set_num;
else
cnt<=(cnt==15)?0:cnt+1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
zero<=0;
else
zero<=(cnt==0)?1:0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
number<=0;
else
number<=cnt;
end
endmodule
1.2 加减计数器
一个十进制计数器模块,当mode
信号为1,计数器输出信号递增,当mode信号为0,计数器输出信号递减。每次到达0,给出指示信号zero。
module count_module(
input clk,
input rst_n,
input mode,
output reg [3:0]number,
output reg zero
);
reg[3:0] number1;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
number1<=0;
end
else if(mode)
number1<=(number==9) ? 0 : number1+1;
else if(~mode)
number1<=(number==0) ? 9 : number1-1;
else
number1<=number1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
number<=0;
else
number<=number1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
zero<=0;
else if(number1==0)
zero<=1;
else
zero<=0;
end
endmodule
二、环形计数器(n位 n状态)
0001-0010-0100-1000-0001
独热码,相邻两位之间会有两位不相同
优点:
- 状态译码简单,设计简单,修改灵活
缺点:
- 有许多无限状态
reg [3:0] count;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
count <= 4‘b0001; //注意复位状态
else
count <= {count[2:0], count[3]}; //向左依次循环
end
2.1 移位寄存器首尾相连构成环形计数器
这种电路的问题在于自锁,无法自启动
。
对输出端进行反馈到输入,把Q2、Q1、Q0或非接到D0端,这样就能自启动了。
状态转移图如下所示。
三、扭环形计数器/Johnson计数器(n位 2*n状态)
1000-1100-1110-1111-0111-0011-0001-0000-1000
相邻两个数之间只有1bit位不同,比较可靠,不存在竞争冒险
reg [3:0] count;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
count <= 0;
else
count <= {~count[0], count[3:1]}; //这里是往右循环的计数
end
3.1 移位寄存器来构成扭环形计数器
文章来源:https://www.toymoban.com/news/detail-466196.html
四、格雷码计数器
分为三个部分:格雷码转二进制、二进制加法、二进制转格雷码。文章来源地址https://www.toymoban.com/news/detail-466196.html
module gray_counter(
input clk,
input rst_n,
output reg [3:0] gray_out
);
reg [3:0] bin;
wire [3:0] gray_r;
reg [3:0] bin_add;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
bin<=0;
else begin
bin[3]=gray_r[3];
bin[2]=gray_r[2]^bin[3];
bin[1]=gray_r[1]^bin[2];
bin[0]=gray_r[0]^bin[1];
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
bin_add<=0;
else
bin_add<=bin+1'b1;
end
assign gray_r = (bin_add>>1) ^ bin_add;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
gray_out<=0;
else
gray_out<=gray_r;
end
endmodule
到了这里,关于verilog手撕代码5——计数器(置位、加减、环形、扭环形、格雷码计数器实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!