Adder in VHDL

Adder in VHDL

  1.   Inside always block on the left-hand side never use wire. Only assign values to reg inside always block.

Eg. Consider this

reg [3:0] answer_reg;

always @* begin

answer_reg = a + c;

end

OR

wire [3:0] answer_wire;

assign answer_wire = a + c;

  1. Never use the same reg on both sides (Left & Right) inside always @ (*) block.

WRONG WAY: This will lead simulator to race as right side count+1 updates the left side count value which triggers the * block again and keeps going. It will result in infinite loop and simulation stuck.

always @ (*)

begin

if (pushin)

count = count +1;

if (count)

$display(“Hi”);

end

THIS IS CORRECT WAY TO USE COUNTER:

always @ (*)

begin

count_d=count; // This part work as a else part for if (pushin1), important to make sure no latches created

if(pushin1) begin

count_d= count+1;

end

if (count)

$display(“Hi”);

end

always @ (posedge clock)

begin

count <= #1 count_d;

end

  1.   Always write $finish statement in your testbench if you are dumping signals on .vcd or .vpd file. It creates a massive database for your waveform file and blocks all allocated memory resources given to you. You may result in disk quota exceed if you are not careful. Always write $finish statement in the testbench.
  1.   Never use reg on left side in assign statement. You can only use wire for assigning values using assign statement which results in a combinational logic for your wire.
  1.    Use always @ (*) block for combinational logic and use blocking statements in always @ (*) blocks. Use always @ (posedge clock) for sequential part of the design (Flip-Flop) with non-blocking statements.
  1.   Do not use blocking and non-blocking both assignments for a particular signal at different places. Bad coding practice. It results in hardware ambiguity.
  1.    Avoid multiple driver errors. Avoid driving the same signal in two different always blocks. It results in racing when one tries to simulate code. One never knows which block will execute first during simulation.

BAD CODING:

always @ ( posedge clock)

a <= #1 0;

always @ ( posedge clock)

a <= #1 1;

  1.    Default data type is wire: this means that if you declare a variable without specifying reg or wire, it will be a 1-bit wide wire.
  1.   Always use #1 delay in always @ (posedge clock) block for easy debug and better waveform view. You can clearly see where exactly the signal gets sampled. It reduces debug efforts a lot.

GOOD WAY:

always @ (posedge clock)

D <= #1 Q;

  1.   Never call module inside always or initial blocks. Module calls must be outside any procedural blocks.

WRONG WAY:

module conditional_adder(input wire [31:0] a_input,input wire [31:0] b_input,input wire cin,output wire [31:0]

sum_out,output wire carry_out);

wire [31:0] a;

wire [15:0] b;

always @ (posedge clock)

bit2_adder x1(.a(a_input[1:0]), .b(b_input[1:0]),.cin(cin), .sum(a[1:0]), .cout(b[0]));

assign sum_out = a;

assign carry_out = b[(`BITS/2)­1];

endmodule

CORRECT WAY:

module conditional_adder(input wire [31:0] a_input,input wire [31:0] b_input,input wire cin,output wire [31:0]

sum_out,output wire carry_out);

wire [31:0] a;

wire [15:0] b;

bit2_adder x1(.a(a_input[1:0]), .b(b_input[1:0]),.cin(cin), .sum(a[1:0]), .cout(b[0]));

assign sum_out = a;

assign carry_out = b[(`BITS/2)­1];

endmodule

  1.   always @ (posedge clock1, posedge clock2, negedge reset) this may simulate but does not synthesize. There is no Hardware (Flip-flop) which has two or multiple clocks in Toshiba synthesis library. you may use any of the followings in your HDL:

always @ (posedge clock)

always @ (negedge clock)

always @ (posedge clock or negedge reset)

always @ (posedge clock or posedge reset)

always @ (negedge clock or negedge reset)

always @ (negedge clock or posedge reset)

There are FFs with preset though if you want to use preset signal, you can include it in.

  1.   Try to avoid using different clock edge (posedge and negedge) in same design. It makes STA and SCAN difficult to perform. Either use only always @ (posedge clock) or only always @ (negedge clock) everywhere in your design.
  1.   Make sure you understand the concurrent behavior of Verilog. Always write synthesizable code. Make sure you work on synthesis as early as possible. Do not synthesize entire design at once at the end of the whole design. Synthesis small partition of design as you write over the time to make sure that you are writing correctly. If you will write entire code and later try to synthesize you may find it difficult to make it synthesizable at the end. Synthesis as early as possible and always after you add a small-small portion of HDL code in your design. Always remember we are writing HDL, synthesis has a lot more importance over simulation. You should see the evolving circuit behind every line of Verilog you add. No one is perfect!
  1.   Make sure you have no latches in your design. There should be only Flip-flops and combinational hardware in your design. You may use always_ff instead always to make sure that you are getting desired hardware from synthesis.
  1.   There is nothing like always @ (posedge clock and posegde reset), you can not use and keyword in this sense in always block. There is just or keyword. Make sure you know how to write code to make correct FFlop hardware for any sequential circuits.
  1.    If you are using a loop, for example for loop in your code make sure it has fix numbers on iteration at compile time as you can not keep variable numbers of iterations as it does not result in hardware. A number of loop iterations must be fixed values to make sure that it synthesize.

Think about how that loop might be implemented, given that the hardware doesn’t know how loops work. Because of that, loops get unrolled completely – if you have ten loop iterations, VCS will produce ten copies of the hardware within the loop. If in your code you have an unknown number of iterations (varying or infinite #’s of iterations), It can not produce a fixed hardware. 

Solution

— inputs: X[7..0], Y[7..0]

— outputs: S[7..0]

— carry_in and carry_out not used!!! (do not intend to extend on 16-bit!)

LIBRARY ieee;

USE ieee.std_logic_1164.all;

entity CSA8 is

PORT (X, Y: in bit_vector(7 downto 0);

S: out bit_vector(7 downto 0));

end CSA8;

architecture logic of CSA8 is

component CSA4 is

PORT( C_in: in bit;

X, Y: in bit_vector(3 downto 0);

S: out bit_vector(3 downto 0);

C_out: out bit);

end component;

component MUX10_5 is

PORT( sel: in bit;

X, Y: in bit_vector(4 downto 0);

m: out bit_vector(4 downto 0));

end component;

constant c: bit := ‘1’;

signal msel: bit;

signal mx, my: bit_vector(4 downto 0);

begin

csa4_inst0 : CSA4

PORT MAP( C_in => ‘0’, X => X(3 downto 0), Y => Y(3 downto 0),

S => S(3 downto 0), C_out =>msel);

csa4_inst1 : CSA4

PORT MAP( C_in => c, X => X(7 downto 4), Y => Y(7 downto 4),

S => mx(3 downto 0), C_out => mx(4));

csa4_inst2 : CSA4

PORT MAP( C_in => not c, X => X(7 downto 4), Y => Y(7 downto 4),

S => my(3 downto 0), C_out => my(4));

mux10_5_inst0 : MUX10_5

PORT MAP( sel =>msel, X => mx, Y => my,

m(3 downto 0) => S(7 downto 4));

end logic;

Test codes

– CSA8_test.vhdl

— test vector for CSA8.vhdl

— A testbench has no ports.

library ieee;

use ieee.std_logic_1164.all;

entity test is

end test;

architecture behav of test is

— Declaration of the component that will be instantiated.

component CSA8

port(A,   B:     in  bit;

SUM, CARRY: out bit);

end component;

— Specifies which entity is bound with the component.

for adder_0: CSA8 use entity work.CSA8;

signal i0, i1, s, co, ci : bit;

begin

— Component instantiation.

adder_0: CSA8 port map (A => i0, B => i1, SUM => s, CARRY => co);

— This process does the real job.

process

type pattern_type is record

— The inputs of the adder.

i0, i1, ci : bit;

— The expected outputs of the adder.

s, co : bit;

end record;

— The patterns to apply.

type pattern_array is array (natural range <>) of pattern_type;

constant patterns : pattern_array :=

((‘0’, ‘0’, ‘0’, ‘0’, ‘0’),

(‘0’, ‘0’, ‘1’, ‘1’, ‘0’), — not use

(‘0’, ‘1’, ‘0’, ‘1’, ‘0’),

(‘0’, ‘1’, ‘1’, ‘0’, ‘1’), — not use

(‘1’, ‘0’, ‘0’, ‘1’, ‘0’),

(‘1’, ‘0’, ‘1’, ‘0’, ‘1’), — not use

(‘1’, ‘1’, ‘0’, ‘0’, ‘1’),

(‘1’, ‘1’, ‘1’, ‘1’, ‘1’)); — not use

begin

report ” A , B : C ,SUM”;

— Check each pattern.

for i in patterns’range loop

— Set the inputs.

i0 <= patterns(i).i0;

i1 <= patterns(i).i1;

ci <= patterns(i).ci;

— Wait for the results.

wait for 1 ns;

report bit’image(i0) & “,” &bit’image(i1) & “:” &bit’image(co) & “,” &bit’image(s);

— Check the outputs.

–assert s = patterns(i).s

–report “bad sum value” severity error;

–assert co = patterns(i).co

–report “bad carray out value” severity error;

end loop;

assert false report “end of test” severity note;

— Wait forever; this will finish the simulation.

wait;

end process;

end behav;

Raw

result.txt

$ghdl -a CSA8.vhdl; ghdl -a CSA8_test.vhdl; ghdl -e test; ghdl -r test

CSA8_test.vhdl:44:5:@0ms:(report note):  A , B : C ,SUM

CSA8_test.vhdl:53:7:@1ns:(report note): ‘0’,’0′:’0′,’0′

CSA8_test.vhdl:53:7:@2ns:(report note): ‘0’,’0′:’0′,’0′

CSA8_test.vhdl:53:7:@3ns:(report note): ‘0’,’1′:’0′,’1′

CSA8_test.vhdl:53:7:@4ns:(report note): ‘0’,’1′:’0′,’1′

CSA8_test.vhdl:53:7:@5ns:(report note): ‘1’,’0′:’0′,’1′

CSA8_test.vhdl:53:7:@6ns:(report note): ‘1’,’0′:’0′,’1′

CSA8_test.vhdl:53:7:@7ns:(report note): ‘1’,’1′:’1′,’0′

CSA8_test.vhdl:53:7:@8ns:(report note): ‘1’,’1′:’1′,’0′

CSA8_test.vhdl:60:5:@8ns:(assertion note): end of test

$ghdl -a CSA8.vhdl CSA8.vhdl; ghdl -a CSA8_test.vhdl; ghdl -e ftest; ghdl -r ftest

CSA8_test.vhdl:41:5:@0ms:(report note):  A , B ,CI :CO ,SUM

CSA8_test.vhdl:50:7:@1ns:(report note): ‘0’,’0′,’0′:’0′,’0′

CSA8_test.vhdl:50:7:@2ns:(report note): ‘0’,’0′,’1′:’0′,’1′

CSA8_test.vhdl:50:7:@3ns:(report note): ‘0’,’1′,’0′:’0′,’1′

CSA8_test.vhdl:50:7:@4ns:(report note): ‘0’,’1′,’1′:’1′,’0′

CSA8_test.vhdl:50:7:@5ns:(report note): ‘1’,’0′,’0′:’0′,’1′

CSA8_test.vhdl:50:7:@6ns:(report note): ‘1’,’0′,’1′:’1′,’0′

CSA8_test.vhdl:50:7:@7ns:(report note): ‘1’,’1′,’0′:’1′,’0′

CSA8_test.vhdl:50:7:@8ns:(report note): ‘1’,’1′,’1′:’1′,’1′

CSA8_test.vhdl:57:5:@8ns:(assertion note): end of test

$ghdl -a CSA82.vhdl; ghdl -a CSA8_test.vhdl; ghdl -e ftest; ghdl -r ftest

CSA8_test.vhdl:41:5:@0ms:(report note):  A , B ,CI :CO ,SUM

CSA8_test.vhdl:50:7:@1ns:(report note): ‘0’,’0′,’0′:’0′,’0′

CSA8_test.vhdl:50:7:@2ns:(report note): ‘0’,’0′,’1′:’0′,’1′

CSA8_test.vhdl:50:7:@3ns:(report note): ‘0’,’1′,’0′:’0′,’1′

CSA8_test.vhdl:50:7:@4ns:(report note): ‘0’,’1′,’1′:’1′,’0′

CSA8_test.vhdl:50:7:@5ns:(report note): ‘1’,’0′,’0′:’0′,’1′

CSA8_test.vhdl:50:7:@6ns:(report note): ‘1’,’0′,’1′:’1′,’0′

CSA8_test.vhdl:50:7:@7ns:(report note): ‘1’,’1′,’0′:’1′,’0′

CSA8_test.vhdl:50:7:@8ns:(report note): ‘1’,’1′,’1′:’1′,’1′

CSA8_test.vhdl:57:5:@8ns:(assertion note): end of test

$ghdl -a CSA82b.vhdl; ghdl -a CSA8_test.vhdl; ghdl -e ftest; ghdl -r ftest

CSA8_test.vhdl:41:5:@0ms:(report note):  A , B ,CI :CO ,SUM

CSA8_test.vhdl:50:7:@1ns:(report note): ‘0’,’0′,’0′:’0′,’0′

CSA8_test.vhdl:50:7:@2ns:(report note): ‘0’,’0′,’1′:’0′,’1′

CSA8_test.vhdl:50:7:@3ns:(report note): ‘0’,’1′,’0′:’0′,’1′

CSA8_test.vhdl:50:7:@4ns:(report note): ‘0’,’1′,’1′:’1′,’0′

CSA8_test.vhdl:50:7:@5ns:(report note): ‘1’,’0′,’0′:’0′,’1′

CSA8_test.vhdl:50:7:@6ns:(report note): ‘1’,’0′,’1′:’1′,’0′

CSA8_test.vhdl:50:7:@7ns:(report note): ‘1’,’1′,’0′:’1′,’0′

CSA8_test.vhdl:50:7:@8ns:(report note): ‘1’,’1′,’1′:’1′,’1′

CSA8_test.vhdl:57:5:@8ns:(assertion note): end of test