前言
提示:这里可以添加本文要记录的大概内容:
BCD码(Binary-Coded Decimal),又称二-十进制码,使用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。
分为有权码(8421 5421 2421码)和无权码(余3码和格雷码)。
有权码计算方式:权重和编码数字之积的和
为十进制数。
例:十进制234=1110-1010(二进制)=0010-0011-0100(8421码)
使用BCD码的原因
:数码管显示234,先显示个位,再显示十位,后显示百位,BCD码可以识别个十百位。
提示:以下是本篇文章正文内容,下面案例可供参考
一、更新系统框图
bcd子模块左侧为待显示data数据(最大值999_999),右侧为个十百千万 十万位。
二、波形图
1.设置最大值
为987654(对应二进制为1111 0001 0010 0000 0110),data的位宽为20位。
2.设置一个移位记数器
,8位二进制转换为BCD码需要左移8次,20位左移20次(对应二进制0001 0100),移位器位宽为5位。声明:需要增加两个状态:还未左移的最初状态和输出结果(提取转化完成的BCD码),故记数0-21共22次。
3.移位产生的中间数据需要寄存,声明一个data_shift寄存器
,其位宽为20位二进制码+24位(6*4)BCD码,位宽为44位。
4.判断信号(是否>4)在前,移位在后,还需要设置一个标志信号
区分这两个操作,也可以看作移位次数记数的条件。
当移位标志信号为低电平时进行判断运算,计数器保持不变,为高电平时进行移位,计数器进行记数。
三、rtl代码和测试代码
module bcd
(
input wire sys_clk , //系统时钟,频率50MHz
input wire sys_rst_n , //复位信号,低电平有效
input wire [19:0] data , //输入需要转换的数据
output reg [3:0] unit , //个位BCD码
output reg [3:0] ten , //十位BCD码
output reg [3:0] hun , //百位BCD码
output reg [3:0] tho , //千位BCD码
output reg [3:0] t_tho , //万位BCD码
output reg [3:0] h_hun //十万位BCD码
);
reg [4:0] cnt_shift ; //移位判断计数器
reg [43:0] data_shift ; //移位判断数据寄存器
reg shift_flag ; //移位判断标志信号
//cnt_shift:从0到21循环计数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_shift <= 5'd0;
else if((cnt_shift == 5'd21) && (shift_flag == 1'b1))
cnt_shift <= 5'd0;
else if(shift_flag == 1'b1)
cnt_shift <= cnt_shift + 1'b1;
else
cnt_shift <= cnt_shift;//低电平保持不变
//data_shift:计数器为0时赋初值,计数器为1~20时进行移位判断操作
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_shift <= 44'b0;
else if(cnt_shift == 5'd0)
data_shift <= {24'b0,data};
else if((cnt_shift <= 20) && (shift_flag == 1'b0))
begin
data_shift[23:20] <= (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]);
data_shift[27:24] <= (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]);
data_shift[31:28] <= (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]);
data_shift[35:32] <= (data_shift[35:32] > 4) ? (data_shift[35:32] + 2'd3) : (data_shift[35:32]);
data_shift[39:36] <= (data_shift[39:36] > 4) ? (data_shift[39:36] + 2'd3) : (data_shift[39:36]);
data_shift[43:40] <= (data_shift[43:40] > 4) ? (data_shift[43:40] + 2'd3) : (data_shift[43:40]);
end
else if((cnt_shift <= 20) && (shift_flag == 1'b1))
data_shift <= data_shift << 1;
else
data_shift <= data_shift;
//shift_flag:移位判断标志信号,用于控制移位判断的先后顺序
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
shift_flag <= 1'b0;
else
shift_flag <= ~shift_flag;
//当计数器等于20时,移位判断操作完成,对各个位数的BCD码进行赋值
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
unit <= 4'b0;
ten <= 4'b0;
hun <= 4'b0;
tho <= 4'b0;
t_tho <= 4'b0;
h_hun <= 4'b0;
end
else if(cnt_shift == 5'd21)
begin
unit <= data_shift[23:20];
ten <= data_shift[27:24];
hun <= data_shift[31:28];
tho <= data_shift[35:32];
t_tho <= data_shift[39:36];
h_hun <= data_shift[43:40];
end
endmodule
`timescale 1ns/1ns
module tb_bcd();
reg sys_clk ;
reg sys_rst_n ;
reg [19:0] data;
wire [3:0] unit ;
wire [3:0] ten ;
wire [3:0] hun ;
wire [3:0] tho ;
wire [3:0] t_tho ;
wire [3:0] h_hun ;
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
//生成模拟数据
data<=20'd0;
#30
sys_rst_n <= 1'b1;
data<=20'd123_456;
#3000
data<=20'd654_321;
#3000
data<=20'd987_654;
#3000
data<=20'd999_999;
end
bcd bcd_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.data (data ) ,
.unit (unit ),
.ten (ten ),
.hun (hun ),
.tho (tho ),
.t_tho (t_tho),
.h_hun (h_hun)
);
endmodule