Щільно упакований десятковий (DPD) до десяткового, з логічними воротами


13

Натхненний недавньою популярністю нандгейму в ТНБ і моїм власним попереднім викликом .

Фон

Щільно упакований десятковий (DPD) - це спосіб ефективно зберігати десяткові цифри у двійкових. Він зберігає три десяткових цифри (000 до 999) в 10 біт, що набагато ефективніше, ніж наївний BCD (який зберігає одну цифру в 4 біти).

Таблиця переходів

DPD призначений для легкого перетворення між бітами та цифрами шляхом простого узгодження шаблону зверху вниз. Кожна бітова схема визначає, скільки високих цифр (8-9) має число, де вони знаходяться, і як переміщати біти, щоб утворити десятковий подання.

Далі наведена таблиця перетворення від 10 біт DPD до трьох десяткових цифр. Кожна десяткова цифра представлена ​​у вигляді 4-розрядного двійкового (BCD). Обидві сторони записуються зліва направо від найбільш значущої цифри до найменшої.

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)

Позначення

  • Малі літери aв iті біти, які копіюються в десятковому поданні.
  • 0і 1є точними бітами у вхідних або вихідних бітах.
  • x біти ігноруються при перетворенні.

Завдання

Побудуйте логічну схему, використовуючи два вхідні ворота NAND для перетворення 10 біт DPD в 12 біт BCD.

Приклади

Підкреслені біти - це біти, що відповідають шаблону.

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
      ^ ^   ^ ^ ^

Критерій оцінювання та виграшу

Оцінка - це кількість двох вхідних воріт NAND, використаних у вашій схемі. Виграє найнижчий бал.

Ви можете визначити невеликі компоненти за двома вхідними воротами NAND, а потім використовувати їх у своїй остаточній конструкції. Якщо компонент Xвключає Nдва вхідні ворота NAND, кожне використання Xдодає Nдо вашої оцінки. Для основних логічних воріт це означає:

  • НЕ: +1
  • 2-вхід І: +2
  • 2-вхід АБО: +3
  • 2-вхід XOR: +4

Відмовлявся від редагування Луїса, оскільки атомний код-гольф - це виграшний тег критерію, а виклик коду - для питань, які мають критерій виграшу, не охоплений іншими тегами.
Пітер Тейлор

Це мені досі незрозуміло. Я думаю , що там має бути подальше опис того , що букви aв iувазі і процес перетворення. Пройдіться кроками, а не просто показуйте приклади і сподіваємось, що ми це зрозуміємо.
mbomb007

@ mbomb007, можливо, мені це просто зрозуміло, оскільки одна з моїх мов - SML. Цей перший блок коду - це практично посилання на реалізацію мови, що відповідає шаблону (хоча він працює і краще в SMLNJ, що відображає результат кожного твердження, ніж у MLton).
Пітер Тейлор

@ mbomb007 Я намагався уточнити характер відповідності таблиці таблиці переходів. Чи допомагає це?
Бубон

1
@Bubbler Так, це корисно
mbomb007

Відповіді:


4

45 НАНД (або 43)

45 здається абсолютним мінімумом, але досягти 43 NAND можна за допомогою хитрості: припускаючи, що найбільші числа правильно закодовані.

888, 889, 898, 899, 988, 989, 998, 999 повинні бути закодовані з 2 MSB як 00, для декодування потрібно всього 43 NAND.

Однак у специфікації для декодування вони вказані для ігнорування, тобто вони можуть бути будь-якими. Цілком обґрунтовано припущення, що ця вільніша специфікація може зажадати ще менше воріт, але це навпаки. Для цього потрібно 45 воріт. Ця економія може дати реальні переваги для реальних схем.

Я також знайшов схеми, які були значно ефективнішими та швидшими, містять ще кілька воріт.

Цього разу жодне зображення не намальовано олівцем. Можливо, пізніше.

Схема представлена ​​в очевидному коді 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 НАНД

Беручи входи як i0для i9і виходи , як o0до o9, oa, obнас

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

Тест-рамка Python для перевірки правильності побудови.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.