Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

Marble line

Hello everyone,

I am trying to make a marble line. I have red marbles and blue marbles and I basically want to fill in order an integer vector with the value 2 for blue marbles, 1 for red marbles and 0 for when there are no marbles. The way I want this to work is that I want to start with an empty line and, every time I press a button called redMarble, a red marble will go to the first empty space of this line and every time I press the blueMarble button, a blue marble will go to the first empty space available of the line. The vector that represent the line is called marbleLine, and I made it in a way that I can change its size if I want.

Unfortunately though, I have not been able to get this right. I have gone through it over and over again but I can't find what I am doing wrong or another way to do what I want.

The code I have so far is:


library IEEE;
use IEEE.std_logic_1164.all;
Entity Central is
    generic (N: integer := 9);
    port(
        redMarble, blueMarble: in std_logic;
        -- outLine is here just for tests
        outLine: out std_logic_vector(N downto 0)
        );
        
end Central;
architecture archC of Central is 
    type Vector is array (N downto 0) of integer range 0 to 2;
    signal marbleLine : Vector;
    begin 
        process(redMarble, blueMarble) is
        variable alreadyFoundFirstZero: std_logic;
        begin
        
        alreadyFoundFirstZero := '0';
        if(rising_edge(redMarble)) then
-- Here I will look for the first empty space, or 0, in the marbleLine
            for i in 0 to N loop
                if(alreadyFoundFirstZero = '0') then
                    if(marbleLine(i) = 0) then
                        marbleLine(i) <= 1;
                        alreadyFoundFirstZero := '1';
                    end if;
                end if;
            end loop;
        end if;
        alreadyFoundFirstZero := '0';
        if(rising_edge(blueMarble)) then
            for i in 0 to N loop
                if(alreadyFoundFirstZero = '0') then
                    if(marbleLine(i) = 0) then
                        marbleLine(i) <= 2;
                        alreadyFoundFirstZero := '1';
                    end if;
                end if;
            end loop;
        end if;
        end process;
        
        
        -- Testing Output
        process(marbleLine) is
        begin
            for i in 0 to N loop
                if (marbleLine(i)= 1) then
                    outLine(i) <= '1';
                end if;
                if (marbleLine(i)= 2) then
                    outLine(i) <= '0';
                end if;
            end loop;
        end process;
        
end archC;

With this code I am getting multiple erros of the kind:

Error (10821): HDL error at Central.vhd(34): can't infer register for "marbleLine[0][0]" because its behavior does not match any supported register model

and

Error (10820): Netlist error at Central.vhd(34): can't infer register for marbleLine[1][0] because its behavior depends on the edges of multiple distinct clocks

Does anyone know how to fix these problems, or even, how to make this possible in a different way?

Thank you all in advance,

Stomp

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    An FPGA register cannot be clocked from multiple sources. I suggest you have a system clock running and then use redMarble and blueMarble as clock enables.

    Did you write a testbench for your code?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I will try that!

    I didn't write one, I am trying to make it work first. But basically I plan to press redMarble and blueMarble a few times and see if marbleLine is filled in the correct order.

    I will come back here once I am done.

    Thanks a lot!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Okay, now I could compile it!

    I didn't get the output I was expecting though.

    Here is the code:

    
    library IEEE;
    use IEEE.std_logic_1164.all;
    Entity Central is
    	generic (N: integer := 9);
    	port(
    		clock, redMarble, blueMarble: in std_logic;
    		outLine: out std_logic_vector(N downto 0)
    		);
    		
    end Central;
    architecture archC of Central is 
    	type Vector is array (N downto 0) of integer;
    	signal marbleLine : Vector;
    	begin 
    		process(redMarble, blueMarble) is
    		variable alreadyFoundFirstZero: std_logic;
    		begin
    		alreadyFoundFirstZero := '0';
    		if(rising_edge(clock)) then
    			if(redMarble = '1' and blueMarble = '0') then
    -- Here I will look for the first empty space, or 0, in the marbleLine
    				for i in 0 to N loop
    					if(alreadyFoundFirstZero = '0') then
    						if(marbleLine(i) = 0) then
    							marbleLine(i) <= 1;
    							alreadyFoundFirstZero := '1';
    						end if;
    					end if;
    				end loop;
    				elsif(redMarble = '0' and blueMarble = '1')then
    					for i in 0 to N loop
    						if(alreadyFoundFirstZero = '0') then
    							if(marbleLine(i) = 0) then
    								marbleLine(i) <= 2;
    								alreadyFoundFirstZero := '1';
    							end if;
    						end if;
    					end loop;
    				end if;
    		end if;
    		end process;
    		
    		-- Testing Output
    		process(marbleLine) is
    		begin
    			for i in 0 to N loop
    				if (marbleLine(i)= 1) then
    					outLine(i) <= '1';
    				end if;
    				if (marbleLine(i)= 2) then
    					outLine(i) <= '0';
    				end if;
    			end loop;
    		end process;
    		
    end archC;
    

    I don't know if it is possible to use an integer vector as an output so I decided to make a std_logic_vector and use 1 for redMarble (marbleLine = 1) and 0 for blueMarble

    (marbleLine = 2) and empty spaces (marbleLine = 0). I am so sorry for this super clumsy test but this was as much as I had time to do right now. Here is what I got:

    https://www.alteraforum.com/forum/attachment.php?attachmentid=8129

    Am I doing anything stupidly wrong and not noticing?

    Thanks again!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You should write a testbench - the testbench will help you debug it without having to go to hardware (it is much harder to debug on hardware).

    You need to make your process sensitive to clock, not red/blueMarble.

    Be aware that for loops will unroll into the worst case hardware. So for your code, it is a long chain of 2:1 muxes.

    Other points to note:

    Using integers makes the values 32 bit. You probably want to limit the range to limit the bit-width (the synthesisor may trim this for you).

    You can use an integer array as an output, but I wouldnt do it for the top level, as you would need to map all the bits to pins on the chip. In VHDL you have no direct access to the bits in an integer (they dont exist in VHDL, the synthesisor maps them for you) so its best to go with some std_logic array type (usually std_logic_vector or signed or unsigned).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Ok,

    I will try to do all that, hopefully things become more clear.

    I appreciate your help and patience, thank you.