Перейти к содержанию
    

Оптимизация определения адреса записи

Здравствуйте. Продолжаю неравный бой за каждый мегагерц. ))

Есть у меня процессы для организации взаимодействия с SDRAM через контроллер.

-- обработчик чтения или записи данных SDRAM
SDRAM_PROCESSOR:process (rst_n, sdrc_clk, RAM_IsReady, ram_old_state, ram_new_state )
variable loc_state: LOC_FSM_STATE := idle ; 

begin 
if rst_n = '0' then
	io_state <= idle;
	loc_state := idle;
elsif falling_edge(sdrc_clk) then	
	if ram_old_state /= ram_new_state then
		loc_state := init; 
		ram_old_state <= ram_new_state;		
		RAM_EXCHANGE_COMPLETE <= '0';
	end if;
	
	case loc_state is
		when idle=>
			RAM_EXCHANGE_COMPLETE <= '1';
			RAM_transmit_en <= '0';
			RAM_Bank_addr 	<= (others=>'0');
			RAM_Row_addr 	<= (others=>'0');
			RAM_Col_addr 	<= (others=>'0');
			RAM_Data_count 	<= (others=>'0');
		when init =>
			if RAM_IsReady = '1' then 
				RAM_Bank_addr <= RAM_BANK_ADDR_BIT_req ; 
				RAM_Row_addr <= RAM_ROW_ADDR_req; 
				RAM_Col_addr <= RAM_COL_ADDR_BIT_req; 
				RAM_Data_count <= RAM_32BIT_WORD_COUNT_BIT_req;
------------------------------------------------------------------------------------
                модуль может за раз записать не более 255 блоков данных по 32 байта.
                также перед записью нужно активировать каждую новую строку для записи
                тут код для проверки количества данных которые нужно записать и обрезка их по максимуму в строке.
                Все константы кратны 2 чтобы работали mod  
				if RAM_RW_BIT_req = WRITE then
					RAM_RW <= WRITE; -- WRITE : std_logic := '0'; 
					if ((RAM_WRITE_PTR mod MAX_ROW_COLS)+ to_integer(unsigned(RAM_32BIT_WORD_COUNT_BIT_req))) > MAX_ROW_COLS then
						RAM_Data_count <= std_logic_vector(to_unsigned(MAX_ROW_COLS - (RAM_WRITE_PTR mod MAX_ROW_COLS), RAM_Data_count'length));
					end if; 
				else					 
					RAM_RW <= READ; -- READ : std_logic := '1';
					if ((RAM_READ_PTR mod MAX_ROW_COLS)+ to_integer(unsigned(RAM_32BIT_WORD_COUNT_BIT_req))) > MAX_ROW_COLS then
						RAM_Data_count <= std_logic_vector(to_unsigned(MAX_ROW_COLS - (RAM_READ_PTR mod MAX_ROW_COLS), RAM_Data_count'length)); 
					end if;
				end if;		 
------------------------------------------------------------------------------------				
				RAM_transmit_en <= '1';
				io_state <= do_work;
				loc_state := processing; 

                del_rst <= '0';
                del_cnt <= std_logic_vector(to_unsigned(4, del_cnt'length));

			end if; 
		when processing=>
            del_rst <= '1'; 
			
			if ram_ack = '1' then 
				RAM_WriteData <= (others => 'Z');
				RAM_Data_count <= (others => '0');
				loc_state := idle; 
				io_state <= idle;
				RAM_transmit_en <= '0';
			end if; 			
	end case;	 
end if;
end process SDRAM_PROCESSOR;

 

 

И второй процесс который формирует команду для записи 

BUFFER_CONTROLLER_PROC:process (rst_n, sdrc_clk, RAM_EXCHANGE_COMPLETE, cam1_write_count, cam_frame_reading)
type LOC_FSM_STATE is (RESET, IDLE, START,  PROCESSING);
variable loc_state: LOC_FSM_STATE := RESET;  
begin
if rst_n = '0' then
    loc_state := RESET;
    RAM_32BIT_WORD_COUNT_BIT_req <= (others =>'0');
    RAM_BANK_ADDR_BIT_req <= (others => '0'); -- банк 
    RAM_ROW_ADDR_req <= (others =>'0');
elsif rising_edge(sdrc_clk) then 
	case loc_state is 
		when RESET =>
			RAM_32BIT_WORD_COUNT_BIT_req <= (others =>'0');
			RAM_BANK_ADDR_BIT_req <= (others => '0'); -- банк 
			RAM_ROW_ADDR_req <= (others =>'0');
            loc_state := IDLE; 
		when IDLE =>
			RAM_BUF_ID_req <= cam_index; -- индекс камеры  			
			if RAM_EXCHANGE_COMPLETE = '1' then
				-- проверка наличия данных в буфере камеры
				-- как только обработали половину массима инициируем запись или чтение RAM для освобождения половины буфера.
				-- чтение или запись должна быть выполнена пока идет обработка другой половины буфера				
				
				if cam1_write_count >= CAM_DROP_THR then
					-- половина буфера заполнена, надо скинуть в память
					loc_state := START; 	
					RAM_RW_BIT_req <= WRITE; -- читаем =1, пишем 0		
                      -----------------------------------------------------------------------------
					RAM_ROW_ADDR_req <= std_logic_vector(to_unsigned(RAM_WRITE_PTR / RAM_ROW_SIZE, RAM_ROW_ADDR_req'length));	
					RAM_COL_ADDR_BIT_req <= std_logic_vector(to_unsigned(RAM_WRITE_PTR mod RAM_ROW_SIZE, RAM_COL_ADDR_BIT_req'length));	
                    RAM_32BIT_WORD_COUNT_BIT_req <=  cam1_read_count;  --(("000" & cam1_write_count(7 downto 1)) + 10); -- делим пополам и добавляем 10
-----------------------------------------------------------------------------
				elsif cam_frame_reading = '1' then
					-- проверка наличия данных в буфере ФИФО					
					if fifo_write_count >= FIFO_DROP_CNT then
						-- половина буфера заполнена, надо скинуть в память
						loc_state := START; 
						RAM_RW_BIT_req <= READ; -- читаем =1, пишем 0	
-----------------------------------------------------------------------------                        
                        а вот тут надо нарезать строку и столбец по известному указателю. 
                        тоже деление на кратное 2 число. 
						RAM_ROW_ADDR_req <= std_logic_vector(to_unsigned(RAM_READ_PTR / RAM_ROW_SIZE, RAM_ROW_ADDR_req'length));		
						RAM_COL_ADDR_BIT_req <= std_logic_vector(to_unsigned(RAM_READ_PTR mod RAM_ROW_SIZE, RAM_COL_ADDR_BIT_req'length));
                        RAM_32BIT_WORD_COUNT_BIT_req <=  fifo_read_count(7 downto 0);   
-----------------------------------------------------------------------------
					end if;  
				end if;  
			end if;
		when START =>  
			ram_new_state <= not ram_new_state; 
			loc_state := PROCESSING; 
		when PROCESSING =>
			if ram_ack = '1' then
				loc_state := RESET;
			end if;
	end case;
end if;

end process BUFFER_CONTROLLER_PROC;

 

 

Так вот собсно вопрос. Можно ли это как то оптимизировать чтобы устранить моды и деление?? В надежде что это повысит скорость. 

осталось набрать всего 60 мегагерц до порога. ))

 

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

MAX_ROW_COLS,RAM_ROW_SIZE чему равно? Степень двойки? Если да то их можно заменить на сдвиги или операцию с маской должно быть быстрее если это компилятор не делает сам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 27.03.2024 в 13:18, MegaVolt сказал:

чему равно? Степень двойки?

Да. Все константы степень двойки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

49 минут назад, Worldmaster сказал:

Да. Все константы степень двойки.

Ну значит целочисленное деление на 2^N это сдвиг на N вправо.
Целочисленное взятие по модулю 2^N это откидывание всего что старше Nого бита.
В железе делается мгновенно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 27.03.2024 в 14:18, MegaVolt сказал:

2^N это сдвиг на N вправо.

А на vhdl есть синтезируемый блок сдвига или нужно городить что то свое?

или делать что то типа:

 

"00000000" & REG(15 downto 8)

 

Изменено пользователем Worldmaster

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, Worldmaster said:

А на vhdl есть синтезируемый блок сдвига или нужно городить что то свое?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity shift_example is
Port ( input_number : in  STD_LOGIC_VECTOR (7 downto 0);
       shift_amount : in  INTEGER;
       result_left : out  STD_LOGIC_VECTOR (7 downto 0);
       result_right : out  STD_LOGIC_VECTOR (7 downto 0));
end shift_example;

architecture Behavioral of shift_example is
begin
    -- Сдвиг влево для умножения
    result_left <= input_number sll shift_amount;
    
    -- Сдвиг вправо для деления
    result_right <= input_number srl shift_amount;
end Behavioral;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 02.04.2024 в 12:57, Maverick_ сказал:
    -- Сдвиг влево для умножения
    result_left <= input_number sll shift_amount;
    
    -- Сдвиг вправо для деления
    result_right <= input_number srl shift_amount;

Эти операторы нормально синтезируются?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 02.04.2024 в 18:08, gibson1980 сказал:

Странно, а у меня ругается на операторы

Вот и у меня тоже, но не стал писать.

Я сделал по другому:

RAM_ROW_ADDR_req <= RAM_READ_PTR(18 downto 8);	 тут отбрасываю младшую часть   это деление
RAM_COL_ADDR_BIT_req <= RAM_READ_PTR(7 downto 0);  тут отбрасываю старшую часть  а это mod

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 часов назад, gibson1980 сказал:

Странно, а у меня ругается на операторы

Может какую то из библиотек не подключили

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...