Forum Discussion

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

Optimizing a set of registers

I am working on optimizing a processor I made (size-wise) and I noticed that the register set is quite large (about 1000 LEs) I looked into the sysnthesized logic using the RTL viewer and it looked very messy (I am trying to upload an image of it) with over 100 multiplexers and lots of unnecessary signals.

I am wondering how I can make it so the design is simpler (i.e. the logic is composed of the register, two multiplexers [for reads], and one de-multiplexer [for writing]).

The VHDL code I used is listed here:


entity default_registers is
port (
      
	   input : in std_logic_vector(31 downto 0);
		
		register_to_write : in std_logic_vector (4 downto 0);
		write_to_register : in std_logic;
		register_to_read_a : in std_logic_vector (4 downto 0);
		register_to_read_b : in std_logic_vector (4 downto 0);	
		clk : in std_logic;		
		clear: in std_logic;
		
		output0 : out std_logic_vector(31 downto 0);
		output1 : out std_logic_vector(31 downto 0)
		
     );
end default_registers;
architecture Behavioral of default_registers is
signal register1 : std_logic_vector (31 downto 0);
signal register2 : std_logic_vector (31 downto 0);
signal register3 : std_logic_vector (31 downto 0);
signal register4 : std_logic_vector (31 downto 0);
signal register5 : std_logic_vector (31 downto 0);
signal register6 : std_logic_vector (31 downto 0);
signal register7 : std_logic_vector (31 downto 0);
signal register8 : std_logic_vector (31 downto 0);
signal register9 : std_logic_vector (31 downto 0);
signal register10 : std_logic_vector (31 downto 0);
signal register11 : std_logic_vector (31 downto 0);
signal register12 : std_logic_vector (31 downto 0);
signal register13 : std_logic_vector (31 downto 0);
signal register14 : std_logic_vector (31 downto 0);
signal register15 : std_logic_vector (31 downto 0);
signal register16 : std_logic_vector (31 downto 0);
signal register17 : std_logic_vector (31 downto 0);
signal register18 : std_logic_vector (31 downto 0);
signal register19 : std_logic_vector (31 downto 0);
signal register20 : std_logic_vector (31 downto 0);
signal register21 : std_logic_vector (31 downto 0);
signal register22 : std_logic_vector (31 downto 0);
signal register23 : std_logic_vector (31 downto 0);
signal register24 : std_logic_vector (31 downto 0);
signal register25 : std_logic_vector (31 downto 0);
signal register26 : std_logic_vector (31 downto 0);
signal register27 : std_logic_vector (31 downto 0);
signal register28 : std_logic_vector (31 downto 0);
signal register29 : std_logic_vector (31 downto 0);
signal register30 : std_logic_vector (31 downto 0);
signal register31 : std_logic_vector (31 downto 0);
begin
process(clear, clk, write_to_register)
begin
if clear = '1' then
register1 <= (others => '0');
register2 <= (others => '0');
register3 <= (others => '0');
register4 <= (others => '0');
register5 <= (others => '0');
register6 <= (others => '0');
register7 <= (others => '0');
register8 <= (others => '0');
register9 <= (others => '0');
register10 <= (others => '0');
register11 <= (others => '0');
register12 <= (others => '0');
register13 <= (others => '0');
register14 <= (others => '0');
register15 <= (others => '0');
register16 <= (others => '0');
register17 <= (others => '0');
register18 <= (others => '0');
register19 <= (others => '0');
register20 <= (others => '0');
register21 <= (others => '0');
register22 <= (others => '0');
register23 <= (others => '0');
register24 <= (others => '0');
register25 <= (others => '0');
register26 <= (others => '0');
register27 <= (others => '0');
register28 <= (others => '0');
register29 <= (others => '0');
register30 <= (others => '0');
register31 <= (others => '0');
elsif falling_edge(clk) then 
if write_to_register = '1' then
case register_to_write is
when "00000" =>
-- Do nothing since register0 is always zero
when "00001" =>
register1 <= input;
when "00010" =>
register2 <= input;
when "00011" =>
register3 <= input;
when "00100" =>
register4 <= input;
when "00101" =>
register5 <= input;
when "00110" =>
register6 <= input;
when "00111" =>
register7 <= input;
when "01000" =>
register8 <= input;
when "01001" =>
register9 <= input;
when "01010" =>
register10 <= input;
when "01011" =>
register11 <= input;
when "01100" =>
register12 <= input;
when "01101" =>
register13 <= input;
when "01110" =>
register14 <= input;
when "01111" =>
register15 <= input;
when "10000" =>
register16 <= input;
when "10001" =>
register17 <= input;
when "10010" =>
register18 <= input;
when "10011" =>
register19 <= input;
when "10100" => 
register20 <= input;
when "10101" =>
register21 <= input;
when "10110" =>
register22 <= input;
when "10111" =>
register23 <= input;
when "11000" =>
register24 <= input;
when "11001" =>
register25 <= input;
when "11010" =>
register26 <= input;
when "11011" =>
register27 <= input;
when "11100" =>
register28 <= input;
when "11101" =>
register29 <= input;
when "11110" =>
register30 <= input;
when "11111" =>
register31 <= input;
when others =>
end case;
end if;
end if;
end process;
process (register_to_read_a, register_to_read_b)
begin
case register_to_read_a is
when "00000" =>
output0 <= (others => '0');
when "00001" =>
output0 <= register1;
when "00010" =>
output0 <= register2;
when "00011" =>
output0 <= register3;
when "00100" =>
output0 <= register4;
when "00101" =>
output0 <= register5;
when "00110" =>
output0 <= register6;
when "00111" =>
output0 <= register7;
when "01000" =>
output0 <= register8;
when "01001" =>
output0 <= register9;
when "01010" =>
output0 <= register10;
when "01011" =>
output0 <= register11;
when "01100" =>
output0 <= register12;
when "01101" =>
output0 <= register13;
when "01110" =>
output0 <= register14;
when "01111" =>
output0 <= register15;
when "10000" =>
output0 <= register16;
when "10001" =>
output0 <= register17;
when "10010" =>
output0 <= register18;
when "10011" =>
output0 <= register19;
when "10100" =>
output0 <= register20;
when "10101" =>
output0 <= register21;
when "10110" =>
output0 <= register22;
when "10111" =>
output0 <= register23;
when "11000" =>
output0 <= register24;
when "11001" =>
output0 <= register25;
when "11010" =>
output0 <= register26;
when "11011" =>
output0 <= register27;
when "11100" =>
output0 <= register28;
when "11101" =>
output0 <= register29;
when "11110" =>
output0 <= register30;
when "11111" =>
output0 <= register31;
when others =>
end case;
case register_to_read_b is
when "00000" =>
output1 <= (others => '0');
when "00001" =>
output1 <= register1;
when "00010" =>
output1 <= register2;
when "00011" =>
output1 <= register3;
when "00100" =>
output1 <= register4;
when "00101" =>
output1 <= register5;
when "00110" =>
output1 <= register6;
when "00111" =>
output1 <= register7;
when "01000" =>
output1 <= register8;
when "01001" =>
output1 <= register9;
when "01010" =>
output1 <= register10;
when "01011" =>
output1 <= register11;
when "01100" =>
output1 <= register12;
when "01101" =>
output1 <= register13;
when "01110" =>
output1 <= register14;
when "01111" =>
output1 <= register15;
when "10000" =>
output1 <= register16;
when "10001" =>
output1 <= register17;
when "10010" =>
output1 <= register18;
when "10011" =>
output1 <= register19;
when "10100" =>
output1 <= register20;
when "10101" =>
output1 <= register21;
when "10110" =>
output1 <= register22;
when "10111" =>
output1 <= register23;
when "11000" =>
output1 <= register24;
when "11001" =>
output1 <= register25;
when "11010" =>
output1 <= register26;
when "11011" =>
output1 <= register27;
when "11100" =>
output1 <= register28;
when "11101" =>
output1 <= register29;
when "11110" =>
output1 <= register30;
when "11111" =>
output1 <= register31;
when others =>
end case;  
end process;
end Behavioral;

22 Replies

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

    This is a more 'generic' way of writing what you want.

    I deliberately added the generics to allow inspection of a 'small' implementation in the RTL Schematic viewer.

    BTW: there are some flaws in your generation of sw(x); if you align a, b,c,d and e vertically the flaws will pop out. Unless you intended it to be that way ... in which case my output process has to be adapted ...

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity default_registers is
    	generic(
    		WIDTH_DATA    : natural := 4;
    		NBR_REGISTERS : natural := 4;
    		WIDTH_ADDRESS : natural := 2
    		);
    	port(
    		clk                : in  std_logic;
    		clear              : in  std_logic;
    		input              : in  std_logic_vector(WIDTH_DATA - 1 downto 0);
    		register_to_write  : in  std_logic_vector(WIDTH_ADDRESS - 1 downto 0);
    		write_to_register  : in  std_logic;
    		register_to_read_a : in  std_logic_vector(WIDTH_ADDRESS - 1 downto 0);
    		register_to_read_b : in  std_logic_vector(WIDTH_ADDRESS - 1 downto 0);
    		output0            : out std_logic_vector(WIDTH_DATA - 1 downto 0);
    		output1            : out std_logic_vector(WIDTH_DATA - 1 downto 0)
    		);
    	end default_registers;
    architecture Behavioral of default_registers is
    	type a_register is array (natural range <>) of std_logic_vector(WIDTH_DATA - 1 downto 0);
    	signal registers : a_register(NBR_REGISTERS - 1  downto 0);
    begin
    	process(clear, clk)
    		begin
    			if clear = '1' then
    				registers <= (others => (others => '0'));
    	
    			elsif falling_edge(clk) then
    				registers(0) <= (others => '0');		-- keep register(0) to all zeroes
    				for i in 1 to NBR_REGISTERS - 1 loop	-- the others are writable
    					if (write_to_register = '1') and (i = to_integer( unsigned( register_to_write ))) then
    						registers(i) <= input;
    					end if;
    				end loop;
    	
    			end if;
    		end process;
    	process(register_to_read_a, register_to_read_b, registers)
    		begin
    			output0 <= registers( to_integer( unsigned( register_to_read_a )));
    			output1 <= registers( to_integer( unsigned( register_to_read_b )));
    	
    		end process;
    end Behavioral;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This is a more 'generic' way of writing what you want.

    I deliberately added the generics to allow inspection of a 'small' implementation in the RTL Schematic viewer.

    BTW: there are some flaws in your generation of sw(x); if you align a, b,c,d and e vertically the flaws will pop out. Unless you intended it to be that way ... in which case my output process has to be adapted ...

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity default_registers is
    	generic(
    		WIDTH_DATA    : natural := 4;
    		NBR_REGISTERS : natural := 4;
    		WIDTH_ADDRESS : natural := 2
    		);
    	port(
    		clk                : in  std_logic;
    		clear              : in  std_logic;
    		input              : in  std_logic_vector(WIDTH_DATA - 1 downto 0);
    		register_to_write  : in  std_logic_vector(WIDTH_ADDRESS - 1 downto 0);
    		write_to_register  : in  std_logic;
    		register_to_read_a : in  std_logic_vector(WIDTH_ADDRESS - 1 downto 0);
    		register_to_read_b : in  std_logic_vector(WIDTH_ADDRESS - 1 downto 0);
    		output0            : out std_logic_vector(WIDTH_DATA - 1 downto 0);
    		output1            : out std_logic_vector(WIDTH_DATA - 1 downto 0)
    		);
    	end default_registers;
    architecture Behavioral of default_registers is
    	type a_register is array (natural range <>) of std_logic_vector(WIDTH_DATA - 1 downto 0);
    	signal registers : a_register(NBR_REGISTERS - 1  downto 0);
    begin
    	process(clear, clk)
    		begin
    			if clear = '1' then
    				registers <= (others => (others => '0'));
    	
    			elsif falling_edge(clk) then
    				registers(0) <= (others => '0');		-- keep register(0) to all zeroes
    				for i in 1 to NBR_REGISTERS - 1 loop	-- the others are writable
    					if (write_to_register = '1') and (i = to_integer( unsigned( register_to_write ))) then
    						registers(i) <= input;
    					end if;
    				end loop;
    	
    			end if;
    		end process;
    	process(register_to_read_a, register_to_read_b, registers)
    		begin
    			output0 <= registers( to_integer( unsigned( register_to_read_a )));
    			output1 <= registers( to_integer( unsigned( register_to_read_b )));
    	
    		end process;
    end Behavioral;

    --- Quote End ---

    The generic style can work as well, but I seem to be fine with the one I am using now.

    I also took a look at the sw(x) generation process and I have fixed the issues that it had.