Mật độ thập phân dày đặc (DPD) đến thập phân, với các cổng logic


13

Lấy cảm hứng từ sự phổ biến gần đây của nandgame trên TNB, và thử thách trước đây của riêng tôi .

Lý lịch

Số thập phân dày đặc (DPD) là một cách hiệu quả để lưu trữ hiệu quả các chữ số thập phân ở dạng nhị phân. Nó lưu trữ ba chữ số thập phân (000 đến 999) trong 10 bit, hiệu quả hơn nhiều so với BCD ngây thơ (lưu trữ một chữ số trong 4 bit).

Bảng chuyển đổi

DPD được thiết kế để dễ dàng chuyển đổi giữa các bit và chữ số bằng cách khớp mẫu đơn giản từ trên xuống dưới. Mỗi mẫu bit xác định có bao nhiêu chữ số cao (8-9) số đó, vị trí của chúng và cách di chuyển các bit để tạo thành biểu diễn thập phân.

Sau đây là bảng chuyển đổi từ 10 bit DPD thành ba chữ số thập phân. Mỗi chữ số thập phân được biểu diễn dưới dạng nhị phân 4 bit (BCD). Cả hai bên được viết từ trái sang phải từ chữ số có nghĩa nhất đến ít nhất.

Bits                 =>  Decimal         (Digit range)

a b c d e f 0 g h i  =>  0abc 0def 0ghi  (0-7) (0-7) (0-7)

a b c d e f 1 0 0 i  =>  0abc 0def 100i  (0–7) (0–7) (8–9)
a b c g h f 1 0 1 i  =>  0abc 100f 0ghi  (0–7) (8–9) (0–7)
g h c d e f 1 1 0 i  =>  100c 0def 0ghi  (8–9) (0–7) (0–7)

g h c 0 0 f 1 1 1 i  =>  100c 100f 0ghi  (8–9) (8–9) (0–7)
d e c 0 1 f 1 1 1 i  =>  100c 0def 100i  (8–9) (0–7) (8–9)
a b c 1 0 f 1 1 1 i  =>  0abc 100f 100i  (0–7) (8–9) (8–9)
x x c 1 1 f 1 1 1 i  =>  100c 100f 100i  (8–9) (8–9) (8–9)

Ký hiệu

  • Các chữ thường ađể ilà các bit được sao chép vào các đại diện thập phân.
  • 01là các bit chính xác trong các mẫu bit đầu vào hoặc đầu ra.
  • x bit được bỏ qua trong chuyển đổi.

Bài tập

Xây dựng một mạch logic bằng cách sử dụng cổng NAND hai đầu vào để chuyển đổi 10 bit DPD thành 12 bit BCD.

Ví dụ

Các bit được nhấn mạnh là các bit khớp mẫu.

DPD                    Decimal  BCD
0 0 0 0 0 0 0 1 0 1    005      0000 0000 0101
            ^
0 0 0 1 1 0 0 0 1 1    063      0000 0110 0011
            ^
0 0 0 1 1 1 1 0 0 1    079      0000 0111 1001
            ^ ^ ^
0 0 0 0 0 1 1 0 1 0    090      0000 1001 0000
            ^ ^ ^
0 0 0 1 0 1 1 1 1 0    098      0000 1001 1000
      ^ ^   ^ ^ ^
1 0 1 0 1 1 1 0 1 0    592      0101 1001 0010
            ^ ^ ^
0 0 1 1 0 0 1 1 0 1    941      1001 0100 0001
            ^ ^ ^
1 1 0 0 1 1 1 1 1 1    879      1000 0111 1001
      ^ ^   ^ ^ ^
1 1 1 0 0 0 1 1 1 0    986      1001 1000 0110
      ^ ^   ^ ^ ^
0 0 1 1 1 1 1 1 1 1    999      1001 1001 1001
      ^ ^   ^ ^ ^
1 1 1 1 1 1 1 1 1 1    999      1001 1001 1001
      ^ ^   ^ ^ ^

Ghi điểm & tiêu chí chiến thắng

Điểm số là số lượng cổng NAND hai đầu vào được sử dụng trong mạch của bạn. Điểm thấp nhất sẽ thắng.

Bạn có thể xác định các thành phần nhỏ theo các cổng NAND hai đầu vào, sau đó sử dụng chúng trong công trình cuối cùng của bạn. Nếu một thành phần Xbao gồm Ncác cổng NAND hai đầu vào, mỗi lần sử dụng Xsẽ thêm Nvào điểm số của bạn. Đối với các cổng logic cơ bản, điều này có nghĩa là:

  • KHÔNG: +1
  • 2 đầu vào VÀ: +2
  • 2 đầu vào HOẶC: +3
  • XOR 2 đầu vào: +4

Quay trở lại chỉnh sửa của Luis vì golf nguyên tử là một thẻ tiêu chí chiến thắngthử thách mã dành cho các câu hỏi có tiêu chí chiến thắng không được bao phủ bởi các thẻ khác.
Peter Taylor

Điều này vẫn chưa rõ ràng với tôi. Tôi nghĩ cần phải có mô tả thêm về những gì các chữ cái ađể icó ý nghĩa và quá trình chuyển đổi. Trải qua các bước, thay vì chỉ hiển thị các ví dụ và hy vọng chúng tôi hiểu từ đó.
mbomb007

@ mbomb007, có lẽ nó chỉ rõ ràng với tôi vì một trong những ngôn ngữ của tôi là SML. Khối mã đầu tiên đó hầu như là một triển khai tham chiếu trong ngôn ngữ khớp mẫu (mặc dù nó hoạt động tốt hơn trong SMLNJ, nó lặp lại kết quả của mỗi câu lệnh, so với MLton).
Peter Taylor

@ mbomb007 Tôi đã cố gắng làm rõ bản chất khớp mẫu của bảng chuyển đổi. Nó có giúp gì không?
Bong bóng

1
@Bubbler Vâng, điều đó hữu ích
mbomb007

Câu trả lời:


4

45 NAND (hoặc 43)

45 dường như là mức tối thiểu tuyệt đối, nhưng có thể đạt tới 43 NAND bằng một mẹo: Bằng cách giả sử rằng các số lớn nhất được mã hóa chính xác.

888, 889, 898, 899, 988, 989, 998, 999 sẽ được mã hóa với 2 MSB là 00, chỉ cần 43 NAND để giải mã.

Tuy nhiên, trong đặc tả để giải mã, chúng được chỉ định bỏ qua, có nghĩa là chúng có thể là bất cứ thứ gì. Đó là một giả định hợp lý rằng đặc điểm kỹ thuật tự do này có thể yêu cầu thậm chí ít cổng hơn, nhưng điều ngược lại là đúng. 45 cổng được yêu cầu cho việc này. Tiết kiệm này có thể mang lại lợi ích thực sự cho các mạch thực.

Tôi cũng tìm thấy các mạch hiệu quả hơn và nhanh hơn đáng kể, có chứa một vài cổng.

Không có bút chì vẽ hình ảnh của mạch lần này. Có lẽ sau này.

Mạch được trình bày bằng mã Verilog rõ ràng, sẵn sàng để chạy với kiểm tra đi kèm.

Mã Verilog:

// Densely packed decimal (DPD) to decimal, circuit in Verilog.
// 45 NANDs only, which seems to be minimal.
//
// By Kim Øyhus 2019 (c) into (CC BY-SA 3.0.)
// This work is licensed under the Creative Commons Attribution 3.0
// Unported License. To view a copy of this license, visit
// https://creativecommons.org/licenses/by-sa/3.0/
//
// This is my entry to win this Programming Puzzle & Code Golf
// at Stack Exchange: 
// /codegolf/176557/densely-packed-decimal-dpd-to-decimal-with-logic-gates
//
// TASK:
// 3 decimal digits are stored in 10 bits in the DPD format,
// and this circuit transforms them into 3 decimal digits in
// 4 bits each, BCD format.
//
// 45 gates seem to be the smallest possible NAND circuit there is
// for this task, but I can get even lower by a trick, to 43:
// I assume that the largest numbers are correctly encoded.
//   888, 889, 898, 899, 988, 989, 998, 999 are to be encoded
// with the 2 MSB as 00, requiring just 43 NANDs for decoding.
//
//   However, in the specification for decoding, they are specified
// to be ignored, meaning they can be anything. It is a reasonable
// assumption that this freer specification could require even fewer
// gates, but the opposite is true. 45 gates are required for this.
// This saving could give real benefits for real circuits.
//
//   This DPD format seems to be used a lot for storing decimal numbers
// in computers and IO for ALUs, even though it is stored as 12 bits
// per 3 digits inside the ALUs and for other calculations.
// It is also used in many patents.


module decode1000 ( in_000, in_001, in_002, in_003, in_004, in_005, in_006, in_007, in_008, in_009, out000, out001, out002, out003, out004, out005, out006, out007, out008, out009, out010, out011 );
  input  in_000, in_001, in_002, in_003, in_004, in_005, in_006, in_007, in_008, in_009;
  output out000, out001, out002, out003, out004, out005, out006, out007, out008, out009, out010, out011;
  wire   wir000, wir001, wir002, wir003, wir004, wir005, wir006, wir007, wir008, wir009, wir010, wir011, wir012, wir013, wir014, wir015, wir016, wir017, wir018, wir019, wir020, wir021, wir022, wir023, wir024, wir025, wir026, wir027, wir028, wir029, wir030, wir031, wir032;

  nand gate000 ( wir000, in_007, in_007 );
  nand gate001 ( wir001, in_003, in_001 );
  nand gate002 ( wir002, in_002, in_003 );
  nand gate003 ( wir003, wir001, in_006 );
  nand gate004 ( wir004, wir002, in_001 );
  nand gate005 ( wir005, wir001, wir001 );
  nand gate006 ( wir006, in_005, in_001 );
  nand gate007 ( wir007, wir006, in_003 );
  nand gate008 ( out008, wir000, wir000 );
  nand gate009 ( wir008, wir004, wir007 );
  nand gate010 ( wir009, wir005, in_006 );
  nand gate011 ( wir010, wir007, wir007 );
  nand gate012 ( wir011, wir009, in_002 );
  nand gate013 ( wir012, wir011, wir009 );
  nand gate014 ( wir013, wir011, wir011 );
  nand gate015 ( wir014, in_008, wir013 );
  nand gate016 ( wir015, in_009, wir013 );
  nand gate017 ( wir016, wir010, wir014 );
  nand gate018 ( wir017, wir014, wir005 );
  nand gate019 ( wir018, wir015, wir015 );
  nand gate020 ( wir019, wir011, wir008 );
  nand gate021 ( wir020, wir019, wir006 );
  nand gate022 ( wir021, wir010, wir018 );
  nand gate023 ( wir022, wir020, wir004 );
  nand gate024 ( wir023, wir016, wir008 );
  nand gate025 ( out001, wir023, wir023 );
  nand gate026 ( out003, wir022, wir022 );
  nand gate027 ( wir024, wir005, wir008 );
  nand gate028 ( wir025, wir012, wir002 );
  nand gate029 ( wir026, wir019, in_003 );
  nand gate030 ( wir027, in_004, in_004 );
  nand gate031 ( out007, wir024, wir009 );
  nand gate032 ( out011, wir026, wir026 );
  nand gate033 ( wir028, wir017, in_005 );
  nand gate034 ( wir029, in_000, in_000 );
  nand gate035 ( wir030, wir026, in_008 );
  nand gate036 ( out005, wir028, wir028 );
  nand gate037 ( out009, wir030, wir030 );
  nand gate038 ( out000, wir029, wir029 );
  nand gate039 ( wir031, wir026, in_009 );
  nand gate040 ( out004, wir027, wir027 );
  nand gate041 ( out010, wir031, wir031 );
  nand gate042 ( wir032, out003, wir018 );
  nand gate043 ( out006, wir003, wir032 );
  nand gate044 ( out002, wir025, wir021 );
endmodule

module test;
   reg  [ 9:0] AB; // input DPD
   wire [11:0] C; // output BCD

  decode1000 U1 ( 
  .in_000 (AB[ 0]), 
  .in_001 (AB[ 1]), 
  .in_002 (AB[ 2]), 
  .in_003 (AB[ 3]), 
  .in_004 (AB[ 4]), 
  .in_005 (AB[ 5]), 
  .in_006 (AB[ 6]), 
  .in_007 (AB[ 7]), 
  .in_008 (AB[ 8]), 
  .in_009 (AB[ 9]), 
  .out000 ( C[ 0]),
  .out001 ( C[ 1]),
  .out002 ( C[ 2]),
  .out003 ( C[ 3]),
  .out004 ( C[ 4]),
  .out005 ( C[ 5]),
  .out006 ( C[ 6]),
  .out007 ( C[ 7]),
  .out008 ( C[ 8]),
  .out009 ( C[ 9]),
  .out010 ( C[10]),
  .out011 ( C[11])
  ); 

   initial  AB=0;  //unary=0;  binary=0
  always  #1  AB = AB+1;
  initial  begin
    $display("\t\ttime,\tinn 10bit   \tout 3x4bit"); 
    $monitor("%d,\t%b %b %b\t%b %b %b\t %d%d%d",$time, AB[9:7],AB[6:4],AB[3:0], C[11:8], C[7:4], C[3:0],  C[11:8], C[7:4], C[3:0]); 
  end 
  initial  #1023  $finish; 
endmodule

// How I run and test it:
// iverilog -o decode1000 decode1000.v
// vvp decode1000

3

65 62 60 58 NAND

Lấy đầu vào như i0để i9và kết quả đầu ra như o0để o9, oa, obchúng tôi có

t0 = nand(i6, i7)
t1 = nand(t0, t0)
t2 = nand(i3, i4)
o0 = nand(nand(nand(t2, i3), t1), nand(nand(t2, i8), t1))
t3 = nand(o0, o0)
t4 = nand(i0, t3)
o1 = nand(t4, t4)
t5 = nand(i1, t3)
o2 = nand(t5, t5)
o3 = i2
# Score 13 for the first decimal digit

u0 = nand(i6, i8)
u1 = nand(u0, t0)
u2 = nand(i4, t2)
o4 = nand(nand(nand(u2, u0), u2), nand(u1, t0))
u3 = nand(o4, o4)
u4 = nand(o0, i8)
u5 = nand(u4, u4)
u6 = nand(u3, nand(nand(u5, i0), nand(u4, i3)))
o5 = nand(u6, u6)
u7 = nand(u3, nand(nand(u5, i1), nand(u4, i4)))
o6 = nand(u7, u7)
o7 = i5
# Score 20 for the second decimal digit

o8 = nand(nand(nand(nand(i4, i8), o0), t1), nand(nand(i6, u1), i6))
v2 = nand(o8, o8)
v3 = nand(i6, i6)
v4 = nand(i7, i7)
v5 = nand(v2, nand(nand(i6, nand(nand(i7, i0), nand(v4, i3))), nand(v3, i7)))
o9 = nand(v5, v5)
v6 = nand(v2, nand(nand(i6, nand(nand(i7, i1), nand(v4, i4))), nand(v3, i8)))
oa = nand(v6, v6)
ob = i9
# Score 25 for the third decimal digit

Khung kiểm tra Python để xác nhận tính đúng đắn của việc xây dựng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.