реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Доступ к ресурсу из разных процессов.
Jenya7
сообщение Feb 28 2017, 08:48
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 062
Регистрация: 29-03-12
Пользователь №: 71 075



У меня есть 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);
ну я понимаю что нельзя модифицировать из двух мест - но читать Карл,читать!?

Сообщение отредактировал Jenya7 - Feb 28 2017, 09:52
Go to the top of the page
 
+Quote Post
iosifk
сообщение Feb 28 2017, 08:51
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 3 457
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369



Цитата(Jenya7 @ Feb 28 2017, 11:48) *
У меня есть RAM. Есть несколько асинхронных событий которые пишут/читают RAM.
...
Проблема в том что ram_addr вычисляется в других процессах и очень трудно вычленить эту переменную оттуда. то есть получается ситуация - в одном месте чинишь в другом ломаешь.
и потом, в последнем случае - если command >0 все время мы никогда не придем к условию if (rx_data_ready = '1')?

Привести все асинхронные процессы к системному клоку, тогда все будет легко...
Поиск по слову "CDC".


--------------------
www.iosifk.narod.ru
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Feb 28 2017, 10:07
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 181
Регистрация: 11-06-13
Пользователь №: 77 140



Цитата(Jenya7 @ Feb 28 2017, 11:48) *

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 процессах, а не мешать всё в кучу.

Сообщение отредактировал Flip-fl0p - Feb 28 2017, 10:21
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Feb 28 2017, 10:12
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 724
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Jenya7 @ Feb 28 2017, 11:48) *
ну я понимаю что нельзя модифицировать из двух мест - но читать Карл,читать!?
А какая разница, что делать? Чудес не бывает. У памяти адресный порт один? Один. Если к нему нужен доступ из разных мест, значит, нужен некий арбитр. В простейшем случае мультиплексор.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 28 2017, 10:32
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 062
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Flip-fl0p @ Feb 28 2017, 16:07) *
Хотя автоматы лучше писать в 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? кто раньше обновиться?


Цитата(andrew_b @ Feb 28 2017, 16:12) *
А какая разница, что делать? Чудес не бывает. У памяти адресный порт один? Один. Если к нему нужен доступ из разных мест, значит, нужен некий арбитр. В простейшем случае мультиплексор.

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

Сообщение отредактировал Jenya7 - Feb 28 2017, 10:35
Go to the top of the page
 
+Quote Post
Flip-fl0p
сообщение Feb 28 2017, 10:46
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 181
Регистрация: 11-06-13
Пользователь №: 77 140



Цитата(Jenya7 @ Feb 28 2017, 13:32) *

Если в разных процессах одному сигналу назначается несколько драйверов, то САПР ругнется, что собственно у Вас он и делает. А можно озвучить Вашу задачу полностью ? А то сейчас гадаем гадаем, как Вам на Марс полететь. А Вам всего-то нужно в соседний дом....
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Feb 28 2017, 10:58
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 062
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(Flip-fl0p @ Feb 28 2017, 16:46) *
Если в разных процессах одному сигналу назначается несколько драйверов, то САПР ругнется, что собственно у Вас он и делает. А можно озвучить Вашу задачу полностью ? А то сейчас гадаем гадаем, как Вам на Марс полететь. А Вам всего-то нужно в соседний дом....

я нарисовал задачу. загвоздка в модуле REG_FILE. он принимает данные от MCP25625 и кладет в RAM и посылает данные из RAM в MCP25625. с другой стороны MCU пишет/читает в RAM.
я вообще думаю а может сделать несколько RAM. каждый процесс будет работать со своим куском памяти. а при адресации от MCU адрес будет пересчитываться под свой кусок памяти.

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th March 2017 - 00:51
Рейтинг@Mail.ru


Страница сгенерированна за 0.01438 секунд с 7
ELECTRONIX ©2004-2016