BCD碼計數器的定義:
對於機器語言,機器與人不同,為了讓人更好的了解機器語言的數據輸出,選用4位二進制數據表示十進制里的每位數據,這便是BCD碼。
以下便是BCD碼與十進制對應的碼表
0-----------0000----------0x0
1-----------0001----------0x1
2-----------0010----------0x2
3-----------0011----------0x3
4-----------0100----------0x4
5-----------0101----------0x5
6-----------0110----------0x6
7-----------0111----------0x7
8-----------1000----------0x8
9-----------1001----------0x9
這里舉個例子,十進制數52,用BCD碼表示即為0101 0010,通過這個例子,就可以很好的了解到BCD碼的實際應用,即更好的區分十進制中的每一位數據。
下面說下這個計數器的設計,其實操作與計數器的基本沒多大區別,重點運用到的就是上一篇講到的計數器的級聯原理,這篇文章的意義是為了為后面講解數碼管的顯示做准備。
新建工程

程序設計:

module BCD_counter(clk,c_in,rst_n,c_out,q);
input clk;//計數器基准時鍾
input c_in;//系統進位輸入
input rst_n;//系統復位
output c_out ;//計數器進位輸出
output [3:0]q;//計數器輸出
reg [3:0]counter,c_out;
//執行計數過程
always@(posedge clk or negedge rst_n)
if(rst_n==0)
counter<=4'd0;
else if (counter==1'b1)
begin
if (counter==9)
counter<=4'd0;
else
counter<=counter+1'b1;
end
else
counter<=counter;
//產生進位信號
always@(posedge clk or negedge rst_n)
if(rst_n==0)
c_out<=1'b0;
else if (c_in==1'b1&&counter==4'd9)
c_out<=1'b1;
else
c_out<=1'b0;
assign q=counter;
endmodule
編寫testbench

`timescale 1ns/1ns
`define clock_period 20
module BCD_counter_tb;
reg clk;
reg c_in;
reg rst_n;
wire c_out;
wire [3:0]q;
BCD_counter u0(.clk(clk),
.c_in(c_in),
.rst_n(rst_n),
.c_out(c_out),
.q(q)
);
initial clk=1'b1;
always#(`clock_period/2) clk=~clk;
initial
begin
c_in=1'b0; //測試即使c_in 為0時,計數器是否會有動作
rst_n=1'b0;
#(`clock_period*200);
rst_n=1'b1;
#(`clock_period*20);
repeat(30) //重復執行30次
begin
c_in=1'b1;
#`clock_period;
c_in=1'b0;
#(`clock_period*5);//保持5個時鍾周期
end
#(`clock_period*20);
$stop;
end
endmodule
設置仿真路徑進行仿真,可以看到每次計數滿9次之后,產生一個c_out的輸出信號。

下面對計數器進行級聯。

module BCD_counter_top(clk,c_in,rst_n,c_out,q);
input clk;//計數器基准時鍾
input c_in;//系統進位輸入
input rst_n;//系統復位
output c_out ;//計數器進位輸出
output [11:0]q;//計數器輸出
wire c_out0,c_out1;
wire [3:0]q0,q1,q2;
BCD_counter u1(.clk(clk),
.c_in(c_in),
.rst_n(rst_n),
.c_out(c_out0),
.q(q0)
);
BCD_counter u2(.clk(clk),
.c_in(c_out0),
.rst_n(rst_n),
.c_out(c_out1),
.q(q1)
);
BCD_counter u3(.clk(clk),
.c_in(c_out1),
.rst_n(rst_n),
.c_out(c_out),
.q(q2)
);
assign q=({q2,q1,q0});//將三個信號拼接起來
endmodule
將其設置為頂層文件,編寫testbench,並設置其路徑。

`timescale 1ns/1ns
`define clock_period 20
module BCD_counter_top_tb;
reg clk;
reg c_in;
reg rst_n;
wire c_out;
wire [11:0]q;
BCD_counter_top BCD_counter_top0(
.clk(clk),
.c_in(c_in),
.rst_n(rst_n),
.c_out(c_out),
.q(q)
);
initial clk = 1'b1;
always#(`clock_period/2) clk = ~clk;
initial begin
rst_n = 1'b0;
c_in = 1'b0;
#(`clock_period*200);
rst_n = 1'b1;
#(`clock_period*20);
c_in = 1'b1;
#(`clock_period*5000);
$stop;
end
endmodule
點擊仿真按鈕進行前仿查看波形,可以看到進位到999后產生了進位輸出,這說明整個設計是正確的。

可以看到q的顯示是按BCD碼的碼表顯示的999,這說明zhegn

