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
相关推荐
Logic10116 小时前
C语言/数据结构字符串题解:按字符类型重排(数字→字母→符号)——三趟扫描稳定分区
c语言·数据结构·字符串·时间复杂度·计数排序·算法题·ascii
m0_547486663 天前
《数字电路与逻辑设计:基于Verilog HDL和Quartus Prime》全套PPT课件2026
verilog·数字电路·数字逻辑电路
学习FPGA的电气小兴兴4 天前
基于FPGA的CORDIC旋转模式实现sin和cos运算_采用EGo1板卡上板验证【FPGA数字信号处理第5讲】
fpga开发·信号处理·数字信号处理·verilog·cordic·ego1·fpga设计入门与提高
Eloudy10 天前
开源 gpunetio examples 01 解析 gpunetio_verbs_put_bw
gpu·fpga·rdma·roce·doca
博览鸿蒙10 天前
FPGA开发使用的语言
fpga开发·fpga
明德扬10 天前
机器人多摄像头如何做FPGA多路视频聚合?
学习·fpga开发·fpga
Eloudy11 天前
GPUNetIO开源实现与FPGA的 RoCEv2 通信延迟实验
gpu·fpga·rdma·roce·doca
啄缘之间11 天前
1.【SVA】什么是SVA?
经验分享·学习·测试用例·verilog·sva
unicrom_深圳市由你创科技11 天前
FPGA仿真正常,上板为何出错?
fpga
SDAU200512 天前
verilog计数器中增减操作之资源占用
verilog