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 天前
verilog实现32位有符号流水乘法器
verilog·乘法器
北城笑笑5 天前
FPGA 34 ,FPGA 与 DSP 技术,赋能工业 4.0 时代,理论解析( FPGA 与 DSP技术,工业界的「硬件快手」与「软件大脑」)
fpga开发·fpga
学习永无止境@5 天前
FPGA设计中IOB约束
开发语言·fpga开发·fpga·时钟约束
我爱C编程6 天前
基于FPGA的16QAM+帧同步系统verilog开发,包含testbench,高斯信道,误码统计,可设置SNR
fpga开发·verilog·16qam·帧同步·误码统计·高斯信道
早睡身体好~6 天前
FPGA原型验证,从零开始直到入门全过程
fpga开发·verilog·soc
xiaguangbo9 天前
Verilog-HDL/SystemVerilog/Bluespec SystemVerilog vscode 配置
linux·fpga
学习永无止境@10 天前
FPGA设计中时间单位科普
fpga开发·fpga·时钟约束
霖0010 天前
FPGA中级项目6——VGA 2part
经验分享·fpga开发·课程设计·模块测试·fpga
林伟_fpga10 天前
关于波士顿动力2025年3月的人形机器人最新视频
机器人·fpga