BCD计数器
1.(1)编写4位计数器
BCD码计数器经常用在需要十进制计数,十进制格式输出的场合
module BCD_counter(Clk,Rst_n,Cin,q,count);
input Clk;//时钟基准端口
input Rst_n;//复位端口
input Cin; //脉冲一次计数一次 计数器进位输入
output [3:0]q;//计数器计数值输出
output reg count;//计数器进位输出
reg [3:0] cnt; //定义计数器寄存器
always @(posedge Clk or negedge Rst_n) //内部信号cnt计数
if(!Rst_n)
cnt <= 4'd0;
else if(Cin == 1'b1) begin
if(cnt == 4'd9)
cnt <= 4'd0;
else cnt <= cnt + 4'b1;
end
else cnt <= cnt;
assign q = count;
always @(posedge Clk or negedge Rst_n) //计数满溢出count
if(!Rst_n)
count <= 1'b0;
else if(Cin == 1'b1 && cnt == 4'd9)
count <= 1'b1;
else
count <= 1'b0;
endmodule
1.(2)编写仿真文件
`timescale 1ns/1ns
`define period_clock 20
module BCD_counter_tb;
reg Clock;
reg Rst_n;
reg Cin;
wire q;
wire count;
BCD_counter BCD_counter0(
.Clk(Clock),
.Rst_n(Rst_n),
.Cin(Cin),
.q(q),
.count(count)
);
initial Clock = 1;
always #(`period_clock/2) Clock = ~Clock;
initial begin
Rst_n = 0;
#(`period_clock*10)
Rst_n = 1;
repeat(50) begin
Cin = 0;
#(`period_clock*5) Cin = 1;
#(`period_clock) Cin = 0;
end
#(`period_clock*100);
$stop;
end
endmodule
仿真结果
2.(1)级联3个4位计数器
module BCD_top(Clock,Rst_n,Cin,q,count);
input Clock;//时钟基准端口
input Rst_n;//复位端口
input Cin; //脉冲一次计数一次 计数器进位输入
output [11:0]q;//计数器计数值输出
output count;//计数器进位输出
wire [3:0] q0,q1,q2;
wire count;
wire count0;
wire count1;
assign q = {q2,q1,q0}; //位拼接
BCD_Counter BCD_counter0(
.Clk(Clock),
.Rst_n(Rst_n),
.Cin(Cin),
.q(q0),
.count(count0)
);
BCD_Counter BCD_counter1(
.Clk(Clock),
.Rst_n(Rst_n),
.Cin(count0),
.q(q1),
.count(count1)
);
BCD_Counter BCD_counter2(
.Clk(Clock),
.Rst_n(Rst_n),
.Cin(count1),
.q(q2),
.count(count)
);
endmodule
2.(2)仿真文件
`timescale 1ns/1ns
`define Clock_period 20
module BCD_top_tb;
reg Clk;
reg Rst_n;
reg Cin;
wire [11:0]q;
wire count;
BCD_top BCD_top_tb0(
.Clock(Clk),
.Rst_n(Rst_n),
.Cin(Cin),
.q(q),
.count(count)
);
initial Clk = 1;
always #(`Clock_period/2) Clk = ~Clk;
initial begin
#(`Clock_period*5);
Rst_n = 1'b0;
Cin=1'b1;
#(`Clock_period*10);
Rst_n = 1'b1;
#(`Clock_period*10);
Cin=1'b1;
#(`Clock_period*5000);
$stop;
end
endmodule
仿真结果
问题:高位低位计数器计数数值满溢出count信号后产生cin信号延迟,导致总效果从999跳变990。
原因:同步时序逻辑电路存在D触发器延迟。
解决方法
更改底层 BCD_Counter模块、
将时序逻辑改为组合逻辑。
module BCD_Counter(Clk,Rst_n,Cin,q,count);
input Clk;//时钟基准端口
input Rst_n;//复位端口
input Cin; //脉冲一次计数一次 计数器进位输入
output [3:0]q;//计数器计数值输出
output count;//计数器进位输出
reg [3:0] cnt; //定义计数器寄存器
always @(posedge Clk or negedge Rst_n) //内部信号cnt计数
if(!Rst_n)
cnt <= 4'd0;
else if(Cin == 1'b1) begin
if(cnt == 4'd9)
cnt <= 4'd0;
else cnt <= cnt + 4'b1;
end
else cnt <= cnt;
assign q = cnt;
assign count = (Cin == 1'b1 && cnt == 4'd9);
endmodule