jenya7 0 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба В одном процессе я принимаю команды when X"01" => --continious data read cont_ram_addr := to_integer(unsigned(addr_bus)); ram_command <= RAM_CONT_WRITE; when X"02" => --continious data write cont_ram_addr := to_integer(unsigned(addr_bus)); ram_command <= RAM_CONT_READ; when X"03" => --read data command ram_command <= RAM_BYTE_WRITE; when X"04" => --write data command ram_command <= RAM_BYTE_READ; В другом я проверяю команду и в соответсвии команде делаю какое то действие. case RamState is when ST_IDLE => if(ram_command > "000") then case ram_command is when RAM_CONT_WRITE => RamState <= ST_CONT_WR_RAM; when RAM_CONT_READ => RamState <= ST_CONT_RD_RAM; when RAM_BYTE_WRITE => RamState <= ST_WR_RAM; when RAM_BYTE_READ => RamState <= ST_RD_RAM; when others => RamState <= ST_IDLE; end case; end if; when ST_WR_RAM => - --do something RamState <= ST_IDLE; when ST_RD_RAM => --do something RamState <= ST_IDLE; when ST_CONT_WR_RAM => -do something RamState <= ST_IDLE; when ST_CONT_RD_RAM => -- do something RamState <= ST_IDLE; Но когда мне обнулить ram_command? Иначе я вернусь в ST_IDLE и снова case ram_command и так буду крутиться в бесконечном цикле. Логично было бы обнулить ram_command во втором процессе но тогда я получу Error (10028): Can't resolve multiple constant drivers for net Получается нет синхронизации между процессами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба Логично было бы обнулить ram_command во втором процессе но тогда я получуОпять те же грабли? Запомните раз и навсегда первое: вы не программу пишете, а "рисуете" схему словами. Запомните раз и навсегда второе: сигнал в схеме -- это не переменная в программе, вы не можете изменять один сигнал из двух независимых источников. Это всё равно что физически соединить выходы двух устройств. Получается нет синхронизации между процессами.Вы разработчик, вы и сделайте так, чтобы она была. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 1 марта, 2017 Опубликовано 1 марта, 2017 (изменено) · Жалоба Опять те же грабли? Запомните раз и навсегда первое: вы не программу пишете, а "рисуете" схему словами. Запомните раз и навсегда второе: сигнал в схеме -- это не переменная в программе, вы не можете изменять один сигнал из двух независимых источников. Это всё равно что физически соединить выходы двух устройств. это я таки понял. Вы разработчик, вы и сделайте так, чтобы она была. опыта в VHDL не хватает. иначе спрашивал я бы на форуме? Изменено 1 марта, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wolfman 0 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба А что мешает обнулять ram_command в первом процессе? И что мешает принимать ram_command и совершать действия по ней в одном процессе? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
semperante 0 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба Ну, вы можете: - автоматически обнулить ram_command после одного или нескольких тактов; - сделать так, чтобы вторая часть выдавала сигнал завершения по-которому ram_command будет сбрасываться; - в конце концов, объединить обе части в один процесс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба опыта в VHDL не хватает.А чо сразу VHDL? Это лишь средство реализации алгоритма. У вас до конца не продуман именно алгоритм работы. Вы не кидайтесь сразу код писать, а распишите детально алгоритм. На листочке, что ли. Диаграммы сигналов нарисуйте потактово. Вот когда всё сойдётся, тогда и код будет проще писать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 1 марта, 2017 Опубликовано 1 марта, 2017 (изменено) · Жалоба А что мешает обнулять ram_command в первом процессе? И что мешает принимать ram_command и совершать действия по ней в одном процессе? Ну, вы можете: - автоматически обнулить ram_command после одного или нескольких тактов; - сделать так, чтобы вторая часть выдавала сигнал завершения по-которому ram_command будет сбрасываться; - в конце концов, объединить обе части в один процесс. в одном и том же процессе... дело в том что я получаю разные комманды - для работы с RAM, для работы с мср25625, и так далее. вот я и подумал выделить отдельные процессы – для RAM для с мср25625 и так далее - так разные таски могут работать параллельно. если я засуну все в один процесс -пришла следующая команда а я еще обрабатываю предыдущую. а так - пришла команда для RAM - выставил ram_command, пришла команда для mcp25625 – выставил mcp25625_command и оба таска выполняют свои задачи паралельно. автоматически обнулить ram_command после одного или нескольких тактов spi_slave_interface : process(REG_CLK, REG_RSTn, SPI_DATA_LATCH) begin if(REG_RSTn = '0') then --REG_DATA_OUT <= (others => '0'); --State <= ST_IDLE; --command <= "000"; --MSPI_CS <= '1'; elsif (rising_edge(REG_CLK) and SPI_DATA_LATCH = '1') then --REG_DATA_LATCH to be sure command, address, data was received from spi slave if (REG_COM_IN(7 downto 5) = REG_CHAN) then --select spi channel case REG_COM_IN(4 downto 0) is --command from mcu spi when "00001" => --continious data read cont_ram_addr := to_integer(unsigned(addr_bus)); ram_command <= RAM_CONT_WRITE; when "00010" => --continious data write cont_ram_addr := to_integer(unsigned(addr_bus)); ram_command <= RAM_CONT_READ; when "00011" => --read data command ram_command <= RAM_BYTE_WRITE; when "00100" => --write data command ram_command <= RAM_BYTE_READ; end case; ram_command <= "000"; end if; end if; end process spi_slave_interface; вопрос сколько тактов пройдет между установкой и обнулением. и сколько тактов нужно второму процессу чтоб "захватить" сигнал. Изменено 1 марта, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба вам надо бы разобраться с типовыми "кусками", применяемыми в ПЛИС для решения тех или иных задач. когда применять очереди (FIFO), арбитры, планировщики (scheduler), рекомендую к прочтению: 10_lec08.pdf в вашем случае, поскольку обработчик команд в момент прихода новой команды может быть занят - логичным решением может стать FIFO команд. т.е. новые команды поступают в FIFO, и обработчик, по мере своих возможностей забирает из него команды для обработки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 1 марта, 2017 Опубликовано 1 марта, 2017 (изменено) · Жалоба Так а почему нельзя написать так: when "00011" => --read data command ram_command <= RAM_BYTE_WRITE; when "00100" => --write data command ram_command <= RAM_BYTE_READ; WHEN OTHERS => ram_command <= NOPE; end case; Где NOPE это и есть "000". Весь процесс я бы вот так написал SPI_SLAVE_INTERFACE : PROCESS ( REG_CLK ) BEGIN IF (RISING_EDGE(REG_CLK)) THEN IF (SPI_DATA_LATCH = '1') THEN --REG_DATA_LATCH TO BE SURE COMMAND, ADDRESS, DATA WAS RECEIVED FROM SPI SLAVE IF (REG_COM_IN(7 DOWNTO 5) = REG_CHAN) THEN --SELECT SPI CHANNEL CASE REG_COM_IN(4 DOWNTO 0) IS --COMMAND FROM MCU SPI WHEN "00001" => --CONTINIOUS DATA READ CONT_RAM_ADDR <= TO_INTEGER(UNSIGNED(ADDR_BUS)); RAM_COMMAND <= RAM_CONT_WRITE; WHEN "00010" => --CONTINIOUS DATA WRITE CONT_RAM_ADDR <= TO_INTEGER(UNSIGNED(ADDR_BUS)); RAM_COMMAND <= RAM_CONT_READ; WHEN "00011" => --READ DATA COMMAND RAM_COMMAND <= RAM_BYTE_WRITE; WHEN "00100" => --WRITE DATA COMMAND RAM_COMMAND <= RAM_BYTE_READ; WHEN OTHERS => RAM_COMMAND <= NOPE; END CASE; END IF; END IF; IF (REG_RSTN = '0') THEN REG_DATA_OUT <= (OTHERS => '0'); STATE <= ST_IDLE; COMMAND <= NOPE; MSPI_CS <= '1'; END IF; END IF; END PROCESS; Изменено 1 марта, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба вам надо бы разобраться с типовыми "кусками", применяемыми в ПЛИС для решения тех или иных задач. когда применять очереди (FIFO), арбитры, планировщики (scheduler), рекомендую к прочтению: 10_lec08.pdf в вашем случае, поскольку обработчик команд в момент прихода новой команды может быть занят - логичным решением может стать FIFO команд. т.е. новые команды поступают в FIFO, и обработчик, по мере своих возможностей забирает из него команды для обработки. почитал. там все на уровне блок-диаграм. а FIFO мне нужно несколько я так понимаю? для каждой комманды FIFO? я привел кусок процесса. а там кроме ram_command есть и другие команды. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба почитал. там все на уровне блок-диаграм. а FIFO мне нужно несколько я так понимаю? для каждой комманды FIFO? я привел кусок процесса. а там кроме ram_command есть и другие команды. Смотря что Вам нужно. Двупортовое FIFO я обычно применяю для пересечения клоковых доменов. Однопортовое FIFO я использую когда каике-то команды\запросы идут с одной периодичностью, к примеру раз в 3 такта. А блок, который эти запросы обрабатывает тратит 10 тактов. Но обычно требуется механизм защиты от переполнения FIFO. Тут уже всё упирается в Вашу фантазию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 1 марта, 2017 Опубликовано 1 марта, 2017 (изменено) · Жалоба Где NOPE это и есть "000". Весь процесс я бы вот так написал ---------------------------------------------- WHEN OTHERS => RAM_COMMAND <= NOPE; ------------------------------------------------- я этот момент не очень понял. WHEN OTHERS сработает по условию прихода команды - SPI_DATA_LATCH = '1'. а если команда не пришла? RAM_COMMAND останется на предыдущем кейсе. а если так? IF (SPI_DATA_LATCH = '1') THEN ----------------------------------- ---------------------------------- ELSE RAM_COMMAND <= NOPE; END IF; Изменено 1 марта, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба я этот момент не очень понял. WHEN OTHERS сработает по условию прихода команды - SPI_DATA_LATCH = '1'. а если команда не пришла? RAM_COMMAND останется на предыдущем кейсе. Ошибся я что-то :crying: Я вижу 2 путя: Первый: IF (RISING_EDGE(REG_CLK)) THEN RAM_COMMAND <= NOPE; А второй - это использовать сигнал (SPI_DATA_LATCH = '1'), как сигнал разрешения работы с память. Т.е пока он равен нулю, памяти без разницы состояние регистра RAM_COMMAND. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 1 марта, 2017 Опубликовано 1 марта, 2017 (изменено) · Жалоба Ошибся я что-то :crying: Я вижу 2 путя: Первый: IF (RISING_EDGE(REG_CLK)) THEN RAM_COMMAND <= NOPE; А второй - это использовать сигнал (SPI_DATA_LATCH = '1'), как сигнал разрешения работы с память. Т.е пока он равен нулю, памяти без разницы состояние регистра RAM_COMMAND. первый опасный. у второго процесса будет только один клок захватить ram_command. а второй это идея. SPI_DATA_LATCH защелкнет мне и состояние ram_command . да. это идея.... следущая тема будет - где поднять и где опустить SPI_DATA_LATCH. :) Изменено 1 марта, 2017 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 1 марта, 2017 Опубликовано 1 марта, 2017 · Жалоба Зря вы отвергли предлагаемые вам пути решения проблемы (предлагали в других темах) У вас "программистическое" мышление, ну так и надо делать программисткие описания. Будет не супер оптимально, зато результат будет без боли и гораздо быстрее. У меня для вас даже есть рецепт успеха, всего то надо на верилог переехать, программистам там удобнее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться