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 getU
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
andelse
to make sure that multiple assignments to variables are mutually exclusive.Here's an optimized implementation of your adder:
Follow-up:
I ran your two files through Modelsim as-is, and the simulation worked fine for me. Here's the waveform display:
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".