概述
计数器
一、写在前面
- 计数器是数字系统和计算机系统常用的基本模块,是计数寄存器的简称
- 74LS161模块是一个同步加法计数器(通用计数器)
下图为其的接口描述
下图为功能描述
二、进入正题
废话不多说,我们进入正题——74LS161的设计:
开门见山给出我的Verilog代码(经过仿真验证过):
module My74LS161(
input CP,CR,
input CTP,CTT,
input L_D,
input [3:0] D,
output reg [3:0] Q,
output CO
);
parameter State_0 = 4'b0000,State_1 = 4'b0001,State_2 = 4'b0010,State_3 = 4'b0011,State_4 = 4'b0100,State_5 = 4'b0101,State_6 = 4'b0110,State_7 = 4'b0111,State_8 = 4'b1000,State_9 = 4'b1001,State_10 = 4'b1010,State_11 = 4'b1011,State_12 = 4'b1100,State_13 = 4'b1101,State_14 = 4'b1110,State_15 = 4'b1111;
always @(posedge CP,negedge CR) begin
if(~CR) begin
Q <= 0;
end
else
if(~L_D) begin
Q <= D;
end
else begin
if(CTT & CTP)
begin
case(Q)
State_0 : Q <= State_1;
State_1 : Q <= State_2;
State_2 : Q <= State_3;
State_3 : Q <= State_4;
State_4 : Q <= State_5;
State_5 : Q <= State_6;
State_6 : Q <= State_7;
State_7 : Q <= State_8;
State_8 : Q <= State_9;
State_9 : Q <= State_10;
State_10 : Q <= State_11;
State_11 : Q <= State_12;
State_12 : Q <= State_13;
State_13 : Q <= State_14;
State_14 : Q <= State_15;
State_15 : Q <= State_0;
endcase
end
end
end
assign CO = (&Q) &CTT;
endmodule
实现思想是:有限状态机,这里一共0~15,十六个状态,实现这些状态之间的相互转换即可,当然也可以通过其他方法给出。
顺便给出我的仿真代码
initial begin
CR = 0;
D = 0;
CTP = 0;
CTT = 0;
L_D = 0;
#100;
CR = 1;
L_D= 1;
D = 4'b1100;
CTT = 0;
CTP = 0;
#30 CR = 0;
#20 CR = 1;
#10 L_D = 0;
#30 CTT = 1;
CTP = 1;
#10 L_D = 1;
#510;
CR = 0;
#20 CR = 1;
#500;
end
always begin
CP = 0;#20;
CP = 1;#20;
end
仿真结果(ISE)
三、24,60进制计数器
设计好了74LS141模块后,就可以设计24,60进制计数器了,这里给出电路图
实际上我们可以通过两个74LS161模块搭成24进制计数器,这里我们采用BCD编码,也就是说个位是逢9清零或者是碰到23就清零,十位是碰到23清零。
可以采取两个与非门用来检测这个9或者23,从而判断是否清零。
献上代码:
module Counter_24(
input clk,
input rst,
output C24,
output [7:0] Q ); //BCD编码,Q[7:4]是十位数,Q[3:0]是个位数
wire LD1;
wire CT;
wire NAND_1,NAND_2;
assign NAND_1 = ~(Q[0]&Q[3]); //检测9的出现
assign NAND_2 = ~(Q[0]&Q[1]&Q[5]); //检测23的出现
assign LD1 = NAND_1 & NAND_2;
assign C24 = NAND_2;
assign CT = ~NAND_1;
//两个74LS161分别计数
My74LS161 m1 (.CP(clk),.CR(rst),
.CTP(1'b1),.CTT(1'b1),
.L_D(LD1),
.D(4'b0000),
.Q({Q[3],Q[2],Q[1],Q[0]})
);
My74LS161 m2 (.CP(clk),.CR(rst),
.CTP(CT),.CTT(CT),
.L_D(NAND_2),
.D(4'b0000),
.Q({Q[7],Q[6],Q[5],Q[4]})
);
endmodule
同理,献上60进制计数器
module Counter_60(
input clk,
input rst,
output C60,
output [7:0] Q );
wire LD1;
wire CT;
wire NAND_1,NAND_2;
assign NAND_1 = ~(Q[0]&Q[3]);
assign NAND_2 = ~(Q[5]&Q[6]);
assign LD1 = NAND_1 & NAND_2;
assign C60 = NAND_2;
assign CT = ~NAND_1;
My74LS161 m1 (.CP(clk),.CR(rst),
.CTP(1'b1),.CTT(1'b1),
.L_D(LD1),
.D(4'b0000),
.Q({Q[3],Q[2],Q[1],Q[0]})
);
My74LS161 m2 (.CP(clk),.CR(rst),
.CTP(CT),.CTT(CT),
.L_D(NAND_2),
.D(4'b0000),
.Q({Q[7],Q[6],Q[5],Q[4]})
);
endmodule
四、附加思考
在某位同学的要求下,我考虑了一下关于计数器初始值的问题,上面默认计数器从0开始计数,逢60或24再清为0;但是我们也可以要求计数器从比如23开始计数。
下面是Verilog代码:
module My74LS161(
input CP,CR, //时钟CP,清零CR
input CTP,CTT, //CTP和CTT使能端
input L_D, //load信号
input [3:0] D, //清零值
input [3:0] D_CR, //初始值
output reg [3:0] Q,
output CO
);
parameter State_0 = 4'b0000,State_1 = 4'b0001,State_2 = 4'b0010,State_3 = 4'b0011,State_4 = 4'b0100,State_5 = 4'b0101,State_6 = 4'b0110,State_7 = 4'b0111,State_8 = 4'b1000,State_9 = 4'b1001,State_10 = 4'b1010,State_11 = 4'b1011,State_12 = 4'b1100,State_13 = 4'b1101,State_14 = 4'b1110,State_15 = 4'b1111;
always @(posedge CP,negedge CR) begin
if(~CR) begin
Q <= D_CR; //这里从0改为D_CR,表示初始值
end
else
if(~L_D) begin
Q <= D;
end
else begin
if(CTT & CTP)
begin
case(Q) //时钟来临,到达下一周期
State_0 : Q <= State_1;
State_1 : Q <= State_2;
State_2 : Q <= State_3;
State_3 : Q <= State_4;
State_4 : Q <= State_5;
State_5 : Q <= State_6;
State_6 : Q <= State_7;
State_7 : Q <= State_8;
State_8 : Q <= State_9;
State_9 : Q <= State_10;
State_10 : Q <= State_11;
State_11 : Q <= State_12;
State_12 : Q <= State_13;
State_13 : Q <= State_14;
State_14 : Q <= State_15;
State_15 : Q <= State_0;
endcase
end
end
end
assign CO = (&Q) &CTT;
endmodule
于是设定初始值为13的24进制计数器可以修改为:
module Counter_24(
input clk,
input rst,
output C24,
output [7:0] Q );
wire LD1;
wire CT;
wire NAND_1,NAND_2;
assign NAND_1 = ~(Q[0]&Q[3]);
assign NAND_2 = ~(Q[0]&Q[1]&Q[5]);
assign LD1 = NAND_1 & NAND_2;
assign C24 = NAND_2;
assign CT = ~NAND_1;
My74LS161 m1 (.CP(clk),.CR(rst),
.CTP(1'b1),.CTT(1'b1),
.L_D(LD1),
.D(4'b0000),
.D_CR(4'b0011), //設置初值
.Q({Q[3],Q[2],Q[1],Q[0]})
);
My74LS161 m2 (.CP(clk),.CR(rst),
.CTP(CT),.CTT(CT),
.L_D(NAND_2),
.D(4'b0000),
.D_CR(4'b0001), //設置初值
.Q({Q[7],Q[6],Q[5],Q[4]})
);
endmodule
最后
以上就是还单身外套为你收集整理的Verilog之计数器设计实现计数器的全部内容,希望文章能够帮你解决Verilog之计数器设计实现计数器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复