Banco de prueba de sumador en serie VHDL de retorno UUUU

Diseñé hace una semana este sumador serial, luego lo dejé pasar por un tiempo y ahora me gustaría decir si funciona o no...

Así que el diseño es este este este

Y les informo el banco de pruebas que he tratado de escribir por mí mismo, cada vez que trato de hacer un banco de pruebas por mí mismo, siempre tengo problemas ya que no tengo en cuenta las cosas de sincronización.

Entonces... debajo está el código

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;

Cuando comienzo la prueba (la sintaxis es correcta), lo que veo es UUUU.

Lo que probablemente me preocupa es: 1. El diseño está mal... (creo que está mal al 65%) 2. El banco de pruebas está mal... (pero no entiendo por qué... excepto que podría ser un problema de sincronización).

Por favor... alguna pista?

Actualizar:

Probablemente sea mejor que incluya el código de mi sumador serial...

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;

Actualización 2...

He modificado el banco de pruebas como se sugiere, el resultado es el siguiente:

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;

Si inicio la simulación con ModelSim (que internamente usa vsim, supongo), tanto la compilación como la simulación funcionan bien... sin embargo, si intento con ncsim, algo sucede... En primer lugar, cuando inicio ncelab, dice que el componente no está limitado serialAdder, en segundo lugar, la salida siempre es UUUU...

Todavía me falta algo, ¿alguna pista?

Respuestas (2)

Echando un vistazo más de cerca a su código, veo que tiene dos procesos separados a los que asigna valores z_reg; me sorprende que esto no le esté dando errores de tiempo de compilación. Cada vez que los dos procesos intenten asignar valores diferentes, obtendrá Uvalores en la salida.

Sería mucho mejor escribir todo su código como un solo proceso. También sería mejor hacer todas las asignaciones a sus registros en asignaciones síncronas (es decir, en un borde de reloj), en lugar de tener una combinación de asignaciones asíncronas y síncronas. Utilice elsify elsepara asegurarse de que las asignaciones múltiples a las variables sean mutuamente excluyentes.

Aquí hay una implementación optimizada de su sumador:

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)
  begin
    if rising_edge(clk) then
      if clr = '1' then
        -- clear all registers
        x_reg <= (others => '0');
        y_reg <= (others => '0');
        z_reg <= (others => '0');
        c_reg <= '0';
      elsif load = '1' then
        -- load X and Y registers from inputs
        x_reg <= x;
        y_reg <= y;
      else
        -- shift all of the registers
        x_reg <= '0' & x_reg(n - 1 downto 1);
        y_reg <= '0' & y_reg(n - 1 downto 1);
        z_reg(n - 1 downto 1) <= z_reg(n - 2 downto 0) & '0';

        -- do the addition
        z_reg(0) <= x_reg(0) xor y_reg(0) xor c_reg;
        c_reg <= (c_reg and x_reg(0)) or (c_reg and y_reg(0)) or (x_reg(0) and y_reg(0));
      end if;
    end if;
  end process;

  -- update of the output
  z <= z_reg;

end architecture arch;

Hacer un seguimiento:

Ejecuté sus dos archivos a través de Modelsim tal cual, y la simulación funcionó bien para mí. Aquí está la pantalla de forma de onda:

traza de forma de onda

Tenga en cuenta que la salida es igual a "1100" donde lo he marcado con un círculo, que es el resultado correcto. Sin embargo, el archivo de salida contiene "0011", que es el valor de salida dos relojes más tarde, porque z_regsigue cambiando.

No sé por qué sigues recibiendo "UUUU".

Ok... comparé su propuesta con mi modificación (vea el enlace en la publicación original) debería ser igual excepto por una asignación en z_reg (realizo tanto la adición como el cambio en una sola declaración, pero he mirado síntesis se parece a lo que espero). Sin embargo, probé mi banco de pruebas, sin cambiar su código, y todavía no funciona, ¿alguna pista?
Ver "seguimiento" arriba.
Hola, lamento molestarte de nuevo, probablemente no he sido claro... el problema que tengo es que ok, inicio ncsim, no uso a ningún tipo, así que la única salida que tengo es el archivo. Cuando veo el archivo, solo tiene una línea "UUUU". Entonces, al mirar los resultados de su simulación, me pregunto si es posible que la "escritura de archivos" se detenga antes de que cambie la salida, mientras que en su lugar ejecuta la simulación durante una ventana de tiempo más amplia. Si es así, ¿cómo debo modificar mi archivo para lograr lo que realmente debo esperar? (brevemente, creo que es un problema de tiempo en mi banco de pruebas)
(porque de lo contrario no sé qué más podría ser)
No puedo ayudarte con ncsim específicamente, porque nunca lo he usado. Pero si todo lo que tiene es el archivo de salida, tendrá que hacer el equivalente a la depuración al estilo printf() en C: debe imprimir los valores de varias señales en cada ciclo de reloj para ver cómo las cosas están cambiando y dónde van mal.
De todos modos... tu respuesta es la mejor. Me ayudaste tanto con el diseño en sí como con el banco de pruebas.
"Cada vez que los dos procesos intenten asignar valores diferentes, obtendrá valores U en la salida". ¿Quizás quisiste decir valores 'X'?
@rick: Los simuladores que usamos el OP y yo muestran valores desconocidos como "U", no "X". (Vea mi captura de pantalla arriba). Es un detalle de implementación menor que no es relevante para la pregunta.
@DaveTweed ¡Gracias por aclararlo! Sin embargo, esto no parece estrictamente compatible con el estándar VHDL.
@rick: No realmente. Es una diferencia sutil, pero establecer una señal en "X" en el código fuente porque no sabe qué estado debería tener no es lo mismo que el simulador que muestra una señal desconocida ("U") debido a un disco en conflicto. niveles Una señal que se muestra como "U" en el simulador se lee como "X" por cualquier otra lógica. Pero Modelsim, al menos, siempre muestra valores desconocidos como "U".

Bien, si sigue recibiendo este error:

En primer lugar, cuando inicio ncelab, dice que el componente serialAdder no está limitado

entonces ese es tu problema. Los componentes no unidos significan que, básicamente, Incisiv sabe que hay un agujero en el diseño, pero no puede encontrar nada que encaje. En otras palabras, está simulando el diseño como si su serialAdder no estuviera allí en absoluto. Si observa el diseño en la GUI de NCSim, verá que el bloque serialAdder está en un recuadro negro (no hay contenido) y, por lo tanto, todas sus salidas conducen automáticamente a 'U'.

En cuanto a la razón por la que no está dando errores de compilación que alguien más mencionó, es porque está usando std_logic(_vector), que es un tipo resuelto y permite múltiples controladores. La síntesis puede quejarse si tiene varios controladores, pero la simulación está perfectamente satisfecha con él. Si desea obtener errores de compilación si accidentalmente tiene varios controladores de una señal, debe usar std_ulogic(_vector).

No sé si el "sin consolidar" es el problema real o no. Pero como dije antes, si usa una interfaz gráfica de usuario, entonces todo está bien (no entiendo qué quiere decir con que la simulación se ejecuta como si el componente real no estuviera allí en absoluto). El problema es que cuando miro el archivo, debería escupir como salida, solo veo una línea donde dice "UUUU". Este es el problema, sin embargo, es cierto que en este momento no presto mucha atención a cosas como la señal resuelta o no, pero solo porque estoy más enfocado en la sintaxis y la compilación de cosas. La próxima vez prestaré más atención.