verilog实现十进制正数与ASCII码互转

verilog实现十进制正数与ASCII码互转

1.小位宽数实现转ASCII码

1.小整数十进制转BCD码(8421码)

十进制数 0 1 2 3 4 5 6 7 8 9
8421码 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001

2.BCD码(8421码)转ASCII码

8421码 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001
ASCII码(BIN) 110000 110001 110010 110011 110100 110101 110110 110111 111000 111001
ASCII码(DEC) 48 49 50 51 52 53 54 55 56 57
ASCII码(HEX) 30 31 32 33 34 35 36 37 38 39

2.大位宽正整数实现转ASCII码

1.整数数位分割(BCD码)

​ 分离数位有多种方法,除法和比较法,除法理解简单,但是在verilog中占用资源严重,需要使用到除法IP核,以下采用比较法。

比较法分离数位:

复制代码
假设一个数为num=123,使用A,B,C来代替百位,十位和个位。(以下为伪代码)

分离百位:
if(num >=900)      A = 9; num = num - 900;
else if(num >=800) A = 8; num = num - 800;
else if(num >=700) A = 7; num = num - 700;
else if(num >=600) A = 6; num = num - 600;
else if(num >=500) A = 5; num = num - 500;
else if(num >=400) A = 4; num = num - 400;
else if(num >=300) A = 3; num = num - 300;
else if(num >=200) A = 2; num = num - 200;
else if(num >=100) A = 1; num = num - 100;
else 			  A = 0; num = num      ;

分离十位和个位:
if(num >=90)      B = 9; C = num - 90;
else if(num >=80) B = 8; C = num - 80;
else if(num >=70) B = 7; C = num - 70;
else if(num >=60) B = 6; C = num - 60;
else if(num >=50) B = 5; C = num - 50;
else if(num >=40) B = 4; C = num - 40;
else if(num >=30) B = 3; C = num - 30;
else if(num >=20) B = 2; C = num - 20;
else if(num >=10) B = 1; C = num - 10;
else 			 B = 0; C = 0      ;

2.verilog实现十进制正数转ASCII码

verilog 复制代码
module	dec_ascii16(
	input			clk			,
	input			rst			,
	
	input			valid		,
	input	[15:0]	din			,//MAX = 65535
	
	output			rdy			,
	output	[39:0]	dout
);

	reg	[$clog2(9999)-1:0]	num0;
	reg	[$clog2(999)-1:0]	num1;
	reg	[$clog2(99)-1:0]	num2;

	reg	[4*4-1:0]	dig0;
	reg	[3*4-1:0]	dig1;
	reg	[2*4-1:0]	dig2;
	reg	[1*4-1:0]	dig3;
	reg	[1*4-1:0]	dig4;
	
	reg	[3:0]		valid_d;

	always @(posedge clk)begin
		if(rst)begin
			valid_d	<= 0;
		end else begin
			valid_d	<= {valid_d,valid};
		end
	end
	
	always @(posedge clk)begin
		if(rst)begin
			dig0	<= 0;
			num0	<= 0;
		end else begin
			if(din >= 60000)     begin	dig0 <= {dig0,4'd6};	num0 <= din - 60000;	end
			else if(din >= 50000)begin	dig0 <= {dig0,4'd5};	num0 <= din - 50000;	end
			else if(din >= 40000)begin	dig0 <= {dig0,4'd4};	num0 <= din - 40000;	end
			else if(din >= 30000)begin	dig0 <= {dig0,4'd3};	num0 <= din - 30000;	end
			else if(din >= 20000)begin	dig0 <= {dig0,4'd2};	num0 <= din - 20000;	end
			else if(din >= 10000)begin	dig0 <= {dig0,4'd1};	num0 <= din - 10000;	end
			else 				 begin	dig0 <= {dig0,4'd0};	num0 <= din 	   ;	end
		end	
	end
	
	always @(posedge clk)begin
		if(rst)begin
			dig1	<= 0;
			num1	<= 0;
		end else begin		
			if	   (num0 >= 9000)begin	dig1 <= {dig1,4'd9};	num1 <= num0 - 9000;	end
			else if(num0 >= 8000)begin	dig1 <= {dig1,4'd8};	num1 <= num0 - 8000;	end
			else if(num0 >= 7000)begin	dig1 <= {dig1,4'd7};	num1 <= num0 - 7000;	end
			else if(num0 >= 6000)begin	dig1 <= {dig1,4'd6};	num1 <= num0 - 6000;	end
			else if(num0 >= 5000)begin	dig1 <= {dig1,4'd5};	num1 <= num0 - 5000;	end
			else if(num0 >= 4000)begin	dig1 <= {dig1,4'd4};	num1 <= num0 - 4000;	end
			else if(num0 >= 3000)begin	dig1 <= {dig1,4'd3};	num1 <= num0 - 3000;	end
			else if(num0 >= 2000)begin	dig1 <= {dig1,4'd2};	num1 <= num0 - 2000;	end
			else if(num0 >= 1000)begin	dig1 <= {dig1,4'd1};	num1 <= num0 - 1000;	end
			else 				  begin	dig1 <= {dig1,4'd0};	num1 <= num0 	   ;	end
		end	
	end	
	
	always @(posedge clk)begin
		if(rst)begin
			dig2	<= 0;
			num2	<= 0;
		end else begin		
			if	   (num1 >= 900)begin	dig2 <= {dig2,4'd9};	num2 <= num1 - 900;	end
			else if(num1 >= 800)begin	dig2 <= {dig2,4'd8};	num2 <= num1 - 800;	end
			else if(num1 >= 700)begin	dig2 <= {dig2,4'd7};	num2 <= num1 - 700;	end
			else if(num1 >= 600)begin	dig2 <= {dig2,4'd6};	num2 <= num1 - 600;	end
			else if(num1 >= 500)begin	dig2 <= {dig2,4'd5};	num2 <= num1 - 500;	end
			else if(num1 >= 400)begin	dig2 <= {dig2,4'd4};	num2 <= num1 - 400;	end
			else if(num1 >= 300)begin	dig2 <= {dig2,4'd3};	num2 <= num1 - 300;	end
			else if(num1 >= 200)begin	dig2 <= {dig2,4'd2};	num2 <= num1 - 200;	end
			else if(num1 >= 100)begin	dig2 <= {dig2,4'd1};	num2 <= num1 - 100;	end
			else 				begin	dig2 <= {dig2,4'd0};	num2 <= num1 	  ;	end
		end	
	end	
	
	always @(posedge clk)begin
		if(rst)begin
			dig3	<= 0;
			dig4	<= 0;
		end else begin		
			if	   (num2 >= 90)begin	dig3 <= {dig3,4'd9};	dig4 <= num2 - 90;	end
			else if(num2 >= 80)begin	dig3 <= {dig3,4'd8};	dig4 <= num2 - 80;	end
			else if(num2 >= 70)begin	dig3 <= {dig3,4'd7};	dig4 <= num2 - 70;	end
			else if(num2 >= 60)begin	dig3 <= {dig3,4'd6};	dig4 <= num2 - 60;	end
			else if(num2 >= 50)begin	dig3 <= {dig3,4'd5};	dig4 <= num2 - 50;	end
			else if(num2 >= 40)begin	dig3 <= {dig3,4'd4};	dig4 <= num2 - 40;	end
			else if(num2 >= 30)begin	dig3 <= {dig3,4'd3};	dig4 <= num2 - 30;	end
			else if(num2 >= 20)begin	dig3 <= {dig3,4'd2};	dig4 <= num2 - 20;	end
			else if(num2 >= 10)begin	dig3 <= {dig3,4'd1};	dig4 <= num2 - 10;	end
			else 			   begin	dig3 <= {dig3,4'd0};	dig4 <= num2 	 ;	end
		end	
	end	
	
	assign	dout	=	{4'h3,dig0[4*4-1 -:4],4'h3,dig1[3*4-1 -:4],4'h3,dig2[2*4-1 -:4],4'h3,dig3[1*4-1 -:4],4'h3,dig4[1*4-1 -:4]};
	assign	rdy 	=	valid_d[3];
	
endmodule

3.大位宽ASCII码转正整数

1.BCD码转整数

复制代码
使用A,B,C来代替百位,十位和个位。(以下为伪代码)
num = A*100 + B*10 + C
dec(100) = bin(1100100) = 2^6 + 2^5 + 2^2
dec(10)  = bin(1010)    = 2^3 + 2^1
num =A*(2^6 + 2^5 + 2^2) + B*(2^3 + 2^1) + C

2.verilog实现ASCII码转十进制正数

verilog 复制代码
module	ascii_dec16(
	input				clk			,
	input				rst			,
	
	input				valid		,
	input		[39:0]	din			,//MAX = 65535
	
	output				rdy			,
	output	reg	[15:0]	dout
);

	reg	[$clog2(60000)-1:0]	num0;
	reg	[$clog2(9000)-1:0]	num1;
	reg	[$clog2(900)-1:0]	num2;
	reg	[$clog2(90)-1:0]	num3;
	reg	[$clog2(9)-1:0]		num4;
	
	reg	[$clog2(65535)-1:0]	num5;
	reg	[$clog2(65535)-1:0]	num6;
	
	reg	[2:0]				valid_d;

	always @(posedge clk)begin
		if(rst)begin
			valid_d	<= 0;
		end else begin
			valid_d	<= {valid_d,valid};
		end
	end

	//10	=	1010				=	2^3  + 2^1
	//100	=	1100100				=	2^6  + 2^5  + 2^2
	//1000	=	001111101000		=	2^10 - 2^5  + 2^3
	//10000	=	0010011100010000	=	2^13 + 2^11 - 2^8 + 2^4

	always @(posedge clk)begin
		if(rst)begin
			num0	<=	0;
		end else begin
			num0	<=	{din[39-4 -:4],13'd0} + {din[39-4 -:4],11'd0} - {din[39-4 -:4],8'd0} + {din[39-4 -:4],4'd0};
		end
	end

	always @(posedge clk)begin
		if(rst)begin
			num1	<=	0;
		end else begin
			num1	<=	{din[39-12 -:4],10'd0} - {din[39-12 -:4],5'd0} + {din[39-12 -:4],3'd0};
		end
	end

	always @(posedge clk)begin
		if(rst)begin
			num2	<=	0;
		end else begin
			num2	<=	{din[39-20 -:4],6'd0} + {din[39-20 -:4],5'd0} + {din[39-20 -:4],2'd0};
		end
	end
	always @(posedge clk)begin
		if(rst)begin
			num3	<=	0;
		end else begin
			num3	<=	{din[39-28 -:4],3'd0} + {din[39-28 -:4],1'd0};
		end
	end
	always @(posedge clk)begin
		if(rst)begin
			num4	<=	0;
		end else begin
			num4	<=	din[39-36 -:4] ;
		end
	end
	always @(posedge clk)begin
		if(rst)begin
			num5	<=	0;
		end else begin
			num5	<=	num0 + num1 ;
		end
	end
	always @(posedge clk)begin
		if(rst)begin
			num6	<=	0;
		end else begin
			num6	<=	num2 + num3 + num4 ;
		end
	end	
	always @(posedge clk)begin
		if(rst)begin
			dout	<=	0;
		end else begin
			dout	<=	num5 + num6 ;
		end
	end
	
	assign	rdy	=	valid_d[2];
endmodule

4.仿真

verilog 复制代码
module tb_ascii();

    reg clk;
    reg rst;

    initial begin
        rst = 1;
        #300
        rst = 0;
    end

    initial begin
        clk = 0;
        forever begin
            #5 clk = ~clk;
        end
    end

	wire				rdy		;
	wire		[39:0]	dout			;//MAX = 65535

	reg			valid		;
	reg	[15:0]	din			;//MAX = 65535

    always @(posedge clk)begin
        if(rst)begin
            valid	<= 0;
            din     <= 0;
        end else begin
            valid	<= 1;
            din     <= din + 1;
        end
    end

    dec_ascii16 dec_ascii16(
        .clk			(clk        ),
        .rst			(rst        ),        
        .valid		    (valid      ),
        .din			(din        ),//MAX = 65535     
        .rdy			(rdy        ),
        .dout           (dout       )
    );

    ascii_dec16 ascii_dec16(
        .clk            (clk        ),
        .rst            (rst        ),	
        .valid          (rdy        ),
        .din	        (dout       ),//MAX = 65535
        .rdy		    (           ),
        .dout           (           )
    );
endmodule
相关推荐
ALINX技术博客6 小时前
【新品解读】一板多能,AXRF49 定义新一代 RFSoC FPGA 开发平台
射频工程·fpga·amd·rfsoc·alinx
迎风打盹儿15 小时前
FPGA仿真中阻塞赋值(=)和非阻塞赋值(<=)区别
verilog·fpga·阻塞赋值·非阻塞赋值·testbench仿真
tiantianuser1 天前
RDMA简介3之四种子协议对比
verilog·fpga·vivado·rdma·高速传输
XINVRY-FPGA7 天前
XCVP1902-2MSEVSVA6865 Xilinx FPGA Versal Premium SoC/ASIC
嵌入式硬件·安全·阿里云·ai·fpga开发·云计算·fpga
可编程芯片开发9 天前
基于FPGA的DES加解密系统verilog实现,包含testbench和开发板硬件测试
fpga开发·des·verilog·加解密
XINVRY-FPGA12 天前
XC7A200T-2FFG1156I FPGA AMD Xilinx Artix-7
5g·ai·fpga开发·云计算·硬件工程·fpga
ALINX技术博客13 天前
助力 FPGA 国产化,ALINX 携多款方案亮相深圳、广州“紫光同创 FPGA 技术研讨会”
图像处理·fpga开发·自动驾驶·射频工程·fpga
北城笑笑14 天前
FPGA 42 ,时序约束深度解析与实战应用指南( FPGA 时序约束 )
fpga开发·fpga
霖0015 天前
FPGA开发全流程
网络·经验分享·嵌入式硬件·fpga开发·流程图·fpga
XINVRY-FPGA15 天前
Xilinx XCAU10P-2FFVB676I 赛灵思 Artix UltraScale+ FPGA
嵌入式硬件·安全·阿里云·ai·fpga开发·云计算·fpga