Skip to content
Rain Hu's Workspace
Go back

[VHDL] HDLbits 3 - Circuits

Rain Hu

1. Getting Started
2. Verilog Language
3. Circuits
4. Verification: Reading Simulations
5. Verification: Writing Testbenches
6. CS450

3 Circuits

3.1 Combinational Logic

3.1.1 Basic Gates

Wire

q4h

module top_module (
    input in,
    output out);

    assign out = in;
    
endmodule

GND

GND

module top_module (
    output out);

    assign out = 1'b0;
    
endmodule

NOR

NOR

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

    assign out = ~(in1|in2);
    
endmodule

Another Gate

AnotherGate

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

    assign out = in1 & (~in2);
    
endmodule

Two gates

TwoGates

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

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

More 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);
    
//    and(out_and, a, b);
//    or(out_or, a, b);
//    xor(out_xor, a, b);
//    nand(out_nand, a, b);
//    nor(out_nor, a, b);
//    xnor(out_xnor, a, b);
//    and(out_anotb, a , ~b);
    
endmodule

7420 chip

7420

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

\(\begin{array}{|c|ccc|c|}\hline \text{Row}&&\text{Inputs}&&\text{Outputs}\\\hline \text{number}&\text{x3}&\text{x2}&\text{x1}&\text{f}\\\hline 0&0&0&0&0\\\hline 1&0&0&1&0\\\hline 2&0&1&0&1\\\hline 3&0&1&1&1\\\hline 4&1&0&0&0\\\hline 5&1&0&1&1\\\hline 6&1&1&0&0\\\hline 7&1&1&1&1\\\hline \end{array truthtable1

module top_module( 
    input x3,
    input x2,
    input x1,
    output f );

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

endmodule

Two-bit equality

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

    assign z = (A == B);
    
endmodule

Simple circuit A

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

    assign z = (x^y) &x;
    
endmodule

Simple circuit B

q4b

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

    assign z = (x==y);
    // assign z = ~(x ^ y);
    
endmodule

Combine circuits A and B

q4

module top_module (input x, input y, output z);
    
    wire o1, o2, o3, o4;
    
    A ia1(x,y,o1);
    B ib1(x,y,o2);
    A ia2(x,y,o3);
    B ib2(x,y,o4);
    
    assign z = (o1|o2)^(o3&o4);

endmodule

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

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

Ringer

module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);

    assign ringer = ring & (~vibrate_mode);
    assign motor = ring & (vibrate_mode);
    
endmodule

Thermostat

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

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

endmodule

3-bit population count

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

    always @(*) begin
        out = 0;
        for (int i = 0; i <= 2; i++) begin
            out += in[i];
        end
    end
    
endmodule

Gates and vectors

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[2:0] = in[2:0] & in[3:1];
    assign out_any[3:1] = in[3:1] | in[2:0];
    assign out_different[3:0] = in[3:0] ^ {in[0], in[3:1]};

    // always @(*) begin
    //    out_different[3] = (in[3] != in[0]);
    //    for (int i = 0; i <= 2; i++) begin
    //        out_both[i] = in[i] & in[i+1];
    //        out_any[i+1] = in[i+1] | in[i];
    //        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 );

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

3.1.2 Multiplexers

2-to-1 multiplexer

module top_module( 
    input a, b, sel,
    output out ); 

    assign out = sel ? b : a;
    
endmodule

2-to-1 bus multiplexer

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

    assign out = sel ? b : a;
    
endmodule

9-to-1 multiplexer

module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output [15:0] out );

    always @(*) begin
        case(sel)
            4'd0: out = a;
            4'd1: out = b;
            4'd2: out = c;
            4'd3: out = d;
            4'd4: out = e;
            4'd5: out = f;
            4'd6: out = g;
            4'd7: out = h;
            4'd8: out = i;
            default: out = '1;  // special literal syntax with all bits set to 1
        endcase
    end
    
endmodule

256-to-1 multiplexer

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

    assign out = in[sel];
    
endmodule

256-to-1 4-bit multiplexer

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    
    assign out = in[sel*4+:4];  // special syntax
    // assign out = in[sel*4+3-:4];
    // assign out = {in[sel*4+3],in[sel*4+2],in[sel*4+1],in[sel*4+0]};

endmodule

3.1.3 Arithmetic Circuits

Half adder

module top_module( 
    input a, b,
    output cout, sum );

    assign {cout, sum} = a + b;
    
endmodule

Full adder

module top_module( 
    input a, b, cin,
    output cout, sum );

    assign {cout, sum} = a + b + cin;
    
endmodule

3-bit binary adder

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

    fulladder f1(a[0], b[0], cin,     cout[0], sum[0]);
    fulladder f2(a[1], b[1], cout[0], cout[1], sum[1]);
    fulladder f3(a[2], b[2], cout[1], cout[2], sum[2]);
    
endmodule

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

Adder

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

    wire [2:0] cout;

    FA f1(x[0], y[0], 0,       cout[0], sum[0]);
    FA f2(x[1], y[1], cout[0], cout[1], sum[1]);
    FA f3(x[2], y[2], cout[1], cout[2], sum[2]);
    FA f4(x[3], y[3], cout[2], sum[4],  sum[3]);
    
endmodule

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

Signed addition 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] && a[7] != s[7]) ? 1 : 0; 

endmodule

100-bit binary adder

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

    assign {cout, sum} = cin + a + b;

endmodule

4-digit BCD adder

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 [2:0] wl;

    bcd_fadd u0 (a[ 3: 0], b[ 3: 0],   cin, wl[0], sum[ 3: 0]);
    bcd_fadd u1 (a[ 7: 4], b[ 7: 4], wl[0], wl[1], sum[ 7: 4]);
    bcd_fadd u2 (a[11: 8], b[11: 8], wl[1], wl[2], sum[11: 8]);
    bcd_fadd u3 (a[15:12], b[15:12], wl[2],  cout, sum[15:12]);

endmodule

3.1.4 Karnaugh Map to Circuit

Kmap1

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

    assign out = a | b | c;

endmodule

Kmap2

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

    // a'd' + b'c' + acd + a'bc
    wire w1, w2, w3, w4;

    assign w1 = (~a)&(~d);
    assign w2 = (~b)&(~c);
    assign w3 = a&c&d;
    assign w4 = (~a)&b&c;

    assign out = w1|w2|w3|w4;
endmodule

Kmap3

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

    // a + b'c
    assign out = a | (~b&c);

endmodule

Kmap4

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

    always @(*) begin
        if (a == b && c != d)
            out = 1;
        else if (a != b && c == d)
            out = 1;
        else
            out = 0;
    end

endmodule

Minimum SOP and POS

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

    // f = d3 + m7 + d11 + m15 + m2
    // f = cd + a'b'c
    assign out_sop = (c & d) | (~a & ~b & c);
    // f' = m0 + m1 + m4 + m5 + m6 + d8 + m9 + m10 + d11 + d12 + m13 + m14
    // f' = c' + ab' + bd'
    // f = (c)(a'+b)(b'+d)
    assign out_pos = c & (~a | b) & (~b | d);

endmodule

Karnaugh map

module top_module (
    input [4:1] x,
    output f );

    // x[2]x[4] + x[1]'x[3]
    assign f = (x[2] & x[4]) | (~x[1] & x[3]);

endmodule

Karnaugh map

module top_module (
    input [4:1] x,
    output f
);

    // x[2]'x[4]' + x[1]'x[3] + x[2]x[3]x[4]
    assign f = (~x[2] & ~x[4]) | (~x[1] & x[3]) | (x[2] & x[3] & x[4]);

endmodule

K-map implemented with a multiplexer

module top_module (
    input c,
    input d,
    output [3:0] mux_in
);
    assign mux_in[0] = c|d;  // 0111
    assign mux_in[1] = 1'b0; // 0000
    assign mux_in[2] = ~d;   // 1001
    assign mux_in[3] = c&d;  // 0010

endmodule

3.2 Sequential Logic

3.2.1 Latches and Flip-Flops

D flip-flop

module top_module (
    input clk,    // Clocks are used in sequential circuits
    input d,
    output reg q );

    always @(posedge clk) begin
        q <= d;
    end

endmodule

D flip-flops

module top_module (
    input clk,
    input [7:0] d,
    output [7:0] q
);

    always @(posedge clk) begin
        q <= d;
    end

endmodule

DFF with reset

module top_module (
    input clk,
    input reset,            // Synchronous reset
    input [7:0] d,
    output [7:0] q
);

    always @(posedge clk) begin
        if (reset) begin
            q <= 8'b0;
        end
        else begin
            q <= d;
        end
    end

endmodule

DFF with reset value

module top_module (
    input clk,
    input reset,
    input [7:0] d,
    output [7:0] q
);

    always @(negedge clk) begin
        if (reset) begin
            q <= 8'h34;
        end
        else begin
            q <= d;
        end
    end

endmodule

DFF with asynchronous reset

module top_module (
    input clk,
    input areset,   // active high asynchronous reset
    input [7:0] d,
    output [7:0] q
);

    always @(posedge clk or posedge areset)
        if (areset) 
            q <= 0;
        else 
            q <= d;

endmodule

DFF with byte enable

module top_module (
    input clk,
    input resetn,
    input [1:0] byteena,
    input [15:0] d,
    output [15:0] q
);

    always @(posedge clk) begin
        if (resetn == 1'b0) begin
            q <= 16'd0;
        end
        else begin
            case(byteena)
                0: q <= q;
                1: q <= {q[15:8], d[7:0]};
                2: q <= {d[15:8], q[7:0]};
                3: q <= d;
            endcase
        end
    end

endmodule

D Latch

module top_module (
    input d,
    input ena,
    output q);

    always @(*) begin
        if (ena == 1'b1)
            q = d;
    end

endmodule

DFFAR

module top_module (
    input clk,
    input d, 
    input ar,   // asynchronous reset
    output q);

    always@(posedge clk or posedge ar) begin
        if (ar == 1)
            q <= 0;
        else
            q <= d;
    end
    
endmodule

DFFR

module top_module (
    input clk,
    input d,
    input r,   // synchronous reset
    output q);

    always@(posedge clk) begin
        if (r == 1) begin
            q <= 0;
        end
        else begin
            q <= d;
        end
    end

endmodule

DFF+gate

module top_module (
    input clk,
    input in,
    output reg out);

    always@(posedge clk) begin
        out <= out ^ in;
    end

endmodule

Mux and DFF

module top_module (
	  input clk,
	  input L,
    input r_in,
	  input q_in,
	  output reg Q);

    always@(posedge clk) begin
        if (L)
            Q <= r_in;
        else
            Q <= q_in;
    end

endmodule

Mux and DFF

DFF+gate

Mux and DFF

Mux and DFF

DFFs and gates

Create circuit from truth table

Detect an edge

Detect both edges

Edge capture register

Dual-edge triggered flip-flop

3.2.2 Counters

3.2.3 Shift Registers

3.2.4 More Circuits

3.2.5 Finite State Machines

3.3 Building Larger Circuits


Share this post on:

Previous
[VHDL] HDLbits 2 - Verilog Language
Next
[VHDL] HDLbits 4 - Verification: Reading Simulations