BCD碼(nary-Coded Decimal)又稱二-十進制代碼,亦稱二進碼十進數。是一種二進制的數字編碼形式,用二進制編碼的十進制代碼。這種編碼形式利用了四個位元來儲存一個十進制的數碼。
在數字電路中,沒有特殊說明的數碼都是順序編碼的二進制。轉換為BCD碼,也就是將順序編碼的二進制數字的個位、十位、百位等計算出來,用四位二進制表示,組合到一起就是BCD碼。
將一個數字對10求余將得到個位。
將一個數字減去個位后,除以10,然后在對10求余將得到十位。由於在FPGA內部,正數除法不會保留小數,所以可以直接除以10,而不用減去個位。
將一個數字除以100,然后對10求余得到百位。
首先設計一個8位的二進制轉成BCD碼。8位的二進制能夠表示最大的數字為255,共有三個BCD碼,輸出共有12位。
此模塊命名為bin2bcd,bin為二進制輸入,bcd為BCD碼輸出。
設計代碼如下:
module bin2bcd (
input wire [7:0] bin,
output wire [11:0] bcd );
assign bcd[3:0] = bin%10; assign bcd[7:4] = (bin/10)%10; assign bcd[11:8] = (bin/100)%10;
endmodule |
在testbench中,可以利用隨機數給出幾個數值。
`timescale 1ns/1ps
module bin2bcd_tb;
reg [7:0] bin;
wire [11:0] bcd;
bin2bcd bin2bcd_inst(
.bin (bin),
.bcd (bcd) );
initial begin repeat (10) begin bin = {$random} % 256; # 20; end end
endmodule |
在modelsim中,將bin設置為符號位,將bcd設置為十六進制。十六進制也是4個二進制碼組成一個,只不過BCD碼中只有0到9,而十六進制中還有A到F。
通過RTL仿真圖可以看出,bin和bcd的數字是相同的。
在此設計代碼中只有三行,但是涉及到了除法器和求余器(也可以認為是除法器),利用了較多的資源。
為了減少資源使用,使得延遲更小,二進制轉BCD還有其他的辦法。
首先分析兩個BCD數碼的相加。
0101 0010
+ 0010 0110
0111 1000
在上述BCD碼加法中,52+26最終結果等於78,結果沒有任何錯誤。
0101 1001
+ 0010 0010
0111 1011
在上述BCD碼加法中,59+22最終結果等於7B,很明顯出現了不屬於BCD碼中的數字。BCD碼是用來表示十進制數字的,順序編碼時表示二進制的,當四個組到一起時,變為十六進制,當BCD碼算完的結果中有大於9的數碼,可以進行加六調整。加上六后,就會得到正確的進位和本位值。
當結果為1011(B)時,加上0110(6),本位結果為0001,進位為0001。
0111 1011(7B)調整后,為1000 0001(81),結果正確。
上面是分析的是兩個不同的BCD碼相加,下面分析兩個相同的BCD碼相加(最終結果不用調整時),相同的兩個數字相加,可以用左移表示。
0010 0011
+ 0010 0011
0100 0110
兩個相同的BCD碼相加(最終結果需要調整時),就需要加六調整了。
0010 0111
+ 0010 0111
0100 1110
上述結果就需要加六調整了,因為最終結果中出現了比9大的數字。因為是兩個相同的數字相加,當數字大於4后,兩個相同的數字相加就會大於9,此時就需要加6調整。
當數字大於4,先加上3,此時把兩個相同的結果進行相加,就實現了加之后的結果大於9,然后再加六。這兩種方法是一樣的。
當數字大於4,先加上3,然后進行移位。和先加,判斷結果是不是大於9,然后再加6是相等的。
由於是相等的兩個數字相加,末位肯定為0 。那么兩個相同的BCD相加,再和一個1bit的數字相加,就可以認為是當數字大於4,先加上3,然后進行移位,把最后移位出來的0直接換成最后加的1bit數字即可,將上述操作定義為操作X。
當了解了上述結論后,下面分析,利用上述結論實現二進制轉BCD。
任何一個二進制碼都可以寫成本位的數字乘以本位的權重的累加和。
將一個7位的二進制數據轉為BCD,首先認為是兩個都為0的bcd碼相加,然后加上7位數據的最高位。
上述的結果就是最高位轉換為BCD碼的結果,它的權重應該是2的6次冪,但是現在是2的0次冪。
然后將上述的結果和數據的次高位進行操作X,那么此時數據的最高位的權重變為2的1次冪,次高位的權重變為2的0次冪,結果為最高位和次高位的BCD碼。
依次類推,將八位數據全部進行操作X后,各個數據位都是自己的權重,並且結果就是BCD碼。
在操作X中,為了方便將1bit的數據去替換結果的最后一位,可以將1bit放在調整好的數據的后面,直接移位進去即可。
在圖中,經歷了7 次的操作X。如果我們可以把操作X設計出來,然后級聯7個即可得到正確結果。
操作X的輸入為前面的BCD碼和后面的二進制(可以將這兩組合到一起)。
操作X為調整和移位,后面用調整和移位來表示。
為了能夠對比兩種二進制轉BCD(除法求余和調整移位),下面利用調整和移位的方法實現8位二進制轉BCD。
輸入是八位,就需要進行八次的調整和移位。由於每次調整和移位的操作是完全相同的,所以將調整和移位做成一個模塊。
該模塊命名為adjust_shift,輸入為BCD碼的位數加上二進制的位數等於20位,輸出也是20位。
module adjust_shift (
input wire [19:0] idata,
output wire [19:0] odata );
wire [19:0] adjust_data;
assign adjust_data[19:16] = idata[19:16] > 4'd4 ? idata[19:16] + 4'd3 : idata[19:16]; assign adjust_data[15:12] = idata[15:12] > 4'd4 ? idata[15:12] + 4'd3 : idata[15:12]; assign adjust_data[11:8] = idata[11:8] > 4'd4 ? idata[11:8] + 4'd3 : idata[11:8]; assign adjust_data[7:0] = idata[7:0];
assign odata = adjust_data << 1'b1;
endmodule |
當調整移位設計做完之后,我們只需要級聯八個就可以得到結果。第一個輸入時,高位(BCD)要輸入為0;最后一個輸出時,高位(BCD)才是輸出。
module bintobcd (
input wire [7:0] bin,
output wire [11:0] bcd );
wire [19:0] adjust_shift_data_0; wire [19:0] adjust_shift_data_1; wire [19:0] adjust_shift_data_2; wire [19:0] adjust_shift_data_3; wire [19:0] adjust_shift_data_4; wire [19:0] adjust_shift_data_5; wire [19:0] adjust_shift_data_6; wire [19:0] adjust_shift_data_7;
adjust_shift adjust_shift_inst0 (.idata({12’d0,bin}),.odata(adjust_shift_data_0)); adjust_shift adjust_shift_inst1 (.idata(adjust_shift_data_0),.odata(adjust_shift_data_1)); adjust_shift adjust_shift_inst2 (.idata(adjust_shift_data_1),.odata(adjust_shift_data_2)); adjust_shift adjust_shift_inst3 (.idata(adjust_shift_data_2),.odata(adjust_shift_data_3)); adjust_shift adjust_shift_inst4 (.idata(adjust_shift_data_3),.odata(adjust_shift_data_4)); adjust_shift adjust_shift_inst5 (.idata(adjust_shift_data_4),.odata(adjust_shift_data_5)); adjust_shift adjust_shift_inst6 (.idata(adjust_shift_data_5),.odata(adjust_shift_data_6)); adjust_shift adjust_shift_inst7 (.idata(adjust_shift_data_6),.odata(adjust_shift_data_7));
assign bcd = adjust_shift_data_7[19:8];
endmodule |
第一級輸入時,采用位拼接的方式。
編寫testbench后,經過RTL仿真驗證,結果都是正確的。 在達到相同功能的前提下,調整和移位的方式實現的設計,資源利用如下:
在達到相同的功能下,一個是164,一個是29,對比結果很明顯。
設計者:郝旭帥 QQ:746833924 QQ交流群: 173560979