Forum Discussion

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

Newbie question about long control signal

hey, in my design i have a very long control signal, when i try complie the code i got error message like "Cannot split carry or cascade chain crossing xxx logic cells and starting on logic cell xxx into legal LABs." so i decide to break the singal manually to fit the maximum for a entire comlomn, and then connect them up.

the maximum length withour error is about 440 here, let's say i want the signal length to be 4000 and i want to break it into several 440 signal and connect them together(the next bit for the end of one column is the start one of the next comlumn), how should i write the code?

6 Replies

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

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;

    USE IEEE.numeric_std.ALL;

    entity rc_adder is

    generic (

    vsize: integer := 440

    );

    Port ( clk : in STD_LOGIC;

    a_in : in STD_LOGIC;

    b_in : in STD_LOGIC;

    r : out STD_LOGIC;

    load : in STD_LOGIC);

    end rc_adder;

    architecture Behavioral of rc_adder is

    signal a, b : STD_LOGIC_VECTOR(vsize-1 downto 0);

    signal rout : STD_LOGIC_VECTOR(vsize-1 downto 0);

    begin

    add : process

    begin

    wait until clk'event and clk = '1';

    if (load = '1') then

    a <= a(vsize-2 downto 0) & a_in;

    b <= b(vsize-2 downto 0) & b_in;

    rout <= rout(vsize-2 downto 0) & '0';

    r <= rout(vsize-1);

    else

    rout <= std_logic_vector(signed(a) + signed(b));

    end if;

    end process add;

    end Behavioral;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Show us what kind of code is producing that error..

    --- Quote End ---

    what i want to do here is add to very large number together, now i set generic to 440 which is ok, but i wish to have like 4000, so i think i need break the carry chain manually and connect it up, how to do that?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think you've come across a bug...

    Quartus should do it automatically for you. There's a synthesis setting for that and it's set to 70.

    A work arround is to use an LCELL primitive to break it, like this:

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;

    USE IEEE.numeric_std.ALL;

    entity rc_adder is

    generic (

    nblocks: integer := 40

    );

    Port ( clk : in STD_LOGIC;

    a_in : in STD_LOGIC;

    b_in : in STD_LOGIC;

    r : out STD_LOGIC;

    load : in STD_LOGIC);

    end rc_adder;

    architecture Behavioral of rc_adder is

    component lcell

    port (

    a_in : in std_logic;

    a_out : out std_logic);

    end component;

    constant vsize : integer := nblocks * 32;

    signal a, b : STD_LOGIC_VECTOR(vsize-1 downto 0);

    signal rout : STD_LOGIC_VECTOR(vsize-1 downto 0);

    signal sum : std_logic_vector(vsize - 1 downto 0);

    signal carry_a : std_logic_vector(nblocks downto 0);

    signal carry_b : std_logic_vector(nblocks downto 0);

    begin

    carry_b(0) <= '0';

    adders : for i in 1 to nblocks generate

    adder : entity work.adder_32

    port map(

    carry_in => carry_b(i-1),

    a => a(32*i-1 downto 32*(i-1)),

    b => b(32*i-1 downto 32*(i-1)),

    z => sum(32*i-1 downto 32*(i-1)),

    carry_out => carry_a(i)

    );

    lc : lcell

    port map (

    a_in => carry_a(i),

    a_out => carry_b(i)

    );

    end generate;

    add : process

    begin

    wait until clk'event and clk = '1';

    if (load = '1') then

    a <= a(vsize-2 downto 0) & a_in;

    b <= b(vsize-2 downto 0) & b_in;

    rout <= rout(vsize-2 downto 0) & '0';

    r <= rout(vsize-1);

    else

    rout <= sum;

    end if;

    end process add;

    end Behavioral;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I think you've come across a bug...

    Quartus should do it automatically for you. There's a synthesis setting for that and it's set to 70.

    A work arround is to use an LCELL primitive to break it, like this:

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;

    USE IEEE.numeric_std.ALL;

    entity rc_adder is

    generic (

    nblocks: integer := 40

    );

    Port ( clk : in STD_LOGIC;

    a_in : in STD_LOGIC;

    b_in : in STD_LOGIC;

    r : out STD_LOGIC;

    load : in STD_LOGIC);

    end rc_adder;

    architecture Behavioral of rc_adder is

    component lcell

    port (

    a_in : in std_logic;

    a_out : out std_logic);

    end component;

    constant vsize : integer := nblocks * 32;

    signal a, b : STD_LOGIC_VECTOR(vsize-1 downto 0);

    signal rout : STD_LOGIC_VECTOR(vsize-1 downto 0);

    signal sum : std_logic_vector(vsize - 1 downto 0);

    signal carry_a : std_logic_vector(nblocks downto 0);

    signal carry_b : std_logic_vector(nblocks downto 0);

    begin

    carry_b(0) <= '0';

    adders : for i in 1 to nblocks generate

    adder : entity work.adder_32

    port map(

    carry_in => carry_b(i-1),

    a => a(32*i-1 downto 32*(i-1)),

    b => b(32*i-1 downto 32*(i-1)),

    z => sum(32*i-1 downto 32*(i-1)),

    carry_out => carry_a(i)

    &nbsp;);

    lc : lcell

    port map (

    a_in => carry_a(i),

    a_out => carry_b(i)

    &nbsp;);

    end generate;

    add : process

    begin

    wait until clk'event and clk = '1';

    if (load = '1') then

    a <= a(vsize-2 downto 0) & a_in;

    b <= b(vsize-2 downto 0) & b_in;

    rout <= rout(vsize-2 downto 0) & '0';

    r <= rout(vsize-1);

    else

    rout <= sum;

    end if;

    end process add;

    end Behavioral;

    --- Quote End ---

    thank you very much rbugalho! im quite new to vhdl and im not quite understand the part you write, can you please expain it a bit?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I broke down the big adder into a series of 40 32 bit adders, creating a 1280 bit adder -- you need to write an "adder_32" module, which is a 32 bit adder with carry in and carry out.

    I pass the carry signal between two adders through an LCELL primitive to break the carry chain.

    I used a generate statement to generate the 40 adders and 40 LCELLs, instead of repeating the code 40 times.