He diseñado un sumador en serie, con una pequeña unidad de control que se supone sincroniza todos los estados ff. Estoy específicamente interesado en la máquina de estado que hace tales cosas (puedes 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 gráfico de los resultados de la simulación:
Estoy bastante seguro de que el problema es cómo diseñé la máquina de estado, soy nuevo en el diseño de unidades de control. ¿Alguna pista de por qué no funciona?
Gracias
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 sigue sin funcionar...
En el siguiente proceso, debe agregar una condición comoif 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 de los siguientes errores en su proceso 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 ni lo incrementa, creo que debería agregarlo en su lógica si desea que la comparación en el S2
estado funcione correctamenteif counter < num_bits then
Intente corregir los errores y creo que su módulo funcionará. Todos los errores que anoté en los comentarios a una línea específica en el código.
Se corrigieron algunos errores, pero no conozco 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 debe resolverlo usted 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 del código tomado arriba.
rising_edge(clk)
en lugar declk'event and clk = '1'
rising_edge(clk)
y clk'event and clk = '1'
lo mismo en este casorising_edge()
y falling_edge()
hacer frente a todos los bordes válidos, el 'event
estilo no lo hace. ¡ El 'event
estilo incluso considera una 'X'
transición '1'
como un borde! ¿Por qué no aprovechar las construcciones de lenguaje simples diseñadas para ayudarlo?
ks0ze
usuario8469759
ks0ze
usuario8469759
usuario8469759
ks0ze
usuario8469759
MarkU