众所周知,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
源码见链接