文章目录
- 1. Basic Gates
- 1.1 Wire
- 1.2 AND
- 1.3 NOR
- 1.4 Another gate
- 1.5 Two gates
- 1.6 More logic gates
- 1.7 7420 chip
- 1.8 Truth table
- Synthesizing a circuit from a truth table 根据真值表推逻辑式
- 练习:Truthtable1
- 1.9 Two-bit equility
- 1.10 Simple circuit A
- 1.11 Simple circuit B
- 1.12 Combine circuit A and B
- 1.13 ring and vibrate?
- 1.14 Thermostat
- 1.15 3-bit population count
- 1.16 Gates and Vectors
- 1.17 Even longer vector
- 2. Multiplexers
- 2.1 2-to-1 multiplexer
- 2.2 2-to-1 bus multiplexer
- 2.3 9-to-1 multiplexer
- 2.4 256-to-1 multiplexer
- 2.5 256-to-1 4-bit multiplexer
- 3. Arithmetic Circuits
- 3.1 Half adder
- 3.2 Full adder
- 3.3 3-bit binary adder
- 3.4 Adder
- 3.5 signed addition overflow
- 3.6 100-bit binary adder
- 3.7 4-digit BCD adder
- 4. Karnaugh map to Circuit
- 4.1 3-variable
- 4.2 4-variable
- 4.3 4-variable
- 4.4 4-variable
- 4.5 Minimum SOP and POS
- 4.6 Karnaugh map
- 4.7 Karnaugh map
- 4.8 K-map implemented with a multiplexer
1. Basic Gates
1.1 Wire
Implement the following circuit:
module top_module (input in,output out);assign out = in;endmodule
1.2 AND
Implement the following circuit:
module top_module (output out);assign out = 1'b0;endmodule
1.3 NOR
module top_module (input in1,input in2,output out);assign out = ~(in1|in2);endmodule
1.4 Another gate
module top_module (input in1,input in2,output out);assign out = in1&(~in2);endmodule
1.5 Two gates
module top_module (input in1,input in2,input in3,output out);assign out = ~(in1^in2)^in3;endmodule
1.6 More logic gates
Ok, let’s try building several logic gates at the same time. Build a combinational circuit with two inputs, a and b.
There are 7 outputs, each with a logic gate driving it:
out_and: a and b
out_or: a or b
out_xor: a xor b
out_nand: a nand b
out_nor: a nor b
out_xnor: a xnor b
out_anotb: a and-not b
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
1.7 7420 chip
The 7400-series integrated circuits are a series of digital chips with a few gates each. The 7420 is a chip with two 4-input NAND gates.
Create a module with the same functionality as the 7420 chip. It has 8 inputs and 2 outputs.
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
1.8 Truth table
In the previous exercises, we used simple logic gates and combinations of several logic gates. These circuits are examples of combinational circuits. Combinational means the outputs of the circuit is a function (in the mathematics sense) of only its inputs. This means that for any given input value, there is only one possible output value. Thus, one way to describe the behaviour of a combinational function is to explicitly list what the output should be for every possible value of the inputs. This is a truth table.
For a boolean function of N inputs, there are 2N possible input combinations. Each row of the truth table lists one input combination, so there are always 2N rows. The output column shows what the output should be for each input value.
The above truth table is for a three-input, one-output function. It has 8 rows for each of the 8 possible input combinations, and one output column. There are four inputs combinations where the output is 1, and four where the output is 0.
Synthesizing a circuit from a truth table 根据真值表推逻辑式
第一步:从真值表内找输出端为“1”的各行,把每行的输入变量写成**乘积(&)**形式;遇到“0”的输入变量上加非号。
第二步:把各乘积项相加( | )
练习:Truthtable1
module top_module( input x3,input x2,input x1, // three inputsoutput f // one output
);assign f = ((~x3)&x2&(~x1))|((~x3)&x2&x1)|(x3&(~x2)&x1)|(x3&x2&x1);endmodule
1.9 Two-bit equility
Create a circuit that has two 2-bit inputs A[1:0] and B[1:0], and produces an output z. The value of z should be 1 if A = B, otherwise z should be 0.
module top_module ( input [1:0] A, input [1:0] B, output z ); always @(*)beginif(A[1:0]==B[1:0])z=1;elsez=0;end//另一个方法//assign = (A[1:0]==B[1:0]);endmodule
1.10 Simple circuit A
Module A is supposed to implement the function z = (x^y) & x. Implement this module.
module top_module (input x, input y, output z);assign z=(x^y) & x;endmodule
1.11 Simple circuit B
Circuit B can be described by the following simulation waveform:
module top_module ( input x, input y, output z );assign z = ((~x)&(~y)) | (x&y);// Or: Notice this is an XNOR.assign z = ~(x^y);endmodule
1.12 Combine circuit A and B
module top_module (input x, input y, output z);wire z1,z2,z3,z4;a a1(x,y,z1);b b1(x,y,z2);a a2(x,y,z3);b b2(x,y,z4);assign z= (z1|z2)^(z3&z4);endmodule module a(input x, input y, output z);assign z = (x^y)&x;
endmodulemodule b(input x, input y, output z);assign z = ~x^y;
endmodule
1.13 ring and vibrate?
Suppose you are designing a circuit to control a cellphone’s ringer and vibration motor.
Whenever the phone needs to ring from an incoming call (input ring), your circuit must either turn on the ringer (output ringer = 1) or the motor (output motor = 1), but not both.
If the phone is in vibrate mode (input vibrate_mode = 1), turn on the motor. Otherwise, turn on the ringer.
Try to use only assign statements, to see whether you can translate a problem description into a collection of logic gates.
module top_module (input ring,input vibrate_mode,output ringer, // Make soundoutput motor // Vibrate
);// When should ringer be on? When (phone is ringing) and (phone is not in vibrate mode)assign ringer = ring&(~vibrate_mode);// When should motor be on? When (phone is ringing) and (phone is in vibrate mode)assign motor = ring&vibrate_mode;endmodule
1.14 Thermostat
A heating/cooling thermostat controls both a heater (during winter) and an air conditioner (during summer). Implement a circuit that will turn on and off the heater, air conditioning, and blower fan as appropriate.
The thermostat can be in one of two modes: heating (mode = 1) and cooling (mode = 0).
- In heating mode, turn the heater on when it is too cold (too_cold = 1) but do not use the air conditioner.
- In cooling mode, turn the air conditioner on when it is too hot (too_hot = 1), but do not turn on the heater.
- When the heater or air conditioner are on, also turn on the fan to circulate the air. In addition, the user can also request the fan to turn on (fan_on = 1), even if the heater and air conditioner are off.
Try to use only assign statements, to see whether you can translate a 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
);// Reminder: The order in which you write assign statements doesn't matter. // assign statements describe circuits, so you get the same circuit in the end// regardless of which portion you describe first.// Fan should be on when either heater or aircon is on, and also when requested to do so (fan_on = 1).assign fan = heater | aircon | fan_on;// Heater is on when it's too cold and mode is "heating".assign heater = (mode & too_cold);// Aircon is on when it's too hot and mode is not "heating".assign aircon = (~mode & too_hot);// * Unlike real thermostats, there is no "off" mode here.endmodule
1.15 3-bit population count
A “population count” circuit counts the number of '1’s in an input vector. Build a population count circuit for a 3-bit input vector.
module top_module( input [2:0] in,output [1:0] out );always @(*)beginout = 2'd0;for(int i=0;i<3;i++)if(in[i]==1'b1)out = out+2'd1;elseout = out;endendmodule
1.16 Gates and Vectors
You are given a four-bit input vector in[3:0]. We want to know some relationships between each bit and its neighbour:
- out_both: Each bit of this output vector should indicate whether both the corresponding input bit and its neighbour to the left (higher index) are ‘1’. For example, out_both[2] should indicate if in[2] and in[3] are both 1. Since in[3] has no neighbour to the left, the answer is obvious so we don’t need to know out_both[3].
- out_any: Each bit of this output vector should indicate whether any of the corresponding input bit and its neighbour to the right are ‘1’. For example, out_any[2] should indicate if either in[2] or in[1] are 1. Since in[0] has no neighbour to the right, the answer is obvious so 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 neighbour to the left. For example, out_different[2] should indicate if in[2] is different from in[3]. For this part, treat the vector as wrapping around, so in[3]'s neighbour to the left 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
);// Use bitwise operators and part-select to do the entire calculation in one line of code// in[3:1] is this vector: in[3] in[2] in[1]// in[2:0] is this vector: in[2] in[1] in[0]// Bitwise-OR produces a 3 bit vector. | | |// Assign this 3-bit result to out_any[3:1]: o_a[3] o_a[2] o_a[1]// Thus, each output bit is the OR of the input bit and its neighbour to the right:// e.g., out_any[1] = in[1] | in[0]; // Notice how this works even for long vectors.assign out_any = in[3:1] | in[2:0];assign out_both = in[2:0] & in[3:1];// XOR 'in' with a vector that is 'in' rotated to the right by 1 position: {in[0], in[3:1]}// The rotation is accomplished by using part selects[] and the concatenation operator{}.assign out_different = in ^ {in[0], in[3:1]};endmodule
1.17 Even longer vector
You are given a 100-bit input vector in[99:0]. We want to know some relationships between each bit and its neighbour:
out_both: Each bit of this output vector should indicate whether both the corresponding input bit and its neighbour to the left are ‘1’. For example, out_both[98] should indicate if in[98] and in[99] are both 1. Since in[99] has no neighbour to the left, the answer is obvious so we don’t need to know out_both[99].
out_any: Each bit of this output vector should indicate whether any of the corresponding input bit and its neighbour to the right are ‘1’. For example, out_any[2] should indicate if either in[2] or in[1] are 1. Since in[0] has no neighbour to the right, the answer is obvious so 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 neighbour to the left. For example, out_different[98] should indicate if in[98] is different from in[99]. For this part, treat the vector as wrapping around, so in[99]'s neighbour to the left is in[0].
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 = in[99:1]&in[98:0];assign out_any = in[98:0]|in[99:1];assign out_different = in ^ {in[0],in[99:1]};endmodule
2. Multiplexers
2.1 2-to-1 multiplexer
Create a one-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module( input a, b, sel,output out ); assign out = sel ? b : a;endmodule
2.2 2-to-1 bus multiplexer
Create a 100-bit wide, 2-to-1 multiplexer. When sel=0, choose a. When sel=1, choose b.
module top_module( input [99:0] a, b,input sel,output [99:0] out );assign out = sel?b:a;endmodule
2.3 9-to-1 multiplexer
Create a 16-bit wide, 9-to-1 multiplexer. sel=0 chooses a, sel=1 chooses b, etc. For the 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 );always @(*)begincase(sel)4'h0: out = a;4'h1: out = b;4'h2: out = c;4'h3: out = d;4'h4: out = e;4'h5: out = f;4'h6: out = g;4'h7: out = h;4'h8: out = i;default: out = {16{1'b1}}; endcaseendendmodule
2.4 256-to-1 multiplexer
Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel=0 should select in[0], sel=1 selects bits in[1], sel=2 selects bits in[2], etc.
module top_module( input [255:0] in,input [7:0] sel,output out );assign out = in[sel];endmodule
2.5 256-to-1 4-bit multiplexer
Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel=0 should select bits in[3:0], sel=1 selects bits in[7:4], sel=2 selects bits in[11:8], etc.
module top_module( input [1023:0] in,input [7:0] sel,output [3:0] out );// 错误写法: assign out = in[4*sel+3:4*sel]; //verilog中要求向量下标可以是变量,但是位宽必须是常量assign out = {in[4*sel+3],in[4*sel+2],in[4*sel+1],in[4*sel]};endmodule
3. Arithmetic Circuits
3.1 Half adder
Create a half adder. A half adder adds two bits (with no carry-in) and produces a sum and carry-out.
module top_module( input a, b,output cout, sum );assign sum = a^b;assign cout = a&b;endmodule
3.2 Full adder
Create a full adder. A full adder adds three bits (including carry-in) and produces a sum and carry-out.
module top_module( input a, b, cin,output cout, sum );assign sum = a^b^cin;assign cout = a&b | a&cin | b&cin;endmodule
3.3 3-bit binary adder
Now that you know how to build a full adder, make 3 instances of it to create a 3-bit binary ripple-carry adder. The adder adds two 3-bit numbers and a carry-in to produce a 3-bit sum and carry out.
To encourage you to actually instantiate full adders, also output the carry-out from each full adder in the ripple-carry adder. cout[2] is the final carry-out from the last full adder, and is the carry-out you usually see.
module top_module( input [2:0] a, b,input cin,output [2:0] cout,output [2:0] sum );add add1(a[0],b[0],cin,cout[0],sum[0]);add add2(a[1],b[1],cout[0],cout[1],sum[1]);add add3(a[2],b[2],cout[1],cout[2],sum[2]);endmodule
module add(input a, input b,input cin, output cout, output sum);assign sum = a^b^cin;assign cout = a&cin | b&cin | a&b;endmodule
3.4 Adder
module top_module (input [3:0] x,input [3:0] y, output [4:0] sum);wire cout0,cout1,cout2;FA U1(x[0],y[0],0,cout0,sum[0]);FA U2(x[1],y[1],cout0,cout1,sum[1]);FA U3(x[2],y[2],cout1,cout2,sum[2]);FA U4(x[3],y[3],cout2,sum[4],sum[3]);// This circuit is a 4-bit ripple-carry adder with carry-out.//assign sum = x+y; // Verilog addition automatically produces the carry-out bit.// Verilog quirk: Even though the value of (x+y) includes the carry-out, (x+y) is still considered to be a 4-bit number (The max width of the two operands).// This is correct:// assign sum = (x+y);// But this is incorrect:// assign sum = {x+y}; // Concatenation operator: This discards the carry-outendmodulemodule FA ( input a, input b, input cin, output cout,output sum);assign sum = a^b^cin;assign cout = a&b|a&cin|b&cin;
endmodule
3.5 signed addition overflow
Assume that you have two 8-bit 2’s complement numbers, a[7:0] and b[7:0]. These numbers are added to produce s[7:0]. Also compute whether a (signed) overflow has occurred.
实现8位有符号数据的二进制补码加法,并通过检测符号位变化来判断是否发生溢出
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
3.6 100-bit binary adder
Create a 100-bit binary adder. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out.
module top_module( input [99:0] a, b,input cin,output cout,output [99:0] sum );assign {cout,sum} = a+b+cin;endmodule
3.7 4-digit BCD adder
You are provided with a BCD (binary-coded decimal) one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.
module bcd_fadd (input [3:0] a,input [3:0] b,input cin,output cout,output [3:0] sum );
Instantiate 4 copies of bcd_fadd to create a 4-digit BCD ripple-carry adder. Your adder should add two 4-digit BCD numbers (packed into 16-bit vectors) and a carry-in to produce a 4-digit sum and carry out.
module top_module ( input [15:0] a, b,input cin,output cout,output [15:0] sum );wire cout1,cout2,cout3;bcd_fadd u1(a[3:0] ,b[3:0] ,cin ,cout1 ,sum[3:0] );bcd_fadd u2(a[7:4] ,b[7:4] ,cout1 ,cout2 ,sum[7:4] );bcd_fadd u3(a[11:8] ,b[11:8] ,cout2 ,cout3 ,sum[11:8] );bcd_fadd u4(a[15:12],b[15:12] ,cout3,cout,sum[15:12] );endmodule
4. Karnaugh map to Circuit
卡诺图的相关知识可以去这里看:https://zhuanlan.zhihu.com/p/158535749
4.1 3-variable
out = a + b + c
module top_module(input a,input b,input c,output out ); assign out = a | b | c ;endmodule
4.2 4-variable
module top_module(input a,input b,input c,input d,output out ); assign out = (~b & ~c) | (~a & ~d) | (b & c & d) | (a & ~b & d) ; endmodule
4.3 4-variable
与上题不同的是,该卡诺图中出现d,其值可以有自己随意设定来方便化简。
module top_module(input a,input b,input c,input d,output out ); assign out = a | (~b & c) ; endmodule
4.4 4-variable
module top_module(input a,input b,input c,input d,output out ); assign out = a ^ b ^ c ^ d;endmodule
4.5 Minimum SOP and POS
A single-output digital system with four inputs (a,b,c,d) generates a logic-1 when 2, 7, or 15 appears on the inputs, and a logic-0 when 0, 1, 4, 5, 6, 9, 10, 13, or 14 appears. The input conditions for the numbers 3, 8, 11, and 12 never occur in this system. For example, 7 corresponds to a,b,c,d being set to 0,1,1,1, respectively.
Determine the output out_sop in minimum SOP form, and the output out_pos in minimum POS form.
module top_module (input a,input b,input c,input d,output out_sop,output out_pos
); assign out_sop = (c & d) | (~a & ~b & c);assign out_pos = c & (~a|d) & (~b|d);endmodule
4.6 Karnaugh map
module top_module (input [4:1] x, output f );assign f = (~x[1] & x[3]) | (x[2] & x[4]);endmodule
4.7 Karnaugh map
module top_module (input [4:1] x,output f
); assign f = (~x[2] & ~x[4]) | (~x[1] & x[3]) | (x[2] & x[3] & x[4]);endmodule
4.8 K-map implemented with a multiplexer
For the following Karnaugh map, give the circuit implementation using one 4-to-1 multiplexer and as many 2-to-1 multiplexers as required, but using as few as possible. You are not allowed to use any other logic gate and you must use a and b as the multiplexer selector inputs, as shown on the 4-to-1 multiplexer below.
You are implementing just the portion labelled top_module, such that the entire circuit (including the 4-to-1 mux) implements the K-map.
(The requirement to use only 2-to-1 multiplexers exists because the original exam question also wanted to test logic function simplification using K-maps and how to synthesize logic functions using only multiplexers. If you wish to treat this as purely a Verilog exercise, you may ignore this constraint and write the module any way you wish.)
module top_module (input c,input d,output [3:0] mux_in
); assign mux_in[0] = c | d;assign mux_in[1] = 0;assign mux_in[2] = ~d;assign mux_in[3] = c & d;endmodule