Verilog之计数器设计实现

计数器

一、写在前面

  1. 计数器是数字系统和计算机系统常用的基本模块,是计数寄存器的简称
  2. 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

在这里插入图片描述

  • 20
    点赞
  • 154
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
很高兴回答你关于Verilog计数器设计的问题!在Verilog设计一个计数器可以使用以下步骤: 1. 首先,确定计数器的位宽。这取决于你想要计数器能够计数到的最大值。假设我们要设计一个8位计数器。 2. 创建一个模块,可以使用`module`关键字定义。给模块起一个适合的名字,比如"counter"。 3. 在模块中声明一个8位的寄存器用于存储计数器的当前值。你可以使用`reg`关键字来声明寄存器,例如:`reg [7:0] count;` 4. 在模块中声明一个时钟信号作为计数器的时钟输入。你可以使用`input`关键字来声明输入信号,例如:`input clk;` 5. 在模块中创建一个时钟边沿敏感的always块。这个always块将在每个时钟上升沿触发时执行。 ```verilog always @(posedge clk) begin // 在这里编写计数逻辑 end ``` 6. 在always块中使用一个条件语句来实现计数逻辑。比如,你可以使用一个if-else语句来判断当前计数器的值,并根据需要进行递增或重置。 ```verilog always @(posedge clk) begin if (count == 8'b11111111) // 如果计数器的值达到最大值 count <= 8'b00000000; // 重置计数器为0 else count <= count + 1; // 递增计数器的值 end ``` 7. 最后,添加任何其他需要的输出或输入信号,并将其包含在模块的端口列表中。 ```verilog module counter(input clk, output reg [7:0] count); always @(posedge clk) begin if (count == 8'b11111111) count <= 8'b00000000; else count <= count + 1; end endmodule ``` 这是一个简单的Verilog计数器设计示例。你可以根据你的需求进行修改和扩展。希望能对你有所帮助!如果你还有其他问题,请随时提问。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值