基于Verilog HDL 的任意模计数器的实现

本文章是笔者大学数字逻辑设计与应用课程的研讨报告,讨论了基于Verilog HDL 的任意模计数器的实现。希望对你有所帮助

1.使用同步状态机实现模31计数器

同步状态机实现任意模计数器只需要使得状态机在该模个状态间循环,这里选用D触发器。显然要具有31状态,至少需要5位二进制数.为实现自启动功能,防止进入其他循环,将11111下一状态设置为00000.

Inputs

Outputs

QE

QD

QC

QB

QA

QE*

QD*

QC*

QB*

QA*

0

0

0

0

0

0

0

0

0

1

0

0

0

0

1

0

0

0

1

0

0

0

0

1

0

0

0

0

1

1

0

0

0

1

1

0

0

1

0

0

0

0

1

0

0

0

0

1

0

1

0

0

1

0

1

0

0

1

1

0

0

0

1

1

0

0

0

1

1

1

0

0

1

1

1

0

1

0

0

0

0

1

0

0

0

0

1

0

0

1

0

1

0

0

1

0

1

0

1

0

0

1

0

1

0

0

1

0

1

1

0

1

0

1

1

0

1

1

0

0

0

1

1

0

0

0

1

1

0

1

0

1

1

0

1

0

1

1

1

0

0

1

1

1

0

0

1

1

1

1

0

1

1

1

1

1

0

0

0

0

1

0

0

0

0

1

0

0

0

1

1

0

0

0

1

1

0

0

1

0

1

0

0

1

0

1

0

0

1

1

1

0

0

1

1

1

0

1

0

0

1

0

1

0

0

1

0

1

0

1

1

0

1

0

1

1

0

1

1

0

1

0

1

1

0

1

0

1

1

1

1

0

1

1

1

1

1

0

0

0

1

1

0

0

0

1

1

0

0

1

1

1

0

0

1

1

1

0

1

0

1

1

0

1

0

1

1

0

1

1

1

1

0

1

1

1

1

1

0

0

1

1

1

0

0

1

1

1

0

1

1

1

1

0

1

1

1

1

1

0

1

1

1

1

0

0

0

0

0

0

1

1

1

1

1

0

0

0

0

0

根据上表可以画出卡罗图,写出各位的新态方程

QE*=ABCDE’+D’E+C’E+B’E

QD*=DC’+DB’+D’CBA+DCBA’E’

QC*=CB’+C’BA+D’CA’+E’DCBA’

QB*=AB’+A’BE’+A’BD’+A’BC’D

QA*=A’B’+A’BE’+A’BD’+A’BC’D

Verilog代码如下

module Dflipflop(input clk,D,
output reg Q);
initial begin Q<=1;end
always @(posedge clk) Q<=D;
endmodule

module count31(input clk,
output [4:0]Q);
wire EN,DN,CN,BN,AN;
assign EN=(Q[0]&Q[1]&Q[2]&Q[3]&~Q[4])|(~Q[3]&Q[4])|(~Q[2]&Q[4])|(~Q[1]&Q[4]);
assign DN=(Q[3]&~Q[2])|(Q[3]&~Q[1])|(~Q[3]&Q[2]&Q[1]&Q[0])|(~Q[4]&Q[3]&Q[2]&Q[1]&~Q[0]);
assign CN=(Q[2]&~Q[1])|(~Q[2]&Q[1]&Q[0])|(~Q[3]&Q[2]&~Q[0])|(~Q[4]&Q[3]&Q[2]&Q[1]&~Q[0]);
assign BN=(Q[0]&~Q[1])|(~Q[0]&Q[1]&~Q[4])|(~Q[0]&Q[1]&~Q[3])|(~Q[0]&Q[1]&~Q[2]&Q[3]);
assign AN=(~Q[0]&~Q[1])|(~Q[0]&Q[1]&~Q[4])|(~Q[0]&Q[1]&~Q[3])|(~Q[0]&Q[1]&~Q[2]&Q[3]);
Dflipflop E(.clk(clk),.D(EN),.Q(Q[4]));
Dflipflop D(.clk(clk),.D(DN),.Q(Q[3]));
Dflipflop C(.clk(clk),.D(CN),.Q(Q[2]));
Dflipflop B(.clk(clk),.D(BN),.Q(Q[1]));
Dflipflop A(.clk(clk),.D(AN),.Q(Q[0]));
Endmodule

添加测试激励

module testbench();
reg clk;
wire [4:0]Q;
initial begin clk<=0; end
always #10 clk=~clk;
count31 test(.clk(clk),.Q(Q));
endmodule

 

2.使用移位寄存器计数器实现模31计数器

 数字电路中,移位寄存器是一种在若干相同时间脉冲下工作的以触发器为基础的器件,数据以并行或串行的方式输入到该器件中,然后每个时间脉冲依次向左或右移动一个比特,在输出端进行输出。这里以74x193移位寄存器为例,其逻辑功能如图

要使用移位寄存器实现计数,使用独热码是最简易的方式。这里以右移计数为例。使用送数功能将初值置1000,然后进入右移功能,输出 QD接DSR端,这样就实现了1000->0100->0010->0001->……的循环计数功能。而要实现能够自启动的右移计数器需要将输出反馈接到置数端,即如果后面几位没有0,则产生一个1,若已经存在1,则产生1个0,这样经过一段时间,输出就会只含有1个1。状态转换原理如图。多模同理

要实现任意模的计数器,需要使用多个74x193级联,将前一级74x193的输出QA连接到后一级74x193的DSR端,所有除第一位的有效输出通过与非门连接后接第一级的DSR端,这样就实现了自启动的模31计数器。

Verilog代码如下

 

module _74193(input clk,CR,S1,S0,SR,SL,A,B,C,D,
output reg QA,QB,QC,QD);
initial begin QA<=1;QB<=1;QC<=1;QD<=1; end
always @(posedge clk or negedge CR)
begin
if(!CR) begin QA<=0;QB<=0;QC<=0;QD<=0; end
else 
begin
if(S1&S0) begin QA<=A;QB<=B;QC<=C;QD<=D; end
if(~S1&S0) begin QA<=SR;QB<=QA;QC<=QB;QD<=QC; end
if(S1&~S0) begin QA<=QB;QB<=QC;QC<=QD;QD<=SL; end
if(~S1&~S0) begin QA<=QA;QB<=QB;QC<=QC;QD<=QD; end
end
end
endmodule

module count31(input clk,
output wire[30:0] Q);
wire j;
assign j=(Q[29:0]>=1)?0:1;
_74193 _1(clk,1,0,1,j,0,0,0,0,0,Q[0],Q[1],Q[2],Q[3]);
_74193 _2(clk,1,0,1,Q[3],0,0,0,0,0,Q[4],Q[5],Q[6],Q[7]);
_74193 _3(clk,1,0,1,Q[7],0,0,0,0,0,Q[8],Q[9],Q[10],Q[11]);
_74193 _4(clk,1,0,1,Q[11],0,0,0,0,0,Q[12],Q[13],Q[14],Q[15]);
_74193 _5(clk,1,0,1,Q[15],0,0,0,0,0,Q[16],Q[17],Q[18],Q[19]);
_74193 _6(clk,1,0,1,Q[19],0,0,0,0,0,Q[20],Q[21],Q[22],Q[23]);
_74193 _7(clk,1,0,1,Q[23],0,0,0,0,0,Q[24],Q[25],Q[26],Q[27]);
_74193 _8(clk,1,0,1,Q[27],0,0,0,0,0,Q[28],Q[29],Q[30],);
Endmodule

 

RTL分析如图

仿真代码如下

module testbench();
reg clk;
wire [30:0] Q;
initial clk<=0;
always #10 clk=~clk;
count31 c(clk,Q);
endmodule

 为验证自启动功能,初始状态设置为1111111……111,可见,计数器一段时间后可以进入正常循环状态

 

3.使用74x163模块实现模31计数器

74LS163是常用的四位二进制可预置的同步加法计数器,其功能表如图

一个74ls163最多实现模16的计数器。要实现任意模计数器可以采用反馈清零法。在多个芯片级联(将前一级的进位输出接到后一级的EP端)的最大状态大于需要模的时候,将输出结果通过与或非逻辑门连接到芯片的清零端,每当输出该结果时状态清零,这样就实现了任意模的计数器。显然,无论初态如何,该计数器最终都能进入到相应循环。

要实现模32计数器可以采用两片74x163级联的方式形成256位计数器。即将74LS163的进位端连接到第二个74x163的EP端口,每当产生一个进位脉冲时,第二片74x163状态码+1.这样就实现了16x16位的计数器。要实现模31,采用反馈清零法,用与非门将输出接至清零端,当状态码为00011110时,状态清零,这样就实现了模31位计数器

module _74163(
 input clk,CR,LD,ET,EP,[3:0]D,
 output  reg [3:0]Q,
 output  CO
    );
    initial begin Q=4'b0000; end
    always@(posedge clk)
    begin
    if(~CR) begin Q=4'b0000; end
    else if(~LD)begin Q<=D; end
    else if(~ET|~EP)begin Q<=Q; end
    else Q<=Q+4'b1;
    end
    assign CO=Q[0]&Q[1]&Q[2]&Q[3];
endmodule

module counter31(
input clk,
 output [4:0]OUT);
    wire clk1,clk2;
    wire judge,CO;
    wire [3:0]OUTA,OUTB;
    _74163 a(.clk(clk1),.CR(~judge),.LD(1),.ET(1),.EP(1),.Q(OUTA),.CO(CO));
    _74163 b(.clk(clk1),.CR(~judge),.LD(1),.ET(CO),.EP(1),.Q(OUTB));
    assign OUT[4]=OUTB[0];
    assign OUT[3]=OUTA[3];
    assign OUT[2]=OUTA[2];
    assign OUT[1]=OUTA[1];
    assign OUT[0]=OUTA[0];
    assign judge=OUT[4]&OUT[3]&OUT[2]&OUT[1]&~OUT[0];
endmodule

 

进行RTL分析得到如图结果

添加测试激励

 

module testbench();
reg clk;
wire [4:0]OUT;
initial begin clk<=0; end
always #10 clk<=~clk;
counter31 s(clk,OUT);
endmodule

 

 

4.口袋实验室的实现

版型xc7a35tfttg256-1数码管为六位八段数码管,因此需要动态扫描显示结果

在板子上有一个50MHZ的脉冲信号

可通过分频器将其转化为1Hz脉冲和1000Hz脉冲。其中1Hz的信号用于驱动计数模块,1000Hz信号用于驱动显示模块。

这里选择在74x163产生的模31计数器代码基础上更改代码

 

//74x163模块的实现
module _74163(
 input clk,CR,LD,ET,EP,[3:0]D,
 output  reg [3:0]Q,
 output  CO
    );
    initial begin Q=4'b0000; end
    always@(posedge clk)
    begin
    if(~CR) begin Q=4'b0000; end
    else if(~LD)begin Q<=D; end
    else if(~ET|~EP)begin Q<=Q; end
    else Q<=Q+4'b1;
    end
    assign CO=Q[0]&Q[1]&Q[2]&Q[3];
endmodule
//数码管显示模块
module display32(input[4:0] IN,
input  clk1,
output [7:0]DISPLAYOUT,
output  DIG0,DIG1);
reg [7:0] D[9:0];
reg [7:0]DIG,OUT1,OUT2;
initial begin
    D[0]=8'b11101110;
    D[1]=8'b01100000; 
    D[2]=8'b11001101; 
    D[3]=8'b11101001;
    D[4]=8'b01100011;    
    D[5]=8'b10101011;    
    D[6]=8'b10101111;   
    D[7]=8'b11100000; 
    D[8]=8'b11101111;  
    D[9]=8'b11101011;    
    DIG=8'b00000000;
    OUT1=D[(IN-(IN%10))/10];
    OUT2=D[IN%10];
    end
    
    always@(IN)
    begin
    OUT1<=D[(IN-(IN%10))/10];
    OUT2<=D[IN%10];
    end
    always @(posedge clk1)  
    begin
     DIG<=~DIG; 
     end
     assign DIG0=~DIG[0];
     assign DIG1=DIG[0];
     assign   DISPLAYOUT=((~DIG)&OUT1)|(DIG&OUT2); 
endmodule
//分频得到1Hz信号
module clk_1s(input clk,output reg clk1);
reg [31:0] cnt;
initial begin  cnt<='d0;clk1<=0; end
always @(posedge clk) 
begin 
if(cnt=='d24999999) begin clk1=~clk1;cnt='d0; end
else cnt<=cnt+5'd1;
end
endmodule
//分频得到1kHz信号
module clk_1ms(input clk,output reg clk2);
reg [31:0] cnt;
initial begin  cnt<='d0;clk2<=0; end
always @(posedge clk)
begin
if(cnt=='d24999) begin clk2=~clk2;cnt='d0; end
else cnt=cnt+5'd1;
end
endmodule
//模31计数器实现与展示
module counter31(
input clk,
output [7:0] DISPLAYOUT,
 output DIG0,DIG1,DIG2,DIG3,DIG4,DIG5,
 output [4:0]OUT);
    wire clk1,clk2;
    wire judge,CO;
    wire [3:0]OUTA,OUTB;
    assign  DIG2=1;
    assign  DIG3=1;
    assign  DIG4=1;
    assign  DIG5=1;
    clk_1s _1s(clk,clk1);
    clk_1ms _1ms(clk,clk2);
    _74163 a(.clk(clk1),.CR(~judge),.LD(1),.ET(1),.EP(1),.Q(OUTA),.CO(CO));
    _74163 b(.clk(clk1),.CR(~judge),.LD(1),.ET(CO),.EP(1),.Q(OUTB));
    assign OUT[4]=OUTB[0];
    assign OUT[3]=OUTA[3];
    assign OUT[2]=OUTA[2];
    assign OUT[1]=OUTA[1];
    assign OUT[0]=OUTA[0];
    assign judge=OUT[4]&OUT[3]&OUT[2]&OUT[1]&~OUT[0];
    display32 c32(OUT,clk2,DISPLAYOUT,DIG0,DIG1);
endmodule

set_property IOSTANDARD LVCMOS33 [get_ports DIG0]
set_property IOSTANDARD LVCMOS33 [get_ports DIG1]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DISPLAYOUT[0]}]
set_property PACKAGE_PIN G12 [get_ports DIG0]
set_property PACKAGE_PIN H13 [get_ports DIG1]
set_property PACKAGE_PIN P11 [get_ports {DISPLAYOUT[7]}]
set_property PACKAGE_PIN N12 [get_ports {DISPLAYOUT[6]}]
set_property PACKAGE_PIN D4 [get_ports clk]
set_property PACKAGE_PIN L14 [get_ports {DISPLAYOUT[5]}]
set_property PACKAGE_PIN L13 [get_ports {DISPLAYOUT[4]}]
set_property PACKAGE_PIN K13 [get_ports {DISPLAYOUT[3]}]
set_property PACKAGE_PIN K12 [get_ports {DISPLAYOUT[2]}]
set_property PACKAGE_PIN P13 [get_ports {DISPLAYOUT[1]}]
set_property PACKAGE_PIN M14 [get_ports {DISPLAYOUT[0]}]
set_property PACKAGE_PIN M12 [get_ports DIG2]
set_property PACKAGE_PIN N13 [get_ports DIG3]
set_property PACKAGE_PIN N14 [get_ports DIG4]
set_property PACKAGE_PIN N11 [get_ports DIG5]
set_property IOSTANDARD LVCMOS33 [get_ports DIG2]
set_property IOSTANDARD LVCMOS33 [get_ports DIG3]
set_property IOSTANDARD LVCMOS33 [get_ports DIG4]
set_property IOSTANDARD LVCMOS33 [get_ports DIG5]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk]
set_property IOSTANDARD LVCMOS33 [get_ports {OUT[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {OUT[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {OUT[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {OUT[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {OUT[0]}]
set_property PACKAGE_PIN N6 [get_ports {OUT[4]}]
set_property PACKAGE_PIN T5 [get_ports {OUT[3]}]
set_property PACKAGE_PIN R7 [get_ports {OUT[2]}]
set_property PACKAGE_PIN R8 [get_ports {OUT[1]}]
set_property PACKAGE_PIN P9 [get_ports {OUT[0]}]

 综合实现后生成bit流文件下载到口袋实验室 

(视频只能放url....最后反正是成功了......)

---------------------------------------------------------------------------------------------------------------------------------

报告到这里就结束了。verilog是自学的。在摸爬滚打的一次次尝试下才完成了这次作业。当然,这次作业不是完美的,它有许多不足之处。比如移位寄存器实现的计数器非常臃肿,此外由于debug次数很多,也在一部分地方留下来冗余的代码,欢迎各位指正。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值