众所周知,FPGA在计算乘法除法的时候比较慢,所以当需要把一个数,例如52020这个数按照个十百千万发送出去的时候,在单片机或者其他软硬件中,可以直接取余得到每一位数据,然后存储起来发送到上位机或者别的地方。但是FPGA无法进行取余操作,所以需要通过BCD编码通过移位的方式实现个十百千万的取出,然后发送。而BCD译码通常通过左移加三法,我在做8个通道的16位AD采集的时候,需要把采集到的8个字节一次的发送到上位机,所以就编写了一个verilog代码来实现左移加三法,主要采用了组合逻辑中的for循环16次实现BCD编码的,硬件实测OK。

//2020.7.12 //BCD译码 移位加三法 module BCD ( //输入16进制 clk_50M, Num, //0-5000的值 rst_n, //硬件复位 AD_RESET, //软件复位

//输出10进制BCD
	dec

);



//--------------------------------------------------------------------
//--定义外部端口端口
//-------------------------------------------------------------------
input								clk_50M;           //input output 默认类型都是wire型
input  		[15:0] 			Num; 
input								rst_n;
input								AD_RESET;
output 		reg[19:0] 		dec;    

//--------------------------------------------------------------------
//--定义内部端口
//-------------------------------------------------------------------
reg			[35:0]			z;     	//65535转为bcd需要5*4=20bits,再加上本身的16bit共需要36bits
reg			[19:0]			dec_n;     //dec的bcd码的寄存器
reg			[5:0] 			i;       //循环次数
//--------------------------------------------------------------------
//--定义参数
//-------------------------------------------------------------------			
				
//--------------------------------------------------------------------
//--逻辑实现
//-------------------------------------------------------------------		

//**************BCD码转换***************
//时序电路
always @(posedge clk_50M or negedge rst_n)
	begin
		if(!rst_n)
			dec<=20'b0;                 //
		else
			dec<=dec_n;		
	end	

//组合电路
always @(*)       
	begin 
		if(AD_RESET)                //软件复位 
			dec_n=20'b0;    
		else
			dec_n=z[35:16];
	end
	
//组合逻辑        //一个时钟可以进行完毕吧?
always @ (*)
	 begin
		  z = 35'b0;                           //置 0
		  z[15:0] = Num;                     //读入低 16位

// repeat (16) //难以综合,勿用

for(i=6'd0;i<6'd16;i=i+1'b1)
			  begin
			  if(z[19:16 ]>4'd4)                   //大于 4 就加 3,加3后不可能溢出的,所以不用向后进位
						z[19:16] = z[19:16] + 2'b11;
					if(z[23:20]>4'd4)
						z[23:20] = z[23:20] + 2'b11;
					if(z[27:24]>4'd4)                   //大于 4 就加 3
						z[27:24]	= z[27:24] + 2'b11;
					if(z[31:28]>4'd4)
						z[31:28] = z[31:28] + 2'b11;
					if(z[35:32]>4'd4)
						z[35:32] = z[35:32] + 2'b11;
					z[35:1] = z[34:0];               //整体左移一位
			  end		
	 end

endmodule

源码见链接