Binary, hex và BCD: cùng bit, khác cách biểu diễn

Khoảng 45 phútMức 1/3Bản nháp: một số khẳng định chưa đối chiếu spec

Tiên quyết

Sau bài này bạn sẽ

  • Đổi số nguyên và phần lẻ hữu hạn giữa binary, decimal và hex
  • Phân biệt byte binary với hai chữ số BCD
  • Chọn độ rộng và nhận ra mã BCD không hợp lệ

Một dãy bit cần cách đọc

Cùng tám bit 0001_0000 có thể chỉ số 16 nếu đọc như số nhị phân không dấu, hoặc số 10 nếu dùng BCD hai chữ số. Bit không tự mang đơn vị, dấu hay quy ước mã hóa.

Hãy chốt ba điều trước khi tính: có bao nhiêu bit, dùng hệ biểu diễn nào và giá trị cần nằm trong miền nào. Hex là cách viết gọn các bit; BCD là một quy ước mã hóa chữ số khác.

Trọng số theo vị trí

Trong hệ cơ số b, mỗi chữ số ở vị trí k có trọng số b^k; vị trí ngay trước dấu chấm có k bằng 0. Binary dùng chữ số 0/1, decimal dùng 0 tới 9, hex dùng 0 tới 9 và A tới F.

Cách viết Tính theo trọng số Giá trị decimal
Binary 1010 8 + 2 10
Hex 2D 2 × 16 + 13 45
Binary 101.01 4 + 1 + 1/4 5.25

Với W bit không dấu chỉ chứa 0/1, có 2^W mẫu và miền 0 .. 2^W-1. Bốn bit có 16 mẫu, không phải chứa được số 16. Dấu phân cách gạch dưới chỉ giúp đọc; nó không thêm bit.

Đổi hệ mà vẫn giữ giá trị

Để đổi số nguyên không âm sang binary, chia liên tiếp cho 2, ghi số dư rồi đọc từ dưới lên. Ví dụ 13 chia 2 lần lượt có dư 1, 0, 1, 1; kết quả là 1101. Kiểm lại bằng 8+4+1=13.

Đổi binary sang hex bằng nhóm bốn bit từ phải sang trái. 101101 thêm các số 0 bên trái thành 0010_1101, nên viết hex là 2D. Việc nhóm này không tạo mã BCD.

Đổi phần lẻ bằng nhân liên tiếp cho 2 và lấy phần nguyên theo thứ tự. Với 0.625: 1.25 → lấy 1; 0.5 → lấy 0; 1.0 → lấy 1. Kết quả là 0.101. Một phân số hữu hạn ở hệ decimal có thể lặp vô hạn trong binary; 0.1 là ví dụ. Khi chốt số bit phần lẻ, cần nêu chính sách làm tròn.

BCD giữ từng chữ số decimal

Packed BCD thường dành một nibble, tức bốn bit, cho mỗi chữ số decimal. Trong bài này dùng đúng hai nibble, không có dấu và không có mã điều khiển.

Giá trị decimal Binary không dấu, viết hex BCD hai chữ số
9 09 09
10 0A 10
42 2A 42
99 63 99

Một nibble từ A tới F không phải chữ số BCD hợp lệ. Trong 256 mẫu tám bit, chỉ 100 mẫu là hai chữ số hợp lệ; 156 mẫu còn lại cần bị từ chối hoặc xử lý theo đặc tả.

BCD hữu ích khi giao diện lưu từng chữ số decimal. Phép cộng binary thông thường trên byte BCD chưa tự trở thành phép cộng decimal: 09 + 01 cho 0A ở bộ cộng binary, trong khi mã BCD của 10 là 10.

Độ rộng cũng là một phần yêu cầu

Số 15 vừa trong bốn bit không dấu; 16 cần năm bit. Nếu giữ bốn bit thấp của 16, kết quả là 0 theo modulo 16. Đây là mất thông tin, không phải đổi cơ số.

Thêm số 0 bên trái giữ giá trị không dấu. Cắt bit cao chỉ an toàn khi chứng minh các bit bị cắt đều không mang thông tin cần giữ. Đối với số có dấu, phải biết cách biểu diễn trước khi mở rộng; bài kế tiếp sẽ dùng sign extension.

Chuỗi ký tự “10” còn là một đối tượng khác. Hai byte ASCII cho ký tự 1 và 0 không phải byte binary có giá trị 10 hoặc byte BCD 10.

Ba nhầm lẫn dễ làm sai dữ liệu

  • Đọc hex 10 như decimal 10: giá trị không dấu của nó là 16.
  • Nhận mọi byte làm BCD: nibble A tới F cần chính sách xử lý rõ.
  • Đổi cách hiển thị rồi tưởng đã đổi nội dung bit: in cùng byte ở hex hay decimal không thay byte ấy.
  • Cho rằng mọi phần lẻ decimal có số bit biểu diễn hữu hạn: cần xem sai số lượng tử và cách làm tròn.

Trong công việc, ghi cả độ rộng lẫn quy ước trong mô tả thanh ghi hoặc giao diện. “Tám bit đếm sản phẩm” còn thiếu việc đếm binary hay lưu hai chữ số BCD.

Tự đổi rồi kiểm lại theo trọng số

  1. Đổi decimal 37 sang binary và hex. Dùng tổng các trọng số để kiểm lại.
  2. Byte 0010_1001 đọc unsigned binary và BCD lần lượt có giá trị gì?
  3. Vì sao byte 7C hợp lệ ở hex nhưng không phải BCD hai chữ số?
  4. Biểu diễn 3.375 bằng binary. Nếu chỉ giữ hai bit phần lẻ và bỏ phần dư, sai số bằng bao nhiêu?
  5. Muốn lưu từ 0 tới 999 theo BCD cần ít nhất bao nhiêu bit? So sánh với binary không dấu.

Kiểm tra

Tự kiểm tra: Binary, hex và BCD: cùng bit, khác cách biểu diễn

  1. Hex 10 đọc như unsigned có giá trị decimal nào?
  2. Byte hex 0A có hợp lệ như BCD hai chữ số không?
  3. Binary 0.101 có giá trị decimal nào?
  4. Bốn bit unsigned có chứa chính xác số 16 không?
  5. In cùng một byte ở hex rồi decimal đã đổi byte ấy chưa?

Bằng chứng kiểm chứng

Expected tính trước chạy: RADIX CHECK raw=256 valid_bcd=100 invalid_bcd=156 encoded=100 formats=5 time_ns=356.

Hệ đếm và BCD: mẫu bit, giá trị và cách hiển thị

Kỳ vọng tính trước chạy: RADIX CHECK raw=256 valid_bcd=100 invalid_bcd=156 encoded=100 formats=5 time_ns=356

tb.sv testbench
`timescale 1ns/1ps// Expected BEFORE execution: 100 valid two-digit BCD patterns, 156 invalid.// 100 decimal encodings and 5 format samples; 256+100 delay steps = 356 ns.module tb_a1_radix;  int expected_value[256],expected_encoded[100];  byte unsigned format_input[5]='{8'h00,8'h09,8'h0a,8'h10,8'hff};  string format_text[5]='{"00","09","0a","10","ff"};  int samples=0,valid_count=0,invalid_count=0,encoded_count=0,formats=0;  int actual;logic [7:0] encoded;string text_hex;  function automatic int decode_bcd(input logic [7:0] value);    if(value[7:4]>9||value[3:0]>9)return -1;    return int'(value[7:4])*10+int'(value[3:0]);  endfunction  function automatic logic [7:0] encode_bcd(input int value);    return {4'(value/10),4'(value%10)};  endfunction  initial begin    for(int i=0;i<256;i++)expected_value[i]=-1;    // Reference enumeration is over decimal digits, not DUT nibble validity checks.    for(int tens=0;tens<10;tens++)for(int ones=0;ones<10;ones++)begin      expected_value[tens*16+ones]=tens*10+ones;      expected_encoded[tens*10+ones]=tens*16+ones;    end    for(int i=0;i<256;i++)begin      #1;actual=decode_bcd(8'(i));samples++;      if(actual!=expected_value[i])$fatal(1,"BCD decode mismatch raw=%0d",i);      if(actual<0)invalid_count++;else valid_count++;    end    for(int value=0;value<100;value++)begin      #1;encoded=encode_bcd(value);encoded_count++;      if(int'($unsigned(encoded))!=expected_encoded[value]||decode_bcd(encoded)!=value)        $fatal(1,"BCD encode mismatch value=%0d",value);    end    for(int i=0;i<5;i++)begin      text_hex=$sformatf("%02h",format_input[i]);formats++;      if(text_hex!=format_text[i])$fatal(1,"hex display mismatch index=%0d got=%s",i,text_hex);    end    if(samples!=256||valid_count!=100||invalid_count!=156||encoded_count!=100||formats!=5||$time!=356||       encode_bcd(10)!==8'h10||decode_bcd(8'h0a)!=-1||decode_bcd(8'h99)!=99)      $fatal(1,"radix experiment contract");    $display("RADIX CHECK raw=256 valid_bcd=100 invalid_bcd=156 encoded=100 formats=5 time_ns=%0d",$time);    $finish;  endendmodule

Đã kiểm chứng thế nào

  • Phân tích và elaborate theo LRM (pyslang 12.1.0)
  • Mô phỏng, exit 0 và output khớp kỳ vọng tính tay (Verilator 5.050, 2-state)

Output phải khớp: RADIX CHECK raw=256 valid_bcd=100 invalid_bcd=156 encoded=100 formats=5 time_ns=356

Verilator 5.050 two-state; finite known input domains only. No X/Z or all-width language-conformance claim.

Các kiểm tra chạy lúc xây dựng nội dung (2026-11-07), không chạy trong trình duyệt. Kỳ vọng được tính tay trước khi chạy.

Tham chiếu duyệt từng cặp chữ số decimal từ 0 tới 9, rồi tạo bảng 100 mã; phần kiểm không dùng lại điều kiện nibble của hàm cần thử. Lượt mô phỏng duyệt đủ 256 byte, kiểm encode/decode 100 giá trị và năm chuỗi hiển thị hex.

Parser và simulation đạt trong toolchain đã khóa phiên bản. Đây là hàm trong testbench, không có claim lint, synthesis hay phần cứng BCD đã triển khai. Miền kiểm chỉ có các bit 0/1; chưa kiểm X/Z hoặc mọi cách viết literal trong ngôn ngữ.

[1] [2] [3]

Nguồn và mức độ đối chiếu

  1. Binary and Decimal System — bản chụp resources.zip, What is a Number System?; Popular Number Systems; Converting Decimal to Binary; Converting Fractional Decimal to Binary; Converting Binary to Decimal; Converting Binary to Hexadecimal; Converting Hexadecimal to Binary; Binary-Coded Decimal (BCD); BCD vs. Pure Binary. Trích dẫn; nguồn đã đọc các mục liên quan.
  2. Thí nghiệm nguyên bản A1.radix, Exhaustive byte BCD decode, decimal encode and hex formatting. Trích dẫn; nguồn đã đọc toàn văn.
  3. IEEE 1800-2023 SystemVerilog LRM, Integral literal formatting, packed vectors, casts and string formatting — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
  4. IEEE 1800-2023 SystemVerilog LRM, Integral bit vectors, casts and hexadecimal formatting — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).