目录
一、BCD码简介
二、十进制转8421BCD码转换思路
三、程序编写
四、仿真验证
总结
一、BCD码简介
BCD码(Binary-Coded Decimal),用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,常应用于计算机内部十进制与二进制之间的转换。
BCD码可分为有权码和无权码两类。其中,常见的有权BCD码有8421码、2421码、5421码;无权BCD码有余3码、余3循环码、格雷码。8421码,顾名思义,自高到低,每个位上的权值分别是8,4,2,1,例如十进制9用8421BCD码表示为1001;2421码和5421码与8421码类似,只是每个位上的权重不同,例如十进制9用2421BCD码表示为1111,十进制9用5421BCD码表示为1100;余3码是在8421码的基础上加3,例如十进制9用余3码表示为1100;余3循环码每个编码中0、1没有确定的权值,相邻码字之间只有一位不同,避免过度码产生的噪声。
下图给出了常用的BCD码
二、十进制转8421BCD码转换思路
以十进制数234为例:
第一步:8'd234对应的二进制8'b1110_1010,由于十进制数234共有三位,每位转换为8421BCD码后对应4个比特位,因此在8'b1110_1010的前边加上3*4=12个0,构成20'b0000_0000_0000_1110_1010
第二步:将20'b0000_0000_0000_1110_1010向左进行移位,每移一位后,分别判断BCD码最高位、次高位、最低位共三组码字对应的十进制码是否大于4,如果该组码字大于4,则在改组对应十进制码的基础上加3,如果该码字小于等于4,则继续进行下一次移位
第三步:向左移位8次后,结束移位,此时前12位就是该十进制对应的8421BCD码

三、程序编写
下图给出该模块的示意图:

输入信号:时钟信号 sys_clk
复位信号 sys_res
输入十进制数 data
输出信号:个位 unit
十位 ten
百位 hun
千位 tho
万位 t_tho
十万位 h_tho
输入信号是20位的二进制数,对应十进制共6位,所以在20位二进制数的前边补上6*4=24个0,构成44位的二进制数,向左移位20次,即可得出对应的8421BCD码
下边给出该模块的时序图:

下边给出Verilog代码:
module bcd_8421(input sys_clk,input sys_res,input [19:0]data,output reg [3:0 ]unit,output reg [3:0 ]ten,output reg [3:0 ]hun,output reg [3:0 ]tho,output reg [3:0 ]t_tho,output reg [3:0 ]h_tho
);
reg [4 : 0]cnt_shift;
reg [43: 0]data_shift;
reg shift_flag;always@(posedge sys_clk or negedge sys_res)if(!sys_res)shift_flag <= 1'b0;elseshift_flag <= ~shift_flag;
always@(posedge sys_clk or negedge sys_res)if(!sys_res)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;always@(posedge sys_clk or negedge sys_res)if(!sys_res)data_shift <= 44'd0;else if(cnt_shift == 5'd0)data_shift <= {24'b0,data};else if(cnt_shift != 5'd0 && cnt_shift < 5'd21 && shift_flag == 1'b1)data_shift <= data_shift << 1;else if(cnt_shift != 5'd0 && cnt_shift < 5'd21 && shift_flag == 1'b0)begindata_shift[43:40] <= data_shift[43:40]>4 ? data_shift[43:40]+ 3: data_shift[43:40];data_shift[39:36] <= data_shift[39:36]>4 ? data_shift[39:36]+ 3: data_shift[39:36];data_shift[35:32] <= data_shift[35:32]>4 ? data_shift[35:32]+ 3: data_shift[35:32];data_shift[31:28] <= data_shift[31:28]>4 ? data_shift[31:28]+ 3: data_shift[31:28];data_shift[27:24] <= data_shift[27:24]>4 ? data_shift[27:24]+ 3: data_shift[27:24];data_shift[23:20] <= data_shift[23:20]>4 ? data_shift[23:20]+ 3: data_shift[23:20];end else if(cnt_shift == 5'd21)data_shift <= data_shift; always@(posedge sys_clk or negedge sys_res)if(!sys_res)beginunit <= 4'd0;ten <= 4'd0;hun <= 4'd0;tho <= 4'd0;t_tho <= 4'd0;h_tho <= 4'd0;end else if(cnt_shift == 5'd21)beginunit <= 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_tho <= data_shift[43:40];end
endmodule
四、仿真验证
下边给出测试文件的代码:
`timescale 1ns/1ns
module tb_bcd_8421();
reg clk ;
reg res ;
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_tho ;initial beginclk <= 1'b0;res <= 1'b0;#200 res <= 1'b1;
end
always #10 clk <= ~clk;
//assign data = 20'd987654;
initial begindata <= 20'd987_654;#1000 data <= 20'd456_123;#2000 data <= 20'd1237_89;#500 data <= 20'd147_852;end
//两次数据间隔时间需大于840nsbcd_8421 u_bcd_8421(.sys_clk (clk) ,.sys_res (res) ,.data (data) ,.unit ( unit ) ,.ten ( ten ) ,.hun ( hun ) ,.tho ( tho ) ,.t_tho ( t_tho) ,.h_tho ( h_tho)
);endmodule
下图是Modelsim中仿真的结果:

每次转换所需的时间至少需要840ns,上图中输入的十进制数20‘d123789与20‘d147852间隔时间小于840ns,因此,20'd123789没有完成转换。
总结
初次创作,难免文章中存在错误,希望读者能够及时纠正并给予私信,望大家共同进步!










![[学习笔记]黑马程序员python教程](https://img-blog.csdnimg.cn/75601c7cf6ef4da0b107543c33e788cd.png)









