I have designed a serial adder, with a small control unit which is supposed to synchronize all the ff states. I'm specifically interested in the state machine that does such stuff (you can see a block diagram here. The design is the following:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
entity serial_adder is
generic(num_bits : integer := 4);
port(rst : in std_logic;
start : in std_logic;
clk : in std_logic;
x : in std_logic_vector(num_bits - 1 downto 0);
y : in std_logic_vector(num_bits - 1 downto 0);
z : out std_logic_vector(num_bits - 1 downto 0);
ovf : out std_logic;
done : out std_logic);
end entity serial_adder;
architecture rtl of serial_adder is
type states is (s0,s1,s2);
signal load, ce : std_logic;
signal x_reg, y_reg, z_reg : unsigned(num_bits - 1 downto 0);
signal s, next_c, c : std_logic;
subtype count is natural range 0 to num_bits;
signal counter : count;
signal current_state, next_state : states;
begin
s <= x_reg(0) xor y_reg(0) xor c;
next_c <= (x_reg(0) and y_reg(0)) xor (x_reg(0) and c) xor (y_reg(0) and c);
z <= std_logic_vector(z_reg);
regs_and_ff : process(clk)
begin
if load <= '1' then
x_reg <= unsigned(x);
y_reg <= unsigned(x);
z_reg <= to_unsigned(0,num_bits);
c <= '0';
counter <= 0;
elsif ce <= '1' then
x_reg <= '0' & x_reg(num_bits - 1 downto 1);
y_reg <= '0' & y_reg(num_bits - 1 downto 1);
z_reg <= s & z_reg(num_bits - 1 downto 1);
c <= next_c;
end if;
end process regs_and_ff;
control_unit_out : process(current_state)
begin
case current_state is
when s0 =>
if start <= '0' then
load <= '0'; ce <= '0'; done <= '1';
next_state <= s1;
end if;
when s1 =>
ce <= '0';
if start <= '1' then
load <= '1'; done <= '0';
else
load <= '0'; done <= '1';
end if;
when s2 =>
load <= '0';
done <= '0';
if counter < num_bits then
ce <= '1';
else
ce <= '0';
end if;
end case;
end process control_unit_out;
control_unit_sm : process(clk,rst)
begin
if rst = '1' then current_state <= s0;
elsif clk'event and clk = '1' then current_state <= next_state;
end if;
end process control_unit_sm;
end architecture rtl;
I've also designed a test bench
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
entity tb_serial_adder is
end entity tb_serial_adder;
architecture test of tb_serial_adder is
signal rst, clk, start, done, ovf : std_logic;
signal x, y, z : std_logic_vector(3 downto 0);
component serial_adder is
generic(num_bits : natural := 4);
port(rst : in std_logic;
start : in std_logic;
clk : in std_logic;
x : in std_logic_vector(num_bits - 1 downto 0);
y : in std_logic_vector(num_bits - 1 downto 0);
z : out std_logic_vector(num_bits - 1 downto 0);
ovf : out std_logic;
done : out std_logic);
end component serial_adder;
constant clk_period : time := 100 ns;
begin
DUT : serial_adder
generic map(num_bits => 4)
port map(rst => rst,
start => start,
clk => clk,
x => x,
y => y,
z => z,
ovf => ovf,
done => done);
clk_proc : process is
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
end process clk_proc;
stim_proc : process is
begin
x <= "1001";
y <= "0101";
rst <= '1';
start <= '0';
wait for 200 ns;
rst <= '0';
start <= '1';
wait for 200 ns;
wait for 1000 ns;
wait;
end process stim_proc;
end architecture test;
However I don't understand why it doesn't work. In the following a plot of the simulation results:
I'm quite sure the problem is how I've designed the state machine, I'm new to control unit design. Any clue on why it's not working?
thx
Update 1
Following the suggestions:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
entity serial_adder is
generic(num_bits : integer := 4);
port(rst : in std_logic;
start : in std_logic;
clk : in std_logic;
x : in std_logic_vector(num_bits - 1 downto 0);
y : in std_logic_vector(num_bits - 1 downto 0);
z : out std_logic_vector(num_bits - 1 downto 0);
ovf : out std_logic;
done : out std_logic);
end entity serial_adder;
architecture rtl of serial_adder is
type states is (s0,s1,s2);
signal load, ce : std_logic;
signal x_reg, y_reg, z_reg : unsigned(num_bits - 1 downto 0);
signal s, next_c, c : std_logic;
subtype count is natural range 0 to num_bits;
signal counter : count;
signal current_state, next_state : states;
begin
s <= x_reg(0) xor y_reg(0) xor c;
next_c <= (x_reg(0) and y_reg(0)) xor (x_reg(0) and c) xor (y_reg(0) and c);
z <= std_logic_vector(z_reg);
regs_and_ff : process(clk)
begin
if clk'event and clk = '1' then
if load <= '1' then
x_reg <= unsigned(x);
y_reg <= unsigned(x);
z_reg <= to_unsigned(0,num_bits);
c <= '0';
counter <= 0;
elsif ce <= '1' then
x_reg <= '0' & x_reg(num_bits - 1 downto 1);
y_reg <= '0' & y_reg(num_bits - 1 downto 1);
z_reg <= s & z_reg(num_bits - 1 downto 1);
c <= next_c;
counter <= counter + 1;
end if;
end if;
end process regs_and_ff;
control_unit_out : process(current_state)
begin
case current_state is
when s0 =>
if start = '0' then
load <= '0'; ce <= '0'; done <= '1';
else
next_state <= s1;
end if;
when s1 =>
ce <= '0';
if start = '1' then
load <= '1'; done <= '0';
next_state <= s2;
else
load <= '0'; done <= '1';
end if;
when s2 =>
load <= '0';
done <= '0';
if counter < num_bits then
ce <= '1';
else
ce <= '0';
next_state <= s0;
end if;
end case;
end process control_unit_out;
control_unit_sm : process(clk,rst)
begin
if rst = '1' then current_state <= s0;
elsif clk'event and clk = '1' then current_state <= next_state;
end if;
end process control_unit_sm;
end architecture rtl;
Unfortunately still doesn't work...