BX 4bit adder with register


#1

Hello, I’m new here. So I’m just getting started trying to rap my head around verilog after doing a vhdl module in university.

Here is what I’ve made so far:

  • user puts value into the switches
  • press the ‘+’ button to put that value into a register (the 4 blue LED’s show whats in the register)
  • user puts new value into the switches
  • a ripple carry adder adds the 2 and displays the sum in the 5 green LED’s

Notes;

  • The switches are high when down so in the picture they represent 4’b1110 or 14 in decimal.
  • The ‘=’ button is not doing anything yet

Here’s the code:

module top(input CLK,
            input PIN_19, // Button CLk
            input PIN_24, // Switch MSB
            input PIN_23,
            input PIN_22,
            input PIN_21,
            output reg PIN_18, // Add LEDs MSB
            output reg PIN_17,
            output reg PIN_16,
            output reg PIN_15,
            output reg PIN_5, // Sum LEDs MSB
            output reg PIN_4,
            output reg PIN_3,
            output reg PIN_2,
            output reg PIN_1,);
            reg [3:0] a;
            reg [3:0] b;
            reg [4:0] sum;

  Reg4 Reg4_1(CLK, PIN_24, PIN_23, PIN_22, PIN_21, PIN_18, PIN_17, PIN_16, PIN_15, PIN_19);
  ripple_carry_adder_2_FA ripple_carry_adder_2_FA_1(a, b, sum);
  
  assign PIN_24 = a[3];
  assign PIN_23 = a[2];
  assign PIN_22 = a[1];
  assign PIN_21 = a[0];
  assign PIN_18 = b[3];
  assign PIN_17 = b[2];
  assign PIN_16 = b[1];
  assign PIN_15 = b[0];
  assign PIN_5 = sum[4];
  assign PIN_4 = sum[3];
  assign PIN_3 = sum[2];
  assign PIN_2 = sum[1];
  assign PIN_1 = sum[0];

endmodule

module Reg4(input CLK,
            input i3, //Button MSB
            input i2,
            input i1,
            input i0,
            output o3, //LED MSB
            output o2,
            output o1,
            output o0,
            input PIN_19); //CLOCK
	reg o3, o2, o1, o0;
  reg pushB; // push button for clock emulation

  debounce debounce_1(CLK, PIN_19, pushB);

  assign PIN_1 = pushB;

	always @(posedge pushB)
	begin
	o3 <= i3;
	o2 <= i2;
	o1 <= i1;
	o0 <= i0;
	end
endmodule // Reg4


module debounce(
    input CLK,
    input i,
    output o,
    );

    reg o = 0;
    reg [24:0] count;

  always @(posedge CLK)
  begin
    if (i)
      //start counting
      count <= count + 1;
    else if (count > 135000)
      begin
        o <= ~o;
        count <= 0;
      end
  else
    count <= 0;
  end

endmodule // debounce


module ripple_carry_adder_2_FA
  (
   input [3:0]  i_add_term1,
   input [3:0]  i_add_term2,
   output [4:0] o_result
   );

  wire [4:0]    w_CARRY;
  wire [3:0]    w_SUM;

  // No carry input on first full adder
  assign w_CARRY[0] = 1'b0;

  full_adder full_adder_1
    (
      .i_bit1(i_add_term1[0]),
      .i_bit2(i_add_term2[0]),
      .i_carry(w_CARRY[0]),
      .o_sum(w_SUM[0]),
      .o_carry(w_CARRY[1])
      );

  full_adder full_adder_2
    (
      .i_bit1(i_add_term1[1]),
      .i_bit2(i_add_term2[1]),
      .i_carry(w_CARRY[1]),
      .o_sum(w_SUM[1]),
      .o_carry(w_CARRY[2])
      );

  full_adder full_adder_3
    (
      .i_bit1(i_add_term1[2]),
      .i_bit2(i_add_term2[2]),
      .i_carry(w_CARRY[2]),
      .o_sum(w_SUM[2]),
      .o_carry(w_CARRY[3])
      );

  full_adder full_adder_4
    (
      .i_bit1(i_add_term1[3]),
      .i_bit2(i_add_term2[3]),
      .i_carry(w_CARRY[3]),
      .o_sum(w_SUM[3]),
      .o_carry(w_CARRY[4])
      );

  assign o_result = {w_CARRY[4], w_SUM};   // Verilog Concatenation

endmodule // ripple_carry_adder_2_FA

module full_adder
  (
   i_bit1,
   i_bit2,
   i_carry,
   o_sum,
   o_carry
   );

  input  i_bit1;
  input  i_bit2;
  input  i_carry;
  output o_sum;
  output o_carry;

  wire   w_WIRE_1;
  wire   w_WIRE_2;
  wire   w_WIRE_3;

  assign w_WIRE_1 = i_bit1 ^ i_bit2;
  assign w_WIRE_2 = w_WIRE_1 & i_carry;
  assign w_WIRE_3 = i_bit1 & i_bit2;

  assign o_sum   = w_WIRE_1 ^ i_carry;
  assign o_carry = w_WIRE_2 | w_WIRE_3;

endmodule // full_adder

edit: code formatting


#2

You had quite a few registers that should have been wires as they were not assigned to. The outputs from a module should be wires.

You also had some top-level assignments the wrong way round.

You can use a Verilog for loop and generate statement to generate the full adder instances and some of the assign statements to make your code shorter and easier to change to a wider adder.

You should use preformatted text button rather than quote button for code , or better use “```verilog” … “```”.

The debounce logic doesn’t look quite right. If it overflows to a value of less than 135000, it will not register a button press.

Here is a cleaned up version of your code (without the generate statements):

module top(
  input CLK,
  input PIN_19, // Button CLk
  input PIN_24, // Switch MSB
  input PIN_23,
  input PIN_22,
  input PIN_21,
  output PIN_18, // Add LEDs MSB
  output PIN_17,
  output PIN_16,
  output PIN_15,
  output PIN_5, // Sum LEDs MSB
  output PIN_4,
  output PIN_3,
  output PIN_2,
  output PIN_1
);

  wire [3:0] a;
  wire [3:0] b;
  wire [4:0] sum;

  // a is the current value of the switches
  assign a[3] = PIN_24;
  assign a[2] = PIN_23;
  assign a[1] = PIN_22;
  assign a[0] = PIN_21;

   // b is the registered value of the switches after
   // the button on PIN19 is pressed and released
  Reg4 Reg4_1(CLK, PIN_24, PIN_23, PIN_22, PIN_21, b[3], b[2], b[1], b[0], PIN_19);

  // Calculate the sum of a and b
  ripple_carry_adder_2_FA ripple_carry_adder_2_FA_1(a, b, sum);

  // Assign b to blue leds
  assign PIN_18 = b[3];
  assign PIN_17 = b[2];
  assign PIN_16 = b[1];
  assign PIN_15 = b[0];

  // Show sum on green leds
  assign PIN_5 = sum[4];
  assign PIN_4 = sum[3];
  assign PIN_3 = sum[2];
  assign PIN_2 = sum[1];
  assign PIN_1 = sum[0];

endmodule

module Reg4(
  input CLK,
  input i3, //Button MSB
  input i2,
  input i1,
  input i0,
  output reg o3, //LED MSB
  output reg o2,
  output reg o1,
  output reg o0,
  input PIN_19
); //CLOCK

  wire pushB; // push button for clock emulation

  debounce debounce_1(CLK, PIN_19, pushB);

  always @(posedge pushB)
  begin
    o3 <= i3;
    o2 <= i2;
    o1 <= i1;
    o0 <= i0;
  end

endmodule // Reg4

module debounce(
  input CLK,
  input i,
  output o
);

  reg o = 0;
  reg [24:0] count;

  always @(posedge CLK)
  begin
    if (i)
      //start counting
      count <= count + 1;
    else if (count > 135000)
    begin
      o <= ~o;
      count <= 0;
    end
    else
      count <= 0;
    end

endmodule // debounce

module ripple_carry_adder_2_FA(
  input [3:0] i_add_term1,
  input [3:0] i_add_term2,
  output [4:0] o_result
);

  wire [4:0] w_CARRY;
  wire [3:0] w_SUM;

  // No carry input on first full adder
  assign w_CARRY[0] = 1'b0;

  full_adder full_adder_1
  (
    .i_bit1(i_add_term1[0]),
    .i_bit2(i_add_term2[0]),
    .i_carry(w_CARRY[0]),
    .o_sum(w_SUM[0]),
    .o_carry(w_CARRY[1])
  );

  full_adder full_adder_2
  (
    .i_bit1(i_add_term1[1]),
    .i_bit2(i_add_term2[1]),
    .i_carry(w_CARRY[1]),
    .o_sum(w_SUM[1]),
    .o_carry(w_CARRY[2])
  );

  full_adder full_adder_3
  (
    .i_bit1(i_add_term1[2]),
    .i_bit2(i_add_term2[2]),
    .i_carry(w_CARRY[2]),
    .o_sum(w_SUM[2]),
    .o_carry(w_CARRY[3])
  );

  full_adder full_adder_4
  (
    .i_bit1(i_add_term1[3]),
    .i_bit2(i_add_term2[3]),
    .i_carry(w_CARRY[3]),
    .o_sum(w_SUM[3]),
    .o_carry(w_CARRY[4])
  );

  assign o_result = {w_CARRY[4], w_SUM}; // Verilog Concatenation

endmodule // ripple_carry_adder_2_FA

module full_adder (
  input i_bit1,
  input i_bit2,
  input i_carry,
  output o_sum,
  output o_carry
);

  wire w_WIRE_1 = i_bit1 ^ i_bit2;
  wire w_WIRE_2 = w_WIRE_1 & i_carry;
  wire w_WIRE_3 = i_bit1 & i_bit2;

  assign o_sum = w_WIRE_1 ^ i_carry;
  assign o_carry = w_WIRE_2 | w_WIRE_3;

endmodule // full_adder

And here is the version of the ripple adder using generate:

module ripple_carry_adder_2_FA(
  input [3:0] i_add_term1,
  input [3:0] i_add_term2,
  output [4:0] o_result
);

  wire [4:0] w_CARRY;
  wire [3:0] w_SUM;

  // No carry input on first full adder
  assign w_CARRY[0] = 1'b0;

  genvar i;
  for (i = 0; i < 4; i = i + 1) begin
    full_adder full_adder_1
    (
      .i_bit1(i_add_term1[i]),
      .i_bit2(i_add_term2[i]),
      .i_carry(w_CARRY[i]),
      .o_sum(w_SUM[i]),
      .o_carry(w_CARRY[i+1])
    );
  end
  
  assign o_result = {w_CARRY[4], w_SUM}; // Verilog Concatenation

endmodule // ripple_carry_adder_2_FA

And here is a version with several improvements, including using module parameters:

module top(
  input CLK,
  input PIN_19, // Button CLk
  input PIN_24, // Switch MSB
  input PIN_23,
  input PIN_22,
  input PIN_21,
  output PIN_18, // Add LEDs MSB
  output PIN_17,
  output PIN_16,
  output PIN_15,
  output PIN_5, // Sum LEDs MSB
  output PIN_4,
  output PIN_3,
  output PIN_2,
  output PIN_1
);

  localparam WIDTH = 4;

  wire [WIDTH-1:0] a = {PIN_24, PIN_23, PIN_22, PIN_21}; // a is current value of switches
  wire [WIDTH-1:0] b;
  wire [WIDTH:0] sum;

   // b is the registered value of the switches after
   // the button on PIN19 is pressed and released
  Reg Reg_1(CLK, a, b, PIN_19);

  // Calculate the sum of a and b
  ripple_carry_adder_2_FA ripple_carry_adder_2_FA_1(a, b, sum);

  // Assign b to blue leds
  assign {PIN_18, PIN_17, PIN_16, PIN_15}  = b;

  // Show sum on green leds
  assign {PIN_5, PIN_4, PIN_3, PIN_2, PIN_1} = sum;

endmodule

module Reg #(parameter WIDTH=4) (
  input CLK,
  input [WIDTH-1:0] i,
  output reg [WIDTH-1:0] o, 
  input PIN_19
); 

  wire pushB; // push button for clock emulation

  debounce debounce_1(CLK, PIN_19, pushB);

  always @(posedge pushB)
  begin
    o <= i;
  end

endmodule // Reg

module debounce(
  input CLK,
  input i,
  output o
);

  reg o = 0;
  reg [24:0] count;

  always @(posedge CLK)
  begin
    if (i)
      //start counting
      count <= count + 1;
    else if (count > 135000)
    begin
      o <= ~o;
      count <= 0;
    end
    else
      count <= 0;
    end

endmodule // debounce

module ripple_carry_adder_2_FA #(parameter WIDTH=4) (
  input [WIDTH-1:0] i_add_term1,
  input [WIDTH-1:0] i_add_term2,
  output [WIDTH:0] o_result
);

  wire [WIDTH:0] w_CARRY;
  wire [WIDTH-1:0] w_SUM;

  // No carry input on first full adder
  assign w_CARRY[0] = 1'b0;

  genvar i;
  for (i = 0; i < WIDTH; i = i + 1) begin
    full_adder full_adder_1
    (
      .i_bit1(i_add_term1[i]),
      .i_bit2(i_add_term2[i]),
      .i_carry(w_CARRY[i]),
      .o_sum(w_SUM[i]),
      .o_carry(w_CARRY[i+1])
    );
  end

  assign o_result = {w_CARRY[4], w_SUM}; // Verilog Concatenation

endmodule // ripple_carry_adder_2_FA

module full_adder (
  input i_bit1,
  input i_bit2,
  input i_carry,
  output o_sum,
  output o_carry
);

  wire w_WIRE_1 = i_bit1 ^ i_bit2;
  wire w_WIRE_2 = w_WIRE_1 & i_carry;
  wire w_WIRE_3 = i_bit1 & i_bit2;

  assign o_sum = w_WIRE_1 ^ i_carry;
  assign o_carry = w_WIRE_2 | w_WIRE_3;

endmodule // full_adder

#3

Thank you for your feedback its much appreciated, ill try to take it on board when making the next thing which is to subtract using 2’s compliments :slight_smile: i may increase it to 8 bits and use a 7 segment display as well


#4

So, I’ve managed to beef up the project, it now can add or subtract using the ‘+ or -’ button (green LED is HIGH when adding), with the ‘CLK’ button storing the fist binary number into a register.

Here’s a rough schematic, (the flip module needs some sort of feed back loop, just ignore it)

)

And Here’s the code:

module Top(input CLK,
            input PIN_14, // Button CLk
            input PIN_16, // Button select add or subtract
            input PIN_17, // Switch MSB PIN_17, PIN_18, PIN_19, PIN_20, PIN_21, PIN_22, PIN_23, PIN_24
            input PIN_18,
            input PIN_19,
            input PIN_20,
            input PIN_21,
            input PIN_22,
            input PIN_23,
            input PIN_24,
            output reg PIN_9, // Sum LEDs MSB PIN_1, PIN_2, PIN_3, PIN_4, PIN_5, PIN_6, PIN_7, PIN_8, PIN_9
            output reg PIN_8,
            output reg PIN_7,
            output reg PIN_6,
            output reg PIN_5,
            output reg PIN_4,
            output reg PIN_3,
            output reg PIN_2,
            output reg PIN_1,
            output reg PIN_15, // Displays if ADDING or SUBTRACTING (HIGH when ADDING)
);

            localparam  WIDTH = 8;

            wire [WIDTH-1:0] a = {~PIN_17, ~PIN_18, ~PIN_19, ~PIN_20, ~PIN_21, ~PIN_22, ~PIN_23, ~PIN_24};
            wire [WIDTH-1:0] aNot;
            wire [WIDTH-1:0] twosComp;
            wire [WIDTH-1:0] b;
            wire [WIDTH:0] sum;
            wire muxSel;
            wire [WIDTH:0]muxOut;
            wire pushDB;

            reg [WIDTH-1:0] plusOne = 8'b00000001;
            reg selAddSub = 1'b0;
            reg pushClk = PIN_14;
            reg pushAddSub = PIN_16;

  DeBounce DeBounce_2(CLK, pushAddSub, pushDB);
  Reg1 Reg1_1(CLK, selAddSub, muxSel, pushAddSub); // save value of +- select
  Ripple Ripple_1(~a, plusOne, twosComp); // convert to twos compliments
  RegWidth RegWidth_1(CLK, a, b, pushClk); // store twos compliment
  Ripple Ripple_2(b, muxOut, sum); // adds the stored twos compliment and the value from the switches

  always @(posedge pushDB)
  begin
    selAddSub <= ~selAddSub;
  end

  assign muxOut = muxSel ? twosComp : a;
  assign {PIN_9, PIN_8, PIN_7, PIN_6, PIN_5, PIN_4, PIN_3, PIN_2, PIN_1} = sum;
  assign PIN_15 = ~muxSel;

endmodule // Top


module Reg1 (
  input CLK,
  input  i,
  output reg o,
  input pshClk, // FROM SWITCH
);

  wire pushB; // push button for clock emulation

  DeBounce DeBounce_1(CLK, pshClk, pushB);

	always @(posedge pushB)
	begin
  	o <= i;
	end

endmodule // Reg1


module RegWidth #(parameter WIDTH=8) (
  input CLK,
  input [WIDTH-1:0] i,
  output reg [WIDTH-1:0] o,
  input pshClk, // FROM SWITCH
);

  wire pushB; // push button for clock emulation

  DeBounce DeBounce_1(CLK, pshClk, pushB);

	always @(posedge pushB)
	begin
  	o <= i;
	end

endmodule // RegWidth


module DeBounce(
  input CLK,
  input i,
  output o,
);
    parameter cDebounceLimit = 19000; // 10ns at 19MHz

    reg pushB = 1'b0;
    reg [15:0] count = 0; // 2^15 = 32768

  always @(posedge CLK)
  begin
     if (i !== pushB && count < cDebounceLimit)
       //start counting
       count <= count + 1;
     else if (count == cDebounceLimit)
       begin
         pushB <= i;
         count <= 0;
       end
     else
       count <= 0;
   end

   assign o = pushB;

endmodule // DeBounce


module Ripple #(parameter WIDTH=8) (
   input [WIDTH-1:0]  i_add_term1,
   input [WIDTH-1:0]  i_add_term2,
   output [WIDTH:0] o_result,
);

  wire [WIDTH:0]    w_CARRY;
  wire [WIDTH-1:0]    w_SUM;

  // No carry input on first full adder
  assign w_CARRY[0] = 1'b0;

  genvar i;
  for (i = 0; i < WIDTH; i = i + 1)
  begin
    FullAdder FullAdder_1
    (
      .i_bit1(i_add_term1[i]),
      .i_bit2(i_add_term2[i]),
      .i_carry(w_CARRY[i]),
      .o_sum(w_SUM[i]),
      .o_carry(w_CARRY[i+1])
    );
  end

  assign o_result = {w_CARRY[WIDTH], w_SUM};   // Verilog Concatenation

endmodule // Ripple

module FullAdder (
   input i_bit1,
   input i_bit2,
   input i_carry,
   output o_sum,
   output o_carry,
);

  wire   w_WIRE_1 = i_bit1 ^ i_bit2;
  wire   w_WIRE_2 = w_WIRE_1 & i_carry;
  wire   w_WIRE_3 = i_bit1 & i_bit2;

  assign o_sum   = w_WIRE_1 ^ i_carry;
  assign o_carry = w_WIRE_2 | w_WIRE_3;

endmodule // FullAdder