1
\$\begingroup\$

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?

\$\endgroup\$
2
\$\begingroup\$

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".

\$\endgroup\$
  • \$\begingroup\$ Ok... i compared your proposal with my modification (see the link in the original post) it should be the same except for an assignment in z_reg (i perform both the addition and shifting in a single statement, but i've looked at synthesis it looks like what i expect). However i tried my test bench, without changing on its code, and still doesn't work, any clue? \$\endgroup\$ – user8469759 Sep 30 '15 at 12:11
  • \$\begingroup\$ See "follow-up" above. \$\endgroup\$ – Dave Tweed Sep 30 '15 at 21:10
  • \$\begingroup\$ Hi i'm sorry to bother again, probably i haven't been clear... the problem i have is that ok i start ncsim, i don't use any guy so the only output i have is the file. When i see the file it has only one line "UUUU". So looking instead at your simulation results i wander if it could be possible that the "file writing" stops before the output changes, while instead you run the simulation for a wider time window. If it is so, how should i modify my file in order to achieve what actually should i expect? (briefly i think it is some timing problem in my test bench) \$\endgroup\$ – user8469759 Oct 1 '15 at 10:33
  • \$\begingroup\$ (because otherwise i don't really know what else could be) \$\endgroup\$ – user8469759 Oct 1 '15 at 10:33
  • \$\begingroup\$ I can't help you with ncsim specifically, because I've never used it. But if all you have is the output file, you're going to have to do the equivalent of printf()-style debugging in C -- you need to print out the values of various signals on every clock cycle in order to see how things are changing and where they go wrong. \$\endgroup\$ – Dave Tweed Oct 1 '15 at 10:50
0
\$\begingroup\$

OK, if you are still getting this error:

First of all when i start ncelab it says that component serialAdder is not bounded

then that's your problem. Unbound components means that basically Incisiv knows that there is a hole in the design, but it can't find anything to fit. In other words, it's simulating the design as if your serialAdder isn't actually there at all. If you look at the design in the NCSim GUI, you will see that the serialAdder block is black-boxed (there are no contents) and therefore all of its outputs automatically drive 'U'.

As for the reason why it isn't giving compile errors that someone else mentioned, that's because you're using std_logic(_vector), which is a resolved type, and allows multiple drivers. Synthesis may complain if you have multiple drivers, but simulation is perfectly happy with it. If you want to get compilation errors if you accidentally have multiple drivers of a signal, you need to use std_ulogic(_vector).

\$\endgroup\$
  • \$\begingroup\$ I don't know if the "unbound" is the actual problem or not. But as i said before if use a gui then everything it's fine (i don't understand what do you mean the simulation runs as if the actual component isn't there at all). The problem is that when i look at the file the should spit out as output i only see a line where it says "UUUU". This is the problem, it is true however that at the present i don't pay much attention to stuff like resolved signal or not, but just because i'm more focused on syntax and compiling stuff. Next time i'll pay more attention. \$\endgroup\$ – user8469759 Oct 1 '15 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.