# HDLBits – 7458

The 7458 is a chip with four AND gates and two OR gates. This problem is slightly more complex than 7420.

Create a module with the same functionality as the 7458 chip. It has 10 inputs and 2 outputs. You may choose to use an assign statement to drive each of the output wires, or you may choose to declare (four) wires for use as intermediate signals, where each internal wire is driven by the output of one of the AND gates. For extra practice, try it both ways.

https://hdlbits.01xz.net/wiki/7458

This problem is extremely similar to the wire declaration exercise. There are a ton correct solutions for this one, but we’ll stick to the node-based approach for simplicity. If the following code snippet doesn’t make sense, try sketching a quick diagram like in the wire declaration exercise. Just remember that each node corresponds to a wire that is created by each assign statement in the code snippet.

module top_module (
input  logic p1a,
input  logic p1b,
input  logic p1c,
input  logic p1d,
input  logic p1e,
input  logic p1f,
input  logic p2a,
input  logic p2b,
input  logic p2c,
input  logic p2d,
output logic p1y,
output logic p2y );
// Declare internal nodes
logic nodeA, nodeB, nodeC, nodeD;
// Internal logic assignments
assign nodeA = p2a & p2b;
assign nodeB = p2c & p2d;
assign nodeC = (p1a & p1b) & p1c;
assign nodeD = (p1d & p1e) & p1f;
// Output assignments
assign p2y = nodeA | nodeB;
assign p1y = nodeC | nodeD;
endmodule : top_module

In this case, since we are creating a model for an existing chip with extremely similar port names, the Verilog-2001 concise port list would definitely help to clean things up here. In addition, a reductive AND gate can be used to clean up the nodeC and nodeD logic. This is simply shorthand for the nodeC and nodeD logic written above. In order to perform this operation, we create a 3-bit logic vector by concatenating the inputs to each 3-input AND gate in the circuit diagram.

module top_module (
input  logic p1a, p1b, p1c, p1d, p1e, p1f,
input  logic p2a, p2b, p2c, p2d,
output logic p1y, p2y );
// Declare internal nodes
logic nodeA, nodeB, nodeC, nodeD;
// Internal logic assignments
assign nodeA = p2a & p2b;
assign nodeB = p2c & p2d;
assign nodeC = &{p1a, p1b, p1c};
assign nodeD = &{p1d, p1e, p1f};
// Output assignments
assign p2y = nodeA | nodeB;
assign p1y = nodeC | nodeD;
endmodule : top_module

Since there are so many ways to solve this problem, opt for whichever approach you feel is the cleanest and most understandable for yourself and others. We could also eliminate all of the internal nets by using substitution (for illustration purposes):

module top_module (
input  logic p1a, p1b, p1c, p1d, p1e, p1f,
input  logic p2a, p2b, p2c, p2d,
output logic p1y, p2y );
// Output assignments
assign p2y = (p2a & p2b) | (p2c & p2d);
assign p1y = &{p1a, p1b, p1c} | &{p1d, p1e, p1f};
endmodule : top_module

Although this solution is much more succinct, I think that you can see why this approach won’t scale once modules get more complicated. The trick is to find a happy balance between lines of code and understandability. The number of nodes that you want to use to improve understandability is up to you. I can write a basic main function in C++ in a couple of lines, but is this good code?

#include <iostream>
int main() { std::cout<<"I'm so optimal."<<std::endl; std::cout<<"Now imagine that I'm 100 times longer and your boss tells you to modify me since the original author left the company years ago."; }