[HDLBits Question 5] Circuits (1) Combinational Logic

write in front

Combinational Logic

Basic Gates

Wire

GND

NOR

Another gate

Two gates

More logic gates

7420 chips

Truth table

Two bit equality

Simple circuit A

Simple circuit B

Combine circuits A and B

Ring or vibrate

Thermostat

3 bit population count

Gates and vectors

Even longer vectors

Multiplexers

2 to 1 mux

2 to 1 bus mux

9 to 1 mux

256 to 1 mux

256 to 1 4bit mux

Arithmetic Circuits

Karnaugh Map to Circuit

Camp 1

kamp2

kamp3

match4

min_SOP

kmap5

kmap6

kmap imple

write in front

This blog provides answers and partial analysis of the first two sections of the combinatorial logic in the Circuits section. Some relatively simple questions will be answered directly, and some difficult questions will be explained a little bit. The answer to each question is not necessarily unique, and there can be multiple solutions. plan, welcome to discuss together.

Combinational Logic

Basic Gates

Wire

Simple logic implementation

module top_module (
input   in,
output  out
);
assign out = in;
endmodule

GND

Directly ground the output, the implication is to set the output to 0

module top_module (
output   out
);
assign out = 1'b0;
endmodule

NOR

Implement a NOR gate

module top_module (
input   in1,
input   in2,
output  out
);
assign out = !(in1 | in2);

endmodule

Another gate

module top_module (
input   in1,
input   in2,
output  out
);
assign out = (in1 & (~in2));
endmodule

Two gates

Continuous XOR operation with a NOT gate added in the middle

module top_module (
input   in1,
input   in2,
input   in3,
output  out
);
assign out = (~(in1 ^ in2)) ^ in3;

endmodule

More logic gates

Implement various logic gates

module top_module(
input   a, b,
output  out_and,
output  out_or,
output  out_xor,
output  out_nand,
output  out_nor,
output  out_xnor,
output  out_anotb
);

assign out_and = a & b;
assign out_or = a | b;
assign out_xor = a ^ b;
assign out_nand = ~(a & b);
assign out_nor = ~(a | b);
assign out_xnor = ~(a ^ b);
assign out_anotb = a & (~b);

endmodule

7420 chips

Realize the function of 7420 chip, simple NAND gate

module top_module (
input   p1a, p1b, p1c, p1d,
output  p1y,
input   p2a, p2b, p2c, p2d,
output  p2y
);

assign p1y = ~(p1a & p1b & p1c & p1d);
assign p2y = ~(p2a & p2b & p2c & p2d);

endmodule

Truth table

Logical implementation of the truth table, this answer is not unique.

module top_module(
input   x3,
input   x2,
input   x1,
output  f
);
assign f = x3?x1:x2;

endmodule

Two bit equality

module top_module (
input [1:0]  A,
input [1:0]  B,
output       z
);
assign z = (A == B)? 1:0;

endmodule

Simple circuit A

module top_module (
input   x,
input   y,
output  z
);
assign z = (x ^ y) & x;

endmodule

Simple circuit B

module top_module (
input   x,
input   y,
output  z
);
assign z = ~(x ^ y);

endmodule

Combine circuits A and B

The functions of the previous circuits A and B are combined, but they can also be implemented directly by logic without calling the previous modules.

module top_module (
input   x,
input   y,
output  z
);
wire    a1,a2,b1,b2;
wire    sum1,sum2;

assign a1 = (x ^ y) & x;
assign b1 = ~(x ^ y);
assign a2 = (x ^ y) & x;
assign b2 = ~(x ^ y);

assign sum1 = a1 | b1;
assign sum2 = a2 & b2;

assign z = sum1 ^ sum2;

endmodule

Ring or vibrate

Design a circuit to control the phone’s ringer and vibration motor. Whenever the phone needs to ring from an incoming call, your circuit must turn on either the ringer or the motor, but not both. If the phone is in vibrate mode, turn on the motor. Otherwise, turn on the ringtone.

input **ring**

output **ringer** = 1

output **motor** = 1

input **vibrate_mode** = 1

module top_module (
input    ring,
input    vibrate_mode,
output   ringer,
output   motor
);

assign ringer = ((ring == 1'b1) && (vibrate_mode == 1'b0))? 1'b1:1'b0;
assign motor = ((vibrate_mode ==1'b1) && (ring == 1'b1))? 1'b1:1'b0;

Thermostat

Heating/cooling thermostat controls heater (winter) and air conditioner (summer). Implement a circuit that will turn the heater, air conditioner, and blower fan on and off as needed.

The thermostat can be in one of two modes: heating and cooling. In heating mode, turn on the heater when it is too cold, but do not use the air conditioner. In cooling mode, turn on the air conditioner when it is too hot, but do not turn on the heater. When the heater or air conditioner is on, also turn on the fan to circulate the air. Additionally, the user can also ask the fan to be on even if the heater and air conditioner are off.

mode = 1 mode = 0 too_cold = 1 too_hot = 1 fan_on = 1

Try using only statements to see if you can convert the problem description into a collection of logic gates.

module top_module (
input    too_cold,
input    too_hot,
input    mode,
input    fan_on,
output   heater,
output   aircon,
output   fan
);

assign heater = too_cold & mode;
assign aircon = too_hot & ~mode;
assign fan = fan_on | heater | aircon;

endmodule

3 bit population count

The “total count” circuit counts the number of ‘1’s in the input vector. Build a total count circuit for a 3-bit input vector.

Logic implements nesting.

module top_module(
input  [2:0]  in,
output [1:0]  out
);

assign out = (in=='d1 | in=='d2 | in=='d4)?'d1:((in=='d3 | in=='d5 | in=='d6)?'d2:((~in)?'d0:'d3));

endmodule

Gates and vectors

In [3:0], a four-bit input vector is obtained. We want to know some relationship between each bit and its neighbors:

• out_both : Each bit of this output vector should indicate whether the corresponding input bit and its left side (higher index) are both ‘1’. For example, out_both[2] should indicate whether in[2] and in[3] are both 1s. Since there is no neighbor to the left of in[3], we don’t need to know out_both[3].
• out_any : Each bit of this output vector shall indicate whether any corresponding input bit and its right side are ‘1’. For example, out_any[2] should indicate whether [2] or [1] is 1. Since in[0] has no right-hand number, we don’t need to know out_any[0].
• out_different : Each bit of this output vector should indicate whether the corresponding input bit is different from its left side . For example, out_different[2] should indicate whether in[2] is different from in[3]. For this part, the vector is treated as wrapping, so the left neighbor in [3] is in [0].

module top_module(
input   [3:0]   in,
output  [2:0]   out_both,
output  [3:1]   out_any,
output  [3:0]   out_different
);
assign   out_both[0]        =   (in[0] & in[1]);
assign   out_both[1]        =   (in[1] & in[2]);
assign   out_both[2]        =   (in[2] & in[3]);
assign   out_any[1]         =   (in[1] | in[0]);
assign   out_any[2]         =   (in[2] | in[1]);
assign   out_any[3]         =   (in[3] | in[2]);
assign   out_different[0]   =   (in[0] != in[1]);
assign   out_different[1]   =   (in[1] != in[2]);
assign   out_different[2]   =   (in[2] != in[3]);
assign   out_different[3]   =   (in[3] != in[0]);

endmodule

Even longer vectors

similar to the above

module top_module(
input  [99:0]   in,
output [98:0]   out_both,
output [99:1]   out_any,
output [99:0]   out_different
);

assign out_both[98:0]      = in[99:1] & in[98:0];
assign out_any[99:1]       = in[99:1] | in[98:0];
assign out_different[98:0] = in[98:0] ^ in[99:1];
assign out_different[99]   = in[99] ^ in[0];

endmodule

Multiplexers

2 to 1 mux

Create a 1-bit wide 2-to-1 multiplexer. When sel=0, select a. When sel=1, select b.

module top_module(
input   a, b, sel,
output  out
);
assign out = sel?b:a;

endmodule

2 to 1 bus mux

Create a 100-bit wide 2-to-1 multiplexer. When sel=0, select a. When sel=1, select b.

module top_module(
input  [99:0]  a, b,
input          sel,
output [99:0]  out
);
assign out = sel?b:a;

endmodule

9 to 1 mux

Create a 16-bit wide, 9-to-1 multiplexer. sel=0 selects a, sel=1 selects b, and so on. For unused cases (sel=9 to 15), set all output bits to ‘1’.

module top_module(
input  [15:0]  a, b, c, d, e, f, g, h, i,
input  [3:0]   sel,
output [15:0]  out
);
assign out = (sel== 'd0)?a:((sel==' d1) ?b : ((sel== 'd2)?c:((sel==' d3) ?d : ( (sel== = 'd4)?e:((sel==' d5) ?f : ((sel== 'd6)?g:((sel==' d7) ?h : ((sel== 'd8)?i :16' hffff))))))));

endmodule

256 to 1 mux

Create a 16-bit wide, 9-to-1 multiplexer. sel=0 selects a, sel=1 selects b, and so on. For unused cases (sel=9 to 15), set all output bits to ‘1’.

module top_module(
input  [255:0] in,
input  [7:0]   sel,
output         out
);
assign out = in[sel];

endmodule

256 to 1 4bit mux

Create a 16-bit wide, 9-to-1 multiplexer. sel=0 selects a, sel=1 selects b, and so on. For unused cases (sel=9 to 15), set all output bits to ‘1’.

module top_module(
input  [1023:0]  in,
input  [7:0]     sel,
output [3:0]     out
);
assign out = in[sel*4+3-:4];

endmodule

Arithmetic Circuits

Create a half adder. Half adder adds two bits (no residue) and produces a sum and executes.

module top_module (
input  [7:0]  a,
input  [7:0]  b,
output [7:0]  s,
output        overflow
);

assign s = a + b;
assign overflow = (~a[7] & ~b[7] & s[7]) | (a[7] & b[7] & ~s[7]);

endmodule

module top_module(
input   a, b, cin,
output  cout, sum
);
assign {cout,sum} = a + b + cin;
endmodule

Create 3 instances to create a 3-bit binary ripple-carrying adder. The adder adds two 3-bit numbers and a carry number to generate a 3-bit sum and executes. Executed from each full adder output in the ripple-carrying adder. cout[2] is the final execution of the last full adder.

module top_module(
input  [2:0]  a, b,
input         cin,
output [2:0]  cout,
output [2:0]  sum
);
assign {cout[0],sum[0]} = a[0] + b[0] + cin;
assign {cout[1],sum[1]} = a[1] + b[1] + cout[0];
assign {cout[2],sum[2]} = a[2] + b[2] + cout[1];

endmodule

Do a traveling wave accumulator, a full adder

module top_module (
input  [3:0]  x,
input  [3:0]  y,
output [4:0]  sum
);

wire     cin1, cin2, cin3;

assign {cin1,sum[0]} = x[0] + y[0];
assign {cin2,sum[1]} = x[1] + y[1] + cin1;
assign {cin3,sum[2]} = x[2] + y[2] + cin2;
assign {sum[4],sum[3]} = x[3] + y[3] + cin3;

endmodule

Suppose there are two 8-bit 2’s complement numbers, a[7:0] and b[7:0]. Adding these numbers produces s[7:0]. Also calculate if a (signed) overflow has occurred. The sign bit of the addition of two positive numbers becomes 1 to indicate overflow, and the sign bit of the addition of two negative numbers becomes 0 to indicate overflow.

module top_module (
input  [7:0]  a,
input  [7:0]  b,
output [7:0]  s,
output        overflow
);

assign s = a + b;
assign overflow = (~a[7] & ~b[7] & s[7]) | (a[7] & b[7] & ~s[7]);

endmodule

Create a 100-bit binary adder. The adder adds two 100-bit numbers and the carry to produce a 100-bit sum.

module top_module(
input  [99:0]  a, b,
input          cin,
output         cout,
output [99:0]  sum
);
assign {cout,sum} = a+b+cin;

endmodule

Instantiate 4 bcd_fadd blocks to create a 4-bit BCD ripple-carrying adder. The adder should add two 4-bit BCD numbers (packed into a 16-bit vector) and the carry value to generate a 4-bit sum and execute.

module top_module (
input  [15:0]  a, b,
input          cin,
output         cout,
output [15:0]  sum
);

wire      cin1 , cin2 , cin3 ;

.a    (a[3:0]),
.b    (b[3:0]),
.cin  (cin),
.cout (cin1),
.sum  (sum[3:0])
);

.a    (a[7:4]),
.b    (b[7:4]),
.cin  (cin1),
.cout (cin2),
.sum  (sum[7:4])
);

.a    (a[11:8]),
.b    (b[11:8]),
.cin  (cin2),
.cout (cin3),
.sum  (sum[11:8])
);

.a    (a[15:12]),
.b    (b[15:12]),
.cin  (cin3),
.cout (cout),
.sum  (sum[15:12])
);

endmodule

Karnaugh Map to Circuit

Camp 1

Logic realization based on Karnaugh map

module top_module(
input   a,
input   b,
input   c,
output  out
);
assign out = ((~a)&(~b)&(~c))?'d0:'d1;

endmodule

kamp2

Logic realization based on Karnaugh map

module top_module(
input   a,
input   b,
input   c,
input   d,
output  out
);

assign out = (a&~b&c&d)|(~a&b&~c&~d)|(~a&c&~d)|(b&c&d)|(~b&~c);

endmodule

kamp3

Logic realization based on Karnaugh map

module top_module(
input   a,
input   b,
input   c,
input   d,
output  out
);

assign out = (a&~c&~d)|(~b&c)|(a&b&c);
endmodule

match4

Logic realization based on Karnaugh map

module top_module(
input   a,
input   b,
input   c,
input   d,
output  out
);

assign out = (~a&b&~c&~d)|(a&~b&~c&~d)|(~a&~b&~c&d)|(a&b&~c&d)|(~a&b&c&d)|(a&~b&c&d)|(~a&~b&c&~d)|(a&b&c&~d);
endmodule

min_SOP

A single-output digital system with four inputs (a, b, c, d) generates logic – 1 when 2, 7, or 15 appears at the input, when 0, 1, 4, 5, 6, 9, 10, 13 or When 14 occurs, a logical -0 is generated. Input conditions for the numbers 3, 8, 11, and 12 never occur in this system. For example, 7 corresponds to a, b, c, d set to 0, 1, 1, 1 respectively. Determine the output out_sop in the smallest SOP form, and the output out_pos in the smallest POS form.

SOP: sum of product
in the Karnaugh map, 1 is positive, 0 is negative, first multiply and then add

POS: product of sum
in the Karnaugh map, 1 is negative, 0 is positive, first add and finally multiply and then negate

module top_module (
input    a,
input    b,
input    c,
input    d,
output   out_sop,
output   out_pos
);
assign out_sop = (~a&~b*c) | (c&d);
assign out_pos = ~((a|b|~c) & (~c|~d));

endmodule

kmap5

Logic realization based on Karnaugh map

module top_module (
input [4:1]  x,
output       f
);
assign f = (~x[1]&x[3]) | (x[1]&x[2]&~x[3]);

endmodule

kmap6

Logic realization based on Karnaugh map

module top_module (
input [4:1]  x,
output       f
);
assign f = (~x[1]&x[3]) | (x[1]&~x[2]&~x[4]) | (x[1]&x[2]&x[3]&x[4]) | (~x[1]&~x[2]&~x[3]&~x[4]);

endmodule

kmap imple

For the Karnaugh diagram below, use one 4-to-1 multiplexer and as many 2-to-1 multiplexers as possible to provide the circuit implementation, but use as few as possible. You must not use any other logic gates, you must use  a  and  b  as multiplexer selector inputs, as shown in the 4-to-1 multiplexer below.

module top_module (
input         c,
input         d,
output [3:0]  mux_in
);
assign mux_in[0] = c | d;
assign mux_in[1] = 'd0;
assign mux_in[2] = ~d;
assign mux_in[3] = c & d;
endmodule