DEV Community

Cover image for Building Adders and Multipliers in Logic Circuits and Verilog HDL
Lena
Lena

Posted on • Updated on

Building Adders and Multipliers in Logic Circuits and Verilog HDL

Back when I was learning Verilog HDL in 2019, I started by designing Logic Circuits on interactive circuit simulators like CircuitVerse, wrote them in Verilog HDL, and tested them out on the DE10-Nano. The Verilog HDL codes available here are not the best and most efficient way to write Verilog HDL (since this was what I wrote back when I started Verilog HDL, so I manually assigned each wire and signals).

Table of contents

  1. Building a 4-bit adder
  2. Building a 4-bit multiplier

Building a 4-bit adder

The 4-bit adder design:
Image description

I made the interactive circuit on CiruitVerse, which can be found here.

Image description

I labeled the wires to keep track of the signals. However, it's not necessary to do this (When I made this, I was still learning Verilog HDL). There are better and more efficient ways to write a 4-bit adder in Verilog HDL.

https://github.com/LambdaMamba/FPGAprojects/blob/main/ARITHMETIC_EXAMPLES/CalcFourBitAdder.v

`timescale 1ns/1ns

    module CalcFourBitAdder
        (
        input [1:0] KEY,
        input [3:0] SW,
        output [3:0] LED,
        output cout
        );


        reg ax;
        reg bx;
        reg ay;
        reg by;
        reg az;
        reg bz;
        reg aw;
        reg bw;
        wire cin;

        wire xwire1;
        wire xwire2;
        wire xwire3;
        wire outwirex;

        wire ywire1;
        wire ywire2;
        wire ywire3;
        wire outwirey;

        wire zwire1;
        wire zwire2;
        wire zwire3;
        wire outwirez; 

        wire wwire1;
        wire wwire2;
        wire wwire3; 

        assign cin = 0;

        //First set of 4 D flip flops
        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            ax <= 1'b0;
            else
            ax <= SW[0];
        end

        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            ay <= 1'b0;
            else
            ay <= SW[1];
        end

        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            az <= 1'b0;
            else
            az <= SW[2];
        end

        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            aw <= 1'b0;
            else
            aw <= SW[3];
        end

        //Second set of 4 D flip flops
        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            bx <= 1'b0;
            else
            bx <= ax;
        end

        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            by <= 1'b0;
            else
            by <= ay;
        end

        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            bz <= 1'b0;
            else
            bz <= az;
        end

        always @(posedge !KEY[0] or posedge !KEY[1])
        begin
            if(!KEY[1]==1'b1)
            bw <= 1'b0;
            else
            bw <= aw;
        end
        //4 bit adder made previously
        assign xwire1 = ax^bx;
        assign xwire2 = xwire1&cin;
        assign xwire3 = ax&bx;
        assign LED[0] = xwire1^cin;
        assign outwirex = xwire2|xwire3;

        assign ywire1 = ay^by;
        assign ywire2 = ywire1&outwirex;
        assign ywire3 = ay&by;
        assign LED[1] = ywire1^outwirex;
        assign outwirey = ywire2|ywire3;

        assign zwire1 = az^bz;
        assign zwire2 = zwire1&outwirey;
        assign zwire3 = az&bz;
        assign LED[2] = zwire1^outwirey;
        assign outwirez = zwire2|zwire3;

        assign wwire1 = aw^bw;
        assign wwire2 = wwire1&outwirez;
        assign wwire3 = aw&bw;
        assign LED[3] = wwire1^outwirez;
        assign cout = wwire2|wwire3;

    endmodule

Enter fullscreen mode Exit fullscreen mode

ModelSim Output:
Image description

Trying this out in the DE10 Nano FPGA:

Here I'm doing 0001 + 0101, reset, then 1101 + 1100. LED[5] lights up when there's an overflow.

Image description

Building a 4-bit multiplier

The 4-bit multiplier design:
Image description

I made the interactive circuit on CiruitVerse, which can be found here.
Image description

Again, I labeled the wires to keep track of signals, and there are better and more efficient ways to write a 4-bit Multiplier in Verilog HDL.

https://github.com/LambdaMamba/FPGAprojects/blob/main/ARITHMETIC_EXAMPLES/FourBitMultiplier.v

    `timescale 1ns/1ns

            module FourBitMultiplier 
                (
                input [1:0] KEY,
                input [3:0] SW,
                output [7:0] LED
                );


                reg ax;
                reg bx;
                reg ay;
                reg by;
                reg az;
                reg bz;
                reg aw;
                reg bw;
                wire cin;

                wire bxax, bxay, bxaz, bxaw;
                wire byax, byay, byaz, byaw;
                wire bzax, bzay, bzaz, bzaw;
                wire bwax, bway, bwaz, bwaw;

                wire si1, si2, si3, si4;
                wire ci1, ci2, ci3, ci4;

                wire sj1, sj2, sj3, sj4;
                wire cj1, cj2, cj3, cj4;

                wire sk1, sk2, sk3, sk4;
                wire ck1, ck2, ck3, ck4;

                assign cin = 0;

                //First set of 4 D flip flops
                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    ax <= 1'b0;
                    else
                    ax <= SW[0];
                end

                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    ay <= 1'b0;
                    else
                    ay <= SW[1];
                end

                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    az <= 1'b0;
                    else
                    az <= SW[2];
                end

                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    aw <= 1'b0;
                    else
                    aw <= SW[3];
                end

                //Second set of 4 D flip flops
                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    bx <= 1'b0;
                    else
                    bx <= ax;
                end

                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    by <= 1'b0;
                    else
                    by <= ay;
                end

                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    bz <= 1'b0;
                    else
                    bz <= az;
                end

                always @(posedge !KEY[0] or posedge !KEY[1])
                begin
                    if(!KEY[1]==1'b1)
                    bw <= 1'b0;
                    else
                    bw <= aw;
                end

                assign bxax = bx&ax;
                assign bxay = bx&ay;
                assign bxaz = bx&az;
                assign bxaw = bx&aw;

                assign byax = by&ax;
                assign byay = by&ay;
                assign byaz = by&az;
                assign byaw = by&aw;

                //first row of 4 bit adders

                assign si1 = (bxay^byax)^cin;
                assign ci1 = ((bxay^byax)&cin)|(bxay&byax);

                assign si2 = (bxaz^byay)^ci1;
                assign ci2 = ((bxaz^byay)&ci1)|(bxaz&byay);

                assign si3 = (bxaw^byaz)^ci2;
                assign ci3 = ((bxaw^byaz)&ci2)|(bxaw&byaz);

                assign si4 = (0^byaw)^ci3;
                assign ci4 = ((0^byaw)&ci3)|(0&byaw);

                assign bzax = bz&ax;
                assign bzay = bz&ay;
                assign bzaz = bz&az;
                assign bzaw = bz&aw;

                //second row of 4 bit adders
                assign sj1 = (bzax^si2)^cin;
                assign cj1 = ((bzax^si2)&cin)|(bzax&si2);

                assign sj2 = (bzay^si3)^cj1;
                assign cj2 = ((bzay^si3)&cj1)|(bzay&si3);

                assign sj3 = (bzaz^si4)^cj2;
                assign cj3 = ((bzaz^si4)&cj2)|(bzaz&si4);

                assign sj4 = (bzaw^ci4)^cj3;
                assign cj4 = ((bzaw^ci4)&cj3)|(bzaw&ci4);

                assign bwax = bw&ax;
                assign bway = bw&ay;
                assign bwaz = bw&az;
                assign bwaw = bw&aw;

                //third row of 4 bit adders
                assign sk1 = (bwax^sj2)^cin;
                assign ck1 = ((bwax^sj2)&cin)|(bwax&sj2);

                assign sk2 = (bway^sj3)^ck1;
                assign ck2 = ((bway^sj3)&ck1)|(bway&sj3);

                assign sk3 = (bwaz^sj4)^ck2;
                assign ck3 = ((bwaz^sj4)&ck2)|(bwaz&sj4);

                assign sk4 = (bwaw^cj4)^ck3;
                assign ck4 = ((bwaw^cj4)&ck3)|(bwaw&cj4);


                assign LED[0] = bxax;
                assign LED[1] = si1;
                assign LED[2] = sj1;
                assign LED[3] = sk1;
                assign LED[4] = sk2;
                assign LED[5] = sk3;
                assign LED[6] = sk4;
                assign LED[7] = ck4;
    endmodule

Enter fullscreen mode Exit fullscreen mode

Trying this out on the DE10 Nano FPGA:

Here I'm doing 0010*0011, reset, then 0100*0101.

Image description

Oldest comments (0)