Search code examples
vhdlxilinx

Why do I get no output at my VHDL multiplier?


I am trying to make a 4 bit multiplier. Here is my top level design: enter image description here

And here are the two modules: enter image description here enter image description here

However when I try to simulate this I get no output. My testbench:

    ARCHITECTURE behavior OF sim3 IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT multiplicator
    PORT(
         a : IN  std_logic_vector(3 downto 0);
         b : IN  std_logic_vector(3 downto 0);
         reset : IN  std_logic;
         clk : IN  std_logic;
         start : IN  std_logic;
         prod : OUT  std_logic_vector(7 downto 0);
         ready : OUT  std_logic
        );
    END COMPONENT;


   --Inputs
   signal a : std_logic_vector(3 downto 0) := (others => '0');
   signal b : std_logic_vector(3 downto 0) := (others => '0');
   signal reset : std_logic := '0';
   signal clk : std_logic := '0';
   signal start : std_logic := '0';

    --Outputs
   signal prod : std_logic_vector(7 downto 0);
   signal ready : std_logic;

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: multiplicator PORT MAP (
          a => a,
          b => b,
          reset => reset,
          clk => clk,
          start => start,
          prod => prod,
          ready => ready
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
        wait for clk_period;
        reset<='1';
        wait for clk_period;
        reset<='0';
        a<="0011";
        b<="0010";
        start <='1';
        wait for clk_period*10;
   end process;

END;

When I am setting the start to '1' the simulation just stops. I don't know why. I get the folowing error:

ERROR: at 20 ns(10000): Iteration limit 10000 is reached. Possible zero delay oscillation detected where simulation can not advance in time because signals can not resolve to a stable value in File "D:/faculta/PL II/multiplicator/reg8.vhd" Line 45. Please correct this code in order to advance past the current simulation time.

enter image description here

I don't see what could be wrong at that line:

q_s <= "00000000" WHEN reset='1' ELSE d WHEN reset='0' and load='1' ELSE q_s;

Some help please?


Solution

  • Don't use a register with a load enable, use clock edge register. The iteration limit is a delta cycle limit in ISIM. Introducing a '1' in b you get a striking oscillator, a loop with delta cycle delays and inversion (the summing). Make num4, reg4 and reg8 clock edge driven with their loads as enables, this appears compatible with Lab10 which shows the use of a clock (and the VHDL source for @scary_jeff, albeit expressed in type BIT instead of std_logic). This feedback phenomenon is mentioned in William Kafig's book VHDL 101 Everything you need to know to get started, in Chapter 4.

    Google Translate helps. No one ever seems to provide their handouts for their assignments.

    If you look at the original implementation of assignment to q_s in reg4:

    block1: 
        block (ck = '1' and not ck'stable)
        begin
            q_s <= guarded "0000" when reset = '1' else
                               d  when reset = '0' and load = '1' else
                             q_s;
        end block block1;
    

    I'd translate this into a synthesizable process statement instead of a block statement, making in clear reg4 (and reg8) is a clocked register:

    block1: 
        process (ck)
        begin
            if rising_edge(ck) then 
                if reset = '1' then
                    q_s <= (others => '0');
                elsif load = '1' then
                    q_s <= d;
                end if;
            end if;
        end process;
    

    The reason the original works is because a block statement can have a guard statement.

    The change makes it clear the q_s is a clocked register with a synchronous reset.

    You also might note we no longer reference q_s and can assign q directly.

    In the control state machine the process assigning next_state to current_state can likewise be updated:

        process (ck)
        begin
            if ck'event and ck = '1' then  -- or rising_edge(ck)
                current_state <= next_state;
            end if;
        end process;
    

    Simply for readability. It's uncommon to use the form not ck'stable for signifying a clock event, noting you also appear to have missed the implication in implementing reg8, potentially in reg4 and automat as well.

    The synthesis eligibility of a guarded expression as an edge sensitive clock is demonstrated in IEEE Std 1076.6-2004, 6.1.3.6 Edge-sensitive storage using a guarded block.