跳转至

Multiplexers

Popcount3

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.

Verilog
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
module top_module (
    input [2:0] in,
    output [1:0] out
);

    // This is a function of 3 inputs. One method is to use a 8-entry truth table:
    // in[2:0] out[1:0]
    // 000      00
    // 001      01
    // 010      01
    // 011      10
    // 100      01
    // 101      10
    // 110      10
    // 111      11
    assign out[0] = (~in[2] & ~in[1] & in[0]) | (~in[2] & in[1] & ~in[0]) | (in[2] & ~in[1] & ~in[0]) | (in[2] & in[1] & in[0]);
    assign out[1] = (in[1] & in[0]) | (in[2] & in[0]) | (in[2] & in[1]);

    // Using the addition operator works too:
    assign out = in[0]+in[1]+in[2];

    // Yet another method uses behavioural code inside a procedure (combinational always block)
    // to directly implement the truth table:

    always @(*) begin
        case (in)
            3'd0: out = 2'd0;
            3'd1: out = 2'd1;
            3'd2: out = 2'd1;
            3'd3: out = 2'd2;
            3'd4: out = 2'd1;
            3'd5: out = 2'd2;
            3'd6: out = 2'd2;
            3'd7: out = 2'd3;
        endcase
    end

endmodule

Gatesv

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].
Verilog
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

Mux256to1v

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.

Hints: - With this many options, a case statement isn't so useful. - Vector indices can be variable, as long as the synthesizer can figure out that the width of the bits being selected is constant. It's not always good at this. An error saying "... is not a constant" means it couldn't prove that the select width is constant. In particular, in[ sel4+3 : sel4 ] does not work. - Bit slicing ("Indexed vector part select", since Verilog-2001) has an even more compact syntax.

Verilog
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
module top_module (
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out
);

    // We can't part-select multiple bits without an error, but we can select one bit at a time,
    // four times, then concatenate them together.
    assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};

    // Alternatively, "indexed vector part select" works better, but has an unfamiliar syntax:
    assign out = in[sel*4 +: 4];        // Select starting at index "sel*4", then select a total width of 4 bits with increasing (+:) index number.
    assign out = in[sel*4+3 -: 4];  // Select starting at index "sel*4+3", then select a total width of 4 bits with decreasing (-:) index number.
    // Note: The width (4 in this case) must be constant.

endmodule