Maverick_ 15 30 ноября, 2021 Опубликовано 30 ноября, 2021 · Жалоба Добрый день подскажите пожалуйста как правильно описать двухпортовую память с CS(Chip select) (altera) такое решение library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use IEEE.NUMERIC_STD.ALL; entity bram_tdp is generic ( DATA : integer := 32; ADDR : integer := 12 ); port ( -- Port A a_clk : in std_logic; ena : in std_logic;-- a_wr : in std_logic; a_addr : in std_logic_vector(ADDR-1 downto 0); a_din : in std_logic_vector(DATA-1 downto 0); a_dout : out std_logic_vector(DATA-1 downto 0); -- Port B b_clk : in std_logic; enb : in std_logic;-- b_wr : in std_logic; b_addr : in std_logic_vector(ADDR-1 downto 0); b_din : in std_logic_vector(DATA-1 downto 0); b_dout : out std_logic_vector(DATA-1 downto 0) ); end bram_tdp; architecture rtl of bram_tdp is -- Shared memory type mem_type is array ( (2**ADDR)-1 downto 0 ) of std_logic_vector(DATA-1 downto 0); FUNCTION initialize_ram return mem_type is variable result : mem_type; BEGIN FOR i IN ((2**ADDR)-1) DOWNTO 0 LOOP result(i) := std_logic_vector( to_unsigned(natural(i), natural'((DATA)))); END LOOP; RETURN result; END initialize_ram; shared variable mem : mem_type := initialize_ram; --shared variable mem : mem_type := (others => (others => '0')); -- := initialize_ram; begin -- Port A process(a_clk) begin if(a_clk'event and a_clk='1') then if ena = '1' then -- if(a_wr='1') then mem(conv_integer(a_addr)) := a_din; end if; a_dout <= mem(conv_integer(a_addr)); end if; -- end if; end process; -- Port B process(b_clk) begin if(b_clk'event and b_clk='1') then if enb = '1' then -- if(b_wr='1') then mem(conv_integer(b_addr)) := b_din; end if; b_dout <= mem(conv_integer(b_addr)); end if; -- end if; end process; end rtl; мне кажется не коректным т.к. не задействуется порт CS (technology viewer) - вложение. Основной вопрос как осуществить доступ к нескольким портам памяти (BRAM) имея один вход: Шина данных Шина адреса Сигнал WE Решение через сигнал WE мне кажется не очень быстродейственным - большой mux. Мне надо соедениться с 16 памятями - чтобы их инициализировать Можно конечно сделать pipeline. Может у кого есть более оригинальные решения? PS Для avalon MM для соединения мастера со многими слейвами MM - все намного проще "Chip select signal to the slave. The slave port should ignore all other Avalon signal inputs unless chipselect is asserted." Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 30 ноября, 2021 Опубликовано 30 ноября, 2021 · Жалоба Насчет возможности с помощью Core Generator я знаю... Начал сомневаться что описать память с Chip select можно - только через Core Generator Вот еще архитектура для записи - вложение Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 30 ноября, 2021 Опубликовано 30 ноября, 2021 · Жалоба 1 hour ago, Maverick_ said: подскажите пожалуйста как правильно описать двухпортовую память с CS(Chip select) (altera) такое решение мне кажется не коректным т.к. не задействуется порт CS (technology viewer) - вложение. ReadEnable/WriteEnable задействованы. Работают как clock_enable. Вам не нравиться что именно сам порт inclkockena не задействован? А есть разница? Quote Решение через сигнал WE мне кажется не очень быстродейственным - большой mux. Не большой мукс, а несколько декодеров. Вы же пишете. Для 16 блоков памяти это будет 16 LUT5, использовать триггер по выбору. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба des00 спасибо за подсказку... Добрый день. (update) есть несколько индентичных модулей (размножены с помощью generic). Модуль выдает ready как данные готовы. Все модули ready выдать одновремнно не могут - только один срабатывет Выход каждого модуля это порт памяти с которого необходимо прочитать результат обработки после ready = '1'. Вопрос как мне определить с какого модуля мне надо забрать данные и как построить мультиплексор к портам памяти (возможно есть другие красивые решения). Мое решение сложное - как по мне: ниже ход мыслей Объеденяем все ready от модулей в один регистр, далее module bitscan (req,sel); parameter WIDTH = 16; input [WIDTH-1:0] req; output [WIDTH-1:0] sel; assign sel = req & ~(req-1); endmodule (что делает этот модуль во вложении картинка) от результата отнимаем 1 и считаем количество едениц ответом и будет номер модуля с какого модуля мне надо забрать данные в котором сработал ready Потом мультиплексор ... library ieee ; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity mux4 is port( d0 : in std_logic_vector(1 downto 0); d1 : in std_logic_vector(1 downto 0); d2 : in std_logic_vector(1 downto 0); d3 : in std_logic_vector(1 downto 0); s : in std_logic_vector(1 downto 0); m : out std_logic_vector(1 downto 0)); end mux4; architecture rtl of mux4 is type t_array_mux is array (0 to 3) of std_logic_vector(1 downto 0); signal array_mux : t_array_mux; begin array_mux(0) <= d0; array_mux(1) <= d1; array_mux(2) <= d2; array_mux(3) <= d3; m <= array_mux(to_integer(unsigned(s))); end rtl; Для шины адреса и данных - необходимых для чтения из памяти (BRAM) Интересуют идеи по реализации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 34 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба Приветствую! 1 hour ago, Maverick_ said: Вопрос как мне определить с какого модуля мне надо забрать данные. Тут надо уточнить что значит (для чего) "... определить с какого"? Получить бинарный код? Ну и доп. условие - могут ли быть одновременно несколько ready? Если да то каков приоритет выбора? Если одновременно может быть только один ready и бинарный код не нужен то объединять шины можно через простой AND-OR мукс. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба Дополню задачу - внесу более четкость Выход каждого модуля это порт памяти с которого необходимо прочитать результат обработки после ready = '1' Давайте пока считать что только 1 ready = '1' может быть Предыдущий пост дополнил для ясности задачи Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба 38 минут назад, Maverick_ сказал: Дополню задачу - внесу более четкость Выход каждого модуля это порт памяти с которого необходимо прочитать результат обработки после ready = '1' Давайте пока считать что только 1 ready = '1' может быть Предыдущий пост дополнил для ясности задачи 1. Простой round_robin 2. Нашли первую единичку в векторе -> прочитали эту память -> обунлили этот сигнал -> Нашли первую единичку в векторе... 3. Обычный кольцевой арбитр. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба 22 minutes ago, Flip-fl0p said: 1. Простой round_robin 2. Нашли первую единичку в векторе -> прочитали эту память -> обунлили этот сигнал -> Нашли первую единичку в векторе... 3. Обычный кольцевой арбитр. можно поподробнее пожалуйста особенно второй пункт с намеком на схемотехнику... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба 22 минуты назад, Maverick_ сказал: можно поподробнее пожалуйста особенно второй пункт. У меня проблема что не могу в оптимальную схемотехнику перевести ... из за этого и прошу помощи Есть старый математический трюк b = a & (-a) Он возвращает вектор где все значения нули, кроме првого бита, где есть лог. 1. Вы как раз картинку этого выложили. Я для этого имею функцию --=========================================================== -- Получить вектор, где есть только старший бит --=========================================================== function GET_LSB_ON_VECTOR ( data : std_logic_vector ) return std_logic_vector is variable minus_data : std_logic_vector(data'left downto 0); variable b : std_logic_vector(data'left downto 0); begin minus_data := std_logic_vector(unsigned(not data) + "1"); -- Получаем отрицательное значение -a b := data and minus_data; -- Умножаем их a & (-a) return b; end function; Ну а далее простой FSM. Анализируем вектор b ---> Вектор b != 0 ---> запускаем чтение из памяти по адресу памяти который выставил ready (адрес определяем как раз таки при помощи этого вектора b, операцией обратной декодеру) ---> данные прочитаны ---> обнуляем сигал ready этой памяти ---> Анализируем вектор b. Например 1. Имеем 4 памяти. 2. Внезапно и одномоментно вектор ready стал "1010" 3. пользуемся трюком и получаем вектор b = "0010" 4. Подаем вектор b на энкодер - и получаем addr = 1 case b is when "0001" => addr <= "00"; when "0010" => addr <= "01"; when "0100" => addr <= "10"; when "1000" => addr <= "11"; when "others => addr <= "--"; end case; 5. Читаем память с адресом addr = 1. 6. После чтения памяти обнуляем соответствующий ready. Т.е было ready = 1010, стало ready = 1000. 7. Опа ! У нас ready = 1000 8. пользуемся трюком и получаем вектор b = "1000" 9 ..... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 1 декабря, 2021 Опубликовано 1 декабря, 2021 · Жалоба 1 minute ago, Flip-fl0p said: Есть старый математический трюк b = a & (-a) Он возвращает вектор где все значения нули, кроме првого бита, где есть лог. 1. Вы как раз картинку этого выложили. Я для этого имею функцию --=========================================================== -- Получить вектор, где есть только старший бит --=========================================================== function GET_LSB_ON_VECTOR ( data : std_logic_vector ) return std_logic_vector is variable minus_data : std_logic_vector(data'left downto 0); variable b : std_logic_vector(data'left downto 0); begin minus_data := std_logic_vector(unsigned(not data) + "1"); -- Получаем отрицательное значение -a b := data and minus_data; -- Умножаем их a & (-a) return b; end function; Ну а далее простой FSM. Анализируем вектор b ---> Вектор b != 0 ---> запускаем чтение из памяти по адресу памяти который выставил ready (адрес определяем как раз таки при помощи этого вектора b, операцией обратной декодеру) ---> данные прочитаны ---> обнуляем сигал ready этой памяти ---> Анализируем вектор b. Например 1. Имеем 4 памяти. 2. Внезапно и одномоментно вектор ready стал "1010" 3. пользуемся трюком и получаем вектор b = "0010" 4. Подаем вектор b на энкодер - и получаем addr = 1 case b is when "0001" => addr <= "00"; when "0010" => addr <= "01"; when "0100" => addr <= "10"; when "1000" => addr <= "11"; when "others => addr <= "--"; end case; 5. Читаем память с адресом addr = 1. 6. После чтения памяти обнуляем соответствующий ready. Т.е было ready = 1010, стало ready = 1000. 7. Опа ! У нас ready = 1000 8. пользуемся трюком и получаем вектор b = "1000" 9 ..... мне пока нравиться решение Спасибо Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 2 декабря, 2021 Опубликовано 2 декабря, 2021 · Жалоба 13 hours ago, Maverick_ said: Давайте пока считать что только 1 ready = '1' может быть если уникальный 146% и будет уникальный до окончания чтения памяти, то, как написал @RobFPGA AND-OR мультиплексор, Если не уникальный то либо простой приоритетный арбитраж, как предложил @Flip-fl0p или RRA арбитр. Вот псевдокод ядра RRA typedef logic [pN-1 : 0] request_t; typedef logic [pN_LOG2-1 : 0] winner_t; logic request ; winner_t last_winner ; winner_t winner ; assign request = (ireq != 0); assign winner = get_winner(ireq, last_winner); always_ff @(posedge iclk) begin if (request) begin last_winner <= winner; grant <= '0; grant[winner] <= request; end end function automatic winner_t get_winner (input request_t request, input winner_t last_winner); get_winner = last_winner; // for (int i = 0; i < pN; i++) begin get_winner = get_winner + 1'b1; if (get_winner == pN) begin get_winner = 0; end if (request [get_winner]) begin return get_winner; end end endfunction ну а дальше уже, зная того кто победил, интегрируете это в ваш FSM по чтению Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 2 декабря, 2021 Опубликовано 2 декабря, 2021 · Жалоба 12 часов назад, Flip-fl0p сказал: variable minus_data : std_logic_vector(data'left downto 0); Занудства ради. Вы рассчитываете на то, что в вашу функцию будут передавться только вектора с индексацией (N downto 0). А вдруг ей передадут вектор (N downto M)? Или тем паче (M to N)? 12 часов назад, Flip-fl0p сказал: minus_data := std_logic_vector(unsigned(not data) + "1"); -- Получаем отрицательное значение -a Почему не minus_data := std_logic_vector(-signed(data)); ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 2 декабря, 2021 Опубликовано 2 декабря, 2021 · Жалоба Всем спасибо за советы... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 2 декабря, 2021 Опубликовано 2 декабря, 2021 · Жалоба 9 часов назад, andrew_b сказал: Занудства ради. Вы рассчитываете на то, что в вашу функцию будут передавться только вектора с индексацией (N downto 0). А вдруг ей передадут вектор (N downto M)? Или тем паче (M to N)? Почему не minus_data := std_logic_vector(-signed(data)); ? Функцию писал для себя. Я почти никогда не пользуюсь векторами(M to N). Ну разве что описание массивов исключение из этого правила. А разве при передаче в функцию Вектора N downto M этот вектор в функции не будет автоматом считаться (M-N downto 0) ? minus_data := std_logic_vector(-signed(data)); До этого не додумался Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 16 2 декабря, 2021 Опубликовано 2 декабря, 2021 · Жалоба 2 часа назад, Flip-fl0p сказал: Функцию писал для себя. Я почти никогда не пользуюсь векторами(M to N). Нет никаких сложностей сделать универсальную функцию. 2 часа назад, Flip-fl0p сказал: А разве при передаче в функцию Вектора N downto M этот вектор в функции не будет автоматом считаться (M-N downto 0) ? А на каком основании? Чем 0 лучше любого другого числа? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться