Worldmaster 0 2 августа Опубликовано 2 августа · Жалоба Здравствуйте. Вот сделал модуль для работы с оперативой. Он нормально работает но может быть кто то подскажет как тут можно что нибудь оптимизировать чтобы максимально поднять скорость работы? library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; use IEEE.numeric_std.all; entity SDRAM_SERIALIZER is port ( rst_n : in std_logic; isdram_clk : in std_logic; isdrc_clk : in std_logic; RAM_InitComplete: out std_logic; cam1_data_ready: in std_logic; cam1_write_clk: in std_logic; cam1_WriteData: in std_logic_vector(15 downto 0); cam2_data_ready: in std_logic; cam2_write_clk: in std_logic; cam2_WriteData: in std_logic_vector(15 downto 0); Buf_Read_Request: in std_logic; -- флаг сообщает что необходимо начать считывание данных из оперативы Buf_Read_Valid: out std_logic; -- флаг валидности данных Buf_ReadData: out std_logic_vector(31 downto 0); -- данные для передачи в выходной буфер FIFO_AlmostFull: in std_logic; -- показывает что приемный буфер почти пуст чтобы модуль оперативы начал заполнение FIFO_AlmostEmpty: in std_logic; -- почти пустой буфер имеет приоритет при отправке max_frame_size: in std_logic_vector(16 downto 0); -- максимальное количество для считывания и записи с нуля из оперативы. Запись и считывание происходит циклично reset_read_ptr: in std_logic; -- сигнал для сброса указателя считывания Busy: out std_logic; all_data_read_complete: out std_logic; IO_sdram_dq: inout std_logic_vector(31 downto 0); O_sdram_clk: out std_logic; O_sdram_cke: out std_logic; O_sdram_cs_n: out std_logic; O_sdram_cas_n: out std_logic; O_sdram_ras_n: out std_logic; O_sdram_wen_n: out std_logic; O_sdram_dqm: out std_logic_vector(3 downto 0); O_sdram_addr: out std_logic_vector(10 downto 0); O_sdram_ba: out std_logic_vector(1 downto 0) ); end SDRAM_SERIALIZER; architecture logic of SDRAM_SERIALIZER is constant WRITE: std_logic := '0'; constant READ: std_logic := '1'; -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- --signal Ack: std_logic; -- подтверждение операции signal IsDataReady: std_logic; -- флаг готовности данных signal IsReady: std_logic; -- флаг готовности модуля signal ReadData: std_logic_vector(31 downto 0):= (others => 'Z'); -- данные для чтения signal WriteData: std_logic_vector(31 downto 0); -- данные для записи -- для модуля работы с сдрам signal RAM_transmit_en : std_logic:='0'; -- флаг начала передачи signal RAM_RW: std_logic:='0'; -- чтение или запись signal RAM_Data_count: std_logic_vector(7 downto 0) := (others => 'Z'); -- количество данных для чтения или записи signal RAM_Bank_addr: std_logic_vector(1 downto 0) := (others => 'Z'); signal RAM_Row_addr: std_logic_vector(10 downto 0) := (others => 'Z'); signal RAM_Col_addr: std_logic_vector(7 downto 0) := (others => 'Z'); signal RAM_IsDataReady: std_logic:='0'; -- флаг готовности данных signal RAM_IsReady: std_logic; -- флаг готовности модуля signal RAM_ReadData: std_logic_vector(31 downto 0); -- данные для чтения signal RAM_WriteData: std_logic_vector(31 downto 0); -- данные для записи signal RAM_Ack: std_logic:='0'; signal RAM_EXCHANGE_COMPLETE: std_logic:= '0'; -- флаг показывает что транзакция взаимодействия с оперативой завершена signal all_data_read_complete_s: std_logic := '0'; -- пропишем просто сигналы для запроса а не массив signal RAM_ROW_ADDR_req: std_logic_vector(10 downto 0) := (others => '0'); signal RAM_COL_ADDR_BIT_req: std_logic_vector(7 downto 0) := (others => '0'); signal RAM_RW_BIT_req: std_logic:='0'; signal RAM_32BIT_WORD_COUNT_BIT_req: std_logic_vector(7 downto 0) := (others => 'Z'); signal ram_start_processing: std_logic:='0'; -- при исполнении пакета фиксируем old_state signal fifo_rst_i: std_logic:='0'; signal cam1_rst_i: std_logic:='0'; signal cam1_ReadData : std_logic_vector(31 downto 0):=(others=>'0'); signal cam1_read_count : std_logic_vector(9 downto 0):=(others=>'0'); signal cam1_write_count : std_logic_vector(10 downto 0):=(others=>'0'); signal cam1_almost_empty : std_logic:='0'; signal cam1_almost_empty_160 : std_logic:='0'; signal cam2_rst_i: std_logic:='0'; signal cam2_in_clk_read_i: std_logic:='0'; signal cam2_in_clk_write_i: std_logic:='0'; signal cam2_ReadData : std_logic_vector(31 downto 0):=(others=>'0'); signal cam2_read_count : std_logic_vector(9 downto 0):=(others=>'0'); signal cam2_write_count : std_logic_vector(10 downto 0):=(others=>'0'); signal cam2_almost_empty : std_logic:='0'; signal RAM_READ_PTR: integer := 0; signal RAM_WRITE_PTR: integer := 0; signal MAX_FRAME_LEN: integer := 78400; -- максимальный размер кадра в памяти 560*560 в блоках по 32 signal cam1_read_en : std_logic := '0'; signal cam2_read_en : std_logic := '0'; signal cam_index: std_logic:= '0'; type BUF_CTRL_PROC_LOC_FSM_STATE is (RESET, IDLE, START,START_READ, START_WRITE, PROCESSING); signal BUF_CTRL_PROC_loc_state: BUF_CTRL_PROC_LOC_FSM_STATE := RESET; type SDRAM_PROC_LOC_FSM_STATE is (Init, Idle, pre_proc, Processing); signal SDRAM_PROC_loc_state: SDRAM_PROC_LOC_FSM_STATE := idle; signal SDRAM_IO_word_cntr: integer := 0; signal reset_write_ptr: std_logic := '0'; signal forceRead: std_logic:='0'; signal bus_clear: std_logic:='0'; signal SDRAMInitDone: std_logic := '0'; signal Total_data_count: integer := 0; signal do_work: std_logic := '0'; signal lock_read: std_logic := '0'; signal cam1buf_empty: std_logic := '0'; signal cam1buf_full: std_logic := '0'; signal cam2buf_empty: std_logic := '0'; signal cam2buf_full: std_logic := '0'; signal can_read : std_logic := '0'; signal can_write : std_logic := '0'; component cam_hs port ( Data: in std_logic_vector(15 downto 0); Reset: in std_logic; WrClk: in std_logic; RdClk: in std_logic; WrEn: in std_logic; RdEn: in std_logic; Wnum: out std_logic_vector(10 downto 0); Rnum: out std_logic_vector(9 downto 0); Almost_Empty: out std_logic; Q: out std_logic_vector(31 downto 0); Empty: out std_logic; Full: out std_logic ); end component; component SDRAM_MODULE port ( rst_n : in std_logic:= '0'; sdram_clk : in std_logic:= '0'; sdrc_clk : in std_logic:= '0'; IO_sdram_dq: inout std_logic_vector(31 downto 0):=(others=>'0'); O_sdram_clk: out std_logic:= '0'; O_sdram_cke: out std_logic:= '0'; O_sdram_cs_n: out std_logic:= '0'; O_sdram_cas_n: out std_logic:= '0'; O_sdram_ras_n: out std_logic:= '0'; O_sdram_wen_n: out std_logic:= '0'; O_sdram_dqm: out std_logic_vector(3 downto 0):=(others=>'0'); O_sdram_addr: out std_logic_vector(10 downto 0):=(others=>'0'); O_sdram_ba: out std_logic_vector(1 downto 0):=(others=>'0'); transmit_en : in std_logic:= '0'; -- флаг начала передачи RW: in std_logic:= '0'; -- чтение или запись Data_count: in std_logic_vector(7 downto 0):=(others=>'0'); -- количество данных для чтения или записи Bank_addr: in std_logic_vector(1 downto 0) :=(others=>'0'); Row_addr: in std_logic_vector(10 downto 0):=(others=>'0'); Col_addr: in std_logic_vector(7 downto 0) :=(others=>'0'); IsDataReady: out std_logic:= '0'; -- флаг готовности данных IsReady: out std_logic:= '0'; -- флаг готовности модуля InitDone: out std_logic:= '0'; ReadData: out std_logic_vector(31 downto 0):=(others=>'0'); -- данные для чтения WriteData: in std_logic_vector(31 downto 0):=(others=>'0'); -- данные для записи Ack: out std_logic:= '0' ); end component; component CDC is port ( I_clk_dest : in std_logic; signal_in : in std_logic; signal_out : out std_logic ); end component; begin -------------------------------------------------------------------------------------------- cam1buf: cam_hs port map ( Data => cam1_WriteData, Reset => cam1_rst_i, WrClk => cam1_write_clk, RdClk => isdrc_clk, WrEn => cam1_data_ready, RdEn => cam1_read_en, Wnum => cam1_write_count, Rnum => cam1_read_count, Almost_Empty => cam1_almost_empty, Q => cam1_ReadData, Empty => cam1buf_empty, Full => cam1buf_full ); -------------------------------------------------------------------------------------------- cam2buf: cam_hs port map ( Data => cam2_WriteData, Reset => cam2_rst_i, WrClk => cam2_write_clk, RdClk => isdrc_clk, WrEn => cam2_data_ready, RdEn => cam2_read_en, Wnum => cam2_write_count, Rnum => cam2_read_count, Almost_Empty => cam2_almost_empty, Q => cam2_ReadData, Empty => cam2buf_empty, Full => cam2buf_full ); -------------------------------------------------------------------------------------------- MySDRAM: SDRAM_MODULE port map ( rst_n => rst_n, sdram_clk => isdram_clk, sdrc_clk => isdrc_clk, IO_sdram_dq => IO_sdram_dq, O_sdram_clk => O_sdram_clk, O_sdram_cke => O_sdram_cke, O_sdram_cs_n => O_sdram_cs_n, O_sdram_cas_n => O_sdram_cas_n, O_sdram_ras_n => O_sdram_ras_n, O_sdram_wen_n => O_sdram_wen_n, O_sdram_dqm => O_sdram_dqm, O_sdram_addr => O_sdram_addr, O_sdram_ba => O_sdram_ba, transmit_en => RAM_transmit_en, RW => RAM_RW, Data_count => RAM_Data_count, Bank_addr => RAM_Bank_addr, Row_addr => RAM_Row_addr, Col_addr => RAM_Col_addr, IsDataReady => RAM_IsDataReady, IsReady => RAM_IsReady, ReadData => RAM_ReadData, WriteData => RAM_WriteData, InitDone => SDRAMInitDone, Ack => RAM_Ack ); cam1_almost_empty_cdc: CDC port map( I_clk_dest => isdrc_clk, signal_in => cam1_almost_empty, signal_out => cam1_almost_empty_160 ); -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- RAM_InitComplete <= SDRAMInitDone; Busy <= '0' when BUF_CTRL_PROC_loc_state = IDLE else '1'; -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- cam1_rst_i <= not rst_n; cam2_rst_i <= not rst_n; fifo_rst_i <= not rst_n; all_data_read_complete <= all_data_read_complete_s; Buf_ReadData <= RAM_ReadData; Buf_Read_Valid <= '1' when RAM_IsDataReady = '1' and RAM_RW_BIT_req = READ else '0'; cmp_proc: process(rst_n, isdrc_clk,ram_ack,MAX_FRAME_LEN,RAM_READ_PTR) variable new_val: integer; begin if rst_n = '0' then all_data_read_complete_s <= '0'; elsif rising_edge(isdrc_clk) then if ram_ack = '1' then -- обновляем только когда модуль закончил чтение new_val := to_integer(unsigned(max_frame_size)); if new_val /= MAX_FRAME_LEN then reset_write_ptr <= '1'; else reset_write_ptr <= '0'; end if; if RAM_READ_PTR >= MAX_FRAME_LEN then all_data_read_complete_s <= '1'; else all_data_read_complete_s <= '0'; end if; MAX_FRAME_LEN <= new_val; end if; end if; end process cmp_proc; -- процесс длясчетчика указателей в оперативе для чтения или записи данных SDRAM_IO: process(rst_n, isdrc_clk,reset_read_ptr,reset_write_ptr, do_work, RAM_IsDataReady,SDRAM_IO_word_cntr, RAM_RW_BIT_req, cam_index, RAM_WRITE_PTR, RAM_READ_PTR, MAX_FRAME_LEN, Total_data_count) variable allow_work: std_logic := '0'; begin if rst_n = '0' then RAM_WRITE_PTR <= 0; RAM_READ_PTR <= 0; elsif rising_edge(isdrc_clk) then if reset_read_ptr = '1' then RAM_READ_PTR <= 0; end if; if reset_write_ptr = '1' then RAM_WRITE_PTR <= 0; end if; lock_read <= '0'; if do_work = '1' then if SDRAM_IO_word_cntr <= Total_data_count - 1 then allow_work := '1'; else allow_work := '0'; end if; if SDRAM_IO_word_cntr < Total_data_count - 1 then lock_read <= '0'; else lock_read <= '1'; end if; if allow_work = '1' then if RAM_IsDataReady = '1' then if RAM_RW_BIT_req = WRITE then if RAM_WRITE_PTR >= MAX_FRAME_LEN - 1 then RAM_WRITE_PTR <= 0; else RAM_WRITE_PTR <= RAM_WRITE_PTR + 1; end if; else if RAM_READ_PTR <= MAX_FRAME_LEN - 1 then RAM_READ_PTR <= RAM_READ_PTR + 1; end if; end if; SDRAM_IO_word_cntr <= SDRAM_IO_word_cntr + 1; end if; end if; else SDRAM_IO_word_cntr <= 0; end if; end if; end process SDRAM_IO; -- определяен какую камеру подключать в момент. пока работа только с одной камерой process(RAM_IsDataReady, RAM_RW_BIT_req, cam_index, cam1_ReadData, cam2_ReadData) begin RAM_WriteData <= (others => '0'); if RAM_IsDataReady = '1' and RAM_RW_BIT_req = WRITE then if cam_index = '0' then RAM_WriteData <= cam1_ReadData; cam1_read_en <= '1'; cam2_read_en <= '0'; else cam2_read_en <= '1'; cam1_read_en <= '0'; RAM_WriteData <= cam2_ReadData; end if; else cam1_read_en <= '0'; cam2_read_en <= '0'; end if; end process; -- обработчик чтения или записи данных SDRAM SDRAM_PROC:process (rst_n, isdrc_clk, SDRAM_PROC_loc_state, RAM_IsReady, ram_start_processing, ram_ack) begin if rst_n = '0' then SDRAM_PROC_loc_state <= idle; RAM_Bank_addr <= (others=>'0'); RAM_Row_addr <= (others=>'0'); RAM_Col_addr <= (others=>'0'); RAM_Data_count <= (others=>'0'); elsif rising_edge(isdrc_clk) then RAM_Bank_addr <= (others=>'0'); case SDRAM_PROC_loc_state is when idle=> if ram_start_processing = '1' then SDRAM_PROC_loc_state <= init; RAM_EXCHANGE_COMPLETE <= '0'; else RAM_EXCHANGE_COMPLETE <= '1'; RAM_transmit_en <= '0'; RAM_Row_addr <= (others=>'0'); RAM_Col_addr <= (others=>'0'); RAM_Data_count <= (others=>'0'); end if; when init => -- инициирование параметров транзакции if RAM_IsReady = '1' then RAM_Row_addr <= RAM_ROW_ADDR_req; RAM_Col_addr <= RAM_COL_ADDR_BIT_req; RAM_Data_count <= RAM_32BIT_WORD_COUNT_BIT_req; -- задаем значение для контроллера, отправляется + 1 Total_data_count <= to_integer(unsigned(RAM_32BIT_WORD_COUNT_BIT_req)) + 1; RAM_RW <= RAM_RW_BIT_req; RAM_transmit_en <= '1'; SDRAM_PROC_loc_state <= pre_proc; end if; when pre_proc => do_work <= '1'; SDRAM_PROC_loc_state <= processing; when processing=> if ram_ack = '1' then SDRAM_PROC_loc_state <= idle; do_work <= '0'; RAM_transmit_en <= '0'; end if; end case; end if; end process SDRAM_PROC; bus_clear <= '1' when Buf_Read_Request = '1' and all_data_read_complete_s = '0' else '0'; -- объединяет сигналы в одно чтобы использовать дальше forceRead <= '1' when bus_clear = '1' and FIFO_AlmostEmpty = '1' else '0'; -- если буфер почти пустой то читаем более агресивно игнорируя размер в буфере камеры. Размер буфера выбран больше. can_read <= '1' when bus_clear = '1' and FIFO_AlmostFull = '0' else '0'; -- показывает что можно начать считывать can_write <= '1' when cam1_almost_empty_160 = '0' and forceRead = '0' else '0'; -- можно начать запись BUF_CTRL_PROC:process (rst_n, isdrc_clk, RAM_EXCHANGE_COMPLETE, can_write, ram_ack, BUF_CTRL_PROC_loc_state, can_read) variable rptr: std_logic_vector(18 downto 0):= (others => '0'); variable wptr: std_logic_vector(18 downto 0):= (others => '0'); variable count: integer := 0; variable ellapsed_count: integer := 0; begin if rst_n = '0' then BUF_CTRL_PROC_loc_state <= RESET; elsif rising_edge(isdrc_clk) then case BUF_CTRL_PROC_loc_state is when RESET => BUF_CTRL_PROC_loc_state <= IDLE; ram_start_processing <= '0'; RAM_RW_BIT_req <= '0'; RAM_ROW_ADDR_req <= (others=>'0'); RAM_COL_ADDR_BIT_req <= (others=>'0'); RAM_32BIT_WORD_COUNT_BIT_req <= (others=>'0'); when IDLE => -- если есть возможность то начинаем выполнять запись или чтение if RAM_EXCHANGE_COMPLETE = '1' then if can_write = '1' then BUF_CTRL_PROC_loc_state <= START_WRITE; elsif can_read = '1' then BUF_CTRL_PROC_loc_state <= START_READ; end if; end if; when START_READ => -- начинаем процесс чтения из оперативы в выходной буфер rptr:= std_logic_vector(to_unsigned(RAM_READ_PTR, 19)); BUF_CTRL_PROC_loc_state <= START; RAM_RW_BIT_req <= READ; -- читаем =1, пишем 0 RAM_ROW_ADDR_req <= rptr(18 downto 8); RAM_COL_ADDR_BIT_req <= rptr(7 downto 0); ellapsed_count := MAX_FRAME_LEN - RAM_READ_PTR; -- контроль остатков для чтения если запрашивается не кратное количество if ellapsed_count >= 256 then count := 255; else count := ellapsed_count - 1; end if; RAM_32BIT_WORD_COUNT_BIT_req <= std_logic_vector(to_unsigned(count, RAM_32BIT_WORD_COUNT_BIT_req'length)); -- 256 за раз всю строку when START_WRITE => -- начинаем процесс записи в оперативу wptr:= std_logic_vector(to_unsigned(RAM_WRITE_PTR, 19)); -- половина буфера заполнена, надо скинуть в память BUF_CTRL_PROC_loc_state <= START; RAM_RW_BIT_req <= WRITE; -- читаем =1, пишем 0 RAM_ROW_ADDR_req <= wptr(18 downto 8); RAM_COL_ADDR_BIT_req <= wptr(7 downto 0); ellapsed_count := MAX_FRAME_LEN - RAM_WRITE_PTR; -- контроль остатков для чтения если запрашивается не кратное количество if ellapsed_count >= 128 then count := 127; else count := ellapsed_count-1; end if; RAM_32BIT_WORD_COUNT_BIT_req <= std_logic_vector(to_unsigned(count, RAM_32BIT_WORD_COUNT_BIT_req'length)); when START => -- ждем пока модуль закончит транзакцию ram_start_processing <= '1'; if ram_ack = '0' then BUF_CTRL_PROC_loc_state <= PROCESSING; end if; when PROCESSING => -- ждем пока головной процесс отключит чтобы не читалось повторно ram_start_processing <= '0'; if ram_ack = '1' then BUF_CTRL_PROC_loc_state <= RESET; end if; end case; end if; end process BUF_CTRL_PROC; end architecture; Сейчас у меня максимально дает вот такие параметры: Но почему то кажется что можно еще лучше. Буду признателен за объективную критику. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться