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

0510_8bitAdder_display

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

8bitAdder_display

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Full Schematic

 

adder.v

`timescale 1ns / 1ps

    module Adder_8bit (
    input [7:0] a,
    input [7:0] b,
    input cin,
    output [7:0] sum,
    output co
    );

    wire w_carry0;

    Adder_4bit U_4bit_Adder0(
    .a(a[3:0]),
    .b(b[3:0]),
    .cin(cin),
    .sum(sum[3:0]),
    .co(w_carry0)
    );

    Adder_4bit U_4bit_Adder1(
    .a(a[7:4]),
    .b(b[7:4]),
    .cin(w_carry0),
    .sum(sum[7:4]),
    .co(co)
    );

    endmodule

    module Adder_4bit(
    input [3:0] a,
    input [3:0] b,
    input cin,
    output [3:0] sum,
    output co
    );

    wire [2: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 (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

 

adder_fnd.v

`timescale 1ns / 1ps

module adder_fnd (
    input        clk,
    input  [7:0] a,
    input  [7:0] b,
    output [3:0] fndCom,
    output [7:0] fndFont
);

    wire [7:0] w_sum;
    wire w_carry;

    Adder_8bit U_Adder (
        .a  (a),
        .b  (b),
        .cin(1'b0),
        .sum(w_sum),
        .co (w_carry)
    );

    fndController U_fndController (
        .clk(clk),
        .digit({5'b0, w_carry, w_sum}),
        .fndFont(fndFont),
        .fndCom(fndCom)
    );


endmodule

 

fndController

`timescale 1ns / 1ps

module fndController (
    input         clk,
    input  [13:0] digit,
    output [ 7:0] fndFont,
    output [ 3:0] fndCom
    );

    wire [3:0] w_digit_1, w_digit_10, w_digit_100, w_digit_1000;
    wire [3:0] w_digit;
    wire [1:0] w_count;
    wire w_clk_1khz;

    clkDiv #(.MAX_COUNT(100_000)) U_ClkDiv( // (100_000)이 없으면 default
        .clk(clk),
        .o_clk(w_clk_1khz)
    );

    counter #(.MAX_COUNT(4)) U_Counter_2bit(
        .clk(w_clk_1khz),
        .count(w_count)
    );

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

    digitSplitter U_DigitSplitter (
        .i_digit(digit),
        .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 (
        .sel(w_count),
        .x0 (w_digit_1),
        .x1 (w_digit_10),
        .x2 (w_digit_100),
        .x3 (w_digit_1000),
        .y  (w_digit)
    );

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

endmodule


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

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

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

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

module counter #(parameter MAX_COUNT = 4)(
    input  clk,
    output [1:0]  count
);

    reg [1:0] counter = 0;
    assign count = counter; // wire은 assign으로 연결해야함.

    always @(posedge clk) begin
        if (counter == MAX_COUNT - 1) begin
            counter <= 0;
        end
        else begin
            counter <= counter + 1;
        end
    end

endmodule

module clkDiv #(parameter MAX_COUNT = 100)(
    input clk,
    output o_clk
);
    reg [$clog2(MAX_COUNT)-1:0] counter = 0;  // [16:0]으로 만들어줌. $clog2 : log2()
    reg r_tick = 0 ;

    assign o_clk = r_tick;

    always @(posedge clk) begin
        if (counter == (MAX_COUNT - 1)) begin // 100M -> 100k
            counter <= 0;
            r_tick <= 1'b1;
        end
        else begin
            counter <= counter + 1;
            r_tick <= 1'b0;
        end
    end
    
endmodule

 

schematic

schematic

 

fndController of 8bitAdder

 


tb_adder

`timescale 1ns / 1ps

class transaction;
    rand logic [7:0] a;
    rand logic [7:0] b; // logic = reg
endclass // transaction

module tb_adder();
    transaction trans;

    logic [7:0] a, b, sum;
    logic co;

    Adder_8bit  dut(
        .a(a),
        .b(b),
        .cin(1'b0),
        .sum(sum),
        .co(co)
    );

    initial begin
        trans = new();
        repeat(10000) begin
            trans.randomize();
            a = trans.a;
            b = trans.b;
            #10;
            $display("%t : a(%d) + b(%d) = sum(%d)", $time, trans.a, trans.b, {co,sum});
            if ((trans.a +  trans.b) == {co, sum}) $display("passed!");
            else $display("failed!");
        end
    end

endmodule

 

simulation

simulation

- co : 256

 

constraint

 

video

 

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

0513 clock_upCounter  0 2024.06.22
0510 clockCounter, upCounter  0 2024.06.22
0509 4bit_Full_Adder & FND 표시  0 2024.06.22
0508 4bit_Full_Adder  0 2024.06.22
0508 half_Adder, full_Adder  0 2024.06.22