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
相关推荐
热爱学习地派大星3 天前
Xilinx FPGA功耗评估
fpga开发·verilog·vivado·fpga功耗·xpe
进击的奶龙4 天前
21verilog函数
verilog·基础语法
XINVRY-FPGA15 天前
XCVU47P-2FSVH2892E Xilinx Virtex UltraScale+ FPGA AMD
c语言·c++·人工智能·嵌入式硬件·阿里云·fpga开发·fpga
迎风打盹儿18 天前
FPGA点亮ILI9488驱动的SPI+RGB接口LCD显示屏(二)
fpga·verilog hdl·ili9488·rgb接口·lcd显示屏
百锦再19 天前
Modbus上位机访问形式详解及代码示例
串口·上位机·ip·tcp·modbus·ascii·网口
tiantianuser22 天前
RDMA简介7之RoCE v2可靠传输
服务器·fpga开发·verilog·xilinx·rdma·可编程逻辑
9527华安1 个月前
国产安路FPGA纯verilog图像缩放,工程项目解决方案,提供5套TD工程源码和技术支持
fpga开发·verilog·图像缩放·双线性插值·安路fpga
贝塔实验室1 个月前
FPGA 的硬件结构
arm开发·fpga开发·职场和发展·硬件架构·硬件工程·fpga·安全架构
贝塔实验室1 个月前
FPGA 动态重构配置流程
驱动开发·fpga开发·硬件架构·硬件工程·射频工程·fpga·基带工程
tiantianuser1 个月前
RDMA简介5之RoCE v2队列
fpga开发·verilog·fpga·rdma·高速传输·rocev2