He diseñado un sumador en serie, con una pequeña unidad de control que se supone que sincroniza todos los estados ff. Estoy especialmente interesado en la máquina de estado que hace esas cosas (puede ver un diagrama de bloques aquí . El diseño es el siguiente:
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;
También he diseñado un banco de pruebas
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;
Sin embargo, no entiendo por qué no funciona. En el siguiente diagrama de los resultados de la simulación:
Estoy bastante seguro de que el problema es cómo diseñé la máquina de estados, soy nuevo en el control de diseño de unidades. ¿Alguna pista de por qué no funciona?
thx
Actualización 1
Siguiendo las sugerencias:
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;
Lamentablemente todavía no funciona ...