2

I created each module and a test bench. each does exactly what its supposed to in the simulator. but when i attempt to synthesize i get the error "2170 - Unit VgaTest : the following signal(s) form a combinatorial loop: U1/Madd_divider_lut<1>" followed by the map process removing every single signal from the top level module (message 701) this leaves my device without any output (confirmed with oscilloscope)

I don't understand why it simulates and works fine, but then does this. any advice or information would be appreciated. (using a mimas v2 with 100Mhz clock, on a spartan6 yes I know the clock is 25.000 mhz not 25.175)

ClockGen:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;

entity ClockGen is
    Port (    clk : in  STD_LOGIC;
               rst : in  STD_LOGIC;
           clkout : out STD_LOGIC);
end ClockGen;

architecture Behavioral of ClockGen is
    signal divider : std_logic_vector(3 downto 0) := (others => '0');
begin
    process(clk, rst)
    begin
        if (rst = '1') then
            divider <= "0000";
        else
            divider <= divider + '1';
        end if;
    end process;

    clkout <= divider(3);
end Behavioral;

VgaController:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity vgaController is
    Port(
          clk: in std_logic;    -- pixel clock (25.175Mhz)
        hsync: out std_logic;
        vsync: out std_logic;
            r: out std_logic_vector(3 downto 0);
            g: out std_logic_vector(3 downto 0);
            b: out std_logic_vector(2 downto 0)
    );
end vgaController;

architecture Behavioral of vgaController is
    -- horizontal timing(line)
    constant hva: integer := 640;   -- visible area
    constant hfp: integer := 16;    -- front porch
    constant hsp: integer := 96;    -- sync pulse
    constant hbp: integer := 48;    -- back porch

    -- vertical timing
    constant vva: integer := 480; -- visible area
    constant vfp: integer := 10;    -- front porch
    constant vsp: integer := 2; -- sync pulse
    constant vbp: integer := 32;    -- back porch

    signal HPOS: integer range 0 to 800 := 0;
    signal VPOS: integer range 0 to 525 := 0;
begin
    process (clk)
    begin
        if (rising_edge(clk)) then
            -- update the position counters
            if (HPOS < (hva+hfp+hsp+hbp)) then  -- are we within the horizontal area?
                HPOS <= HPOS + 1;
            else
                HPOS <= 0;
                if (VPOS < (vva+vfp+vsp+vbp)) then  -- are we within vertical area?
                    VPOS <= VPOS + 1;
                else
                    VPOS <= 0;
                end if;
            end if;

            -- update the sync signals
            if (HPOS > (hva+hfp) and HPOS < (hva+hfp+hsp)) then -- horiz sync
                hsync <= '0';
            else
                hsync <= '1';
            end if;

            if (VPOS > (vva+vfp) and VPOS < (vva+vfp+vsp)) then -- vertical sync
                vsync <= '0';
            else
                vsync <= '1';
            end if;

            -- TEMP -- SET OUR PIXELS (this will be replaced with actual driver code later)
            if ((HPOS > hva) or (VPOS > vva)) then
                -- blank signal
                R <= (others => '0');
                G <= (others => '0');
                B <= (others => '0');
            else
                -- blue background
                R <= (others => '0');
                G <= (others => '0');
                B <= (others => '1');

                -- white cross hair
                if ((HPOS > 475 and HPOS < 485) or (VPOS > 280 and VPOS < 290)) then
                    R <= (others => '1');
                    G <= (others => '1');
                    B <= (others => '1');
                end if;
            end if;
        end if;
    end process;
end Behavioral;

and VgaTest (topmost module):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity VgaTest is
    Port(
          clk: in std_logic;
        HSYNC: out std_logic;
        VSYNC: out std_logic;
            r: out std_logic_vector(3 downto 0);
            g: out std_logic_vector(3 downto 0);
            b: out std_logic_vector(2 downto 0)
    );
end VgaTest;

architecture Behavioral of VgaTest is
    component ClockGen
    Port(
         clk : IN  std_logic;
         rst : IN  std_logic;
         clkout : OUT  std_logic
        );
    end component;

    component vgaController
    Port(
         clk : IN  std_logic;
         hsync : OUT  std_logic;
         vsync : OUT  std_logic;
         r : OUT  std_logic_vector(3 downto 0);
         g : OUT  std_logic_vector(3 downto 0);
         b : OUT  std_logic_vector(2 downto 0)
        );
    end component;

     signal clktmp: std_logic;

     signal out_hsync: std_logic := '0';
     signal out_vsync: std_logic := '0';

     signal out_r: std_logic_vector(3 downto 0);
     signal out_g: std_logic_vector(3 downto 0);
     signal out_b: std_logic_vector(2 downto 0);

begin

   U1: ClockGen Port map (
          clk => clk,
          rst => '0',           -- reset is not being used, so hardwire it low
          clkout => clktmp
       );

   U2: vgaController Port map (
          clk => clktmp,
          hsync => out_hsync,
          vsync => out_vsync,
          r => out_r,
          g => out_g,
          b => out_b
        );

    HSYNC <= out_hsync;
    VSYNC <= out_vsync;
    r <= out_r;
    g <= out_g;
    b <= out_b;
end Behavioral;

I'm really thinking its likely a newbie issue, but I just cant seem to figure out why.

edited to remove the similarity to another question. i will be flagging as solved, but the issue that was pointed out was that my clockgen process was not actually being clocked. by changing it to have

elsif(rising_edge(clk)) then
 ...

resolved the synthesizers complaints. not yet tested on real hardware but i see no reason it will still fail.

  • 2
    Your divider process isnt clocked. Its just a looped version of divider. – Tricky Oct 23 '19 at 21:07
  • Possible duplicate of [How to solve a combinatorial logic with an output feeding back to the input, forming a loop?](https://stackoverflow.com/questions/19747478/how-to-solve-a-combinatorial-logic-with-an-output-feeding-back-to-the-input-for) –  Oct 23 '19 at 23:16
  • 2
    Transform the else into elsif rising_edge(clk) then divider <= divider + 1; Also adjust the length of divider and the tap off for clkout. You won't be using both edges of clk in simulation when you provide a synthesis eligible form. –  Oct 23 '19 at 23:28
  • is was definately not a duplicate, as I read that q a few times. however the divider was indeed the issue. I'm not positive i understood the "tap off for clkout" but I did change it to elsif(rising_edge(clk)) then and the warnings/removals are gone. It will be a few hours before I am home again and able to test the design on hardware but this seems like the fix. thank you very much user1155120!! – James Wilson Oct 24 '19 at 12:28
  • one more thing. I want to post that user1155120 (as well as tricky if a little under verbose) had the solution, but I'm only seeing how *I* could answer it. someone want to either flag theirs as the answer or let me know how I can? – James Wilson Oct 24 '19 at 12:36
  • 1
    Don't worry. user1155120 only writes an answer if he can write it elaborately enough. He has high standards. So he often answers questions in the comments. He is not supposed to do that, but he's been doing that for many years now. You can always write your own answer and mention him in it. – JHBonarius Oct 25 '19 at 11:21

1 Answers1

0

as per user1155120 the issue was the clock. it would synthesize out the entirety of the net because it never generated a clock. here is the fix

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;

entity ClockGen is
    Port (    clk : in  STD_LOGIC;
               rst : in  STD_LOGIC;
           clkout : out STD_LOGIC);
end ClockGen;

architecture Behavioral of ClockGen is
    signal divider : std_logic_vector(3 downto 0) := (others => '0');
begin
    process(clk, rst)
    begin
        if (rst = '1') then
            divider <= "0000";
        elsif (rising_edge(clk)) then
            divider <= divider + '1';
        end if;
    end process;

    clkout <= divider(3);
end Behavioral;

using this it displays fine providing the monitor will support 25Mhz flat. the clock was replaced with a PLL setup to give me exactly 25.175 to make it work on any monitor (at least that i've tried so far)