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

仿真結果如下圖所示:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM