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?
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á U
valores 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 elsif
y else
para 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;
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:
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_reg
sigue cambiando.
No sé por qué sigues recibiendo "UUUU".
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).
usuario8469759
david tweed
usuario8469759
usuario8469759
david tweed
usuario8469759
almiar
david tweed
almiar
david tweed