Negative Edge Trigger and Asynchronous Clear no funciona en ModelSim

0

He creado un contador de 4 bits con las siguientes entradas y salidas

relojN: reloj bajo activo

clearN: active low clear

cP: Cuando está alto, el contador cuenta. Cuando está bajo, el contador permanece igual.

eP: activa alta. Esto activa el búfer de tres estados en las salidas

Cuando simulo esto, y afirmo que el clearN (N significa activo bajo) en t = 0, en realidad no se borra hasta el siguiente borde positivo del reloj. No entiendo porque. Además, cada vez que qOut cuenta en uno, lo hace en el borde positivo del reloj, aunque mi código le está diciendo que lo haga en el borde negativo del reloj. Mi código, banco de pruebas y salida de modelsim se muestran a continuación.

Aquí está el código del contador

    --Program Counter for SAP-1

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;    --This is required when doing additions to STD_LOGIC_VECTORs

ENTITY PROG_COUNT_SAP_1 IS 

    GENERIC(size: INTEGER:= 3); --This is the size of the register

    PORT(
        clockN, clearN, cP, eP: IN STD_LOGIC;
        qOut: OUT STD_LOGIC_VECTOR(size DOWNTO 0));

END PROG_COUNT_SAP_1;

ARCHITECTURE Behavioral OF PROG_COUNT_SAP_1 IS
    SIGNAL valueBeforeTriBuffer: STD_LOGIC_VECTOR(size DOWNTO 0);

BEGIN

    PROCESS(clockN, clearN, cP, eP)
    BEGIN
        IF(clearN = '0') THEN
            valueBeforeTriBuffer<=(OTHERS=>'0');

        ELSIF (falling_edge(clockN)) THEN

            IF (cP = '1') THEN
                valueBeforeTriBuffer<= valueBeforeTriBuffer + 1;
            END IF;

        END IF;

        IF (eP = '1') THEN
            qOut<= valueBeforeTriBuffer;
        ELSE
            qOut<=(OTHERS=>'Z');
        END IF;

    END PROCESS;

END Behavioral;

Aquí está el banco de pruebas

    library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity TB_PROG_COUNT_SAP_1 is
end TB_PROG_COUNT_SAP_1;

architecture test of TB_PROG_COUNT_SAP_1 is

--create time constant
constant CLOCK_PERIOD: time:=2 us;

--create constants for all generics.
constant size: INTEGER:=3;

--create signals for every port
signal clockN: std_logic;
signal clearN: std_logic;
signal cP: std_logic;
signal eP: std_logic;
signal qOut: std_logic_vector(size DOWNTO 0);

begin

dut: entity work.PROG_COUNT_SAP_1
generic map(size=>size)
port map(clockN=>clockN,
    clearN=>clearN,
    cP=>cP,
    eP=>eP,
    qOut=>qOut);

--simulate the clock
clockNSimulation: process
BEGIN

    FOR count IN 1 TO 16 LOOP
        clockN<= '0';
        wait for CLOCK_PERIOD/2;
        clockN<='1';
        wait for CLOCK_PERIOD/2;
    END LOOP;

END PROCESS clockNSimulation;



--simulate the clearN
clearNSimulation: process
BEGIN

    clearN<='0';
    wait for  3 us;
    clearN<='1';
    wait for 7 us;
    clearN<='0';
    wait for 2 us;
    clearN<='1';
    wait;

END PROCESS clearNSimulation;


--simulate the cP
cPSimulation: process
BEGIN
    cP<='1';
    wait;

END PROCESS cPSimulation;   

ePSimulation: process
BEGIN
    eP<='1';
    wait;

END PROCESS ePSimulation;   


end architecture test;

Aquí está la forma de onda de salida de modelsim:

    
pregunta BPoy

1 respuesta

0

Como lo mencionó el usuario 8352 en los comentarios: su problema es que necesita inducir un ciclo delta adicional cuando haya actualizado valuebeforetribuffer (pro-tip: VHDL no distingue mayúsculas de minúsculas). La solución rápida y sucia es agregar valuebeforetribuffer a su lista de sensibilidad. Sin embargo, en ese punto estás gravitando hacia un lío cada vez mayor de un código.

El limpiador es:

p_main: process(clk, clear_n, enable_out)
  variable r_value_before_tri_buffer : unsigned(size-1 downto 0);
begin

  if clear_n = '0' then
    r_value_before_tri_buffer := (others=>'0');
  elsif falling_edge(clk) then
    if c_p = '1' then
      r_value_before_tri_buffer := r_value_before_tri_buffer +1;
    end if;
  end if;

  if enable_out then
    q_out <= std_logic_vector(r_value_before_tri_buffer);
  else
    q_out <= (others=>'Z');
  end if;

end process;

Otras observaciones:

  • Uso numeric_std en lugar del lío que es std_logic_unsigned
  • size downto 0 declara un vector de tamaño + 1
  • no es necesario tener c_p en tu lista de sensibilidad si solo lo usas en los flancos del reloj, también reduce el tiempo de simulación
respondido por el DonFusili

Lea otras preguntas en las etiquetas