[하만]세미콘 아카데미/verilog

0509 4bit_Full_Adder & FND 표시

내머리속은이런걸로 2024. 6. 22. 11:24

4bit Full Adder

: 4비트의 두 이진수를 더하는 디지털 회로이다.


아래의 코드를 보다보면 always 문이 나온다.

Always 문

: block 내부에 있는 코드가 계속 실행됨. @ () 내부에 있는 port의 값에 변화가 생길 때마다 코드가 실행 됨.

  • level sensitive : @() port의 값에 따라 코드가 실행됨.
  • edge sensitive : @() port의 edge[rising, falling]에 따라 코드가 실행됨.
    • rising = posedge, falling = negedge
    • ex) always @(posedge a) begin → a가 0에서 1로 변하는 그 순간, edge에서 코드가 실행됨.
    • 보통 edge sensitive가 많이 사용됨.

Adder_Fnd.v

`timescale 1ns / 1ps

module Adder_Fnd (  // top
    input  [7:0] a,
    input  [7:0] b,
    input  [1:0] fndSel,
    output [3:0] fndCom,
    output [7:0] fndFont,
    output       carry
);

    wire [7:0] w_sum;
    wire [3:0] w_digit_1, w_digit_10, w_digit_100, w_digit_1000;
    wire [3:0] w_digit;

    Decoder U_Decoder_2x4 (
        .x(fndSel),
        .y(fndCom)
    );

    Adder U_8bitAdder (
        .a  (a),
        .b  (b),
        .cin(1'b0),
        .sum(w_sum),
        .co (carry)
    );

    digitSplitter U_DigitSplitter(
    .i_digit({5'b00000, carry, w_sum}),
    .o_digit_1(w_digit_1),
    .o_digit_10(w_digit_10),
    .o_digit_100(w_digit_100),
    .o_digit_1000(w_digit_1000)
    );

    Mux U_Mux_4x1(
    .sel(fndSel),
    .x0(w_digit_1),
    .x1(w_digit_10),
    .x2(w_digit_100),
    .x3(w_digit_1000),
    .y(w_digit)
    );

    BCDtoSEG U_BcdToSeg (
        .bcd(w_digit),
        .seg(fndFont)
    );


endmodule

: 8bitAdder에서 나온 sum 값을 DigitSplitter에서 1, 10, 100, 1000의 자리로 나누고, 4x1Mux를 거쳐 차례대로 빠르게 나타낸다.

Adder.v

`timescale 1ns / 1ps

module Adder (
    input [7:0] a,
    input [7:0] b,
    input cin,
    output [7:0] sum,
    output co
);
    wire [6:0] w_carry;

    fullAdder U_FA0 (
        .a  (a[0]),
        .b  (b[0]),
        .cin(cin),
        .sum(sum[0]),
        .co (w_carry[0])
    );

    fullAdder U_FA1 (
        .a  (a[1]),
        .b  (b[1]),
        .cin(w_carry[0]),
        .sum(sum[1]),
        .co (w_carry[1])
    );

    fullAdder U_FA2 (
        .a  (a[2]),
        .b  (b[2]),
        .cin(w_carry[1]),
        .sum(sum[2]),
        .co (w_carry[2])
    );

    fullAdder U_FA3 (
        .a  (a[3]),
        .b  (b[3]),
        .cin(w_carry[2]),
        .sum(sum[3]),
        .co (w_carry[3])
    );

    fullAdder U_FA4 (
        .a  (a[4]),
        .b  (b[4]),
        .cin(w_carry[3]),
        .sum(sum[4]),
        .co (w_carry[4])
    );

    fullAdder U_FA5 (
        .a  (a[5]),
        .b  (b[5]),
        .cin(w_carry[4]),
        .sum(sum[5]),
        .co (w_carry[5])
    );

    fullAdder U_FA6 (
        .a  (a[6]),
        .b  (b[6]),
        .cin(w_carry[5]),
        .sum(sum[6]),
        .co (w_carry[6])
    );

    fullAdder U_FA7 (
        .a  (a[7]),
        .b  (b[7]),
        .cin(w_carry[6]),
        .sum(sum[7]),
        .co (co)
    );



endmodule

module halfAdder (
    input  a,
    input  b,
    output sum,
    output carry
);
    assign sum   = a ^ b;
    assign carry = a & b;

endmodule

module fullAdder (
    input  a,
    input  b,
    input  cin,
    output sum,
    output co
);
    wire w_sum1, w_carry1, w_carry2;

    halfAdder U_HA1 (
        .a(a),
        .b(b),
        .sum(w_sum1),
        .carry(w_carry1)
    );

    halfAdder U_HA2 (
        .a(w_sum1),
        .b(cin),
        .sum(sum),
        .carry(w_carry2)
    );

    assign co = w_carry1 | w_carry2;

endmodule

Mux.v

`timescale 1ns / 1ps

module Mux (
    input      [1:0] sel,
    input      [3:0] x0,
    input      [3:0] x1,
    input      [3:0] x2,
    input      [3:0] x3,
    output reg [3:0] y
);

    always @(sel, x0, x1, x2, x3) begin
        case (sel)
            2'b00:   y = x0;
            2'b01:   y = x1;
            2'b10:   y = x2;
            2'b11:   y = x3;
            default: y = x0;
        endcase
    end
endmodule

※ output reg를 쓰는 이유 : assign 문에서 변경된 값을 저장해야하기 때문.

output reg를 안쓸 경우:

  1. 밑에 reg를 선언해줘야 함.
  2. assign(연속할당문) 사용하기. output은 기본적인 wire 타입이기 대문에 별도의 wire를 선언하지 않아도 가능.

digitSplitter.v

`timescale 1ns / 1ps

module digitSplitter (
    input  [13:0] i_digit,
    output [ 3:0] o_digit_1,
    output [ 3:0] o_digit_10,
    output [ 3:0] o_digit_100,
    output [ 3:0] o_digit_1000
);

    assign o_digit_1 = i_digit % 10;
    assign o_digit_10 = i_digit / 10 % 10;
    assign o_digit_100 = i_digit / 100 % 10;
    assign o_digit_1000 = i_digit / 1000 % 10;

endmodule

Decoder.v

`timescale 1ns / 1ps

module Decoder (
    input      [1:0] x,
    output reg [3:0] y
);

    always @(x) begin
        case (x)
            2'h0: y = 4'b1110;
            2'h1: y = 4'b1101;
            2'h2: y = 4'b1011;
            2'h3: y = 4'b0111;
            default: y = 4'b1110;
        endcase
    end

endmodule

BCDtoSEG.v

`timescale 1ns / 1ps

module BCDtoSEG (
    input      [3:0] bcd,
    output reg [7:0] seg
);

    always @(bcd) begin// bcd 변화가 감지되면 실행
        case (bcd)
            4'h0: seg = 8'hc0;
            4'h1: seg = 8'hf9;
            4'h2: seg = 8'ha4;
            4'h3: seg = 8'hb0;
            4'h4: seg = 8'h99;
            4'h5: seg = 8'h92;
            4'h6: seg = 8'h82;
            4'h7: seg = 8'hf8;
            4'h8: seg = 8'h80;
            4'h9: seg = 8'h90;
            4'ha: seg = 8'h88;
            4'hb: seg = 8'h83;
            4'hc: seg = 8'hc6;
            4'hd: seg = 8'ha1;
            4'he: seg = 8'h86;
            4'hf: seg = 8'h8e;
            default: seg = 8'hff;
        endcase
    end

endmodule

schemaitc

schemaitc

tb_Adder._sv

`timescale 1ns / 1ps

class transaction;
    rand bit [3:0] a;
    rand bit [3:0] b;
endclass

module tb_Adder_sv ();

    reg         [3:0] a;
    reg         [3:0] b;
    wire        [3:0] sum;
    wire              co;

    transaction       trans;

    Adder dut (  // dut (design under test)
        .a  (a),
        .b  (b),
        .cin(1'b0),
        .sum(sum),
        .co (co)
    );

    initial begin
        trans = new();

        for (int i = 0; i < 100; i++) begin
            trans.randomize();
            a = trans.a;
            b = trans.b;
            #10 $display("a:%d + b:%d = %d", trans.a, trans.b, sum);

            if ((a+b) == sum) begin
                $display("passed!");
            end
            else begin
                $display("failed!");
            end
        end
        #10 $finish;
    end

endmodule

Tol Console

Tol Console

constraint

video

'[하만]세미콘 아카데미 > verilog' 카테고리의 다른 글

0510 clockCounter, upCounter  (0) 2024.06.22
0510_8bitAdder_display  (0) 2024.06.22
0508 4bit_Full_Adder  (0) 2024.06.22
0508 half_Adder, full_Adder  (0) 2024.06.22
0508 gate  (0) 2024.06.22