Fahren Sie eine hexadezimale 7-Segment-Anzeige mit NAND-Logikgattern

9

Die allgegenwärtige numerische 7-Segment-Anzeige kann alle 16 hexadezimalen Ziffern eindeutig anzeigen, wie in dieser Wikipedia .gif gezeigt

Einträge für diese Herausforderung erstellen ein Schaltbild unter Verwendung von NAND-Logikgattern, das die vier Bits einer hexadezimalen Ziffer in die Eingänge für die sieben Segmente transformiert. Die Eingaben für die 7-Segment-Anzeige sind normalerweise wie folgt gekennzeichnet: (DP (Dezimalpunkt) wird bei dieser Herausforderung ignoriert)

Geben Sie hier die Bildbeschreibung ein

Daher muss Ihre Schaltung der folgenden Wahrheitstabelle entsprechen:

Hex   | Hex Input Bit | Output to Segment line:
digit |  3  2  1  0   |  A  B  C  D  E  F  G
------+---------------+-----------------------
   0  |  0  0  0  0   |  1  1  1  1  1  1  0
   1  |  0  0  0  1   |  0  1  1  0  0  0  0
   2  |  0  0  1  0   |  1  1  0  1  1  0  1
   3  |  0  0  1  1   |  1  1  1  1  0  0  1
   4  |  0  1  0  0   |  0  1  1  0  0  1  1
   5  |  0  1  0  1   |  1  0  1  1  0  1  1
   6  |  0  1  1  0   |  1  0  1  1  1  1  1
   7  |  0  1  1  1   |  1  1  1  0  0  0  0
   8  |  1  0  0  0   |  1  1  1  1  1  1  1
   9  |  1  0  0  1   |  1  1  1  1  0  1  1
   A  |  1  0  1  0   |  1  1  1  0  1  1  1
   b  |  1  0  1  1   |  0  0  1  1  1  1  1
   C  |  1  1  0  0   |  1  0  0  1  1  1  0
   d  |  1  1  0  1   |  0  1  1  1  1  0  1
   E  |  1  1  1  0   |  1  0  0  1  1  1  1
   F  |  1  1  1  1   |  1  0  0  0  1  1  1

Ich denke, diese Tabelle ist korrekt, aber bitte lassen Sie mich wissen, wenn Sie Fehler entdecken.

Ihre Punktzahl wird durch die Anzahl der von Ihnen verwendeten NAND-Gatter mit 2 Eingängen bestimmt (1 Punkt pro Gatter). Zur Vereinfachung können Sie in Ihrem Diagramm UND-, ODER-, NICHT- und XOR-Gatter mit den folgenden entsprechenden Bewertungen verwenden:

  • NOT: 1
  • AND: 2
  • OR: 3
  • XOR: 4
Digitales Trauma
quelle
Bei dieser Herausforderung scheint es darum zu gehen, einen Schaltplan zu zeichnen und nicht um die Codierung. Außerdem scheinen die Punktwerte pro Gate willkürlich zu sein (möglicherweise absichtlich), und die Verwendung von AND + NOT beträgt 3 Punkte, wenn Sie
angeben
@stokastic Es gibt viele andere Logic-Gates- Herausforderungen auf dieser Site, daher gehe ich davon aus, dass diese Kategorie von Herausforderungen für die Community akzeptabel ist. Viele verwenden das gleiche Bewertungssystem. Die NAND-Logik erklärt dieses Bewertungssystem meiner Meinung nach recht gut.
Digitales Trauma
Meinetwegen. Ich hatte diese Tags noch nie gesehen. Es scheint einfach nicht wirklich in "Programmierpuzzles" oder "Code Golf" zu passen.
stokastic
Kann sich der Stromkreis teilen? Mit anderen Worten, können Sie Werte in Variablen speichern und später abrufen?
xnor
@xnor Sprechen Sie über so etwas: codegolf.stackexchange.com/a/26235/11259 ? Wenn ja, lautet die Antwort ja.
Digitales Trauma

Antworten:

17

Domino - Gesamtpunktzahl: 243 NANDs

  • Verwendete ORs: 61 (jeweils 3 NANDs -> 183 NANDs)

  • Verwendete NOTs: 60 (je 1 NANDs -> 60 NANDs)

Diese Lösung besteht aus Dominosteinen und erfordert eine Sammlung von Software, die ich im Zuge der Beantwortung der beiden Domino-bezogenen Fragen von Martin Büttner ( Golfing for Domino Day und Domino Circuits ) geschrieben habe.

Durch Ändern meines Domino Circuit- Solvers konnte ich eine Domino-Schaltung (diese Datei enthält auch den Solver-Ausgang und das Schaltungsskelett) erstellen, die aus ORs und IFNOTs besteht, wobei der erste Eingang immer TRUE ist (es handelt sich also im Wesentlichen um ein NOT). Da gibt es nicht viel , das wird in dieser Antwort passen, präsentiere ich die OR und NOT - Lösungen für die Wahrheitstabelle:

A: 1011011111101011
((-1 ifnot (2 or (1 or (-1 ifnot 0)))) or ((-1 ifnot ((-1 ifnot 1) or (-1 ifnot 2))) or ((-1 ifnot (3 or (-1 ifnot (0 or (-1 ifnot 1))))) or (-1 ifnot (0 or ((-1 ifnot 3) or (-1 ifnot (2 or 1))))))))
B: 1111100111100100
((-1 ifnot (3 or 1)) or ((-1 ifnot (3 or (2 or 0))) or (-1 ifnot ((-1 ifnot 3) or ((-1 ifnot (2 or (0 or (-1 ifnot 1)))) or (-1 ifnot ((-1 ifnot 0) or (-1 ifnot 2))))))))
C: 1101111111110100
((-1 ifnot (2 or (-1 ifnot 3))) or ((-1 ifnot (1 or (-1 ifnot 0))) or (-1 ifnot (0 or (-1 ifnot (3 or (1 or (-1 ifnot 2))))))))
D: 1011011011011110
((-1 ifnot (3 or (1 or 0))) or ((-1 ifnot (2 or ((-1 ifnot (3 or 0)) or (-1 ifnot (1 or 0))))) or (-1 ifnot ((-1 ifnot 2) or ((-1 ifnot (3 or 1)) or (-1 ifnot ((-1 ifnot 1) or (-1 ifnot 3))))))))
E: 1010001010111111
((-1 ifnot (3 or (-1 ifnot (2 or (-1 ifnot 1))))) or (-1 ifnot ((-1 ifnot 0) or (-1 ifnot (2 or 1)))))
F: 1000111011111011
((-1 ifnot (3 or (-1 ifnot 1))) or ((-1 ifnot (2 or (0 or (-1 ifnot (1 or (-1 ifnot 3)))))) or (-1 ifnot ((-1 ifnot 0) or (-1 ifnot (2 or (-1 ifnot 1)))))))
G: 0011111011110111
((-1 ifnot (2 or (0 or (-1 ifnot 1)))) or ((-1 ifnot (1 or (-1 ifnot (2 or 0)))) or (-1 ifnot ((-1 ifnot (3 or 2)) or (-1 ifnot (0 or (-1 ifnot 3)))))))

Beachten Sie, dass die einzigen verwendeten binären Operationen OR und IFNOT sind, wobei ich jedes IFNOT für Bewertungszwecke als NICHT zähle

Ich habe am Ende der Schaltung eine 7-Segment-Anzeige hinzugefügt und sie einem Domino-Simulator / GIF-Generator zugeführt. Die Erstellung des resultierenden Gifs (das zeigt, dass 'A' angezeigt wird) dauerte ungefähr 2 Stunden. Da die endgültige Schaltung 1141 * 517 groß ist, wird jede "Zelle" durch ein einzelnes Pixel dargestellt. Eine schwarze Zelle ist leer, eine graue Zelle hat einen stehenden Domino und eine weiße Zelle hat einen gefallenen Domino. Dies bedeutet, dass Sie nicht wirklich sagen können, was los ist, und es hilft nicht, wenn es überhaupt gequetscht wird. Sparr hat freundlicherweise eine viel kleinere Version meines Original-Gifs (650kB) zur Verfügung gestellt, also hier ist es!

Animation

Unten ist das letzte Bild der Animation für Eingabe 1010 ('A') wie oben. Sie sehen die Eingänge ganz links, die Stromleitung oben, die Schalttafel, die den größten Teil des Platzes einnimmt, die 7 einzelnen Logikelemente (dies sind Domino-Darstellungen der obigen Funktionen) links von der Schalttafel und bis Ganz rechts befindet sich die 7-Segment-Anzeige. Wenn dies ausgeführt wird, leuchten die einzelnen Segmente ungefähr gleichzeitig auf, sodass Sie es nicht zu lange betrachten können, da einige Segmente leuchten und darauf warten, dass andere aufleuchten.

Letzter Frame der Animation

Sehen Sie die Animation in voller Pracht hier (36 MB) oder hier (650 KB, mit freundlicher Genehmigung von Sparr) (die kleinere Kopie ist viel kleiner, aber mein Browser schien es zu mögen, Frames zu überspringen, die die Schönheit beeinträchtigen, also habe ich das Original so belassen)

Die Details der 7-Segment - Anzeige zu erkennen sind hier ( ‚1‘ ist gezeigt)

VisualMelon
quelle
3
+1 für die reine Surrealität, ein 7-Segment-Display mit Dominosteinen zu fahren!
Digitales Trauma
Das ist erstaunlich ... Jemand sollte dies im wirklichen Leben versuchen
Beta Decay
11

30 NANDs

Ich bin mir ziemlich sicher, dass es keine einfacheren Lösungen für dieses Problem gibt, außer vielleicht durch Ändern der Symbole auf dem Display, aber das wäre ein anderes und anderes Problem.

Da dies tatsächlich nützlich ist, beispielsweise beim Programmieren eines FPGA zur Anzeige der Ausgabe, stelle ich Verilog-Code bereit.

Was den Minimalismus betrifft: Natürlich war es schwierig zu machen. Es ist nicht nachvollziehbar, da eine 7-Segment-Anzeige nur eine ziemlich zufällige Art ist, wie Menschen Zahlen anzeigen, was zu einer Schaltung führt, die ebenfalls ziemlich zufällig ist. Und wie es für diese minimalen Schaltungen typisch ist, ist ihre logische Tiefe etwas höher als für enge Lösungen. Ich denke, das liegt daran, dass seriell einfacher als parallel ist.

Die Übertragungsverzögerung wird durch die Abwärtsposition jedes NAND-Gatters auf dem Blatt angezeigt.

Minimaler hexadezimaler 7-Segment-Anzeigetreiber

Verilog-Code:

// Hexadecimal 7-segment display driver
// Minimal at 30 NANDs
//
// By Kim Øyhus 2018 (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/37648/drive-a-hexadecimal-7-segment-display-using-nand-logic-gates
//
// I am quite sure there are no simpler solutions to this problem,
// except perhaps by changing the symbols on the display,
// but that would be another and different problem.
//
// Since this is actually something useful to do, for instance when
// programming an FPGA to show output, I provide this Verilog code.
//
// As for the minimalism: Of course it was tricky to make.
// It is not comprehensible, since a 7-segment display is
// just a fairly random way of showing numbers, resulting
// in a circuit that is fairly random too.
// And as is typical for these minimal circuits, its logical depth
// is somewhat higher than for close solutions. I guess this is because
// serial is simpler than parallel.
//
// 4 bits of input "in_00?", and 7 bits of output,
// one bit per LED in the segment.
//   A
// F   B
//   G
// E   C
//   D

module display7 ( in_000, in_001, in_002, in_003,  G, F, E, D, C, B, A );
  input in_000, in_001, in_002, in_003;
  output G, F, E, D, C, B, A;
  wire wir000, wir001, wir002, wir003, wir004, wir005, wir006, wir007, wir008, wir009, wir010, wir011, wir012, wir013, wir014, wir015, wir016, wir017, wir018, wir019, wir020, wir021, wir022 ;

  nand gate000 ( wir000, in_000, in_002 );
  nand gate001 ( wir001, in_000, in_000 );
  nand gate002 ( wir002, wir000, in_001 );
  nand gate003 ( wir003, in_001, wir002 );
  nand gate004 ( wir004, wir000, wir002 );
  nand gate005 ( wir005, in_002, wir003 );
  nand gate006 ( wir006, in_003, wir001 );
  nand gate007 ( wir007, wir006, wir004 );
  nand gate008 ( wir008, in_003, wir005 );
  nand gate009 ( wir009, wir005, wir008 );
  nand gate010 ( wir010, in_003, wir008 );
  nand gate011 ( wir011, wir010, wir009 );
  nand gate012 ( wir012, wir010, wir007 );
  nand gate013 ( wir013, wir001, wir011 );
  nand gate014 ( wir014, wir003, wir004 );
  nand gate015 (      G, wir011, wir014 );
  nand gate016 ( wir015, in_003, wir014 );
  nand gate017 ( wir016, wir015, wir013 );
  nand gate018 (      C, wir016, wir012 );
  nand gate019 ( wir017, wir016, wir007 );
  nand gate020 ( wir018, wir003, wir012 );
  nand gate021 ( wir019, wir017, in_003 );
  nand gate022 (      F, wir011, wir017 );
  nand gate023 (      D, wir018, wir017 );
  nand gate024 (      B, wir012,      F );
  nand gate025 ( wir020, wir004, wir018 );
  nand gate026 ( wir021, wir001,      D );
  nand gate027 (      E, wir019, wir021 );
  nand gate028 ( wir022,      D, wir019 );
  nand gate029 (      A, wir020, wir022 );
endmodule

Kim Øyhus

KimOyhus
quelle
Dies ist eine wirklich beeindruckende Lösung! Warum bist du so zuversichtlich, dass man es nicht besser als 30 machen kann? 37 sah schon "ziemlich reduziert" aus, imo.
Alex Meiburg
Vielen Dank. Ich habe über diese Lösung hinaus gesucht und viel mehr Zeit dafür aufgewendet, als die Lösung selbst zu finden, und da war nichts. Die Wahrscheinlichkeit, dass ich etwas Besseres verpasst habe, ist sehr gering. Es ist ein statistisches Argument.
KimOyhus
7

Mit ~ für NOT und N für NAND findet eine Computersuche (ohne Begriffe zwischen Ausgängen zu teilen) eine Lösung mit 82 NANDs ohne Teilen. Das manuelle Suchen nach Freigabebegriffen reduziert diese auf 54 NANDs, und eine Computersuche, die das Freigeben umfasst, reduziert sie weiter auf 37 NANDs. Das Minimum könnte sogar noch niedriger sein, da die Methode sicherlich nicht erschöpfend ist.

Hier ist das Programm, das die obige Tabelle neu erstellt. Jede Zeile ist mit den NANDS für diese Ausgabe gekennzeichnet.

#include <stdio.h>

int N(int x, int y) { return 1 & ~(x & y); }

void main(void)
{
    int i0, i1, i2, i3;
    for (i3 = 0; i3 <= 1; i3++) {
    for (i2 = 0; i2 <= 1; i2++) {
    for (i1 = 0; i1 <= 1; i1++) {
    for (i0 = 0; i0 <= 1; i0++) {
            printf("%d %d %d %d : %d %d %d %d %d %d %d\n", i3, i2, i1, i0,
    /* 14 */        N(N(N(i3, N(i2, i1)), N(N(i2, i0), ~i1)), N(N(i2, N(i3, N(i3, i0))), N(i0, N(i3, N(i3, i1))))),
    /* 12 */        N(N(N(i3, i0), N(i2, N(i1, i0))), N(~i1, N(N(i3, i0), N(~i3, N(i2, i0))))),
    /* 10 */        N(N(i0, N(i3, i1)), N(N(i3, i2), N(i1, N(i1, N(~i3, ~i2))))),
    /* 16 */        N(N(N(i2, i1), N(N(i3, i0), N(i2, i0))), N(N(i0, N(i1, ~i2)), N(N(i3, i2), N(N(i3, i1), N(i2, N(i2, i1)))))),
    /*  7 */        N(N(i3, i2), N(N(i2, N(i2, i1)), N(i0, N(i3, i1)))),
    /* 11 */        N(N(i3, N(i2, N(i3, i1))), N(N(i1, N(i2, N(i2, i0))), N(i0, N(i2, ~i3)))),
    /* 12 */        N(N(i3, i0), ~N(N(i1, N(i2, i0)), N(N(i3, i2), N(~i3, N(i2, N(i2, i1)))))) );
    } } } }
}

Und hier ist die Ausgabe:

0 0 0 0 : 1 1 1 1 1 1 0
0 0 0 1 : 0 1 1 0 0 0 0
0 0 1 0 : 1 1 0 1 1 0 1
0 0 1 1 : 1 1 1 1 0 0 1
0 1 0 0 : 0 1 1 0 0 1 1
0 1 0 1 : 1 0 1 1 0 1 1
0 1 1 0 : 1 0 1 1 1 1 1
0 1 1 1 : 1 1 1 0 0 0 0
1 0 0 0 : 1 1 1 1 1 1 1
1 0 0 1 : 1 1 1 1 0 1 1
1 0 1 0 : 1 1 1 0 1 1 1
1 0 1 1 : 0 0 1 1 1 1 1
1 1 0 0 : 1 0 0 1 1 1 0
1 1 0 1 : 0 1 1 1 1 0 1
1 1 1 0 : 1 0 0 1 1 1 1
1 1 1 1 : 1 0 0 0 1 1 1

Und hier sind die äquivalenten Gleichungen, die Begriffe teilen, die es auf 54 NANDs bringen:

    /* 1 */ int z1 = 1 - i1;
    /* 1 */ int z2 = 1 - i2;
    /* 1 */ int z3 = 1 - i3;

    /* 1 */ int n_i2_i0 = N(i2, i0);
    /* 1 */ int n_i2_i1 = N(i2, i1);
    /* 1 */ int n_i3_i0 = N(i3, i0);
    /* 1 */ int n_i3_i1 = N(i3, i1);
    /* 1 */ int n_i3_i2 = N(i3, i2);

    /* 1 */ int n_i0_n_i3_i1 = N(i0, n_i3_i1);
    /* 1 */ int n_i2_n_i2_i1 = N(i2, n_i2_i1);

            printf("%d %d %d %d : %d %d %d %d %d %d %d\n", i3, i2, i1, i0,
    /* 9 */ N(N(N(i3, n_i2_i1), N(n_i2_i0, z1)), N(N(i2, N(i3, n_i3_i0)), N(i0, N(i3, n_i3_i1)))),
    /* 7 */ N(N(n_i3_i0, N(i2, N(i1, i0))), N(z1, N(n_i3_i0, N(z3, n_i2_i0)))),
    /* 5 */ N(n_i0_n_i3_i1, N(n_i3_i2, N(i1, N(i1, N(z3, z2))))),
    /* 8 */ N(N(n_i2_i1, N(n_i3_i0, n_i2_i0)), N(N(i0, N(i1, z2)), N(n_i3_i2, N(n_i3_i1, n_i2_n_i2_i1)))),
    /* 2 */ N(n_i3_i2, N(n_i2_n_i2_i1, n_i0_n_i3_i1)),
    /* 8 */ N(N(i3, N(i2, n_i3_i1)), N(N(i1, N(i2, n_i2_i0)), N(i0, N(i2, z3)))),
    /* 6 */ N(n_i3_i0, ~N(N(i1, n_i2_i0), N(n_i3_i2, N(z3, n_i2_n_i2_i1)))) );

Und hier ist die 37 NAND-Lösung:

    x0fff =  N(i3, i2);
    x33ff =  N(i3, i1);
    x55ff =  N(i3, i0);
    x0f0f =  not(i2);
    x3f3f =  N(i2, i1);
    x5f5f =  N(i2, i0);
    xcfcf =  N(i2, x3f3f);
    xf3f3 =  N(i1, x0f0f);
    x5d5d =  N(i0, xf3f3);
    xaaa0 =  N(x55ff, x5f5f);
    xfc30 =  N(x33ff, xcfcf);
    xd5df =  N(x3f3f, xaaa0);
    xf3cf =  N(x0fff, xfc30);
    xaeb2 =  N(x5d5d, xf3cf);
    x7b6d =  N(xd5df, xaeb2);
    xb7b3 =  N(i1, x7b6d);
    xf55f =  N(x0fff, xaaa0);
    xcea0 =  N(x33ff, xf55f);
    x795f =  N(xb7b3, xcea0);
    xd7ed =  N(xaeb2, x795f);
    xfaf0 =  N(x55ff, x0f0f);
    xae92 =  N(x55ff, x7b6d);
    xdd6d =  N(x33ff, xae92);
    x279f =  N(xfaf0, xdd6d);
    xaf0f =  N(i2, x55ff);
    x50ff =  N(i3, xaf0f);
    xef4c =  N(xb7b3, x50ff);
    x1cb3 =  N(xf3cf, xef4c);
    xef7c =  N(xf3cf, x1cb3);
    xfb73 =  N(i1, x279f);
    x2c9e =  N(xd7ed, xfb73);
    xdf71 =  N(xf3cf, x2c9e);
    xdd55 =  N(i0, x33ff);
    xf08e =  N(x0fff, xdf71);
    x2ffb =  N(xdd55, xf08e);
    x32ba =  N(xcfcf, xdd55);
    xfd45 =  N(x0fff, x32ba);

    printf("%d %d %d %d : %d %d %d %d %d %d %d\n", i3, i2, i1, i0,
            xd7ed, x279f, x2ffb, x7b6d, xfd45, xdf71, xef7c);
    } } } }
AoneOne
quelle
2
Sie sollten einen stolzen Header mit "37 NANDs" haben. Ihr Beitrag ist ohne das zu bescheiden.
KimOyhus
4

197 NANDs

Da dies meine erste Herausforderung für Logikgatter ist. Es wird nicht viel Golf gespielt und ist möglicherweise nicht die kleinste Lösung. Ich verwende hier keinen Circuit Split.

A = OR(AND(d, NOT(AND(a, XOR(c, b)))), AND(NOT(d), NOT(AND(NOT(b), XOR(a, c)))))
B = AND(OR(OR(NOT(c), AND(NOT(d), NOT(XOR(b, a)))), AND(d, a)), NOT(AND(AND(d, b), a)))
C = OR(AND(NOT(c), NOT(AND(AND(NOT(d), b), NOT(a)))), AND(c, OR(NOT(d), AND(AND(d, NOT(b)), a))))
D = AND(OR(OR(OR(a, c), AND(AND(NOT(d), NOT(c)), NOT(a))), AND(AND(d, NOT(c)), NOT(b))), NOT(OR(AND(AND(NOT(d), NOT(b)), XOR(c, a)), AND(AND(c, b), a))))
E = OR(AND(NOT(a), NOT(AND(AND(NOT(d), c), NOT(b)))), AND(d, NOT(AND(AND(NOT(c), NOT(b)), a))))
F = AND(OR(OR(d, c), AND(NOT(b), NOT(a))), NOT(AND(AND(c, a), XOR(d, b))))
G = AND(OR(OR(d, c), b), NOT(OR(AND(AND(NOT(d), c), AND(b, a)), AND(AND(d, c), AND(NOT(b), NOT(a))))))
  • 36 NOTs verwendet, 36 NANDs
  • 41 ANDs verwendet, 84 NANDs
  • 19 OPs verwendet, 57 NANDs
  • 5 XORs verwendet, 20 NANDs

Wenn ich recht habe, ist meine Punktzahl 197 .


Während dieser Herausforderung habe ich einen einfachen JavaScript-Code erstellt, um mein Gate zu testen.

function NOT(a){return !a}function AND(a,b){return a&b}function OR(a,b){return a|b}function XOR(a,b){return a^b}
for(d=0;d<=1;d++){for(c=0;c<=1;c++){for(b=0;b<=1;b++){for(a=0;a<=1;a++){console.log(""+d+c+b+a,
    // Enter your gate here
    // OR(AND(d, NOT(AND(a, XOR(c, b)))), AND(NOT(d), NOT(AND(NOT(b), XOR(a, c)))))
)}}}}

Kopieren und ändern Sie das Gate und fügen Sie es in die Konsole Ihres Browsers oder in Node.js REPL ein.

Snack
quelle