一、题目说明——HDLbits_Countbcd
Build a 4-digit BCD (binary-coded decimal) counter. Each decimal digit is encoded using 4 bits: q[3:0] is the ones digit, q[7:4] is the tens digit, etc. For digits [3:1], also output an enable signal indicating when each of the upper three digits should be incremented.
二、题目分析
分析题目可知,我们需要设计的电路应满足以下特征:
1)功能:实现从0到9999计数 。
2)端口:输入时钟clk和复位信号reset,输出16位宽计数结果信号q和3位宽进位使能信号ena。
3)触发方式:时钟上升沿触发,reset同步且高电平有效。
4)解释说明:16位宽的q被分为了四部分,其中q[3:0]代表个位,q[7:4]代表十位,q[11:8]代表百位,q[15:12]代表千位,每个位的范围很显然是0~9,也就是4’b0000~4‘b1001,其他的情况不能出现;3位宽的ena的每一位分别代表了该位的是否进位,比如当q=16’h0009时,ena应该为3‘b001。
三、实现与总结
需要我们注意的是:
1)ena只有四种情况,即’b000、‘b001、’b011和‘b111。这是因为所有的进位都是个位进位引起的,这里是+1的计数方式,所以不可能出现十位进位而个位不进位的情况。
2)因为使用的是非阻塞赋值,所以如果当某一位为9的时候再赋值ena就晚了。具体的逻辑是检测到q为4’hxxx8、4’hxx98、4’hx998时,对ena赋值,因此可以想到使用casex完成行为级建模。这里要注意描述的顺序,casex只会选择第一个匹配的情况。
3)注意到是0~9999的计数电路,所以对于ena为’b111的情况要分类处理,如果当前的q为9999则清零,否则才选择千位进位且百十个位清零。
4)在判断q是否为9999的时候需要格外小心,可以写为if(q!=16'h9999),但是写为以下的两种是错误的:
错误:if(q!=4'h9999)
错误:if(q!=9999)//这是因为十进制9999其实是十六进制的16‘h270F
以下是代码实现:
module top_module (
input clk,
input reset, // Synchronous active-high reset
output reg [3:1] ena,
output reg [15:0] q);
always @(posedge clk)begin
if (reset)begin
q <= 0;
ena <= 0;
end
else begin
q<=q+1;
casex(q) //触发进位标志
16'hx998:begin ena<=3'b111;end
16'hxx98:begin ena<=3'b011;end
16'hxxx8:begin ena<=3'b001;end
default:;
endcase
case(ena) //进位操作
'b000:;
'b001:begin q[7:4] <= q[7:4]+4'b0001;q[3:0]<=4'b0;ena<=0;end
'b011:begin q[11:8] <= q[11:8]+4'b0001;q[7:0]<=8'b0;ena<=0;end
'b111:begin
ena<=0;
if(q!=16'h9999)begin //注意16‘h9999不等于9999
q[15:12] <= q[15:12]+4'b0001;
q[11:0]<=12'b0;
end
else
q<=0;
end
default:ena<=0;
endcase
end
end
endmodule