Electronic – VHDL serial adder test bench return UUUU

adderclocktestvhdl

I've designed some week ago this serial adder, then i let it go for a while and now i would like to state if it works or not…

So the design is this one this one

And i report to you the testbench i've tried to write by self, every time i try to do a test bench by my self i've always problem since i don't keep in mind the synchronization stuff.

So… below there's the code

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;

entity tb_serialAdder is
end entity tb_serialAdder;

architecture arch of tb_serialAdder is

    component serialAdder
        generic(n : natural := 4);
        port(x : in std_logic_vector(n - 1 downto 0);
             y : in std_logic_vector(n - 1 downto 0);
             clk : in std_logic;
             load : in std_logic;
             clr : in std_logic;
             z : out std_logic_vector(n - 1 downto 0));
    end component;

    signal clk, load, clr : std_logic;
    signal x, y , z : std_logic_vector(3 downto 0);
    constant clk_period : time := 10 ns;
begin

    serialAdderComp : serialAdder
        generic map(n => 4)
        port map(x => x, y => y, clk => clk, load => load, clr => clr, z => z);

    clk_proc : process is
    begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
    end process clk_proc;

    process is
        file out_file : text open write_mode is "output_serial_adder.txt";
        variable line_out : line;
    begin
        clr <= '1';
        wait for clk_period;
        clr <= '0';
        wait for clk_period;
        x <= "0101";
        y <= "0111";
        load <= '1';
        wait for clk_period;
        load <= '0';
        wait for clk_period;
        wait for 5*clk_period;
        write(line_out,z);
        writeline(out_file,line_out);
        wait;
    end process;    

end architecture arch;

When i start the test (syntax is correct) then what i see is UUUU.

What is troubling me probably are:
1. The design is wrong… (i think it is wrong at 65%)
2. The test bench is wrong.. (but i don't understand why… except that it could be a problem of synchronization).

Please… any clue?

Update:

Is probably better i include the code of my serial adder…

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;

entity serialAdder is
    generic(n : natural := 4);
    port(x : in std_logic_vector(n - 1 downto 0);
         y : in std_logic_vector(n - 1 downto 0);
         clk : in std_logic;
         load : in std_logic;
         clr : in std_logic;
         z : out std_logic_vector(n - 1 downto 0));
end entity serialAdder;

architecture arch of serialAdder is
    signal x_reg : std_logic_vector(n - 1 downto 0);
    signal y_reg : std_logic_vector(n - 1 downto 0);
    signal z_reg : std_logic_vector(n - 1 downto 0);
    signal c_reg : std_logic;
begin
    process(clk) is --handling of registers "x" and "y", synchronous
    begin

        if rising_edge(clk) then
            if clr = '1' then --clear all the registers, and flip flop
                x_reg <= (others => '0');
                y_reg <= (others => '0');
                c_reg <= '0';
                z_reg <= (others => '0');
            elsif load = '1' then
                x_reg <= x;
                y_reg <= y;
            else --execute sum
                x_reg <= '0' & x_reg(n - 1 downto 1); --right input register shift
                y_reg <= '0' & y_reg(n - 1 downto 1);       

                --full adder logic      
                z_reg <= (x_reg(0) xor y_reg(0) xor c_reg) & z_reg(n - 1 downto 1); --right shift and adding a new bit
                c_reg <= (c_reg and x_reg(0)) or (c_reg and y_reg(0)) or (x_reg(0) and y_reg(0)); --carry update
            end if;
        end if;
    end process;

    z <= z_reg; --update of the output

end architecture arch;

Update 2…

I've modified of the testbench as suggested, the result is the following:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;

entity tb_serialAdder is
end entity tb_serialAdder;

architecture arch of tb_serialAdder is

    component serialAdder
        generic(n : natural := 4);
        port(x : in std_logic_vector(n - 1 downto 0);
             y : in std_logic_vector(n - 1 downto 0);
             clk : in std_logic;
             load : in std_logic;
             clr : in std_logic;
             z : out std_logic_vector(n - 1 downto 0));
    end component;

    signal clk, load, clr : std_logic;
    signal x, y , z : std_logic_vector(3 downto 0);
    constant clk_period : time := 10 ns;
begin

    serialAdderComp : serialAdder
        generic map(n => 4)
        port map(x => x, y => y, clk => clk, load => load, clr => clr, z => z);

    clk_proc : process is
    begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
    end process clk_proc;

    sum_test : process is
        file out_file : text open write_mode is "output_serial_adder.txt";
        variable line_out : line;
    begin
        clr <= '1';
        wait for clk_period;
        clr <= '0';
        wait for clk_period;
        x <= "0101";
        y <= "0111";
        load <= '1';
        wait for clk_period;
        load <= '0';
        wait for 4*clk_period;
        write(line_out,z);
        writeline(out_file,line_out);
        wait;
    end process;    

end architecture arch;

If i start the simulation with ModelSim (which internally uses vsim i guess) both compilation and simulation runs fine… however if i try with ncsim something happens…
First of all when i start ncelab it says that component serialAdder is not bounded, secondly the output is always UUUU

I'm still missing something, any clue?

Best Answer

Taking a closer look at your code, I see that you have two separate processes assigning values to z_reg — I'm surprised this isn't giving you compile-time errors. Whenever the two processes try to assign different values, you'll get U values in the output.

It would be far better to write all of your code as a single process. It would also be better to make all assignments to your registers into synchronous assignments (i.e., on a clock edge), rather than having a mix of asynchronous and synchronous assignments. Make use of elsif and else to make sure that multiple assignments to variables are mutually exclusive.

Here's an optimized implementation of your adder:

architecture arch of serialAdder is
  signal x_reg : std_logic_vector(n - 1 downto 0);
  signal y_reg : std_logic_vector(n - 1 downto 0);
  signal z_reg : std_logic_vector(n - 1 downto 0);
  signal c_reg : std_logic;
begin

  process (clk)
  begin
    if rising_edge(clk) then
      if clr = '1' then
        -- clear all registers
        x_reg <= (others => '0');
        y_reg <= (others => '0');
        z_reg <= (others => '0');
        c_reg <= '0';
      elsif load = '1' then
        -- load X and Y registers from inputs
        x_reg <= x;
        y_reg <= y;
      else
        -- shift all of the registers
        x_reg <= '0' & x_reg(n - 1 downto 1);
        y_reg <= '0' & y_reg(n - 1 downto 1);
        z_reg(n - 1 downto 1) <= z_reg(n - 2 downto 0) & '0';

        -- do the addition
        z_reg(0) <= x_reg(0) xor y_reg(0) xor c_reg;
        c_reg <= (c_reg and x_reg(0)) or (c_reg and y_reg(0)) or (x_reg(0) and y_reg(0));
      end if;
    end if;
  end process;

  -- update of the output
  z <= z_reg;

end architecture arch;

Follow-up:

I ran your two files through Modelsim as-is, and the simulation worked fine for me. Here's the waveform display:

waveform trace

Note that the output equals "1100" where I've circled it, which is the correct result. However, the output file contains "0011", which is the output value two clocks later, because z_reg continues to shift.

I don't know why you're still getting "UUUU".