Diseño de sumador serial tonto con unidad de control

1

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

    
pregunta user8469759

1 respuesta

1

En el siguiente proceso debes agregar una condición como if clk'event and clk = '1' then

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;
        end if;
    end if;
end process regs_and_ff;

Encontré algunos errores de seguimiento en su proceso de FSM:

control_unit_out : process(current_state, start, counter) --here in sensitivity list you should add all signals which will use in any comparison (if/elsif/else, case and etc. structures)
begin
    case current_state is
        when s0 =>
            if start = '0' then --here you used incorrect sign for comparison
                load <= '0'; ce <= '0'; done <= '1';
                next_state <= s1;
            end if;
        when s1 => -- in this state you didn't assign next_state so your FSM stop in this state
            ce <= '0';
            if start = '1' then --here you used incorrect sign for comparison
                load <= '1'; done <= '0';
            else
                load <= '0'; done <= '1';
            end if;
        when s2 => --you also should add condition to achieve a next_state in this state too (like in prev)
            load <= '0';
            done <= '0';
            if counter < num_bits then
                ce <= '1';
            else 
                ce <= '0';
            end if;
    end case;
end process control_unit_out;

También tiene un reinicio del contador counter <= 0; pero nunca lo cuenta y lo incrementa, creo que debería agregarlo en su lógica si desea que la comparación en el estado S2 funcione correctamente if counter < num_bits then

Intente corregir los errores y creo que su módulo funcionará. Todos los errores que he anotado en los comentarios a la línea específica en el código.
Se corrigieron algunos errores, pero no sé la lógica de su FSM, así que hágalo usted mismo.

Actualización 1: este código funciona, pero no creo que la lógica sea correcta, por lo que debes resolverlo, pero por ti mismo

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 -- here was mistake ('<=' instead '=')
                x_reg <= unsigned(x);
                y_reg <= unsigned(x);
                z_reg <= to_unsigned(0,num_bits);
                c <= '0';
                counter <= 0;
            elsif ce = '1' then -- here was mistake ('<=' instead '=')
                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, start, counter)
    begin
        case current_state is
            when s0 =>
                if start = '0' then
                    load <= '0'; ce <= '0'; done <= '1';
                    next_state <= s0; -- I added this line to avoid latch implementation. 
                    --You can change the next_state value in for this condition as you need
                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';
                    next_state <= s1; -- I added this line to avoid latch implementation. 
                    --You can change the next_state value in for this condition as you need
                end if;
            when s2 =>
                load <= '0';
                done <= '0';
                if counter < num_bits then
                    ce <= '1';
                    next_state <= s2; -- I added this line to avoid latch implementation. 
                    --You can change the next_state value in for this condition as you need
                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;

A continuación puede encontrar la forma de onda de mi simulación con el código tomado anteriormente.

    
respondido por el Roman

Lea otras preguntas en las etiquetas