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

Доступ к ресурсу из разных процессов.

У меня есть 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

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


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

У меня есть RAM. Есть несколько асинхронных событий которые пишут/читают RAM.

...

Проблема в том что ram_addr вычисляется в других процессах и очень трудно вычленить эту переменную оттуда. то есть получается ситуация - в одном месте чинишь в другом ломаешь.

и потом, в последнем случае - если command >0 все время мы никогда не придем к условию if (rx_data_ready = '1')?

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

Поиск по слову "CDC".

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


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

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

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


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

ну я понимаю что нельзя модифицировать из двух мест - но читать Карл,читать!?
А какая разница, что делать? Чудес не бывает. У памяти адресный порт один? Один. Если к нему нужен доступ из разных мест, значит, нужен некий арбитр. В простейшем случае мультиплексор.

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


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

Хотя автоматы лучше писать в 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? кто раньше обновиться?

 

 

А какая разница, что делать? Чудес не бывает. У памяти адресный порт один? Один. Если к нему нужен доступ из разных мест, значит, нужен некий арбитр. В простейшем случае мультиплексор.

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

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

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


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

Если в разных процессах одному сигналу назначается несколько драйверов, то САПР ругнется, что собственно у Вас он и делает. А можно озвучить Вашу задачу полностью ? А то сейчас гадаем гадаем, как Вам на Марс полететь. А Вам всего-то нужно в соседний дом....

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


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

Если в разных процессах одному сигналу назначается несколько драйверов, то САПР ругнется, что собственно у Вас он и делает. А можно озвучить Вашу задачу полностью ? А то сейчас гадаем гадаем, как Вам на Марс полететь. А Вам всего-то нужно в соседний дом....

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

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

post-71075-1488279454_thumb.png

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


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

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

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

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

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

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

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

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

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

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