Pur calcolando internamente tutte le risposte, e quindi usando un mux per selezionare tra di loro funzionerà, non è certamente un design minimale.
Considera che puoi dividere il problema in bit; invece di un singolo blocco logico con due ingressi a 8 bit, è possibile partizionarlo come due sezioni a 4 bit, purché sia possibile collegarli per ottenere un risultato complessivo corretto. Fortunatamente, collegare le sezioni non è peggio di un singolo bit, che in caso di aggiunta rappresenta il bit di riporto. Quindi ogni slice a 4 bit ha un bit di carry-in e un bit di carry-out. (Nota che logici come AND e NOR non ne avranno nemmeno bisogno, anche se in seguito implementerai i turni sinistro / destro, questo bit sarà facilmente riutilizzato).
Portati all'estremo, potresti usare 8 fette da 1 bit ciascuna. È utile pensare alle sezioni da 1 bit, perché rende più semplice pensare a un approccio che ridimensiona a sezioni più grandi. Quindi con uno slice da 1 bit, hai solo 7 ingressi: il codice funzione a 4 bit, un bit dall'ingresso A, un bit dall'ingresso B e un bit carry-in. Hai anche solo due uscite: funzione e realizzazione. Quindi ora puoi scrivere le due funzioni di output in termini di soli 7 input, che è nel regno della capacità umana di ridurre ragionevolmente. Ti ritroverai con una manciata di porte che non necessariamente calcoleranno sempre tutte le funzioni, ma non importa cosa succede all'interno della fetta, solo che produce il risultato corretto se visto dall'esterno.
Ora puoi andare in un paio di modi. Un modo è semplicemente usare 8 di queste sezioni da 1 bit e il gioco è fatto. Un altro modo è quello di fare fette più grandi e quindi usarle. Passando da 1 bit a 2 bit, le equazioni vanno da 7 ingressi a 9 e 4 bit richiederanno funzioni di 13 ingressi. Non è necessariamente facile, ma darà risultati più compatti rispetto all'approccio compute-everything-then-mux. Inoltre, se guardi gli interni di un slice ALU 74181 a 4 bit, non vedrai un mux lì dentro.