HDLBits练习:Countbcd
题目
题目链接:Countbcd
题目让写一个四位的BCD计数器,可以等价看成0000~9999的计数器,进位规则和我们日常的十进制计数一样。
代码
解法一
通过例化或者修改一位的十进制计数器实现
- 有关ena信号的处理部分,其实是与clk信号无关的;
- 但是,也可以根据clk信号进行设计,需要注意什么时候ena有效
下述代码有关if条件语句的处理是有问题的,但是写的过程中并没有意识到
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)
ena <= 0;
else begin
//这部分代码块有问题
if(q[3:0] == 4'd8)
ena <= 3'b001;
else if(q[7:4]== 4'd9 && q[3:0] == 4'd8)
ena <= 3'b011;
else if(q[11:8] == 4'd9 && q[7:4]== 4'd9 && q[3:0] == 4'd8)
ena <= 3'b111;
else
ena <= 0;
end
end
decade_counter cnt0( clk, reset, 1'b1, q[3:0] );
decade_counter cnt1( clk, reset, ena[1], q[7:4] );
decade_counter cnt2( clk, reset, ena[2], q[11:8] );
decade_counter cnt3( clk, reset, ena[3], q[15:12] );
endmodule
module decade_counter(
input clk,
input reset, // Synchronous active-high reset
input enable,
output [3:0] q);
always @(posedge clk)begin
if(reset)
q <= 4'd0;
else if(enable) begin
if(q == 4'd9)
q <= 4'd0;
else
q <= q + 4'd1;
end
else
q <= q;
end
endmodule
两种修改方式:
- 方式1:
if(q[11:8] == 4'd9 && q[7:4]== 4'd9 && q[3:0] == 4'd8)
ena <= 3'b111;
else if(q[7:4]== 4'd9 && q[3:0] == 4'd8)
ena <= 3'b011;
else if(q[3:0] == 4'd8)
ena <= 3'b001;
else
ena <= 0;
- 方式2:
分开单独考虑,就不会忽略掉某一位的进位
if (q[3:0]==4'd8)
ena[1] <= 1'b1;
else
ena[1] <= 1'b0;
if (q[3:0]==4'd8 && q[7:4]==4'd9)
ena[2] <= 1'b1;
else
ena[2] <= 1'b0;
if (q[3:0]==4'd8 && q[7:4]==4'd9 &&q[11:8]==4'd9)
ena[3] <= 1'b1;
else
ena[3] <= 1'b0;
解法二
与解法一类似,区别在于处理ena信号的方式。
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
assign ena[1] = (q[3:0]==9);
assign ena[2] = (q[7:4]==9)&&ena[1];
assign ena[3] = (q[11:8]==9)&&ena[2];
decade_counter cnt0( clk, reset, 1'b1, q[3:0] );
decade_counter cnt1( clk, reset, ena[1], q[7:4] );
decade_counter cnt2( clk, reset, ena[2], q[11:8] );
decade_counter cnt3( clk, reset, ena[3], q[15:12] );
endmodule
module decade_counter(
input clk,
input reset, // Synchronous active-high reset
input enable,
output [3:0] q);
always @(posedge clk)begin
if(reset)
q <= 4'd0;
else if(enable) begin
if(q == 4'd9)
q <= 4'd0;
else
q <= q + 4'd1;
end
else
q <= q;
end
endmodule
解法三
没有使用1位十进制计数器进行例化处理,这种写法逻辑上感觉很清晰
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)
q <= 'd0;
else begin
q[3:0] <= q[3:0] + 1;
if(ena[1])begin
q[3:0] <= 0;
q[7:4] <= q[7:4]+1;
end
if(ena[2])begin
q[3:0] <= 0;
q[7:4] <= 0;
q[11:8] <= q[11:8]+1;
end
if(ena[3])begin
q[3:0] <= 0;
q[7:4] <= 0;
q[11:8] <= 0;
q[15:12] <= (q[15:12]<9)?q[15:12] +1:0;
end
end
end
assign ena[1] = (q[3:0]==9);
assign ena[2] = (q[7:4]==9)&&ena[1];
assign ena[3] = (q[11:8]==9)&&ena[2];
endmodule