本节是一些练习巩固的习题。

Wire

Solution

module top_module (
    input in,
    output out);

    assign out = in;
endmodule

GND

GND(Ground): “地线” 或 “接地”。
Solution

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

NOR

Solution

module top_module (
    input in1,
    input in2,
    output out);
    assign out = ~(in1 | in2);  //注意别忘了“非”
endmodule

Another gate

Solution

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

Two gates

Solution

module top_module (
    input in1,
    input in2,
    input in3,
    output out);

    wire m1;
    assign m1 = ~(in1 ^ in2);
    assign out = m1 ^ in3;
endmodule

More logic gates

Solution

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;   //a 和 非b
endmodule

7420 chip

Solution

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 tables

One simple method to create a circuit that implements the truth table's function is to express the function in sum-of-products form. Sum (meaning OR) of products (meaning AND) means using one N-input AND gate per row of the truth table (to detect when the input matches each row), followed by an OR gate that chooses only those rows that result in a '1' output.

总结:推导 sum-of-products (SOP,积之和)的核心逻辑:
用最小项 “标记” 所有输出为 1 的输入组合,再用 OR 运算 “汇总” 这些有效组合。由于最小项仅在唯一输入组合下为 1,OR 之后的表达式能精准复现真值表的输出逻辑。
“找 1 行,写反 / 原变量乘积,再 OR”

Solution

module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output f   // one output
);

    assign f = (~x3 & x2 & ~x1) | (~x3 & x2 & x1) | (x3 & ~x2 & x1) | (x3 & x2 & x1);
endmodule

Two-bit equality

通过直接比较两个 2 位输入 A 和 B 来判断它们是否相等,采用了 Verilog 的条件赋值语句即可。

Solution

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

Simple circuit A

Solution

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

Simple circuit B

先列出真值表:

input: xinput: youtput: z
001
100
010
111

Solution

module top_module ( input x, input y, output z );
    assign z = (~x & ~y) | (x & y);
endmodule

Combine circuits A and B

Solution

module top_module (input x, input y, output z);

    wire z1,z2,z3,z4;
    moduleA u1 (.x(x), .y(y), .z(z1));  //通过实例化可以用A模块获得 z1
    moduleB u2 (.x(x), .y(y), .z(z2));
    moduleA u3 (.x(x), .y(y), .z(z3));
    moduleB u4 (.x(x), .y(y), .z(z4));  
    
    wire m1,m2;
    assign m1 = z1 | z2;
    assign m2 = z3 & z4;  
    
    assign z = m1 ^ m2;
endmodule

//module之间是并行的,所以不需要提前声明。  
module moduleA (input x, input y, output z);
    assign z = (x ^ y) & x;
endmodule

module moduleB ( input x, input y, output z );
    assign z = (~x & ~y) | (x & y);
endmodule

Ring or vibrate?

响铃还是震动?

When designing circuits, one often has to think of the problem "backwards", starting from the outputs then working backwards towards the inputs. This is often the opposite of how one would think about a (sequential, imperative) programming problem, where one would look at the inputs first then decide on an action (or output). For sequential programs, one would often think "If (inputs are --- ) then (output should be --- )". On the other hand, hardware designers often think "The (output should be ---) when (inputs are ---)".

Solution

module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);
    //assign ringer = (ring ? 1'b1 : 1'b0);         //Error
    //assign motor = (vibrate_mode ?  1'b1 : 1'b0); //Error

    assign ringer = ring & ~vibrate_mode;  //有来电,且没有设置为震动模式时响铃
    assign motor = ring & vibrate_mode;    //有来电,且有设置为震动模式时震动
endmodule

Thermostat

Solution

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 = too_cold | too_hot | fan_on; //Logic Error 
    assign fan = heater | aircon | fan_on;
endmodule

3-bit population count

Solution

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

    integer i;  
    always @(*) begin 
        out = 2'b00;
        for (i = 0; i < 3; i++) begin 
            if(in[i] == 1'b1)
                out = out + 1;
        end
    end
    
endmodule

Gates and vectors

Solution

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

    integer i;
    always @(*) begin 
        for(i = 0; i < 3; i++) begin 
            out_both[i] = in[i] & in[i + 1];
        end
        for(i = 1; i < 4; i++) begin 
            out_any[i] = in[i] | in[i - 1];
        end
        for(i = 0; i < 4; i++) begin 
            if(i == 3)
                out_different[3] = in[3] ^ in[0];
            else
            out_different[i] = in[i] ^ in[i + 1];
        end
    end
endmodule

Even longer vectors

module top_module( 
    input [99:0] in,
    output [98:0] out_both,
    output [99:1] out_any,
    output [99:0] out_different );
    
    integer i;
    always @(*) begin 
        for(i = 0; i < 99; i++) begin 
            out_both[i] = in[i] & in[i + 1];
        end
        for(i = 1; i < 100; i++) begin 
            out_any[i] = in[i] | in[i - 1];
        end
        for(i = 0; i < 100; i++) begin 
            if(i == 99)
                out_different[99] = in[99] ^ in[0];
            else
            out_different[i] = in[i] ^ in[i + 1];
        end
    end
endmodule