23- BCD码

发布时间 2023-07-06 22:23:28作者: Icer_Newer

1.BCD码

  • 数码管动态显示的data[19:0]使用二进制数表示的多位十进制数,不能直接生成段选和片选信号,需要使用BCD码表示的十进制数
  • BCD码(Binary-Coded Decimal),又称为二-十进制码,使用四位二进制数来表示1位十进制数中的0-9这十个数,是一种二进制的数字编码形式,用二进制编码的十进制代码
  • 分类:有权码和无权码,这里的权字表示权值,有权码四位二进制数中的
  • 有权码:8421码,5421码,2421码
  • 无权码:余三码,余三循环码,格雷码
  • 使用多位数码管表示234,二进制表示就是1110_1010,使用8421码表示0010_0011_0100
  • 使用多位数码管显示234,需要使用动态扫描的方式,要依次显示个位,十位,百位,要求能从传入的数据中得到个位,十位,百位,所以使用BCD码可以直接得到位选信号和段选信号

1.1 二进制数转换为BCD码

  • 实现转换的第一步,就是在输入的二进制码之前补多少个0,补(十进制数位数*4)个0
  • 234 -- 前面补12个0,然后看BCD码每一位,如果小于等于4,就保持不变,进行移位操作(左移);如果大于4,就将补的BCD码进行加3
  • 直到二进制数为0,补充的BCD码位就是对应的二进制数的BCD码,十进制数-->二进制数-->BCD码
  • 移位次数:输入多少位二进制数,就会移位多少次

2.BCD码转换模块

2.1 模块框图

添加BCD码转换模块

  • 输入时钟和复位信号
  • 输入十进制数的二进制编码
  • 输出六路BCD码4bit,输出的6路BCD码分别用个位,十位,百位,千位,万位,十万位表示

    系统框图需要进行修改

2.2 波形图

  • 二进制码向BCD码的转换是通过判断运算加移位操作实现的,移位次数是与二进制数的位数相关的,需要移位计数器对于判断运算和移位次数进行计数,移位次数是20次,所以位宽为5bit
  • 需要一个中间变量存储中间的数据,data_shift[43:0],(二进制数位数+BCD码位数)
  • 判断运算在前,移位操作在后,需要一个标志信号区分这两个操作(shift_flag),但是这两个操作是在一个时钟周期内完成的,每次移位操作都是在判断计算之后进行的

2.3 RTL

module bcd_8421(
	input	wire			sys_clk,
	input	wire			sys_rst_n,
	input	wire	[19:0]	data,
	
	output	reg	[3:0]	unit	,
	output	reg	[3:0]	ten		,
	output	reg	[3:0]	hun		,
	output	reg	[3:0]	thou	,
	output	reg	[3:0]	t_thou	,
	output	reg	[3:0]	h_hun	,
	
);

	reg	[4:0]	cnt_shift;
	reg	[43:0]	data_shift;
	reg			shift_flag;
	
	
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_clk == 1'b1)
			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;
			
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_clk == 1'b1)
			data_shift <= 44'b0;
		else if(cnt_shift == 5'd0)
			data_shift <= {24'b0,data};
		else if((shift_flag == 1'b0) && (cnt_shift <= 20))
			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((shift_flag == 1'b1)&&(cnt_shift <= 20))
			data_shift <= data_shift << 1;
		else	
			data_shift <= data_shift;
			
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_clk == 1'b1)
			shift_flag <= 1'b0;
		else 
			shift_flag <= ~shift_flag;
	
	// 输出信号
	always@(posedge sys_clk or negedge sys_rst_n)
		if(sys_clk == 1'b1)
			begin
				unit	<= 4'b0;
				ten		<= 4'b0;
				hun		<= 4'b0;
				thou	<= 4'b0;
				t_thou	<= 4'b0;
				h_hun	<= 4'b0;
			end
		else if(data_shift == 5'd21)
			begin
				unit	<= data_shift[23:20];
				ten		<= data_shift[27:24];
                hun		<= data_shift[31:28];
                thou	<= data_shift[35:32];
                t_thou	<= data_shift[39:36];
				h_hun	<= data_shift[43:40];
			end
	
endmodule

2.4 Testbench


`timescale 1ns/1ns
module tb_bcd_8421();
	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]	thou		;
	wire [3:0]	t_thou		;
	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;
		#2000;
		data <= 20'd999_999;
	end
	
	always #10 sys_clk = ~sys_clk;
	
	
	bcd_8421 bcd_8421_inst(
	.sys_clk	(sys_clk	)	,
	.sys_rst_n	(sys_rst_n	)	,
	.data		(data		)	,
	.unit		(unit		)	,
	.ten		(ten		)	,
	.hun		(hun		)	,
	.thou		(thou		)	,
	.t_thou		(t_thou		)	,
	.h_hun		(h_hun		)	,
	
);
	
	

endmodule

2.5 仿真