十进制数转换BCD码

有必要仔细阐述这一节,目前就是用在数码管显示,在单片机使用时,我们通常是将十进制数字进行/和%运算,得到每个位置的十进制数字,在这里可能是为了节省使用存储器的量,运用的是加三移位法具体其实就是将每个数字不顾位置,各自转换为二进制形式

例如:

255 变成 0010 _0101_0101 的过程

十进制数转换BCD码_第1张图片

移位的次数一定是该数字的二进制位数,加三不确定(加三也是要判断每4位的二进制大于4才加三,所以是每次移位以后都要判断)

module bcd_8421(
						input  wire sys_clk,
						input  wire  sys_rst,
						input  wire [19:0] data,
						
						output reg [3:0] ge,
						output reg [3:0] shi,
						output reg [3:0] bai,
						output reg [3:0] qian,
						output reg [3:0] wan,
						output reg [3:0] shi_wan

    );
	 
reg [4:0]  cnt_shift;  //移位判断计数器
reg [43:0] data_shift;  //移位判断数据寄存器
reg shift_flag;          //移位判断标志信号

always @(posedge sys_clk or negedge sys_rst) //0到21的循环计数(移位加三的方式实现的话,首位各加一个,999_999十进制换算到二进制有20位)
	if(!sys_rst )
		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) //移位判断标志信号,控制移位判断的先后顺序
	if(!sys_rst )
		shift_flag <= 1'b0;
	else 
		shift_flag <= ~shift_flag;
	
always @(posedge sys_clk or negedge sys_rst) //data_shift有44位,其中高24位是999_999形成的BCD码需要24位,低20位是999_999的二进制形式是20位
	if(!sys_rst )
		data_shift <=44'b0;
	else if (cnt_shift == 5'd0)
		data_shift <= {24'b0, data };	
		else if ((cnt_shift <= 5'd20)&&(shift_flag==1'b0))   //cnt_shift=0时,还是上次的,因为六位数最大变成二进制有20位,所以考虑有20次判断和移位操作,21次稳定,将它输出,
		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 <= 5'd20)&&(shift_flag==1'b1))
		data_shift <= data_shift << 1;
	else 		
		data_shift <= data_shift;
always @(posedge sys_clk or negedge sys_rst) //当计数器等于20时,对各位置的赋值(BCD)
	if(!sys_rst )
		begin 
			ge		  <= 4'b0;
			shi       <= 4'b0;
			bai       <= 4'b0;
			qian      <= 4'b0;
			wan       <= 4'b0;
			shi_wan   <= 4'b0;
		end
	else if (cnt_shift == 5'd21)
		begin
			ge		  <= data_shift[23:20];
		    shi       <= data_shift[27:24];
	        bai       <= data_shift[31:28];
		    qian      <= data_shift[35:32];
	        wan       <= data_shift[39:36];
	        shi_wan   <= data_shift[43:40];
		end 
	else
		begin
			    ge		  <=  ge		     ;
		       shi       <=  shi        ;
			    bai       <=  bai        ;
             qian      <=  qian       ;
             wan       <=  wan        ;
             shi_wan   <=  shi_wan    ;
		end 	
			
endmodule

 

module vtf;

	// Inputs
	reg sys_clk;
	reg sys_rst;
	reg [19:0] data;

	// Outputs
	wire [3:0] ge;
	wire [3:0] shi;
	wire [3:0] bai;
	wire [3:0] qian;
	wire [3:0] wan;
	wire [3:0] shi_wan;

	// Instantiate the Unit Under Test (UUT)
	bcd_8421 uut (
		.sys_clk(sys_clk), 
		.sys_rst(sys_rst), 
		.data(data), 
		.ge(ge), 
		.shi(shi), 
		.bai(bai), 
		.qian(qian), 
		.wan(wan), 
		.shi_wan(shi_wan)
	);

	initial begin
		// Initialize Inputs
		sys_clk = 0;
		sys_rst = 0;
		data = 0;

		// Wait 100 ns for global reset to finish
		#100;
        sys_rst <= 1'b1;
		data <= 20'd0;
		#100000;
		data <= 20'd123_456;
		#100000;
		data <= 20'd999_999;
		#100000;
		data <= 20'd123_895;
		#100000;
		data <= 20'd456_789;
		#100000;
		data <= 20'd999_999;
		#100000;
		data <= 20'd456_789;
		
		// Add stimulus here

	end
	always # 10 sys_clk = ~sys_clk;
      
endmodule

十进制数转换BCD码_第2张图片

你可能感兴趣的:(蓝桥杯,职场和发展)