jenya7 0 28 февраля, 2017 Опубликовано 28 февраля, 2017 (изменено) · Жалоба У меня есть RAM. Есть несколько асинхронных событий которые пишут/читают RAM. Команда от контроллера. process(REG_CLK) begin if (rising_edge(REG_CLK) ) then if (REG_COM_IN(7 downto 5) = REG_CHAN) then --select spi channel case command is --command from mcu spi when X"03" => --read data command ram_addr := to_integer(unsigned(addr_bus)); REG_DATA_OUT <= ram_mem(ram_addr); when X"04" => --write data command ram_addr := to_integer(unsigned(addr_bus)); ram_mem(ram_addr) <= REG_DATA1_IN; when others => null; end case; end if; end if; end process; И пришли данные от конвертера process (REG_CLK) begin if (rising_edge(REG_CLK)) then if (rx_data_ready = '1') then ram_mem(ram_addr) <= temp_rx_mailbox(0); ram_mem(ram_addr+1) <= temp_rx_mailbox(1); ram_mem(ram_addr +2) <= temp_rx_mailbox(2); loaded_mailboxes(i) <= '1'; end if; end if; end process; Понятно дело получаем Error (10028): Can't resolve multiple constant drivers for net Решил работать с RAM в отдельном процессе ram_manager : process (REG_CLK) begin if (rising_edge(REG_CLK)) then case RamState is when ST_IDLE => if (ram_command > "000") then case ram_command is when "001" => --read from ram RamState <= ST_WR_RAM; when "010" => RamState <= ST_RD_RAM; when others => null; end case; elsif (rx_data_ready = '1') then RamState <= ST_WR_MCP25625_TO_RAM; end if; when ST_WR_RAM => ram_addr := to_integer(unsigned(addr_bus)); ram_mem(ram_addr) <= REG_DATA1_IN; when ST_RD_RAM => ram_addr := to_integer(unsigned(addr_bus)); REG_DATA_OUT <= ram_mem(ram_addr); when others => null; end case; end if; end process ram_manager; Проблема в том что ram_addr вычисляется в других процессах и очень трудно вычленить эту переменную оттуда. то есть получается ситуация - в одном месте чинишь в другом ломаешь. и потом, в последнем случае - если command >0 все время мы никогда не придем к условию if (rx_data_ready = '1')? с ram_addr я вроде разобрался - сделал его shared variable и компайлер не ругается. Но скажем есть другой процесс где я должен загружать байты из памяти и посылать when ST_TX_DATA => if (tx_byte_idx < DATA_LENGHT) then MSPI_WR_DATA <= ram_mem(ram_addr); MSPI_WR_START_TRIG <= '1'; --send a byte tx_byte_idx := tx_byte_idx + 1; ram_addr := ram_addr + 1; NextState <= ST_TX_DATA; State <= ST_WAIT_DONE; Пробовал через сигнал. в ram_manager пишу ram_manager : process (REG_CLK) begin if (rising_edge(REG_CLK)) then case RamState is -------------------------------------------------- --------------------------------------------------- when ST_WR_RAM => ram_addr := to_integer(unsigned(addr_bus)); ram_mem(ram_addr) <= REG_DATA1_IN; when ST_RD_RAM => ram_addr := to_integer(unsigned(addr_bus)); REG_DATA_OUT <= ram_mem(ram_addr); when ST_RAM_TO_MCP25625 => temp_ram_val <= ram_mem(ram_addr); when others => null; end case; end if; end process ram_manager; а в другом процессе MSPI_WR_DATA <= temp_ram_val; ругается Error (10028): Can't resolve multiple constant drivers то есть не может писать в два места REG_DATA_OUT <= ram_mem(ram_addr); и temp_ram_val <= ram_mem(ram_addr); ну я понимаю что нельзя модифицировать из двух мест - но читать Карл,читать!? Изменено 28 февраля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 28 февраля, 2017 Опубликовано 28 февраля, 2017 · Жалоба У меня есть RAM. Есть несколько асинхронных событий которые пишут/читают RAM. ... Проблема в том что ram_addr вычисляется в других процессах и очень трудно вычленить эту переменную оттуда. то есть получается ситуация - в одном месте чинишь в другом ломаешь. и потом, в последнем случае - если command >0 все время мы никогда не придем к условию if (rx_data_ready = '1')? Привести все асинхронные процессы к системному клоку, тогда все будет легко... Поиск по слову "CDC". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 февраля, 2017 Опубликовано 28 февраля, 2017 (изменено) · Жалоба 1. Я бы не применял конструкцию типа case ram_command is when "001" => --read from ram RamState <= ST_WR_RAM; when "010" => RamState <= ST_RD_RAM; when others => null; end case; Поскольку код становиться нечитаемым. Я бы команды определил как константы: CONSTANT WRITE : STD_LOGIC_VECTOR(2 DOWNTO 0) := "010"; CONSTANT READ : STD_LOGIC_VECTOR(2 DOWNTO 0) := "001"; И в процессе работал с нормальными именами. Это Вы сейчас помните код. А что будет через неделю, месяц, год ? case ram_command is when READ => --read from ram RamState <= ST_WR_RAM; when WRITE => RamState <= ST_RD_RAM; when others => null; end case; 2. А почему нельзя записать так ? when ST_WR_RAM => ram_mem( to_integer(unsigned(addr_bus))) <= REG_DATA1_IN; when ST_RD_RAM => REG_DATA_OUT <= ram_mem( to_integer(unsigned(addr_bus))); 3. последнем случае - если command >0 все время мы никогда не придем к условию if (rx_data_ready = '1')? Так вы уже сами назначаете приоритет, к примеру: RAM_MANAGER : PROCESS ( REG_CLK ) BEGIN IF (RISING_EDGE(REG_CLK)) THEN CASE RAMSTATE IS WHEN ST_IDLE => IF (RX_DATA_READY = '1') THEN RAMSTATE <= ST_WR_MCP25625_TO_RAM; ELSE CASE RAM_COMMAND IS WHEN WRITE => RAMSTATE <= ST_WR_RAM; WHEN READ => RAMSTATE <= ST_RD_RAM; WHEN OTHERS => NULL; END CASE; END IF; WHEN T_WR_RAM => RAM_MEM(TO_INTEGER(UNSIGNED(ADDR_BUS))) <= REG_DATA1_IN; WHEN ST_RD_RAM => REG_DATA_OUT <= RAM_MEM(TO_INTEGER(UNSIGNED(ADDR_BUS))); WHEN OTHERS => NULL; END CASE; END IF; END PROCESS RAM_MANAGER; Хотя автоматы лучше писать в 2 или 3 процессах, а не мешать всё в кучу. Изменено 28 февраля, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 14 28 февраля, 2017 Опубликовано 28 февраля, 2017 · Жалоба ну я понимаю что нельзя модифицировать из двух мест - но читать Карл,читать!?А какая разница, что делать? Чудес не бывает. У памяти адресный порт один? Один. Если к нему нужен доступ из разных мест, значит, нужен некий арбитр. В простейшем случае мультиплексор. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 28 февраля, 2017 Опубликовано 28 февраля, 2017 (изменено) · Жалоба Хотя автоматы лучше писать в 2 или 3 процессах, а не мешать всё в кучу. я понял. про константы думал, как то руки не дошли. если писать в разных процессах возникает проблема Can't resolve multiple constant drivers. я пока сделал так в одном процессе MSPI_WR_DATA <= temp_ram_val; temp_ram_addr := temp_ram_addr + 1; в другом when ST_RAM_TO_MCP25625 => temp_ram_val <= ram_mem(temp_ram_addr); не возникнет ли тут race condition? кто раньше обновиться? А какая разница, что делать? Чудес не бывает. У памяти адресный порт один? Один. Если к нему нужен доступ из разных мест, значит, нужен некий арбитр. В простейшем случае мультиплексор. к памяти доступ из нескольких источников, пишем, читаем, побайтово или последовательно, разные режимы. нужен конечно очень умный арбитратор. Изменено 28 февраля, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 февраля, 2017 Опубликовано 28 февраля, 2017 · Жалоба Если в разных процессах одному сигналу назначается несколько драйверов, то САПР ругнется, что собственно у Вас он и делает. А можно озвучить Вашу задачу полностью ? А то сейчас гадаем гадаем, как Вам на Марс полететь. А Вам всего-то нужно в соседний дом.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 28 февраля, 2017 Опубликовано 28 февраля, 2017 · Жалоба Если в разных процессах одному сигналу назначается несколько драйверов, то САПР ругнется, что собственно у Вас он и делает. А можно озвучить Вашу задачу полностью ? А то сейчас гадаем гадаем, как Вам на Марс полететь. А Вам всего-то нужно в соседний дом.... я нарисовал задачу. загвоздка в модуле REG_FILE. он принимает данные от MCP25625 и кладет в RAM и посылает данные из RAM в MCP25625. с другой стороны MCU пишет/читает в RAM. я вообще думаю а может сделать несколько RAM. каждый процесс будет работать со своим куском памяти. а при адресации от MCU адрес будет пересчитываться под свой кусок памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться