zoukankan      html  css  js  c++  java
  • FPGA中将十进制数在数码管中显示(verilog版)--二进制转换为BCD码

    这周有朋友问怎样在fpga中用数码管来显示一个十进制数,比如1000。每个数码管上显示一位十进制数。如果用高级语言来分离各位,只需要分别对该数做1000,100,10对应的取商和取余即可分离出千百十个位。但是FPGA做除法非常耗资源。有没有其它解决办法?因为用verilog写程序时虽然形式上可以写为比如256,但是实际存储对应的还是0100H,且一个数码管只能显示一个十进制数。因此这个问题相当于二进制如何转换为一个BCD(Binary Code Decimal)码数。

    本文只考虑最常见的8421码的转换,而且是压缩BCD码。

    一、算法原理

    根据二进制与十进制转换的定义可知,将二进制数按位加权求和即可得到。用公式描述为n位二进制转换10进制公式

    A(n-1)*2^(n-1)+A(n-2)*2^(n-2)+........+A(0)*2^0=对应十进制数    (1)

    将公式(1)一直提取公因子2,可很容易将公式(1)转换为公式(2),如下所示:

    (A(n-1)*2+A(n-2))*2+A(n-3))*2........+a(0) =对应十进制数          (2)

    即对于n位二进制数的按权展开求和,由最高的2的n-1次幂,转换为乘以n-1次2,以此类推n-2次幂,n-3次幂……。因为左移一位相当于乘以2,这样乘法操作就转换为了左移操作。

    1、BCD码有0~9共计10个数码,用四位二进制表示0000~1001即可表示,而四位二进制可以表示数的范围为0000~1001~1111,即0~9~15。总计多处了 6个数码A~F。我们知道十进制逢十进一,十六进制逢十六进一。从而产生了一个非常关键的问题,转换到大于等于10以后的数字后本应由低位向紧邻的高位进位,但是只能到大于16以后进位。如DH(12D)十进制本应进位产生十位1,和个位2,但是却变成十六进制的DH。所以必须进行修正,修正的方法是加6。

    2、BCD码是二进制编码的十进制,逢十进一,10/2=5.因此得到判断条件,即判断每四位是否大于4,因为5-9进一位(左移)溢出。

    3、对于左移操作,相当于每进一位就会丢掉6,那么就要加上6/2=3(3左移一位后相当于6)。每次调整在左移之前完成。

    *因此二进制转BCD的方法是通过左移,然后每四位判断是否大于4,满足则加3.

    二、基于Verilog的代码实现

    为了简便,本代码是以十进制数1000为例进行测试。1000D = 3E8H = 0011 1110 1000B。

      1 /*******************************************************************
      2 *  功能:将二进制数转换为BCD码数,在七段数码管上显示
      3 *  原理:左移 + 3
      4 *  作者:国静德远
      5 *  时间:2017年4月16日
      6 *******************************************************************/
      7 module   BinaryToBCD(CLOCK_50, HEX3, HEX2, HEX1, HEX0);
      8 
      9 input   CLOCK_50;
     10 output  [7:0] HEX3, HEX2, HEX1, HEX0;
     11 
     12 wire      [9:0] TestData;
     13 wire     [15:0]  ResultData;
     14 assign  TestData = 10'd1001;
     15     //Binary to BCD    
     16     Binary2BCD  ConvertData(CLOCK_50, TestData, ResultData);
     17     //Display
     18     Seg7    H1(ResultData[ 3 :  0], HEX0);
     19     Seg7    H2(ResultData[ 7 :  4], HEX1);
     20     Seg7    H3(ResultData[11 :  8], HEX2);
     21     Seg7    H4(ResultData[15 : 12], HEX3);
     22 
     23 endmodule
     24 
     25 //Convert Data by left + 3
     26 module   Binary2BCD(inClk, inData, outData);
     27 input   inClk;
     28 input   [9:0] inData;
     29 output  [15:0]outData;
     30 
     31 
     32 reg     [3:0]count10 = 9;
     33 reg     [15:0]ShiftReg;
     34 
     35 
     36     always@(posedge inClk)
     37     begin
     38         if(count10 >= 0 && count10 <= 9)
     39         begin
     40             count10 <= count10 - 1'b1;      
     41         end
     42         else
     43             count10 <= 4'd15;
     44     end
     45 
     46     always @(posedge inClk)
     47     begin
     48         //for(i = 9; i >= 0; i = i - 1)
     49         if(count10 >= 0 && count10 <= 9)
     50         begin
     51             // shift left 
     52             ShiftReg = (ShiftReg << 1);
     53             ShiftReg[0] = inData[count10];
     54             //adjust by add 3
     55             if(ShiftReg[15:12] > 4)
     56                 ShiftReg[15:12] = ShiftReg[15:12] + 2'd3;
     57             else
     58                 ShiftReg[15:12] = ShiftReg[15:12];
     59             
     60             if(ShiftReg[11:8] > 4)
     61                 ShiftReg[11:8] = ShiftReg[11:8] + 2'd3;
     62             else
     63                 ShiftReg[11:8] = ShiftReg[11:8];            
     64         
     65             if(ShiftReg[7:4] > 4)
     66                 ShiftReg[7:4] = ShiftReg[7:4] + 2'd3;
     67             else
     68                 ShiftReg[7:4] = ShiftReg[7:4];
     69         
     70             if(ShiftReg[3:0] > 4)
     71                 ShiftReg[3:0] = ShiftReg[3:0] + 2'd3;
     72             else
     73                 ShiftReg[3:0] = ShiftReg[3:0];        
     74         
     75                         
     76         end
     77         else
     78             ShiftReg = ShiftReg;
     79     end
     80 
     81         assign outData = ShiftReg;
     82         
     83 endmodule    
     84 
     85 //Display on 7seg
     86 module  Seg7(inData, outData);
     87 input   [3:0]inData;
     88 output  [7:0]outData;
     89 //reg    [3:0]inData;
     90 reg     [7:0]outData;
     91     always@(inData)
     92     begin    
     93     case(inData)     
     94         4'd0: outData = 8'b1100_0000;
     95         4'd1: outData = 8'b1111_1001;
     96         4'd2: outData = 8'b1010_0100;
     97         4'd3: outData = 8'b1011_0000;
     98         4'd4: outData = 8'b1001_1001;
     99         4'd5: outData = 8'b1001_0010;
    100         4'd6: outData = 8'b1000_0010;
    101         4'd7: outData = 8'b1111_1000;
    102         4'd8: outData = 8'b1000_0000;
    103         4'd9: outData = 8'b1001_0000;
    104         default: outData = 8'b1111_1111;
    105      endcase
    106      end 
    107 endmodule

    仿真结果如下图所示:

  • 相关阅读:
    元数据Metadata
    博客园如何使用MarkDown
    zookeeper集群搭建
    Java 疑问自问自答
    R中rep函数的使用
    R中unlist函数的使用
    Windows7 系统 CMD命令行,点阵字体不能改变大小以及中文乱码的问题
    C# ConfigurationManager不存在问题解决
    Servlet中的请求转发RequestDispatcher接口的forword与Include的区别
    Servlet中的乱码问题及解决办法
  • 原文地址:https://www.cnblogs.com/guojingdeyuan/p/6718828.html
Copyright © 2011-2022 走看看