Countbcd
构建一个4位BCD模10计数器,实现个十百千四位的计数器。每个十进制数字使用4位进行编码:q[3:0]是个位,q[7:4]是十位,q[11:8]是百位,q[15:12]是千位,以此类推。每个进制上的进位时也需输出一个使能信号ena。
最开始自己写的代码,采用四个always语句块进行赋值,但是就是时序图对不上,之后发现最重要是有两方面问题:
第一个是always语句块中变量必须是reg类型,自己压根没有意识到;
第二个是使能端信号其实只受数值变化影响,不受时钟信号控制,这部分应该用组合逻辑进行赋值,时序图一直对应不上的原因也是这个,后面的时序结果图也说明了使能端没有拉高,导致变成了模16计数器。(后面附上了这个代码的时序图)
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
always@(posedge clk)begin
if(!reset)begin
q[3:0]<=q[3:0]+4'd1;
ena[1]<=0;
end
else if(!reset && q[3:0]==4'd9)begin
q[3:0]<=4'b0;
ena[1]<=1;
end
else
q[3:0]<=4'b0;
end
always@(posedge clk)begin
if(!reset && ena[1]==1)begin
q[7:4]<=q[7:4]+4'd1;
ena[2]<=0;
end
else if(!reset && q[7:4]==4'd9 && q[3:0]==4'd9)begin
q[7:4]<=4'b0;
ena[2]<=1;
end
else
q[7:4]<=4'b0;
end
always@(posedge clk)begin
if(!reset && ena[2]==1&& ena[1]==1)begin
q[11:8]<=q[11:8]+4'd1;
ena[3]<=0;
end
else if(!reset && q[11:8]==4'd9 && q[7:4]==4'd9 && q[3:0]==4'd9)begin
q[11:8]<=4'b0;
ena[3]<=1;
end
else
q[11:8]<=4'b0;
end
always@(posedge clk)begin
if(!reset && ena[3]==1 && ena[2]==1 && ena[1]==1)begin
q[15:12]<=q[15:12]+4'd1;
end
else if(!reset && q==15'd9999)begin
q[15:12]<=4'b0;
end
else
q[15:12]<=4'b0;
end
endmodule
之后参考了别人的代码,此代码是正确代码,还有更简便的其实是再写一个module,直接进行四次实例化,这个方法我也附在后面。
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
reg [3:0] ones;
reg [3:0] tens;
reg [3:0] hundreds;
reg [3:0] thousands;
always @(posedge clk) begin
if(reset)begin
ones <= 4'b0;
end
else if(ones == 4'd9)begin
ones <=4'b0;
end
else begin
ones <= ones + 4'd1;
end
end
always @(posedge clk)begin
if(reset)begin
tens <= 4'b0;
end
else if(tens == 4'd9 && ones == 4'd9)begin
tens <= 4'b0;
end
else if(ones == 4'd9)begin
tens <= tens + 4'd1;
end
end
always @(posedge clk)begin
if(reset)begin
hundreds <= 4'b0;
end
else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
hundreds <= 4'b0;
end
else if(tens == 4'd9 && ones == 4'd9) begin
hundreds <= hundreds + 4'd1;
end
end
always @(posedge clk)begin
if(reset)begin
thousands <= 4'b0;
end
else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
thousands <= 4'b0;
end
else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
thousands <= thousands + 4'd1;
end
end
assign q = {thousands,hundreds,tens,ones};
assign ena[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
assign ena[2] = ((ones == 4'd9) && (tens == 4'd9)) ? 1'b1 : 1'b0;
assign ena[3] = ((ones == 4'd9) && (tens == 4'd9) && (hundreds == 4'd9)) ? 1'b1: 1'b0;
endmodule
这个是module实例化版本的代码
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
wire [3:0] valid,q0,q1,q2,q3;
assign valid = {{(q2 == 9)&&(q1 == 9)&&(q0 == 9)},{(q[7:4] == 9)&&(q[3:0] == 9)},{q0 == 9},1'b1};
assign ena = {{(q2 == 9)&&(q1 == 9)&&(q0 == 9)},{(q[7:4] == 9)&&(q[3:0] == 9)},q[3:0] == 9};
assign q = {q3,q2,q1,q0};
count count0(clk,reset,q0,valid[0],1'b1);
count count1(clk,reset,q1,valid[1],{(q[7:4] == 9)&&(q[3:0] == 9)});
count count2(clk,reset,q2,valid[2],{(q2 == 9)&&(q1 == 9)&&(q0 == 9)});
count count3(clk,reset,q3,valid[3],{(q3 == 9)&&(q2 == 9)&&(q1 == 9)&&(q0 == 9)});
endmodule
module count(clk,reset,q_a,vld,ena);
input clk;
input reset;
input vld;
input ena;
output [3:0] q_a;
always@(posedge clk) begin
if(reset)
q_a <= 4'd0;
else if((q_a == 4'd9)&&(ena))
q_a <= 0;
else if (vld)begin
q_a <= q_a + 1'b1;
end
end
endmodule